about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc/hir/def.rs31
-rw-r--r--src/librustc/hir/lowering.rs24
-rw-r--r--src/librustc/hir/pat_util.rs10
-rw-r--r--src/librustc/middle/dead.rs3
-rw-r--r--src/librustc/middle/expr_use_visitor.rs4
-rw-r--r--src/librustc/middle/mem_categorization.rs21
-rw-r--r--src/librustc/middle/stability.rs15
-rw-r--r--src/librustc_const_eval/check_match.rs15
-rw-r--r--src/librustc_const_eval/eval.rs9
-rw-r--r--src/librustc_mir/hair/cx/expr.rs39
-rw-r--r--src/librustc_passes/static_recursion.rs4
-rw-r--r--src/librustc_privacy/lib.rs37
-rw-r--r--src/librustc_resolve/lib.rs3
-rw-r--r--src/librustc_save_analysis/dump_visitor.rs56
-rw-r--r--src/librustc_save_analysis/lib.rs10
-rw-r--r--src/librustc_typeck/check/_match.rs33
-rw-r--r--src/librustc_typeck/check/mod.rs67
-rw-r--r--src/librustdoc/clean/inline.rs18
18 files changed, 161 insertions, 238 deletions
diff --git a/src/librustc/hir/def.rs b/src/librustc/hir/def.rs
index 5a69de90d2a..8b9cee1d2f6 100644
--- a/src/librustc/hir/def.rs
+++ b/src/librustc/hir/def.rs
@@ -25,29 +25,34 @@ pub enum CtorKind {
 
 #[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub enum Def {
-    Fn(DefId),
-    SelfTy(Option<DefId> /* trait */, Option<DefId> /* impl */),
+    // Type namespace
     Mod(DefId),
-    Static(DefId, bool /* is_mutbl */),
-    Const(DefId),
-    AssociatedConst(DefId),
-    Local(DefId),
-    Variant(DefId),
-    VariantCtor(DefId, CtorKind),
+    Struct(DefId), // DefId refers to NodeId of the struct itself
+    Union(DefId),
     Enum(DefId),
+    Variant(DefId),
+    Trait(DefId),
     TyAlias(DefId),
     AssociatedTy(DefId),
-    Trait(DefId),
     PrimTy(hir::PrimTy),
     TyParam(DefId),
+    SelfTy(Option<DefId> /* trait */, Option<DefId> /* impl */),
+
+    // Value namespace
+    Fn(DefId),
+    Const(DefId),
+    Static(DefId, bool /* is_mutbl */),
+    StructCtor(DefId, CtorKind), // DefId refers to NodeId of the struct's constructor
+    VariantCtor(DefId, CtorKind),
+    Method(DefId),
+    AssociatedConst(DefId),
+    Local(DefId),
     Upvar(DefId,        // def id of closed over local
           usize,        // index in the freevars list of the closure
           ast::NodeId), // expr node that creates the closure
-    Struct(DefId), // DefId refers to NodeId of the struct itself
-    StructCtor(DefId, CtorKind), // DefId refers to NodeId of the struct's constructor
-    Union(DefId),
     Label(ast::NodeId),
-    Method(DefId),
+
+    // Both namespaces
     Err,
 }
 
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index dace486b277..f56a27b9ae0 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -44,8 +44,9 @@ use hir;
 use hir::map::Definitions;
 use hir::map::definitions::DefPathData;
 use hir::def_id::{DefIndex, DefId};
-use hir::def::{Def, PathResolution};
+use hir::def::{Def, CtorKind, PathResolution};
 use session::Session;
+use lint;
 
 use std::collections::BTreeMap;
 use std::iter;
@@ -855,10 +856,23 @@ impl<'a> LoweringContext<'a> {
                     })
                 }
                 PatKind::Lit(ref e) => hir::PatKind::Lit(self.lower_expr(e)),
-                PatKind::TupleStruct(ref pth, ref pats, ddpos) => {
-                    hir::PatKind::TupleStruct(self.lower_path(pth),
-                                              pats.iter().map(|x| self.lower_pat(x)).collect(),
-                                              ddpos)
+                PatKind::TupleStruct(ref path, ref pats, ddpos) => {
+                    match self.resolver.get_resolution(p.id).map(|d| d.base_def) {
+                        Some(def @ Def::StructCtor(_, CtorKind::Const)) |
+                        Some(def @ Def::VariantCtor(_, CtorKind::Const)) => {
+                            // Temporarily lower `UnitVariant(..)` into `UnitVariant`
+                            // for backward compatibility.
+                            let msg = format!("expected tuple struct/variant, found {} `{}`",
+                                            def.kind_name(), path);
+                            self.sess.add_lint(
+                                lint::builtin::MATCH_OF_UNIT_VARIANT_VIA_PAREN_DOTDOT,
+                                p.id, p.span, msg
+                            );
+                            hir::PatKind::Path(None, self.lower_path(path))
+                        }
+                        _ => hir::PatKind::TupleStruct(self.lower_path(path),
+                                        pats.iter().map(|x| self.lower_pat(x)).collect(), ddpos)
+                    }
                 }
                 PatKind::Path(ref opt_qself, ref path) => {
                     let opt_qself = opt_qself.as_ref().map(|qself| {
diff --git a/src/librustc/hir/pat_util.rs b/src/librustc/hir/pat_util.rs
index 0e78acb15c8..0deea941463 100644
--- a/src/librustc/hir/pat_util.rs
+++ b/src/librustc/hir/pat_util.rs
@@ -58,7 +58,7 @@ pub fn pat_is_refutable(dm: &DefMap, pat: &hir::Pat) -> bool {
         PatKind::Path(..) |
         PatKind::Struct(..) => {
             match dm.get(&pat.id).map(|d| d.full_def()) {
-                Some(Def::Variant(..)) => true,
+                Some(Def::Variant(..)) | Some(Def::VariantCtor(..)) => true,
                 _ => false
             }
         }
@@ -173,11 +173,9 @@ pub fn necessary_variants(dm: &DefMap, pat: &hir::Pat) -> Vec<DefId> {
             PatKind::TupleStruct(..) |
             PatKind::Path(..) |
             PatKind::Struct(..) => {
-                match dm.get(&p.id) {
-                    Some(&PathResolution { base_def: Def::Variant(id), .. }) |
-                    Some(&PathResolution { base_def: Def::VariantCtor(id, ..), .. }) => {
-                        variants.push(id);
-                    }
+                match dm.get(&p.id).map(|d| d.full_def()) {
+                    Some(Def::Variant(id)) |
+                    Some(Def::VariantCtor(id, ..)) => variants.push(id),
                     _ => ()
                 }
             }
diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs
index af22ef0bd3d..dc634b08784 100644
--- a/src/librustc/middle/dead.rs
+++ b/src/librustc/middle/dead.rs
@@ -106,8 +106,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
                 self.check_def_id(def.def_id());
             }
             _ if self.ignore_non_const_paths => (),
-            Def::PrimTy(_) => (),
-            Def::SelfTy(..) => (),
+            Def::PrimTy(..) | Def::SelfTy(..) => (),
             Def::Variant(variant_id) | Def::VariantCtor(variant_id, ..) => {
                 if let Some(enum_id) = self.tcx.parent_def_id(variant_id) {
                     self.check_def_id(enum_id);
diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs
index a03a0372e48..799c02b7403 100644
--- a/src/librustc/middle/expr_use_visitor.rs
+++ b/src/librustc/middle/expr_use_visitor.rs
@@ -1021,7 +1021,9 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
                     debug!("struct cmt_pat={:?} pat={:?}", cmt_pat, pat);
                     delegate.matched_pat(pat, cmt_pat, match_mode);
                 }
-                _ => {}
+                None | Some(Def::Local(..)) |
+                Some(Def::Const(..)) | Some(Def::AssociatedConst(..)) => {}
+                def => bug!("unexpected definition: {:?}", def)
             }
         }));
     }
diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs
index 4d1151c2826..9214138d210 100644
--- a/src/librustc/middle/mem_categorization.rs
+++ b/src/librustc/middle/mem_categorization.rs
@@ -74,7 +74,7 @@ use hir::def_id::DefId;
 use hir::map as ast_map;
 use infer::InferCtxt;
 use middle::const_qualif::ConstQualif;
-use hir::def::Def;
+use hir::def::{Def, CtorKind};
 use ty::adjustment;
 use ty::{self, Ty, TyCtxt};
 
@@ -524,22 +524,11 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
                id, expr_ty, def);
 
         match def {
-          Def::StructCtor(..) | Def::Union(..) | Def::VariantCtor(..) | Def::Const(..) |
+          Def::StructCtor(..) | Def::VariantCtor(..) | Def::Const(..) |
           Def::AssociatedConst(..) | Def::Fn(..) | Def::Method(..) => {
                 Ok(self.cat_rvalue_node(id, span, expr_ty))
           }
 
-          Def::Mod(_) |
-          Def::Trait(_) | Def::Enum(..) | Def::TyAlias(..) | Def::PrimTy(_) |
-          Def::TyParam(..) |
-          Def::Label(_) | Def::SelfTy(..) |
-          Def::Variant(..) |
-          Def::Struct(..) |
-          Def::AssociatedTy(..) => {
-              span_bug!(span, "Unexpected definition in \
-                               memory categorization: {:?}", def);
-          }
-
           Def::Static(_, mutbl) => {
               Ok(Rc::new(cmt_ {
                   id:id,
@@ -600,7 +589,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
             }))
           }
 
-          Def::Err => bug!("Def::Err in memory categorization")
+          def => span_bug!(span, "unexpected definition in memory categorization: {:?}", def)
         }
     }
 
@@ -1095,11 +1084,11 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
         match pat.node {
           PatKind::TupleStruct(_, ref subpats, ddpos) => {
             let expected_len = match self.tcx().expect_def(pat.id) {
-                Def::VariantCtor(def_id, ..) => {
+                Def::VariantCtor(def_id, CtorKind::Fn) => {
                     let enum_def = self.tcx().parent_def_id(def_id).unwrap();
                     self.tcx().lookup_adt_def(enum_def).variant_with_id(def_id).fields.len()
                 }
-                Def::StructCtor(..) => {
+                Def::StructCtor(_, CtorKind::Fn) => {
                     match self.pat_ty(&pat)?.sty {
                         ty::TyAdt(adt_def, _) => {
                             adt_def.struct_variant().fields.len()
diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs
index ccab4279232..5192575972b 100644
--- a/src/librustc/middle/stability.rs
+++ b/src/librustc/middle/stability.rs
@@ -617,12 +617,8 @@ pub fn check_path<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                            &Option<DeprecationEntry>)) {
     // Paths in import prefixes may have no resolution.
     match tcx.expect_def_or_none(id) {
-        Some(Def::PrimTy(..)) => {}
-        Some(Def::SelfTy(..)) => {}
-        Some(def) => {
-            maybe_do_stability_check(tcx, def.def_id(), path.span, cb);
-        }
-        None => {}
+        None | Some(Def::PrimTy(..)) | Some(Def::SelfTy(..)) => {}
+        Some(def) => maybe_do_stability_check(tcx, def.def_id(), path.span, cb)
     }
 }
 
@@ -631,12 +627,7 @@ pub fn check_path_list_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                       cb: &mut FnMut(DefId, Span,
                                                      &Option<&Stability>,
                                                      &Option<DeprecationEntry>)) {
-    match tcx.expect_def(item.node.id) {
-        Def::PrimTy(..) => {}
-        def => {
-            maybe_do_stability_check(tcx, def.def_id(), item.span, cb);
-        }
-    }
+    maybe_do_stability_check(tcx, tcx.expect_def(item.node.id).def_id(), item.span, cb);
 }
 
 pub fn check_pat<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, pat: &hir::Pat,
diff --git a/src/librustc_const_eval/check_match.rs b/src/librustc_const_eval/check_match.rs
index 287203c2f65..cf54f5908ca 100644
--- a/src/librustc_const_eval/check_match.rs
+++ b/src/librustc_const_eval/check_match.rs
@@ -913,10 +913,10 @@ pub fn specialize<'a, 'b, 'tcx>(
                 Def::Const(..) | Def::AssociatedConst(..) =>
                     span_bug!(pat_span, "const pattern should've \
                                          been rewritten"),
-                Def::VariantCtor(id, ..) if *constructor != Variant(id) => None,
-                Def::VariantCtor(..) | Def::StructCtor(..) => Some(Vec::new()),
-                def => span_bug!(pat_span, "specialize: unexpected \
-                                          definition {:?}", def),
+                Def::VariantCtor(id, CtorKind::Const) if *constructor != Variant(id) => None,
+                Def::VariantCtor(_, CtorKind::Const) |
+                Def::StructCtor(_, CtorKind::Const) => Some(Vec::new()),
+                def => span_bug!(pat_span, "specialize: unexpected definition: {:?}", def),
             }
         }
 
@@ -925,8 +925,9 @@ pub fn specialize<'a, 'b, 'tcx>(
                 Def::Const(..) | Def::AssociatedConst(..) =>
                     span_bug!(pat_span, "const pattern should've \
                                          been rewritten"),
-                Def::VariantCtor(id, ..) if *constructor != Variant(id) => None,
-                Def::VariantCtor(..) | Def::StructCtor(..) => {
+                Def::VariantCtor(id, CtorKind::Fn) if *constructor != Variant(id) => None,
+                Def::VariantCtor(_, CtorKind::Fn) |
+                Def::StructCtor(_, CtorKind::Fn) => {
                     match ddpos {
                         Some(ddpos) => {
                             let mut pats: Vec<_> = args[..ddpos].iter().map(|p| {
@@ -939,7 +940,7 @@ pub fn specialize<'a, 'b, 'tcx>(
                         None => Some(args.iter().map(|p| wpat(p)).collect())
                     }
                 }
-                _ => None
+                def => span_bug!(pat_span, "specialize: unexpected definition: {:?}", def),
             }
         }
 
diff --git a/src/librustc_const_eval/eval.rs b/src/librustc_const_eval/eval.rs
index 890319d5024..d876b4b6fec 100644
--- a/src/librustc_const_eval/eval.rs
+++ b/src/librustc_const_eval/eval.rs
@@ -19,7 +19,7 @@ use rustc::hir::map as ast_map;
 use rustc::hir::map::blocks::FnLikeNode;
 use rustc::middle::cstore::InlinedItem;
 use rustc::traits;
-use rustc::hir::def::{Def, PathResolution};
+use rustc::hir::def::{Def, CtorKind, PathResolution};
 use rustc::hir::def_id::DefId;
 use rustc::hir::pat_util::def_to_path;
 use rustc::ty::{self, Ty, TyCtxt};
@@ -287,8 +287,8 @@ pub fn const_expr_to_pat<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                entry.insert(PathResolution::new(def));
             }
             let path = match def {
-                Def::StructCtor(def_id, ..) => def_to_path(tcx, def_id),
-                Def::VariantCtor(variant_did, ..) => def_to_path(tcx, variant_did),
+                Def::StructCtor(def_id, CtorKind::Fn) |
+                Def::VariantCtor(def_id, CtorKind::Fn) => def_to_path(tcx, def_id),
                 Def::Fn(..) | Def::Method(..) => return Ok(P(hir::Pat {
                     id: expr.id,
                     node: PatKind::Lit(P(expr.clone())),
@@ -326,7 +326,8 @@ pub fn const_expr_to_pat<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
         hir::ExprPath(_, ref path) => {
             match tcx.expect_def(expr.id) {
-                Def::StructCtor(..) | Def::VariantCtor(..) => PatKind::Path(None, path.clone()),
+                Def::StructCtor(_, CtorKind::Const) |
+                Def::VariantCtor(_, CtorKind::Const) => PatKind::Path(None, path.clone()),
                 Def::Const(def_id) | Def::AssociatedConst(def_id) => {
                     let substs = Some(tcx.node_id_item_substs(expr.id).substs);
                     let (expr, _ty) = lookup_const_by_id(tcx, def_id, substs).unwrap();
diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs
index 926b0dc1fc1..a6c5cd1eeea 100644
--- a/src/librustc_mir/hair/cx/expr.rs
+++ b/src/librustc_mir/hair/cx/expr.rs
@@ -271,10 +271,10 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                     // Tuple-like ADTs are represented as ExprCall. We convert them here.
                     expr_ty.ty_adt_def().and_then(|adt_def|{
                         match cx.tcx.expect_def(fun.id) {
-                            Def::VariantCtor(variant_id, ..) => {
+                            Def::VariantCtor(variant_id, CtorKind::Fn) => {
                                 Some((adt_def, adt_def.variant_index_with_id(variant_id)))
                             },
-                            Def::StructCtor(..) => {
+                            Def::StructCtor(_, CtorKind::Fn) => {
                                 Some((adt_def, 0))
                             },
                             _ => None
@@ -670,38 +670,25 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
     // Otherwise there may be def_map borrow conflicts
     let def = cx.tcx.expect_def(expr.id);
     let def_id = match def {
-        // A regular function.
-        Def::Fn(def_id) | Def::Method(def_id) => def_id,
+        // A regular function, constructor function or a constant.
+        Def::Fn(def_id) | Def::Method(def_id) |
         Def::StructCtor(def_id, CtorKind::Fn) |
-        Def::VariantCtor(def_id, CtorKind::Fn) => def_id,
-        Def::StructCtor(_, CtorKind::Const) => match cx.tcx.node_id_to_type(expr.id).sty {
-            // A unit struct which is used as a value. We return a completely different ExprKind
-            // here to account for this special case.
+        Def::VariantCtor(def_id, CtorKind::Fn) |
+        Def::Const(def_id) | Def::AssociatedConst(def_id) => def_id,
+
+        Def::StructCtor(def_id, CtorKind::Const) |
+        Def::VariantCtor(def_id, CtorKind::Const) => match cx.tcx.node_id_to_type(expr.id).sty {
+            // A unit struct/variant which is used as a value.
+            // We return a completely different ExprKind here to account for this special case.
             ty::TyAdt(adt_def, substs) => return ExprKind::Adt {
                 adt_def: adt_def,
-                variant_index: 0,
+                variant_index: adt_def.variant_index_with_id(def_id),
                 substs: substs,
                 fields: vec![],
-                base: None
-            },
-            ref sty => bug!("unexpected sty: {:?}", sty)
-        },
-        Def::VariantCtor(def_id, CtorKind::Const) => match cx.tcx.node_id_to_type(expr.id).sty {
-            // A unit variant, similar special case to the struct case above.
-            ty::TyAdt(adt_def, substs) => {
-                let index = adt_def.variant_index_with_id(def_id);
-                return ExprKind::Adt {
-                    adt_def: adt_def,
-                    substs: substs,
-                    variant_index: index,
-                    fields: vec![],
-                    base: None
-                };
+                base: None,
             },
             ref sty => bug!("unexpected sty: {:?}", sty)
         },
-        Def::Const(def_id) |
-        Def::AssociatedConst(def_id) => def_id,
 
         Def::Static(node_id, _) => return ExprKind::StaticRef {
             id: node_id,
diff --git a/src/librustc_passes/static_recursion.rs b/src/librustc_passes/static_recursion.rs
index 0f5a67e66fb..0e0f8a84567 100644
--- a/src/librustc_passes/static_recursion.rs
+++ b/src/librustc_passes/static_recursion.rs
@@ -14,7 +14,7 @@
 use rustc::dep_graph::DepNode;
 use rustc::hir::map as ast_map;
 use rustc::session::{CompileResult, Session};
-use rustc::hir::def::{Def, DefMap};
+use rustc::hir::def::{Def, CtorKind, DefMap};
 use rustc::util::nodemap::NodeMap;
 
 use syntax::ast;
@@ -272,7 +272,7 @@ impl<'a, 'ast: 'a> Visitor<'ast> for CheckItemRecursionVisitor<'a, 'ast> {
                     // affect the specific variant used, but we need to check
                     // the whole enum definition to see what expression that
                     // might be (if any).
-                    Some(Def::VariantCtor(variant_id, ..)) => {
+                    Some(Def::VariantCtor(variant_id, CtorKind::Const)) => {
                         if let Some(variant_id) = self.ast_map.as_local_node_id(variant_id) {
                             let variant = self.ast_map.expect_variant(variant_id);
                             let enum_id = self.ast_map.get_parent(variant_id);
diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs
index a6a1326b719..4ffe2fe3856 100644
--- a/src/librustc_privacy/lib.rs
+++ b/src/librustc_privacy/lib.rs
@@ -28,7 +28,7 @@ extern crate syntax_pos;
 
 use rustc::dep_graph::DepNode;
 use rustc::hir::{self, PatKind};
-use rustc::hir::def::{self, Def};
+use rustc::hir::def::{self, Def, CtorKind};
 use rustc::hir::def_id::DefId;
 use rustc::hir::intravisit::{self, Visitor};
 use rustc::hir::pat_util::EnumerateAndAdjustIterator;
@@ -454,36 +454,25 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> {
                 }
             }
             hir::ExprPath(..) => {
-                if let Def::StructCtor(..) = self.tcx.expect_def(expr.id) {
-                    let expr_ty = self.tcx.expr_ty(expr);
-                    let def = match expr_ty.sty {
-                        ty::TyFnDef(.., &ty::BareFnTy { sig: ty::Binder(ty::FnSig {
-                            output: ty, ..
-                        }), ..}) => ty,
-                        _ => expr_ty
-                    }.ty_adt_def().unwrap();
-
-                    let private_indexes : Vec<_> = def.struct_variant().fields.iter().enumerate()
-                        .filter(|&(_,f)| {
-                            !f.vis.is_accessible_from(self.curitem, &self.tcx.map)
-                    }).map(|(n,&_)|n).collect();
+                if let def @ Def::StructCtor(_, CtorKind::Fn) = self.tcx.expect_def(expr.id) {
+                    let adt_def = self.tcx.expect_variant_def(def);
+                    let private_indexes = adt_def.fields.iter().enumerate().filter(|&(_, field)| {
+                        !field.vis.is_accessible_from(self.curitem, &self.tcx.map)
+                    }).map(|(i, _)| i).collect::<Vec<_>>();
 
                     if !private_indexes.is_empty() {
-
                         let mut error = struct_span_err!(self.tcx.sess, expr.span, E0450,
                                                          "cannot invoke tuple struct constructor \
-                                                         with private fields");
+                                                          with private fields");
                         error.span_label(expr.span,
                                          &format!("cannot construct with a private field"));
 
-                        if let Some(def_id) = self.tcx.map.as_local_node_id(def.did) {
-                            if let Some(hir::map::NodeItem(node)) = self.tcx.map.find(def_id) {
-                                if let hir::Item_::ItemStruct(ref tuple_data, _) = node.node {
-
-                                    for i in private_indexes {
-                                        error.span_label(tuple_data.fields()[i].span,
-                                                         &format!("private field declared here"));
-                                    }
+                        if let Some(node_id) = self.tcx.map.as_local_node_id(adt_def.did) {
+                            let node = self.tcx.map.find(node_id);
+                            if let Some(hir::map::NodeStructCtor(vdata)) = node {
+                                for i in private_indexes {
+                                    error.span_label(vdata.fields()[i].span,
+                                                     &format!("private field declared here"));
                                 }
                             }
                         }
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index 49e7f3ba19c..4f41dfc8b64 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -2786,8 +2786,7 @@ impl<'a> Resolver<'a> {
             // Look for a field with the same name in the current self_type.
             if let Some(resolution) = self.def_map.get(&node_id) {
                 match resolution.base_def {
-                    Def::Enum(did) | Def::TyAlias(did) | Def::Union(did) |
-                    Def::Struct(did) | Def::Variant(did) if resolution.depth == 0 => {
+                    Def::Struct(did) | Def::Union(did) if resolution.depth == 0 => {
                         if let Some(field_names) = self.field_names.get(&did) {
                             if field_names.iter().any(|&field_name| name == field_name) {
                                 return Field;
diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs
index 8dd1a7940b3..6d9cd88afb1 100644
--- a/src/librustc_save_analysis/dump_visitor.rs
+++ b/src/librustc_save_analysis/dump_visitor.rs
@@ -271,12 +271,10 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
         }
     }
 
-    // looks up anything, not just a type
-    fn lookup_type_ref(&self, ref_id: NodeId) -> Option<DefId> {
+    fn lookup_def_id(&self, ref_id: NodeId) -> Option<DefId> {
         self.tcx.expect_def_or_none(ref_id).and_then(|def| {
             match def {
-                Def::PrimTy(..) => None,
-                Def::SelfTy(..) => None,
+                Def::PrimTy(..) | Def::SelfTy(..) => None,
                 def => Some(def.def_id()),
             }
         })
@@ -303,11 +301,10 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
                 }.lower(self.tcx));
             }
             Def::Struct(..) |
-            Def::StructCtor(..) |
+            Def::Variant(..) |
             Def::Union(..) |
             Def::Enum(..) |
             Def::TyAlias(..) |
-            Def::AssociatedTy(..) |
             Def::Trait(_) => {
                 self.dumper.type_ref(TypeRefData {
                     span: sub_span.expect("No span found for type ref"),
@@ -317,12 +314,9 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
                 }.lower(self.tcx));
             }
             Def::Static(..) |
-            Def::Const(_) |
-            Def::AssociatedConst(..) |
-            Def::Local(..) |
-            Def::Variant(..) |
-            Def::VariantCtor(..) |
-            Def::Upvar(..) => {
+            Def::Const(..) |
+            Def::StructCtor(..) |
+            Def::VariantCtor(..) => {
                 self.dumper.variable_ref(VariableRefData {
                     span: sub_span.expect("No span found for var ref"),
                     ref_id: def_id,
@@ -337,10 +331,14 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
                     scope: scope
                 }.lower(self.tcx));
             }
+            Def::Local(..) |
+            Def::Upvar(..) |
             Def::SelfTy(..) |
             Def::Label(_) |
             Def::TyParam(..) |
             Def::Method(..) |
+            Def::AssociatedTy(..) |
+            Def::AssociatedConst(..) |
             Def::PrimTy(_) |
             Def::Err => {
                span_bug!(span,
@@ -424,7 +422,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
                             None => {
                                 if let Some(NodeItem(item)) = self.tcx.map.get_if_local(id) {
                                     if let hir::ItemImpl(_, _, _, _, ref ty, _) = item.node {
-                                        trait_id = self.lookup_type_ref(ty.id);
+                                        trait_id = self.lookup_def_id(ty.id);
                                     }
                                 }
                             }
@@ -807,7 +805,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
             };
 
             let trait_ref = &trait_ref.trait_ref;
-            if let Some(id) = self.lookup_type_ref(trait_ref.ref_id) {
+            if let Some(id) = self.lookup_def_id(trait_ref.ref_id) {
                 let sub_span = self.span.sub_span_for_type_name(trait_ref.path.span);
                 if !self.span.filter_generated(sub_span, trait_ref.path.span) {
                     self.dumper.type_ref(TypeRefData {
@@ -926,15 +924,19 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
                     }
                 }
             }
-            Def::Local(..) |
-            Def::Static(..) |
+            Def::Fn(..) |
             Def::Const(..) |
+            Def::Static(..) |
+            Def::StructCtor(..) |
+            Def::VariantCtor(..) |
             Def::AssociatedConst(..) |
+            Def::Local(..) |
+            Def::Upvar(..) |
             Def::Struct(..) |
-            Def::StructCtor(..) |
+            Def::Union(..) |
             Def::Variant(..) |
-            Def::VariantCtor(..) |
-            Def::Fn(..) => self.write_sub_paths_truncated(path, false),
+            Def::TyAlias(..) |
+            Def::AssociatedTy(..) => self.write_sub_paths_truncated(path, false),
             _ => {}
         }
     }
@@ -1167,7 +1169,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor for DumpVisitor<'l, 'tcx, 'll, D>
                 match use_item.node {
                     ast::ViewPathSimple(ident, ref path) => {
                         let sub_span = self.span.span_for_last_ident(path.span);
-                        let mod_id = match self.lookup_type_ref(item.id) {
+                        let mod_id = match self.lookup_def_id(item.id) {
                             Some(def_id) => {
                                 let scope = self.cur_scope;
                                 self.process_def_kind(item.id, path.span, sub_span, def_id, scope);
@@ -1225,7 +1227,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor for DumpVisitor<'l, 'tcx, 'll, D>
                         for plid in list {
                             let scope = self.cur_scope;
                             let id = plid.node.id;
-                            if let Some(def_id) = self.lookup_type_ref(id) {
+                            if let Some(def_id) = self.lookup_def_id(id) {
                                 let span = plid.span;
                                 self.process_def_kind(id, span, Some(span), def_id, scope);
                             }
@@ -1320,7 +1322,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor for DumpVisitor<'l, 'tcx, 'll, D>
         self.process_macro_use(t.span, t.id);
         match t.node {
             ast::TyKind::Path(_, ref path) => {
-                if let Some(id) = self.lookup_type_ref(t.id) {
+                if let Some(id) = self.lookup_def_id(t.id) {
                     let sub_span = self.span.sub_span_for_type_name(t.span);
                     if !self.span.filter_generated(sub_span, t.span) {
                         self.dumper.type_ref(TypeRefData {
@@ -1490,14 +1492,12 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor for DumpVisitor<'l, 'tcx, 'll, D>
                         }.lower(self.tcx));
                     }
                 }
-                Def::Variant(..) | Def::VariantCtor(..) | Def::Enum(..) |
-                Def::TyAlias(..) | Def::Struct(..) | Def::StructCtor(..) => {
+                Def::StructCtor(..) | Def::VariantCtor(..) |
+                Def::Const(..) | Def::AssociatedConst(..) |
+                Def::Struct(..) | Def::Variant(..) |
+                Def::TyAlias(..) | Def::AssociatedTy(..) => {
                     paths_to_process.push((id, p.clone(), Some(ref_kind)))
                 }
-                // FIXME(nrc) what are these doing here?
-                Def::Static(..) |
-                Def::Const(..) |
-                Def::AssociatedConst(..) => {}
                 def => error!("unexpected definition kind when processing collected paths: {:?}",
                               def),
             }
diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs
index 0e3ee5e9fff..15c74f2ed6a 100644
--- a/src/librustc_save_analysis/lib.rs
+++ b/src/librustc_save_analysis/lib.rs
@@ -507,7 +507,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
             Def::Static(..) |
             Def::Const(..) |
             Def::AssociatedConst(..) |
-            Def::Variant(..) |
+            Def::StructCtor(..) |
             Def::VariantCtor(..) => {
                 Some(Data::VariableRefData(VariableRefData {
                     name: self.span_utils.snippet(sub_span.unwrap()),
@@ -517,10 +517,11 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
                 }))
             }
             Def::Struct(def_id) |
-            Def::StructCtor(def_id, ..) |
+            Def::Variant(def_id, ..) |
             Def::Union(def_id) |
             Def::Enum(def_id) |
             Def::TyAlias(def_id) |
+            Def::AssociatedTy(def_id) |
             Def::Trait(def_id) |
             Def::TyParam(def_id) => {
                 Some(Data::TypeRefData(TypeRefData {
@@ -574,7 +575,10 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
                     qualname: String::new() // FIXME: generate the real qualname
                 }))
             }
-            _ => None,
+            Def::PrimTy(..) |
+            Def::SelfTy(..) |
+            Def::Label(..) |
+            Def::Err => None,
         }
     }
 
diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs
index 27491c6dfce..87729da773f 100644
--- a/src/librustc_typeck/check/_match.rs
+++ b/src/librustc_typeck/check/_match.rs
@@ -14,7 +14,6 @@ use rustc::hir::pat_util::EnumerateAndAdjustIterator;
 use rustc::infer::{self, InferOk, TypeOrigin};
 use rustc::ty::{self, Ty, TypeFoldable, LvaluePreference};
 use check::{FnCtxt, Expectation};
-use lint;
 use util::nodemap::FnvHashMap;
 
 use std::collections::hash_map::Entry::{Occupied, Vacant};
@@ -557,17 +556,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                 self.check_pat(&pat, tcx.types.err);
             }
         };
-        let report_unexpected_def = |def: Def, is_lint| {
+        let report_unexpected_def = |def: Def| {
             let msg = format!("expected tuple struct/variant, found {} `{}`",
                               def.kind_name(), path);
-            if is_lint {
-                tcx.sess.add_lint(lint::builtin::MATCH_OF_UNIT_VARIANT_VIA_PAREN_DOTDOT,
-                                  pat.id, pat.span, msg);
-            } else {
-                struct_span_err!(tcx.sess, pat.span, E0164, "{}", msg)
-                    .span_label(pat.span, &format!("not a tuple variant or struct")).emit();
-                on_error();
-            }
+            struct_span_err!(tcx.sess, pat.span, E0164, "{}", msg)
+                .span_label(pat.span, &format!("not a tuple variant or struct")).emit();
+            on_error();
         };
 
         // Resolve the path and check the definition for errors.
@@ -579,15 +573,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                 return tcx.types.err;
             }
             Def::AssociatedConst(..) | Def::Method(..) => {
-                report_unexpected_def(def, false);
+                report_unexpected_def(def);
                 return tcx.types.err;
             }
-            Def::VariantCtor(_, ctor_kind) | Def::StructCtor(_, ctor_kind) => {
-                if ctor_kind == CtorKind::Const {
-                    // Matching unit structs with tuple variant patterns (`UnitVariant(..)`)
-                    // is allowed for backward compatibility.
-                    report_unexpected_def(def, true);
-                }
+            Def::VariantCtor(_, CtorKind::Fn) |
+            Def::StructCtor(_, CtorKind::Fn) => {
                 tcx.expect_variant_def(def)
             }
             _ => bug!("unexpected pattern definition: {:?}", def)
@@ -595,13 +585,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
 
         // Type check the path.
         let pat_ty = self.instantiate_value_path(segments, opt_ty, def, pat.span, pat.id);
-        let pat_ty = if pat_ty.is_fn() {
-            // Replace constructor type with constructed type for tuple struct patterns.
-            tcx.no_late_bound_regions(&pat_ty.fn_ret()).unwrap()
-        } else {
-            // Leave the type as is for unit structs (backward compatibility).
-            pat_ty
-        };
+        // Replace constructor type with constructed type for tuple struct patterns.
+        let pat_ty = tcx.no_late_bound_regions(&pat_ty.fn_ret()).expect("expected fn type");
         self.demand_eqtype(pat.span, expected, pat_ty);
 
         // Type check subpatterns.
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 4f348a7b32b..79c1c5fb5e2 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -3245,7 +3245,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
             Def::Struct(type_did) | Def::Union(type_did) => {
                 Some((type_did, self.tcx.expect_variant_def(def)))
             }
-            Def::TyAlias(did) => {
+            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()))
@@ -4064,34 +4064,15 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         //
         // There are basically four cases to consider:
         //
-        // 1. Reference to a *type*, such as a struct or enum:
+        // 1. Reference to a constructor of enum variant or struct:
         //
-        //        mod a { struct Foo<T> { ... } }
-        //
-        //    Because we don't allow types to be declared within one
-        //    another, a path that leads to a type will always look like
-        //    `a::b::Foo<T>` where `a` and `b` are modules. This implies
-        //    that only the final segment can have type parameters, and
-        //    they are located in the TypeSpace.
-        //
-        //    *Note:* Generally speaking, references to types don't
-        //    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_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.)
-        //
-        // 1b. Reference to an enum variant or tuple-like struct:
-        //
-        //        struct foo<T>(...)
-        //        enum E<T> { foo(...) }
+        //        struct Foo<T>(...)
+        //        enum E<T> { Foo(...) }
         //
         //    In these cases, the parameters are declared in the type
         //    space.
         //
-        // 2. Reference to a *fn item*:
+        // 2. Reference to a fn item or a free constant:
         //
         //        fn foo<T>() { }
         //
@@ -4100,7 +4081,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         //    type parameters. However, in this case, those parameters are
         //    declared on a value, and hence are in the `FnSpace`.
         //
-        // 3. Reference to a *method*:
+        // 3. Reference to a method or an associated constant:
         //
         //        impl<A> SomeStruct<A> {
         //            fn foo<B>(...)
@@ -4112,15 +4093,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         //    `SomeStruct::<A>`, contains parameters in TypeSpace, and the
         //    final segment, `foo::<B>` contains parameters in fn space.
         //
-        // 4. Reference to an *associated const*:
-        //
-        // impl<A> AnotherStruct<A> {
-        // const FOO: B = BAR;
-        // }
+        // 4. Reference to a local variable
         //
-        // The path in this case will look like
-        // `a::b::AnotherStruct::<A>::FOO`, so the penultimate segment
-        // only will have parameters in TypeSpace.
+        //    Local variables can't have any type parameters.
         //
         // The first step then is to categorize the segments appropriately.
 
@@ -4130,14 +4105,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         let mut type_segment = None;
         let mut fn_segment = None;
         match def {
-            // Case 1 and 1b. Reference to a *type* or *enum variant*.
+            // Case 1. Reference to a struct/variant constructor.
             Def::StructCtor(def_id, ..) |
-            Def::Union(def_id) |
-            Def::VariantCtor(def_id, ..) |
-            Def::Enum(def_id) |
-            Def::TyAlias(def_id) |
-            Def::AssociatedTy(def_id) |
-            Def::Trait(def_id) => {
+            Def::VariantCtor(def_id, ..) => {
                 // Everything but the final segment should have no
                 // parameters at all.
                 let mut generics = self.tcx.lookup_generics(def_id);
@@ -4180,19 +4150,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                 fn_segment = Some((segments.last().unwrap(), generics));
             }
 
-            // Other cases. Various nonsense that really shouldn't show up
-            // here. If they do, an error will have been reported
-            // elsewhere. (I hope)
-            Def::Mod(..) |
-            Def::PrimTy(..) |
-            Def::SelfTy(..) |
-            Def::TyParam(..) |
-            Def::Local(..) |
-            Def::Label(..) |
-            Def::Upvar(..) |
-            Def::Variant(..) |
-            Def::Struct(..) |
-            Def::Err => {}
+            // Case 4. Local variable, no generics.
+            Def::Local(..) | Def::Upvar(..) => {}
+
+            _ => bug!("unexpected definition: {:?}", def),
         }
 
         // In `<T as Trait<A, B>>::method`, `A` and `B` are mandatory, but
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index 68e5bc6c21e..feca2d328fe 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -17,7 +17,6 @@ use rustc::hir;
 
 use rustc::hir::def::{Def, CtorKind};
 use rustc::hir::def_id::DefId;
-use rustc::hir::map::DefPathData;
 use rustc::hir::print as pprust;
 use rustc::ty::{self, TyCtxt};
 use rustc::util::nodemap::FnvHashSet;
@@ -81,9 +80,7 @@ fn try_inline_def<'a, 'tcx>(cx: &DocContext, tcx: TyCtxt<'a, 'tcx, 'tcx>,
             record_extern_fqn(cx, did, clean::TypeKind::Function);
             clean::FunctionItem(build_external_function(cx, tcx, did))
         }
-        Def::Struct(did)
-                // If this is a struct constructor, we skip it
-                if tcx.def_key(did).disambiguated_data.data != DefPathData::StructCtor => {
+        Def::Struct(did) => {
             record_extern_fqn(cx, did, clean::TypeKind::Struct);
             ret.extend(build_impls(cx, tcx, did));
             clean::StructItem(build_struct(cx, tcx, did))
@@ -105,7 +102,10 @@ fn try_inline_def<'a, 'tcx>(cx: &DocContext, tcx: TyCtxt<'a, 'tcx, 'tcx>,
         }
         // Assume that the enum type is reexported next to the variant, and
         // variants don't show up in documentation specially.
-        Def::Variant(..) => return Some(Vec::new()),
+        // Similarly, consider that struct type is reexported next to its constructor.
+        Def::Variant(..) |
+        Def::VariantCtor(..) |
+        Def::StructCtor(..) => return Some(Vec::new()),
         Def::Mod(did) => {
             record_extern_fqn(cx, did, clean::TypeKind::Module);
             clean::ModuleItem(build_module(cx, tcx, did))
@@ -114,7 +114,7 @@ fn try_inline_def<'a, 'tcx>(cx: &DocContext, tcx: TyCtxt<'a, 'tcx, 'tcx>,
             record_extern_fqn(cx, did, clean::TypeKind::Static);
             clean::StaticItem(build_static(cx, tcx, did, mtbl))
         }
-        Def::Const(did) | Def::AssociatedConst(did) => {
+        Def::Const(did) => {
             record_extern_fqn(cx, did, clean::TypeKind::Const);
             clean::ConstantItem(build_const(cx, tcx, did))
         }
@@ -501,10 +501,8 @@ fn build_module<'a, 'tcx>(cx: &DocContext, tcx: TyCtxt<'a, 'tcx, 'tcx>,
             let def_id = item.def.def_id();
             if tcx.sess.cstore.visibility(def_id) == ty::Visibility::Public {
                 if !visited.insert(def_id) { continue }
-                if let Some(def) = tcx.sess.cstore.describe_def(def_id) {
-                    if let Some(i) = try_inline_def(cx, tcx, def) {
-                        items.extend(i)
-                    }
+                if let Some(i) = try_inline_def(cx, tcx, item.def) {
+                    items.extend(i)
                 }
             }
         }