about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--crates/hir/src/display.rs5
-rw-r--r--crates/hir/src/lib.rs25
-rw-r--r--crates/hir_def/src/data.rs4
-rw-r--r--crates/hir_ty/src/db.rs4
-rw-r--r--crates/hir_ty/src/diagnostics/decl_check.rs5
-rw-r--r--crates/ide/src/call_hierarchy.rs8
-rw-r--r--crates/ide/src/display/navigation_target.rs14
-rw-r--r--crates/ide/src/doc_links.rs254
-rw-r--r--crates/ide/src/goto_declaration.rs2
-rw-r--r--crates/ide/src/goto_definition.rs9
-rw-r--r--crates/ide/src/goto_implementation.rs104
-rw-r--r--crates/ide/src/goto_type_definition.rs4
-rw-r--r--crates/ide/src/highlight_related.rs2
-rw-r--r--crates/ide/src/hover.rs45
-rw-r--r--crates/ide/src/hover/render.rs41
-rw-r--r--crates/ide/src/references.rs6
-rw-r--r--crates/ide/src/rename.rs2
-rw-r--r--crates/ide/src/syntax_highlighting/highlight.rs178
-rw-r--r--crates/ide/src/syntax_highlighting/inject.rs39
-rw-r--r--crates/ide_assists/src/handlers/add_turbo_fish.rs2
-rw-r--r--crates/ide_assists/src/handlers/convert_tuple_struct_to_named_struct.rs4
-rw-r--r--crates/ide_assists/src/handlers/expand_glob_import.rs58
-rw-r--r--crates/ide_assists/src/handlers/extract_module.rs254
-rw-r--r--crates/ide_assists/src/handlers/extract_struct_from_enum_variant.rs3
-rw-r--r--crates/ide_assists/src/handlers/fix_visibility.rs2
-rw-r--r--crates/ide_assists/src/handlers/generate_function.rs7
-rw-r--r--crates/ide_assists/src/handlers/inline_call.rs2
-rw-r--r--crates/ide_assists/src/handlers/remove_unused_param.rs2
-rw-r--r--crates/ide_db/src/defs.rs187
-rw-r--r--crates/ide_db/src/items_locator.rs3
-rw-r--r--crates/ide_db/src/rename.rs73
-rw-r--r--crates/ide_db/src/search.rs65
32 files changed, 710 insertions, 703 deletions
diff --git a/crates/hir/src/display.rs b/crates/hir/src/display.rs
index a541cbd5e18..e9ace855fc3 100644
--- a/crates/hir/src/display.rs
+++ b/crates/hir/src/display.rs
@@ -421,10 +421,7 @@ impl HirDisplay for Static {
         if data.mutable {
             write!(f, "mut ")?;
         }
-        match &data.name {
-            Some(name) => write!(f, "{}: ", name)?,
-            None => write!(f, "_: ")?,
-        }
+        write!(f, "{}: ", &data.name)?;
         data.type_ref.hir_fmt(f)?;
         Ok(())
     }
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index 2096c485e46..c46324f988c 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -316,17 +316,18 @@ impl ModuleDef {
     }
 
     pub fn name(self, db: &dyn HirDatabase) -> Option<Name> {
-        match self {
-            ModuleDef::Adt(it) => Some(it.name(db)),
-            ModuleDef::Trait(it) => Some(it.name(db)),
-            ModuleDef::Function(it) => Some(it.name(db)),
-            ModuleDef::Variant(it) => Some(it.name(db)),
-            ModuleDef::TypeAlias(it) => Some(it.name(db)),
-            ModuleDef::Module(it) => it.name(db),
-            ModuleDef::Const(it) => it.name(db),
+        let name = match self {
+            ModuleDef::Module(it) => it.name(db)?,
+            ModuleDef::Const(it) => it.name(db)?,
+            ModuleDef::Adt(it) => it.name(db),
+            ModuleDef::Trait(it) => it.name(db),
+            ModuleDef::Function(it) => it.name(db),
+            ModuleDef::Variant(it) => it.name(db),
+            ModuleDef::TypeAlias(it) => it.name(db),
             ModuleDef::Static(it) => it.name(db),
-            ModuleDef::BuiltinType(it) => Some(it.name()),
-        }
+            ModuleDef::BuiltinType(it) => it.name(),
+        };
+        Some(name)
     }
 
     pub fn diagnostics(self, db: &dyn HirDatabase) -> Vec<AnyDiagnostic> {
@@ -1036,7 +1037,7 @@ impl DefWithBody {
     pub fn name(self, db: &dyn HirDatabase) -> Option<Name> {
         match self {
             DefWithBody::Function(f) => Some(f.name(db)),
-            DefWithBody::Static(s) => s.name(db),
+            DefWithBody::Static(s) => Some(s.name(db)),
             DefWithBody::Const(c) => c.name(db),
         }
     }
@@ -1484,7 +1485,7 @@ impl Static {
         Module { id: self.id.lookup(db.upcast()).module(db.upcast()) }
     }
 
-    pub fn name(self, db: &dyn HirDatabase) -> Option<Name> {
+    pub fn name(self, db: &dyn HirDatabase) -> Name {
         db.static_data(self.id).name.clone()
     }
 
diff --git a/crates/hir_def/src/data.rs b/crates/hir_def/src/data.rs
index 435073f6753..f4d0c3af90b 100644
--- a/crates/hir_def/src/data.rs
+++ b/crates/hir_def/src/data.rs
@@ -273,7 +273,7 @@ impl ConstData {
 
 #[derive(Debug, Clone, PartialEq, Eq)]
 pub struct StaticData {
-    pub name: Option<Name>,
+    pub name: Name,
     pub type_ref: Interned<TypeRef>,
     pub visibility: RawVisibility,
     pub mutable: bool,
@@ -287,7 +287,7 @@ impl StaticData {
         let statik = &item_tree[node.id.value];
 
         Arc::new(StaticData {
-            name: Some(statik.name.clone()),
+            name: statik.name.clone(),
             type_ref: statik.type_ref.clone(),
             visibility: item_tree[statik.visibility].clone(),
             mutable: statik.mutable,
diff --git a/crates/hir_ty/src/db.rs b/crates/hir_ty/src/db.rs
index 3a787aa47f6..2583227ff40 100644
--- a/crates/hir_ty/src/db.rs
+++ b/crates/hir_ty/src/db.rs
@@ -162,9 +162,7 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
 fn infer_wait(db: &dyn HirDatabase, def: DefWithBodyId) -> Arc<InferenceResult> {
     let _p = profile::span("infer:wait").detail(|| match def {
         DefWithBodyId::FunctionId(it) => db.function_data(it).name.to_string(),
-        DefWithBodyId::StaticId(it) => {
-            db.static_data(it).name.clone().unwrap_or_else(Name::missing).to_string()
-        }
+        DefWithBodyId::StaticId(it) => db.static_data(it).name.clone().to_string(),
         DefWithBodyId::ConstId(it) => {
             db.const_data(it).name.clone().unwrap_or_else(Name::missing).to_string()
         }
diff --git a/crates/hir_ty/src/diagnostics/decl_check.rs b/crates/hir_ty/src/diagnostics/decl_check.rs
index 6fbb9c93b49..4f4a92447ff 100644
--- a/crates/hir_ty/src/diagnostics/decl_check.rs
+++ b/crates/hir_ty/src/diagnostics/decl_check.rs
@@ -581,10 +581,7 @@ impl<'a> DeclValidator<'a> {
             return;
         }
 
-        let name = match &data.name {
-            Some(name) => name,
-            None => return,
-        };
+        let name = &data.name;
 
         let static_name = name.to_string();
         let replacement = if let Some(new_name) = to_upper_snake_case(&static_name) {
diff --git a/crates/ide/src/call_hierarchy.rs b/crates/ide/src/call_hierarchy.rs
index 7268478191c..23bffd56489 100644
--- a/crates/ide/src/call_hierarchy.rs
+++ b/crates/ide/src/call_hierarchy.rs
@@ -47,15 +47,11 @@ pub(crate) fn incoming_calls(
         .find_nodes_at_offset_with_descend(file, offset)
         .filter_map(move |node| match node {
             ast::NameLike::NameRef(name_ref) => match NameRefClass::classify(sema, &name_ref)? {
-                NameRefClass::Definition(
-                    def @ Definition::ModuleDef(hir::ModuleDef::Function(_)),
-                ) => Some(def),
+                NameRefClass::Definition(def @ Definition::Function(_)) => Some(def),
                 _ => None,
             },
             ast::NameLike::Name(name) => match NameClass::classify(sema, &name)? {
-                NameClass::Definition(def @ Definition::ModuleDef(hir::ModuleDef::Function(_))) => {
-                    Some(def)
-                }
+                NameClass::Definition(def @ Definition::Function(_)) => Some(def),
                 _ => None,
             },
             ast::NameLike::Lifetime(_) => None,
diff --git a/crates/ide/src/display/navigation_target.rs b/crates/ide/src/display/navigation_target.rs
index b21998e0d22..3121cdd4a23 100644
--- a/crates/ide/src/display/navigation_target.rs
+++ b/crates/ide/src/display/navigation_target.rs
@@ -196,13 +196,21 @@ impl ToNav for FileSymbol {
 impl TryToNav for Definition {
     fn try_to_nav(&self, db: &RootDatabase) -> Option<NavigationTarget> {
         match self {
+            Definition::Local(it) => Some(it.to_nav(db)),
+            Definition::Label(it) => Some(it.to_nav(db)),
+            Definition::Module(it) => Some(it.to_nav(db)),
             Definition::Macro(it) => it.try_to_nav(db),
             Definition::Field(it) => it.try_to_nav(db),
-            Definition::ModuleDef(it) => it.try_to_nav(db),
             Definition::SelfType(it) => it.try_to_nav(db),
-            Definition::Local(it) => Some(it.to_nav(db)),
             Definition::GenericParam(it) => it.try_to_nav(db),
-            Definition::Label(it) => Some(it.to_nav(db)),
+            Definition::Function(it) => it.try_to_nav(db),
+            Definition::Adt(it) => it.try_to_nav(db),
+            Definition::Variant(it) => it.try_to_nav(db),
+            Definition::Const(it) => it.try_to_nav(db),
+            Definition::Static(it) => it.try_to_nav(db),
+            Definition::Trait(it) => it.try_to_nav(db),
+            Definition::TypeAlias(it) => it.try_to_nav(db),
+            Definition::BuiltinType(_) => None,
         }
     }
 }
diff --git a/crates/ide/src/doc_links.rs b/crates/ide/src/doc_links.rs
index 703449fe404..075c9172257 100644
--- a/crates/ide/src/doc_links.rs
+++ b/crates/ide/src/doc_links.rs
@@ -8,10 +8,7 @@ use pulldown_cmark_to_cmark::{cmark_with_options, Options as CMarkOptions};
 use stdx::format_to;
 use url::Url;
 
-use hir::{
-    db::HirDatabase, Adt, AsAssocItem, AssocItem, AssocItemContainer, Crate, HasAttrs, MacroDef,
-    ModuleDef,
-};
+use hir::{db::HirDatabase, Adt, AsAssocItem, AssocItem, AssocItemContainer, Crate, HasAttrs};
 use ide_db::{
     defs::{Definition, NameClass, NameRefClass},
     helpers::pick_best_token,
@@ -53,10 +50,8 @@ pub(crate) fn rewrite_links(db: &RootDatabase, markdown: &str, definition: Defin
             if let Some(rewritten) = rewrite_intra_doc_link(db, definition, target, title) {
                 return rewritten;
             }
-            if let Definition::ModuleDef(def) = definition {
-                if let Some(target) = rewrite_url_link(db, Either::Left(def), target) {
-                    return (target, title.to_string());
-                }
+            if let Some(target) = rewrite_url_link(db, definition, target) {
+                return (target, title.to_string());
             }
 
             (target.to_string(), title.to_string())
@@ -174,25 +169,27 @@ pub(crate) fn resolve_doc_path_for_def(
     def: Definition,
     link: &str,
     ns: Option<hir::Namespace>,
-) -> Option<Either<ModuleDef, MacroDef>> {
-    match def {
-        Definition::ModuleDef(def) => match def {
-            hir::ModuleDef::Module(it) => it.resolve_doc_path(db, link, ns),
-            hir::ModuleDef::Function(it) => it.resolve_doc_path(db, link, ns),
-            hir::ModuleDef::Adt(it) => it.resolve_doc_path(db, link, ns),
-            hir::ModuleDef::Variant(it) => it.resolve_doc_path(db, link, ns),
-            hir::ModuleDef::Const(it) => it.resolve_doc_path(db, link, ns),
-            hir::ModuleDef::Static(it) => it.resolve_doc_path(db, link, ns),
-            hir::ModuleDef::Trait(it) => it.resolve_doc_path(db, link, ns),
-            hir::ModuleDef::TypeAlias(it) => it.resolve_doc_path(db, link, ns),
-            hir::ModuleDef::BuiltinType(_) => None,
-        },
+) -> Option<Definition> {
+    let def = match def {
+        Definition::Module(it) => it.resolve_doc_path(db, link, ns),
+        Definition::Function(it) => it.resolve_doc_path(db, link, ns),
+        Definition::Adt(it) => it.resolve_doc_path(db, link, ns),
+        Definition::Variant(it) => it.resolve_doc_path(db, link, ns),
+        Definition::Const(it) => it.resolve_doc_path(db, link, ns),
+        Definition::Static(it) => it.resolve_doc_path(db, link, ns),
+        Definition::Trait(it) => it.resolve_doc_path(db, link, ns),
+        Definition::TypeAlias(it) => it.resolve_doc_path(db, link, ns),
         Definition::Macro(it) => it.resolve_doc_path(db, link, ns),
         Definition::Field(it) => it.resolve_doc_path(db, link, ns),
-        Definition::SelfType(_)
+        Definition::BuiltinType(_)
+        | Definition::SelfType(_)
         | Definition::Local(_)
         | Definition::GenericParam(_)
         | Definition::Label(_) => None,
+    }?;
+    match def {
+        Either::Left(def) => Some(Definition::from(def)),
+        Either::Right(def) => Some(Definition::Macro(def)),
     }
 }
 
@@ -202,17 +199,17 @@ pub(crate) fn doc_attributes(
 ) -> Option<(hir::AttrsWithOwner, Definition)> {
     match_ast! {
         match node {
-            ast::SourceFile(it)  => sema.to_def(&it).map(|def| (def.attrs(sema.db), Definition::ModuleDef(hir::ModuleDef::Module(def)))),
-            ast::Module(it)      => sema.to_def(&it).map(|def| (def.attrs(sema.db), Definition::ModuleDef(hir::ModuleDef::Module(def)))),
-            ast::Fn(it)          => sema.to_def(&it).map(|def| (def.attrs(sema.db), Definition::ModuleDef(hir::ModuleDef::Function(def)))),
-            ast::Struct(it)      => sema.to_def(&it).map(|def| (def.attrs(sema.db), Definition::ModuleDef(hir::ModuleDef::Adt(hir::Adt::Struct(def))))),
-            ast::Union(it)       => sema.to_def(&it).map(|def| (def.attrs(sema.db), Definition::ModuleDef(hir::ModuleDef::Adt(hir::Adt::Union(def))))),
-            ast::Enum(it)        => sema.to_def(&it).map(|def| (def.attrs(sema.db), Definition::ModuleDef(hir::ModuleDef::Adt(hir::Adt::Enum(def))))),
-            ast::Variant(it)     => sema.to_def(&it).map(|def| (def.attrs(sema.db), Definition::ModuleDef(hir::ModuleDef::Variant(def)))),
-            ast::Trait(it)       => sema.to_def(&it).map(|def| (def.attrs(sema.db), Definition::ModuleDef(hir::ModuleDef::Trait(def)))),
-            ast::Static(it)      => sema.to_def(&it).map(|def| (def.attrs(sema.db), Definition::ModuleDef(hir::ModuleDef::Static(def)))),
-            ast::Const(it)       => sema.to_def(&it).map(|def| (def.attrs(sema.db), Definition::ModuleDef(hir::ModuleDef::Const(def)))),
-            ast::TypeAlias(it)   => sema.to_def(&it).map(|def| (def.attrs(sema.db), Definition::ModuleDef(hir::ModuleDef::TypeAlias(def)))),
+            ast::SourceFile(it)  => sema.to_def(&it).map(|def| (def.attrs(sema.db), Definition::Module(def))),
+            ast::Module(it)      => sema.to_def(&it).map(|def| (def.attrs(sema.db), Definition::Module(def))),
+            ast::Fn(it)          => sema.to_def(&it).map(|def| (def.attrs(sema.db), Definition::Function(def))),
+            ast::Struct(it)      => sema.to_def(&it).map(|def| (def.attrs(sema.db), Definition::Adt(hir::Adt::Struct(def)))),
+            ast::Union(it)       => sema.to_def(&it).map(|def| (def.attrs(sema.db), Definition::Adt(hir::Adt::Union(def)))),
+            ast::Enum(it)        => sema.to_def(&it).map(|def| (def.attrs(sema.db), Definition::Adt(hir::Adt::Enum(def)))),
+            ast::Variant(it)     => sema.to_def(&it).map(|def| (def.attrs(sema.db), Definition::Variant(def))),
+            ast::Trait(it)       => sema.to_def(&it).map(|def| (def.attrs(sema.db), Definition::Trait(def))),
+            ast::Static(it)      => sema.to_def(&it).map(|def| (def.attrs(sema.db), Definition::Static(def))),
+            ast::Const(it)       => sema.to_def(&it).map(|def| (def.attrs(sema.db), Definition::Const(def))),
+            ast::TypeAlias(it)   => sema.to_def(&it).map(|def| (def.attrs(sema.db), Definition::TypeAlias(def))),
             ast::Impl(it)        => sema.to_def(&it).map(|def| (def.attrs(sema.db), Definition::SelfType(def))),
             ast::RecordField(it) => sema.to_def(&it).map(|def| (def.attrs(sema.db), Definition::Field(def))),
             ast::TupleField(it)  => sema.to_def(&it).map(|def| (def.attrs(sema.db), Definition::Field(def))),
@@ -274,10 +271,7 @@ impl DocCommentToken {
             let in_expansion_relative_range = in_expansion_range - descended_prefix_len - token_start;
             // Apply relative range to the original input comment
             let absolute_range = in_expansion_relative_range + original_start + prefix_len;
-            let def = match resolve_doc_path_for_def(sema.db, def, &link, ns)? {
-                Either::Left(it) => Definition::ModuleDef(it),
-                Either::Right(it) => Definition::Macro(it),
-            };
+            let def = resolve_doc_path_for_def(sema.db, def, &link, ns)?;
             cb(def, node, absolute_range)
         })
     }
@@ -299,33 +293,8 @@ fn broken_link_clone_cb<'a, 'b>(link: BrokenLink<'a>) -> Option<(CowStr<'b>, Cow
 //
 // This should cease to be a problem if RFC2988 (Stable Rustdoc URLs) is implemented
 // https://github.com/rust-lang/rfcs/pull/2988
-fn get_doc_link(db: &RootDatabase, definition: Definition) -> Option<String> {
-    let (target, frag) = match definition {
-        Definition::ModuleDef(def) => {
-            if let Some(assoc_item) = def.as_assoc_item(db) {
-                let def = match assoc_item.container(db) {
-                    AssocItemContainer::Trait(t) => t.into(),
-                    AssocItemContainer::Impl(i) => i.self_ty(db).as_adt()?.into(),
-                };
-                let frag = get_assoc_item_fragment(db, assoc_item)?;
-                (Either::Left(def), Some(frag))
-            } else {
-                (Either::Left(def), None)
-            }
-        }
-        Definition::Field(field) => {
-            let def = match field.parent_def(db) {
-                hir::VariantDef::Struct(it) => it.into(),
-                hir::VariantDef::Union(it) => it.into(),
-                hir::VariantDef::Variant(it) => it.into(),
-            };
-            (Either::Left(def), Some(format!("structfield.{}", field.name(db))))
-        }
-        Definition::Macro(makro) => (Either::Right(makro), None),
-        // FIXME impls
-        Definition::SelfType(_) => return None,
-        Definition::Local(_) | Definition::GenericParam(_) | Definition::Label(_) => return None,
-    };
+fn get_doc_link(db: &RootDatabase, def: Definition) -> Option<String> {
+    let (target, file, frag) = filename_and_frag_for_def(db, def)?;
 
     let krate = crate_of_def(db, target)?;
     let mut url = get_doc_base_url(db, &krate)?;
@@ -334,7 +303,7 @@ fn get_doc_link(db: &RootDatabase, definition: Definition) -> Option<String> {
         url = url.join(&path).ok()?;
     }
 
-    url = url.join(&get_symbol_filename(db, target)?).ok()?;
+    url = url.join(&file).ok()?;
     url.set_fragment(frag.as_deref());
 
     Some(url.into())
@@ -352,73 +321,51 @@ fn rewrite_intra_doc_link(
     let krate = crate_of_def(db, resolved)?;
     let mut url = get_doc_base_url(db, &krate)?;
 
+    let (_, file, frag) = filename_and_frag_for_def(db, resolved)?;
     if let Some(path) = mod_path_of_def(db, resolved) {
         url = url.join(&path).ok()?;
     }
 
-    let (resolved, frag) =
-        if let Some(assoc_item) = resolved.left().and_then(|it| it.as_assoc_item(db)) {
-            let resolved = match assoc_item.container(db) {
-                AssocItemContainer::Trait(t) => t.into(),
-                AssocItemContainer::Impl(i) => i.self_ty(db).as_adt()?.into(),
-            };
-            let frag = get_assoc_item_fragment(db, assoc_item)?;
-            (Either::Left(resolved), Some(frag))
-        } else {
-            (resolved, None)
-        };
-    url = url.join(&get_symbol_filename(db, resolved)?).ok()?;
+    url = url.join(&file).ok()?;
     url.set_fragment(frag.as_deref());
 
     Some((url.into(), strip_prefixes_suffixes(title).to_string()))
 }
 
 /// Try to resolve path to local documentation via path-based links (i.e. `../gateway/struct.Shard.html`).
-fn rewrite_url_link(
-    db: &RootDatabase,
-    def: Either<ModuleDef, MacroDef>,
-    target: &str,
-) -> Option<String> {
+fn rewrite_url_link(db: &RootDatabase, def: Definition, target: &str) -> Option<String> {
     if !(target.contains('#') || target.contains(".html")) {
         return None;
     }
 
     let krate = crate_of_def(db, def)?;
     let mut url = get_doc_base_url(db, &krate)?;
+    let (def, file, frag) = filename_and_frag_for_def(db, def)?;
 
     if let Some(path) = mod_path_of_def(db, def) {
         url = url.join(&path).ok()?;
     }
 
-    url = url.join(&get_symbol_filename(db, def)?).ok()?;
+    url = url.join(&file).ok()?;
+    url.set_fragment(frag.as_deref());
     url.join(target).ok().map(Into::into)
 }
 
-fn crate_of_def(db: &RootDatabase, def: Either<ModuleDef, MacroDef>) -> Option<Crate> {
+fn crate_of_def(db: &RootDatabase, def: Definition) -> Option<Crate> {
     let krate = match def {
         // Definition::module gives back the parent module, we don't want that as it fails for root modules
-        Either::Left(ModuleDef::Module(module)) => module.krate(),
-        Either::Left(def) => def.module(db)?.krate(),
-        Either::Right(def) => def.module(db)?.krate(),
+        Definition::Module(module) => module.krate(),
+        def => def.module(db)?.krate(),
     };
     Some(krate)
 }
 
-fn mod_path_of_def(db: &RootDatabase, def: Either<ModuleDef, MacroDef>) -> Option<String> {
-    match def {
-        Either::Left(def) => def.canonical_module_path(db).map(|it| {
-            let mut path = String::new();
-            it.flat_map(|it| it.name(db)).for_each(|name| format_to!(path, "{}/", name));
-            path
-        }),
-        Either::Right(def) => {
-            def.module(db).map(|it| it.path_to_root(db).into_iter().rev()).map(|it| {
-                let mut path = String::new();
-                it.flat_map(|it| it.name(db)).for_each(|name| format_to!(path, "{}/", name));
-                path
-            })
-        }
-    }
+fn mod_path_of_def(db: &RootDatabase, def: Definition) -> Option<String> {
+    def.canonical_module_path(db).map(|it| {
+        let mut path = String::new();
+        it.flat_map(|it| it.name(db)).for_each(|name| format_to!(path, "{}/", name));
+        path
+    })
 }
 
 /// Rewrites a markdown document, applying 'callback' to each link.
@@ -496,34 +443,61 @@ fn get_doc_base_url(db: &RootDatabase, krate: &Crate) -> Option<Url> {
 /// https://doc.rust-lang.org/std/iter/trait.Iterator.html#tymethod.next
 ///                                    ^^^^^^^^^^^^^^^^^^^
 /// ```
-fn get_symbol_filename(
+fn filename_and_frag_for_def(
     db: &dyn HirDatabase,
-    definition: Either<ModuleDef, MacroDef>,
-) -> Option<String> {
-    let res = match definition {
-        Either::Left(definition) => match definition {
-            ModuleDef::Adt(adt) => match adt {
-                Adt::Struct(s) => format!("struct.{}.html", s.name(db)),
-                Adt::Enum(e) => format!("enum.{}.html", e.name(db)),
-                Adt::Union(u) => format!("union.{}.html", u.name(db)),
-            },
-            ModuleDef::Module(m) => match m.name(db) {
-                Some(name) => format!("{}/index.html", name),
-                None => String::from("index.html"),
-            },
-            ModuleDef::Trait(t) => format!("trait.{}.html", t.name(db)),
-            ModuleDef::TypeAlias(t) => format!("type.{}.html", t.name(db)),
-            ModuleDef::BuiltinType(t) => format!("primitive.{}.html", t.name()),
-            ModuleDef::Function(f) => format!("fn.{}.html", f.name(db)),
-            ModuleDef::Variant(ev) => {
-                format!("enum.{}.html#variant.{}", ev.parent_enum(db).name(db), ev.name(db))
-            }
-            ModuleDef::Const(c) => format!("const.{}.html", c.name(db)?),
-            ModuleDef::Static(s) => format!("static.{}.html", s.name(db)?),
+    def: Definition,
+) -> Option<(Definition, String, Option<String>)> {
+    if let Some(assoc_item) = def.as_assoc_item(db) {
+        let def = match assoc_item.container(db) {
+            AssocItemContainer::Trait(t) => t.into(),
+            AssocItemContainer::Impl(i) => i.self_ty(db).as_adt()?.into(),
+        };
+        let (_, file, _) = filename_and_frag_for_def(db, def)?;
+        let frag = get_assoc_item_fragment(db, assoc_item)?;
+        return Some((def, file, Some(frag)));
+    }
+
+    let res = match def {
+        Definition::Adt(adt) => match adt {
+            Adt::Struct(s) => format!("struct.{}.html", s.name(db)),
+            Adt::Enum(e) => format!("enum.{}.html", e.name(db)),
+            Adt::Union(u) => format!("union.{}.html", u.name(db)),
+        },
+        Definition::Module(m) => match m.name(db) {
+            Some(name) => format!("{}/index.html", name),
+            None => String::from("index.html"),
         },
-        Either::Right(mac) => format!("macro.{}.html", mac.name(db)?),
+        Definition::Trait(t) => format!("trait.{}.html", t.name(db)),
+        Definition::TypeAlias(t) => format!("type.{}.html", t.name(db)),
+        Definition::BuiltinType(t) => format!("primitive.{}.html", t.name()),
+        Definition::Function(f) => format!("fn.{}.html", f.name(db)),
+        Definition::Variant(ev) => {
+            format!("enum.{}.html#variant.{}", ev.parent_enum(db).name(db), ev.name(db))
+        }
+        Definition::Const(c) => format!("const.{}.html", c.name(db)?),
+        Definition::Static(s) => format!("static.{}.html", s.name(db)),
+        Definition::Macro(mac) => format!("macro.{}.html", mac.name(db)?),
+        Definition::Field(field) => {
+            let def = match field.parent_def(db) {
+                hir::VariantDef::Struct(it) => Definition::Adt(it.into()),
+                hir::VariantDef::Union(it) => Definition::Adt(it.into()),
+                hir::VariantDef::Variant(it) => Definition::Variant(it),
+            };
+            let (_, file, _) = filename_and_frag_for_def(db, def)?;
+            return Some((def, file, Some(format!("structfield.{}", field.name(db)))));
+        }
+        Definition::SelfType(impl_) => {
+            let adt = impl_.self_ty(db).as_adt()?.into();
+            let (_, file, _) = filename_and_frag_for_def(db, adt)?;
+            // FIXME fragment numbering
+            return Some((adt, file, Some(String::from("impl"))));
+        }
+        Definition::Local(_) => return None,
+        Definition::GenericParam(_) => return None,
+        Definition::Label(_) => return None,
     };
-    Some(res)
+
+    Some((def, res, None))
 }
 
 /// Get the fragment required to link to a specific field, method, associated type, or associated constant.
@@ -803,8 +777,6 @@ pub struct B$0ar
 
     #[test]
     fn rewrite_on_field() {
-        // FIXME: Should be
-        //  [Foo](https://docs.rs/test/*/test/struct.Foo.html)
         check_rewrite(
             r#"
 //- /main.rs crate:foo
@@ -813,7 +785,7 @@ pub struct Foo {
     fie$0ld: ()
 }
 "#,
-            expect![[r#"[Foo](struct.Foo.html)"#]],
+            expect![[r#"[Foo](https://docs.rs/foo/*/foo/struct.Foo.html)"#]],
         );
     }
 
@@ -927,17 +899,17 @@ pub struct $0Foo;
     ) -> Option<Option<(Option<hir::Documentation>, Definition)>> {
         Some(match_ast! {
             match node {
-                ast::SourceFile(it)  => sema.to_def(&it).map(|def| (def.docs(sema.db), Definition::ModuleDef(hir::ModuleDef::Module(def)))),
-                ast::Module(it)      => sema.to_def(&it).map(|def| (def.docs(sema.db), Definition::ModuleDef(hir::ModuleDef::Module(def)))),
-                ast::Fn(it)          => sema.to_def(&it).map(|def| (def.docs(sema.db), Definition::ModuleDef(hir::ModuleDef::Function(def)))),
-                ast::Struct(it)      => sema.to_def(&it).map(|def| (def.docs(sema.db), Definition::ModuleDef(hir::ModuleDef::Adt(hir::Adt::Struct(def))))),
-                ast::Union(it)       => sema.to_def(&it).map(|def| (def.docs(sema.db), Definition::ModuleDef(hir::ModuleDef::Adt(hir::Adt::Union(def))))),
-                ast::Enum(it)        => sema.to_def(&it).map(|def| (def.docs(sema.db), Definition::ModuleDef(hir::ModuleDef::Adt(hir::Adt::Enum(def))))),
-                ast::Variant(it)     => sema.to_def(&it).map(|def| (def.docs(sema.db), Definition::ModuleDef(hir::ModuleDef::Variant(def)))),
-                ast::Trait(it)       => sema.to_def(&it).map(|def| (def.docs(sema.db), Definition::ModuleDef(hir::ModuleDef::Trait(def)))),
-                ast::Static(it)      => sema.to_def(&it).map(|def| (def.docs(sema.db), Definition::ModuleDef(hir::ModuleDef::Static(def)))),
-                ast::Const(it)       => sema.to_def(&it).map(|def| (def.docs(sema.db), Definition::ModuleDef(hir::ModuleDef::Const(def)))),
-                ast::TypeAlias(it)   => sema.to_def(&it).map(|def| (def.docs(sema.db), Definition::ModuleDef(hir::ModuleDef::TypeAlias(def)))),
+                ast::SourceFile(it)  => sema.to_def(&it).map(|def| (def.docs(sema.db), Definition::Module(def))),
+                ast::Module(it)      => sema.to_def(&it).map(|def| (def.docs(sema.db), Definition::Module(def))),
+                ast::Fn(it)          => sema.to_def(&it).map(|def| (def.docs(sema.db), Definition::Function(def))),
+                ast::Struct(it)      => sema.to_def(&it).map(|def| (def.docs(sema.db), Definition::Adt(hir::Adt::Struct(def)))),
+                ast::Union(it)       => sema.to_def(&it).map(|def| (def.docs(sema.db), Definition::Adt(hir::Adt::Union(def)))),
+                ast::Enum(it)        => sema.to_def(&it).map(|def| (def.docs(sema.db), Definition::Adt(hir::Adt::Enum(def)))),
+                ast::Variant(it)     => sema.to_def(&it).map(|def| (def.docs(sema.db), Definition::Variant(def))),
+                ast::Trait(it)       => sema.to_def(&it).map(|def| (def.docs(sema.db), Definition::Trait(def))),
+                ast::Static(it)      => sema.to_def(&it).map(|def| (def.docs(sema.db), Definition::Static(def))),
+                ast::Const(it)       => sema.to_def(&it).map(|def| (def.docs(sema.db), Definition::Const(def))),
+                ast::TypeAlias(it)   => sema.to_def(&it).map(|def| (def.docs(sema.db), Definition::TypeAlias(def))),
                 ast::Impl(it)        => sema.to_def(&it).map(|def| (def.docs(sema.db), Definition::SelfType(def))),
                 ast::RecordField(it) => sema.to_def(&it).map(|def| (def.docs(sema.db), Definition::Field(def))),
                 ast::TupleField(it)  => sema.to_def(&it).map(|def| (def.docs(sema.db), Definition::Field(def))),
diff --git a/crates/ide/src/goto_declaration.rs b/crates/ide/src/goto_declaration.rs
index c79015c7160..e62daf03f98 100644
--- a/crates/ide/src/goto_declaration.rs
+++ b/crates/ide/src/goto_declaration.rs
@@ -39,7 +39,7 @@ pub(crate) fn goto_declaration(
                 }
             };
             match def? {
-                Definition::ModuleDef(hir::ModuleDef::Module(module)) => {
+                Definition::Module(module) => {
                     Some(NavigationTarget::from_module_to_decl(db, module))
                 }
                 _ => None,
diff --git a/crates/ide/src/goto_definition.rs b/crates/ide/src/goto_definition.rs
index 1edb17739b5..77f90eee194 100644
--- a/crates/ide/src/goto_definition.rs
+++ b/crates/ide/src/goto_definition.rs
@@ -3,7 +3,7 @@ use std::convert::TryInto;
 use crate::{
     display::TryToNav, doc_links::token_as_doc_comment, FilePosition, NavigationTarget, RangeInfo,
 };
-use hir::{AsAssocItem, ModuleDef, Semantics};
+use hir::{AsAssocItem, Semantics};
 use ide_db::{
     base_db::{AnchoredPath, FileId, FileLoader},
     defs::Definition,
@@ -110,12 +110,7 @@ fn try_find_trait_item_definition(
     def: &Definition,
 ) -> Option<Vec<NavigationTarget>> {
     let name = def.name(db)?;
-    let assoc = match def {
-        Definition::ModuleDef(ModuleDef::Function(f)) => f.as_assoc_item(db),
-        Definition::ModuleDef(ModuleDef::Const(c)) => c.as_assoc_item(db),
-        Definition::ModuleDef(ModuleDef::TypeAlias(ty)) => ty.as_assoc_item(db),
-        _ => None,
-    }?;
+    let assoc = def.as_assoc_item(db)?;
 
     let imp = match assoc.container(db) {
         hir::AssocItemContainer::Impl(imp) => imp,
diff --git a/crates/ide/src/goto_implementation.rs b/crates/ide/src/goto_implementation.rs
index 9b0e42d8cff..c9c7e232f29 100644
--- a/crates/ide/src/goto_implementation.rs
+++ b/crates/ide/src/goto_implementation.rs
@@ -34,63 +34,57 @@ pub(crate) fn goto_implementation(
             _ => 0,
         })?;
     let range = original_token.text_range();
-    let navs =
-        sema.descend_into_macros(original_token)
-            .into_iter()
-            .filter_map(|token| token.parent().and_then(ast::NameLike::cast))
-            .filter_map(|node| {
-                let def = match &node {
-                    ast::NameLike::Name(name) => {
-                        NameClass::classify(&sema, name).map(|class| match class {
-                            NameClass::Definition(it) | NameClass::ConstReference(it) => it,
-                            NameClass::PatFieldShorthand { local_def, field_ref: _ } => {
-                                Definition::Local(local_def)
-                            }
-                        })
-                    }
-                    ast::NameLike::NameRef(name_ref) => NameRefClass::classify(&sema, name_ref)
-                        .map(|class| match class {
-                            NameRefClass::Definition(def) => def,
-                            NameRefClass::FieldShorthand { local_ref, field_ref: _ } => {
-                                Definition::Local(local_ref)
-                            }
-                        }),
-                    ast::NameLike::Lifetime(_) => None,
-                }?;
-
-                match def {
-                    Definition::ModuleDef(def) => Some(def),
-                    _ => None,
-                }
-            })
-            .unique()
-            .filter_map(|def| {
-                let navs = match def {
-                    hir::ModuleDef::Trait(trait_) => impls_for_trait(&sema, trait_),
-                    hir::ModuleDef::Adt(adt) => impls_for_ty(&sema, adt.ty(sema.db)),
-                    hir::ModuleDef::TypeAlias(alias) => impls_for_ty(&sema, alias.ty(sema.db)),
-                    hir::ModuleDef::BuiltinType(builtin) => {
-                        let module = sema.to_module_def(position.file_id)?;
-                        impls_for_ty(&sema, builtin.ty(sema.db, module))
-                    }
-                    hir::ModuleDef::Function(f) => {
-                        let assoc = f.as_assoc_item(sema.db)?;
-                        let name = assoc.name(sema.db)?;
-                        let trait_ = assoc.containing_trait_or_trait_impl(sema.db)?;
-                        impls_for_trait_item(&sema, trait_, name)
+    let navs = sema
+        .descend_into_macros(original_token)
+        .into_iter()
+        .filter_map(|token| token.parent().and_then(ast::NameLike::cast))
+        .filter_map(|node| match &node {
+            ast::NameLike::Name(name) => {
+                NameClass::classify(&sema, name).map(|class| match class {
+                    NameClass::Definition(it) | NameClass::ConstReference(it) => it,
+                    NameClass::PatFieldShorthand { local_def, field_ref: _ } => {
+                        Definition::Local(local_def)
                     }
-                    hir::ModuleDef::Const(c) => {
-                        let assoc = c.as_assoc_item(sema.db)?;
-                        let name = assoc.name(sema.db)?;
-                        let trait_ = assoc.containing_trait_or_trait_impl(sema.db)?;
-                        impls_for_trait_item(&sema, trait_, name)
+                })
+            }
+            ast::NameLike::NameRef(name_ref) => {
+                NameRefClass::classify(&sema, name_ref).map(|class| match class {
+                    NameRefClass::Definition(def) => def,
+                    NameRefClass::FieldShorthand { local_ref, field_ref: _ } => {
+                        Definition::Local(local_ref)
                     }
-                    _ => return None,
-                };
-                Some(navs)
-            })
-            .flatten()
-            .collect();
+                })
+            }
+            ast::NameLike::Lifetime(_) => None,
+        })
+        .unique()
+        .filter_map(|def| {
+            let navs = match def {
+                Definition::Trait(trait_) => impls_for_trait(&sema, trait_),
+                Definition::Adt(adt) => impls_for_ty(&sema, adt.ty(sema.db)),
+                Definition::TypeAlias(alias) => impls_for_ty(&sema, alias.ty(sema.db)),
+                Definition::BuiltinType(builtin) => {
+                    let module = sema.to_module_def(position.file_id)?;
+                    impls_for_ty(&sema, builtin.ty(sema.db, module))
+                }
+                Definition::Function(f) => {
+                    let assoc = f.as_assoc_item(sema.db)?;
+                    let name = assoc.name(sema.db)?;
+                    let trait_ = assoc.containing_trait_or_trait_impl(sema.db)?;
+                    impls_for_trait_item(&sema, trait_, name)
+                }
+                Definition::Const(c) => {
+                    let assoc = c.as_assoc_item(sema.db)?;
+                    let name = assoc.name(sema.db)?;
+                    let trait_ = assoc.containing_trait_or_trait_impl(sema.db)?;
+                    impls_for_trait_item(&sema, trait_, name)
+                }
+                _ => return None,
+            };
+            Some(navs)
+        })
+        .flatten()
+        .collect();
 
     Some(RangeInfo { range, info: navs })
 }
diff --git a/crates/ide/src/goto_type_definition.rs b/crates/ide/src/goto_type_definition.rs
index 693098e3f29..ce58f72a775 100644
--- a/crates/ide/src/goto_type_definition.rs
+++ b/crates/ide/src/goto_type_definition.rs
@@ -1,4 +1,4 @@
-use ide_db::{base_db::Upcast, helpers::pick_best_token, RootDatabase};
+use ide_db::{base_db::Upcast, defs::Definition, helpers::pick_best_token, RootDatabase};
 use syntax::{ast, match_ast, AstNode, SyntaxKind::*, SyntaxToken, T};
 
 use crate::{display::TryToNav, FilePosition, NavigationTarget, RangeInfo};
@@ -29,7 +29,7 @@ pub(crate) fn goto_type_definition(
         })?;
 
     let mut res = Vec::new();
-    let mut push = |def: hir::ModuleDef| {
+    let mut push = |def: Definition| {
         if let Some(nav) = def.try_to_nav(db) {
             if !res.contains(&nav) {
                 res.push(nav);
diff --git a/crates/ide/src/highlight_related.rs b/crates/ide/src/highlight_related.rs
index e452f8c9386..5ff6fd10bc8 100644
--- a/crates/ide/src/highlight_related.rs
+++ b/crates/ide/src/highlight_related.rs
@@ -97,7 +97,7 @@ fn highlight_references(
 
     let declarations = defs.iter().flat_map(|def| {
         match def {
-            &Definition::ModuleDef(hir::ModuleDef::Module(module)) => {
+            &Definition::Module(module) => {
                 Some(NavigationTarget::from_module_to_decl(sema.db, module))
             }
             def => def.try_to_nav(sema.db),
diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs
index d4244628787..f4fb52647e7 100644
--- a/crates/ide/src/hover.rs
+++ b/crates/ide/src/hover.rs
@@ -163,9 +163,7 @@ pub(crate) fn hover_for_definition(
     config: &HoverConfig,
 ) -> Option<HoverResult> {
     let famous_defs = match &definition {
-        Definition::ModuleDef(hir::ModuleDef::BuiltinType(_)) => {
-            Some(FamousDefs(sema, sema.scope(node).krate()))
-        }
+        Definition::BuiltinType(_) => Some(FamousDefs(sema, sema.scope(node).krate())),
         _ => None,
     };
     if let Some(markup) = render::definition(sema.db, definition, famous_defs.as_ref(), config) {
@@ -260,10 +258,8 @@ fn show_implementations_action(db: &RootDatabase, def: Definition) -> Option<Hov
     }
 
     let adt = match def {
-        Definition::ModuleDef(hir::ModuleDef::Trait(it)) => {
-            return it.try_to_nav(db).map(to_action)
-        }
-        Definition::ModuleDef(hir::ModuleDef::Adt(it)) => Some(it),
+        Definition::Trait(it) => return it.try_to_nav(db).map(to_action),
+        Definition::Adt(it) => Some(it),
         Definition::SelfType(it) => it.self_ty(db).as_adt(),
         _ => None,
     }?;
@@ -272,14 +268,12 @@ fn show_implementations_action(db: &RootDatabase, def: Definition) -> Option<Hov
 
 fn show_fn_references_action(db: &RootDatabase, def: Definition) -> Option<HoverAction> {
     match def {
-        Definition::ModuleDef(hir::ModuleDef::Function(it)) => {
-            it.try_to_nav(db).map(|nav_target| {
-                HoverAction::Reference(FilePosition {
-                    file_id: nav_target.file_id,
-                    offset: nav_target.focus_or_full_range().start(),
-                })
+        Definition::Function(it) => it.try_to_nav(db).map(|nav_target| {
+            HoverAction::Reference(FilePosition {
+                file_id: nav_target.file_id,
+                offset: nav_target.focus_or_full_range().start(),
             })
-        }
+        }),
         _ => None,
     }
 }
@@ -290,20 +284,17 @@ fn runnable_action(
     file_id: FileId,
 ) -> Option<HoverAction> {
     match def {
-        Definition::ModuleDef(it) => match it {
-            hir::ModuleDef::Module(it) => runnable_mod(sema, it).map(HoverAction::Runnable),
-            hir::ModuleDef::Function(func) => {
-                let src = func.source(sema.db)?;
-                if src.file_id != file_id.into() {
-                    cov_mark::hit!(hover_macro_generated_struct_fn_doc_comment);
-                    cov_mark::hit!(hover_macro_generated_struct_fn_doc_attr);
-                    return None;
-                }
-
-                runnable_fn(sema, func).map(HoverAction::Runnable)
+        Definition::Module(it) => runnable_mod(sema, it).map(HoverAction::Runnable),
+        Definition::Function(func) => {
+            let src = func.source(sema.db)?;
+            if src.file_id != file_id.into() {
+                cov_mark::hit!(hover_macro_generated_struct_fn_doc_comment);
+                cov_mark::hit!(hover_macro_generated_struct_fn_doc_attr);
+                return None;
             }
-            _ => None,
-        },
+
+            runnable_fn(sema, func).map(HoverAction::Runnable)
+        }
         _ => None,
     }
 }
diff --git a/crates/ide/src/hover/render.rs b/crates/ide/src/hover/render.rs
index 7f9a91286a4..59068028ed9 100644
--- a/crates/ide/src/hover/render.rs
+++ b/crates/ide/src/hover/render.rs
@@ -242,7 +242,7 @@ pub(super) fn keyword(
     let docs = doc_owner.attrs(sema.db).docs()?;
     let markup = process_markup(
         sema.db,
-        Definition::ModuleDef(doc_owner.into()),
+        Definition::Module(doc_owner),
         &markup(Some(docs.into()), token.text().into(), None)?,
         config,
     );
@@ -311,14 +311,11 @@ fn definition_owner_name(db: &RootDatabase, def: &Definition) -> Option<String>
     match def {
         Definition::Field(f) => Some(f.parent_def(db).name(db)),
         Definition::Local(l) => l.parent(db).name(db),
-        Definition::ModuleDef(md) => match md {
-            hir::ModuleDef::Function(f) => match f.as_assoc_item(db)?.container(db) {
-                hir::AssocItemContainer::Trait(t) => Some(t.name(db)),
-                hir::AssocItemContainer::Impl(i) => i.self_ty(db).as_adt().map(|adt| adt.name(db)),
-            },
-            hir::ModuleDef::Variant(e) => Some(e.parent_enum(db).name(db)),
-            _ => None,
+        Definition::Function(f) => match f.as_assoc_item(db)?.container(db) {
+            hir::AssocItemContainer::Trait(t) => Some(t.name(db)),
+            hir::AssocItemContainer::Impl(i) => i.self_ty(db).as_adt().map(|adt| adt.name(db)),
         },
+        Definition::Variant(e) => Some(e.parent_enum(db).name(db)),
         _ => None,
     }
     .map(|name| name.to_string())
@@ -351,21 +348,19 @@ pub(super) fn definition(
             it.attrs(db).docs(),
         ),
         Definition::Field(def) => label_and_docs(db, def),
-        Definition::ModuleDef(it) => match it {
-            hir::ModuleDef::Module(it) => label_and_docs(db, it),
-            hir::ModuleDef::Function(it) => label_and_docs(db, it),
-            hir::ModuleDef::Adt(it) => label_and_docs(db, it),
-            hir::ModuleDef::Variant(it) => label_and_docs(db, it),
-            hir::ModuleDef::Const(it) => label_and_docs(db, it),
-            hir::ModuleDef::Static(it) => label_and_docs(db, it),
-            hir::ModuleDef::Trait(it) => label_and_docs(db, it),
-            hir::ModuleDef::TypeAlias(it) => label_and_docs(db, it),
-            hir::ModuleDef::BuiltinType(it) => {
-                return famous_defs
-                    .and_then(|fd| builtin(fd, it))
-                    .or_else(|| Some(Markup::fenced_block(&it.name())))
-            }
-        },
+        Definition::Module(it) => label_and_docs(db, it),
+        Definition::Function(it) => label_and_docs(db, it),
+        Definition::Adt(it) => label_and_docs(db, it),
+        Definition::Variant(it) => label_and_docs(db, it),
+        Definition::Const(it) => label_and_docs(db, it),
+        Definition::Static(it) => label_and_docs(db, it),
+        Definition::Trait(it) => label_and_docs(db, it),
+        Definition::TypeAlias(it) => label_and_docs(db, it),
+        Definition::BuiltinType(it) => {
+            return famous_defs
+                .and_then(|fd| builtin(fd, it))
+                .or_else(|| Some(Markup::fenced_block(&it.name())))
+        }
         Definition::Local(it) => return local(db, it),
         Definition::SelfType(impl_def) => {
             impl_def.self_ty(db).as_adt().map(|adt| label_and_docs(db, adt))?
diff --git a/crates/ide/src/references.rs b/crates/ide/src/references.rs
index fd36cfc44de..d1219044fe5 100644
--- a/crates/ide/src/references.rs
+++ b/crates/ide/src/references.rs
@@ -80,7 +80,7 @@ pub(crate) fn find_all_refs(
                 let mut usages =
                     def.usages(sema).set_scope(search_scope.clone()).include_self_refs().all();
                 let declaration = match def {
-                    Definition::ModuleDef(hir::ModuleDef::Module(module)) => {
+                    Definition::Module(module) => {
                         Some(NavigationTarget::from_module_to_decl(sema.db, module))
                     }
                     def => def.try_to_nav(sema.db),
@@ -168,7 +168,7 @@ fn retain_adt_literal_usages(
 ) {
     let refs = usages.references.values_mut();
     match def {
-        Definition::ModuleDef(hir::ModuleDef::Adt(hir::Adt::Enum(enum_))) => {
+        Definition::Adt(hir::Adt::Enum(enum_)) => {
             refs.for_each(|it| {
                 it.retain(|reference| {
                     reference
@@ -179,7 +179,7 @@ fn retain_adt_literal_usages(
             });
             usages.references.retain(|_, it| !it.is_empty());
         }
-        Definition::ModuleDef(hir::ModuleDef::Adt(_) | hir::ModuleDef::Variant(_)) => {
+        Definition::Adt(_) | Definition::Variant(_) => {
             refs.for_each(|it| {
                 it.retain(|reference| reference.name.as_name_ref().map_or(false, is_lit_name_ref))
             });
diff --git a/crates/ide/src/rename.rs b/crates/ide/src/rename.rs
index a7ebba82b03..f9f9c0832cd 100644
--- a/crates/ide/src/rename.rs
+++ b/crates/ide/src/rename.rs
@@ -113,7 +113,7 @@ pub(crate) fn will_rename_file(
 ) -> Option<SourceChange> {
     let sema = Semantics::new(db);
     let module = sema.to_module_def(file_id)?;
-    let def = Definition::ModuleDef(module.into());
+    let def = Definition::Module(module);
     let mut change = def.rename(&sema, new_name_stem).ok()?;
     change.file_system_edits.clear();
     Some(change)
diff --git a/crates/ide/src/syntax_highlighting/highlight.rs b/crates/ide/src/syntax_highlighting/highlight.rs
index 2bf83da4dfa..d63b0c87a90 100644
--- a/crates/ide/src/syntax_highlighting/highlight.rs
+++ b/crates/ide/src/syntax_highlighting/highlight.rs
@@ -246,7 +246,7 @@ fn node(
 fn highlight_name_ref_in_attr(sema: &Semantics<RootDatabase>, name_ref: ast::NameRef) -> Highlight {
     match NameRefClass::classify(sema, &name_ref) {
         Some(name_class) => match name_class {
-            NameRefClass::Definition(Definition::ModuleDef(hir::ModuleDef::Module(_)))
+            NameRefClass::Definition(Definition::Module(_))
                 if name_ref
                     .syntax()
                     .ancestors()
@@ -302,9 +302,7 @@ fn highlight_name_ref(
                     {
                         h |= HlMod::Consuming;
                     }
-                    Definition::ModuleDef(hir::ModuleDef::Trait(trait_))
-                        if trait_.is_unsafe(db) =>
-                    {
+                    Definition::Trait(trait_) if trait_.is_unsafe(db) => {
                         if ast::Impl::for_trait_name_ref(&name_ref)
                             .map_or(false, |impl_| impl_.unsafe_token().is_some())
                         {
@@ -358,7 +356,7 @@ fn highlight_name(
     match name_kind {
         Some(NameClass::Definition(def)) => {
             let mut h = highlight_def(sema, krate, def) | HlMod::Definition;
-            if let Definition::ModuleDef(hir::ModuleDef::Trait(trait_)) = &def {
+            if let Definition::Trait(trait_) = &def {
                 if trait_.is_unsafe(db) {
                     h |= HlMod::Unsafe;
                 }
@@ -398,112 +396,110 @@ fn highlight_def(
     let mut h = match def {
         Definition::Macro(_) => Highlight::new(HlTag::Symbol(SymbolKind::Macro)),
         Definition::Field(_) => Highlight::new(HlTag::Symbol(SymbolKind::Field)),
-        Definition::ModuleDef(def) => match def {
-            hir::ModuleDef::Module(module) => {
-                let mut h = Highlight::new(HlTag::Symbol(SymbolKind::Module));
-                if module.parent(db).is_none() {
-                    h |= HlMod::CrateRoot
-                }
-                h
+        Definition::Module(module) => {
+            let mut h = Highlight::new(HlTag::Symbol(SymbolKind::Module));
+            if module.parent(db).is_none() {
+                h |= HlMod::CrateRoot
             }
-            hir::ModuleDef::Function(func) => {
-                let mut h = Highlight::new(HlTag::Symbol(SymbolKind::Function));
-                if let Some(item) = func.as_assoc_item(db) {
-                    h |= HlMod::Associated;
-                    match func.self_param(db) {
-                        Some(sp) => match sp.access(db) {
-                            hir::Access::Exclusive => {
-                                h |= HlMod::Mutable;
-                                h |= HlMod::Reference;
-                            }
-                            hir::Access::Shared => h |= HlMod::Reference,
-                            hir::Access::Owned => h |= HlMod::Consuming,
-                        },
-                        None => h |= HlMod::Static,
-                    }
-
-                    match item.container(db) {
-                        hir::AssocItemContainer::Impl(i) => {
-                            if i.trait_(db).is_some() {
-                                h |= HlMod::Trait;
-                            }
+            h
+        }
+        Definition::Function(func) => {
+            let mut h = Highlight::new(HlTag::Symbol(SymbolKind::Function));
+            if let Some(item) = func.as_assoc_item(db) {
+                h |= HlMod::Associated;
+                match func.self_param(db) {
+                    Some(sp) => match sp.access(db) {
+                        hir::Access::Exclusive => {
+                            h |= HlMod::Mutable;
+                            h |= HlMod::Reference;
                         }
-                        hir::AssocItemContainer::Trait(_t) => {
+                        hir::Access::Shared => h |= HlMod::Reference,
+                        hir::Access::Owned => h |= HlMod::Consuming,
+                    },
+                    None => h |= HlMod::Static,
+                }
+
+                match item.container(db) {
+                    hir::AssocItemContainer::Impl(i) => {
+                        if i.trait_(db).is_some() {
                             h |= HlMod::Trait;
                         }
                     }
+                    hir::AssocItemContainer::Trait(_t) => {
+                        h |= HlMod::Trait;
+                    }
                 }
-
-                if func.is_unsafe(db) {
-                    h |= HlMod::Unsafe;
-                }
-                if func.is_async(db) {
-                    h |= HlMod::Async;
-                }
-
-                h
             }
-            hir::ModuleDef::Adt(adt) => {
-                let h = match adt {
-                    hir::Adt::Struct(_) => HlTag::Symbol(SymbolKind::Struct),
-                    hir::Adt::Enum(_) => HlTag::Symbol(SymbolKind::Enum),
-                    hir::Adt::Union(_) => HlTag::Symbol(SymbolKind::Union),
-                };
 
-                Highlight::new(h)
+            if func.is_unsafe(db) {
+                h |= HlMod::Unsafe;
             }
-            hir::ModuleDef::Variant(_) => Highlight::new(HlTag::Symbol(SymbolKind::Variant)),
-            hir::ModuleDef::Const(konst) => {
-                let mut h = Highlight::new(HlTag::Symbol(SymbolKind::Const));
-
-                if let Some(item) = konst.as_assoc_item(db) {
-                    h |= HlMod::Associated;
-                    match item.container(db) {
-                        hir::AssocItemContainer::Impl(i) => {
-                            if i.trait_(db).is_some() {
-                                h |= HlMod::Trait;
-                            }
-                        }
-                        hir::AssocItemContainer::Trait(_t) => {
+            if func.is_async(db) {
+                h |= HlMod::Async;
+            }
+
+            h
+        }
+        Definition::Adt(adt) => {
+            let h = match adt {
+                hir::Adt::Struct(_) => HlTag::Symbol(SymbolKind::Struct),
+                hir::Adt::Enum(_) => HlTag::Symbol(SymbolKind::Enum),
+                hir::Adt::Union(_) => HlTag::Symbol(SymbolKind::Union),
+            };
+
+            Highlight::new(h)
+        }
+        Definition::Variant(_) => Highlight::new(HlTag::Symbol(SymbolKind::Variant)),
+        Definition::Const(konst) => {
+            let mut h = Highlight::new(HlTag::Symbol(SymbolKind::Const));
+
+            if let Some(item) = konst.as_assoc_item(db) {
+                h |= HlMod::Associated;
+                match item.container(db) {
+                    hir::AssocItemContainer::Impl(i) => {
+                        if i.trait_(db).is_some() {
                             h |= HlMod::Trait;
                         }
                     }
+                    hir::AssocItemContainer::Trait(_t) => {
+                        h |= HlMod::Trait;
+                    }
                 }
-
-                h
             }
-            hir::ModuleDef::Trait(_) => Highlight::new(HlTag::Symbol(SymbolKind::Trait)),
-            hir::ModuleDef::TypeAlias(type_) => {
-                let mut h = Highlight::new(HlTag::Symbol(SymbolKind::TypeAlias));
-
-                if let Some(item) = type_.as_assoc_item(db) {
-                    h |= HlMod::Associated;
-                    match item.container(db) {
-                        hir::AssocItemContainer::Impl(i) => {
-                            if i.trait_(db).is_some() {
-                                h |= HlMod::Trait;
-                            }
-                        }
-                        hir::AssocItemContainer::Trait(_t) => {
+
+            h
+        }
+        Definition::Trait(_) => Highlight::new(HlTag::Symbol(SymbolKind::Trait)),
+        Definition::TypeAlias(type_) => {
+            let mut h = Highlight::new(HlTag::Symbol(SymbolKind::TypeAlias));
+
+            if let Some(item) = type_.as_assoc_item(db) {
+                h |= HlMod::Associated;
+                match item.container(db) {
+                    hir::AssocItemContainer::Impl(i) => {
+                        if i.trait_(db).is_some() {
                             h |= HlMod::Trait;
                         }
                     }
+                    hir::AssocItemContainer::Trait(_t) => {
+                        h |= HlMod::Trait;
+                    }
                 }
-
-                h
             }
-            hir::ModuleDef::BuiltinType(_) => Highlight::new(HlTag::BuiltinType),
-            hir::ModuleDef::Static(s) => {
-                let mut h = Highlight::new(HlTag::Symbol(SymbolKind::Static));
 
-                if s.is_mut(db) {
-                    h |= HlMod::Mutable;
-                    h |= HlMod::Unsafe;
-                }
+            h
+        }
+        Definition::BuiltinType(_) => Highlight::new(HlTag::BuiltinType),
+        Definition::Static(s) => {
+            let mut h = Highlight::new(HlTag::Symbol(SymbolKind::Static));
 
-                h
+            if s.is_mut(db) {
+                h |= HlMod::Mutable;
+                h |= HlMod::Unsafe;
             }
-        },
+
+            h
+        }
         Definition::SelfType(_) => Highlight::new(HlTag::Symbol(SymbolKind::Impl)),
         Definition::GenericParam(it) => match it {
             hir::GenericParam::TypeParam(_) => Highlight::new(HlTag::Symbol(SymbolKind::TypeParam)),
@@ -540,13 +536,13 @@ fn highlight_def(
 
     let famous_defs = FamousDefs(sema, krate);
     let def_crate = def.module(db).map(hir::Module::krate).or_else(|| match def {
-        Definition::ModuleDef(hir::ModuleDef::Module(module)) => Some(module.krate()),
+        Definition::Module(module) => Some(module.krate()),
         _ => None,
     });
     let is_from_other_crate = def_crate != krate;
     let is_from_builtin_crate =
         def_crate.map_or(false, |def_crate| famous_defs.builtin_crates().any(|it| def_crate == it));
-    let is_builtin_type = matches!(def, Definition::ModuleDef(hir::ModuleDef::BuiltinType(_)));
+    let is_builtin_type = matches!(def, Definition::BuiltinType(_));
     let is_public = def.visibility(db) == Some(hir::Visibility::Public);
 
     match (is_from_other_crate, is_builtin_type, is_public) {
diff --git a/crates/ide/src/syntax_highlighting/inject.rs b/crates/ide/src/syntax_highlighting/inject.rs
index 91587b11f53..b7a3fb62cb4 100644
--- a/crates/ide/src/syntax_highlighting/inject.rs
+++ b/crates/ide/src/syntax_highlighting/inject.rs
@@ -4,7 +4,9 @@ use std::mem;
 
 use either::Either;
 use hir::{InFile, Semantics};
-use ide_db::{call_info::ActiveParameter, helpers::rust_doc::is_rust_fence, SymbolKind};
+use ide_db::{
+    call_info::ActiveParameter, defs::Definition, helpers::rust_doc::is_rust_fence, SymbolKind,
+};
 use syntax::{
     ast::{self, AstNode, IsString},
     AstToken, NodeOrToken, SyntaxNode, SyntaxToken, TextRange, TextSize,
@@ -237,22 +239,29 @@ fn find_doc_string_in_attr(attr: &hir::Attr, it: &ast::Attr) -> Option<ast::Stri
     }
 }
 
-fn module_def_to_hl_tag(def: Either<hir::ModuleDef, hir::MacroDef>) -> HlTag {
+fn module_def_to_hl_tag(def: Definition) -> HlTag {
     let symbol = match def {
-        Either::Left(def) => match def {
-            hir::ModuleDef::Module(_) => SymbolKind::Module,
-            hir::ModuleDef::Function(_) => SymbolKind::Function,
-            hir::ModuleDef::Adt(hir::Adt::Struct(_)) => SymbolKind::Struct,
-            hir::ModuleDef::Adt(hir::Adt::Enum(_)) => SymbolKind::Enum,
-            hir::ModuleDef::Adt(hir::Adt::Union(_)) => SymbolKind::Union,
-            hir::ModuleDef::Variant(_) => SymbolKind::Variant,
-            hir::ModuleDef::Const(_) => SymbolKind::Const,
-            hir::ModuleDef::Static(_) => SymbolKind::Static,
-            hir::ModuleDef::Trait(_) => SymbolKind::Trait,
-            hir::ModuleDef::TypeAlias(_) => SymbolKind::TypeAlias,
-            hir::ModuleDef::BuiltinType(_) => return HlTag::BuiltinType,
+        Definition::Module(_) => SymbolKind::Module,
+        Definition::Function(_) => SymbolKind::Function,
+        Definition::Adt(hir::Adt::Struct(_)) => SymbolKind::Struct,
+        Definition::Adt(hir::Adt::Enum(_)) => SymbolKind::Enum,
+        Definition::Adt(hir::Adt::Union(_)) => SymbolKind::Union,
+        Definition::Variant(_) => SymbolKind::Variant,
+        Definition::Const(_) => SymbolKind::Const,
+        Definition::Static(_) => SymbolKind::Static,
+        Definition::Trait(_) => SymbolKind::Trait,
+        Definition::TypeAlias(_) => SymbolKind::TypeAlias,
+        Definition::BuiltinType(_) => return HlTag::BuiltinType,
+        Definition::Macro(_) => SymbolKind::Macro,
+        Definition::Field(_) => SymbolKind::Field,
+        Definition::SelfType(_) => SymbolKind::Impl,
+        Definition::Local(_) => SymbolKind::Local,
+        Definition::GenericParam(gp) => match gp {
+            hir::GenericParam::TypeParam(_) => SymbolKind::TypeParam,
+            hir::GenericParam::LifetimeParam(_) => SymbolKind::LifetimeParam,
+            hir::GenericParam::ConstParam(_) => SymbolKind::ConstParam,
         },
-        Either::Right(_) => SymbolKind::Macro,
+        Definition::Label(_) => SymbolKind::Label,
     };
     HlTag::Symbol(symbol)
 }
diff --git a/crates/ide_assists/src/handlers/add_turbo_fish.rs b/crates/ide_assists/src/handlers/add_turbo_fish.rs
index d08111a90da..64f9eb9586a 100644
--- a/crates/ide_assists/src/handlers/add_turbo_fish.rs
+++ b/crates/ide_assists/src/handlers/add_turbo_fish.rs
@@ -44,7 +44,7 @@ pub(crate) fn add_turbo_fish(acc: &mut Assists, ctx: &AssistContext) -> Option<(
         NameRefClass::FieldShorthand { .. } => return None,
     };
     let fun = match def {
-        Definition::ModuleDef(hir::ModuleDef::Function(it)) => it,
+        Definition::Function(it) => it,
         _ => return None,
     };
     let generics = hir::GenericDef::Function(fun).params(ctx.sema.db);
diff --git a/crates/ide_assists/src/handlers/convert_tuple_struct_to_named_struct.rs b/crates/ide_assists/src/handlers/convert_tuple_struct_to_named_struct.rs
index 9ff4ab90c8f..8093ba2560c 100644
--- a/crates/ide_assists/src/handlers/convert_tuple_struct_to_named_struct.rs
+++ b/crates/ide_assists/src/handlers/convert_tuple_struct_to_named_struct.rs
@@ -127,8 +127,8 @@ fn edit_struct_references(
     names: &[ast::Name],
 ) {
     let strukt_def = match strukt {
-        Either::Left(s) => Definition::ModuleDef(hir::ModuleDef::Adt(hir::Adt::Struct(s))),
-        Either::Right(v) => Definition::ModuleDef(hir::ModuleDef::Variant(v)),
+        Either::Left(s) => Definition::Adt(hir::Adt::Struct(s)),
+        Either::Right(v) => Definition::Variant(v),
     };
     let usages = strukt_def.usages(&ctx.sema).include_self_refs().all();
 
diff --git a/crates/ide_assists/src/handlers/expand_glob_import.rs b/crates/ide_assists/src/handlers/expand_glob_import.rs
index 3abf06d5887..72c17b674c4 100644
--- a/crates/ide_assists/src/handlers/expand_glob_import.rs
+++ b/crates/ide_assists/src/handlers/expand_glob_import.rs
@@ -1,5 +1,5 @@
 use either::Either;
-use hir::{AssocItem, HasVisibility, MacroDef, Module, ModuleDef, Name, PathResolution, ScopeDef};
+use hir::{AssocItem, HasVisibility, Module, ModuleDef, Name, PathResolution, ScopeDef};
 use ide_db::{
     defs::{Definition, NameRefClass},
     search::SearchScope,
@@ -112,36 +112,27 @@ fn find_parent_and_path(
     }
 }
 
-#[derive(Debug, PartialEq, Clone)]
-enum Def {
-    ModuleDef(ModuleDef),
-    MacroDef(MacroDef),
-}
-
-impl Def {
-    fn is_referenced_in(&self, ctx: &AssistContext) -> bool {
-        let def = match self {
-            Def::ModuleDef(def) => Definition::ModuleDef(*def),
-            Def::MacroDef(def) => Definition::Macro(*def),
-        };
-
-        let search_scope = SearchScope::single_file(ctx.file_id());
-        def.usages(&ctx.sema).in_scope(search_scope).at_least_one()
-    }
+fn def_is_referenced_in(def: Definition, ctx: &AssistContext) -> bool {
+    let search_scope = SearchScope::single_file(ctx.file_id());
+    def.usages(&ctx.sema).in_scope(search_scope).at_least_one()
 }
 
 #[derive(Debug, Clone)]
 struct Ref {
     // could be alias
     visible_name: Name,
-    def: Def,
+    def: Definition,
 }
 
 impl Ref {
     fn from_scope_def(name: Name, scope_def: ScopeDef) -> Option<Self> {
         match scope_def {
-            ScopeDef::ModuleDef(def) => Some(Ref { visible_name: name, def: Def::ModuleDef(def) }),
-            ScopeDef::MacroDef(def) => Some(Ref { visible_name: name, def: Def::MacroDef(def) }),
+            ScopeDef::ModuleDef(def) => {
+                Some(Ref { visible_name: name, def: Definition::from(def) })
+            }
+            ScopeDef::MacroDef(def) => {
+                Some(Ref { visible_name: name, def: Definition::Macro(def) })
+            }
             _ => None,
         }
     }
@@ -157,10 +148,10 @@ impl Refs {
                 .clone()
                 .into_iter()
                 .filter(|r| {
-                    if let Def::ModuleDef(ModuleDef::Trait(tr)) = r.def {
+                    if let Definition::Trait(tr) = r.def {
                         if tr.items(ctx.db()).into_iter().any(|ai| {
                             if let AssocItem::Function(f) = ai {
-                                Def::ModuleDef(ModuleDef::Function(f)).is_referenced_in(ctx)
+                                def_is_referenced_in(Definition::Function(f), ctx)
                             } else {
                                 false
                             }
@@ -169,13 +160,13 @@ impl Refs {
                         }
                     }
 
-                    r.def.is_referenced_in(ctx)
+                    def_is_referenced_in(r.def, ctx)
                 })
                 .collect(),
         )
     }
 
-    fn filter_out_by_defs(&self, defs: Vec<Def>) -> Refs {
+    fn filter_out_by_defs(&self, defs: Vec<Definition>) -> Refs {
         Refs(self.0.clone().into_iter().filter(|r| !defs.contains(&r.def)).collect())
     }
 }
@@ -220,7 +211,7 @@ fn is_mod_visible_from(ctx: &AssistContext, module: Module, from: Module) -> boo
 // use foo::*$0;
 // use baz::Baz;
 // ↑ ---------------
-fn find_imported_defs(ctx: &AssistContext, star: SyntaxToken) -> Option<Vec<Def>> {
+fn find_imported_defs(ctx: &AssistContext, star: SyntaxToken) -> Option<Vec<Definition>> {
     let parent_use_item_syntax =
         star.ancestors().find_map(|n| if ast::Use::can_cast(n.kind()) { Some(n) } else { None })?;
 
@@ -234,8 +225,19 @@ fn find_imported_defs(ctx: &AssistContext, star: SyntaxToken) -> Option<Vec<Def>
             })
             .flat_map(|n| n.descendants().filter_map(ast::NameRef::cast))
             .filter_map(|r| match NameRefClass::classify(&ctx.sema, &r)? {
-                NameRefClass::Definition(Definition::ModuleDef(def)) => Some(Def::ModuleDef(def)),
-                NameRefClass::Definition(Definition::Macro(def)) => Some(Def::MacroDef(def)),
+                NameRefClass::Definition(
+                    def
+                    @
+                    (Definition::Macro(_)
+                    | Definition::Module(_)
+                    | Definition::Function(_)
+                    | Definition::Adt(_)
+                    | Definition::Variant(_)
+                    | Definition::Const(_)
+                    | Definition::Static(_)
+                    | Definition::Trait(_)
+                    | Definition::TypeAlias(_)),
+                ) => Some(def),
                 _ => None,
             })
             .collect(),
@@ -245,7 +247,7 @@ fn find_imported_defs(ctx: &AssistContext, star: SyntaxToken) -> Option<Vec<Def>
 fn find_names_to_import(
     ctx: &AssistContext,
     refs_in_target: Refs,
-    imported_defs: Vec<Def>,
+    imported_defs: Vec<Definition>,
 ) -> Vec<Name> {
     let used_refs = refs_in_target.used_refs(ctx).filter_out_by_defs(imported_defs);
     used_refs.0.iter().map(|r| r.visible_name.clone()).collect()
diff --git a/crates/ide_assists/src/handlers/extract_module.rs b/crates/ide_assists/src/handlers/extract_module.rs
index dc0683866c2..80fc7946ce3 100644
--- a/crates/ide_assists/src/handlers/extract_module.rs
+++ b/crates/ide_assists/src/handlers/extract_module.rs
@@ -1,6 +1,6 @@
 use std::collections::{HashMap, HashSet};
 
-use hir::{HasSource, ModuleDef, ModuleSource};
+use hir::{HasSource, ModuleSource};
 use ide_db::{
     assists::{AssistId, AssistKind},
     base_db::FileId,
@@ -184,7 +184,7 @@ impl Module {
                 match (item.syntax()) {
                     ast::Adt(it) => {
                         if let Some( nod ) = ctx.sema.to_def(&it) {
-                            let node_def = Definition::ModuleDef(nod.into());
+                            let node_def = Definition::Adt(nod.into());
                             self.expand_and_group_usages_file_wise(ctx, node_def, &mut refs);
 
                             //Enum Fields are not allowed to explicitly specify pub, it is implied
@@ -218,25 +218,25 @@ impl Module {
                     },
                     ast::TypeAlias(it) => {
                         if let Some( nod ) = ctx.sema.to_def(&it) {
-                            let node_def = Definition::ModuleDef(nod.into());
+                            let node_def = Definition::TypeAlias(nod.into());
                             self.expand_and_group_usages_file_wise(ctx, node_def, &mut refs);
                         }
                     },
                     ast::Const(it) => {
                         if let Some( nod ) = ctx.sema.to_def(&it) {
-                            let node_def = Definition::ModuleDef(nod.into());
+                            let node_def = Definition::Const(nod.into());
                             self.expand_and_group_usages_file_wise(ctx, node_def, &mut refs);
                         }
                     },
                     ast::Static(it) => {
                         if let Some( nod ) = ctx.sema.to_def(&it) {
-                            let node_def = Definition::ModuleDef(nod.into());
+                            let node_def = Definition::Static(nod.into());
                             self.expand_and_group_usages_file_wise(ctx, node_def, &mut refs);
                         }
                     },
                     ast::Fn(it) => {
                         if let Some( nod ) = ctx.sema.to_def(&it) {
-                            let node_def = Definition::ModuleDef(nod.into());
+                            let node_def = Definition::Function(nod.into());
                             self.expand_and_group_usages_file_wise(ctx, node_def, &mut refs);
                         }
                     },
@@ -603,161 +603,151 @@ fn does_source_exists_outside_sel_in_same_mod(
 ) -> bool {
     let mut source_exists_outside_sel_in_same_mod = false;
     match def {
-        Definition::ModuleDef(it) => match it {
-            ModuleDef::Module(x) => {
-                let source = x.definition_source(ctx.db());
-                let have_same_parent;
-                if let Some(ast_module) = &curr_parent_module {
-                    if let Some(hir_module) = x.parent(ctx.db()) {
-                        have_same_parent =
-                            compare_hir_and_ast_module(&ast_module, hir_module, ctx).is_some();
-                    } else {
-                        let source_file_id = source.file_id.original_file(ctx.db());
-                        have_same_parent = source_file_id == curr_file_id;
-                    }
+        Definition::Module(x) => {
+            let source = x.definition_source(ctx.db());
+            let have_same_parent;
+            if let Some(ast_module) = &curr_parent_module {
+                if let Some(hir_module) = x.parent(ctx.db()) {
+                    have_same_parent =
+                        compare_hir_and_ast_module(&ast_module, hir_module, ctx).is_some();
                 } else {
                     let source_file_id = source.file_id.original_file(ctx.db());
                     have_same_parent = source_file_id == curr_file_id;
                 }
+            } else {
+                let source_file_id = source.file_id.original_file(ctx.db());
+                have_same_parent = source_file_id == curr_file_id;
+            }
 
-                if have_same_parent {
-                    match source.value {
-                        ModuleSource::Module(module_) => {
-                            source_exists_outside_sel_in_same_mod =
-                                !selection_range.contains_range(module_.syntax().text_range());
-                        }
-                        _ => {}
+            if have_same_parent {
+                match source.value {
+                    ModuleSource::Module(module_) => {
+                        source_exists_outside_sel_in_same_mod =
+                            !selection_range.contains_range(module_.syntax().text_range());
                     }
+                    _ => {}
                 }
             }
-            ModuleDef::Function(x) => {
-                if let Some(source) = x.source(ctx.db()) {
-                    let have_same_parent;
-                    if let Some(ast_module) = &curr_parent_module {
-                        have_same_parent =
-                            compare_hir_and_ast_module(&ast_module, x.module(ctx.db()), ctx)
-                                .is_some();
-                    } else {
-                        let source_file_id = source.file_id.original_file(ctx.db());
-                        have_same_parent = source_file_id == curr_file_id;
-                    }
+        }
+        Definition::Function(x) => {
+            if let Some(source) = x.source(ctx.db()) {
+                let have_same_parent;
+                if let Some(ast_module) = &curr_parent_module {
+                    have_same_parent =
+                        compare_hir_and_ast_module(&ast_module, x.module(ctx.db()), ctx).is_some();
+                } else {
+                    let source_file_id = source.file_id.original_file(ctx.db());
+                    have_same_parent = source_file_id == curr_file_id;
+                }
 
-                    if have_same_parent {
-                        source_exists_outside_sel_in_same_mod =
-                            !selection_range.contains_range(source.value.syntax().text_range());
-                    }
+                if have_same_parent {
+                    source_exists_outside_sel_in_same_mod =
+                        !selection_range.contains_range(source.value.syntax().text_range());
                 }
             }
-            ModuleDef::Adt(x) => {
-                if let Some(source) = x.source(ctx.db()) {
-                    let have_same_parent;
-                    if let Some(ast_module) = &curr_parent_module {
-                        have_same_parent =
-                            compare_hir_and_ast_module(&ast_module, x.module(ctx.db()), ctx)
-                                .is_some();
-                    } else {
-                        let source_file_id = source.file_id.original_file(ctx.db());
-                        have_same_parent = source_file_id == curr_file_id;
-                    }
+        }
+        Definition::Adt(x) => {
+            if let Some(source) = x.source(ctx.db()) {
+                let have_same_parent;
+                if let Some(ast_module) = &curr_parent_module {
+                    have_same_parent =
+                        compare_hir_and_ast_module(&ast_module, x.module(ctx.db()), ctx).is_some();
+                } else {
+                    let source_file_id = source.file_id.original_file(ctx.db());
+                    have_same_parent = source_file_id == curr_file_id;
+                }
 
-                    if have_same_parent {
-                        source_exists_outside_sel_in_same_mod =
-                            !selection_range.contains_range(source.value.syntax().text_range());
-                    }
+                if have_same_parent {
+                    source_exists_outside_sel_in_same_mod =
+                        !selection_range.contains_range(source.value.syntax().text_range());
                 }
             }
-            ModuleDef::Variant(x) => {
-                if let Some(source) = x.source(ctx.db()) {
-                    let have_same_parent;
-                    if let Some(ast_module) = &curr_parent_module {
-                        have_same_parent =
-                            compare_hir_and_ast_module(&ast_module, x.module(ctx.db()), ctx)
-                                .is_some();
-                    } else {
-                        let source_file_id = source.file_id.original_file(ctx.db());
-                        have_same_parent = source_file_id == curr_file_id;
-                    }
+        }
+        Definition::Variant(x) => {
+            if let Some(source) = x.source(ctx.db()) {
+                let have_same_parent;
+                if let Some(ast_module) = &curr_parent_module {
+                    have_same_parent =
+                        compare_hir_and_ast_module(&ast_module, x.module(ctx.db()), ctx).is_some();
+                } else {
+                    let source_file_id = source.file_id.original_file(ctx.db());
+                    have_same_parent = source_file_id == curr_file_id;
+                }
 
-                    if have_same_parent {
-                        source_exists_outside_sel_in_same_mod =
-                            !selection_range.contains_range(source.value.syntax().text_range());
-                    }
+                if have_same_parent {
+                    source_exists_outside_sel_in_same_mod =
+                        !selection_range.contains_range(source.value.syntax().text_range());
                 }
             }
-            ModuleDef::Const(x) => {
-                if let Some(source) = x.source(ctx.db()) {
-                    let have_same_parent;
-                    if let Some(ast_module) = &curr_parent_module {
-                        have_same_parent =
-                            compare_hir_and_ast_module(&ast_module, x.module(ctx.db()), ctx)
-                                .is_some();
-                    } else {
-                        let source_file_id = source.file_id.original_file(ctx.db());
-                        have_same_parent = source_file_id == curr_file_id;
-                    }
+        }
+        Definition::Const(x) => {
+            if let Some(source) = x.source(ctx.db()) {
+                let have_same_parent;
+                if let Some(ast_module) = &curr_parent_module {
+                    have_same_parent =
+                        compare_hir_and_ast_module(&ast_module, x.module(ctx.db()), ctx).is_some();
+                } else {
+                    let source_file_id = source.file_id.original_file(ctx.db());
+                    have_same_parent = source_file_id == curr_file_id;
+                }
 
-                    if have_same_parent {
-                        source_exists_outside_sel_in_same_mod =
-                            !selection_range.contains_range(source.value.syntax().text_range());
-                    }
+                if have_same_parent {
+                    source_exists_outside_sel_in_same_mod =
+                        !selection_range.contains_range(source.value.syntax().text_range());
                 }
             }
-            ModuleDef::Static(x) => {
-                if let Some(source) = x.source(ctx.db()) {
-                    let have_same_parent;
-                    if let Some(ast_module) = &curr_parent_module {
-                        have_same_parent =
-                            compare_hir_and_ast_module(&ast_module, x.module(ctx.db()), ctx)
-                                .is_some();
-                    } else {
-                        let source_file_id = source.file_id.original_file(ctx.db());
-                        have_same_parent = source_file_id == curr_file_id;
-                    }
+        }
+        Definition::Static(x) => {
+            if let Some(source) = x.source(ctx.db()) {
+                let have_same_parent;
+                if let Some(ast_module) = &curr_parent_module {
+                    have_same_parent =
+                        compare_hir_and_ast_module(&ast_module, x.module(ctx.db()), ctx).is_some();
+                } else {
+                    let source_file_id = source.file_id.original_file(ctx.db());
+                    have_same_parent = source_file_id == curr_file_id;
+                }
 
-                    if have_same_parent {
-                        source_exists_outside_sel_in_same_mod =
-                            !selection_range.contains_range(source.value.syntax().text_range());
-                    }
+                if have_same_parent {
+                    source_exists_outside_sel_in_same_mod =
+                        !selection_range.contains_range(source.value.syntax().text_range());
                 }
             }
-            ModuleDef::Trait(x) => {
-                if let Some(source) = x.source(ctx.db()) {
-                    let have_same_parent;
-                    if let Some(ast_module) = &curr_parent_module {
-                        have_same_parent =
-                            compare_hir_and_ast_module(&ast_module, x.module(ctx.db()), ctx)
-                                .is_some();
-                    } else {
-                        let source_file_id = source.file_id.original_file(ctx.db());
-                        have_same_parent = source_file_id == curr_file_id;
-                    }
+        }
+        Definition::Trait(x) => {
+            if let Some(source) = x.source(ctx.db()) {
+                let have_same_parent;
+                if let Some(ast_module) = &curr_parent_module {
+                    have_same_parent =
+                        compare_hir_and_ast_module(&ast_module, x.module(ctx.db()), ctx).is_some();
+                } else {
+                    let source_file_id = source.file_id.original_file(ctx.db());
+                    have_same_parent = source_file_id == curr_file_id;
+                }
 
-                    if have_same_parent {
-                        source_exists_outside_sel_in_same_mod =
-                            !selection_range.contains_range(source.value.syntax().text_range());
-                    }
+                if have_same_parent {
+                    source_exists_outside_sel_in_same_mod =
+                        !selection_range.contains_range(source.value.syntax().text_range());
                 }
             }
-            ModuleDef::TypeAlias(x) => {
-                if let Some(source) = x.source(ctx.db()) {
-                    let have_same_parent;
-                    if let Some(ast_module) = &curr_parent_module {
-                        have_same_parent =
-                            compare_hir_and_ast_module(&ast_module, x.module(ctx.db()), ctx)
-                                .is_some();
-                    } else {
-                        let source_file_id = source.file_id.original_file(ctx.db());
-                        have_same_parent = source_file_id == curr_file_id;
-                    }
+        }
+        Definition::TypeAlias(x) => {
+            if let Some(source) = x.source(ctx.db()) {
+                let have_same_parent;
+                if let Some(ast_module) = &curr_parent_module {
+                    have_same_parent =
+                        compare_hir_and_ast_module(&ast_module, x.module(ctx.db()), ctx).is_some();
+                } else {
+                    let source_file_id = source.file_id.original_file(ctx.db());
+                    have_same_parent = source_file_id == curr_file_id;
+                }
 
-                    if have_same_parent {
-                        source_exists_outside_sel_in_same_mod =
-                            !selection_range.contains_range(source.value.syntax().text_range());
-                    }
+                if have_same_parent {
+                    source_exists_outside_sel_in_same_mod =
+                        !selection_range.contains_range(source.value.syntax().text_range());
                 }
             }
-            _ => {}
-        },
+        }
         _ => {}
     }
 
diff --git a/crates/ide_assists/src/handlers/extract_struct_from_enum_variant.rs b/crates/ide_assists/src/handlers/extract_struct_from_enum_variant.rs
index 8e28f0443d6..82e0970cc4b 100644
--- a/crates/ide_assists/src/handlers/extract_struct_from_enum_variant.rs
+++ b/crates/ide_assists/src/handlers/extract_struct_from_enum_variant.rs
@@ -63,8 +63,7 @@ pub(crate) fn extract_struct_from_enum_variant(
         |builder| {
             let variant_hir_name = variant_hir.name(ctx.db());
             let enum_module_def = ModuleDef::from(enum_hir);
-            let usages =
-                Definition::ModuleDef(ModuleDef::Variant(variant_hir)).usages(&ctx.sema).all();
+            let usages = Definition::Variant(variant_hir).usages(&ctx.sema).all();
 
             let mut visited_modules_set = FxHashSet::default();
             let current_module = enum_hir.module(ctx.db());
diff --git a/crates/ide_assists/src/handlers/fix_visibility.rs b/crates/ide_assists/src/handlers/fix_visibility.rs
index 80da4a35ad8..0b743307486 100644
--- a/crates/ide_assists/src/handlers/fix_visibility.rs
+++ b/crates/ide_assists/src/handlers/fix_visibility.rs
@@ -181,7 +181,7 @@ fn target_data_for_def(
             offset_target_and_file_id(db, c)?
         }
         hir::ModuleDef::Static(s) => {
-            target_name = s.name(db);
+            target_name = Some(s.name(db));
             offset_target_and_file_id(db, s)?
         }
         hir::ModuleDef::Trait(t) => {
diff --git a/crates/ide_assists/src/handlers/generate_function.rs b/crates/ide_assists/src/handlers/generate_function.rs
index edc4697f2ca..db3379abf4c 100644
--- a/crates/ide_assists/src/handlers/generate_function.rs
+++ b/crates/ide_assists/src/handlers/generate_function.rs
@@ -1,6 +1,6 @@
 use rustc_hash::{FxHashMap, FxHashSet};
 
-use hir::{HasSource, HirDisplay, Module, ModuleDef, Semantics, TypeInfo};
+use hir::{HasSource, HirDisplay, Module, Semantics, TypeInfo};
 use ide_db::helpers::FamousDefs;
 use ide_db::{
     base_db::FileId,
@@ -482,9 +482,8 @@ fn fn_arg_name(sema: &Semantics<RootDatabase>, arg_expr: &ast::Expr) -> String {
         ast::Expr::CastExpr(cast_expr) => Some(fn_arg_name(sema, &cast_expr.expr()?)),
         expr => {
             let name_ref = expr.syntax().descendants().filter_map(ast::NameRef::cast).last()?;
-            if let Some(NameRefClass::Definition(Definition::ModuleDef(
-                ModuleDef::Const(_) | ModuleDef::Static(_),
-            ))) = NameRefClass::classify(sema, &name_ref)
+            if let Some(NameRefClass::Definition(Definition::Const(_) | Definition::Static(_))) =
+                NameRefClass::classify(sema, &name_ref)
             {
                 return Some(name_ref.to_string().to_lowercase());
             };
diff --git a/crates/ide_assists/src/handlers/inline_call.rs b/crates/ide_assists/src/handlers/inline_call.rs
index ae7707667e0..cd4f0464116 100644
--- a/crates/ide_assists/src/handlers/inline_call.rs
+++ b/crates/ide_assists/src/handlers/inline_call.rs
@@ -69,7 +69,7 @@ pub(crate) fn inline_into_callers(acc: &mut Assists, ctx: &AssistContext) -> Opt
 
     let params = get_fn_params(ctx.sema.db, function, &param_list)?;
 
-    let usages = Definition::ModuleDef(hir::ModuleDef::Function(function)).usages(&ctx.sema);
+    let usages = Definition::Function(function).usages(&ctx.sema);
     if !usages.at_least_one() {
         return None;
     }
diff --git a/crates/ide_assists/src/handlers/remove_unused_param.rs b/crates/ide_assists/src/handlers/remove_unused_param.rs
index 5210166738a..80e2ca918b9 100644
--- a/crates/ide_assists/src/handlers/remove_unused_param.rs
+++ b/crates/ide_assists/src/handlers/remove_unused_param.rs
@@ -62,7 +62,7 @@ pub(crate) fn remove_unused_param(acc: &mut Assists, ctx: &AssistContext) -> Opt
     }
     let fn_def = {
         let func = ctx.sema.to_def(&func)?;
-        Definition::ModuleDef(func.into())
+        Definition::Function(func)
     };
 
     let param_def = {
diff --git a/crates/ide_db/src/defs.rs b/crates/ide_db/src/defs.rs
index e4874c7c482..5fdbb600814 100644
--- a/crates/ide_db/src/defs.rs
+++ b/crates/ide_db/src/defs.rs
@@ -7,9 +7,11 @@
 
 use arrayvec::ArrayVec;
 use hir::{
-    Field, GenericParam, HasVisibility, Impl, Label, Local, MacroDef, Module, ModuleDef, Name,
-    PathResolution, Semantics, Visibility,
+    Adt, AsAssocItem, AssocItem, BuiltinType, Const, Field, Function, GenericParam, HasVisibility,
+    Impl, ItemInNs, Label, Local, MacroDef, Module, ModuleDef, Name, PathResolution, Semantics,
+    Static, Trait, TypeAlias, Variant, Visibility,
 };
+use stdx::impl_from;
 use syntax::{
     ast::{self, AstNode},
     match_ast, AstToken, SyntaxKind, SyntaxNode, SyntaxToken,
@@ -22,7 +24,15 @@ use crate::{helpers::try_resolve_derive_input, RootDatabase};
 pub enum Definition {
     Macro(MacroDef),
     Field(Field),
-    ModuleDef(ModuleDef),
+    Module(Module),
+    Function(Function),
+    Adt(Adt),
+    Variant(Variant),
+    Const(Const),
+    Static(Static),
+    Trait(Trait),
+    TypeAlias(TypeAlias),
+    BuiltinType(BuiltinType),
     SelfType(Impl),
     Local(Local),
     GenericParam(GenericParam),
@@ -98,49 +108,65 @@ impl Definition {
         res
     }
 
+    pub fn canonical_module_path(&self, db: &RootDatabase) -> Option<impl Iterator<Item = Module>> {
+        self.module(db).map(|it| it.path_to_root(db).into_iter().rev())
+    }
+
     pub fn module(&self, db: &RootDatabase) -> Option<Module> {
-        match self {
-            Definition::Macro(it) => it.module(db),
-            Definition::Field(it) => Some(it.parent_def(db).module(db)),
-            Definition::ModuleDef(it) => it.module(db),
-            Definition::SelfType(it) => Some(it.module(db)),
-            Definition::Local(it) => Some(it.module(db)),
-            Definition::GenericParam(it) => Some(it.module(db)),
-            Definition::Label(it) => Some(it.module(db)),
-        }
+        let module = match self {
+            Definition::Macro(it) => it.module(db)?,
+            Definition::Module(it) => it.parent(db)?,
+            Definition::Field(it) => it.parent_def(db).module(db),
+            Definition::Function(it) => it.module(db),
+            Definition::Adt(it) => it.module(db),
+            Definition::Const(it) => it.module(db),
+            Definition::Static(it) => it.module(db),
+            Definition::Trait(it) => it.module(db),
+            Definition::TypeAlias(it) => it.module(db),
+            Definition::Variant(it) => it.module(db),
+            Definition::SelfType(it) => it.module(db),
+            Definition::Local(it) => it.module(db),
+            Definition::GenericParam(it) => it.module(db),
+            Definition::Label(it) => it.module(db),
+            Definition::BuiltinType(_) => return None,
+        };
+        Some(module)
     }
 
     pub fn visibility(&self, db: &RootDatabase) -> Option<Visibility> {
-        match self {
-            Definition::Field(sf) => Some(sf.visibility(db)),
-            Definition::ModuleDef(def) => Some(def.visibility(db)),
-            Definition::Macro(_)
-            | Definition::SelfType(_)
+        let vis = match self {
+            Definition::Field(sf) => sf.visibility(db),
+            Definition::Module(it) => it.visibility(db),
+            Definition::Function(it) => it.visibility(db),
+            Definition::Adt(it) => it.visibility(db),
+            Definition::Const(it) => it.visibility(db),
+            Definition::Static(it) => it.visibility(db),
+            Definition::Trait(it) => it.visibility(db),
+            Definition::TypeAlias(it) => it.visibility(db),
+            Definition::Variant(it) => it.visibility(db),
+            Definition::BuiltinType(_) => Visibility::Public,
+            Definition::Macro(_) => return None,
+            Definition::SelfType(_)
             | Definition::Local(_)
             | Definition::GenericParam(_)
-            | Definition::Label(_) => None,
-        }
+            | Definition::Label(_) => return None,
+        };
+        Some(vis)
     }
 
     pub fn name(&self, db: &RootDatabase) -> Option<Name> {
         let name = match self {
             Definition::Macro(it) => it.name(db)?,
             Definition::Field(it) => it.name(db),
-            Definition::ModuleDef(def) => match def {
-                hir::ModuleDef::Module(it) => it.name(db)?,
-                hir::ModuleDef::Function(it) => it.name(db),
-                hir::ModuleDef::Adt(def) => match def {
-                    hir::Adt::Struct(it) => it.name(db),
-                    hir::Adt::Union(it) => it.name(db),
-                    hir::Adt::Enum(it) => it.name(db),
-                },
-                hir::ModuleDef::Variant(it) => it.name(db),
-                hir::ModuleDef::Const(it) => it.name(db)?,
-                hir::ModuleDef::Static(it) => it.name(db)?,
-                hir::ModuleDef::Trait(it) => it.name(db),
-                hir::ModuleDef::TypeAlias(it) => it.name(db),
-                hir::ModuleDef::BuiltinType(it) => it.name(),
-            },
+            Definition::Module(it) => it.name(db)?,
+            Definition::Function(it) => it.name(db),
+            Definition::Adt(it) => it.name(db),
+            Definition::Variant(it) => it.name(db),
+            Definition::Const(it) => it.name(db)?,
+            Definition::Static(it) => it.name(db),
+            Definition::Trait(it) => it.name(db),
+            Definition::TypeAlias(it) => it.name(db),
+            Definition::BuiltinType(it) => it.name(),
             Definition::SelfType(_) => return None,
             Definition::Local(it) => it.name(db)?,
             Definition::GenericParam(it) => it.name(db),
@@ -193,7 +219,7 @@ impl NameClass {
 
         if let Some(bind_pat) = ast::IdentPat::cast(parent.clone()) {
             if let Some(def) = sema.resolve_bind_pat_to_const(&bind_pat) {
-                return Some(NameClass::ConstReference(Definition::ModuleDef(def)));
+                return Some(NameClass::ConstReference(Definition::from(def)));
             }
         }
 
@@ -231,7 +257,7 @@ impl NameClass {
                         let extern_crate = it.syntax().parent().and_then(ast::ExternCrate::cast)?;
                         let krate = sema.resolve_extern_crate(&extern_crate)?;
                         let root_module = krate.root_module(sema.db);
-                        Some(NameClass::Definition(Definition::ModuleDef(root_module.into())))
+                        Some(NameClass::Definition(Definition::Module(root_module)))
                     }
                 },
                 ast::IdentPat(it) => {
@@ -257,43 +283,43 @@ impl NameClass {
                 },
                 ast::Module(it) => {
                     let def = sema.to_def(&it)?;
-                    Some(NameClass::Definition(Definition::ModuleDef(def.into())))
+                    Some(NameClass::Definition(Definition::Module(def)))
                 },
                 ast::Struct(it) => {
                     let def: hir::Struct = sema.to_def(&it)?;
-                    Some(NameClass::Definition(Definition::ModuleDef(def.into())))
+                    Some(NameClass::Definition(Definition::Adt(def.into())))
                 },
                 ast::Union(it) => {
                     let def: hir::Union = sema.to_def(&it)?;
-                    Some(NameClass::Definition(Definition::ModuleDef(def.into())))
+                    Some(NameClass::Definition(Definition::Adt(def.into())))
                 },
                 ast::Enum(it) => {
                     let def: hir::Enum = sema.to_def(&it)?;
-                    Some(NameClass::Definition(Definition::ModuleDef(def.into())))
+                    Some(NameClass::Definition(Definition::Adt(def.into())))
                 },
                 ast::Trait(it) => {
                     let def: hir::Trait = sema.to_def(&it)?;
-                    Some(NameClass::Definition(Definition::ModuleDef(def.into())))
+                    Some(NameClass::Definition(Definition::Trait(def)))
                 },
                 ast::Static(it) => {
                     let def: hir::Static = sema.to_def(&it)?;
-                    Some(NameClass::Definition(Definition::ModuleDef(def.into())))
+                    Some(NameClass::Definition(Definition::Static(def)))
                 },
                 ast::Variant(it) => {
                     let def: hir::Variant = sema.to_def(&it)?;
-                    Some(NameClass::Definition(Definition::ModuleDef(def.into())))
+                    Some(NameClass::Definition(Definition::Variant(def)))
                 },
                 ast::Fn(it) => {
                     let def: hir::Function = sema.to_def(&it)?;
-                    Some(NameClass::Definition(Definition::ModuleDef(def.into())))
+                    Some(NameClass::Definition(Definition::Function(def)))
                 },
                 ast::Const(it) => {
                     let def: hir::Const = sema.to_def(&it)?;
-                    Some(NameClass::Definition(Definition::ModuleDef(def.into())))
+                    Some(NameClass::Definition(Definition::Const(def)))
                 },
                 ast::TypeAlias(it) => {
                     let def: hir::TypeAlias = sema.to_def(&it)?;
-                    Some(NameClass::Definition(Definition::ModuleDef(def.into())))
+                    Some(NameClass::Definition(Definition::TypeAlias(def)))
                 },
                 ast::Macro(it) => {
                     let def = sema.to_def(&it)?;
@@ -360,7 +386,7 @@ impl NameRefClass {
 
         if let Some(method_call) = ast::MethodCallExpr::cast(parent.clone()) {
             if let Some(func) = sema.resolve_method_call(&method_call) {
-                return Some(NameRefClass::Definition(Definition::ModuleDef(func.into())));
+                return Some(NameRefClass::Definition(Definition::Function(func)));
             }
         }
 
@@ -406,9 +432,7 @@ impl NameRefClass {
                         })
                         .find(|alias| alias.name(sema.db).to_smol_str() == name_ref.text().as_str())
                     {
-                        return Some(NameRefClass::Definition(Definition::ModuleDef(
-                            ModuleDef::TypeAlias(ty),
-                        )));
+                        return Some(NameRefClass::Definition(Definition::TypeAlias(ty)));
                     }
                 }
 
@@ -440,9 +464,9 @@ impl NameRefClass {
                     .map(NameRefClass::Definition),
                 // in case of the path being a qualifier, don't resolve to anything but a module
                 Some(true) => match sema.resolve_path(&path)? {
-                    PathResolution::Def(module @ ModuleDef::Module(_)) => {
+                    PathResolution::Def(ModuleDef::Module(module)) => {
                         cov_mark::hit!(name_ref_classify_attr_path_qualifier);
-                        Some(NameRefClass::Definition(Definition::ModuleDef(module)))
+                        Some(NameRefClass::Definition(Definition::Module(module)))
                     }
                     _ => None,
                 },
@@ -455,7 +479,7 @@ impl NameRefClass {
         let extern_crate = ast::ExternCrate::cast(parent)?;
         let krate = sema.resolve_extern_crate(&extern_crate)?;
         let root_module = krate.root_module(sema.db);
-        Some(NameRefClass::Definition(Definition::ModuleDef(root_module.into())))
+        Some(NameRefClass::Definition(Definition::Module(root_module)))
     }
 
     pub fn classify_lifetime(
@@ -492,17 +516,34 @@ impl NameRefClass {
     }
 }
 
+impl AsAssocItem for Definition {
+    fn as_assoc_item(self, db: &dyn hir::db::HirDatabase) -> Option<AssocItem> {
+        match self {
+            Definition::Function(it) => it.as_assoc_item(db),
+            Definition::Const(it) => it.as_assoc_item(db),
+            Definition::TypeAlias(it) => it.as_assoc_item(db),
+            _ => None,
+        }
+    }
+}
+
+impl_from!(
+    Field, Module, Function, Adt, Variant, Const, Static, Trait, TypeAlias, BuiltinType, Local,
+    GenericParam, Label
+    for Definition
+);
+
 impl From<PathResolution> for Definition {
     fn from(path_resolution: PathResolution) -> Self {
         match path_resolution {
-            PathResolution::Def(def) => Definition::ModuleDef(def),
+            PathResolution::Def(def) => def.into(),
             PathResolution::AssocItem(item) => {
-                let def = match item {
+                let def: ModuleDef = match item {
                     hir::AssocItem::Function(it) => it.into(),
                     hir::AssocItem::Const(it) => it.into(),
                     hir::AssocItem::TypeAlias(it) => it.into(),
                 };
-                Definition::ModuleDef(def)
+                def.into()
             }
             PathResolution::Local(local) => Definition::Local(local),
             PathResolution::TypeParam(par) => Definition::GenericParam(par.into()),
@@ -512,3 +553,37 @@ impl From<PathResolution> for Definition {
         }
     }
 }
+
+impl From<ModuleDef> for Definition {
+    fn from(def: ModuleDef) -> Self {
+        match def {
+            ModuleDef::Module(it) => Definition::Module(it),
+            ModuleDef::Function(it) => Definition::Function(it),
+            ModuleDef::Adt(it) => Definition::Adt(it),
+            ModuleDef::Variant(it) => Definition::Variant(it),
+            ModuleDef::Const(it) => Definition::Const(it),
+            ModuleDef::Static(it) => Definition::Static(it),
+            ModuleDef::Trait(it) => Definition::Trait(it),
+            ModuleDef::TypeAlias(it) => Definition::TypeAlias(it),
+            ModuleDef::BuiltinType(it) => Definition::BuiltinType(it),
+        }
+    }
+}
+
+impl From<Definition> for Option<ItemInNs> {
+    fn from(def: Definition) -> Self {
+        let item = match def {
+            Definition::Module(it) => ModuleDef::Module(it),
+            Definition::Function(it) => ModuleDef::Function(it),
+            Definition::Adt(it) => ModuleDef::Adt(it),
+            Definition::Variant(it) => ModuleDef::Variant(it),
+            Definition::Const(it) => ModuleDef::Const(it),
+            Definition::Static(it) => ModuleDef::Static(it),
+            Definition::Trait(it) => ModuleDef::Trait(it),
+            Definition::TypeAlias(it) => ModuleDef::TypeAlias(it),
+            Definition::BuiltinType(it) => ModuleDef::BuiltinType(it),
+            _ => return None,
+        };
+        Some(ItemInNs::from(item))
+    }
+}
diff --git a/crates/ide_db/src/items_locator.rs b/crates/ide_db/src/items_locator.rs
index 6a326eb4ca3..a3ea3edc977 100644
--- a/crates/ide_db/src/items_locator.rs
+++ b/crates/ide_db/src/items_locator.rs
@@ -117,9 +117,8 @@ fn find_items<'a>(
         .into_iter()
         .filter_map(move |local_candidate| get_name_definition(sema, &local_candidate))
         .filter_map(|name_definition_to_import| match name_definition_to_import {
-            Definition::ModuleDef(module_def) => Some(ItemInNs::from(module_def)),
             Definition::Macro(macro_def) => Some(ItemInNs::from(macro_def)),
-            _ => None,
+            def => <Option<_>>::from(def),
         });
 
     external_importables.chain(local_results).filter(move |&item| match assoc_item_search {
diff --git a/crates/ide_db/src/rename.rs b/crates/ide_db/src/rename.rs
index 4fb5c770e52..678153c6e1d 100644
--- a/crates/ide_db/src/rename.rs
+++ b/crates/ide_db/src/rename.rs
@@ -67,10 +67,8 @@ pub use _bail as bail;
 impl Definition {
     pub fn rename(&self, sema: &Semantics<RootDatabase>, new_name: &str) -> Result<SourceChange> {
         match *self {
-            Definition::ModuleDef(hir::ModuleDef::Module(module)) => {
-                rename_mod(sema, module, new_name)
-            }
-            Definition::ModuleDef(hir::ModuleDef::BuiltinType(_)) => {
+            Definition::Module(module) => rename_mod(sema, module, new_name),
+            Definition::BuiltinType(_) => {
                 bail!("Cannot rename builtin type")
             }
             Definition::SelfType(_) => bail!("Cannot rename `Self`"),
@@ -101,25 +99,23 @@ impl Definition {
                     FieldSource::Pos(_) => None,
                 }
             }
-            Definition::ModuleDef(module_def) => match module_def {
-                hir::ModuleDef::Module(module) => {
-                    let src = module.declaration_source(sema.db)?;
-                    let name = src.value.name()?;
-                    src.with_value(name.syntax()).original_file_range_opt(sema.db)
-                }
-                hir::ModuleDef::Function(it) => name_range(it, sema),
-                hir::ModuleDef::Adt(adt) => match adt {
-                    hir::Adt::Struct(it) => name_range(it, sema),
-                    hir::Adt::Union(it) => name_range(it, sema),
-                    hir::Adt::Enum(it) => name_range(it, sema),
-                },
-                hir::ModuleDef::Variant(it) => name_range(it, sema),
-                hir::ModuleDef::Const(it) => name_range(it, sema),
-                hir::ModuleDef::Static(it) => name_range(it, sema),
-                hir::ModuleDef::Trait(it) => name_range(it, sema),
-                hir::ModuleDef::TypeAlias(it) => name_range(it, sema),
-                hir::ModuleDef::BuiltinType(_) => return None,
+            Definition::Module(module) => {
+                let src = module.declaration_source(sema.db)?;
+                let name = src.value.name()?;
+                src.with_value(name.syntax()).original_file_range_opt(sema.db)
+            }
+            Definition::Function(it) => name_range(it, sema),
+            Definition::Adt(adt) => match adt {
+                hir::Adt::Struct(it) => name_range(it, sema),
+                hir::Adt::Union(it) => name_range(it, sema),
+                hir::Adt::Enum(it) => name_range(it, sema),
             },
+            Definition::Variant(it) => name_range(it, sema),
+            Definition::Const(it) => name_range(it, sema),
+            Definition::Static(it) => name_range(it, sema),
+            Definition::Trait(it) => name_range(it, sema),
+            Definition::TypeAlias(it) => name_range(it, sema),
+            Definition::BuiltinType(_) => return None,
             Definition::SelfType(_) => return None,
             Definition::Local(local) => {
                 let src = local.source(sema.db);
@@ -200,7 +196,7 @@ fn rename_mod(
             _ => never!("Module source node is missing a name"),
         }
     }
-    let def = Definition::ModuleDef(hir::ModuleDef::Module(module));
+    let def = Definition::Module(module);
     let usages = def.usages(sema).all();
     let ref_edits = usages.iter().map(|(&file_id, references)| {
         (file_id, source_edit_from_references(references, def, new_name))
@@ -239,35 +235,40 @@ fn rename_reference(
         }
     }
 
-    def = match def {
+    let assoc_item = match def {
         // HACK: resolve trait impl items to the item def of the trait definition
         // so that we properly resolve all trait item references
-        Definition::ModuleDef(mod_def) => mod_def
-            .as_assoc_item(sema.db)
-            .and_then(|it| it.containing_trait_impl(sema.db))
-            .and_then(|it| {
-                it.items(sema.db).into_iter().find_map(|it| match (it, mod_def) {
-                    (hir::AssocItem::Function(trait_func), hir::ModuleDef::Function(func))
+        Definition::Function(it) => it.as_assoc_item(sema.db),
+        Definition::TypeAlias(it) => it.as_assoc_item(sema.db),
+        Definition::Const(it) => it.as_assoc_item(sema.db),
+        _ => None,
+    };
+    def = match assoc_item {
+        Some(assoc) => assoc
+            .containing_trait_impl(sema.db)
+            .and_then(|trait_| {
+                trait_.items(sema.db).into_iter().find_map(|it| match (it, assoc) {
+                    (hir::AssocItem::Function(trait_func), hir::AssocItem::Function(func))
                         if trait_func.name(sema.db) == func.name(sema.db) =>
                     {
-                        Some(Definition::ModuleDef(hir::ModuleDef::Function(trait_func)))
+                        Some(Definition::Function(trait_func))
                     }
-                    (hir::AssocItem::Const(trait_konst), hir::ModuleDef::Const(konst))
+                    (hir::AssocItem::Const(trait_konst), hir::AssocItem::Const(konst))
                         if trait_konst.name(sema.db) == konst.name(sema.db) =>
                     {
-                        Some(Definition::ModuleDef(hir::ModuleDef::Const(trait_konst)))
+                        Some(Definition::Const(trait_konst))
                     }
                     (
                         hir::AssocItem::TypeAlias(trait_type_alias),
-                        hir::ModuleDef::TypeAlias(type_alias),
+                        hir::AssocItem::TypeAlias(type_alias),
                     ) if trait_type_alias.name(sema.db) == type_alias.name(sema.db) => {
-                        Some(Definition::ModuleDef(hir::ModuleDef::TypeAlias(trait_type_alias)))
+                        Some(Definition::TypeAlias(trait_type_alias))
                     }
                     _ => None,
                 })
             })
             .unwrap_or(def),
-        _ => def,
+        None => def,
     };
     let usages = def.usages(sema).all();
 
diff --git a/crates/ide_db/src/search.rs b/crates/ide_db/src/search.rs
index 65deaf4d7df..c23a9ee2572 100644
--- a/crates/ide_db/src/search.rs
+++ b/crates/ide_db/src/search.rs
@@ -8,8 +8,7 @@ use std::{convert::TryInto, mem};
 
 use base_db::{FileId, FileRange, SourceDatabase, SourceDatabaseExt};
 use hir::{
-    AsAssocItem, DefWithBody, HasAttrs, HasSource, InFile, ModuleDef, ModuleSource, Semantics,
-    Visibility,
+    AsAssocItem, DefWithBody, HasAttrs, HasSource, InFile, ModuleSource, Semantics, Visibility,
 };
 use once_cell::unsync::Lazy;
 use rustc_hash::FxHashMap;
@@ -217,13 +216,13 @@ impl Definition {
     fn search_scope(&self, db: &RootDatabase) -> SearchScope {
         let _p = profile::span("search_scope");
 
-        if let Definition::ModuleDef(hir::ModuleDef::BuiltinType(_)) = self {
+        if let Definition::BuiltinType(_) = self {
             return SearchScope::crate_graph(db);
         }
 
         // def is crate root
         // FIXME: We don't do searches for crates currently, as a crate does not actually have a single name
-        if let &Definition::ModuleDef(hir::ModuleDef::Module(module)) = self {
+        if let &Definition::Module(module) = self {
             if module.crate_root(db) == module {
                 return SearchScope::reverse_dependencies(db, module.krate());
             }
@@ -431,7 +430,7 @@ impl<'a> FindUsages<'a> {
 
         // search for module `self` references in our module's definition source
         match self.def {
-            Definition::ModuleDef(hir::ModuleDef::Module(module)) if self.search_self_mod => {
+            Definition::Module(module) if self.search_self_mod => {
                 let src = module.definition_source(sema.db);
                 let file_id = src.file_id.original_file(sema.db);
                 let (file_id, search_range) = match src.value {
@@ -491,7 +490,7 @@ impl<'a> FindUsages<'a> {
         sink: &mut dyn FnMut(FileId, FileReference) -> bool,
     ) -> bool {
         match NameRefClass::classify(self.sema, name_ref) {
-            Some(NameRefClass::Definition(def @ Definition::ModuleDef(_))) if def == self.def => {
+            Some(NameRefClass::Definition(def @ Definition::Module(_))) if def == self.def => {
                 let FileRange { file_id, range } = self.sema.original_range(name_ref.syntax());
                 let reference = FileReference {
                     range,
@@ -604,30 +603,27 @@ impl<'a> FindUsages<'a> {
                 sink(file_id, reference)
             }
             // Resolve trait impl function definitions to the trait definition's version if self.def is the trait definition's
-            Some(NameClass::Definition(Definition::ModuleDef(mod_def))) => {
+            Some(NameClass::Definition(def)) if def != self.def => {
                 /* poor man's try block */
                 (|| {
-                    let this = match self.def {
-                        Definition::ModuleDef(this) if this != mod_def => this,
-                        _ => return None,
-                    };
-                    let this_trait = this
+                    let this_trait = self
+                        .def
                         .as_assoc_item(self.sema.db)?
                         .containing_trait_or_trait_impl(self.sema.db)?;
-                    let trait_ = mod_def
+                    let trait_ = def
                         .as_assoc_item(self.sema.db)?
                         .containing_trait_or_trait_impl(self.sema.db)?;
-                    (trait_ == this_trait
-                        && self.def.name(self.sema.db) == mod_def.name(self.sema.db))
-                    .then(|| {
-                        let FileRange { file_id, range } = self.sema.original_range(name.syntax());
-                        let reference = FileReference {
-                            range,
-                            name: ast::NameLike::Name(name.clone()),
-                            category: None,
-                        };
-                        sink(file_id, reference)
-                    })
+                    (trait_ == this_trait && self.def.name(self.sema.db) == def.name(self.sema.db))
+                        .then(|| {
+                            let FileRange { file_id, range } =
+                                self.sema.original_range(name.syntax());
+                            let reference = FileReference {
+                                range,
+                                name: ast::NameLike::Name(name.clone()),
+                                category: None,
+                            };
+                            sink(file_id, reference)
+                        })
                 })()
                 .unwrap_or(false)
             }
@@ -638,18 +634,15 @@ impl<'a> FindUsages<'a> {
 
 fn def_to_ty(sema: &Semantics<RootDatabase>, def: &Definition) -> Option<hir::Type> {
     match def {
-        Definition::ModuleDef(def) => match def {
-            ModuleDef::Adt(adt) => Some(adt.ty(sema.db)),
-            ModuleDef::TypeAlias(it) => Some(it.ty(sema.db)),
-            ModuleDef::BuiltinType(it) => {
-                let graph = sema.db.crate_graph();
-                let krate = graph.iter().next()?;
-                let root_file = graph[krate].root_file_id;
-                let module = sema.to_module_def(root_file)?;
-                Some(it.ty(sema.db, module))
-            }
-            _ => None,
-        },
+        Definition::Adt(adt) => Some(adt.ty(sema.db)),
+        Definition::TypeAlias(it) => Some(it.ty(sema.db)),
+        Definition::BuiltinType(it) => {
+            let graph = sema.db.crate_graph();
+            let krate = graph.iter().next()?;
+            let root_file = graph[krate].root_file_id;
+            let module = sema.to_module_def(root_file)?;
+            Some(it.ty(sema.db, module))
+        }
         Definition::SelfType(it) => Some(it.self_ty(sema.db)),
         _ => None,
     }