]> git.lizzy.rs Git - rust.git/commitdiff
Preparations and cleanup
authorVadim Petrochenkov <vadim.petrochenkov@gmail.com>
Wed, 14 Sep 2016 21:51:46 +0000 (00:51 +0300)
committerVadim Petrochenkov <vadim.petrochenkov@gmail.com>
Thu, 27 Oct 2016 19:14:41 +0000 (22:14 +0300)
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.

29 files changed:
src/librustc/middle/expr_use_visitor.rs
src/librustc/ty/mod.rs
src/librustc/util/ppaux.rs
src/librustc_passes/consts.rs
src/librustc_resolve/diagnostics.rs
src/librustc_resolve/lib.rs
src/librustc_save_analysis/dump_visitor.rs
src/librustc_typeck/astconv.rs
src/librustc_typeck/check/_match.rs
src/librustc_typeck/check/mod.rs
src/librustc_typeck/diagnostics.rs
src/test/compile-fail-fulldeps/issue-18986.rs
src/test/compile-fail/E0071.rs
src/test/compile-fail/E0422.rs [deleted file]
src/test/compile-fail/enums-are-namespaced-xc.rs
src/test/compile-fail/issue-16058.rs
src/test/compile-fail/issue-17001.rs
src/test/compile-fail/issue-17405.rs
src/test/compile-fail/issue-17518.rs
src/test/compile-fail/issue-21449.rs
src/test/compile-fail/issue-26459.rs
src/test/compile-fail/issue-27815.rs
src/test/compile-fail/lexical-scopes.rs
src/test/compile-fail/struct-pat-associated-path.rs [deleted file]
src/test/compile-fail/struct-path-alias-bounds.rs [new file with mode: 0644]
src/test/compile-fail/struct-path-associated-type.rs [new file with mode: 0644]
src/test/compile-fail/trait-as-struct-constructor.rs
src/test/run-pass/issue-22546.rs
src/test/run-pass/struct-path-associated-type.rs [new file with mode: 0644]

index 799c02b740310cad9bbd78e66af61b94ad3f6251..c37b6df369dfcf46ef302b40850a8874aecad116 100644 (file)
@@ -1017,7 +1017,7 @@ fn walk_pat(&mut self, cmt_discr: mc::cmt<'tcx>, pat: &hir::Pat, match_mode: Mat
                     delegate.matched_pat(pat, downcast_cmt, match_mode);
                 }
                 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);
                     delegate.matched_pat(pat, cmt_pat, match_mode);
                 }
index f65976a8c110b17382fa8722ad7d0d1f14e25c45..96700a8da86a3c1aa36ee8d47b12137044e2e679 100644 (file)
@@ -1698,7 +1698,7 @@ pub fn variant_of_def(&self, def: Def) -> &VariantDefData<'gcx, 'container> {
         match def {
             Def::Variant(vid) | Def::VariantCtor(vid, ..) => self.variant_with_id(vid),
             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)
         }
     }
index af92569cc350c0ceb0ede0caab46185a0bf3e9be..c0b5969fa95986e10e8a9c14815da177023e2e8a 100644 (file)
@@ -14,7 +14,7 @@
 use ty::{TyBool, TyChar, TyAdt};
 use ty::{TyError, TyStr, TyArray, TySlice, TyFloat, TyFnDef, TyFnPtr};
 use ty::{TyParam, TyRawPtr, TyRef, TyNever, TyTuple};
-use ty::TyClosure;
+use ty::{TyClosure, TyProjection, TyAnon};
 use ty::{TyBox, TyTrait, TyInt, TyUint, TyInfer};
 use ty::{self, Ty, TyCtxt, TypeFoldable};
 use ty::fold::{TypeFolder, TypeVisitor};
@@ -802,6 +802,34 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
     }
 }
 
+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> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match *self {
@@ -879,8 +907,8 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                 })
             }
             TyTrait(ref data) => write!(f, "{}", data),
-            ty::TyProjection(ref data) => write!(f, "{}", data),
-            ty::TyAnon(def_id, substs) => {
+            TyProjection(ref data) => write!(f, "{}", data),
+            TyAnon(def_id, substs) => {
                 ty::tls::with(|tcx| {
                     // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
                     // by looking up the projections associated with the def_id.
index ee731dd042e4fe0c6d4f5ec027097f1e429e3729..8ad4d7f57a6f0a4505c5116654acfc2b5de07fd3 100644 (file)
@@ -565,9 +565,11 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node
             }
         }
         hir::ExprStruct(..) => {
-            // unsafe_cell_type doesn't necessarily exist with no_core
-            if Some(v.tcx.expect_def(e.id).def_id()) == v.tcx.lang_items.unsafe_cell_type() {
-                v.add_qualif(ConstQualif::MUTABLE_MEM);
+            if let ty::TyAdt(adt, ..) = v.tcx.expr_ty(e).sty {
+                // unsafe_cell_type doesn't necessarily exist with no_core
+                if Some(adt.did) == v.tcx.lang_items.unsafe_cell_type() {
+                    v.add_qualif(ConstQualif::MUTABLE_MEM);
+                }
             }
         }
 
index f2a5aedbb3ab463cbe2f12d10ed7c3e360b8b537..1fb5db05dd5088e0b7c8f55942f5a3b496537024 100644 (file)
@@ -860,31 +860,6 @@ fn foo(f: i32, g: i32) {} // ok!
 ```
 "##,
 
-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##"
 A `struct` variant name was used like a function name.
 
@@ -1503,6 +1478,7 @@ macro_rules! drink {
 //  E0419, merged into 531
 //  E0420, merged into 532
 //  E0421, merged into 531
+//  E0422, merged into 531/532
     E0531, // unresolved pattern path kind `name`
     E0532, // expected pattern path kind, found another pattern path kind
 //  E0427, merged into 530
index 856eb348eaeec615cd44fff73d110046b6fd6a76..d4900be575873f993508b5f0a159fdc9eeca4512 100644 (file)
@@ -129,8 +129,6 @@ enum ResolutionError<'a> {
     IdentifierBoundMoreThanOnceInParameterList(&'a str),
     /// error E0416: identifier is bound more than once in the same pattern
     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
     StructVariantUsedAsFunction(&'a str),
     /// 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
         }
-        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) => {
             let mut err = struct_span_err!(resolver.session,
                              span,
@@ -2383,6 +2372,18 @@ fn resolve_pattern_path<ExpectedFn>(&mut self,
         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,
                        pat: &Pat,
                        pat_src: PatternSource,
@@ -2460,13 +2461,7 @@ fn resolve_pattern(&mut self,
                 }
 
                 PatKind::Struct(ref path, ..) => {
-                    self.resolve_pattern_path(pat.id, None, path, TypeNS, |def| {
-                        match def {
-                            Def::Struct(..) | Def::Union(..) | Def::Variant(..) |
-                            Def::TyAlias(..) | Def::AssociatedTy(..) => true,
-                            _ => false,
-                        }
-                    }, "variant, struct or type alias");
+                    self.resolve_struct_path(pat.id, path);
                 }
 
                 _ => {}
@@ -3024,23 +3019,7 @@ fn resolve_expr(&mut self, expr: &Expr, parent: Option<&Expr>) {
             }
 
             ExprKind::Struct(ref path, ..) => {
-                // Resolve the path to the structure it goes to. We don't
-                // 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());
-                    }
-                }
+                self.resolve_struct_path(expr.id, path);
 
                 visit::walk_expr(self, expr);
             }
index 1c60ccb9765880f8a197eeeecb6171b6aa10f79a..53a5f3193231d9b600d3dccccb4b23cc4bef2176 100644 (file)
@@ -1493,7 +1493,8 @@ fn visit_arm(&mut self, arm: &ast::Arm) {
                 Def::StructCtor(..) | Def::VariantCtor(..) |
                 Def::Const(..) | Def::AssociatedConst(..) |
                 Def::Struct(..) | Def::Variant(..) |
-                Def::TyAlias(..) | Def::AssociatedTy(..) => {
+                Def::TyAlias(..) | Def::AssociatedTy(..) |
+                Def::SelfTy(..) => {
                     paths_to_process.push((id, p.clone(), Some(ref_kind)))
                 }
                 def => error!("unexpected definition kind when processing collected paths: {:?}",
index c137fca58afb961abf695875872b30fe927f7270..0c71b0424ae6d08cf40ec37493c640bc64a97ab9 100644 (file)
@@ -1484,7 +1484,8 @@ fn base_def_to_ty(&self,
                       def: Def,
                       opt_self_ty: Option<Ty<'tcx>>,
                       base_path_ref_id: ast::NodeId,
-                      base_segments: &[hir::PathSegment])
+                      base_segments: &[hir::PathSegment],
+                      permit_variants: bool)
                       -> Ty<'tcx> {
         let tcx = self.tcx();
 
@@ -1515,6 +1516,22 @@ fn base_def_to_ty(&self,
                                     did,
                                     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) => {
                 tcx.prohibit_type_params(base_segments);
 
@@ -1604,7 +1621,8 @@ pub fn finish_resolving_def_to_ty(&self,
                                       opt_self_ty: Option<Ty<'tcx>>,
                                       base_path_ref_id: ast::NodeId,
                                       base_segments: &[hir::PathSegment],
-                                      assoc_segments: &[hir::PathSegment])
+                                      assoc_segments: &[hir::PathSegment],
+                                      permit_variants: bool)
                                       -> (Ty<'tcx>, Def) {
         // Convert the base type.
         debug!("finish_resolving_def_to_ty(base_def={:?}, \
@@ -1619,7 +1637,8 @@ pub fn finish_resolving_def_to_ty(&self,
                                           base_def,
                                           opt_self_ty,
                                           base_path_ref_id,
-                                          base_segments);
+                                          base_segments,
+                                          permit_variants);
         debug!("finish_resolving_def_to_ty: base_def_to_ty returned {:?}", base_ty);
 
         // If any associated type segments remain, attempt to resolve them.
@@ -1775,7 +1794,8 @@ pub fn ast_ty_to_ty(&self, rscope: &RegionScope, ast_ty: &hir::Ty) -> Ty<'tcx> {
                                                                 opt_self_ty,
                                                                 ast_ty.id,
                                                                 &path.segments[..base_ty_end],
-                                                                &path.segments[base_ty_end..]);
+                                                                &path.segments[base_ty_end..],
+                                                                false);
 
                 // Write back the new resolution.
                 if path_res.depth != 0 {
index d3fef0711b246b37bfc8e26ca70dbf0e1d34d8d0..c842514227ca090b50b19ed6abc854a7189e3035 100644 (file)
@@ -489,8 +489,7 @@ fn check_pat_struct(&self,
                         expected: Ty<'tcx>) -> Ty<'tcx>
     {
         // 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,
-                                                                                 pat.span) {
+        let (variant, pat_ty) = if let Some(variant_ty) = self.check_struct_path(path, pat.id) {
             variant_ty
         } else {
             for field in fields {
index 21da8cd388cd97b2f171313e16c786b0cfab96ef..1c29867bfb8fa603ce371e6362ca7b3dda19ce42 100644 (file)
@@ -1686,41 +1686,6 @@ fn normalize_associated_type(&self,
                                        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) {
         self.write_ty(node_id, self.tcx.mk_nil());
     }
@@ -3252,46 +3217,56 @@ fn check_struct_fields_on_error(&self,
 
     pub fn check_struct_path(&self,
                          path: &hir::Path,
-                         node_id: ast::NodeId,
-                         span: Span)
+                         node_id: ast::NodeId)
                          -> 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 {
             Def::Err => {
                 self.set_tainted_by_errors();
                 return None;
             }
-            Def::Variant(did) => {
-                let type_did = self.tcx.parent_def_id(did).unwrap();
-                Some((type_did, self.tcx.expect_variant_def(def)))
-            }
-            Def::Struct(type_did) | Def::Union(type_did) => {
-                Some((type_did, self.tcx.expect_variant_def(def)))
+            Def::Variant(..) => {
+                match ty.sty {
+                    ty::TyAdt(adt, substs) => {
+                        Some((adt.variant_of_def(def), adt.did, substs))
+                    }
+                    _ => bug!("unexpected type: {:?}", ty.sty)
+                }
             }
-            Def::TyAlias(did) | Def::AssociatedTy(did) => {
-                match self.tcx.opt_lookup_item_type(did).map(|scheme| &scheme.ty.sty) {
-                    Some(&ty::TyAdt(adt, _)) if !adt.is_enum() => {
-                        Some((did, adt.struct_variant()))
+            Def::Struct(..) | Def::Union(..) | Def::TyAlias(..) |
+            Def::AssociatedTy(..) => {
+                match ty.sty {
+                    ty::TyAdt(adt, substs) if !adt.is_enum() => {
+                        Some((adt.struct_variant(), adt.did, substs))
                     }
                     _ => 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 &&
                     !self.tcx.sess.features.borrow().relaxed_adts {
                 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");
             }
-            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))
         } else {
             struct_span_err!(self.tcx.sess, path.span, E0071,
-                             "`{}` does not name a struct or a struct variant",
-                             pprust::path_to_string(path))
+                             "expected struct, variant or union type, found {} `{}`",
+                             ty.sty.descr(), ty)
                 .span_label(path.span, &format!("not a struct"))
                 .emit();
             None
@@ -3305,12 +3280,11 @@ fn check_expr_struct(&self,
                          base_expr: &'gcx Option<P<hir::Expr>>) -> Ty<'tcx>
     {
         // Find the relevant variant
-        let (variant, struct_ty) = if let Some(variant_ty) = self.check_struct_path(path, expr.id,
-                                                                                    expr.span) {
+        let (variant, struct_ty) = if let Some(variant_ty) = self.check_struct_path(path, expr.id) {
             variant_ty
         } else {
             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,
@@ -3805,7 +3779,7 @@ fn check_expr_kind(&self,
                               }
                           }
                           err.emit();
-                          self.tcx().types.err
+                          self.tcx.types.err
                       }
                   }
               }
@@ -3815,29 +3789,26 @@ fn check_expr_kind(&self,
 
     // Finish resolving a path in a struct expression or pattern `S::A { .. }` if necessary.
     // The newly resolved definition is written into `def_map`.
-    pub fn finish_resolving_struct_path(&self,
-                                        path: &hir::Path,
-                                        node_id: ast::NodeId,
-                                        span: Span)
-                                        -> Def
+    fn finish_resolving_struct_path(&self,
+                                    path: &hir::Path,
+                                    node_id: ast::NodeId)
+                                    -> (Def, Ty<'tcx>)
     {
-        let path_res = self.tcx().expect_resolution(node_id);
-        if path_res.depth == 0 {
-            // If fully resolved already, we don't have to do anything.
-            path_res.base_def
-        } else {
-            let base_ty_end = path.segments.len() - path_res.depth;
-            let (_ty, def) = AstConv::finish_resolving_def_to_ty(self, self, span,
-                                                                 PathParamMode::Optional,
-                                                                 path_res.base_def,
-                                                                 None,
-                                                                 node_id,
-                                                                 &path.segments[..base_ty_end],
-                                                                 &path.segments[base_ty_end..]);
-            // Write back the new resolution.
-            self.tcx().def_map.borrow_mut().insert(node_id, PathResolution::new(def));
-            def
+        let path_res = self.tcx.expect_resolution(node_id);
+        let base_ty_end = path.segments.len() - path_res.depth;
+        let (ty, def) = AstConv::finish_resolving_def_to_ty(self, self, path.span,
+                                                            PathParamMode::Optional,
+                                                            path_res.base_def,
+                                                            None,
+                                                            node_id,
+                                                            &path.segments[..base_ty_end],
+                                                            &path.segments[base_ty_end..],
+                                                            true);
+        // Write back the new resolution.
+        if path_res.depth != 0 {
+            self.tcx.def_map.borrow_mut().insert(node_id, PathResolution::new(def));
         }
+        (def, ty)
     }
 
     // Resolve associated value path into a base type and associated constant or method definition.
@@ -3849,7 +3820,7 @@ pub fn resolve_ty_and_def_ufcs<'b>(&self,
                                        span: Span)
                                        -> (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 fully resolved already, we don't have to do anything.
             (path_res.base_def, opt_self_ty, &path.segments)
@@ -3863,7 +3834,8 @@ pub fn resolve_ty_and_def_ufcs<'b>(&self,
                                                                  opt_self_ty,
                                                                  node_id,
                                                                  &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.
             let item_segment = path.segments.last().unwrap();
@@ -3883,7 +3855,7 @@ pub fn resolve_ty_and_def_ufcs<'b>(&self,
             };
 
             // 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))
         }
     }
@@ -4308,7 +4280,6 @@ pub fn instantiate_value_path(&self,
         // the referenced item.
         let ty_substituted = self.instantiate_type_scheme(span, &substs, &scheme.ty);
 
-
         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`
             // is inherent, there is no `Self` parameter, instead, the impl needs
index 189f8490f6c1d62d75e430e10e381d53c8029560..7dd850180d44206ffd167ee32ff6ee6558867274 100644 (file)
@@ -895,17 +895,14 @@ fn some_func(x: &mut i32) {
 
 E0071: r##"
 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:
 
 ```compile_fail,E0071
-enum Foo { FirstValue(i32) };
-
-let u = Foo::FirstValue { value: 0 }; // error: Foo::FirstValue
-                                         // 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.
+type U32 = u32;
+let t = U32 { value: 4 }; // error: expected struct, variant or union type,
+                          // found builtin type `u32`
 ```
 
 To fix this, ensure that the name was correctly spelled, and that
index 3c32cb947b382f1107473fd6d81d0437c0ca927e..95af37605441da366b6a6ada5171c7fe024ffef2 100644 (file)
@@ -15,6 +15,6 @@
 
 fn main() {
     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`
     }
 }
index c13ba7bf136712efd1cb50732de9e8a36b81688e..95653ae83e7cd6080fcd0142a727db746168d51c 100644 (file)
@@ -9,13 +9,10 @@
 // except according to those terms.
 
 enum Foo {}
+type FooAlias = Foo;
 
 fn main() {
-    let u = Foo { value: 0 };
-    //~^ ERROR `Foo` does not name a struct or a struct variant [E0071]
-    //~| NOTE not a struct
-
-    let t = u32 { value: 4 };
-    //~^ ERROR `u32` does not name a struct or a struct variant [E0071]
+    let u = FooAlias { value: 0 };
+    //~^ ERROR expected struct, variant or union type, found enum `Foo` [E0071]
     //~| NOTE not a struct
 }
diff --git a/src/test/compile-fail/E0422.rs b/src/test/compile-fail/E0422.rs
deleted file mode 100644 (file)
index 61e96b8..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-// 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.
-
-fn main () {
-    let x = Foo { x: 1, y: 2 };
-    //~^ ERROR E0422
-    //~| NOTE not a structure
-}
index 5315e6c834ab3a629c7f5ac2cdc2a93888710c96..02939565f69cd0417b160218761931fab61a05f7 100644 (file)
@@ -14,5 +14,6 @@
 fn main() {
     let _ = namespaced_enums::A; //~ 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`
 }
index 671232e701f872b33721803aba16349e5ca33ed1..92c1e4b5f5060810c5bb8da8e6cd39b8d7baa19f 100644 (file)
@@ -16,7 +16,7 @@ pub struct GslResult {
 
 impl 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,
             err: 0f64
         }
index 218f68714ff929821d1f9b5a975fa7ea0634afd8..413e8b464fff78a2aacbe103f7e0651f970407d2 100644 (file)
@@ -11,5 +11,5 @@
 mod foo {}
 
 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`
 }
index 2f2c252b947c90f38994c142985e6ae3fdd8cdb1..5a6bd5ed588a676d6ecfcecc944f9c10970c209c 100644 (file)
@@ -14,6 +14,6 @@ enum Foo {
 
 fn main() {
     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`
     }
 }
index 0410fadeb7892b3fddab9b8f031c365376c71914..2113e38c45cc38aab2c7e1bf9413ef63ad08d00f 100644 (file)
@@ -13,5 +13,5 @@ enum SomeEnum {
 }
 
 fn main() {
-    E { name: "foobar" }; //~ ERROR `E` does not name a structure
+    E { name: "foobar" }; //~ ERROR unresolved struct, variant or union type `E`
 }
index 090b8a0d16e64ca9a890fde406512ce8d22c82bb..cc44cf88f09bd97b0d5364052265657c3f89e2d7 100644 (file)
@@ -11,5 +11,6 @@
 mod MyMod {}
 
 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`
 }
index 24b39eeff0f791c0e3508e77c6e99e82d11ec383..8be3d88bd5c8f5bcfdbbf24fd16d895ed77f411a 100644 (file)
@@ -11,6 +11,6 @@
 fn main() {
     match 'a' {
         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`
     };
 }
index 33930d1db1476dcaa1995027ef481dec3f5ed3de..d9840abf0ca77a371182b9f69e33e4f67251fbe5 100644 (file)
 mod A {}
 
 fn main() {
-    let u = A { x: 1 }; //~ ERROR `A` does not name a struct or a struct variant
-    let v = u32 { x: 1 }; //~ ERROR `u32` 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 expected struct, variant or union type, found builtin type `u32`
     match () {
         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 } => {}
-        //~^ ERROR expected variant, struct or type alias, found builtin type `u32`
+        //~^ ERROR expected struct, variant or union type, found builtin type `u32`
     }
 }
index 505a91f223cc6ceb99afb37edf5540b923105301..1ab59e790d7ee5975a6a41524625763b08c24930 100644 (file)
@@ -10,7 +10,7 @@
 
 struct T { i: i32 }
 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 {
diff --git a/src/test/compile-fail/struct-pat-associated-path.rs b/src/test/compile-fail/struct-pat-associated-path.rs
deleted file mode 100644 (file)
index d3f840f..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-// 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>() {
-    match S {
-        T::A {} => {} //~ ERROR `T::A` does not name a struct or a struct variant
-    }
-}
-
-fn g<T: Tr<A = S>>() {
-    match S {
-        T::A {} => {} //~ ERROR `T::A` does not name a struct or a struct variant
-    }
-}
-
-fn main() {
-    match S {
-        S::A {} => {} //~ ERROR ambiguous associated type
-    }
-}
diff --git a/src/test/compile-fail/struct-path-alias-bounds.rs b/src/test/compile-fail/struct-path-alias-bounds.rs
new file mode 100644 (file)
index 0000000..1b6e51e
--- /dev/null
@@ -0,0 +1,21 @@
+// 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.
+
+// issue #36286
+
+struct S<T: Clone> { a: T }
+
+struct NoClone;
+type A = S<NoClone>;
+
+fn main() {
+    let s = A { a: NoClone };
+    //~^ ERROR the trait bound `NoClone: std::clone::Clone` is not satisfied
+}
diff --git a/src/test/compile-fail/struct-path-associated-type.rs b/src/test/compile-fail/struct-path-associated-type.rs
new file mode 100644 (file)
index 0000000..2f7330c
--- /dev/null
@@ -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
+    }
+}
index c78eebddbfdb80051d8b5be9a4150f51df653000..49d58580da52ddb34f353c6b7df55e0ed655865d 100644 (file)
@@ -12,6 +12,5 @@ trait TraitNotAStruct {}
 
 fn main() {
     TraitNotAStruct{ value: 0 };
-    //~^ ERROR: `TraitNotAStruct` does not name a struct or a struct variant [E0071]
-    //~| NOTE not a struct
+    //~^ ERROR expected struct, variant or union type, found trait `TraitNotAStruct`
 }
index b3cb8a78213b8ff64a0f857483bb0d177ff3702a..fd9eb1f87c7433bee6b9bad525cfce1b06f65327 100644 (file)
@@ -51,4 +51,7 @@ fn main() {
     if let None::<u8> = Some(8) {
         panic!();
     }
+    if let None::<u8> { .. } = Some(8) {
+        panic!();
+    }
 }
diff --git a/src/test/run-pass/struct-path-associated-type.rs b/src/test/run-pass/struct-path-associated-type.rs
new file mode 100644 (file)
index 0000000..b033ed5
--- /dev/null
@@ -0,0 +1,35 @@
+// 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<T, U = u16> {
+    a: T,
+    b: U,
+}
+
+trait Tr {
+    type A;
+}
+impl Tr for u8 {
+    type A = S<u8, u16>;
+}
+
+fn f<T: Tr<A = S<u8>>>() {
+    let s = T::A { a: 0, b: 1 };
+    match s {
+        T::A { a, b } => {
+            assert_eq!(a, 0);
+            assert_eq!(b, 1);
+        }
+    }
+}
+
+fn main() {
+    f::<u8>();
+}