1
Fork 0

Preparations and cleanup

Diagnostics for struct path resolution errors in resolve and typeck are unified.
Self type is treated as a type alias in few places (not reachable yet).
Unsafe cell is seen in constants even through type aliases.
All checks for struct paths in typeck work on type level.
This commit is contained in:
Vadim Petrochenkov 2016-09-15 00:51:46 +03:00
parent 07436946b6
commit a9f91b1b0e
27 changed files with 232 additions and 206 deletions

View file

@ -1017,7 +1017,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
delegate.matched_pat(pat, downcast_cmt, match_mode); delegate.matched_pat(pat, downcast_cmt, match_mode);
} }
Some(Def::Struct(..)) | Some(Def::StructCtor(..)) | Some(Def::Union(..)) | Some(Def::Struct(..)) | Some(Def::StructCtor(..)) | Some(Def::Union(..)) |
Some(Def::TyAlias(..)) | Some(Def::AssociatedTy(..)) => { Some(Def::TyAlias(..)) | Some(Def::AssociatedTy(..)) | Some(Def::SelfTy(..)) => {
debug!("struct cmt_pat={:?} pat={:?}", cmt_pat, pat); debug!("struct cmt_pat={:?} pat={:?}", cmt_pat, pat);
delegate.matched_pat(pat, cmt_pat, match_mode); delegate.matched_pat(pat, cmt_pat, match_mode);
} }

View file

@ -1698,7 +1698,7 @@ impl<'a, 'gcx, 'tcx, 'container> AdtDefData<'gcx, 'container> {
match def { match def {
Def::Variant(vid) | Def::VariantCtor(vid, ..) => self.variant_with_id(vid), Def::Variant(vid) | Def::VariantCtor(vid, ..) => self.variant_with_id(vid),
Def::Struct(..) | Def::StructCtor(..) | Def::Union(..) | Def::Struct(..) | Def::StructCtor(..) | Def::Union(..) |
Def::TyAlias(..) | Def::AssociatedTy(..) => self.struct_variant(), Def::TyAlias(..) | Def::AssociatedTy(..) | Def::SelfTy(..) => self.struct_variant(),
_ => bug!("unexpected def {:?} in variant_of_def", def) _ => bug!("unexpected def {:?} in variant_of_def", def)
} }
} }

View file

@ -14,7 +14,7 @@ use ty::{BrAnon, BrEnv, BrFresh, BrNamed};
use ty::{TyBool, TyChar, TyAdt}; use ty::{TyBool, TyChar, TyAdt};
use ty::{TyError, TyStr, TyArray, TySlice, TyFloat, TyFnDef, TyFnPtr}; use ty::{TyError, TyStr, TyArray, TySlice, TyFloat, TyFnDef, TyFnPtr};
use ty::{TyParam, TyRawPtr, TyRef, TyNever, TyTuple}; use ty::{TyParam, TyRawPtr, TyRef, TyNever, TyTuple};
use ty::TyClosure; use ty::{TyClosure, TyProjection, TyAnon};
use ty::{TyBox, TyTrait, TyInt, TyUint, TyInfer}; use ty::{TyBox, TyTrait, TyInt, TyUint, TyInfer};
use ty::{self, Ty, TyCtxt, TypeFoldable}; use ty::{self, Ty, TyCtxt, TypeFoldable};
use ty::fold::{TypeFolder, TypeVisitor}; use ty::fold::{TypeFolder, TypeVisitor};
@ -802,6 +802,34 @@ impl<'tcx> fmt::Display for ty::TraitRef<'tcx> {
} }
} }
impl<'tcx> ty::TypeVariants<'tcx> {
pub fn descr(&self) -> &'static str {
match *self {
TyInt(..) | TyUint(..) | TyFloat(..) |
TyBool | TyChar | TyStr => "builtin type",
TyRawPtr(..) => "pointer",
TyRef(..) => "reference",
TyTuple(..) => "tuple",
TyFnDef(..) => "function type",
TyFnPtr(..) => "function pointer",
TyArray(..) => "array",
TySlice(..) => "slice",
TyParam(..) => "type parameter",
TyProjection(..) => "associated type",
TyTrait(..) => "trait type",
TyClosure(..) => "closure type",
TyBox(..) => "struct",
TyAdt(def, ..) => match def.adt_kind() {
ty::AdtKind::Struct => "struct",
ty::AdtKind::Union => "union",
ty::AdtKind::Enum => "enum",
},
TyInfer(..) | TyAnon(..) |
TyNever | TyError => "type",
}
}
}
impl<'tcx> fmt::Display for ty::TypeVariants<'tcx> { impl<'tcx> fmt::Display for ty::TypeVariants<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self { match *self {
@ -879,8 +907,8 @@ impl<'tcx> fmt::Display for ty::TypeVariants<'tcx> {
}) })
} }
TyTrait(ref data) => write!(f, "{}", data), TyTrait(ref data) => write!(f, "{}", data),
ty::TyProjection(ref data) => write!(f, "{}", data), TyProjection(ref data) => write!(f, "{}", data),
ty::TyAnon(def_id, substs) => { TyAnon(def_id, substs) => {
ty::tls::with(|tcx| { ty::tls::with(|tcx| {
// Grab the "TraitA + TraitB" from `impl TraitA + TraitB`, // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
// by looking up the projections associated with the def_id. // by looking up the projections associated with the def_id.

View file

@ -565,9 +565,11 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node
} }
} }
hir::ExprStruct(..) => { hir::ExprStruct(..) => {
// unsafe_cell_type doesn't necessarily exist with no_core if let ty::TyAdt(adt, ..) = v.tcx.expr_ty(e).sty {
if Some(v.tcx.expect_def(e.id).def_id()) == v.tcx.lang_items.unsafe_cell_type() { // unsafe_cell_type doesn't necessarily exist with no_core
v.add_qualif(ConstQualif::MUTABLE_MEM); if Some(adt.did) == v.tcx.lang_items.unsafe_cell_type() {
v.add_qualif(ConstQualif::MUTABLE_MEM);
}
} }
} }

View file

@ -860,31 +860,6 @@ match (A, B, C) {
``` ```
"##, "##,
E0422: r##"
You are trying to use an identifier that is either undefined or not a struct.
Erroneous code example:
``` compile_fail,E0422
fn main () {
let x = Foo { x: 1, y: 2 };
}
```
In this case, `Foo` is undefined, so it inherently isn't anything, and
definitely not a struct.
```compile_fail,E0422
fn main () {
let foo = 1;
let x = foo { x: 1, y: 2 };
}
```
In this case, `foo` is defined, but is not a struct, so Rust can't use it as
one.
"##,
E0423: r##" E0423: r##"
A `struct` variant name was used like a function name. A `struct` variant name was used like a function name.
@ -1503,6 +1478,7 @@ register_diagnostics! {
// E0419, merged into 531 // E0419, merged into 531
// E0420, merged into 532 // E0420, merged into 532
// E0421, merged into 531 // E0421, merged into 531
// E0422, merged into 531/532
E0531, // unresolved pattern path kind `name` E0531, // unresolved pattern path kind `name`
E0532, // expected pattern path kind, found another pattern path kind E0532, // expected pattern path kind, found another pattern path kind
// E0427, merged into 530 // E0427, merged into 530

View file

@ -129,8 +129,6 @@ enum ResolutionError<'a> {
IdentifierBoundMoreThanOnceInParameterList(&'a str), IdentifierBoundMoreThanOnceInParameterList(&'a str),
/// error E0416: identifier is bound more than once in the same pattern /// error E0416: identifier is bound more than once in the same pattern
IdentifierBoundMoreThanOnceInSamePattern(&'a str), IdentifierBoundMoreThanOnceInSamePattern(&'a str),
/// error E0422: does not name a struct
DoesNotNameAStruct(&'a str),
/// error E0423: is a struct variant name, but this expression uses it like a function name /// error E0423: is a struct variant name, but this expression uses it like a function name
StructVariantUsedAsFunction(&'a str), StructVariantUsedAsFunction(&'a str),
/// error E0424: `self` is not available in a static method /// error E0424: `self` is not available in a static method
@ -336,15 +334,6 @@ fn resolve_struct_error<'b, 'a: 'b, 'c>(resolver: &'b Resolver<'a>,
err.span_label(span, &format!("used in a pattern more than once")); err.span_label(span, &format!("used in a pattern more than once"));
err err
} }
ResolutionError::DoesNotNameAStruct(name) => {
let mut err = struct_span_err!(resolver.session,
span,
E0422,
"`{}` does not name a structure",
name);
err.span_label(span, &format!("not a structure"));
err
}
ResolutionError::StructVariantUsedAsFunction(path_name) => { ResolutionError::StructVariantUsedAsFunction(path_name) => {
let mut err = struct_span_err!(resolver.session, let mut err = struct_span_err!(resolver.session,
span, span,
@ -2383,6 +2372,18 @@ impl<'a> Resolver<'a> {
self.record_def(pat_id, resolution); self.record_def(pat_id, resolution);
} }
fn resolve_struct_path(&mut self, node_id: NodeId, path: &Path) {
// Resolution logic is equivalent for expressions and patterns,
// reuse `resolve_pattern_path` for both.
self.resolve_pattern_path(node_id, None, path, TypeNS, |def| {
match def {
Def::Struct(..) | Def::Union(..) | Def::Variant(..) |
Def::TyAlias(..) | Def::AssociatedTy(..) | Def::SelfTy(..) => true,
_ => false,
}
}, "struct, variant or union type");
}
fn resolve_pattern(&mut self, fn resolve_pattern(&mut self,
pat: &Pat, pat: &Pat,
pat_src: PatternSource, pat_src: PatternSource,
@ -2460,13 +2461,7 @@ impl<'a> Resolver<'a> {
} }
PatKind::Struct(ref path, ..) => { PatKind::Struct(ref path, ..) => {
self.resolve_pattern_path(pat.id, None, path, TypeNS, |def| { self.resolve_struct_path(pat.id, path);
match def {
Def::Struct(..) | Def::Union(..) | Def::Variant(..) |
Def::TyAlias(..) | Def::AssociatedTy(..) => true,
_ => false,
}
}, "variant, struct or type alias");
} }
_ => {} _ => {}
@ -3024,23 +3019,7 @@ impl<'a> Resolver<'a> {
} }
ExprKind::Struct(ref path, ..) => { ExprKind::Struct(ref path, ..) => {
// Resolve the path to the structure it goes to. We don't self.resolve_struct_path(expr.id, path);
// check to ensure that the path is actually a structure; that
// is checked later during typeck.
match self.resolve_path(expr.id, path, 0, TypeNS) {
Ok(definition) => self.record_def(expr.id, definition),
Err(true) => self.record_def(expr.id, err_path_resolution()),
Err(false) => {
debug!("(resolving expression) didn't find struct def",);
resolve_error(self,
path.span,
ResolutionError::DoesNotNameAStruct(
&path_names_to_string(path, 0))
);
self.record_def(expr.id, err_path_resolution());
}
}
visit::walk_expr(self, expr); visit::walk_expr(self, expr);
} }

View file

@ -1493,7 +1493,8 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor for DumpVisitor<'l, 'tcx, 'll, D>
Def::StructCtor(..) | Def::VariantCtor(..) | Def::StructCtor(..) | Def::VariantCtor(..) |
Def::Const(..) | Def::AssociatedConst(..) | Def::Const(..) | Def::AssociatedConst(..) |
Def::Struct(..) | Def::Variant(..) | Def::Struct(..) | Def::Variant(..) |
Def::TyAlias(..) | Def::AssociatedTy(..) => { Def::TyAlias(..) | Def::AssociatedTy(..) |
Def::SelfTy(..) => {
paths_to_process.push((id, p.clone(), Some(ref_kind))) paths_to_process.push((id, p.clone(), Some(ref_kind)))
} }
def => error!("unexpected definition kind when processing collected paths: {:?}", def => error!("unexpected definition kind when processing collected paths: {:?}",

View file

@ -1484,7 +1484,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
def: Def, def: Def,
opt_self_ty: Option<Ty<'tcx>>, opt_self_ty: Option<Ty<'tcx>>,
base_path_ref_id: ast::NodeId, base_path_ref_id: ast::NodeId,
base_segments: &[hir::PathSegment]) base_segments: &[hir::PathSegment],
permit_variants: bool)
-> Ty<'tcx> { -> Ty<'tcx> {
let tcx = self.tcx(); let tcx = self.tcx();
@ -1515,6 +1516,22 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
did, did,
base_segments.last().unwrap()) base_segments.last().unwrap())
} }
Def::Variant(did) if permit_variants => {
// Convert "variant type" as if it were a real type.
// The resulting `Ty` is type of the variant's enum for now.
tcx.prohibit_type_params(base_segments.split_last().unwrap().1);
let mut ty = self.ast_path_to_ty(rscope,
span,
param_mode,
tcx.parent_def_id(did).unwrap(),
base_segments.last().unwrap());
if ty.is_fn() {
// Tuple variants have fn type even in type namespace,
// extract true variant type from it.
ty = tcx.no_late_bound_regions(&ty.fn_ret()).unwrap();
}
ty
}
Def::TyParam(did) => { Def::TyParam(did) => {
tcx.prohibit_type_params(base_segments); tcx.prohibit_type_params(base_segments);
@ -1604,7 +1621,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
opt_self_ty: Option<Ty<'tcx>>, opt_self_ty: Option<Ty<'tcx>>,
base_path_ref_id: ast::NodeId, base_path_ref_id: ast::NodeId,
base_segments: &[hir::PathSegment], base_segments: &[hir::PathSegment],
assoc_segments: &[hir::PathSegment]) assoc_segments: &[hir::PathSegment],
permit_variants: bool)
-> (Ty<'tcx>, Def) { -> (Ty<'tcx>, Def) {
// Convert the base type. // Convert the base type.
debug!("finish_resolving_def_to_ty(base_def={:?}, \ debug!("finish_resolving_def_to_ty(base_def={:?}, \
@ -1619,7 +1637,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
base_def, base_def,
opt_self_ty, opt_self_ty,
base_path_ref_id, base_path_ref_id,
base_segments); base_segments,
permit_variants);
debug!("finish_resolving_def_to_ty: base_def_to_ty returned {:?}", base_ty); debug!("finish_resolving_def_to_ty: base_def_to_ty returned {:?}", base_ty);
// If any associated type segments remain, attempt to resolve them. // If any associated type segments remain, attempt to resolve them.
@ -1775,7 +1794,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
opt_self_ty, opt_self_ty,
ast_ty.id, ast_ty.id,
&path.segments[..base_ty_end], &path.segments[..base_ty_end],
&path.segments[base_ty_end..]); &path.segments[base_ty_end..],
false);
// Write back the new resolution. // Write back the new resolution.
if path_res.depth != 0 { if path_res.depth != 0 {

View file

@ -489,8 +489,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
expected: Ty<'tcx>) -> Ty<'tcx> expected: Ty<'tcx>) -> Ty<'tcx>
{ {
// Resolve the path and check the definition for errors. // Resolve the path and check the definition for errors.
let (variant, pat_ty) = if let Some(variant_ty) = self.check_struct_path(path, pat.id, let (variant, pat_ty) = if let Some(variant_ty) = self.check_struct_path(path, pat.id) {
pat.span) {
variant_ty variant_ty
} else { } else {
for field in fields { for field in fields {

View file

@ -1686,41 +1686,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
cause) cause)
} }
/// Instantiates the type in `did` with the generics in `path` and returns
/// it (registering the necessary trait obligations along the way).
///
/// Note that this function is only intended to be used with type-paths,
/// not with value-paths.
pub fn instantiate_type_path(&self,
did: DefId,
path: &hir::Path,
node_id: ast::NodeId)
-> Ty<'tcx> {
debug!("instantiate_type_path(did={:?}, path={:?})", did, path);
let mut ty = self.tcx.lookup_item_type(did).ty;
if ty.is_fn() {
// Tuple variants have fn type even in type namespace, extract true variant type from it
ty = self.tcx.no_late_bound_regions(&ty.fn_ret()).unwrap();
}
let type_predicates = self.tcx.lookup_predicates(did);
let substs = AstConv::ast_path_substs_for_ty(self, self,
path.span,
PathParamMode::Optional,
did,
path.segments.last().unwrap());
debug!("instantiate_type_path: ty={:?} substs={:?}", ty, substs);
let bounds = self.instantiate_bounds(path.span, substs, &type_predicates);
let cause = traits::ObligationCause::new(path.span, self.body_id,
traits::ItemObligation(did));
self.add_obligations_for_parameters(cause, &bounds);
let ty_substituted = self.instantiate_type_scheme(path.span, substs, &ty);
self.write_substs(node_id, ty::ItemSubsts {
substs: substs
});
ty_substituted
}
pub fn write_nil(&self, node_id: ast::NodeId) { pub fn write_nil(&self, node_id: ast::NodeId) {
self.write_ty(node_id, self.tcx.mk_nil()); self.write_ty(node_id, self.tcx.mk_nil());
} }
@ -3252,46 +3217,56 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
pub fn check_struct_path(&self, pub fn check_struct_path(&self,
path: &hir::Path, path: &hir::Path,
node_id: ast::NodeId, node_id: ast::NodeId)
span: Span)
-> Option<(ty::VariantDef<'tcx>, Ty<'tcx>)> { -> Option<(ty::VariantDef<'tcx>, Ty<'tcx>)> {
let def = self.finish_resolving_struct_path(path, node_id, span); let (def, ty) = self.finish_resolving_struct_path(path, node_id);
let variant = match def { let variant = match def {
Def::Err => { Def::Err => {
self.set_tainted_by_errors(); self.set_tainted_by_errors();
return None; return None;
} }
Def::Variant(did) => { Def::Variant(..) => {
let type_did = self.tcx.parent_def_id(did).unwrap(); match ty.sty {
Some((type_did, self.tcx.expect_variant_def(def))) ty::TyAdt(adt, substs) => {
Some((adt.variant_of_def(def), adt.did, substs))
}
_ => bug!("unexpected type: {:?}", ty.sty)
}
} }
Def::Struct(type_did) | Def::Union(type_did) => { Def::Struct(..) | Def::Union(..) | Def::TyAlias(..) |
Some((type_did, self.tcx.expect_variant_def(def))) Def::AssociatedTy(..) => {
} match ty.sty {
Def::TyAlias(did) | Def::AssociatedTy(did) => { ty::TyAdt(adt, substs) if !adt.is_enum() => {
match self.tcx.opt_lookup_item_type(did).map(|scheme| &scheme.ty.sty) { Some((adt.struct_variant(), adt.did, substs))
Some(&ty::TyAdt(adt, _)) if !adt.is_enum() => {
Some((did, adt.struct_variant()))
} }
_ => None, _ => None,
} }
} }
_ => None // Self is not supported yet.
Def::SelfTy(..) => None,
_ => bug!("unexpected definition: {:?}", def)
}; };
if let Some((def_id, variant)) = variant { if let Some((variant, did, substs)) = variant {
if variant.ctor_kind == CtorKind::Fn && if variant.ctor_kind == CtorKind::Fn &&
!self.tcx.sess.features.borrow().relaxed_adts { !self.tcx.sess.features.borrow().relaxed_adts {
emit_feature_err(&self.tcx.sess.parse_sess, emit_feature_err(&self.tcx.sess.parse_sess,
"relaxed_adts", span, GateIssue::Language, "relaxed_adts", path.span, GateIssue::Language,
"tuple structs and variants in struct patterns are unstable"); "tuple structs and variants in struct patterns are unstable");
} }
let ty = self.instantiate_type_path(def_id, path, node_id);
// Check bounds on type arguments used in the path.
let type_predicates = self.tcx.lookup_predicates(did);
let bounds = self.instantiate_bounds(path.span, substs, &type_predicates);
let cause = traits::ObligationCause::new(path.span, self.body_id,
traits::ItemObligation(did));
self.add_obligations_for_parameters(cause, &bounds);
Some((variant, ty)) Some((variant, ty))
} else { } else {
struct_span_err!(self.tcx.sess, path.span, E0071, struct_span_err!(self.tcx.sess, path.span, E0071,
"`{}` does not name a struct or a struct variant", "expected struct, variant or union type, found {} `{}`",
pprust::path_to_string(path)) ty.sty.descr(), ty)
.span_label(path.span, &format!("not a struct")) .span_label(path.span, &format!("not a struct"))
.emit(); .emit();
None None
@ -3305,12 +3280,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
base_expr: &'gcx Option<P<hir::Expr>>) -> Ty<'tcx> base_expr: &'gcx Option<P<hir::Expr>>) -> Ty<'tcx>
{ {
// Find the relevant variant // Find the relevant variant
let (variant, struct_ty) = if let Some(variant_ty) = self.check_struct_path(path, expr.id, let (variant, struct_ty) = if let Some(variant_ty) = self.check_struct_path(path, expr.id) {
expr.span) {
variant_ty variant_ty
} else { } else {
self.check_struct_fields_on_error(fields, base_expr); self.check_struct_fields_on_error(fields, base_expr);
return self.tcx().types.err; return self.tcx.types.err;
}; };
self.check_expr_struct_fields(struct_ty, path.span, variant, fields, self.check_expr_struct_fields(struct_ty, path.span, variant, fields,
@ -3805,7 +3779,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
} }
} }
err.emit(); err.emit();
self.tcx().types.err self.tcx.types.err
} }
} }
} }
@ -3815,29 +3789,26 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
// Finish resolving a path in a struct expression or pattern `S::A { .. }` if necessary. // Finish resolving a path in a struct expression or pattern `S::A { .. }` if necessary.
// The newly resolved definition is written into `def_map`. // The newly resolved definition is written into `def_map`.
pub fn finish_resolving_struct_path(&self, fn finish_resolving_struct_path(&self,
path: &hir::Path, path: &hir::Path,
node_id: ast::NodeId, node_id: ast::NodeId)
span: Span) -> (Def, Ty<'tcx>)
-> Def
{ {
let path_res = self.tcx().expect_resolution(node_id); let path_res = self.tcx.expect_resolution(node_id);
if path_res.depth == 0 { let base_ty_end = path.segments.len() - path_res.depth;
// If fully resolved already, we don't have to do anything. let (ty, def) = AstConv::finish_resolving_def_to_ty(self, self, path.span,
path_res.base_def PathParamMode::Optional,
} else { path_res.base_def,
let base_ty_end = path.segments.len() - path_res.depth; None,
let (_ty, def) = AstConv::finish_resolving_def_to_ty(self, self, span, node_id,
PathParamMode::Optional, &path.segments[..base_ty_end],
path_res.base_def, &path.segments[base_ty_end..],
None, true);
node_id, // Write back the new resolution.
&path.segments[..base_ty_end], if path_res.depth != 0 {
&path.segments[base_ty_end..]); self.tcx.def_map.borrow_mut().insert(node_id, PathResolution::new(def));
// Write back the new resolution.
self.tcx().def_map.borrow_mut().insert(node_id, PathResolution::new(def));
def
} }
(def, ty)
} }
// Resolve associated value path into a base type and associated constant or method definition. // Resolve associated value path into a base type and associated constant or method definition.
@ -3849,7 +3820,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
span: Span) span: Span)
-> (Def, Option<Ty<'tcx>>, &'b [hir::PathSegment]) -> (Def, Option<Ty<'tcx>>, &'b [hir::PathSegment])
{ {
let path_res = self.tcx().expect_resolution(node_id); let path_res = self.tcx.expect_resolution(node_id);
if path_res.depth == 0 { if path_res.depth == 0 {
// If fully resolved already, we don't have to do anything. // If fully resolved already, we don't have to do anything.
(path_res.base_def, opt_self_ty, &path.segments) (path_res.base_def, opt_self_ty, &path.segments)
@ -3863,7 +3834,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
opt_self_ty, opt_self_ty,
node_id, node_id,
&ty_segments[..base_ty_end], &ty_segments[..base_ty_end],
&ty_segments[base_ty_end..]); &ty_segments[base_ty_end..],
false);
// Resolve an associated constant or method on the previously resolved type. // Resolve an associated constant or method on the previously resolved type.
let item_segment = path.segments.last().unwrap(); let item_segment = path.segments.last().unwrap();
@ -3883,7 +3855,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
}; };
// Write back the new resolution. // Write back the new resolution.
self.tcx().def_map.borrow_mut().insert(node_id, PathResolution::new(def)); self.tcx.def_map.borrow_mut().insert(node_id, PathResolution::new(def));
(def, Some(ty), slice::ref_slice(item_segment)) (def, Some(ty), slice::ref_slice(item_segment))
} }
} }
@ -4308,7 +4280,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
// the referenced item. // the referenced item.
let ty_substituted = self.instantiate_type_scheme(span, &substs, &scheme.ty); let ty_substituted = self.instantiate_type_scheme(span, &substs, &scheme.ty);
if let Some((ty::ImplContainer(impl_def_id), self_ty)) = ufcs_associated { if let Some((ty::ImplContainer(impl_def_id), self_ty)) = ufcs_associated {
// In the case of `Foo<T>::method` and `<Foo<T>>::method`, if `method` // In the case of `Foo<T>::method` and `<Foo<T>>::method`, if `method`
// is inherent, there is no `Self` parameter, instead, the impl needs // is inherent, there is no `Self` parameter, instead, the impl needs

View file

@ -895,17 +895,14 @@ fn some_func(x: &mut i32) {
E0071: r##" E0071: r##"
You tried to use structure-literal syntax to create an item that is You tried to use structure-literal syntax to create an item that is
not a struct-style structure or enum variant. not a structure or enum variant.
Example of erroneous code: Example of erroneous code:
```compile_fail,E0071 ```compile_fail,E0071
enum Foo { FirstValue(i32) }; type U32 = u32;
let t = U32 { value: 4 }; // error: expected struct, variant or union type,
let u = Foo::FirstValue { value: 0 }; // error: Foo::FirstValue // found builtin type `u32`
// isn't a structure!
// or even simpler, if the name doesn't refer to a structure at all.
let t = u32 { value: 4 }; // error: `u32` does not name a structure.
``` ```
To fix this, ensure that the name was correctly spelled, and that To fix this, ensure that the name was correctly spelled, and that

View file

@ -15,6 +15,6 @@ pub use use_from_trait_xc::Trait;
fn main() { fn main() {
match () { match () {
Trait { x: 42 } => () //~ ERROR expected variant, struct or type alias, found trait `Trait` Trait { x: 42 } => () //~ ERROR expected struct, variant or union type, found trait `Trait`
} }
} }

View file

@ -9,13 +9,10 @@
// except according to those terms. // except according to those terms.
enum Foo {} enum Foo {}
type FooAlias = Foo;
fn main() { fn main() {
let u = Foo { value: 0 }; let u = FooAlias { value: 0 };
//~^ ERROR `Foo` does not name a struct or a struct variant [E0071] //~^ ERROR expected struct, variant or union type, found enum `Foo` [E0071]
//~| NOTE not a struct
let t = u32 { value: 4 };
//~^ ERROR `u32` does not name a struct or a struct variant [E0071]
//~| NOTE not a struct //~| NOTE not a struct
} }

View file

@ -14,5 +14,6 @@ extern crate namespaced_enums;
fn main() { fn main() {
let _ = namespaced_enums::A; //~ ERROR unresolved name let _ = namespaced_enums::A; //~ ERROR unresolved name
let _ = namespaced_enums::B(10); //~ ERROR unresolved name let _ = namespaced_enums::B(10); //~ ERROR unresolved name
let _ = namespaced_enums::C { a: 10 }; //~ ERROR does not name a structure let _ = namespaced_enums::C { a: 10 };
//~^ ERROR unresolved struct, variant or union type `namespaced_enums::C`
} }

View file

@ -16,7 +16,7 @@ pub struct GslResult {
impl GslResult { impl GslResult {
pub fn new() -> GslResult { pub fn new() -> GslResult {
Result { //~ ERROR: `Result` does not name a struct or a struct variant Result { //~ ERROR: expected struct, variant or union type, found enum `Result`
val: 0f64, val: 0f64,
err: 0f64 err: 0f64
} }

View file

@ -11,5 +11,5 @@
mod foo {} mod foo {}
fn main() { fn main() {
let p = foo { x: () }; //~ ERROR `foo` does not name a struct or a struct variant let p = foo { x: () }; //~ ERROR expected struct, variant or union type, found module `foo`
} }

View file

@ -14,6 +14,6 @@ enum Foo {
fn main() { fn main() {
match Foo::Bar(1) { match Foo::Bar(1) {
Foo { i } => () //~ ERROR expected variant, struct or type alias, found enum `Foo` Foo { i } => () //~ ERROR expected struct, variant or union type, found enum `Foo`
} }
} }

View file

@ -13,5 +13,5 @@ enum SomeEnum {
} }
fn main() { fn main() {
E { name: "foobar" }; //~ ERROR `E` does not name a structure E { name: "foobar" }; //~ ERROR unresolved struct, variant or union type `E`
} }

View file

@ -11,5 +11,6 @@
mod MyMod {} mod MyMod {}
fn main() { fn main() {
let myVar = MyMod { T: 0 }; //~ ERROR `MyMod` does not name a struct or a struct variant let myVar = MyMod { T: 0 };
//~^ ERROR expected struct, variant or union type, found module `MyMod`
} }

View file

@ -11,6 +11,6 @@
fn main() { fn main() {
match 'a' { match 'a' {
char{ch} => true char{ch} => true
//~^ ERROR expected variant, struct or type alias, found builtin type `char` //~^ ERROR expected struct, variant or union type, found builtin type `char`
}; };
} }

View file

@ -11,12 +11,12 @@
mod A {} mod A {}
fn main() { fn main() {
let u = A { x: 1 }; //~ ERROR `A` does not name a struct or a struct variant let u = A { x: 1 }; //~ ERROR expected struct, variant or union type, found module `A`
let v = u32 { x: 1 }; //~ ERROR `u32` does not name a struct or a struct variant let v = u32 { x: 1 }; //~ ERROR expected struct, variant or union type, found builtin type `u32`
match () { match () {
A { x: 1 } => {} A { x: 1 } => {}
//~^ ERROR expected variant, struct or type alias, found module `A` //~^ ERROR expected struct, variant or union type, found module `A`
u32 { x: 1 } => {} u32 { x: 1 } => {}
//~^ ERROR expected variant, struct or type alias, found builtin type `u32` //~^ ERROR expected struct, variant or union type, found builtin type `u32`
} }
} }

View file

@ -10,7 +10,7 @@
struct T { i: i32 } struct T { i: i32 }
fn f<T>() { fn f<T>() {
let t = T { i: 0 }; //~ ERROR `T` does not name a struct or a struct variant let t = T { i: 0 }; //~ ERROR expected struct, variant or union type, found type parameter `T`
} }
mod Foo { mod Foo {

View file

@ -8,8 +8,14 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
fn main () { // issue #36286
let x = Foo { x: 1, y: 2 };
//~^ ERROR E0422 struct S<T: Clone> { a: T }
//~| NOTE not a structure
struct NoClone;
type A = S<NoClone>;
fn main() {
let s = A { a: NoClone };
//~^ ERROR the trait bound `NoClone: std::clone::Clone` is not satisfied
} }

View file

@ -0,0 +1,48 @@
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
struct S;
trait Tr {
type A;
}
impl Tr for S {
type A = S;
}
fn f<T: Tr>() {
let s = T::A {};
//~^ ERROR expected struct, variant or union type, found associated type `<T as Tr>::A`
let z = T::A::<u8> {};
//~^ ERROR expected struct, variant or union type, found associated type `<T as Tr>::A`
//~| ERROR type parameters are not allowed on this type
match S {
T::A {} => {}
//~^ ERROR expected struct, variant or union type, found associated type `<T as Tr>::A`
}
}
fn g<T: Tr<A = S>>() {
let s = T::A {}; // OK
let z = T::A::<u8> {}; //~ ERROR type parameters are not allowed on this type
match S {
T::A {} => {} // OK
}
}
fn main() {
let s = S::A {}; //~ ERROR ambiguous associated type
let z = S::A::<u8> {}; //~ ERROR ambiguous associated type
//~^ ERROR type parameters are not allowed on this type
match S {
S::A {} => {} //~ ERROR ambiguous associated type
}
}

View file

@ -12,6 +12,5 @@ trait TraitNotAStruct {}
fn main() { fn main() {
TraitNotAStruct{ value: 0 }; TraitNotAStruct{ value: 0 };
//~^ ERROR: `TraitNotAStruct` does not name a struct or a struct variant [E0071] //~^ ERROR expected struct, variant or union type, found trait `TraitNotAStruct`
//~| NOTE not a struct
} }

View file

@ -51,4 +51,7 @@ fn main() {
if let None::<u8> = Some(8) { if let None::<u8> = Some(8) {
panic!(); panic!();
} }
if let None::<u8> { .. } = Some(8) {
panic!();
}
} }

View file

@ -8,30 +8,28 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
struct S; struct S<T, U = u16> {
a: T,
b: U,
}
trait Tr { trait Tr {
type A; type A;
} }
impl Tr for u8 {
impl Tr for S { type A = S<u8, u16>;
type A = S;
} }
fn f<T: Tr>() { fn f<T: Tr<A = S<u8>>>() {
match S { let s = T::A { a: 0, b: 1 };
T::A {} => {} //~ ERROR `T::A` does not name a struct or a struct variant match s {
} T::A { a, b } => {
} assert_eq!(a, 0);
assert_eq!(b, 1);
fn g<T: Tr<A = S>>() { }
match S {
T::A {} => {} //~ ERROR `T::A` does not name a struct or a struct variant
} }
} }
fn main() { fn main() {
match S { f::<u8>();
S::A {} => {} //~ ERROR ambiguous associated type
}
} }