Repository: rust-lang/rust-analyzer
Pull request #19142 (2025-02-12 07:30:58)

Spawn toolchain querying processes in parallel

Veykril: r? @davidbarsky 

Patch:
diff --git a/crates/hir-def/src/dyn_map.rs b/crates/hir-def/src/dyn_map.rs
index e9318d146d..0f73595347 100644
--- a/crates/hir-def/src/dyn_map.rs
+++ b/crates/hir-def/src/dyn_map.rs
@@ -31,9 +31,9 @@ pub mod keys {
 
     use crate::{
         dyn_map::{DynMap, Policy},
-        BlockId, ConstId, EnumId, EnumVariantId, ExternBlockId, ExternCrateId, FieldId, FunctionId,
-        ImplId, LifetimeParamId, Macro2Id, MacroRulesId, ProcMacroId, StaticId, StructId,
-        TraitAliasId, TraitId, TypeAliasId, TypeOrConstParamId, UnionId, UseId,
+        BlockId, ConstId, EnumId, EnumVariantId, ExternCrateId, FieldId, FunctionId, ImplId,
+        LifetimeParamId, Macro2Id, MacroRulesId, ProcMacroId, StaticId, StructId, TraitAliasId,
+        TraitId, TypeAliasId, TypeOrConstParamId, UnionId, UseId,
     };
 
     pub type Key<K, V> = crate::dyn_map::Key<AstPtr<K>, V, AstPtrPolicy<K, V>>;
@@ -44,7 +44,6 @@ pub mod keys {
     pub const STATIC: Key<ast::Static, StaticId> = Key::new();
     pub const TYPE_ALIAS: Key<ast::TypeAlias, TypeAliasId> = Key::new();
     pub const IMPL: Key<ast::Impl, ImplId> = Key::new();
-    pub const EXTERN_BLOCK: Key<ast::ExternBlock, ExternBlockId> = Key::new();
     pub const TRAIT: Key<ast::Trait, TraitId> = Key::new();
     pub const TRAIT_ALIAS: Key<ast::TraitAlias, TraitAliasId> = Key::new();
     pub const STRUCT: Key<ast::Struct, StructId> = Key::new();
diff --git a/crates/hir-def/src/expr_store.rs b/crates/hir-def/src/expr_store.rs
index 5ff6a7ffe5..9df6eaade7 100644
--- a/crates/hir-def/src/expr_store.rs
+++ b/crates/hir-def/src/expr_store.rs
@@ -112,9 +112,9 @@ pub struct ExpressionStoreSourceMap {
     // AST expressions can create patterns in destructuring assignments. Therefore, `ExprSource` can also map
     // to `PatId`, and `PatId` can also map to `ExprSource` (the other way around is unaffected).
     expr_map: FxHashMap<ExprSource, ExprOrPatId>,
-    expr_map_back: ArenaMap<ExprId, ExprOrPatSource>,
+    expr_map_back: ArenaMap<ExprId, ExprSource>,
 
-    pat_map: FxHashMap<PatSource, ExprOrPatId>,
+    pat_map: FxHashMap<PatSource, PatId>,
     pat_map_back: ArenaMap<PatId, ExprOrPatSource>,
 
     label_map: FxHashMap<LabelSource, LabelId>,
@@ -606,12 +606,12 @@ impl Index<TypeRefId> for ExpressionStore {
 impl ExpressionStoreSourceMap {
     pub fn expr_or_pat_syntax(&self, id: ExprOrPatId) -> Result<ExprOrPatSource, SyntheticSyntax> {
         match id {
-            ExprOrPatId::ExprId(id) => self.expr_syntax(id),
+            ExprOrPatId::ExprId(id) => self.expr_syntax(id).map(|it| it.map(AstPtr::wrap_left)),
             ExprOrPatId::PatId(id) => self.pat_syntax(id),
         }
     }
 
-    pub fn expr_syntax(&self, expr: ExprId) -> Result<ExprOrPatSource, SyntheticSyntax> {
+    pub fn expr_syntax(&self, expr: ExprId) -> Result<ExprSource, SyntheticSyntax> {
         self.expr_map_back.get(expr).cloned().ok_or(SyntheticSyntax)
     }
 
@@ -633,7 +633,7 @@ impl ExpressionStoreSourceMap {
         self.pat_map_back.get(pat).cloned().ok_or(SyntheticSyntax)
     }
 
-    pub fn node_pat(&self, node: InFile<&ast::Pat>) -> Option<ExprOrPatId> {
+    pub fn node_pat(&self, node: InFile<&ast::Pat>) -> Option<PatId> {
         self.pat_map.get(&node.map(AstPtr::new)).cloned()
     }
 
diff --git a/crates/hir-def/src/expr_store/lower.rs b/crates/hir-def/src/expr_store/lower.rs
index 6e505a6b11..88f770da02 100644
--- a/crates/hir-def/src/expr_store/lower.rs
+++ b/crates/hir-def/src/expr_store/lower.rs
@@ -44,8 +44,8 @@ use crate::{
             FormatPlaceholder, FormatSign, FormatTrait,
         },
         Array, Binding, BindingAnnotation, BindingId, BindingProblems, CaptureBy, ClosureKind,
-        Expr, ExprId, Item, Label, LabelId, Literal, MatchArm, Movability, OffsetOf, Pat, PatId,
-        RecordFieldPat, RecordLitField, Statement,
+        Expr, ExprId, Item, Label, LabelId, Literal, LiteralOrConst, MatchArm, Movability,
+        OffsetOf, Pat, PatId, RecordFieldPat, RecordLitField, Statement,
     },
     item_scope::BuiltinShadowMode,
     lang_item::LangItem,
@@ -1784,33 +1784,23 @@ impl ExprCollector<'_> {
                         self.collect_macro_call(call, macro_ptr, true, |this, expanded_pat| {
                             this.collect_pat_opt(expanded_pat, binding_list)
                         });
-                    self.source_map.pat_map.insert(src, pat.into());
+                    self.source_map.pat_map.insert(src, pat);
                     return pat;
                 }
                 None => Pat::Missing,
             },
+            // FIXME: implement in a way that also builds source map and calculates assoc resolutions in type inference.
             ast::Pat::RangePat(p) => {
-                let mut range_part_lower = |p: Option<ast::Pat>| -> Option<ExprId> {
-                    p.and_then(|it| {
-                        let ptr = PatPtr::new(&it);
-                        match &it {
-                            ast::Pat::LiteralPat(it) => Some(self.alloc_expr_from_pat(
-                                Expr::Literal(pat_literal_to_hir(it)?.0),
-                                ptr,
-                            )),
-                            ast::Pat::IdentPat(ident) if ident.is_simple_ident() => ident
-                                .name()
-                                .map(|name| name.as_name())
-                                .map(Path::from)
-                                .map(|path| self.alloc_expr_from_pat(Expr::Path(path), ptr)),
-                            ast::Pat::PathPat(p) => p
-                                .path()
-                                .and_then(|path| self.parse_path(path))
-                                .map(|parsed| self.alloc_expr_from_pat(Expr::Path(parsed), ptr)),
-                            // We only need to handle literal, ident (if bare) and path patterns here,
-                            // as any other pattern as a range pattern operand is semantically invalid.
-                            _ => None,
+                let mut range_part_lower = |p: Option<ast::Pat>| {
+                    p.and_then(|it| match &it {
+                        ast::Pat::LiteralPat(it) => {
+                            Some(Box::new(LiteralOrConst::Literal(pat_literal_to_hir(it)?.0)))
                         }
+                        pat @ (ast::Pat::IdentPat(_) | ast::Pat::PathPat(_)) => {
+                            let subpat = self.collect_pat(pat.clone(), binding_list);
+                            Some(Box::new(LiteralOrConst::Const(subpat)))
+                        }
+                        _ => None,
                     })
                 };
                 let start = range_part_lower(p.start());
@@ -1873,7 +1863,7 @@ impl ExprCollector<'_> {
                             }
                         });
                     if let Some(pat) = pat.left() {
-                        self.source_map.pat_map.insert(src, pat.into());
+                        self.source_map.pat_map.insert(src, pat);
                     }
                     pat
                 }
@@ -2500,7 +2490,7 @@ impl ExprCollector<'_> {
     fn alloc_expr(&mut self, expr: Expr, ptr: ExprPtr) -> ExprId {
         let src = self.expander.in_file(ptr);
         let id = self.store.exprs.alloc(expr);
-        self.source_map.expr_map_back.insert(id, src.map(AstPtr::wrap_left));
+        self.source_map.expr_map_back.insert(id, src);
         self.source_map.expr_map.insert(src, id.into());
         id
     }
@@ -2512,7 +2502,7 @@ impl ExprCollector<'_> {
     fn alloc_expr_desugared_with_ptr(&mut self, expr: Expr, ptr: ExprPtr) -> ExprId {
         let src = self.expander.in_file(ptr);
         let id = self.store.exprs.alloc(expr);
-        self.source_map.expr_map_back.insert(id, src.map(AstPtr::wrap_left));
+        self.source_map.expr_map_back.insert(id, src);
         // We intentionally don't fill this as it could overwrite a non-desugared entry
         // self.source_map.expr_map.insert(src, id);
         id
@@ -2536,20 +2526,11 @@ impl ExprCollector<'_> {
         self.source_map.pat_map_back.insert(id, src.map(AstPtr::wrap_left));
         id
     }
-
-    fn alloc_expr_from_pat(&mut self, expr: Expr, ptr: PatPtr) -> ExprId {
-        let src = self.expander.in_file(ptr);
-        let id = self.store.exprs.alloc(expr);
-        self.source_map.pat_map.insert(src, id.into());
-        self.source_map.expr_map_back.insert(id, src.map(AstPtr::wrap_right));
-        id
-    }
-
     fn alloc_pat(&mut self, pat: Pat, ptr: PatPtr) -> PatId {
         let src = self.expander.in_file(ptr);
         let id = self.store.pats.alloc(pat);
         self.source_map.pat_map_back.insert(id, src.map(AstPtr::wrap_right));
-        self.source_map.pat_map.insert(src, id.into());
+        self.source_map.pat_map.insert(src, id);
         id
     }
     // FIXME: desugared pats don't have ptr, that's wrong and should be fixed somehow.
diff --git a/crates/hir-def/src/expr_store/pretty.rs b/crates/hir-def/src/expr_store/pretty.rs
index 82ad756dc2..6a0b1e5197 100644
--- a/crates/hir-def/src/expr_store/pretty.rs
+++ b/crates/hir-def/src/expr_store/pretty.rs
@@ -6,7 +6,10 @@ use itertools::Itertools;
 use span::Edition;
 
 use crate::{
-    hir::{Array, BindingAnnotation, CaptureBy, ClosureKind, Literal, Movability, Statement},
+    hir::{
+        Array, BindingAnnotation, CaptureBy, ClosureKind, Literal, LiteralOrConst, Movability,
+        Statement,
+    },
     pretty::{print_generic_args, print_path, print_type_ref},
 };
 
@@ -653,11 +656,11 @@ impl Printer<'_> {
             }
             Pat::Range { start, end } => {
                 if let Some(start) = start {
-                    self.print_expr(*start);
+                    self.print_literal_or_const(start);
                 }
                 w!(self, "..=");
                 if let Some(end) = end {
-                    self.print_expr(*end);
+                    self.print_literal_or_const(end);
                 }
             }
             Pat::Slice { prefix, slice, suffix } => {
@@ -754,6 +757,13 @@ impl Printer<'_> {
         }
     }
 
+    fn print_literal_or_const(&mut self, literal_or_const: &LiteralOrConst) {
+        match literal_or_const {
+            LiteralOrConst::Literal(l) => self.print_literal(l),
+            LiteralOrConst::Const(c) => self.print_pat(*c),
+        }
+    }
+
     fn print_literal(&mut self, literal: &Literal) {
         match literal {
             Literal::String(it) => w!(self, "{:?}", it),
diff --git a/crates/hir-def/src/hir.rs b/crates/hir-def/src/hir.rs
index 494644d8ef..0dcddf162b 100644
--- a/crates/hir-def/src/hir.rs
+++ b/crates/hir-def/src/hir.rs
@@ -55,20 +55,12 @@ impl ExprOrPatId {
         }
     }
 
-    pub fn is_expr(&self) -> bool {
-        matches!(self, Self::ExprId(_))
-    }
-
     pub fn as_pat(self) -> Option<PatId> {
         match self {
             Self::PatId(v) => Some(v),
             _ => None,
         }
     }
-
-    pub fn is_pat(&self) -> bool {
-        matches!(self, Self::PatId(_))
-    }
 }
 stdx::impl_from!(ExprId, PatId for ExprOrPatId);
 
@@ -579,8 +571,8 @@ pub enum Pat {
         ellipsis: bool,
     },
     Range {
-        start: Option<ExprId>,
-        end: Option<ExprId>,
+        start: Option<Box<LiteralOrConst>>,
+        end: Option<Box<LiteralOrConst>>,
     },
     Slice {
         prefix: Box<[PatId]>,
diff --git a/crates/hir-def/src/import_map.rs b/crates/hir-def/src/import_map.rs
index d43776b8a6..6137bd34d6 100644
--- a/crates/hir-def/src/import_map.rs
+++ b/crates/hir-def/src/import_map.rs
@@ -320,7 +320,7 @@ impl SearchMode {
                     };
                     match m {
                         Some((index, _)) => {
-                            name = name[index..].strip_prefix(|_: char| true).unwrap_or_default();
+                            name = &name[index + 1..];
                             true
                         }
                         None => false,
@@ -1039,22 +1039,4 @@ pub mod fmt {
             "#]],
         );
     }
-
-    #[test]
-    fn unicode_fn_name() {
-        let ra_fixture = r#"
-            //- /main.rs crate:main deps:dep
-            //- /dep.rs crate:dep
-            pub fn あい() {}
-        "#;
-
-        check_search(
-            ra_fixture,
-            "main",
-            Query::new("あ".to_owned()).fuzzy(),
-            expect![[r#"
-            dep::あい (f)
-        "#]],
-        );
-    }
 }
diff --git a/crates/hir-def/src/item_scope.rs b/crates/hir-def/src/item_scope.rs
index 0ca1eb9bcf..65a39c5656 100644
--- a/crates/hir-def/src/item_scope.rs
+++ b/crates/hir-def/src/item_scope.rs
@@ -18,8 +18,8 @@ use crate::{
     db::DefDatabase,
     per_ns::{Item, MacrosItem, PerNs, TypesItem, ValuesItem},
     visibility::{Visibility, VisibilityExplicitness},
-    AdtId, BuiltinType, ConstId, ExternBlockId, ExternCrateId, FxIndexMap, HasModule, ImplId,
-    LocalModuleId, Lookup, MacroId, ModuleDefId, ModuleId, TraitId, UseId,
+    AdtId, BuiltinType, ConstId, ExternCrateId, FxIndexMap, HasModule, ImplId, LocalModuleId,
+    Lookup, MacroId, ModuleDefId, ModuleId, TraitId, UseId,
 };
 
 #[derive(Debug, Default)]
@@ -158,8 +158,6 @@ pub struct ItemScope {
     declarations: Vec<ModuleDefId>,
 
     impls: Vec<ImplId>,
-    #[allow(clippy::box_collection)]
-    extern_blocks: Option<Box<Vec<ExternBlockId>>>,
     unnamed_consts: Vec<ConstId>,
     /// Traits imported via `use Trait as _;`.
     unnamed_trait_imports: FxHashMap<TraitId, Item<()>>,
@@ -321,10 +319,6 @@ impl ItemScope {
         self.extern_crate_decls.iter().copied()
     }
 
-    pub fn extern_blocks(&self) -> impl Iterator<Item = ExternBlockId> + '_ {
-        self.extern_blocks.iter().flat_map(|it| it.iter()).copied()
-    }
-
     pub fn use_decls(&self) -> impl ExactSizeIterator<Item = UseId> + '_ {
         self.use_decls.iter().copied()
     }
@@ -475,10 +469,6 @@ impl ItemScope {
         self.impls.push(imp);
     }
 
-    pub(crate) fn define_extern_block(&mut self, extern_block: ExternBlockId) {
-        self.extern_blocks.get_or_insert_default().push(extern_block);
-    }
-
     pub(crate) fn define_extern_crate_decl(&mut self, extern_crate: ExternCrateId) {
         self.extern_crate_decls.push(extern_crate);
     }
@@ -816,11 +806,7 @@ impl ItemScope {
             use_imports_types,
             use_imports_macros,
             macro_invocations,
-            extern_blocks,
         } = self;
-        if let Some(it) = extern_blocks {
-            it.shrink_to_fit();
-        }
         types.shrink_to_fit();
         values.shrink_to_fit();
         macros.shrink_to_fit();
diff --git a/crates/hir-def/src/nameres/collector.rs b/crates/hir-def/src/nameres/collector.rs
index 254c137991..06276335b7 100644
--- a/crates/hir-def/src/nameres/collector.rs
+++ b/crates/hir-def/src/nameres/collector.rs
@@ -1759,20 +1759,16 @@ impl ModCollector<'_, '_> {
                         );
                     }
                 }
-                ModItem::ExternBlock(block) => {
-                    let extern_block_id = ExternBlockLoc {
-                        container: module,
-                        id: ItemTreeId::new(self.tree_id, block),
-                    }
-                    .intern(db);
-                    self.def_collector.def_map.modules[self.module_id]
-                        .scope
-                        .define_extern_block(extern_block_id);
-                    self.collect(
-                        &self.item_tree[block].children,
-                        ItemContainerId::ExternBlockId(extern_block_id),
-                    )
-                }
+                ModItem::ExternBlock(block) => self.collect(
+                    &self.item_tree[block].children,
+                    ItemContainerId::ExternBlockId(
+                        ExternBlockLoc {
+                            container: module,
+                            id: ItemTreeId::new(self.tree_id, block),
+                        }
+                        .intern(db),
+                    ),
+                ),
                 ModItem::MacroCall(mac) => self.collect_macro_call(&self.item_tree[mac], container),
                 ModItem::MacroRules(id) => self.collect_macro_rules(id, module),
                 ModItem::Macro2(id) => self.collect_macro_def(id, module),
diff --git a/crates/hir-expand/src/cfg_process.rs b/crates/hir-expand/src/cfg_process.rs
index 626a82ae08..01a3103af8 100644
--- a/crates/hir-expand/src/cfg_process.rs
+++ b/crates/hir-expand/src/cfg_process.rs
@@ -201,6 +201,9 @@ pub(crate) fn process_cfg_attrs(
         MacroDefKind::BuiltInAttr(_, expander) => expander.is_derive(),
         _ => false,
     };
+    if !is_derive {
+        return None;
+    }
     let mut remove = FxHashSet::default();
 
     let item = ast::Item::cast(node.clone())?;
@@ -217,43 +220,28 @@ pub(crate) fn process_cfg_attrs(
             }
         }
     }
-
-    if is_derive {
-        // Only derives get their code cfg-clean, normal attribute macros process only the cfg at their level
-        // (cfg_attr is handled above, cfg is handled in the def map).
-        match item {
-            ast::Item::Struct(it) => match it.field_list()? {
-                ast::FieldList::RecordFieldList(fields) => {
-                    process_has_attrs_with_possible_comma(
-                        db,
-                        fields.fields(),
-                        loc.krate,
-                        &mut remove,
-                    )?;
-                }
-                ast::FieldList::TupleFieldList(fields) => {
-                    process_has_attrs_with_possible_comma(
-                        db,
-                        fields.fields(),
-                        loc.krate,
-                        &mut remove,
-                    )?;
-                }
-            },
-            ast::Item::Enum(it) => {
-                process_enum(db, it.variant_list()?, loc.krate, &mut remove)?;
+    match item {
+        ast::Item::Struct(it) => match it.field_list()? {
+            ast::FieldList::RecordFieldList(fields) => {
+                process_has_attrs_with_possible_comma(db, fields.fields(), loc.krate, &mut remove)?;
             }
-            ast::Item::Union(it) => {
-                process_has_attrs_with_possible_comma(
-                    db,
-                    it.record_field_list()?.fields(),
-                    loc.krate,
-                    &mut remove,
-                )?;
+            ast::FieldList::TupleFieldList(fields) => {
+                process_has_attrs_with_possible_comma(db, fields.fields(), loc.krate, &mut remove)?;
             }
-            // FIXME: Implement for other items if necessary. As we do not support #[cfg_eval] yet, we do not need to implement it for now
-            _ => {}
+        },
+        ast::Item::Enum(it) => {
+            process_enum(db, it.variant_list()?, loc.krate, &mut remove)?;
+        }
+        ast::Item::Union(it) => {
+            process_has_attrs_with_possible_comma(
+                db,
+                it.record_field_list()?.fields(),
+                loc.krate,
+                &mut remove,
+            )?;
         }
+        // FIXME: Implement for other items if necessary. As we do not support #[cfg_eval] yet, we do not need to implement it for now
+        _ => {}
     }
     Some(remove)
 }
diff --git a/crates/hir-ty/src/diagnostics/expr.rs b/crates/hir-ty/src/diagnostics/expr.rs
index 59aaf85164..0b5f131924 100644
--- a/crates/hir-ty/src/diagnostics/expr.rs
+++ b/crates/hir-ty/src/diagnostics/expr.rs
@@ -440,9 +440,7 @@ impl ExprValidator {
                             return;
                         };
                         let root = source_ptr.file_syntax(db.upcast());
-                        let either::Left(ast::Expr::IfExpr(if_expr)) =
-                            source_ptr.value.to_node(&root)
-                        else {
+                        let ast::Expr::IfExpr(if_expr) = source_ptr.value.to_node(&root) else {
                             return;
                         };
                         let mut top_if_expr = if_expr;
diff --git a/crates/hir-ty/src/infer.rs b/crates/hir-ty/src/infer.rs
index 9f20117bf1..617ebba881 100644
--- a/crates/hir-ty/src/infer.rs
+++ b/crates/hir-ty/src/infer.rs
@@ -1239,29 +1239,7 @@ impl<'a> InferenceContext<'a> {
     }
 
     fn write_expr_adj(&mut self, expr: ExprId, adjustments: Vec<Adjustment>) {
-        if adjustments.is_empty() {
-            return;
-        }
-        match self.result.expr_adjustments.entry(expr) {
-            std::collections::hash_map::Entry::Occupied(mut entry) => {
-                match (&mut entry.get_mut()[..], &adjustments[..]) {
-                    (
-                        [Adjustment { kind: Adjust::NeverToAny, target }],
-                        [.., Adjustment { target: new_target, .. }],
-                    ) => {
-                        // NeverToAny coercion can target any type, so instead of adding a new
-                        // adjustment on top we can change the target.
-                        *target = new_target.clone();
-                    }
-                    _ => {
-                        *entry.get_mut() = adjustments;
-                    }
-                }
-            }
-            std::collections::hash_map::Entry::Vacant(entry) => {
-                entry.insert(adjustments);
-            }
-        }
+        self.result.expr_adjustments.insert(expr, adjustments);
     }
 
     fn write_method_resolution(&mut self, expr: ExprId, func: FunctionId, subst: Substitution) {
diff --git a/crates/hir-ty/src/infer/coerce.rs b/crates/hir-ty/src/infer/coerce.rs
index b490a31f68..d40816ba8c 100644
--- a/crates/hir-ty/src/infer/coerce.rs
+++ b/crates/hir-ty/src/infer/coerce.rs
@@ -163,27 +163,10 @@ impl CoerceMany {
         // type is a type variable and the new one is `!`, trying it the other
         // way around first would mean we make the type variable `!`, instead of
         // just marking it as possibly diverging.
-        //
-        // - [Comment from rustc](https://github.com/rust-lang/rust/blob/5ff18d0eaefd1bd9ab8ec33dab2404a44e7631ed/compiler/rustc_hir_typeck/src/coercion.rs#L1334-L1335)
-        // First try to coerce the new expression to the type of the previous ones,
-        // but only if the new expression has no coercion already applied to it.
-        if expr.is_none_or(|expr| !ctx.result.expr_adjustments.contains_key(&expr)) {
-            if let Ok(res) = ctx.coerce(expr, &expr_ty, &self.merged_ty(), CoerceNever::Yes) {
-                self.final_ty = Some(res);
-                if let Some(expr) = expr {
-                    self.expressions.push(expr);
-                }
-                return;
-            }
-        }
-
-        if let Ok((adjustments, res)) =
-            ctx.coerce_inner(&self.merged_ty(), &expr_ty, CoerceNever::Yes)
-        {
+        if let Ok(res) = ctx.coerce(expr, &expr_ty, &self.merged_ty(), CoerceNever::Yes) {
+            self.final_ty = Some(res);
+        } else if let Ok(res) = ctx.coerce(expr, &self.merged_ty(), &expr_ty, CoerceNever::Yes) {
             self.final_ty = Some(res);
-            for &e in &self.expressions {
-                ctx.write_expr_adj(e, adjustments.clone());
-            }
         } else {
             match cause {
                 CoercionCause::Expr(id) => {
@@ -261,23 +244,14 @@ impl InferenceContext<'_> {
         // between places and values.
         coerce_never: CoerceNever,
     ) -> Result<Ty, TypeError> {
-        let (adjustments, ty) = self.coerce_inner(from_ty, to_ty, coerce_never)?;
+        let from_ty = self.resolve_ty_shallow(from_ty);
+        let to_ty = self.resolve_ty_shallow(to_ty);
+        let (adjustments, ty) = self.table.coerce(&from_ty, &to_ty, coerce_never)?;
         if let Some(expr) = expr {
             self.write_expr_adj(expr, adjustments);
         }
         Ok(ty)
     }
-
-    fn coerce_inner(
-        &mut self,
-        from_ty: &Ty,
-        to_ty: &Ty,
-        coerce_never: CoerceNever,
-    ) -> Result<(Vec<Adjustment>, Ty), TypeError> {
-        let from_ty = self.resolve_ty_shallow(from_ty);
-        let to_ty = self.resolve_ty_shallow(to_ty);
-        self.table.coerce(&from_ty, &to_ty, coerce_never)
-    }
 }
 
 impl InferenceTable<'_> {
diff --git a/crates/hir-ty/src/mir.rs b/crates/hir-ty/src/mir.rs
index 41304bbd8a..84d8950b1a 100644
--- a/crates/hir-ty/src/mir.rs
+++ b/crates/hir-ty/src/mir.rs
@@ -10,7 +10,7 @@ use crate::{
     lang_items::is_box,
     mapping::ToChalk,
     CallableDefId, ClosureId, Const, ConstScalar, InferenceResult, Interner, MemoryMap,
-    Substitution, TraitEnvironment, Ty, TyExt, TyKind,
+    Substitution, TraitEnvironment, Ty, TyKind,
 };
 use base_db::CrateId;
 use chalk_ir::Mutability;
@@ -144,13 +144,6 @@ impl<V, T> ProjectionElem<V, T> {
         closure_field: impl FnOnce(ClosureId, &Substitution, usize) -> Ty,
         krate: CrateId,
     ) -> Ty {
-        // we only bail on mir building when there are type mismatches
-        // but error types may pop up resulting in us still attempting to build the mir
-        // so just propagate the error type
-        if base.is_unknown() {
-            return TyKind::Error.intern(Interner);
-        }
-
         if matches!(base.kind(Interner), TyKind::Alias(_) | TyKind::AssociatedType(..)) {
             base = normalize(
                 db,
@@ -173,7 +166,7 @@ impl<V, T> ProjectionElem<V, T> {
                     TyKind::Error.intern(Interner)
                 }
             },
-            ProjectionElem::Field(Either::Left(f)) => match base.kind(Interner) {
+            ProjectionElem::Field(Either::Left(f)) => match &base.kind(Interner) {
                 TyKind::Adt(_, subst) => {
                     db.field_types(f.parent)[f.local_id].clone().substitute(Interner, subst)
                 }
diff --git a/crates/hir-ty/src/mir/lower.rs b/crates/hir-ty/src/mir/lower.rs
index f88696692e..549450e9be 100644
--- a/crates/hir-ty/src/mir/lower.rs
+++ b/crates/hir-ty/src/mir/lower.rs
@@ -8,8 +8,8 @@ use hir_def::{
     data::adt::{StructKind, VariantData},
     expr_store::{Body, HygieneId},
     hir::{
-        ArithOp, Array, BinaryOp, BindingAnnotation, BindingId, ExprId, LabelId, Literal, MatchArm,
-        Pat, PatId, RecordFieldPat, RecordLitField,
+        ArithOp, Array, BinaryOp, BindingAnnotation, BindingId, ExprId, LabelId, Literal,
+        LiteralOrConst, MatchArm, Pat, PatId, RecordFieldPat, RecordLitField,
     },
     lang_item::{LangItem, LangItemTarget},
     path::Path,
@@ -1358,10 +1358,20 @@ impl<'ctx> MirLowerCtx<'ctx> {
         Ok(())
     }
 
-    fn lower_literal_or_const_to_operand(&mut self, ty: Ty, loc: &ExprId) -> Result<Operand> {
-        match &self.body.exprs[*loc] {
-            Expr::Literal(l) => self.lower_literal_to_operand(ty, l),
-            Expr::Path(c) => {
+    fn lower_literal_or_const_to_operand(
+        &mut self,
+        ty: Ty,
+        loc: &LiteralOrConst,
+    ) -> Result<Operand> {
+        match loc {
+            LiteralOrConst::Literal(l) => self.lower_literal_to_operand(ty, l),
+            LiteralOrConst::Const(c) => {
+                let c = match &self.body.pats[*c] {
+                    Pat::Path(p) => p,
+                    _ => not_supported!(
+                        "only `char` and numeric types are allowed in range patterns"
+                    ),
+                };
                 let edition = self.edition();
                 let unresolved_name =
                     || MirLowerError::unresolved_path(self.db, c, edition, &self.body.types);
@@ -1382,9 +1392,6 @@ impl<'ctx> MirLowerCtx<'ctx> {
                     }
                 }
             }
-            _ => {
-                not_supported!("only `char` and numeric types are allowed in range patterns");
-            }
         }
     }
 
diff --git a/crates/hir-ty/src/mir/lower/pattern_matching.rs b/crates/hir-ty/src/mir/lower/pattern_matching.rs
index 289175feef..2ffea34c85 100644
--- a/crates/hir-ty/src/mir/lower/pattern_matching.rs
+++ b/crates/hir-ty/src/mir/lower/pattern_matching.rs
@@ -1,6 +1,6 @@
 //! MIR lowering for patterns
 
-use hir_def::{hir::ExprId, AssocItemId};
+use hir_def::{hir::LiteralOrConst, AssocItemId};
 
 use crate::{
     mir::{
@@ -207,7 +207,7 @@ impl MirLowerCtx<'_> {
                 )?
             }
             Pat::Range { start, end } => {
-                let mut add_check = |l: &ExprId, binop| -> Result<()> {
+                let mut add_check = |l: &LiteralOrConst, binop| -> Result<()> {
                     let lv =
                         self.lower_literal_or_const_to_operand(self.infer[pattern].clone(), l)?;
                     let else_target = *current_else.get_or_insert_with(|| self.new_basic_block());
diff --git a/crates/hir/src/diagnostics.rs b/crates/hir/src/diagnostics.rs
index 5876529df9..64e982c42d 100644
--- a/crates/hir/src/diagnostics.rs
+++ b/crates/hir/src/diagnostics.rs
@@ -6,7 +6,6 @@
 use cfg::{CfgExpr, CfgOptions};
 use either::Either;
 use hir_def::{
-    expr_store::ExprOrPatPtr,
     hir::ExprOrPatId,
     path::{hir_segment_to_ast_segment, ModPath},
     type_ref::TypesSourceMap,
@@ -116,14 +115,14 @@ diagnostics![
 
 #[derive(Debug)]
 pub struct BreakOutsideOfLoop {
-    pub expr: InFile<ExprOrPatPtr>,
+    pub expr: InFile<AstPtr<ast::Expr>>,
     pub is_break: bool,
     pub bad_value_break: bool,
 }
 
 #[derive(Debug)]
 pub struct TypedHole {
-    pub expr: InFile<ExprOrPatPtr>,
+    pub expr: InFile<AstPtr<ast::Expr>>,
     pub expected: Type,
 }
 
@@ -222,26 +221,26 @@ pub struct NoSuchField {
 
 #[derive(Debug)]
 pub struct PrivateAssocItem {
-    pub expr_or_pat: InFile<ExprOrPatPtr>,
+    pub expr_or_pat: InFile<AstPtr<Either<ast::Expr, ast::Pat>>>,
     pub item: AssocItem,
 }
 
 #[derive(Debug)]
 pub struct MismatchedTupleStructPatArgCount {
-    pub expr_or_pat: InFile<ExprOrPatPtr>,
+    pub expr_or_pat: InFile<AstPtr<Either<ast::Expr, ast::Pat>>>,
     pub expected: usize,
     pub found: usize,
 }
 
 #[derive(Debug)]
 pub struct ExpectedFunction {
-    pub call: InFile<ExprOrPatPtr>,
+    pub call: InFile<AstPtr<ast::Expr>>,
     pub found: Type,
 }
 
 #[derive(Debug)]
 pub struct UnresolvedField {
-    pub expr: InFile<ExprOrPatPtr>,
+    pub expr: InFile<AstPtr<ast::Expr>>,
     pub receiver: Type,
     pub name: Name,
     pub method_with_same_name_exists: bool,
@@ -249,7 +248,7 @@ pub struct UnresolvedField {
 
 #[derive(Debug)]
 pub struct UnresolvedMethodCall {
-    pub expr: InFile<ExprOrPatPtr>,
+    pub expr: InFile<AstPtr<ast::Expr>>,
     pub receiver: Type,
     pub name: Name,
     pub field_with_same_name: Option<Type>,
@@ -258,17 +257,17 @@ pub struct UnresolvedMethodCall {
 
 #[derive(Debug)]
 pub struct UnresolvedAssocItem {
-    pub expr_or_pat: InFile<ExprOrPatPtr>,
+    pub expr_or_pat: InFile<AstPtr<Either<ast::Expr, ast::Pat>>>,
 }
 
 #[derive(Debug)]
 pub struct UnresolvedIdent {
-    pub node: InFile<(ExprOrPatPtr, Option<TextRange>)>,
+    pub node: InFile<(AstPtr<Either<ast::Expr, ast::Pat>>, Option<TextRange>)>,
 }
 
 #[derive(Debug)]
 pub struct PrivateField {
-    pub expr: InFile<ExprOrPatPtr>,
+    pub expr: InFile<AstPtr<ast::Expr>>,
     pub field: Field,
 }
 
@@ -281,7 +280,7 @@ pub enum UnsafeLint {
 
 #[derive(Debug)]
 pub struct MissingUnsafe {
-    pub node: InFile<ExprOrPatPtr>,
+    pub node: InFile<AstPtr<Either<ast::Expr, ast::Pat>>>,
     pub lint: UnsafeLint,
     pub reason: UnsafetyReason,
 }
@@ -303,7 +302,7 @@ pub struct ReplaceFilterMapNextWithFindMap {
 
 #[derive(Debug)]
 pub struct MismatchedArgCount {
-    pub call_expr: InFile<ExprOrPatPtr>,
+    pub call_expr: InFile<AstPtr<ast::Expr>>,
     pub expected: usize,
     pub found: usize,
 }
@@ -322,7 +321,7 @@ pub struct NonExhaustiveLet {
 
 #[derive(Debug)]
 pub struct TypeMismatch {
-    pub expr_or_pat: InFile<ExprOrPatPtr>,
+    pub expr_or_pat: InFile<AstPtr<Either<ast::Expr, ast::Pat>>>,
     pub expected: Type,
     pub actual: Type,
 }
@@ -396,13 +395,13 @@ pub struct RemoveUnnecessaryElse {
 
 #[derive(Debug)]
 pub struct CastToUnsized {
-    pub expr: InFile<ExprOrPatPtr>,
+    pub expr: InFile<AstPtr<ast::Expr>>,
     pub cast_ty: Type,
 }
 
 #[derive(Debug)]
 pub struct InvalidCast {
-    pub expr: InFile<ExprOrPatPtr>,
+    pub expr: InFile<AstPtr<ast::Expr>>,
     pub error: CastError,
     pub expr_ty: Type,
     pub cast_ty: Type,
@@ -429,7 +428,9 @@ impl AnyDiagnostic {
                     .collect();
 
                 let record = match record {
-                    Either::Left(record_expr) => source_map.expr_syntax(record_expr).ok()?,
+                    Either::Left(record_expr) => {
+                        source_map.expr_syntax(record_expr).ok()?.map(AstPtr::wrap_left)
+                    }
                     Either::Right(record_pat) => source_map.pat_syntax(record_pat).ok()?,
                 };
                 let file = record.file_id;
@@ -473,7 +474,7 @@ impl AnyDiagnostic {
                     return Some(
                         ReplaceFilterMapNextWithFindMap {
                             file: next_source_ptr.file_id,
-                            next_expr: next_source_ptr.value.cast()?,
+                            next_expr: next_source_ptr.value,
                         }
                         .into(),
                     );
@@ -483,9 +484,7 @@ impl AnyDiagnostic {
                 match source_map.expr_syntax(match_expr) {
                     Ok(source_ptr) => {
                         let root = source_ptr.file_syntax(db.upcast());
-                        if let Either::Left(ast::Expr::MatchExpr(match_expr)) =
-                            &source_ptr.value.to_node(&root)
-                        {
+                        if let ast::Expr::MatchExpr(match_expr) = &source_ptr.value.to_node(&root) {
                             match match_expr.expr() {
                                 Some(scrut_expr) if match_expr.match_arm_list().is_some() => {
                                     return Some(
@@ -562,7 +561,7 @@ impl AnyDiagnostic {
         let pat_syntax =
             |pat| source_map.pat_syntax(pat).inspect_err(|_| stdx::never!("synthetic syntax")).ok();
         let expr_or_pat_syntax = |id| match id {
-            ExprOrPatId::ExprId(expr) => expr_syntax(expr),
+            ExprOrPatId::ExprId(expr) => expr_syntax(expr).map(|it| it.map(AstPtr::wrap_left)),
             ExprOrPatId::PatId(pat) => pat_syntax(pat),
         };
         Some(match d {
@@ -634,7 +633,7 @@ impl AnyDiagnostic {
             &InferenceDiagnostic::UnresolvedIdent { id } => {
                 let node = match id {
                     ExprOrPatId::ExprId(id) => match source_map.expr_syntax(id) {
-                        Ok(syntax) => syntax.map(|it| (it, None)),
+                        Ok(syntax) => syntax.map(|it| (it.wrap_left(), None)),
                         Err(SyntheticSyntax) => source_map
                             .format_args_implicit_capture(id)?
                             .map(|(node, range)| (node.wrap_left(), Some(range))),
@@ -653,7 +652,7 @@ impl AnyDiagnostic {
             }
             &InferenceDiagnostic::MismatchedTupleStructPatArgCount { pat, expected, found } => {
                 let expr_or_pat = match pat {
-                    ExprOrPatId::ExprId(expr) => expr_syntax(expr)?,
+                    ExprOrPatId::ExprId(expr) => expr_syntax(expr)?.map(AstPtr::wrap_left),
                     ExprOrPatId::PatId(pat) => {
                         let InFile { file_id, value } = pat_syntax(pat)?;
 
diff --git a/crates/hir/src/from_id.rs b/crates/hir/src/from_id.rs
index 72df07ef8c..537401afdc 100644
--- a/crates/hir/src/from_id.rs
+++ b/crates/hir/src/from_id.rs
@@ -49,7 +49,6 @@ from_id![
     (hir_def::LifetimeParamId, crate::LifetimeParam),
     (hir_def::MacroId, crate::Macro),
     (hir_def::ExternCrateId, crate::ExternCrateDecl),
-    (hir_def::ExternBlockId, crate::ExternBlock),
 ];
 
 impl From<AdtId> for Adt {
diff --git a/crates/hir/src/has_source.rs b/crates/hir/src/has_source.rs
index a34b498083..82c90ac301 100644
--- a/crates/hir/src/has_source.rs
+++ b/crates/hir/src/has_source.rs
@@ -248,7 +248,7 @@ impl HasSource for Param {
                 let ast @ InFile { file_id, value } = source_map.expr_syntax(expr_id).ok()?;
                 let root = db.parse_or_expand(file_id);
                 match value.to_node(&root) {
-                    Either::Left(ast::Expr::ClosureExpr(it)) => it
+                    ast::Expr::ClosureExpr(it) => it
                         .param_list()?
                         .params()
                         .nth(self.idx)
@@ -301,7 +301,7 @@ impl HasSource for InlineAsmOperand {
             let root = src.file_syntax(db.upcast());
             return src
                 .map(|ast| match ast.to_node(&root) {
-                    Either::Left(ast::Expr::AsmExpr(asm)) => asm
+                    ast::Expr::AsmExpr(asm) => asm
                         .asm_pieces()
                         .filter_map(|it| match it {
                             ast::AsmPiece::AsmOperandNamed(it) => Some(it),
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index 5923a1bc30..56090bc6b6 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -55,8 +55,8 @@ use hir_def::{
     resolver::{HasResolver, Resolver},
     type_ref::TypesSourceMap,
     AdtId, AssocItemId, AssocItemLoc, AttrDefId, CallableDefId, ConstId, ConstParamId,
-    CrateRootModuleId, DefWithBodyId, EnumId, EnumVariantId, ExternBlockId, ExternCrateId,
-    FunctionId, GenericDefId, GenericParamId, HasModule, ImplId, InTypeConstId, ItemContainerId,
+    CrateRootModuleId, DefWithBodyId, EnumId, EnumVariantId, ExternCrateId, FunctionId,
+    GenericDefId, GenericParamId, HasModule, ImplId, InTypeConstId, ItemContainerId,
     LifetimeParamId, LocalFieldId, Lookup, MacroExpander, MacroId, ModuleId, StaticId, StructId,
     SyntheticSyntax, TraitAliasId, TupleId, TypeAliasId, TypeOrConstParamId, TypeParamId, UnionId,
 };
@@ -1957,7 +1957,7 @@ impl DefWithBody {
                 ExprOrPatId::PatId(pat) => source_map.pat_syntax(pat).map(Either::Right),
             };
             let expr_or_pat = match expr_or_pat {
-                Ok(Either::Left(expr)) => expr,
+                Ok(Either::Left(expr)) => expr.map(AstPtr::wrap_left),
                 Ok(Either::Right(InFile { file_id, value: pat })) => {
                     // cast from Either<Pat, SelfParam> -> Either<_, Pat>
                     let Some(ptr) = AstPtr::try_from_raw(pat.syntax_node_ptr()) else {
@@ -2003,7 +2003,7 @@ impl DefWithBody {
             match source_map.expr_syntax(node) {
                 Ok(node) => acc.push(
                     MissingUnsafe {
-                        node,
+                        node: node.map(|it| it.wrap_left()),
                         lint: UnsafeLint::DeprecatedSafe2024,
                         reason: UnsafetyReason::UnsafeFnCall,
                     }
@@ -2327,13 +2327,6 @@ impl Function {
         db.function_data(self.id).is_async()
     }
 
-    pub fn extern_block(self, db: &dyn HirDatabase) -> Option<ExternBlock> {
-        match self.id.lookup(db.upcast()).container {
-            ItemContainerId::ExternBlockId(id) => Some(ExternBlock { id }),
-            _ => None,
-        }
-    }
-
     pub fn returns_impl_future(self, db: &dyn HirDatabase) -> bool {
         if self.is_async(db) {
             return true;
@@ -2768,13 +2761,6 @@ impl Static {
         Type::from_value_def(db, self.id)
     }
 
-    pub fn extern_block(self, db: &dyn HirDatabase) -> Option<ExternBlock> {
-        match self.id.lookup(db.upcast()).container {
-            ItemContainerId::ExternBlockId(id) => Some(ExternBlock { id }),
-            _ => None,
-        }
-    }
-
     /// Evaluate the static initializer.
     pub fn eval(self, db: &dyn HirDatabase) -> Result<EvaluatedConst, ConstEvalError> {
         db.const_eval(self.id.into(), Substitution::empty(Interner), None)
@@ -2942,17 +2928,6 @@ impl HasVisibility for TypeAlias {
     }
 }
 
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
-pub struct ExternBlock {
-    pub(crate) id: ExternBlockId,
-}
-
-impl ExternBlock {
-    pub fn module(self, db: &dyn HirDatabase) -> Module {
-        Module { id: self.id.module(db.upcast()) }
-    }
-}
-
 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
 pub struct StaticLifetime;
 
@@ -4617,7 +4592,10 @@ impl CaptureUsages {
             match span {
                 mir::MirSpan::ExprId(expr) => {
                     if let Ok(expr) = source_map.expr_syntax(expr) {
-                        result.push(CaptureUsageSource { is_ref, source: expr })
+                        result.push(CaptureUsageSource {
+                            is_ref,
+                            source: expr.map(AstPtr::wrap_left),
+                        })
                     }
                 }
                 mir::MirSpan::PatId(pat) => {
@@ -6202,15 +6180,9 @@ impl HasContainer for TraitAlias {
     }
 }
 
-impl HasContainer for ExternBlock {
-    fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
-        ItemContainer::Module(Module { id: self.id.lookup(db.upcast()).container })
-    }
-}
-
 fn container_id_to_hir(c: ItemContainerId) -> ItemContainer {
     match c {
-        ItemContainerId::ExternBlockId(id) => ItemContainer::ExternBlock(ExternBlock { id }),
+        ItemContainerId::ExternBlockId(_id) => ItemContainer::ExternBlock(),
         ItemContainerId::ModuleId(id) => ItemContainer::Module(Module { id }),
         ItemContainerId::ImplId(id) => ItemContainer::Impl(Impl { id }),
         ItemContainerId::TraitId(id) => ItemContainer::Trait(Trait { id }),
@@ -6222,7 +6194,7 @@ pub enum ItemContainer {
     Trait(Trait),
     Impl(Impl),
     Module(Module),
-    ExternBlock(ExternBlock),
+    ExternBlock(),
     Crate(CrateId),
 }
 
diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs
index c9145f7d21..882a27182f 100644
--- a/crates/hir/src/semantics.rs
+++ b/crates/hir/src/semantics.rs
@@ -1998,7 +1998,6 @@ to_def_impls![
     (crate::Adt, ast::Adt, adt_to_def),
     (crate::ExternCrateDecl, ast::ExternCrate, extern_crate_to_def),
     (crate::InlineAsmOperand, ast::AsmOperandNamed, asm_operand_to_def),
-    (crate::ExternBlock, ast::ExternBlock, extern_block_to_def),
     (MacroCallId, ast::MacroCall, macro_call_to_macro_call),
 ];
 
diff --git a/crates/hir/src/semantics/child_by_source.rs b/crates/hir/src/semantics/child_by_source.rs
index d0fdf5cbdf..d5dfb98571 100644
--- a/crates/hir/src/semantics/child_by_source.rs
+++ b/crates/hir/src/semantics/child_by_source.rs
@@ -74,9 +74,6 @@ impl ChildBySource for ItemScope {
     fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap, file_id: HirFileId) {
         self.declarations().for_each(|item| add_module_def(db, res, file_id, item));
         self.impls().for_each(|imp| insert_item_loc(db, res, file_id, imp, keys::IMPL));
-        self.extern_blocks().for_each(|extern_block| {
-            insert_item_loc(db, res, file_id, extern_block, keys::EXTERN_BLOCK)
-        });
         self.extern_crate_decls()
             .for_each(|ext| insert_item_loc(db, res, file_id, ext, keys::EXTERN_CRATE));
         self.use_decls().for_each(|ext| insert_item_loc(db, res, file_id, ext, keys::USE));
diff --git a/crates/hir/src/semantics/source_to_def.rs b/crates/hir/src/semantics/source_to_def.rs
index 4481b8855f..3c9e7065c4 100644
--- a/crates/hir/src/semantics/source_to_def.rs
+++ b/crates/hir/src/semantics/source_to_def.rs
@@ -92,10 +92,10 @@ use hir_def::{
         DynMap,
     },
     hir::{BindingId, Expr, LabelId},
-    AdtId, BlockId, ConstId, ConstParamId, DefWithBodyId, EnumId, EnumVariantId, ExternBlockId,
-    ExternCrateId, FieldId, FunctionId, GenericDefId, GenericParamId, ImplId, LifetimeParamId,
-    Lookup, MacroId, ModuleId, StaticId, StructId, TraitAliasId, TraitId, TypeAliasId, TypeParamId,
-    UnionId, UseId, VariantId,
+    AdtId, BlockId, ConstId, ConstParamId, DefWithBodyId, EnumId, EnumVariantId, ExternCrateId,
+    FieldId, FunctionId, GenericDefId, GenericParamId, ImplId, LifetimeParamId, Lookup, MacroId,
+    ModuleId, StaticId, StructId, TraitAliasId, TraitId, TypeAliasId, TypeParamId, UnionId, UseId,
+    VariantId,
 };
 use hir_expand::{
     attrs::AttrId, name::AsName, ExpansionInfo, HirFileId, HirFileIdExt, InMacroFile, MacroCallId,
@@ -308,12 +308,6 @@ impl SourceToDefCtx<'_, '_> {
     ) -> Option<ExternCrateId> {
         self.to_def(src, keys::EXTERN_CRATE)
     }
-    pub(super) fn extern_block_to_def(
-        &mut self,
-        src: InFile<&ast::ExternBlock>,
-    ) -> Option<ExternBlockId> {
-        self.to_def(src, keys::EXTERN_BLOCK)
-    }
     #[allow(dead_code)]
     pub(super) fn use_to_def(&mut self, src: InFile<&ast::Use>) -> Option<UseId> {
         self.to_def(src, keys::USE)
@@ -358,7 +352,7 @@ impl SourceToDefCtx<'_, '_> {
         let src = src.cloned().map(ast::Pat::from);
         let pat_id = source_map.node_pat(src.as_ref())?;
         // the pattern could resolve to a constant, verify that this is not the case
-        if let crate::Pat::Bind { id, .. } = body[pat_id.as_pat()?] {
+        if let crate::Pat::Bind { id, .. } = body[pat_id] {
             Some((container, id))
         } else {
             None
diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs
index 9019863f7f..c687e2d8a0 100644
--- a/crates/hir/src/source_analyzer.rs
+++ b/crates/hir/src/source_analyzer.rs
@@ -18,7 +18,7 @@ use hir_def::{
         scope::{ExprScopes, ScopeId},
         Body, BodySourceMap, HygieneId,
     },
-    hir::{BindingId, Expr, ExprId, ExprOrPatId, Pat},
+    hir::{BindingId, Expr, ExprId, ExprOrPatId, Pat, PatId},
     lang_item::LangItem,
     lower::LowerCtx,
     nameres::MacroSubNs,
@@ -139,7 +139,7 @@ impl SourceAnalyzer {
         sm.node_expr(src.as_ref())
     }
 
-    fn pat_id(&self, pat: &ast::Pat) -> Option<ExprOrPatId> {
+    fn pat_id(&self, pat: &ast::Pat) -> Option<PatId> {
         // FIXME: macros, see `expr_id`
         let src = InFile { file_id: self.file_id, value: pat };
         self.body_source_map()?.node_pat(src)
@@ -147,7 +147,7 @@ impl SourceAnalyzer {
 
     fn binding_id_of_pat(&self, pat: &ast::IdentPat) -> Option<BindingId> {
         let pat_id = self.pat_id(&pat.clone().into())?;
-        if let Pat::Bind { id, .. } = self.body()?.pats[pat_id.as_pat()?] {
+        if let Pat::Bind { id, .. } = self.body()?.pats[pat_id] {
             Some(id)
         } else {
             None
@@ -210,20 +210,11 @@ impl SourceAnalyzer {
         db: &dyn HirDatabase,
         pat: &ast::Pat,
     ) -> Option<(Type, Option<Type>)> {
-        let expr_or_pat_id = self.pat_id(pat)?;
+        let pat_id = self.pat_id(pat)?;
         let infer = self.infer.as_ref()?;
-        let coerced = match expr_or_pat_id {
-            ExprOrPatId::ExprId(idx) => infer
-                .expr_adjustments
-                .get(&idx)
-                .and_then(|adjusts| adjusts.last().cloned())
-                .map(|adjust| adjust.target),
-            ExprOrPatId::PatId(idx) => {
-                infer.pat_adjustments.get(&idx).and_then(|adjusts| adjusts.last().cloned())
-            }
-        };
-
-        let ty = infer[expr_or_pat_id].clone();
+        let coerced =
+            infer.pat_adjustments.get(&pat_id).and_then(|adjusts| adjusts.last().cloned());
+        let ty = infer[pat_id].clone();
         let mk_ty = |ty| Type::new_with_resolver(db, &self.resolver, ty);
         Some((mk_ty(ty), coerced.map(mk_ty)))
     }
@@ -257,7 +248,7 @@ impl SourceAnalyzer {
     ) -> Option<BindingMode> {
         let id = self.pat_id(&pat.clone().into())?;
         let infer = self.infer.as_ref()?;
-        infer.binding_modes.get(id.as_pat()?).map(|bm| match bm {
+        infer.binding_modes.get(id).map(|bm| match bm {
             hir_ty::BindingMode::Move => BindingMode::Move,
             hir_ty::BindingMode::Ref(hir_ty::Mutability::Mut) => BindingMode::Ref(Mutability::Mut),
             hir_ty::BindingMode::Ref(hir_ty::Mutability::Not) => {
@@ -275,7 +266,7 @@ impl SourceAnalyzer {
         Some(
             infer
                 .pat_adjustments
-                .get(&pat_id.as_pat()?)?
+                .get(&pat_id)?
                 .iter()
                 .map(|ty| Type::new_with_resolver(db, &self.resolver, ty.clone()))
                 .collect(),
@@ -658,10 +649,10 @@ impl SourceAnalyzer {
         let field_name = field.field_name()?.as_name();
         let record_pat = ast::RecordPat::cast(field.syntax().parent().and_then(|p| p.parent())?)?;
         let pat_id = self.pat_id(&record_pat.into())?;
-        let variant = self.infer.as_ref()?.variant_resolution_for_pat(pat_id.as_pat()?)?;
+        let variant = self.infer.as_ref()?.variant_resolution_for_pat(pat_id)?;
         let variant_data = variant.variant_data(db.upcast());
         let field = FieldId { parent: variant, local_id: variant_data.field(&field_name)? };
-        let (adt, subst) = self.infer.as_ref()?.type_of_pat.get(pat_id.as_pat()?)?.as_adt()?;
+        let (adt, subst) = self.infer.as_ref()?.type_of_pat.get(pat_id)?.as_adt()?;
         let field_ty =
             db.field_types(variant).get(field.local_id)?.clone().substitute(Interner, subst);
         Some((
@@ -691,20 +682,12 @@ impl SourceAnalyzer {
         db: &dyn HirDatabase,
         pat: &ast::IdentPat,
     ) -> Option<ModuleDef> {
-        let expr_or_pat_id = self.pat_id(&pat.clone().into())?;
+        let pat_id = self.pat_id(&pat.clone().into())?;
         let body = self.body()?;
-
-        let path = match expr_or_pat_id {
-            ExprOrPatId::ExprId(idx) => match &body[idx] {
-                Expr::Path(path) => path,
-                _ => return None,
-            },
-            ExprOrPatId::PatId(idx) => match &body[idx] {
-                Pat::Path(path) => path,
-                _ => return None,
-            },
+        let path = match &body[pat_id] {
+            Pat::Path(path) => path,
+            _ => return None,
         };
-
         let res = resolve_hir_path(db, &self.resolver, path, HygieneId::ROOT, TypesMap::EMPTY)?;
         match res {
             PathResolution::Def(def) => Some(def),
@@ -799,9 +782,8 @@ impl SourceAnalyzer {
                 }
                 prefer_value_ns = true;
             } else if let Some(path_pat) = parent().and_then(ast::PathPat::cast) {
-                let expr_or_pat_id = self.pat_id(&path_pat.into())?;
-                if let Some((assoc, subs)) = infer.assoc_resolutions_for_expr_or_pat(expr_or_pat_id)
-                {
+                let pat_id = self.pat_id(&path_pat.into())?;
+                if let Some((assoc, subs)) = infer.assoc_resolutions_for_pat(pat_id) {
                     let (assoc, subst) = match assoc {
                         AssocItemId::ConstId(const_id) => {
                             let (konst, subst) =
@@ -825,7 +807,7 @@ impl SourceAnalyzer {
                     return Some((PathResolution::Def(AssocItem::from(assoc).into()), Some(subst)));
                 }
                 if let Some(VariantId::EnumVariantId(variant)) =
-                    infer.variant_resolution_for_expr_or_pat(expr_or_pat_id)
+                    infer.variant_resolution_for_pat(pat_id)
                 {
                     return Some((PathResolution::Def(ModuleDef::Variant(variant.into())), None));
                 }
@@ -842,7 +824,7 @@ impl SourceAnalyzer {
                     || parent().and_then(ast::TupleStructPat::cast).map(ast::Pat::from);
                 if let Some(pat) = record_pat.or_else(tuple_struct_pat) {
                     let pat_id = self.pat_id(&pat)?;
-                    let variant_res_for_pat = infer.variant_resolution_for_pat(pat_id.as_pat()?);
+                    let variant_res_for_pat = infer.variant_resolution_for_pat(pat_id);
                     if let Some(VariantId::EnumVariantId(variant)) = variant_res_for_pat {
                         return Some((
                             PathResolution::Def(ModuleDef::Variant(variant.into())),
@@ -1098,7 +1080,7 @@ impl SourceAnalyzer {
         let body = self.body()?;
         let infer = self.infer.as_ref()?;
 
-        let pat_id = self.pat_id(&pattern.clone().into())?.as_pat()?;
+        let pat_id = self.pat_id(&pattern.clone().into())?;
         let substs = infer.type_of_pat[pat_id].as_adt()?.1;
 
         let (variant, missing_fields, _exhaustive) =
diff --git a/crates/ide-completion/src/completions/postfix.rs b/crates/ide-completion/src/completions/postfix.rs
index 28e2853096..2c39a8fdfe 100644
--- a/crates/ide-completion/src/completions/postfix.rs
+++ b/crates/ide-completion/src/completions/postfix.rs
@@ -2,18 +2,17 @@
 
 mod format_like;
 
-use base_db::SourceDatabase;
-use hir::{ItemInNs, Semantics};
+use hir::ItemInNs;
+use ide_db::text_edit::TextEdit;
 use ide_db::{
     documentation::{Documentation, HasDocs},
     imports::insert_use::ImportScope,
-    text_edit::TextEdit,
     ty_filter::TryEnum,
-    RootDatabase, SnippetCap,
+    SnippetCap,
 };
 use stdx::never;
 use syntax::{
-    ast::{self, AstNode, AstToken},
+    ast::{self, make, AstNode, AstToken},
     SyntaxKind::{BLOCK_EXPR, EXPR_STMT, FOR_EXPR, IF_EXPR, LOOP_EXPR, STMT_LIST, WHILE_EXPR},
     TextRange, TextSize,
 };
@@ -49,8 +48,7 @@ pub(crate) fn complete_postfix(
     };
     let expr_ctx = &dot_access.ctx;
 
-    let receiver_text =
-        get_receiver_text(&ctx.sema, dot_receiver, receiver_is_ambiguous_float_literal);
+    let receiver_text = get_receiver_text(dot_receiver, receiver_is_ambiguous_float_literal);
 
     let cap = match ctx.config.snippet_cap {
         Some(it) => it,
@@ -174,15 +172,13 @@ pub(crate) fn complete_postfix(
     // The rest of the postfix completions create an expression that moves an argument,
     // so it's better to consider references now to avoid breaking the compilation
 
-    let (dot_receiver_including_refs, prefix) = include_references(dot_receiver);
-    let mut receiver_text =
-        get_receiver_text(&ctx.sema, dot_receiver, receiver_is_ambiguous_float_literal);
-    receiver_text.insert_str(0, &prefix);
-    let postfix_snippet =
-        match build_postfix_snippet_builder(ctx, cap, &dot_receiver_including_refs) {
-            Some(it) => it,
-            None => return,
-        };
+    let (dot_receiver, node_to_replace_with) = include_references(dot_receiver);
+    let receiver_text =
+        get_receiver_text(&node_to_replace_with, receiver_is_ambiguous_float_literal);
+    let postfix_snippet = match build_postfix_snippet_builder(ctx, cap, &dot_receiver) {
+        Some(it) => it,
+        None => return,
+    };
 
     if !ctx.config.snippets.is_empty() {
         add_custom_postfix_completions(acc, ctx, &postfix_snippet, &receiver_text);
@@ -226,7 +222,7 @@ pub(crate) fn complete_postfix(
     postfix_snippet("call", "function(expr)", &format!("${{1}}({receiver_text})"))
         .add_to(acc, ctx.db);
 
-    if let Some(parent) = dot_receiver_including_refs.syntax().parent().and_then(|p| p.parent()) {
+    if let Some(parent) = dot_receiver.syntax().parent().and_then(|p| p.parent()) {
         if matches!(parent.kind(), STMT_LIST | EXPR_STMT) {
             postfix_snippet("let", "let", &format!("let $0 = {receiver_text};"))
                 .add_to(acc, ctx.db);
@@ -235,9 +231,9 @@ pub(crate) fn complete_postfix(
         }
     }
 
-    if let ast::Expr::Literal(literal) = dot_receiver_including_refs.clone() {
+    if let ast::Expr::Literal(literal) = dot_receiver.clone() {
         if let Some(literal_text) = ast::String::cast(literal.token()) {
-            add_format_like_completions(acc, ctx, &dot_receiver_including_refs, cap, &literal_text);
+            add_format_like_completions(acc, ctx, &dot_receiver, cap, &literal_text);
         }
     }
 
@@ -264,20 +260,14 @@ pub(crate) fn complete_postfix(
     }
 }
 
-fn get_receiver_text(
-    sema: &Semantics<'_, RootDatabase>,
-    receiver: &ast::Expr,
-    receiver_is_ambiguous_float_literal: bool,
-) -> String {
-    // Do not just call `receiver.to_string()`, as that will mess up whitespaces inside macros.
-    let Some(mut range) = sema.original_range_opt(receiver.syntax()) else {
-        return receiver.to_string();
+fn get_receiver_text(receiver: &ast::Expr, receiver_is_ambiguous_float_literal: bool) -> String {
+    let mut text = if receiver_is_ambiguous_float_literal {
+        let text = receiver.syntax().text();
+        let without_dot = ..text.len() - TextSize::of('.');
+        text.slice(without_dot).to_string()
+    } else {
+        receiver.to_string()
     };
-    if receiver_is_ambiguous_float_literal {
-        range.range = TextRange::at(range.range.start(), range.range.len() - TextSize::of('.'))
-    }
-    let file_text = sema.db.file_text(range.file_id.file_id());
-    let mut text = file_text[range.range].to_owned();
 
     // The receiver texts should be interpreted as-is, as they are expected to be
     // normal Rust expressions.
@@ -294,7 +284,7 @@ fn escape_snippet_bits(text: &mut String) {
     stdx::replace(text, '$', "\\$");
 }
 
-fn include_references(initial_element: &ast::Expr) -> (ast::Expr, String) {
+fn include_references(initial_element: &ast::Expr) -> (ast::Expr, ast::Expr) {
     let mut resulting_element = initial_element.clone();
 
     while let Some(field_expr) = resulting_element.syntax().parent().and_then(ast::FieldExpr::cast)
@@ -302,7 +292,7 @@ fn include_references(initial_element: &ast::Expr) -> (ast::Expr, String) {
         resulting_element = ast::Expr::from(field_expr);
     }
 
-    let mut prefix = String::new();
+    let mut new_element_opt = initial_element.clone();
 
     while let Some(parent_deref_element) =
         resulting_element.syntax().parent().and_then(ast::PrefixExpr::cast)
@@ -313,7 +303,7 @@ fn include_references(initial_element: &ast::Expr) -> (ast::Expr, String) {
 
         resulting_element = ast::Expr::from(parent_deref_element);
 
-        prefix.insert(0, '*');
+        new_element_opt = make::expr_prefix(syntax::T![*], new_element_opt).into();
     }
 
     if let Some(first_ref_expr) = resulting_element.syntax().parent().and_then(ast::RefExpr::cast) {
@@ -327,7 +317,7 @@ fn include_references(initial_element: &ast::Expr) -> (ast::Expr, String) {
             let exclusive = parent_ref_element.mut_token().is_some();
             resulting_element = ast::Expr::from(parent_ref_element);
 
-            prefix.insert_str(0, if exclusive { "&mut " } else { "&" });
+            new_element_opt = make::expr_ref(new_element_opt, exclusive);
         }
     } else {
         // If we do not find any ref expressions, restore
@@ -335,7 +325,7 @@ fn include_references(initial_element: &ast::Expr) -> (ast::Expr, String) {
         resulting_element = initial_element.clone();
     }
 
-    (resulting_element, prefix)
+    (resulting_element, new_element_opt)
 }
 
 fn build_postfix_snippet_builder<'ctx>(
@@ -911,31 +901,4 @@ fn main() {
 "#,
         );
     }
-
-    #[test]
-    fn inside_macro() {
-        check_edit(
-            "box",
-            r#"
-macro_rules! assert {
-    ( $it:expr $(,)? ) => { $it };
-}
-
-fn foo() {
-    let a = true;
-    assert!(if a == false { true } else { false }.$0);
-}
-        "#,
-            r#"
-macro_rules! assert {
-    ( $it:expr $(,)? ) => { $it };
-}
-
-fn foo() {
-    let a = true;
-    assert!(Box::new(if a == false { true } else { false }));
-}
-        "#,
-        );
-    }
 }
diff --git a/crates/ide-db/src/defs.rs b/crates/ide-db/src/defs.rs
index 6f71c3d9bd..bad5360805 100644
--- a/crates/ide-db/src/defs.rs
+++ b/crates/ide-db/src/defs.rs
@@ -108,7 +108,7 @@ impl Definition {
                 ItemContainer::Trait(it) => Some(it.into()),
                 ItemContainer::Impl(it) => Some(it.into()),
                 ItemContainer::Module(it) => Some(it.into()),
-                ItemContainer::ExternBlock(_) | ItemContainer::Crate(_) => None,
+                ItemContainer::ExternBlock() | ItemContainer::Crate(_) => None,
             }
         }
         match self {
diff --git a/crates/ide-diagnostics/src/handlers/mismatched_arg_count.rs b/crates/ide-diagnostics/src/handlers/mismatched_arg_count.rs
index 0520bb3fe9..7126617cde 100644
--- a/crates/ide-diagnostics/src/handlers/mismatched_arg_count.rs
+++ b/crates/ide-diagnostics/src/handlers/mismatched_arg_count.rs
@@ -40,7 +40,7 @@ pub(crate) fn mismatched_arg_count(
     Diagnostic::new(
         DiagnosticCode::RustcHardError("E0107"),
         message,
-        invalid_args_range(ctx, d.call_expr, d.expected, d.found),
+        invalid_args_range(ctx, d.call_expr.map(AstPtr::wrap_left), d.expected, d.found),
     )
 }
 
diff --git a/crates/ide-diagnostics/src/handlers/unresolved_field.rs b/crates/ide-diagnostics/src/handlers/unresolved_field.rs
index dfb03eee73..4accd181ca 100644
--- a/crates/ide-diagnostics/src/handlers/unresolved_field.rs
+++ b/crates/ide-diagnostics/src/handlers/unresolved_field.rs
@@ -1,6 +1,5 @@
 use std::iter;
 
-use either::Either;
 use hir::{db::ExpandDatabase, Adt, FileRange, HasSource, HirDisplay, InFile, Struct, Union};
 use ide_db::text_edit::TextEdit;
 use ide_db::{
@@ -42,7 +41,7 @@ pub(crate) fn unresolved_field(
         ),
         adjusted_display_range(ctx, d.expr, &|expr| {
             Some(
-                match expr.left()? {
+                match expr {
                     ast::Expr::MethodCallExpr(it) => it.name_ref(),
                     ast::Expr::FieldExpr(it) => it.name_ref(),
                     _ => None,
@@ -73,7 +72,7 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::UnresolvedField) -> Option<Vec<A
 fn field_fix(ctx: &DiagnosticsContext<'_>, d: &hir::UnresolvedField) -> Option<Assist> {
     // Get the FileRange of the invalid field access
     let root = ctx.sema.db.parse_or_expand(d.expr.file_id);
-    let expr = d.expr.value.to_node(&root).left()?;
+    let expr = d.expr.value.to_node(&root);
 
     let error_range = ctx.sema.original_range_opt(expr.syntax())?;
     let field_name = d.name.as_str();
@@ -264,7 +263,7 @@ fn record_field_layout(
 // FIXME: We should fill out the call here, move the cursor and trigger signature help
 fn method_fix(
     ctx: &DiagnosticsContext<'_>,
-    expr_ptr: &InFile<AstPtr<Either<ast::Expr, ast::Pat>>>,
+    expr_ptr: &InFile<AstPtr<ast::Expr>>,
 ) -> Option<Assist> {
     let root = ctx.sema.db.parse_or_expand(expr_ptr.file_id);
     let expr = expr_ptr.value.to_node(&root);
diff --git a/crates/ide-diagnostics/src/handlers/unresolved_method.rs b/crates/ide-diagnostics/src/handlers/unresolved_method.rs
index dd1b593e8f..4ab649cc16 100644
--- a/crates/ide-diagnostics/src/handlers/unresolved_method.rs
+++ b/crates/ide-diagnostics/src/handlers/unresolved_method.rs
@@ -35,7 +35,7 @@ pub(crate) fn unresolved_method(
         ),
         adjusted_display_range(ctx, d.expr, &|expr| {
             Some(
-                match expr.left()? {
+                match expr {
                     ast::Expr::MethodCallExpr(it) => it.name_ref(),
                     ast::Expr::FieldExpr(it) => it.name_ref(),
                     _ => None,
@@ -85,7 +85,7 @@ fn field_fix(
     let expr_ptr = &d.expr;
     let root = ctx.sema.db.parse_or_expand(expr_ptr.file_id);
     let expr = expr_ptr.value.to_node(&root);
-    let (file_id, range) = match expr.left()? {
+    let (file_id, range) = match expr {
         ast::Expr::MethodCallExpr(mcall) => {
             let FileRange { range, file_id } =
                 ctx.sema.original_range_opt(mcall.receiver()?.syntax())?;
@@ -117,7 +117,7 @@ fn assoc_func_fix(ctx: &DiagnosticsContext<'_>, d: &hir::UnresolvedMethodCall) -
 
         let expr_ptr = &d.expr;
         let root = db.parse_or_expand(expr_ptr.file_id);
-        let expr: ast::Expr = expr_ptr.value.to_node(&root).left()?;
+        let expr: ast::Expr = expr_ptr.value.to_node(&root);
 
         let call = ast::MethodCallExpr::cast(expr.syntax().clone())?;
         let range = InFile::new(expr_ptr.file_id, call.syntax().text_range())
diff --git a/crates/ide-diagnostics/src/handlers/unused_variables.rs b/crates/ide-diagnostics/src/handlers/unused_variables.rs
index d5caf4de33..67ece56694 100644
--- a/crates/ide-diagnostics/src/handlers/unused_variables.rs
+++ b/crates/ide-diagnostics/src/handlers/unused_variables.rs
@@ -260,19 +260,6 @@ fn main() {
     let arr = [1, 2, 3, 4, 5];
     let [_x, _y @ ..] = arr;
 }
-"#,
-        );
-    }
-
-    // regression test as we used to panic in this scenario
-    #[test]
-    fn unknown_struct_pattern_param_type() {
-        check_diagnostics(
-            r#"
-struct S { field : u32 }
-fn f(S { field }: error) {
-      // ^^^^^ 💡 warn: unused variable
-}
 "#,
         );
     }
diff --git a/crates/ide/src/inlay_hints/extern_block.rs b/crates/ide/src/inlay_hints/extern_block.rs
index 652dff0bc5..2bc91b68ed 100644
--- a/crates/ide/src/inlay_hints/extern_block.rs
+++ b/crates/ide/src/inlay_hints/extern_block.rs
@@ -7,7 +7,7 @@ use crate::{InlayHint, InlayHintsConfig};
 
 pub(super) fn extern_block_hints(
     acc: &mut Vec<InlayHint>,
-    FamousDefs(sema, _): &FamousDefs<'_, '_>,
+    FamousDefs(_sema, _): &FamousDefs<'_, '_>,
     config: &InlayHintsConfig,
     _file_id: EditionedFileId,
     extern_block: ast::ExternBlock,
@@ -16,7 +16,6 @@ pub(super) fn extern_block_hints(
         return None;
     }
     let abi = extern_block.abi()?;
-    sema.to_def(&extern_block)?;
     acc.push(InlayHint {
         range: abi.syntax().text_range(),
         position: crate::InlayHintPosition::Before,
@@ -34,7 +33,7 @@ pub(super) fn extern_block_hints(
 
 pub(super) fn fn_hints(
     acc: &mut Vec<InlayHint>,
-    FamousDefs(sema, _): &FamousDefs<'_, '_>,
+    FamousDefs(_sema, _): &FamousDefs<'_, '_>,
     config: &InlayHintsConfig,
     _file_id: EditionedFileId,
     fn_: &ast::Fn,
@@ -44,16 +43,14 @@ pub(super) fn fn_hints(
     if !implicit_unsafe {
         return None;
     }
-    let fn_token = fn_.fn_token()?;
-    if sema.to_def(fn_).is_some_and(|def| def.extern_block(sema.db).is_some()) {
-        acc.push(item_hint(config, extern_block, fn_token));
-    }
+    let fn_ = fn_.fn_token()?;
+    acc.push(item_hint(config, extern_block, fn_));
     Some(())
 }
 
 pub(super) fn static_hints(
     acc: &mut Vec<InlayHint>,
-    FamousDefs(sema, _): &FamousDefs<'_, '_>,
+    FamousDefs(_sema, _): &FamousDefs<'_, '_>,
     config: &InlayHintsConfig,
     _file_id: EditionedFileId,
     static_: &ast::Static,
@@ -63,10 +60,8 @@ pub(super) fn static_hints(
     if !implicit_unsafe {
         return None;
     }
-    let static_token = static_.static_token()?;
-    if sema.to_def(static_).is_some_and(|def| def.extern_block(sema.db).is_some()) {
-        acc.push(item_hint(config, extern_block, static_token));
-    }
+    let static_ = static_.static_token()?;
+    acc.push(item_hint(config, extern_block, static_));
     Some(())
 }
 
diff --git a/crates/ide/src/inlay_hints/implicit_drop.rs b/crates/ide/src/inlay_hints/implicit_drop.rs
index 390139d214..58dc0fdf62 100644
--- a/crates/ide/src/inlay_hints/implicit_drop.rs
+++ b/crates/ide/src/inlay_hints/implicit_drop.rs
@@ -73,8 +73,8 @@ pub(super) fn hints(
                     _ => continue,
                 },
                 MirSpan::PatId(p) => match source_map.pat_syntax(p) {
-                    Ok(s) if !s.file_id.is_macro() => s.value.text_range(),
-                    _ => continue,
+                    Ok(s) => s.value.text_range(),
+                    Err(_) => continue,
                 },
                 MirSpan::BindingId(b) => {
                     match source_map
@@ -82,13 +82,13 @@ pub(super) fn hints(
                         .iter()
                         .find_map(|p| source_map.pat_syntax(*p).ok())
                     {
-                        Some(s) if !s.file_id.is_macro() => s.value.text_range(),
-                        _ => continue,
+                        Some(s) => s.value.text_range(),
+                        None => continue,
                     }
                 }
                 MirSpan::SelfParam => match source_map.self_param_syntax() {
-                    Some(s) if !s.file_id.is_macro() => s.value.text_range(),
-                    _ => continue,
+                    Some(s) => s.value.text_range(),
+                    None => continue,
                 },
                 MirSpan::Unknown => continue,
             };
diff --git a/crates/project-model/src/lib.rs b/crates/project-model/src/lib.rs
index fc1fd7b877..0c73447468 100644
--- a/crates/project-model/src/lib.rs
+++ b/crates/project-model/src/lib.rs
@@ -260,19 +260,19 @@ fn parse_cfg(s: &str) -> Result<cfg::CfgAtom, String> {
 }
 
 #[derive(Clone, Debug, PartialEq, Eq)]
-pub enum SysrootSourceWorkspaceConfig {
+pub enum RustSourceWorkspaceConfig {
     CargoMetadata(CargoMetadataConfig),
     Stitched,
 }
 
-impl Default for SysrootSourceWorkspaceConfig {
+impl Default for RustSourceWorkspaceConfig {
     fn default() -> Self {
-        SysrootSourceWorkspaceConfig::default_cargo()
+        RustSourceWorkspaceConfig::default_cargo()
     }
 }
 
-impl SysrootSourceWorkspaceConfig {
+impl RustSourceWorkspaceConfig {
     pub fn default_cargo() -> Self {
-        SysrootSourceWorkspaceConfig::CargoMetadata(Default::default())
+        RustSourceWorkspaceConfig::CargoMetadata(Default::default())
     }
 }
diff --git a/crates/project-model/src/sysroot.rs b/crates/project-model/src/sysroot.rs
index 8f633d24be..510c18dd14 100644
--- a/crates/project-model/src/sysroot.rs
+++ b/crates/project-model/src/sysroot.rs
@@ -22,38 +22,40 @@ use toolchain::{probe_for_binary, Tool};
 
 use crate::{
     cargo_workspace::CargoMetadataConfig, utf8_stdout, CargoWorkspace, ManifestPath,
-    SysrootSourceWorkspaceConfig,
+    RustSourceWorkspaceConfig,
 };
 
 #[derive(Debug, Clone, PartialEq, Eq)]
 pub struct Sysroot {
     root: Option<AbsPathBuf>,
-    src_root: Option<AbsPathBuf>,
-    workspace: SysrootWorkspace,
+    rust_lib_src_root: Option<AbsPathBuf>,
+    workspace: RustLibSrcWorkspace,
     error: Option<String>,
 }
 
 #[derive(Debug, Clone, Eq, PartialEq)]
-pub(crate) enum SysrootWorkspace {
+pub enum RustLibSrcWorkspace {
     Workspace(CargoWorkspace),
     Stitched(Stitched),
     Empty,
 }
 
 #[derive(Debug, Clone, Eq, PartialEq)]
-pub(crate) struct Stitched {
-    crates: Arena<SysrootCrateData>,
+pub struct Stitched {
+    crates: Arena<RustLibSrcCrateData>,
 }
 
-impl ops::Index<SysrootCrate> for Stitched {
-    type Output = SysrootCrateData;
-    fn index(&self, index: SysrootCrate) -> &SysrootCrateData {
+impl ops::Index<RustLibSrcCrate> for Stitched {
+    type Output = RustLibSrcCrateData;
+    fn index(&self, index: RustLibSrcCrate) -> &RustLibSrcCrateData {
         &self.crates[index]
     }
 }
 
 impl Stitched {
-    pub(crate) fn public_deps(&self) -> impl Iterator<Item = (CrateName, SysrootCrate, bool)> + '_ {
+    pub(crate) fn public_deps(
+        &self,
+    ) -> impl Iterator<Item = (CrateName, RustLibSrcCrate, bool)> + '_ {
         // core is added as a dependency before std in order to
         // mimic rustcs dependency order
         [("core", true), ("alloc", false), ("std", true), ("test", false)].into_iter().filter_map(
@@ -63,32 +65,37 @@ impl Stitched {
         )
     }
 
-    pub(crate) fn proc_macro(&self) -> Option<SysrootCrate> {
+    pub(crate) fn proc_macro(&self) -> Option<RustLibSrcCrate> {
         self.by_name("proc_macro")
     }
 
-    pub(crate) fn crates(&self) -> impl ExactSizeIterator<Item = SysrootCrate> + '_ {
+    pub(crate) fn crates(&self) -> impl ExactSizeIterator<Item = RustLibSrcCrate> + '_ {
         self.crates.iter().map(|(id, _data)| id)
     }
 
-    fn by_name(&self, name: &str) -> Option<SysrootCrate> {
+    fn by_name(&self, name: &str) -> Option<RustLibSrcCrate> {
         let (id, _data) = self.crates.iter().find(|(_id, data)| data.name == name)?;
         Some(id)
     }
 }
 
-pub(crate) type SysrootCrate = Idx<SysrootCrateData>;
+pub(crate) type RustLibSrcCrate = Idx<RustLibSrcCrateData>;
 
 #[derive(Debug, Clone, Eq, PartialEq)]
-pub(crate) struct SysrootCrateData {
+pub(crate) struct RustLibSrcCrateData {
     pub(crate) name: String,
     pub(crate) root: ManifestPath,
-    pub(crate) deps: Vec<SysrootCrate>,
+    pub(crate) deps: Vec<RustLibSrcCrate>,
 }
 
 impl Sysroot {
     pub const fn empty() -> Sysroot {
-        Sysroot { root: None, src_root: None, workspace: SysrootWorkspace::Empty, error: None }
+        Sysroot {
+            root: None,
+            rust_lib_src_root: None,
+            workspace: RustLibSrcWorkspace::Empty,
+            error: None,
+        }
     }
 
     /// Returns sysroot "root" directory, where `bin/`, `etc/`, `lib/`, `libexec/`
@@ -100,15 +107,15 @@ impl Sysroot {
 
     /// Returns the sysroot "source" directory, where stdlib sources are located, like:
     /// `$HOME/.rustup/toolchains/nightly-2022-07-23-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library`
-    pub fn src_root(&self) -> Option<&AbsPath> {
-        self.src_root.as_deref()
+    pub fn rust_lib_src_root(&self) -> Option<&AbsPath> {
+        self.rust_lib_src_root.as_deref()
     }
 
-    pub fn is_empty(&self) -> bool {
+    pub fn is_rust_lib_src_empty(&self) -> bool {
         match &self.workspace {
-            SysrootWorkspace::Workspace(ws) => ws.packages().next().is_none(),
-            SysrootWorkspace::Stitched(stitched) => stitched.crates.is_empty(),
-            SysrootWorkspace::Empty => true,
+            RustLibSrcWorkspace::Workspace(ws) => ws.packages().next().is_none(),
+            RustLibSrcWorkspace::Stitched(stitched) => stitched.crates.is_empty(),
+            RustLibSrcWorkspace::Empty => true,
         }
     }
 
@@ -118,13 +125,13 @@ impl Sysroot {
 
     pub fn num_packages(&self) -> usize {
         match &self.workspace {
-            SysrootWorkspace::Workspace(ws) => ws.packages().count(),
-            SysrootWorkspace::Stitched(c) => c.crates().count(),
-            SysrootWorkspace::Empty => 0,
+            RustLibSrcWorkspace::Workspace(ws) => ws.packages().count(),
+            RustLibSrcWorkspace::Stitched(c) => c.crates().count(),
+            RustLibSrcWorkspace::Empty => 0,
         }
     }
 
-    pub(crate) fn workspace(&self) -> &SysrootWorkspace {
+    pub(crate) fn workspace(&self) -> &RustLibSrcWorkspace {
         &self.workspace
     }
 }
@@ -133,33 +140,33 @@ impl Sysroot {
     /// Attempts to discover the toolchain's sysroot from the given `dir`.
     pub fn discover(dir: &AbsPath, extra_env: &FxHashMap<String, String>) -> Sysroot {
         let sysroot_dir = discover_sysroot_dir(dir, extra_env);
-        let sysroot_src_dir = sysroot_dir.as_ref().ok().map(|sysroot_dir| {
-            discover_sysroot_src_dir_or_add_component(sysroot_dir, dir, extra_env)
+        let rust_lib_src_dir = sysroot_dir.as_ref().ok().map(|sysroot_dir| {
+            discover_rust_lib_src_dir_or_add_component(sysroot_dir, dir, extra_env)
         });
-        Sysroot::assemble(Some(sysroot_dir), sysroot_src_dir)
+        Sysroot::assemble(Some(sysroot_dir), rust_lib_src_dir)
     }
 
     pub fn discover_with_src_override(
         current_dir: &AbsPath,
         extra_env: &FxHashMap<String, String>,
-        sysroot_src_dir: AbsPathBuf,
+        rust_lib_src_dir: AbsPathBuf,
     ) -> Sysroot {
         let sysroot_dir = discover_sysroot_dir(current_dir, extra_env);
-        Sysroot::assemble(Some(sysroot_dir), Some(Ok(sysroot_src_dir)))
+        Sysroot::assemble(Some(sysroot_dir), Some(Ok(rust_lib_src_dir)))
     }
 
-    pub fn discover_sysroot_src_dir(sysroot_dir: AbsPathBuf) -> Sysroot {
-        let sysroot_src_dir = discover_sysroot_src_dir(&sysroot_dir)
+    pub fn discover_rust_lib_src_dir(sysroot_dir: AbsPathBuf) -> Sysroot {
+        let rust_lib_src_dir = discover_rust_lib_src_dir(&sysroot_dir)
             .ok_or_else(|| format_err!("can't find standard library sources in {sysroot_dir}"));
-        Sysroot::assemble(Some(Ok(sysroot_dir)), Some(sysroot_src_dir))
+        Sysroot::assemble(Some(Ok(sysroot_dir)), Some(rust_lib_src_dir))
     }
 
     pub fn discover_rustc_src(&self) -> Option<ManifestPath> {
         get_rustc_src(self.root()?)
     }
 
-    pub fn new(sysroot_dir: Option<AbsPathBuf>, sysroot_src_dir: Option<AbsPathBuf>) -> Sysroot {
-        Self::assemble(sysroot_dir.map(Ok), sysroot_src_dir.map(Ok))
+    pub fn new(sysroot_dir: Option<AbsPathBuf>, rust_lib_src_dir: Option<AbsPathBuf>) -> Sysroot {
+        Self::assemble(sysroot_dir.map(Ok), rust_lib_src_dir.map(Ok))
     }
 
     /// Returns a command to run a tool preferring the cargo proxies if the sysroot exists.
@@ -200,7 +207,7 @@ impl Sysroot {
 
     fn assemble(
         sysroot_dir: Option<Result<AbsPathBuf, anyhow::Error>>,
-        sysroot_src_dir: Option<Result<AbsPathBuf, anyhow::Error>>,
+        rust_lib_src_dir: Option<Result<AbsPathBuf, anyhow::Error>>,
     ) -> Sysroot {
         let mut errors = String::new();
         let root = match sysroot_dir {
@@ -211,8 +218,8 @@ impl Sysroot {
             }
             None => None,
         };
-        let src_root = match sysroot_src_dir {
-            Some(Ok(sysroot_src_dir)) => Some(sysroot_src_dir),
+        let rust_lib_src_root = match rust_lib_src_dir {
+            Some(Ok(rust_lib_src_dir)) => Some(rust_lib_src_dir),
             Some(Err(e)) => {
                 format_to!(errors, "{e}\n");
                 None
@@ -221,24 +228,28 @@ impl Sysroot {
         };
         Sysroot {
             root,
-            src_root,
-            workspace: SysrootWorkspace::Empty,
+            rust_lib_src_root,
+            workspace: RustLibSrcWorkspace::Empty,
             error: errors.is_empty().not().then_some(errors),
         }
     }
 
-    pub fn load_workspace(&mut self, sysroot_source_config: &SysrootSourceWorkspaceConfig) {
-        assert!(matches!(self.workspace, SysrootWorkspace::Empty), "workspace already loaded");
-        let Self { root: _, src_root: Some(src_root), workspace, error: _ } = self else { return };
-        if let SysrootSourceWorkspaceConfig::CargoMetadata(cargo_config) = sysroot_source_config {
+    pub fn load_workspace(
+        &self,
+        sysroot_source_config: &RustSourceWorkspaceConfig,
+    ) -> Option<RustLibSrcWorkspace> {
+        assert!(matches!(self.workspace, RustLibSrcWorkspace::Empty), "workspace already loaded");
+        let Self { root: _, rust_lib_src_root: Some(src_root), workspace: _, error: _ } = self
+        else {
+            return None;
+        };
+        if let RustSourceWorkspaceConfig::CargoMetadata(cargo_config) = sysroot_source_config {
             let library_manifest = ManifestPath::try_from(src_root.join("Cargo.toml")).unwrap();
             if fs::metadata(&library_manifest).is_ok() {
                 if let Some(loaded) =
                     Self::load_library_via_cargo(library_manifest, src_root, cargo_config)
                 {
-                    *workspace = loaded;
-                    self.load_core_check();
-                    return;
+                    return Some(loaded);
                 }
             }
         }
@@ -255,7 +266,7 @@ impl Sysroot {
                 .find(|it| fs::metadata(it).is_ok());
 
             if let Some(root) = root {
-                stitched.crates.alloc(SysrootCrateData {
+                stitched.crates.alloc(RustLibSrcCrateData {
                     name: name.into(),
                     root,
                     deps: Vec::new(),
@@ -286,21 +297,23 @@ impl Sysroot {
                 }
             }
         }
-        *workspace = SysrootWorkspace::Stitched(stitched);
-        self.load_core_check();
+        Some(RustLibSrcWorkspace::Stitched(stitched))
     }
 
-    fn load_core_check(&mut self) {
+    pub fn set_workspace(&mut self, workspace: RustLibSrcWorkspace) {
+        self.workspace = workspace;
         if self.error.is_none() {
-            if let Some(src_root) = &self.src_root {
+            if let Some(src_root) = &self.rust_lib_src_root {
                 let has_core = match &self.workspace {
-                    SysrootWorkspace::Workspace(ws) => ws.packages().any(|p| ws[p].name == "core"),
-                    SysrootWorkspace::Stitched(stitched) => stitched.by_name("core").is_some(),
-                    SysrootWorkspace::Empty => true,
+                    RustLibSrcWorkspace::Workspace(ws) => {
+                        ws.packages().any(|p| ws[p].name == "core")
+                    }
+                    RustLibSrcWorkspace::Stitched(stitched) => stitched.by_name("core").is_some(),
+                    RustLibSrcWorkspace::Empty => true,
                 };
                 if !has_core {
-                    let var_note = if env::var_os("RUST_SRC_PATH").is_some() {
-                        " (env var `RUST_SRC_PATH` is set and may be incorrect, try unsetting it)"
+                    let var_note = if env::var_os("rust_lib_src_PATH").is_some() {
+                        " (env var `rust_lib_src_PATH` is set and may be incorrect, try unsetting it)"
                     } else {
                         ", try running `rustup component add rust-src` to possibly fix this"
                     };
@@ -314,9 +327,9 @@ impl Sysroot {
 
     fn load_library_via_cargo(
         library_manifest: ManifestPath,
-        sysroot_src_dir: &AbsPathBuf,
+        rust_lib_src_dir: &AbsPathBuf,
         cargo_config: &CargoMetadataConfig,
-    ) -> Option<SysrootWorkspace> {
+    ) -> Option<RustLibSrcWorkspace> {
         tracing::debug!("Loading library metadata: {library_manifest}");
         let mut cargo_config = cargo_config.clone();
         // the sysroot uses `public-dependency`, so we make cargo think it's a nightly
@@ -327,7 +340,7 @@ impl Sysroot {
 
         let (mut res, _) = match CargoWorkspace::fetch_metadata(
             &library_manifest,
-            sysroot_src_dir,
+            rust_lib_src_dir,
             &cargo_config,
             &Sysroot::empty(),
             // Make sure we never attempt to write to the sysroot
@@ -391,7 +404,7 @@ impl Sysroot {
         });
 
         let cargo_workspace = CargoWorkspace::new(res, library_manifest, Default::default());
-        Some(SysrootWorkspace::Workspace(cargo_workspace))
+        Some(RustLibSrcWorkspace::Workspace(cargo_workspace))
     }
 }
 
@@ -407,36 +420,38 @@ fn discover_sysroot_dir(
     Ok(AbsPathBuf::assert(Utf8PathBuf::from(stdout)))
 }
 
-fn discover_sysroot_src_dir(sysroot_path: &AbsPathBuf) -> Option<AbsPathBuf> {
-    if let Ok(path) = env::var("RUST_SRC_PATH") {
+fn discover_rust_lib_src_dir(sysroot_path: &AbsPathBuf) -> Option<AbsPathBuf> {
+    if let Ok(path) = env::var("rust_lib_src_PATH") {
         if let Ok(path) = AbsPathBuf::try_from(path.as_str()) {
             let core = path.join("core");
             if fs::metadata(&core).is_ok() {
-                tracing::debug!("Discovered sysroot by RUST_SRC_PATH: {path}");
+                tracing::debug!("Discovered sysroot by rust_lib_src_PATH: {path}");
                 return Some(path);
             }
-            tracing::debug!("RUST_SRC_PATH is set, but is invalid (no core: {core:?}), ignoring");
+            tracing::debug!(
+                "rust_lib_src_PATH is set, but is invalid (no core: {core:?}), ignoring"
+            );
         } else {
-            tracing::debug!("RUST_SRC_PATH is set, but is invalid, ignoring");
+            tracing::debug!("rust_lib_src_PATH is set, but is invalid, ignoring");
         }
     }
 
-    get_rust_src(sysroot_path)
+    get_rust_lib_src(sysroot_path)
 }
 
-fn discover_sysroot_src_dir_or_add_component(
+fn discover_rust_lib_src_dir_or_add_component(
     sysroot_path: &AbsPathBuf,
     current_dir: &AbsPath,
     extra_env: &FxHashMap<String, String>,
 ) -> Result<AbsPathBuf> {
-    discover_sysroot_src_dir(sysroot_path)
+    discover_rust_lib_src_dir(sysroot_path)
         .or_else(|| {
             let mut rustup = toolchain::command(Tool::Rustup.prefer_proxy(), current_dir);
             rustup.envs(extra_env);
             rustup.args(["component", "add", "rust-src"]);
             tracing::info!("adding rust-src component by {:?}", rustup);
             utf8_stdout(&mut rustup).ok()?;
-            get_rust_src(sysroot_path)
+            get_rust_lib_src(sysroot_path)
         })
         .ok_or_else(|| {
             tracing::error!(%sysroot_path, "can't load standard library, try installing `rust-src`");
@@ -461,11 +476,11 @@ fn get_rustc_src(sysroot_path: &AbsPath) -> Option<ManifestPath> {
     }
 }
 
-fn get_rust_src(sysroot_path: &AbsPath) -> Option<AbsPathBuf> {
-    let rust_src = sysroot_path.join("lib/rustlib/src/rust/library");
-    tracing::debug!("checking sysroot library: {rust_src}");
-    if fs::metadata(&rust_src).is_ok() {
-        Some(rust_src)
+fn get_rust_lib_src(sysroot_path: &AbsPath) -> Option<AbsPathBuf> {
+    let rust_lib_src = sysroot_path.join("lib/rustlib/src/rust/library");
+    tracing::debug!("checking sysroot library: {rust_lib_src}");
+    if fs::metadata(&rust_lib_src).is_ok() {
+        Some(rust_lib_src)
     } else {
         None
     }
diff --git a/crates/project-model/src/workspace.rs b/crates/project-model/src/workspace.rs
index dcd62753cb..4f8449cb68 100644
--- a/crates/project-model/src/workspace.rs
+++ b/crates/project-model/src/workspace.rs
@@ -2,7 +2,7 @@
 //! metadata` or `rust-project.json`) into representation stored in the salsa
 //! database -- `CrateGraph`.
 
-use std::{collections::VecDeque, fmt, fs, iter, ops::Deref, sync};
+use std::{collections::VecDeque, fmt, fs, iter, ops::Deref, sync, thread};
 
 use anyhow::Context;
 use base_db::{
@@ -23,10 +23,10 @@ use crate::{
     cargo_workspace::{CargoMetadataConfig, DepKind, PackageData, RustLibSource},
     env::{cargo_config_env, inject_cargo_env, inject_cargo_package_env, inject_rustc_tool_env},
     project_json::{Crate, CrateArrayIdx},
-    sysroot::{SysrootCrate, SysrootWorkspace},
+    sysroot::{RustLibSrcCrate, RustLibSrcWorkspace},
     toolchain_info::{rustc_cfg, target_data_layout, target_tuple, version, QueryConfig},
     CargoConfig, CargoWorkspace, CfgOverrides, InvocationStrategy, ManifestPath, Package,
-    ProjectJson, ProjectManifest, Sysroot, SysrootSourceWorkspaceConfig, TargetData, TargetKind,
+    ProjectJson, ProjectManifest, RustSourceWorkspaceConfig, Sysroot, TargetData, TargetKind,
     WorkspaceBuildScripts,
 };
 use tracing::{debug, error, info};
@@ -186,7 +186,7 @@ impl ProjectWorkspace {
                 let project_location = project_json.parent().to_path_buf();
                 let project_json: ProjectJson =
                     ProjectJson::new(Some(project_json.clone()), &project_location, data);
-                ProjectWorkspace::load_inline(project_json, config)
+                ProjectWorkspace::load_inline(project_json, config, progress)
             }
             ProjectManifest::CargoScript(rust_file) => {
                 ProjectWorkspace::load_detached_file(rust_file, config)?
@@ -204,19 +204,33 @@ impl ProjectWorkspace {
         config: &CargoConfig,
         progress: &dyn Fn(String),
     ) -> Result<ProjectWorkspace, anyhow::Error> {
-        let mut sysroot = match (&config.sysroot, &config.sysroot_src) {
+        progress("Discovering sysroot".to_owned());
+        let CargoConfig {
+            features,
+            rustc_source,
+            extra_args,
+            extra_env,
+            set_test,
+            cfg_overrides,
+            extra_includes,
+            sysroot,
+            sysroot_src,
+            target,
+            ..
+        } = config;
+        let mut sysroot = match (sysroot, sysroot_src) {
             (Some(RustLibSource::Discover), None) => {
-                Sysroot::discover(cargo_toml.parent(), &config.extra_env)
+                Sysroot::discover(cargo_toml.parent(), extra_env)
             }
             (Some(RustLibSource::Discover), Some(sysroot_src)) => {
                 Sysroot::discover_with_src_override(
                     cargo_toml.parent(),
-                    &config.extra_env,
+                    extra_env,
                     sysroot_src.clone(),
                 )
             }
             (Some(RustLibSource::Path(path)), None) => {
-                Sysroot::discover_sysroot_src_dir(path.clone())
+                Sysroot::discover_rust_lib_src_dir(path.clone())
             }
             (Some(RustLibSource::Path(sysroot)), Some(sysroot_src)) => {
                 Sysroot::new(Some(sysroot.clone()), Some(sysroot_src.clone()))
@@ -224,100 +238,147 @@ impl ProjectWorkspace {
             (None, _) => Sysroot::empty(),
         };
 
-        let rustc_dir = match &config.rustc_source {
-            Some(RustLibSource::Path(path)) => ManifestPath::try_from(path.clone())
-                .map_err(|p| Some(format!("rustc source path is not absolute: {p}"))),
-            Some(RustLibSource::Discover) => sysroot
-                .discover_rustc_src()
-                .ok_or_else(|| Some("Failed to discover rustc source for sysroot.".to_owned())),
-            None => Err(None),
-        };
-
-        tracing::info!(workspace = %cargo_toml, src_root = ?sysroot.src_root(), root = ?sysroot.root(), "Using sysroot");
+        tracing::info!(workspace = %cargo_toml, src_root = ?sysroot.rust_lib_src_root(), root = ?sysroot.root(), "Using sysroot");
+        progress("Querying project metadata".to_owned());
         let toolchain_config = QueryConfig::Cargo(&sysroot, cargo_toml);
         let targets =
-            target_tuple::get(toolchain_config, config.target.as_deref(), &config.extra_env)
-                .unwrap_or_default();
-        let toolchain = version::get(toolchain_config, &config.extra_env)
-            .inspect_err(|e| {
-                tracing::error!(%e,
-                    "failed fetching toolchain version for {cargo_toml:?} workspace"
-                )
-            })
-            .ok()
-            .flatten();
-        let rustc_cfg =
-            rustc_cfg::get(toolchain_config, targets.first().map(Deref::deref), &config.extra_env);
-        let cfg_overrides = config.cfg_overrides.clone();
-        let data_layout = target_data_layout::get(
-            toolchain_config,
-            targets.first().map(Deref::deref),
-            &config.extra_env,
-        );
-        if let Err(e) = &data_layout {
-            tracing::error!(%e, "failed fetching data layout for {cargo_toml:?} workspace");
-        }
-        sysroot.load_workspace(&SysrootSourceWorkspaceConfig::CargoMetadata(
-            sysroot_metadata_config(&config.extra_env, &targets),
-        ));
+            target_tuple::get(toolchain_config, target.as_deref(), extra_env).unwrap_or_default();
+
+        // We spawn a bunch of processes to query various information about the workspace's
+        // toolchain and sysroot
+        // We can speed up loading a bit by spawning all of these processes in parallel (especially
+        // on systems were process spawning is delayed)
+        let join = thread::scope(|s| {
+            let workspace_dir = cargo_toml.parent();
+            let toolchain = s.spawn(|| {
+                version::get(toolchain_config, extra_env)
+                    .inspect_err(|e| {
+                        tracing::error!(%e,
+                            "failed fetching toolchain version for {cargo_toml:?} workspace"
+                        )
+                    })
+                    .ok()
+                    .flatten()
+            });
 
-        let rustc = rustc_dir.and_then(|rustc_dir| {
-            info!(workspace = %cargo_toml, rustc_dir = %rustc_dir, "Using rustc source");
-            match CargoWorkspace::fetch_metadata(
-                &rustc_dir,
-                cargo_toml.parent(),
-                &CargoMetadataConfig {
-                    features: crate::CargoFeatures::default(),
-                    targets: targets.clone(),
-                    extra_args: config.extra_args.clone(),
-                    extra_env: config.extra_env.clone(),
-                },
-                &sysroot,
-                false,
-                progress,
-            ) {
-                Ok((meta, _error)) => {
-                    let workspace = CargoWorkspace::new(meta, cargo_toml.clone(), Env::default());
-                    let build_scripts = WorkspaceBuildScripts::rustc_crates(
-                        &workspace,
-                        cargo_toml.parent(),
-                        &config.extra_env,
+            let rustc_cfg = s.spawn(|| {
+                rustc_cfg::get(toolchain_config, targets.first().map(Deref::deref), extra_env)
+            });
+            let data_layout = s.spawn(|| {
+                target_data_layout::get(
+                    toolchain_config,
+                    targets.first().map(Deref::deref),
+                    extra_env,
+                ).inspect_err(|e| {
+                    tracing::error!(%e, "failed fetching data layout for {cargo_toml:?} workspace")
+                })
+            });
+
+            let rustc_dir = s.spawn(|| {
+                let rustc_dir = match rustc_source {
+                    Some(RustLibSource::Path(path)) => ManifestPath::try_from(path.clone())
+                        .map_err(|p| Some(format!("rustc source path is not absolute: {p}"))),
+                    Some(RustLibSource::Discover) => {
+                        sysroot.discover_rustc_src().ok_or_else(|| {
+                            Some("Failed to discover rustc source for sysroot.".to_owned())
+                        })
+                    }
+                    None => Err(None),
+                };
+                rustc_dir.and_then(|rustc_dir| {
+                    info!(workspace = %cargo_toml, rustc_dir = %rustc_dir, "Using rustc source");
+                    match CargoWorkspace::fetch_metadata(
+                        &rustc_dir,
+                        workspace_dir,
+                        &CargoMetadataConfig {
+                            features: crate::CargoFeatures::default(),
+                            targets: targets.clone(),
+                            extra_args: extra_args.clone(),
+                            extra_env: extra_env.clone(),
+                        },
                         &sysroot,
-                    );
-                    Ok(Box::new((workspace, build_scripts)))
-                }
-                Err(e) => {
-                    tracing::error!(
-                        %e,
-                        "Failed to read Cargo metadata from rustc source at {rustc_dir}",
-                    );
-                    Err(Some(format!(
-                        "Failed to read Cargo metadata from rustc source at {rustc_dir}: {e}"
-                    )))
-                }
-            }
+                        false,
+                        &|_| (),
+                    ) {
+                        Ok((meta, _error)) => {
+                            let workspace =
+                                CargoWorkspace::new(meta, cargo_toml.clone(), Env::default());
+                            let build_scripts = WorkspaceBuildScripts::rustc_crates(
+                                &workspace,
+                                workspace_dir,
+                                extra_env,
+                                &sysroot,
+                            );
+                            Ok(Box::new((workspace, build_scripts)))
+                        }
+                        Err(e) => {
+                            tracing::error!(
+                                %e,
+                                "Failed to read Cargo metadata from rustc source at {rustc_dir}",
+                            );
+                            Err(Some(format!(
+                            "Failed to read Cargo metadata from rustc source at {rustc_dir}: {e}"
+                        )))
+                        }
+                    }
+                })
+            });
+
+            let cargo_metadata = s.spawn(|| {
+                CargoWorkspace::fetch_metadata(
+                    cargo_toml,
+                    workspace_dir,
+                    &CargoMetadataConfig {
+                        features: features.clone(),
+                        targets: targets.clone(),
+                        extra_args: extra_args.clone(),
+                        extra_env: extra_env.clone(),
+                    },
+                    &sysroot,
+                    false,
+                    &|_| (),
+                )
+            });
+            let loaded_sysroot = s.spawn(|| {
+                sysroot.load_workspace(&RustSourceWorkspaceConfig::CargoMetadata(
+                    sysroot_metadata_config(extra_env, &targets),
+                ))
+            });
+            let cargo_config_extra_env =
+                s.spawn(|| cargo_config_env(cargo_toml, extra_env, &sysroot));
+            thread::Result::Ok((
+                toolchain.join()?,
+                rustc_cfg.join()?,
+                data_layout.join()?,
+                rustc_dir.join()?,
+                loaded_sysroot.join()?,
+                cargo_metadata.join()?,
+                cargo_config_extra_env.join()?,
+            ))
         });
 
-        let (meta, error) = CargoWorkspace::fetch_metadata(
-            cargo_toml,
-            cargo_toml.parent(),
-            &CargoMetadataConfig {
-                features: config.features.clone(),
-                targets,
-                extra_args: config.extra_args.clone(),
-                extra_env: config.extra_env.clone(),
-            },
-            &sysroot,
-            false,
-            progress,
-        )
-        .with_context(|| {
+        let (
+            toolchain,
+            rustc_cfg,
+            data_layout,
+            rustc,
+            loaded_sysroot,
+            cargo_metadata,
+            cargo_config_extra_env,
+        ) = match join {
+            Ok(it) => it,
+            Err(e) => std::panic::resume_unwind(e),
+        };
+
+        let (meta, error) = cargo_metadata.with_context(|| {
             format!(
                 "Failed to read Cargo metadata from Cargo.toml file {cargo_toml}, {toolchain:?}",
             )
         })?;
-        let cargo_config_extra_env = cargo_config_env(cargo_toml, &config.extra_env, &sysroot);
         let cargo = CargoWorkspace::new(meta, cargo_toml.clone(), cargo_config_extra_env);
+        if let Some(loaded_sysroot) = loaded_sysroot {
+            sysroot.set_workspace(loaded_sysroot);
+        }
 
         Ok(ProjectWorkspace {
             kind: ProjectWorkspaceKind::Cargo {
@@ -325,33 +386,67 @@ impl ProjectWorkspace {
                 build_scripts: WorkspaceBuildScripts::default(),
                 rustc,
                 error: error.map(Arc::new),
-                set_test: config.set_test,
+                set_test: *set_test,
             },
             sysroot,
             rustc_cfg,
-            cfg_overrides,
+            cfg_overrides: cfg_overrides.clone(),
             toolchain,
             target_layout: data_layout.map(Arc::from).map_err(|it| Arc::from(it.to_string())),
-            extra_includes: config.extra_includes.clone(),
+            extra_includes: extra_includes.clone(),
         })
     }
 
-    pub fn load_inline(project_json: ProjectJson, config: &CargoConfig) -> ProjectWorkspace {
+    pub fn load_inline(
+        project_json: ProjectJson,
+        config: &CargoConfig,
+        progress: &dyn Fn(String),
+    ) -> ProjectWorkspace {
+        progress("Discovering sysroot".to_owned());
         let mut sysroot =
             Sysroot::new(project_json.sysroot.clone(), project_json.sysroot_src.clone());
-        sysroot.load_workspace(&SysrootSourceWorkspaceConfig::Stitched);
+        let loaded_sysroot = sysroot.load_workspace(&RustSourceWorkspaceConfig::Stitched);
+        if let Some(loaded_sysroot) = loaded_sysroot {
+            sysroot.set_workspace(loaded_sysroot);
+        }
+
+        tracing::info!(workspace = %project_json.manifest_or_root(), src_root = ?sysroot.rust_lib_src_root(), root = ?sysroot.root(), "Using sysroot");
+        progress("Querying project metadata".to_owned());
         let query_config = QueryConfig::Rustc(&sysroot, project_json.path().as_ref());
-        let toolchain = version::get(query_config, &config.extra_env).ok().flatten();
+        let targets = target_tuple::get(query_config, config.target.as_deref(), &config.extra_env)
+            .unwrap_or_default();
+
+        // We spawn a bunch of processes to query various information about the workspace's
+        // toolchain and sysroot
+        // We can speed up loading a bit by spawning all of these processes in parallel (especially
+        // on systems were process spawning is delayed)
+        let join = thread::scope(|s| {
+            let toolchain =
+                s.spawn(|| version::get(query_config, &config.extra_env).ok().flatten());
+            let rustc_cfg = s.spawn(|| {
+                rustc_cfg::get(query_config, targets.first().map(Deref::deref), &config.extra_env)
+            });
+            let data_layout = s.spawn(|| {
+                target_data_layout::get(
+                    query_config,
+                    targets.first().map(Deref::deref),
+                    &config.extra_env,
+                )
+            });
+            thread::Result::Ok((toolchain.join()?, rustc_cfg.join()?, data_layout.join()?))
+        });
+
+        let (toolchain, rustc_cfg, target_layout) = match join {
+            Ok(it) => it,
+            Err(e) => std::panic::resume_unwind(e),
+        };
 
-        let target = config.target.as_deref();
-        let rustc_cfg = rustc_cfg::get(query_config, target, &config.extra_env);
-        let data_layout = target_data_layout::get(query_config, target, &config.extra_env);
         ProjectWorkspace {
             kind: ProjectWorkspaceKind::Json(project_json),
             sysroot,
             rustc_cfg,
             toolchain,
-            target_layout: data_layout.map(Arc::from).map_err(|it| Arc::from(it.to_string())),
+            target_layout: target_layout.map(Arc::from).map_err(|it| Arc::from(it.to_string())),
             cfg_overrides: config.cfg_overrides.clone(),
             extra_includes: config.extra_includes.clone(),
         }
@@ -363,7 +458,7 @@ impl ProjectWorkspace {
     ) -> anyhow::Result<ProjectWorkspace> {
         let dir = detached_file.parent();
         let mut sysroot = match &config.sysroot {
-            Some(RustLibSource::Path(path)) => Sysroot::discover_sysroot_src_dir(path.clone()),
+            Some(RustLibSource::Path(path)) => Sysroot::discover_rust_lib_src_dir(path.clone()),
             Some(RustLibSource::Discover) => Sysroot::discover(dir, &config.extra_env),
             None => Sysroot::empty(),
         };
@@ -374,9 +469,12 @@ impl ProjectWorkspace {
             .unwrap_or_default();
         let rustc_cfg = rustc_cfg::get(query_config, None, &config.extra_env);
         let data_layout = target_data_layout::get(query_config, None, &config.extra_env);
-        sysroot.load_workspace(&SysrootSourceWorkspaceConfig::CargoMetadata(
+        let loaded_sysroot = sysroot.load_workspace(&RustSourceWorkspaceConfig::CargoMetadata(
             sysroot_metadata_config(&config.extra_env, &targets),
         ));
+        if let Some(loaded_sysroot) = loaded_sysroot {
+            sysroot.set_workspace(loaded_sysroot);
+        }
 
         let cargo_script = CargoWorkspace::fetch_metadata(
             detached_file,
@@ -545,7 +643,7 @@ impl ProjectWorkspace {
     pub fn to_roots(&self) -> Vec<PackageRoot> {
         let mk_sysroot = || {
             let mut r = match self.sysroot.workspace() {
-                SysrootWorkspace::Workspace(ws) => ws
+                RustLibSrcWorkspace::Workspace(ws) => ws
                     .packages()
                     .filter_map(|pkg| {
                         if ws[pkg].is_local {
@@ -566,12 +664,17 @@ impl ProjectWorkspace {
                         Some(PackageRoot { is_local: false, include, exclude })
                     })
                     .collect(),
-                SysrootWorkspace::Stitched(_) | SysrootWorkspace::Empty => vec![],
+                RustLibSrcWorkspace::Stitched(_) | RustLibSrcWorkspace::Empty => vec![],
             };
 
             r.push(PackageRoot {
                 is_local: false,
-                include: self.sysroot.src_root().map(|it| it.to_path_buf()).into_iter().collect(),
+                include: self
+                    .sysroot
+                    .rust_lib_src_root()
+                    .map(|it| it.to_path_buf())
+                    .into_iter()
+                    .collect(),
                 exclude: Vec::new(),
             });
             r
@@ -1385,7 +1488,7 @@ fn sysroot_to_crate_graph(
 ) -> (SysrootPublicDeps, Option<CrateId>) {
     let _p = tracing::info_span!("sysroot_to_crate_graph").entered();
     match sysroot.workspace() {
-        SysrootWorkspace::Workspace(cargo) => {
+        RustLibSrcWorkspace::Workspace(cargo) => {
             let (mut cg, mut pm) = cargo_to_crate_graph(
                 load,
                 None,
@@ -1460,7 +1563,7 @@ fn sysroot_to_crate_graph(
 
             (SysrootPublicDeps { deps: pub_deps }, libproc_macro)
         }
-        SysrootWorkspace::Stitched(stitched) => {
+        RustLibSrcWorkspace::Stitched(stitched) => {
             let cfg_options = Arc::new({
                 let mut cfg_options = CfgOptions::default();
                 cfg_options.extend(rustc_cfg);
@@ -1468,7 +1571,7 @@ fn sysroot_to_crate_graph(
                 cfg_options.insert_atom(sym::miri.clone());
                 cfg_options
             });
-            let sysroot_crates: FxHashMap<SysrootCrate, CrateId> = stitched
+            let sysroot_crates: FxHashMap<RustLibSrcCrate, CrateId> = stitched
                 .crates()
                 .filter_map(|krate| {
                     let file_id = load(&stitched[krate].root)?;
@@ -1513,7 +1616,7 @@ fn sysroot_to_crate_graph(
                 stitched.proc_macro().and_then(|it| sysroot_crates.get(&it).copied());
             (public_deps, libproc_macro)
         }
-        SysrootWorkspace::Empty => (SysrootPublicDeps { deps: vec![] }, None),
+        RustLibSrcWorkspace::Empty => (SysrootPublicDeps { deps: vec![] }, None),
     }
 }
 
diff --git a/crates/rust-analyzer/src/reload.rs b/crates/rust-analyzer/src/reload.rs
index e3c003dbf8..ba72ea35df 100644
--- a/crates/rust-analyzer/src/reload.rs
+++ b/crates/rust-analyzer/src/reload.rs
@@ -316,6 +316,7 @@ impl GlobalState {
                             let workspace = project_model::ProjectWorkspace::load_inline(
                                 it.clone(),
                                 &cargo_config,
+                                &progress,
                             );
                             Ok(workspace)
                         }
diff --git a/crates/stdx/src/panic_context.rs b/crates/stdx/src/panic_context.rs
index a35d50b78d..4ec74c0742 100644
--- a/crates/stdx/src/panic_context.rs
+++ b/crates/stdx/src/panic_context.rs
@@ -1,25 +1,28 @@
 //! A micro-crate to enhance panic messages with context info.
+//!
+//! FIXME: upstream to <https://github.com/kriomant/panic-context> ?
 
 use std::{cell::RefCell, panic, sync::Once};
 
-/// Dummy for leveraging RAII cleanup to pop frames.
+pub fn enter(context: String) -> PanicContext {
+    static ONCE: Once = Once::new();
+    ONCE.call_once(PanicContext::init);
+
+    with_ctx(|ctx| ctx.push(context));
+    PanicContext { _priv: () }
+}
+
 #[must_use]
 pub struct PanicContext {
-    // prevent arbitrary construction
     _priv: (),
 }
 
-impl Drop for PanicContext {
-    fn drop(&mut self) {
-        with_ctx(|ctx| assert!(ctx.pop().is_some()));
-    }
-}
-
-pub fn enter(frame: String) -> PanicContext {
+impl PanicContext {
     #[allow(clippy::print_stderr)]
-    fn set_hook() {
+    fn init() {
         let default_hook = panic::take_hook();
-        panic::set_hook(Box::new(move |panic_info| {
+        #[allow(deprecated)]
+        let hook = move |panic_info: &panic::PanicInfo<'_>| {
             with_ctx(|ctx| {
                 if !ctx.is_empty() {
                     eprintln!("Panic context:");
@@ -27,16 +30,17 @@ pub fn enter(frame: String) -> PanicContext {
                         eprintln!("> {frame}\n");
                     }
                 }
+                default_hook(panic_info);
             });
-            default_hook(panic_info);
-        }));
+        };
+        panic::set_hook(Box::new(hook));
     }
+}
 
-    static SET_HOOK: Once = Once::new();
-    SET_HOOK.call_once(set_hook);
-
-    with_ctx(|ctx| ctx.push(frame));
-    PanicContext { _priv: () }
+impl Drop for PanicContext {
+    fn drop(&mut self) {
+        with_ctx(|ctx| assert!(ctx.pop().is_some()));
+    }
 }
 
 fn with_ctx(f: impl FnOnce(&mut Vec<String>)) {
diff --git a/docs/book/README.md b/docs/book/README.md
index 043524b234..a9d10df664 100644
--- a/docs/book/README.md
+++ b/docs/book/README.md
@@ -26,4 +26,4 @@ Start with the mdbook [User Guide](https://rust-lang.github.io/mdBook/guide/inst
 Four sections are generated dynamically: assists, configuration, diagnostics and features. Their content is found in the `generated.md` files
 of the respective book section, for example `src/configuration_generated.md`, and are included in the book via mdbook's
 [include](https://rust-lang.github.io/mdBook/format/mdbook.html#including-files) functionality. Generated files can be rebuilt by running the various
-test cases that generate them, or by simply running all of the `rust-analyzer` tests with `cargo test` and `cargo xtask codegen`.
+test cases that generate them, or by simply running all of the `rust-analyzer` tests with `cargo test`.
diff --git a/docs/book/book.toml b/docs/book/book.toml
index 5ca4badde8..ba3c1dede5 100644
--- a/docs/book/book.toml
+++ b/docs/book/book.toml
@@ -9,10 +9,10 @@ title = "rust-analyzer"
 edition = "2021"
 
 [output.html]
-edit-url-template = "https://github.com/rust-lang/rust-analyzer/edit/master/docs/book/{path}"
-git-repository-url = "https://github.com/rust-lang/rust-analyzer/tree/master/docs/book"
+edit-url-template = "https://github.com/rust-lang/rust-analyzer/edit/master/manual/{path}"
+git-repository-url = "https://github.com/rust-lang/rust-analyzer/tree/master/manual"
 mathjax-support = true
-site-url = "/book/"
+site-url = "/manual/"
 
 [output.html.playground]
 editable = true
@@ -34,3 +34,8 @@ use-boolean-and = true
 [output.html.fold]
 enable = true
 level = 3
+
+[preprocessor.toc]
+command = "mdbook-toc"
+renderer = ["html"]
+max-level = 3
diff --git a/docs/book/src/assists_generated.md b/docs/book/src/assists_generated.md
deleted file mode 100644
index 3617badeef..0000000000
--- a/docs/book/src/assists_generated.md
+++ /dev/null
@@ -1,3820 +0,0 @@
-//! Generated by `cargo xtask codegen assists-doc-tests`, do not edit by hand.
-
-### `add_braces`
-**Source:**  [add_braces.rs](crates/ide-assists/src/handlers/add_braces.rs#8) 
-
-Adds braces to lambda and match arm expressions.
-
-#### Before
-```rust
-fn foo(n: i32) -> i32 {
-    match n {
-        1 =>┃ n + 1,
-        _ => 0
-    }
-}
-```
-
-#### After
-```rust
-fn foo(n: i32) -> i32 {
-    match n {
-        1 => {
-            n + 1
-        },
-        _ => 0
-    }
-}
-```
-
-
-### `add_explicit_type`
-**Source:**  [add_explicit_type.rs](crates/ide-assists/src/handlers/add_explicit_type.rs#7) 
-
-Specify type for a let binding.
-
-#### Before
-```rust
-fn main() {
-    let x┃ = 92;
-}
-```
-
-#### After
-```rust
-fn main() {
-    let x: i32 = 92;
-}
-```
-
-
-### `add_hash`
-**Source:**  [raw_string.rs](crates/ide-assists/src/handlers/raw_string.rs#89) 
-
-Adds a hash to a raw string literal.
-
-#### Before
-```rust
-fn main() {
-    r#"Hello,┃ World!"#;
-}
-```
-
-#### After
-```rust
-fn main() {
-    r##"Hello, World!"##;
-}
-```
-
-
-### `add_impl_default_members`
-**Source:**  [add_missing_impl_members.rs](crates/ide-assists/src/handlers/add_missing_impl_members.rs#58) 
-
-Adds scaffold for overriding default impl members.
-
-#### Before
-```rust
-trait Trait {
-    type X;
-    fn foo(&self);
-    fn bar(&self) {}
-}
-
-impl Trait for () {
-    type X = ();
-    fn foo(&self) {}┃
-}
-```
-
-#### After
-```rust
-trait Trait {
-    type X;
-    fn foo(&self);
-    fn bar(&self) {}
-}
-
-impl Trait for () {
-    type X = ();
-    fn foo(&self) {}
-
-    ┃fn bar(&self) {}
-}
-```
-
-
-### `add_impl_missing_members`
-**Source:**  [add_missing_impl_members.rs](crates/ide-assists/src/handlers/add_missing_impl_members.rs#16) 
-
-Adds scaffold for required impl members.
-
-#### Before
-```rust
-trait Trait<T> {
-    type X;
-    fn foo(&self) -> T;
-    fn bar(&self) {}
-}
-
-impl Trait<u32> for () {┃
-
-}
-```
-
-#### After
-```rust
-trait Trait<T> {
-    type X;
-    fn foo(&self) -> T;
-    fn bar(&self) {}
-}
-
-impl Trait<u32> for () {
-    ┃type X;
-
-    fn foo(&self) -> u32 {
-        todo!()
-    }
-}
-```
-
-
-### `add_label_to_loop`
-**Source:**  [add_label_to_loop.rs](crates/ide-assists/src/handlers/add_label_to_loop.rs#9) 
-
-Adds a label to a loop.
-
-#### Before
-```rust
-fn main() {
-    loop┃ {
-        break;
-        continue;
-    }
-}
-```
-
-#### After
-```rust
-fn main() {
-    'l: loop {
-        break 'l;
-        continue 'l;
-    }
-}
-```
-
-
-### `add_lifetime_to_type`
-**Source:**  [add_lifetime_to_type.rs](crates/ide-assists/src/handlers/add_lifetime_to_type.rs#5) 
-
-Adds a new lifetime to a struct, enum or union.
-
-#### Before
-```rust
-struct Point {
-    x: &┃u32,
-    y: u32,
-}
-```
-
-#### After
-```rust
-struct Point<'a> {
-    x: &'a u32,
-    y: u32,
-}
-```
-
-
-### `add_missing_match_arms`
-**Source:**  [add_missing_match_arms.rs](crates/ide-assists/src/handlers/add_missing_match_arms.rs#14) 
-
-Adds missing clauses to a `match` expression.
-
-#### Before
-```rust
-enum Action { Move { distance: u32 }, Stop }
-
-fn handle(action: Action) {
-    match action {
-        ┃
-    }
-}
-```
-
-#### After
-```rust
-enum Action { Move { distance: u32 }, Stop }
-
-fn handle(action: Action) {
-    match action {
-        Action::Move { distance } => ${1:todo!()},
-        Action::Stop => ${2:todo!()},┃
-    }
-}
-```
-
-
-### `add_return_type`
-**Source:**  [add_return_type.rs](crates/ide-assists/src/handlers/add_return_type.rs#6) 
-
-Adds the return type to a function or closure inferred from its tail expression if it doesn't have a return
-type specified. This assists is useable in a functions or closures tail expression or return type position.
-
-#### Before
-```rust
-fn foo() { 4┃2i32 }
-```
-
-#### After
-```rust
-fn foo() -> i32 { 42i32 }
-```
-
-
-### `add_turbo_fish`
-**Source:**  [add_turbo_fish.rs](crates/ide-assists/src/handlers/add_turbo_fish.rs#14) 
-
-Adds `::<_>` to a call of a generic method or function.
-
-#### Before
-```rust
-fn make<T>() -> T { todo!() }
-fn main() {
-    let x = make┃();
-}
-```
-
-#### After
-```rust
-fn make<T>() -> T { todo!() }
-fn main() {
-    let x = make::<${0:_}>();
-}
-```
-
-
-### `apply_demorgan`
-**Source:**  [apply_demorgan.rs](crates/ide-assists/src/handlers/apply_demorgan.rs#16) 
-
-Apply [De Morgan's law](https://en.wikipedia.org/wiki/De_Morgan%27s_laws).
-This transforms expressions of the form `!l || !r` into `!(l && r)`.
-This also works with `&&`. This assist can only be applied with the cursor
-on either `||` or `&&`.
-
-#### Before
-```rust
-fn main() {
-    if x != 4 ||┃ y < 3.14 {}
-}
-```
-
-#### After
-```rust
-fn main() {
-    if !(x == 4 && y >= 3.14) {}
-}
-```
-
-
-### `apply_demorgan_iterator`
-**Source:**  [apply_demorgan.rs](crates/ide-assists/src/handlers/apply_demorgan.rs#132) 
-
-Apply [De Morgan's law](https://en.wikipedia.org/wiki/De_Morgan%27s_laws) to
-`Iterator::all` and `Iterator::any`.
-
-This transforms expressions of the form `!iter.any(|x| predicate(x))` into
-`iter.all(|x| !predicate(x))` and vice versa. This also works the other way for
-`Iterator::all` into `Iterator::any`.
-
-#### Before
-```rust
-fn main() {
-    let arr = [1, 2, 3];
-    if !arr.into_iter().┃any(|num| num == 4) {
-        println!("foo");
-    }
-}
-```
-
-#### After
-```rust
-fn main() {
-    let arr = [1, 2, 3];
-    if arr.into_iter().all(|num| num != 4) {
-        println!("foo");
-    }
-}
-```
-
-
-### `auto_import`
-**Source:**  [auto_import.rs](crates/ide-assists/src/handlers/auto_import.rs#73) 
-
-If the name is unresolved, provides all possible imports for it.
-
-#### Before
-```rust
-fn main() {
-    let map = HashMap┃::new();
-}
-```
-
-#### After
-```rust
-use std::collections::HashMap;
-
-fn main() {
-    let map = HashMap::new();
-}
-```
-
-
-### `bind_unused_param`
-**Source:**  [bind_unused_param.rs](crates/ide-assists/src/handlers/bind_unused_param.rs#12) 
-
-Binds unused function parameter to an underscore.
-
-#### Before
-```rust
-fn some_function(x: i32┃) {}
-```
-
-#### After
-```rust
-fn some_function(x: i32) {
-    let _ = x;
-}
-```
-
-
-### `bool_to_enum`
-**Source:**  [bool_to_enum.rs](crates/ide-assists/src/handlers/bool_to_enum.rs#29) 
-
-This converts boolean local variables, fields, constants, and statics into a new
-enum with two variants `Bool::True` and `Bool::False`, as well as replacing
-all assignments with the variants and replacing all usages with `== Bool::True` or
-`== Bool::False`.
-
-#### Before
-```rust
-fn main() {
-    let ┃bool = true;
-
-    if bool {
-        println!("foo");
-    }
-}
-```
-
-#### After
-```rust
-#[derive(PartialEq, Eq)]
-enum Bool { True, False }
-
-fn main() {
-    let bool = Bool::True;
-
-    if bool == Bool::True {
-        println!("foo");
-    }
-}
-```
-
-
-### `change_visibility`
-**Source:**  [change_visibility.rs](crates/ide-assists/src/handlers/change_visibility.rs#13) 
-
-Adds or changes existing visibility specifier.
-
-#### Before
-```rust
-┃fn frobnicate() {}
-```
-
-#### After
-```rust
-pub(crate) fn frobnicate() {}
-```
-
-
-### `comment_to_doc`
-**Source:**  [convert_comment_from_or_to_doc.rs](crates/ide-assists/src/handlers/convert_comment_from_or_to_doc.rs#9) 
-
-Converts comments to documentation.
-
-#### Before
-```rust
-// Wow what ┃a nice module
-// I sure hope this shows up when I hover over it
-```
-
-#### After
-```rust
-//! Wow what a nice module
-//! I sure hope this shows up when I hover over it
-```
-
-
-### `convert_bool_then_to_if`
-**Source:**  [convert_bool_then.rs](crates/ide-assists/src/handlers/convert_bool_then.rs#131) 
-
-Converts a `bool::then` method call to an equivalent if expression.
-
-#### Before
-```rust
-fn main() {
-    (0 == 0).then┃(|| val)
-}
-```
-
-#### After
-```rust
-fn main() {
-    if 0 == 0 {
-        Some(val)
-    } else {
-        None
-    }
-}
-```
-
-
-### `convert_closure_to_fn`
-**Source:**  [convert_closure_to_fn.rs](crates/ide-assists/src/handlers/convert_closure_to_fn.rs#25) 
-
-This converts a closure to a freestanding function, changing all captures to parameters.
-
-#### Before
-```rust
-fn main() {
-    let mut s = String::new();
-    let closure = |┃a| s.push_str(a);
-    closure("abc");
-}
-```
-
-#### After
-```rust
-fn main() {
-    let mut s = String::new();
-    fn closure(a: &str, s: &mut String) {
-        s.push_str(a)
-    }
-    closure("abc", &mut s);
-}
-```
-
-
-### `convert_for_loop_with_for_each`
-**Source:**  [convert_iter_for_each_to_for.rs](crates/ide-assists/src/handlers/convert_iter_for_each_to_for.rs#76) 
-
-Converts a for loop into a for_each loop on the Iterator.
-
-#### Before
-```rust
-fn main() {
-    let x = vec![1, 2, 3];
-    for┃ v in x {
-        let y = v * 2;
-    }
-}
-```
-
-#### After
-```rust
-fn main() {
-    let x = vec![1, 2, 3];
-    x.into_iter().for_each(|v| {
-        let y = v * 2;
-    });
-}
-```
-
-
-### `convert_from_to_tryfrom`
-**Source:**  [convert_from_to_tryfrom.rs](crates/ide-assists/src/handlers/convert_from_to_tryfrom.rs#10) 
-
-Converts a From impl to a TryFrom impl, wrapping returns in `Ok`.
-
-#### Before
-```rust
-impl ┃From<usize> for Thing {
-    fn from(val: usize) -> Self {
-        Thing {
-            b: val.to_string(),
-            a: val
-        }
-    }
-}
-```
-
-#### After
-```rust
-impl TryFrom<usize> for Thing {
-    type Error = ${0:()};
-
-    fn try_from(val: usize) -> Result<Self, Self::Error> {
-        Ok(Thing {
-            b: val.to_string(),
-            a: val
-        })
-    }
-}
-```
-
-
-### `convert_if_to_bool_then`
-**Source:**  [convert_bool_then.rs](crates/ide-assists/src/handlers/convert_bool_then.rs#20) 
-
-Converts an if expression into a corresponding `bool::then` call.
-
-#### Before
-```rust
-fn main() {
-    if┃ cond {
-        Some(val)
-    } else {
-        None
-    }
-}
-```
-
-#### After
-```rust
-fn main() {
-    cond.then(|| val)
-}
-```
-
-
-### `convert_integer_literal`
-**Source:**  [convert_integer_literal.rs](crates/ide-assists/src/handlers/convert_integer_literal.rs#5) 
-
-Converts the base of integer literals to other bases.
-
-#### Before
-```rust
-const _: i32 = 10┃;
-```
-
-#### After
-```rust
-const _: i32 = 0b1010;
-```
-
-
-### `convert_into_to_from`
-**Source:**  [convert_into_to_from.rs](crates/ide-assists/src/handlers/convert_into_to_from.rs#8) 
-
-Converts an Into impl to an equivalent From impl.
-
-#### Before
-```rust
-impl ┃Into<Thing> for usize {
-    fn into(self) -> Thing {
-        Thing {
-            b: self.to_string(),
-            a: self
-        }
-    }
-}
-```
-
-#### After
-```rust
-impl From<usize> for Thing {
-    fn from(val: usize) -> Self {
-        Thing {
-            b: val.to_string(),
-            a: val
-        }
-    }
-}
-```
-
-
-### `convert_iter_for_each_to_for`
-**Source:**  [convert_iter_for_each_to_for.rs](crates/ide-assists/src/handlers/convert_iter_for_each_to_for.rs#11) 
-
-Converts an Iterator::for_each function into a for loop.
-
-#### Before
-```rust
-fn main() {
-    let iter = iter::repeat((9, 2));
-    iter.for_each┃(|(x, y)| {
-        println!("x: {}, y: {}", x, y);
-    });
-}
-```
-
-#### After
-```rust
-fn main() {
-    let iter = iter::repeat((9, 2));
-    for (x, y) in iter {
-        println!("x: {}, y: {}", x, y);
-    }
-}
-```
-
-
-### `convert_let_else_to_match`
-**Source:**  [convert_let_else_to_match.rs](crates/ide-assists/src/handlers/convert_let_else_to_match.rs#9) 
-
-Converts let-else statement to let statement and match expression.
-
-#### Before
-```rust
-fn main() {
-    let Ok(mut x) = f() else┃ { return };
-}
-```
-
-#### After
-```rust
-fn main() {
-    let mut x = match f() {
-        Ok(x) => x,
-        _ => return,
-    };
-}
-```
-
-
-### `convert_match_to_let_else`
-**Source:**  [convert_match_to_let_else.rs](crates/ide-assists/src/handlers/convert_match_to_let_else.rs#12) 
-
-Converts let statement with match initializer to let-else statement.
-
-#### Before
-```rust
-fn foo(opt: Option<()>) {
-    let val┃ = match opt {
-        Some(it) => it,
-        None => return,
-    };
-}
-```
-
-#### After
-```rust
-fn foo(opt: Option<()>) {
-    let Some(val) = opt else { return };
-}
-```
-
-
-### `convert_named_struct_to_tuple_struct`
-**Source:**  [convert_named_struct_to_tuple_struct.rs](crates/ide-assists/src/handlers/convert_named_struct_to_tuple_struct.rs#11) 
-
-Converts struct with named fields to tuple struct, and analogously for enum variants with named
-fields.
-
-#### Before
-```rust
-struct Point┃ { x: f32, y: f32 }
-
-impl Point {
-    pub fn new(x: f32, y: f32) -> Self {
-        Point { x, y }
-    }
-
-    pub fn x(&self) -> f32 {
-        self.x
-    }
-
-    pub fn y(&self) -> f32 {
-        self.y
-    }
-}
-```
-
-#### After
-```rust
-struct Point(f32, f32);
-
-impl Point {
-    pub fn new(x: f32, y: f32) -> Self {
-        Point(x, y)
-    }
-
-    pub fn x(&self) -> f32 {
-        self.0
-    }
-
-    pub fn y(&self) -> f32 {
-        self.1
-    }
-}
-```
-
-
-### `convert_nested_function_to_closure`
-**Source:**  [convert_nested_function_to_closure.rs](crates/ide-assists/src/handlers/convert_nested_function_to_closure.rs#7) 
-
-Converts a function that is defined within the body of another function into a closure.
-
-#### Before
-```rust
-fn main() {
-    fn fo┃o(label: &str, number: u64) {
-        println!("{}: {}", label, number);
-    }
-
-    foo("Bar", 100);
-}
-```
-
-#### After
-```rust
-fn main() {
-    let foo = |label: &str, number: u64| {
-        println!("{}: {}", label, number);
-    };
-
-    foo("Bar", 100);
-}
-```
-
-
-### `convert_to_guarded_return`
-**Source:**  [convert_to_guarded_return.rs](crates/ide-assists/src/handlers/convert_to_guarded_return.rs#24) 
-
-Replace a large conditional with a guarded return.
-
-#### Before
-```rust
-fn main() {
-    ┃if cond {
-        foo();
-        bar();
-    }
-}
-```
-
-#### After
-```rust
-fn main() {
-    if !cond {
-        return;
-    }
-    foo();
-    bar();
-}
-```
-
-
-### `convert_tuple_return_type_to_struct`
-**Source:**  [convert_tuple_return_type_to_struct.rs](crates/ide-assists/src/handlers/convert_tuple_return_type_to_struct.rs#20) 
-
-This converts the return type of a function from a tuple type
-into a tuple struct and updates the body accordingly.
-
-#### Before
-```rust
-fn bar() {
-    let (a, b, c) = foo();
-}
-
-fn foo() -> (┃u32, u32, u32) {
-    (1, 2, 3)
-}
-```
-
-#### After
-```rust
-fn bar() {
-    let FooResult(a, b, c) = foo();
-}
-
-struct FooResult(u32, u32, u32);
-
-fn foo() -> FooResult {
-    FooResult(1, 2, 3)
-}
-```
-
-
-### `convert_tuple_struct_to_named_struct`
-**Source:**  [convert_tuple_struct_to_named_struct.rs](crates/ide-assists/src/handlers/convert_tuple_struct_to_named_struct.rs#10) 
-
-Converts tuple struct to struct with named fields, and analogously for tuple enum variants.
-
-#### Before
-```rust
-struct Point┃(f32, f32);
-
-impl Point {
-    pub fn new(x: f32, y: f32) -> Self {
-        Point(x, y)
-    }
-
-    pub fn x(&self) -> f32 {
-        self.0
-    }
-
-    pub fn y(&self) -> f32 {
-        self.1
-    }
-}
-```
-
-#### After
-```rust
-struct Point { field1: f32, field2: f32 }
-
-impl Point {
-    pub fn new(x: f32, y: f32) -> Self {
-        Point { field1: x, field2: y }
-    }
-
-    pub fn x(&self) -> f32 {
-        self.field1
-    }
-
-    pub fn y(&self) -> f32 {
-        self.field2
-    }
-}
-```
-
-
-### `convert_two_arm_bool_match_to_matches_macro`
-**Source:**  [convert_two_arm_bool_match_to_matches_macro.rs](crates/ide-assists/src/handlers/convert_two_arm_bool_match_to_matches_macro.rs#8) 
-
-Convert 2-arm match that evaluates to a boolean into the equivalent matches! invocation.
-
-#### Before
-```rust
-fn main() {
-    match scrutinee┃ {
-        Some(val) if val.cond() => true,
-        _ => false,
-    }
-}
-```
-
-#### After
-```rust
-fn main() {
-    matches!(scrutinee, Some(val) if val.cond())
-}
-```
-
-
-### `convert_while_to_loop`
-**Source:**  [convert_while_to_loop.rs](crates/ide-assists/src/handlers/convert_while_to_loop.rs#20) 
-
-Replace a while with a loop.
-
-#### Before
-```rust
-fn main() {
-    ┃while cond {
-        foo();
-    }
-}
-```
-
-#### After
-```rust
-fn main() {
-    loop {
-        if !cond {
-            break;
-        }
-        foo();
-    }
-}
-```
-
-
-### `destructure_struct_binding`
-**Source:**  [destructure_struct_binding.rs](crates/ide-assists/src/handlers/destructure_struct_binding.rs#18) 
-
-Destructures a struct binding in place.
-
-#### Before
-```rust
-struct Foo {
-    bar: i32,
-    baz: i32,
-}
-fn main() {
-    let ┃foo = Foo { bar: 1, baz: 2 };
-    let bar2 = foo.bar;
-    let baz2 = &foo.baz;
-}
-```
-
-#### After
-```rust
-struct Foo {
-    bar: i32,
-    baz: i32,
-}
-fn main() {
-    let Foo { bar, baz } = Foo { bar: 1, baz: 2 };
-    let bar2 = bar;
-    let baz2 = &baz;
-}
-```
-
-
-### `destructure_tuple_binding`
-**Source:**  [destructure_tuple_binding.rs](crates/ide-assists/src/handlers/destructure_tuple_binding.rs#19) 
-
-Destructures a tuple binding in place.
-
-#### Before
-```rust
-fn main() {
-    let ┃t = (1,2);
-    let v = t.0;
-}
-```
-
-#### After
-```rust
-fn main() {
-    let (┃_0, _1) = (1,2);
-    let v = _0;
-}
-```
-
-
-### `desugar_async_into_impl_future`
-**Source:**  [toggle_async_sugar.rs](crates/ide-assists/src/handlers/toggle_async_sugar.rs#103) 
-
-Rewrites asynchronous function from `async fn` into `-> impl Future`.
-This action does not touch the function body and therefore `0`
-block does not transform to `async { 0 }`.
-
-#### Before
-```rust
-pub as┃ync fn foo() -> usize {
-    0
-}
-```
-
-#### After
-```rust
-pub fn foo() -> impl core::future::Future<Output = usize> {
-    0
-}
-```
-
-
-### `desugar_doc_comment`
-**Source:**  [desugar_doc_comment.rs](crates/ide-assists/src/handlers/desugar_doc_comment.rs#14) 
-
-Desugars doc-comments to the attribute form.
-
-#### Before
-```rust
-/// Multi-line┃
-/// comment
-```
-
-#### After
-```rust
-#[doc = r"Multi-line
-comment"]
-```
-
-
-### `expand_glob_import`
-**Source:**  [expand_glob_import.rs](crates/ide-assists/src/handlers/expand_glob_import.rs#18) 
-
-Expands glob imports.
-
-#### Before
-```rust
-mod foo {
-    pub struct Bar;
-    pub struct Baz;
-}
-
-use foo::*┃;
-
-fn qux(bar: Bar, baz: Baz) {}
-```
-
-#### After
-```rust
-mod foo {
-    pub struct Bar;
-    pub struct Baz;
-}
-
-use foo::{Bar, Baz};
-
-fn qux(bar: Bar, baz: Baz) {}
-```
-
-
-### `explicit_enum_discriminant`
-**Source:**  [explicit_enum_discriminant.rs](crates/ide-assists/src/handlers/explicit_enum_discriminant.rs#11) 
-
-Adds explicit discriminant to all enum variants.
-
-#### Before
-```rust
-enum TheEnum┃ {
-    Foo,
-    Bar,
-    Baz = 42,
-    Quux,
-}
-```
-
-#### After
-```rust
-enum TheEnum {
-    Foo = 0,
-    Bar = 1,
-    Baz = 42,
-    Quux = 43,
-}
-```
-
-
-### `extract_constant`
-**Source:**  [extract_variable.rs](crates/ide-assists/src/handlers/extract_variable.rs#35) 
-
-Extracts subexpression into a constant.
-
-#### Before
-```rust
-fn main() {
-    ┃(1 + 2)┃ * 4;
-}
-```
-
-#### After
-```rust
-fn main() {
-    const ┃VAR_NAME: i32 = 1 + 2;
-    VAR_NAME * 4;
-}
-```
-
-
-### `extract_expressions_from_format_string`
-**Source:**  [extract_expressions_from_format_string.rs](crates/ide-assists/src/handlers/extract_expressions_from_format_string.rs#14) 
-
-Move an expression out of a format string.
-
-#### Before
-```rust
-fn main() {
-    print!("{var} {x + 1}┃");
-}
-```
-
-#### After
-```rust
-fn main() {
-    print!("{var} {}"┃, x + 1);
-}
-```
-
-
-### `extract_function`
-**Source:**  [extract_function.rs](crates/ide-assists/src/handlers/extract_function.rs#39) 
-
-Extracts selected statements and comments into new function.
-
-#### Before
-```rust
-fn main() {
-    let n = 1;
-    ┃let m = n + 2;
-    // calculate
-    let k = m + n;┃
-    let g = 3;
-}
-```
-
-#### After
-```rust
-fn main() {
-    let n = 1;
-    fun_name(n);
-    let g = 3;
-}
-
-fn ┃fun_name(n: i32) {
-    let m = n + 2;
-    // calculate
-    let k = m + n;
-}
-```
-
-
-### `extract_module`
-**Source:**  [extract_module.rs](crates/ide-assists/src/handlers/extract_module.rs#29) 
-
-Extracts a selected region as separate module. All the references, visibility and imports are
-resolved.
-
-#### Before
-```rust
-┃fn foo(name: i32) -> i32 {
-    name + 1
-}┃
-
-fn bar(name: i32) -> i32 {
-    name + 2
-}
-```
-
-#### After
-```rust
-mod modname {
-    pub(crate) fn foo(name: i32) -> i32 {
-        name + 1
-    }
-}
-
-fn bar(name: i32) -> i32 {
-    name + 2
-}
-```
-
-
-### `extract_static`
-**Source:**  [extract_variable.rs](crates/ide-assists/src/handlers/extract_variable.rs#52) 
-
-Extracts subexpression into a static.
-
-#### Before
-```rust
-fn main() {
-    ┃(1 + 2)┃ * 4;
-}
-```
-
-#### After
-```rust
-fn main() {
-    static ┃VAR_NAME: i32 = 1 + 2;
-    VAR_NAME * 4;
-}
-```
-
-
-### `extract_struct_from_enum_variant`
-**Source:**  [extract_struct_from_enum_variant.rs](crates/ide-assists/src/handlers/extract_struct_from_enum_variant.rs#26) 
-
-Extracts a struct from enum variant.
-
-#### Before
-```rust
-enum A { ┃One(u32, u32) }
-```
-
-#### After
-```rust
-struct One(u32, u32);
-
-enum A { One(One) }
-```
-
-
-### `extract_type_alias`
-**Source:**  [extract_type_alias.rs](crates/ide-assists/src/handlers/extract_type_alias.rs#10) 
-
-Extracts the selected type as a type alias.
-
-#### Before
-```rust
-struct S {
-    field: ┃(u8, u8, u8)┃,
-}
-```
-
-#### After
-```rust
-type ┃Type = (u8, u8, u8);
-
-struct S {
-    field: Type,
-}
-```
-
-
-### `extract_variable`
-**Source:**  [extract_variable.rs](crates/ide-assists/src/handlers/extract_variable.rs#18) 
-
-Extracts subexpression into a variable.
-
-#### Before
-```rust
-fn main() {
-    ┃(1 + 2)┃ * 4;
-}
-```
-
-#### After
-```rust
-fn main() {
-    let ┃var_name = 1 + 2;
-    var_name * 4;
-}
-```
-
-
-### `fill_record_pattern_fields`
-**Source:**  [fill_record_pattern_fields.rs](crates/ide-assists/src/handlers/fill_record_pattern_fields.rs#8) 
-
-Fills fields by replacing rest pattern in record patterns.
-
-#### Before
-```rust
-struct Bar { y: Y, z: Z }
-
-fn foo(bar: Bar) {
-    let Bar { ..┃ } = bar;
-}
-```
-
-#### After
-```rust
-struct Bar { y: Y, z: Z }
-
-fn foo(bar: Bar) {
-    let Bar { y, z  } = bar;
-}
-```
-
-
-### `fix_visibility`
-**Source:**  [fix_visibility.rs](crates/ide-assists/src/handlers/fix_visibility.rs#14) 
-
-Makes inaccessible item public.
-
-#### Before
-```rust
-mod m {
-    fn frobnicate() {}
-}
-fn main() {
-    m::frobnicate┃();
-}
-```
-
-#### After
-```rust
-mod m {
-    ┃pub(crate) fn frobnicate() {}
-}
-fn main() {
-    m::frobnicate();
-}
-```
-
-
-### `flip_binexpr`
-**Source:**  [flip_binexpr.rs](crates/ide-assists/src/handlers/flip_binexpr.rs#8) 
-
-Flips operands of a binary expression.
-
-#### Before
-```rust
-fn main() {
-    let _ = 90 +┃ 2;
-}
-```
-
-#### After
-```rust
-fn main() {
-    let _ = 2 + 90;
-}
-```
-
-
-### `flip_comma`
-**Source:**  [flip_comma.rs](crates/ide-assists/src/handlers/flip_comma.rs#10) 
-
-Flips two comma-separated items.
-
-#### Before
-```rust
-fn main() {
-    ((1, 2),┃ (3, 4));
-}
-```
-
-#### After
-```rust
-fn main() {
-    ((3, 4), (1, 2));
-}
-```
-
-
-### `flip_trait_bound`
-**Source:**  [flip_trait_bound.rs](crates/ide-assists/src/handlers/flip_trait_bound.rs#9) 
-
-Flips two trait bounds.
-
-#### Before
-```rust
-fn foo<T: Clone +┃ Copy>() { }
-```
-
-#### After
-```rust
-fn foo<T: Copy + Clone>() { }
-```
-
-
-### `generate_constant`
-**Source:**  [generate_constant.rs](crates/ide-assists/src/handlers/generate_constant.rs#14) 
-
-Generate a named constant.
-
-#### Before
-```rust
-struct S { i: usize }
-impl S { pub fn new(n: usize) {} }
-fn main() {
-    let v = S::new(CAPA┃CITY);
-}
-```
-
-#### After
-```rust
-struct S { i: usize }
-impl S { pub fn new(n: usize) {} }
-fn main() {
-    const CAPACITY: usize = ┃;
-    let v = S::new(CAPACITY);
-}
-```
-
-
-### `generate_default_from_enum_variant`
-**Source:**  [generate_default_from_enum_variant.rs](crates/ide-assists/src/handlers/generate_default_from_enum_variant.rs#6) 
-
-Adds a Default impl for an enum using a variant.
-
-#### Before
-```rust
-enum Version {
- Undefined,
- Minor┃,
- Major,
-}
-```
-
-#### After
-```rust
-enum Version {
- Undefined,
- Minor,
- Major,
-}
-
-impl Default for Version {
-    fn default() -> Self {
-        Self::Minor
-    }
-}
-```
-
-
-### `generate_default_from_new`
-**Source:**  [generate_default_from_new.rs](crates/ide-assists/src/handlers/generate_default_from_new.rs#13) 
-
-Generates default implementation from new method.
-
-#### Before
-```rust
-struct Example { _inner: () }
-
-impl Example {
-    pub fn n┃ew() -> Self {
-        Self { _inner: () }
-    }
-}
-```
-
-#### After
-```rust
-struct Example { _inner: () }
-
-impl Example {
-    pub fn new() -> Self {
-        Self { _inner: () }
-    }
-}
-
-impl Default for Example {
-    fn default() -> Self {
-        Self::new()
-    }
-}
-```
-
-
-### `generate_delegate_methods`
-**Source:**  [generate_delegate_methods.rs](crates/ide-assists/src/handlers/generate_delegate_methods.rs#15) 
-
-Generate delegate methods.
-
-#### Before
-```rust
-struct Age(u8);
-impl Age {
-    fn age(&self) -> u8 {
-        self.0
-    }
-}
-
-struct Person {
-    ag┃e: Age,
-}
-```
-
-#### After
-```rust
-struct Age(u8);
-impl Age {
-    fn age(&self) -> u8 {
-        self.0
-    }
-}
-
-struct Person {
-    age: Age,
-}
-
-impl Person {
-    ┃fn age(&self) -> u8 {
-        self.age.age()
-    }
-}
-```
-
-
-### `generate_delegate_trait`
-**Source:**  [generate_delegate_trait.rs](crates/ide-assists/src/handlers/generate_delegate_trait.rs#29) 
-
-Generate delegate trait implementation for `StructField`s.
-
-#### Before
-```rust
-trait SomeTrait {
-    type T;
-    fn fn_(arg: u32) -> u32;
-    fn method_(&mut self) -> bool;
-}
-struct A;
-impl SomeTrait for A {
-    type T = u32;
-
-    fn fn_(arg: u32) -> u32 {
-        42
-    }
-
-    fn method_(&mut self) -> bool {
-        false
-    }
-}
-struct B {
-    a┃: A,
-}
-```
-
-#### After
-```rust
-trait SomeTrait {
-    type T;
-    fn fn_(arg: u32) -> u32;
-    fn method_(&mut self) -> bool;
-}
-struct A;
-impl SomeTrait for A {
-    type T = u32;
-
-    fn fn_(arg: u32) -> u32 {
-        42
-    }
-
-    fn method_(&mut self) -> bool {
-        false
-    }
-}
-struct B {
-    a: A,
-}
-
-impl SomeTrait for B {
-    type T = <A as SomeTrait>::T;
-
-    fn fn_(arg: u32) -> u32 {
-        <A as SomeTrait>::fn_(arg)
-    }
-
-    fn method_(&mut self) -> bool {
-        <A as SomeTrait>::method_(&mut self.a)
-    }
-}
-```
-
-
-### `generate_deref`
-**Source:**  [generate_deref.rs](crates/ide-assists/src/handlers/generate_deref.rs#16) 
-
-Generate `Deref` impl using the given struct field.
-
-#### Before
-```rust
-struct A;
-struct B {
-   ┃a: A
-}
-```
-
-#### After
-```rust
-struct A;
-struct B {
-   a: A
-}
-
-impl core::ops::Deref for B {
-    type Target = A;
-
-    fn deref(&self) -> &Self::Target {
-        &self.a
-    }
-}
-```
-
-
-### `generate_derive`
-**Source:**  [generate_derive.rs](crates/ide-assists/src/handlers/generate_derive.rs#8) 
-
-Adds a new `#[derive()]` clause to a struct or enum.
-
-#### Before
-```rust
-struct Point {
-    x: u32,
-    y: u32,┃
-}
-```
-
-#### After
-```rust
-#[derive(┃)]
-struct Point {
-    x: u32,
-    y: u32,
-}
-```
-
-
-### `generate_doc_example`
-**Source:**  [generate_documentation_template.rs](crates/ide-assists/src/handlers/generate_documentation_template.rs#76) 
-
-Generates a rustdoc example when editing an item's documentation.
-
-#### Before
-```rust
-/// Adds two numbers.┃
-pub fn add(a: i32, b: i32) -> i32 { a + b }
-```
-
-#### After
-```rust
-/// Adds two numbers.
-///
-/// # Examples
-///
-/// ```
-/// use ra_test_fixture::add;
-///
-/// assert_eq!(add(a, b), );
-/// ```
-pub fn add(a: i32, b: i32) -> i32 { a + b }
-```
-
-
-### `generate_documentation_template`
-**Source:**  [generate_documentation_template.rs](crates/ide-assists/src/handlers/generate_documentation_template.rs#13) 
-
-Adds a documentation template above a function definition / declaration.
-
-#### Before
-```rust
-pub struct S;
-impl S {
-    pub unsafe fn set_len┃(&mut self, len: usize) -> Result<(), std::io::Error> {
-        /* ... */
-    }
-}
-```
-
-#### After
-```rust
-pub struct S;
-impl S {
-    /// Sets the length of this [`S`].
-    ///
-    /// # Errors
-    ///
-    /// This function will return an error if .
-    ///
-    /// # Safety
-    ///
-    /// .
-    pub unsafe fn set_len(&mut self, len: usize) -> Result<(), std::io::Error> {
-        /* ... */
-    }
-}
-```
-
-
-### `generate_enum_as_method`
-**Source:**  [generate_enum_projection_method.rs](crates/ide-assists/src/handlers/generate_enum_projection_method.rs#59) 
-
-Generate an `as_` method for this enum variant.
-
-#### Before
-```rust
-enum Value {
- Number(i32),
- Text(String)┃,
-}
-```
-
-#### After
-```rust
-enum Value {
- Number(i32),
- Text(String),
-}
-
-impl Value {
-    fn as_text(&self) -> Option<&String> {
-        if let Self::Text(v) = self {
-            Some(v)
-        } else {
-            None
-        }
-    }
-}
-```
-
-
-### `generate_enum_is_method`
-**Source:**  [generate_enum_is_method.rs](crates/ide-assists/src/handlers/generate_enum_is_method.rs#11) 
-
-Generate an `is_` method for this enum variant.
-
-#### Before
-```rust
-enum Version {
- Undefined,
- Minor┃,
- Major,
-}
-```
-
-#### After
-```rust
-enum Version {
- Undefined,
- Minor,
- Major,
-}
-
-impl Version {
-    /// Returns `true` if the version is [`Minor`].
-    ///
-    /// [`Minor`]: Version::Minor
-    #[must_use]
-    fn is_minor(&self) -> bool {
-        matches!(self, Self::Minor)
-    }
-}
-```
-
-
-### `generate_enum_try_into_method`
-**Source:**  [generate_enum_projection_method.rs](crates/ide-assists/src/handlers/generate_enum_projection_method.rs#12) 
-
-Generate a `try_into_` method for this enum variant.
-
-#### Before
-```rust
-enum Value {
- Number(i32),
- Text(String)┃,
-}
-```
-
-#### After
-```rust
-enum Value {
- Number(i32),
- Text(String),
-}
-
-impl Value {
-    fn try_into_text(self) -> Result<String, Self> {
-        if let Self::Text(v) = self {
-            Ok(v)
-        } else {
-            Err(self)
-        }
-    }
-}
-```
-
-
-### `generate_enum_variant`
-**Source:**  [generate_enum_variant.rs](crates/ide-assists/src/handlers/generate_enum_variant.rs#10) 
-
-Adds a variant to an enum.
-
-#### Before
-```rust
-enum Countries {
-    Ghana,
-}
-
-fn main() {
-    let country = Countries::Lesotho┃;
-}
-```
-
-#### After
-```rust
-enum Countries {
-    Ghana,
-    Lesotho,
-}
-
-fn main() {
-    let country = Countries::Lesotho;
-}
-```
-
-
-### `generate_fn_type_alias_named`
-**Source:**  [generate_fn_type_alias.rs](crates/ide-assists/src/handlers/generate_fn_type_alias.rs#10) 
-
-Generate a type alias for the function with named parameters.
-
-#### Before
-```rust
-unsafe fn fo┃o(n: i32) -> i32 { 42i32 }
-```
-
-#### After
-```rust
-type ${0:FooFn} = unsafe fn(n: i32) -> i32;
-
-unsafe fn foo(n: i32) -> i32 { 42i32 }
-```
-
-
-### `generate_fn_type_alias_unnamed`
-**Source:**  [generate_fn_type_alias.rs](crates/ide-assists/src/handlers/generate_fn_type_alias.rs#24) 
-
-Generate a type alias for the function with unnamed parameters.
-
-#### Before
-```rust
-unsafe fn fo┃o(n: i32) -> i32 { 42i32 }
-```
-
-#### After
-```rust
-type ${0:FooFn} = unsafe fn(i32) -> i32;
-
-unsafe fn foo(n: i32) -> i32 { 42i32 }
-```
-
-
-### `generate_from_impl_for_enum`
-**Source:**  [generate_from_impl_for_enum.rs](crates/ide-assists/src/handlers/generate_from_impl_for_enum.rs#8) 
-
-Adds a From impl for this enum variant with one tuple field.
-
-#### Before
-```rust
-enum A { ┃One(u32) }
-```
-
-#### After
-```rust
-enum A { One(u32) }
-
-impl From<u32> for A {
-    fn from(v: u32) -> Self {
-        Self::One(v)
-    }
-}
-```
-
-
-### `generate_function`
-**Source:**  [generate_function.rs](crates/ide-assists/src/handlers/generate_function.rs#28) 
-
-Adds a stub function with a signature matching the function under the cursor.
-
-#### Before
-```rust
-struct Baz;
-fn baz() -> Baz { Baz }
-fn foo() {
-    bar┃("", baz());
-}
-
-```
-
-#### After
-```rust
-struct Baz;
-fn baz() -> Baz { Baz }
-fn foo() {
-    bar("", baz());
-}
-
-fn bar(arg: &str, baz: Baz) ${0:-> _} {
-    todo!()
-}
-
-```
-
-
-### `generate_getter`
-**Source:**  [generate_getter_or_setter.rs](crates/ide-assists/src/handlers/generate_getter_or_setter.rs#73) 
-
-Generate a getter method.
-
-#### Before
-```rust
-struct Person {
-    nam┃e: String,
-}
-```
-
-#### After
-```rust
-struct Person {
-    name: String,
-}
-
-impl Person {
-    fn ┃name(&self) -> &str {
-        &self.name
-    }
-}
-```
-
-
-### `generate_getter_mut`
-**Source:**  [generate_getter_or_setter.rs](crates/ide-assists/src/handlers/generate_getter_or_setter.rs#127) 
-
-Generate a mut getter method.
-
-#### Before
-```rust
-struct Person {
-    nam┃e: String,
-}
-```
-
-#### After
-```rust
-struct Person {
-    name: String,
-}
-
-impl Person {
-    fn ┃name_mut(&mut self) -> &mut String {
-        &mut self.name
-    }
-}
-```
-
-
-### `generate_impl`
-**Source:**  [generate_impl.rs](crates/ide-assists/src/handlers/generate_impl.rs#20) 
-
-Adds a new inherent impl for a type.
-
-#### Before
-```rust
-struct Ctx┃<T: Clone> {
-    data: T,
-}
-```
-
-#### After
-```rust
-struct Ctx<T: Clone> {
-    data: T,
-}
-
-impl<T: Clone> Ctx<T> {┃}
-```
-
-
-### `generate_is_empty_from_len`
-**Source:**  [generate_is_empty_from_len.rs](crates/ide-assists/src/handlers/generate_is_empty_from_len.rs#12) 
-
-Generates is_empty implementation from the len method.
-
-#### Before
-```rust
-struct MyStruct { data: Vec<String> }
-
-impl MyStruct {
-    #[must_use]
-    p┃ub fn len(&self) -> usize {
-        self.data.len()
-    }
-}
-```
-
-#### After
-```rust
-struct MyStruct { data: Vec<String> }
-
-impl MyStruct {
-    #[must_use]
-    pub fn len(&self) -> usize {
-        self.data.len()
-    }
-
-    #[must_use]
-    pub fn is_empty(&self) -> bool {
-        self.len() == 0
-    }
-}
-```
-
-
-### `generate_mut_trait_impl`
-**Source:**  [generate_mut_trait_impl.rs](crates/ide-assists/src/handlers/generate_mut_trait_impl.rs#12) 
-
-Adds a IndexMut impl from the `Index` trait.
-
-#### Before
-```rust
-pub enum Axis { X = 0, Y = 1, Z = 2 }
-
-impl<T> core::ops::Index┃<Axis> for [T; 3] {
-    type Output = T;
-
-    fn index(&self, index: Axis) -> &Self::Output {
-        &self[index as usize]
-    }
-}
-```
-
-#### After
-```rust
-pub enum Axis { X = 0, Y = 1, Z = 2 }
-
-┃impl<T> core::ops::IndexMut<Axis> for [T; 3] {
-    fn index_mut(&mut self, index: Axis) -> &mut Self::Output {
-        &self[index as usize]
-    }
-}
-
-impl<T> core::ops::Index<Axis> for [T; 3] {
-    type Output = T;
-
-    fn index(&self, index: Axis) -> &Self::Output {
-        &self[index as usize]
-    }
-}
-```
-
-
-### `generate_new`
-**Source:**  [generate_new.rs](crates/ide-assists/src/handlers/generate_new.rs#14) 
-
-Adds a `fn new` for a type.
-
-#### Before
-```rust
-struct Ctx<T: Clone> {
-     data: T,┃
-}
-```
-
-#### After
-```rust
-struct Ctx<T: Clone> {
-     data: T,
-}
-
-impl<T: Clone> Ctx<T> {
-    fn ┃new(data: T) -> Self {
-        Self { data }
-    }
-}
-```
-
-
-### `generate_setter`
-**Source:**  [generate_getter_or_setter.rs](crates/ide-assists/src/handlers/generate_getter_or_setter.rs#13) 
-
-Generate a setter method.
-
-#### Before
-```rust
-struct Person {
-    nam┃e: String,
-}
-```
-
-#### After
-```rust
-struct Person {
-    name: String,
-}
-
-impl Person {
-    fn ┃set_name(&mut self, name: String) {
-        self.name = name;
-    }
-}
-```
-
-
-### `generate_trait_from_impl`
-**Source:**  [generate_trait_from_impl.rs](crates/ide-assists/src/handlers/generate_trait_from_impl.rs#18) 
-
-Generate trait for an already defined inherent impl and convert impl to a trait impl.
-
-#### Before
-```rust
-struct Foo<const N: usize>([i32; N]);
-
-macro_rules! const_maker {
-    ($t:ty, $v:tt) => {
-        const CONST: $t = $v;
-    };
-}
-
-impl<const N: usize> Fo┃o<N> {
-    // Used as an associated constant.
-    const CONST_ASSOC: usize = N * 4;
-
-    fn create() -> Option<()> {
-        Some(())
-    }
-
-    const_maker! {i32, 7}
-}
-```
-
-#### After
-```rust
-struct Foo<const N: usize>([i32; N]);
-
-macro_rules! const_maker {
-    ($t:ty, $v:tt) => {
-        const CONST: $t = $v;
-    };
-}
-
-trait ${0:NewTrait}<const N: usize> {
-    // Used as an associated constant.
-    const CONST_ASSOC: usize = N * 4;
-
-    fn create() -> Option<()>;
-
-    const_maker! {i32, 7}
-}
-
-impl<const N: usize> ${0:NewTrait}<N> for Foo<N> {
-    // Used as an associated constant.
-    const CONST_ASSOC: usize = N * 4;
-
-    fn create() -> Option<()> {
-        Some(())
-    }
-
-    const_maker! {i32, 7}
-}
-```
-
-
-### `generate_trait_impl`
-**Source:**  [generate_impl.rs](crates/ide-assists/src/handlers/generate_impl.rs#66) 
-
-Adds a new trait impl for a type.
-
-#### Before
-```rust
-struct ┃Ctx<T: Clone> {
-    data: T,
-}
-```
-
-#### After
-```rust
-struct Ctx<T: Clone> {
-    data: T,
-}
-
-impl<T: Clone> ${0:_} for Ctx<T> {}
-```
-
-
-### `inline_call`
-**Source:**  [inline_call.rs](crates/ide-assists/src/handlers/inline_call.rs#170) 
-
-Inlines a function or method body creating a `let` statement per parameter unless the parameter
-can be inlined. The parameter will be inlined either if it the supplied argument is a simple local
-or if the parameter is only accessed inside the function body once.
-
-#### Before
-```rust
-fn foo(name: Option<&str>) {
-    let name = name.unwrap┃();
-}
-```
-
-#### After
-```rust
-fn foo(name: Option<&str>) {
-    let name = match name {
-            Some(val) => val,
-            None => panic!("called `Option::unwrap()` on a `None` value"),
-        };
-}
-```
-
-
-### `inline_const_as_literal`
-**Source:**  [inline_const_as_literal.rs](crates/ide-assists/src/handlers/inline_const_as_literal.rs#6) 
-
-Evaluate and inline const variable as literal.
-
-#### Before
-```rust
-const STRING: &str = "Hello, World!";
-
-fn something() -> &'static str {
-    STRING┃
-}
-```
-
-#### After
-```rust
-const STRING: &str = "Hello, World!";
-
-fn something() -> &'static str {
-    "Hello, World!"
-}
-```
-
-
-### `inline_into_callers`
-**Source:**  [inline_call.rs](crates/ide-assists/src/handlers/inline_call.rs#32) 
-
-Inline a function or method body into all of its callers where possible, creating a `let` statement per parameter
-unless the parameter can be inlined. The parameter will be inlined either if it the supplied argument is a simple local
-or if the parameter is only accessed inside the function body once.
-If all calls can be inlined the function will be removed.
-
-#### Before
-```rust
-fn print(_: &str) {}
-fn foo┃(word: &str) {
-    if !word.is_empty() {
-        print(word);
-    }
-}
-fn bar() {
-    foo("안녕하세요");
-    foo("여러분");
-}
-```
-
-#### After
-```rust
-fn print(_: &str) {}
-
-fn bar() {
-    {
-        let word: &str = "안녕하세요";
-        if !word.is_empty() {
-            print(word);
-        }
-    };
-    {
-        let word: &str = "여러분";
-        if !word.is_empty() {
-            print(word);
-        }
-    };
-}
-```
-
-
-### `inline_local_variable`
-**Source:**  [inline_local_variable.rs](crates/ide-assists/src/handlers/inline_local_variable.rs#17) 
-
-Inlines a local variable.
-
-#### Before
-```rust
-fn main() {
-    let x┃ = 1 + 2;
-    x * 4;
-}
-```
-
-#### After
-```rust
-fn main() {
-    (1 + 2) * 4;
-}
-```
-
-
-### `inline_macro`
-**Source:**  [inline_macro.rs](crates/ide-assists/src/handlers/inline_macro.rs#7) 
-
-Takes a macro and inlines it one step.
-
-#### Before
-```rust
-macro_rules! num {
-    (+$($t:tt)+) => (1 + num!($($t )+));
-    (-$($t:tt)+) => (-1 + num!($($t )+));
-    (+) => (1);
-    (-) => (-1);
-}
-
-fn main() {
-    let number = num┃!(+ + + - + +);
-    println!("{number}");
-}
-```
-
-#### After
-```rust
-macro_rules! num {
-    (+$($t:tt)+) => (1 + num!($($t )+));
-    (-$($t:tt)+) => (-1 + num!($($t )+));
-    (+) => (1);
-    (-) => (-1);
-}
-
-fn main() {
-    let number = 1+num!(+ + - + +);
-    println!("{number}");
-}
-```
-
-
-### `inline_type_alias`
-**Source:**  [inline_type_alias.rs](crates/ide-assists/src/handlers/inline_type_alias.rs#106) 
-
-Replace a type alias with its concrete type.
-
-#### Before
-```rust
-type A<T = u32> = Vec<T>;
-
-fn main() {
-    let a: ┃A;
-}
-```
-
-#### After
-```rust
-type A<T = u32> = Vec<T>;
-
-fn main() {
-    let a: Vec<u32>;
-}
-```
-
-
-### `inline_type_alias_uses`
-**Source:**  [inline_type_alias.rs](crates/ide-assists/src/handlers/inline_type_alias.rs#24) 
-
-Inline a type alias into all of its uses where possible.
-
-#### Before
-```rust
-type ┃A = i32;
-fn id(x: A) -> A {
-    x
-};
-fn foo() {
-    let _: A = 3;
-}
-```
-
-#### After
-```rust
-
-fn id(x: i32) -> i32 {
-    x
-};
-fn foo() {
-    let _: i32 = 3;
-}
-```
-
-
-### `into_to_qualified_from`
-**Source:**  [into_to_qualified_from.rs](crates/ide-assists/src/handlers/into_to_qualified_from.rs#10) 
-
-Convert an `into` method call to a fully qualified `from` call.
-
-#### Before
-```rust
-//- minicore: from
-struct B;
-impl From<i32> for B {
-    fn from(a: i32) -> Self {
-       B
-    }
-}
-
-fn main() -> () {
-    let a = 3;
-    let b: B = a.in┃to();
-}
-```
-
-#### After
-```rust
-struct B;
-impl From<i32> for B {
-    fn from(a: i32) -> Self {
-       B
-    }
-}
-
-fn main() -> () {
-    let a = 3;
-    let b: B = B::from(a);
-}
-```
-
-
-### `introduce_named_generic`
-**Source:**  [introduce_named_generic.rs](crates/ide-assists/src/handlers/introduce_named_generic.rs#7) 
-
-Replaces `impl Trait` function argument with the named generic.
-
-#### Before
-```rust
-fn foo(bar: ┃impl Bar) {}
-```
-
-#### After
-```rust
-fn foo<┃B: Bar>(bar: B) {}
-```
-
-
-### `introduce_named_lifetime`
-**Source:**  [introduce_named_lifetime.rs](crates/ide-assists/src/handlers/introduce_named_lifetime.rs#13) 
-
-Change an anonymous lifetime to a named lifetime.
-
-#### Before
-```rust
-impl Cursor<'_┃> {
-    fn node(self) -> &SyntaxNode {
-        match self {
-            Cursor::Replace(node) | Cursor::Before(node) => node,
-        }
-    }
-}
-```
-
-#### After
-```rust
-impl<'a> Cursor<'a> {
-    fn node(self) -> &SyntaxNode {
-        match self {
-            Cursor::Replace(node) | Cursor::Before(node) => node,
-        }
-    }
-}
-```
-
-
-### `invert_if`
-**Source:**  [invert_if.rs](crates/ide-assists/src/handlers/invert_if.rs#13) 
-
-This transforms if expressions of the form `if !x {A} else {B}` into `if x {B} else {A}`
-This also works with `!=`. This assist can only be applied with the cursor on `if`.
-
-#### Before
-```rust
-fn main() {
-    if┃ !y { A } else { B }
-}
-```
-
-#### After
-```rust
-fn main() {
-    if y { B } else { A }
-}
-```
-
-
-### `line_to_block`
-**Source:**  [convert_comment_block.rs](crates/ide-assists/src/handlers/convert_comment_block.rs#9) 
-
-Converts comments between block and single-line form.
-
-#### Before
-```rust
-   // Multi-line┃
-   // comment
-```
-
-#### After
-```rust
-  /*
-  Multi-line
-  comment
-  */
-```
-
-
-### `make_raw_string`
-**Source:**  [raw_string.rs](crates/ide-assists/src/handlers/raw_string.rs#7) 
-
-Adds `r#` to a plain string literal.
-
-#### Before
-```rust
-fn main() {
-    "Hello,┃ World!";
-}
-```
-
-#### After
-```rust
-fn main() {
-    r#"Hello, World!"#;
-}
-```
-
-
-### `make_usual_string`
-**Source:**  [raw_string.rs](crates/ide-assists/src/handlers/raw_string.rs#47) 
-
-Turns a raw string into a plain string.
-
-#### Before
-```rust
-fn main() {
-    r#"Hello,┃ "World!""#;
-}
-```
-
-#### After
-```rust
-fn main() {
-    "Hello, \"World!\"";
-}
-```
-
-
-### `merge_imports`
-**Source:**  [merge_imports.rs](crates/ide-assists/src/handlers/merge_imports.rs#21) 
-
-Merges neighbor imports with a common prefix.
-
-#### Before
-```rust
-use std::┃fmt::Formatter;
-use std::io;
-```
-
-#### After
-```rust
-use std::{fmt::Formatter, io};
-```
-
-
-### `merge_match_arms`
-**Source:**  [merge_match_arms.rs](crates/ide-assists/src/handlers/merge_match_arms.rs#12) 
-
-Merges the current match arm with the following if their bodies are identical.
-
-#### Before
-```rust
-enum Action { Move { distance: u32 }, Stop }
-
-fn handle(action: Action) {
-    match action {
-        ┃Action::Move(..) => foo(),
-        Action::Stop => foo(),
-    }
-}
-```
-
-#### After
-```rust
-enum Action { Move { distance: u32 }, Stop }
-
-fn handle(action: Action) {
-    match action {
-        Action::Move(..) | Action::Stop => foo(),
-    }
-}
-```
-
-
-### `merge_nested_if`
-**Source:**  [merge_nested_if.rs](crates/ide-assists/src/handlers/merge_nested_if.rs#11) 
-
-This transforms if expressions of the form `if x { if y {A} }` into `if x && y {A}`
-This assist can only be applied with the cursor on `if`.
-
-#### Before
-```rust
-fn main() {
-   i┃f x == 3 { if y == 4 { 1 } }
-}
-```
-
-#### After
-```rust
-fn main() {
-   if x == 3 && y == 4 { 1 }
-}
-```
-
-
-### `move_arm_cond_to_match_guard`
-**Source:**  [move_guard.rs](crates/ide-assists/src/handlers/move_guard.rs#69) 
-
-Moves if expression from match arm body into a guard.
-
-#### Before
-```rust
-enum Action { Move { distance: u32 }, Stop }
-
-fn handle(action: Action) {
-    match action {
-        Action::Move { distance } => ┃if distance > 10 { foo() },
-        _ => (),
-    }
-}
-```
-
-#### After
-```rust
-enum Action { Move { distance: u32 }, Stop }
-
-fn handle(action: Action) {
-    match action {
-        Action::Move { distance } if distance > 10 => foo(),
-        _ => (),
-    }
-}
-```
-
-
-### `move_bounds_to_where_clause`
-**Source:**  [move_bounds.rs](crates/ide-assists/src/handlers/move_bounds.rs#12) 
-
-Moves inline type bounds to a where clause.
-
-#### Before
-```rust
-fn apply<T, U, ┃F: FnOnce(T) -> U>(f: F, x: T) -> U {
-    f(x)
-}
-```
-
-#### After
-```rust
-fn apply<T, U, F>(f: F, x: T) -> U where F: FnOnce(T) -> U {
-    f(x)
-}
-```
-
-
-### `move_const_to_impl`
-**Source:**  [move_const_to_impl.rs](crates/ide-assists/src/handlers/move_const_to_impl.rs#14) 
-
-Move a local constant item in a method to impl's associated constant. All the references will be
-qualified with `Self::`.
-
-#### Before
-```rust
-struct S;
-impl S {
-    fn foo() -> usize {
-        /// The answer.
-        const C┃: usize = 42;
-
-        C * C
-    }
-}
-```
-
-#### After
-```rust
-struct S;
-impl S {
-    /// The answer.
-    const C: usize = 42;
-
-    fn foo() -> usize {
-        Self::C * Self::C
-    }
-}
-```
-
-
-### `move_from_mod_rs`
-**Source:**  [move_from_mod_rs.rs](crates/ide-assists/src/handlers/move_from_mod_rs.rs#12) 
-
-Moves xxx/mod.rs to xxx.rs.
-
-#### Before
-```rust
-//- /main.rs
-mod a;
-//- /a/mod.rs
-┃fn t() {}┃
-```
-
-#### After
-```rust
-fn t() {}
-```
-
-
-### `move_guard_to_arm_body`
-**Source:**  [move_guard.rs](crates/ide-assists/src/handlers/move_guard.rs#8) 
-
-Moves match guard into match arm body.
-
-#### Before
-```rust
-enum Action { Move { distance: u32 }, Stop }
-
-fn handle(action: Action) {
-    match action {
-        Action::Move { distance } ┃if distance > 10 => foo(),
-        _ => (),
-    }
-}
-```
-
-#### After
-```rust
-enum Action { Move { distance: u32 }, Stop }
-
-fn handle(action: Action) {
-    match action {
-        Action::Move { distance } => if distance > 10 {
-            foo()
-        },
-        _ => (),
-    }
-}
-```
-
-
-### `move_module_to_file`
-**Source:**  [move_module_to_file.rs](crates/ide-assists/src/handlers/move_module_to_file.rs#15) 
-
-Moves inline module's contents to a separate file.
-
-#### Before
-```rust
-mod ┃foo {
-    fn t() {}
-}
-```
-
-#### After
-```rust
-mod foo;
-```
-
-
-### `move_to_mod_rs`
-**Source:**  [move_to_mod_rs.rs](crates/ide-assists/src/handlers/move_to_mod_rs.rs#12) 
-
-Moves xxx.rs to xxx/mod.rs.
-
-#### Before
-```rust
-//- /main.rs
-mod a;
-//- /a.rs
-┃fn t() {}┃
-```
-
-#### After
-```rust
-fn t() {}
-```
-
-
-### `normalize_import`
-**Source:**  [normalize_import.rs](crates/ide-assists/src/handlers/normalize_import.rs#9) 
-
-Normalizes an import.
-
-#### Before
-```rust
-use┃ std::{io, {fmt::Formatter}};
-```
-
-#### After
-```rust
-use std::{fmt::Formatter, io};
-```
-
-
-### `promote_local_to_const`
-**Source:**  [promote_local_to_const.rs](crates/ide-assists/src/handlers/promote_local_to_const.rs#17) 
-
-Promotes a local variable to a const item changing its name to a `SCREAMING_SNAKE_CASE` variant
-if the local uses no non-const expressions.
-
-#### Before
-```rust
-fn main() {
-    let foo┃ = true;
-
-    if foo {
-        println!("It's true");
-    } else {
-        println!("It's false");
-    }
-}
-```
-
-#### After
-```rust
-fn main() {
-    const ┃FOO: bool = true;
-
-    if FOO {
-        println!("It's true");
-    } else {
-        println!("It's false");
-    }
-}
-```
-
-
-### `pull_assignment_up`
-**Source:**  [pull_assignment_up.rs](crates/ide-assists/src/handlers/pull_assignment_up.rs#11) 
-
-Extracts variable assignment to outside an if or match statement.
-
-#### Before
-```rust
-fn main() {
-    let mut foo = 6;
-
-    if true {
-        ┃foo = 5;
-    } else {
-        foo = 4;
-    }
-}
-```
-
-#### After
-```rust
-fn main() {
-    let mut foo = 6;
-
-    foo = if true {
-        5
-    } else {
-        4
-    };
-}
-```
-
-
-### `qualify_method_call`
-**Source:**  [qualify_method_call.rs](crates/ide-assists/src/handlers/qualify_method_call.rs#10) 
-
-Replaces the method call with a qualified function call.
-
-#### Before
-```rust
-struct Foo;
-impl Foo {
-    fn foo(&self) {}
-}
-fn main() {
-    let foo = Foo;
-    foo.fo┃o();
-}
-```
-
-#### After
-```rust
-struct Foo;
-impl Foo {
-    fn foo(&self) {}
-}
-fn main() {
-    let foo = Foo;
-    Foo::foo(&foo);
-}
-```
-
-
-### `qualify_path`
-**Source:**  [qualify_path.rs](crates/ide-assists/src/handlers/qualify_path.rs#24) 
-
-If the name is unresolved, provides all possible qualified paths for it.
-
-#### Before
-```rust
-fn main() {
-    let map = HashMap┃::new();
-}
-```
-
-#### After
-```rust
-fn main() {
-    let map = std::collections::HashMap::new();
-}
-```
-
-
-### `reformat_number_literal`
-**Source:**  [number_representation.rs](crates/ide-assists/src/handlers/number_representation.rs#7) 
-
-Adds or removes separators from integer literal.
-
-#### Before
-```rust
-const _: i32 = 1012345┃;
-```
-
-#### After
-```rust
-const _: i32 = 1_012_345;
-```
-
-
-### `remove_dbg`
-**Source:**  [remove_dbg.rs](crates/ide-assists/src/handlers/remove_dbg.rs#9) 
-
-Removes `dbg!()` macro call.
-
-#### Before
-```rust
-fn main() {
-    let x = ┃dbg!(42 * dbg!(4 + 2));┃
-}
-```
-
-#### After
-```rust
-fn main() {
-    let x = 42 * (4 + 2);
-}
-```
-
-
-### `remove_hash`
-**Source:**  [raw_string.rs](crates/ide-assists/src/handlers/raw_string.rs#117) 
-
-Removes a hash from a raw string literal.
-
-#### Before
-```rust
-fn main() {
-    r#"Hello,┃ World!"#;
-}
-```
-
-#### After
-```rust
-fn main() {
-    r"Hello, World!";
-}
-```
-
-
-### `remove_mut`
-**Source:**  [remove_mut.rs](crates/ide-assists/src/handlers/remove_mut.rs#5) 
-
-Removes the `mut` keyword.
-
-#### Before
-```rust
-impl Walrus {
-    fn feed(&mut┃ self, amount: u32) {}
-}
-```
-
-#### After
-```rust
-impl Walrus {
-    fn feed(&self, amount: u32) {}
-}
-```
-
-
-### `remove_parentheses`
-**Source:**  [remove_parentheses.rs](crates/ide-assists/src/handlers/remove_parentheses.rs#5) 
-
-Removes redundant parentheses.
-
-#### Before
-```rust
-fn main() {
-    _ = ┃(2) + 2;
-}
-```
-
-#### After
-```rust
-fn main() {
-    _ = 2 + 2;
-}
-```
-
-
-### `remove_unused_imports`
-**Source:**  [remove_unused_imports.rs](crates/ide-assists/src/handlers/remove_unused_imports.rs#17) 
-
-Removes any use statements in the current selection that are unused.
-
-#### Before
-```rust
-struct X();
-mod foo {
-    use super::X┃;
-}
-```
-
-#### After
-```rust
-struct X();
-mod foo {
-}
-```
-
-
-### `remove_unused_param`
-**Source:**  [remove_unused_param.rs](crates/ide-assists/src/handlers/remove_unused_param.rs#15) 
-
-Removes unused function parameter.
-
-#### Before
-```rust
-fn frobnicate(x: i32┃) {}
-
-fn main() {
-    frobnicate(92);
-}
-```
-
-#### After
-```rust
-fn frobnicate() {}
-
-fn main() {
-    frobnicate();
-}
-```
-
-
-### `reorder_fields`
-**Source:**  [reorder_fields.rs](crates/ide-assists/src/handlers/reorder_fields.rs#8) 
-
-Reorder the fields of record literals and record patterns in the same order as in
-the definition.
-
-#### Before
-```rust
-struct Foo {foo: i32, bar: i32};
-const test: Foo = ┃Foo {bar: 0, foo: 1}
-```
-
-#### After
-```rust
-struct Foo {foo: i32, bar: i32};
-const test: Foo = Foo {foo: 1, bar: 0}
-```
-
-
-### `reorder_impl_items`
-**Source:**  [reorder_impl_items.rs](crates/ide-assists/src/handlers/reorder_impl_items.rs#11) 
-
-Reorder the items of an `impl Trait`. The items will be ordered
-in the same order as in the trait definition.
-
-#### Before
-```rust
-trait Foo {
-    type A;
-    const B: u8;
-    fn c();
-}
-
-struct Bar;
-┃impl Foo for Bar┃ {
-    const B: u8 = 17;
-    fn c() {}
-    type A = String;
-}
-```
-
-#### After
-```rust
-trait Foo {
-    type A;
-    const B: u8;
-    fn c();
-}
-
-struct Bar;
-impl Foo for Bar {
-    type A = String;
-    const B: u8 = 17;
-    fn c() {}
-}
-```
-
-
-### `replace_arith_with_checked`
-**Source:**  [replace_arith_op.rs](crates/ide-assists/src/handlers/replace_arith_op.rs#9) 
-
-Replaces arithmetic on integers with the `checked_*` equivalent.
-
-#### Before
-```rust
-fn main() {
-  let x = 1 ┃+ 2;
-}
-```
-
-#### After
-```rust
-fn main() {
-  let x = 1.checked_add(2);
-}
-```
-
-
-### `replace_arith_with_saturating`
-**Source:**  [replace_arith_op.rs](crates/ide-assists/src/handlers/replace_arith_op.rs#28) 
-
-Replaces arithmetic on integers with the `saturating_*` equivalent.
-
-#### Before
-```rust
-fn main() {
-  let x = 1 ┃+ 2;
-}
-```
-
-#### After
-```rust
-fn main() {
-  let x = 1.saturating_add(2);
-}
-```
-
-
-### `replace_arith_with_wrapping`
-**Source:**  [replace_arith_op.rs](crates/ide-assists/src/handlers/replace_arith_op.rs#50) 
-
-Replaces arithmetic on integers with the `wrapping_*` equivalent.
-
-#### Before
-```rust
-fn main() {
-  let x = 1 ┃+ 2;
-}
-```
-
-#### After
-```rust
-fn main() {
-  let x = 1.wrapping_add(2);
-}
-```
-
-
-### `replace_char_with_string`
-**Source:**  [replace_string_with_char.rs](crates/ide-assists/src/handlers/replace_string_with_char.rs#51) 
-
-Replace a char literal with a string literal.
-
-#### Before
-```rust
-fn main() {
-    find('{┃');
-}
-```
-
-#### After
-```rust
-fn main() {
-    find("{");
-}
-```
-
-
-### `replace_derive_with_manual_impl`
-**Source:**  [replace_derive_with_manual_impl.rs](crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs#20) 
-
-Converts a `derive` impl into a manual one.
-
-#### Before
-```rust
-#[derive(Deb┃ug, Display)]
-struct S;
-```
-
-#### After
-```rust
-#[derive(Display)]
-struct S;
-
-impl Debug for S {
-    ┃fn fmt(&self, f: &mut Formatter) -> Result<()> {
-        f.debug_struct("S").finish()
-    }
-}
-```
-
-
-### `replace_if_let_with_match`
-**Source:**  [replace_if_let_with_match.rs](crates/ide-assists/src/handlers/replace_if_let_with_match.rs#20) 
-
-Replaces a `if let` expression with a `match` expression.
-
-#### Before
-```rust
-enum Action { Move { distance: u32 }, Stop }
-
-fn handle(action: Action) {
-    ┃if let Action::Move { distance } = action {
-        foo(distance)
-    } else {
-        bar()
-    }
-}
-```
-
-#### After
-```rust
-enum Action { Move { distance: u32 }, Stop }
-
-fn handle(action: Action) {
-    match action {
-        Action::Move { distance } => foo(distance),
-        _ => bar(),
-    }
-}
-```
-
-
-### `replace_is_some_with_if_let_some`
-**Source:**  [replace_is_method_with_if_let_method.rs](crates/ide-assists/src/handlers/replace_is_method_with_if_let_method.rs#9) 
-
-Replace `if x.is_some()` with `if let Some(_tmp) = x` or `if x.is_ok()` with `if let Ok(_tmp) = x`.
-
-#### Before
-```rust
-fn main() {
-    let x = Some(1);
-    if x.is_som┃e() {}
-}
-```
-
-#### After
-```rust
-fn main() {
-    let x = Some(1);
-    if let Some(${0:x1}) = x {}
-}
-```
-
-
-### `replace_let_with_if_let`
-**Source:**  [replace_let_with_if_let.rs](crates/ide-assists/src/handlers/replace_let_with_if_let.rs#9) 
-
-Replaces `let` with an `if let`.
-
-#### Before
-```rust
-
-fn main(action: Action) {
-    ┃let x = compute();
-}
-
-fn compute() -> Option<i32> { None }
-```
-
-#### After
-```rust
-
-fn main(action: Action) {
-    if let Some(x) = compute() {
-    }
-}
-
-fn compute() -> Option<i32> { None }
-```
-
-
-### `replace_match_with_if_let`
-**Source:**  [replace_if_let_with_match.rs](crates/ide-assists/src/handlers/replace_if_let_with_match.rs#188) 
-
-Replaces a binary `match` with a wildcard pattern and no guards with an `if let` expression.
-
-#### Before
-```rust
-enum Action { Move { distance: u32 }, Stop }
-
-fn handle(action: Action) {
-    ┃match action {
-        Action::Move { distance } => foo(distance),
-        _ => bar(),
-    }
-}
-```
-
-#### After
-```rust
-enum Action { Move { distance: u32 }, Stop }
-
-fn handle(action: Action) {
-    if let Action::Move { distance } = action {
-        foo(distance)
-    } else {
-        bar()
-    }
-}
-```
-
-
-### `replace_named_generic_with_impl`
-**Source:**  [replace_named_generic_with_impl.rs](crates/ide-assists/src/handlers/replace_named_generic_with_impl.rs#18) 
-
-Replaces named generic with an `impl Trait` in function argument.
-
-#### Before
-```rust
-fn new<P┃: AsRef<Path>>(location: P) -> Self {}
-```
-
-#### After
-```rust
-fn new(location: impl AsRef<Path>) -> Self {}
-```
-
-
-### `replace_qualified_name_with_use`
-**Source:**  [replace_qualified_name_with_use.rs](crates/ide-assists/src/handlers/replace_qualified_name_with_use.rs#13) 
-
-Adds a use statement for a given fully-qualified name.
-
-#### Before
-```rust
-fn process(map: std::collections::┃HashMap<String, String>) {}
-```
-
-#### After
-```rust
-use std::collections::HashMap;
-
-fn process(map: HashMap<String, String>) {}
-```
-
-
-### `replace_string_with_char`
-**Source:**  [replace_string_with_char.rs](crates/ide-assists/src/handlers/replace_string_with_char.rs#11) 
-
-Replace string literal with char literal.
-
-#### Before
-```rust
-fn main() {
-    find("{┃");
-}
-```
-
-#### After
-```rust
-fn main() {
-    find('{');
-}
-```
-
-
-### `replace_try_expr_with_match`
-**Source:**  [replace_try_expr_with_match.rs](crates/ide-assists/src/handlers/replace_try_expr_with_match.rs#18) 
-
-Replaces a `try` expression with a `match` expression.
-
-#### Before
-```rust
-fn handle() {
-    let pat = Some(true)┃?;
-}
-```
-
-#### After
-```rust
-fn handle() {
-    let pat = match Some(true) {
-        Some(it) => it,
-        None => return None,
-    };
-}
-```
-
-
-### `replace_turbofish_with_explicit_type`
-**Source:**  [replace_turbofish_with_explicit_type.rs](crates/ide-assists/src/handlers/replace_turbofish_with_explicit_type.rs#12) 
-
-Converts `::<_>` to an explicit type assignment.
-
-#### Before
-```rust
-fn make<T>() -> T { ) }
-fn main() {
-    let a = make┃::<i32>();
-}
-```
-
-#### After
-```rust
-fn make<T>() -> T { ) }
-fn main() {
-    let a: i32 = make();
-}
-```
-
-
-### `replace_with_eager_method`
-**Source:**  [replace_method_eager_lazy.rs](crates/ide-assists/src/handlers/replace_method_eager_lazy.rs#89) 
-
-Replace `unwrap_or_else` with `unwrap_or` and `ok_or_else` with `ok_or`.
-
-#### Before
-```rust
-fn foo() {
-    let a = Some(1);
-    a.unwra┃p_or_else(|| 2);
-}
-```
-
-#### After
-```rust
-fn foo() {
-    let a = Some(1);
-    a.unwrap_or(2);
-}
-```
-
-
-### `replace_with_lazy_method`
-**Source:**  [replace_method_eager_lazy.rs](crates/ide-assists/src/handlers/replace_method_eager_lazy.rs#9) 
-
-Replace `unwrap_or` with `unwrap_or_else` and `ok_or` with `ok_or_else`.
-
-#### Before
-```rust
-fn foo() {
-    let a = Some(1);
-    a.unwra┃p_or(2);
-}
-```
-
-#### After
-```rust
-fn foo() {
-    let a = Some(1);
-    a.unwrap_or_else(|| 2);
-}
-```
-
-
-### `sort_items`
-**Source:**  [sort_items.rs](crates/ide-assists/src/handlers/sort_items.rs#12) 
-
-Sorts item members alphabetically: fields, enum variants and methods.
-
-#### Before
-```rust
-struct ┃Foo┃ { second: u32, first: String }
-```
-
-#### After
-```rust
-struct Foo { first: String, second: u32 }
-```
-
----
-
-#### Before
-```rust
-trait ┃Bar┃ {
-    fn second(&self) -> u32;
-    fn first(&self) -> String;
-}
-```
-
-#### After
-```rust
-trait Bar {
-    fn first(&self) -> String;
-    fn second(&self) -> u32;
-}
-```
-
----
-
-#### Before
-```rust
-struct Baz;
-impl ┃Baz┃ {
-    fn second(&self) -> u32;
-    fn first(&self) -> String;
-}
-```
-
-#### After
-```rust
-struct Baz;
-impl Baz {
-    fn first(&self) -> String;
-    fn second(&self) -> u32;
-}
-```
-
----
-There is a difference between sorting enum variants:
-
-#### Before
-```rust
-enum ┃Animal┃ {
-  Dog(String, f64),
-  Cat { weight: f64, name: String },
-}
-```
-
-#### After
-```rust
-enum Animal {
-  Cat { weight: f64, name: String },
-  Dog(String, f64),
-}
-```
-
-and sorting a single enum struct variant:
-
-#### Before
-```rust
-enum Animal {
-  Dog(String, f64),
-  Cat ┃{ weight: f64, name: String }┃,
-}
-```
-
-#### After
-```rust
-enum Animal {
-  Dog(String, f64),
-  Cat { name: String, weight: f64 },
-}
-```
-
-
-### `split_import`
-**Source:**  [split_import.rs](crates/ide-assists/src/handlers/split_import.rs#5) 
-
-Wraps the tail of import into braces.
-
-#### Before
-```rust
-use std::┃collections::HashMap;
-```
-
-#### After
-```rust
-use std::{collections::HashMap};
-```
-
-
-### `sugar_impl_future_into_async`
-**Source:**  [toggle_async_sugar.rs](crates/ide-assists/src/handlers/toggle_async_sugar.rs#13) 
-
-Rewrites asynchronous function from `-> impl Future` into `async fn`.
-This action does not touch the function body and therefore `async { 0 }`
-block does not transform to just `0`.
-
-#### Before
-```rust
-pub fn foo() -> impl core::future::F┃uture<Output = usize> {
-    async { 0 }
-}
-```
-
-#### After
-```rust
-pub async fn foo() -> usize {
-    async { 0 }
-}
-```
-
-
-### `toggle_ignore`
-**Source:**  [toggle_ignore.rs](crates/ide-assists/src/handlers/toggle_ignore.rs#8) 
-
-Adds `#[ignore]` attribute to the test.
-
-#### Before
-```rust
-┃#[test]
-fn arithmetics {
-    assert_eq!(2 + 2, 5);
-}
-```
-
-#### After
-```rust
-#[test]
-#[ignore]
-fn arithmetics {
-    assert_eq!(2 + 2, 5);
-}
-```
-
-
-### `toggle_macro_delimiter`
-**Source:**  [toggle_macro_delimiter.rs](crates/ide-assists/src/handlers/toggle_macro_delimiter.rs#9) 
-
-Change macro delimiters in the order of `( -> { -> [ -> (`.
-
-#### Before
-```rust
-macro_rules! sth {
-    () => {};
-}
-
-sth!┃( );
-```
-
-#### After
-```rust
-macro_rules! sth {
-    () => {};
-}
-
-sth!{ }
-```
-
-
-### `unmerge_match_arm`
-**Source:**  [unmerge_match_arm.rs](crates/ide-assists/src/handlers/unmerge_match_arm.rs#10) 
-
-Splits the current match with a `|` pattern into two arms with identical bodies.
-
-#### Before
-```rust
-enum Action { Move { distance: u32 }, Stop }
-
-fn handle(action: Action) {
-    match action {
-        Action::Move(..) ┃| Action::Stop => foo(),
-    }
-}
-```
-
-#### After
-```rust
-enum Action { Move { distance: u32 }, Stop }
-
-fn handle(action: Action) {
-    match action {
-        Action::Move(..) => foo(),
-        Action::Stop => foo(),
-    }
-}
-```
-
-
-### `unmerge_use`
-**Source:**  [unmerge_use.rs](crates/ide-assists/src/handlers/unmerge_use.rs#12) 
-
-Extracts single use item from use list.
-
-#### Before
-```rust
-use std::fmt::{Debug, Display┃};
-```
-
-#### After
-```rust
-use std::fmt::{Debug};
-use std::fmt::Display;
-```
-
-
-### `unnecessary_async`
-**Source:**  [unnecessary_async.rs](crates/ide-assists/src/handlers/unnecessary_async.rs#17) 
-
-Removes the `async` mark from functions which have no `.await` in their body.
-Looks for calls to the functions and removes the `.await` on the call site.
-
-#### Before
-```rust
-pub asy┃nc fn foo() {}
-pub async fn bar() { foo().await }
-```
-
-#### After
-```rust
-pub fn foo() {}
-pub async fn bar() { foo() }
-```
-
-
-### `unqualify_method_call`
-**Source:**  [unqualify_method_call.rs](crates/ide-assists/src/handlers/unqualify_method_call.rs#9) 
-
-Transforms universal function call syntax into a method call.
-
-#### Before
-```rust
-fn main() {
-    std::ops::Add::add┃(1, 2);
-}
-```
-
-#### After
-```rust
-use std::ops::Add;
-
-fn main() {
-    1.add(2);
-}
-```
-
-
-### `unwrap_block`
-**Source:**  [unwrap_block.rs](crates/ide-assists/src/handlers/unwrap_block.rs#12) 
-
-This assist removes if...else, for, while and loop control statements to just keep the body.
-
-#### Before
-```rust
-fn foo() {
-    if true {┃
-        println!("foo");
-    }
-}
-```
-
-#### After
-```rust
-fn foo() {
-    println!("foo");
-}
-```
-
-
-### `unwrap_option_return_type`
-**Source:**  [unwrap_return_type.rs](crates/ide-assists/src/handlers/unwrap_return_type.rs#13) 
-
-Unwrap the function's return type.
-
-#### Before
-```rust
-fn foo() -> Option<i32>┃ { Some(42i32) }
-```
-
-#### After
-```rust
-fn foo() -> i32 { 42i32 }
-```
-
-
-### `unwrap_result_return_type`
-**Source:**  [unwrap_return_type.rs](crates/ide-assists/src/handlers/unwrap_return_type.rs#26) 
-
-Unwrap the function's return type.
-
-#### Before
-```rust
-fn foo() -> Result<i32>┃ { Ok(42i32) }
-```
-
-#### After
-```rust
-fn foo() -> i32 { 42i32 }
-```
-
-
-### `unwrap_tuple`
-**Source:**  [unwrap_tuple.rs](crates/ide-assists/src/handlers/unwrap_tuple.rs#8) 
-
-Unwrap the tuple to different variables.
-
-#### Before
-```rust
-fn main() {
-    ┃let (foo, bar) = ("Foo", "Bar");
-}
-```
-
-#### After
-```rust
-fn main() {
-    let foo = "Foo";
-    let bar = "Bar";
-}
-```
-
-
-### `wrap_return_type_in_option`
-**Source:**  [wrap_return_type.rs](crates/ide-assists/src/handlers/wrap_return_type.rs#16) 
-
-Wrap the function's return type into Option.
-
-#### Before
-```rust
-fn foo() -> i32┃ { 42i32 }
-```
-
-#### After
-```rust
-fn foo() -> Option<i32> { Some(42i32) }
-```
-
-
-### `wrap_return_type_in_result`
-**Source:**  [wrap_return_type.rs](crates/ide-assists/src/handlers/wrap_return_type.rs#29) 
-
-Wrap the function's return type into Result.
-
-#### Before
-```rust
-fn foo() -> i32┃ { 42i32 }
-```
-
-#### After
-```rust
-fn foo() -> Result<i32, ${0:_}> { Ok(42i32) }
-```
-
-
-### `wrap_unwrap_cfg_attr`
-**Source:**  [wrap_unwrap_cfg_attr.rs](crates/ide-assists/src/handlers/wrap_unwrap_cfg_attr.rs#12) 
-
-Wraps an attribute to a cfg_attr attribute or unwraps a cfg_attr attribute to the inner attributes.
-
-#### Before
-```rust
-#[derive┃(Debug)]
-struct S {
-   field: i32
-}
-```
-
-#### After
-```rust
-#[cfg_attr(┃, derive(Debug))]
-struct S {
-   field: i32
-}
-```
diff --git a/docs/book/src/diagnostics_generated.md b/docs/book/src/diagnostics_generated.md
deleted file mode 100644
index d34c459ad0..0000000000
--- a/docs/book/src/diagnostics_generated.md
+++ /dev/null
@@ -1,516 +0,0 @@
-//! Generated by `cargo xtask codegen diagnostics-docs`, do not edit by hand.
-
-#### attribute-expansion-disabled
-
-Source:  [macro_error.rs](crates/ide-diagnostics/src/handlers/macro_error.rs#7) 
-
-
-This diagnostic is shown for attribute proc macros when attribute expansions have been disabled.
-
-
-
-
-#### await-outside-of-async
-
-Source:  [await_outside_of_async.rs](crates/ide-diagnostics/src/handlers/await_outside_of_async.rs#3) 
-
-
-This diagnostic is triggered if the `await` keyword is used outside of an async function or block
-
-
-
-
-#### break-outside-of-loop
-
-Source:  [break_outside_of_loop.rs](crates/ide-diagnostics/src/handlers/break_outside_of_loop.rs#3) 
-
-
-This diagnostic is triggered if the `break` keyword is used outside of a loop.
-
-
-
-
-#### cast-to-unsized
-
-Source:  [invalid_cast.rs](crates/ide-diagnostics/src/handlers/invalid_cast.rs#106) 
-
-
-This diagnostic is triggered when casting to an unsized type
-
-
-
-
-#### expected-function
-
-Source:  [expected_function.rs](crates/ide-diagnostics/src/handlers/expected_function.rs#5) 
-
-
-This diagnostic is triggered if a call is made on something that is not callable.
-
-
-
-
-#### generic-args-prohibited
-
-Source:  [generic_args_prohibited.rs](crates/ide-diagnostics/src/handlers/generic_args_prohibited.rs#10) 
-
-
-This diagnostic is shown when generic arguments are provided for a type that does not accept
-generic arguments.
-
-
-
-
-#### inactive-code
-
-Source:  [inactive_code.rs](crates/ide-diagnostics/src/handlers/inactive_code.rs#6) 
-
-
-This diagnostic is shown for code with inactive `#[cfg]` attributes.
-
-
-
-
-#### incoherent-impl
-
-Source:  [incoherent_impl.rs](crates/ide-diagnostics/src/handlers/incoherent_impl.rs#6) 
-
-
-This diagnostic is triggered if the targe type of an impl is from a foreign crate.
-
-
-
-
-#### incorrect-ident-case
-
-Source:  [incorrect_case.rs](crates/ide-diagnostics/src/handlers/incorrect_case.rs#13) 
-
-
-This diagnostic is triggered if an item name doesn't follow [Rust naming convention](https://doc.rust-lang.org/1.0.0/style/style/naming/README.html).
-
-
-
-
-#### invalid-cast
-
-Source:  [invalid_cast.rs](crates/ide-diagnostics/src/handlers/invalid_cast.rs#18) 
-
-
-This diagnostic is triggered if the code contains an illegal cast
-
-
-
-
-#### invalid-derive-target
-
-Source:  [invalid_derive_target.rs](crates/ide-diagnostics/src/handlers/invalid_derive_target.rs#3) 
-
-
-This diagnostic is shown when the derive attribute is used on an item other than a `struct`,
-`enum` or `union`.
-
-
-
-
-#### macro-def-error
-
-Source:  [macro_error.rs](crates/ide-diagnostics/src/handlers/macro_error.rs#24) 
-
-
-This diagnostic is shown for macro expansion errors.
-
-
-
-
-#### macro-error
-
-Source:  [macro_error.rs](crates/ide-diagnostics/src/handlers/macro_error.rs#3) 
-
-
-This diagnostic is shown for macro expansion errors.
-
-
-
-
-#### malformed-derive
-
-Source:  [malformed_derive.rs](crates/ide-diagnostics/src/handlers/malformed_derive.rs#3) 
-
-
-This diagnostic is shown when the derive attribute has invalid input.
-
-
-
-
-#### mismatched-arg-count
-
-Source:  [mismatched_arg_count.rs](crates/ide-diagnostics/src/handlers/mismatched_arg_count.rs#31) 
-
-
-This diagnostic is triggered if a function is invoked with an incorrect amount of arguments.
-
-
-
-
-#### mismatched-tuple-struct-pat-arg-count
-
-Source:  [mismatched_arg_count.rs](crates/ide-diagnostics/src/handlers/mismatched_arg_count.rs#11) 
-
-
-This diagnostic is triggered if a function is invoked with an incorrect amount of arguments.
-
-
-
-
-#### missing-fields
-
-Source:  [missing_fields.rs](crates/ide-diagnostics/src/handlers/missing_fields.rs#19) 
-
-
-This diagnostic is triggered if record lacks some fields that exist in the corresponding structure.
-
-Example:
-
-```rust
-struct A { a: u8, b: u8 }
-
-let a = A { a: 10 };
-```
-
-
-
-
-#### missing-match-arm
-
-Source:  [missing_match_arms.rs](crates/ide-diagnostics/src/handlers/missing_match_arms.rs#3) 
-
-
-This diagnostic is triggered if `match` block is missing one or more match arms.
-
-
-
-
-#### missing-unsafe
-
-Source:  [missing_unsafe.rs](crates/ide-diagnostics/src/handlers/missing_unsafe.rs#10) 
-
-
-This diagnostic is triggered if an operation marked as `unsafe` is used outside of an `unsafe` function or block.
-
-
-
-
-#### moved-out-of-ref
-
-Source:  [moved_out_of_ref.rs](crates/ide-diagnostics/src/handlers/moved_out_of_ref.rs#4) 
-
-
-This diagnostic is triggered on moving non copy things out of references.
-
-
-
-
-#### need-mut
-
-Source:  [mutability_errors.rs](crates/ide-diagnostics/src/handlers/mutability_errors.rs#8) 
-
-
-This diagnostic is triggered on mutating an immutable variable.
-
-
-
-
-#### no-such-field
-
-Source:  [no_such_field.rs](crates/ide-diagnostics/src/handlers/no_such_field.rs#12) 
-
-
-This diagnostic is triggered if created structure does not have field provided in record.
-
-
-
-
-#### non-exhaustive-let
-
-Source:  [non_exhaustive_let.rs](crates/ide-diagnostics/src/handlers/non_exhaustive_let.rs#3) 
-
-
-This diagnostic is triggered if a `let` statement without an `else` branch has a non-exhaustive
-pattern.
-
-
-
-
-#### private-assoc-item
-
-Source:  [private_assoc_item.rs](crates/ide-diagnostics/src/handlers/private_assoc_item.rs#3) 
-
-
-This diagnostic is triggered if the referenced associated item is not visible from the current
-module.
-
-
-
-
-#### private-field
-
-Source:  [private_field.rs](crates/ide-diagnostics/src/handlers/private_field.rs#3) 
-
-
-This diagnostic is triggered if the accessed field is not visible from the current module.
-
-
-
-
-#### proc-macro-disabled
-
-Source:  [macro_error.rs](crates/ide-diagnostics/src/handlers/macro_error.rs#11) 
-
-
-This diagnostic is shown for proc macros that have been specifically disabled via `rust-analyzer.procMacro.ignored`.
-
-
-
-
-#### remove-trailing-return
-
-Source:  [remove_trailing_return.rs](crates/ide-diagnostics/src/handlers/remove_trailing_return.rs#8) 
-
-
-This diagnostic is triggered when there is a redundant `return` at the end of a function
-or closure.
-
-
-
-
-#### remove-unnecessary-else
-
-Source:  [remove_unnecessary_else.rs](crates/ide-diagnostics/src/handlers/remove_unnecessary_else.rs#17) 
-
-
-This diagnostic is triggered when there is an `else` block for an `if` expression whose
-then branch diverges (e.g. ends with a `return`, `continue`, `break` e.t.c).
-
-
-
-
-#### replace-filter-map-next-with-find-map
-
-Source:  [replace_filter_map_next_with_find_map.rs](crates/ide-diagnostics/src/handlers/replace_filter_map_next_with_find_map.rs#11) 
-
-
-This diagnostic is triggered when `.filter_map(..).next()` is used, rather than the more concise `.find_map(..)`.
-
-
-
-
-#### trait-impl-incorrect-safety
-
-Source:  [trait_impl_incorrect_safety.rs](crates/ide-diagnostics/src/handlers/trait_impl_incorrect_safety.rs#6) 
-
-
-Diagnoses incorrect safety annotations of trait impls.
-
-
-
-
-#### trait-impl-missing-assoc_item
-
-Source:  [trait_impl_missing_assoc_item.rs](crates/ide-diagnostics/src/handlers/trait_impl_missing_assoc_item.rs#7) 
-
-
-Diagnoses missing trait items in a trait impl.
-
-
-
-
-#### trait-impl-orphan
-
-Source:  [trait_impl_orphan.rs](crates/ide-diagnostics/src/handlers/trait_impl_orphan.rs#5) 
-
-
-Only traits defined in the current crate can be implemented for arbitrary types
-
-
-
-
-#### trait-impl-redundant-assoc_item
-
-Source:  [trait_impl_redundant_assoc_item.rs](crates/ide-diagnostics/src/handlers/trait_impl_redundant_assoc_item.rs#12) 
-
-
-Diagnoses redundant trait items in a trait impl.
-
-
-
-
-#### type-mismatch
-
-Source:  [type_mismatch.rs](crates/ide-diagnostics/src/handlers/type_mismatch.rs#20) 
-
-
-This diagnostic is triggered when the type of an expression or pattern does not match
-the expected type.
-
-
-
-
-#### typed-hole
-
-Source:  [typed_hole.rs](crates/ide-diagnostics/src/handlers/typed_hole.rs#18) 
-
-
-This diagnostic is triggered when an underscore expression is used in an invalid position.
-
-
-
-
-#### undeclared-label
-
-Source:  [undeclared_label.rs](crates/ide-diagnostics/src/handlers/undeclared_label.rs#3) 
-
-
-
-
-
-
-#### unimplemented-builtin-macro
-
-Source:  [unimplemented_builtin_macro.rs](crates/ide-diagnostics/src/handlers/unimplemented_builtin_macro.rs#3) 
-
-
-This diagnostic is shown for builtin macros which are not yet implemented by rust-analyzer
-
-
-
-
-#### unlinked-file
-
-Source:  [unlinked_file.rs](crates/ide-diagnostics/src/handlers/unlinked_file.rs#20) 
-
-
-This diagnostic is shown for files that are not included in any crate, or files that are part of
-crates rust-analyzer failed to discover. The file will not have IDE features available.
-
-
-
-
-#### unnecessary-braces
-
-Source:  [useless_braces.rs](crates/ide-diagnostics/src/handlers/useless_braces.rs#9) 
-
-
-Diagnostic for unnecessary braces in `use` items.
-
-
-
-
-#### unreachable-label
-
-Source:  [unreachable_label.rs](crates/ide-diagnostics/src/handlers/unreachable_label.rs#3) 
-
-
-
-
-
-
-#### unresolved-assoc-item
-
-Source:  [unresolved_assoc_item.rs](crates/ide-diagnostics/src/handlers/unresolved_assoc_item.rs#3) 
-
-
-This diagnostic is triggered if the referenced associated item does not exist.
-
-
-
-
-#### unresolved-extern-crate
-
-Source:  [unresolved_extern_crate.rs](crates/ide-diagnostics/src/handlers/unresolved_extern_crate.rs#3) 
-
-
-This diagnostic is triggered if rust-analyzer is unable to discover referred extern crate.
-
-
-
-
-#### unresolved-field
-
-Source:  [unresolved_field.rs](crates/ide-diagnostics/src/handlers/unresolved_field.rs#23) 
-
-
-This diagnostic is triggered if a field does not exist on a given type.
-
-
-
-
-#### unresolved-ident
-
-Source:  [unresolved_ident.rs](crates/ide-diagnostics/src/handlers/unresolved_ident.rs#3) 
-
-
-This diagnostic is triggered if an expr-position ident is invalid.
-
-
-
-
-#### unresolved-import
-
-Source:  [unresolved_import.rs](crates/ide-diagnostics/src/handlers/unresolved_import.rs#3) 
-
-
-This diagnostic is triggered if rust-analyzer is unable to resolve a path in
-a `use` declaration.
-
-
-
-
-#### unresolved-macro-call
-
-Source:  [unresolved_macro_call.rs](crates/ide-diagnostics/src/handlers/unresolved_macro_call.rs#3) 
-
-
-This diagnostic is triggered if rust-analyzer is unable to resolve the path
-to a macro in a macro invocation.
-
-
-
-
-#### unresolved-method
-
-Source:  [unresolved_method.rs](crates/ide-diagnostics/src/handlers/unresolved_method.rs#15) 
-
-
-This diagnostic is triggered if a method does not exist on a given type.
-
-
-
-
-#### unresolved-module
-
-Source:  [unresolved_module.rs](crates/ide-diagnostics/src/handlers/unresolved_module.rs#8) 
-
-
-This diagnostic is triggered if rust-analyzer is unable to discover referred module.
-
-
-
-
-#### unused-mut
-
-Source:  [mutability_errors.rs](crates/ide-diagnostics/src/handlers/mutability_errors.rs#62) 
-
-
-This diagnostic is triggered when a mutable variable isn't actually mutated.
-
-
-
-
-#### unused-variables
-
-Source:  [unused_variables.rs](crates/ide-diagnostics/src/handlers/unused_variables.rs#13) 
-
-
-This diagnostic is triggered when a local variable is not used.
-
-
diff --git a/docs/book/src/features_generated.md b/docs/book/src/features_generated.md
deleted file mode 100644
index 2c5829b1f5..0000000000
--- a/docs/book/src/features_generated.md
+++ /dev/null
@@ -1,940 +0,0 @@
-//! Generated by `cargo xtask codegen feature-docs`, do not edit by hand.
-
-### Annotations
-**Source:**  [annotations.rs](crates/ide/src/annotations.rs#19) 
-
-Provides user with annotations above items for looking up references or impl blocks
-and running/debugging binaries.
-
-![Annotations](https://user-images.githubusercontent.com/48062697/113020672-b7c34f00-917a-11eb-8f6e-858735660a0e.png)
-
-
-### Auto Import
-**Source:**  [auto_import.rs](crates/ide-assists/src/handlers/auto_import.rs#15) 
-
-Using the `auto-import` assist it is possible to insert missing imports for unresolved items.
-When inserting an import it will do so in a structured manner by keeping imports grouped,
-separated by a newline in the following order:
-
-- `std` and `core`
-- External Crates
-- Current Crate, paths prefixed by `crate`
-- Current Module, paths prefixed by `self`
-- Super Module, paths prefixed by `super`
-
-Example:
-```rust
-use std::fs::File;
-
-use itertools::Itertools;
-use syntax::ast;
-
-use crate::utils::insert_use;
-
-use self::auto_import;
-
-use super::AssistContext;
-```
-
-#### Import Granularity
-
-It is possible to configure how use-trees are merged with the `imports.granularity.group` setting.
-It has the following configurations:
-
-- `crate`: Merge imports from the same crate into a single use statement. This kind of
- nesting is only supported in Rust versions later than 1.24.
-- `module`: Merge imports from the same module into a single use statement.
-- `item`: Don't merge imports at all, creating one import per item.
-- `preserve`: Do not change the granularity of any imports. For auto-import this has the same
- effect as `item`.
-- `one`: Merge all imports into a single use statement as long as they have the same visibility
- and attributes.
-
-In `VS Code` the configuration for this is `rust-analyzer.imports.granularity.group`.
-
-#### Import Prefix
-
-The style of imports in the same crate is configurable through the `imports.prefix` setting.
-It has the following configurations:
-
-- `crate`: This setting will force paths to be always absolute, starting with the `crate`
- prefix, unless the item is defined outside of the current crate.
-- `self`: This setting will force paths that are relative to the current module to always
- start with `self`. This will result in paths that always start with either `crate`, `self`,
- `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`.
-
-![Auto Import](https://user-images.githubusercontent.com/48062697/113020673-b85be580-917a-11eb-9022-59585f35d4f8.gif)
-
-
-### Completion With Autoimport
-**Source:**  [flyimport.rs](crates/ide-completion/src/completions/flyimport.rs#20) 
-
-When completing names in the current scope, proposes additional imports from other modules or crates,
-if they can be qualified in the scope, and their name contains all symbols from the completion input.
-
-To be considered applicable, the name must contain all input symbols in the given order, not necessarily adjacent.
-If any input symbol is not lowercased, the name must contain all symbols in exact case; otherwise the containing is checked case-insensitively.
-
-```
-fn main() {
-    pda$0
-}
-# pub mod std { pub mod marker { pub struct PhantomData { } } }
-```
-->
-```
-use std::marker::PhantomData;
-
-fn main() {
-    PhantomData
-}
-# pub mod std { pub mod marker { pub struct PhantomData { } } }
-```
-
-Also completes associated items, that require trait imports.
-If any unresolved and/or partially-qualified path precedes the input, it will be taken into account.
-Currently, only the imports with their import path ending with the whole qualifier will be proposed
-(no fuzzy matching for qualifier).
-
-```
-mod foo {
-    pub mod bar {
-        pub struct Item;
-
-        impl Item {
-            pub const TEST_ASSOC: usize = 3;
-        }
-    }
-}
-
-fn main() {
-    bar::Item::TEST_A$0
-}
-```
-->
-```
-use foo::bar;
-
-mod foo {
-    pub mod bar {
-        pub struct Item;
-
-        impl Item {
-            pub const TEST_ASSOC: usize = 3;
-        }
-    }
-}
-
-fn main() {
-    bar::Item::TEST_ASSOC
-}
-```
-
-NOTE: currently, if an assoc item comes from a trait that's not currently imported, and it also has an unresolved and/or partially-qualified path,
-no imports will be proposed.
-
-#### Fuzzy search details
-
-To avoid an excessive amount of the results returned, completion input is checked for inclusion in the names only
-(i.e. in `HashMap` in the `std::collections::HashMap` path).
-For the same reasons, avoids searching for any path imports for inputs with their length less than 2 symbols
-(but shows all associated items for any input length).
-
-#### Import configuration
-
-It is possible to configure how use-trees are merged with the `imports.granularity.group` setting.
-Mimics the corresponding behavior of the `Auto Import` feature.
-
-#### LSP and performance implications
-
-The feature is enabled only if the LSP client supports LSP protocol version 3.16+ and reports the `additionalTextEdits`
-(case-sensitive) resolve client capability in its client capabilities.
-This way the server is able to defer the costly computations, doing them for a selected completion item only.
-For clients with no such support, all edits have to be calculated on the completion request, including the fuzzy search completion ones,
-which might be slow ergo the feature is automatically disabled.
-
-#### Feature toggle
-
-The feature can be forcefully turned off in the settings with the `rust-analyzer.completion.autoimport.enable` flag.
-Note that having this flag set to `true` does not guarantee that the feature is enabled: your client needs to have the corresponding
-capability enabled.
-
-
-### Debug ItemTree
-**Source:**  [view_item_tree.rs](crates/ide/src/view_item_tree.rs#5) 
-
-Displays the ItemTree of the currently open file, for debugging.
-
-| Editor  | Action Name |
-|---------|-------------|
-| VS Code | **rust-analyzer: Debug ItemTree** |
-
-
-### Expand Macro Recursively
-**Source:**  [expand_macro.rs](crates/ide/src/expand_macro.rs#18) 
-
-Shows the full macro expansion of the macro at the current caret position.
-
-| Editor  | Action Name |
-|---------|-------------|
-| VS Code | **rust-analyzer: Expand macro recursively at caret** |
-
-![Expand Macro Recursively](https://user-images.githubusercontent.com/48062697/113020648-b3973180-917a-11eb-84a9-ecb921293dc5.gif)
-
-
-### Expand and Shrink Selection
-**Source:**  [extend_selection.rs](crates/ide/src/extend_selection.rs#15) 
-
-Extends or shrinks the current selection to the encompassing syntactic construct
-(expression, statement, item, module, etc). It works with multiple cursors.
-
-| Editor  | Shortcut |
-|---------|----------|
-| VS Code | <kbd>Alt+Shift+→</kbd>, <kbd>Alt+Shift+←</kbd> |
-
-![Expand and Shrink Selection](https://user-images.githubusercontent.com/48062697/113020651-b42fc800-917a-11eb-8a4f-cf1a07859fac.gif)
-
-
-### File Structure
-**Source:**  [file_structure.rs](crates/ide/src/file_structure.rs#26) 
-
-Provides a tree of the symbols defined in the file. Can be used to
-
-* fuzzy search symbol in a file (super useful)
-* draw breadcrumbs to describe the context around the cursor
-* draw outline of the file
-
-| Editor  | Shortcut |
-|---------|----------|
-| VS Code | <kbd>Ctrl+Shift+O</kbd> |
-
-![File Structure](https://user-images.githubusercontent.com/48062697/113020654-b42fc800-917a-11eb-8388-e7dc4d92b02e.gif)
-
-
-### Find All References
-**Source:**  [references.rs](crates/ide/src/references.rs#42) 
-
-Shows all references of the item at the cursor location
-
-| Editor  | Shortcut |
-|---------|----------|
-| VS Code | <kbd>Shift+Alt+F12</kbd> |
-
-![Find All References](https://user-images.githubusercontent.com/48062697/113020670-b7c34f00-917a-11eb-8003-370ac5f2b3cb.gif)
-
-
-### Folding
-**Source:**  [folding_ranges.rs](crates/ide/src/folding_ranges.rs#36) 
-
-Defines folding regions for curly braced blocks, runs of consecutive use, mod, const or static
-items, and `region` / `endregion` comment markers.
-
-
-### Format String Completion
-**Source:**  [format_like.rs](crates/ide-completion/src/completions/postfix/format_like.rs#0) 
-
-`"Result {result} is {2 + 2}"` is expanded to the `"Result {} is {}", result, 2 + 2`.
-
-The following postfix snippets are available:
-
-* `format` -> `format!(...)`
-* `panic` -> `panic!(...)`
-* `println` -> `println!(...)`
-* `log`:
-** `logd` -> `log::debug!(...)`
-** `logt` -> `log::trace!(...)`
-** `logi` -> `log::info!(...)`
-** `logw` -> `log::warn!(...)`
-** `loge` -> `log::error!(...)`
-
-![Format String Completion](https://user-images.githubusercontent.com/48062697/113020656-b560f500-917a-11eb-87de-02991f61beb8.gif)
-
-
-### Go to Declaration
-**Source:**  [goto_declaration.rs](crates/ide/src/goto_declaration.rs#13) 
-
-Navigates to the declaration of an identifier.
-
-This is the same as `Go to Definition` with the following exceptions:
-- outline modules will navigate to the `mod name;` item declaration
-- trait assoc items will navigate to the assoc item of the trait declaration as opposed to the trait impl
-- fields in patterns will navigate to the field declaration of the struct, union or variant
-
-
-### Go to Definition
-**Source:**  [goto_definition.rs](crates/ide/src/goto_definition.rs#28) 
-
-Navigates to the definition of an identifier.
-
-For outline modules, this will navigate to the source file of the module.
-
-| Editor  | Shortcut |
-|---------|----------|
-| VS Code | <kbd>F12</kbd> |
-
-![Go to Definition](https://user-images.githubusercontent.com/48062697/113065563-025fbe00-91b1-11eb-83e4-a5a703610b23.gif)
-
-
-### Go to Implementation
-**Source:**  [goto_implementation.rs](crates/ide/src/goto_implementation.rs#11) 
-
-Navigates to the impl items of types.
-
-| Editor  | Shortcut |
-|---------|----------|
-| VS Code | <kbd>Ctrl+F12</kbd>
-
-![Go to Implementation](https://user-images.githubusercontent.com/48062697/113065566-02f85480-91b1-11eb-9288-aaad8abd8841.gif)
-
-
-### Go to Type Definition
-**Source:**  [goto_type_definition.rs](crates/ide/src/goto_type_definition.rs#7) 
-
-Navigates to the type of an identifier.
-
-| Editor  | Action Name |
-|---------|-------------|
-| VS Code | **Go to Type Definition** |
-
-![Go to Type Definition](https://user-images.githubusercontent.com/48062697/113020657-b560f500-917a-11eb-9007-0f809733a338.gif)
-
-
-### Highlight Related
-**Source:**  [highlight_related.rs](crates/ide/src/highlight_related.rs#42) 
-
-Highlights constructs related to the thing under the cursor:
-
-1. if on an identifier, highlights all references to that identifier in the current file
-     * additionally, if the identifier is a trait in a where clause, type parameter trait bound or use item, highlights all references to that trait's assoc items in the corresponding scope
-1. if on an `async` or `await` token, highlights all yield points for that async context
-1. if on a `return` or `fn` keyword, `?` character or `->` return type arrow, highlights all exit points for that context
-1. if on a `break`, `loop`, `while` or `for` token, highlights all break points for that loop or block context
-1. if on a `move` or `|` token that belongs to a closure, highlights all captures of the closure.
-
-Note: `?`, `|` and `->` do not currently trigger this behavior in the VSCode editor.
-
-
-### Hover
-**Source:**  [hover.rs](crates/ide/src/hover.rs#116) 
-
-Shows additional information, like the type of an expression or the documentation for a definition when "focusing" code.
-Focusing is usually hovering with a mouse, but can also be triggered with a shortcut.
-
-![Hover](https://user-images.githubusercontent.com/48062697/113020658-b5f98b80-917a-11eb-9f88-3dbc27320c95.gif)
-
-
-### Inlay Hints
-**Source:**  [inlay_hints.rs](crates/ide/src/inlay_hints.rs#41) 
-
-rust-analyzer shows additional information inline with the source code.
-Editors usually render this using read-only virtual text snippets interspersed with code.
-
-rust-analyzer by default shows hints for
-
-* types of local variables
-* names of function arguments
-* names of const generic parameters
-* types of chained expressions
-
-Optionally, one can enable additional hints for
-
-* return types of closure expressions
-* elided lifetimes
-* compiler inserted reborrows
-* names of generic type and lifetime parameters
-
-Note: inlay hints for function argument names are heuristically omitted to reduce noise and will not appear if
-any of the
-[following criteria](https://github.com/rust-lang/rust-analyzer/blob/6b8b8ff4c56118ddee6c531cde06add1aad4a6af/crates/ide/src/inlay_hints/param_name.rs#L92-L99)
-are met:
-
-* the parameter name is a suffix of the function's name
-* the argument is a qualified constructing or call expression where the qualifier is an ADT
-* exact argument<->parameter match(ignoring leading underscore) or parameter is a prefix/suffix
-  of argument with _ splitting it off
-* the parameter name starts with `ra_fixture`
-* the parameter name is a
-[well known name](https://github.com/rust-lang/rust-analyzer/blob/6b8b8ff4c56118ddee6c531cde06add1aad4a6af/crates/ide/src/inlay_hints/param_name.rs#L200)
-in a unary function
-* the parameter name is a
-[single character](https://github.com/rust-lang/rust-analyzer/blob/6b8b8ff4c56118ddee6c531cde06add1aad4a6af/crates/ide/src/inlay_hints/param_name.rs#L201)
-in a unary function
-
-![Inlay hints](https://user-images.githubusercontent.com/48062697/113020660-b5f98b80-917a-11eb-8d70-3be3fd558cdd.png)
-
-
-### Interpret A Function, Static Or Const.
-**Source:**  [interpret.rs](crates/ide/src/interpret.rs#8) 
-
-| Editor  | Action Name |
-|---------|-------------|
-| VS Code | **rust-analyzer: Interpret** |
-
-
-### Join Lines
-**Source:**  [join_lines.rs](crates/ide/src/join_lines.rs#20) 
-
-Join selected lines into one, smartly fixing up whitespace, trailing commas, and braces.
-
-See [this gif](https://user-images.githubusercontent.com/1711539/124515923-4504e800-dde9-11eb-8d58-d97945a1a785.gif) for the cases handled specially by joined lines.
-
-| Editor  | Action Name |
-|---------|-------------|
-| VS Code | **rust-analyzer: Join lines** |
-
-![Join Lines](https://user-images.githubusercontent.com/48062697/113020661-b6922200-917a-11eb-87c4-b75acc028f11.gif)
-
-
-### Magic Completions
-**Source:**  [lib.rs](crates/ide-completion/src/lib.rs#78) 
-
-In addition to usual reference completion, rust-analyzer provides some ✨magic✨
-completions as well:
-
-Keywords like `if`, `else` `while`, `loop` are completed with braces, and cursor
-is placed at the appropriate position. Even though `if` is easy to type, you
-still want to complete it, to get ` { }` for free! `return` is inserted with a
-space or `;` depending on the return type of the function.
-
-When completing a function call, `()` are automatically inserted. If a function
-takes arguments, the cursor is positioned inside the parenthesis.
-
-There are postfix completions, which can be triggered by typing something like
-`foo().if`. The word after `.` determines postfix completion. Possible variants are:
-
-- `expr.if` -> `if expr {}` or `if let ... {}` for `Option` or `Result`
-- `expr.match` -> `match expr {}`
-- `expr.while` -> `while expr {}` or `while let ... {}` for `Option` or `Result`
-- `expr.ref` -> `&expr`
-- `expr.refm` -> `&mut expr`
-- `expr.let` -> `let $0 = expr;`
-- `expr.lete` -> `let $1 = expr else { $0 };`
-- `expr.letm` -> `let mut $0 = expr;`
-- `expr.not` -> `!expr`
-- `expr.dbg` -> `dbg!(expr)`
-- `expr.dbgr` -> `dbg!(&expr)`
-- `expr.call` -> `(expr)`
-
-There also snippet completions:
-
-#### Expressions
-
-- `pd` -> `eprintln!(" = {:?}", );`
-- `ppd` -> `eprintln!(" = {:#?}", );`
-
-#### Items
-
-- `tfn` -> `#[test] fn feature(){}`
-- `tmod` ->
-```rust
-#[cfg(test)]
-mod tests {
-    use super::*;
-
-    #[test]
-    fn test_name() {}
-}
-```
-
-And the auto import completions, enabled with the `rust-analyzer.completion.autoimport.enable` setting and the corresponding LSP client capabilities.
-Those are the additional completion options with automatic `use` import and options from all project importable items,
-fuzzy matched against the completion input.
-
-![Magic Completions](https://user-images.githubusercontent.com/48062697/113020667-b72ab880-917a-11eb-8778-716cf26a0eb3.gif)
-
-
-### Matching Brace
-**Source:**  [matching_brace.rs](crates/ide/src/matching_brace.rs#6) 
-
-If the cursor is on any brace (`<>(){}[]||`) which is a part of a brace-pair,
-moves cursor to the matching brace. It uses the actual parser to determine
-braces, so it won't confuse generics with comparisons.
-
-| Editor  | Action Name |
-|---------|-------------|
-| VS Code | **rust-analyzer: Find matching brace** |
-
-![Matching Brace](https://user-images.githubusercontent.com/48062697/113065573-04298180-91b1-11eb-8dec-d4e2a202f304.gif)
-
-
-### Memory Usage
-**Source:**  [apply_change.rs](crates/ide-db/src/apply_change.rs#43) 
-
-Clears rust-analyzer's internal database and prints memory usage statistics.
-
-| Editor  | Action Name |
-|---------|-------------|
-| VS Code | **rust-analyzer: Memory Usage (Clears Database)**
-
-
-### Move Item
-**Source:**  [move_item.rs](crates/ide/src/move_item.rs#16) 
-
-Move item under cursor or selection up and down.
-
-| Editor  | Action Name |
-|---------|-------------|
-| VS Code | **rust-analyzer: Move item up**
-| VS Code | **rust-analyzer: Move item down**
-
-![Move Item](https://user-images.githubusercontent.com/48062697/113065576-04298180-91b1-11eb-91ce-4505e99ed598.gif)
-
-
-### On Enter
-**Source:**  [on_enter.rs](crates/ide/src/typing/on_enter.rs#17) 
-
-rust-analyzer can override <kbd>Enter</kbd> key to make it smarter:
-
-- <kbd>Enter</kbd> inside triple-slash comments automatically inserts `///`
-- <kbd>Enter</kbd> in the middle or after a trailing space in `//` inserts `//`
-- <kbd>Enter</kbd> inside `//!` doc comments automatically inserts `//!`
-- <kbd>Enter</kbd> after `{` indents contents and closing `}` of single-line block
-
-This action needs to be assigned to shortcut explicitly.
-
-Note that, depending on the other installed extensions, this feature can visibly slow down typing.
-Similarly, if rust-analyzer crashes or stops responding, `Enter` might not work.
-In that case, you can still press `Shift-Enter` to insert a newline.
-
-#### VS Code
-
-Add the following to `keybindings.json`:
-```json
-{
-  "key": "Enter",
-  "command": "rust-analyzer.onEnter",
-  "when": "editorTextFocus && !suggestWidgetVisible && editorLangId == rust"
-}
-````
-
-When using the Vim plugin:
-```json
-{
-  "key": "Enter",
-  "command": "rust-analyzer.onEnter",
-  "when": "editorTextFocus && !suggestWidgetVisible && editorLangId == rust && vim.mode == 'Insert'"
-}
-````
-
-![On Enter](https://user-images.githubusercontent.com/48062697/113065578-04c21800-91b1-11eb-82b8-22b8c481e645.gif)
-
-
-### On Typing Assists
-**Source:**  [typing.rs](crates/ide/src/typing.rs#42) 
-
-Some features trigger on typing certain characters:
-
-- typing `let =` tries to smartly add `;` if `=` is followed by an existing expression
-- typing `=` between two expressions adds `;` when in statement position
-- typing `=` to turn an assignment into an equality comparison removes `;` when in expression position
-- typing `.` in a chain method call auto-indents
-- typing `{` or `(` in front of an expression inserts a closing `}` or `)` after the expression
-- typing `{` in a use item adds a closing `}` in the right place
-- typing `>` to complete a return type `->` will insert a whitespace after it
-
-#### VS Code
-
-Add the following to `settings.json`:
-```json
-"editor.formatOnType": true,
-```
-
-![On Typing Assists](https://user-images.githubusercontent.com/48062697/113166163-69758500-923a-11eb-81ee-eb33ec380399.gif)
-![On Typing Assists](https://user-images.githubusercontent.com/48062697/113171066-105c2000-923f-11eb-87ab-f4a263346567.gif)
-
-
-### Open Docs
-**Source:**  [doc_links.rs](crates/ide/src/doc_links.rs#118) 
-
-Retrieve a links to documentation for the given symbol.
-
-The simplest way to use this feature is via the context menu. Right-click on
-the selected item. The context menu opens. Select **Open Docs**.
-
-| Editor  | Action Name |
-|---------|-------------|
-| VS Code | **rust-analyzer: Open Docs** |
-
-
-### Parent Module
-**Source:**  [parent_module.rs](crates/ide/src/parent_module.rs#14) 
-
-Navigates to the parent module of the current module.
-
-| Editor  | Action Name |
-|---------|-------------|
-| VS Code | **rust-analyzer: Locate parent module** |
-
-![Parent Module](https://user-images.githubusercontent.com/48062697/113065580-04c21800-91b1-11eb-9a32-00086161c0bd.gif)
-
-
-### Related Tests
-**Source:**  [runnables.rs](crates/ide/src/runnables.rs#202) 
-
-Provides a sneak peek of all tests where the current item is used.
-
-The simplest way to use this feature is via the context menu. Right-click on
-the selected item. The context menu opens. Select **Peek Related Tests**.
-
-| Editor  | Action Name |
-|---------|-------------|
-| VS Code | **rust-analyzer: Peek Related Tests** |
-
-
-### Rename
-**Source:**  [rename.rs](crates/ide/src/rename.rs#70) 
-
-Renames the item below the cursor and all of its references
-
-| Editor  | Shortcut |
-|---------|----------|
-| VS Code | <kbd>F2</kbd> |
-
-![Rename](https://user-images.githubusercontent.com/48062697/113065582-055aae80-91b1-11eb-8ade-2b58e6d81883.gif)
-
-
-### Run
-**Source:**  [runnables.rs](crates/ide/src/runnables.rs#116) 
-
-Shows a popup suggesting to run a test/benchmark/binary **at the current cursor
-location**. Super useful for repeatedly running just a single test. Do bind this
-to a shortcut!
-
-| Editor  | Action Name |
-|---------|-------------|
-| VS Code | **rust-analyzer: Run** |
-
-![Run](https://user-images.githubusercontent.com/48062697/113065583-055aae80-91b1-11eb-958f-d67efcaf6a2f.gif)
-
-
-### Semantic Syntax Highlighting
-**Source:**  [syntax_highlighting.rs](crates/ide/src/syntax_highlighting.rs#68) 
-
-rust-analyzer highlights the code semantically.
-For example, `Bar` in `foo::Bar` might be colored differently depending on whether `Bar` is an enum or a trait.
-rust-analyzer does not specify colors directly, instead it assigns a tag (like `struct`) and a set of modifiers (like `declaration`) to each token.
-It's up to the client to map those to specific colors.
-
-The general rule is that a reference to an entity gets colored the same way as the entity itself.
-We also give special modifier for `mut` and `&mut` local variables.
-
-
-#### Token Tags
-
-Rust-analyzer currently emits the following token tags:
-
-- For items:
-
-|           |                                |
-|-----------|--------------------------------|
-| attribute |  Emitted for attribute macros. |
-|enum| Emitted for enums. |
-|function| Emitted for free-standing functions. |
-|derive| Emitted for derive macros. |
-|macro| Emitted for function-like macros. |
-|method| Emitted for associated functions, also knowns as methods. |
-|namespace| Emitted for modules. |
-|struct| Emitted for structs.|
-|trait| Emitted for traits.|
-|typeAlias| Emitted for type aliases and `Self` in `impl`s.|
-|union| Emitted for unions.|
-
-- For literals:
-
-|           |                                |
-|-----------|--------------------------------|
-| boolean|  Emitted for the boolean literals `true` and `false`.|
-| character| Emitted for character literals.|
-| number| Emitted for numeric literals.|
-| string| Emitted for string literals.|
-| escapeSequence| Emitted for escaped sequences inside strings like `\n`.|
-| formatSpecifier| Emitted for format specifiers `{:?}` in `format!`-like macros.|
-
-- For operators:
-
-|           |                                |
-|-----------|--------------------------------|
-|operator| Emitted for general operators.|
-|arithmetic| Emitted for the arithmetic operators `+`, `-`, `*`, `/`, `+=`, `-=`, `*=`, `/=`.|
-|bitwise| Emitted for the bitwise operators `|`, `&`, `!`, `^`, `|=`, `&=`, `^=`.|
-|comparison| Emitted for the comparison oerators `>`, `<`, `==`, `>=`, `<=`, `!=`.|
-|logical| Emitted for the logical operatos `||`, `&&`, `!`.|
-
-- For punctuation:
-
-|           |                                |
-|-----------|--------------------------------|
-|punctuation| Emitted for general punctuation.|
-|attributeBracket| Emitted for attribute invocation brackets, that is the `#[` and `]` tokens.|
-|angle| Emitted for `<>` angle brackets.|
-|brace| Emitted for `{}` braces.|
-|bracket| Emitted for `[]` brackets.|
-|parenthesis| Emitted for `()` parentheses.|
-|colon| Emitted for the `:` token.|
-|comma| Emitted for the `,` token.|
-|dot| Emitted for the `.` token.|
-|semi| Emitted for the `;` token.|
-|macroBang| Emitted for the `!` token in macro calls.|
-
--
-
-|           |                                |
-|-----------|--------------------------------|
-|builtinAttribute| Emitted for names to builtin attributes in attribute path, the `repr` in `#[repr(u8)]` for example.|
-|builtinType| Emitted for builtin types like `u32`, `str` and `f32`.|
-|comment| Emitted for comments.|
-|constParameter| Emitted for const parameters.|
-|deriveHelper| Emitted for derive helper attributes.|
-|enumMember| Emitted for enum variants.|
-|generic| Emitted for generic tokens that have no mapping.|
-|keyword| Emitted for keywords.|
-|label| Emitted for labels.|
-|lifetime| Emitted for lifetimes.|
-|parameter| Emitted for non-self function parameters.|
-|property| Emitted for struct and union fields.|
-|selfKeyword| Emitted for the self function parameter and self path-specifier.|
-|selfTypeKeyword| Emitted for the Self type parameter.|
-|toolModule| Emitted for tool modules.|
-|typeParameter| Emitted for type parameters.|
-|unresolvedReference| Emitted for unresolved references, names that rust-analyzer can't find the definition of.|
-|variable| Emitted for locals, constants and statics.|
-
-
-#### Token Modifiers
-
-Token modifiers allow to style some elements in the source code more precisely.
-
-Rust-analyzer currently emits the following token modifiers:
-
-|           |                                |
-|-----------|--------------------------------|
-|async| Emitted for async functions and the `async` and `await` keywords.|
-|attribute| Emitted for tokens inside attributes.|
-|callable| Emitted for locals whose types implements one of the `Fn*` traits.|
-|constant| Emitted for const.|
-|consuming| Emitted for locals that are being consumed when use in a function call.|
-|controlFlow| Emitted for control-flow related tokens, this includes th `?` operator.|
-|crateRoot| Emitted for crate names, like `serde` and `crate.|
-|declaration| Emitted for names of definitions, like `foo` in `fn foo(){}`.|
-|defaultLibrary| Emitted for items from built-in crates (std, core, allc, test and proc_macro).|
-|documentation| Emitted for documentation comment.|
-|injected| Emitted for doc-string injected highlighting like rust source blocks in documentation.|
-|intraDocLink| Emitted for intra doc links in doc-string.|
-|library| Emitted for items that are defined outside of the current crae.|
-|macro|  Emitted for tokens inside macro call.|
-|mutable| Emitted for mutable locals and statics as well as functions taking `&mut self`.|
-|public| Emitted for items that are from the current crate and are `pub.|
-|reference| Emitted for locals behind a reference and functions taking self` by reference.|
-|static| Emitted for "static" functions, also known as functions that d not take a `self` param, as well as statics and consts.|
-|trait| Emitted for associated trait item.|
-|unsafe| Emitted for unsafe operations, like unsafe function calls, as ell as the `unsafe` token.|
-
-![Semantic Syntax Highlighting](https://user-images.githubusercontent.com/48062697/113164457-06cfb980-9239-11eb-819b-0f93e646acf8.png)
-![Semantic Syntax Highlighting](https://user-images.githubusercontent.com/48062697/113187625-f7f50100-9250-11eb-825e-91c58f236071.png)
-
-
-### Show Dependency Tree
-**Source:**  [fetch_crates.rs](crates/ide/src/fetch_crates.rs#13) 
-
-Shows a view tree with all the dependencies of this project
-
-| Editor  | Panel Name |
-|---------|------------|
-| VS Code | **Rust Dependencies** |
-
-![Show Dependency Tree](https://user-images.githubusercontent.com/5748995/229394139-2625beab-f4c9-484b-84ed-ad5dee0b1e1a.png)
-
-
-### Show Syntax Tree
-**Source:**  [view_syntax_tree.rs](crates/ide/src/view_syntax_tree.rs#14) 
-
-Shows a tree view with the syntax tree of the current file
-
-| Editor  | Panel Name |
-|---------|-------------|
-| VS Code | **Rust Syntax Tree** |
-
-
-### Status
-**Source:**  [status.rs](crates/ide/src/status.rs#28) 
-
-Shows internal statistic about memory usage of rust-analyzer.
-
-| Editor  | Action Name |
-|---------|-------------|
-| VS Code | **rust-analyzer: Status** |
-
-![Status](https://user-images.githubusercontent.com/48062697/113065584-05f34500-91b1-11eb-98cc-5c196f76be7f.gif)
-
-
-### Structural Search and Replace
-**Source:**  [lib.rs](crates/ide-ssr/src/lib.rs#6) 
-
-Search and replace with named wildcards that will match any expression, type, path, pattern or item.
-The syntax for a structural search replace command is `<search_pattern> ==>> <replace_pattern>`.
-A `$<name>` placeholder in the search pattern will match any AST node and `$<name>` will reference it in the replacement.
-Within a macro call, a placeholder will match up until whatever token follows the placeholder.
-
-All paths in both the search pattern and the replacement template must resolve in the context
-in which this command is invoked. Paths in the search pattern will then match the code if they
-resolve to the same item, even if they're written differently. For example if we invoke the
-command in the module `foo` with a pattern of `Bar`, then code in the parent module that refers
-to `foo::Bar` will match.
-
-Paths in the replacement template will be rendered appropriately for the context in which the
-replacement occurs. For example if our replacement template is `foo::Bar` and we match some
-code in the `foo` module, we'll insert just `Bar`.
-
-Inherent method calls should generally be written in UFCS form. e.g. `foo::Bar::baz($s, $a)` will
-match `$s.baz($a)`, provided the method call `baz` resolves to the method `foo::Bar::baz`. When a
-placeholder is the receiver of a method call in the search pattern (e.g. `$s.foo()`), but not in
-the replacement template (e.g. `bar($s)`), then *, & and &mut will be added as needed to mirror
-whatever autoderef and autoref was happening implicitly in the matched code.
-
-The scope of the search / replace will be restricted to the current selection if any, otherwise
-it will apply to the whole workspace.
-
-Placeholders may be given constraints by writing them as `${<name>:<constraint1>:<constraint2>...}`.
-
-Supported constraints:
-
-| Constraint    | Restricts placeholder |
-|---------------|------------------------|
-| kind(literal) | Is a literal (e.g. `42` or `"forty two"`) |
-| not(a)        | Negates the constraint `a` |
-
-Available via the command `rust-analyzer.ssr`.
-
-```rust
-// Using structural search replace command [foo($a, $b) ==>> ($a).foo($b)]
-
-// BEFORE
-String::from(foo(y + 5, z))
-
-// AFTER
-String::from((y + 5).foo(z))
-```
-
-| Editor  | Action Name |
-|---------|--------------|
-| VS Code | **rust-analyzer: Structural Search Replace** |
-
-Also available as an assist, by writing a comment containing the structural
-search and replace rule. You will only see the assist if the comment can
-be parsed as a valid structural search and replace rule.
-
-```rust
-// Place the cursor on the line below to see the assist 💡.
-// foo($a, $b) ==>> ($a).foo($b)
-```
-
-
-### User Snippet Completions
-**Source:**  [snippet.rs](crates/ide-completion/src/snippet.rs#5) 
-
-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.
-
-```json
-{
-  "rust-analyzer.completion.snippets.custom": {
-    "thread spawn": {
-      "prefix": ["spawn", "tspawn"],
-      "body": [
-        "thread::spawn(move || {",
-        "\t$0",
-        "});",
-      ],
-      "description": "Insert a thread::spawn call",
-      "requires": "std::thread",
-      "scope": "expr",
-    }
-  }
-}
-```
-
-In the example above:
-
-* `"thread spawn"` is the name of the snippet.
-
-* `prefix` defines one or more trigger words that will trigger the snippets completion.
-Using `postfix` will instead create a postfix snippet.
-
-* `body` is one or more lines of content joined via newlines for the final output.
-
-* `description` is an optional description of the snippet, if unset the snippet name will be used.
-
-* `requires` is an optional list of item paths that have to be resolvable in the current crate where the completion is rendered.
-
-
-### View Crate Graph
-**Source:**  [view_crate_graph.rs](crates/ide/src/view_crate_graph.rs#8) 
-
-Renders the currently loaded crate graph as an SVG graphic. Requires the `dot` tool, which
-is part of graphviz, to be installed.
-
-Only workspace crates are included, no crates.io dependencies or sysroot crates.
-
-| Editor  | Action Name |
-|---------|-------------|
-| VS Code | **rust-analyzer: View Crate Graph** |
-
-
-### View Hir
-**Source:**  [view_hir.rs](crates/ide/src/view_hir.rs#5) 
-
-| Editor  | Action Name |
-|---------|--------------|
-| VS Code | **rust-analyzer: View Hir**
-
-![View Hir](https://user-images.githubusercontent.com/48062697/113065588-068bdb80-91b1-11eb-9a78-0b4ef1e972fb.gif)
-
-
-### View Memory Layout
-**Source:**  [view_memory_layout.rs](crates/ide/src/view_memory_layout.rs#74) 
-
-Displays the recursive memory layout of a datatype.
-
-| Editor  | Action Name |
-|---------|-------------|
-| VS Code | **rust-analyzer: View Memory Layout** |
-
-
-### View Mir
-**Source:**  [view_mir.rs](crates/ide/src/view_mir.rs#5) 
-
-| Editor  | Action Name |
-|---------|-------------|
-| VS Code | **rust-analyzer: View Mir**
-
-
-### Workspace Symbol
-**Source:**  [symbol_index.rs](crates/ide-db/src/symbol_index.rs#174) 
-
-Uses fuzzy-search to find types, modules and functions by name across your
-project and dependencies. This is **the** most useful feature, which improves code
-navigation tremendously. It mostly works on top of the built-in LSP
-functionality, however `#` and `*` symbols can be used to narrow down the
-search. Specifically,
-
-- `Foo` searches for `Foo` type in the current workspace
-- `foo#` searches for `foo` function in the current workspace
-- `Foo*` searches for `Foo` type among dependencies, including `stdlib`
-- `foo#*` searches for `foo` function among dependencies
-
-That is, `#` switches from "types" to all symbols, `*` switches from the current
-workspace to dependencies.
-
-Note that filtering does not currently work in VSCode due to the editor never
-sending the special symbols to the language server. Instead, you can configure
-the filtering via the `rust-analyzer.workspace.symbol.search.scope` and
-`rust-analyzer.workspace.symbol.search.kind` settings. Symbols prefixed
-with `__` are hidden from the search results unless configured otherwise.
-
-| Editor  | Shortcut |
-|---------|-----------|
-| VS Code | <kbd>Ctrl+T</kbd>
diff --git a/editors/code/package-lock.json b/editors/code/package-lock.json
index 86a066454a..6027f81331 100644
--- a/editors/code/package-lock.json
+++ b/editors/code/package-lock.json
@@ -23,7 +23,7 @@
                 "@typescript-eslint/parser": "^6.0.0",
                 "@vscode/test-electron": "^2.3.8",
                 "@vscode/vsce": "^3.0.0",
-                "esbuild": "^0.25.0",
+                "esbuild": "^0.18.12",
                 "eslint": "^8.44.0",
                 "eslint-config-prettier": "^8.8.0",
                 "ovsx": "^0.8.2",
@@ -256,429 +256,356 @@
                 "node": ">=16"
             }
         },
-        "node_modules/@esbuild/aix-ppc64": {
-            "version": "0.25.0",
-            "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.0.tgz",
-            "integrity": "sha512-O7vun9Sf8DFjH2UtqK8Ku3LkquL9SZL8OLY1T5NZkA34+wG3OQF7cl4Ql8vdNzM6fzBbYfLaiRLIOZ+2FOCgBQ==",
-            "cpu": [
-                "ppc64"
-            ],
-            "dev": true,
-            "license": "MIT",
-            "optional": true,
-            "os": [
-                "aix"
-            ],
-            "engines": {
-                "node": ">=18"
-            }
-        },
         "node_modules/@esbuild/android-arm": {
-            "version": "0.25.0",
-            "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.0.tgz",
-            "integrity": "sha512-PTyWCYYiU0+1eJKmw21lWtC+d08JDZPQ5g+kFyxP0V+es6VPPSUhM6zk8iImp2jbV6GwjX4pap0JFbUQN65X1g==",
+            "version": "0.18.12",
+            "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.12.tgz",
+            "integrity": "sha512-LIxaNIQfkFZbTLb4+cX7dozHlAbAshhFE5PKdro0l+FnCpx1GDJaQ2WMcqm+ToXKMt8p8Uojk/MFRuGyz3V5Sw==",
             "cpu": [
                 "arm"
             ],
             "dev": true,
-            "license": "MIT",
             "optional": true,
             "os": [
                 "android"
             ],
             "engines": {
-                "node": ">=18"
+                "node": ">=12"
             }
         },
         "node_modules/@esbuild/android-arm64": {
-            "version": "0.25.0",
-            "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.0.tgz",
-            "integrity": "sha512-grvv8WncGjDSyUBjN9yHXNt+cq0snxXbDxy5pJtzMKGmmpPxeAmAhWxXI+01lU5rwZomDgD3kJwulEnhTRUd6g==",
+            "version": "0.18.12",
+            "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.12.tgz",
+            "integrity": "sha512-BMAlczRqC/LUt2P97E4apTBbkvS9JTJnp2DKFbCwpZ8vBvXVbNdqmvzW/OsdtI/+mGr+apkkpqGM8WecLkPgrA==",
             "cpu": [
                 "arm64"
             ],
             "dev": true,
-            "license": "MIT",
             "optional": true,
             "os": [
                 "android"
             ],
             "engines": {
-                "node": ">=18"
+                "node": ">=12"
             }
         },
         "node_modules/@esbuild/android-x64": {
-            "version": "0.25.0",
-            "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.0.tgz",
-            "integrity": "sha512-m/ix7SfKG5buCnxasr52+LI78SQ+wgdENi9CqyCXwjVR2X4Jkz+BpC3le3AoBPYTC9NHklwngVXvbJ9/Akhrfg==",
+            "version": "0.18.12",
+            "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.12.tgz",
+            "integrity": "sha512-zU5MyluNsykf5cOJ0LZZZjgAHbhPJ1cWfdH1ZXVMXxVMhEV0VZiZXQdwBBVvmvbF28EizeK7obG9fs+fpmS0eQ==",
             "cpu": [
                 "x64"
             ],
             "dev": true,
-            "license": "MIT",
             "optional": true,
             "os": [
                 "android"
             ],
             "engines": {
-                "node": ">=18"
+                "node": ">=12"
             }
         },
         "node_modules/@esbuild/darwin-arm64": {
-            "version": "0.25.0",
-            "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.0.tgz",
-            "integrity": "sha512-mVwdUb5SRkPayVadIOI78K7aAnPamoeFR2bT5nszFUZ9P8UpK4ratOdYbZZXYSqPKMHfS1wdHCJk1P1EZpRdvw==",
+            "version": "0.18.12",
+            "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.12.tgz",
+            "integrity": "sha512-zUZMep7YONnp6954QOOwEBwFX9svlKd3ov6PkxKd53LGTHsp/gy7vHaPGhhjBmEpqXEXShi6dddjIkmd+NgMsA==",
             "cpu": [
                 "arm64"
             ],
             "dev": true,
-            "license": "MIT",
             "optional": true,
             "os": [
                 "darwin"
             ],
             "engines": {
-                "node": ">=18"
+                "node": ">=12"
             }
         },
         "node_modules/@esbuild/darwin-x64": {
-            "version": "0.25.0",
-            "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.0.tgz",
-            "integrity": "sha512-DgDaYsPWFTS4S3nWpFcMn/33ZZwAAeAFKNHNa1QN0rI4pUjgqf0f7ONmXf6d22tqTY+H9FNdgeaAa+YIFUn2Rg==",
+            "version": "0.18.12",
+            "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.12.tgz",
+            "integrity": "sha512-ohqLPc7i67yunArPj1+/FeeJ7AgwAjHqKZ512ADk3WsE3FHU9l+m5aa7NdxXr0HmN1bjDlUslBjWNbFlD9y12Q==",
             "cpu": [
                 "x64"
             ],
             "dev": true,
-            "license": "MIT",
             "optional": true,
             "os": [
                 "darwin"
             ],
             "engines": {
-                "node": ">=18"
+                "node": ">=12"
             }
         },
         "node_modules/@esbuild/freebsd-arm64": {
-            "version": "0.25.0",
-            "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.0.tgz",
-            "integrity": "sha512-VN4ocxy6dxefN1MepBx/iD1dH5K8qNtNe227I0mnTRjry8tj5MRk4zprLEdG8WPyAPb93/e4pSgi1SoHdgOa4w==",
+            "version": "0.18.12",
+            "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.12.tgz",
+            "integrity": "sha512-GIIHtQXqgeOOqdG16a/A9N28GpkvjJnjYMhOnXVbn3EDJcoItdR58v/pGN31CHjyXDc8uCcRnFWmqaJt24AYJg==",
             "cpu": [
                 "arm64"
             ],
             "dev": true,
-            "license": "MIT",
             "optional": true,
             "os": [
                 "freebsd"
             ],
             "engines": {
-                "node": ">=18"
+                "node": ">=12"
             }
         },
         "node_modules/@esbuild/freebsd-x64": {
-            "version": "0.25.0",
-            "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.0.tgz",
-            "integrity": "sha512-mrSgt7lCh07FY+hDD1TxiTyIHyttn6vnjesnPoVDNmDfOmggTLXRv8Id5fNZey1gl/V2dyVK1VXXqVsQIiAk+A==",
+            "version": "0.18.12",
+            "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.12.tgz",
+            "integrity": "sha512-zK0b9a1/0wZY+6FdOS3BpZcPc1kcx2G5yxxfEJtEUzVxI6n/FrC2Phsxj/YblPuBchhBZ/1wwn7AyEBUyNSa6g==",
             "cpu": [
                 "x64"
             ],
             "dev": true,
-            "license": "MIT",
             "optional": true,
             "os": [
                 "freebsd"
             ],
             "engines": {
-                "node": ">=18"
+                "node": ">=12"
             }
         },
         "node_modules/@esbuild/linux-arm": {
-            "version": "0.25.0",
-            "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.0.tgz",
-            "integrity": "sha512-vkB3IYj2IDo3g9xX7HqhPYxVkNQe8qTK55fraQyTzTX/fxaDtXiEnavv9geOsonh2Fd2RMB+i5cbhu2zMNWJwg==",
+            "version": "0.18.12",
+            "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.12.tgz",
+            "integrity": "sha512-y75OijvrBE/1XRrXq1jtrJfG26eHeMoqLJ2dwQNwviwTuTtHGCojsDO6BJNF8gU+3jTn1KzJEMETytwsFSvc+Q==",
             "cpu": [
                 "arm"
             ],
             "dev": true,
-            "license": "MIT",
             "optional": true,
             "os": [
                 "linux"
             ],
             "engines": {
-                "node": ">=18"
+                "node": ">=12"
             }
         },
         "node_modules/@esbuild/linux-arm64": {
-            "version": "0.25.0",
-            "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.0.tgz",
-            "integrity": "sha512-9QAQjTWNDM/Vk2bgBl17yWuZxZNQIF0OUUuPZRKoDtqF2k4EtYbpyiG5/Dk7nqeK6kIJWPYldkOcBqjXjrUlmg==",
+            "version": "0.18.12",
+            "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.12.tgz",
+            "integrity": "sha512-JKgG8Q/LL/9sw/iHHxQyVMoQYu3rU3+a5Z87DxC+wAu3engz+EmctIrV+FGOgI6gWG1z1+5nDDbXiRMGQZXqiw==",
             "cpu": [
                 "arm64"
             ],
             "dev": true,
-            "license": "MIT",
             "optional": true,
             "os": [
                 "linux"
             ],
             "engines": {
-                "node": ">=18"
+                "node": ">=12"
             }
         },
         "node_modules/@esbuild/linux-ia32": {
-            "version": "0.25.0",
-            "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.0.tgz",
-            "integrity": "sha512-43ET5bHbphBegyeqLb7I1eYn2P/JYGNmzzdidq/w0T8E2SsYL1U6un2NFROFRg1JZLTzdCoRomg8Rvf9M6W6Gg==",
+            "version": "0.18.12",
+            "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.12.tgz",
+            "integrity": "sha512-yoRIAqc0B4lDIAAEFEIu9ttTRFV84iuAl0KNCN6MhKLxNPfzwCBvEMgwco2f71GxmpBcTtn7KdErueZaM2rEvw==",
             "cpu": [
                 "ia32"
             ],
             "dev": true,
-            "license": "MIT",
             "optional": true,
             "os": [
                 "linux"
             ],
             "engines": {
-                "node": ">=18"
+                "node": ">=12"
             }
         },
         "node_modules/@esbuild/linux-loong64": {
-            "version": "0.25.0",
-            "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.0.tgz",
-            "integrity": "sha512-fC95c/xyNFueMhClxJmeRIj2yrSMdDfmqJnyOY4ZqsALkDrrKJfIg5NTMSzVBr5YW1jf+l7/cndBfP3MSDpoHw==",
+            "version": "0.18.12",
+            "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.12.tgz",
+            "integrity": "sha512-qYgt3dHPVvf/MgbIBpJ4Sup/yb9DAopZ3a2JgMpNKIHUpOdnJ2eHBo/aQdnd8dJ21X/+sS58wxHtA9lEazYtXQ==",
             "cpu": [
                 "loong64"
             ],
             "dev": true,
-            "license": "MIT",
             "optional": true,
             "os": [
                 "linux"
             ],
             "engines": {
-                "node": ">=18"
+                "node": ">=12"
             }
         },
         "node_modules/@esbuild/linux-mips64el": {
-            "version": "0.25.0",
-            "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.0.tgz",
-            "integrity": "sha512-nkAMFju7KDW73T1DdH7glcyIptm95a7Le8irTQNO/qtkoyypZAnjchQgooFUDQhNAy4iu08N79W4T4pMBwhPwQ==",
+            "version": "0.18.12",
+            "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.12.tgz",
+            "integrity": "sha512-wHphlMLK4ufNOONqukELfVIbnGQJrHJ/mxZMMrP2jYrPgCRZhOtf0kC4yAXBwnfmULimV1qt5UJJOw4Kh13Yfg==",
             "cpu": [
                 "mips64el"
             ],
             "dev": true,
-            "license": "MIT",
             "optional": true,
             "os": [
                 "linux"
             ],
             "engines": {
-                "node": ">=18"
+                "node": ">=12"
             }
         },
         "node_modules/@esbuild/linux-ppc64": {
-            "version": "0.25.0",
-            "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.0.tgz",
-            "integrity": "sha512-NhyOejdhRGS8Iwv+KKR2zTq2PpysF9XqY+Zk77vQHqNbo/PwZCzB5/h7VGuREZm1fixhs4Q/qWRSi5zmAiO4Fw==",
+            "version": "0.18.12",
+            "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.12.tgz",
+            "integrity": "sha512-TeN//1Ft20ZZW41+zDSdOI/Os1bEq5dbvBvYkberB7PHABbRcsteeoNVZFlI0YLpGdlBqohEpjrn06kv8heCJg==",
             "cpu": [
                 "ppc64"
             ],
             "dev": true,
-            "license": "MIT",
             "optional": true,
             "os": [
                 "linux"
             ],
             "engines": {
-                "node": ">=18"
+                "node": ">=12"
             }
         },
         "node_modules/@esbuild/linux-riscv64": {
-            "version": "0.25.0",
-            "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.0.tgz",
-            "integrity": "sha512-5S/rbP5OY+GHLC5qXp1y/Mx//e92L1YDqkiBbO9TQOvuFXM+iDqUNG5XopAnXoRH3FjIUDkeGcY1cgNvnXp/kA==",
+            "version": "0.18.12",
+            "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.12.tgz",
+            "integrity": "sha512-AgUebVS4DoAblBgiB2ACQ/8l4eGE5aWBb8ZXtkXHiET9mbj7GuWt3OnsIW/zX+XHJt2RYJZctbQ2S/mDjbp0UA==",
             "cpu": [
                 "riscv64"
             ],
             "dev": true,
-            "license": "MIT",
             "optional": true,
             "os": [
                 "linux"
             ],
             "engines": {
-                "node": ">=18"
+                "node": ">=12"
             }
         },
         "node_modules/@esbuild/linux-s390x": {
-            "version": "0.25.0",
-            "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.0.tgz",
-            "integrity": "sha512-XM2BFsEBz0Fw37V0zU4CXfcfuACMrppsMFKdYY2WuTS3yi8O1nFOhil/xhKTmE1nPmVyvQJjJivgDT+xh8pXJA==",
+            "version": "0.18.12",
+            "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.12.tgz",
+            "integrity": "sha512-dJ3Rb3Ei2u/ysSXd6pzleGtfDdc2MuzKt8qc6ls8vreP1G3B7HInX3i7gXS4BGeVd24pp0yqyS7bJ5NHaI9ing==",
             "cpu": [
                 "s390x"
             ],
             "dev": true,
-            "license": "MIT",
             "optional": true,
             "os": [
                 "linux"
             ],
             "engines": {
-                "node": ">=18"
+                "node": ">=12"
             }
         },
         "node_modules/@esbuild/linux-x64": {
-            "version": "0.25.0",
-            "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.0.tgz",
-            "integrity": "sha512-9yl91rHw/cpwMCNytUDxwj2XjFpxML0y9HAOH9pNVQDpQrBxHy01Dx+vaMu0N1CKa/RzBD2hB4u//nfc+Sd3Cw==",
+            "version": "0.18.12",
+            "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.12.tgz",
+            "integrity": "sha512-OrNJMGQbPaVyHHcDF8ybNSwu7TDOfX8NGpXCbetwOSP6txOJiWlgQnRymfC9ocR1S0Y5PW0Wb1mV6pUddqmvmQ==",
             "cpu": [
                 "x64"
             ],
             "dev": true,
-            "license": "MIT",
             "optional": true,
             "os": [
                 "linux"
             ],
             "engines": {
-                "node": ">=18"
-            }
-        },
-        "node_modules/@esbuild/netbsd-arm64": {
-            "version": "0.25.0",
-            "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.0.tgz",
-            "integrity": "sha512-RuG4PSMPFfrkH6UwCAqBzauBWTygTvb1nxWasEJooGSJ/NwRw7b2HOwyRTQIU97Hq37l3npXoZGYMy3b3xYvPw==",
-            "cpu": [
-                "arm64"
-            ],
-            "dev": true,
-            "license": "MIT",
-            "optional": true,
-            "os": [
-                "netbsd"
-            ],
-            "engines": {
-                "node": ">=18"
+                "node": ">=12"
             }
         },
         "node_modules/@esbuild/netbsd-x64": {
-            "version": "0.25.0",
-            "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.0.tgz",
-            "integrity": "sha512-jl+qisSB5jk01N5f7sPCsBENCOlPiS/xptD5yxOx2oqQfyourJwIKLRA2yqWdifj3owQZCL2sn6o08dBzZGQzA==",
+            "version": "0.18.12",
+            "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.12.tgz",
+            "integrity": "sha512-55FzVCAiwE9FK8wWeCRuvjazNRJ1QqLCYGZVB6E8RuQuTeStSwotpSW4xoRGwp3a1wUsaVCdYcj5LGCASVJmMg==",
             "cpu": [
                 "x64"
             ],
             "dev": true,
-            "license": "MIT",
             "optional": true,
             "os": [
                 "netbsd"
             ],
             "engines": {
-                "node": ">=18"
-            }
-        },
-        "node_modules/@esbuild/openbsd-arm64": {
-            "version": "0.25.0",
-            "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.0.tgz",
-            "integrity": "sha512-21sUNbq2r84YE+SJDfaQRvdgznTD8Xc0oc3p3iW/a1EVWeNj/SdUCbm5U0itZPQYRuRTW20fPMWMpcrciH2EJw==",
-            "cpu": [
-                "arm64"
-            ],
-            "dev": true,
-            "license": "MIT",
-            "optional": true,
-            "os": [
-                "openbsd"
-            ],
-            "engines": {
-                "node": ">=18"
+                "node": ">=12"
             }
         },
         "node_modules/@esbuild/openbsd-x64": {
-            "version": "0.25.0",
-            "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.0.tgz",
-            "integrity": "sha512-2gwwriSMPcCFRlPlKx3zLQhfN/2WjJ2NSlg5TKLQOJdV0mSxIcYNTMhk3H3ulL/cak+Xj0lY1Ym9ysDV1igceg==",
+            "version": "0.18.12",
+            "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.12.tgz",
+            "integrity": "sha512-qnluf8rfb6Y5Lw2tirfK2quZOBbVqmwxut7GPCIJsM8lc4AEUj9L8y0YPdLaPK0TECt4IdyBdBD/KRFKorlK3g==",
             "cpu": [
                 "x64"
             ],
             "dev": true,
-            "license": "MIT",
             "optional": true,
             "os": [
                 "openbsd"
             ],
             "engines": {
-                "node": ">=18"
+                "node": ">=12"
             }
         },
         "node_modules/@esbuild/sunos-x64": {
-            "version": "0.25.0",
-            "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.0.tgz",
-            "integrity": "sha512-bxI7ThgLzPrPz484/S9jLlvUAHYMzy6I0XiU1ZMeAEOBcS0VePBFxh1JjTQt3Xiat5b6Oh4x7UC7IwKQKIJRIg==",
+            "version": "0.18.12",
+            "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.12.tgz",
+            "integrity": "sha512-+RkKpVQR7bICjTOPUpkTBTaJ4TFqQBX5Ywyd/HSdDkQGn65VPkTsR/pL4AMvuMWy+wnXgIl4EY6q4mVpJal8Kg==",
             "cpu": [
                 "x64"
             ],
             "dev": true,
-            "license": "MIT",
             "optional": true,
             "os": [
                 "sunos"
             ],
             "engines": {
-                "node": ">=18"
+                "node": ">=12"
             }
         },
         "node_modules/@esbuild/win32-arm64": {
-            "version": "0.25.0",
-            "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.0.tgz",
-            "integrity": "sha512-ZUAc2YK6JW89xTbXvftxdnYy3m4iHIkDtK3CLce8wg8M2L+YZhIvO1DKpxrd0Yr59AeNNkTiic9YLf6FTtXWMw==",
+            "version": "0.18.12",
+            "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.12.tgz",
+            "integrity": "sha512-GNHuciv0mFM7ouzsU0+AwY+7eV4Mgo5WnbhfDCQGtpvOtD1vbOiRjPYG6dhmMoFyBjj+pNqQu2X+7DKn0KQ/Gw==",
             "cpu": [
                 "arm64"
             ],
             "dev": true,
-            "license": "MIT",
             "optional": true,
             "os": [
                 "win32"
             ],
             "engines": {
-                "node": ">=18"
+                "node": ">=12"
             }
         },
         "node_modules/@esbuild/win32-ia32": {
-            "version": "0.25.0",
-            "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.0.tgz",
-            "integrity": "sha512-eSNxISBu8XweVEWG31/JzjkIGbGIJN/TrRoiSVZwZ6pkC6VX4Im/WV2cz559/TXLcYbcrDN8JtKgd9DJVIo8GA==",
+            "version": "0.18.12",
+            "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.12.tgz",
+            "integrity": "sha512-kR8cezhYipbbypGkaqCTWIeu4zID17gamC8YTPXYtcN3E5BhhtTnwKBn9I0PJur/T6UVwIEGYzkffNL0lFvxEw==",
             "cpu": [
                 "ia32"
             ],
             "dev": true,
-            "license": "MIT",
             "optional": true,
             "os": [
                 "win32"
             ],
             "engines": {
-                "node": ">=18"
+                "node": ">=12"
             }
         },
         "node_modules/@esbuild/win32-x64": {
-            "version": "0.25.0",
-            "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.0.tgz",
-            "integrity": "sha512-ZENoHJBxA20C2zFzh6AI4fT6RraMzjYw4xKWemRTRmRVtN9c5DcH9r/f2ihEkMjOW5eGgrwCslG/+Y/3bL+DHQ==",
+            "version": "0.18.12",
+            "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.12.tgz",
+            "integrity": "sha512-O0UYQVkvfM/jO8a4OwoV0mAKSJw+mjWTAd1MJd/1FCX6uiMdLmMRPK/w6e9OQ0ob2WGxzIm9va/KG0Ja4zIOgg==",
             "cpu": [
                 "x64"
             ],
             "dev": true,
-            "license": "MIT",
             "optional": true,
             "os": [
                 "win32"
             ],
             "engines": {
-                "node": ">=18"
+                "node": ">=12"
             }
         },
         "node_modules/@eslint-community/eslint-utils": {
@@ -2594,44 +2521,40 @@
             }
         },
         "node_modules/esbuild": {
-            "version": "0.25.0",
-            "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.0.tgz",
-            "integrity": "sha512-BXq5mqc8ltbaN34cDqWuYKyNhX8D/Z0J1xdtdQ8UcIIIyJyz+ZMKUt58tF3SrZ85jcfN/PZYhjR5uDQAYNVbuw==",
+            "version": "0.18.12",
+            "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.12.tgz",
+            "integrity": "sha512-XuOVLDdtsDslXStStduT41op21Ytmf4/BDS46aa3xPJ7X5h2eMWBF1oAe3QjUH3bDksocNXgzGUZ7XHIBya6Tg==",
             "dev": true,
             "hasInstallScript": true,
-            "license": "MIT",
             "bin": {
                 "esbuild": "bin/esbuild"
             },
             "engines": {
-                "node": ">=18"
+                "node": ">=12"
             },
             "optionalDependencies": {
-                "@esbuild/aix-ppc64": "0.25.0",
-                "@esbuild/android-arm": "0.25.0",
-                "@esbuild/android-arm64": "0.25.0",
-                "@esbuild/android-x64": "0.25.0",
-                "@esbuild/darwin-arm64": "0.25.0",
-                "@esbuild/darwin-x64": "0.25.0",
-                "@esbuild/freebsd-arm64": "0.25.0",
-                "@esbuild/freebsd-x64": "0.25.0",
-                "@esbuild/linux-arm": "0.25.0",
-                "@esbuild/linux-arm64": "0.25.0",
-                "@esbuild/linux-ia32": "0.25.0",
-                "@esbuild/linux-loong64": "0.25.0",
-                "@esbuild/linux-mips64el": "0.25.0",
-                "@esbuild/linux-ppc64": "0.25.0",
-                "@esbuild/linux-riscv64": "0.25.0",
-                "@esbuild/linux-s390x": "0.25.0",
-                "@esbuild/linux-x64": "0.25.0",
-                "@esbuild/netbsd-arm64": "0.25.0",
-                "@esbuild/netbsd-x64": "0.25.0",
-                "@esbuild/openbsd-arm64": "0.25.0",
-                "@esbuild/openbsd-x64": "0.25.0",
-                "@esbuild/sunos-x64": "0.25.0",
-                "@esbuild/win32-arm64": "0.25.0",
-                "@esbuild/win32-ia32": "0.25.0",
-                "@esbuild/win32-x64": "0.25.0"
+                "@esbuild/android-arm": "0.18.12",
+                "@esbuild/android-arm64": "0.18.12",
+                "@esbuild/android-x64": "0.18.12",
+                "@esbuild/darwin-arm64": "0.18.12",
+                "@esbuild/darwin-x64": "0.18.12",
+                "@esbuild/freebsd-arm64": "0.18.12",
+                "@esbuild/freebsd-x64": "0.18.12",
+                "@esbuild/linux-arm": "0.18.12",
+                "@esbuild/linux-arm64": "0.18.12",
+                "@esbuild/linux-ia32": "0.18.12",
+                "@esbuild/linux-loong64": "0.18.12",
+                "@esbuild/linux-mips64el": "0.18.12",
+                "@esbuild/linux-ppc64": "0.18.12",
+                "@esbuild/linux-riscv64": "0.18.12",
+                "@esbuild/linux-s390x": "0.18.12",
+                "@esbuild/linux-x64": "0.18.12",
+                "@esbuild/netbsd-x64": "0.18.12",
+                "@esbuild/openbsd-x64": "0.18.12",
+                "@esbuild/sunos-x64": "0.18.12",
+                "@esbuild/win32-arm64": "0.18.12",
+                "@esbuild/win32-ia32": "0.18.12",
+                "@esbuild/win32-x64": "0.18.12"
             }
         },
         "node_modules/escalade": {
diff --git a/editors/code/package.json b/editors/code/package.json
index 3f09033051..58571a540e 100644
--- a/editors/code/package.json
+++ b/editors/code/package.json
@@ -59,7 +59,7 @@
         "@typescript-eslint/parser": "^6.0.0",
         "@vscode/test-electron": "^2.3.8",
         "@vscode/vsce": "^3.0.0",
-        "esbuild": "^0.25.0",
+        "esbuild": "^0.18.12",
         "eslint": "^8.44.0",
         "eslint-config-prettier": "^8.8.0",
         "ovsx": "^0.8.2",
diff --git a/xtask/src/codegen.rs b/xtask/src/codegen.rs
index e84c259e97..18f49643dc 100644
--- a/xtask/src/codegen.rs
+++ b/xtask/src/codegen.rs
@@ -117,7 +117,7 @@ impl fmt::Display for Location {
         let path = self.file.strip_prefix(project_root()).unwrap().display().to_string();
         let path = path.replace('\\', "/");
         let name = self.file.file_name().unwrap();
-        write!(f, " [{}](/{}#{}) ", name.to_str().unwrap(), path, self.line)
+        write!(f, " [{}]({}#{}) ", name.to_str().unwrap(), path, self.line)
     }
 }
 


Test patch:
diff --git a/crates/hir-def/src/expr_store/tests.rs b/crates/hir-def/src/expr_store/tests.rs
index 16bf46d3e3..9bf1ddb479 100644
--- a/crates/hir-def/src/expr_store/tests.rs
+++ b/crates/hir-def/src/expr_store/tests.rs
@@ -1,10 +1,11 @@
 mod block;
 
-use crate::{hir::MatchArm, test_db::TestDB, ModuleDefId};
 use expect_test::{expect, Expect};
 use la_arena::RawIdx;
 use test_fixture::WithFixture;
 
+use crate::{test_db::TestDB, ModuleDefId};
+
 use super::*;
 
 fn lower(#[rust_analyzer::rust_fixture] ra_fixture: &str) -> (TestDB, Arc<Body>, DefWithBodyId) {
@@ -459,45 +460,3 @@ async fn foo(a: (), b: i32) -> u32 {
     expect!["fn foo(�: (), �: i32) -> impl ::core::future::Future::<Output = u32> �"]
         .assert_eq(&printed);
 }
-
-#[test]
-fn range_bounds_are_hir_exprs() {
-    let (_, body, _) = lower(
-        r#"
-pub const L: i32 = 6;
-mod x {
-    pub const R: i32 = 100;
-}
-const fn f(x: i32) -> i32 {
-    match x {
-        -1..=5 => x * 10,
-        L..=x::R => x * 100,
-        _ => x,
-    }
-}"#,
-    );
-
-    let mtch_arms = body
-        .exprs
-        .iter()
-        .find_map(|(_, expr)| {
-            if let Expr::Match { arms, .. } = expr {
-                return Some(arms);
-            }
-
-            None
-        })
-        .unwrap();
-
-    let MatchArm { pat, .. } = mtch_arms[1];
-    match body.pats[pat] {
-        Pat::Range { start, end } => {
-            let hir_start = &body.exprs[start.unwrap()];
-            let hir_end = &body.exprs[end.unwrap()];
-
-            assert!(matches!(hir_start, Expr::Path { .. }));
-            assert!(matches!(hir_end, Expr::Path { .. }));
-        }
-        _ => {}
-    }
-}
diff --git a/crates/hir-def/src/macro_expansion_tests/proc_macros.rs b/crates/hir-def/src/macro_expansion_tests/proc_macros.rs
index a43c0eb9d7..70e3e1ed4e 100644
--- a/crates/hir-def/src/macro_expansion_tests/proc_macros.rs
+++ b/crates/hir-def/src/macro_expansion_tests/proc_macros.rs
@@ -5,7 +5,7 @@
 //! in-memory macros.
 use expect_test::expect;
 
-use crate::macro_expansion_tests::{check, check_errors};
+use crate::macro_expansion_tests::check;
 
 #[test]
 fn attribute_macro_attr_censoring() {
@@ -216,21 +216,3 @@ struct S;
 #[doc = "doc attr"] struct S;"##]],
     );
 }
-
-#[test]
-fn cfg_evaluated_before_attr_macros() {
-    check_errors(
-        r#"
-//- proc_macros: disallow_cfg
-
-use proc_macros::disallow_cfg;
-
-#[disallow_cfg] #[cfg(false)] fn foo() {}
-// True cfg are kept.
-// #[disallow_cfg] #[cfg(true)] fn bar() {}
-#[disallow_cfg] #[cfg_attr(false, inline)] fn baz() {}
-#[disallow_cfg] #[cfg_attr(true, inline)] fn qux() {}
-    "#,
-        expect![[r#""#]],
-    );
-}
diff --git a/crates/hir-ty/src/mir/eval/tests.rs b/crates/hir-ty/src/mir/eval/tests.rs
index 9625ae5f88..f1e86daea2 100644
--- a/crates/hir-ty/src/mir/eval/tests.rs
+++ b/crates/hir-ty/src/mir/eval/tests.rs
@@ -912,36 +912,3 @@ fn main() {
         "",
     );
 }
-
-#[test]
-fn regression_19021() {
-    check_pass(
-        r#"
-//- minicore: deref
-use core::ops::Deref;
-
-#[lang = "owned_box"]
-struct Box<T>(T);
-
-impl<T> Deref for Box<T> {
-    type Target = T;
-
-    fn deref(&self) -> &Self::Target {
-        &self.0
-    }
-}
-
-struct Foo;
-
-fn main() {
-    let x = Box(Foo);
-    let y = &Foo;
-
-    || match x {
-        ref x => x,
-        _ => y,
-    };
-}
-"#,
-    );
-}
diff --git a/crates/hir-ty/src/tests/coercion.rs b/crates/hir-ty/src/tests/coercion.rs
index 7e7c1f835c..7992f1feee 100644
--- a/crates/hir-ty/src/tests/coercion.rs
+++ b/crates/hir-ty/src/tests/coercion.rs
@@ -185,10 +185,11 @@ fn test() {
     let t = &mut 1;
     let x = match 1 {
         1 => t as *mut i32,
-           //^^^^^^^^^^^^^ adjustments: Pointer(MutToConstPointer)
         2 => t as &i32,
            //^^^^^^^^^ expected *mut i32, got &'? i32
         _ => t as *const i32,
+          // ^^^^^^^^^^^^^^^ adjustments: Pointer(MutToConstPointer)
+
     };
     x;
   //^ type: *const i32
diff --git a/crates/project-model/src/tests.rs b/crates/project-model/src/tests.rs
index 2856086543..25e4368d95 100644
--- a/crates/project-model/src/tests.rs
+++ b/crates/project-model/src/tests.rs
@@ -12,9 +12,9 @@ use span::FileId;
 use triomphe::Arc;
 
 use crate::{
-    sysroot::SysrootWorkspace, workspace::ProjectWorkspaceKind, CargoWorkspace, CfgOverrides,
-    ManifestPath, ProjectJson, ProjectJsonData, ProjectWorkspace, Sysroot,
-    SysrootSourceWorkspaceConfig, WorkspaceBuildScripts,
+    sysroot::RustLibSrcWorkspace, workspace::ProjectWorkspaceKind, CargoWorkspace, CfgOverrides,
+    ManifestPath, ProjectJson, ProjectJsonData, ProjectWorkspace, RustSourceWorkspaceConfig,
+    Sysroot, WorkspaceBuildScripts,
 };
 
 fn load_cargo(file: &str) -> (CrateGraph, ProcMacroPaths) {
@@ -125,7 +125,10 @@ fn get_fake_sysroot() -> Sysroot {
     let sysroot_dir = AbsPathBuf::assert(sysroot_path);
     let sysroot_src_dir = sysroot_dir.clone();
     let mut sysroot = Sysroot::new(Some(sysroot_dir), Some(sysroot_src_dir));
-    sysroot.load_workspace(&SysrootSourceWorkspaceConfig::default_cargo());
+    let loaded_sysroot = sysroot.load_workspace(&RustSourceWorkspaceConfig::default_cargo());
+    if let Some(loaded_sysroot) = loaded_sysroot {
+        sysroot.set_workspace(loaded_sysroot);
+    }
     sysroot
 }
 
@@ -271,8 +274,11 @@ fn smoke_test_real_sysroot_cargo() {
         AbsPath::assert(Utf8Path::new(env!("CARGO_MANIFEST_DIR"))),
         &Default::default(),
     );
-    sysroot.load_workspace(&SysrootSourceWorkspaceConfig::default_cargo());
-    assert!(matches!(sysroot.workspace(), SysrootWorkspace::Workspace(_)));
+    let loaded_sysroot = sysroot.load_workspace(&RustSourceWorkspaceConfig::default_cargo());
+    if let Some(loaded_sysroot) = loaded_sysroot {
+        sysroot.set_workspace(loaded_sysroot);
+    }
+    assert!(matches!(sysroot.workspace(), RustLibSrcWorkspace::Workspace(_)));
     let project_workspace = ProjectWorkspace {
         kind: ProjectWorkspaceKind::Cargo {
             cargo: cargo_workspace,
diff --git a/crates/rust-analyzer/src/cli/rustc_tests.rs b/crates/rust-analyzer/src/cli/rustc_tests.rs
index 199f61e70f..b9b7ad1faf 100644
--- a/crates/rust-analyzer/src/cli/rustc_tests.rs
+++ b/crates/rust-analyzer/src/cli/rustc_tests.rs
@@ -12,8 +12,8 @@ use paths::Utf8PathBuf;
 use profile::StopWatch;
 use project_model::toolchain_info::{target_data_layout, QueryConfig};
 use project_model::{
-    CargoConfig, ManifestPath, ProjectWorkspace, ProjectWorkspaceKind, RustLibSource, Sysroot,
-    SysrootSourceWorkspaceConfig,
+    CargoConfig, ManifestPath, ProjectWorkspace, ProjectWorkspaceKind, RustLibSource,
+    RustSourceWorkspaceConfig, Sysroot,
 };
 
 use load_cargo::{load_workspace, LoadCargoConfig, ProcMacroServerChoice};
@@ -75,7 +75,11 @@ impl Tester {
         };
 
         let mut sysroot = Sysroot::discover(tmp_file.parent().unwrap(), &cargo_config.extra_env);
-        sysroot.load_workspace(&SysrootSourceWorkspaceConfig::default_cargo());
+        let loaded_sysroot = sysroot.load_workspace(&RustSourceWorkspaceConfig::default_cargo());
+        if let Some(loaded_sysroot) = loaded_sysroot {
+            sysroot.set_workspace(loaded_sysroot);
+        }
+
         let data_layout = target_data_layout::get(
             QueryConfig::Rustc(&sysroot, tmp_file.parent().unwrap().as_ref()),
             None,
diff --git a/crates/rust-analyzer/tests/slow-tests/main.rs b/crates/rust-analyzer/tests/slow-tests/main.rs
index e764bd4770..6f26bdc2cf 100644
--- a/crates/rust-analyzer/tests/slow-tests/main.rs
+++ b/crates/rust-analyzer/tests/slow-tests/main.rs
@@ -1152,7 +1152,11 @@ fn resolve_proc_macro() {
         &AbsPathBuf::assert_utf8(std::env::current_dir().unwrap()),
         &Default::default(),
     );
-    sysroot.load_workspace(&project_model::SysrootSourceWorkspaceConfig::default_cargo());
+    let loaded_sysroot =
+        sysroot.load_workspace(&project_model::RustSourceWorkspaceConfig::default_cargo());
+    if let Some(loaded_sysroot) = loaded_sysroot {
+        sysroot.set_workspace(loaded_sysroot);
+    }
 
     let proc_macro_server_path = sysroot.discover_proc_macro_srv().unwrap();
 
diff --git a/crates/test-fixture/src/lib.rs b/crates/test-fixture/src/lib.rs
index 613f27c795..ca59658359 100644
--- a/crates/test-fixture/src/lib.rs
+++ b/crates/test-fixture/src/lib.rs
@@ -17,7 +17,7 @@ use hir_expand::{
     tt::{Leaf, TokenTree, TopSubtree, TopSubtreeBuilder, TtElement, TtIter},
     FileRange,
 };
-use intern::{sym, Symbol};
+use intern::Symbol;
 use rustc_hash::FxHashMap;
 use span::{Edition, EditionedFileId, FileId, Span};
 use stdx::itertools::Itertools;
@@ -511,21 +511,6 @@ pub fn issue_18898(_attr: TokenStream, input: TokenStream) -> TokenStream {
                 disabled: false,
             },
         ),
-        (
-            r#"
-#[proc_macro_attribute]
-pub fn disallow_cfg(_attr: TokenStream, input: TokenStream) -> TokenStream {
-    input
-}
-"#
-            .into(),
-            ProcMacro {
-                name: Symbol::intern("disallow_cfg"),
-                kind: ProcMacroKind::Attr,
-                expander: sync::Arc::new(DisallowCfgProcMacroExpander),
-                disabled: false,
-            },
-        ),
     ])
 }
 
@@ -880,30 +865,3 @@ impl ProcMacroExpander for Issue18898ProcMacroExpander {
         })
     }
 }
-
-// Reads ident type within string quotes, for issue #17479.
-#[derive(Debug)]
-struct DisallowCfgProcMacroExpander;
-impl ProcMacroExpander for DisallowCfgProcMacroExpander {
-    fn expand(
-        &self,
-        subtree: &TopSubtree,
-        _: Option<&TopSubtree>,
-        _: &Env,
-        _: Span,
-        _: Span,
-        _: Span,
-        _: Option<String>,
-    ) -> Result<TopSubtree, ProcMacroExpansionError> {
-        for tt in subtree.token_trees().flat_tokens() {
-            if let tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) = tt {
-                if ident.sym == sym::cfg || ident.sym == sym::cfg_attr {
-                    return Err(ProcMacroExpansionError::Panic(
-                        "cfg or cfg_attr found in DisallowCfgProcMacroExpander".to_owned(),
-                    ));
-                }
-            }
-        }
-        Ok(subtree.clone())
-    }
-}