about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorEduard-Mihai Burtescu <edy.burt@gmail.com>2019-04-20 18:26:26 +0300
committerEduard-Mihai Burtescu <edy.burt@gmail.com>2019-05-03 22:48:27 +0300
commita3fcab36d25317ff2bad24d67f7e932c37f35d19 (patch)
tree3f24997e9d0e1d57bfb7912ec33f9be3743fafda /src
parent3af1bdc4bcc502d576b1e836f99bae1eb29dbafd (diff)
downloadrust-a3fcab36d25317ff2bad24d67f7e932c37f35d19.tar.gz
rust-a3fcab36d25317ff2bad24d67f7e932c37f35d19.zip
rustc: factor most DefId-containing variants out of Def and into DefKind.
Diffstat (limited to 'src')
-rw-r--r--src/librustc/hir/def.rs166
-rw-r--r--src/librustc/hir/lowering.rs41
-rw-r--r--src/librustc/hir/map/mod.rs93
-rw-r--r--src/librustc/hir/mod.rs11
-rw-r--r--src/librustc/hir/pat_util.rs8
-rw-r--r--src/librustc/middle/dead.rs10
-rw-r--r--src/librustc/middle/expr_use_visitor.rs14
-rw-r--r--src/librustc/middle/intrinsicck.rs4
-rw-r--r--src/librustc/middle/mem_categorization.rs22
-rw-r--r--src/librustc/middle/reachable.rs6
-rw-r--r--src/librustc/middle/resolve_lifetime.rs25
-rw-r--r--src/librustc/middle/stability.rs10
-rw-r--r--src/librustc/ty/context.rs4
-rw-r--r--src/librustc/ty/mod.rs32
-rw-r--r--src/librustc_lint/builtin.rs6
-rw-r--r--src/librustc_lint/nonstandard_style.rs4
-rw-r--r--src/librustc_lint/unused.rs4
-rw-r--r--src/librustc_metadata/decoder.rs64
-rw-r--r--src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs3
-rw-r--r--src/librustc_mir/const_eval.rs4
-rw-r--r--src/librustc_mir/hair/cx/expr.rs40
-rw-r--r--src/librustc_mir/hair/pattern/mod.rs21
-rw-r--r--src/librustc_mir/interpret/eval_context.rs6
-rw-r--r--src/librustc_mir/transform/const_prop.rs4
-rw-r--r--src/librustc_mir/util/pretty.rs13
-rw-r--r--src/librustc_passes/rvalue_promotion.rs19
-rw-r--r--src/librustc_privacy/lib.rs12
-rw-r--r--src/librustc_resolve/build_reduced_graph.rs87
-rw-r--r--src/librustc_resolve/diagnostics.rs38
-rw-r--r--src/librustc_resolve/lib.rs161
-rw-r--r--src/librustc_resolve/macros.rs16
-rw-r--r--src/librustc_resolve/resolve_imports.rs4
-rw-r--r--src/librustc_save_analysis/dump_visitor.rs16
-rw-r--r--src/librustc_save_analysis/lib.rs48
-rw-r--r--src/librustc_save_analysis/sig.rs6
-rw-r--r--src/librustc_typeck/astconv.rs52
-rw-r--r--src/librustc_typeck/check/_match.rs18
-rw-r--r--src/librustc_typeck/check/compare_method.rs3
-rw-r--r--src/librustc_typeck/check/demand.rs4
-rw-r--r--src/librustc_typeck/check/method/mod.rs7
-rw-r--r--src/librustc_typeck/check/method/probe.rs4
-rw-r--r--src/librustc_typeck/check/method/suggest.rs10
-rw-r--r--src/librustc_typeck/check/mod.rs26
-rw-r--r--src/librustc_typeck/collect.rs14
-rw-r--r--src/librustdoc/clean/inline.rs30
-rw-r--r--src/librustdoc/clean/mod.rs94
-rw-r--r--src/librustdoc/passes/collect_intra_doc_links.rs39
-rw-r--r--src/librustdoc/visit_ast.rs21
-rw-r--r--src/librustdoc/visit_lib.rs4
49 files changed, 737 insertions, 611 deletions
diff --git a/src/librustc/hir/def.rs b/src/librustc/hir/def.rs
index 4af79764a60..d4ad4225b99 100644
--- a/src/librustc/hir/def.rs
+++ b/src/librustc/hir/def.rs
@@ -11,12 +11,12 @@ use std::fmt::Debug;
 
 use self::Namespace::*;
 
-/// Encodes if a `Def::Ctor` is the constructor of an enum variant or a struct.
+/// Encodes if a `DefKind::Ctor` is the constructor of an enum variant or a struct.
 #[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, HashStable)]
 pub enum CtorOf {
-    /// This `Def::Ctor` is a synthesized constructor of a tuple or unit struct.
+    /// This `DefKind::Ctor` is a synthesized constructor of a tuple or unit struct.
     Struct,
-    /// This `Def::Ctor` is a synthesized constructor of a tuple or unit variant.
+    /// This `DefKind::Ctor` is a synthesized constructor of a tuple or unit variant.
     Variant,
 }
 
@@ -45,41 +45,52 @@ pub enum NonMacroAttrKind {
 }
 
 #[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, HashStable)]
-pub enum Def<Id = hir::HirId> {
+pub enum DefKind {
     // Type namespace
-    Mod(DefId),
-    /// `DefId` refers to the struct itself, `Def::Ctor` refers to its constructor if it exists.
-    Struct(DefId),
-    Union(DefId),
-    Enum(DefId),
-    /// `DefId` refers to the variant itself, `Def::Ctor` refers to its constructor if it exists.
-    Variant(DefId),
-    Trait(DefId),
+    Mod,
+    /// Refers to the struct itself, `DefKind::Ctor` refers to its constructor if it exists.
+    Struct,
+    Union,
+    Enum,
+    /// Refers to the variant itself, `DefKind::Ctor` refers to its constructor if it exists.
+    Variant,
+    Trait,
     /// `existential type Foo: Bar;`
-    Existential(DefId),
+    Existential,
     /// `type Foo = Bar;`
-    TyAlias(DefId),
-    ForeignTy(DefId),
-    TraitAlias(DefId),
-    AssociatedTy(DefId),
+    TyAlias,
+    ForeignTy,
+    TraitAlias,
+    AssociatedTy,
     /// `existential type Foo: Bar;`
-    AssociatedExistential(DefId),
+    AssociatedExistential,
+    TyParam,
+
+    // Value namespace
+    Fn,
+    Const,
+    ConstParam,
+    Static,
+    /// Refers to the struct or enum variant's constructor.
+    Ctor(CtorOf, CtorKind),
+    Method,
+    AssociatedConst,
+
+    // Macro namespace
+    Macro(MacroKind),
+}
+
+#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, HashStable)]
+pub enum Def<Id = hir::HirId> {
+    Def(DefKind, DefId),
+
+    // Type namespace
     PrimTy(hir::PrimTy),
-    TyParam(DefId),
     SelfTy(Option<DefId> /* trait */, Option<DefId> /* impl */),
     ToolMod, // e.g., `rustfmt` in `#[rustfmt::skip]`
 
     // Value namespace
-    Fn(DefId),
-    Const(DefId),
-    ConstParam(DefId),
-    Static(DefId),
-    /// `DefId` refers to the struct or enum variant's constructor.
-    Ctor(DefId, CtorOf, CtorKind),
     SelfCtor(DefId /* impl */),  // `DefId` refers to the impl
-    Method(DefId),
-    AssociatedConst(DefId),
-
     Local(Id),
     Upvar(Id,           // `HirId` of closed over local
           usize,        // index in the `freevars` list of the closure
@@ -87,10 +98,9 @@ pub enum Def<Id = hir::HirId> {
     Label(ast::NodeId),
 
     // Macro namespace
-    Macro(DefId, MacroKind),
     NonMacroAttr(NonMacroAttrKind), // e.g., `#[inline]` or `#[rustfmt::skip]`
 
-    // Both namespaces
+    // All namespaces
     Err,
 }
 
@@ -291,15 +301,7 @@ impl<Id> Def<Id> {
     /// Return `Some(..)` with the `DefId` of this `Def` if it has a id, else `None`.
     pub fn opt_def_id(&self) -> Option<DefId> {
         match *self {
-            Def::Fn(id) | Def::Mod(id) | Def::Static(id) |
-            Def::Variant(id) | Def::Ctor(id, ..) | Def::Enum(id) |
-            Def::TyAlias(id) | Def::TraitAlias(id) |
-            Def::AssociatedTy(id) | Def::TyParam(id) | Def::ConstParam(id) | Def::Struct(id) |
-            Def::Union(id) | Def::Trait(id) | Def::Method(id) | Def::Const(id) |
-            Def::AssociatedConst(id) | Def::Macro(id, ..) |
-            Def::Existential(id) | Def::AssociatedExistential(id) | Def::ForeignTy(id) => {
-                Some(id)
-            }
+            Def::Def(_, id) => Some(id),
 
             Def::Local(..) |
             Def::Upvar(..) |
@@ -318,7 +320,7 @@ impl<Id> Def<Id> {
     /// Return the `DefId` of this `Def` if it represents a module.
     pub fn mod_def_id(&self) -> Option<DefId> {
         match *self {
-            Def::Mod(id) => Some(id),
+            Def::Def(DefKind::Mod, id) => Some(id),
             _ => None,
         }
     }
@@ -326,39 +328,39 @@ impl<Id> Def<Id> {
     /// A human readable name for the def kind ("function", "module", etc.).
     pub fn kind_name(&self) -> &'static str {
         match *self {
-            Def::Fn(..) => "function",
-            Def::Mod(..) => "module",
-            Def::Static(..) => "static",
-            Def::Enum(..) => "enum",
-            Def::Variant(..) => "variant",
-            Def::Ctor(_, CtorOf::Variant, CtorKind::Fn) => "tuple variant",
-            Def::Ctor(_, CtorOf::Variant, CtorKind::Const) => "unit variant",
-            Def::Ctor(_, CtorOf::Variant, CtorKind::Fictive) => "struct variant",
-            Def::Struct(..) => "struct",
-            Def::Ctor(_, CtorOf::Struct, CtorKind::Fn) => "tuple struct",
-            Def::Ctor(_, CtorOf::Struct, CtorKind::Const) => "unit struct",
-            Def::Ctor(_, CtorOf::Struct, CtorKind::Fictive) =>
+            Def::Def(DefKind::Fn, _) => "function",
+            Def::Def(DefKind::Mod, _) => "module",
+            Def::Def(DefKind::Static, _) => "static",
+            Def::Def(DefKind::Enum, _) => "enum",
+            Def::Def(DefKind::Variant, _) => "variant",
+            Def::Def(DefKind::Ctor(CtorOf::Variant, CtorKind::Fn), _) => "tuple variant",
+            Def::Def(DefKind::Ctor(CtorOf::Variant, CtorKind::Const), _) => "unit variant",
+            Def::Def(DefKind::Ctor(CtorOf::Variant, CtorKind::Fictive), _) => "struct variant",
+            Def::Def(DefKind::Struct, _) => "struct",
+            Def::Def(DefKind::Ctor(CtorOf::Struct, CtorKind::Fn), _) => "tuple struct",
+            Def::Def(DefKind::Ctor(CtorOf::Struct, CtorKind::Const), _) => "unit struct",
+            Def::Def(DefKind::Ctor(CtorOf::Struct, CtorKind::Fictive), _) =>
                 bug!("impossible struct constructor"),
-            Def::Existential(..) => "existential type",
-            Def::TyAlias(..) => "type alias",
-            Def::TraitAlias(..) => "trait alias",
-            Def::AssociatedTy(..) => "associated type",
-            Def::AssociatedExistential(..) => "associated existential type",
+            Def::Def(DefKind::Existential, _) => "existential type",
+            Def::Def(DefKind::TyAlias, _) => "type alias",
+            Def::Def(DefKind::TraitAlias, _) => "trait alias",
+            Def::Def(DefKind::AssociatedTy, _) => "associated type",
+            Def::Def(DefKind::AssociatedExistential, _) => "associated existential type",
             Def::SelfCtor(..) => "self constructor",
-            Def::Union(..) => "union",
-            Def::Trait(..) => "trait",
-            Def::ForeignTy(..) => "foreign type",
-            Def::Method(..) => "method",
-            Def::Const(..) => "constant",
-            Def::AssociatedConst(..) => "associated constant",
-            Def::TyParam(..) => "type parameter",
-            Def::ConstParam(..) => "const parameter",
+            Def::Def(DefKind::Union, _) => "union",
+            Def::Def(DefKind::Trait, _) => "trait",
+            Def::Def(DefKind::ForeignTy, _) => "foreign type",
+            Def::Def(DefKind::Method, _) => "method",
+            Def::Def(DefKind::Const, _) => "constant",
+            Def::Def(DefKind::AssociatedConst, _) => "associated constant",
+            Def::Def(DefKind::TyParam, _) => "type parameter",
+            Def::Def(DefKind::ConstParam, _) => "const parameter",
             Def::PrimTy(..) => "builtin type",
             Def::Local(..) => "local variable",
             Def::Upvar(..) => "closure capture",
             Def::Label(..) => "label",
             Def::SelfTy(..) => "self type",
-            Def::Macro(.., macro_kind) => macro_kind.descr(),
+            Def::Def(DefKind::Macro(macro_kind), _) => macro_kind.descr(),
             Def::ToolMod => "tool module",
             Def::NonMacroAttr(attr_kind) => attr_kind.descr(),
             Def::Err => "unresolved item",
@@ -368,36 +370,21 @@ impl<Id> Def<Id> {
     /// An English article for the def.
     pub fn article(&self) -> &'static str {
         match *self {
-            Def::AssociatedTy(..) | Def::AssociatedConst(..) | Def::AssociatedExistential(..) |
-            Def::Enum(..) | Def::Existential(..) | Def::Err => "an",
-            Def::Macro(.., macro_kind) => macro_kind.article(),
+            Def::Def(DefKind::AssociatedTy, _)
+            | Def::Def(DefKind::AssociatedConst, _)
+            | Def::Def(DefKind::AssociatedExistential, _)
+            | Def::Def(DefKind::Enum, _)
+            | Def::Def(DefKind::Existential, _)
+            | Def::Err => "an",
+            Def::Def(DefKind::Macro(macro_kind), _) => macro_kind.article(),
             _ => "a",
         }
     }
 
     pub fn map_id<R>(self, mut map: impl FnMut(Id) -> R) -> Def<R> {
         match self {
-            Def::Fn(id) => Def::Fn(id),
-            Def::Mod(id) => Def::Mod(id),
-            Def::Static(id) => Def::Static(id),
-            Def::Enum(id) => Def::Enum(id),
-            Def::Variant(id) => Def::Variant(id),
-            Def::Ctor(a, b, c) => Def::Ctor(a, b, c),
-            Def::Struct(id) => Def::Struct(id),
-            Def::Existential(id) => Def::Existential(id),
-            Def::TyAlias(id) => Def::TyAlias(id),
-            Def::TraitAlias(id) => Def::TraitAlias(id),
-            Def::AssociatedTy(id) => Def::AssociatedTy(id),
-            Def::AssociatedExistential(id) => Def::AssociatedExistential(id),
+            Def::Def(kind, id) => Def::Def(kind, id),
             Def::SelfCtor(id) => Def::SelfCtor(id),
-            Def::Union(id) => Def::Union(id),
-            Def::Trait(id) => Def::Trait(id),
-            Def::ForeignTy(id) => Def::ForeignTy(id),
-            Def::Method(id) => Def::Method(id),
-            Def::Const(id) => Def::Const(id),
-            Def::AssociatedConst(id) => Def::AssociatedConst(id),
-            Def::TyParam(id) => Def::TyParam(id),
-            Def::ConstParam(id) => Def::ConstParam(id),
             Def::PrimTy(id) => Def::PrimTy(id),
             Def::Local(id) => Def::Local(map(id)),
             Def::Upvar(id, index, closure) => Def::Upvar(
@@ -407,7 +394,6 @@ impl<Id> Def<Id> {
             ),
             Def::Label(id) => Def::Label(id),
             Def::SelfTy(a, b) => Def::SelfTy(a, b),
-            Def::Macro(id, macro_kind) => Def::Macro(id, macro_kind),
             Def::ToolMod => Def::ToolMod,
             Def::NonMacroAttr(attr_kind) => Def::NonMacroAttr(attr_kind),
             Def::Err => Def::Err,
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index ad26e05bf80..583508bfb7e 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -37,7 +37,7 @@ use crate::hir::{self, ParamName};
 use crate::hir::HirVec;
 use crate::hir::map::{DefKey, DefPathData, Definitions};
 use crate::hir::def_id::{DefId, DefIndex, DefIndexAddressSpace, CRATE_DEF_INDEX};
-use crate::hir::def::{Def, PathResolution, PerNS};
+use crate::hir::def::{Def, DefKind, PathResolution, PerNS};
 use crate::hir::{GenericArg, ConstArg};
 use crate::lint::builtin::{self, PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES,
                     ELIDED_LIFETIMES_IN_PATHS};
@@ -1500,7 +1500,7 @@ impl<'a> LoweringContext<'a> {
                             None,
                             P(hir::Path {
                                 span,
-                                def: Def::TyParam(DefId::local(def_index)),
+                                def: Def::Def(DefKind::TyParam, DefId::local(def_index)),
                                 segments: hir_vec![hir::PathSegment::from_ident(ident)],
                             }),
                         ))
@@ -1870,17 +1870,17 @@ impl<'a> LoweringContext<'a> {
                         index: this.def_key(def_id).parent.expect("missing parent"),
                     };
                     let type_def_id = match resolution.base_def() {
-                        Def::AssociatedTy(def_id) if i + 2 == proj_start => {
+                        Def::Def(DefKind::AssociatedTy, def_id) if i + 2 == proj_start => {
                             Some(parent_def_id(self, def_id))
                         }
-                        Def::Variant(def_id) if i + 1 == proj_start => {
+                        Def::Def(DefKind::Variant, def_id) if i + 1 == proj_start => {
                             Some(parent_def_id(self, def_id))
                         }
-                        Def::Struct(def_id)
-                        | Def::Union(def_id)
-                        | Def::Enum(def_id)
-                        | Def::TyAlias(def_id)
-                        | Def::Trait(def_id) if i + 1 == proj_start =>
+                        Def::Def(DefKind::Struct, def_id)
+                        | Def::Def(DefKind::Union, def_id)
+                        | Def::Def(DefKind::Enum, def_id)
+                        | Def::Def(DefKind::TyAlias, def_id)
+                        | Def::Def(DefKind::Trait, def_id) if i + 1 == proj_start =>
                         {
                             Some(def_id)
                         }
@@ -1888,9 +1888,12 @@ impl<'a> LoweringContext<'a> {
                     };
                     let parenthesized_generic_args = match resolution.base_def() {
                         // `a::b::Trait(Args)`
-                        Def::Trait(..) if i + 1 == proj_start => ParenthesizedGenericArgs::Ok,
+                        Def::Def(DefKind::Trait, _)
+                            if i + 1 == proj_start => ParenthesizedGenericArgs::Ok,
                         // `a::b::Trait(Args)::TraitItem`
-                        Def::Method(..) | Def::AssociatedConst(..) | Def::AssociatedTy(..)
+                        Def::Def(DefKind::Method, _)
+                        | Def::Def(DefKind::AssociatedConst, _)
+                        | Def::Def(DefKind::AssociatedTy, _)
                             if i + 2 == proj_start =>
                         {
                             ParenthesizedGenericArgs::Ok
@@ -1898,11 +1901,11 @@ impl<'a> LoweringContext<'a> {
                         // Avoid duplicated errors.
                         Def::Err => ParenthesizedGenericArgs::Ok,
                         // An error
-                        Def::Struct(..)
-                        | Def::Enum(..)
-                        | Def::Union(..)
-                        | Def::TyAlias(..)
-                        | Def::Variant(..) if i + 1 == proj_start =>
+                        Def::Def(DefKind::Struct, _)
+                        | Def::Def(DefKind::Enum, _)
+                        | Def::Def(DefKind::Union, _)
+                        | Def::Def(DefKind::TyAlias, _)
+                        | Def::Def(DefKind::Variant, _) if i + 1 == proj_start =>
                         {
                             ParenthesizedGenericArgs::Err
                         }
@@ -2788,7 +2791,7 @@ impl<'a> LoweringContext<'a> {
                                 if path.segments.len() == 1
                                     && bound_pred.bound_generic_params.is_empty() =>
                             {
-                                if let Some(Def::TyParam(def_id)) = self.resolver
+                                if let Some(Def::Def(DefKind::TyParam, def_id)) = self.resolver
                                     .get_resolution(bound_pred.bounded_ty.id)
                                     .map(|d| d.base_def())
                                 {
@@ -3242,7 +3245,7 @@ impl<'a> LoweringContext<'a> {
                         });
 
                         if let Some(ref trait_ref) = trait_ref {
-                            if let Def::Trait(def_id) = trait_ref.path.def {
+                            if let Def::Def(DefKind::Trait, def_id) = trait_ref.path.def {
                                 this.trait_impls.entry(def_id).or_default().push(
                                     lowered_trait_impl_id);
                             }
@@ -5277,7 +5280,7 @@ impl<'a> LoweringContext<'a> {
             hir::QPath::Resolved(None, path) => {
                 // Turn trait object paths into `TyKind::TraitObject` instead.
                 match path.def {
-                    Def::Trait(_) | Def::TraitAlias(_) => {
+                    Def::Def(DefKind::Trait, _) | Def::Def(DefKind::TraitAlias, _) => {
                         let principal = hir::PolyTraitRef {
                             bound_generic_params: hir::HirVec::new(),
                             trait_ref: hir::TraitRef {
diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs
index 826ae836a90..9251f8e797b 100644
--- a/src/librustc/hir/map/mod.rs
+++ b/src/librustc/hir/map/mod.rs
@@ -17,6 +17,7 @@ use syntax::ext::base::MacroKind;
 use syntax_pos::{Span, DUMMY_SP};
 
 use crate::hir::*;
+use crate::hir::{Def, DefKind};
 use crate::hir::itemlikevisit::ItemLikeVisitor;
 use crate::hir::print::Nested;
 use crate::util::nodemap::FxHashMap;
@@ -316,67 +317,61 @@ impl<'hir> Map<'hir> {
             return None
         };
 
-        match node {
+        let kind = match node {
             Node::Item(item) => {
-                let def_id = || self.local_def_id_from_hir_id(item.hir_id);
-
                 match item.node {
-                    ItemKind::Static(..) => Some(Def::Static(def_id())),
-                    ItemKind::Const(..) => Some(Def::Const(def_id())),
-                    ItemKind::Fn(..) => Some(Def::Fn(def_id())),
-                    ItemKind::Mod(..) => Some(Def::Mod(def_id())),
-                    ItemKind::Existential(..) => Some(Def::Existential(def_id())),
-                    ItemKind::Ty(..) => Some(Def::TyAlias(def_id())),
-                    ItemKind::Enum(..) => Some(Def::Enum(def_id())),
-                    ItemKind::Struct(..) => Some(Def::Struct(def_id())),
-                    ItemKind::Union(..) => Some(Def::Union(def_id())),
-                    ItemKind::Trait(..) => Some(Def::Trait(def_id())),
-                    ItemKind::TraitAlias(..) => Some(Def::TraitAlias(def_id())),
+                    ItemKind::Static(..) => DefKind::Static,
+                    ItemKind::Const(..) => DefKind::Const,
+                    ItemKind::Fn(..) => DefKind::Fn,
+                    ItemKind::Mod(..) => DefKind::Mod,
+                    ItemKind::Existential(..) => DefKind::Existential,
+                    ItemKind::Ty(..) => DefKind::TyAlias,
+                    ItemKind::Enum(..) => DefKind::Enum,
+                    ItemKind::Struct(..) => DefKind::Struct,
+                    ItemKind::Union(..) => DefKind::Union,
+                    ItemKind::Trait(..) => DefKind::Trait,
+                    ItemKind::TraitAlias(..) => DefKind::TraitAlias,
                     ItemKind::ExternCrate(_) |
                     ItemKind::Use(..) |
                     ItemKind::ForeignMod(..) |
                     ItemKind::GlobalAsm(..) |
-                    ItemKind::Impl(..) => None,
+                    ItemKind::Impl(..) => return None,
                 }
             }
             Node::ForeignItem(item) => {
-                let def_id = self.local_def_id_from_hir_id(item.hir_id);
                 match item.node {
-                    ForeignItemKind::Fn(..) => Some(Def::Fn(def_id)),
-                    ForeignItemKind::Static(..) => Some(Def::Static(def_id)),
-                    ForeignItemKind::Type => Some(Def::ForeignTy(def_id)),
+                    ForeignItemKind::Fn(..) => DefKind::Fn,
+                    ForeignItemKind::Static(..) => DefKind::Static,
+                    ForeignItemKind::Type => DefKind::ForeignTy,
                 }
             }
             Node::TraitItem(item) => {
-                let def_id = self.local_def_id_from_hir_id(item.hir_id);
                 match item.node {
-                    TraitItemKind::Const(..) => Some(Def::AssociatedConst(def_id)),
-                    TraitItemKind::Method(..) => Some(Def::Method(def_id)),
-                    TraitItemKind::Type(..) => Some(Def::AssociatedTy(def_id)),
+                    TraitItemKind::Const(..) => DefKind::AssociatedConst,
+                    TraitItemKind::Method(..) => DefKind::Method,
+                    TraitItemKind::Type(..) => DefKind::AssociatedTy,
                 }
             }
             Node::ImplItem(item) => {
-                let def_id = self.local_def_id_from_hir_id(item.hir_id);
                 match item.node {
-                    ImplItemKind::Const(..) => Some(Def::AssociatedConst(def_id)),
-                    ImplItemKind::Method(..) => Some(Def::Method(def_id)),
-                    ImplItemKind::Type(..) => Some(Def::AssociatedTy(def_id)),
-                    ImplItemKind::Existential(..) => Some(Def::AssociatedExistential(def_id)),
+                    ImplItemKind::Const(..) => DefKind::AssociatedConst,
+                    ImplItemKind::Method(..) => DefKind::Method,
+                    ImplItemKind::Type(..) => DefKind::AssociatedTy,
+                    ImplItemKind::Existential(..) => DefKind::AssociatedExistential,
                 }
             }
-            Node::Variant(variant) => {
-                let def_id = self.local_def_id_from_hir_id(variant.node.id);
-                Some(Def::Variant(def_id))
-            }
+            Node::Variant(_) => DefKind::Variant,
             Node::Ctor(variant_data) => {
+                // FIXME(eddyb) is this even possible, if we have a `Node::Ctor`?
+                if variant_data.ctor_hir_id().is_none() {
+                    return None;
+                }
                 let ctor_of = match self.find(self.get_parent_node(node_id)) {
                     Some(Node::Item(..)) => def::CtorOf::Struct,
                     Some(Node::Variant(..)) => def::CtorOf::Variant,
                     _ => unreachable!(),
                 };
-                variant_data.ctor_hir_id()
-                    .map(|hir_id| self.local_def_id_from_hir_id(hir_id))
-                    .map(|def_id| Def::Ctor(def_id, ctor_of, def::CtorKind::from_hir(variant_data)))
+                DefKind::Ctor(ctor_of, def::CtorKind::from_hir(variant_data))
             }
             Node::AnonConst(_) |
             Node::Field(_) |
@@ -390,26 +385,22 @@ impl<'hir> Map<'hir> {
             Node::Lifetime(_) |
             Node::Visibility(_) |
             Node::Block(_) |
-            Node::Crate => None,
+            Node::Crate => return None,
+            // FIXME(eddyb) this is the only non-`DefKind` case here,
+            // investigate whether it's actually used, and ideally remove it.
             Node::Local(local) => {
-                Some(Def::Local(local.hir_id))
-            }
-            Node::MacroDef(macro_def) => {
-                Some(Def::Macro(self.local_def_id_from_hir_id(macro_def.hir_id),
-                                MacroKind::Bang))
+                return Some(Def::Local(local.hir_id));
             }
+            Node::MacroDef(_) => DefKind::Macro(MacroKind::Bang),
             Node::GenericParam(param) => {
-                Some(match param.kind {
-                    GenericParamKind::Lifetime { .. } => {
-                        Def::Local(param.hir_id)
-                    },
-                    GenericParamKind::Type { .. } => Def::TyParam(
-                        self.local_def_id_from_hir_id(param.hir_id)),
-                    GenericParamKind::Const { .. } => Def::ConstParam(
-                        self.local_def_id_from_hir_id(param.hir_id)),
-                })
+                match param.kind {
+                    GenericParamKind::Lifetime { .. } => return None,
+                    GenericParamKind::Type { .. } => DefKind::TyParam,
+                    GenericParamKind::Const { .. } => DefKind::ConstParam,
+                }
             }
-        }
+        };
+        Some(Def::Def(kind, self.local_def_id(node_id)))
     }
 
     // FIXME(@ljedrz): replace the NodeId variant
diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs
index 4293019aed5..f474ab1a1a5 100644
--- a/src/librustc/hir/mod.rs
+++ b/src/librustc/hir/mod.rs
@@ -10,7 +10,7 @@ pub use self::PrimTy::*;
 pub use self::UnOp::*;
 pub use self::UnsafeSource::*;
 
-use crate::hir::def::Def;
+use crate::hir::def::{Def, DefKind};
 use crate::hir::def_id::{DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX};
 use crate::util::nodemap::{NodeMap, FxHashSet};
 use crate::mir::mono::Linkage;
@@ -1394,7 +1394,10 @@ impl Expr {
          match self.node {
             ExprKind::Path(QPath::Resolved(_, ref path)) => {
                 match path.def {
-                    Def::Local(..) | Def::Upvar(..) | Def::Static(..) | Def::Err => true,
+                    Def::Local(..)
+                    | Def::Upvar(..)
+                    | Def::Def(DefKind::Static, _)
+                    | Def::Err => true,
                     _ => false,
                 }
             }
@@ -2152,8 +2155,8 @@ impl TraitRef {
     /// Gets the `DefId` of the referenced trait. It _must_ actually be a trait or trait alias.
     pub fn trait_def_id(&self) -> DefId {
         match self.path.def {
-            Def::Trait(did) => did,
-            Def::TraitAlias(did) => did,
+            Def::Def(DefKind::Trait, did) => did,
+            Def::Def(DefKind::TraitAlias, did) => did,
             Def::Err => {
                 FatalError.raise();
             }
diff --git a/src/librustc/hir/pat_util.rs b/src/librustc/hir/pat_util.rs
index e7eda5aab13..a1ff3dcda2d 100644
--- a/src/librustc/hir/pat_util.rs
+++ b/src/librustc/hir/pat_util.rs
@@ -1,4 +1,4 @@
-use crate::hir::def::{CtorOf, Def};
+use crate::hir::def::{CtorOf, Def, DefKind};
 use crate::hir::def_id::DefId;
 use crate::hir::{self, HirId, PatKind};
 use syntax::ast;
@@ -55,7 +55,7 @@ impl hir::Pat {
             PatKind::TupleStruct(hir::QPath::Resolved(_, ref path), ..) |
             PatKind::Struct(hir::QPath::Resolved(_, ref path), ..) => {
                 match path.def {
-                    Def::Variant(..) => true,
+                    Def::Def(DefKind::Variant, _) => true,
                     _ => false
                 }
             }
@@ -125,8 +125,8 @@ impl hir::Pat {
                 PatKind::TupleStruct(hir::QPath::Resolved(_, ref path), ..) |
                 PatKind::Struct(hir::QPath::Resolved(_, ref path), ..) => {
                     match path.def {
-                        Def::Variant(id) => variants.push(id),
-                        Def::Ctor(id, CtorOf::Variant, ..) => variants.push(id),
+                        Def::Def(DefKind::Variant, id) => variants.push(id),
+                        Def::Def(DefKind::Ctor(CtorOf::Variant, ..), id) => variants.push(id),
                         _ => ()
                     }
                 }
diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs
index 28fc3047af6..a58fb1a933e 100644
--- a/src/librustc/middle/dead.rs
+++ b/src/librustc/middle/dead.rs
@@ -7,7 +7,7 @@ use crate::hir::{self, PatKind, TyKind};
 use crate::hir::intravisit::{self, Visitor, NestedVisitorMap};
 use crate::hir::itemlikevisit::ItemLikeVisitor;
 
-use crate::hir::def::{CtorOf, Def};
+use crate::hir::def::{CtorOf, Def, DefKind};
 use crate::hir::CodegenFnAttrFlags;
 use crate::hir::def_id::{DefId, LOCAL_CRATE};
 use crate::lint;
@@ -70,13 +70,15 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
 
     fn handle_definition(&mut self, def: Def) {
         match def {
-            Def::Const(_) | Def::AssociatedConst(..) | Def::TyAlias(_) => {
+            Def::Def(DefKind::Const, _)
+            | Def::Def(DefKind::AssociatedConst, _)
+            | Def::Def(DefKind::TyAlias, _) => {
                 self.check_def_id(def.def_id());
             }
             _ if self.in_pat => {},
             Def::PrimTy(..) | Def::SelfTy(..) | Def::SelfCtor(..) |
             Def::Local(..) | Def::Upvar(..) => {}
-            Def::Ctor(ctor_def_id, CtorOf::Variant, ..) => {
+            Def::Def(DefKind::Ctor(CtorOf::Variant, ..), ctor_def_id) => {
                 let variant_id = self.tcx.parent(ctor_def_id).unwrap();
                 let enum_id = self.tcx.parent(variant_id).unwrap();
                 self.check_def_id(enum_id);
@@ -84,7 +86,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
                     self.check_def_id(variant_id);
                 }
             }
-            Def::Variant(variant_id) => {
+            Def::Def(DefKind::Variant, variant_id) => {
                 let enum_id = self.tcx.parent(variant_id).unwrap();
                 self.check_def_id(enum_id);
                 if !self.ignore_variant_stack.contains(&variant_id) {
diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs
index 3b9af75bd0a..149f9fe96f6 100644
--- a/src/librustc/middle/expr_use_visitor.rs
+++ b/src/librustc/middle/expr_use_visitor.rs
@@ -9,7 +9,7 @@ pub use self::MatchMode::*;
 use self::TrackMatchMode::*;
 use self::OverloadedCallType::*;
 
-use crate::hir::def::{CtorOf, Def};
+use crate::hir::def::{CtorOf, Def, DefKind};
 use crate::hir::def_id::DefId;
 use crate::infer::InferCtxt;
 use crate::middle::mem_categorization as mc;
@@ -900,21 +900,25 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
             };
             let def = mc.tables.qpath_def(qpath, pat.hir_id);
             match def {
-                Def::Ctor(variant_ctor_did, CtorOf::Variant, ..) => {
+                Def::Def(DefKind::Ctor(CtorOf::Variant, ..), variant_ctor_did) => {
                     let variant_did = mc.tcx.parent(variant_ctor_did).unwrap();
                     let downcast_cmt = mc.cat_downcast_if_needed(pat, cmt_pat, variant_did);
 
                     debug!("variantctor downcast_cmt={:?} pat={:?}", downcast_cmt, pat);
                     delegate.matched_pat(pat, &downcast_cmt, match_mode);
                 }
-                Def::Variant(variant_did) => {
+                Def::Def(DefKind::Variant, variant_did) => {
                     let downcast_cmt = mc.cat_downcast_if_needed(pat, cmt_pat, variant_did);
 
                     debug!("variant downcast_cmt={:?} pat={:?}", downcast_cmt, pat);
                     delegate.matched_pat(pat, &downcast_cmt, match_mode);
                 }
-                Def::Struct(..) | Def::Ctor(..) | Def::Union(..) |
-                Def::TyAlias(..) | Def::AssociatedTy(..) | Def::SelfTy(..) => {
+                Def::Def(DefKind::Struct, _)
+                | Def::Def(DefKind::Ctor(..), _)
+                | Def::Def(DefKind::Union, _)
+                | Def::Def(DefKind::TyAlias, _)
+                | Def::Def(DefKind::AssociatedTy, _)
+                | Def::SelfTy(..) => {
                     debug!("struct cmt_pat={:?} pat={:?}", cmt_pat, pat);
                     delegate.matched_pat(pat, &cmt_pat, match_mode);
                 }
diff --git a/src/librustc/middle/intrinsicck.rs b/src/librustc/middle/intrinsicck.rs
index c4071e9f354..507aff69005 100644
--- a/src/librustc/middle/intrinsicck.rs
+++ b/src/librustc/middle/intrinsicck.rs
@@ -1,4 +1,4 @@
-use crate::hir::def::Def;
+use crate::hir::def::{Def, DefKind};
 use crate::hir::def_id::DefId;
 use crate::ty::{self, Ty, TyCtxt};
 use crate::ty::layout::{LayoutError, Pointer, SizeSkeleton, VariantIdx};
@@ -157,7 +157,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ExprVisitor<'a, 'tcx> {
         } else {
             Def::Err
         };
-        if let Def::Fn(did) = def {
+        if let Def::Def(DefKind::Fn, did) = def {
             if self.def_id_is_transmute(did) {
                 let typ = self.tables.node_type(expr.hir_id);
                 let sig = typ.fn_sig(self.tcx);
diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs
index 34b44234279..21c7152ed7d 100644
--- a/src/librustc/middle/mem_categorization.rs
+++ b/src/librustc/middle/mem_categorization.rs
@@ -62,7 +62,7 @@ use crate::middle::region;
 use crate::hir::def_id::{DefId, LocalDefId};
 use crate::hir::Node;
 use crate::infer::InferCtxt;
-use crate::hir::def::{CtorOf, Def, CtorKind};
+use crate::hir::def::{CtorOf, Def, DefKind, CtorKind};
 use crate::ty::adjustment;
 use crate::ty::{self, DefIdTree, Ty, TyCtxt};
 use crate::ty::fold::TypeFoldable;
@@ -699,12 +699,17 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
                hir_id, expr_ty, def);
 
         match def {
-            Def::Ctor(..) | Def::Const(..) | Def::ConstParam(..) |
-            Def::AssociatedConst(..) | Def::Fn(..) | Def::Method(..) | Def::SelfCtor(..) => {
+            Def::Def(DefKind::Ctor(..), _)
+            | Def::Def(DefKind::Const, _)
+            | Def::Def(DefKind::ConstParam, _)
+            | Def::Def(DefKind::AssociatedConst, _)
+            | Def::Def(DefKind::Fn, _)
+            | Def::Def(DefKind::Method, _)
+            | Def::SelfCtor(..) => {
                 Ok(self.cat_rvalue_node(hir_id, span, expr_ty))
             }
 
-            Def::Static(def_id) => {
+            Def::Def(DefKind::Static, def_id) => {
                 // `#[thread_local]` statics may not outlive the current function, but
                 // they also cannot be moved out of.
                 let is_thread_local = self.tcx.get_attrs(def_id)[..]
@@ -1274,14 +1279,15 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
                         debug!("access to unresolvable pattern {:?}", pat);
                         return Err(())
                     }
-                    Def::Ctor(variant_ctor_did, CtorOf::Variant, CtorKind::Fn) => {
+                    Def::Def(DefKind::Ctor(CtorOf::Variant, CtorKind::Fn), variant_ctor_did) => {
                         let variant_did = self.tcx.parent(variant_ctor_did).unwrap();
                         let enum_did = self.tcx.parent(variant_did).unwrap();
                         (self.cat_downcast_if_needed(pat, cmt, variant_did),
                          self.tcx.adt_def(enum_did)
                              .variant_with_ctor_id(variant_ctor_did).fields.len())
                     }
-                    Def::Ctor(_, CtorOf::Struct, CtorKind::Fn) | Def::SelfCtor(..) => {
+                    Def::Def(DefKind::Ctor(CtorOf::Struct, CtorKind::Fn), _)
+                    | Def::SelfCtor(..) => {
                         let ty = self.pat_ty_unadjusted(&pat)?;
                         match ty.sty {
                             ty::Adt(adt_def, _) => {
@@ -1316,11 +1322,11 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
                         debug!("access to unresolvable pattern {:?}", pat);
                         return Err(())
                     }
-                    Def::Ctor(variant_ctor_did, CtorOf::Variant, _) => {
+                    Def::Def(DefKind::Ctor(CtorOf::Variant, _), variant_ctor_did) => {
                         let variant_did = self.tcx.parent(variant_ctor_did).unwrap();
                         self.cat_downcast_if_needed(pat, cmt, variant_did)
                     }
-                    Def::Variant(variant_did) => {
+                    Def::Def(DefKind::Variant, variant_did) => {
                         self.cat_downcast_if_needed(pat, cmt, variant_did)
                     }
                     _ => cmt,
diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs
index 92266838dd8..8647820d574 100644
--- a/src/librustc/middle/reachable.rs
+++ b/src/librustc/middle/reachable.rs
@@ -7,7 +7,7 @@
 
 use crate::hir::{CodegenFnAttrs, CodegenFnAttrFlags};
 use crate::hir::Node;
-use crate::hir::def::Def;
+use crate::hir::def::{Def, DefKind};
 use crate::hir::def_id::{DefId, CrateNum};
 use rustc_data_structures::sync::Lrc;
 use crate::ty::{self, TyCtxt};
@@ -117,7 +117,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ReachableContext<'a, 'tcx> {
                             // If this path leads to a constant, then we need to
                             // recurse into the constant to continue finding
                             // items that are reachable.
-                            Def::Const(..) | Def::AssociatedConst(..) => {
+                            Def::Def(DefKind::Const, _) | Def::Def(DefKind::AssociatedConst, _) => {
                                 self.worklist.push(hir_id);
                             }
 
@@ -357,7 +357,7 @@ impl<'a, 'tcx: 'a> ItemLikeVisitor<'tcx> for CollectPrivateImplItemsVisitor<'a,
                 self.worklist.extend(impl_item_refs.iter().map(|ii_ref| ii_ref.id.hir_id));
 
                 let trait_def_id = match trait_ref.path.def {
-                    Def::Trait(def_id) => def_id,
+                    Def::Def(DefKind::Trait, def_id) => def_id,
                     _ => unreachable!()
                 };
 
diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs
index 814776c21bd..1e886c08d41 100644
--- a/src/librustc/middle/resolve_lifetime.rs
+++ b/src/librustc/middle/resolve_lifetime.rs
@@ -5,7 +5,7 @@
 //! used between functions, and they operate in a purely top-down
 //! way. Therefore, we break lifetime name resolution into a separate pass.
 
-use crate::hir::def::Def;
+use crate::hir::def::{Def, DefKind};
 use crate::hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
 use crate::hir::map::Map;
 use crate::hir::{GenericArg, GenericParam, ItemLocalId, LifetimeName, Node, ParamName};
@@ -1365,7 +1365,7 @@ fn object_lifetime_defaults_for_item(
                         _ => continue,
                     };
 
-                    if def == Def::TyParam(param_def_id) {
+                    if def == Def::Def(DefKind::TyParam, param_def_id) {
                         add_bounds(&mut set, &data.bounds);
                     }
                 }
@@ -1929,13 +1929,15 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
             }
         };
         let type_def_id = match def {
-            Def::AssociatedTy(def_id) if depth == 1 => Some(parent_def_id(self, def_id)),
-            Def::Variant(def_id) if depth == 0 => Some(parent_def_id(self, def_id)),
-            Def::Struct(def_id)
-            | Def::Union(def_id)
-            | Def::Enum(def_id)
-            | Def::TyAlias(def_id)
-            | Def::Trait(def_id) if depth == 0 =>
+            Def::Def(DefKind::AssociatedTy, def_id)
+                if depth == 1 => Some(parent_def_id(self, def_id)),
+            Def::Def(DefKind::Variant, def_id)
+                if depth == 0 => Some(parent_def_id(self, def_id)),
+            Def::Def(DefKind::Struct, def_id)
+            | Def::Def(DefKind::Union, def_id)
+            | Def::Def(DefKind::Enum, def_id)
+            | Def::Def(DefKind::TyAlias, def_id)
+            | Def::Def(DefKind::Trait, def_id) if depth == 0 =>
             {
                 Some(def_id)
             }
@@ -2139,7 +2141,10 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
                         // Whitelist the types that unambiguously always
                         // result in the same type constructor being used
                         // (it can't differ between `Self` and `self`).
-                        Def::Struct(_) | Def::Union(_) | Def::Enum(_) | Def::PrimTy(_) => {
+                        Def::Def(DefKind::Struct, _)
+                        | Def::Def(DefKind::Union, _)
+                        | Def::Def(DefKind::Enum, _)
+                        | Def::PrimTy(_) => {
                             return def == path.def
                         }
                         _ => {}
diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs
index 8ce86f70a55..e651e82d304 100644
--- a/src/librustc/middle/stability.rs
+++ b/src/librustc/middle/stability.rs
@@ -5,7 +5,7 @@ pub use self::StabilityLevel::*;
 
 use crate::lint::{self, Lint, in_derive_expansion};
 use crate::hir::{self, Item, Generics, StructField, Variant, HirId};
-use crate::hir::def::Def;
+use crate::hir::def::{Def, DefKind};
 use crate::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId, LOCAL_CRATE};
 use crate::hir::intravisit::{self, Visitor, NestedVisitorMap};
 use crate::ty::query::Providers;
@@ -526,9 +526,9 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
     fn skip_stability_check_due_to_privacy(self, mut def_id: DefId) -> bool {
         // Check if `def_id` is a trait method.
         match self.describe_def(def_id) {
-            Some(Def::Method(_)) |
-            Some(Def::AssociatedTy(_)) |
-            Some(Def::AssociatedConst(_)) => {
+            Some(Def::Def(DefKind::Method, _)) |
+            Some(Def::Def(DefKind::AssociatedTy, _)) |
+            Some(Def::Def(DefKind::AssociatedConst, _)) => {
                 if let ty::TraitContainer(trait_def_id) = self.associated_item(def_id).container {
                     // Trait methods do not declare visibility (even
                     // for visibility info in cstore). Use containing
@@ -779,7 +779,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
             // individually as it's possible to have a stable trait with unstable
             // items.
             hir::ItemKind::Impl(.., Some(ref t), _, ref impl_item_refs) => {
-                if let Def::Trait(trait_did) = t.path.def {
+                if let Def::Def(DefKind::Trait, trait_did) = t.path.def {
                     for impl_item_ref in impl_item_refs {
                         let impl_item = self.tcx.hir().impl_item(impl_item_ref.id);
                         let trait_item_def_id = self.tcx.associated_items(trait_did)
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index c07175d9451..48c3400c597 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -10,7 +10,7 @@ use crate::session::config::{BorrowckMode, OutputFilenames};
 use crate::session::config::CrateType;
 use crate::middle;
 use crate::hir::{TraitCandidate, HirId, ItemKind, ItemLocalId, Node};
-use crate::hir::def::{Def, Export};
+use crate::hir::def::{Def, DefKind, Export};
 use crate::hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE};
 use crate::hir::map as hir_map;
 use crate::hir::map::DefPathHash;
@@ -658,7 +658,7 @@ impl<'tcx> TypeckTables<'tcx> {
         }
 
         match self.type_dependent_defs().get(expr.hir_id) {
-            Some(&Def::Method(_)) => true,
+            Some(&Def::Def(DefKind::Method, _)) => true,
             _ => false
         }
     }
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index 36da21b71f5..3871b465cab 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -10,7 +10,7 @@ pub use self::fold::TypeFoldable;
 
 use crate::hir::{map as hir_map, FreevarMap, GlobMap, TraitMap};
 use crate::hir::{HirId, Node};
-use crate::hir::def::{Def, CtorOf, CtorKind, ExportMap};
+use crate::hir::def::{Def, DefKind, CtorOf, CtorKind, ExportMap};
 use crate::hir::def_id::{CrateNum, DefId, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE};
 use rustc_data_structures::svh::Svh;
 use rustc_macros::HashStable;
@@ -193,10 +193,10 @@ pub enum AssociatedKind {
 impl AssociatedItem {
     pub fn def(&self) -> Def {
         match self.kind {
-            AssociatedKind::Const => Def::AssociatedConst(self.def_id),
-            AssociatedKind::Method => Def::Method(self.def_id),
-            AssociatedKind::Type => Def::AssociatedTy(self.def_id),
-            AssociatedKind::Existential => Def::AssociatedExistential(self.def_id),
+            AssociatedKind::Const => Def::Def(DefKind::AssociatedConst, self.def_id),
+            AssociatedKind::Method => Def::Def(DefKind::Method, self.def_id),
+            AssociatedKind::Type => Def::Def(DefKind::AssociatedTy, self.def_id),
+            AssociatedKind::Existential => Def::Def(DefKind::AssociatedExistential, self.def_id),
         }
     }
 
@@ -2339,10 +2339,10 @@ impl<'a, 'gcx, 'tcx> AdtDef {
 
     pub fn variant_of_def(&self, def: Def) -> &VariantDef {
         match def {
-            Def::Variant(vid) => self.variant_with_id(vid),
-            Def::Ctor(cid, ..) => self.variant_with_ctor_id(cid),
-            Def::Struct(..) | Def::Union(..) |
-            Def::TyAlias(..) | Def::AssociatedTy(..) | Def::SelfTy(..) |
+            Def::Def(DefKind::Variant, vid) => self.variant_with_id(vid),
+            Def::Def(DefKind::Ctor(..), cid) => self.variant_with_ctor_id(cid),
+            Def::Def(DefKind::Struct, _) | Def::Def(DefKind::Union, _) |
+            Def::Def(DefKind::TyAlias, _) | Def::Def(DefKind::AssociatedTy, _) | Def::SelfTy(..) |
             Def::SelfCtor(..) => self.non_enum_variant(),
             _ => bug!("unexpected def {:?} in variant_of_def", def)
         }
@@ -2806,7 +2806,9 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
             }
         } else {
             match self.describe_def(def_id).expect("no def for def-id") {
-                Def::AssociatedConst(_) | Def::Method(_) | Def::AssociatedTy(_) => true,
+                Def::Def(DefKind::AssociatedConst, _)
+                | Def::Def(DefKind::Method, _)
+                | Def::Def(DefKind::AssociatedTy, _) => true,
                 _ => false,
             }
         };
@@ -2952,19 +2954,19 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
     /// or variant or their constructors, panics otherwise.
     pub fn expect_variant_def(self, def: Def) -> &'tcx VariantDef {
         match def {
-            Def::Variant(did) => {
+            Def::Def(DefKind::Variant, did) => {
                 let enum_did = self.parent(did).unwrap();
                 self.adt_def(enum_did).variant_with_id(did)
             }
-            Def::Struct(did) | Def::Union(did) => {
+            Def::Def(DefKind::Struct, did) | Def::Def(DefKind::Union, did) => {
                 self.adt_def(did).non_enum_variant()
             }
-            Def::Ctor(variant_ctor_did, CtorOf::Variant, ..) => {
+            Def::Def(DefKind::Ctor(CtorOf::Variant, ..), variant_ctor_did) => {
                 let variant_did = self.parent(variant_ctor_did).unwrap();
                 let enum_did = self.parent(variant_did).unwrap();
                 self.adt_def(enum_did).variant_with_ctor_id(variant_ctor_did)
             }
-            Def::Ctor(ctor_did, CtorOf::Struct, ..) => {
+            Def::Def(DefKind::Ctor(CtorOf::Struct, ..), ctor_did) => {
                 let struct_did = self.parent(ctor_did).expect("struct ctor has no parent");
                 self.adt_def(struct_did).non_enum_variant()
             }
@@ -3044,7 +3046,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
     /// `DefId` of the impl that the method belongs to; otherwise, returns `None`.
     pub fn impl_of_method(self, def_id: DefId) -> Option<DefId> {
         let item = if def_id.krate != LOCAL_CRATE {
-            if let Some(Def::Method(_)) = self.describe_def(def_id) {
+            if let Some(Def::Def(DefKind::Method, _)) = self.describe_def(def_id) {
                 Some(self.associated_item(def_id))
             } else {
                 None
diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs
index 47c1c16f1f8..8f583f3546b 100644
--- a/src/librustc_lint/builtin.rs
+++ b/src/librustc_lint/builtin.rs
@@ -21,7 +21,7 @@
 //! If you define a new `LateLintPass`, you will also need to add it to the
 //! `late_lint_methods!` invocation in `lib.rs`.
 
-use rustc::hir::def::Def;
+use rustc::hir::def::{Def, DefKind};
 use rustc::hir::def_id::{DefId, LOCAL_CRATE};
 use rustc::ty::{self, Ty};
 use rustc::{lint, util};
@@ -916,7 +916,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MutableTransmutes {
             } else {
                 return None;
             };
-            if let Def::Fn(did) = def {
+            if let Def::Def(DefKind::Fn, did) = def {
                 if !def_id_is_transmute(cx, did) {
                     return None;
                 }
@@ -1072,7 +1072,7 @@ impl TypeAliasBounds {
                 match ty.node {
                     hir::TyKind::Path(hir::QPath::Resolved(None, ref path)) => {
                         match path.def {
-                            Def::TyParam(_) => true,
+                            Def::Def(DefKind::TyParam, _) => true,
                             _ => false
                         }
                     }
diff --git a/src/librustc_lint/nonstandard_style.rs b/src/librustc_lint/nonstandard_style.rs
index 1d8979f7d1c..7e6af43c500 100644
--- a/src/librustc_lint/nonstandard_style.rs
+++ b/src/librustc_lint/nonstandard_style.rs
@@ -1,5 +1,5 @@
 use rustc::hir::{self, GenericParamKind, PatKind};
-use rustc::hir::def::Def;
+use rustc::hir::def::{Def, DefKind};
 use rustc::hir::intravisit::FnKind;
 use rustc::lint;
 use rustc::ty;
@@ -415,7 +415,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonUpperCaseGlobals {
     fn check_pat(&mut self, cx: &LateContext<'_, '_>, p: &hir::Pat) {
         // Lint for constants that look like binding identifiers (#7526)
         if let PatKind::Path(hir::QPath::Resolved(None, ref path)) = p.node {
-            if let Def::Const(..) = path.def {
+            if let Def::Def(DefKind::Const, _) = path.def {
                 if path.segments.len() == 1 {
                     NonUpperCaseGlobals::check_upper_case(
                         cx,
diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs
index 043bc62ddce..9962caf0731 100644
--- a/src/librustc_lint/unused.rs
+++ b/src/librustc_lint/unused.rs
@@ -1,4 +1,4 @@
-use rustc::hir::def::Def;
+use rustc::hir::def::{Def, DefKind};
 use rustc::hir::def_id::DefId;
 use rustc::lint;
 use rustc::ty;
@@ -93,7 +93,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults {
                     hir::ExprKind::Path(ref qpath) => {
                         let def = cx.tables.qpath_def(qpath, callee.hir_id);
                         match def {
-                            Def::Fn(_) | Def::Method(_) => Some(def),
+                            Def::Def(DefKind::Fn, _) | Def::Def(DefKind::Method, _) => Some(def),
                             // `Def::Local` if it was a closure, for which we
                             // do not currently support must-use linting
                             _ => None
diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs
index 0e3d05d29a3..cc7a72c7593 100644
--- a/src/librustc_metadata/decoder.rs
+++ b/src/librustc_metadata/decoder.rs
@@ -8,7 +8,7 @@ use rustc::hir::map::{DefKey, DefPath, DefPathData, DefPathHash, Definitions};
 use rustc::hir;
 use rustc::middle::cstore::LinkagePreference;
 use rustc::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel};
-use rustc::hir::def::{self, Def, CtorOf, CtorKind};
+use rustc::hir::def::{self, Def, DefKind, CtorOf, CtorKind};
 use rustc::hir::def_id::{CrateNum, DefId, DefIndex, DefIndexAddressSpace,
                          CRATE_DEF_INDEX, LOCAL_CRATE, LocalDefId};
 use rustc::hir::map::definitions::DefPathTable;
@@ -401,30 +401,30 @@ impl<'a, 'tcx> MetadataBlob {
 impl<'tcx> EntryKind<'tcx> {
     fn to_def(&self, did: DefId) -> Option<Def> {
         Some(match *self {
-            EntryKind::Const(..) => Def::Const(did),
-            EntryKind::AssociatedConst(..) => Def::AssociatedConst(did),
+            EntryKind::Const(..) => Def::Def(DefKind::Const, did),
+            EntryKind::AssociatedConst(..) => Def::Def(DefKind::AssociatedConst, did),
             EntryKind::ImmStatic |
             EntryKind::MutStatic |
             EntryKind::ForeignImmStatic |
-            EntryKind::ForeignMutStatic => Def::Static(did),
-            EntryKind::Struct(_, _) => Def::Struct(did),
-            EntryKind::Union(_, _) => Def::Union(did),
+            EntryKind::ForeignMutStatic => Def::Def(DefKind::Static, did),
+            EntryKind::Struct(_, _) => Def::Def(DefKind::Struct, did),
+            EntryKind::Union(_, _) => Def::Def(DefKind::Union, did),
             EntryKind::Fn(_) |
-            EntryKind::ForeignFn(_) => Def::Fn(did),
-            EntryKind::Method(_) => Def::Method(did),
-            EntryKind::Type => Def::TyAlias(did),
-            EntryKind::TypeParam => Def::TyParam(did),
-            EntryKind::ConstParam => Def::ConstParam(did),
-            EntryKind::Existential => Def::Existential(did),
-            EntryKind::AssociatedType(_) => Def::AssociatedTy(did),
-            EntryKind::AssociatedExistential(_) => Def::AssociatedExistential(did),
-            EntryKind::Mod(_) => Def::Mod(did),
-            EntryKind::Variant(_) => Def::Variant(did),
-            EntryKind::Trait(_) => Def::Trait(did),
-            EntryKind::TraitAlias(_) => Def::TraitAlias(did),
-            EntryKind::Enum(..) => Def::Enum(did),
-            EntryKind::MacroDef(_) => Def::Macro(did, MacroKind::Bang),
-            EntryKind::ForeignType => Def::ForeignTy(did),
+            EntryKind::ForeignFn(_) => Def::Def(DefKind::Fn, did),
+            EntryKind::Method(_) => Def::Def(DefKind::Method, did),
+            EntryKind::Type => Def::Def(DefKind::TyAlias, did),
+            EntryKind::TypeParam => Def::Def(DefKind::TyParam, did),
+            EntryKind::ConstParam => Def::Def(DefKind::ConstParam, did),
+            EntryKind::Existential => Def::Def(DefKind::Existential, did),
+            EntryKind::AssociatedType(_) => Def::Def(DefKind::AssociatedTy, did),
+            EntryKind::AssociatedExistential(_) => Def::Def(DefKind::AssociatedExistential, did),
+            EntryKind::Mod(_) => Def::Def(DefKind::Mod, did),
+            EntryKind::Variant(_) => Def::Def(DefKind::Variant, did),
+            EntryKind::Trait(_) => Def::Def(DefKind::Trait, did),
+            EntryKind::TraitAlias(_) => Def::Def(DefKind::TraitAlias, did),
+            EntryKind::Enum(..) => Def::Def(DefKind::Enum, did),
+            EntryKind::MacroDef(_) => Def::Def(DefKind::Macro(MacroKind::Bang), did),
+            EntryKind::ForeignType => Def::Def(DefKind::ForeignTy, did),
 
             EntryKind::ForeignMod |
             EntryKind::GlobalAsm |
@@ -512,7 +512,7 @@ impl<'a, 'tcx> CrateMetadata {
             self.entry(index).kind.to_def(self.local_def_id(index))
         } else {
             let kind = self.proc_macros.as_ref().unwrap()[index.to_proc_macro_index()].1.kind();
-            Some(Def::Macro(self.local_def_id(index), kind))
+            Some(Def::Def(DefKind::Macro(kind), self.local_def_id(index)))
         }
     }
 
@@ -743,12 +743,12 @@ impl<'a, 'tcx> CrateMetadata {
              */
             if id == CRATE_DEF_INDEX {
                 for (id, &(name, ref ext)) in proc_macros.iter().enumerate() {
-                    let def = Def::Macro(
+                    let def = Def::Def(
+                        DefKind::Macro(ext.kind()),
                         DefId {
                             krate: self.cnum,
                             index: DefIndex::from_proc_macro_index(id),
                         },
-                        ext.kind()
                     );
                     let ident = Ident::with_empty_ctxt(name);
                     callback(def::Export {
@@ -815,22 +815,28 @@ impl<'a, 'tcx> CrateMetadata {
                     // For non-re-export structs and variants add their constructors to children.
                     // Re-export lists automatically contain constructors when necessary.
                     match def {
-                        Def::Struct(..) => {
+                        Def::Def(DefKind::Struct, _) => {
                             if let Some(ctor_def_id) = self.get_ctor_def_id(child_index) {
                                 let ctor_kind = self.get_ctor_kind(child_index);
-                                let ctor_def = Def::Ctor(ctor_def_id, CtorOf::Struct, ctor_kind);
+                                let ctor_def = Def::Def(
+                                    DefKind::Ctor(CtorOf::Struct, ctor_kind),
+                                    ctor_def_id,
+                                );
                                 let vis = self.get_visibility(ctor_def_id.index);
                                 callback(def::Export { def: ctor_def, vis, ident, span });
                             }
                         }
-                        Def::Variant(def_id) => {
+                        Def::Def(DefKind::Variant, def_id) => {
                             // Braced variants, unlike structs, generate unusable names in
                             // value namespace, they are reserved for possible future use.
                             // It's ok to use the variant's id as a ctor id since an
                             // error will be reported on any use of such resolution anyway.
                             let ctor_def_id = self.get_ctor_def_id(child_index).unwrap_or(def_id);
                             let ctor_kind = self.get_ctor_kind(child_index);
-                            let ctor_def = Def::Ctor(ctor_def_id, CtorOf::Variant, ctor_kind);
+                            let ctor_def = Def::Def(
+                                DefKind::Ctor(CtorOf::Variant, ctor_kind),
+                                ctor_def_id,
+                            );
                             let mut vis = self.get_visibility(ctor_def_id.index);
                             if ctor_def_id == def_id && vis == ty::Visibility::Public {
                                 // For non-exhaustive variants lower the constructor visibility to
@@ -854,7 +860,7 @@ impl<'a, 'tcx> CrateMetadata {
         if let EntryKind::Mod(data) = item.kind {
             for exp in data.decode((self, sess)).reexports.decode((self, sess)) {
                 match exp.def {
-                    Def::Macro(..) => {}
+                    Def::Def(DefKind::Macro(..), _) => {}
                     _ if macros_only => continue,
                     _ => {}
                 }
diff --git a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs
index f9b571a7d60..4a636fa87c6 100644
--- a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs
+++ b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs
@@ -4,6 +4,7 @@ use crate::borrow_check::nll::universal_regions::DefiningTy;
 use crate::borrow_check::nll::ToRegionVid;
 use crate::borrow_check::Upvar;
 use rustc::hir;
+use rustc::hir::def::{Def, DefKind};
 use rustc::hir::def_id::DefId;
 use rustc::infer::InferCtxt;
 use rustc::mir::Mir;
@@ -496,7 +497,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                         // be the same as those of the ADT.
                         // FIXME: We should be able to do something similar to
                         // match_adt_and_segment in this case.
-                        hir::def::Def::TyAlias(_) => (),
+                        Def::Def(DefKind::TyAlias, _) => (),
                         _ => if let Some(last_segment) = path.segments.last() {
                             if let Some(name) = self.match_adt_and_segment(
                                 substs,
diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs
index 681a204d76e..f4c7b40647c 100644
--- a/src/librustc_mir/const_eval.rs
+++ b/src/librustc_mir/const_eval.rs
@@ -6,7 +6,7 @@ use std::borrow::{Borrow, Cow};
 use std::hash::Hash;
 use std::collections::hash_map::Entry;
 
-use rustc::hir::def::Def;
+use rustc::hir::def::{Def, DefKind};
 use rustc::hir::def_id::DefId;
 use rustc::mir::interpret::{ConstEvalErr, ErrorHandled};
 use rustc::mir;
@@ -641,7 +641,7 @@ pub fn const_eval_raw_provider<'a, 'tcx>(
                 // note that validation may still cause a hard error on this very same constant,
                 // because any code that existed before validation could not have failed validation
                 // thus preventing such a hard error from being a backwards compatibility hazard
-                Some(Def::Const(_)) | Some(Def::AssociatedConst(_)) => {
+                Some(Def::Def(DefKind::Const, _)) | Some(Def::Def(DefKind::AssociatedConst, _)) => {
                     let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
                     err.report_as_lint(
                         tcx.at(tcx.def_span(def_id)),
diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs
index 6e11f1dae9b..b1c3cdc9dc8 100644
--- a/src/librustc_mir/hair/cx/expr.rs
+++ b/src/librustc_mir/hair/cx/expr.rs
@@ -4,7 +4,7 @@ use crate::hair::cx::block;
 use crate::hair::cx::to_ref::ToRef;
 use crate::hair::util::UserAnnotatedTyHelpers;
 use rustc_data_structures::indexed_vec::Idx;
-use rustc::hir::def::{CtorOf, Def, CtorKind};
+use rustc::hir::def::{CtorOf, Def, DefKind, CtorKind};
 use rustc::mir::interpret::{GlobalId, ErrorHandled, ConstValue};
 use rustc::ty::{self, AdtKind, Ty};
 use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow, AutoBorrowMutability, PointerCast};
@@ -250,7 +250,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                     // Tuple-like ADTs are represented as ExprKind::Call. We convert them here.
                     expr_ty.ty_adt_def().and_then(|adt_def| {
                         match path.def {
-                            Def::Ctor(ctor_id, _, CtorKind::Fn) =>
+                            Def::Def(DefKind::Ctor(_, CtorKind::Fn), ctor_id) =>
                                 Some((adt_def, adt_def.variant_index_with_ctor_id(ctor_id))),
                             Def::SelfCtor(..) => Some((adt_def, VariantIdx::new(0))),
                             _ => None,
@@ -470,7 +470,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                         AdtKind::Enum => {
                             let def = cx.tables().qpath_def(qpath, expr.hir_id);
                             match def {
-                                Def::Variant(variant_id) => {
+                                Def::Def(DefKind::Variant, variant_id) => {
                                     assert!(base.is_none());
 
                                     let index = adt.variant_index_with_id(variant_id);
@@ -664,7 +664,10 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                         .ty_adt_def()
                         .and_then(|adt_def| {
                         match def {
-                            Def::Ctor(variant_ctor_id, CtorOf::Variant, CtorKind::Const) => {
+                            Def::Def(
+                                DefKind::Ctor(CtorOf::Variant, CtorKind::Const),
+                                variant_ctor_id,
+                            ) => {
                                 let idx = adt_def.variant_index_with_ctor_id(variant_ctor_id);
                                 let (d, o) = adt_def.discriminant_def_for_variant(idx);
                                 use rustc::ty::util::IntTypeExt;
@@ -792,17 +795,18 @@ fn user_substs_applied_to_def(
         // A reference to something callable -- e.g., a fn, method, or
         // a tuple-struct or tuple-variant. This has the type of a
         // `Fn` but with the user-given substitutions.
-        Def::Fn(_) |
-        Def::Method(_) |
-        Def::Ctor(_, _, CtorKind::Fn) |
-        Def::Const(_) |
-        Def::AssociatedConst(_) => cx.tables().user_provided_types().get(hir_id).map(|u_ty| *u_ty),
+        Def::Def(DefKind::Fn, _) |
+        Def::Def(DefKind::Method, _) |
+        Def::Def(DefKind::Ctor(_, CtorKind::Fn), _) |
+        Def::Def(DefKind::Const, _) |
+        Def::Def(DefKind::AssociatedConst, _) =>
+            cx.tables().user_provided_types().get(hir_id).map(|u_ty| *u_ty),
 
         // A unit struct/variant which is used as a value (e.g.,
         // `None`). This has the type of the enum/struct that defines
         // this variant -- but with the substitutions given by the
         // user.
-        Def::Ctor(_, _, CtorKind::Const) =>
+        Def::Def(DefKind::Ctor(_, CtorKind::Const), _) =>
             cx.user_substs_applied_to_ty_of_hir_id(hir_id),
 
         // `Self` is used in expression as a tuple struct constructor or an unit struct constructor
@@ -895,9 +899,9 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
     let substs = cx.tables().node_substs(expr.hir_id);
     match def {
         // A regular function, constructor function or a constant.
-        Def::Fn(_) |
-        Def::Method(_) |
-        Def::Ctor(_, _, CtorKind::Fn) |
+        Def::Def(DefKind::Fn, _) |
+        Def::Def(DefKind::Method, _) |
+        Def::Def(DefKind::Ctor(_, CtorKind::Fn), _) |
         Def::SelfCtor(..) => {
             let user_ty = user_substs_applied_to_def(cx, expr.hir_id, &def);
             debug!("convert_path_expr: user_ty={:?}", user_ty);
@@ -909,7 +913,7 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
             }
         }
 
-        Def::ConstParam(def_id) => {
+        Def::Def(DefKind::ConstParam, def_id) => {
             let node_id = cx.tcx.hir().as_local_node_id(def_id).unwrap();
             let item_id = cx.tcx.hir().get_parent_node(node_id);
             let item_def_id = cx.tcx.hir().local_def_id(item_id);
@@ -928,8 +932,8 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
             }
         }
 
-        Def::Const(def_id) |
-        Def::AssociatedConst(def_id) => {
+        Def::Def(DefKind::Const, def_id) |
+        Def::Def(DefKind::AssociatedConst, def_id) => {
             let user_ty = user_substs_applied_to_def(cx, expr.hir_id, &def);
             debug!("convert_path_expr: (const) user_ty={:?}", user_ty);
             ExprKind::Literal {
@@ -941,7 +945,7 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
             }
         },
 
-        Def::Ctor(def_id, _, CtorKind::Const) => {
+        Def::Def(DefKind::Ctor(_, CtorKind::Const), def_id) => {
             let user_provided_types = cx.tables.user_provided_types();
             let user_provided_type = user_provided_types.get(expr.hir_id).map(|u_ty| *u_ty);
             debug!("convert_path_expr: user_provided_type={:?}", user_provided_type);
@@ -963,7 +967,7 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
             }
         }
 
-        Def::Static(id) => ExprKind::StaticRef { id },
+        Def::Def(DefKind::Static, id) => ExprKind::StaticRef { id },
 
         Def::Local(..) | Def::Upvar(..) => convert_var(cx, expr, def),
 
diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs
index e354ec3e0ba..90551d8d167 100644
--- a/src/librustc_mir/hair/pattern/mod.rs
+++ b/src/librustc_mir/hair/pattern/mod.rs
@@ -18,7 +18,7 @@ use rustc::ty::{CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTyp
 use rustc::ty::subst::{SubstsRef, Kind};
 use rustc::ty::layout::VariantIdx;
 use rustc::hir::{self, PatKind, RangeEnd};
-use rustc::hir::def::{CtorOf, Def, CtorKind};
+use rustc::hir::def::{CtorOf, Def, DefKind, CtorKind};
 use rustc::hir::pat_util::EnumerateAndAdjustIterator;
 
 use rustc_data_structures::indexed_vec::Idx;
@@ -733,15 +733,15 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
         subpatterns: Vec<FieldPattern<'tcx>>,
     ) -> PatternKind<'tcx> {
         let def = match def {
-            Def::Ctor(variant_ctor_id, CtorOf::Variant, ..) => {
+            Def::Def(DefKind::Ctor(CtorOf::Variant, ..), variant_ctor_id) => {
                 let variant_id = self.tcx.parent(variant_ctor_id).unwrap();
-                Def::Variant(variant_id)
+                Def::Def(DefKind::Variant, variant_id)
             },
             def => def,
         };
 
         let mut kind = match def {
-            Def::Variant(variant_id) => {
+            Def::Def(DefKind::Variant, variant_id) => {
                 let enum_id = self.tcx.parent(variant_id).unwrap();
                 let adt_def = self.tcx.adt_def(enum_id);
                 if adt_def.is_enum() {
@@ -764,8 +764,13 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
                 }
             }
 
-            Def::Struct(..) | Def::Ctor(_, CtorOf::Struct, ..) | Def::Union(..) |
-            Def::TyAlias(..) | Def::AssociatedTy(..) | Def::SelfTy(..) | Def::SelfCtor(..) => {
+            Def::Def(DefKind::Struct, _)
+            | Def::Def(DefKind::Ctor(CtorOf::Struct, ..), _)
+            | Def::Def(DefKind::Union, _)
+            | Def::Def(DefKind::TyAlias, _)
+            | Def::Def(DefKind::AssociatedTy, _)
+            | Def::SelfTy(..)
+            | Def::SelfCtor(..) => {
                 PatternKind::Leaf { subpatterns }
             }
 
@@ -805,11 +810,11 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
         let ty = self.tables.node_type(id);
         let def = self.tables.qpath_def(qpath, id);
         let is_associated_const = match def {
-            Def::AssociatedConst(_) => true,
+            Def::Def(DefKind::AssociatedConst, _) => true,
             _ => false,
         };
         let kind = match def {
-            Def::Const(def_id) | Def::AssociatedConst(def_id) => {
+            Def::Def(DefKind::Const, def_id) | Def::Def(DefKind::AssociatedConst, def_id) => {
                 let substs = self.tables.node_substs(id);
                 match ty::Instance::resolve(
                     self.tcx,
diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs
index 4ae8bfe854d..7a8530b31ce 100644
--- a/src/librustc_mir/interpret/eval_context.rs
+++ b/src/librustc_mir/interpret/eval_context.rs
@@ -4,7 +4,7 @@ use std::mem;
 
 use syntax::source_map::{self, Span, DUMMY_SP};
 use rustc::hir::def_id::DefId;
-use rustc::hir::def::Def;
+use rustc::hir::def::{Def, DefKind};
 use rustc::mir;
 use rustc::ty::layout::{
     self, Size, Align, HasDataLayout, LayoutOf, TyLayout
@@ -503,7 +503,9 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tc
             // Now mark those locals as dead that we do not want to initialize
             match self.tcx.describe_def(instance.def_id()) {
                 // statics and constants don't have `Storage*` statements, no need to look for them
-                Some(Def::Static(..)) | Some(Def::Const(..)) | Some(Def::AssociatedConst(..)) => {},
+                Some(Def::Def(DefKind::Static, _))
+                | Some(Def::Def(DefKind::Const, _))
+                | Some(Def::Def(DefKind::AssociatedConst, _)) => {},
                 _ => {
                     trace!("push_stack_frame: {:?}: num_bbs: {}", span, mir.basic_blocks().len());
                     for block in mir.basic_blocks() {
diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs
index 2d89f73a95f..a114c18ace8 100644
--- a/src/librustc_mir/transform/const_prop.rs
+++ b/src/librustc_mir/transform/const_prop.rs
@@ -1,7 +1,7 @@
 //! Propagates constants for early reporting of statically known
 //! assertion failures
 
-use rustc::hir::def::Def;
+use rustc::hir::def::{Def, DefKind};
 use rustc::mir::{
     Constant, Location, Place, PlaceBase, Mir, Operand, Rvalue, Local,
     NullOp, UnOp, StatementKind, Statement, LocalKind, Static, StaticKind,
@@ -43,7 +43,7 @@ impl MirPass for ConstProp {
 
         let is_fn_like = FnLikeNode::from_node(tcx.hir().get_by_hir_id(hir_id)).is_some();
         let is_assoc_const = match tcx.describe_def(source.def_id()) {
-            Some(Def::AssociatedConst(_)) => true,
+            Some(Def::Def(DefKind::AssociatedConst, _)) => true,
             _ => false,
         };
 
diff --git a/src/librustc_mir/util/pretty.rs b/src/librustc_mir/util/pretty.rs
index 6c377684bee..790d3c6624a 100644
--- a/src/librustc_mir/util/pretty.rs
+++ b/src/librustc_mir/util/pretty.rs
@@ -575,19 +575,22 @@ fn write_mir_sig(
     mir: &Mir<'_>,
     w: &mut dyn Write,
 ) -> io::Result<()> {
-    use rustc::hir::def::Def;
+    use rustc::hir::def::{Def, DefKind};
 
     trace!("write_mir_sig: {:?}", src.instance);
     let descr = tcx.describe_def(src.def_id());
     let is_function = match descr {
-        Some(Def::Fn(_)) | Some(Def::Method(_)) | Some(Def::Ctor(..)) => true,
+        Some(Def::Def(DefKind::Fn, _))
+        | Some(Def::Def(DefKind::Method, _))
+        | Some(Def::Def(DefKind::Ctor(..), _)) => true,
         _ => tcx.is_closure(src.def_id()),
     };
     match (descr, src.promoted) {
         (_, Some(i)) => write!(w, "{:?} in ", i)?,
-        (Some(Def::Const(_)), _) | (Some(Def::AssociatedConst(_)), _) => write!(w, "const ")?,
-        (Some(Def::Static(def_id)), _) =>
-            write!(w, "static {}", if tcx.is_mutable_static(def_id) { "mut " } else { "" })?,
+        (Some(Def::Def(DefKind::Const, _)), _)
+        | (Some(Def::Def(DefKind::AssociatedConst, _)), _) => write!(w, "const ")?,
+        (Some(Def::Def(DefKind::Static, _)), _) =>
+            write!(w, "static {}", if tcx.is_mutable_static(src.def_id()) { "mut " } else { "" })?,
         (_, _) if is_function => write!(w, "fn ")?,
         (None, _) => {}, // things like anon const, not an item
         _ => bug!("Unexpected def description {:?}", descr),
diff --git a/src/librustc_passes/rvalue_promotion.rs b/src/librustc_passes/rvalue_promotion.rs
index 881f63e994d..57cea198c72 100644
--- a/src/librustc_passes/rvalue_promotion.rs
+++ b/src/librustc_passes/rvalue_promotion.rs
@@ -15,7 +15,7 @@
 // by borrowck::gather_loans
 
 use rustc::ty::cast::CastTy;
-use rustc::hir::def::{Def, CtorKind};
+use rustc::hir::def::{Def, DefKind, CtorKind};
 use rustc::hir::def_id::DefId;
 use rustc::middle::expr_use_visitor as euv;
 use rustc::middle::mem_categorization as mc;
@@ -321,14 +321,17 @@ fn check_expr_kind<'a, 'tcx>(
         hir::ExprKind::Path(ref qpath) => {
             let def = v.tables.qpath_def(qpath, e.hir_id);
             match def {
-                Def::Ctor(..) | Def::Fn(..) | Def::Method(..) | Def::SelfCtor(..) =>
+                Def::Def(DefKind::Ctor(..), _)
+                | Def::Def(DefKind::Fn, _)
+                | Def::Def(DefKind::Method, _)
+                | Def::SelfCtor(..) =>
                     Promotable,
 
                 // References to a static that are themselves within a static
                 // are inherently promotable with the exception
                 //  of "#[thread_local]" statics, which may not
                 // outlive the current function
-                Def::Static(did) => {
+                Def::Def(DefKind::Static, did) => {
 
                     if v.in_static {
                         for attr in &v.tcx.get_attrs(did)[..] {
@@ -346,8 +349,8 @@ fn check_expr_kind<'a, 'tcx>(
                     }
                 }
 
-                Def::Const(did) |
-                Def::AssociatedConst(did) => {
+                Def::Def(DefKind::Const, did) |
+                Def::Def(DefKind::AssociatedConst, did) => {
                     let promotable = if v.tcx.trait_of_item(did).is_some() {
                         // Don't peek inside trait associated constants.
                         NotPromotable
@@ -386,10 +389,10 @@ fn check_expr_kind<'a, 'tcx>(
                 Def::Err
             };
             let def_result = match def {
-                Def::Ctor(_, _, CtorKind::Fn) |
+                Def::Def(DefKind::Ctor(_, CtorKind::Fn), _) |
                 Def::SelfCtor(..) => Promotable,
-                Def::Fn(did) => v.handle_const_fn_call(did),
-                Def::Method(did) => {
+                Def::Def(DefKind::Fn, did) => v.handle_const_fn_call(did),
+                Def::Def(DefKind::Method, did) => {
                     match v.tcx.associated_item(did).container {
                         ty::ImplContainer(_) => v.handle_const_fn_call(did),
                         ty::TraitContainer(_) => NotPromotable,
diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs
index 702b6200a16..b971de06bbf 100644
--- a/src/librustc_privacy/lib.rs
+++ b/src/librustc_privacy/lib.rs
@@ -12,7 +12,7 @@
 
 use rustc::bug;
 use rustc::hir::{self, Node, PatKind, AssociatedItemKind};
-use rustc::hir::def::Def;
+use rustc::hir::def::{Def, DefKind};
 use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, CrateNum, DefId};
 use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
 use rustc::hir::itemlikevisit::DeepVisitor;
@@ -1107,9 +1107,9 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> {
     fn visit_qpath(&mut self, qpath: &'tcx hir::QPath, id: hir::HirId, span: Span) {
         let def = match *qpath {
             hir::QPath::Resolved(_, ref path) => match path.def {
-                Def::Method(..) | Def::AssociatedConst(..) |
-                Def::AssociatedTy(..) | Def::AssociatedExistential(..) |
-                Def::Static(..) => Some(path.def),
+                Def::Def(DefKind::Method, _) | Def::Def(DefKind::AssociatedConst, _) |
+                Def::Def(DefKind::AssociatedTy, _) | Def::Def(DefKind::AssociatedExistential, _) |
+                Def::Def(DefKind::Static, _) => Some(path.def),
                 _ => None,
             }
             hir::QPath::TypeRelative(..) => {
@@ -1118,7 +1118,9 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> {
         };
         if let Some(def) = def {
             let def_id = def.def_id();
-            let is_local_static = if let Def::Static(..) = def { def_id.is_local() } else { false };
+            let is_local_static = if let Def::Def(DefKind::Static, _) = def {
+                def_id.is_local()
+            } else { false };
             if !self.item_is_accessible(def_id) && !is_local_static {
                 let name = match *qpath {
                     hir::QPath::Resolved(_, ref path) => path.to_string(),
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
index 6870e97b53b..5c7e51d4057 100644
--- a/src/librustc_resolve/build_reduced_graph.rs
+++ b/src/librustc_resolve/build_reduced_graph.rs
@@ -424,7 +424,7 @@ impl<'a> Resolver<'a> {
 
             ItemKind::Mod(..) => {
                 let def_id = self.definitions.local_def_id(item.id);
-                let module_kind = ModuleKind::Def(Def::Mod(def_id), ident.name);
+                let module_kind = ModuleKind::Def(Def::Def(DefKind::Mod, def_id), ident.name);
                 let module = self.arenas.alloc_module(ModuleData {
                     no_implicit_prelude: parent.no_implicit_prelude || {
                         attr::contains_name(&item.attrs, "no_implicit_prelude")
@@ -443,29 +443,32 @@ impl<'a> Resolver<'a> {
 
             // These items live in the value namespace.
             ItemKind::Static(..) => {
-                let def = Def::Static(self.definitions.local_def_id(item.id));
+                let def = Def::Def(DefKind::Static, self.definitions.local_def_id(item.id));
                 self.define(parent, ident, ValueNS, (def, vis, sp, expansion));
             }
             ItemKind::Const(..) => {
-                let def = Def::Const(self.definitions.local_def_id(item.id));
+                let def = Def::Def(DefKind::Const, self.definitions.local_def_id(item.id));
                 self.define(parent, ident, ValueNS, (def, vis, sp, expansion));
             }
             ItemKind::Fn(..) => {
-                let def = Def::Fn(self.definitions.local_def_id(item.id));
+                let def = Def::Def(DefKind::Fn, self.definitions.local_def_id(item.id));
                 self.define(parent, ident, ValueNS, (def, vis, sp, expansion));
 
                 // Functions introducing procedural macros reserve a slot
                 // in the macro namespace as well (see #52225).
                 if attr::contains_name(&item.attrs, "proc_macro") ||
                    attr::contains_name(&item.attrs, "proc_macro_attribute") {
-                    let def = Def::Macro(def.def_id(), MacroKind::ProcMacroStub);
+                    let def = Def::Def(DefKind::Macro(MacroKind::ProcMacroStub), def.def_id());
                     self.define(parent, ident, MacroNS, (def, vis, sp, expansion));
                 }
                 if let Some(attr) = attr::find_by_name(&item.attrs, "proc_macro_derive") {
                     if let Some(trait_attr) =
                             attr.meta_item_list().and_then(|list| list.get(0).cloned()) {
                         if let Some(ident) = trait_attr.ident() {
-                            let def = Def::Macro(def.def_id(), MacroKind::ProcMacroStub);
+                            let def = Def::Def(
+                                DefKind::Macro(MacroKind::ProcMacroStub),
+                                def.def_id(),
+                            );
                             self.define(parent, ident, MacroNS, (def, vis, ident.span, expansion));
                         }
                     }
@@ -474,17 +477,17 @@ impl<'a> Resolver<'a> {
 
             // These items live in the type namespace.
             ItemKind::Ty(..) => {
-                let def = Def::TyAlias(self.definitions.local_def_id(item.id));
+                let def = Def::Def(DefKind::TyAlias, self.definitions.local_def_id(item.id));
                 self.define(parent, ident, TypeNS, (def, vis, sp, expansion));
             }
 
             ItemKind::Existential(_, _) => {
-                let def = Def::Existential(self.definitions.local_def_id(item.id));
+                let def = Def::Def(DefKind::Existential, self.definitions.local_def_id(item.id));
                 self.define(parent, ident, TypeNS, (def, vis, sp, expansion));
             }
 
             ItemKind::Enum(ref enum_definition, _) => {
-                let def = Def::Enum(self.definitions.local_def_id(item.id));
+                let def = Def::Def(DefKind::Enum, self.definitions.local_def_id(item.id));
                 let module_kind = ModuleKind::Def(def, ident.name);
                 let module = self.new_module(parent,
                                              module_kind,
@@ -499,7 +502,7 @@ impl<'a> Resolver<'a> {
             }
 
             ItemKind::TraitAlias(..) => {
-                let def = Def::TraitAlias(self.definitions.local_def_id(item.id));
+                let def = Def::Def(DefKind::TraitAlias, self.definitions.local_def_id(item.id));
                 self.define(parent, ident, TypeNS, (def, vis, sp, expansion));
             }
 
@@ -507,7 +510,7 @@ impl<'a> Resolver<'a> {
             ItemKind::Struct(ref struct_def, _) => {
                 // Define a name in the type namespace.
                 let def_id = self.definitions.local_def_id(item.id);
-                let def = Def::Struct(def_id);
+                let def = Def::Def(DefKind::Struct, def_id);
                 self.define(parent, ident, TypeNS, (def, vis, sp, expansion));
 
                 let mut ctor_vis = vis;
@@ -534,16 +537,17 @@ impl<'a> Resolver<'a> {
                 // If this is a tuple or unit struct, define a name
                 // in the value namespace as well.
                 if let Some(ctor_node_id) = struct_def.ctor_id() {
-                    let ctor_def = Def::Ctor(self.definitions.local_def_id(ctor_node_id),
-                                             CtorOf::Struct,
-                                             CtorKind::from_ast(struct_def));
+                    let ctor_def = Def::Def(
+                        DefKind::Ctor(CtorOf::Struct, CtorKind::from_ast(struct_def)),
+                        self.definitions.local_def_id(ctor_node_id),
+                    );
                     self.define(parent, ident, ValueNS, (ctor_def, ctor_vis, sp, expansion));
                     self.struct_constructors.insert(def.def_id(), (ctor_def, ctor_vis));
                 }
             }
 
             ItemKind::Union(ref vdata, _) => {
-                let def = Def::Union(self.definitions.local_def_id(item.id));
+                let def = Def::Def(DefKind::Union, self.definitions.local_def_id(item.id));
                 self.define(parent, ident, TypeNS, (def, vis, sp, expansion));
 
                 // Record field names for error reporting.
@@ -561,7 +565,7 @@ impl<'a> Resolver<'a> {
                 let def_id = self.definitions.local_def_id(item.id);
 
                 // Add all the items within to a new module.
-                let module_kind = ModuleKind::Def(Def::Trait(def_id), ident.name);
+                let module_kind = ModuleKind::Def(Def::Def(DefKind::Trait, def_id), ident.name);
                 let module = self.new_module(parent,
                                              module_kind,
                                              parent.normal_ancestor_id,
@@ -586,7 +590,7 @@ impl<'a> Resolver<'a> {
 
         // Define a name in the type namespace.
         let def_id = self.definitions.local_def_id(variant.node.id);
-        let def = Def::Variant(def_id);
+        let def = Def::Def(DefKind::Variant, def_id);
         self.define(parent, ident, TypeNS, (def, vis, variant.span, expansion));
 
         // If the variant is marked as non_exhaustive then lower the visibility to within the
@@ -605,7 +609,7 @@ impl<'a> Resolver<'a> {
         let ctor_node_id = variant.node.data.ctor_id().unwrap_or(variant.node.id);
         let ctor_def_id = self.definitions.local_def_id(ctor_node_id);
         let ctor_kind = CtorKind::from_ast(&variant.node.data);
-        let ctor_def = Def::Ctor(ctor_def_id, CtorOf::Variant, ctor_kind);
+        let ctor_def = Def::Def(DefKind::Ctor(CtorOf::Variant, ctor_kind), ctor_def_id);
         self.define(parent, ident, ValueNS, (ctor_def, ctor_vis, variant.span, expansion));
     }
 
@@ -613,13 +617,13 @@ impl<'a> Resolver<'a> {
     fn build_reduced_graph_for_foreign_item(&mut self, item: &ForeignItem, expansion: Mark) {
         let (def, ns) = match item.node {
             ForeignItemKind::Fn(..) => {
-                (Def::Fn(self.definitions.local_def_id(item.id)), ValueNS)
+                (Def::Def(DefKind::Fn, self.definitions.local_def_id(item.id)), ValueNS)
             }
             ForeignItemKind::Static(..) => {
-                (Def::Static(self.definitions.local_def_id(item.id)), ValueNS)
+                (Def::Def(DefKind::Static, self.definitions.local_def_id(item.id)), ValueNS)
             }
             ForeignItemKind::Ty => {
-                (Def::ForeignTy(self.definitions.local_def_id(item.id)), TypeNS)
+                (Def::Def(DefKind::ForeignTy, self.definitions.local_def_id(item.id)), TypeNS)
             }
             ForeignItemKind::Macro(_) => unreachable!(),
         };
@@ -654,7 +658,7 @@ impl<'a> Resolver<'a> {
         let ident = ident.gensym_if_underscore();
         let expansion = Mark::root(); // FIXME(jseyfried) intercrate hygiene
         match def {
-            Def::Mod(def_id) | Def::Enum(def_id) => {
+            Def::Def(DefKind::Mod, def_id) | Def::Def(DefKind::Enum, def_id) => {
                 let module = self.new_module(parent,
                                              ModuleKind::Def(def, ident.name),
                                              def_id,
@@ -662,15 +666,22 @@ impl<'a> Resolver<'a> {
                                              span);
                 self.define(parent, ident, TypeNS, (module, vis, DUMMY_SP, expansion));
             }
-            Def::Variant(..) | Def::TyAlias(..) | Def::ForeignTy(..) | Def::Existential(..) |
-            Def::TraitAlias(..) | Def::PrimTy(..) | Def::ToolMod => {
+            Def::Def(DefKind::Variant, _)
+            | Def::Def(DefKind::TyAlias, _)
+            | Def::Def(DefKind::ForeignTy, _)
+            | Def::Def(DefKind::Existential, _)
+            | Def::Def(DefKind::TraitAlias, _)
+            | Def::PrimTy(..)
+            | Def::ToolMod => {
                 self.define(parent, ident, TypeNS, (def, vis, DUMMY_SP, expansion));
             }
-            Def::Fn(..) | Def::Static(..) | Def::Const(..) |
-            Def::Ctor(_, CtorOf::Variant, ..) => {
+            Def::Def(DefKind::Fn, _)
+            | Def::Def(DefKind::Static, _)
+            | Def::Def(DefKind::Const, _)
+            | Def::Def(DefKind::Ctor(CtorOf::Variant, ..), _) => {
                 self.define(parent, ident, ValueNS, (def, vis, DUMMY_SP, expansion));
             }
-            Def::Ctor(def_id, CtorOf::Struct, ..) => {
+            Def::Def(DefKind::Ctor(CtorOf::Struct, ..), def_id) => {
                 self.define(parent, ident, ValueNS, (def, vis, DUMMY_SP, expansion));
 
                 if let Some(struct_def_id) =
@@ -679,7 +690,7 @@ impl<'a> Resolver<'a> {
                     self.struct_constructors.insert(struct_def_id, (def, vis));
                 }
             }
-            Def::Trait(def_id) => {
+            Def::Def(DefKind::Trait, def_id) => {
                 let module_kind = ModuleKind::Def(def, ident.name);
                 let module = self.new_module(parent,
                                              module_kind,
@@ -690,7 +701,9 @@ impl<'a> Resolver<'a> {
 
                 for child in self.cstore.item_children_untracked(def_id, self.session) {
                     let def = child.def.map_id(|_| panic!("unexpected id"));
-                    let ns = if let Def::AssociatedTy(..) = def { TypeNS } else { ValueNS };
+                    let ns = if let Def::Def(DefKind::AssociatedTy, _) = def {
+                        TypeNS
+                    } else { ValueNS };
                     self.define(module, child.ident, ns,
                                 (def, ty::Visibility::Public, DUMMY_SP, expansion));
 
@@ -701,14 +714,14 @@ impl<'a> Resolver<'a> {
                 }
                 module.populated.set(true);
             }
-            Def::Struct(def_id) | Def::Union(def_id) => {
+            Def::Def(DefKind::Struct, def_id) | Def::Def(DefKind::Union, def_id) => {
                 self.define(parent, ident, TypeNS, (def, vis, DUMMY_SP, expansion));
 
                 // Record field names for error reporting.
                 let field_names = self.cstore.struct_field_names_untracked(def_id);
                 self.insert_field_names(def_id, field_names);
             }
-            Def::Macro(..) | Def::NonMacroAttr(..) => {
+            Def::Def(DefKind::Macro(..), _) | Def::NonMacroAttr(..) => {
                 self.define(parent, ident, MacroNS, (def, vis, DUMMY_SP, expansion));
             }
             _ => bug!("unexpected definition: {:?}", def)
@@ -733,7 +746,7 @@ impl<'a> Resolver<'a> {
              Some(self.get_module(DefId { index: def_key.parent.unwrap(), ..def_id })))
         };
 
-        let kind = ModuleKind::Def(Def::Mod(def_id), name.as_symbol());
+        let kind = ModuleKind::Def(Def::Def(DefKind::Mod, def_id), name.as_symbol());
         let module =
             self.arenas.alloc_module(ModuleData::new(parent, kind, def_id, Mark::root(), DUMMY_SP));
         self.extern_module_map.insert((def_id, macros_only), module);
@@ -754,11 +767,11 @@ impl<'a> Resolver<'a> {
 
     pub fn get_macro(&mut self, def: Def) -> Lrc<SyntaxExtension> {
         let def_id = match def {
-            Def::Macro(def_id, ..) => def_id,
+            Def::Def(DefKind::Macro(..), def_id) => def_id,
             Def::NonMacroAttr(attr_kind) => return Lrc::new(SyntaxExtension::NonMacroAttr {
                 mark_used: attr_kind == NonMacroAttrKind::Tool,
             }),
-            _ => panic!("expected `Def::Macro` or `Def::NonMacroAttr`"),
+            _ => panic!("expected `DefKind::Macro` or `Def::NonMacroAttr`"),
         };
         if let Some(ext) = self.macro_map.get(&def_id) {
             return ext.clone();
@@ -1016,14 +1029,14 @@ impl<'a, 'b> Visitor<'a> for BuildReducedGraphVisitor<'a, 'b> {
         // Add the item to the trait info.
         let item_def_id = self.resolver.definitions.local_def_id(item.id);
         let (def, ns) = match item.node {
-            TraitItemKind::Const(..) => (Def::AssociatedConst(item_def_id), ValueNS),
+            TraitItemKind::Const(..) => (Def::Def(DefKind::AssociatedConst, item_def_id), ValueNS),
             TraitItemKind::Method(ref sig, _) => {
                 if sig.decl.has_self() {
                     self.resolver.has_self.insert(item_def_id);
                 }
-                (Def::Method(item_def_id), ValueNS)
+                (Def::Def(DefKind::Method, item_def_id), ValueNS)
             }
-            TraitItemKind::Type(..) => (Def::AssociatedTy(item_def_id), TypeNS),
+            TraitItemKind::Type(..) => (Def::Def(DefKind::AssociatedTy, item_def_id), TypeNS),
             TraitItemKind::Macro(_) => bug!(),  // handled above
         };
 
diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs
index c89c222ad57..a86319801dc 100644
--- a/src/librustc_resolve/diagnostics.rs
+++ b/src/librustc_resolve/diagnostics.rs
@@ -2,7 +2,7 @@ use std::cmp::Reverse;
 
 use errors::{Applicability, DiagnosticBuilder, DiagnosticId};
 use log::debug;
-use rustc::hir::def::{self, CtorKind, Namespace::*};
+use rustc::hir::def::{self, DefKind, CtorKind, Namespace::*};
 use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId};
 use rustc::session::{Session, config::nightly_options};
 use syntax::ast::{self, Expr, ExprKind, Ident};
@@ -31,7 +31,9 @@ impl<'a> Resolver<'a> {
         let ident_span = path.last().map_or(span, |ident| ident.ident.span);
         let ns = source.namespace();
         let is_expected = &|def| source.is_expected(def);
-        let is_enum_variant = &|def| if let Def::Variant(..) = def { true } else { false };
+        let is_enum_variant = &|def| {
+            if let Def::Def(DefKind::Variant, _) = def { true } else { false }
+        };
 
         // Make the base error.
         let expected = source.descr_expected();
@@ -117,7 +119,8 @@ impl<'a> Resolver<'a> {
                 }
             })
             .collect::<Vec<_>>();
-        if candidates.is_empty() && is_expected(Def::Enum(DefId::local(CRATE_DEF_INDEX))) {
+        let crate_def_id = DefId::local(CRATE_DEF_INDEX);
+        if candidates.is_empty() && is_expected(Def::Def(DefKind::Enum, crate_def_id)) {
             let enum_candidates =
                 self.lookup_import_candidates(ident, ns, is_enum_variant);
             let mut enum_candidates = enum_candidates.iter()
@@ -362,7 +365,7 @@ impl<'a> Resolver<'a> {
         };
 
         match (def, source) {
-            (Def::Macro(..), _) => {
+            (Def::Def(DefKind::Macro(..), _), _) => {
                 err.span_suggestion(
                     span,
                     "use `!` to invoke the macro",
@@ -373,17 +376,19 @@ impl<'a> Resolver<'a> {
                     err.note("if you want the `try` keyword, you need to be in the 2018 edition");
                 }
             }
-            (Def::TyAlias(..), PathSource::Trait(_)) => {
+            (Def::Def(DefKind::TyAlias, _), PathSource::Trait(_)) => {
                 err.span_label(span, "type aliases cannot be used as traits");
                 if nightly_options::is_nightly_build() {
                     err.note("did you mean to use a trait alias?");
                 }
             }
-            (Def::Mod(..), PathSource::Expr(Some(parent))) => if !path_sep(err, &parent) {
-                return false;
-            },
-            (Def::Enum(..), PathSource::TupleStruct)
-                | (Def::Enum(..), PathSource::Expr(..))  => {
+            (Def::Def(DefKind::Mod, _), PathSource::Expr(Some(parent))) => {
+                if !path_sep(err, &parent) {
+                    return false;
+                }
+            }
+            (Def::Def(DefKind::Enum, _), PathSource::TupleStruct)
+                | (Def::Def(DefKind::Enum, _), PathSource::Expr(..))  => {
                 if let Some(variants) = self.collect_enum_variants(def) {
                     if !variants.is_empty() {
                         let msg = if variants.len() == 1 {
@@ -403,7 +408,7 @@ impl<'a> Resolver<'a> {
                     err.note("did you mean to use one of the enum's variants?");
                 }
             },
-            (Def::Struct(def_id), _) if ns == ValueNS => {
+            (Def::Def(DefKind::Struct, def_id), _) if ns == ValueNS => {
                 if let Some((ctor_def, ctor_vis))
                         = self.struct_constructors.get(&def_id).cloned() {
                     let accessible_ctor = self.is_accessible(ctor_vis);
@@ -417,16 +422,17 @@ impl<'a> Resolver<'a> {
                     bad_struct_syntax_suggestion();
                 }
             }
-            (Def::Union(..), _) |
-            (Def::Variant(..), _) |
-            (Def::Ctor(_, _, CtorKind::Fictive), _) if ns == ValueNS => {
+            (Def::Def(DefKind::Union, _), _) |
+            (Def::Def(DefKind::Variant, _), _) |
+            (Def::Def(DefKind::Ctor(_, CtorKind::Fictive), _), _) if ns == ValueNS => {
                 bad_struct_syntax_suggestion();
             }
             (Def::SelfTy(..), _) if ns == ValueNS => {
                 err.span_label(span, fallback_label);
                 err.note("can't use `Self` as a constructor, you must use the implemented struct");
             }
-            (Def::TyAlias(_), _) | (Def::AssociatedTy(..), _) if ns == ValueNS => {
+            (Def::Def(DefKind::TyAlias, _), _)
+            | (Def::Def(DefKind::AssociatedTy, _), _) if ns == ValueNS => {
                 err.note("can't use a type alias as a constructor");
             }
             _ => return false,
@@ -622,7 +628,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
         let resolutions = crate_module.resolutions.borrow();
         let resolution = resolutions.get(&(ident, MacroNS))?;
         let binding = resolution.borrow().binding()?;
-        if let Def::Macro(_, MacroKind::Bang) = binding.def() {
+        if let Def::Def(DefKind::Macro(MacroKind::Bang), _) = binding.def() {
             let module_name = crate_module.kind.name().unwrap();
             let import = match directive.subclass {
                 ImportDirectiveSubclass::SingleImport { source, target, .. } if source != target =>
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index dcfe00069c5..f7b8103a521 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -24,7 +24,7 @@ use rustc::middle::cstore::CrateStore;
 use rustc::session::Session;
 use rustc::lint;
 use rustc::hir::def::{
-    self, PathResolution, CtorKind, CtorOf, NonMacroAttrKind, DefMap, ImportMap, ExportMap
+    self, DefKind, PathResolution, CtorKind, CtorOf, NonMacroAttrKind, DefMap, ImportMap, ExportMap
 };
 use rustc::hir::def::Namespace::*;
 use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, DefId};
@@ -236,19 +236,19 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver<'_>,
                     }
                     return err;
                 },
-                Def::TyParam(def_id) => {
+                Def::Def(DefKind::TyParam, def_id) => {
                     if let Some(span) = resolver.definitions.opt_span(def_id) {
                         err.span_label(span, "type parameter from outer function");
                     }
                 }
-                Def::ConstParam(def_id) => {
+                Def::Def(DefKind::ConstParam, def_id) => {
                     if let Some(span) = resolver.definitions.opt_span(def_id) {
                         err.span_label(span, "const parameter from outer function");
                     }
                 }
                 _ => {
                     bug!("GenericParamsFromOuterFunction should only be used with Def::SelfTy, \
-                         Def::TyParam");
+                         DefKind::TyParam");
                 }
             }
 
@@ -570,7 +570,7 @@ impl<'a> PathSource<'a> {
                 MacroNS => bug!("associated macro"),
             },
             PathSource::Expr(parent) => match parent.map(|p| &p.node) {
-                // "function" here means "anything callable" rather than `Def::Fn`,
+                // "function" here means "anything callable" rather than `DefKind::Fn`,
                 // this is not precise but usually more helpful than just "value".
                 Some(&ExprKind::Call(..)) => "function",
                 _ => "value",
@@ -581,50 +581,70 @@ impl<'a> PathSource<'a> {
     fn is_expected(self, def: Def) -> bool {
         match self {
             PathSource::Type => match def {
-                Def::Struct(..) | Def::Union(..) | Def::Enum(..) |
-                Def::Trait(..) | Def::TraitAlias(..) | Def::TyAlias(..) |
-                Def::AssociatedTy(..) | Def::PrimTy(..) | Def::TyParam(..) |
-                Def::SelfTy(..) | Def::Existential(..) | Def::ForeignTy(..) => true,
+                Def::Def(DefKind::Struct, _)
+                | Def::Def(DefKind::Union, _)
+                | Def::Def(DefKind::Enum, _)
+                | Def::Def(DefKind::Trait, _)
+                | Def::Def(DefKind::TraitAlias, _)
+                | Def::Def(DefKind::TyAlias, _)
+                | Def::Def(DefKind::AssociatedTy, _)
+                | Def::PrimTy(..)
+                | Def::Def(DefKind::TyParam, _)
+                | Def::SelfTy(..)
+                | Def::Def(DefKind::Existential, _)
+                | Def::Def(DefKind::ForeignTy, _) => true,
                 _ => false,
             },
             PathSource::Trait(AliasPossibility::No) => match def {
-                Def::Trait(..) => true,
+                Def::Def(DefKind::Trait, _) => true,
                 _ => false,
             },
             PathSource::Trait(AliasPossibility::Maybe) => match def {
-                Def::Trait(..) => true,
-                Def::TraitAlias(..) => true,
+                Def::Def(DefKind::Trait, _) => true,
+                Def::Def(DefKind::TraitAlias, _) => true,
                 _ => false,
             },
             PathSource::Expr(..) => match def {
-                Def::Ctor(_, _, CtorKind::Const) | Def::Ctor(_, _, CtorKind::Fn) |
-                Def::Const(..) | Def::Static(..) | Def::Local(..) | Def::Upvar(..) |
-                Def::Fn(..) | Def::Method(..) | Def::AssociatedConst(..) |
-                Def::SelfCtor(..) | Def::ConstParam(..) => true,
+                Def::Def(DefKind::Ctor(_, CtorKind::Const), _)
+                | Def::Def(DefKind::Ctor(_, CtorKind::Fn), _)
+                | Def::Def(DefKind::Const, _)
+                | Def::Def(DefKind::Static, _)
+                | Def::Local(..)
+                | Def::Upvar(..)
+                | Def::Def(DefKind::Fn, _)
+                | Def::Def(DefKind::Method, _)
+                | Def::Def(DefKind::AssociatedConst, _)
+                | Def::SelfCtor(..)
+                | Def::Def(DefKind::ConstParam, _) => true,
                 _ => false,
             },
             PathSource::Pat => match def {
-                Def::Ctor(_, _, CtorKind::Const) |
-                Def::Const(..) | Def::AssociatedConst(..) |
+                Def::Def(DefKind::Ctor(_, CtorKind::Const), _) |
+                Def::Def(DefKind::Const, _) | Def::Def(DefKind::AssociatedConst, _) |
                 Def::SelfCtor(..) => true,
                 _ => false,
             },
             PathSource::TupleStruct => match def {
-                Def::Ctor(_, _, CtorKind::Fn) | Def::SelfCtor(..) => true,
+                Def::Def(DefKind::Ctor(_, CtorKind::Fn), _) | Def::SelfCtor(..) => true,
                 _ => false,
             },
             PathSource::Struct => match def {
-                Def::Struct(..) | Def::Union(..) | Def::Variant(..) |
-                Def::TyAlias(..) | Def::AssociatedTy(..) | Def::SelfTy(..) => true,
+                Def::Def(DefKind::Struct, _)
+                | Def::Def(DefKind::Union, _)
+                | Def::Def(DefKind::Variant, _)
+                | Def::Def(DefKind::TyAlias, _)
+                | Def::Def(DefKind::AssociatedTy, _)
+                | Def::SelfTy(..) => true,
                 _ => false,
             },
             PathSource::TraitItem(ns) => match def {
-                Def::AssociatedConst(..) | Def::Method(..) if ns == ValueNS => true,
-                Def::AssociatedTy(..) if ns == TypeNS => true,
+                Def::Def(DefKind::AssociatedConst, _)
+                | Def::Def(DefKind::Method, _) if ns == ValueNS => true,
+                Def::Def(DefKind::AssociatedTy, _) if ns == TypeNS => true,
                 _ => false,
             },
             PathSource::Visibility => match def {
-                Def::Mod(..) => true,
+                Def::Def(DefKind::Mod, _) => true,
                 _ => false,
             },
         }
@@ -1263,14 +1283,14 @@ impl<'a> ModuleData<'a> {
     // `self` resolves to the first module ancestor that `is_normal`.
     fn is_normal(&self) -> bool {
         match self.kind {
-            ModuleKind::Def(Def::Mod(_), _) => true,
+            ModuleKind::Def(Def::Def(DefKind::Mod, _), _) => true,
             _ => false,
         }
     }
 
     fn is_trait(&self) -> bool {
         match self.kind {
-            ModuleKind::Def(Def::Trait(_), _) => true,
+            ModuleKind::Def(Def::Def(DefKind::Trait, _), _) => true,
             _ => false,
         }
     }
@@ -1443,8 +1463,8 @@ impl<'a> NameBinding<'a> {
 
     fn is_variant(&self) -> bool {
         match self.kind {
-            NameBindingKind::Def(Def::Variant(..), _) |
-            NameBindingKind::Def(Def::Ctor(_, CtorOf::Variant, ..), _) => true,
+            NameBindingKind::Def(Def::Def(DefKind::Variant, _), _) |
+            NameBindingKind::Def(Def::Def(DefKind::Ctor(CtorOf::Variant, ..), _), _) => true,
             _ => false,
         }
     }
@@ -1457,7 +1477,7 @@ impl<'a> NameBinding<'a> {
                 }, ..
             } => true,
             NameBindingKind::Module(
-                &ModuleData { kind: ModuleKind::Def(Def::Mod(def_id), _), .. }
+                &ModuleData { kind: ModuleKind::Def(Def::Def(DefKind::Mod, def_id), _), .. }
             ) => def_id.index == CRATE_DEF_INDEX,
             _ => false,
         }
@@ -1479,21 +1499,23 @@ impl<'a> NameBinding<'a> {
 
     fn is_importable(&self) -> bool {
         match self.def() {
-            Def::AssociatedConst(..) | Def::Method(..) | Def::AssociatedTy(..) => false,
+            Def::Def(DefKind::AssociatedConst, _)
+            | Def::Def(DefKind::Method, _)
+            | Def::Def(DefKind::AssociatedTy, _) => false,
             _ => true,
         }
     }
 
     fn is_macro_def(&self) -> bool {
         match self.kind {
-            NameBindingKind::Def(Def::Macro(..), _) => true,
+            NameBindingKind::Def(Def::Def(DefKind::Macro(..), _), _) => true,
             _ => false,
         }
     }
 
     fn macro_kind(&self) -> Option<MacroKind> {
         match self.def() {
-            Def::Macro(_, kind) => Some(kind),
+            Def::Def(DefKind::Macro(kind), _) => Some(kind),
             Def::NonMacroAttr(..) => Some(MacroKind::Attr),
             _ => None,
         }
@@ -1915,7 +1937,10 @@ impl<'a> Resolver<'a> {
                arenas: &'a ResolverArenas<'a>)
                -> Resolver<'a> {
         let root_def_id = DefId::local(CRATE_DEF_INDEX);
-        let root_module_kind = ModuleKind::Def(Def::Mod(root_def_id), keywords::Invalid.name());
+        let root_module_kind = ModuleKind::Def(
+            Def::Def(DefKind::Mod, root_def_id),
+            keywords::Invalid.name(),
+        );
         let graph_root = arenas.alloc_module(ModuleData {
             no_implicit_prelude: attr::contains_name(&krate.attrs, "no_implicit_prelude"),
             ..ModuleData::new(None, root_module_kind, root_def_id, Mark::root(), krate.span)
@@ -2663,8 +2688,11 @@ impl<'a> Resolver<'a> {
                             }
                             seen_bindings.entry(ident).or_insert(param.ident.span);
 
-                        // Plain insert (no renaming).
-                        let def = Def::TyParam(self.definitions.local_def_id(param.id));
+                            // Plain insert (no renaming).
+                            let def = Def::Def(
+                                DefKind::TyParam,
+                                self.definitions.local_def_id(param.id),
+                            );
                             function_type_rib.bindings.insert(ident, def);
                             self.record_def(param.id, PathResolution::new(def));
                         }
@@ -2682,7 +2710,10 @@ impl<'a> Resolver<'a> {
                             }
                             seen_bindings.entry(ident).or_insert(param.ident.span);
 
-                            let def = Def::ConstParam(self.definitions.local_def_id(param.id));
+                            let def = Def::Def(
+                                DefKind::ConstParam,
+                                self.definitions.local_def_id(param.id),
+                            );
                             function_value_rib.bindings.insert(ident, def);
                             self.record_def(param.id, PathResolution::new(def));
                         }
@@ -3175,14 +3206,16 @@ impl<'a> Resolver<'a> {
                         let is_syntactic_ambiguity = opt_pat.is_none() &&
                             bmode == BindingMode::ByValue(Mutability::Immutable);
                         match def {
-                            Def::Ctor(_, _, CtorKind::Const) |
-                            Def::Const(..) if is_syntactic_ambiguity => {
+                            Def::Def(DefKind::Ctor(_, CtorKind::Const), _) |
+                            Def::Def(DefKind::Const, _) if is_syntactic_ambiguity => {
                                 // Disambiguate in favor of a unit struct/variant
                                 // or constant pattern.
                                 self.record_use(ident, ValueNS, binding.unwrap(), false);
                                 Some(PathResolution::new(def))
                             }
-                            Def::Ctor(..) | Def::Const(..) | Def::Static(..) => {
+                            Def::Def(DefKind::Ctor(..), _)
+                            | Def::Def(DefKind::Const, _)
+                            | Def::Def(DefKind::Static, _) => {
                                 // This is unambiguously a fresh binding, either syntactically
                                 // (e.g., `IDENT @ PAT` or `ref IDENT`) or because `IDENT` resolves
                                 // to something unusable as a pattern (e.g., constructor function),
@@ -3196,7 +3229,7 @@ impl<'a> Resolver<'a> {
                                 );
                                 None
                             }
-                            Def::Fn(..) | Def::Err => {
+                            Def::Def(DefKind::Fn, _) | Def::Err => {
                                 // These entities are explicitly allowed
                                 // to be shadowed by fresh bindings.
                                 None
@@ -3310,7 +3343,7 @@ impl<'a> Resolver<'a> {
                     // Add a temporary hack to smooth the transition to new struct ctor
                     // visibility rules. See #38932 for more details.
                     let mut res = None;
-                    if let Def::Struct(def_id) = resolution.base_def() {
+                    if let Def::Def(DefKind::Struct, def_id) = resolution.base_def() {
                         if let Some((ctor_def, ctor_vis))
                                 = self.struct_constructors.get(&def_id).cloned() {
                             if is_expected(ctor_def) && self.is_accessible(ctor_vis) {
@@ -3501,9 +3534,10 @@ impl<'a> Resolver<'a> {
             self.macro_use_prelude.get(&path[0].ident.name).cloned()
                                   .and_then(NameBinding::macro_kind) == Some(MacroKind::Bang)) {
             // Return some dummy definition, it's enough for error reporting.
-            return Some(
-                PathResolution::new(Def::Macro(DefId::local(CRATE_DEF_INDEX), MacroKind::Bang))
-            );
+            return Some(PathResolution::new(Def::Def(
+                DefKind::Macro(MacroKind::Bang),
+                DefId::local(CRATE_DEF_INDEX),
+            )));
         }
         fin_res
     }
@@ -3536,7 +3570,7 @@ impl<'a> Resolver<'a> {
                 // trait to resolve.  In that case, we leave the `B`
                 // segment to be resolved by type-check.
                 return Some(PathResolution::with_unresolved_segments(
-                    Def::Mod(DefId::local(CRATE_DEF_INDEX)), path.len()
+                    Def::Def(DefKind::Mod, DefId::local(CRATE_DEF_INDEX)), path.len()
                 ));
             }
 
@@ -3862,7 +3896,9 @@ impl<'a> Resolver<'a> {
                         _ => None,
                     };
                     let (label, suggestion) = if module_def == self.graph_root.def() {
-                        let is_mod = |def| match def { Def::Mod(..) => true, _ => false };
+                        let is_mod = |def| {
+                            match def { Def::Def(DefKind::Mod, _) => true, _ => false }
+                        };
                         let mut candidates =
                             self.lookup_import_candidates(ident, TypeNS, is_mod);
                         candidates.sort_by_cached_key(|c| {
@@ -4059,7 +4095,7 @@ impl<'a> Resolver<'a> {
                      return Def::Err;
                 }
             }
-            Def::TyParam(..) | Def::SelfTy(..) => {
+            Def::Def(DefKind::TyParam, _) | Def::SelfTy(..) => {
                 for rib in ribs {
                     match rib.kind {
                         NormalRibKind | TraitOrImplItemRibKind | ClosureRibKind(..) |
@@ -4081,7 +4117,7 @@ impl<'a> Resolver<'a> {
                     }
                 }
             }
-            Def::ConstParam(..) => {
+            Def::Def(DefKind::ConstParam, _) => {
                 let mut ribs = ribs.iter().peekable();
                 if let Some(Rib { kind: FnItemRibKind, .. }) = ribs.peek() {
                     // When declaring const parameters inside function signatures, the first rib
@@ -4132,7 +4168,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::Struct(did) | Def::Union(did)
+                        Def::Def(DefKind::Struct, did) | Def::Def(DefKind::Union, did)
                                 if resolution.unresolved_segments() == 0 => {
                             if let Some(field_names) = self.field_names.get(&did) {
                                 if field_names.iter().any(|&field_name| ident.name == field_name) {
@@ -4223,10 +4259,13 @@ impl<'a> Resolver<'a> {
                                 self.crate_loader
                                     .maybe_process_path_extern(ident.name, ident.span)
                                     .and_then(|crate_id| {
-                                        let crate_mod = Def::Mod(DefId {
-                                            krate: crate_id,
-                                            index: CRATE_DEF_INDEX,
-                                        });
+                                        let crate_mod = Def::Def(
+                                            DefKind::Mod,
+                                            DefId {
+                                                krate: crate_id,
+                                                index: CRATE_DEF_INDEX,
+                                            },
+                                        );
 
                                         if !ident.name.is_gensymed() && filter_fn(crate_mod) {
                                             Some(TypoSuggestion {
@@ -4566,8 +4605,8 @@ impl<'a> Resolver<'a> {
             module.for_each_child(|name, ns, binding| {
                 if ns != TypeNS { return }
                 match binding.def() {
-                    Def::Trait(_) |
-                    Def::TraitAlias(_) => collected_traits.push((name, binding)),
+                    Def::Def(DefKind::Trait, _) |
+                    Def::Def(DefKind::TraitAlias, _) => collected_traits.push((name, binding)),
                     _ => (),
                 }
             });
@@ -4602,7 +4641,7 @@ impl<'a> Resolver<'a> {
                     let trait_def_id = module.def_id().unwrap();
                     found_traits.push(TraitCandidate { def_id: trait_def_id, import_id });
                 }
-            } else if let Def::TraitAlias(_) = binding.def() {
+            } else if let Def::Def(DefKind::TraitAlias, _) = binding.def() {
                 // For now, just treat all trait aliases as possible candidates, since we don't
                 // know if the ident is somewhere in the transitive bounds.
 
@@ -4677,7 +4716,7 @@ impl<'a> Resolver<'a> {
                         // outside crate private modules => no need to check this)
                         if !in_module_is_extern || name_binding.vis == ty::Visibility::Public {
                             let did = match def {
-                                Def::Ctor(did, ..) => self.parent(did),
+                                Def::Def(DefKind::Ctor(..), did) => self.parent(did),
                                 _ => def.opt_def_id(),
                             };
                             candidates.push(ImportSuggestion { did, path });
@@ -4793,7 +4832,7 @@ impl<'a> Resolver<'a> {
     }
 
     fn collect_enum_variants(&mut self, enum_def: Def) -> Option<Vec<Path>> {
-        if let Def::Enum(..) = enum_def {} else {
+        if let Def::Def(DefKind::Enum, _) = enum_def {} else {
             panic!("Non-enum def passed to collect_enum_variants: {:?}", enum_def)
         }
 
@@ -4802,7 +4841,7 @@ impl<'a> Resolver<'a> {
 
             let mut variants = Vec::new();
             enum_module.for_each_child_stable(|ident, _, name_binding| {
-                if let Def::Variant(..) = name_binding.def() {
+                if let Def::Def(DefKind::Variant, _) = name_binding.def() {
                     let mut segms = enum_import_suggestion.path.segments.clone();
                     segms.push(ast::PathSegment::from_ident(ident));
                     variants.push(Path {
@@ -5050,8 +5089,8 @@ impl<'a> Resolver<'a> {
         }
 
         let container = match parent.kind {
-            ModuleKind::Def(Def::Mod(_), _) => "module",
-            ModuleKind::Def(Def::Trait(_), _) => "trait",
+            ModuleKind::Def(Def::Def(DefKind::Mod, _), _) => "module",
+            ModuleKind::Def(Def::Def(DefKind::Trait, _), _) => "trait",
             ModuleKind::Block(..) => "block",
             _ => "enum",
         };
diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs
index cb0cfd93a60..eea48f0711f 100644
--- a/src/librustc_resolve/macros.rs
+++ b/src/librustc_resolve/macros.rs
@@ -8,7 +8,7 @@ use crate::build_reduced_graph::{BuildReducedGraphVisitor, IsMacroExport};
 use crate::resolve_imports::ImportResolver;
 use rustc::hir::def_id::{DefId, CRATE_DEF_INDEX, DefIndex,
                          CrateNum, DefIndexAddressSpace};
-use rustc::hir::def::{self, NonMacroAttrKind};
+use rustc::hir::def::{self, DefKind, NonMacroAttrKind};
 use rustc::hir::map::{self, DefCollector};
 use rustc::{ty, lint};
 use rustc::{bug, span_bug};
@@ -179,7 +179,7 @@ impl<'a> base::Resolver for Resolver<'a> {
         let kind = ext.kind();
         self.macro_map.insert(def_id, ext);
         let binding = self.arenas.alloc_name_binding(NameBinding {
-            kind: NameBindingKind::Def(Def::Macro(def_id, kind), false),
+            kind: NameBindingKind::Def(Def::Def(DefKind::Macro(kind), def_id), false),
             ambiguity: None,
             span: DUMMY_SP,
             vis: ty::Visibility::Public,
@@ -218,7 +218,7 @@ impl<'a> base::Resolver for Resolver<'a> {
             Err(determinacy) => return Err(determinacy),
         };
 
-        if let Def::Macro(def_id, _) = def {
+        if let Def::Def(DefKind::Macro(_), def_id) = def {
             if after_derive {
                 self.session.span_err(invoc.span(),
                                       "macro attributes must be placed before `#[derive]`");
@@ -297,7 +297,7 @@ impl<'a> Resolver<'a> {
         let def = def?;
 
         match def {
-            Def::Macro(def_id, macro_kind) => {
+            Def::Def(DefKind::Macro(macro_kind), def_id) => {
                 self.unused_macros.remove(&def_id);
                 if macro_kind == MacroKind::ProcMacroStub {
                     let msg = "can't use a procedural macro from the same crate that defines it";
@@ -341,7 +341,7 @@ impl<'a> Resolver<'a> {
             Def::Err => {
                 return Err(Determinacy::Determined);
             }
-            _ => panic!("expected `Def::Macro` or `Def::NonMacroAttr`"),
+            _ => panic!("expected `DefKind::Macro` or `Def::NonMacroAttr`"),
         }
 
         Ok((def, self.get_macro(def)))
@@ -1028,7 +1028,7 @@ impl<'a> Resolver<'a> {
         // Then check modules.
         }).or_else(|| {
             let is_macro = |def| {
-                if let Def::Macro(_, def_kind) = def {
+                if let Def::Def(DefKind::Macro(def_kind), _) = def {
                     def_kind == kind
                 } else {
                     false
@@ -1107,7 +1107,7 @@ impl<'a> Resolver<'a> {
         if def.legacy {
             let ident = ident.modern();
             self.macro_names.insert(ident);
-            let def = Def::Macro(def_id, MacroKind::Bang);
+            let def = Def::Def(DefKind::Macro(MacroKind::Bang), def_id);
             let is_macro_export = attr::contains_name(&item.attrs, "macro_export");
             let vis = if is_macro_export {
                 ty::Visibility::Public
@@ -1133,7 +1133,7 @@ impl<'a> Resolver<'a> {
             }
         } else {
             let module = self.current_module;
-            let def = Def::Macro(def_id, MacroKind::Bang);
+            let def = Def::Def(DefKind::Macro(MacroKind::Bang), def_id);
             let vis = self.resolve_visibility(&item.vis);
             if vis != ty::Visibility::Public {
                 self.unused_macros.insert(def_id);
diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs
index 4dddf811c05..6ad09b2f7e7 100644
--- a/src/librustc_resolve/resolve_imports.rs
+++ b/src/librustc_resolve/resolve_imports.rs
@@ -21,7 +21,7 @@ use rustc::lint::builtin::{
     UNUSED_IMPORTS,
 };
 use rustc::hir::def_id::{CrateNum, DefId};
-use rustc::hir::def::{self, PathResolution, Export};
+use rustc::hir::def::{self, DefKind, PathResolution, Export};
 use rustc::session::DiagnosticMessageId;
 use rustc::util::nodemap::FxHashSet;
 use rustc::{bug, span_bug};
@@ -1224,7 +1224,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
         // purposes it's good enough to just favor one over the other.
         self.per_ns(|this, ns| if let Some(binding) = source_bindings[ns].get().ok() {
             let mut def = binding.def();
-            if let Def::Macro(def_id, _) = def {
+            if let Def::Def(DefKind::Macro(_), def_id) = def {
                 // `DefId`s from the "built-in macro crate" should not leak from resolve because
                 // later stages are not ready to deal with them and produce lots of ICEs. Replace
                 // them with `Def::Err` until some saner scheme is implemented for built-in macros.
diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs
index a5ddf89d3d4..36413e76a1e 100644
--- a/src/librustc_save_analysis/dump_visitor.rs
+++ b/src/librustc_save_analysis/dump_visitor.rs
@@ -13,7 +13,7 @@
 //! DumpVisitor walks the AST and processes it, and JsonDumper is used for
 //! recording the output.
 
-use rustc::hir::def::Def as HirDef;
+use rustc::hir::def::{Def as HirDef, DefKind as HirDefKind};
 use rustc::hir::def_id::DefId;
 use rustc::session::config::Input;
 use rustc::span_bug;
@@ -957,13 +957,13 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
                         );
                     }
                 }
-                HirDef::Ctor(_, _, _) |
-                HirDef::Const(..) |
-                HirDef::AssociatedConst(..) |
-                HirDef::Struct(..) |
-                HirDef::Variant(..) |
-                HirDef::TyAlias(..) |
-                HirDef::AssociatedTy(..) |
+                HirDef::Def(HirDefKind::Ctor(..), _) |
+                HirDef::Def(HirDefKind::Const, _) |
+                HirDef::Def(HirDefKind::AssociatedConst, _) |
+                HirDef::Def(HirDefKind::Struct, _) |
+                HirDef::Def(HirDefKind::Variant, _) |
+                HirDef::Def(HirDefKind::TyAlias, _) |
+                HirDef::Def(HirDefKind::AssociatedTy, _) |
                 HirDef::SelfTy(..) => {
                     self.dump_path_ref(id, &ast::Path::from_ident(ident));
                 }
diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs
index c173d51fd40..47d0b5055ea 100644
--- a/src/librustc_save_analysis/lib.rs
+++ b/src/librustc_save_analysis/lib.rs
@@ -15,7 +15,7 @@ mod span_utils;
 mod sig;
 
 use rustc::hir;
-use rustc::hir::def::{CtorOf, Def as HirDef};
+use rustc::hir::def::{CtorOf, Def as HirDef, DefKind as HirDefKind};
 use rustc::hir::Node;
 use rustc::hir::def_id::{DefId, LOCAL_CRATE};
 use rustc::middle::privacy::AccessLevels;
@@ -710,39 +710,39 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
                     ref_id: id_from_node_id(self.tcx.hir().hir_to_node_id(id), self),
                 })
             }
-            HirDef::Trait(def_id) if fn_type(path_seg) => {
+            HirDef::Def(HirDefKind::Trait, def_id) if fn_type(path_seg) => {
                 Some(Ref {
                     kind: RefKind::Type,
                     span,
                     ref_id: id_from_def_id(def_id),
                 })
             }
-            HirDef::Struct(def_id) |
-            HirDef::Variant(def_id, ..) |
-            HirDef::Union(def_id) |
-            HirDef::Enum(def_id) |
-            HirDef::TyAlias(def_id) |
-            HirDef::ForeignTy(def_id) |
-            HirDef::TraitAlias(def_id) |
-            HirDef::AssociatedExistential(def_id) |
-            HirDef::AssociatedTy(def_id) |
-            HirDef::Trait(def_id) |
-            HirDef::Existential(def_id) |
-            HirDef::TyParam(def_id) => {
+            HirDef::Def(HirDefKind::Struct, def_id) |
+            HirDef::Def(HirDefKind::Variant, def_id) |
+            HirDef::Def(HirDefKind::Union, def_id) |
+            HirDef::Def(HirDefKind::Enum, def_id) |
+            HirDef::Def(HirDefKind::TyAlias, def_id) |
+            HirDef::Def(HirDefKind::ForeignTy, def_id) |
+            HirDef::Def(HirDefKind::TraitAlias, def_id) |
+            HirDef::Def(HirDefKind::AssociatedExistential, def_id) |
+            HirDef::Def(HirDefKind::AssociatedTy, def_id) |
+            HirDef::Def(HirDefKind::Trait, def_id) |
+            HirDef::Def(HirDefKind::Existential, def_id) |
+            HirDef::Def(HirDefKind::TyParam, def_id) => {
                 Some(Ref {
                     kind: RefKind::Type,
                     span,
                     ref_id: id_from_def_id(def_id),
                 })
             }
-            HirDef::ConstParam(def_id) => {
+            HirDef::Def(HirDefKind::ConstParam, def_id) => {
                 Some(Ref {
                     kind: RefKind::Variable,
                     span,
                     ref_id: id_from_def_id(def_id),
                 })
             }
-            HirDef::Ctor(def_id, CtorOf::Struct, ..) => {
+            HirDef::Def(HirDefKind::Ctor(CtorOf::Struct, ..), def_id) => {
                 // This is a reference to a tuple struct where the def_id points
                 // to an invisible constructor function. That is not a very useful
                 // def, so adjust to point to the tuple struct itself.
@@ -753,17 +753,17 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
                     ref_id: id_from_def_id(parent_def_id),
                 })
             }
-            HirDef::Static(..) |
-            HirDef::Const(..) |
-            HirDef::AssociatedConst(..) |
-            HirDef::Ctor(..) => {
+            HirDef::Def(HirDefKind::Static, _) |
+            HirDef::Def(HirDefKind::Const, _) |
+            HirDef::Def(HirDefKind::AssociatedConst, _) |
+            HirDef::Def(HirDefKind::Ctor(..), _) => {
                 Some(Ref {
                     kind: RefKind::Variable,
                     span,
                     ref_id: id_from_def_id(def.def_id()),
                 })
             }
-            HirDef::Method(decl_id) => {
+            HirDef::Def(HirDefKind::Method, decl_id) => {
                 let def_id = if decl_id.is_local() {
                     let ti = self.tcx.associated_item(decl_id);
                     self.tcx
@@ -780,14 +780,14 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
                     ref_id: id_from_def_id(def_id.unwrap_or(decl_id)),
                 })
             }
-            HirDef::Fn(def_id) => {
+            HirDef::Def(HirDefKind::Fn, def_id) => {
                 Some(Ref {
                     kind: RefKind::Function,
                     span,
                     ref_id: id_from_def_id(def_id),
                 })
             }
-            HirDef::Mod(def_id) => {
+            HirDef::Def(HirDefKind::Mod, def_id) => {
                 Some(Ref {
                     kind: RefKind::Mod,
                     span,
@@ -797,7 +797,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
             HirDef::PrimTy(..) |
             HirDef::SelfTy(..) |
             HirDef::Label(..) |
-            HirDef::Macro(..) |
+            HirDef::Def(HirDefKind::Macro(..), _) |
             HirDef::ToolMod |
             HirDef::NonMacroAttr(..) |
             HirDef::SelfCtor(..) |
diff --git a/src/librustc_save_analysis/sig.rs b/src/librustc_save_analysis/sig.rs
index 5ac75d01275..bcdb6be0ebd 100644
--- a/src/librustc_save_analysis/sig.rs
+++ b/src/librustc_save_analysis/sig.rs
@@ -29,7 +29,7 @@ use crate::{id_from_def_id, id_from_node_id, SaveContext};
 
 use rls_data::{SigElement, Signature};
 
-use rustc::hir::def::Def;
+use rustc::hir::def::{Def, DefKind};
 use syntax::ast::{self, NodeId};
 use syntax::print::pprust;
 
@@ -586,7 +586,9 @@ impl Sig for ast::Path {
                     refs: vec![],
                 })
             }
-            Def::AssociatedConst(..) | Def::Variant(..) | Def::Ctor(..) => {
+            Def::Def(DefKind::AssociatedConst, _)
+            | Def::Def(DefKind::Variant, _)
+            | Def::Def(DefKind::Ctor(..), _) => {
                 let len = self.segments.len();
                 if len < 2 {
                     return Err("Bad path");
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index 98d72ee03d0..8807e1aa62a 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -4,7 +4,7 @@
 
 use errors::{Applicability, DiagnosticId};
 use crate::hir::{self, GenericArg, GenericArgs, ExprKind};
-use crate::hir::def::{CtorOf, Def};
+use crate::hir::def::{CtorOf, Def, DefKind};
 use crate::hir::def_id::DefId;
 use crate::hir::HirVec;
 use crate::lint;
@@ -1330,7 +1330,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
                     tcx.hygienic_eq(assoc_ident, vd.ident, adt_def.did)
                 });
                 if let Some(variant_def) = variant_def {
-                    let def = Def::Variant(variant_def.def_id);
+                    let def = Def::Def(DefKind::Variant, variant_def.def_id);
                     if permit_variants {
                         check_type_alias_enum_variants_enabled(tcx, span);
                         tcx.check_stability(variant_def.def_id, Some(hir_ref_id), span);
@@ -1365,7 +1365,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
                 }
             }
             (&ty::Param(_), Def::SelfTy(Some(param_did), None)) |
-            (&ty::Param(_), Def::TyParam(param_did)) => {
+            (&ty::Param(_), Def::Def(DefKind::TyParam, param_did)) => {
                 match self.find_bound_for_assoc_item(param_did, assoc_ident, span) {
                     Ok(bound) => bound,
                     Err(ErrorReported) => return (tcx.types.err, Def::Err),
@@ -1427,7 +1427,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
         let ty = self.projected_ty_from_poly_trait_ref(span, item.def_id, bound);
         let ty = self.normalize_ty(span, ty);
 
-        let def = Def::AssociatedTy(item.def_id);
+        let def = Def::Def(DefKind::AssociatedTy, item.def_id);
         if !item.vis.is_accessible_from(def_scope, tcx) {
             let msg = format!("{} `{}` is private", def.kind_name(), assoc_ident);
             tcx.sess.span_err(span, &msg);
@@ -1617,7 +1617,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
 
         match def {
             // Case 1. Reference to a struct constructor.
-            Def::Ctor(def_id, CtorOf::Struct, ..) |
+            Def::Def(DefKind::Ctor(CtorOf::Struct, ..), def_id) |
             Def::SelfCtor(.., def_id) => {
                 // Everything but the final segment should have no
                 // parameters at all.
@@ -1629,7 +1629,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
             }
 
             // Case 2. Reference to a variant constructor.
-            Def::Ctor(def_id, CtorOf::Variant, ..) | Def::Variant(def_id, ..) => {
+            Def::Def(DefKind::Ctor(CtorOf::Variant, ..), def_id)
+            | Def::Def(DefKind::Variant, def_id) => {
                 let adt_def = self_ty.map(|t| t.ty_adt_def().unwrap());
                 let (generics_def_id, index) = if let Some(adt_def) = adt_def {
                     debug_assert!(adt_def.is_enum());
@@ -1639,12 +1640,12 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
                     // parameters at all.
                     let mut def_id = def_id;
 
-                    // `Def::Ctor` -> `Def::Variant`
-                    if let Def::Ctor(..) = def {
+                    // `DefKind::Ctor` -> `DefKind::Variant`
+                    if let Def::Def(DefKind::Ctor(..), _) = def {
                         def_id = tcx.parent(def_id).unwrap()
                     }
 
-                    // `Def::Variant` -> `Def::Item` (enum)
+                    // `DefKind::Variant` -> `DefKind::Item` (enum)
                     let enum_def_id = tcx.parent(def_id).unwrap();
                     (enum_def_id, last - 1)
                 } else {
@@ -1662,16 +1663,16 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
             }
 
             // Case 3. Reference to a top-level value.
-            Def::Fn(def_id) |
-            Def::Const(def_id) |
-            Def::ConstParam(def_id) |
-            Def::Static(def_id) => {
+            Def::Def(DefKind::Fn, def_id) |
+            Def::Def(DefKind::Const, def_id) |
+            Def::Def(DefKind::ConstParam, def_id) |
+            Def::Def(DefKind::Static, def_id) => {
                 path_segs.push(PathSeg(def_id, last));
             }
 
             // Case 4. Reference to a method or associated const.
-            Def::Method(def_id) |
-            Def::AssociatedConst(def_id) => {
+            Def::Def(DefKind::Method, def_id) |
+            Def::Def(DefKind::AssociatedConst, def_id) => {
                 if segments.len() >= 2 {
                     let generics = tcx.generics_of(def_id);
                     path_segs.push(PathSeg(generics.parent.unwrap(), last - 1));
@@ -1703,7 +1704,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
 
         let span = path.span;
         match path.def {
-            Def::Existential(did) => {
+            Def::Def(DefKind::Existential, did) => {
                 // Check for desugared impl trait.
                 assert!(ty::is_impl_trait_defn(tcx, did).is_none());
                 let item_segment = path.segments.split_last().unwrap();
@@ -1714,13 +1715,16 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
                     tcx.mk_opaque(did, substs),
                 )
             }
-            Def::Enum(did) | Def::TyAlias(did) | Def::Struct(did) |
-            Def::Union(did) | Def::ForeignTy(did) => {
+            Def::Def(DefKind::Enum, did)
+            | Def::Def(DefKind::TyAlias, did)
+            | Def::Def(DefKind::Struct, did)
+            | Def::Def(DefKind::Union, did)
+            | Def::Def(DefKind::ForeignTy, did) => {
                 assert_eq!(opt_self_ty, None);
                 self.prohibit_generics(path.segments.split_last().unwrap().1);
                 self.ast_path_to_ty(span, did, path.segments.last().unwrap())
             }
-            Def::Variant(_) if permit_variants => {
+            Def::Def(DefKind::Variant, _) if permit_variants => {
                 // Convert "variant type" as if it were a real type.
                 // The resulting `Ty` is type of the variant's enum for now.
                 assert_eq!(opt_self_ty, None);
@@ -1739,7 +1743,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
                 let PathSeg(def_id, index) = path_segs.last().unwrap();
                 self.ast_path_to_ty(span, *def_id, &path.segments[*index])
             }
-            Def::TyParam(did) => {
+            Def::Def(DefKind::TyParam, did) => {
                 assert_eq!(opt_self_ty, None);
                 self.prohibit_generics(&path.segments);
 
@@ -1764,7 +1768,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
                 self.prohibit_generics(&path.segments);
                 tcx.mk_self_type()
             }
-            Def::AssociatedTy(def_id) => {
+            Def::Def(DefKind::AssociatedTy, def_id) => {
                 debug_assert!(path.segments.len() >= 2);
                 self.prohibit_generics(&path.segments[..path.segments.len() - 2]);
                 self.qpath_to_ty(span,
@@ -1911,7 +1915,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
         let expr = &tcx.hir().body(ast_const.body).value;
         if let ExprKind::Path(ref qpath) = expr.node {
             if let hir::QPath::Resolved(_, ref path) = qpath {
-                if let Def::ConstParam(def_id) = path.def {
+                if let Def::Def(DefKind::ConstParam, def_id) = path.def {
                     let node_id = tcx.hir().as_local_node_id(def_id).unwrap();
                     let item_id = tcx.hir().get_parent_node(node_id);
                     let item_def_id = tcx.hir().local_def_id(item_id);
@@ -2098,7 +2102,7 @@ fn split_auto_traits<'a, 'b, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
     let (auto_traits, trait_bounds): (Vec<_>, _) = trait_bounds.iter().partition(|bound| {
         // Checks whether `trait_did` is an auto trait and adds it to `auto_traits` if so.
         match bound.trait_ref.path.def {
-            Def::Trait(trait_did) if tcx.trait_is_auto(trait_did) => {
+            Def::Def(DefKind::Trait, trait_did) if tcx.trait_is_auto(trait_did) => {
                 true
             }
             _ => false
@@ -2106,7 +2110,7 @@ fn split_auto_traits<'a, 'b, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
     });
 
     let auto_traits = auto_traits.into_iter().map(|tr| {
-        if let Def::Trait(trait_did) = tr.trait_ref.path.def {
+        if let Def::Def(DefKind::Trait, trait_did) = tr.trait_ref.path.def {
             trait_did
         } else {
             unreachable!()
diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs
index 6cc7818d712..bd04e12eb24 100644
--- a/src/librustc_typeck/check/_match.rs
+++ b/src/librustc_typeck/check/_match.rs
@@ -3,7 +3,7 @@ use crate::check::coercion::CoerceMany;
 use crate::util::nodemap::FxHashMap;
 use errors::{Applicability, DiagnosticBuilder};
 use rustc::hir::{self, PatKind, Pat};
-use rustc::hir::def::{Def, CtorKind};
+use rustc::hir::def::{Def, DefKind, CtorKind};
 use rustc::hir::pat_util::EnumerateAndAdjustIterator;
 use rustc::infer;
 use rustc::infer::type_variable::TypeVariableOrigin;
@@ -67,7 +67,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
             PatKind::Path(ref qpath) => {
                 let (def, _, _) = self.resolve_ty_and_def_ufcs(qpath, pat.hir_id, pat.span);
                 match def {
-                    Def::Const(..) | Def::AssociatedConst(..) => false,
+                    Def::Def(DefKind::Const, _) | Def::Def(DefKind::AssociatedConst, _) => false,
                     _ => true,
                 }
             }
@@ -846,17 +846,17 @@ https://doc.rust-lang.org/reference/types.html#trait-objects");
                 self.set_tainted_by_errors();
                 return tcx.types.err;
             }
-            Def::Method(..) => {
+            Def::Def(DefKind::Method, _) => {
                 report_unexpected_variant_def(tcx, &def, pat.span, qpath);
                 return tcx.types.err;
             }
-            Def::Ctor(_, _, CtorKind::Fictive) |
-            Def::Ctor(_, _, CtorKind::Fn) => {
+            Def::Def(DefKind::Ctor(_, CtorKind::Fictive), _) |
+            Def::Def(DefKind::Ctor(_, CtorKind::Fn), _) => {
                 report_unexpected_variant_def(tcx, &def, pat.span, qpath);
                 return tcx.types.err;
             }
-            Def::Ctor(_, _, CtorKind::Const) | Def::SelfCtor(..) |
-            Def::Const(..) | Def::AssociatedConst(..) => {} // OK
+            Def::Def(DefKind::Ctor(_, CtorKind::Const), _) | Def::SelfCtor(..) |
+            Def::Def(DefKind::Const, _) | Def::Def(DefKind::AssociatedConst, _) => {} // OK
             _ => bug!("unexpected pattern definition: {:?}", def)
         }
 
@@ -913,11 +913,11 @@ https://doc.rust-lang.org/reference/types.html#trait-objects");
                 on_error();
                 return tcx.types.err;
             }
-            Def::AssociatedConst(..) | Def::Method(..) => {
+            Def::Def(DefKind::AssociatedConst, _) | Def::Def(DefKind::Method, _) => {
                 report_unexpected_def(def);
                 return tcx.types.err;
             }
-            Def::Ctor(_, _, CtorKind::Fn) => {
+            Def::Def(DefKind::Ctor(_, CtorKind::Fn), _) => {
                 tcx.expect_variant_def(def)
             }
             _ => bug!("unexpected pattern definition: {:?}", def)
diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs
index b47cce04012..a3ee6ffe8da 100644
--- a/src/librustc_typeck/check/compare_method.rs
+++ b/src/librustc_typeck/check/compare_method.rs
@@ -1,4 +1,5 @@
 use rustc::hir::{self, GenericParamKind, ImplItemKind, TraitItemKind};
+use rustc::hir::def::{Def, DefKind};
 use rustc::infer::{self, InferOk};
 use rustc::ty::{self, TyCtxt, GenericParamDefKind};
 use rustc::ty::util::ExplicitSelf;
@@ -844,7 +845,7 @@ fn compare_synthetic_generics<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                 if let hir::TyKind::Path(
                                     hir::QPath::Resolved(None, ref path)) = ty.node
                                 {
-                                    if let hir::def::Def::TyParam(def_id) = path.def {
+                                    if let Def::Def(DefKind::TyParam, def_id) = path.def {
                                         if def_id == self.1 {
                                             self.0 = Some(ty.span);
                                         }
diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs
index 8ae66a96c76..537ea9a4b44 100644
--- a/src/librustc_typeck/check/demand.rs
+++ b/src/librustc_typeck/check/demand.rs
@@ -5,7 +5,7 @@ use rustc::traits::{self, ObligationCause, ObligationCauseCode};
 use syntax::util::parser::PREC_POSTFIX;
 use syntax_pos::Span;
 use rustc::hir;
-use rustc::hir::def::Def;
+use rustc::hir::def::{Def, DefKind};
 use rustc::hir::Node;
 use rustc::hir::{print, lowering::is_range_literal};
 use rustc::ty::{self, Ty, AssociatedItem};
@@ -207,7 +207,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
     // This function checks if the method isn't static and takes other arguments than `self`.
     fn has_no_input_arg(&self, method: &AssociatedItem) -> bool {
         match method.def() {
-            Def::Method(def_id) => {
+            Def::Def(DefKind::Method, def_id) => {
                 self.tcx.fn_sig(def_id).inputs().skip_binder().len() == 1
             }
             _ => false,
diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs
index 34a24308e49..b0f0856615d 100644
--- a/src/librustc_typeck/check/method/mod.rs
+++ b/src/librustc_typeck/check/method/mod.rs
@@ -15,7 +15,7 @@ use crate::namespace::Namespace;
 use errors::{Applicability, DiagnosticBuilder};
 use rustc_data_structures::sync::Lrc;
 use rustc::hir;
-use rustc::hir::def::{CtorOf, Def};
+use rustc::hir::def::{CtorOf, Def, DefKind};
 use rustc::hir::def_id::DefId;
 use rustc::traits;
 use rustc::ty::subst::{InternalSubsts, SubstsRef};
@@ -422,7 +422,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                     // them as well. It's ok to use the variant's id as a ctor id since an
                     // error will be reported on any use of such resolution anyway.
                     let ctor_def_id = variant_def.ctor_def_id.unwrap_or(variant_def.def_id);
-                    let def = Def::Ctor(ctor_def_id, CtorOf::Variant, variant_def.ctor_kind);
+                    let def = Def::Def(
+                        DefKind::Ctor(CtorOf::Variant, variant_def.ctor_kind),
+                        ctor_def_id,
+                    );
                     tcx.check_stability(def.def_id(), Some(expr_id), span);
                     return Ok(def);
                 }
diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs
index a35777873ab..54260f196ce 100644
--- a/src/librustc_typeck/check/method/probe.rs
+++ b/src/librustc_typeck/check/method/probe.rs
@@ -6,7 +6,7 @@ use super::suggest;
 use crate::check::autoderef::{self, Autoderef};
 use crate::check::FnCtxt;
 use crate::hir::def_id::DefId;
-use crate::hir::def::Def;
+use crate::hir::def::{Def, DefKind};
 use crate::namespace::Namespace;
 
 use rustc_data_structures::sync::Lrc;
@@ -862,7 +862,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
                                self_ty: Option<Ty<'tcx>>,
                                expected: Ty<'tcx>) -> bool {
         match method.def() {
-            Def::Method(def_id) => {
+            Def::Def(DefKind::Method, def_id) => {
                 let fty = self.tcx.fn_sig(def_id);
                 self.probe(|_| {
                     let substs = self.fresh_substs_for_item(self.span, method.def_id);
diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs
index 35d4568bd9c..2c567a86991 100644
--- a/src/librustc_typeck/check/method/suggest.rs
+++ b/src/librustc_typeck/check/method/suggest.rs
@@ -8,7 +8,7 @@ use crate::util::nodemap::FxHashSet;
 use errors::{Applicability, DiagnosticBuilder};
 use rustc_data_structures::sync::Lrc;
 use rustc::hir::{self, ExprKind, Node, QPath};
-use rustc::hir::def::Def;
+use rustc::hir::def::{Def, DefKind};
 use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, DefId};
 use rustc::hir::map as hir_map;
 use rustc::hir::print;
@@ -804,11 +804,11 @@ fn compute_all_traits<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Vec<DefId>
                            external_mods: &mut FxHashSet<DefId>,
                            def: Def) {
         match def {
-            Def::Trait(def_id) |
-            Def::TraitAlias(def_id) => {
+            Def::Def(DefKind::Trait, def_id) |
+            Def::Def(DefKind::TraitAlias, def_id) => {
                 traits.push(def_id);
             }
-            Def::Mod(def_id) => {
+            Def::Def(DefKind::Mod, def_id) => {
                 if !external_mods.insert(def_id) {
                     return;
                 }
@@ -824,7 +824,7 @@ fn compute_all_traits<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Vec<DefId>
             krate: cnum,
             index: CRATE_DEF_INDEX,
         };
-        handle_external_def(tcx, &mut traits, &mut external_mods, Def::Mod(def_id));
+        handle_external_def(tcx, &mut traits, &mut external_mods, Def::Def(DefKind::Mod, def_id));
     }
 
     traits
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index d2d486b52b3..47974bc5564 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -88,7 +88,7 @@ mod op;
 use crate::astconv::{AstConv, PathSeg};
 use errors::{Applicability, DiagnosticBuilder, DiagnosticId};
 use rustc::hir::{self, ExprKind, GenericArg, ItemKind, Node, PatKind, QPath};
-use rustc::hir::def::{CtorOf, CtorKind, Def};
+use rustc::hir::def::{CtorOf, CtorKind, Def, DefKind};
 use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
 use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
 use rustc::hir::itemlikevisit::ItemLikeVisitor;
@@ -2149,7 +2149,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         self.tables
             .borrow_mut()
             .type_dependent_defs_mut()
-            .insert(hir_id, Def::Method(method.def_id));
+            .insert(hir_id, Def::Def(DefKind::Method, method.def_id));
 
         self.write_substs(hir_id, method.substs);
 
@@ -3926,7 +3926,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                 self.set_tainted_by_errors();
                 return None;
             }
-            Def::Variant(..) => {
+            Def::Def(DefKind::Variant, _) => {
                 match ty.sty {
                     ty::Adt(adt, substs) => {
                         Some((adt.variant_of_def(def), adt.did, substs))
@@ -3934,8 +3934,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                     _ => bug!("unexpected type: {:?}", ty)
                 }
             }
-            Def::Struct(..) | Def::Union(..) | Def::TyAlias(..) |
-            Def::AssociatedTy(..) | Def::SelfTy(..) => {
+            Def::Def(DefKind::Struct, _)
+            | Def::Def(DefKind::Union, _)
+            | Def::Def(DefKind::TyAlias, _)
+            | Def::Def(DefKind::AssociatedTy, _)
+            | Def::SelfTy(..) => {
                 match ty.sty {
                     ty::Adt(adt, substs) if !adt.is_enum() => {
                         Some((adt.non_enum_variant(), adt.did, substs))
@@ -4237,7 +4240,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                         self.set_tainted_by_errors();
                         tcx.types.err
                     }
-                    Def::Ctor(_, _, CtorKind::Fictive) => {
+                    Def::Def(DefKind::Ctor(_, CtorKind::Fictive), _) => {
                         report_unexpected_variant_def(tcx, &def, expr.span, qpath);
                         tcx.types.err
                     }
@@ -5362,7 +5365,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                 Some(adt_def) if adt_def.has_ctor() => {
                     let variant = adt_def.non_enum_variant();
                     let ctor_def_id = variant.ctor_def_id.unwrap();
-                    let def = Def::Ctor(ctor_def_id, CtorOf::Struct, variant.ctor_kind);
+                    let def = Def::Def(
+                        DefKind::Ctor(CtorOf::Struct, variant.ctor_kind),
+                        ctor_def_id,
+                    );
                     (def, ctor_def_id, tcx.type_of(ctor_def_id))
                 }
                 _ => {
@@ -5434,7 +5440,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         let mut user_self_ty = None;
         let mut is_alias_variant_ctor = false;
         match def {
-            Def::Ctor(_, CtorOf::Variant, _) => {
+            Def::Def(DefKind::Ctor(CtorOf::Variant, _), _) => {
                 if let Some(self_ty) = self_ty {
                     let adt_def = self_ty.ty_adt_def().unwrap();
                     user_self_ty = Some(UserSelfTy {
@@ -5444,8 +5450,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                     is_alias_variant_ctor = true;
                 }
             }
-            Def::Method(def_id) |
-            Def::AssociatedConst(def_id) => {
+            Def::Def(DefKind::Method, def_id) |
+            Def::Def(DefKind::AssociatedConst, def_id) => {
                 let container = tcx.associated_item(def_id).container;
                 debug!("instantiate_value_path: def={:?} container={:?}", def, container);
                 match container {
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index 9c8b5ac58e3..89409deb145 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -42,7 +42,7 @@ use syntax::feature_gate;
 use syntax::symbol::{keywords, Symbol};
 use syntax_pos::{Span, DUMMY_SP};
 
-use rustc::hir::def::{CtorKind, Def};
+use rustc::hir::def::{CtorKind, Def, DefKind};
 use rustc::hir::Node;
 use rustc::hir::def_id::{DefId, LOCAL_CRATE};
 use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
@@ -381,7 +381,7 @@ fn is_param<'a, 'tcx>(
 ) -> bool {
     if let hir::TyKind::Path(hir::QPath::Resolved(None, ref path)) = ast_ty.node {
         match path.def {
-            Def::SelfTy(Some(def_id), None) | Def::TyParam(def_id) => {
+            Def::SelfTy(Some(def_id), None) | Def::Def(DefKind::TyParam, def_id) => {
                 def_id == tcx.hir().local_def_id_from_hir_id(param_id)
             }
             _ => false,
@@ -1381,10 +1381,10 @@ pub fn checked_type_of<'a, 'tcx>(
                                 // We've encountered an `AnonConst` in some path, so we need to
                                 // figure out which generic parameter it corresponds to and return
                                 // the relevant type.
-                                Def::Struct(def_id)
-                                | Def::Union(def_id)
-                                | Def::Enum(def_id)
-                                | Def::Fn(def_id) => {
+                                Def::Def(DefKind::Struct, def_id)
+                                | Def::Def(DefKind::Union, def_id)
+                                | Def::Def(DefKind::Enum, def_id)
+                                | Def::Def(DefKind::Fn, def_id) => {
                                     let generics = tcx.generics_of(def_id);
                                     let mut param_index = 0;
                                     for param in &generics.params {
@@ -1778,7 +1778,7 @@ fn is_unsized<'gcx: 'tcx, 'tcx>(
         Some(ref tpb) => {
             // FIXME(#8559) currently requires the unbound to be built-in.
             if let Ok(kind_id) = kind_id {
-                if tpb.path.def != Def::Trait(kind_id) {
+                if tpb.path.def != Def::Def(DefKind::Trait, kind_id) {
                     tcx.sess.span_warn(
                         span,
                         "default bound relaxed for a type parameter, but \
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index 5da74a588c9..365af15e006 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -7,7 +7,7 @@ use syntax::ext::base::{MacroKind, SyntaxExtension};
 use syntax_pos::Span;
 
 use rustc::hir;
-use rustc::hir::def::{Def, CtorKind};
+use rustc::hir::def::{Def, DefKind, CtorKind};
 use rustc::hir::def_id::DefId;
 use rustc_metadata::cstore::LoadedMacro;
 use rustc::ty;
@@ -50,59 +50,59 @@ pub fn try_inline(
     if did.is_local() { return None }
     let mut ret = Vec::new();
     let inner = match def {
-        Def::Trait(did) => {
+        Def::Def(DefKind::Trait, did) => {
             record_extern_fqn(cx, did, clean::TypeKind::Trait);
             ret.extend(build_impls(cx, did));
             clean::TraitItem(build_external_trait(cx, did))
         }
-        Def::Fn(did) => {
+        Def::Def(DefKind::Fn, did) => {
             record_extern_fqn(cx, did, clean::TypeKind::Function);
             clean::FunctionItem(build_external_function(cx, did))
         }
-        Def::Struct(did) => {
+        Def::Def(DefKind::Struct, did) => {
             record_extern_fqn(cx, did, clean::TypeKind::Struct);
             ret.extend(build_impls(cx, did));
             clean::StructItem(build_struct(cx, did))
         }
-        Def::Union(did) => {
+        Def::Def(DefKind::Union, did) => {
             record_extern_fqn(cx, did, clean::TypeKind::Union);
             ret.extend(build_impls(cx, did));
             clean::UnionItem(build_union(cx, did))
         }
-        Def::TyAlias(did) => {
+        Def::Def(DefKind::TyAlias, did) => {
             record_extern_fqn(cx, did, clean::TypeKind::Typedef);
             ret.extend(build_impls(cx, did));
             clean::TypedefItem(build_type_alias(cx, did), false)
         }
-        Def::Enum(did) => {
+        Def::Def(DefKind::Enum, did) => {
             record_extern_fqn(cx, did, clean::TypeKind::Enum);
             ret.extend(build_impls(cx, did));
             clean::EnumItem(build_enum(cx, did))
         }
-        Def::ForeignTy(did) => {
+        Def::Def(DefKind::ForeignTy, did) => {
             record_extern_fqn(cx, did, clean::TypeKind::Foreign);
             ret.extend(build_impls(cx, did));
             clean::ForeignTypeItem
         }
         // Never inline enum variants but leave them shown as re-exports.
-        Def::Variant(..) => return None,
+        Def::Def(DefKind::Variant, _) => return None,
         // Assume that enum variants and struct types are re-exported next to
         // their constructors.
-        Def::Ctor(..) | Def::SelfCtor(..) => return Some(Vec::new()),
-        Def::Mod(did) => {
+        Def::Def(DefKind::Ctor(..), _) | Def::SelfCtor(..) => return Some(Vec::new()),
+        Def::Def(DefKind::Mod, did) => {
             record_extern_fqn(cx, did, clean::TypeKind::Module);
             clean::ModuleItem(build_module(cx, did, visited))
         }
-        Def::Static(did) => {
+        Def::Def(DefKind::Static, did) => {
             record_extern_fqn(cx, did, clean::TypeKind::Static);
             clean::StaticItem(build_static(cx, did, cx.tcx.is_mutable_static(did)))
         }
-        Def::Const(did) => {
+        Def::Def(DefKind::Const, did) => {
             record_extern_fqn(cx, did, clean::TypeKind::Const);
             clean::ConstantItem(build_const(cx, did))
         }
         // FIXME: proc-macros don't propagate attributes or spans across crates, so they look empty
-        Def::Macro(did, MacroKind::Bang) => {
+        Def::Def(DefKind::Macro(MacroKind::Bang), did) => {
             let mac = build_macro(cx, did, name);
             if let clean::MacroItem(..) = mac {
                 record_extern_fqn(cx, did, clean::TypeKind::Macro);
@@ -135,7 +135,7 @@ pub fn try_inline_glob(cx: &DocContext<'_>, def: Def, visited: &mut FxHashSet<De
     if did.is_local() { return None }
 
     match def {
-        Def::Mod(did) => {
+        Def::Def(DefKind::Mod, did) => {
             let m = build_module(cx, did, visited);
             Some(m.items)
         }
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 7f5ba91900b..95a2664954d 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -19,7 +19,7 @@ use rustc::middle::lang_items;
 use rustc::middle::stability;
 use rustc::mir::interpret::{GlobalId, ConstValue};
 use rustc::hir::{self, HirVec};
-use rustc::hir::def::{self, Def, CtorKind};
+use rustc::hir::def::{self, Def, DefKind, CtorKind};
 use rustc::hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
 use rustc::ty::subst::{InternalSubsts, SubstsRef, UnpackedKind};
 use rustc::ty::{self, DefIdTree, TyCtxt, Region, RegionVid, Ty, AdtKind};
@@ -258,7 +258,7 @@ impl Clean<ExternalCrate> for CrateNum {
         // duplicately for the same primitive. This is handled later on when
         // rendering by delegating everything to a hash map.
         let as_primitive = |def: Def| {
-            if let Def::Mod(def_id) = def {
+            if let Def::Def(DefKind::Mod, def_id) = def {
                 let attrs = cx.tcx.get_attrs(def_id).clean(cx);
                 let mut prim = None;
                 for attr in attrs.lists("doc") {
@@ -281,7 +281,10 @@ impl Clean<ExternalCrate> for CrateNum {
                 let item = cx.tcx.hir().expect_item_by_hir_id(id.id);
                 match item.node {
                     hir::ItemKind::Mod(_) => {
-                        as_primitive(Def::Mod(cx.tcx.hir().local_def_id_from_hir_id(id.id)))
+                        as_primitive(Def::Def(
+                            DefKind::Mod,
+                            cx.tcx.hir().local_def_id_from_hir_id(id.id),
+                        ))
                     }
                     hir::ItemKind::Use(ref path, hir::UseKind::Single)
                     if item.vis.node.is_pub() => {
@@ -299,7 +302,7 @@ impl Clean<ExternalCrate> for CrateNum {
         };
 
         let as_keyword = |def: Def| {
-            if let Def::Mod(def_id) = def {
+            if let Def::Def(DefKind::Mod, def_id) = def {
                 let attrs = cx.tcx.get_attrs(def_id).clean(cx);
                 let mut keyword = None;
                 for attr in attrs.lists("doc") {
@@ -323,7 +326,10 @@ impl Clean<ExternalCrate> for CrateNum {
                 let item = cx.tcx.hir().expect_item_by_hir_id(id.id);
                 match item.node {
                     hir::ItemKind::Mod(_) => {
-                        as_keyword(Def::Mod(cx.tcx.hir().local_def_id_from_hir_id(id.id)))
+                        as_keyword(Def::Def(
+                            DefKind::Mod,
+                            cx.tcx.hir().local_def_id_from_hir_id(id.id),
+                        ))
                     }
                     hir::ItemKind::Use(ref path, hir::UseKind::Single)
                     if item.vis.node.is_pub() => {
@@ -2785,14 +2791,14 @@ impl Clean<Type> for hir::Ty {
                     return new_ty;
                 }
 
-                if let Def::TyParam(did) = path.def {
+                if let Def::Def(DefKind::TyParam, did) = path.def {
                     if let Some(bounds) = cx.impl_trait_bounds.borrow_mut().remove(&did) {
                         return ImplTrait(bounds);
                     }
                 }
 
                 let mut alias = None;
-                if let Def::TyAlias(def_id) = path.def {
+                if let Def::Def(DefKind::TyAlias, def_id) = path.def {
                     // Substitute private type aliases
                     if let Some(hir_id) = cx.tcx.hir().as_local_hir_id(def_id) {
                         if !cx.renderinfo.borrow().access_levels.is_exported(def_id) {
@@ -2835,8 +2841,10 @@ impl Clean<Type> for hir::Ty {
                                 }
                                 hir::GenericParamKind::Type { ref default, .. } => {
                                     let ty_param_def =
-                                        Def::TyParam(
-                                            cx.tcx.hir().local_def_id_from_hir_id(param.hir_id));
+                                        Def::Def(
+                                            DefKind::TyParam,
+                                            cx.tcx.hir().local_def_id_from_hir_id(param.hir_id),
+                                        );
                                     let mut j = 0;
                                     let type_ = generic_args.args.iter().find_map(|arg| {
                                         match arg {
@@ -2860,8 +2868,10 @@ impl Clean<Type> for hir::Ty {
                                 }
                                 hir::GenericParamKind::Const { .. } => {
                                     let const_param_def =
-                                        Def::ConstParam(
-                                            cx.tcx.hir().local_def_id_from_hir_id(param.hir_id));
+                                        Def::Def(
+                                            DefKind::ConstParam,
+                                            cx.tcx.hir().local_def_id_from_hir_id(param.hir_id),
+                                        );
                                     let mut j = 0;
                                     let const_ = generic_args.args.iter().find_map(|arg| {
                                         match arg {
@@ -2893,7 +2903,10 @@ impl Clean<Type> for hir::Ty {
                 segments.pop();
                 let trait_path = hir::Path {
                     span: p.span,
-                    def: Def::Trait(cx.tcx.associated_item(p.def.def_id()).container.id()),
+                    def: Def::Def(
+                        DefKind::Trait,
+                        cx.tcx.associated_item(p.def.def_id()).container.id(),
+                    ),
                     segments: segments.into(),
                 };
                 Type::QPath {
@@ -2906,7 +2919,7 @@ impl Clean<Type> for hir::Ty {
                 let mut def = Def::Err;
                 let ty = hir_ty_to_ty(cx.tcx, self);
                 if let ty::Projection(proj) = ty.sty {
-                    def = Def::Trait(proj.trait_ref(cx.tcx).def_id);
+                    def = Def::Def(DefKind::Trait, proj.trait_ref(cx.tcx).def_id);
                 }
                 let trait_path = hir::Path {
                     span: self.span,
@@ -3898,10 +3911,13 @@ impl Clean<Vec<Item>> for doctree::ExternCrate {
         if please_inline {
             let mut visited = FxHashSet::default();
 
-            let def = Def::Mod(DefId {
-                krate: self.cnum,
-                index: CRATE_DEF_INDEX,
-            });
+            let def = Def::Def(
+                DefKind::Mod,
+                DefId {
+                    krate: self.cnum,
+                    index: CRATE_DEF_INDEX,
+                },
+            );
 
             if let Some(items) = inline::try_inline(cx, def, self.name, &mut visited) {
                 return items;
@@ -3951,10 +3967,12 @@ impl Clean<Vec<Item>> for doctree::Import {
             let name = self.name;
             if !please_inline {
                 match path.def {
-                    Def::Mod(did) => if !did.is_local() && did.index == CRATE_DEF_INDEX {
-                        // if we're `pub use`ing an extern crate root, don't inline it unless we
-                        // were specifically asked for it
-                        denied = true;
+                    Def::Def(DefKind::Mod, did) => {
+                        if !did.is_local() && did.index == CRATE_DEF_INDEX {
+                            // if we're `pub use`ing an extern crate root, don't inline it unless we
+                            // were specifically asked for it
+                            denied = true;
+                        }
                     }
                     _ => {}
                 }
@@ -4157,10 +4175,12 @@ fn resolve_type(cx: &DocContext<'_>,
         Def::SelfTy(..) if path.segments.len() == 1 => {
             return Generic(keywords::SelfUpper.name().to_string());
         }
-        Def::TyParam(..) if path.segments.len() == 1 => {
+        Def::Def(DefKind::TyParam, _) if path.segments.len() == 1 => {
             return Generic(format!("{:#}", path));
         }
-        Def::SelfTy(..) | Def::TyParam(..) | Def::AssociatedTy(..) => true,
+        Def::SelfTy(..)
+        | Def::Def(DefKind::TyParam, _)
+        | Def::Def(DefKind::AssociatedTy, _) => true,
         _ => false,
     };
     let did = register_def(&*cx, path.def);
@@ -4171,25 +4191,25 @@ pub fn register_def(cx: &DocContext<'_>, def: Def) -> DefId {
     debug!("register_def({:?})", def);
 
     let (did, kind) = match def {
-        Def::Fn(i) => (i, TypeKind::Function),
-        Def::TyAlias(i) => (i, TypeKind::Typedef),
-        Def::Enum(i) => (i, TypeKind::Enum),
-        Def::Trait(i) => (i, TypeKind::Trait),
-        Def::Struct(i) => (i, TypeKind::Struct),
-        Def::Union(i) => (i, TypeKind::Union),
-        Def::Mod(i) => (i, TypeKind::Module),
-        Def::ForeignTy(i) => (i, TypeKind::Foreign),
-        Def::Const(i) => (i, TypeKind::Const),
-        Def::Static(i) => (i, TypeKind::Static),
-        Def::Variant(i) => (cx.tcx.parent(i).expect("cannot get parent def id"),
+        Def::Def(DefKind::Fn, i) => (i, TypeKind::Function),
+        Def::Def(DefKind::TyAlias, i) => (i, TypeKind::Typedef),
+        Def::Def(DefKind::Enum, i) => (i, TypeKind::Enum),
+        Def::Def(DefKind::Trait, i) => (i, TypeKind::Trait),
+        Def::Def(DefKind::Struct, i) => (i, TypeKind::Struct),
+        Def::Def(DefKind::Union, i) => (i, TypeKind::Union),
+        Def::Def(DefKind::Mod, i) => (i, TypeKind::Module),
+        Def::Def(DefKind::ForeignTy, i) => (i, TypeKind::Foreign),
+        Def::Def(DefKind::Const, i) => (i, TypeKind::Const),
+        Def::Def(DefKind::Static, i) => (i, TypeKind::Static),
+        Def::Def(DefKind::Variant, i) => (cx.tcx.parent(i).expect("cannot get parent def id"),
                             TypeKind::Enum),
-        Def::Macro(i, mac_kind) => match mac_kind {
+        Def::Def(DefKind::Macro(mac_kind), i) => match mac_kind {
             MacroKind::Bang => (i, TypeKind::Macro),
             MacroKind::Attr => (i, TypeKind::Attr),
             MacroKind::Derive => (i, TypeKind::Derive),
             MacroKind::ProcMacroStub => unreachable!(),
         },
-        Def::TraitAlias(i) => (i, TypeKind::TraitAlias),
+        Def::Def(DefKind::TraitAlias, i) => (i, TypeKind::TraitAlias),
         Def::SelfTy(Some(def_id), _) => (def_id, TypeKind::Trait),
         Def::SelfTy(_, Some(impl_def_id)) => return impl_def_id,
         _ => return def.def_id()
@@ -4418,7 +4438,7 @@ pub fn path_to_def(tcx: TyCtxt<'_, '_, '_>, path: &[&str]) -> Option<DefId> {
                 if item.ident.name == *segment {
                     if path_it.peek().is_none() {
                         return match item.def {
-                            def::Def::Trait(did) => Some(did),
+                            def::Def::Def(DefKind::Trait, did) => Some(did),
                             _ => None,
                         }
                     }
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index 902414bd8fd..f5b97797897 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -1,5 +1,5 @@
 use errors::Applicability;
-use rustc::hir::def::{Def, Namespace::{self, *}, PerNS};
+use rustc::hir::def::{Def, DefKind, Namespace::{self, *}, PerNS};
 use rustc::hir::def_id::DefId;
 use rustc::hir;
 use rustc::lint as lint;
@@ -75,9 +75,9 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
                 // In case this is a trait item, skip the
                 // early return and try looking for the trait.
                 let value = match result.def {
-                    Def::Method(_) | Def::AssociatedConst(_) => true,
-                    Def::AssociatedTy(_) => false,
-                    Def::Variant(_) => return handle_variant(cx, result.def),
+                    Def::Def(DefKind::Method, _) | Def::Def(DefKind::AssociatedConst, _) => true,
+                    Def::Def(DefKind::AssociatedTy, _) => false,
+                    Def::Def(DefKind::Variant, _) => return handle_variant(cx, result.def),
                     // Not a trait item; just return what we found.
                     _ => return Ok((result.def, None))
                 };
@@ -133,7 +133,10 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
                     resolver.resolve_str_path_error(DUMMY_SP, &path, false)
             }))?;
             match ty.def {
-                Def::Struct(did) | Def::Union(did) | Def::Enum(did) | Def::TyAlias(did) => {
+                Def::Def(DefKind::Struct, did)
+                | Def::Def(DefKind::Union, did)
+                | Def::Def(DefKind::Enum, did)
+                | Def::Def(DefKind::TyAlias, did) => {
                     let item = cx.tcx.inherent_impls(did)
                                      .iter()
                                      .flat_map(|imp| cx.tcx.associated_items(*imp))
@@ -172,7 +175,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
                         }
                     }
                 }
-                Def::Trait(did) => {
+                Def::Def(DefKind::Trait, did) => {
                     let item = cx.tcx.associated_item_def_ids(did).iter()
                                  .map(|item| cx.tcx.associated_item(*item))
                                  .find(|item| item.ident.name == item_name);
@@ -347,7 +350,7 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
                                 .and_then(|(def, fragment)| {
                                     // Constructors are picked up in the type namespace.
                                     match def {
-                                        Def::Ctor(..) | Def::SelfCtor(..) => None,
+                                        Def::Def(DefKind::Ctor(..), _) | Def::SelfCtor(..) => None,
                                         _ => Some((def, fragment))
                                     }
                                 }),
@@ -427,7 +430,7 @@ fn macro_resolve(cx: &DocContext<'_>, path_str: &str) -> Option<Def> {
         let parent_scope = resolver.dummy_parent_scope();
         if let Ok(def) = resolver.resolve_macro_to_def_inner(&path, MacroKind::Bang,
                                                             &parent_scope, false, false) {
-            if let Def::Macro(_, MacroKind::ProcMacroStub) = def {
+            if let Def::Def(DefKind::Macro(MacroKind::ProcMacroStub), _) = def {
                 // skip proc-macro stubs, they'll cause `get_macro` to crash
             } else {
                 if let SyntaxExtension::DeclMacro { .. } = *resolver.get_macro(def) {
@@ -541,21 +544,21 @@ fn ambiguity_error(
 
             for (def, ns) in candidates {
                 let (action, mut suggestion) = match def {
-                    Def::Method(..) | Def::Fn(..) => {
+                    Def::Def(DefKind::Method, _) | Def::Def(DefKind::Fn, _) => {
                         ("add parentheses", format!("{}()", path_str))
                     }
-                    Def::Macro(..) => {
+                    Def::Def(DefKind::Macro(..), _) => {
                         ("add an exclamation mark", format!("{}!", path_str))
                     }
                     _ => {
                         let type_ = match (def, ns) {
-                            (Def::Const(..), _) => "const",
-                            (Def::Static(..), _) => "static",
-                            (Def::Struct(..), _) => "struct",
-                            (Def::Enum(..), _) => "enum",
-                            (Def::Union(..), _) => "union",
-                            (Def::Trait(..), _) => "trait",
-                            (Def::Mod(..), _) => "module",
+                            (Def::Def(DefKind::Const, _), _) => "const",
+                            (Def::Def(DefKind::Static, _), _) => "static",
+                            (Def::Def(DefKind::Struct, _), _) => "struct",
+                            (Def::Def(DefKind::Enum, _), _) => "enum",
+                            (Def::Def(DefKind::Union, _), _) => "union",
+                            (Def::Def(DefKind::Trait, _), _) => "trait",
+                            (Def::Def(DefKind::Mod, _), _) => "module",
                             (_, TypeNS) => "type",
                             (_, ValueNS) => "value",
                             (_, MacroNS) => "macro",
@@ -609,7 +612,7 @@ fn handle_variant(cx: &DocContext<'_>, def: Def) -> Result<(Def, Option<String>)
     } else {
         return Err(())
     };
-    let parent_def = Def::Enum(parent);
+    let parent_def = Def::Def(DefKind::Enum, parent);
     let variant = cx.tcx.expect_variant_def(def);
     Ok((parent_def, Some(format!("{}.v", variant.ident.name))))
 }
diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs
index badf37c9671..b7a617cdbd9 100644
--- a/src/librustdoc/visit_ast.rs
+++ b/src/librustdoc/visit_ast.rs
@@ -2,7 +2,7 @@
 //! usable for `clean`.
 
 use rustc::hir::{self, Node};
-use rustc::hir::def::Def;
+use rustc::hir::def::{Def, DefKind};
 use rustc::hir::def_id::{DefId, LOCAL_CRATE};
 use rustc::middle::privacy::AccessLevel;
 use rustc::util::nodemap::{FxHashSet, FxHashMap};
@@ -306,18 +306,18 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
             let attrs = clean::inline::load_attrs(self.cx, def_did);
             let self_is_hidden = attrs.lists("doc").has_word("hidden");
             match def {
-                Def::Trait(did) |
-                Def::Struct(did) |
-                Def::Union(did) |
-                Def::Enum(did) |
-                Def::ForeignTy(did) |
-                Def::TyAlias(did) if !self_is_hidden => {
+                Def::Def(DefKind::Trait, did) |
+                Def::Def(DefKind::Struct, did) |
+                Def::Def(DefKind::Union, did) |
+                Def::Def(DefKind::Enum, did) |
+                Def::Def(DefKind::ForeignTy, did) |
+                Def::Def(DefKind::TyAlias, did) if !self_is_hidden => {
                     self.cx.renderinfo
                         .borrow_mut()
                         .access_levels.map
                         .insert(did, AccessLevel::Public);
                 },
-                Def::Mod(did) => if !self_is_hidden {
+                Def::Def(DefKind::Mod, did) => if !self_is_hidden {
                     crate::visit_lib::LibEmbargoVisitor::new(self.cx).visit_mod(did);
                 },
                 _ => {},
@@ -421,8 +421,9 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
                 // Struct and variant constructors and proc macro stubs always show up alongside
                 // their definitions, we've already processed them so just discard these.
                 match path.def {
-                    Def::Ctor(..) | Def::SelfCtor(..) | Def::Macro(_, MacroKind::ProcMacroStub) =>
-                        return,
+                    Def::Def(DefKind::Ctor(..), _)
+                    | Def::SelfCtor(..)
+                    | Def::Def(DefKind::Macro(MacroKind::ProcMacroStub), _) => return,
                     _ => {}
                 }
 
diff --git a/src/librustdoc/visit_lib.rs b/src/librustdoc/visit_lib.rs
index def6f8b557b..22c750011d9 100644
--- a/src/librustdoc/visit_lib.rs
+++ b/src/librustdoc/visit_lib.rs
@@ -1,5 +1,5 @@
 use rustc::middle::privacy::{AccessLevels, AccessLevel};
-use rustc::hir::def::Def;
+use rustc::hir::def::{Def, DefKind};
 use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId};
 use rustc::ty::Visibility;
 use rustc::util::nodemap::FxHashSet;
@@ -80,7 +80,7 @@ impl<'a, 'tcx> LibEmbargoVisitor<'a, 'tcx> {
 
         let item_level = self.update(def_id, inherited_item_level);
 
-        if let Def::Mod(..) = def {
+        if let Def::Def(DefKind::Mod, _) = def {
             let orig_level = self.prev_level;
 
             self.prev_level = item_level;