about summary refs log tree commit diff
diff options
context:
space:
mode:
authorVadim Petrochenkov <vadim.petrochenkov@gmail.com>2016-06-11 18:47:47 +0300
committerVadim Petrochenkov <vadim.petrochenkov@gmail.com>2016-07-08 12:42:57 +0300
commita397b60ebba531fb4de7e88111e0d489e44c549e (patch)
tree79dc821f33f2ba03e767bbcc28ffb86d37f58bd0
parent49ea3d48a26c1325dd584c8420227f6e35721f66 (diff)
downloadrust-a397b60ebba531fb4de7e88111e0d489e44c549e.tar.gz
rust-a397b60ebba531fb4de7e88111e0d489e44c549e.zip
Resolve partially resolved paths in struct patterns/expressions
Treat Def::Err correctly in struct patterns
Make instantiate_path and instantiate_type a bit closer to each other
-rw-r--r--src/librustc/hir/pat_util.rs15
-rw-r--r--src/librustc_typeck/check/_match.rs81
-rw-r--r--src/librustc_typeck/check/mod.rs196
-rw-r--r--src/librustc_typeck/diagnostics.rs28
-rw-r--r--src/test/compile-fail/E0163.rs20
-rw-r--r--src/test/compile-fail/issue-16058.rs2
-rw-r--r--src/test/compile-fail/issue-17001.rs2
-rw-r--r--src/test/compile-fail/issue-17405.rs1
-rw-r--r--src/test/compile-fail/issue-21449.rs2
-rw-r--r--src/test/compile-fail/issue-26459.rs1
-rw-r--r--src/test/compile-fail/issue-27815.rs6
-rw-r--r--src/test/compile-fail/issue-27831.rs2
-rw-r--r--src/test/compile-fail/issue-4736.rs2
-rw-r--r--src/test/compile-fail/lexical-scopes.rs2
-rw-r--r--src/test/compile-fail/trait-as-struct-constructor.rs2
15 files changed, 156 insertions, 206 deletions
diff --git a/src/librustc/hir/pat_util.rs b/src/librustc/hir/pat_util.rs
index 234edc647f0..a26480114bc 100644
--- a/src/librustc/hir/pat_util.rs
+++ b/src/librustc/hir/pat_util.rs
@@ -67,21 +67,6 @@ pub fn pat_is_refutable(dm: &DefMap, pat: &hir::Pat) -> bool {
     }
 }
 
-pub fn pat_is_variant_or_struct(dm: &DefMap, pat: &hir::Pat) -> bool {
-    match pat.node {
-        PatKind::TupleStruct(..) |
-        PatKind::Path(..) |
-        PatKind::Struct(..) => {
-            match dm.get(&pat.id).map(|d| d.full_def()) {
-                Some(Def::Variant(..)) | Some(Def::Struct(..)) |
-                Some(Def::TyAlias(..)) | Some(Def::AssociatedTy(..)) => true,
-                _ => false
-            }
-        }
-        _ => false
-    }
-}
-
 pub fn pat_is_const(dm: &DefMap, pat: &hir::Pat) -> bool {
     match pat.node {
         PatKind::Path(..) | PatKind::QPath(..) => {
diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs
index 82c676adc70..4f7c8fbabdb 100644
--- a/src/librustc_typeck/check/_match.rs
+++ b/src/librustc_typeck/check/_match.rs
@@ -489,39 +489,35 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
 }
 
 impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
-    pub fn check_pat_struct(&self, pat: &'gcx hir::Pat,
-                            path: &hir::Path, fields: &'gcx [Spanned<hir::FieldPat>],
-                            etc: bool, expected: Ty<'tcx>) {
-        let tcx = self.tcx;
-
-        let def = tcx.expect_def(pat.id);
-        let variant = match self.def_struct_variant(def, path.span) {
-            Some((_, variant)) => variant,
-            None => {
-                let name = pprust::path_to_string(path);
-                span_err!(tcx.sess, pat.span, E0163,
-                          "`{}` does not name a struct or a struct variant", name);
-                self.write_error(pat.id);
-
-                for field in fields {
-                    self.check_pat(&field.node.pat, tcx.types.err);
-                }
-                return;
+    fn check_pat_struct(&self,
+                        pat: &'gcx hir::Pat,
+                        path: &hir::Path,
+                        fields: &'gcx [Spanned<hir::FieldPat>],
+                        etc: bool,
+                        expected: Ty<'tcx>)
+    {
+        // Resolve the path and check the definition for errors.
+        let def = self.finish_resolving_struct_path(path, pat.id, pat.span);
+        let variant = if let Some(variant) = self.check_struct_path(def, path, pat.span) {
+            variant
+        } else {
+            self.write_error(pat.id);
+            for field in fields {
+                self.check_pat(&field.node.pat, self.tcx.types.err);
             }
+            return;
         };
 
-        let pat_ty = self.instantiate_type(def.def_id(), path);
-        let item_substs = match pat_ty.sty {
+        // Type check the path.
+        let pat_ty = self.instantiate_type_path(def.def_id(), path, pat.id);
+        self.demand_eqtype(pat.span, expected, pat_ty);
+
+        // Type check subpatterns.
+        let substs = match pat_ty.sty {
             ty::TyStruct(_, substs) | ty::TyEnum(_, substs) => substs,
             _ => span_bug!(pat.span, "struct variant is not an ADT")
         };
-        self.demand_eqtype(pat.span, expected, pat_ty);
-        self.check_struct_pat_fields(pat.span, fields, variant, &item_substs, etc);
-
-        self.write_ty(pat.id, pat_ty);
-        self.write_substs(pat.id, ty::ItemSubsts {
-            substs: item_substs
-        });
+        self.check_struct_pat_fields(pat.span, fields, variant, substs, etc);
     }
 
     fn check_pat_path(&self,
@@ -539,8 +535,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         };
 
         // Resolve the path and check the definition for errors.
-        let (def, opt_ty, segments) = self.resolve_ty_and_def_ufcs(tcx.expect_resolution(pat.id),
-                                                            opt_self_ty, path, pat.span, pat.id);
+        let (def, opt_ty, segments) = self.resolve_ty_and_def_ufcs(opt_self_ty, path,
+                                                                   pat.id, pat.span);
         match def {
             Def::Err => {
                 self.set_tainted_by_errors();
@@ -565,8 +561,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         // Type check the path.
         let scheme = tcx.lookup_item_type(def.def_id());
         let predicates = tcx.lookup_predicates(def.def_id());
-        self.instantiate_path(segments, scheme, &predicates, opt_ty, def, pat.span, pat.id);
-        let pat_ty = self.node_ty(pat.id);
+        let pat_ty = self.instantiate_value_path(segments, scheme, &predicates,
+                                                 opt_ty, def, pat.span, pat.id);
         self.demand_suptype(pat.span, expected, pat_ty);
     }
 
@@ -597,9 +593,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         };
 
         // Resolve the path and check the definition for errors.
-        let (def, opt_ty, segments) = self.resolve_ty_and_def_ufcs(tcx.expect_resolution(pat.id),
-                                                                   None, path, pat.span, pat.id);
-        match def {
+        let (def, opt_ty, segments) = self.resolve_ty_and_def_ufcs(None, path, pat.id, pat.span);
+        let variant = match def {
             Def::Err => {
                 self.set_tainted_by_errors();
                 on_error();
@@ -609,10 +604,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                 report_unexpected_def(false);
                 return;
             }
-            Def::Variant(..) | Def::Struct(..) => {} // OK
+            Def::Variant(..) | Def::Struct(..) => {
+                tcx.expect_variant_def(def)
+            }
             _ => bug!("unexpected pattern definition {:?}", def)
-        }
-        let variant = tcx.expect_variant_def(def);
+        };
         if variant.kind == VariantKind::Unit && subpats.is_empty() && ddpos.is_some() {
             // Matching unit structs with tuple variant patterns (`UnitVariant(..)`)
             // is allowed for backward compatibility.
@@ -633,20 +629,19 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
             scheme
         };
         let predicates = tcx.lookup_predicates(def.def_id());
-        self.instantiate_path(segments, scheme, &predicates, opt_ty, def, pat.span, pat.id);
-        let pat_ty = self.node_ty(pat.id);
+        let pat_ty = self.instantiate_value_path(segments, scheme, &predicates,
+                                                 opt_ty, def, pat.span, pat.id);
         self.demand_eqtype(pat.span, expected, pat_ty);
 
         // Type check subpatterns.
         if subpats.len() == variant.fields.len() ||
                 subpats.len() < variant.fields.len() && ddpos.is_some() {
-            let expected_substs = match pat_ty.sty {
-                ty::TyEnum(_, expected_substs) => expected_substs,
-                ty::TyStruct(_, expected_substs) => expected_substs,
+            let substs = match pat_ty.sty {
+                ty::TyStruct(_, substs) | ty::TyEnum(_, substs) => substs,
                 ref ty => bug!("unexpected pattern type {:?}", ty),
             };
             for (i, subpat) in subpats.iter().enumerate_and_adjust(variant.fields.len(), ddpos) {
-                let field_ty = self.field_ty(subpat.span, &variant.fields[i], expected_substs);
+                let field_ty = self.field_ty(subpat.span, &variant.fields[i], substs);
                 self.check_pat(&subpat, field_ty);
             }
         } else {
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 08a8b124b1c..929ab580fc3 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -1621,62 +1621,32 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
     ///
     /// Note that this function is only intended to be used with type-paths,
     /// not with value-paths.
-    pub fn instantiate_type(&self,
-                            did: DefId,
-                            path: &hir::Path)
-                            -> Ty<'tcx>
-    {
-        debug!("instantiate_type(did={:?}, path={:?})", did, path);
-        let type_scheme =
-            self.tcx.lookup_item_type(did);
-        let type_predicates =
-            self.tcx.lookup_predicates(did);
+    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 type_scheme = self.tcx.lookup_item_type(did);
+        let type_predicates = self.tcx.lookup_predicates(did);
         let substs = AstConv::ast_path_substs_for_ty(self, self,
                                                      path.span,
                                                      PathParamMode::Optional,
                                                      &type_scheme.generics,
                                                      path.segments.last().unwrap());
-        debug!("instantiate_type: ty={:?} substs={:?}", &type_scheme.ty, &substs);
-        let bounds =
-            self.instantiate_bounds(path.span, &substs, &type_predicates);
-        self.add_obligations_for_parameters(
-            traits::ObligationCause::new(
-                path.span,
-                self.body_id,
-                traits::ItemObligation(did)),
-            &bounds);
-
-        self.instantiate_type_scheme(path.span, &substs, &type_scheme.ty)
-    }
-
-    /// Return the dict-like variant corresponding to a given `Def`.
-    pub fn def_struct_variant(&self,
-                              def: Def,
-                              _span: Span)
-                              -> Option<(ty::AdtDef<'tcx>, ty::VariantDef<'tcx>)>
-    {
-        let (adt, variant) = match def {
-            Def::Variant(enum_id, variant_id) => {
-                let adt = self.tcx.lookup_adt_def(enum_id);
-                (adt, adt.variant_with_id(variant_id))
-            }
-            Def::Struct(did) | Def::TyAlias(did) => {
-                let typ = self.tcx.lookup_item_type(did);
-                if let ty::TyStruct(adt, _) = typ.ty.sty {
-                    (adt, adt.struct_variant())
-                } else {
-                    return None;
-                }
-            }
-            _ => return None
-        };
+        let substs = self.tcx.mk_substs(substs);
+        debug!("instantiate_type_path: ty={:?} substs={:?}", &type_scheme.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);
 
-        if variant.kind == ty::VariantKind::Struct ||
-           variant.kind == ty::VariantKind::Unit {
-            Some((adt, variant))
-        } else {
-            None
-        }
+        let ty_substituted = self.instantiate_type_scheme(path.span, substs, &type_scheme.ty);
+        self.write_ty(node_id, ty_substituted);
+        self.write_substs(node_id, ty::ItemSubsts {
+            substs: substs
+        });
+        ty_substituted
     }
 
     pub fn write_nil(&self, node_id: ast::NodeId) {
@@ -3151,34 +3121,54 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         }
     }
 
+    pub fn check_struct_path(&self,
+                         def: Def,
+                         path: &hir::Path,
+                         span: Span)
+                         -> Option<ty::VariantDef<'tcx>> {
+        let variant = match def {
+            Def::Err => {
+                self.set_tainted_by_errors();
+                return None;
+            }
+            Def::Variant(..) | Def::Struct(..) => {
+                Some(self.tcx.expect_variant_def(def))
+            }
+            Def::TyAlias(did) | Def::AssociatedTy(_, did) => {
+                if let ty::TyStruct(adt, _) = self.tcx.lookup_item_type(did).ty.sty {
+                    Some(adt.struct_variant())
+                } else {
+                    None
+                }
+            }
+            _ => None
+        };
+        if variant.is_none() || variant.unwrap().kind == ty::VariantKind::Tuple {
+            // Reject tuple structs for now, braced and unit structs are allowed.
+            span_err!(self.tcx.sess, span, E0071,
+                      "`{}` does not name a struct or a struct variant",
+                      pprust::path_to_string(path));
+            return None;
+        }
+        variant
+    }
+
     fn check_expr_struct(&self,
                          expr: &hir::Expr,
                          path: &hir::Path,
                          fields: &'gcx [hir::Field],
                          base_expr: &'gcx Option<P<hir::Expr>>)
     {
-        let tcx = self.tcx;
-
         // Find the relevant variant
-        let def = tcx.expect_def(expr.id);
-        if def == Def::Err {
-            self.set_tainted_by_errors();
+        let def = self.finish_resolving_struct_path(path, expr.id, expr.span);
+        let variant = if let Some(variant) = self.check_struct_path(def, path, expr.span) {
+            variant
+        } else {
             self.check_struct_fields_on_error(expr.id, fields, base_expr);
             return;
-        }
-        let variant = match self.def_struct_variant(def, path.span) {
-            Some((_, variant)) => variant,
-            None => {
-                span_err!(self.tcx.sess, path.span, E0071,
-                          "`{}` does not name a structure",
-                          pprust::path_to_string(path));
-                self.check_struct_fields_on_error(expr.id, fields, base_expr);
-                return;
-            }
         };
 
-        let expr_ty = self.instantiate_type(def.def_id(), path);
-        self.write_ty(expr.id, expr_ty);
+        let expr_ty = self.instantiate_type_path(def.def_id(), path, expr.id);
 
         self.check_expr_struct_fields(expr_ty, path.span, variant, fields,
                                       base_expr.is_none());
@@ -3190,13 +3180,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                         expr.id,
                         adt.struct_variant().fields.iter().map(|f| {
                             self.normalize_associated_types_in(
-                                expr.span, &f.ty(tcx, substs)
+                                expr.span, &f.ty(self.tcx, substs)
                             )
                         }).collect()
                     );
                 }
                 _ => {
-                    span_err!(tcx.sess, base_expr.span, E0436,
+                    span_err!(self.tcx.sess, base_expr.span, E0436,
                               "functional record update syntax requires a struct");
                 }
             }
@@ -3349,12 +3339,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
           }
           hir::ExprPath(ref opt_qself, ref path) => {
               let opt_self_ty = opt_qself.as_ref().map(|qself| self.to_ty(&qself.ty));
-              let (def, opt_ty, segments) = self.resolve_ty_and_def_ufcs(tcx.expect_resolution(id),
-                                                            opt_self_ty, path, expr.span, expr.id);
+              let (def, opt_ty, segments) = self.resolve_ty_and_def_ufcs(opt_self_ty, path,
+                                                                         expr.id, expr.span);
               if def != Def::Err {
                   let (scheme, predicates) = self.type_scheme_and_predicates_for_def(expr.span,
                                                                                      def);
-                  self.instantiate_path(segments, scheme, &predicates, opt_ty, def, expr.span, id);
+                  self.instantiate_value_path(segments, scheme, &predicates,
+                                              opt_ty, def, expr.span, id);
               } else {
                   self.set_tainted_by_errors();
                   self.write_error(id);
@@ -3695,18 +3686,45 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                expected);
     }
 
+    // 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
+    {
+        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
+        }
+    }
+
     // Resolve associated value path into a base type and associated constant or method definition.
     // The newly resolved definition is written into `def_map`.
     pub fn resolve_ty_and_def_ufcs<'b>(&self,
-                                       path_res: PathResolution,
                                        opt_self_ty: Option<Ty<'tcx>>,
                                        path: &'b hir::Path,
-                                       span: Span,
-                                       node_id: ast::NodeId)
+                                       node_id: ast::NodeId,
+                                       span: Span)
                                        -> (Def, Option<Ty<'tcx>>, &'b [hir::PathSegment])
     {
-        // If fully resolved already, we don't have to do anything.
+        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)
         } else {
             // Try to resolve everything except for the last segment as a type.
@@ -3975,15 +3993,16 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
 
     // Instantiates the given path, which must refer to an item with the given
     // number of type parameters and type.
-    pub fn instantiate_path(&self,
-                            segments: &[hir::PathSegment],
-                            type_scheme: TypeScheme<'tcx>,
-                            type_predicates: &ty::GenericPredicates<'tcx>,
-                            opt_self_ty: Option<Ty<'tcx>>,
-                            def: Def,
-                            span: Span,
-                            node_id: ast::NodeId) {
-        debug!("instantiate_path(path={:?}, def={:?}, node_id={}, type_scheme={:?})",
+    pub fn instantiate_value_path(&self,
+                                  segments: &[hir::PathSegment],
+                                  type_scheme: TypeScheme<'tcx>,
+                                  type_predicates: &ty::GenericPredicates<'tcx>,
+                                  opt_self_ty: Option<Ty<'tcx>>,
+                                  def: Def,
+                                  span: Span,
+                                  node_id: ast::NodeId)
+                                  -> Ty<'tcx> {
+        debug!("instantiate_value_path(path={:?}, def={:?}, node_id={}, type_scheme={:?})",
                segments,
                def,
                node_id,
@@ -4012,7 +4031,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         //    actually pass through this function, but rather the
         //    `ast_ty_to_ty` function in `astconv`. However, in the case
         //    of struct patterns (and maybe literals) we do invoke
-        //    `instantiate_path` to get the general type of an instance of
+        //    `instantiate_value_path` to get the general type of an instance of
         //    a struct. (In these cases, there are actually no type
         //    parameters permitted at present, but perhaps we will allow
         //    them in the future.)
@@ -4235,20 +4254,21 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                 }
                 Err(_) => {
                     span_bug!(span,
-                        "instantiate_path: (UFCS) {:?} was a subtype of {:?} but now is not?",
+                        "instantiate_value_path: (UFCS) {:?} was a subtype of {:?} but now is not?",
                         self_ty,
                         impl_ty);
                 }
             }
         }
 
-        debug!("instantiate_path: type of {:?} is {:?}",
+        debug!("instantiate_value_path: type of {:?} is {:?}",
                node_id,
                ty_substituted);
         self.write_ty(node_id, ty_substituted);
         self.write_substs(node_id, ty::ItemSubsts {
             substs: substs
         });
+        ty_substituted
     }
 
     /// Finds the parameters that the user provided and adds them to `substs`. If too many
diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs
index b4d1f710704..8769bc1a32b 100644
--- a/src/librustc_typeck/diagnostics.rs
+++ b/src/librustc_typeck/diagnostics.rs
@@ -1895,33 +1895,6 @@ fn my_start(argc: isize, argv: *const *const u8) -> isize {
 ```
 "##,
 
-E0163: r##"
-This error means that an attempt was made to match an enum variant as a
-struct type when the variant isn't a struct type:
-
-```compile_fail
-enum Foo { B(u32) }
-
-fn bar(foo: Foo) -> u32 {
-    match foo {
-        B{i} => i, // error E0163
-    }
-}
-```
-
-Try using `()` instead:
-
-```
-enum Foo { B(u32) }
-
-fn bar(foo: Foo) -> u32 {
-    match foo {
-        Foo::B(i) => i,
-    }
-}
-```
-"##,
-
 E0164: r##"
 This error means that an attempt was made to match a struct type enum
 variant as a non-struct type:
@@ -4070,6 +4043,7 @@ register_diagnostics! {
 //  E0129,
 //  E0141,
 //  E0159, // use of trait `{}` as struct constructor
+//  E0163, // merged into E0071
     E0167,
 //  E0168,
 //  E0173, // manual implementations of unboxed closure traits are experimental
diff --git a/src/test/compile-fail/E0163.rs b/src/test/compile-fail/E0163.rs
deleted file mode 100644
index 5cb6f4d2803..00000000000
--- a/src/test/compile-fail/E0163.rs
+++ /dev/null
@@ -1,20 +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.
-
-enum Foo { B(u32) }
-
-fn bar(foo: Foo) -> u32 {
-    match foo {
-        Foo::B { i } => i, //~ ERROR E0163
-    }
-}
-
-fn main() {
-}
diff --git a/src/test/compile-fail/issue-16058.rs b/src/test/compile-fail/issue-16058.rs
index 4637512216c..671232e701f 100644
--- a/src/test/compile-fail/issue-16058.rs
+++ b/src/test/compile-fail/issue-16058.rs
@@ -16,7 +16,7 @@ pub struct GslResult {
 
 impl GslResult {
     pub fn new() -> GslResult {
-        Result { //~ ERROR: `Result` does not name a structure
+        Result { //~ ERROR: `Result` does not name a struct or a struct variant
             val: 0f64,
             err: 0f64
         }
diff --git a/src/test/compile-fail/issue-17001.rs b/src/test/compile-fail/issue-17001.rs
index 0fee6dc7617..218f68714ff 100644
--- a/src/test/compile-fail/issue-17001.rs
+++ b/src/test/compile-fail/issue-17001.rs
@@ -11,5 +11,5 @@
 mod foo {}
 
 fn main() {
-    let p = foo { x: () }; //~ ERROR `foo` does not name a structure
+    let p = foo { x: () }; //~ ERROR `foo` does not name a struct or a struct variant
 }
diff --git a/src/test/compile-fail/issue-17405.rs b/src/test/compile-fail/issue-17405.rs
index db43c1cce99..2f2c252b947 100644
--- a/src/test/compile-fail/issue-17405.rs
+++ b/src/test/compile-fail/issue-17405.rs
@@ -15,6 +15,5 @@ enum Foo {
 fn main() {
     match Foo::Bar(1) {
         Foo { i } => () //~ ERROR expected variant, struct or type alias, found enum `Foo`
-        //~^ ERROR `Foo` does not name a struct or a struct variant
     }
 }
diff --git a/src/test/compile-fail/issue-21449.rs b/src/test/compile-fail/issue-21449.rs
index 93c4f4bfcef..090b8a0d16e 100644
--- a/src/test/compile-fail/issue-21449.rs
+++ b/src/test/compile-fail/issue-21449.rs
@@ -11,5 +11,5 @@
 mod MyMod {}
 
 fn main() {
-    let myVar = MyMod { T: 0 }; //~ ERROR `MyMod` does not name a structure
+    let myVar = MyMod { T: 0 }; //~ ERROR `MyMod` does not name a struct or a struct variant
 }
diff --git a/src/test/compile-fail/issue-26459.rs b/src/test/compile-fail/issue-26459.rs
index 6cadbef33e7..24b39eeff0f 100644
--- a/src/test/compile-fail/issue-26459.rs
+++ b/src/test/compile-fail/issue-26459.rs
@@ -12,6 +12,5 @@ fn main() {
     match 'a' {
         char{ch} => true
         //~^ ERROR expected variant, struct or type alias, found builtin type `char`
-        //~| ERROR `char` does not name a struct or a struct variant
     };
 }
diff --git a/src/test/compile-fail/issue-27815.rs b/src/test/compile-fail/issue-27815.rs
index d2f9abd2e31..7a329bac61b 100644
--- a/src/test/compile-fail/issue-27815.rs
+++ b/src/test/compile-fail/issue-27815.rs
@@ -11,12 +11,10 @@
 mod A {}
 
 fn main() {
-    let u = A { x: 1 }; //~ ERROR `A` does not name a structure
-    let v = u32 { x: 1 }; //~ ERROR `u32` does not name a structure
+    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
     match () {
         A { x: 1 } => {} //~ ERROR expected variant, struct or type alias, found module `A`
-        //~^ ERROR `A` does not name a struct or a struct variant
         u32 { x: 1 } => {} //~ ERROR expected variant, struct or type alias, found builtin type `u32
-        //~^ ERROR `u32` does not name a struct or a struct variant
     }
 }
diff --git a/src/test/compile-fail/issue-27831.rs b/src/test/compile-fail/issue-27831.rs
index d014c45ad2d..e20e6ea2319 100644
--- a/src/test/compile-fail/issue-27831.rs
+++ b/src/test/compile-fail/issue-27831.rs
@@ -18,7 +18,7 @@ enum Enum {
 
 fn main() {
     let x = Foo(1);
-    Foo { ..x }; //~ ERROR `Foo` does not name a structure
+    Foo { ..x }; //~ ERROR `Foo` does not name a struct or a struct variant
     let Foo { .. } = x; //~ ERROR `Foo` does not name a struct
 
     let x = Bar;
diff --git a/src/test/compile-fail/issue-4736.rs b/src/test/compile-fail/issue-4736.rs
index 843ff38df49..55983c672aa 100644
--- a/src/test/compile-fail/issue-4736.rs
+++ b/src/test/compile-fail/issue-4736.rs
@@ -11,5 +11,5 @@
 struct NonCopyable(());
 
 fn main() {
-    let z = NonCopyable{ p: () }; //~ ERROR `NonCopyable` does not name a structure
+    let z = NonCopyable{ p: () }; //~ ERROR `NonCopyable` does not name a struct or a struct variant
 }
diff --git a/src/test/compile-fail/lexical-scopes.rs b/src/test/compile-fail/lexical-scopes.rs
index dbcd3f32f3b..505a91f223c 100644
--- a/src/test/compile-fail/lexical-scopes.rs
+++ b/src/test/compile-fail/lexical-scopes.rs
@@ -10,7 +10,7 @@
 
 struct T { i: i32 }
 fn f<T>() {
-    let t = T { i: 0 }; //~ ERROR `T` does not name a structure
+    let t = T { i: 0 }; //~ ERROR `T` does not name a struct or a struct variant
 }
 
 mod Foo {
diff --git a/src/test/compile-fail/trait-as-struct-constructor.rs b/src/test/compile-fail/trait-as-struct-constructor.rs
index 67ccd6b7cd0..13fdaa302f7 100644
--- a/src/test/compile-fail/trait-as-struct-constructor.rs
+++ b/src/test/compile-fail/trait-as-struct-constructor.rs
@@ -12,5 +12,5 @@ trait TraitNotAStruct {}
 
 fn main() {
     TraitNotAStruct{ value: 0 };
-    //~^ ERROR: `TraitNotAStruct` does not name a structure [E0071]
+    //~^ ERROR: `TraitNotAStruct` does not name a struct or a struct variant [E0071]
 }