Repository: rust-lang/rust-analyzer
Pull request #12778 (2022-07-17 01:08:49)

Support negative, `char` & `bool` const generics
Before:
![Before](https://user-images.githubusercontent.com/29541480/179379832-0c3b2a74-fef6-427e-b89f-7e31d9c37b3d.png)

After:
![After](https://user-images.githubusercontent.com/29541480/179379863-b62475dd-e7bf-41f2-b437-08dfe55951af.png)

I tried to implement stuff like `Const<{NUM1 + 3 + NUM2}>` by using already existing constant evaluation mechanism for ordinary constants, but turned out to be harder than I thought, maybe because I've never ever tinkered with compilers before


Patch:
diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml
index 0c81ff0789..8ba4f07d4a 100644
--- a/.github/workflows/ci.yaml
+++ b/.github/workflows/ci.yaml
@@ -37,10 +37,21 @@ jobs:
         ref: ${{ github.event.pull_request.head.sha }}
         fetch-depth: 20
 
+    # We need to disable the existing toolchain to avoid updating rust-docs
+    # which takes a long time. The fastest way to do this is to rename the
+    # existing folder, as deleting it takes about as much time as not doing
+    # anything and just updating rust-docs.
+    - name: Rename existing rust toolchain (Windows)
+      if: matrix.os == 'windows-latest'
+      run: Rename-Item C:\Users\runneradmin\.rustup\toolchains\stable-x86_64-pc-windows-msvc C:\Users\runneradmin\.rustup\toolchains\stable-x86_64-pc-windows-msvc.old
+
     - name: Install Rust toolchain
-      run: |
-        rustup update --no-self-update stable
-        rustup component add rustfmt rust-src
+      uses: actions-rs/toolchain@v1
+      with:
+        toolchain: stable
+        profile: minimal
+        override: true
+        components: rustfmt, rust-src
 
     - name: Cache Dependencies
       uses: Swatinem/rust-cache@ce325b60658c1b38465c06cc965b79baf32c1e72
@@ -68,9 +79,14 @@ jobs:
       uses: actions/checkout@v3
 
     - name: Install Rust toolchain
-      run: |
-        rustup update --no-self-update stable
-        rustup target add ${{ env.targets }} ${{ env.targets_ide }}
+      uses: actions-rs/toolchain@v1
+      with:
+        toolchain: stable
+        profile: minimal
+        override: true
+
+    - name: Install Rust targets
+      run: rustup target add ${{ env.targets }} ${{ env.targets_ide }}
 
     - name: Cache Dependencies
       uses: Swatinem/rust-cache@ce325b60658c1b38465c06cc965b79baf32c1e72
diff --git a/.github/workflows/metrics.yaml b/.github/workflows/metrics.yaml
index 3fe2fc917a..af6c610784 100644
--- a/.github/workflows/metrics.yaml
+++ b/.github/workflows/metrics.yaml
@@ -20,9 +20,12 @@ jobs:
       uses: actions/checkout@v3
 
     - name: Install Rust toolchain
-      run: |
-        rustup update --no-self-update stable
-        rustup component add rustfmt rust-src
+      uses: actions-rs/toolchain@v1
+      with:
+        toolchain: stable
+        profile: minimal
+        override: true
+        components: rust-src
 
     - name: Collect metrics
       run: cargo xtask metrics
diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml
index 927996c1be..e4892dccf4 100644
--- a/.github/workflows/publish.yml
+++ b/.github/workflows/publish.yml
@@ -20,10 +20,16 @@ jobs:
           fetch-depth: 0
 
       - name: Install Rust toolchain
-        run: rustup update --no-self-update stable
+        uses: actions-rs/toolchain@v1
+        with:
+          toolchain: stable
+          profile: minimal
+          override: true
 
       - name: Install cargo-workspaces
-        run: cargo install cargo-workspaces
+        uses: actions-rs/install@v0.1
+        with:
+          crate: cargo-workspaces
 
       - name: Release
         env:
diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml
index 4e62f2cde2..9205d86f93 100644
--- a/.github/workflows/release.yaml
+++ b/.github/workflows/release.yaml
@@ -55,11 +55,31 @@ jobs:
         with:
           fetch-depth: ${{ env.FETCH_DEPTH }}
 
+      # We need to disable the existing toolchain to avoid updating rust-docs
+      # which takes a long time. The fastest way to do this is to rename the
+      # existing folder, as deleting it takes about as much time as not doing
+      # anything and just updating rust-docs.
+      - name: Rename existing Rust toolchain
+        if: matrix.os == 'windows-latest'
+        run: Rename-Item C:\Users\runneradmin\.rustup\toolchains\stable-x86_64-pc-windows-msvc C:\Users\runneradmin\.rustup\toolchains\stable-x86_64-pc-windows-msvc.old
+
       - name: Install Rust toolchain
-        run: |
-          rustup update --no-self-update stable
-          rustup target add ${{ matrix.target }}
-          rustup component add rust-src
+        uses: actions-rs/toolchain@v1
+        with:
+          toolchain: stable
+          target: ${{ matrix.target }}
+          profile: minimal
+          override: true
+
+      - name: Install Rust library source
+        if: matrix.target == 'x86_64-unknown-linux-gnu'
+        uses: actions-rs/toolchain@v1
+        with:
+          toolchain: stable
+          target: ${{ matrix.target }}
+          profile: minimal
+          override: true
+          components: rust-src
 
       - name: Install Node.js
         uses: actions/setup-node@v1
diff --git a/.github/workflows/rustdoc.yaml b/.github/workflows/rustdoc.yaml
index 05f3e254e5..227fab54eb 100644
--- a/.github/workflows/rustdoc.yaml
+++ b/.github/workflows/rustdoc.yaml
@@ -20,7 +20,12 @@ jobs:
       uses: actions/checkout@v3
 
     - name: Install Rust toolchain
-      run: rustup update --no-self-update stable
+      uses: actions-rs/toolchain@v1
+      with:
+        toolchain: stable
+        profile: minimal
+        override: true
+        components: rustfmt, rust-src
 
     - name: Build Documentation
       run: cargo doc --all --no-deps
diff --git a/crates/hir-def/src/body.rs b/crates/hir-def/src/body.rs
index 94210ab33f..33851d90a2 100644
--- a/crates/hir-def/src/body.rs
+++ b/crates/hir-def/src/body.rs
@@ -24,7 +24,7 @@ use syntax::{ast, AstNode, AstPtr, SyntaxNodePtr};
 use crate::{
     attr::{Attrs, RawAttrs},
     db::DefDatabase,
-    expr::{Expr, ExprId, Label, LabelId, Pat, PatId},
+    expr::{dummy_expr_id, Expr, ExprId, Label, LabelId, Pat, PatId},
     item_scope::BuiltinShadowMode,
     macro_id_to_def_id,
     nameres::DefMap,
@@ -389,6 +389,21 @@ impl Body {
     }
 }
 
+impl Default for Body {
+    fn default() -> Self {
+        Self {
+            body_expr: dummy_expr_id(),
+            exprs: Default::default(),
+            pats: Default::default(),
+            or_pats: Default::default(),
+            labels: Default::default(),
+            params: Default::default(),
+            block_scopes: Default::default(),
+            _c: Default::default(),
+        }
+    }
+}
+
 impl Index<ExprId> for Body {
     type Output = Expr;
 
diff --git a/crates/hir-def/src/child_by_source.rs b/crates/hir-def/src/child_by_source.rs
index 5b1435e8f4..b1337ecc24 100644
--- a/crates/hir-def/src/child_by_source.rs
+++ b/crates/hir-def/src/child_by_source.rs
@@ -102,15 +102,13 @@ impl ChildBySource for ItemScope {
                 res[keys::ATTR_MACRO_CALL].insert(ast_id.to_node(db.upcast()), call_id);
             },
         );
-        self.legacy_macros().for_each(|(_, ids)| {
-            ids.iter().for_each(|&id| {
-                if let MacroId::MacroRulesId(id) = id {
-                    let loc = id.lookup(db);
-                    if loc.id.file_id() == file_id {
-                        res[keys::MACRO_RULES].insert(loc.source(db).value, id);
-                    }
+        self.legacy_macros().for_each(|(_, id)| {
+            if let MacroId::MacroRulesId(id) = id {
+                let loc = id.lookup(db);
+                if loc.id.file_id() == file_id {
+                    res[keys::MACRO_RULES].insert(loc.source(db).value, id);
                 }
-            })
+            }
         });
         self.derive_macro_invocs().filter(|(id, _)| id.file_id == file_id).for_each(
             |(ast_id, calls)| {
diff --git a/crates/hir-def/src/expr.rs b/crates/hir-def/src/expr.rs
index 4295bacc46..a991365d6b 100644
--- a/crates/hir-def/src/expr.rs
+++ b/crates/hir-def/src/expr.rs
@@ -26,8 +26,10 @@ use crate::{
 pub use syntax::ast::{ArithOp, BinaryOp, CmpOp, LogicOp, Ordering, RangeOp, UnaryOp};
 
 pub type ExprId = Idx<Expr>;
+
+/// FIXME: this is a hacky function which should be removed
 pub(crate) fn dummy_expr_id() -> ExprId {
-    ExprId::from_raw(RawIdx::from(!0))
+    ExprId::from_raw(RawIdx::from(u32::MAX))
 }
 
 pub type PatId = Idx<Pat>;
diff --git a/crates/hir-def/src/item_scope.rs b/crates/hir-def/src/item_scope.rs
index b98b2855cb..ddccbbfef9 100644
--- a/crates/hir-def/src/item_scope.rs
+++ b/crates/hir-def/src/item_scope.rs
@@ -61,7 +61,7 @@ pub struct ItemScope {
     /// Module scoped macros will be inserted into `items` instead of here.
     // FIXME: Macro shadowing in one module is not properly handled. Non-item place macros will
     // be all resolved to the last one defined if shadowing happens.
-    legacy_macros: FxHashMap<Name, SmallVec<[MacroId; 1]>>,
+    legacy_macros: FxHashMap<Name, MacroId>,
     /// The derive macro invocations in this scope.
     attr_macros: FxHashMap<AstId<ast::Item>, MacroCallId>,
     /// The derive macro invocations in this scope, keyed by the owner item over the actual derive attributes
@@ -129,13 +129,13 @@ impl ItemScope {
     }
 
     /// Iterate over all module scoped macros
-    pub(crate) fn macros(&self) -> impl Iterator<Item = (&Name, MacroId)> + '_ {
+    pub(crate) fn macros<'a>(&'a self) -> impl Iterator<Item = (&'a Name, MacroId)> + 'a {
         self.entries().filter_map(|(name, def)| def.take_macros().map(|macro_| (name, macro_)))
     }
 
     /// Iterate over all legacy textual scoped macros visible at the end of the module
-    pub fn legacy_macros(&self) -> impl Iterator<Item = (&Name, &[MacroId])> + '_ {
-        self.legacy_macros.iter().map(|(name, def)| (name, &**def))
+    pub fn legacy_macros<'a>(&'a self) -> impl Iterator<Item = (&'a Name, MacroId)> + 'a {
+        self.legacy_macros.iter().map(|(name, def)| (name, *def))
     }
 
     /// Get a name from current module scope, legacy macros are not included
@@ -180,8 +180,8 @@ impl ItemScope {
         self.declarations.push(def)
     }
 
-    pub(crate) fn get_legacy_macro(&self, name: &Name) -> Option<&[MacroId]> {
-        self.legacy_macros.get(name).map(|it| &**it)
+    pub(crate) fn get_legacy_macro(&self, name: &Name) -> Option<MacroId> {
+        self.legacy_macros.get(name).copied()
     }
 
     pub(crate) fn define_impl(&mut self, imp: ImplId) {
@@ -193,7 +193,7 @@ impl ItemScope {
     }
 
     pub(crate) fn define_legacy_macro(&mut self, name: Name, mac: MacroId) {
-        self.legacy_macros.entry(name).or_default().push(mac);
+        self.legacy_macros.insert(name, mac);
     }
 
     pub(crate) fn add_attr_macro_invoc(&mut self, item: AstId<ast::Item>, call: MacroCallId) {
@@ -270,33 +270,35 @@ impl ItemScope {
                 $glob_imports:ident [ $lookup:ident ],
                 $def_import_type:ident
             ) => {{
-                if let Some(fld) = $def.$field {
-                    let existing = $this.$field.entry($lookup.1.clone());
-                    match existing {
-                        Entry::Vacant(entry) => {
-                            match $def_import_type {
-                                ImportType::Glob => {
-                                    $glob_imports.$field.insert($lookup.clone());
-                                }
-                                ImportType::Named => {
-                                    $glob_imports.$field.remove(&$lookup);
-                                }
+                let existing = $this.$field.entry($lookup.1.clone());
+                match (existing, $def.$field) {
+                    (Entry::Vacant(entry), Some(_)) => {
+                        match $def_import_type {
+                            ImportType::Glob => {
+                                $glob_imports.$field.insert($lookup.clone());
                             }
+                            ImportType::Named => {
+                                $glob_imports.$field.remove(&$lookup);
+                            }
+                        }
 
+                        if let Some(fld) = $def.$field {
                             entry.insert(fld);
-                            $changed = true;
                         }
-                        Entry::Occupied(mut entry)
-                            if $glob_imports.$field.contains(&$lookup)
-                                && matches!($def_import_type, ImportType::Named) =>
-                        {
-                            cov_mark::hit!(import_shadowed);
-                            $glob_imports.$field.remove(&$lookup);
+                        $changed = true;
+                    }
+                    (Entry::Occupied(mut entry), Some(_))
+                        if $glob_imports.$field.contains(&$lookup)
+                            && matches!($def_import_type, ImportType::Named) =>
+                    {
+                        cov_mark::hit!(import_shadowed);
+                        $glob_imports.$field.remove(&$lookup);
+                        if let Some(fld) = $def.$field {
                             entry.insert(fld);
-                            $changed = true;
                         }
-                        _ => {}
+                        $changed = true;
                     }
+                    _ => {}
                 }
             }};
         }
@@ -320,7 +322,7 @@ impl ItemScope {
         )
     }
 
-    pub(crate) fn collect_legacy_macros(&self) -> FxHashMap<Name, SmallVec<[MacroId; 1]>> {
+    pub(crate) fn collect_legacy_macros(&self) -> FxHashMap<Name, MacroId> {
         self.legacy_macros.clone()
     }
 
diff --git a/crates/hir-def/src/nameres.rs b/crates/hir-def/src/nameres.rs
index a32513cf65..536eecf020 100644
--- a/crates/hir-def/src/nameres.rs
+++ b/crates/hir-def/src/nameres.rs
@@ -219,7 +219,7 @@ impl DefMap {
 
         let edition = crate_graph[krate].edition;
         let origin = ModuleOrigin::CrateRoot { definition: crate_graph[krate].root_file_id };
-        let def_map = DefMap::empty(krate, edition, ModuleData::new(origin, Visibility::Public));
+        let def_map = DefMap::empty(krate, edition, origin);
         let def_map = collector::collect_defs(
             db,
             def_map,
@@ -241,26 +241,30 @@ impl DefMap {
             return None;
         }
 
-        let parent_map = block.module.def_map(db);
-        let krate = block.module.krate;
-        let local_id = LocalModuleId::from_raw(la_arena::RawIdx::from(0));
-        // NB: we use `None` as block here, which would be wrong for implicit
-        // modules declared by blocks with items. At the moment, we don't use
-        // this visibility for anything outside IDE, so that's probably OK.
-        let visibility = Visibility::Module(ModuleId { krate, local_id, block: None });
-        let module_data =
-            ModuleData::new(ModuleOrigin::BlockExpr { block: block.ast_id }, visibility);
+        let block_info = BlockInfo { block: block_id, parent: block.module };
 
-        let mut def_map = DefMap::empty(krate, parent_map.edition, module_data);
-        def_map.block = Some(BlockInfo { block: block_id, parent: block.module });
+        let parent_map = block.module.def_map(db);
+        let mut def_map = DefMap::empty(
+            block.module.krate,
+            parent_map.edition,
+            ModuleOrigin::BlockExpr { block: block.ast_id },
+        );
+        def_map.block = Some(block_info);
 
         let def_map = collector::collect_defs(db, def_map, tree_id);
         Some(Arc::new(def_map))
     }
 
-    fn empty(krate: CrateId, edition: Edition, module_data: ModuleData) -> DefMap {
+    fn empty(krate: CrateId, edition: Edition, root_module_origin: ModuleOrigin) -> DefMap {
         let mut modules: Arena<ModuleData> = Arena::default();
-        let root = modules.alloc(module_data);
+
+        let local_id = LocalModuleId::from_raw(la_arena::RawIdx::from(0));
+        // NB: we use `None` as block here, which would be wrong for implicit
+        // modules declared by blocks with items. At the moment, we don't use
+        // this visibility for anything outside IDE, so that's probably OK.
+        let visibility = Visibility::Module(ModuleId { krate, local_id, block: None });
+        let root = modules.alloc(ModuleData::new(root_module_origin, visibility));
+        assert_eq!(local_id, root);
 
         DefMap {
             _c: Count::new(),
diff --git a/crates/hir-def/src/nameres/collector.rs b/crates/hir-def/src/nameres/collector.rs
index 317e21538b..ca0cb99b37 100644
--- a/crates/hir-def/src/nameres/collector.rs
+++ b/crates/hir-def/src/nameres/collector.rs
@@ -395,8 +395,9 @@ impl DefCollector<'_> {
         // As some of the macros will expand newly import shadowing partial resolved imports
         // FIXME: We maybe could skip this, if we handle the indeterminate imports in `resolve_imports`
         // correctly
-        let partial_resolved = self.indeterminate_imports.drain(..).map(|directive| {
-            ImportDirective { status: PartialResolvedImport::Unresolved, ..directive }
+        let partial_resolved = self.indeterminate_imports.drain(..).filter_map(|mut directive| {
+            directive.status = PartialResolvedImport::Unresolved;
+            Some(directive)
         });
         self.unresolved_imports.extend(partial_resolved);
         self.resolve_imports();
@@ -433,48 +434,50 @@ impl DefCollector<'_> {
     fn reseed_with_unresolved_attribute(&mut self) -> ReachedFixedPoint {
         cov_mark::hit!(unresolved_attribute_fallback);
 
-        let unresolved_attr =
-            self.unresolved_macros.iter().enumerate().find_map(|(idx, directive)| match &directive
-                .kind
-            {
-                MacroDirectiveKind::Attr { ast_id, mod_item, attr, tree } => {
-                    self.def_map.diagnostics.push(DefDiagnostic::unresolved_macro_call(
-                        directive.module_id,
-                        MacroCallKind::Attr {
-                            ast_id: ast_id.ast_id,
-                            attr_args: Default::default(),
-                            invoc_attr_index: attr.id.ast_index,
-                            is_derive: false,
-                        },
-                        attr.path().clone(),
-                    ));
-
-                    self.skip_attrs.insert(ast_id.ast_id.with_value(*mod_item), attr.id);
+        let mut unresolved_macros = mem::take(&mut self.unresolved_macros);
+        let pos = unresolved_macros.iter().position(|directive| {
+            if let MacroDirectiveKind::Attr { ast_id, mod_item, attr, tree } = &directive.kind {
+                self.def_map.diagnostics.push(DefDiagnostic::unresolved_macro_call(
+                    directive.module_id,
+                    MacroCallKind::Attr {
+                        ast_id: ast_id.ast_id,
+                        attr_args: Default::default(),
+                        invoc_attr_index: attr.id.ast_index,
+                        is_derive: false,
+                    },
+                    attr.path().clone(),
+                ));
 
-                    Some((idx, directive, *mod_item, *tree))
-                }
-                _ => None,
-            });
+                self.skip_attrs.insert(ast_id.ast_id.with_value(*mod_item), attr.id);
 
-        match unresolved_attr {
-            Some((pos, &MacroDirective { module_id, depth, container, .. }, mod_item, tree_id)) => {
-                let item_tree = &tree_id.item_tree(self.db);
-                let mod_dir = self.mod_dirs[&module_id].clone();
+                let item_tree = tree.item_tree(self.db);
+                let mod_dir = self.mod_dirs[&directive.module_id].clone();
                 ModCollector {
                     def_collector: self,
-                    macro_depth: depth,
-                    module_id,
-                    tree_id,
-                    item_tree,
+                    macro_depth: directive.depth,
+                    module_id: directive.module_id,
+                    tree_id: *tree,
+                    item_tree: &item_tree,
                     mod_dir,
                 }
-                .collect(&[mod_item], container);
-
-                self.unresolved_macros.swap_remove(pos);
-                // Continue name resolution with the new data.
-                ReachedFixedPoint::No
+                .collect(&[*mod_item], directive.container);
+                true
+            } else {
+                false
             }
-            None => ReachedFixedPoint::Yes,
+        });
+
+        if let Some(pos) = pos {
+            unresolved_macros.swap_remove(pos);
+        }
+
+        self.unresolved_macros.extend(unresolved_macros);
+
+        if pos.is_some() {
+            // Continue name resolution with the new data.
+            ReachedFixedPoint::No
+        } else {
+            ReachedFixedPoint::Yes
         }
     }
 
@@ -719,8 +722,7 @@ impl DefCollector<'_> {
     fn resolve_imports(&mut self) -> ReachedFixedPoint {
         let mut res = ReachedFixedPoint::Yes;
         let imports = mem::take(&mut self.unresolved_imports);
-
-        self.unresolved_imports = imports
+        let imports = imports
             .into_iter()
             .filter_map(|mut directive| {
                 directive.status = self.resolve_import(directive.module_id, &directive.import);
@@ -740,6 +742,7 @@ impl DefCollector<'_> {
                 }
             })
             .collect();
+        self.unresolved_imports = imports;
         res
     }
 
@@ -1031,7 +1034,7 @@ impl DefCollector<'_> {
             .glob_imports
             .get(&module_id)
             .into_iter()
-            .flatten()
+            .flat_map(|v| v.iter())
             .filter(|(glob_importing_module, _)| {
                 // we know all resolutions have the same visibility (`vis`), so we
                 // just need to check that once
@@ -1806,9 +1809,7 @@ impl ModCollector<'_, '_> {
         let res = modules.alloc(ModuleData::new(origin, vis));
         modules[res].parent = Some(self.module_id);
         for (name, mac) in modules[self.module_id].scope.collect_legacy_macros() {
-            for &mac in &mac {
-                modules[res].scope.define_legacy_macro(name.clone(), mac);
-            }
+            modules[res].scope.define_legacy_macro(name, mac)
         }
         modules[self.module_id].children.insert(name.clone(), res);
 
@@ -2026,8 +2027,7 @@ impl ModCollector<'_, '_> {
                             map[module]
                                 .scope
                                 .get_legacy_macro(name)
-                                .and_then(|it| it.last())
-                                .map(|&it| macro_id_to_def_id(self.def_collector.db, it.into()))
+                                .map(|it| macro_id_to_def_id(self.def_collector.db, it.into()))
                         },
                     )
                 })
@@ -2080,10 +2080,8 @@ impl ModCollector<'_, '_> {
 
     fn import_all_legacy_macros(&mut self, module_id: LocalModuleId) {
         let macros = self.def_collector.def_map[module_id].scope.collect_legacy_macros();
-        for (name, macs) in macros {
-            macs.last().map(|&mac| {
-                self.def_collector.define_legacy_macro(self.module_id, name.clone(), mac)
-            });
+        for (name, macro_) in macros {
+            self.def_collector.define_legacy_macro(self.module_id, name.clone(), macro_);
         }
     }
 
@@ -2143,8 +2141,7 @@ mod tests {
 
         let edition = db.crate_graph()[krate].edition;
         let module_origin = ModuleOrigin::CrateRoot { definition: file_id };
-        let def_map =
-            DefMap::empty(krate, edition, ModuleData::new(module_origin, Visibility::Public));
+        let def_map = DefMap::empty(krate, edition, module_origin);
         do_collect_defs(&db, def_map)
     }
 
diff --git a/crates/hir-def/src/nameres/path_resolution.rs b/crates/hir-def/src/nameres/path_resolution.rs
index c579bc9194..cc5fc0a52a 100644
--- a/crates/hir-def/src/nameres/path_resolution.rs
+++ b/crates/hir-def/src/nameres/path_resolution.rs
@@ -381,9 +381,7 @@ impl DefMap {
         let from_legacy_macro = self[module]
             .scope
             .get_legacy_macro(name)
-            // FIXME: shadowing
-            .and_then(|it| it.last())
-            .map_or_else(PerNs::none, |&m| PerNs::macros(m.into(), Visibility::Public));
+            .map_or_else(PerNs::none, |m| PerNs::macros(m.into(), Visibility::Public));
         let from_scope = self[module].scope.get(name);
         let from_builtin = match self.block {
             Some(_) => {
diff --git a/crates/hir-def/src/resolver.rs b/crates/hir-def/src/resolver.rs
index c8d3052102..f3dcdcfa4a 100644
--- a/crates/hir-def/src/resolver.rs
+++ b/crates/hir-def/src/resolver.rs
@@ -508,13 +508,8 @@ impl Scope {
                 m.def_map[m.module_id].scope.entries().for_each(|(name, def)| {
                     acc.add_per_ns(name, def);
                 });
-                m.def_map[m.module_id].scope.legacy_macros().for_each(|(name, macs)| {
-                    macs.iter().for_each(|&mac| {
-                        acc.add(
-                            name,
-                            ScopeDef::ModuleDef(ModuleDefId::MacroId(MacroId::from(mac))),
-                        );
-                    })
+                m.def_map[m.module_id].scope.legacy_macros().for_each(|(name, mac)| {
+                    acc.add(name, ScopeDef::ModuleDef(ModuleDefId::MacroId(MacroId::from(mac))));
                 });
                 m.def_map.extern_prelude().for_each(|(name, &def)| {
                     acc.add(name, ScopeDef::ModuleDef(ModuleDefId::ModuleId(def)));
diff --git a/crates/hir-def/src/type_ref.rs b/crates/hir-def/src/type_ref.rs
index 81a2f024b3..867d82f45a 100644
--- a/crates/hir-def/src/type_ref.rs
+++ b/crates/hir-def/src/type_ref.rs
@@ -1,14 +1,21 @@
 //! HIR for references to types. Paths in these are not yet resolved. They can
 //! be directly created from an ast::TypeRef, without further queries.
 
+use std::fmt::Write;
+
 use hir_expand::{
     name::{AsName, Name},
     AstId, InFile,
 };
-use std::{convert::TryInto, fmt::Write};
 use syntax::ast::{self, HasName};
 
-use crate::{body::LowerCtx, intern::Interned, path::Path};
+use crate::{
+    body::LowerCtx,
+    builtin_type::{BuiltinInt, BuiltinType, BuiltinUint},
+    expr::Literal,
+    intern::Interned,
+    path::Path,
+};
 
 #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
 pub enum Mutability {
@@ -178,7 +185,6 @@ impl TypeRef {
                 // `hir_ty` level, which would allow knowing the type of:
                 // let v: [u8; 2 + 2] = [0u8; 4];
                 let len = ConstScalarOrPath::from_expr_opt(inner.expr());
-
                 TypeRef::Array(Box::new(TypeRef::from_ast_opt(ctx, inner.ty())), len)
             }
             ast::Type::SliceType(inner) => {
@@ -403,22 +409,31 @@ impl ConstScalarOrPath {
                     None => Self::Scalar(ConstScalar::Unknown),
                 }
             }
-            ast::Expr::Literal(lit) => {
-                let lkind = lit.kind();
-                match lkind {
-                    ast::LiteralKind::IntNumber(num)
-                        if num.suffix() == None || num.suffix() == Some("usize") =>
-                    {
-                        Self::Scalar(
-                            num.value()
-                                .and_then(|v| v.try_into().ok())
-                                .map(ConstScalar::Usize)
-                                .unwrap_or(ConstScalar::Unknown),
-                        )
+            ast::Expr::PrefixExpr(prefix_expr) => match prefix_expr.op_kind() {
+                Some(ast::UnaryOp::Neg) => {
+                    let unsigned = prefix_expr
+                        .expr()
+                        .map_or(Self::Scalar(ConstScalar::Unknown), Self::from_expr);
+                    // Add sign
+                    match unsigned {
+                        Self::Scalar(ConstScalar::UInt(num)) => {
+                            Self::Scalar(ConstScalar::Int(-(num as i128)))
+                        }
+                        other => other,
                     }
-                    _ => Self::Scalar(ConstScalar::Unknown),
                 }
-            }
+                _ => prefix_expr.expr().map_or(Self::Scalar(ConstScalar::Unknown), Self::from_expr),
+            },
+            ast::Expr::Literal(literal) => Self::Scalar(match literal.kind() {
+                ast::LiteralKind::IntNumber(num) => {
+                    num.value().map(ConstScalar::UInt).unwrap_or(ConstScalar::Unknown)
+                }
+                ast::LiteralKind::Char(c) => {
+                    c.value().map(ConstScalar::Char).unwrap_or(ConstScalar::Unknown)
+                }
+                ast::LiteralKind::Bool(f) => ConstScalar::Bool(f),
+                _ => ConstScalar::Unknown,
+            }),
             _ => Self::Scalar(ConstScalar::Unknown),
         }
     }
@@ -427,9 +442,10 @@ impl ConstScalarOrPath {
 /// A concrete constant value
 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
 pub enum ConstScalar {
-    // for now, we only support the trivial case of constant evaluating the length of an array
-    // Note that this is u64 because the target usize may be bigger than our usize
-    Usize(u64),
+    Int(i128),
+    UInt(u128),
+    Bool(bool),
+    Char(char),
 
     /// Case of an unknown value that rustc might know but we don't
     // FIXME: this is a hack to get around chalk not being able to represent unevaluatable
@@ -439,21 +455,37 @@ pub enum ConstScalar {
     Unknown,
 }
 
-impl std::fmt::Display for ConstScalar {
-    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
+impl ConstScalar {
+    pub fn builtin_type(&self) -> BuiltinType {
         match self {
-            ConstScalar::Usize(us) => us.fmt(f),
-            ConstScalar::Unknown => f.write_char('_'),
+            ConstScalar::UInt(_) | ConstScalar::Unknown => BuiltinType::Uint(BuiltinUint::U128),
+            ConstScalar::Int(_) => BuiltinType::Int(BuiltinInt::I128),
+            ConstScalar::Char(_) => BuiltinType::Char,
+            ConstScalar::Bool(_) => BuiltinType::Bool,
         }
     }
 }
 
-impl ConstScalar {
-    /// Gets a target usize out of the ConstScalar
-    pub fn as_usize(&self) -> Option<u64> {
+impl From<Literal> for ConstScalar {
+    fn from(literal: Literal) -> Self {
+        match literal {
+            Literal::Char(c) => Self::Char(c),
+            Literal::Bool(flag) => Self::Bool(flag),
+            Literal::Int(num, _) => Self::Int(num),
+            Literal::Uint(num, _) => Self::UInt(num),
+            _ => Self::Unknown,
+        }
+    }
+}
+
+impl std::fmt::Display for ConstScalar {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
         match self {
-            &ConstScalar::Usize(us) => Some(us),
-            _ => None,
+            ConstScalar::Int(num) => num.fmt(f),
+            ConstScalar::UInt(num) => num.fmt(f),
+            ConstScalar::Bool(flag) => flag.fmt(f),
+            ConstScalar::Char(c) => write!(f, "'{c}'"),
+            ConstScalar::Unknown => f.write_char('_'),
         }
     }
 }
diff --git a/crates/hir-expand/src/db.rs b/crates/hir-expand/src/db.rs
index bd60c3d268..8c08fdcd2e 100644
--- a/crates/hir-expand/src/db.rs
+++ b/crates/hir-expand/src/db.rs
@@ -150,7 +150,7 @@ pub fn expand_speculative(
     // Build the subtree and token mapping for the speculative args
     let censor = censor_for_macro_input(&loc, speculative_args);
     let mut fixups = fixup::fixup_syntax(speculative_args);
-    fixups.replace.extend(censor.into_iter().map(|node| (node.into(), Vec::new())));
+    fixups.replace.extend(censor.into_iter().map(|node| (node, Vec::new())));
     let (mut tt, spec_args_tmap, _) = mbe::syntax_node_to_token_tree_with_modifications(
         speculative_args,
         fixups.token_map,
@@ -295,7 +295,7 @@ fn macro_arg(
     let node = SyntaxNode::new_root(arg);
     let censor = censor_for_macro_input(&loc, &node);
     let mut fixups = fixup::fixup_syntax(&node);
-    fixups.replace.extend(censor.into_iter().map(|node| (node.into(), Vec::new())));
+    fixups.replace.extend(censor.into_iter().map(|node| (node, Vec::new())));
     let (mut tt, tmap, _) = mbe::syntax_node_to_token_tree_with_modifications(
         &node,
         fixups.token_map,
diff --git a/crates/hir-expand/src/fixup.rs b/crates/hir-expand/src/fixup.rs
index 9999790fae..c924478cec 100644
--- a/crates/hir-expand/src/fixup.rs
+++ b/crates/hir-expand/src/fixup.rs
@@ -6,7 +6,7 @@ use mbe::{SyntheticToken, SyntheticTokenId, TokenMap};
 use rustc_hash::FxHashMap;
 use syntax::{
     ast::{self, AstNode},
-    match_ast, SyntaxElement, SyntaxKind, SyntaxNode, TextRange,
+    match_ast, SyntaxKind, SyntaxNode, TextRange,
 };
 use tt::Subtree;
 
@@ -15,8 +15,8 @@ use tt::Subtree;
 /// reverse those changes afterwards, and a token map.
 #[derive(Debug)]
 pub(crate) struct SyntaxFixups {
-    pub(crate) append: FxHashMap<SyntaxElement, Vec<SyntheticToken>>,
-    pub(crate) replace: FxHashMap<SyntaxElement, Vec<SyntheticToken>>,
+    pub(crate) append: FxHashMap<SyntaxNode, Vec<SyntheticToken>>,
+    pub(crate) replace: FxHashMap<SyntaxNode, Vec<SyntheticToken>>,
     pub(crate) undo_info: SyntaxFixupUndoInfo,
     pub(crate) token_map: TokenMap,
     pub(crate) next_id: u32,
@@ -31,8 +31,8 @@ pub struct SyntaxFixupUndoInfo {
 const EMPTY_ID: SyntheticTokenId = SyntheticTokenId(!0);
 
 pub(crate) fn fixup_syntax(node: &SyntaxNode) -> SyntaxFixups {
-    let mut append = FxHashMap::<SyntaxElement, _>::default();
-    let mut replace = FxHashMap::<SyntaxElement, _>::default();
+    let mut append = FxHashMap::default();
+    let mut replace = FxHashMap::default();
     let mut preorder = node.preorder();
     let mut original = Vec::new();
     let mut token_map = TokenMap::default();
@@ -63,7 +63,7 @@ pub(crate) fn fixup_syntax(node: &SyntaxNode) -> SyntaxFixups {
                 range: node.text_range(),
                 id: SyntheticTokenId(idx),
             };
-            replace.insert(node.clone().into(), vec![replacement]);
+            replace.insert(node.clone(), vec![replacement]);
             preorder.skip_subtree();
             continue;
         }
@@ -75,7 +75,7 @@ pub(crate) fn fixup_syntax(node: &SyntaxNode) -> SyntaxFixups {
                 ast::FieldExpr(it) => {
                     if it.name_ref().is_none() {
                         // incomplete field access: some_expr.|
-                        append.insert(node.clone().into(), vec![
+                        append.insert(node.clone(), vec![
                             SyntheticToken {
                                 kind: SyntaxKind::IDENT,
                                 text: "__ra_fixup".into(),
@@ -87,7 +87,7 @@ pub(crate) fn fixup_syntax(node: &SyntaxNode) -> SyntaxFixups {
                 },
                 ast::ExprStmt(it) => {
                     if it.semicolon_token().is_none() {
-                        append.insert(node.clone().into(), vec![
+                        append.insert(node.clone(), vec![
                             SyntheticToken {
                                 kind: SyntaxKind::SEMICOLON,
                                 text: ";".into(),
@@ -99,7 +99,7 @@ pub(crate) fn fixup_syntax(node: &SyntaxNode) -> SyntaxFixups {
                 },
                 ast::LetStmt(it) => {
                     if it.semicolon_token().is_none() {
-                        append.insert(node.clone().into(), vec![
+                        append.insert(node.clone(), vec![
                             SyntheticToken {
                                 kind: SyntaxKind::SEMICOLON,
                                 text: ";".into(),
@@ -109,41 +109,6 @@ pub(crate) fn fixup_syntax(node: &SyntaxNode) -> SyntaxFixups {
                         ]);
                     }
                 },
-                ast::IfExpr(it) => {
-                    if it.condition().is_none() {
-                        // insert placeholder token after the if token
-                        let if_token = match it.if_token() {
-                            Some(t) => t,
-                            None => continue,
-                        };
-                        append.insert(if_token.into(), vec![
-                            SyntheticToken {
-                                kind: SyntaxKind::IDENT,
-                                text: "__ra_fixup".into(),
-                                range: end_range,
-                                id: EMPTY_ID,
-                            },
-                        ]);
-                    }
-                    if it.then_branch().is_none() {
-                        append.insert(node.clone().into(), vec![
-                            SyntheticToken {
-                                kind: SyntaxKind::L_CURLY,
-                                text: "{".into(),
-                                range: end_range,
-                                id: EMPTY_ID,
-                            },
-                            SyntheticToken {
-                                kind: SyntaxKind::R_CURLY,
-                                text: "}".into(),
-                                range: end_range,
-                                id: EMPTY_ID,
-                            },
-                        ]);
-                    }
-                },
-                // FIXME: foo::
-                // FIXME: for, loop, match etc.
                 _ => (),
             }
         }
@@ -179,10 +144,7 @@ pub(crate) fn reverse_fixups(
             token_map.synthetic_token_id(leaf.id()).is_none()
                 || token_map.synthetic_token_id(leaf.id()) != Some(EMPTY_ID)
         }
-        tt::TokenTree::Subtree(st) => st.delimiter.map_or(true, |d| {
-            token_map.synthetic_token_id(d.id).is_none()
-                || token_map.synthetic_token_id(d.id) != Some(EMPTY_ID)
-        }),
+        _ => true,
     });
     tt.token_trees.iter_mut().for_each(|tt| match tt {
         tt::TokenTree::Subtree(tt) => reverse_fixups(tt, token_map, undo_info),
@@ -333,49 +295,6 @@ fn foo() {
 "#,
             expect![[r#"
 fn foo () {__ra_fixup ;}
-"#]],
-        )
-    }
-
-    #[test]
-    fn fixup_if_1() {
-        check(
-            r#"
-fn foo() {
-    if a
-}
-"#,
-            expect![[r#"
-fn foo () {if a {}}
-"#]],
-        )
-    }
-
-    #[test]
-    fn fixup_if_2() {
-        check(
-            r#"
-fn foo() {
-    if
-}
-"#,
-            expect![[r#"
-fn foo () {if __ra_fixup {}}
-"#]],
-        )
-    }
-
-    #[test]
-    fn fixup_if_3() {
-        check(
-            r#"
-fn foo() {
-    if {}
-}
-"#,
-            // the {} gets parsed as the condition, I think?
-            expect![[r#"
-fn foo () {if {} {}}
 "#]],
         )
     }
diff --git a/crates/hir-expand/src/lib.rs b/crates/hir-expand/src/lib.rs
index 8fcfad2009..0844e1f625 100644
--- a/crates/hir-expand/src/lib.rs
+++ b/crates/hir-expand/src/lib.rs
@@ -778,19 +778,36 @@ impl<'a> InFile<&'a SyntaxNode> {
     /// For attributes and derives, this will point back to the attribute only.
     /// For the entire item `InFile::use original_file_range_full`.
     pub fn original_file_range(self, db: &dyn db::AstDatabase) -> FileRange {
+        if let Some(res) = self.original_file_range_opt(db) {
+            return res;
+        }
+
+        // Fall back to whole macro call.
         match self.file_id.0 {
             HirFileIdRepr::FileId(file_id) => FileRange { file_id, range: self.value.text_range() },
             HirFileIdRepr::MacroFile(mac_file) => {
-                if let Some(res) = self.original_file_range_opt(db) {
-                    return res;
-                }
-                // Fall back to whole macro call.
                 let loc = db.lookup_intern_macro_call(mac_file.macro_call_id);
                 loc.kind.original_call_range(db)
             }
         }
     }
 
+    /// Falls back to the macro call range if the node cannot be mapped up fully.
+    pub fn original_file_range_full(self, db: &dyn db::AstDatabase) -> FileRange {
+        if let Some(res) = self.original_file_range_opt(db) {
+            return res;
+        }
+
+        // Fall back to whole macro call.
+        match self.file_id.0 {
+            HirFileIdRepr::FileId(file_id) => FileRange { file_id, range: self.value.text_range() },
+            HirFileIdRepr::MacroFile(mac_file) => {
+                let loc = db.lookup_intern_macro_call(mac_file.macro_call_id);
+                loc.kind.original_call_range_with_body(db)
+            }
+        }
+    }
+
     /// Attempts to map the syntax node back up its macro calls.
     pub fn original_file_range_opt(self, db: &dyn db::AstDatabase) -> Option<FileRange> {
         match ascend_node_border_tokens(db, self) {
@@ -817,49 +834,6 @@ impl InFile<SyntaxToken> {
         let expansion = self.file_id.expansion_info(db)?;
         expansion.map_token_up(db, self.as_ref()).map(|(it, _)| it)
     }
-
-    /// Falls back to the macro call range if the node cannot be mapped up fully.
-    pub fn original_file_range(self, db: &dyn db::AstDatabase) -> FileRange {
-        match self.file_id.0 {
-            HirFileIdRepr::FileId(file_id) => FileRange { file_id, range: self.value.text_range() },
-            HirFileIdRepr::MacroFile(mac_file) => {
-                if let Some(res) = self.original_file_range_opt(db) {
-                    return res;
-                }
-                // Fall back to whole macro call.
-                let loc = db.lookup_intern_macro_call(mac_file.macro_call_id);
-                loc.kind.original_call_range(db)
-            }
-        }
-    }
-
-    /// Attempts to map the syntax node back up its macro calls.
-    pub fn original_file_range_opt(self, db: &dyn db::AstDatabase) -> Option<FileRange> {
-        match self.file_id.0 {
-            HirFileIdRepr::FileId(file_id) => {
-                Some(FileRange { file_id, range: self.value.text_range() })
-            }
-            HirFileIdRepr::MacroFile(_) => {
-                let expansion = self.file_id.expansion_info(db)?;
-                let InFile { file_id, value } = ascend_call_token(db, &expansion, self)?;
-                let original_file = file_id.original_file(db);
-                if file_id != original_file.into() {
-                    return None;
-                }
-                Some(FileRange { file_id: original_file, range: value.text_range() })
-            }
-        }
-    }
-
-    pub fn ancestors_with_macros(
-        self,
-        db: &dyn db::AstDatabase,
-    ) -> impl Iterator<Item = InFile<SyntaxNode>> + '_ {
-        self.value.parent().into_iter().flat_map({
-            let file_id = self.file_id;
-            move |parent| InFile::new(file_id, &parent).ancestors_with_macros(db)
-        })
-    }
 }
 
 fn ascend_node_border_tokens(
@@ -893,6 +867,18 @@ fn ascend_call_token(
     None
 }
 
+impl InFile<SyntaxToken> {
+    pub fn ancestors_with_macros(
+        self,
+        db: &dyn db::AstDatabase,
+    ) -> impl Iterator<Item = InFile<SyntaxNode>> + '_ {
+        self.value.parent().into_iter().flat_map({
+            let file_id = self.file_id;
+            move |parent| InFile::new(file_id, &parent).ancestors_with_macros(db)
+        })
+    }
+}
+
 impl<N: AstNode> InFile<N> {
     pub fn descendants<T: AstNode>(self) -> impl Iterator<Item = InFile<T>> {
         self.value.syntax().descendants().filter_map(T::cast).map(move |n| self.with_value(n))
diff --git a/crates/hir-ty/src/consteval.rs b/crates/hir-ty/src/consteval.rs
index 4b58262dac..0495a4e64c 100644
--- a/crates/hir-ty/src/consteval.rs
+++ b/crates/hir-ty/src/consteval.rs
@@ -347,17 +347,6 @@ pub fn eval_const(
     }
 }
 
-pub fn eval_usize(expr: Idx<Expr>, mut ctx: ConstEvalCtx<'_>) -> Option<u64> {
-    if let Ok(ce) = eval_const(expr, &mut ctx) {
-        match ce {
-            ComputedExpr::Literal(Literal::Int(x, _)) => return x.try_into().ok(),
-            ComputedExpr::Literal(Literal::Uint(x, _)) => return x.try_into().ok(),
-            _ => {}
-        }
-    }
-    None
-}
-
 pub(crate) fn path_to_const(
     db: &dyn HirDatabase,
     resolver: &Resolver,
@@ -406,17 +395,14 @@ pub fn unknown_const_as_generic(ty: Ty) -> GenericArg {
 }
 
 /// Interns a constant scalar with the given type
-pub fn intern_scalar_const(value: ConstScalar, ty: Ty) -> Const {
+pub fn intern_const_scalar(value: ConstScalar, ty: Ty) -> Const {
     ConstData { ty, value: ConstValue::Concrete(chalk_ir::ConcreteConst { interned: value }) }
         .intern(Interner)
 }
 
 /// Interns a possibly-unknown target usize
-pub fn usize_const(value: Option<u64>) -> Const {
-    intern_scalar_const(
-        value.map(ConstScalar::Usize).unwrap_or(ConstScalar::Unknown),
-        TyBuilder::usize(),
-    )
+pub fn usize_const(value: Option<u128>) -> Const {
+    intern_const_scalar(value.map_or(ConstScalar::Unknown, ConstScalar::UInt), TyBuilder::usize())
 }
 
 pub(crate) fn const_eval_recover(
@@ -463,7 +449,7 @@ pub(crate) fn eval_to_const<'a>(
         }
     }
     let body = ctx.body.clone();
-    let ctx = ConstEvalCtx {
+    let mut ctx = ConstEvalCtx {
         db: ctx.db,
         owner: ctx.owner,
         exprs: &body.exprs,
@@ -471,7 +457,12 @@ pub(crate) fn eval_to_const<'a>(
         local_data: HashMap::default(),
         infer: &ctx.result,
     };
-    usize_const(eval_usize(expr, ctx))
+    let computed_expr = eval_const(expr, &mut ctx);
+    let const_scalar = match computed_expr {
+        Ok(ComputedExpr::Literal(literal)) => literal.into(),
+        _ => ConstScalar::Unknown,
+    };
+    intern_const_scalar(const_scalar, TyBuilder::usize())
 }
 
 #[cfg(test)]
diff --git a/crates/hir-ty/src/infer.rs b/crates/hir-ty/src/infer.rs
index ecadfb6ce4..c7c8deaaee 100644
--- a/crates/hir-ty/src/infer.rs
+++ b/crates/hir-ty/src/infer.rs
@@ -605,10 +605,10 @@ impl<'a> InferenceContext<'a> {
         let data = c.data(Interner);
         match data.value {
             ConstValue::Concrete(cc) => match cc.interned {
-                hir_def::type_ref::ConstScalar::Usize(_) => c,
                 hir_def::type_ref::ConstScalar::Unknown => {
                     self.table.new_const_var(data.ty.clone())
                 }
+                _ => c,
             },
             _ => c,
         }
diff --git a/crates/hir-ty/src/infer/expr.rs b/crates/hir-ty/src/infer/expr.rs
index 6dee0322a9..2f33467072 100644
--- a/crates/hir-ty/src/infer/expr.rs
+++ b/crates/hir-ty/src/infer/expr.rs
@@ -729,7 +729,7 @@ impl<'a> InferenceContext<'a> {
                             let cur_elem_ty = self.infer_expr_inner(expr, &expected);
                             coerce.coerce(self, Some(expr), &cur_elem_ty);
                         }
-                        consteval::usize_const(Some(items.len() as u64))
+                        consteval::usize_const(Some(items.len() as u128))
                     }
                     &Array::Repeat { initializer, repeat } => {
                         self.infer_expr_coerce(initializer, &Expectation::has_type(elem_ty));
@@ -766,7 +766,7 @@ impl<'a> InferenceContext<'a> {
                 Literal::ByteString(bs) => {
                     let byte_type = TyKind::Scalar(Scalar::Uint(UintTy::U8)).intern(Interner);
 
-                    let len = consteval::usize_const(Some(bs.len() as u64));
+                    let len = consteval::usize_const(Some(bs.len() as u128));
 
                     let array_type = TyKind::Array(byte_type, len).intern(Interner);
                     TyKind::Ref(Mutability::Not, static_lifetime(), array_type).intern(Interner)
diff --git a/crates/hir-ty/src/infer/pat.rs b/crates/hir-ty/src/infer/pat.rs
index dc86f696d4..5e7320a5dd 100644
--- a/crates/hir-ty/src/infer/pat.rs
+++ b/crates/hir-ty/src/infer/pat.rs
@@ -11,6 +11,7 @@ use hir_def::{
 use hir_expand::name::Name;
 
 use crate::{
+    consteval::intern_const_scalar,
     infer::{BindingMode, Expectation, InferenceContext, TypeMismatch},
     lower::lower_to_chalk_mutability,
     static_lifetime, ConcreteConst, ConstValue, Interner, Substitution, Ty, TyBuilder, TyExt,
@@ -262,13 +263,19 @@ impl<'a> InferenceContext<'a> {
                 if let &Some(slice_pat_id) = slice {
                     let rest_pat_ty = match expected.kind(Interner) {
                         TyKind::Array(_, length) => {
-                            let length = match length.data(Interner).value {
+                            let len = match length.data(Interner).value {
                                 ConstValue::Concrete(ConcreteConst {
-                                    interned: ConstScalar::Usize(length),
-                                }) => length.checked_sub((prefix.len() + suffix.len()) as u64),
+                                    interned: ConstScalar::UInt(len),
+                                }) => len.checked_sub((prefix.len() + suffix.len()) as u128),
                                 _ => None,
                             };
-                            TyKind::Array(elem_ty.clone(), crate::consteval::usize_const(length))
+                            TyKind::Array(
+                                elem_ty.clone(),
+                                intern_const_scalar(
+                                    len.map_or(ConstScalar::Unknown, |len| ConstScalar::UInt(len)),
+                                    TyBuilder::usize(),
+                                ),
+                            )
                         }
                         _ => TyKind::Slice(elem_ty.clone()),
                     }
diff --git a/crates/hir-ty/src/interner.rs b/crates/hir-ty/src/interner.rs
index 07197d8a19..c34c4b8a7c 100644
--- a/crates/hir-ty/src/interner.rs
+++ b/crates/hir-ty/src/interner.rs
@@ -257,12 +257,7 @@ impl chalk_ir::interner::Interner for Interner {
         c1: &Self::InternedConcreteConst,
         c2: &Self::InternedConcreteConst,
     ) -> bool {
-        match (c1, c2) {
-            (&ConstScalar::Usize(a), &ConstScalar::Usize(b)) => a == b,
-            // we were previously assuming this to be true, I'm not whether true or false on
-            // unknown values is safer.
-            (_, _) => true,
-        }
+        (c1 == &ConstScalar::Unknown) || (c2 == &ConstScalar::Unknown) || (c1 == c2)
     }
 
     fn intern_generic_arg(
diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs
index f9747f3b34..e86b52c987 100644
--- a/crates/hir-ty/src/lower.rs
+++ b/crates/hir-ty/src/lower.rs
@@ -44,7 +44,7 @@ use syntax::{ast, SmolStr};
 
 use crate::{
     all_super_traits,
-    consteval::{intern_scalar_const, path_to_const, unknown_const, unknown_const_as_generic},
+    consteval::{intern_const_scalar, path_to_const, unknown_const, unknown_const_as_generic},
     db::HirDatabase,
     make_binders,
     mapping::ToChalk,
@@ -1742,7 +1742,7 @@ pub(crate) fn const_or_path_to_chalk(
     debruijn: DebruijnIndex,
 ) -> Const {
     match value {
-        ConstScalarOrPath::Scalar(s) => intern_scalar_const(s.clone(), expected_ty),
+        ConstScalarOrPath::Scalar(s) => intern_const_scalar(s.clone(), expected_ty),
         ConstScalarOrPath::Path(n) => {
             let path = ModPath::from_segments(PathKind::Plain, Some(n.clone()));
             path_to_const(db, resolver, &path, mode, args, debruijn)
diff --git a/crates/hir/src/display.rs b/crates/hir/src/display.rs
index b4fd70d082..e26c8440d9 100644
--- a/crates/hir/src/display.rs
+++ b/crates/hir/src/display.rs
@@ -505,7 +505,7 @@ impl HirDisplay for Module {
         // FIXME: Module doesn't have visibility saved in data.
         match self.name(f.db) {
             Some(name) => write!(f, "mod {}", name),
-            None if self.is_crate_root(f.db) => match self.krate(f.db).display_name(f.db) {
+            None if self.is_crate_root(f.db) => match self.krate().display_name(f.db) {
                 Some(name) => write!(f, "extern crate {}", name),
                 None => f.write_str("extern crate {unknown}"),
             },
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index 7e262b4e4c..96424d087e 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -560,7 +560,7 @@ impl Module {
     pub fn legacy_macros(self, db: &dyn HirDatabase) -> Vec<Macro> {
         let def_map = self.id.def_map(db.upcast());
         let scope = &def_map[self.id.local_id].scope;
-        scope.legacy_macros().flat_map(|(_, it)| it).map(|&it| MacroId::from(it).into()).collect()
+        scope.legacy_macros().map(|(_, it)| MacroId::from(it).into()).collect()
     }
 
     pub fn impl_defs(self, db: &dyn HirDatabase) -> Vec<Impl> {
@@ -3307,15 +3307,6 @@ impl Type {
         let tys = hir_ty::replace_errors_with_variables(&(self.ty.clone(), to.ty.clone()));
         hir_ty::could_coerce(db, self.env.clone(), &tys)
     }
-
-    pub fn as_type_param(&self, db: &dyn HirDatabase) -> Option<TypeParam> {
-        match self.ty.kind(Interner) {
-            TyKind::Placeholder(p) => Some(TypeParam {
-                id: TypeParamId::from_unchecked(hir_ty::from_placeholder_idx(db, *p)),
-            }),
-            _ => None,
-        }
-    }
 }
 
 #[derive(Debug)]
@@ -3582,27 +3573,3 @@ impl HasCrate for Macro {
         self.module(db).krate()
     }
 }
-
-impl HasCrate for Trait {
-    fn krate(&self, db: &dyn HirDatabase) -> Crate {
-        self.module(db).krate()
-    }
-}
-
-impl HasCrate for Static {
-    fn krate(&self, db: &dyn HirDatabase) -> Crate {
-        self.module(db).krate()
-    }
-}
-
-impl HasCrate for Adt {
-    fn krate(&self, db: &dyn HirDatabase) -> Crate {
-        self.module(db).krate()
-    }
-}
-
-impl HasCrate for Module {
-    fn krate(&self, _: &dyn HirDatabase) -> Crate {
-        Module::krate(*self)
-    }
-}
diff --git a/crates/hir/src/symbols.rs b/crates/hir/src/symbols.rs
index 3b84877dd3..bdb8c7552d 100644
--- a/crates/hir/src/symbols.rs
+++ b/crates/hir/src/symbols.rs
@@ -176,13 +176,11 @@ impl<'a> SymbolCollector<'a> {
         }
 
         for (_, id) in scope.legacy_macros() {
-            for &id in id {
-                if id.module(self.db.upcast()) == module_id {
-                    match id {
-                        MacroId::Macro2Id(id) => self.push_decl(id, FileSymbolKind::Macro),
-                        MacroId::MacroRulesId(id) => self.push_decl(id, FileSymbolKind::Macro),
-                        MacroId::ProcMacroId(id) => self.push_decl(id, FileSymbolKind::Macro),
-                    }
+            if id.module(self.db.upcast()) == module_id {
+                match id {
+                    MacroId::Macro2Id(id) => self.push_decl(id, FileSymbolKind::Macro),
+                    MacroId::MacroRulesId(id) => self.push_decl(id, FileSymbolKind::Macro),
+                    MacroId::ProcMacroId(id) => self.push_decl(id, FileSymbolKind::Macro),
                 }
             }
         }
diff --git a/crates/ide-assists/src/handlers/auto_import.rs b/crates/ide-assists/src/handlers/auto_import.rs
index 802449f858..1ec24d8fcc 100644
--- a/crates/ide-assists/src/handlers/auto_import.rs
+++ b/crates/ide-assists/src/handlers/auto_import.rs
@@ -40,7 +40,7 @@ use crate::{AssistContext, AssistId, AssistKind, Assists, GroupLabel};
 //
 // .Import Granularity
 //
-// It is possible to configure how use-trees are merged with the `imports.granularity.group` setting.
+// It is possible to configure how use-trees are merged with the `importGranularity` setting.
 // It has the following configurations:
 //
 // - `crate`: Merge imports from the same crate into a single use statement. This kind of
@@ -50,11 +50,11 @@ use crate::{AssistContext, AssistId, AssistKind, Assists, GroupLabel};
 // - `preserve`: Do not change the granularity of any imports. For auto-import this has the same
 //  effect as `item`.
 //
-// In `VS Code` the configuration for this is `rust-analyzer.imports.granularity.group`.
+// In `VS Code` the configuration for this is `rust-analyzer.assist.importGranularity`.
 //
 // .Import Prefix
 //
-// The style of imports in the same crate is configurable through the `imports.prefix` setting.
+// The style of imports in the same crate is configurable through the `importPrefix` setting.
 // It has the following configurations:
 //
 // - `crate`: This setting will force paths to be always absolute, starting with the `crate`
@@ -64,7 +64,7 @@ use crate::{AssistContext, AssistId, AssistKind, Assists, GroupLabel};
 //  `super` or an extern crate identifier.
 // - `plain`: This setting does not impose any restrictions in imports.
 //
-// In `VS Code` the configuration for this is `rust-analyzer.imports.prefix`.
+// In `VS Code` the configuration for this is `rust-analyzer.assist.importPrefix`.
 //
 // image::https://user-images.githubusercontent.com/48062697/113020673-b85be580-917a-11eb-9022-59585f35d4f8.gif[]
 
diff --git a/crates/ide-assists/src/handlers/extract_function.rs b/crates/ide-assists/src/handlers/extract_function.rs
index 94b638d4c6..9233c198df 100644
--- a/crates/ide-assists/src/handlers/extract_function.rs
+++ b/crates/ide-assists/src/handlers/extract_function.rs
@@ -2,9 +2,7 @@ use std::iter;
 
 use ast::make;
 use either::Either;
-use hir::{
-    HasSource, HirDisplay, InFile, Local, ModuleDef, PathResolution, Semantics, TypeInfo, TypeParam,
-};
+use hir::{HasSource, HirDisplay, InFile, Local, ModuleDef, Semantics, TypeInfo};
 use ide_db::{
     defs::{Definition, NameRefClass},
     famous_defs::FamousDefs,
@@ -20,7 +18,7 @@ use syntax::{
     ast::{
         self,
         edit::{AstNodeEdit, IndentLevel},
-        AstNode, HasGenericParams,
+        AstNode,
     },
     match_ast, ted, SyntaxElement,
     SyntaxKind::{self, COMMENT},
@@ -296,8 +294,6 @@ struct ContainerInfo {
     parent_loop: Option<SyntaxNode>,
     /// The function's return type, const's type etc.
     ret_type: Option<hir::Type>,
-    generic_param_lists: Vec<ast::GenericParamList>,
-    where_clauses: Vec<ast::WhereClause>,
 }
 
 /// Control flow that is exported from extracted function
@@ -521,24 +517,6 @@ impl FunctionBody {
         }
     }
 
-    fn descendants(&self) -> impl Iterator<Item = SyntaxNode> {
-        match self {
-            FunctionBody::Expr(expr) => expr.syntax().descendants(),
-            FunctionBody::Span { parent, .. } => parent.syntax().descendants(),
-        }
-    }
-
-    fn descendant_paths(&self) -> impl Iterator<Item = ast::Path> {
-        self.descendants().filter_map(|node| {
-            match_ast! {
-                match node {
-                    ast::Path(it) => Some(it),
-                    _ => None
-                }
-            }
-        })
-    }
-
     fn from_expr(expr: ast::Expr) -> Option<Self> {
         match expr {
             ast::Expr::BreakExpr(it) => it.expr().map(Self::Expr),
@@ -753,7 +731,6 @@ impl FunctionBody {
                 parent_loop.get_or_insert(loop_.syntax().clone());
             }
         };
-
         let (is_const, expr, ty) = loop {
             let anc = ancestors.next()?;
             break match_ast! {
@@ -821,20 +798,7 @@ impl FunctionBody {
             container_tail.zip(self.tail_expr()).map_or(false, |(container_tail, body_tail)| {
                 container_tail.syntax().text_range().contains_range(body_tail.syntax().text_range())
             });
-
-        let parent = self.parent()?;
-        let parents = generic_parents(&parent);
-        let generic_param_lists = parents.iter().filter_map(|it| it.generic_param_list()).collect();
-        let where_clauses = parents.iter().filter_map(|it| it.where_clause()).collect();
-
-        Some(ContainerInfo {
-            is_in_tail,
-            is_const,
-            parent_loop,
-            ret_type: ty,
-            generic_param_lists,
-            where_clauses,
-        })
+        Some(ContainerInfo { is_in_tail, is_const, parent_loop, ret_type: ty })
     }
 
     fn return_ty(&self, ctx: &AssistContext) -> Option<RetType> {
@@ -991,56 +955,6 @@ impl FunctionBody {
     }
 }
 
-enum GenericParent {
-    Fn(ast::Fn),
-    Impl(ast::Impl),
-    Trait(ast::Trait),
-}
-
-impl GenericParent {
-    fn generic_param_list(&self) -> Option<ast::GenericParamList> {
-        match self {
-            GenericParent::Fn(fn_) => fn_.generic_param_list(),
-            GenericParent::Impl(impl_) => impl_.generic_param_list(),
-            GenericParent::Trait(trait_) => trait_.generic_param_list(),
-        }
-    }
-
-    fn where_clause(&self) -> Option<ast::WhereClause> {
-        match self {
-            GenericParent::Fn(fn_) => fn_.where_clause(),
-            GenericParent::Impl(impl_) => impl_.where_clause(),
-            GenericParent::Trait(trait_) => trait_.where_clause(),
-        }
-    }
-}
-
-/// Search `parent`'s ancestors for items with potentially applicable generic parameters
-fn generic_parents(parent: &SyntaxNode) -> Vec<GenericParent> {
-    let mut list = Vec::new();
-    if let Some(parent_item) = parent.ancestors().find_map(ast::Item::cast) {
-        match parent_item {
-            ast::Item::Fn(ref fn_) => {
-                if let Some(parent_parent) = parent_item
-                    .syntax()
-                    .parent()
-                    .and_then(|it| it.parent())
-                    .and_then(ast::Item::cast)
-                {
-                    match parent_parent {
-                        ast::Item::Impl(impl_) => list.push(GenericParent::Impl(impl_)),
-                        ast::Item::Trait(trait_) => list.push(GenericParent::Trait(trait_)),
-                        _ => (),
-                    }
-                }
-                list.push(GenericParent::Fn(fn_.clone()));
-            }
-            _ => (),
-        }
-    }
-    list
-}
-
 /// checks if relevant var is used with `&mut` access inside body
 fn has_exclusive_usages(ctx: &AssistContext, usages: &LocalUsages, body: &FunctionBody) -> bool {
     usages
@@ -1448,154 +1362,37 @@ fn format_function(
     let const_kw = if fun.mods.is_const { "const " } else { "" };
     let async_kw = if fun.control_flow.is_async { "async " } else { "" };
     let unsafe_kw = if fun.control_flow.is_unsafe { "unsafe " } else { "" };
-    let (generic_params, where_clause) = make_generic_params_and_where_clause(ctx, fun);
     match ctx.config.snippet_cap {
         Some(_) => format_to!(
             fn_def,
-            "\n\n{}{}{}{}fn $0{}",
+            "\n\n{}{}{}{}fn $0{}{}",
             new_indent,
             const_kw,
             async_kw,
             unsafe_kw,
             fun.name,
+            params
         ),
         None => format_to!(
             fn_def,
-            "\n\n{}{}{}{}fn {}",
+            "\n\n{}{}{}{}fn {}{}",
             new_indent,
             const_kw,
             async_kw,
             unsafe_kw,
             fun.name,
+            params
         ),
     }
-
-    if let Some(generic_params) = generic_params {
-        format_to!(fn_def, "{}", generic_params);
-    }
-
-    format_to!(fn_def, "{}", params);
-
     if let Some(ret_ty) = ret_ty {
         format_to!(fn_def, " {}", ret_ty);
     }
-
-    if let Some(where_clause) = where_clause {
-        format_to!(fn_def, " {}", where_clause);
-    }
-
     format_to!(fn_def, " {}", body);
 
     fn_def
 }
 
-fn make_generic_params_and_where_clause(
-    ctx: &AssistContext,
-    fun: &Function,
-) -> (Option<ast::GenericParamList>, Option<ast::WhereClause>) {
-    let used_type_params = fun.type_params(ctx);
-
-    let generic_param_list = make_generic_param_list(ctx, fun, &used_type_params);
-    let where_clause = make_where_clause(ctx, fun, &used_type_params);
-
-    (generic_param_list, where_clause)
-}
-
-fn make_generic_param_list(
-    ctx: &AssistContext,
-    fun: &Function,
-    used_type_params: &[TypeParam],
-) -> Option<ast::GenericParamList> {
-    let mut generic_params = fun
-        .mods
-        .generic_param_lists
-        .iter()
-        .flat_map(|parent_params| {
-            parent_params
-                .generic_params()
-                .filter(|param| param_is_required(ctx, param, used_type_params))
-        })
-        .peekable();
-
-    if generic_params.peek().is_some() {
-        Some(make::generic_param_list(generic_params))
-    } else {
-        None
-    }
-}
-
-fn param_is_required(
-    ctx: &AssistContext,
-    param: &ast::GenericParam,
-    used_type_params: &[TypeParam],
-) -> bool {
-    match param {
-        ast::GenericParam::ConstParam(_) | ast::GenericParam::LifetimeParam(_) => false,
-        ast::GenericParam::TypeParam(type_param) => match &ctx.sema.to_def(type_param) {
-            Some(def) => used_type_params.contains(def),
-            _ => false,
-        },
-    }
-}
-
-fn make_where_clause(
-    ctx: &AssistContext,
-    fun: &Function,
-    used_type_params: &[TypeParam],
-) -> Option<ast::WhereClause> {
-    let mut predicates = fun
-        .mods
-        .where_clauses
-        .iter()
-        .flat_map(|parent_where_clause| {
-            parent_where_clause
-                .predicates()
-                .filter(|pred| pred_is_required(ctx, pred, used_type_params))
-        })
-        .peekable();
-
-    if predicates.peek().is_some() {
-        Some(make::where_clause(predicates))
-    } else {
-        None
-    }
-}
-
-fn pred_is_required(
-    ctx: &AssistContext,
-    pred: &ast::WherePred,
-    used_type_params: &[TypeParam],
-) -> bool {
-    match resolved_type_param(ctx, pred) {
-        Some(it) => used_type_params.contains(&it),
-        None => false,
-    }
-}
-
-fn resolved_type_param(ctx: &AssistContext, pred: &ast::WherePred) -> Option<TypeParam> {
-    let path = match pred.ty()? {
-        ast::Type::PathType(path_type) => path_type.path(),
-        _ => None,
-    }?;
-
-    match ctx.sema.resolve_path(&path)? {
-        PathResolution::TypeParam(type_param) => Some(type_param),
-        _ => None,
-    }
-}
-
 impl Function {
-    /// Collect all the `TypeParam`s used in the `body` and `params`.
-    fn type_params(&self, ctx: &AssistContext) -> Vec<TypeParam> {
-        let type_params_in_descendant_paths =
-            self.body.descendant_paths().filter_map(|it| match ctx.sema.resolve_path(&it) {
-                Some(PathResolution::TypeParam(type_param)) => Some(type_param),
-                _ => None,
-            });
-        let type_params_in_params = self.params.iter().filter_map(|p| p.ty.as_type_param(ctx.db()));
-        type_params_in_descendant_paths.chain(type_params_in_params).collect()
-    }
-
     fn make_param_list(&self, ctx: &AssistContext, module: hir::Module) -> ast::ParamList {
         let self_param = self.self_param.clone();
         let params = self.params.iter().map(|param| param.to_param(ctx, module));
@@ -5075,254 +4872,6 @@ fn parent(factor: i32) {
 fn $0fun_name(v: &[i32; 3], factor: i32) {
     v.iter().map(|it| it * factor);
 }
-"#,
-        );
-    }
-
-    #[test]
-    fn preserve_generics() {
-        check_assist(
-            extract_function,
-            r#"
-fn func<T: Debug>(i: T) {
-    $0foo(i);$0
-}
-"#,
-            r#"
-fn func<T: Debug>(i: T) {
-    fun_name(i);
-}
-
-fn $0fun_name<T: Debug>(i: T) {
-    foo(i);
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn preserve_generics_from_body() {
-        check_assist(
-            extract_function,
-            r#"
-fn func<T: Default>() -> T {
-    $0T::default()$0
-}
-"#,
-            r#"
-fn func<T: Default>() -> T {
-    fun_name()
-}
-
-fn $0fun_name<T: Default>() -> T {
-    T::default()
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn filter_unused_generics() {
-        check_assist(
-            extract_function,
-            r#"
-fn func<T: Debug, U: Copy>(i: T, u: U) {
-    bar(u);
-    $0foo(i);$0
-}
-"#,
-            r#"
-fn func<T: Debug, U: Copy>(i: T, u: U) {
-    bar(u);
-    fun_name(i);
-}
-
-fn $0fun_name<T: Debug>(i: T) {
-    foo(i);
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn empty_generic_param_list() {
-        check_assist(
-            extract_function,
-            r#"
-fn func<T: Debug>(t: T, i: u32) {
-    bar(t);
-    $0foo(i);$0
-}
-"#,
-            r#"
-fn func<T: Debug>(t: T, i: u32) {
-    bar(t);
-    fun_name(i);
-}
-
-fn $0fun_name(i: u32) {
-    foo(i);
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn preserve_where_clause() {
-        check_assist(
-            extract_function,
-            r#"
-fn func<T>(i: T) where T: Debug {
-    $0foo(i);$0
-}
-"#,
-            r#"
-fn func<T>(i: T) where T: Debug {
-    fun_name(i);
-}
-
-fn $0fun_name<T>(i: T) where T: Debug {
-    foo(i);
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn filter_unused_where_clause() {
-        check_assist(
-            extract_function,
-            r#"
-fn func<T, U>(i: T, u: U) where T: Debug, U: Copy {
-    bar(u);
-    $0foo(i);$0
-}
-"#,
-            r#"
-fn func<T, U>(i: T, u: U) where T: Debug, U: Copy {
-    bar(u);
-    fun_name(i);
-}
-
-fn $0fun_name<T>(i: T) where T: Debug {
-    foo(i);
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn nested_generics() {
-        check_assist(
-            extract_function,
-            r#"
-struct Struct<T: Into<i32>>(T);
-impl <T: Into<i32> + Copy> Struct<T> {
-    fn func<V: Into<i32>>(&self, v: V) -> i32 {
-        let t = self.0;
-        $0t.into() + v.into()$0
-    }
-}
-"#,
-            r#"
-struct Struct<T: Into<i32>>(T);
-impl <T: Into<i32> + Copy> Struct<T> {
-    fn func<V: Into<i32>>(&self, v: V) -> i32 {
-        let t = self.0;
-        fun_name(t, v)
-    }
-}
-
-fn $0fun_name<T: Into<i32> + Copy, V: Into<i32>>(t: T, v: V) -> i32 {
-    t.into() + v.into()
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn filters_unused_nested_generics() {
-        check_assist(
-            extract_function,
-            r#"
-struct Struct<T: Into<i32>, U: Debug>(T, U);
-impl <T: Into<i32> + Copy, U: Debug> Struct<T, U> {
-    fn func<V: Into<i32>>(&self, v: V) -> i32 {
-        let t = self.0;
-        $0t.into() + v.into()$0
-    }
-}
-"#,
-            r#"
-struct Struct<T: Into<i32>, U: Debug>(T, U);
-impl <T: Into<i32> + Copy, U: Debug> Struct<T, U> {
-    fn func<V: Into<i32>>(&self, v: V) -> i32 {
-        let t = self.0;
-        fun_name(t, v)
-    }
-}
-
-fn $0fun_name<T: Into<i32> + Copy, V: Into<i32>>(t: T, v: V) -> i32 {
-    t.into() + v.into()
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn nested_where_clauses() {
-        check_assist(
-            extract_function,
-            r#"
-struct Struct<T>(T) where T: Into<i32>;
-impl <T> Struct<T> where T: Into<i32> + Copy {
-    fn func<V>(&self, v: V) -> i32 where V: Into<i32> {
-        let t = self.0;
-        $0t.into() + v.into()$0
-    }
-}
-"#,
-            r#"
-struct Struct<T>(T) where T: Into<i32>;
-impl <T> Struct<T> where T: Into<i32> + Copy {
-    fn func<V>(&self, v: V) -> i32 where V: Into<i32> {
-        let t = self.0;
-        fun_name(t, v)
-    }
-}
-
-fn $0fun_name<T, V>(t: T, v: V) -> i32 where T: Into<i32> + Copy, V: Into<i32> {
-    t.into() + v.into()
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn filters_unused_nested_where_clauses() {
-        check_assist(
-            extract_function,
-            r#"
-struct Struct<T, U>(T, U) where T: Into<i32>, U: Debug;
-impl <T, U> Struct<T, U> where T: Into<i32> + Copy, U: Debug {
-    fn func<V>(&self, v: V) -> i32 where V: Into<i32> {
-        let t = self.0;
-        $0t.into() + v.into()$0
-    }
-}
-"#,
-            r#"
-struct Struct<T, U>(T, U) where T: Into<i32>, U: Debug;
-impl <T, U> Struct<T, U> where T: Into<i32> + Copy, U: Debug {
-    fn func<V>(&self, v: V) -> i32 where V: Into<i32> {
-        let t = self.0;
-        fun_name(t, v)
-    }
-}
-
-fn $0fun_name<T, V>(t: T, v: V) -> i32 where T: Into<i32> + Copy, V: Into<i32> {
-    t.into() + v.into()
-}
 "#,
         );
     }
diff --git a/crates/ide-assists/src/handlers/generate_function.rs b/crates/ide-assists/src/handlers/generate_function.rs
index 061a481344..c8650979e9 100644
--- a/crates/ide-assists/src/handlers/generate_function.rs
+++ b/crates/ide-assists/src/handlers/generate_function.rs
@@ -176,7 +176,7 @@ fn get_adt_source(
     adt: &hir::Adt,
     fn_name: &str,
 ) -> Option<(Option<ast::Impl>, FileId)> {
-    let range = adt.source(ctx.sema.db)?.syntax().original_file_range(ctx.sema.db);
+    let range = adt.source(ctx.sema.db)?.syntax().original_file_range_full(ctx.sema.db);
     let file = ctx.sema.parse(range.file_id);
     let adt_source =
         ctx.sema.find_node_at_offset_with_macros(file.syntax(), range.range.start())?;
diff --git a/crates/ide-assists/src/handlers/generate_new.rs b/crates/ide-assists/src/handlers/generate_new.rs
index 5f4715bb53..6a1f710f6d 100644
--- a/crates/ide-assists/src/handlers/generate_new.rs
+++ b/crates/ide-assists/src/handlers/generate_new.rs
@@ -1,6 +1,3 @@
-use ide_db::{
-    imports::import_assets::item_for_path_search, use_trivial_contructor::use_trivial_constructor,
-};
 use itertools::Itertools;
 use stdx::format_to;
 use syntax::ast::{self, AstNode, HasName, HasVisibility, StructKind};
@@ -41,8 +38,6 @@ pub(crate) fn generate_new(acc: &mut Assists, ctx: &AssistContext) -> Option<()>
     // Return early if we've found an existing new fn
     let impl_def = find_struct_impl(ctx, &ast::Adt::Struct(strukt.clone()), "new")?;
 
-    let current_module = ctx.sema.scope(strukt.syntax())?.module();
-
     let target = strukt.syntax().text_range();
     acc.add(AssistId("generate_new", AssistKind::Generate), "Generate `new`", target, |builder| {
         let mut buf = String::with_capacity(512);
@@ -53,50 +48,11 @@ pub(crate) fn generate_new(acc: &mut Assists, ctx: &AssistContext) -> Option<()>
 
         let vis = strukt.visibility().map_or(String::new(), |v| format!("{} ", v));
 
-        let trivial_constructors = field_list
-            .fields()
-            .map(|f| {
-                let ty = ctx.sema.resolve_type(&f.ty()?)?;
-
-                let item_in_ns = hir::ItemInNs::from(hir::ModuleDef::from(ty.as_adt()?));
-
-                let type_path = current_module
-                    .find_use_path(ctx.sema.db, item_for_path_search(ctx.sema.db, item_in_ns)?)?;
-
-                let expr = use_trivial_constructor(
-                    &ctx.sema.db,
-                    ide_db::helpers::mod_path_to_ast(&type_path),
-                    &ty,
-                )?;
-
-                Some(format!("{}: {}", f.name()?.syntax(), expr))
-            })
-            .collect::<Vec<_>>();
-
         let params = field_list
             .fields()
-            .enumerate()
-            .filter_map(|(i, f)| {
-                if trivial_constructors[i].is_none() {
-                    Some(format!("{}: {}", f.name()?.syntax(), f.ty()?.syntax()))
-                } else {
-                    None
-                }
-            })
-            .format(", ");
-
-        let fields = field_list
-            .fields()
-            .enumerate()
-            .filter_map(|(i, f)| {
-                let contructor = trivial_constructors[i].clone();
-                if contructor.is_some() {
-                    contructor
-                } else {
-                    Some(f.name()?.to_string())
-                }
-            })
+            .filter_map(|f| Some(format!("{}: {}", f.name()?.syntax(), f.ty()?.syntax())))
             .format(", ");
+        let fields = field_list.fields().filter_map(|f| f.name()).format(", ");
 
         format_to!(buf, "    {}fn new({}) -> Self {{ Self {{ {} }} }}", vis, params, fields);
 
@@ -123,97 +79,6 @@ mod tests {
 
     use super::*;
 
-    #[test]
-    fn test_generate_new_with_zst_fields() {
-        check_assist(
-            generate_new,
-            r#"
-struct Empty;
-
-struct Foo { empty: Empty $0}
-"#,
-            r#"
-struct Empty;
-
-struct Foo { empty: Empty }
-
-impl Foo {
-    fn $0new() -> Self { Self { empty: Empty } }
-}
-"#,
-        );
-        check_assist(
-            generate_new,
-            r#"
-struct Empty;
-
-struct Foo { baz: String, empty: Empty $0}
-"#,
-            r#"
-struct Empty;
-
-struct Foo { baz: String, empty: Empty }
-
-impl Foo {
-    fn $0new(baz: String) -> Self { Self { baz, empty: Empty } }
-}
-"#,
-        );
-        check_assist(
-            generate_new,
-            r#"
-enum Empty { Bar }
-
-struct Foo { empty: Empty $0}
-"#,
-            r#"
-enum Empty { Bar }
-
-struct Foo { empty: Empty }
-
-impl Foo {
-    fn $0new() -> Self { Self { empty: Empty::Bar } }
-}
-"#,
-        );
-
-        // make sure the assist only works on unit variants
-        check_assist(
-            generate_new,
-            r#"
-struct Empty {}
-
-struct Foo { empty: Empty $0}
-"#,
-            r#"
-struct Empty {}
-
-struct Foo { empty: Empty }
-
-impl Foo {
-    fn $0new(empty: Empty) -> Self { Self { empty } }
-}
-"#,
-        );
-        check_assist(
-            generate_new,
-            r#"
-enum Empty { Bar {} }
-
-struct Foo { empty: Empty $0}
-"#,
-            r#"
-enum Empty { Bar {} }
-
-struct Foo { empty: Empty }
-
-impl Foo {
-    fn $0new(empty: Empty) -> Self { Self { empty } }
-}
-"#,
-        );
-    }
-
     #[test]
     fn test_generate_new() {
         check_assist(
diff --git a/crates/ide-assists/src/handlers/inline_call.rs b/crates/ide-assists/src/handlers/inline_call.rs
index c857adf876..ab614b0ace 100644
--- a/crates/ide-assists/src/handlers/inline_call.rs
+++ b/crates/ide-assists/src/handlers/inline_call.rs
@@ -198,7 +198,7 @@ pub(crate) fn inline_call(acc: &mut Assists, ctx: &AssistContext) -> Option<()>
     let fn_body = fn_source.value.body()?;
     let param_list = fn_source.value.param_list()?;
 
-    let FileRange { file_id, range } = fn_source.syntax().original_file_range(ctx.sema.db);
+    let FileRange { file_id, range } = fn_source.syntax().original_file_range_full(ctx.sema.db);
     if file_id == ctx.file_id() && range.contains(ctx.offset()) {
         cov_mark::hit!(inline_call_recursive);
         return None;
diff --git a/crates/ide-completion/src/completions.rs b/crates/ide-completion/src/completions.rs
index 7b90307988..1bcbb3aaa6 100644
--- a/crates/ide-completion/src/completions.rs
+++ b/crates/ide-completion/src/completions.rs
@@ -91,31 +91,11 @@ impl Completions {
     }
 
     pub(crate) fn add_nameref_keywords_with_colon(&mut self, ctx: &CompletionContext) {
-        ["self::", "crate::"].into_iter().for_each(|kw| self.add_keyword(ctx, kw));
-
-        if ctx.depth_from_crate_root > 0 {
-            self.add_keyword(ctx, "super::");
-        }
+        ["self::", "super::", "crate::"].into_iter().for_each(|kw| self.add_keyword(ctx, kw));
     }
 
     pub(crate) fn add_nameref_keywords(&mut self, ctx: &CompletionContext) {
-        ["self", "crate"].into_iter().for_each(|kw| self.add_keyword(ctx, kw));
-
-        if ctx.depth_from_crate_root > 0 {
-            self.add_keyword(ctx, "super");
-        }
-    }
-
-    pub(crate) fn add_super_keyword(
-        &mut self,
-        ctx: &CompletionContext,
-        super_chain_len: Option<usize>,
-    ) {
-        if let Some(len) = super_chain_len {
-            if len > 0 && len < ctx.depth_from_crate_root {
-                self.add_keyword(ctx, "super::");
-            }
-        }
+        ["self", "super", "crate"].into_iter().for_each(|kw| self.add_keyword(ctx, kw));
     }
 
     pub(crate) fn add_keyword_snippet_expr(
@@ -174,19 +154,13 @@ impl Completions {
         local_name: hir::Name,
         resolution: hir::ScopeDef,
     ) {
-        let is_private_editable = match ctx.def_is_visible(&resolution) {
-            Visible::Yes => false,
-            Visible::Editable => true,
-            Visible::No => return,
-        };
+        if ctx.is_scope_def_hidden(resolution) {
+            cov_mark::hit!(qualified_path_doc_hidden);
+            return;
+        }
         self.add(
-            render_path_resolution(
-                RenderContext::new(ctx).private_editable(is_private_editable),
-                path_ctx,
-                local_name,
-                resolution,
-            )
-            .build(),
+            render_path_resolution(RenderContext::new(ctx), path_ctx, local_name, resolution)
+                .build(),
         );
     }
 
@@ -197,19 +171,13 @@ impl Completions {
         local_name: hir::Name,
         resolution: hir::ScopeDef,
     ) {
-        let is_private_editable = match ctx.def_is_visible(&resolution) {
-            Visible::Yes => false,
-            Visible::Editable => true,
-            Visible::No => return,
-        };
+        if ctx.is_scope_def_hidden(resolution) {
+            cov_mark::hit!(qualified_path_doc_hidden);
+            return;
+        }
         self.add(
-            render_pattern_resolution(
-                RenderContext::new(ctx).private_editable(is_private_editable),
-                pattern_ctx,
-                local_name,
-                resolution,
-            )
-            .build(),
+            render_pattern_resolution(RenderContext::new(ctx), pattern_ctx, local_name, resolution)
+                .build(),
         );
     }
 
diff --git a/crates/ide-completion/src/completions/attribute.rs b/crates/ide-completion/src/completions/attribute.rs
index cbf40e9134..2de33a7362 100644
--- a/crates/ide-completion/src/completions/attribute.rs
+++ b/crates/ide-completion/src/completions/attribute.rs
@@ -82,10 +82,12 @@ pub(crate) fn complete_attribute_path(
     match qualified {
         Qualified::With {
             resolution: Some(hir::PathResolution::Def(hir::ModuleDef::Module(module))),
-            super_chain_len,
+            is_super_chain,
             ..
         } => {
-            acc.add_super_keyword(ctx, *super_chain_len);
+            if *is_super_chain {
+                acc.add_keyword(ctx, "super::");
+            }
 
             for (name, def) in module.scope(ctx.db, Some(ctx.module)) {
                 match def {
diff --git a/crates/ide-completion/src/completions/attribute/derive.rs b/crates/ide-completion/src/completions/attribute/derive.rs
index b3cc1826a6..48eb76029f 100644
--- a/crates/ide-completion/src/completions/attribute/derive.rs
+++ b/crates/ide-completion/src/completions/attribute/derive.rs
@@ -21,10 +21,12 @@ pub(crate) fn complete_derive_path(
     match qualified {
         Qualified::With {
             resolution: Some(hir::PathResolution::Def(hir::ModuleDef::Module(module))),
-            super_chain_len,
+            is_super_chain,
             ..
         } => {
-            acc.add_super_keyword(ctx, *super_chain_len);
+            if *is_super_chain {
+                acc.add_keyword(ctx, "super::");
+            }
 
             for (name, def) in module.scope(ctx.db, Some(ctx.module)) {
                 match def {
diff --git a/crates/ide-completion/src/completions/flyimport.rs b/crates/ide-completion/src/completions/flyimport.rs
index 6dbcfb0a5d..1c62347fb5 100644
--- a/crates/ide-completion/src/completions/flyimport.rs
+++ b/crates/ide-completion/src/completions/flyimport.rs
@@ -95,7 +95,7 @@ use super::Completions;
 //
 // .Import configuration
 //
-// It is possible to configure how use-trees are merged with the `imports.granularity.group` setting.
+// It is possible to configure how use-trees are merged with the `importMergeBehavior` setting.
 // Mimics the corresponding behavior of the `Auto Import` feature.
 //
 // .LSP and performance implications
diff --git a/crates/ide-completion/src/completions/fn_param.rs b/crates/ide-completion/src/completions/fn_param.rs
index cc6c17450b..94e2f489f5 100644
--- a/crates/ide-completion/src/completions/fn_param.rs
+++ b/crates/ide-completion/src/completions/fn_param.rs
@@ -5,11 +5,11 @@ use ide_db::FxHashMap;
 use syntax::{
     algo,
     ast::{self, HasModuleItem},
-    match_ast, AstNode, Direction, SyntaxKind, TextRange, TextSize,
+    match_ast, AstNode, Direction, SyntaxKind, TextRange,
 };
 
 use crate::{
-    context::{ParamContext, ParamKind, PatternContext},
+    context::{ParamKind, PatternContext},
     CompletionContext, CompletionItem, CompletionItemKind, Completions,
 };
 
@@ -24,7 +24,7 @@ pub(crate) fn complete_fn_param(
     ctx: &CompletionContext,
     pattern_ctx: &PatternContext,
 ) -> Option<()> {
-    let (ParamContext { param_list, kind, .. }, impl_) = match pattern_ctx {
+    let ((param_list, _, param_kind), impl_) = match pattern_ctx {
         PatternContext { param_ctx: Some(kind), impl_, .. } => (kind, impl_),
         _ => return None,
     };
@@ -43,7 +43,7 @@ pub(crate) fn complete_fn_param(
         item.add_to(acc)
     };
 
-    match kind {
+    match param_kind {
         ParamKind::Function(function) => {
             fill_fn_params(ctx, function, param_list, impl_, add_new_item_to_acc);
         }
@@ -105,7 +105,7 @@ fn fill_fn_params(
     }
     remove_duplicated(&mut file_params, param_list.params());
     let self_completion_items = ["self", "&self", "mut self", "&mut self"];
-    if should_add_self_completions(ctx.token.text_range().start(), param_list, impl_) {
+    if should_add_self_completions(param_list, impl_) {
         self_completion_items.into_iter().for_each(|self_item| add_new_item_to_acc(self_item));
     }
 
@@ -156,18 +156,10 @@ fn remove_duplicated(
     })
 }
 
-fn should_add_self_completions(
-    cursor: TextSize,
-    param_list: &ast::ParamList,
-    impl_: &Option<ast::Impl>,
-) -> bool {
-    if impl_.is_none() || param_list.self_param().is_some() {
-        return false;
-    }
-    match param_list.params().next() {
-        Some(first) => first.pat().map_or(false, |pat| pat.syntax().text_range().contains(cursor)),
-        None => true,
-    }
+fn should_add_self_completions(param_list: &ast::ParamList, impl_: &Option<ast::Impl>) -> bool {
+    let no_params = param_list.params().next().is_none() && param_list.self_param().is_none();
+
+    impl_.is_some() && no_params
 }
 
 fn comma_wrapper(ctx: &CompletionContext) -> Option<(impl Fn(&str) -> String, TextRange)> {
diff --git a/crates/ide-completion/src/completions/item_list.rs b/crates/ide-completion/src/completions/item_list.rs
index 43b4899390..4a32e0ebf5 100644
--- a/crates/ide-completion/src/completions/item_list.rs
+++ b/crates/ide-completion/src/completions/item_list.rs
@@ -36,7 +36,7 @@ pub(crate) fn complete_item_list(
     match qualified {
         Qualified::With {
             resolution: Some(hir::PathResolution::Def(hir::ModuleDef::Module(module))),
-            super_chain_len,
+            is_super_chain,
             ..
         } => {
             for (name, def) in module.scope(ctx.db, Some(ctx.module)) {
@@ -51,7 +51,9 @@ pub(crate) fn complete_item_list(
                 }
             }
 
-            acc.add_super_keyword(ctx, *super_chain_len);
+            if *is_super_chain {
+                acc.add_keyword(ctx, "super::");
+            }
         }
         Qualified::Absolute => acc.add_crate_roots(ctx, path_ctx),
         Qualified::No if ctx.qualifier_ctx.none() => {
diff --git a/crates/ide-completion/src/completions/item_list/trait_impl.rs b/crates/ide-completion/src/completions/item_list/trait_impl.rs
index 49b8537029..67eb175460 100644
--- a/crates/ide-completion/src/completions/item_list/trait_impl.rs
+++ b/crates/ide-completion/src/completions/item_list/trait_impl.rs
@@ -438,10 +438,6 @@ impl Test for T {
             expect![[r#"
                 sp Self
                 st T
-                bn &mut self
-                bn &self
-                bn mut self
-                bn self
             "#]],
         );
 
diff --git a/crates/ide-completion/src/completions/pattern.rs b/crates/ide-completion/src/completions/pattern.rs
index 8d7fbc6627..65b6eee188 100644
--- a/crates/ide-completion/src/completions/pattern.rs
+++ b/crates/ide-completion/src/completions/pattern.rs
@@ -111,8 +111,10 @@ pub(crate) fn complete_pattern_path(
     path_ctx @ PathCompletionCtx { qualified, .. }: &PathCompletionCtx,
 ) {
     match qualified {
-        Qualified::With { resolution: Some(resolution), super_chain_len, .. } => {
-            acc.add_super_keyword(ctx, *super_chain_len);
+        Qualified::With { resolution: Some(resolution), is_super_chain, .. } => {
+            if *is_super_chain {
+                acc.add_keyword(ctx, "super::");
+            }
 
             match resolution {
                 hir::PathResolution::Def(hir::ModuleDef::Module(module)) => {
diff --git a/crates/ide-completion/src/completions/use_.rs b/crates/ide-completion/src/completions/use_.rs
index d4827771ad..e5689f332d 100644
--- a/crates/ide-completion/src/completions/use_.rs
+++ b/crates/ide-completion/src/completions/use_.rs
@@ -17,9 +17,10 @@ pub(crate) fn complete_use_path(
     name_ref: &Option<ast::NameRef>,
 ) {
     match qualified {
-        Qualified::With { path, resolution: Some(resolution), super_chain_len } => {
-            acc.add_super_keyword(ctx, *super_chain_len);
-
+        Qualified::With { path, resolution: Some(resolution), is_super_chain } => {
+            if *is_super_chain {
+                acc.add_keyword(ctx, "super::");
+            }
             // only show `self` in a new use-tree when the qualifier doesn't end in self
             let not_preceded_by_self = *use_tree_parent
                 && !matches!(
diff --git a/crates/ide-completion/src/completions/vis.rs b/crates/ide-completion/src/completions/vis.rs
index 39028eca41..6621aafe4b 100644
--- a/crates/ide-completion/src/completions/vis.rs
+++ b/crates/ide-completion/src/completions/vis.rs
@@ -14,7 +14,7 @@ pub(crate) fn complete_vis_path(
     match qualified {
         Qualified::With {
             resolution: Some(hir::PathResolution::Def(hir::ModuleDef::Module(module))),
-            super_chain_len,
+            is_super_chain,
             ..
         } => {
             // Try completing next child module of the path that is still a parent of the current module
@@ -27,7 +27,9 @@ pub(crate) fn complete_vis_path(
                 }
             }
 
-            acc.add_super_keyword(ctx, *super_chain_len);
+            if *is_super_chain {
+                acc.add_keyword(ctx, "super::");
+            }
         }
         Qualified::Absolute | Qualified::Infer | Qualified::With { .. } => {}
         Qualified::No => {
diff --git a/crates/ide-completion/src/context.rs b/crates/ide-completion/src/context.rs
index 7c53db9bf2..b371c97880 100644
--- a/crates/ide-completion/src/context.rs
+++ b/crates/ide-completion/src/context.rs
@@ -4,8 +4,6 @@ mod analysis;
 #[cfg(test)]
 mod tests;
 
-use std::iter;
-
 use base_db::SourceDatabaseExt;
 use hir::{
     HasAttrs, Local, Name, PathResolution, ScopeDef, Semantics, SemanticsScope, Type, TypeInfo,
@@ -33,7 +31,6 @@ pub(crate) enum PatternRefutability {
     Irrefutable,
 }
 
-#[derive(Debug)]
 pub(crate) enum Visible {
     Yes,
     Editable,
@@ -177,17 +174,8 @@ pub(super) enum Qualified {
     With {
         path: ast::Path,
         resolution: Option<PathResolution>,
-        /// How many `super` segments are present in the path
-        ///
-        /// This would be None, if path is not solely made of
-        /// `super` segments, e.g.
-        ///
-        /// ```rust
-        ///   use super::foo;
-        /// ```
-        ///
-        /// Otherwise it should be Some(count of `super`)
-        super_chain_len: Option<usize>,
+        /// Whether this path consists solely of `super` segments
+        is_super_chain: bool,
     },
     /// <_>::
     Infer,
@@ -199,7 +187,7 @@ pub(super) enum Qualified {
 #[derive(Debug, Clone, PartialEq, Eq)]
 pub(super) struct PatternContext {
     pub(super) refutability: PatternRefutability,
-    pub(super) param_ctx: Option<ParamContext>,
+    pub(super) param_ctx: Option<(ast::ParamList, ast::Param, ParamKind)>,
     pub(super) has_type_ascription: bool,
     pub(super) parent_pat: Option<ast::Pat>,
     pub(super) ref_token: Option<SyntaxToken>,
@@ -209,13 +197,6 @@ pub(super) struct PatternContext {
     pub(super) impl_: Option<ast::Impl>,
 }
 
-#[derive(Debug, Clone, PartialEq, Eq)]
-pub(super) struct ParamContext {
-    pub(super) param_list: ast::ParamList,
-    pub(super) param: ast::Param,
-    pub(super) kind: ParamKind,
-}
-
 /// The state of the lifetime we are completing.
 #[derive(Debug)]
 pub(super) struct LifetimeContext {
@@ -362,13 +343,6 @@ pub(crate) struct CompletionContext<'a> {
     pub(super) qualifier_ctx: QualifierCtx,
 
     pub(super) locals: FxHashMap<Name, Local>,
-
-    /// The module depth of the current module of the cursor position.
-    /// - crate-root
-    ///  - mod foo
-    ///   - mod bar
-    /// Here depth will be 2
-    pub(super) depth_from_crate_root: usize,
 }
 
 impl<'a> CompletionContext<'a> {
@@ -392,30 +366,6 @@ impl<'a> CompletionContext<'a> {
         FamousDefs(&self.sema, self.krate)
     }
 
-    /// Checks if an item is visible and not `doc(hidden)` at the completion site.
-    pub(crate) fn def_is_visible(&self, item: &ScopeDef) -> Visible {
-        match item {
-            ScopeDef::ModuleDef(def) => match def {
-                hir::ModuleDef::Module(it) => self.is_visible(it),
-                hir::ModuleDef::Function(it) => self.is_visible(it),
-                hir::ModuleDef::Adt(it) => self.is_visible(it),
-                hir::ModuleDef::Variant(it) => self.is_visible(it),
-                hir::ModuleDef::Const(it) => self.is_visible(it),
-                hir::ModuleDef::Static(it) => self.is_visible(it),
-                hir::ModuleDef::Trait(it) => self.is_visible(it),
-                hir::ModuleDef::TypeAlias(it) => self.is_visible(it),
-                hir::ModuleDef::Macro(it) => self.is_visible(it),
-                hir::ModuleDef::BuiltinType(_) => Visible::Yes,
-            },
-            ScopeDef::GenericParam(_)
-            | ScopeDef::ImplSelfType(_)
-            | ScopeDef::AdtSelfType(_)
-            | ScopeDef::Local(_)
-            | ScopeDef::Label(_)
-            | ScopeDef::Unknown => Visible::Yes,
-        }
-    }
-
     /// Checks if an item is visible and not `doc(hidden)` at the completion site.
     pub(crate) fn is_visible<I>(&self, item: &I) -> Visible
     where
@@ -426,6 +376,14 @@ impl<'a> CompletionContext<'a> {
         self.is_visible_impl(&vis, &attrs, item.krate(self.db))
     }
 
+    pub(crate) fn is_scope_def_hidden(&self, scope_def: ScopeDef) -> bool {
+        if let (Some(attrs), Some(krate)) = (scope_def.attrs(self.db), scope_def.krate(self.db)) {
+            return self.is_doc_hidden(&attrs, krate);
+        }
+
+        false
+    }
+
     /// Check if an item is `#[doc(hidden)]`.
     pub(crate) fn is_item_hidden(&self, item: &hir::ItemInNs) -> bool {
         let attrs = item.attrs(self.db);
@@ -493,14 +451,6 @@ impl<'a> CompletionContext<'a> {
         self.scope.process_all_names(&mut |name, def| f(name, def));
     }
 
-    fn is_scope_def_hidden(&self, scope_def: ScopeDef) -> bool {
-        if let (Some(attrs), Some(krate)) = (scope_def.attrs(self.db), scope_def.krate(self.db)) {
-            return self.is_doc_hidden(&attrs, krate);
-        }
-
-        false
-    }
-
     fn is_visible_impl(
         &self,
         vis: &hir::Visibility,
@@ -571,8 +521,6 @@ impl<'a> CompletionContext<'a> {
             }
         });
 
-        let depth_from_crate_root = iter::successors(module.parent(db), |m| m.parent(db)).count();
-
         let mut ctx = CompletionContext {
             sema,
             scope,
@@ -587,7 +535,6 @@ impl<'a> CompletionContext<'a> {
             expected_type: None,
             qualifier_ctx: Default::default(),
             locals,
-            depth_from_crate_root,
         };
         let ident_ctx = ctx.expand_and_analyze(
             original_file.syntax().clone(),
diff --git a/crates/ide-completion/src/context/analysis.rs b/crates/ide-completion/src/context/analysis.rs
index fabbbe867e..e13950d56a 100644
--- a/crates/ide-completion/src/context/analysis.rs
+++ b/crates/ide-completion/src/context/analysis.rs
@@ -13,9 +13,8 @@ use syntax::{
 use crate::context::{
     AttrCtx, CompletionAnalysis, CompletionContext, DotAccess, DotAccessKind, ExprCtx,
     ItemListKind, LifetimeContext, LifetimeKind, NameContext, NameKind, NameRefContext,
-    NameRefKind, ParamContext, ParamKind, PathCompletionCtx, PathKind, PatternContext,
-    PatternRefutability, Qualified, QualifierCtx, TypeAscriptionTarget, TypeLocation,
-    COMPLETION_MARKER,
+    NameRefKind, ParamKind, PathCompletionCtx, PathKind, PatternContext, PatternRefutability,
+    Qualified, QualifierCtx, TypeAscriptionTarget, TypeLocation, COMPLETION_MARKER,
 };
 
 impl<'a> CompletionContext<'a> {
@@ -900,25 +899,10 @@ impl<'a> CompletionContext<'a> {
                         Qualified::Infer
                     } else {
                         let res = sema.resolve_path(&path);
-
-                        // For understanding how and why super_chain_len is calculated the way it
-                        // is check the documentation at it's definition
-                        let mut segment_count = 0;
-                        let super_count = iter::successors(Some(path.clone()), |p| p.qualifier())
-                            .take_while(|p| {
-                                p.segment()
-                                    .and_then(|s| {
-                                        segment_count += 1;
-                                        s.super_token()
-                                    })
-                                    .is_some()
-                            })
-                            .count();
-
-                        let super_chain_len =
-                            if segment_count > super_count { None } else { Some(super_count) };
-
-                        Qualified::With { path, resolution: res, super_chain_len }
+                        let is_super_chain =
+                            iter::successors(Some(path.clone()), |p| p.qualifier())
+                                .all(|p| p.segment().and_then(|s| s.super_token()).is_some());
+                        Qualified::With { path, resolution: res, is_super_chain }
                     }
                 };
             }
@@ -991,7 +975,7 @@ fn pattern_context_for(
     original_file: &SyntaxNode,
     pat: ast::Pat,
 ) -> PatternContext {
-    let mut param_ctx = None;
+    let mut is_param = None;
     let (refutability, has_type_ascription) =
     pat
         .syntax()
@@ -1004,7 +988,7 @@ fn pattern_context_for(
                     ast::LetStmt(let_) => return (PatternRefutability::Irrefutable, let_.ty().is_some()),
                     ast::Param(param) => {
                         let has_type_ascription = param.ty().is_some();
-                        param_ctx = (|| {
+                        is_param = (|| {
                             let fake_param_list = param.syntax().parent().and_then(ast::ParamList::cast)?;
                             let param_list = find_node_in_file_compensated(sema, original_file, &fake_param_list)?;
                             let param_list_owner = param_list.syntax().parent()?;
@@ -1015,9 +999,7 @@ fn pattern_context_for(
                                     _ => return None,
                                 }
                             };
-                            Some(ParamContext {
-                                param_list, param, kind
-                            })
+                            Some((param_list, param, kind))
                         })();
                         return (PatternRefutability::Irrefutable, has_type_ascription)
                     },
@@ -1036,7 +1018,7 @@ fn pattern_context_for(
 
     PatternContext {
         refutability,
-        param_ctx,
+        param_ctx: is_param,
         has_type_ascription,
         parent_pat: pat.syntax().parent().and_then(ast::Pat::cast),
         mut_token,
diff --git a/crates/ide-completion/src/render/pattern.rs b/crates/ide-completion/src/render/pattern.rs
index 03db08a911..d6779961c0 100644
--- a/crates/ide-completion/src/render/pattern.rs
+++ b/crates/ide-completion/src/render/pattern.rs
@@ -6,7 +6,7 @@ use itertools::Itertools;
 use syntax::SmolStr;
 
 use crate::{
-    context::{ParamContext, ParamKind, PatternContext},
+    context::{ParamKind, PatternContext},
     render::{
         variant::{format_literal_label, visible_fields},
         RenderContext,
@@ -102,7 +102,7 @@ fn render_pat(
     let needs_ascription = matches!(
         pattern_ctx,
         PatternContext {
-            param_ctx: Some(ParamContext { kind: ParamKind::Function(_), .. }),
+            param_ctx: Some((.., ParamKind::Function(_))),
             has_type_ascription: false,
             ..
         }
diff --git a/crates/ide-completion/src/snippet.rs b/crates/ide-completion/src/snippet.rs
index d2680c7758..a6bb3d0648 100644
--- a/crates/ide-completion/src/snippet.rs
+++ b/crates/ide-completion/src/snippet.rs
@@ -6,12 +6,12 @@
 //
 // rust-analyzer allows the user to define custom (postfix)-snippets that may depend on items to be accessible for the current scope to be applicable.
 //
-// A custom snippet can be defined by adding it to the `rust-analyzer.completion.snippets.custom` object respectively.
+// A custom snippet can be defined by adding it to the `rust-analyzer.completion.snippets` object respectively.
 //
 // [source,json]
 // ----
 // {
-//   "rust-analyzer.completion.snippets.custom": {
+//   "rust-analyzer.completion.snippets": {
 //     "thread spawn": {
 //       "prefix": ["spawn", "tspawn"],
 //       "body": [
diff --git a/crates/ide-db/src/imports/insert_use.rs b/crates/ide-db/src/imports/insert_use.rs
index c14182279d..d1cd347819 100644
--- a/crates/ide-db/src/imports/insert_use.rs
+++ b/crates/ide-db/src/imports/insert_use.rs
@@ -396,19 +396,10 @@ fn insert_use_(
         }
     }
 
-    let l_curly = match scope {
-        ImportScope::File(_) => None,
-        // don't insert the imports before the item list/block expr's opening curly brace
-        ImportScope::Module(item_list) => item_list.l_curly_token(),
-        // don't insert the imports before the item list's opening curly brace
-        ImportScope::Block(block) => block.l_curly_token(),
-    };
     // there are no imports in this file at all
     // so put the import after all inner module attributes and possible license header comments
     if let Some(last_inner_element) = scope_syntax
         .children_with_tokens()
-        // skip the curly brace
-        .skip(l_curly.is_some() as usize)
         .take_while(|child| match child {
             NodeOrToken::Node(node) => is_inner_attribute(node.clone()),
             NodeOrToken::Token(token) => {
@@ -422,21 +413,30 @@ fn insert_use_(
         cov_mark::hit!(insert_empty_inner_attr);
         ted::insert(ted::Position::after(&last_inner_element), use_item.syntax());
         ted::insert(ted::Position::after(last_inner_element), make::tokens::single_newline());
-    } else {
-        match l_curly {
-            Some(b) => {
-                cov_mark::hit!(insert_empty_module);
-                ted::insert(ted::Position::after(&b), make::tokens::single_newline());
-                ted::insert(ted::Position::after(&b), use_item.syntax());
-            }
-            None => {
-                cov_mark::hit!(insert_empty_file);
-                ted::insert(
-                    ted::Position::first_child_of(scope_syntax),
-                    make::tokens::blank_line(),
-                );
-                ted::insert(ted::Position::first_child_of(scope_syntax), use_item.syntax());
-            }
+        return;
+    }
+    let l_curly = match scope {
+        ImportScope::File(_) => {
+            cov_mark::hit!(insert_empty_file);
+            ted::insert(ted::Position::first_child_of(scope_syntax), make::tokens::blank_line());
+            ted::insert(ted::Position::first_child_of(scope_syntax), use_item.syntax());
+            return;
+        }
+        // don't insert the imports before the item list/block expr's opening curly brace
+        ImportScope::Module(item_list) => item_list.l_curly_token(),
+        // don't insert the imports before the item list's opening curly brace
+        ImportScope::Block(block) => block.l_curly_token(),
+    };
+    match l_curly {
+        Some(b) => {
+            cov_mark::hit!(insert_empty_module);
+            ted::insert(ted::Position::after(&b), make::tokens::single_newline());
+            ted::insert(ted::Position::after(&b), use_item.syntax());
+        }
+        None => {
+            // This should never happens, broken module syntax node
+            ted::insert(ted::Position::first_child_of(scope_syntax), make::tokens::blank_line());
+            ted::insert(ted::Position::first_child_of(scope_syntax), use_item.syntax());
         }
     }
 }
diff --git a/crates/ide-db/src/lib.rs b/crates/ide-db/src/lib.rs
index 165b98d72e..8fad4ac0f3 100644
--- a/crates/ide-db/src/lib.rs
+++ b/crates/ide-db/src/lib.rs
@@ -20,7 +20,6 @@ pub mod source_change;
 pub mod symbol_index;
 pub mod traits;
 pub mod ty_filter;
-pub mod use_trivial_contructor;
 
 pub mod imports {
     pub mod import_assets;
diff --git a/crates/ide-db/src/rename.rs b/crates/ide-db/src/rename.rs
index bff8265e01..fa139ebc24 100644
--- a/crates/ide-db/src/rename.rs
+++ b/crates/ide-db/src/rename.rs
@@ -177,10 +177,6 @@ fn rename_mod(
 
     let mut source_change = SourceChange::default();
 
-    if module.is_crate_root(sema.db) {
-        return Ok(source_change);
-    }
-
     let InFile { file_id, value: def_source } = module.definition_source(sema.db);
     if let ModuleSource::SourceFile(..) = def_source {
         let anchor = file_id.original_file(sema.db);
diff --git a/crates/ide-db/src/search.rs b/crates/ide-db/src/search.rs
index 4a11fb73cd..e6bd46347d 100644
--- a/crates/ide-db/src/search.rs
+++ b/crates/ide-db/src/search.rs
@@ -239,14 +239,14 @@ impl Definition {
                 DefWithBody::Static(s) => s.source(db).map(|src| src.syntax().cloned()),
             };
             return match def {
-                Some(def) => SearchScope::file_range(def.as_ref().original_file_range(db)),
+                Some(def) => SearchScope::file_range(def.as_ref().original_file_range_full(db)),
                 None => SearchScope::single_file(file_id),
             };
         }
 
         if let Definition::SelfType(impl_) = self {
             return match impl_.source(db).map(|src| src.syntax().cloned()) {
-                Some(def) => SearchScope::file_range(def.as_ref().original_file_range(db)),
+                Some(def) => SearchScope::file_range(def.as_ref().original_file_range_full(db)),
                 None => SearchScope::single_file(file_id),
             };
         }
@@ -262,7 +262,7 @@ impl Definition {
                 hir::GenericDef::Const(it) => it.source(db).map(|src| src.syntax().cloned()),
             };
             return match def {
-                Some(def) => SearchScope::file_range(def.as_ref().original_file_range(db)),
+                Some(def) => SearchScope::file_range(def.as_ref().original_file_range_full(db)),
                 None => SearchScope::single_file(file_id),
             };
         }
diff --git a/crates/ide-db/src/use_trivial_contructor.rs b/crates/ide-db/src/use_trivial_contructor.rs
deleted file mode 100644
index 39431bed38..0000000000
--- a/crates/ide-db/src/use_trivial_contructor.rs
+++ /dev/null
@@ -1,34 +0,0 @@
-//! Functionality for generating trivial contructors
-
-use hir::StructKind;
-use syntax::ast;
-
-/// given a type return the trivial contructor (if one exists)
-pub fn use_trivial_constructor(
-    db: &crate::RootDatabase,
-    path: ast::Path,
-    ty: &hir::Type,
-) -> Option<ast::Expr> {
-    match ty.as_adt() {
-        Some(hir::Adt::Enum(x)) => {
-            if let &[variant] = &*x.variants(db) {
-                if variant.kind(db) == hir::StructKind::Unit {
-                    let path = ast::make::path_qualified(
-                        path,
-                        syntax::ast::make::path_segment(ast::make::name_ref(
-                            &variant.name(db).to_smol_str(),
-                        )),
-                    );
-
-                    return Some(syntax::ast::make::expr_path(path));
-                }
-            }
-        }
-        Some(hir::Adt::Struct(x)) if x.kind(db) == StructKind::Unit => {
-            return Some(syntax::ast::make::expr_path(path));
-        }
-        _ => {}
-    }
-
-    None
-}
diff --git a/crates/ide-diagnostics/src/handlers/missing_fields.rs b/crates/ide-diagnostics/src/handlers/missing_fields.rs
index 30f903af50..891547aaef 100644
--- a/crates/ide-diagnostics/src/handlers/missing_fields.rs
+++ b/crates/ide-diagnostics/src/handlers/missing_fields.rs
@@ -3,10 +3,7 @@ use hir::{
     db::{AstDatabase, HirDatabase},
     known, AssocItem, HirDisplay, InFile, Type,
 };
-use ide_db::{
-    assists::Assist, famous_defs::FamousDefs, imports::import_assets::item_for_path_search,
-    source_change::SourceChange, use_trivial_contructor::use_trivial_constructor, FxHashMap,
-};
+use ide_db::{assists::Assist, famous_defs::FamousDefs, source_change::SourceChange, FxHashMap};
 use stdx::format_to;
 use syntax::{
     algo,
@@ -58,11 +55,6 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::MissingFields) -> Option<Vec<Ass
 
     let root = ctx.sema.db.parse_or_expand(d.file)?;
 
-    let current_module = match &d.field_list_parent {
-        Either::Left(ptr) => ctx.sema.scope(ptr.to_node(&root).syntax()).map(|it| it.module()),
-        Either::Right(ptr) => ctx.sema.scope(ptr.to_node(&root).syntax()).map(|it| it.module()),
-    };
-
     let build_text_edit = |parent_syntax, new_syntax: &SyntaxNode, old_syntax| {
         let edit = {
             let mut builder = TextEdit::builder();
@@ -118,26 +110,7 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::MissingFields) -> Option<Vec<Ass
                         Some(generate_fill_expr(ty))
                     }
                 } else {
-                    let expr = (|| -> Option<ast::Expr> {
-                        let item_in_ns = hir::ItemInNs::from(hir::ModuleDef::from(ty.as_adt()?));
-
-                        let type_path = current_module?.find_use_path(
-                            ctx.sema.db,
-                            item_for_path_search(ctx.sema.db, item_in_ns)?,
-                        )?;
-
-                        use_trivial_constructor(
-                            &ctx.sema.db,
-                            ide_db::helpers::mod_path_to_ast(&type_path),
-                            &ty,
-                        )
-                    })();
-
-                    if expr.is_some() {
-                        expr
-                    } else {
-                        Some(generate_fill_expr(ty))
-                    }
+                    Some(generate_fill_expr(ty))
                 };
                 let field = make::record_expr_field(
                     make::name_ref(&f.name(ctx.sema.db).to_smol_str()),
@@ -345,92 +318,6 @@ fn test_fn() {
         );
     }
 
-    #[test]
-    fn test_fill_struct_zst_fields() {
-        check_fix(
-            r#"
-struct Empty;
-
-struct TestStruct { one: i32, two: Empty }
-
-fn test_fn() {
-    let s = TestStruct {$0};
-}
-"#,
-            r#"
-struct Empty;
-
-struct TestStruct { one: i32, two: Empty }
-
-fn test_fn() {
-    let s = TestStruct { one: 0, two: Empty };
-}
-"#,
-        );
-        check_fix(
-            r#"
-enum Empty { Foo };
-
-struct TestStruct { one: i32, two: Empty }
-
-fn test_fn() {
-    let s = TestStruct {$0};
-}
-"#,
-            r#"
-enum Empty { Foo };
-
-struct TestStruct { one: i32, two: Empty }
-
-fn test_fn() {
-    let s = TestStruct { one: 0, two: Empty::Foo };
-}
-"#,
-        );
-
-        // make sure the assist doesn't fill non Unit variants
-        check_fix(
-            r#"
-struct Empty {};
-
-struct TestStruct { one: i32, two: Empty }
-
-fn test_fn() {
-    let s = TestStruct {$0};
-}
-"#,
-            r#"
-struct Empty {};
-
-struct TestStruct { one: i32, two: Empty }
-
-fn test_fn() {
-    let s = TestStruct { one: 0, two: todo!() };
-}
-"#,
-        );
-        check_fix(
-            r#"
-enum Empty { Foo {} };
-
-struct TestStruct { one: i32, two: Empty }
-
-fn test_fn() {
-    let s = TestStruct {$0};
-}
-"#,
-            r#"
-enum Empty { Foo {} };
-
-struct TestStruct { one: i32, two: Empty }
-
-fn test_fn() {
-    let s = TestStruct { one: 0, two: todo!() };
-}
-"#,
-        );
-    }
-
     #[test]
     fn test_fill_struct_fields_self() {
         check_fix(
diff --git a/crates/ide-diagnostics/src/handlers/type_mismatch.rs b/crates/ide-diagnostics/src/handlers/type_mismatch.rs
index 2239382472..442268d135 100644
--- a/crates/ide-diagnostics/src/handlers/type_mismatch.rs
+++ b/crates/ide-diagnostics/src/handlers/type_mismatch.rs
@@ -35,7 +35,6 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::TypeMismatch) -> Option<Vec<Assi
     add_reference(ctx, d, &mut fixes);
     add_missing_ok_or_some(ctx, d, &mut fixes);
     remove_semicolon(ctx, d, &mut fixes);
-    str_ref_to_string(ctx, d, &mut fixes);
 
     if fixes.is_empty() {
         None
@@ -135,32 +134,6 @@ fn remove_semicolon(
     Some(())
 }
 
-fn str_ref_to_string(
-    ctx: &DiagnosticsContext<'_>,
-    d: &hir::TypeMismatch,
-    acc: &mut Vec<Assist>,
-) -> Option<()> {
-    let expected = d.expected.display(ctx.sema.db);
-    let actual = d.actual.display(ctx.sema.db);
-
-    if expected.to_string() != "String" || actual.to_string() != "&str" {
-        return None;
-    }
-
-    let root = ctx.sema.db.parse_or_expand(d.expr.file_id)?;
-    let expr = d.expr.value.to_node(&root);
-    let expr_range = expr.syntax().text_range();
-
-    let to_string = format!(".to_string()");
-
-    let edit = TextEdit::insert(expr.syntax().text_range().end(), to_string);
-    let source_change =
-        SourceChange::from_text_edit(d.expr.file_id.original_file(ctx.sema.db), edit);
-    acc.push(fix("str_ref_to_string", "Add .to_string() here", source_change, expr_range));
-
-    Some(())
-}
-
 #[cfg(test)]
 mod tests {
     use crate::tests::{check_diagnostics, check_fix, check_no_fix};
@@ -525,24 +498,4 @@ fn foo() -> SomeOtherEnum { 0$0 }
     fn remove_semicolon() {
         check_fix(r#"fn f() -> i32 { 92$0; }"#, r#"fn f() -> i32 { 92 }"#);
     }
-
-    #[test]
-    fn str_ref_to_string() {
-        check_fix(
-            r#"
-struct String;
-
-fn test() -> String {
-    "a"$0
-}
-            "#,
-            r#"
-struct String;
-
-fn test() -> String {
-    "a".to_string()
-}
-            "#,
-        );
-    }
 }
diff --git a/crates/ide-diagnostics/src/handlers/unresolved_proc_macro.rs b/crates/ide-diagnostics/src/handlers/unresolved_proc_macro.rs
index 760f51f904..fde3901a73 100644
--- a/crates/ide-diagnostics/src/handlers/unresolved_proc_macro.rs
+++ b/crates/ide-diagnostics/src/handlers/unresolved_proc_macro.rs
@@ -1,5 +1,4 @@
 use hir::db::DefDatabase;
-use syntax::NodeOrToken;
 
 use crate::{Diagnostic, DiagnosticsContext, Severity};
 
@@ -19,16 +18,9 @@ pub(crate) fn unresolved_proc_macro(
     proc_attr_macros_enabled: bool,
 ) -> Diagnostic {
     // Use more accurate position if available.
-    let display_range = (|| {
-        let precise_location = d.precise_location?;
-        let root = ctx.sema.parse_or_expand(d.node.file_id)?;
-        match root.covering_element(precise_location) {
-            NodeOrToken::Node(it) => Some(ctx.sema.original_range(&it)),
-            NodeOrToken::Token(it) => d.node.with_value(it).original_file_range_opt(ctx.sema.db),
-        }
-    })()
-    .unwrap_or_else(|| ctx.sema.diagnostics_display_range(d.node.clone()))
-    .range;
+    let display_range = d
+        .precise_location
+        .unwrap_or_else(|| ctx.sema.diagnostics_display_range(d.node.clone()).range);
 
     let config_enabled = match d.kind {
         hir::MacroKind::Attr => proc_macros_enabled && proc_attr_macros_enabled,
diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs
index 3372d74af6..592fff322e 100644
--- a/crates/ide/src/hover.rs
+++ b/crates/ide/src/hover.rs
@@ -173,27 +173,17 @@ pub(crate) fn hover_for_definition(
         Definition::BuiltinType(_) => Some(FamousDefs(sema, sema.scope(node)?.krate())),
         _ => None,
     };
-    if let Some(markup) = render::definition(sema.db, definition, famous_defs.as_ref(), config) {
-        let mut res = HoverResult::default();
-        res.markup = render::process_markup(sema.db, definition, &markup, config);
-        if let Some(action) = show_implementations_action(sema.db, definition) {
-            res.actions.push(action);
+    render::definition(sema.db, definition, famous_defs.as_ref(), config).map(|markup| {
+        HoverResult {
+            markup: render::process_markup(sema.db, definition, &markup, config),
+            actions: show_implementations_action(sema.db, definition)
+                .into_iter()
+                .chain(show_fn_references_action(sema.db, definition))
+                .chain(runnable_action(sema, definition, file_id))
+                .chain(goto_type_action_for_def(sema.db, definition))
+                .collect(),
         }
-
-        if let Some(action) = show_fn_references_action(sema.db, definition) {
-            res.actions.push(action);
-        }
-
-        if let Some(action) = runnable_action(sema, definition, file_id) {
-            res.actions.push(action);
-        }
-
-        if let Some(action) = goto_type_action_for_def(sema.db, definition) {
-            res.actions.push(action);
-        }
-        return Some(res);
-    }
-    None
+    })
 }
 
 fn hover_ranged(
diff --git a/crates/ide/src/rename.rs b/crates/ide/src/rename.rs
index 23d6f8d8e4..0f8033611a 100644
--- a/crates/ide/src/rename.rs
+++ b/crates/ide/src/rename.rs
@@ -379,15 +379,6 @@ mod tests {
         expect.assert_debug_eq(&source_change)
     }
 
-    fn check_expect_will_rename_file(new_name: &str, ra_fixture: &str, expect: Expect) {
-        let (analysis, position) = fixture::position(ra_fixture);
-        let source_change = analysis
-            .will_rename_file(position.file_id, new_name)
-            .unwrap()
-            .expect("Expect returned a RenameError");
-        expect.assert_debug_eq(&source_change)
-    }
-
     fn check_prepare(ra_fixture: &str, expect: Expect) {
         let (analysis, position) = fixture::position(ra_fixture);
         let result = analysis
@@ -1254,26 +1245,6 @@ submodule!(bar);
         )
     }
 
-    #[test]
-    fn test_rename_mod_for_crate_root() {
-        check_expect_will_rename_file(
-            "main",
-            r#"
-//- /lib.rs
-use crate::foo as bar;
-fn foo() {}
-mod bar$0;
-"#,
-            expect![[r#"
-                SourceChange {
-                    source_file_edits: {},
-                    file_system_edits: [],
-                    is_snippet: false,
-                }
-                "#]],
-        )
-    }
-
     #[test]
     fn test_enum_variant_from_module_1() {
         cov_mark::check!(rename_non_local);
diff --git a/crates/ide/src/syntax_highlighting/highlight.rs b/crates/ide/src/syntax_highlighting/highlight.rs
index b91d54dd92..4c5bdfd967 100644
--- a/crates/ide/src/syntax_highlighting/highlight.rs
+++ b/crates/ide/src/syntax_highlighting/highlight.rs
@@ -328,8 +328,8 @@ fn highlight_def(sema: &Semantics<RootDatabase>, krate: hir::Crate, def: Definit
         Definition::Field(_) => Highlight::new(HlTag::Symbol(SymbolKind::Field)),
         Definition::Module(module) => {
             let mut h = Highlight::new(HlTag::Symbol(SymbolKind::Module));
-            if module.is_crate_root(db) {
-                h |= HlMod::CrateRoot;
+            if module.parent(db).is_none() {
+                h |= HlMod::CrateRoot
             }
             h
         }
diff --git a/crates/mbe/src/syntax_bridge.rs b/crates/mbe/src/syntax_bridge.rs
index aca6ecd424..21a0aa4284 100644
--- a/crates/mbe/src/syntax_bridge.rs
+++ b/crates/mbe/src/syntax_bridge.rs
@@ -31,8 +31,8 @@ pub fn syntax_node_to_token_tree_with_modifications(
     node: &SyntaxNode,
     existing_token_map: TokenMap,
     next_id: u32,
-    replace: FxHashMap<SyntaxElement, Vec<SyntheticToken>>,
-    append: FxHashMap<SyntaxElement, Vec<SyntheticToken>>,
+    replace: FxHashMap<SyntaxNode, Vec<SyntheticToken>>,
+    append: FxHashMap<SyntaxNode, Vec<SyntheticToken>>,
 ) -> (tt::Subtree, TokenMap, u32) {
     let global_offset = node.text_range().start();
     let mut c = Convertor::new(node, global_offset, existing_token_map, next_id, replace, append);
@@ -221,7 +221,7 @@ fn convert_tokens<C: TokenConvertor>(conv: &mut C) -> tt::Subtree {
 
             if let Some(kind) = delim {
                 let mut subtree = tt::Subtree::default();
-                let (id, idx) = conv.id_alloc().open_delim(range, synth_id);
+                let (id, idx) = conv.id_alloc().open_delim(range);
                 subtree.delimiter = Some(tt::Delimiter { id, kind });
                 stack.push(StackEntry { subtree, idx, open_range: range });
                 continue;
@@ -404,11 +404,7 @@ impl TokenIdAlloc {
         token_id
     }
 
-    fn open_delim(
-        &mut self,
-        open_abs_range: TextRange,
-        synthetic_id: Option<SyntheticTokenId>,
-    ) -> (tt::TokenId, usize) {
+    fn open_delim(&mut self, open_abs_range: TextRange) -> (tt::TokenId, usize) {
         let token_id = tt::TokenId(self.next_id);
         self.next_id += 1;
         let idx = self.map.insert_delim(
@@ -416,9 +412,6 @@ impl TokenIdAlloc {
             open_abs_range - self.global_offset,
             open_abs_range - self.global_offset,
         );
-        if let Some(id) = synthetic_id {
-            self.map.insert_synthetic(token_id, id);
-        }
         (token_id, idx)
     }
 
@@ -518,8 +511,8 @@ struct Convertor {
     current: Option<SyntaxToken>,
     current_synthetic: Vec<SyntheticToken>,
     preorder: PreorderWithTokens,
-    replace: FxHashMap<SyntaxElement, Vec<SyntheticToken>>,
-    append: FxHashMap<SyntaxElement, Vec<SyntheticToken>>,
+    replace: FxHashMap<SyntaxNode, Vec<SyntheticToken>>,
+    append: FxHashMap<SyntaxNode, Vec<SyntheticToken>>,
     range: TextRange,
     punct_offset: Option<(SyntaxToken, TextSize)>,
 }
@@ -530,8 +523,8 @@ impl Convertor {
         global_offset: TextSize,
         existing_token_map: TokenMap,
         next_id: u32,
-        mut replace: FxHashMap<SyntaxElement, Vec<SyntheticToken>>,
-        mut append: FxHashMap<SyntaxElement, Vec<SyntheticToken>>,
+        mut replace: FxHashMap<SyntaxNode, Vec<SyntheticToken>>,
+        mut append: FxHashMap<SyntaxNode, Vec<SyntheticToken>>,
     ) -> Convertor {
         let range = node.text_range();
         let mut preorder = node.preorder_with_tokens();
@@ -550,14 +543,14 @@ impl Convertor {
 
     fn next_token(
         preorder: &mut PreorderWithTokens,
-        replace: &mut FxHashMap<SyntaxElement, Vec<SyntheticToken>>,
-        append: &mut FxHashMap<SyntaxElement, Vec<SyntheticToken>>,
+        replace: &mut FxHashMap<SyntaxNode, Vec<SyntheticToken>>,
+        append: &mut FxHashMap<SyntaxNode, Vec<SyntheticToken>>,
     ) -> (Option<SyntaxToken>, Vec<SyntheticToken>) {
         while let Some(ev) = preorder.next() {
             let ele = match ev {
                 WalkEvent::Enter(ele) => ele,
-                WalkEvent::Leave(ele) => {
-                    if let Some(mut v) = append.remove(&ele) {
+                WalkEvent::Leave(SyntaxElement::Node(node)) => {
+                    if let Some(mut v) = append.remove(&node) {
                         if !v.is_empty() {
                             v.reverse();
                             return (None, v);
@@ -565,17 +558,19 @@ impl Convertor {
                     }
                     continue;
                 }
+                _ => continue,
             };
-            if let Some(mut v) = replace.remove(&ele) {
-                preorder.skip_subtree();
-                if !v.is_empty() {
-                    v.reverse();
-                    return (None, v);
-                }
-            }
             match ele {
                 SyntaxElement::Token(t) => return (Some(t), Vec::new()),
-                _ => {}
+                SyntaxElement::Node(node) => {
+                    if let Some(mut v) = replace.remove(&node) {
+                        preorder.skip_subtree();
+                        if !v.is_empty() {
+                            v.reverse();
+                            return (None, v);
+                        }
+                    }
+                }
             }
         }
         (None, Vec::new())
diff --git a/crates/project-model/src/workspace.rs b/crates/project-model/src/workspace.rs
index de42458354..ad2f7e51bb 100644
--- a/crates/project-model/src/workspace.rs
+++ b/crates/project-model/src/workspace.rs
@@ -737,7 +737,7 @@ fn handle_rustc_crates(
     let root_pkg =
         rustc_workspace.packages().find(|package| rustc_workspace[*package].name == "rustc_driver");
     // The rustc workspace might be incomplete (such as if rustc-dev is not
-    // installed for the current toolchain) and `rustc_source` is set to discover.
+    // installed for the current toolchain) and `rustcSource` is set to discover.
     if let Some(root_pkg) = root_pkg {
         // Iterate through every crate in the dependency subtree of rustc_driver using BFS
         let mut queue = VecDeque::new();
@@ -822,7 +822,7 @@ fn handle_rustc_crates(
                 for (from, _) in pkg_crates.get(&pkg).into_iter().flatten() {
                     // Avoid creating duplicate dependencies
                     // This avoids the situation where `from` depends on e.g. `arrayvec`, but
-                    // `rust_analyzer` thinks that it should use the one from the `rustc_source`
+                    // `rust_analyzer` thinks that it should use the one from the `rustcSource`
                     // instead of the one from `crates.io`
                     if !crate_graph[*from].dependencies.iter().any(|d| d.name == name) {
                         add_dep(crate_graph, *from, name.clone(), to);
diff --git a/crates/rust-analyzer/src/handlers.rs b/crates/rust-analyzer/src/handlers.rs
index e3875228a1..69a03850b5 100644
--- a/crates/rust-analyzer/src/handlers.rs
+++ b/crates/rust-analyzer/src/handlers.rs
@@ -1798,7 +1798,7 @@ fn run_rustfmt(
                         String::from(
                             "rustfmt range formatting is unstable. \
                             Opt-in by using a nightly build of rustfmt and setting \
-                            `rustfmt.rangeFormatting.enable` to true in your LSP configuration",
+                            `rustfmt.enableRangeFormatting` to true in your LSP configuration",
                         ),
                     )
                     .into());
diff --git a/docs/user/manual.adoc b/docs/user/manual.adoc
index 999a6437ab..f55dfd4703 100644
--- a/docs/user/manual.adoc
+++ b/docs/user/manual.adoc
@@ -308,16 +308,12 @@ nvim_lsp.rust_analyzer.setup({
     on_attach=on_attach,
     settings = {
         ["rust-analyzer"] = {
-            imports = {
-                granularity = {
-                    group = "module",
-                },
-                prefix = "self",
+            assist = {
+                importGranularity = "module",
+                importPrefix = "self",
             },
             cargo = {
-                buildScripts = {
-                    enable = true,
-                },
+                loadOutDirsFromCheck = true
             },
             procMacro = {
                 enable = true
@@ -368,9 +364,7 @@ if executable('rust-analyzer')
         \   'whitelist': ['rust'],
         \   'initialization_options': {
         \     'cargo': {
-        \       'buildScripts': {
-        \         'enable': v:true,
-        \       },
+        \       'loadOutDirsFromCheck': v:true,
         \     },
         \     'procMacro': {
         \       'enable': v:true,
@@ -533,9 +527,7 @@ For example, a very common configuration is to enable proc-macro support, can be
 ----
 {
   "cargo": {
-    "buildScripts": {
-      "enable": true,
-    },
+    "loadOutDirsFromCheck": true,
   },
   "procMacro": {
     "enable": true,
@@ -713,7 +705,7 @@ include::./generated_assists.adoc[]
 == Diagnostics
 
 While most errors and warnings provided by rust-analyzer come from the `cargo check` integration, there's a growing number of diagnostics implemented using rust-analyzer's own analysis.
-Some of these diagnostics don't respect `\#[allow]` or `\#[deny]` attributes yet, but can be turned off using the `rust-analyzer.diagnostics.enable`, `rust-analyzer.diagnostics.experimental.enable` or `rust-analyzer.diagnostics.disabled` settings.
+Some of these diagnostics don't respect `\#[allow]` or `\#[deny]` attributes yet, but can be turned off using the `rust-analyzer.diagnostics.enable`, `rust-analyzer.diagnostics.enableExperimental` or `rust-analyzer.diagnostics.disabled` settings.
 
 include::./generated_diagnostic.adoc[]
 
diff --git a/editors/code/src/ctx.ts b/editors/code/src/ctx.ts
index f2d4737010..992c3d5de6 100644
--- a/editors/code/src/ctx.ts
+++ b/editors/code/src/ctx.ts
@@ -77,35 +77,34 @@ export class Ctx {
 
     setServerStatus(status: ServerStatusParams) {
         let icon = "";
-        const statusBar = this.statusBar;
         switch (status.health) {
             case "ok":
-                statusBar.tooltip = status.message ?? "Ready";
-                statusBar.command = undefined;
-                statusBar.color = undefined;
-                statusBar.backgroundColor = undefined;
+                this.statusBar.tooltip = status.message ?? "Ready";
+                this.statusBar.command = undefined;
+                this.statusBar.color = undefined;
+                this.statusBar.backgroundColor = undefined;
                 break;
             case "warning":
-                statusBar.tooltip =
-                    (status.message ? status.message + "\n" : "") + "Click to reload.";
-
-                statusBar.command = "rust-analyzer.reloadWorkspace";
-                statusBar.color = new vscode.ThemeColor("statusBarItem.warningForeground");
-                statusBar.backgroundColor = new vscode.ThemeColor(
+                this.statusBar.tooltip += "\nClick to reload.";
+                this.statusBar.command = "rust-analyzer.reloadWorkspace";
+                this.statusBar.color = new vscode.ThemeColor("statusBarItem.warningForeground");
+                this.statusBar.backgroundColor = new vscode.ThemeColor(
                     "statusBarItem.warningBackground"
                 );
                 icon = "$(warning) ";
                 break;
             case "error":
-                statusBar.tooltip += "\nClick to reload.";
-                statusBar.command = "rust-analyzer.reloadWorkspace";
-                statusBar.color = new vscode.ThemeColor("statusBarItem.errorForeground");
-                statusBar.backgroundColor = new vscode.ThemeColor("statusBarItem.errorBackground");
+                this.statusBar.tooltip += "\nClick to reload.";
+                this.statusBar.command = "rust-analyzer.reloadWorkspace";
+                this.statusBar.color = new vscode.ThemeColor("statusBarItem.errorForeground");
+                this.statusBar.backgroundColor = new vscode.ThemeColor(
+                    "statusBarItem.errorBackground"
+                );
                 icon = "$(error) ";
                 break;
         }
         if (!status.quiescent) icon = "$(sync~spin) ";
-        statusBar.text = `${icon}rust-analyzer`;
+        this.statusBar.text = `${icon}rust-analyzer`;
     }
 
     pushCleanup(d: Disposable) {
diff --git a/xtask/src/dist.rs b/xtask/src/dist.rs
index 686aec4ae5..c82867d3b4 100644
--- a/xtask/src/dist.rs
+++ b/xtask/src/dist.rs
@@ -24,6 +24,9 @@ impl flags::Dist {
         sh.remove_path(&dist)?;
         sh.create_dir(&dist)?;
 
+        let release_channel = if stable { "stable" } else { "nightly" };
+        dist_server(sh, release_channel, &target)?;
+
         if let Some(patch_version) = self.client_patch_version {
             let version = if stable {
                 format!("{}.{}", VERSION_STABLE, patch_version)
@@ -31,11 +34,8 @@ impl flags::Dist {
                 // A hack to make VS Code prefer nightly over stable.
                 format!("{}.{}", VERSION_NIGHTLY, patch_version)
             };
-            dist_server(sh, &format!("{version}-standalone"), &target)?;
             let release_tag = if stable { date_iso(sh)? } else { "nightly".to_string() };
             dist_client(sh, &version, &release_tag, &target)?;
-        } else {
-            dist_server(sh, "0.0.0-standalone", &target)?;
         }
         Ok(())
     }
@@ -71,8 +71,9 @@ fn dist_client(
     Ok(())
 }
 
-fn dist_server(sh: &Shell, release: &str, target: &Target) -> anyhow::Result<()> {
-    let _e = sh.push_env("CFG_RELEASE", release);
+fn dist_server(sh: &Shell, release_channel: &str, target: &Target) -> anyhow::Result<()> {
+    let _e = sh.push_env("CFG_RELEASE_CHANNEL", release_channel);
+    let _e = sh.push_env("CFG_RELEASE", "0.0.0");
     let _e = sh.push_env("CARGO_PROFILE_RELEASE_LTO", "thin");
 
     // Uncomment to enable debug info for releases. Note that:


Test patch:
diff --git a/crates/ide-completion/src/tests/attribute.rs b/crates/ide-completion/src/tests/attribute.rs
index 1578ba2c37..3b366c94bf 100644
--- a/crates/ide-completion/src/tests/attribute.rs
+++ b/crates/ide-completion/src/tests/attribute.rs
@@ -35,6 +35,7 @@ struct Foo;
             md proc_macros
             kw crate::
             kw self::
+            kw super::
         "#]],
     )
 }
@@ -84,6 +85,7 @@ fn with_existing_attr() {
             at warn(…)
             kw crate::
             kw self::
+            kw super::
         "#]],
     )
 }
@@ -115,6 +117,7 @@ fn attr_on_source_file() {
             at windows_subsystem = "…"
             kw crate::
             kw self::
+            kw super::
         "#]],
     );
 }
@@ -187,6 +190,7 @@ fn attr_on_macro_rules() {
             at warn(…)
             kw crate::
             kw self::
+            kw super::
         "#]],
     );
 }
@@ -210,6 +214,7 @@ fn attr_on_macro_def() {
             at warn(…)
             kw crate::
             kw self::
+            kw super::
         "#]],
     );
 }
@@ -234,6 +239,7 @@ fn attr_on_extern_crate() {
             at warn(…)
             kw crate::
             kw self::
+            kw super::
         "#]],
     );
 }
@@ -257,6 +263,7 @@ fn attr_on_use() {
             at warn(…)
             kw crate::
             kw self::
+            kw super::
         "#]],
     );
 }
@@ -280,6 +287,7 @@ fn attr_on_type_alias() {
             at warn(…)
             kw crate::
             kw self::
+            kw super::
         "#]],
     );
 }
@@ -312,6 +320,7 @@ struct Foo;
             md core
             kw crate::
             kw self::
+            kw super::
         "#]],
     );
 }
@@ -338,6 +347,7 @@ fn attr_on_enum() {
             at warn(…)
             kw crate::
             kw self::
+            kw super::
         "#]],
     );
 }
@@ -361,6 +371,7 @@ fn attr_on_const() {
             at warn(…)
             kw crate::
             kw self::
+            kw super::
         "#]],
     );
 }
@@ -389,6 +400,7 @@ fn attr_on_static() {
             at warn(…)
             kw crate::
             kw self::
+            kw super::
         "#]],
     );
 }
@@ -413,6 +425,7 @@ fn attr_on_trait() {
             at warn(…)
             kw crate::
             kw self::
+            kw super::
         "#]],
     );
 }
@@ -437,6 +450,7 @@ fn attr_on_impl() {
             at warn(…)
             kw crate::
             kw self::
+            kw super::
         "#]],
     );
     check(
@@ -456,6 +470,7 @@ fn attr_on_impl() {
             at warn(…)
             kw crate::
             kw self::
+            kw super::
         "#]],
     );
 }
@@ -480,6 +495,7 @@ fn attr_on_extern_block() {
             at warn(…)
             kw crate::
             kw self::
+            kw super::
         "#]],
     );
     check(
@@ -500,6 +516,7 @@ fn attr_on_extern_block() {
             at warn(…)
             kw crate::
             kw self::
+            kw super::
         "#]],
     );
 }
@@ -518,6 +535,7 @@ fn attr_on_variant() {
             at warn(…)
             kw crate::
             kw self::
+            kw super::
         "#]],
     );
 }
@@ -556,6 +574,7 @@ fn attr_on_fn() {
             at warn(…)
             kw crate::
             kw self::
+            kw super::
         "#]],
     );
 }
@@ -603,6 +622,7 @@ fn attr_in_source_file_end() {
             at warn(…)
             kw crate::
             kw self::
+            kw super::
         "#]],
     );
 }
@@ -659,6 +679,7 @@ mod derive {
                 md core
                 kw crate::
                 kw self::
+                kw super::
             "#]],
         );
     }
@@ -680,6 +701,7 @@ mod derive {
                 md core
                 kw crate::
                 kw self::
+                kw super::
             "#]],
         )
     }
@@ -701,6 +723,7 @@ mod derive {
                 md core
                 kw crate::
                 kw self::
+                kw super::
             "#]],
         );
     }
@@ -721,6 +744,7 @@ mod derive {
                 md core
                 kw crate::
                 kw self::
+                kw super::
             "#]],
         );
     }
@@ -739,6 +763,7 @@ mod derive {
                 md proc_macros
                 kw crate::
                 kw self::
+                kw super::
             "#]],
         );
         check_derive(
@@ -754,6 +779,7 @@ use proc_macros::DeriveIdentity;
                 md proc_macros
                 kw crate::
                 kw self::
+                kw super::
             "#]],
         );
     }
diff --git a/crates/ide-completion/src/tests/expression.rs b/crates/ide-completion/src/tests/expression.rs
index ce9d01d337..c05a7ad9fa 100644
--- a/crates/ide-completion/src/tests/expression.rs
+++ b/crates/ide-completion/src/tests/expression.rs
@@ -58,6 +58,7 @@ fn baz() {
             kw mut
             kw return
             kw self::
+            kw super::
             kw true
             kw unsafe
             kw while
@@ -99,6 +100,7 @@ fn func(param0 @ (param1, param2): (i32, i32)) {
             kw match
             kw return
             kw self::
+            kw super::
             kw true
             kw unsafe
             kw while
@@ -160,6 +162,7 @@ impl Unit {
             kw self::
             kw static
             kw struct
+            kw super::
             kw trait
             kw true
             kw type
@@ -237,6 +240,7 @@ fn complete_in_block() {
             kw self::
             kw static
             kw struct
+            kw super::
             kw trait
             kw true
             kw type
@@ -284,6 +288,7 @@ fn complete_after_if_expr() {
             kw self::
             kw static
             kw struct
+            kw super::
             kw trait
             kw true
             kw type
@@ -321,6 +326,7 @@ fn complete_in_match_arm() {
             kw match
             kw return
             kw self::
+            kw super::
             kw true
             kw unsafe
             kw while
@@ -356,6 +362,7 @@ fn completes_in_loop_ctx() {
             kw self::
             kw static
             kw struct
+            kw super::
             kw trait
             kw true
             kw type
@@ -387,6 +394,7 @@ fn completes_in_let_initializer() {
             kw match
             kw return
             kw self::
+            kw super::
             kw true
             kw unsafe
             kw while
@@ -421,6 +429,7 @@ fn foo() {
             kw match
             kw return
             kw self::
+            kw super::
             kw true
             kw unsafe
             kw while
@@ -456,6 +465,7 @@ fn foo() {
             kw match
             kw return
             kw self::
+            kw super::
             kw true
             kw unsafe
             kw while
@@ -487,6 +497,7 @@ fn quux(x: i32) {
             kw match
             kw return
             kw self::
+            kw super::
             kw true
             kw unsafe
             kw while
@@ -514,6 +525,7 @@ fn quux(x: i32) {
             kw match
             kw return
             kw self::
+            kw super::
             kw true
             kw unsafe
             kw while
diff --git a/crates/ide-completion/src/tests/item.rs b/crates/ide-completion/src/tests/item.rs
index 409413c1dc..81303eb38f 100644
--- a/crates/ide-completion/src/tests/item.rs
+++ b/crates/ide-completion/src/tests/item.rs
@@ -29,6 +29,7 @@ impl Tra$0
             bt u32
             kw crate::
             kw self::
+            kw super::
         "#]],
     )
 }
@@ -51,6 +52,7 @@ impl Trait for Str$0
             bt u32
             kw crate::
             kw self::
+            kw super::
         "#]],
     )
 }
diff --git a/crates/ide-completion/src/tests/item_list.rs b/crates/ide-completion/src/tests/item_list.rs
index 5076c6e86c..09ea78a3d5 100644
--- a/crates/ide-completion/src/tests/item_list.rs
+++ b/crates/ide-completion/src/tests/item_list.rs
@@ -60,6 +60,7 @@ fn in_source_file_item_list() {
             kw self::
             kw static
             kw struct
+            kw super::
             kw trait
             kw type
             kw union
@@ -92,6 +93,7 @@ fn in_item_list_after_attr() {
             kw self::
             kw static
             kw struct
+            kw super::
             kw trait
             kw type
             kw union
@@ -173,6 +175,7 @@ fn in_impl_assoc_item_list() {
             kw pub(crate)
             kw pub(super)
             kw self::
+            kw super::
             kw unsafe
         "#]],
     )
@@ -192,6 +195,7 @@ fn in_impl_assoc_item_list_after_attr() {
             kw pub(crate)
             kw pub(super)
             kw self::
+            kw super::
             kw unsafe
         "#]],
     )
@@ -208,6 +212,7 @@ fn in_trait_assoc_item_list() {
             kw crate::
             kw fn
             kw self::
+            kw super::
             kw type
             kw unsafe
         "#]],
@@ -242,6 +247,7 @@ impl Test for () {
             ta type Type1 =
             kw crate::
             kw self::
+            kw super::
         "#]],
     );
 }
diff --git a/crates/ide-completion/src/tests/pattern.rs b/crates/ide-completion/src/tests/pattern.rs
index 877b5f2164..63ccf9003b 100644
--- a/crates/ide-completion/src/tests/pattern.rs
+++ b/crates/ide-completion/src/tests/pattern.rs
@@ -414,6 +414,7 @@ fn foo() {
             st Bar
             kw crate::
             kw self::
+            kw super::
         "#]],
     );
     check_empty(
@@ -429,6 +430,7 @@ fn foo() {
             st Foo
             kw crate::
             kw self::
+            kw super::
         "#]],
     );
     check_empty(
@@ -630,87 +632,3 @@ fn f(v: u32) {
         "#]],
     );
 }
-
-#[test]
-fn in_method_param() {
-    check_empty(
-        r#"
-struct Ty(u8);
-
-impl Ty {
-    fn foo($0)
-}
-"#,
-        expect![[r#"
-            sp Self
-            st Ty
-            bn &mut self
-            bn &self
-            bn Self(…)   Self($1): Self$0
-            bn Ty(…)     Ty($1): Ty$0
-            bn mut self
-            bn self
-            kw mut
-            kw ref
-        "#]],
-    );
-    check_empty(
-        r#"
-struct Ty(u8);
-
-impl Ty {
-    fn foo(s$0)
-}
-"#,
-        expect![[r#"
-            sp Self
-            st Ty
-            bn &mut self
-            bn &self
-            bn Self(…)   Self($1): Self$0
-            bn Ty(…)     Ty($1): Ty$0
-            bn mut self
-            bn self
-            kw mut
-            kw ref
-        "#]],
-    );
-    check_empty(
-        r#"
-struct Ty(u8);
-
-impl Ty {
-    fn foo(s$0, foo: u8)
-}
-"#,
-        expect![[r#"
-            sp Self
-            st Ty
-            bn &mut self
-            bn &self
-            bn Self(…)   Self($1): Self$0
-            bn Ty(…)     Ty($1): Ty$0
-            bn mut self
-            bn self
-            kw mut
-            kw ref
-        "#]],
-    );
-    check_empty(
-        r#"
-struct Ty(u8);
-
-impl Ty {
-    fn foo(foo: u8, b$0)
-}
-"#,
-        expect![[r#"
-            sp Self
-            st Ty
-            bn Self(…) Self($1): Self$0
-            bn Ty(…)   Ty($1): Ty$0
-            kw mut
-            kw ref
-        "#]],
-    );
-}
diff --git a/crates/ide-completion/src/tests/predicate.rs b/crates/ide-completion/src/tests/predicate.rs
index a8676e2f24..f2b9c061dc 100644
--- a/crates/ide-completion/src/tests/predicate.rs
+++ b/crates/ide-completion/src/tests/predicate.rs
@@ -28,6 +28,7 @@ struct Foo<'lt, T, const C: usize> where $0 {}
             bt u32
             kw crate::
             kw self::
+            kw super::
         "#]],
     );
 }
@@ -44,6 +45,7 @@ struct Foo<'lt, T, const C: usize> where T: $0 {}
             tt Trait
             kw crate::
             kw self::
+            kw super::
         "#]],
     );
 }
@@ -62,6 +64,7 @@ struct Foo<'lt, T, const C: usize> where 'lt: $0 {}
             tt Trait
             kw crate::
             kw self::
+            kw super::
         "#]],
     );
 }
@@ -78,6 +81,7 @@ struct Foo<'lt, T, const C: usize> where for<'a> T: $0 {}
             tt Trait
             kw crate::
             kw self::
+            kw super::
         "#]],
     );
 }
@@ -101,6 +105,7 @@ struct Foo<'lt, T, const C: usize> where for<'a> $0 {}
             bt u32
             kw crate::
             kw self::
+            kw super::
         "#]],
     );
 }
@@ -126,6 +131,7 @@ impl Record {
             bt u32
             kw crate::
             kw self::
+            kw super::
         "#]],
     );
 }
diff --git a/crates/ide-completion/src/tests/record.rs b/crates/ide-completion/src/tests/record.rs
index ec32602fa3..d9b3183208 100644
--- a/crates/ide-completion/src/tests/record.rs
+++ b/crates/ide-completion/src/tests/record.rs
@@ -171,6 +171,7 @@ fn main() {
             bt u32
             kw crate::
             kw self::
+            kw super::
         "#]],
     );
     check(
diff --git a/crates/ide-completion/src/tests/special.rs b/crates/ide-completion/src/tests/special.rs
index ca779c2fc7..fc59f781dd 100644
--- a/crates/ide-completion/src/tests/special.rs
+++ b/crates/ide-completion/src/tests/special.rs
@@ -419,9 +419,9 @@ mod m {
     pub use super::p::WrongType as RightType;
 }
 mod p {
-    pub fn wrong_fn() {}
-    pub const WRONG_CONST: u32 = 1;
-    pub struct WrongType {};
+    fn wrong_fn() {}
+    const WRONG_CONST: u32 = 1;
+    struct WrongType {};
 }
 "#,
         expect![[r#"
@@ -442,9 +442,9 @@ mod m {
     pub use super::p::WrongType as RightType;
 }
 mod p {
-    pub fn wrong_fn() {}
-    pub const WRONG_CONST: u32 = 1;
-    pub struct WrongType {};
+    fn wrong_fn() {}
+    const WRONG_CONST: u32 = 1;
+    struct WrongType {};
 }
 "#,
         r#"
@@ -456,9 +456,9 @@ mod m {
     pub use super::p::WrongType as RightType;
 }
 mod p {
-    pub fn wrong_fn() {}
-    pub const WRONG_CONST: u32 = 1;
-    pub struct WrongType {};
+    fn wrong_fn() {}
+    const WRONG_CONST: u32 = 1;
+    struct WrongType {};
 }
 "#,
     );
@@ -627,6 +627,7 @@ fn main() {
 
 #[test]
 fn respects_doc_hidden2() {
+    cov_mark::check!(qualified_path_doc_hidden);
     check(
         r#"
 //- /lib.rs crate:lib deps:dep
diff --git a/crates/ide-completion/src/tests/type_pos.rs b/crates/ide-completion/src/tests/type_pos.rs
index f0b7726c51..fcd4743f74 100644
--- a/crates/ide-completion/src/tests/type_pos.rs
+++ b/crates/ide-completion/src/tests/type_pos.rs
@@ -31,6 +31,7 @@ struct Foo<'lt, T, const C: usize> {
             bt u32
             kw crate::
             kw self::
+            kw super::
         "#]],
     )
 }
@@ -59,6 +60,7 @@ struct Foo<'lt, T, const C: usize>(f$0);
             kw pub(crate)
             kw pub(super)
             kw self::
+            kw super::
         "#]],
     )
 }
@@ -82,6 +84,7 @@ fn x<'lt, T, const C: usize>() -> $0
             bt u32
             kw crate::
             kw self::
+            kw super::
         "#]],
     );
 }
@@ -112,6 +115,7 @@ fn foo() -> B$0 {
         it ()
         kw crate::
         kw self::
+        kw super::
     "#]],
     )
 }
@@ -137,6 +141,7 @@ const FOO: $0 = Foo(2);
             it Foo<i32>
             kw crate::
             kw self::
+            kw super::
         "#]],
     );
 }
@@ -163,6 +168,7 @@ fn f2() {
             it i32
             kw crate::
             kw self::
+            kw super::
         "#]],
     );
 }
@@ -191,6 +197,7 @@ fn f2() {
             it u64
             kw crate::
             kw self::
+            kw super::
         "#]],
     );
 }
@@ -216,6 +223,7 @@ fn f2(x: u64) -> $0 {
             it u64
             kw crate::
             kw self::
+            kw super::
         "#]],
     );
 }
@@ -242,6 +250,7 @@ fn f2(x: $0) {
             it i32
             kw crate::
             kw self::
+            kw super::
         "#]],
     );
 }
@@ -276,6 +285,7 @@ fn foo<'lt, T, const C: usize>() {
             it a::Foo<a::Foo<i32>>
             kw crate::
             kw self::
+            kw super::
         "#]],
     );
 }
@@ -305,6 +315,7 @@ fn foo<'lt, T, const C: usize>() {
             it Foo<i32>
             kw crate::
             kw self::
+            kw super::
         "#]],
     );
 }
@@ -331,6 +342,7 @@ fn foo<'lt, T, const C: usize>() {
             bt u32
             kw crate::
             kw self::
+            kw super::
         "#]],
     );
     check(
@@ -400,6 +412,7 @@ fn foo<'lt, T: Trait2<$0>, const CONST_PARAM: usize>(_: T) {}
             bt u32
             kw crate::
             kw self::
+            kw super::
         "#]],
     );
     check(
@@ -452,6 +465,7 @@ impl Tr<$0
             bt u32
             kw crate::
             kw self::
+            kw super::
         "#]],
     );
 }
@@ -498,6 +512,7 @@ fn f(t: impl MyTrait<u$0
             bt u32
             kw crate::
             kw self::
+            kw super::
         "#]],
     );
 
@@ -524,6 +539,7 @@ fn f(t: impl MyTrait<u8, u$0
             bt u32
             kw crate::
             kw self::
+            kw super::
         "#]],
     );
 
@@ -568,6 +584,7 @@ fn f(t: impl MyTrait<u$0
             bt u32
             kw crate::
             kw self::
+            kw super::
         "#]],
     );
 
@@ -596,6 +613,7 @@ fn f(t: impl MyTrait<u8, u$0
             bt u32
             kw crate::
             kw self::
+            kw super::
         "#]],
     );
 
@@ -640,6 +658,7 @@ fn f(t: impl MyTrait<Item1 = $0
             bt u32
             kw crate::
             kw self::
+            kw super::
         "#]],
     );
 
@@ -666,6 +685,7 @@ fn f(t: impl MyTrait<Item1 = u8, Item2 = $0
             bt u32
             kw crate::
             kw self::
+            kw super::
         "#]],
     );
 }
diff --git a/crates/ide-completion/src/tests/use_tree.rs b/crates/ide-completion/src/tests/use_tree.rs
index 037d7dce52..109007c7a0 100644
--- a/crates/ide-completion/src/tests/use_tree.rs
+++ b/crates/ide-completion/src/tests/use_tree.rs
@@ -31,6 +31,7 @@ mod foo {}
             md other_crate
             kw crate::
             kw self::
+            kw super::
         "#]],
     );
 }
@@ -213,6 +214,7 @@ struct Bar;
             md bar
             md foo
             st Bar
+            kw super::
         "#]],
     );
 }
@@ -282,73 +284,9 @@ pub use $0;
             md bar
             kw crate::
             kw self::
-        "#]],
-    );
-}
-
-#[test]
-fn pub_suggest_use_tree_super_acc_to_depth_in_tree() {
-    // https://github.com/rust-lang/rust-analyzer/issues/12439
-    // Check discussion in https://github.com/rust-lang/rust-analyzer/pull/12447
-
-    check(
-        r#"
-mod foo {
-    mod bar {
-        pub use super::$0;
-    }
-}
-"#,
-        expect![[r#"
-            md bar
-            kw super::
-        "#]],
-    );
-
-    // Not suggest super when at crate root
-    check(
-        r#"
-mod foo {
-    mod bar {
-        pub use super::super::$0;
-    }
-}
-"#,
-        expect![[r#"
-            md foo
-        "#]],
-    );
-
-    check(
-        r#"
-mod foo {
-    use $0;
-}
-"#,
-        expect![[r#"
-            kw crate::
-            kw self::
             kw super::
         "#]],
     );
-
-    // Not suggest super after another kw in path ( here it is foo1 )
-    check(
-        r#"
-mod foo {
-    mod bar {
-        use super::super::foo1::$0;
-    }
-}
-
-mod foo1 {
-    pub mod bar1 {}
-}
-"#,
-        expect![[r#"
-            md bar1
-        "#]],
-    );
 }
 
 #[test]
@@ -363,6 +301,7 @@ use {$0};
             md bar
             kw crate::
             kw self::
+            kw super::
         "#]],
     );
 }
diff --git a/crates/ide-completion/src/tests/visibility.rs b/crates/ide-completion/src/tests/visibility.rs
index c18d6e66dd..151dd6a7e8 100644
--- a/crates/ide-completion/src/tests/visibility.rs
+++ b/crates/ide-completion/src/tests/visibility.rs
@@ -25,6 +25,7 @@ pub($0)
             kw crate
             kw in
             kw self
+            kw super
         "#]],
     );
 }
@@ -38,6 +39,7 @@ pub(in $0)
         expect![[r#"
             kw crate
             kw self
+            kw super
         "#]],
     );
 }
diff --git a/crates/ide-db/src/imports/insert_use/tests.rs b/crates/ide-db/src/imports/insert_use/tests.rs
index 59673af320..70a7a15232 100644
--- a/crates/ide-db/src/imports/insert_use/tests.rs
+++ b/crates/ide-db/src/imports/insert_use/tests.rs
@@ -441,19 +441,6 @@ fn inserts_after_single_line_inner_comments() {
 
 use foo::bar::Baz;"#,
     );
-    check_none(
-        "foo::bar::Baz",
-        r"mod foo {
-    //! Single line inner comments do not allow any code before them.
-$0
-}",
-        r"mod foo {
-    //! Single line inner comments do not allow any code before them.
-
-    use foo::bar::Baz;
-
-}",
-    );
 }
 
 #[test]
diff --git a/crates/ide/src/hover/tests.rs b/crates/ide/src/hover/tests.rs
index a1484fa19f..867d1f54d4 100644
--- a/crates/ide/src/hover/tests.rs
+++ b/crates/ide/src/hover/tests.rs
@@ -2958,6 +2958,106 @@ struct S$0T<const C: usize = 1, T = Foo>(T);
     );
 }
 
+#[test]
+fn const_generic_positive_i8_literal() {
+    check(
+        r#"
+struct Const<const N: i8>;
+
+fn main() {
+    let v$0alue = Const::<1>;
+}
+"#,
+        expect![[r#"
+            *value*
+
+            ```rust
+            let value: Const<1>
+            ```
+        "#]],
+    );
+}
+
+#[test]
+fn const_generic_zero_i8_literal() {
+    check(
+        r#"
+struct Const<const N: i8>;
+
+fn main() {
+    let v$0alue = Const::<0>;
+}
+"#,
+        expect![[r#"
+            *value*
+
+            ```rust
+            let value: Const<0>
+            ```
+        "#]],
+    );
+}
+
+#[test]
+fn const_generic_negative_i8_literal() {
+    check(
+        r#"
+struct Const<const N: i8>;
+
+fn main() {
+    let v$0alue = Const::<-1>;
+}
+"#,
+        expect![[r#"
+            *value*
+
+            ```rust
+            let value: Const<-1>
+            ```
+        "#]],
+    );
+}
+
+#[test]
+fn const_generic_bool_literal() {
+    check(
+        r#"
+struct Const<const F: bool>;
+
+fn main() {
+    let v$0alue = Const::<true>;
+}
+"#,
+        expect![[r#"
+            *value*
+
+            ```rust
+            let value: Const<true>
+            ```
+        "#]],
+    );
+}
+
+#[test]
+fn const_generic_char_literal() {
+    check(
+        r#"
+struct Const<const C: char>;
+
+fn main() {
+    let v$0alue = Const::<'🦀'>;
+}
+"#,
+        expect![[r#"
+            *value*
+
+            ```rust
+            let value: Const<'🦀'>
+            ```
+        "#]],
+    );
+}
+
 #[test]
 fn hover_self_param_shows_type() {
     check(
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_crate_root.html b/crates/ide/src/syntax_highlighting/test_data/highlight_crate_root.html
index 1e4c06df7e..6704e5e8d5 100644
--- a/crates/ide/src/syntax_highlighting/test_data/highlight_crate_root.html
+++ b/crates/ide/src/syntax_highlighting/test_data/highlight_crate_root.html
@@ -49,18 +49,18 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 
 <span class="keyword">use</span> <span class="module crate_root library">foo</span> <span class="keyword">as</span> <span class="module crate_root declaration library">foooo</span><span class="semicolon">;</span>
 
-<span class="keyword">pub</span><span class="parenthesis">(</span><span class="keyword crate_root public">crate</span><span class="parenthesis">)</span> <span class="keyword">fn</span> <span class="function declaration">main</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span>
+<span class="keyword">pub</span><span class="parenthesis">(</span><span class="keyword crate_root">crate</span><span class="parenthesis">)</span> <span class="keyword">fn</span> <span class="function declaration">main</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span>
     <span class="keyword">let</span> <span class="variable declaration">baz</span> <span class="operator">=</span> <span class="module default_library library">iter</span><span class="operator">::</span><span class="function default_library library">repeat</span><span class="parenthesis">(</span><span class="numeric_literal">92</span><span class="parenthesis">)</span><span class="semicolon">;</span>
 <span class="brace">}</span>
 
 <span class="keyword">mod</span> <span class="module declaration">bar</span> <span class="brace">{</span>
-    <span class="keyword">pub</span><span class="parenthesis">(</span><span class="keyword control">in</span> <span class="keyword crate_root public">super</span><span class="parenthesis">)</span> <span class="keyword">const</span> <span class="constant declaration">FORTY_TWO</span><span class="colon">:</span> <span class="builtin_type">u8</span> <span class="operator">=</span> <span class="numeric_literal">42</span><span class="semicolon">;</span>
+    <span class="keyword">pub</span><span class="parenthesis">(</span><span class="keyword control">in</span> <span class="keyword crate_root">super</span><span class="parenthesis">)</span> <span class="keyword">const</span> <span class="constant declaration">FORTY_TWO</span><span class="colon">:</span> <span class="builtin_type">u8</span> <span class="operator">=</span> <span class="numeric_literal">42</span><span class="semicolon">;</span>
 
     <span class="keyword">mod</span> <span class="module declaration">baz</span> <span class="brace">{</span>
-        <span class="keyword">use</span> <span class="keyword">super</span><span class="operator">::</span><span class="keyword crate_root public">super</span><span class="operator">::</span><span class="constant public">NINETY_TWO</span><span class="semicolon">;</span>
-        <span class="keyword">use</span> <span class="keyword crate_root public">crate</span><span class="operator">::</span><span class="module crate_root library">foooo</span><span class="operator">::</span><span class="struct library">Point</span><span class="semicolon">;</span>
+        <span class="keyword">use</span> <span class="keyword">super</span><span class="operator">::</span><span class="keyword crate_root">super</span><span class="operator">::</span><span class="constant public">NINETY_TWO</span><span class="semicolon">;</span>
+        <span class="keyword">use</span> <span class="keyword crate_root">crate</span><span class="operator">::</span><span class="module crate_root library">foooo</span><span class="operator">::</span><span class="struct library">Point</span><span class="semicolon">;</span>
 
-        <span class="keyword">pub</span><span class="parenthesis">(</span><span class="keyword control">in</span> <span class="keyword">super</span><span class="operator">::</span><span class="keyword crate_root public">super</span><span class="parenthesis">)</span> <span class="keyword">const</span> <span class="constant declaration">TWENTY_NINE</span><span class="colon">:</span> <span class="builtin_type">u8</span> <span class="operator">=</span> <span class="numeric_literal">29</span><span class="semicolon">;</span>
+        <span class="keyword">pub</span><span class="parenthesis">(</span><span class="keyword control">in</span> <span class="keyword">super</span><span class="operator">::</span><span class="keyword crate_root">super</span><span class="parenthesis">)</span> <span class="keyword">const</span> <span class="constant declaration">TWENTY_NINE</span><span class="colon">:</span> <span class="builtin_type">u8</span> <span class="operator">=</span> <span class="numeric_literal">29</span><span class="semicolon">;</span>
     <span class="brace">}</span>
 <span class="brace">}</span>
 </code></pre>
\ No newline at end of file
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_general.html b/crates/ide/src/syntax_highlighting/test_data/highlight_general.html
index a97802cbbd..7bb7ddd280 100644
--- a/crates/ide/src/syntax_highlighting/test_data/highlight_general.html
+++ b/crates/ide/src/syntax_highlighting/test_data/highlight_general.html
@@ -84,7 +84,7 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
     <span class="brace">}</span>
 <span class="brace">}</span>
 
-<span class="keyword">use</span> <span class="self_keyword crate_root public">self</span><span class="operator">::</span><span class="struct">FooCopy</span><span class="operator">::</span><span class="brace">{</span><span class="self_keyword">self</span> <span class="keyword">as</span> <span class="struct declaration">BarCopy</span><span class="brace">}</span><span class="semicolon">;</span>
+<span class="keyword">use</span> <span class="self_keyword crate_root">self</span><span class="operator">::</span><span class="struct">FooCopy</span><span class="operator">::</span><span class="brace">{</span><span class="self_keyword">self</span> <span class="keyword">as</span> <span class="struct declaration">BarCopy</span><span class="brace">}</span><span class="semicolon">;</span>
 
 <span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="attribute attribute default_library library">derive</span><span class="parenthesis attribute">(</span><span class="derive attribute default_library library">Copy</span><span class="parenthesis attribute">)</span><span class="attribute_bracket attribute">]</span>
 <span class="keyword">struct</span> <span class="struct declaration">FooCopy</span> <span class="brace">{</span>
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_keywords.html b/crates/ide/src/syntax_highlighting/test_data/highlight_keywords.html
index 66f9ede962..ba62b68e9d 100644
--- a/crates/ide/src/syntax_highlighting/test_data/highlight_keywords.html
+++ b/crates/ide/src/syntax_highlighting/test_data/highlight_keywords.html
@@ -42,12 +42,12 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 
 .unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
 </style>
-<pre><code><span class="keyword">extern</span> <span class="keyword">crate</span> <span class="self_keyword crate_root public">self</span><span class="semicolon">;</span>
+<pre><code><span class="keyword">extern</span> <span class="keyword">crate</span> <span class="self_keyword crate_root">self</span><span class="semicolon">;</span>
 
-<span class="keyword">use</span> <span class="keyword crate_root public">crate</span><span class="semicolon">;</span>
-<span class="keyword">use</span> <span class="self_keyword crate_root public">self</span><span class="semicolon">;</span>
+<span class="keyword">use</span> <span class="keyword crate_root">crate</span><span class="semicolon">;</span>
+<span class="keyword">use</span> <span class="self_keyword crate_root">self</span><span class="semicolon">;</span>
 <span class="keyword">mod</span> <span class="module declaration">__</span> <span class="brace">{</span>
-    <span class="keyword">use</span> <span class="keyword crate_root public">super</span><span class="operator">::</span><span class="punctuation">*</span><span class="semicolon">;</span>
+    <span class="keyword">use</span> <span class="keyword crate_root">super</span><span class="operator">::</span><span class="punctuation">*</span><span class="semicolon">;</span>
 <span class="brace">}</span>
 
 <span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration">void</span> <span class="brace">{</span>
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_macros.html b/crates/ide/src/syntax_highlighting/test_data/highlight_macros.html
index 54d4279525..b725c80565 100644
--- a/crates/ide/src/syntax_highlighting/test_data/highlight_macros.html
+++ b/crates/ide/src/syntax_highlighting/test_data/highlight_macros.html
@@ -68,13 +68,6 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
     <span class="brace">}</span>
 <span class="brace">}</span>
 
-<span class="comment documentation">/// textually shadow previous definition</span>
-<span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration">noop</span> <span class="brace">{</span>
-    <span class="parenthesis">(</span><span class="punctuation">$</span>expr<span class="colon">:</span>expr<span class="parenthesis">)</span> <span class="operator">=</span><span class="angle">&gt;</span> <span class="brace">{</span>
-        <span class="punctuation">$</span>expr
-    <span class="brace">}</span>
-<span class="brace">}</span>
-
 <span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration">keyword_frag</span> <span class="brace">{</span>
     <span class="parenthesis">(</span><span class="punctuation">$</span>type<span class="colon">:</span>ty<span class="parenthesis">)</span> <span class="operator">=</span><span class="angle">&gt;</span> <span class="parenthesis">(</span><span class="punctuation">$</span>type<span class="parenthesis">)</span>
 <span class="brace">}</span>
diff --git a/crates/ide/src/syntax_highlighting/tests.rs b/crates/ide/src/syntax_highlighting/tests.rs
index 6ba6153178..83bdca295d 100644
--- a/crates/ide/src/syntax_highlighting/tests.rs
+++ b/crates/ide/src/syntax_highlighting/tests.rs
@@ -63,13 +63,6 @@ macro_rules! noop {
     }
 }
 
-/// textually shadow previous definition
-macro_rules! noop {
-    ($expr:expr) => {
-        $expr
-    }
-}
-
 macro_rules! keyword_frag {
     ($type:ty) => ($type)
 }