about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2015-11-28 00:45:34 +0000
committerbors <bors@rust-lang.org>2015-11-28 00:45:34 +0000
commite9ac44026d2d4ac11728263726505ea4cea3c1ff (patch)
tree84d2da81ff9bf40e61c38664ccabf1e07e0ce0e3
parentbac2b13a5a0132a020a3954031635fed65fd6c22 (diff)
parentaf96402cc88a40db4f61b22924bfeb24a53cf424 (diff)
downloadrust-e9ac44026d2d4ac11728263726505ea4cea3c1ff.tar.gz
rust-e9ac44026d2d4ac11728263726505ea4cea3c1ff.zip
Auto merge of #29383 - petrochenkov:empstr, r=pnkfelix
Fixes https://github.com/rust-lang/rust/issues/28692
Fixes https://github.com/rust-lang/rust/issues/28992
Fixes some other similar issues (see the tests)

[breaking-change], needs crater run (cc @brson or @alexcrichton )

The pattern with parens `UnitVariant(..)` for unit variants seems to be popular in rustc (see the second commit), but mostly used by one person (@nikomatsakis), according to git blame. If it causes breakage on crates.io I'll add an exceptional case for it.
-rw-r--r--src/librustc/middle/intrinsicck.rs3
-rw-r--r--src/librustc/middle/mem_categorization.rs2
-rw-r--r--src/librustc/middle/resolve_lifetime.rs4
-rw-r--r--src/librustc/middle/traits/coherence.rs2
-rw-r--r--src/librustc/middle/traits/select.rs10
-rw-r--r--src/librustc/middle/ty/outlives.rs8
-rw-r--r--src/librustc_borrowck/borrowck/check_loans.rs16
-rw-r--r--src/librustc_borrowck/borrowck/gather_loans/restrictions.rs2
-rw-r--r--src/librustc_borrowck/borrowck/mod.rs6
-rw-r--r--src/librustc_mir/build/matches/simplify.rs2
-rw-r--r--src/librustc_mir/hair/cx/expr.rs2
-rw-r--r--src/librustc_resolve/lib.rs2
-rw-r--r--src/librustc_trans/trans/type_of.rs4
-rw-r--r--src/librustc_typeck/check/_match.rs84
-rw-r--r--src/librustc_typeck/check/method/probe.rs2
-rw-r--r--src/librustc_typeck/check/mod.rs2
-rw-r--r--src/librustc_typeck/coherence/mod.rs2
-rw-r--r--src/librustdoc/clean/mod.rs4
-rw-r--r--src/test/compile-fail/empty-struct-braces-gate-2.rs17
-rw-r--r--src/test/compile-fail/empty-struct-braces-pat-1.rs10
-rw-r--r--src/test/compile-fail/empty-struct-braces-pat-2.rs12
-rw-r--r--src/test/compile-fail/empty-struct-braces-pat-3.rs29
-rw-r--r--src/test/compile-fail/empty-struct-unit-pat.rs21
-rw-r--r--src/test/compile-fail/issue-19086.rs2
-rw-r--r--src/test/compile-fail/issue-27831.rs2
-rw-r--r--src/test/compile-fail/issue-28992-empty.rs26
-rw-r--r--src/test/compile-fail/match-pattern-field-mismatch-2.rs1
-rw-r--r--src/test/compile-fail/move-fragments-2.rs8
-rw-r--r--src/test/compile-fail/move-fragments-3.rs2
-rw-r--r--src/test/compile-fail/pattern-error-continue.rs1
-rw-r--r--src/test/run-pass/empty-struct-braces.rs20
-rw-r--r--src/test/run-pass/issue-14308.rs9
-rw-r--r--src/test/run-pass/issue-1701.rs2
33 files changed, 192 insertions, 127 deletions
diff --git a/src/librustc/middle/intrinsicck.rs b/src/librustc/middle/intrinsicck.rs
index 11a28c0b5ea..48d7f44063e 100644
--- a/src/librustc/middle/intrinsicck.rs
+++ b/src/librustc/middle/intrinsicck.rs
@@ -225,11 +225,10 @@ impl<'a, 'tcx, 'v> Visitor<'v> for IntrinsicCheckingVisitor<'a, 'tcx> {
                 intravisit::walk_fn(self, fk, fd, b, s);
                 self.param_envs.pop();
             }
-            FnKind::Closure(..) => {
+            FnKind::Closure => {
                 intravisit::walk_fn(self, fk, fd, b, s);
             }
         }
-
     }
 
     fn visit_expr(&mut self, expr: &hir::Expr) {
diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs
index d8031e3134d..70ef112efba 100644
--- a/src/librustc/middle/mem_categorization.rs
+++ b/src/librustc/middle/mem_categorization.rs
@@ -1424,7 +1424,7 @@ impl<'tcx> cmt_<'tcx> {
                 NonAliasable
             }
 
-            Categorization::StaticItem(..) => {
+            Categorization::StaticItem => {
                 if self.mutbl.is_mutable() {
                     FreelyAliasable(AliasableStaticMut)
                 } else {
diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs
index 1452cf2cd76..4425a24590c 100644
--- a/src/librustc/middle/resolve_lifetime.rs
+++ b/src/librustc/middle/resolve_lifetime.rs
@@ -184,7 +184,7 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> {
                     this.walk_fn(fk, fd, b, s)
                 })
             }
-            FnKind::Closure(..) => {
+            FnKind::Closure => {
                 self.walk_fn(fk, fd, b, s)
             }
         }
@@ -479,7 +479,7 @@ impl<'a> LifetimeContext<'a> {
                 self.visit_generics(&sig.generics);
                 self.visit_explicit_self(&sig.explicit_self);
             }
-            FnKind::Closure(..) => {
+            FnKind::Closure => {
                 intravisit::walk_fn_decl(self, fd);
             }
         }
diff --git a/src/librustc/middle/traits/coherence.rs b/src/librustc/middle/traits/coherence.rs
index 56dc259b1c2..76428ca6d90 100644
--- a/src/librustc/middle/traits/coherence.rs
+++ b/src/librustc/middle/traits/coherence.rs
@@ -300,7 +300,7 @@ fn ty_is_local_constructor<'tcx>(tcx: &ty::ctxt<'tcx>,
         ty::TyInt(..) |
         ty::TyUint(..) |
         ty::TyFloat(..) |
-        ty::TyStr(..) |
+        ty::TyStr |
         ty::TyBareFn(..) |
         ty::TyArray(..) |
         ty::TySlice(..) |
diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs
index e73f0cafb04..0b0f6c0b998 100644
--- a/src/librustc/middle/traits/select.rs
+++ b/src/librustc/middle/traits/select.rs
@@ -1563,7 +1563,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         }
 
         match other {
-            &ObjectCandidate(..) |
+            &ObjectCandidate |
             &ParamCandidate(_) | &ProjectionCandidate => match victim {
                 &DefaultImplCandidate(..) => {
                     self.tcx().sess.bug(
@@ -1572,16 +1572,16 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 }
                 &ImplCandidate(..) |
                 &ClosureCandidate(..) |
-                &FnPointerCandidate(..) |
-                &BuiltinObjectCandidate(..) |
-                &BuiltinUnsizeCandidate(..) |
+                &FnPointerCandidate |
+                &BuiltinObjectCandidate |
+                &BuiltinUnsizeCandidate |
                 &DefaultImplObjectCandidate(..) |
                 &BuiltinCandidate(..) => {
                     // We have a where-clause so don't go around looking
                     // for impls.
                     true
                 }
-                &ObjectCandidate(..) |
+                &ObjectCandidate |
                 &ProjectionCandidate => {
                     // Arbitrarily give param candidates priority
                     // over projection and object candidates.
diff --git a/src/librustc/middle/ty/outlives.rs b/src/librustc/middle/ty/outlives.rs
index 9a2570d710d..ea092ed977e 100644
--- a/src/librustc/middle/ty/outlives.rs
+++ b/src/librustc/middle/ty/outlives.rs
@@ -188,21 +188,21 @@ fn compute_components<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
         // the type and then visits the types that are lexically
         // contained within. (The comments refer to relevant rules
         // from RFC1214.)
-        ty::TyBool(..) |        // OutlivesScalar
-        ty::TyChar(..) |        // OutlivesScalar
+        ty::TyBool |            // OutlivesScalar
+        ty::TyChar |            // OutlivesScalar
         ty::TyInt(..) |         // OutlivesScalar
         ty::TyUint(..) |        // OutlivesScalar
         ty::TyFloat(..) |       // OutlivesScalar
         ty::TyEnum(..) |        // OutlivesNominalType
         ty::TyStruct(..) |      // OutlivesNominalType
         ty::TyBox(..) |         // OutlivesNominalType (ish)
-        ty::TyStr(..) |         // OutlivesScalar (ish)
+        ty::TyStr |             // OutlivesScalar (ish)
         ty::TyArray(..) |       // ...
         ty::TySlice(..) |       // ...
         ty::TyRawPtr(..) |      // ...
         ty::TyRef(..) |         // OutlivesReference
         ty::TyTuple(..) |       // ...
-        ty::TyError(..) => {
+        ty::TyError => {
             push_region_constraints(out, ty.regions());
             for subty in ty.walk_shallow() {
                 compute_components(infcx, subty, out);
diff --git a/src/librustc_borrowck/borrowck/check_loans.rs b/src/librustc_borrowck/borrowck/check_loans.rs
index cec0cf18fb7..f6bb51a26ad 100644
--- a/src/librustc_borrowck/borrowck/check_loans.rs
+++ b/src/librustc_borrowck/borrowck/check_loans.rs
@@ -540,14 +540,14 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
                             ol, old_loan_msg)
                 }
 
-                euv::OverloadedOperator(..) |
-                euv::AddrOf(..) |
-                euv::AutoRef(..) |
-                euv::AutoUnsafe(..) |
-                euv::ClosureInvocation(..) |
-                euv::ForLoop(..) |
-                euv::RefBinding(..) |
-                euv::MatchDiscriminant(..) => {
+                euv::OverloadedOperator |
+                euv::AddrOf |
+                euv::AutoRef |
+                euv::AutoUnsafe |
+                euv::ClosureInvocation |
+                euv::ForLoop |
+                euv::RefBinding |
+                euv::MatchDiscriminant => {
                     format!("previous borrow of `{}` occurs here{}",
                             ol, old_loan_msg)
                 }
diff --git a/src/librustc_borrowck/borrowck/gather_loans/restrictions.rs b/src/librustc_borrowck/borrowck/gather_loans/restrictions.rs
index 426da7809d8..e7ce9397263 100644
--- a/src/librustc_borrowck/borrowck/gather_loans/restrictions.rs
+++ b/src/librustc_borrowck/borrowck/gather_loans/restrictions.rs
@@ -101,7 +101,7 @@ impl<'a, 'tcx> RestrictionsContext<'a, 'tcx> {
                 self.extend(result, &cmt, LpInterior(i.cleaned()))
             }
 
-            Categorization::StaticItem(..) => {
+            Categorization::StaticItem => {
                 Safe
             }
 
diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs
index a9a7b34df12..162c91ee4e9 100644
--- a/src/librustc_borrowck/borrowck/mod.rs
+++ b/src/librustc_borrowck/borrowck/mod.rs
@@ -942,8 +942,8 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
                            "consider changing this closure to take self by mutable reference");
                 }
             }
-            mc::AliasableStatic(..) |
-            mc::AliasableStaticMut(..) => {
+            mc::AliasableStatic |
+            mc::AliasableStaticMut => {
                 span_err!(
                     self.tcx.sess, span, E0388,
                     "{} in a static location", prefix);
@@ -998,7 +998,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
     pub fn note_and_explain_bckerr(&self, err: BckError<'tcx>) {
         let code = err.code;
         match code {
-            err_mutbl(..) => {
+            err_mutbl => {
                 match err.cmt.note {
                     mc::NoteClosureEnv(upvar_id) | mc::NoteUpvarRef(upvar_id) => {
                         // If this is an `Fn` closure, it simply can't mutate upvars.
diff --git a/src/librustc_mir/build/matches/simplify.rs b/src/librustc_mir/build/matches/simplify.rs
index e69a04322c2..b9637addccf 100644
--- a/src/librustc_mir/build/matches/simplify.rs
+++ b/src/librustc_mir/build/matches/simplify.rs
@@ -66,7 +66,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
                                  candidate: &mut Candidate<'pat, 'tcx>)
                                  -> Result<BasicBlock, MatchPair<'pat, 'tcx>> {
         match *match_pair.pattern.kind {
-            PatternKind::Wild(..) => {
+            PatternKind::Wild => {
                 // nothing left to do
                 Ok(block)
             }
diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs
index c546a264be1..3380b3a6c14 100644
--- a/src/librustc_mir/hair/cx/expr.rs
+++ b/src/librustc_mir/hair/cx/expr.rs
@@ -178,7 +178,7 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
                     }
                     ty::TyEnum(adt, substs) => {
                         match cx.tcx.def_map.borrow()[&self.id].full_def() {
-                            def::DefVariant(enum_id, variant_id, true) => {
+                            def::DefVariant(enum_id, variant_id, _) => {
                                 debug_assert!(adt.did == enum_id);
                                 let index = adt.variant_index_with_id(variant_id);
                                 let field_refs = field_refs(&adt.variants[index], fields);
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index c2fb921c891..b161d7f3330 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -619,7 +619,7 @@ impl<'a, 'v, 'tcx> Visitor<'v> for Resolver<'a, 'tcx> {
                 self.visit_explicit_self(&sig.explicit_self);
                 MethodRibKind
             }
-            FnKind::Closure(..) => ClosureRibKind(node_id),
+            FnKind::Closure => ClosureRibKind(node_id),
         };
         self.resolve_function(rib_kind, declaration, block);
     }
diff --git a/src/librustc_trans/trans/type_of.rs b/src/librustc_trans/trans/type_of.rs
index 1e371a16970..e65a212e41b 100644
--- a/src/librustc_trans/trans/type_of.rs
+++ b/src/librustc_trans/trans/type_of.rs
@@ -247,7 +247,7 @@ pub fn sizing_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Typ
             }
         }
 
-        ty::TyProjection(..) | ty::TyInfer(..) | ty::TyParam(..) | ty::TyError(..) => {
+        ty::TyProjection(..) | ty::TyInfer(..) | ty::TyParam(..) | ty::TyError => {
             cx.sess().bug(&format!("fictitious type {:?} in sizing_type_of()",
                                    t))
         }
@@ -451,7 +451,7 @@ pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) ->
       ty::TyInfer(..) => cx.sess().bug("type_of with TyInfer"),
       ty::TyProjection(..) => cx.sess().bug("type_of with TyProjection"),
       ty::TyParam(..) => cx.sess().bug("type_of with ty_param"),
-      ty::TyError(..) => cx.sess().bug("type_of with TyError"),
+      ty::TyError => cx.sess().bug("type_of with TyError"),
     };
 
     debug!("--> mapped t={:?} to llty={}",
diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs
index 5ffe34d61bf..1053919be53 100644
--- a/src/librustc_typeck/check/_match.rs
+++ b/src/librustc_typeck/check/_match.rs
@@ -21,6 +21,7 @@ use check::{check_expr_with_lvalue_pref};
 use check::{instantiate_path, resolve_ty_and_def_ufcs, structurally_resolved_type};
 use require_same_types;
 use util::nodemap::FnvHashMap;
+use session::Session;
 
 use std::cmp;
 use std::collections::hash_map::Entry::{Occupied, Vacant};
@@ -136,6 +137,12 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
         }
         hir::PatEnum(..) | hir::PatIdent(..)
                 if pat_is_resolved_const(&tcx.def_map.borrow(), pat) => {
+            if let hir::PatEnum(ref path, ref subpats) = pat.node {
+                if !(subpats.is_some() && subpats.as_ref().unwrap().is_empty()) {
+                    bad_struct_kind_err(tcx.sess, pat.span, path, false);
+                    return;
+                }
+            }
             let const_did = tcx.def_map.borrow().get(&pat.id).unwrap().def_id();
             let const_scheme = tcx.lookup_item_type(const_did);
             assert!(const_scheme.generics.is_empty());
@@ -192,11 +199,12 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
         }
         hir::PatIdent(_, ref path, _) => {
             let path = hir_util::ident_to_path(path.span, path.node);
-            check_pat_enum(pcx, pat, &path, Some(&[]), expected);
+            check_pat_enum(pcx, pat, &path, Some(&[]), expected, false);
         }
         hir::PatEnum(ref path, ref subpats) => {
             let subpats = subpats.as_ref().map(|v| &v[..]);
-            check_pat_enum(pcx, pat, path, subpats, expected);
+            let is_tuple_struct_pat = !(subpats.is_some() && subpats.unwrap().is_empty());
+            check_pat_enum(pcx, pat, path, subpats, expected, is_tuple_struct_pat);
         }
         hir::PatQPath(ref qself, ref path) => {
             let self_ty = fcx.to_ty(&qself.ty);
@@ -572,11 +580,19 @@ pub fn check_pat_struct<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, pat: &'tcx hir::Pat,
     fcx.write_substs(pat.id, ty::ItemSubsts { substs: item_substs.clone() });
 }
 
+// This function exists due to the warning "diagnostic code E0164 already used"
+fn bad_struct_kind_err(sess: &Session, span: Span, path: &hir::Path, is_warning: bool) {
+    let name = pprust::path_to_string(path);
+    span_err_or_warn!(is_warning, sess, span, E0164,
+        "`{}` does not name a tuple variant or a tuple struct", name);
+}
+
 pub fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
                                 pat: &hir::Pat,
                                 path: &hir::Path,
                                 subpats: Option<&'tcx [P<hir::Pat>]>,
-                                expected: Ty<'tcx>)
+                                expected: Ty<'tcx>,
+                                is_tuple_struct_pat: bool)
 {
     // Typecheck the path.
     let fcx = pcx.fcx;
@@ -618,25 +634,52 @@ pub fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
                      path_scheme, &ctor_predicates,
                      opt_ty, def, pat.span, pat.id);
 
+    let report_bad_struct_kind = |is_warning| {
+        bad_struct_kind_err(tcx.sess, pat.span, path, is_warning);
+        fcx.write_error(pat.id);
+
+        if let Some(subpats) = subpats {
+            for pat in subpats {
+                check_pat(pcx, &**pat, tcx.types.err);
+            }
+        }
+    };
+
     // If we didn't have a fully resolved path to start with, we had an
     // associated const, and we should quit now, since the rest of this
     // function uses checks specific to structs and enums.
     if path_res.depth != 0 {
-        let pat_ty = fcx.node_ty(pat.id);
-        demand::suptype(fcx, pat.span, expected, pat_ty);
+        if is_tuple_struct_pat {
+            report_bad_struct_kind(false);
+        } else {
+            let pat_ty = fcx.node_ty(pat.id);
+            demand::suptype(fcx, pat.span, expected, pat_ty);
+        }
         return;
     }
 
     let pat_ty = fcx.node_ty(pat.id);
     demand::eqtype(fcx, pat.span, expected, pat_ty);
 
-
     let real_path_ty = fcx.node_ty(pat.id);
     let (arg_tys, kind_name): (Vec<_>, &'static str) = match real_path_ty.sty {
         ty::TyEnum(enum_def, expected_substs)
             if def == def::DefVariant(enum_def.did, def.def_id(), false) =>
         {
             let variant = enum_def.variant_of_def(def);
+            if is_tuple_struct_pat && variant.kind() != ty::VariantKind::Tuple {
+                // Matching unit variants with tuple variant patterns (`UnitVariant(..)`)
+                // is allowed for backward compatibility.
+                let is_special_case = variant.kind() == ty::VariantKind::Unit;
+                report_bad_struct_kind(is_special_case);
+                if !is_special_case {
+                    return
+                } else {
+                    span_note!(tcx.sess, pat.span,
+                        "this warning will become a HARD ERROR in a future release. \
+                        See RFC 218 for details.");
+                }
+            }
             (variant.fields
                     .iter()
                     .map(|f| fcx.instantiate_type_scheme(pat.span,
@@ -646,26 +689,21 @@ pub fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
              "variant")
         }
         ty::TyStruct(struct_def, expected_substs) => {
-            (struct_def.struct_variant()
-                       .fields
-                       .iter()
-                       .map(|f| fcx.instantiate_type_scheme(pat.span,
-                                                            expected_substs,
-                                                            &f.unsubst_ty()))
-                       .collect(),
+            let variant = struct_def.struct_variant();
+            if is_tuple_struct_pat && variant.kind() != ty::VariantKind::Tuple {
+                report_bad_struct_kind(false);
+                return;
+            }
+            (variant.fields
+                    .iter()
+                    .map(|f| fcx.instantiate_type_scheme(pat.span,
+                                                         expected_substs,
+                                                         &f.unsubst_ty()))
+                    .collect(),
              "struct")
         }
         _ => {
-            let name = pprust::path_to_string(path);
-            span_err!(tcx.sess, pat.span, E0164,
-                "`{}` does not name a non-struct variant or a tuple struct", name);
-            fcx.write_error(pat.id);
-
-            if let Some(subpats) = subpats {
-                for pat in subpats {
-                    check_pat(pcx, &**pat, tcx.types.err);
-                }
-            }
+            report_bad_struct_kind(false);
             return;
         }
     };
diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs
index 59790d72265..ed819d46041 100644
--- a/src/librustc_typeck/check/method/probe.rs
+++ b/src/librustc_typeck/check/method/probe.rs
@@ -1052,7 +1052,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
                     (impl_def_id, substs, ref_obligations)
                 }
 
-                ObjectCandidate(..) |
+                ObjectCandidate |
                 TraitCandidate |
                 WhereClauseCandidate(..) => {
                     // These have no additional conditions to check.
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index f81161addd9..ed8bb6a9625 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -1446,7 +1446,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                               -> Option<(ty::AdtDef<'tcx>, ty::VariantDef<'tcx>)>
     {
         let (adt, variant) = match def {
-            def::DefVariant(enum_id, variant_id, true) => {
+            def::DefVariant(enum_id, variant_id, _) => {
                 let adt = self.tcx().lookup_adt_def(enum_id);
                 (adt, adt.variant_with_id(variant_id))
             }
diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs
index 4c81c807ebd..cdbfda40813 100644
--- a/src/librustc_typeck/coherence/mod.rs
+++ b/src/librustc_typeck/coherence/mod.rs
@@ -69,7 +69,7 @@ fn get_base_type_def_id<'a, 'tcx>(inference_context: &InferCtxt<'a, 'tcx>,
         }
 
         TyBool | TyChar | TyInt(..) | TyUint(..) | TyFloat(..) |
-        TyStr(..) | TyArray(..) | TySlice(..) | TyBareFn(..) | TyTuple(..) |
+        TyStr | TyArray(..) | TySlice(..) | TyBareFn(..) | TyTuple(..) |
         TyParam(..) | TyError |
         TyRawPtr(_) | TyRef(_, _) | TyProjection(..) => {
             None
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index a1b3d88f083..4ea834cce2d 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -774,7 +774,7 @@ impl Clean<Option<Lifetime>> for ty::Region {
             ty::ReScope(..) |
             ty::ReVar(..) |
             ty::ReSkolemized(..) |
-            ty::ReEmpty(..) => None
+            ty::ReEmpty => None
         }
     }
 }
@@ -1607,7 +1607,7 @@ impl Clean<Type> for hir::Ty {
             TyPolyTraitRef(ref bounds) => {
                 PolyTraitRef(bounds.clean(cx))
             },
-            TyInfer(..) => {
+            TyInfer => {
                 Infer
             },
             TyTypeof(..) => {
diff --git a/src/test/compile-fail/empty-struct-braces-gate-2.rs b/src/test/compile-fail/empty-struct-braces-gate-2.rs
index c1b73bdc96a..b2d44301eed 100644
--- a/src/test/compile-fail/empty-struct-braces-gate-2.rs
+++ b/src/test/compile-fail/empty-struct-braces-gate-2.rs
@@ -20,8 +20,7 @@ enum E {
 fn main() {
     let e2: Empty2 = Empty2 {}; //~ ERROR empty structs and enum variants with braces are unstable
     let e2: Empty2 = Empty2;
-    // Issue #28692
-    // let e5: E = E::Empty5 {}; // ERROR empty structs and enum variants with braces are unstable
+    let e5: E = E::Empty5 {}; //~ ERROR empty structs and enum variants with braces are unstable
     let e5: E = E::Empty5;
 
     match e2 {
@@ -33,17 +32,15 @@ fn main() {
     match e2 {
         Empty2 { .. } => {} //~ ERROR empty structs and enum variants with braces are unstable
     }
-    // Issue #28692
-    // match e5 {
-    //     E::Empty5 {} => {} // ERROR empty structs and enum variants with braces are unstable
-    // }
+    match e5 {
+        E::Empty5 {} => {} //~ ERROR empty structs and enum variants with braces are unstable
+    }
     match e5 {
         E::Empty5 => {}
     }
-    // Issue #28692
-    // match e5 {
-    //     E::Empty5 { .. } => {} // ERROR empty structs and enum variants with braces are unstable
-    // }
+    match e5 {
+        E::Empty5 { .. } => {} //~ ERROR empty structs and enum variants with braces are unstable
+    }
 
     let e22 = Empty2 { ..e2 }; //~ ERROR empty structs and enum variants with braces are unstable
 }
diff --git a/src/test/compile-fail/empty-struct-braces-pat-1.rs b/src/test/compile-fail/empty-struct-braces-pat-1.rs
index e095f69ed7d..6a6c3f16c04 100644
--- a/src/test/compile-fail/empty-struct-braces-pat-1.rs
+++ b/src/test/compile-fail/empty-struct-braces-pat-1.rs
@@ -10,7 +10,6 @@
 
 // Can't use empty braced struct as constant pattern
 
-#![deny(warnings)]
 #![feature(braced_empty_structs)]
 
 struct Empty1 {}
@@ -23,11 +22,10 @@ fn main() {
     let e1 = Empty1 {};
     let e2 = E::Empty2 {};
 
-    // Issue #28692
-    // match e1 {
-    //     Empty1 => () // ERROR incorrect error
-    // }
+    match e1 {
+        Empty1 => () // Not an error, `Empty1` is interpreted as a new binding
+    }
     match e2 {
-        E::Empty2 => () //~ ERROR `E::Empty2` does not name a non-struct variant or a tuple struct
+        E::Empty2 => () //~ ERROR `E::Empty2` does not name a tuple variant or a tuple struct
     }
 }
diff --git a/src/test/compile-fail/empty-struct-braces-pat-2.rs b/src/test/compile-fail/empty-struct-braces-pat-2.rs
index 0e7152ec89a..d98d64b712a 100644
--- a/src/test/compile-fail/empty-struct-braces-pat-2.rs
+++ b/src/test/compile-fail/empty-struct-braces-pat-2.rs
@@ -14,13 +14,8 @@
 
 struct Empty1 {}
 
-enum E {
-    Empty2 {}
-}
-
 fn main() {
     let e1 = Empty1 {};
-    let e2 = E::Empty2 {};
 
     // Rejected by parser as yet
     // match e1 {
@@ -29,11 +24,4 @@ fn main() {
     match e1 {
         Empty1(..) => () //~ ERROR unresolved enum variant, struct or const `Empty1`
     }
-    // Issue #28692
-    // match e2 {
-    //     E::Empty2() => () // ERROR unresolved enum variant, struct or const `Empty2`
-    // }
-    // match e2 {
-    //     E::Empty2(..) => () // ERROR unresolved enum variant, struct or const `Empty2`
-    // }
 }
diff --git a/src/test/compile-fail/empty-struct-braces-pat-3.rs b/src/test/compile-fail/empty-struct-braces-pat-3.rs
new file mode 100644
index 00000000000..9fae203f389
--- /dev/null
+++ b/src/test/compile-fail/empty-struct-braces-pat-3.rs
@@ -0,0 +1,29 @@
+// Copyright 2015 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.
+
+// Can't use empty braced struct as enum pattern
+
+#![feature(braced_empty_structs)]
+
+enum E {
+    Empty2 {}
+}
+
+fn main() {
+    let e2 = E::Empty2 {};
+
+    // Rejected by parser as yet
+    // match e2 {
+    //     E::Empty2() => () // ERROR `E::Empty2` does not name a tuple variant or a tuple struct
+    // }
+    match e2 {
+        E::Empty2(..) => () //~ ERROR `E::Empty2` does not name a tuple variant or a tuple struct
+    }
+}
diff --git a/src/test/compile-fail/empty-struct-unit-pat.rs b/src/test/compile-fail/empty-struct-unit-pat.rs
index 966a2780f9f..6cb9a3f007f 100644
--- a/src/test/compile-fail/empty-struct-unit-pat.rs
+++ b/src/test/compile-fail/empty-struct-unit-pat.rs
@@ -12,8 +12,6 @@
 
 #![feature(braced_empty_structs)]
 
-FIXME //~ ERROR expected item, found `FIXME`
-
 struct Empty1;
 
 enum E {
@@ -24,17 +22,18 @@ fn main() {
     let e1 = Empty1;
     let e2 = E::Empty2;
 
-    // Issue #28692
-    // match e1 {
-    //     Empty1() => () // ERROR variable `Empty1` should have a snake case name
-    // }
+    // Rejected by parser as yet
     // match e1 {
-    //     Empty1(..) => () // ERROR variable `Empty1` should have a snake case name
-    // }
-    // match e2 {
-    //     E::Empty2() => () // ERROR variable `Empty2` should have a snake case name
+    //     Empty1() => () // ERROR `Empty1` does not name a tuple variant or a tuple struct
     // }
+    match e1 {
+        Empty1(..) => () //~ ERROR `Empty1` does not name a tuple variant or a tuple struct
+    }
+    // Rejected by parser as yet
     // match e2 {
-    //     E::Empty2(..) => () // ERROR variable `Empty2` should have a snake case name
+    //     E::Empty2() => () // ERROR `E::Empty2` does not name a tuple variant or a tuple struct
     // }
+    match e2 {
+        E::Empty2(..) => () //~ WARN `E::Empty2` does not name a tuple variant or a tuple struct
+    }
 }
diff --git a/src/test/compile-fail/issue-19086.rs b/src/test/compile-fail/issue-19086.rs
index 69201859457..56452449d4e 100644
--- a/src/test/compile-fail/issue-19086.rs
+++ b/src/test/compile-fail/issue-19086.rs
@@ -18,6 +18,6 @@ fn main() {
     let f = FooB { x: 3, y: 4 };
     match f {
         FooB(a, b) => println!("{} {}", a, b),
-//~^ ERROR `FooB` does not name a non-struct variant or a tuple struct
+//~^ ERROR `FooB` does not name a tuple variant or a tuple struct
     }
 }
diff --git a/src/test/compile-fail/issue-27831.rs b/src/test/compile-fail/issue-27831.rs
index 3cdb370f0e9..ff2846dc705 100644
--- a/src/test/compile-fail/issue-27831.rs
+++ b/src/test/compile-fail/issue-27831.rs
@@ -26,7 +26,7 @@ fn main() {
     let Bar { .. } = x; //~ ERROR empty structs and enum variants with braces are unstable
 
     match Enum::Bar {
-        Enum::Bar { .. } //~ ERROR `Enum::Bar` does not name a struct
+        Enum::Bar { .. } //~ ERROR empty structs and enum variants with braces are unstable
            => {}
         Enum::Foo { .. } //~ ERROR `Enum::Foo` does not name a struct
            => {}
diff --git a/src/test/compile-fail/issue-28992-empty.rs b/src/test/compile-fail/issue-28992-empty.rs
new file mode 100644
index 00000000000..f7d53ba23da
--- /dev/null
+++ b/src/test/compile-fail/issue-28992-empty.rs
@@ -0,0 +1,26 @@
+// Copyright 2015 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.
+
+// Can't use constants as tuple struct patterns
+
+#![feature(associated_consts)]
+
+const C1: i32 = 0;
+
+struct S;
+
+impl S {
+    const C2: i32 = 0;
+}
+
+fn main() {
+    if let C1(..) = 0 {} //~ ERROR `C1` does not name a tuple variant or a tuple struct
+    if let S::C2(..) = 0 {} //~ ERROR `S::C2` does not name a tuple variant or a tuple struct
+}
diff --git a/src/test/compile-fail/match-pattern-field-mismatch-2.rs b/src/test/compile-fail/match-pattern-field-mismatch-2.rs
index e63ddf6c7fd..17debdabb61 100644
--- a/src/test/compile-fail/match-pattern-field-mismatch-2.rs
+++ b/src/test/compile-fail/match-pattern-field-mismatch-2.rs
@@ -21,6 +21,7 @@ fn main() {
           color::cmyk(_, _, _, _) => { }
           color::no_color(_) => { }
           //~^ ERROR this pattern has 1 field, but the corresponding variant has no fields
+          //~^^ WARN `color::no_color` does not name a tuple variant or a tuple struct
         }
     }
 }
diff --git a/src/test/compile-fail/move-fragments-2.rs b/src/test/compile-fail/move-fragments-2.rs
index 1171755c953..15c28ec2713 100644
--- a/src/test/compile-fail/move-fragments-2.rs
+++ b/src/test/compile-fail/move-fragments-2.rs
@@ -32,7 +32,7 @@ pub fn test_match_partial(p: Lonely<D, D>) {
     //~^ ERROR                 parent_of_fragments: `$(local p)`
     //~| ERROR                  assigned_leaf_path: `($(local p) as Lonely::Zero)`
     match p {
-        Zero(..) => {}
+        Zero => {}
         _ => {}
     }
 }
@@ -44,7 +44,7 @@ pub fn test_match_full(p: Lonely<D, D>) {
     //~| ERROR                  assigned_leaf_path: `($(local p) as Lonely::One)`
     //~| ERROR                  assigned_leaf_path: `($(local p) as Lonely::Two)`
     match p {
-        Zero(..) => {}
+        Zero => {}
         One(..) => {}
         Two(..) => {}
     }
@@ -59,7 +59,7 @@ pub fn test_match_bind_one(p: Lonely<D, D>) {
     //~| ERROR                  assigned_leaf_path: `($(local p) as Lonely::Two)`
     //~| ERROR                  assigned_leaf_path: `$(local data)`
     match p {
-        Zero(..) => {}
+        Zero => {}
         One(data) => {}
         Two(..) => {}
     }
@@ -78,7 +78,7 @@ pub fn test_match_bind_many(p: Lonely<D, D>) {
     //~| ERROR                  assigned_leaf_path: `$(local left)`
     //~| ERROR                  assigned_leaf_path: `$(local right)`
     match p {
-        Zero(..) => {}
+        Zero => {}
         One(data) => {}
         Two(left, right) => {}
     }
diff --git a/src/test/compile-fail/move-fragments-3.rs b/src/test/compile-fail/move-fragments-3.rs
index 34b34471f4f..a1152333900 100644
--- a/src/test/compile-fail/move-fragments-3.rs
+++ b/src/test/compile-fail/move-fragments-3.rs
@@ -38,7 +38,7 @@ pub fn test_match_bind_and_underscore(p: Lonely<D, D>) {
     //~| ERROR                  assigned_leaf_path: `$(local left)`
 
     match p {
-        Zero(..) => {}
+        Zero => {}
 
         One(_) => {}       // <-- does not fragment `($(local p) as One)` ...
 
diff --git a/src/test/compile-fail/pattern-error-continue.rs b/src/test/compile-fail/pattern-error-continue.rs
index aa7202574ab..1721d1f0ae1 100644
--- a/src/test/compile-fail/pattern-error-continue.rs
+++ b/src/test/compile-fail/pattern-error-continue.rs
@@ -26,6 +26,7 @@ fn main() {
     match A::B(1, 2) {
         A::B(_, _, _) => (), //~ ERROR this pattern has 3 fields, but
         A::D(_) => (),       //~ ERROR this pattern has 1 field, but
+        //~^ WARN `A::D` does not name a tuple variant or a tuple struct
         _ => ()
     }
     match 'c' {
diff --git a/src/test/run-pass/empty-struct-braces.rs b/src/test/run-pass/empty-struct-braces.rs
index f2fbf2dd337..80ea1bc3a0e 100644
--- a/src/test/run-pass/empty-struct-braces.rs
+++ b/src/test/run-pass/empty-struct-braces.rs
@@ -30,7 +30,7 @@ fn main() {
     let e3: Empty3 = Empty3 {};
     let e3: Empty3 = Empty3;
     let e4: E = E::Empty4 {};
-    // let e5: E = E::Empty5 {}; // Issue #28692
+    let e5: E = E::Empty5 {};
     let e5: E = E::Empty5;
 
     match e1 {
@@ -46,11 +46,10 @@ fn main() {
         E::Empty4 {} => {}
         _ => {}
     }
-    // Issue #28692
-    // match e5 {
-    //     E::Empty5 {} => {}
-    //     _ => {}
-    // }
+    match e5 {
+        E::Empty5 {} => {}
+        _ => {}
+    }
 
     match e1 {
         Empty1 { .. } => {}
@@ -65,11 +64,10 @@ fn main() {
         E::Empty4 { .. } => {}
         _ => {}
     }
-    // Issue #28692
-    // match e5 {
-    //     E::Empty5 { .. } => {}
-    //     _ => {}
-    // }
+    match e5 {
+        E::Empty5 { .. } => {}
+        _ => {}
+    }
 
     match e2 {
         Empty2 => {}
diff --git a/src/test/run-pass/issue-14308.rs b/src/test/run-pass/issue-14308.rs
index a61cb18faa6..74936411da2 100644
--- a/src/test/run-pass/issue-14308.rs
+++ b/src/test/run-pass/issue-14308.rs
@@ -10,7 +10,6 @@
 
 
 struct A(isize);
-struct B;
 
 fn main() {
     let x = match A(3) {
@@ -22,12 +21,4 @@ fn main() {
         A(..) => 2
     };
     assert_eq!(x, 2);
-
-    // This next test uses a (..) wildcard match on a nullary struct.
-    // There's no particularly good reason to support this, but it's currently allowed,
-    // and this makes sure it doesn't ICE or break LLVM.
-    let x = match B {
-        B(..) => 3
-    };
-    assert_eq!(x, 3);
 }
diff --git a/src/test/run-pass/issue-1701.rs b/src/test/run-pass/issue-1701.rs
index 3a2e46c62b0..49ee99b22a1 100644
--- a/src/test/run-pass/issue-1701.rs
+++ b/src/test/run-pass/issue-1701.rs
@@ -20,7 +20,7 @@ fn noise(a: animal) -> Option<String> {
       animal::cat(..)    => { Some("meow".to_string()) }
       animal::dog(..)    => { Some("woof".to_string()) }
       animal::rabbit(..) => { None }
-      animal::tiger(..)  => { Some("roar".to_string()) }
+      animal::tiger  => { Some("roar".to_string()) }
     }
 }