Repository: rust-lang/rust-analyzer
Pull request #15260 (2023-07-10 22:01:18)

internal: Migrate assists to the structured snippet API, part 3
Continuing from #15231

Migrates the following assists:
- `add_missing_match_arms`
- `fix_visibility`
- `promote_local_to_const`

The `add_missing_match_arms` changes are best reviewed commit-by-commit since they're relatively big changes compared to the rest of the commits.


Patch:
diff --git a/Cargo.lock b/Cargo.lock
index f880679497..c8c1b881c3 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -600,7 +600,6 @@ dependencies = [
  "limit",
  "nohash-hasher",
  "once_cell",
- "oorandom",
  "profile",
  "project-model",
  "rustc-hash",
diff --git a/crates/hir-expand/src/builtin_derive_macro.rs b/crates/hir-expand/src/builtin_derive_macro.rs
index c8c3cebb88..78218a8345 100644
--- a/crates/hir-expand/src/builtin_derive_macro.rs
+++ b/crates/hir-expand/src/builtin_derive_macro.rs
@@ -12,7 +12,9 @@ use crate::{
     name::{AsName, Name},
     tt::{self, TokenId},
 };
-use syntax::ast::{self, AstNode, FieldList, HasAttrs, HasGenericParams, HasName, HasTypeBounds};
+use syntax::ast::{
+    self, AstNode, FieldList, HasAttrs, HasGenericParams, HasModuleItem, HasName, HasTypeBounds,
+};
 
 use crate::{db::ExpandDatabase, name, quote, ExpandError, ExpandResult, MacroCallId};
 
@@ -28,13 +30,12 @@ macro_rules! register_builtin {
                 &self,
                 db: &dyn ExpandDatabase,
                 id: MacroCallId,
-                tt: &ast::Adt,
-                token_map: &TokenMap,
+                tt: &tt::Subtree,
             ) -> ExpandResult<tt::Subtree> {
                 let expander = match *self {
                     $( BuiltinDeriveExpander::$trait => $expand, )*
                 };
-                expander(db, id, tt, token_map)
+                expander(db, id, tt)
             }
 
             fn find_by_name(name: &name::Name) -> Option<Self> {
@@ -117,13 +118,13 @@ impl VariantShape {
         }
     }
 
-    fn from(tm: &TokenMap, value: Option<FieldList>) -> Result<Self, ExpandError> {
+    fn from(value: Option<FieldList>, token_map: &TokenMap) -> Result<Self, ExpandError> {
         let r = match value {
             None => VariantShape::Unit,
             Some(FieldList::RecordFieldList(it)) => VariantShape::Struct(
                 it.fields()
                     .map(|it| it.name())
-                    .map(|it| name_to_token(tm, it))
+                    .map(|it| name_to_token(token_map, it))
                     .collect::<Result<_, _>>()?,
             ),
             Some(FieldList::TupleFieldList(it)) => VariantShape::Tuple(it.fields().count()),
@@ -189,12 +190,25 @@ struct BasicAdtInfo {
     associated_types: Vec<tt::Subtree>,
 }
 
-fn parse_adt(tm: &TokenMap, adt: &ast::Adt) -> Result<BasicAdtInfo, ExpandError> {
+fn parse_adt(tt: &tt::Subtree) -> Result<BasicAdtInfo, ExpandError> {
+    let (parsed, token_map) = mbe::token_tree_to_syntax_node(tt, mbe::TopEntryPoint::MacroItems);
+    let macro_items = ast::MacroItems::cast(parsed.syntax_node()).ok_or_else(|| {
+        debug!("derive node didn't parse");
+        ExpandError::other("invalid item definition")
+    })?;
+    let item = macro_items.items().next().ok_or_else(|| {
+        debug!("no module item parsed");
+        ExpandError::other("no item found")
+    })?;
+    let adt = ast::Adt::cast(item.syntax().clone()).ok_or_else(|| {
+        debug!("expected adt, found: {:?}", item);
+        ExpandError::other("expected struct, enum or union")
+    })?;
     let (name, generic_param_list, shape) = match &adt {
         ast::Adt::Struct(it) => (
             it.name(),
             it.generic_param_list(),
-            AdtShape::Struct(VariantShape::from(tm, it.field_list())?),
+            AdtShape::Struct(VariantShape::from(it.field_list(), &token_map)?),
         ),
         ast::Adt::Enum(it) => {
             let default_variant = it
@@ -213,8 +227,8 @@ fn parse_adt(tm: &TokenMap, adt: &ast::Adt) -> Result<BasicAdtInfo, ExpandError>
                         .flat_map(|it| it.variants())
                         .map(|it| {
                             Ok((
-                                name_to_token(tm, it.name())?,
-                                VariantShape::from(tm, it.field_list())?,
+                                name_to_token(&token_map, it.name())?,
+                                VariantShape::from(it.field_list(), &token_map)?,
                             ))
                         })
                         .collect::<Result<_, ExpandError>>()?,
@@ -284,7 +298,7 @@ fn parse_adt(tm: &TokenMap, adt: &ast::Adt) -> Result<BasicAdtInfo, ExpandError>
         })
         .map(|it| mbe::syntax_node_to_token_tree(it.syntax()).0)
         .collect();
-    let name_token = name_to_token(&tm, name)?;
+    let name_token = name_to_token(&token_map, name)?;
     Ok(BasicAdtInfo { name: name_token, shape, param_types, associated_types })
 }
 
@@ -331,12 +345,11 @@ fn name_to_token(token_map: &TokenMap, name: Option<ast::Name>) -> Result<tt::Id
 /// where B1, ..., BN are the bounds given by `bounds_paths`. Z is a phantom type, and
 /// therefore does not get bound by the derived trait.
 fn expand_simple_derive(
-    tt: &ast::Adt,
-    tm: &TokenMap,
+    tt: &tt::Subtree,
     trait_path: tt::Subtree,
     make_trait_body: impl FnOnce(&BasicAdtInfo) -> tt::Subtree,
 ) -> ExpandResult<tt::Subtree> {
-    let info = match parse_adt(tm, tt) {
+    let info = match parse_adt(tt) {
         Ok(info) => info,
         Err(e) => return ExpandResult::new(tt::Subtree::empty(), e),
     };
@@ -392,21 +405,19 @@ fn find_builtin_crate(db: &dyn ExpandDatabase, id: MacroCallId) -> tt::TokenTree
 fn copy_expand(
     db: &dyn ExpandDatabase,
     id: MacroCallId,
-    tt: &ast::Adt,
-    tm: &TokenMap,
+    tt: &tt::Subtree,
 ) -> ExpandResult<tt::Subtree> {
     let krate = find_builtin_crate(db, id);
-    expand_simple_derive(tt, tm, quote! { #krate::marker::Copy }, |_| quote! {})
+    expand_simple_derive(tt, quote! { #krate::marker::Copy }, |_| quote! {})
 }
 
 fn clone_expand(
     db: &dyn ExpandDatabase,
     id: MacroCallId,
-    tt: &ast::Adt,
-    tm: &TokenMap,
+    tt: &tt::Subtree,
 ) -> ExpandResult<tt::Subtree> {
     let krate = find_builtin_crate(db, id);
-    expand_simple_derive(tt, tm, quote! { #krate::clone::Clone }, |adt| {
+    expand_simple_derive(tt, quote! { #krate::clone::Clone }, |adt| {
         if matches!(adt.shape, AdtShape::Union) {
             let star = tt::Punct {
                 char: '*',
@@ -468,11 +479,10 @@ fn and_and() -> ::tt::Subtree<TokenId> {
 fn default_expand(
     db: &dyn ExpandDatabase,
     id: MacroCallId,
-    tt: &ast::Adt,
-    tm: &TokenMap,
+    tt: &tt::Subtree,
 ) -> ExpandResult<tt::Subtree> {
     let krate = &find_builtin_crate(db, id);
-    expand_simple_derive(tt, tm, quote! { #krate::default::Default }, |adt| {
+    expand_simple_derive(tt, quote! { #krate::default::Default }, |adt| {
         let body = match &adt.shape {
             AdtShape::Struct(fields) => {
                 let name = &adt.name;
@@ -508,11 +518,10 @@ fn default_expand(
 fn debug_expand(
     db: &dyn ExpandDatabase,
     id: MacroCallId,
-    tt: &ast::Adt,
-    tm: &TokenMap,
+    tt: &tt::Subtree,
 ) -> ExpandResult<tt::Subtree> {
     let krate = &find_builtin_crate(db, id);
-    expand_simple_derive(tt, tm, quote! { #krate::fmt::Debug }, |adt| {
+    expand_simple_derive(tt, quote! { #krate::fmt::Debug }, |adt| {
         let for_variant = |name: String, v: &VariantShape| match v {
             VariantShape::Struct(fields) => {
                 let for_fields = fields.iter().map(|it| {
@@ -589,11 +598,10 @@ fn debug_expand(
 fn hash_expand(
     db: &dyn ExpandDatabase,
     id: MacroCallId,
-    tt: &ast::Adt,
-    tm: &TokenMap,
+    tt: &tt::Subtree,
 ) -> ExpandResult<tt::Subtree> {
     let krate = &find_builtin_crate(db, id);
-    expand_simple_derive(tt, tm, quote! { #krate::hash::Hash }, |adt| {
+    expand_simple_derive(tt, quote! { #krate::hash::Hash }, |adt| {
         if matches!(adt.shape, AdtShape::Union) {
             // FIXME: Return expand error here
             return quote! {};
@@ -638,21 +646,19 @@ fn hash_expand(
 fn eq_expand(
     db: &dyn ExpandDatabase,
     id: MacroCallId,
-    tt: &ast::Adt,
-    tm: &TokenMap,
+    tt: &tt::Subtree,
 ) -> ExpandResult<tt::Subtree> {
     let krate = find_builtin_crate(db, id);
-    expand_simple_derive(tt, tm, quote! { #krate::cmp::Eq }, |_| quote! {})
+    expand_simple_derive(tt, quote! { #krate::cmp::Eq }, |_| quote! {})
 }
 
 fn partial_eq_expand(
     db: &dyn ExpandDatabase,
     id: MacroCallId,
-    tt: &ast::Adt,
-    tm: &TokenMap,
+    tt: &tt::Subtree,
 ) -> ExpandResult<tt::Subtree> {
     let krate = find_builtin_crate(db, id);
-    expand_simple_derive(tt, tm, quote! { #krate::cmp::PartialEq }, |adt| {
+    expand_simple_derive(tt, quote! { #krate::cmp::PartialEq }, |adt| {
         if matches!(adt.shape, AdtShape::Union) {
             // FIXME: Return expand error here
             return quote! {};
@@ -716,11 +722,10 @@ fn self_and_other_patterns(
 fn ord_expand(
     db: &dyn ExpandDatabase,
     id: MacroCallId,
-    tt: &ast::Adt,
-    tm: &TokenMap,
+    tt: &tt::Subtree,
 ) -> ExpandResult<tt::Subtree> {
     let krate = &find_builtin_crate(db, id);
-    expand_simple_derive(tt, tm, quote! { #krate::cmp::Ord }, |adt| {
+    expand_simple_derive(tt, quote! { #krate::cmp::Ord }, |adt| {
         fn compare(
             krate: &tt::TokenTree,
             left: tt::Subtree,
@@ -781,11 +786,10 @@ fn ord_expand(
 fn partial_ord_expand(
     db: &dyn ExpandDatabase,
     id: MacroCallId,
-    tt: &ast::Adt,
-    tm: &TokenMap,
+    tt: &tt::Subtree,
 ) -> ExpandResult<tt::Subtree> {
     let krate = &find_builtin_crate(db, id);
-    expand_simple_derive(tt, tm, quote! { #krate::cmp::PartialOrd }, |adt| {
+    expand_simple_derive(tt, quote! { #krate::cmp::PartialOrd }, |adt| {
         fn compare(
             krate: &tt::TokenTree,
             left: tt::Subtree,
diff --git a/crates/hir-expand/src/db.rs b/crates/hir-expand/src/db.rs
index a2b642cd11..3f08a09869 100644
--- a/crates/hir-expand/src/db.rs
+++ b/crates/hir-expand/src/db.rs
@@ -1,6 +1,6 @@
 //! Defines database & queries for macro expansion.
 
-use base_db::{salsa, CrateId, Edition, SourceDatabase};
+use base_db::{salsa, Edition, SourceDatabase};
 use either::Either;
 use limit::Limit;
 use mbe::syntax_node_to_token_tree;
@@ -13,7 +13,7 @@ use triomphe::Arc;
 
 use crate::{
     ast_id_map::AstIdMap, builtin_attr_macro::pseudo_derive_attr_expansion,
-    builtin_fn_macro::EagerExpander, fixup, hygiene::HygieneFrame, tt, AstId, BuiltinAttrExpander,
+    builtin_fn_macro::EagerExpander, fixup, hygiene::HygieneFrame, tt, BuiltinAttrExpander,
     BuiltinDeriveExpander, BuiltinFnLikeExpander, EagerCallInfo, ExpandError, ExpandResult,
     ExpandTo, HirFileId, HirFileIdRepr, MacroCallId, MacroCallKind, MacroCallLoc, MacroDefId,
     MacroDefKind, MacroFile, ProcMacroExpander,
@@ -27,68 +27,59 @@ use crate::{
 /// Actual max for `analysis-stats .` at some point: 30672.
 static TOKEN_LIMIT: Limit = Limit::new(1_048_576);
 
-#[derive(Debug, Clone, Eq, PartialEq)]
-/// Old-style `macro_rules` or the new macros 2.0
-pub struct DeclarativeMacroExpander {
-    pub mac: mbe::DeclarativeMacro,
-    pub def_site_token_map: mbe::TokenMap,
-}
-
-impl DeclarativeMacroExpander {
-    pub fn expand(&self, tt: tt::Subtree) -> ExpandResult<tt::Subtree> {
-        match self.mac.err() {
-            Some(e) => ExpandResult::new(
-                tt::Subtree::empty(),
-                ExpandError::other(format!("invalid macro definition: {e}")),
-            ),
-            None => self.mac.expand(tt).map_err(Into::into),
-        }
-    }
-
-    pub fn map_id_down(&self, token_id: tt::TokenId) -> tt::TokenId {
-        self.mac.map_id_down(token_id)
-    }
-
-    pub fn map_id_up(&self, token_id: tt::TokenId) -> (tt::TokenId, mbe::Origin) {
-        self.mac.map_id_up(token_id)
-    }
-}
-
 #[derive(Debug, Clone, Eq, PartialEq)]
 pub enum TokenExpander {
-    DeclarativeMacro(Arc<DeclarativeMacroExpander>),
+    /// Old-style `macro_rules` or the new macros 2.0
+    DeclarativeMacro { mac: mbe::DeclarativeMacro, def_site_token_map: mbe::TokenMap },
     /// Stuff like `line!` and `file!`.
-    BuiltIn(BuiltinFnLikeExpander),
+    Builtin(BuiltinFnLikeExpander),
     /// Built-in eagerly expanded fn-like macros (`include!`, `concat!`, etc.)
-    BuiltInEager(EagerExpander),
+    BuiltinEager(EagerExpander),
     /// `global_allocator` and such.
-    BuiltInAttr(BuiltinAttrExpander),
+    BuiltinAttr(BuiltinAttrExpander),
     /// `derive(Copy)` and such.
-    BuiltInDerive(BuiltinDeriveExpander),
+    BuiltinDerive(BuiltinDeriveExpander),
     /// The thing we love the most here in rust-analyzer -- procedural macros.
     ProcMacro(ProcMacroExpander),
 }
 
-// FIXME: Get rid of these methods
 impl TokenExpander {
+    fn expand(
+        &self,
+        db: &dyn ExpandDatabase,
+        id: MacroCallId,
+        tt: &tt::Subtree,
+    ) -> ExpandResult<tt::Subtree> {
+        match self {
+            TokenExpander::DeclarativeMacro { mac, .. } => mac.expand(tt).map_err(Into::into),
+            TokenExpander::Builtin(it) => it.expand(db, id, tt).map_err(Into::into),
+            TokenExpander::BuiltinEager(it) => it.expand(db, id, tt).map_err(Into::into),
+            TokenExpander::BuiltinAttr(it) => it.expand(db, id, tt),
+            TokenExpander::BuiltinDerive(it) => it.expand(db, id, tt),
+            TokenExpander::ProcMacro(_) => {
+                unreachable!("ExpandDatabase::expand_proc_macro should be used for proc macros")
+            }
+        }
+    }
+
     pub(crate) fn map_id_down(&self, id: tt::TokenId) -> tt::TokenId {
         match self {
-            TokenExpander::DeclarativeMacro(expander) => expander.map_id_down(id),
-            TokenExpander::BuiltIn(..)
-            | TokenExpander::BuiltInEager(..)
-            | TokenExpander::BuiltInAttr(..)
-            | TokenExpander::BuiltInDerive(..)
+            TokenExpander::DeclarativeMacro { mac, .. } => mac.map_id_down(id),
+            TokenExpander::Builtin(..)
+            | TokenExpander::BuiltinEager(..)
+            | TokenExpander::BuiltinAttr(..)
+            | TokenExpander::BuiltinDerive(..)
             | TokenExpander::ProcMacro(..) => id,
         }
     }
 
     pub(crate) fn map_id_up(&self, id: tt::TokenId) -> (tt::TokenId, mbe::Origin) {
         match self {
-            TokenExpander::DeclarativeMacro(expander) => expander.map_id_up(id),
-            TokenExpander::BuiltIn(..)
-            | TokenExpander::BuiltInEager(..)
-            | TokenExpander::BuiltInAttr(..)
-            | TokenExpander::BuiltInDerive(..)
+            TokenExpander::DeclarativeMacro { mac, .. } => mac.map_id_up(id),
+            TokenExpander::Builtin(..)
+            | TokenExpander::BuiltinEager(..)
+            | TokenExpander::BuiltinAttr(..)
+            | TokenExpander::BuiltinDerive(..)
             | TokenExpander::ProcMacro(..) => (id, mbe::Origin::Call),
         }
     }
@@ -131,14 +122,7 @@ pub trait ExpandDatabase: SourceDatabase {
     fn macro_arg_text(&self, id: MacroCallId) -> Option<GreenNode>;
     /// Gets the expander for this macro. This compiles declarative macros, and
     /// just fetches procedural ones.
-    // FIXME: Rename this
-    #[salsa::transparent]
-    fn macro_def(&self, id: MacroDefId) -> TokenExpander;
-    fn decl_macro_expander(
-        &self,
-        def_crate: CrateId,
-        id: AstId<ast::Macro>,
-    ) -> Arc<DeclarativeMacroExpander>;
+    fn macro_def(&self, id: MacroDefId) -> Result<Arc<TokenExpander>, mbe::ParseError>;
 
     /// Expand macro call to a token tree.
     // This query is LRU cached
@@ -176,6 +160,7 @@ pub fn expand_speculative(
     token_to_map: SyntaxToken,
 ) -> Option<(SyntaxNode, SyntaxToken)> {
     let loc = db.lookup_intern_macro_call(actual_macro_call);
+    let macro_def = db.macro_def(loc.def).ok()?;
     let token_range = token_to_map.text_range();
 
     // Build the subtree and token mapping for the speculative args
@@ -233,12 +218,7 @@ pub fn expand_speculative(
         None => {
             let range = token_range.checked_sub(speculative_args.text_range().start())?;
             let token_id = spec_args_tmap.token_by_range(range)?;
-            match loc.def.kind {
-                MacroDefKind::Declarative(it) => {
-                    db.decl_macro_expander(loc.krate, it).map_id_down(token_id)
-                }
-                _ => token_id,
-            }
+            macro_def.map_id_down(token_id)
         }
     };
 
@@ -252,17 +232,7 @@ pub fn expand_speculative(
         MacroDefKind::BuiltInAttr(BuiltinAttrExpander::Derive, _) => {
             pseudo_derive_attr_expansion(&tt, attr_arg.as_ref()?)
         }
-        MacroDefKind::BuiltInDerive(expander, ..) => {
-            // this cast is a bit sus, can we avoid losing the typedness here?
-            let adt = ast::Adt::cast(speculative_args.clone()).unwrap();
-            expander.expand(db, actual_macro_call, &adt, &spec_args_tmap)
-        }
-        MacroDefKind::Declarative(it) => db.decl_macro_expander(loc.krate, it).expand(tt),
-        MacroDefKind::BuiltIn(it, _) => it.expand(db, actual_macro_call, &tt).map_err(Into::into),
-        MacroDefKind::BuiltInEager(it, _) => {
-            it.expand(db, actual_macro_call, &tt).map_err(Into::into)
-        }
-        MacroDefKind::BuiltInAttr(it, _) => it.expand(db, actual_macro_call, &tt),
+        _ => macro_def.expand(db, actual_macro_call, &tt),
     };
 
     let expand_to = macro_expand_to(db, actual_macro_call);
@@ -363,9 +333,6 @@ fn macro_arg(
     Some(Arc::new((tt, tmap, fixups.undo_info)))
 }
 
-/// Certain macro calls expect some nodes in the input to be preprocessed away, namely:
-/// - derives expect all `#[derive(..)]` invocations up to the currently invoked one to be stripped
-/// - attributes expect the invoking attribute to be stripped
 fn censor_for_macro_input(loc: &MacroCallLoc, node: &SyntaxNode) -> FxHashSet<SyntaxNode> {
     // FIXME: handle `cfg_attr`
     (|| {
@@ -435,55 +402,44 @@ fn macro_arg_text(db: &dyn ExpandDatabase, id: MacroCallId) -> Option<GreenNode>
     }
 }
 
-fn decl_macro_expander(
+fn macro_def(
     db: &dyn ExpandDatabase,
-    def_crate: CrateId,
-    id: AstId<ast::Macro>,
-) -> Arc<DeclarativeMacroExpander> {
-    let is_2021 = db.crate_graph()[def_crate].edition >= Edition::Edition2021;
-    let (mac, def_site_token_map) = match id.to_node(db) {
-        ast::Macro::MacroRules(macro_rules) => match macro_rules.token_tree() {
-            Some(arg) => {
-                let (tt, def_site_token_map) = mbe::syntax_node_to_token_tree(arg.syntax());
-                let mac = mbe::DeclarativeMacro::parse_macro_rules(&tt, is_2021);
-                (mac, def_site_token_map)
-            }
-            None => (
-                mbe::DeclarativeMacro::from_err(
-                    mbe::ParseError::Expected("expected a token tree".into()),
-                    is_2021,
-                ),
-                Default::default(),
-            ),
-        },
-        ast::Macro::MacroDef(macro_def) => match macro_def.body() {
-            Some(arg) => {
-                let (tt, def_site_token_map) = mbe::syntax_node_to_token_tree(arg.syntax());
-                let mac = mbe::DeclarativeMacro::parse_macro2(&tt, is_2021);
-                (mac, def_site_token_map)
-            }
-            None => (
-                mbe::DeclarativeMacro::from_err(
-                    mbe::ParseError::Expected("expected a token tree".into()),
-                    is_2021,
-                ),
-                Default::default(),
-            ),
-        },
-    };
-    Arc::new(DeclarativeMacroExpander { mac, def_site_token_map })
-}
-
-fn macro_def(db: &dyn ExpandDatabase, id: MacroDefId) -> TokenExpander {
+    id: MacroDefId,
+) -> Result<Arc<TokenExpander>, mbe::ParseError> {
     match id.kind {
         MacroDefKind::Declarative(ast_id) => {
-            TokenExpander::DeclarativeMacro(db.decl_macro_expander(id.krate, ast_id))
+            let is_2021 = db.crate_graph()[id.krate].edition >= Edition::Edition2021;
+            let (mac, def_site_token_map) = match ast_id.to_node(db) {
+                ast::Macro::MacroRules(macro_rules) => {
+                    let arg = macro_rules
+                        .token_tree()
+                        .ok_or_else(|| mbe::ParseError::Expected("expected a token tree".into()))?;
+                    let (tt, def_site_token_map) = mbe::syntax_node_to_token_tree(arg.syntax());
+                    let mac = mbe::DeclarativeMacro::parse_macro_rules(&tt, is_2021)?;
+                    (mac, def_site_token_map)
+                }
+                ast::Macro::MacroDef(macro_def) => {
+                    let arg = macro_def
+                        .body()
+                        .ok_or_else(|| mbe::ParseError::Expected("expected a token tree".into()))?;
+                    let (tt, def_site_token_map) = mbe::syntax_node_to_token_tree(arg.syntax());
+                    let mac = mbe::DeclarativeMacro::parse_macro2(&tt, is_2021)?;
+                    (mac, def_site_token_map)
+                }
+            };
+            Ok(Arc::new(TokenExpander::DeclarativeMacro { mac, def_site_token_map }))
+        }
+        MacroDefKind::BuiltIn(expander, _) => Ok(Arc::new(TokenExpander::Builtin(expander))),
+        MacroDefKind::BuiltInAttr(expander, _) => {
+            Ok(Arc::new(TokenExpander::BuiltinAttr(expander)))
+        }
+        MacroDefKind::BuiltInDerive(expander, _) => {
+            Ok(Arc::new(TokenExpander::BuiltinDerive(expander)))
         }
-        MacroDefKind::BuiltIn(expander, _) => TokenExpander::BuiltIn(expander),
-        MacroDefKind::BuiltInAttr(expander, _) => TokenExpander::BuiltInAttr(expander),
-        MacroDefKind::BuiltInDerive(expander, _) => TokenExpander::BuiltInDerive(expander),
-        MacroDefKind::BuiltInEager(expander, ..) => TokenExpander::BuiltInEager(expander),
-        MacroDefKind::ProcMacro(expander, ..) => TokenExpander::ProcMacro(expander),
+        MacroDefKind::BuiltInEager(expander, ..) => {
+            Ok(Arc::new(TokenExpander::BuiltinEager(expander)))
+        }
+        MacroDefKind::ProcMacro(expander, ..) => Ok(Arc::new(TokenExpander::ProcMacro(expander))),
     }
 }
 
@@ -495,53 +451,37 @@ fn macro_expand(db: &dyn ExpandDatabase, id: MacroCallId) -> ExpandResult<Arc<tt
         return ExpandResult { value: Arc::new(arg.0.clone()), err: error.clone() };
     }
 
-    let (ExpandResult { value: mut tt, mut err }, tmap) = match loc.def.kind {
-        MacroDefKind::ProcMacro(..) => return db.expand_proc_macro(id),
-        MacroDefKind::BuiltInDerive(expander, ..) => {
-            let arg = db.macro_arg_text(id).unwrap();
-
-            let node = SyntaxNode::new_root(arg);
-            let censor = censor_for_macro_input(&loc, &node);
-            let mut fixups = fixup::fixup_syntax(&node);
-            fixups.replace.extend(censor.into_iter().map(|node| (node.into(), Vec::new())));
-            let (tmap, _) = mbe::syntax_node_to_token_map_with_modifications(
-                &node,
-                fixups.token_map,
-                fixups.next_id,
-                fixups.replace,
-                fixups.append,
-            );
-
-            // this cast is a bit sus, can we avoid losing the typedness here?
-            let adt = ast::Adt::cast(node).unwrap();
-            (expander.expand(db, id, &adt, &tmap), Some((tmap, fixups.undo_info)))
-        }
-        _ => {
-            let Some(macro_arg) = db.macro_arg(id) else {
-                return ExpandResult {
-                    value: Arc::new(tt::Subtree {
-                        delimiter: tt::Delimiter::UNSPECIFIED,
-                        token_trees: Vec::new(),
-                    }),
-                    // FIXME: We should make sure to enforce an invariant that invalid macro
-                    // calls do not reach this call path!
-                    err: Some(ExpandError::other("invalid token tree")),
-                };
-            };
-            let (arg, arg_tm, undo_info) = &*macro_arg;
-            let mut res = match loc.def.kind {
-                MacroDefKind::Declarative(id) => {
-                    db.decl_macro_expander(loc.def.krate, id).expand(arg.clone())
-                }
-                MacroDefKind::BuiltIn(it, _) => it.expand(db, id, &arg).map_err(Into::into),
-                MacroDefKind::BuiltInEager(it, _) => it.expand(db, id, &arg).map_err(Into::into),
-                MacroDefKind::BuiltInAttr(it, _) => it.expand(db, id, &arg),
-                _ => unreachable!(),
-            };
-            fixup::reverse_fixups(&mut res.value, arg_tm, undo_info);
-            (res, None)
+    if let MacroDefKind::ProcMacro(..) = loc.def.kind {
+        return db.expand_proc_macro(id);
+    }
+
+    let expander = match db.macro_def(loc.def) {
+        Ok(it) => it,
+        // FIXME: We should make sure to enforce a variant that invalid macro
+        // definitions do not get expanders that could reach this call path!
+        Err(err) => {
+            return ExpandResult {
+                value: Arc::new(tt::Subtree {
+                    delimiter: tt::Delimiter::UNSPECIFIED,
+                    token_trees: vec![],
+                }),
+                err: Some(ExpandError::other(format!("invalid macro definition: {err}"))),
+            }
         }
     };
+    let Some(macro_arg) = db.macro_arg(id) else {
+        return ExpandResult {
+            value: Arc::new(tt::Subtree {
+                delimiter: tt::Delimiter::UNSPECIFIED,
+                token_trees: Vec::new(),
+            }),
+            // FIXME: We should make sure to enforce an invariant that invalid macro
+            // calls do not reach this call path!
+            err: Some(ExpandError::other("invalid token tree")),
+        };
+    };
+    let (arg_tt, arg_tm, undo_info) = &*macro_arg;
+    let ExpandResult { value: mut tt, mut err } = expander.expand(db, id, arg_tt);
 
     if let Some(EagerCallInfo { error, .. }) = loc.eager.as_deref() {
         // FIXME: We should report both errors!
@@ -553,9 +493,7 @@ fn macro_expand(db: &dyn ExpandDatabase, id: MacroCallId) -> ExpandResult<Arc<tt
         return value;
     }
 
-    if let Some((arg_tm, undo_info)) = &tmap {
-        fixup::reverse_fixups(&mut tt, arg_tm, undo_info);
-    }
+    fixup::reverse_fixups(&mut tt, arg_tm, undo_info);
 
     ExpandResult { value: Arc::new(tt), err }
 }
diff --git a/crates/hir-expand/src/hygiene.rs b/crates/hir-expand/src/hygiene.rs
index b2921bb173..10f8fe9cec 100644
--- a/crates/hir-expand/src/hygiene.rs
+++ b/crates/hir-expand/src/hygiene.rs
@@ -126,7 +126,7 @@ struct HygieneInfo {
     /// The start offset of the `macro_rules!` arguments or attribute input.
     attr_input_or_mac_def_start: Option<InFile<TextSize>>,
 
-    macro_def: TokenExpander,
+    macro_def: Arc<TokenExpander>,
     macro_arg: Arc<(crate::tt::Subtree, mbe::TokenMap, fixup::SyntaxFixupUndoInfo)>,
     macro_arg_shift: mbe::Shift,
     exp_map: Arc<mbe::TokenMap>,
@@ -159,9 +159,9 @@ impl HygieneInfo {
                     &self.macro_arg.1,
                     InFile::new(loc.kind.file_id(), loc.kind.arg(db)?.text_range().start()),
                 ),
-                mbe::Origin::Def => match (&self.macro_def, &self.attr_input_or_mac_def_start) {
-                    (TokenExpander::DeclarativeMacro(expander), Some(tt)) => {
-                        (&expander.def_site_token_map, *tt)
+                mbe::Origin::Def => match (&*self.macro_def, &self.attr_input_or_mac_def_start) {
+                    (TokenExpander::DeclarativeMacro { def_site_token_map, .. }, Some(tt)) => {
+                        (def_site_token_map, *tt)
                     }
                     _ => panic!("`Origin::Def` used with non-`macro_rules!` macro"),
                 },
@@ -198,7 +198,7 @@ fn make_hygiene_info(
         _ => None,
     });
 
-    let macro_def = db.macro_def(loc.def);
+    let macro_def = db.macro_def(loc.def).ok()?;
     let (_, exp_map) = db.parse_macro_expansion(macro_file).value;
     let macro_arg = db.macro_arg(macro_file.macro_call_id).unwrap_or_else(|| {
         Arc::new((
diff --git a/crates/hir-expand/src/lib.rs b/crates/hir-expand/src/lib.rs
index a92c17f4ed..3a534f56e4 100644
--- a/crates/hir-expand/src/lib.rs
+++ b/crates/hir-expand/src/lib.rs
@@ -274,7 +274,7 @@ impl HirFileId {
 
         let arg_tt = loc.kind.arg(db)?;
 
-        let macro_def = db.macro_def(loc.def);
+        let macro_def = db.macro_def(loc.def).ok()?;
         let (parse, exp_map) = db.parse_macro_expansion(macro_file).value;
         let macro_arg = db.macro_arg(macro_file.macro_call_id).unwrap_or_else(|| {
             Arc::new((
@@ -287,7 +287,7 @@ impl HirFileId {
         let def = loc.def.ast_id().left().and_then(|id| {
             let def_tt = match id.to_node(db) {
                 ast::Macro::MacroRules(mac) => mac.token_tree()?,
-                ast::Macro::MacroDef(_) if matches!(macro_def, TokenExpander::BuiltInAttr(_)) => {
+                ast::Macro::MacroDef(_) if matches!(*macro_def, TokenExpander::BuiltinAttr(_)) => {
                     return None
                 }
                 ast::Macro::MacroDef(mac) => mac.body()?,
@@ -633,7 +633,7 @@ pub struct ExpansionInfo {
     /// The `macro_rules!` or attribute input.
     attr_input_or_mac_def: Option<InFile<ast::TokenTree>>,
 
-    macro_def: TokenExpander,
+    macro_def: Arc<TokenExpander>,
     macro_arg: Arc<(tt::Subtree, mbe::TokenMap, fixup::SyntaxFixupUndoInfo)>,
     /// A shift built from `macro_arg`'s subtree, relevant for attributes as the item is the macro arg
     /// and as such we need to shift tokens if they are part of an attributes input instead of their item.
@@ -780,9 +780,9 @@ impl ExpansionInfo {
             }
             _ => match origin {
                 mbe::Origin::Call => (&self.macro_arg.1, self.arg.clone()),
-                mbe::Origin::Def => match (&self.macro_def, &self.attr_input_or_mac_def) {
-                    (TokenExpander::DeclarativeMacro(expander), Some(tt)) => {
-                        (&expander.def_site_token_map, tt.syntax().cloned())
+                mbe::Origin::Def => match (&*self.macro_def, &self.attr_input_or_mac_def) {
+                    (TokenExpander::DeclarativeMacro { def_site_token_map, .. }, Some(tt)) => {
+                        (def_site_token_map, tt.syntax().cloned())
                     }
                     _ => panic!("`Origin::Def` used with non-`macro_rules!` macro"),
                 },
diff --git a/crates/hir-ty/Cargo.toml b/crates/hir-ty/Cargo.toml
index abc19d63ab..f462ca3dff 100644
--- a/crates/hir-ty/Cargo.toml
+++ b/crates/hir-ty/Cargo.toml
@@ -19,7 +19,6 @@ bitflags = "2.1.0"
 smallvec.workspace = true
 ena = "0.14.0"
 either = "1.7.0"
-oorandom = "11.1.3"
 tracing = "0.1.35"
 rustc-hash = "1.1.0"
 scoped-tls = "1.0.0"
diff --git a/crates/hir-ty/src/mir/eval.rs b/crates/hir-ty/src/mir/eval.rs
index a1bab09795..010ebcbd06 100644
--- a/crates/hir-ty/src/mir/eval.rs
+++ b/crates/hir-ty/src/mir/eval.rs
@@ -137,7 +137,6 @@ pub struct Evaluator<'a> {
     /// time of use.
     vtable_map: VTableMap,
     thread_local_storage: TlsData,
-    random_state: oorandom::Rand64,
     stdout: Vec<u8>,
     stderr: Vec<u8>,
     layout_cache: RefCell<FxHashMap<Ty, Arc<Layout>>>,
@@ -148,8 +147,6 @@ pub struct Evaluator<'a> {
     execution_limit: usize,
     /// An additional limit on stack depth, to prevent stack overflow
     stack_depth_limit: usize,
-    /// Maximum count of bytes that heap and stack can grow
-    memory_limit: usize,
 }
 
 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@@ -523,7 +520,6 @@ impl Evaluator<'_> {
             thread_local_storage: TlsData::default(),
             static_locations: HashMap::default(),
             db,
-            random_state: oorandom::Rand64::new(0),
             trait_env,
             crate_id,
             stdout: vec![],
@@ -531,7 +527,6 @@ impl Evaluator<'_> {
             assert_placeholder_ty_is_unused,
             stack_depth_limit: 100,
             execution_limit: 1000_000,
-            memory_limit: 1000_000_000, // 2GB, 1GB for stack and 1GB for heap
             layout_cache: RefCell::new(HashMap::default()),
         }
     }
@@ -943,11 +938,6 @@ impl Evaluator<'_> {
         };
         locals.ptr = locals_ptr;
         let prev_stack_pointer = self.stack.len();
-        if stack_size > self.memory_limit {
-            return Err(MirEvalError::Panic(format!(
-                "Stack overflow. Tried to grow stack to {stack_size} bytes"
-            )));
-        }
         self.stack.extend(iter::repeat(0).take(stack_size));
         Ok((locals, prev_stack_pointer))
     }
@@ -1190,7 +1180,7 @@ impl Evaluator<'_> {
                 let Some((size, align)) = self.size_align_of(ty, locals)? else {
                     not_supported!("unsized box initialization");
                 };
-                let addr = self.heap_allocate(size, align)?;
+                let addr = self.heap_allocate(size, align);
                 Owned(addr.to_bytes())
             }
             Rvalue::CopyForDeref(_) => not_supported!("copy for deref"),
@@ -1575,7 +1565,7 @@ impl Evaluator<'_> {
             ConstScalar::Bytes(v, memory_map) => {
                 let mut v: Cow<'_, [u8]> = Cow::Borrowed(v);
                 let patch_map = memory_map.transform_addresses(|b, align| {
-                    let addr = self.heap_allocate(b.len(), align)?;
+                    let addr = self.heap_allocate(b.len(), align);
                     self.write_memory(addr, b)?;
                     Ok(addr.to_usize())
                 })?;
@@ -1590,7 +1580,7 @@ impl Evaluator<'_> {
                         return Err(MirEvalError::InvalidConst(konst.clone()));
                     }
                 }
-                let addr = self.heap_allocate(size, align)?;
+                let addr = self.heap_allocate(size, align);
                 self.write_memory(addr, &v)?;
                 self.patch_addresses(&patch_map, &memory_map.vtable, addr, ty, locals)?;
                 Interval::new(addr, size)
@@ -1693,19 +1683,13 @@ impl Evaluator<'_> {
         }
     }
 
-    fn heap_allocate(&mut self, size: usize, align: usize) -> Result<Address> {
-        if !align.is_power_of_two() || align > 10000 {
-            return Err(MirEvalError::UndefinedBehavior(format!("Alignment {align} is invalid")));
-        }
+    fn heap_allocate(&mut self, size: usize, align: usize) -> Address {
         while self.heap.len() % align != 0 {
             self.heap.push(0);
         }
-        if size.checked_add(self.heap.len()).map_or(true, |x| x > self.memory_limit) {
-            return Err(MirEvalError::Panic(format!("Memory allocation of {size} bytes failed")));
-        }
         let pos = self.heap.len();
         self.heap.extend(iter::repeat(0).take(size));
-        Ok(Address::Heap(pos))
+        Address::Heap(pos)
     }
 
     fn detect_fn_trait(&self, def: FunctionId) -> Option<FnTrait> {
@@ -2216,7 +2200,7 @@ impl Evaluator<'_> {
                     )?;
                     // FIXME: there is some leak here
                     let size = layout.size.bytes_usize();
-                    let addr = self.heap_allocate(size, layout.align.abi.bytes() as usize)?;
+                    let addr = self.heap_allocate(size, layout.align.abi.bytes() as usize);
                     self.write_memory(addr, &result)?;
                     IntervalAndTy { interval: Interval { addr, size }, ty }
                 };
@@ -2251,10 +2235,10 @@ impl Evaluator<'_> {
             let Some((size, align)) = self.size_align_of(&ty, locals)? else {
                 not_supported!("unsized extern static");
             };
-            let addr = self.heap_allocate(size, align)?;
+            let addr = self.heap_allocate(size, align);
             Interval::new(addr, size)
         };
-        let addr = self.heap_allocate(self.ptr_size(), self.ptr_size())?;
+        let addr = self.heap_allocate(self.ptr_size(), self.ptr_size());
         self.write_memory(addr, &result.addr.to_bytes())?;
         self.static_locations.insert(st, addr);
         Ok(addr)
@@ -2414,11 +2398,11 @@ pub fn render_const_using_debug_impl(
         not_supported!("core::fmt::Debug::fmt not found");
     };
     // a1 = &[""]
-    let a1 = evaluator.heap_allocate(evaluator.ptr_size() * 2, evaluator.ptr_size())?;
+    let a1 = evaluator.heap_allocate(evaluator.ptr_size() * 2, evaluator.ptr_size());
     // a2 = &[::core::fmt::ArgumentV1::new(&(THE_CONST), ::core::fmt::Debug::fmt)]
     // FIXME: we should call the said function, but since its name is going to break in the next rustc version
     // and its ABI doesn't break yet, we put it in memory manually.
-    let a2 = evaluator.heap_allocate(evaluator.ptr_size() * 2, evaluator.ptr_size())?;
+    let a2 = evaluator.heap_allocate(evaluator.ptr_size() * 2, evaluator.ptr_size());
     evaluator.write_memory(a2, &data.addr.to_bytes())?;
     let debug_fmt_fn_ptr = evaluator.vtable_map.id(TyKind::FnDef(
         db.intern_callable_def(debug_fmt_fn.into()).into(),
@@ -2428,7 +2412,7 @@ pub fn render_const_using_debug_impl(
     evaluator.write_memory(a2.offset(evaluator.ptr_size()), &debug_fmt_fn_ptr.to_le_bytes())?;
     // a3 = ::core::fmt::Arguments::new_v1(a1, a2)
     // FIXME: similarly, we should call function here, not directly working with memory.
-    let a3 = evaluator.heap_allocate(evaluator.ptr_size() * 6, evaluator.ptr_size())?;
+    let a3 = evaluator.heap_allocate(evaluator.ptr_size() * 6, evaluator.ptr_size());
     evaluator.write_memory(a3.offset(2 * evaluator.ptr_size()), &a1.to_bytes())?;
     evaluator.write_memory(a3.offset(3 * evaluator.ptr_size()), &[1])?;
     evaluator.write_memory(a3.offset(4 * evaluator.ptr_size()), &a2.to_bytes())?;
diff --git a/crates/hir-ty/src/mir/eval/shim.rs b/crates/hir-ty/src/mir/eval/shim.rs
index 3b8b720122..6cdf9f03c9 100644
--- a/crates/hir-ty/src/mir/eval/shim.rs
+++ b/crates/hir-ty/src/mir/eval/shim.rs
@@ -140,7 +140,7 @@ impl Evaluator<'_> {
                 };
                 let size = from_bytes!(usize, size.get(self)?);
                 let align = from_bytes!(usize, align.get(self)?);
-                let result = self.heap_allocate(size, align)?;
+                let result = self.heap_allocate(size, align);
                 destination.write_from_bytes(self, &result.to_bytes())?;
             }
             "rustc_deallocator" => { /* no-op for now */ }
@@ -155,7 +155,7 @@ impl Evaluator<'_> {
                 } else {
                     let ptr = Address::from_bytes(ptr.get(self)?)?;
                     let align = from_bytes!(usize, align.get(self)?);
-                    let result = self.heap_allocate(new_size, align)?;
+                    let result = self.heap_allocate(new_size, align);
                     Interval { addr: result, size: old_size }
                         .write_from_interval(self, Interval { addr: ptr, size: old_size })?;
                     destination.write_from_bytes(self, &result.to_bytes())?;
@@ -239,34 +239,6 @@ impl Evaluator<'_> {
         }
     }
 
-    fn exec_syscall(
-        &mut self,
-        id: i64,
-        args: &[IntervalAndTy],
-        destination: Interval,
-        _locals: &Locals,
-        _span: MirSpan,
-    ) -> Result<()> {
-        match id {
-            318 => {
-                // SYS_getrandom
-                let [buf, len, _flags] = args else {
-                    return Err(MirEvalError::TypeError("SYS_getrandom args are not provided"));
-                };
-                let addr = Address::from_bytes(buf.get(self)?)?;
-                let size = from_bytes!(usize, len.get(self)?);
-                for i in 0..size {
-                    let rand_byte = self.random_state.rand_u64() as u8;
-                    self.write_memory(addr.offset(i), &[rand_byte])?;
-                }
-                destination.write_from_interval(self, len.interval)
-            }
-            _ => {
-                not_supported!("Unknown syscall id {id:?}")
-            }
-        }
-    }
-
     fn exec_extern_c(
         &mut self,
         as_str: &str,
@@ -274,7 +246,7 @@ impl Evaluator<'_> {
         _generic_args: &Substitution,
         destination: Interval,
         locals: &Locals,
-        span: MirSpan,
+        _span: MirSpan,
     ) -> Result<()> {
         match as_str {
             "memcmp" => {
@@ -371,15 +343,6 @@ impl Evaluator<'_> {
                 destination.write_from_bytes(self, &0u64.to_le_bytes()[0..destination.size])?;
                 Ok(())
             }
-            "syscall" => {
-                let Some((id, rest)) = args.split_first() else {
-                    return Err(MirEvalError::TypeError(
-                        "syscall arg1 is not provided",
-                    ));
-                };
-                let id = from_bytes!(i64, id.get(self)?);
-                self.exec_syscall(id, rest, destination, locals, span)
-            }
             _ => not_supported!("unknown external function {as_str}"),
         }
     }
@@ -925,13 +888,6 @@ impl Evaluator<'_> {
                 }
                 not_supported!("FnOnce was not available for executing const_eval_select");
             }
-            "read_via_copy" | "volatile_load" => {
-                let [arg] = args else {
-                    return Err(MirEvalError::TypeError("read_via_copy args are not provided"));
-                };
-                let addr = Address::from_bytes(arg.interval.get(self)?)?;
-                destination.write_from_interval(self, Interval { addr, size: destination.size })
-            }
             _ => not_supported!("unknown intrinsic {name}"),
         }
     }
diff --git a/crates/hir-ty/src/mir/eval/shim/simd.rs b/crates/hir-ty/src/mir/eval/shim/simd.rs
index bc9529d38f..64fd130182 100644
--- a/crates/hir-ty/src/mir/eval/shim/simd.rs
+++ b/crates/hir-ty/src/mir/eval/shim/simd.rs
@@ -22,7 +22,7 @@ macro_rules! not_supported {
 }
 
 impl Evaluator<'_> {
-    fn detect_simd_ty(&self, ty: &Ty) -> Result<(usize, Ty)> {
+    fn detect_simd_ty(&self, ty: &Ty) -> Result<usize> {
         match ty.kind(Interner) {
             TyKind::Adt(id, subst) => {
                 let len = match subst.as_slice(Interner).get(1).and_then(|it| it.constant(Interner))
@@ -30,21 +30,13 @@ impl Evaluator<'_> {
                     Some(len) => len,
                     _ => {
                         if let AdtId::StructId(id) = id.0 {
-                            let struct_data = self.db.struct_data(id);
-                            let fields = struct_data.variant_data.fields();
-                            let Some((first_field, _)) = fields.iter().next() else {
-                                not_supported!("simd type with no field");
-                            };
-                            let field_ty = self.db.field_types(id.into())[first_field]
-                                .clone()
-                                .substitute(Interner, subst);
-                            return Ok((fields.len(), field_ty));
+                            return Ok(self.db.struct_data(id).variant_data.fields().len());
                         }
                         return Err(MirEvalError::TypeError("simd type with no len param"));
                     }
                 };
                 match try_const_usize(self.db, len) {
-                    Some(_) => not_supported!("array like simd type"),
+                    Some(it) => Ok(it as usize),
                     None => Err(MirEvalError::TypeError("simd type with unevaluatable len param")),
                 }
             }
@@ -83,8 +75,7 @@ impl Evaluator<'_> {
                 let [left, right] = args else {
                     return Err(MirEvalError::TypeError("simd args are not provided"));
                 };
-                let (len, ty) = self.detect_simd_ty(&left.ty)?;
-                let is_signed = matches!(ty.as_builtin(), Some(BuiltinType::Int(_)));
+                let len = self.detect_simd_ty(&left.ty)?;
                 let size = left.interval.size / len;
                 let dest_size = destination.size / len;
                 let mut destination_bytes = vec![];
@@ -98,13 +89,6 @@ impl Evaluator<'_> {
                             break;
                         }
                     }
-                    if is_signed {
-                        if let Some((&l, &r)) = l.iter().zip(r).rev().next() {
-                            if l != r {
-                                result = (l as i8).cmp(&(r as i8));
-                            }
-                        }
-                    }
                     let result = match result {
                         Ordering::Less => ["lt", "le", "ne"].contains(&name),
                         Ordering::Equal => ["ge", "le", "eq"].contains(&name),
@@ -118,9 +102,9 @@ impl Evaluator<'_> {
             }
             "bitmask" => {
                 let [op] = args else {
-                    return Err(MirEvalError::TypeError("simd_bitmask args are not provided"));
+                    return Err(MirEvalError::TypeError("simd_shuffle args are not provided"));
                 };
-                let (op_len, _) = self.detect_simd_ty(&op.ty)?;
+                let op_len = self.detect_simd_ty(&op.ty)?;
                 let op_count = op.interval.size / op_len;
                 let mut result: u64 = 0;
                 for (i, val) in op.get(self)?.chunks(op_count).enumerate() {
@@ -147,7 +131,7 @@ impl Evaluator<'_> {
                         ))
                     }
                 };
-                let (left_len, _) = self.detect_simd_ty(&left.ty)?;
+                let left_len = self.detect_simd_ty(&left.ty)?;
                 let left_size = left.interval.size / left_len;
                 let vector =
                     left.get(self)?.chunks(left_size).chain(right.get(self)?.chunks(left_size));
diff --git a/crates/hir-ty/src/mir/lower/pattern_matching.rs b/crates/hir-ty/src/mir/lower/pattern_matching.rs
index 3354cbd76a..ff43c64a9e 100644
--- a/crates/hir-ty/src/mir/lower/pattern_matching.rs
+++ b/crates/hir-ty/src/mir/lower/pattern_matching.rs
@@ -307,11 +307,6 @@ impl MirLowerCtx<'_> {
                     mode,
                 )?,
                 None => {
-                    // The path is not a variant, so it is a const
-                    if mode != MatchingMode::Check {
-                        // A const don't bind anything. Only needs check.
-                        return Ok((current, current_else));
-                    }
                     let unresolved_name = || MirLowerError::unresolved_path(self.db, p);
                     let resolver = self.owner.resolver(self.db.upcast());
                     let pr = resolver
@@ -367,8 +362,8 @@ impl MirLowerCtx<'_> {
             },
             Pat::Lit(l) => match &self.body.exprs[*l] {
                 Expr::Literal(l) => {
+                    let c = self.lower_literal_to_operand(self.infer[pattern].clone(), l)?;
                     if mode == MatchingMode::Check {
-                        let c = self.lower_literal_to_operand(self.infer[pattern].clone(), l)?;
                         self.pattern_match_const(current_else, current, c, cond_place, pattern)?
                     } else {
                         (current, current_else)
diff --git a/crates/hir/src/db.rs b/crates/hir/src/db.rs
index fa2deb7215..e0cde689fe 100644
--- a/crates/hir/src/db.rs
+++ b/crates/hir/src/db.rs
@@ -5,9 +5,9 @@
 //! But we need this for at least LRU caching at the query level.
 pub use hir_def::db::*;
 pub use hir_expand::db::{
-    AstIdMapQuery, DeclMacroExpanderQuery, ExpandDatabase, ExpandDatabaseStorage,
-    ExpandProcMacroQuery, HygieneFrameQuery, InternMacroCallQuery, MacroArgTextQuery,
-    MacroExpandQuery, ParseMacroExpansionErrorQuery, ParseMacroExpansionQuery,
+    AstIdMapQuery, ExpandDatabase, ExpandDatabaseStorage, ExpandProcMacroQuery, HygieneFrameQuery,
+    InternMacroCallQuery, MacroArgTextQuery, MacroDefQuery, MacroExpandQuery,
+    ParseMacroExpansionErrorQuery, ParseMacroExpansionQuery,
 };
 pub use hir_ty::db::*;
 
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index d09963d4d3..44f901fb3a 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -698,18 +698,16 @@ impl Module {
 
 fn emit_macro_def_diagnostics(db: &dyn HirDatabase, acc: &mut Vec<AnyDiagnostic>, m: Macro) {
     let id = macro_id_to_def_id(db.upcast(), m.id);
-    if let hir_expand::db::TokenExpander::DeclarativeMacro(expander) = db.macro_def(id) {
-        if let Some(e) = expander.mac.err() {
-            let Some(ast) = id.ast_id().left() else {
-                never!("declarative expander for non decl-macro: {:?}", e);
-                return;
-            };
-            emit_def_diagnostic_(
-                db,
-                acc,
-                &DefDiagnosticKind::MacroDefError { ast, message: e.to_string() },
-            );
-        }
+    if let Err(e) = db.macro_def(id) {
+        let Some(ast) = id.ast_id().left() else {
+            never!("MacroDefError for proc-macro: {:?}", e);
+            return;
+        };
+        emit_def_diagnostic_(
+            db,
+            acc,
+            &DefDiagnosticKind::MacroDefError { ast, message: e.to_string() },
+        );
     }
 }
 
diff --git a/crates/ide-assists/src/handlers/add_missing_match_arms.rs b/crates/ide-assists/src/handlers/add_missing_match_arms.rs
index 7384390f28..ac0b74ee8e 100644
--- a/crates/ide-assists/src/handlers/add_missing_match_arms.rs
+++ b/crates/ide-assists/src/handlers/add_missing_match_arms.rs
@@ -8,10 +8,7 @@ use itertools::Itertools;
 use syntax::ast::edit_in_place::Removable;
 use syntax::ast::{self, make, AstNode, HasName, MatchArmList, MatchExpr, Pat};
 
-use crate::{
-    utils::{self, render_snippet, Cursor},
-    AssistContext, AssistId, AssistKind, Assists,
-};
+use crate::{utils, AssistContext, AssistId, AssistKind, Assists};
 
 // Assist: add_missing_match_arms
 //
@@ -75,14 +72,18 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>)
         .collect();
 
     let module = ctx.sema.scope(expr.syntax())?.module();
-    let (mut missing_pats, is_non_exhaustive): (
+    let (mut missing_pats, is_non_exhaustive, has_hidden_variants): (
         Peekable<Box<dyn Iterator<Item = (ast::Pat, bool)>>>,
         bool,
+        bool,
     ) = if let Some(enum_def) = resolve_enum_def(&ctx.sema, &expr) {
         let is_non_exhaustive = enum_def.is_non_exhaustive(ctx.db(), module.krate());
 
         let variants = enum_def.variants(ctx.db());
 
+        let has_hidden_variants =
+            variants.iter().any(|variant| variant.should_be_hidden(ctx.db(), module.krate()));
+
         let missing_pats = variants
             .into_iter()
             .filter_map(|variant| {
@@ -101,7 +102,7 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>)
         } else {
             Box::new(missing_pats)
         };
-        (missing_pats.peekable(), is_non_exhaustive)
+        (missing_pats.peekable(), is_non_exhaustive, has_hidden_variants)
     } else if let Some(enum_defs) = resolve_tuple_of_enum_def(&ctx.sema, &expr) {
         let is_non_exhaustive =
             enum_defs.iter().any(|enum_def| enum_def.is_non_exhaustive(ctx.db(), module.krate()));
@@ -124,6 +125,12 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>)
         if n_arms > 256 {
             return None;
         }
+
+        let has_hidden_variants = variants_of_enums
+            .iter()
+            .flatten()
+            .any(|variant| variant.should_be_hidden(ctx.db(), module.krate()));
+
         let missing_pats = variants_of_enums
             .into_iter()
             .multi_cartesian_product()
@@ -139,7 +146,11 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>)
                 (ast::Pat::from(make::tuple_pat(patterns)), is_hidden)
             })
             .filter(|(variant_pat, _)| is_variant_missing(&top_lvl_pats, variant_pat));
-        ((Box::new(missing_pats) as Box<dyn Iterator<Item = _>>).peekable(), is_non_exhaustive)
+        (
+            (Box::new(missing_pats) as Box<dyn Iterator<Item = _>>).peekable(),
+            is_non_exhaustive,
+            has_hidden_variants,
+        )
     } else if let Some((enum_def, len)) = resolve_array_of_enum_def(&ctx.sema, &expr) {
         let is_non_exhaustive = enum_def.is_non_exhaustive(ctx.db(), module.krate());
         let variants = enum_def.variants(ctx.db());
@@ -148,6 +159,9 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>)
             return None;
         }
 
+        let has_hidden_variants =
+            variants.iter().any(|variant| variant.should_be_hidden(ctx.db(), module.krate()));
+
         let variants_of_enums = vec![variants; len];
 
         let missing_pats = variants_of_enums
@@ -164,14 +178,20 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>)
                 (ast::Pat::from(make::slice_pat(patterns)), is_hidden)
             })
             .filter(|(variant_pat, _)| is_variant_missing(&top_lvl_pats, variant_pat));
-        ((Box::new(missing_pats) as Box<dyn Iterator<Item = _>>).peekable(), is_non_exhaustive)
+        (
+            (Box::new(missing_pats) as Box<dyn Iterator<Item = _>>).peekable(),
+            is_non_exhaustive,
+            has_hidden_variants,
+        )
     } else {
         return None;
     };
 
     let mut needs_catch_all_arm = is_non_exhaustive && !has_catch_all_arm;
 
-    if !needs_catch_all_arm && missing_pats.peek().is_none() {
+    if !needs_catch_all_arm
+        && ((has_hidden_variants && has_catch_all_arm) || missing_pats.peek().is_none())
+    {
         return None;
     }
 
@@ -179,13 +199,21 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>)
         AssistId("add_missing_match_arms", AssistKind::QuickFix),
         "Fill match arms",
         target_range,
-        |builder| {
+        |edit| {
             let new_match_arm_list = match_arm_list.clone_for_update();
+
+            // having any hidden variants means that we need a catch-all arm
+            needs_catch_all_arm |= has_hidden_variants;
+
             let missing_arms = missing_pats
-                .map(|(pat, hidden)| {
-                    (make::match_arm(iter::once(pat), None, make::ext::expr_todo()), hidden)
+                .filter(|(_, hidden)| {
+                    // filter out hidden patterns because they're handled by the catch-all arm
+                    !hidden
                 })
-                .map(|(it, hidden)| (it.clone_for_update(), hidden));
+                .map(|(pat, _)| {
+                    make::match_arm(iter::once(pat), None, make::ext::expr_todo())
+                        .clone_for_update()
+                });
 
             let catch_all_arm = new_match_arm_list
                 .arms()
@@ -204,15 +232,13 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>)
                     cov_mark::hit!(add_missing_match_arms_empty_expr);
                 }
             }
+
             let mut first_new_arm = None;
-            for (arm, hidden) in missing_arms {
-                if hidden {
-                    needs_catch_all_arm = !has_catch_all_arm;
-                } else {
-                    first_new_arm.get_or_insert_with(|| arm.clone());
-                    new_match_arm_list.add_arm(arm);
-                }
+            for arm in missing_arms {
+                first_new_arm.get_or_insert_with(|| arm.clone());
+                new_match_arm_list.add_arm(arm);
             }
+
             if needs_catch_all_arm && !has_catch_all_arm {
                 cov_mark::hit!(added_wildcard_pattern);
                 let arm = make::match_arm(
@@ -225,24 +251,39 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>)
                 new_match_arm_list.add_arm(arm);
             }
 
-            let old_range = ctx.sema.original_range(match_arm_list.syntax()).range;
-            match (first_new_arm, ctx.config.snippet_cap) {
-                (Some(first_new_arm), Some(cap)) => {
-                    let extend_lifetime;
-                    let cursor =
-                        match first_new_arm.syntax().descendants().find_map(ast::WildcardPat::cast)
-                        {
-                            Some(it) => {
-                                extend_lifetime = it.syntax().clone();
-                                Cursor::Replace(&extend_lifetime)
-                            }
-                            None => Cursor::Before(first_new_arm.syntax()),
-                        };
-                    let snippet = render_snippet(cap, new_match_arm_list.syntax(), cursor);
-                    builder.replace_snippet(cap, old_range, snippet);
+            if let (Some(first_new_arm), Some(cap)) = (first_new_arm, ctx.config.snippet_cap) {
+                match first_new_arm.syntax().descendants().find_map(ast::WildcardPat::cast) {
+                    Some(it) => edit.add_placeholder_snippet(cap, it),
+                    None => edit.add_tabstop_before(cap, first_new_arm),
                 }
-                _ => builder.replace(old_range, new_match_arm_list.to_string()),
             }
+
+            // FIXME: Hack for mutable syntax trees not having great support for macros
+            // Just replace the element that the original range came from
+            let old_place = {
+                // Find the original element
+                let old_file_range = ctx.sema.original_range(match_arm_list.syntax());
+                let file = ctx.sema.parse(old_file_range.file_id);
+                let old_place = file.syntax().covering_element(old_file_range.range);
+
+                // Make `old_place` mut
+                match old_place {
+                    syntax::SyntaxElement::Node(it) => {
+                        syntax::SyntaxElement::from(edit.make_syntax_mut(it))
+                    }
+                    syntax::SyntaxElement::Token(it) => {
+                        // Don't have a way to make tokens mut, so instead make the parent mut
+                        // and find the token again
+                        let parent = edit.make_syntax_mut(it.parent().unwrap());
+                        let mut_token =
+                            parent.covering_element(it.text_range()).into_token().unwrap();
+
+                        syntax::SyntaxElement::from(mut_token)
+                    }
+                }
+            };
+
+            syntax::ted::replace(old_place, new_match_arm_list.syntax());
         },
     )
 }
@@ -1621,10 +1662,9 @@ pub enum E { #[doc(hidden)] A, }
         );
     }
 
-    // FIXME: I don't think the assist should be applicable in this case
     #[test]
     fn does_not_fill_wildcard_with_wildcard() {
-        check_assist(
+        check_assist_not_applicable(
             add_missing_match_arms,
             r#"
 //- /main.rs crate:main deps:e
@@ -1635,13 +1675,6 @@ fn foo(t: ::e::E) {
 }
 //- /e.rs crate:e
 pub enum E { #[doc(hidden)] A, }
-"#,
-            r#"
-fn foo(t: ::e::E) {
-    match t {
-        _ => todo!(),
-    }
-}
 "#,
         );
     }
@@ -1777,7 +1810,7 @@ fn foo(t: ::e::E, b: bool) {
 
     #[test]
     fn does_not_fill_wildcard_with_partial_wildcard_and_wildcard() {
-        check_assist(
+        check_assist_not_applicable(
             add_missing_match_arms,
             r#"
 //- /main.rs crate:main deps:e
@@ -1789,14 +1822,6 @@ fn foo(t: ::e::E, b: bool) {
 }
 //- /e.rs crate:e
 pub enum E { #[doc(hidden)] A, }"#,
-            r#"
-fn foo(t: ::e::E, b: bool) {
-    match t {
-        _ if b => todo!(),
-        _ => todo!(),
-    }
-}
-"#,
         );
     }
 
diff --git a/crates/ide-assists/src/handlers/extract_function.rs b/crates/ide-assists/src/handlers/extract_function.rs
index e9db38aca0..2a67909e63 100644
--- a/crates/ide-assists/src/handlers/extract_function.rs
+++ b/crates/ide-assists/src/handlers/extract_function.rs
@@ -1360,15 +1360,14 @@ fn make_call(ctx: &AssistContext<'_>, fun: &Function, indent: IndentLevel) -> St
     }
 
     format_to!(buf, "{expr}");
-    let parent_match_arm = fun.body.parent().and_then(ast::MatchArm::cast);
-    let insert_comma = parent_match_arm.as_ref().is_some_and(|it| it.comma_token().is_none());
-
+    let insert_comma = fun
+        .body
+        .parent()
+        .and_then(ast::MatchArm::cast)
+        .map_or(false, |it| it.comma_token().is_none());
     if insert_comma {
         buf.push(',');
-    } else if parent_match_arm.is_none()
-        && fun.ret_ty.is_unit()
-        && (!fun.outliving_locals.is_empty() || !expr.is_block_like())
-    {
+    } else if fun.ret_ty.is_unit() && (!fun.outliving_locals.is_empty() || !expr.is_block_like()) {
         buf.push(';');
     }
     buf
@@ -4612,29 +4611,6 @@ fn $0fun_name() -> i32 {
 }
 "#,
         );
-
-        // Makes sure no semicolon is added for unit-valued match arms
-        check_assist(
-            extract_function,
-            r#"
-fn main() {
-    match () {
-        _ => $0()$0,
-    }
-}
-"#,
-            r#"
-fn main() {
-    match () {
-        _ => fun_name(),
-    }
-}
-
-fn $0fun_name() {
-    ()
-}
-"#,
-        )
     }
 
     #[test]
diff --git a/crates/ide-assists/src/handlers/fix_visibility.rs b/crates/ide-assists/src/handlers/fix_visibility.rs
index 4a2ab18c98..c9f272474e 100644
--- a/crates/ide-assists/src/handlers/fix_visibility.rs
+++ b/crates/ide-assists/src/handlers/fix_visibility.rs
@@ -1,11 +1,11 @@
 use hir::{db::HirDatabase, HasSource, HasVisibility, ModuleDef, PathResolution, ScopeDef};
 use ide_db::base_db::FileId;
 use syntax::{
-    ast::{self, HasVisibility as _},
-    AstNode, TextRange, TextSize,
+    ast::{self, edit_in_place::HasVisibilityEdit, make, HasVisibility as _},
+    AstNode, TextRange,
 };
 
-use crate::{utils::vis_offset, AssistContext, AssistId, AssistKind, Assists};
+use crate::{AssistContext, AssistId, AssistKind, Assists};
 
 // FIXME: this really should be a fix for diagnostic, rather than an assist.
 
@@ -58,11 +58,13 @@ fn add_vis_to_referenced_module_def(acc: &mut Assists, ctx: &AssistContext<'_>)
         return None;
     };
 
-    let (offset, current_visibility, target, target_file, target_name) =
-        target_data_for_def(ctx.db(), def)?;
+    let (vis_owner, target, target_file, target_name) = target_data_for_def(ctx.db(), def)?;
 
-    let missing_visibility =
-        if current_module.krate() == target_module.krate() { "pub(crate)" } else { "pub" };
+    let missing_visibility = if current_module.krate() == target_module.krate() {
+        make::visibility_pub_crate()
+    } else {
+        make::visibility_pub()
+    };
 
     let assist_label = match target_name {
         None => format!("Change visibility to {missing_visibility}"),
@@ -71,23 +73,14 @@ fn add_vis_to_referenced_module_def(acc: &mut Assists, ctx: &AssistContext<'_>)
         }
     };
 
-    acc.add(AssistId("fix_visibility", AssistKind::QuickFix), assist_label, target, |builder| {
-        builder.edit_file(target_file);
-        match ctx.config.snippet_cap {
-            Some(cap) => match current_visibility {
-                Some(current_visibility) => builder.replace_snippet(
-                    cap,
-                    current_visibility.syntax().text_range(),
-                    format!("$0{missing_visibility}"),
-                ),
-                None => builder.insert_snippet(cap, offset, format!("$0{missing_visibility} ")),
-            },
-            None => match current_visibility {
-                Some(current_visibility) => {
-                    builder.replace(current_visibility.syntax().text_range(), missing_visibility)
-                }
-                None => builder.insert(offset, format!("{missing_visibility} ")),
-            },
+    acc.add(AssistId("fix_visibility", AssistKind::QuickFix), assist_label, target, |edit| {
+        edit.edit_file(target_file);
+
+        let vis_owner = edit.make_mut(vis_owner);
+        vis_owner.set_visibility(missing_visibility.clone_for_update());
+
+        if let Some((cap, vis)) = ctx.config.snippet_cap.zip(vis_owner.visibility()) {
+            edit.add_tabstop_before(cap, vis);
         }
     })
 }
@@ -107,19 +100,22 @@ fn add_vis_to_referenced_record_field(acc: &mut Assists, ctx: &AssistContext<'_>
     let target_module = parent.module(ctx.db());
 
     let in_file_source = record_field_def.source(ctx.db())?;
-    let (offset, current_visibility, target) = match in_file_source.value {
+    let (vis_owner, target) = match in_file_source.value {
         hir::FieldSource::Named(it) => {
-            let s = it.syntax();
-            (vis_offset(s), it.visibility(), s.text_range())
+            let range = it.syntax().text_range();
+            (ast::AnyHasVisibility::new(it), range)
         }
         hir::FieldSource::Pos(it) => {
-            let s = it.syntax();
-            (vis_offset(s), it.visibility(), s.text_range())
+            let range = it.syntax().text_range();
+            (ast::AnyHasVisibility::new(it), range)
         }
     };
 
-    let missing_visibility =
-        if current_module.krate() == target_module.krate() { "pub(crate)" } else { "pub" };
+    let missing_visibility = if current_module.krate() == target_module.krate() {
+        make::visibility_pub_crate()
+    } else {
+        make::visibility_pub()
+    };
     let target_file = in_file_source.file_id.original_file(ctx.db());
 
     let target_name = record_field_def.name(ctx.db());
@@ -129,23 +125,14 @@ fn add_vis_to_referenced_record_field(acc: &mut Assists, ctx: &AssistContext<'_>
         target_name.display(ctx.db())
     );
 
-    acc.add(AssistId("fix_visibility", AssistKind::QuickFix), assist_label, target, |builder| {
-        builder.edit_file(target_file);
-        match ctx.config.snippet_cap {
-            Some(cap) => match current_visibility {
-                Some(current_visibility) => builder.replace_snippet(
-                    cap,
-                    current_visibility.syntax().text_range(),
-                    format!("$0{missing_visibility}"),
-                ),
-                None => builder.insert_snippet(cap, offset, format!("$0{missing_visibility} ")),
-            },
-            None => match current_visibility {
-                Some(current_visibility) => {
-                    builder.replace(current_visibility.syntax().text_range(), missing_visibility)
-                }
-                None => builder.insert(offset, format!("{missing_visibility} ")),
-            },
+    acc.add(AssistId("fix_visibility", AssistKind::QuickFix), assist_label, target, |edit| {
+        edit.edit_file(target_file);
+
+        let vis_owner = edit.make_mut(vis_owner);
+        vis_owner.set_visibility(missing_visibility.clone_for_update());
+
+        if let Some((cap, vis)) = ctx.config.snippet_cap.zip(vis_owner.visibility()) {
+            edit.add_tabstop_before(cap, vis);
         }
     })
 }
@@ -153,11 +140,11 @@ fn add_vis_to_referenced_record_field(acc: &mut Assists, ctx: &AssistContext<'_>
 fn target_data_for_def(
     db: &dyn HirDatabase,
     def: hir::ModuleDef,
-) -> Option<(TextSize, Option<ast::Visibility>, TextRange, FileId, Option<hir::Name>)> {
+) -> Option<(ast::AnyHasVisibility, TextRange, FileId, Option<hir::Name>)> {
     fn offset_target_and_file_id<S, Ast>(
         db: &dyn HirDatabase,
         x: S,
-    ) -> Option<(TextSize, Option<ast::Visibility>, TextRange, FileId)>
+    ) -> Option<(ast::AnyHasVisibility, TextRange, FileId)>
     where
         S: HasSource<Ast = Ast>,
         Ast: AstNode + ast::HasVisibility,
@@ -165,18 +152,12 @@ fn target_data_for_def(
         let source = x.source(db)?;
         let in_file_syntax = source.syntax();
         let file_id = in_file_syntax.file_id;
-        let syntax = in_file_syntax.value;
-        let current_visibility = source.value.visibility();
-        Some((
-            vis_offset(syntax),
-            current_visibility,
-            syntax.text_range(),
-            file_id.original_file(db.upcast()),
-        ))
+        let range = in_file_syntax.value.text_range();
+        Some((ast::AnyHasVisibility::new(source.value), range, file_id.original_file(db.upcast())))
     }
 
     let target_name;
-    let (offset, current_visibility, target, target_file) = match def {
+    let (offset, target, target_file) = match def {
         hir::ModuleDef::Function(f) => {
             target_name = Some(f.name(db));
             offset_target_and_file_id(db, f)?
@@ -213,8 +194,8 @@ fn target_data_for_def(
             target_name = m.name(db);
             let in_file_source = m.declaration_source(db)?;
             let file_id = in_file_source.file_id.original_file(db.upcast());
-            let syntax = in_file_source.value.syntax();
-            (vis_offset(syntax), in_file_source.value.visibility(), syntax.text_range(), file_id)
+            let range = in_file_source.value.syntax().text_range();
+            (ast::AnyHasVisibility::new(in_file_source.value), range, file_id)
         }
         // FIXME
         hir::ModuleDef::Macro(_) => return None,
@@ -222,7 +203,7 @@ fn target_data_for_def(
         hir::ModuleDef::Variant(_) | hir::ModuleDef::BuiltinType(_) => return None,
     };
 
-    Some((offset, current_visibility, target, target_file, target_name))
+    Some((offset, target, target_file, target_name))
 }
 
 #[cfg(test)]
diff --git a/crates/ide-assists/src/handlers/promote_local_to_const.rs b/crates/ide-assists/src/handlers/promote_local_to_const.rs
index 23153b4c56..5cc110cf12 100644
--- a/crates/ide-assists/src/handlers/promote_local_to_const.rs
+++ b/crates/ide-assists/src/handlers/promote_local_to_const.rs
@@ -8,13 +8,10 @@ use ide_db::{
 use stdx::to_upper_snake_case;
 use syntax::{
     ast::{self, make, HasName},
-    AstNode, WalkEvent,
+    ted, AstNode, WalkEvent,
 };
 
-use crate::{
-    assist_context::{AssistContext, Assists},
-    utils::{render_snippet, Cursor},
-};
+use crate::assist_context::{AssistContext, Assists};
 
 // Assist: promote_local_to_const
 //
@@ -70,29 +67,33 @@ pub(crate) fn promote_local_to_const(acc: &mut Assists, ctx: &AssistContext<'_>)
         cov_mark::hit!(promote_local_non_const);
         return None;
     }
-    let target = let_stmt.syntax().text_range();
+
     acc.add(
         AssistId("promote_local_to_const", AssistKind::Refactor),
         "Promote local to constant",
-        target,
-        |builder| {
+        let_stmt.syntax().text_range(),
+        |edit| {
             let name = to_upper_snake_case(&name.to_string());
             let usages = Definition::Local(local).usages(&ctx.sema).all();
             if let Some(usages) = usages.references.get(&ctx.file_id()) {
+                let name = make::name_ref(&name);
+
                 for usage in usages {
-                    builder.replace(usage.range, &name);
+                    let Some(usage) = usage.name.as_name_ref().cloned() else { continue };
+                    let usage = edit.make_mut(usage);
+                    ted::replace(usage.syntax(), name.clone_for_update().syntax());
                 }
             }
 
-            let item = make::item_const(None, make::name(&name), make::ty(&ty), initializer);
-            match ctx.config.snippet_cap.zip(item.name()) {
-                Some((cap, name)) => builder.replace_snippet(
-                    cap,
-                    target,
-                    render_snippet(cap, item.syntax(), Cursor::Before(name.syntax())),
-                ),
-                None => builder.replace(target, item.to_string()),
+            let item = make::item_const(None, make::name(&name), make::ty(&ty), initializer)
+                .clone_for_update();
+            let let_stmt = edit.make_mut(let_stmt);
+
+            if let Some((cap, name)) = ctx.config.snippet_cap.zip(item.name()) {
+                edit.add_tabstop_before(cap, name);
             }
+
+            ted::replace(let_stmt.syntax(), item.syntax());
         },
     )
 }
@@ -157,6 +158,27 @@ fn foo() {
         );
     }
 
+    #[test]
+    fn multiple_uses() {
+        check_assist(
+            promote_local_to_const,
+            r"
+fn foo() {
+    let x$0 = 0;
+    let y = x;
+    let z = (x, x, x, x);
+}
+",
+            r"
+fn foo() {
+    const $0X: i32 = 0;
+    let y = X;
+    let z = (X, X, X, X);
+}
+",
+        );
+    }
+
     #[test]
     fn not_applicable_non_const_meth_call() {
         cov_mark::check!(promote_local_non_const);
diff --git a/crates/ide-db/src/apply_change.rs b/crates/ide-db/src/apply_change.rs
index 7ba0bd73ec..0dd544d0ae 100644
--- a/crates/ide-db/src/apply_change.rs
+++ b/crates/ide-db/src/apply_change.rs
@@ -100,7 +100,7 @@ impl RootDatabase {
             hir::db::ParseMacroExpansionQuery
             hir::db::InternMacroCallQuery
             hir::db::MacroArgTextQuery
-            hir::db::DeclMacroExpanderQuery
+            hir::db::MacroDefQuery
             hir::db::MacroExpandQuery
             hir::db::ExpandProcMacroQuery
             hir::db::HygieneFrameQuery
diff --git a/crates/ide-db/src/helpers.rs b/crates/ide-db/src/helpers.rs
index 1eb8f00020..eba9d8afc4 100644
--- a/crates/ide-db/src/helpers.rs
+++ b/crates/ide-db/src/helpers.rs
@@ -9,10 +9,7 @@ use syntax::{
     AstToken, SyntaxKind, SyntaxToken, TokenAtOffset,
 };
 
-use crate::{
-    defs::{Definition, IdentClass},
-    generated, RootDatabase,
-};
+use crate::{defs::Definition, generated, RootDatabase};
 
 pub fn item_name(db: &RootDatabase, item: ItemInNs) -> Option<Name> {
     match item {
@@ -112,16 +109,3 @@ pub fn is_editable_crate(krate: Crate, db: &RootDatabase) -> bool {
     let source_root_id = db.file_source_root(root_file);
     !db.source_root(source_root_id).is_library
 }
-
-pub fn get_definition(
-    sema: &Semantics<'_, RootDatabase>,
-    token: SyntaxToken,
-) -> Option<Definition> {
-    for token in sema.descend_into_macros(token) {
-        let def = IdentClass::classify_token(sema, &token).map(IdentClass::definitions_no_ops);
-        if let Some(&[x]) = def.as_deref() {
-            return Some(x);
-        }
-    }
-    None
-}
diff --git a/crates/ide-db/src/lib.rs b/crates/ide-db/src/lib.rs
index feced7e4bb..ff1a20f03f 100644
--- a/crates/ide-db/src/lib.rs
+++ b/crates/ide-db/src/lib.rs
@@ -201,7 +201,7 @@ impl RootDatabase {
             // hir_db::ParseMacroExpansionQuery
             // hir_db::InternMacroCallQuery
             hir_db::MacroArgTextQuery
-            hir_db::DeclMacroExpanderQuery
+            hir_db::MacroDefQuery
             // hir_db::MacroExpandQuery
             hir_db::ExpandProcMacroQuery
             hir_db::HygieneFrameQuery
diff --git a/crates/ide-diagnostics/src/handlers/mutability_errors.rs b/crates/ide-diagnostics/src/handlers/mutability_errors.rs
index 935f12a396..0a004c0647 100644
--- a/crates/ide-diagnostics/src/handlers/mutability_errors.rs
+++ b/crates/ide-diagnostics/src/handlers/mutability_errors.rs
@@ -795,22 +795,6 @@ fn main() {
              //^^^^^ 💡 warn: variable does not need to be mutable
     f(x);
 }
-"#,
-        );
-        check_diagnostics(
-            r#"
-struct Foo(i32);
-
-const X: Foo = Foo(5);
-const Y: Foo = Foo(12);
-
-const fn f(mut a: Foo) -> bool {
-         //^^^^^ 💡 warn: variable does not need to be mutable
-    match a {
-        X | Y => true,
-        _ => false,
-    }
-}
 "#,
         );
     }
diff --git a/crates/ide/src/lib.rs b/crates/ide/src/lib.rs
index 0ad4c6c47e..cb2a1140ba 100644
--- a/crates/ide/src/lib.rs
+++ b/crates/ide/src/lib.rs
@@ -60,7 +60,6 @@ mod interpret_function;
 mod view_item_tree;
 mod shuffle_crate_graph;
 mod fetch_crates;
-mod view_memory_layout;
 
 use std::ffi::OsStr;
 
@@ -75,7 +74,6 @@ use ide_db::{
 };
 use syntax::SourceFile;
 use triomphe::Arc;
-use view_memory_layout::{view_memory_layout, RecursiveMemoryLayout};
 
 use crate::navigation_target::{ToNav, TryToNav};
 
@@ -726,13 +724,6 @@ impl Analysis {
         self.with_db(|db| move_item::move_item(db, range, direction))
     }
 
-    pub fn get_recursive_memory_layout(
-        &self,
-        position: FilePosition,
-    ) -> Cancellable<Option<RecursiveMemoryLayout>> {
-        self.with_db(|db| view_memory_layout(db, position))
-    }
-
     /// Performs an operation on the database that may be canceled.
     ///
     /// rust-analyzer needs to be able to answer semantic questions about the
diff --git a/crates/ide/src/static_index.rs b/crates/ide/src/static_index.rs
index 59e8300dcd..7101e8ed20 100644
--- a/crates/ide/src/static_index.rs
+++ b/crates/ide/src/static_index.rs
@@ -3,14 +3,13 @@
 
 use std::collections::HashMap;
 
-use hir::{db::HirDatabase, Crate, Module};
-use ide_db::helpers::get_definition;
+use hir::{db::HirDatabase, Crate, Module, Semantics};
 use ide_db::{
     base_db::{FileId, FileRange, SourceDatabaseExt},
-    defs::Definition,
+    defs::{Definition, IdentClass},
     FxHashSet, RootDatabase,
 };
-use syntax::{AstNode, SyntaxKind::*, TextRange, T};
+use syntax::{AstNode, SyntaxKind::*, SyntaxToken, TextRange, T};
 
 use crate::{
     hover::hover_for_definition,
@@ -215,6 +214,16 @@ impl StaticIndex<'_> {
     }
 }
 
+fn get_definition(sema: &Semantics<'_, RootDatabase>, token: SyntaxToken) -> Option<Definition> {
+    for token in sema.descend_into_macros(token) {
+        let def = IdentClass::classify_token(sema, &token).map(IdentClass::definitions_no_ops);
+        if let Some(&[it]) = def.as_deref() {
+            return Some(it);
+        }
+    }
+    None
+}
+
 #[cfg(test)]
 mod tests {
     use crate::{fixture, StaticIndex};
diff --git a/crates/ide/src/view_memory_layout.rs b/crates/ide/src/view_memory_layout.rs
deleted file mode 100644
index 2f6332abd2..0000000000
--- a/crates/ide/src/view_memory_layout.rs
+++ /dev/null
@@ -1,409 +0,0 @@
-use std::fmt;
-
-use hir::{Field, HirDisplay, Layout, Semantics, Type};
-use ide_db::{
-    defs::Definition,
-    helpers::{get_definition, pick_best_token},
-    RootDatabase,
-};
-use syntax::{AstNode, SyntaxKind};
-
-use crate::FilePosition;
-
-pub struct MemoryLayoutNode {
-    pub item_name: String,
-    pub typename: String,
-    pub size: u64,
-    pub alignment: u64,
-    pub offset: u64,
-    pub parent_idx: i64,
-    pub children_start: i64,
-    pub children_len: u64,
-}
-
-pub struct RecursiveMemoryLayout {
-    pub nodes: Vec<MemoryLayoutNode>,
-}
-
-// NOTE: this is currently strictly for testing and so isn't super useful as a visualization tool, however it could be adapted to become one?
-impl fmt::Display for RecursiveMemoryLayout {
-    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-        fn process(
-            fmt: &mut fmt::Formatter<'_>,
-            nodes: &Vec<MemoryLayoutNode>,
-            idx: usize,
-            depth: usize,
-        ) -> fmt::Result {
-            let mut out = "\t".repeat(depth);
-            let node = &nodes[idx];
-            out += &format!(
-                "{}: {} (size: {}, align: {}, field offset: {})\n",
-                node.item_name, node.typename, node.size, node.alignment, node.offset
-            );
-            write!(fmt, "{}", out)?;
-            if node.children_start != -1 {
-                for j in nodes[idx].children_start
-                    ..(nodes[idx].children_start + nodes[idx].children_len as i64)
-                {
-                    process(fmt, nodes, j as usize, depth + 1)?;
-                }
-            }
-            Ok(())
-        }
-
-        process(fmt, &self.nodes, 0, 0)
-    }
-}
-
-enum FieldOrTupleIdx {
-    Field(Field),
-    TupleIdx(usize),
-}
-
-impl FieldOrTupleIdx {
-    fn name(&self, db: &RootDatabase) -> String {
-        match *self {
-            FieldOrTupleIdx::Field(f) => f
-                .name(db)
-                .as_str()
-                .map(|s| s.to_owned())
-                .unwrap_or_else(|| format!(".{}", f.name(db).as_tuple_index().unwrap())),
-            FieldOrTupleIdx::TupleIdx(i) => format!(".{i}").to_owned(),
-        }
-    }
-
-    fn index(&self) -> usize {
-        match *self {
-            FieldOrTupleIdx::Field(f) => f.index(),
-            FieldOrTupleIdx::TupleIdx(i) => i,
-        }
-    }
-}
-
-// Feature: View Memory Layout
-//
-// Displays the recursive memory layout of a datatype.
-//
-// |===
-// | Editor  | Action Name
-//
-// | VS Code | **rust-analyzer: View Memory Layout**
-// |===
-pub(crate) fn view_memory_layout(
-    db: &RootDatabase,
-    position: FilePosition,
-) -> Option<RecursiveMemoryLayout> {
-    let sema = Semantics::new(db);
-    let file = sema.parse(position.file_id);
-    let token =
-        pick_best_token(file.syntax().token_at_offset(position.offset), |kind| match kind {
-            SyntaxKind::IDENT => 3,
-            _ => 0,
-        })?;
-
-    let def = get_definition(&sema, token)?;
-
-    let ty = match def {
-        Definition::Adt(it) => it.ty(db),
-        Definition::TypeAlias(it) => it.ty(db),
-        Definition::BuiltinType(it) => it.ty(db),
-        Definition::SelfType(it) => it.self_ty(db),
-        Definition::Local(it) => it.ty(db),
-        Definition::Field(it) => it.ty(db),
-        Definition::Const(it) => it.ty(db),
-        Definition::Static(it) => it.ty(db),
-        _ => return None,
-    };
-
-    fn read_layout(
-        nodes: &mut Vec<MemoryLayoutNode>,
-        db: &RootDatabase,
-        ty: &Type,
-        layout: &Layout,
-        parent_idx: usize,
-    ) {
-        let mut fields = ty
-            .fields(db)
-            .into_iter()
-            .map(|(f, ty)| (FieldOrTupleIdx::Field(f), ty))
-            .chain(
-                ty.tuple_fields(db)
-                    .into_iter()
-                    .enumerate()
-                    .map(|(i, ty)| (FieldOrTupleIdx::TupleIdx(i), ty)),
-            )
-            .collect::<Vec<_>>();
-
-        if fields.len() == 0 {
-            return;
-        }
-
-        fields.sort_by_key(|(f, _)| layout.field_offset(f.index()).unwrap());
-
-        let children_start = nodes.len();
-        nodes[parent_idx].children_start = children_start as i64;
-        nodes[parent_idx].children_len = fields.len() as u64;
-
-        for (field, child_ty) in fields.iter() {
-            if let Ok(child_layout) = child_ty.layout(db) {
-                nodes.push(MemoryLayoutNode {
-                    item_name: field.name(db),
-                    typename: child_ty.display(db).to_string(),
-                    size: child_layout.size(),
-                    alignment: child_layout.align(),
-                    offset: layout.field_offset(field.index()).unwrap_or(0),
-                    parent_idx: parent_idx as i64,
-                    children_start: -1,
-                    children_len: 0,
-                });
-            } else {
-                nodes.push(MemoryLayoutNode {
-                    item_name: field.name(db)
-                        + format!("(no layout data: {:?})", child_ty.layout(db).unwrap_err())
-                            .as_ref(),
-                    typename: child_ty.display(db).to_string(),
-                    size: 0,
-                    offset: 0,
-                    alignment: 0,
-                    parent_idx: parent_idx as i64,
-                    children_start: -1,
-                    children_len: 0,
-                });
-            }
-        }
-
-        for (i, (_, child_ty)) in fields.iter().enumerate() {
-            if let Ok(child_layout) = child_ty.layout(db) {
-                read_layout(nodes, db, &child_ty, &child_layout, children_start + i);
-            }
-        }
-    }
-
-    ty.layout(db)
-        .map(|layout| {
-            let item_name = match def {
-                // def is a datatype
-                Definition::Adt(_)
-                | Definition::TypeAlias(_)
-                | Definition::BuiltinType(_)
-                | Definition::SelfType(_) => "[ROOT]".to_owned(),
-
-                // def is an item
-                def => def
-                    .name(db)
-                    .map(|n| {
-                        n.as_str()
-                            .map(|s| s.to_owned())
-                            .unwrap_or_else(|| format!(".{}", n.as_tuple_index().unwrap()))
-                    })
-                    .unwrap_or("[ROOT]".to_owned()),
-            };
-
-            let typename = ty.display(db).to_string();
-
-            let mut nodes = vec![MemoryLayoutNode {
-                item_name,
-                typename: typename.clone(),
-                size: layout.size(),
-                offset: 0,
-                alignment: layout.align(),
-                parent_idx: -1,
-                children_start: -1,
-                children_len: 0,
-            }];
-            read_layout(&mut nodes, db, &ty, &layout, 0);
-
-            RecursiveMemoryLayout { nodes }
-        })
-        .ok()
-}
-
-#[cfg(test)]
-mod tests {
-    use super::*;
-
-    use crate::fixture;
-    use expect_test::expect;
-
-    fn make_memory_layout(ra_fixture: &str) -> Option<RecursiveMemoryLayout> {
-        let (analysis, position, _) = fixture::annotations(ra_fixture);
-
-        view_memory_layout(&analysis.db, position)
-    }
-
-    #[test]
-    fn view_memory_layout_none() {
-        assert!(make_memory_layout(r#"$0"#).is_none());
-        assert!(make_memory_layout(r#"stru$0ct Blah {}"#).is_none());
-    }
-
-    #[test]
-    fn view_memory_layout_primitive() {
-        expect![[r#"
-            foo: i32 (size: 4, align: 4, field offset: 0)
-        "#]]
-        .assert_eq(
-            &make_memory_layout(
-                r#"
-fn main() {
-    let foo$0 = 109; // default i32
-}
-"#,
-            )
-            .unwrap()
-            .to_string(),
-        );
-    }
-
-    #[test]
-    fn view_memory_layout_constant() {
-        expect![[r#"
-            BLAH: bool (size: 1, align: 1, field offset: 0)
-        "#]]
-        .assert_eq(
-            &make_memory_layout(
-                r#"
-const BLAH$0: bool = 0;
-"#,
-            )
-            .unwrap()
-            .to_string(),
-        );
-    }
-
-    #[test]
-    fn view_memory_layout_static() {
-        expect![[r#"
-            BLAH: bool (size: 1, align: 1, field offset: 0)
-        "#]]
-        .assert_eq(
-            &make_memory_layout(
-                r#"
-static BLAH$0: bool = 0;
-"#,
-            )
-            .unwrap()
-            .to_string(),
-        );
-    }
-
-    #[test]
-    fn view_memory_layout_tuple() {
-        expect![[r#"
-            x: (f64, u8, i64) (size: 24, align: 8, field offset: 0)
-            	.0: f64 (size: 8, align: 8, field offset: 0)
-            	.1: u8 (size: 1, align: 1, field offset: 8)
-            	.2: i64 (size: 8, align: 8, field offset: 16)
-        "#]]
-        .assert_eq(
-            &make_memory_layout(
-                r#"
-fn main() {
-    let x$0 = (101.0, 111u8, 119i64);
-}
-"#,
-            )
-            .unwrap()
-            .to_string(),
-        );
-    }
-
-    #[test]
-    fn view_memory_layout_c_struct() {
-        expect![[r#"
-            [ROOT]: Blah (size: 16, align: 4, field offset: 0)
-            	a: u32 (size: 4, align: 4, field offset: 0)
-            	b: (i32, u8) (size: 8, align: 4, field offset: 4)
-            		.0: i32 (size: 4, align: 4, field offset: 0)
-            		.1: u8 (size: 1, align: 1, field offset: 4)
-            	c: i8 (size: 1, align: 1, field offset: 12)
-        "#]]
-        .assert_eq(
-            &make_memory_layout(
-                r#"
-#[repr(C)]
-struct Blah$0 {
-    a: u32,
-    b: (i32, u8),
-    c: i8,
-}
-"#,
-            )
-            .unwrap()
-            .to_string(),
-        );
-    }
-
-    #[test]
-    fn view_memory_layout_struct() {
-        expect![[r#"
-            [ROOT]: Blah (size: 16, align: 4, field offset: 0)
-            	b: (i32, u8) (size: 8, align: 4, field offset: 0)
-            		.0: i32 (size: 4, align: 4, field offset: 0)
-            		.1: u8 (size: 1, align: 1, field offset: 4)
-            	a: u32 (size: 4, align: 4, field offset: 8)
-            	c: i8 (size: 1, align: 1, field offset: 12)
-        "#]]
-        .assert_eq(
-            &make_memory_layout(
-                r#"
-struct Blah$0 {
-    a: u32,
-    b: (i32, u8),
-    c: i8,
-}
-"#,
-            )
-            .unwrap()
-            .to_string(),
-        );
-    }
-
-    #[test]
-    fn view_memory_layout_member() {
-        expect![[r#"
-            a: bool (size: 1, align: 1, field offset: 0)
-        "#]]
-        .assert_eq(
-            &make_memory_layout(
-                r#"
-#[repr(C)]
-struct Oof {
-    a$0: bool,
-}
-"#,
-            )
-            .unwrap()
-            .to_string(),
-        );
-    }
-
-    #[test]
-    fn view_memory_layout_alias() {
-        let ml_a = make_memory_layout(
-            r#"
-struct X {
-    a: u32,
-    b: i8,
-    c: (f32, f32),
-}
-
-type Foo$0 = X;
-"#,
-        )
-        .unwrap();
-
-        let ml_b = make_memory_layout(
-            r#"
-struct X$0 {
-    a: u32,
-    b: i8,
-    c: (f32, f32),
-}
-"#,
-        )
-        .unwrap();
-
-        assert_eq!(ml_a.to_string(), ml_b.to_string());
-    }
-}
diff --git a/crates/load-cargo/Cargo.toml b/crates/load-cargo/Cargo.toml
index f041ca88ac..4a6946d7f6 100644
--- a/crates/load-cargo/Cargo.toml
+++ b/crates/load-cargo/Cargo.toml
@@ -1,8 +1,6 @@
 [package]
 name = "load-cargo"
 version = "0.0.0"
-description = "TBD"
-
 rust-version.workspace = true
 edition.workspace = true
 license.workspace = true
diff --git a/crates/mbe/src/benchmark.rs b/crates/mbe/src/benchmark.rs
index 9d43e13045..d28dd17def 100644
--- a/crates/mbe/src/benchmark.rs
+++ b/crates/mbe/src/benchmark.rs
@@ -20,7 +20,10 @@ fn benchmark_parse_macro_rules() {
     let rules = macro_rules_fixtures_tt();
     let hash: usize = {
         let _pt = bench("mbe parse macro rules");
-        rules.values().map(|it| DeclarativeMacro::parse_macro_rules(it, true).rules.len()).sum()
+        rules
+            .values()
+            .map(|it| DeclarativeMacro::parse_macro_rules(it, true).unwrap().rules.len())
+            .sum()
     };
     assert_eq!(hash, 1144);
 }
@@ -38,7 +41,7 @@ fn benchmark_expand_macro_rules() {
         invocations
             .into_iter()
             .map(|(id, tt)| {
-                let res = rules[&id].expand(tt);
+                let res = rules[&id].expand(&tt);
                 assert!(res.err.is_none());
                 res.value.token_trees.len()
             })
@@ -50,7 +53,7 @@ fn benchmark_expand_macro_rules() {
 fn macro_rules_fixtures() -> FxHashMap<String, DeclarativeMacro> {
     macro_rules_fixtures_tt()
         .into_iter()
-        .map(|(id, tt)| (id, DeclarativeMacro::parse_macro_rules(&tt, true)))
+        .map(|(id, tt)| (id, DeclarativeMacro::parse_macro_rules(&tt, true).unwrap()))
         .collect()
 }
 
@@ -102,7 +105,7 @@ fn invocation_fixtures(rules: &FxHashMap<String, DeclarativeMacro>) -> Vec<(Stri
                     for op in rule.lhs.iter() {
                         collect_from_op(op, &mut subtree, &mut seed);
                     }
-                    if it.expand(subtree.clone()).err.is_none() {
+                    if it.expand(&subtree).err.is_none() {
                         res.push((name.clone(), subtree));
                         break;
                     }
diff --git a/crates/mbe/src/lib.rs b/crates/mbe/src/lib.rs
index c17ba1c58e..5ef20ff8a9 100644
--- a/crates/mbe/src/lib.rs
+++ b/crates/mbe/src/lib.rs
@@ -34,8 +34,7 @@ pub use ::parser::TopEntryPoint;
 
 pub use crate::{
     syntax_bridge::{
-        parse_exprs_with_sep, parse_to_token_tree, syntax_node_to_token_map,
-        syntax_node_to_token_map_with_modifications, syntax_node_to_token_tree,
+        parse_exprs_with_sep, parse_to_token_tree, syntax_node_to_token_tree,
         syntax_node_to_token_tree_with_modifications, token_tree_to_syntax_node, SyntheticToken,
         SyntheticTokenId,
     },
@@ -132,7 +131,6 @@ pub struct DeclarativeMacro {
     // This is used for correctly determining the behavior of the pat fragment
     // FIXME: This should be tracked by hygiene of the fragment identifier!
     is_2021: bool,
-    err: Option<Box<ParseError>>,
 }
 
 #[derive(Clone, Debug, PartialEq, Eq)]
@@ -215,111 +213,74 @@ pub enum Origin {
 }
 
 impl DeclarativeMacro {
-    pub fn from_err(err: ParseError, is_2021: bool) -> DeclarativeMacro {
-        DeclarativeMacro {
-            rules: Box::default(),
-            shift: Shift(0),
-            is_2021,
-            err: Some(Box::new(err)),
-        }
-    }
-
     /// The old, `macro_rules! m {}` flavor.
-    pub fn parse_macro_rules(tt: &tt::Subtree, is_2021: bool) -> DeclarativeMacro {
+    pub fn parse_macro_rules(
+        tt: &tt::Subtree,
+        is_2021: bool,
+    ) -> Result<DeclarativeMacro, ParseError> {
         // Note: this parsing can be implemented using mbe machinery itself, by
         // matching against `$($lhs:tt => $rhs:tt);*` pattern, but implementing
         // manually seems easier.
         let mut src = TtIter::new(tt);
         let mut rules = Vec::new();
-        let mut err = None;
-
         while src.len() > 0 {
-            let rule = match Rule::parse(&mut src, true) {
-                Ok(it) => it,
-                Err(e) => {
-                    err = Some(Box::new(e));
-                    break;
-                }
-            };
+            let rule = Rule::parse(&mut src, true)?;
             rules.push(rule);
             if let Err(()) = src.expect_char(';') {
                 if src.len() > 0 {
-                    err = Some(Box::new(ParseError::expected("expected `;`")));
+                    return Err(ParseError::expected("expected `;`"));
                 }
                 break;
             }
         }
 
         for Rule { lhs, .. } in &rules {
-            if let Err(e) = validate(lhs) {
-                err = Some(Box::new(e));
-                break;
-            }
+            validate(lhs)?;
         }
 
-        DeclarativeMacro { rules: rules.into_boxed_slice(), shift: Shift::new(tt), is_2021, err }
+        Ok(DeclarativeMacro { rules: rules.into_boxed_slice(), shift: Shift::new(tt), is_2021 })
     }
 
     /// The new, unstable `macro m {}` flavor.
-    pub fn parse_macro2(tt: &tt::Subtree, is_2021: bool) -> DeclarativeMacro {
+    pub fn parse_macro2(tt: &tt::Subtree, is_2021: bool) -> Result<DeclarativeMacro, ParseError> {
         let mut src = TtIter::new(tt);
         let mut rules = Vec::new();
-        let mut err = None;
 
         if tt::DelimiterKind::Brace == tt.delimiter.kind {
             cov_mark::hit!(parse_macro_def_rules);
             while src.len() > 0 {
-                let rule = match Rule::parse(&mut src, true) {
-                    Ok(it) => it,
-                    Err(e) => {
-                        err = Some(Box::new(e));
-                        break;
-                    }
-                };
+                let rule = Rule::parse(&mut src, true)?;
                 rules.push(rule);
                 if let Err(()) = src.expect_any_char(&[';', ',']) {
                     if src.len() > 0 {
-                        err = Some(Box::new(ParseError::expected(
-                            "expected `;` or `,` to delimit rules",
-                        )));
+                        return Err(ParseError::expected("expected `;` or `,` to delimit rules"));
                     }
                     break;
                 }
             }
         } else {
             cov_mark::hit!(parse_macro_def_simple);
-            match Rule::parse(&mut src, false) {
-                Ok(rule) => {
-                    if src.len() != 0 {
-                        err = Some(Box::new(ParseError::expected("remaining tokens in macro def")));
-                    }
-                    rules.push(rule);
-                }
-                Err(e) => {
-                    err = Some(Box::new(e));
-                }
+            let rule = Rule::parse(&mut src, false)?;
+            if src.len() != 0 {
+                return Err(ParseError::expected("remaining tokens in macro def"));
             }
+            rules.push(rule);
         }
 
         for Rule { lhs, .. } in &rules {
-            if let Err(e) = validate(lhs) {
-                err = Some(Box::new(e));
-                break;
-            }
+            validate(lhs)?;
         }
 
-        DeclarativeMacro { rules: rules.into_boxed_slice(), shift: Shift::new(tt), is_2021, err }
+        Ok(DeclarativeMacro { rules: rules.into_boxed_slice(), shift: Shift::new(tt), is_2021 })
     }
 
-    pub fn expand(&self, mut tt: tt::Subtree) -> ExpandResult<tt::Subtree> {
+    pub fn expand(&self, tt: &tt::Subtree) -> ExpandResult<tt::Subtree> {
+        // apply shift
+        let mut tt = tt.clone();
         self.shift.shift_all(&mut tt);
         expander::expand_rules(&self.rules, &tt, self.is_2021)
     }
 
-    pub fn err(&self) -> Option<&ParseError> {
-        self.err.as_deref()
-    }
-
     pub fn map_id_down(&self, id: tt::TokenId) -> tt::TokenId {
         self.shift.shift(id)
     }
diff --git a/crates/mbe/src/syntax_bridge.rs b/crates/mbe/src/syntax_bridge.rs
index 62b2accf5c..b90a067d2a 100644
--- a/crates/mbe/src/syntax_bridge.rs
+++ b/crates/mbe/src/syntax_bridge.rs
@@ -53,37 +53,6 @@ pub fn syntax_node_to_token_tree_with_modifications(
     (subtree, c.id_alloc.map, c.id_alloc.next_id)
 }
 
-/// Convert the syntax node to a `TokenTree` (what macro
-/// will consume).
-pub fn syntax_node_to_token_map(node: &SyntaxNode) -> TokenMap {
-    syntax_node_to_token_map_with_modifications(
-        node,
-        Default::default(),
-        0,
-        Default::default(),
-        Default::default(),
-    )
-    .0
-}
-
-/// Convert the syntax node to a `TokenTree` (what macro will consume)
-/// with the censored range excluded.
-pub fn syntax_node_to_token_map_with_modifications(
-    node: &SyntaxNode,
-    existing_token_map: TokenMap,
-    next_id: u32,
-    replace: FxHashMap<SyntaxElement, Vec<SyntheticToken>>,
-    append: FxHashMap<SyntaxElement, Vec<SyntheticToken>>,
-) -> (TokenMap, u32) {
-    let global_offset = node.text_range().start();
-    let mut c = Converter::new(node, global_offset, existing_token_map, next_id, replace, append);
-    collect_tokens(&mut c);
-    c.id_alloc.map.shrink_to_fit();
-    always!(c.replace.is_empty(), "replace: {:?}", c.replace);
-    always!(c.append.is_empty(), "append: {:?}", c.append);
-    (c.id_alloc.map, c.id_alloc.next_id)
-}
-
 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
 pub struct SyntheticTokenId(pub u32);
 
@@ -358,111 +327,6 @@ fn convert_tokens<C: TokenConverter>(conv: &mut C) -> tt::Subtree {
     }
 }
 
-fn collect_tokens<C: TokenConverter>(conv: &mut C) {
-    struct StackEntry {
-        idx: usize,
-        open_range: TextRange,
-        delimiter: tt::DelimiterKind,
-    }
-
-    let entry = StackEntry {
-        delimiter: tt::DelimiterKind::Invisible,
-        // never used (delimiter is `None`)
-        idx: !0,
-        open_range: TextRange::empty(TextSize::of('.')),
-    };
-    let mut stack = NonEmptyVec::new(entry);
-
-    loop {
-        let StackEntry { delimiter, .. } = stack.last_mut();
-        let (token, range) = match conv.bump() {
-            Some(it) => it,
-            None => break,
-        };
-        let synth_id = token.synthetic_id(conv);
-
-        let kind = token.kind(conv);
-        if kind == COMMENT {
-            // Since `convert_doc_comment` can fail, we need to peek the next id, so that we can
-            // figure out which token id to use for the doc comment, if it is converted successfully.
-            let next_id = conv.id_alloc().peek_next_id();
-            if let Some(_tokens) = conv.convert_doc_comment(&token, next_id) {
-                let id = conv.id_alloc().alloc(range, synth_id);
-                debug_assert_eq!(id, next_id);
-            }
-            continue;
-        }
-        if kind.is_punct() && kind != UNDERSCORE {
-            if synth_id.is_none() {
-                assert_eq!(range.len(), TextSize::of('.'));
-            }
-
-            let expected = match delimiter {
-                tt::DelimiterKind::Parenthesis => Some(T![')']),
-                tt::DelimiterKind::Brace => Some(T!['}']),
-                tt::DelimiterKind::Bracket => Some(T![']']),
-                tt::DelimiterKind::Invisible => None,
-            };
-
-            if let Some(expected) = expected {
-                if kind == expected {
-                    if let Some(entry) = stack.pop() {
-                        conv.id_alloc().close_delim(entry.idx, Some(range));
-                    }
-                    continue;
-                }
-            }
-
-            let delim = match kind {
-                T!['('] => Some(tt::DelimiterKind::Parenthesis),
-                T!['{'] => Some(tt::DelimiterKind::Brace),
-                T!['['] => Some(tt::DelimiterKind::Bracket),
-                _ => None,
-            };
-
-            if let Some(kind) = delim {
-                let (_id, idx) = conv.id_alloc().open_delim(range, synth_id);
-
-                stack.push(StackEntry { idx, open_range: range, delimiter: kind });
-                continue;
-            }
-
-            conv.id_alloc().alloc(range, synth_id);
-        } else {
-            macro_rules! make_leaf {
-                ($i:ident) => {{
-                    conv.id_alloc().alloc(range, synth_id);
-                }};
-            }
-            match kind {
-                T![true] | T![false] => make_leaf!(Ident),
-                IDENT => make_leaf!(Ident),
-                UNDERSCORE => make_leaf!(Ident),
-                k if k.is_keyword() => make_leaf!(Ident),
-                k if k.is_literal() => make_leaf!(Literal),
-                LIFETIME_IDENT => {
-                    let char_unit = TextSize::of('\'');
-                    let r = TextRange::at(range.start(), char_unit);
-                    conv.id_alloc().alloc(r, synth_id);
-
-                    let r = TextRange::at(range.start() + char_unit, range.len() - char_unit);
-                    conv.id_alloc().alloc(r, synth_id);
-                    continue;
-                }
-                _ => continue,
-            };
-        };
-
-        // If we get here, we've consumed all input tokens.
-        // We might have more than one subtree in the stack, if the delimiters are improperly balanced.
-        // Merge them so we're left with one.
-        while let Some(entry) = stack.pop() {
-            conv.id_alloc().close_delim(entry.idx, None);
-            conv.id_alloc().alloc(entry.open_range, None);
-        }
-    }
-}
-
 fn is_single_token_op(kind: SyntaxKind) -> bool {
     matches!(
         kind,
diff --git a/crates/rust-analyzer/src/handlers/request.rs b/crates/rust-analyzer/src/handlers/request.rs
index aad74b7466..bb0c7ffa72 100644
--- a/crates/rust-analyzer/src/handlers/request.rs
+++ b/crates/rust-analyzer/src/handlers/request.rs
@@ -1689,34 +1689,6 @@ pub(crate) fn handle_move_item(
     }
 }
 
-pub(crate) fn handle_view_recursive_memory_layout(
-    snap: GlobalStateSnapshot,
-    params: lsp_types::TextDocumentPositionParams,
-) -> anyhow::Result<Option<lsp_ext::RecursiveMemoryLayout>> {
-    let _p = profile::span("view_recursive_memory_layout");
-    let file_id = from_proto::file_id(&snap, &params.text_document.uri)?;
-    let line_index = snap.file_line_index(file_id)?;
-    let offset = from_proto::offset(&line_index, params.position)?;
-
-    let res = snap.analysis.get_recursive_memory_layout(FilePosition { file_id, offset })?;
-    Ok(res.map(|it| lsp_ext::RecursiveMemoryLayout {
-        nodes: it
-            .nodes
-            .iter()
-            .map(|n| lsp_ext::MemoryLayoutNode {
-                item_name: n.item_name.clone(),
-                typename: n.typename.clone(),
-                size: n.size,
-                offset: n.offset,
-                alignment: n.alignment,
-                parent_idx: n.parent_idx,
-                children_start: n.children_start,
-                children_len: n.children_len,
-            })
-            .collect(),
-    }))
-}
-
 fn to_command_link(command: lsp_types::Command, tooltip: String) -> lsp_ext::CommandLink {
     lsp_ext::CommandLink { tooltip: Some(tooltip), command }
 }
diff --git a/crates/rust-analyzer/src/lsp_ext.rs b/crates/rust-analyzer/src/lsp_ext.rs
index d0989b3230..4d67c8b305 100644
--- a/crates/rust-analyzer/src/lsp_ext.rs
+++ b/crates/rust-analyzer/src/lsp_ext.rs
@@ -182,33 +182,6 @@ pub struct ExpandedMacro {
     pub expansion: String,
 }
 
-pub enum ViewRecursiveMemoryLayout {}
-
-impl Request for ViewRecursiveMemoryLayout {
-    type Params = lsp_types::TextDocumentPositionParams;
-    type Result = Option<RecursiveMemoryLayout>;
-    const METHOD: &'static str = "rust-analyzer/viewRecursiveMemoryLayout";
-}
-
-#[derive(Deserialize, Serialize, Debug)]
-#[serde(rename_all = "camelCase")]
-pub struct RecursiveMemoryLayout {
-    pub nodes: Vec<MemoryLayoutNode>,
-}
-
-#[derive(Deserialize, Serialize, Debug)]
-#[serde(rename_all = "camelCase")]
-pub struct MemoryLayoutNode {
-    pub item_name: String,
-    pub typename: String,
-    pub size: u64,
-    pub offset: u64,
-    pub alignment: u64,
-    pub parent_idx: i64,
-    pub children_start: i64,
-    pub children_len: u64,
-}
-
 pub enum CancelFlycheck {}
 
 impl Notification for CancelFlycheck {
diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs
index 74036710fa..9eecf4957a 100644
--- a/crates/rust-analyzer/src/main_loop.rs
+++ b/crates/rust-analyzer/src/main_loop.rs
@@ -753,7 +753,6 @@ impl GlobalState {
             )
             .on::<lsp_types::request::WillRenameFiles>(handlers::handle_will_rename_files)
             .on::<lsp_ext::Ssr>(handlers::handle_ssr)
-            .on::<lsp_ext::ViewRecursiveMemoryLayout>(handlers::handle_view_recursive_memory_layout)
             .finish();
     }
 
diff --git a/crates/syntax/src/ast/edit_in_place.rs b/crates/syntax/src/ast/edit_in_place.rs
index 1f5ed206b4..606804aea2 100644
--- a/crates/syntax/src/ast/edit_in_place.rs
+++ b/crates/syntax/src/ast/edit_in_place.rs
@@ -748,6 +748,27 @@ fn normalize_ws_between_braces(node: &SyntaxNode) -> Option<()> {
     Some(())
 }
 
+pub trait HasVisibilityEdit: ast::HasVisibility {
+    fn set_visibility(&self, visbility: ast::Visibility) {
+        match self.visibility() {
+            Some(current_visibility) => {
+                ted::replace(current_visibility.syntax(), visbility.syntax())
+            }
+            None => {
+                let vis_before = self
+                    .syntax()
+                    .children_with_tokens()
+                    .find(|it| !matches!(it.kind(), WHITESPACE | COMMENT | ATTR))
+                    .unwrap_or_else(|| self.syntax().first_child_or_token().unwrap());
+
+                ted::insert(ted::Position::before(vis_before), visbility.syntax());
+            }
+        }
+    }
+}
+
+impl<T: ast::HasVisibility> HasVisibilityEdit for T {}
+
 pub trait Indent: AstNode + Clone + Sized {
     fn indent_level(&self) -> IndentLevel {
         IndentLevel::from_node(self.syntax())
diff --git a/docs/dev/lsp-extensions.md b/docs/dev/lsp-extensions.md
index 024acb8770..bc58aa7220 100644
--- a/docs/dev/lsp-extensions.md
+++ b/docs/dev/lsp-extensions.md
@@ -1,5 +1,5 @@
 <!---
-lsp_ext.rs hash: 149a5be3c5e469d1
+lsp_ext.rs hash: 2d60bbffe70ae198
 
 If you need to change the above hash to make the test pass, please check if you
 need to adjust this doc as well and ping this issue:
@@ -886,48 +886,3 @@ export interface FetchDependencyListResult {
 }
 ```
 Returns all crates from this workspace, so it can be used create a viewTree to help navigate the dependency tree.
-
-## View Recursive Memory Layout
-
-**Method:** `rust-analyzer/viewRecursiveMemoryLayout`
-
-**Request:** `TextDocumentPositionParams`
-
-**Response:**
-
-```typescript
-export interface RecursiveMemoryLayoutNode = {
-    /// Name of the item, or [ROOT], `.n` for tuples
-    item_name: string;
-    /// Full name of the type (type aliases are ignored)
-    typename: string;
-    /// Size of the type in bytes
-    size: number;
-    /// Alignment of the type in bytes
-    alignment: number;
-    /// Offset of the type relative to its parent (or 0 if its the root)
-    offset: number;
-    /// Index of the node's parent (or -1 if its the root)
-    parent_idx: number;
-    /// Index of the node's children (or -1 if it does not have children)
-    children_start: number;
-    /// Number of child nodes (unspecified it does not have children)
-    children_len: number;
-};
-
-export interface RecursiveMemoryLayout = {
-    nodes: RecursiveMemoryLayoutNode[];
-};
-```
-
-Returns a vector of nodes representing items in the datatype as a tree, `RecursiveMemoryLayout::nodes[0]` is the root node.
-
-If `RecursiveMemoryLayout::nodes::length == 0` we could not find a suitable type.
-
-Generic Types do not give anything because they are incomplete. Fully specified generic types do not give anything if they are selected directly but do work when a child of other types [this is consistent with other behavior](https://github.com/rust-lang/rust-analyzer/issues/15010).
-
-### Unresolved questions:
-
-- How should enums/unions be represented? currently they do not produce any children because they have multiple distinct sets of children.
-- Should niches be represented? currently they are not reported.
-- A visual representation of the memory layout is not specified, see the provided implementation for an example, however it may not translate well to terminal based editors or other such things.
diff --git a/docs/user/manual.adoc b/docs/user/manual.adoc
index 31035c4b72..bd924031e0 100644
--- a/docs/user/manual.adoc
+++ b/docs/user/manual.adoc
@@ -64,8 +64,22 @@ You can install the latest release of the plugin from
 https://marketplace.visualstudio.com/items?itemName=rust-lang.rust-analyzer[the marketplace].
 
 Note that the plugin may cause conflicts with the
-https://marketplace.visualstudio.com/items?itemName=rust-lang.rust[previous official Rust plugin].
-The latter is no longer maintained and should be uninstalled.
+https://marketplace.visualstudio.com/items?itemName=rust-lang.rust[official Rust plugin].
+It is recommended to disable the Rust plugin when using the rust-analyzer extension.
+
+By default, the plugin will prompt you to download the matching version of the server as well:
+
+image::https://user-images.githubusercontent.com/9021944/75067008-17502500-54ba-11ea-835a-f92aac50e866.png[]
+
+[NOTE]
+====
+To disable this notification put the following to `settings.json`
+
+[source,json]
+----
+{ "rust-analyzer.updates.askBeforeDownload": false }
+----
+====
 
 The server binary is stored in the extension install directory, which starts with `rust-lang.rust-analyzer-` and is located under:
 
@@ -127,9 +141,6 @@ If you're not using Code, you can compile and install only the LSP server:
 $ cargo xtask install --server
 ----
 
-Make sure that `.cargo/bin` is in `$PATH` and precedes paths where `rust-analyzer` may also be installed.
-Specifically, `rustup` includes a proxy called `rust-analyzer`, which can cause problems if you're planning to use a source build or even a downloaded binary.
-
 === rust-analyzer Language Server Binary
 
 Other editors generally require the `rust-analyzer` binary to be in `$PATH`.
diff --git a/editors/code/.eslintrc.js b/editors/code/.eslintrc.js
index 69f02b4ab5..297e9fa1e5 100644
--- a/editors/code/.eslintrc.js
+++ b/editors/code/.eslintrc.js
@@ -33,14 +33,5 @@ module.exports = {
         "@typescript-eslint/semi": ["error", "always"],
         "@typescript-eslint/no-unnecessary-type-assertion": "error",
         "@typescript-eslint/no-floating-promises": "error",
-
-        "@typescript-eslint/consistent-type-imports": [
-            "error",
-            {
-                prefer: "type-imports",
-                fixStyle: "inline-type-imports",
-            },
-        ],
-        "@typescript-eslint/no-import-type-side-effects": "error",
     },
 };
diff --git a/editors/code/package.json b/editors/code/package.json
index cd8b40e355..1a1d76c699 100644
--- a/editors/code/package.json
+++ b/editors/code/package.json
@@ -284,11 +284,6 @@
                 "command": "rust-analyzer.revealDependency",
                 "title": "Reveal File",
                 "category": "rust-analyzer"
-            },
-            {
-                "command": "rust-analyzer.viewMemoryLayout",
-                "title": "View Memory Layout",
-                "category": "rust-analyzer"
             }
         ],
         "keybindings": [
@@ -2072,10 +2067,6 @@
                 {
                     "command": "rust-analyzer.openCargoToml",
                     "when": "inRustProject"
-                },
-                {
-                    "command": "rust-analyzer.viewMemoryLayout",
-                    "when": "inRustProject"
                 }
             ],
             "editor/context": [
diff --git a/editors/code/src/ast_inspector.ts b/editors/code/src/ast_inspector.ts
index 2ebfd564ca..fa963d8eb9 100644
--- a/editors/code/src/ast_inspector.ts
+++ b/editors/code/src/ast_inspector.ts
@@ -1,7 +1,7 @@
 import * as vscode from "vscode";
 
-import type { Ctx, Disposable } from "./ctx";
-import { type RustEditor, isRustEditor } from "./util";
+import { Ctx, Disposable } from "./ctx";
+import { RustEditor, isRustEditor } from "./util";
 import { unwrapUndefinable } from "./undefinable";
 
 // FIXME: consider implementing this via the Tree View API?
diff --git a/editors/code/src/bootstrap.ts b/editors/code/src/bootstrap.ts
index 85668a23f3..7b831a8a69 100644
--- a/editors/code/src/bootstrap.ts
+++ b/editors/code/src/bootstrap.ts
@@ -1,8 +1,8 @@
 import * as vscode from "vscode";
 import * as os from "os";
-import type { Config } from "./config";
+import { Config } from "./config";
 import { log, isValidExecutable } from "./util";
-import type { PersistentState } from "./persistent_state";
+import { PersistentState } from "./persistent_state";
 import { exec } from "child_process";
 
 export async function bootstrap(
diff --git a/editors/code/src/client.ts b/editors/code/src/client.ts
index 35a114fb04..7b151c804a 100644
--- a/editors/code/src/client.ts
+++ b/editors/code/src/client.ts
@@ -6,7 +6,7 @@ import * as Is from "vscode-languageclient/lib/common/utils/is";
 import { assert } from "./util";
 import * as diagnostics from "./diagnostics";
 import { WorkspaceEdit } from "vscode";
-import { type Config, prepareVSCodeConfig } from "./config";
+import { Config, prepareVSCodeConfig } from "./config";
 import { randomUUID } from "crypto";
 import { sep as pathSeparator } from "path";
 import { unwrapUndefinable } from "./undefinable";
diff --git a/editors/code/src/commands.ts b/editors/code/src/commands.ts
index 1289fa2ac7..3c6105e89f 100644
--- a/editors/code/src/commands.ts
+++ b/editors/code/src/commands.ts
@@ -3,23 +3,23 @@ import * as lc from "vscode-languageclient";
 import * as ra from "./lsp_ext";
 import * as path from "path";
 
-import { type Ctx, type Cmd, type CtxInit, discoverWorkspace } from "./ctx";
+import { Ctx, Cmd, CtxInit, discoverWorkspace } from "./ctx";
 import { applySnippetWorkspaceEdit, applySnippetTextEdits } from "./snippets";
 import { spawnSync } from "child_process";
-import { type RunnableQuickPick, selectRunnable, createTask, createArgs } from "./run";
+import { RunnableQuickPick, selectRunnable, createTask, createArgs } from "./run";
 import { AstInspector } from "./ast_inspector";
 import {
     isRustDocument,
     isCargoTomlDocument,
     sleep,
     isRustEditor,
-    type RustEditor,
-    type RustDocument,
+    RustEditor,
+    RustDocument,
 } from "./util";
 import { startDebugSession, makeDebugConfig } from "./debug";
-import type { LanguageClient } from "vscode-languageclient/node";
+import { LanguageClient } from "vscode-languageclient/node";
 import { LINKED_COMMANDS } from "./client";
-import type { DependencyId } from "./dependencies_provider";
+import { DependencyId } from "./dependencies_provider";
 import { unwrapUndefinable } from "./undefinable";
 
 export * from "./ast_inspector";
@@ -373,7 +373,7 @@ export function ssr(ctx: CtxInit): Cmd {
                         selections,
                     });
                 } catch (e) {
-                    return String(e);
+                    return e.toString();
                 }
                 return null;
             },
@@ -1129,281 +1129,3 @@ export function linkToCommand(_: Ctx): Cmd {
         }
     };
 }
-
-export function viewMemoryLayout(ctx: CtxInit): Cmd {
-    return async () => {
-        const editor = vscode.window.activeTextEditor;
-        if (!editor) return;
-        const client = ctx.client;
-
-        const position = editor.selection.active;
-        const expanded = await client.sendRequest(ra.viewRecursiveMemoryLayout, {
-            textDocument: client.code2ProtocolConverter.asTextDocumentIdentifier(editor.document),
-            position,
-        });
-
-        const document = vscode.window.createWebviewPanel(
-            "memory_layout",
-            "[Memory Layout]",
-            vscode.ViewColumn.Two,
-            { enableScripts: true }
-        );
-
-        document.webview.html = `<!DOCTYPE html>
-<html lang="en">
-<head>
-    <meta charset="UTF-8">
-    <meta http-equiv="X-UA-Compatible" content="IE=edge">
-    <meta name="viewport" content="width=device-width, initial-scale=1.0">
-    <title>Document</title>
-    <style>
-        * {
-            box-sizing: border-box;
-        }
-
-        body {
-            margin: 0;
-            overflow: hidden;
-            min-height: 100%;
-            height: 100vh;
-            padding: 32px;
-            position: relative;
-            display: block;
-
-            background-color: var(--vscode-editor-background);
-            font-family: var(--vscode-editor-font-family);
-            font-size: var(--vscode-editor-font-size);
-            color: var(--vscode-editor-foreground);
-        }
-
-        .container {
-            position: relative;
-        }
-
-        .trans {
-            transition: all 0.2s ease-in-out;
-        }
-
-        .grid {
-            height: 100%;
-            position: relative;
-            color: var(--vscode-commandCenter-activeBorder);
-            pointer-events: none;
-        }
-
-        .grid-line {
-            position: absolute;
-            width: 100%;
-            height: 1px;
-            background-color: var(--vscode-commandCenter-activeBorder);
-        }
-
-        #tooltip {
-            position: fixed;
-            display: none;
-            z-index: 1;
-            pointer-events: none;
-            padding: 4px 8px;
-            z-index: 2;
-
-            color: var(--vscode-editorHoverWidget-foreground);
-            background-color: var(--vscode-editorHoverWidget-background);
-            border: 1px solid var(--vscode-editorHoverWidget-border);
-        }
-
-        #tooltip b {
-            color: var(--vscode-editorInlayHint-typeForeground);
-        }
-
-        #tooltip ul {
-            margin-left: 0;
-            padding-left: 20px;
-        }
-
-        table {
-            position: absolute;
-            transform: rotateZ(90deg) rotateX(180deg);
-            transform-origin: top left;
-            border-collapse: collapse;
-            table-layout: fixed;
-            left: 48px;
-            top: 0;
-            max-height: calc(100vw - 64px - 48px);
-            z-index: 1;
-        }
-
-        td {
-            border: 1px solid var(--vscode-focusBorder);
-            writing-mode: vertical-rl;
-            text-orientation: sideways-right;
-
-            height: 80px;
-        }
-
-        td p {
-            height: calc(100% - 16px);
-            width: calc(100% - 8px);
-            margin: 8px 4px;
-            display: inline-block;
-            transform: rotateY(180deg);
-            pointer-events: none;
-            overflow: hidden;
-        }
-
-        td p * {
-            overflow: hidden;
-            white-space: nowrap;
-            text-overflow: ellipsis;
-            display: inline-block;
-            height: 100%;
-        }
-
-        td p b {
-            color: var(--vscode-editorInlayHint-typeForeground);
-        }
-
-        td:hover {
-            background-color: var(--vscode-editor-hoverHighlightBackground);
-        }
-
-        td:empty {
-            visibility: hidden;
-            border: 0;
-        }
-    </style>
-</head>
-<body>
-    <div id="tooltip"></div>
-</body>
-<script>(function() {
-
-const data = ${JSON.stringify(expanded)}
-
-if (!(data && data.nodes.length)) {
-    document.body.innerText = "Not Available"
-    return
-}
-
-data.nodes.map(n => {
-    n.typename = n.typename.replaceAll('&', '&amp;').replaceAll('<', '&lt;').replaceAll('>', '&gt;').replaceAll('"', ' & quot; ').replaceAll("'", '&#039;')
-    return n
-})
-
-let height = window.innerHeight - 64
-
-addEventListener("resize", e => {
-    const new_height = window.innerHeight - 64
-    height = new_height
-    container.classList.remove("trans")
-    table.classList.remove("trans")
-    locate()
-    setTimeout(() => { // give delay to redraw, annoying but needed
-        container.classList.add("trans")
-        table.classList.add("trans")
-    }, 0)
-})
-
-const container = document.createElement("div")
-container.classList.add("container")
-container.classList.add("trans")
-document.body.appendChild(container)
-
-const tooltip = document.getElementById("tooltip")
-
-let y = 0
-let zoom = 1.0
-
-const table = document.createElement("table")
-table.classList.add("trans")
-container.appendChild(table)
-const rows = []
-
-function node_t(idx, depth, offset) {
-    if (!rows[depth]) {
-        rows[depth] = { el: document.createElement("tr"), offset: 0 }
-    }
-
-    if (rows[depth].offset < offset) {
-        const pad = document.createElement("td")
-        pad.colSpan = offset - rows[depth].offset
-        rows[depth].el.appendChild(pad)
-        rows[depth].offset += offset - rows[depth].offset
-    }
-
-    const td = document.createElement("td")
-    td.innerHTML = '<p><span>' + data.nodes[idx].itemName + ':</span> <b>' + data.nodes[idx].typename + '</b></p>'
-
-    td.colSpan = data.nodes[idx].size
-
-    td.addEventListener("mouseover", e => {
-        const node = data.nodes[idx]
-        tooltip.innerHTML = node.itemName + ": <b>" + node.typename + "</b><br/>"
-            + "<ul>"
-            + "<li>size = " + node.size + "</li>"
-            + "<li>align = " + node.alignment + "</li>"
-            + "<li>field offset = " + node.offset + "</li>"
-            + "</ul>"
-            + "<i>double click to focus</i>"
-
-        tooltip.style.display = "block"
-    })
-    td.addEventListener("mouseleave", _ => tooltip.style.display = "none")
-    const total_offset = rows[depth].offset
-    td.addEventListener("dblclick", e => {
-        const node = data.nodes[idx]
-        zoom = data.nodes[0].size / node.size
-        y = -(total_offset) / data.nodes[0].size * zoom
-        x = 0
-        locate()
-    })
-
-    rows[depth].el.appendChild(td)
-    rows[depth].offset += data.nodes[idx].size
-
-
-    if (data.nodes[idx].childrenStart != -1) {
-        for (let i = 0; i < data.nodes[idx].childrenLen; i++) {
-            if (data.nodes[data.nodes[idx].childrenStart + i].size) {
-                node_t(data.nodes[idx].childrenStart + i, depth + 1, offset + data.nodes[data.nodes[idx].childrenStart + i].offset)
-            }
-        }
-    }
-}
-
-node_t(0, 0, 0)
-
-for (const row of rows) table.appendChild(row.el)
-
-const grid = document.createElement("div")
-grid.classList.add("grid")
-container.appendChild(grid)
-
-for (let i = 0; i < data.nodes[0].size / 8 + 1; i++) {
-    const el = document.createElement("div")
-    el.classList.add("grid-line")
-    el.style.top = (i / (data.nodes[0].size / 8) * 100) + "%"
-    el.innerText = i * 8
-    grid.appendChild(el)
-}
-
-addEventListener("mousemove", e => {
-    tooltip.style.top = e.clientY + 10 + "px"
-    tooltip.style.left = e.clientX + 10 + "px"
-})
-
-function locate() {
-    container.style.top = height * y + "px"
-    container.style.height = (height * zoom) + "px"
-
-    table.style.width = container.style.height
-}
-
-locate()
-
-})()
-</script>
-</html>`;
-
-        ctx.pushExtCleanup(document);
-    };
-}
diff --git a/editors/code/src/config.ts b/editors/code/src/config.ts
index 7dbc4bdd47..7f4efebb2a 100644
--- a/editors/code/src/config.ts
+++ b/editors/code/src/config.ts
@@ -2,7 +2,7 @@ import * as Is from "vscode-languageclient/lib/common/utils/is";
 import * as os from "os";
 import * as path from "path";
 import * as vscode from "vscode";
-import type { Env } from "./client";
+import { Env } from "./client";
 import { log } from "./util";
 import { expectNotUndefined, unwrapUndefinable } from "./undefinable";
 
diff --git a/editors/code/src/ctx.ts b/editors/code/src/ctx.ts
index 1ae0c96c6e..a72b5391ff 100644
--- a/editors/code/src/ctx.ts
+++ b/editors/code/src/ctx.ts
@@ -1,5 +1,5 @@
 import * as vscode from "vscode";
-import type * as lc from "vscode-languageclient/node";
+import * as lc from "vscode-languageclient/node";
 import * as ra from "./lsp_ext";
 import * as path from "path";
 
@@ -12,19 +12,19 @@ import {
     isRustEditor,
     LazyOutputChannel,
     log,
-    type RustEditor,
+    RustEditor,
 } from "./util";
-import type { ServerStatusParams } from "./lsp_ext";
+import { ServerStatusParams } from "./lsp_ext";
 import {
-    type Dependency,
-    type DependencyFile,
+    Dependency,
+    DependencyFile,
     RustDependenciesProvider,
-    type DependencyId,
+    DependencyId,
 } from "./dependencies_provider";
 import { execRevealDependency } from "./commands";
 import { PersistentState } from "./persistent_state";
 import { bootstrap } from "./bootstrap";
-import type { ExecOptions } from "child_process";
+import { ExecOptions } from "child_process";
 
 // We only support local folders, not eg. Live Share (`vlsl:` scheme), so don't activate if
 // only those are in use. We use "Empty" to represent these scenarios
diff --git a/editors/code/src/debug.ts b/editors/code/src/debug.ts
index 484f547230..29758feafe 100644
--- a/editors/code/src/debug.ts
+++ b/editors/code/src/debug.ts
@@ -1,10 +1,10 @@
 import * as os from "os";
 import * as vscode from "vscode";
 import * as path from "path";
-import type * as ra from "./lsp_ext";
+import * as ra from "./lsp_ext";
 
 import { Cargo, getRustcId, getSysroot } from "./toolchain";
-import type { Ctx } from "./ctx";
+import { Ctx } from "./ctx";
 import { prepareEnv } from "./run";
 import { unwrapUndefinable } from "./undefinable";
 
diff --git a/editors/code/src/dependencies_provider.ts b/editors/code/src/dependencies_provider.ts
index 98d6d7001a..51ba11ecc9 100644
--- a/editors/code/src/dependencies_provider.ts
+++ b/editors/code/src/dependencies_provider.ts
@@ -1,9 +1,9 @@
 import * as vscode from "vscode";
 import * as fspath from "path";
 import * as fs from "fs";
-import type { CtxInit } from "./ctx";
+import { CtxInit } from "./ctx";
 import * as ra from "./lsp_ext";
-import type { FetchDependencyListResult } from "./lsp_ext";
+import { FetchDependencyListResult } from "./lsp_ext";
 import { unwrapUndefinable } from "./undefinable";
 
 export class RustDependenciesProvider
diff --git a/editors/code/src/diagnostics.ts b/editors/code/src/diagnostics.ts
index e573f5a63f..a7e0845a27 100644
--- a/editors/code/src/diagnostics.ts
+++ b/editors/code/src/diagnostics.ts
@@ -1,13 +1,7 @@
 import * as anser from "anser";
 import * as vscode from "vscode";
-import {
-    type ProviderResult,
-    Range,
-    type TextEditorDecorationType,
-    ThemeColor,
-    window,
-} from "vscode";
-import type { Ctx } from "./ctx";
+import { ProviderResult, Range, TextEditorDecorationType, ThemeColor, window } from "vscode";
+import { Ctx } from "./ctx";
 import { unwrapUndefinable } from "./undefinable";
 
 export const URI_SCHEME = "rust-analyzer-diagnostics-view";
diff --git a/editors/code/src/lsp_ext.ts b/editors/code/src/lsp_ext.ts
index 5af2cab0ee..b72804e510 100644
--- a/editors/code/src/lsp_ext.ts
+++ b/editors/code/src/lsp_ext.ts
@@ -150,11 +150,6 @@ export const serverStatus = new lc.NotificationType<ServerStatusParams>(
     "experimental/serverStatus"
 );
 export const ssr = new lc.RequestType<SsrParams, lc.WorkspaceEdit, void>("experimental/ssr");
-export const viewRecursiveMemoryLayout = new lc.RequestType<
-    lc.TextDocumentPositionParams,
-    RecursiveMemoryLayout | null,
-    void
->("rust-analyzer/viewRecursiveMemoryLayout");
 
 export type JoinLinesParams = {
     textDocument: lc.TextDocumentIdentifier;
@@ -202,17 +197,3 @@ export type SsrParams = {
     position: lc.Position;
     selections: readonly lc.Range[];
 };
-
-export type RecursiveMemoryLayoutNode = {
-    item_name: string;
-    typename: string;
-    size: number;
-    alignment: number;
-    offset: number;
-    parent_idx: number;
-    children_start: number;
-    children_len: number;
-};
-export type RecursiveMemoryLayout = {
-    nodes: RecursiveMemoryLayoutNode[];
-};
diff --git a/editors/code/src/main.ts b/editors/code/src/main.ts
index 1121951c07..be9bc9d363 100644
--- a/editors/code/src/main.ts
+++ b/editors/code/src/main.ts
@@ -2,7 +2,7 @@ import * as vscode from "vscode";
 import * as lc from "vscode-languageclient/node";
 
 import * as commands from "./commands";
-import { type CommandFactory, Ctx, fetchWorkspace } from "./ctx";
+import { CommandFactory, Ctx, fetchWorkspace } from "./ctx";
 import * as diagnostics from "./diagnostics";
 import { activateTaskProvider } from "./tasks";
 import { setContextValue } from "./util";
@@ -179,7 +179,6 @@ function createCommands(): Record<string, CommandFactory> {
         runFlycheck: { enabled: commands.runFlycheck },
         ssr: { enabled: commands.ssr },
         serverVersion: { enabled: commands.serverVersion },
-        viewMemoryLayout: { enabled: commands.viewMemoryLayout },
         // Internal commands which are invoked by the server.
         applyActionGroup: { enabled: commands.applyActionGroup },
         applySnippetWorkspaceEdit: { enabled: commands.applySnippetWorkspaceEditCommand },
diff --git a/editors/code/src/persistent_state.ts b/editors/code/src/persistent_state.ts
index cebd16a3c9..8964a78dc3 100644
--- a/editors/code/src/persistent_state.ts
+++ b/editors/code/src/persistent_state.ts
@@ -1,4 +1,4 @@
-import type * as vscode from "vscode";
+import * as vscode from "vscode";
 import { log } from "./util";
 
 export class PersistentState {
diff --git a/editors/code/src/run.ts b/editors/code/src/run.ts
index 8ec569b603..c20a5487b7 100644
--- a/editors/code/src/run.ts
+++ b/editors/code/src/run.ts
@@ -1,11 +1,11 @@
 import * as vscode from "vscode";
-import type * as lc from "vscode-languageclient";
+import * as lc from "vscode-languageclient";
 import * as ra from "./lsp_ext";
 import * as tasks from "./tasks";
 
-import type { CtxInit } from "./ctx";
+import { CtxInit } from "./ctx";
 import { makeDebugConfig } from "./debug";
-import type { Config, RunnableEnvCfg } from "./config";
+import { Config, RunnableEnvCfg } from "./config";
 import { unwrapUndefinable } from "./undefinable";
 
 const quickPickButtons = [
diff --git a/editors/code/src/tasks.ts b/editors/code/src/tasks.ts
index f451e738d5..5199508c82 100644
--- a/editors/code/src/tasks.ts
+++ b/editors/code/src/tasks.ts
@@ -1,6 +1,6 @@
 import * as vscode from "vscode";
 import * as toolchain from "./toolchain";
-import type { Config } from "./config";
+import { Config } from "./config";
 import { log } from "./util";
 import { unwrapUndefinable } from "./undefinable";
 
diff --git a/editors/code/src/util.ts b/editors/code/src/util.ts
index 64f4582770..b6b779e266 100644
--- a/editors/code/src/util.ts
+++ b/editors/code/src/util.ts
@@ -1,6 +1,7 @@
+import * as lc from "vscode-languageclient/node";
 import * as vscode from "vscode";
 import { strict as nativeAssert } from "assert";
-import { exec, type ExecOptions, spawnSync } from "child_process";
+import { exec, ExecOptions, spawnSync } from "child_process";
 import { inspect } from "util";
 
 export function assert(condition: boolean, explanation: string): asserts condition {
@@ -56,6 +57,37 @@ export const log = new (class {
     }
 })();
 
+export async function sendRequestWithRetry<TParam, TRet>(
+    client: lc.LanguageClient,
+    reqType: lc.RequestType<TParam, TRet, unknown>,
+    param: TParam,
+    token?: vscode.CancellationToken
+): Promise<TRet> {
+    // The sequence is `10 * (2 ** (2 * n))` where n is 1, 2, 3...
+    for (const delay of [40, 160, 640, 2560, 10240, null]) {
+        try {
+            return await (token
+                ? client.sendRequest(reqType, param, token)
+                : client.sendRequest(reqType, param));
+        } catch (error) {
+            if (delay === null) {
+                log.warn("LSP request timed out", { method: reqType.method, param, error });
+                throw error;
+            }
+            if (error.code === lc.LSPErrorCodes.RequestCancelled) {
+                throw error;
+            }
+
+            if (error.code !== lc.LSPErrorCodes.ContentModified) {
+                log.warn("LSP request failed", { method: reqType.method, param, error });
+                throw error;
+            }
+            await sleep(delay);
+        }
+    }
+    throw "unreachable";
+}
+
 export function sleep(ms: number) {
     return new Promise((resolve) => setTimeout(resolve, ms));
 }
diff --git a/editors/code/tsconfig.json b/editors/code/tsconfig.json
index ee353c28dd..4b107a5d25 100644
--- a/editors/code/tsconfig.json
+++ b/editors/code/tsconfig.json
@@ -10,8 +10,9 @@
         "sourceMap": true,
         "rootDir": ".",
         "newLine": "LF",
-
-        // FIXME: https://github.com/rust-lang/rust-analyzer/issues/15253
+        // These disables some enhancement type checking options
+        // to update typescript version without any code change.
+        "useUnknownInCatchVariables": false,
         "exactOptionalPropertyTypes": false
     },
     "exclude": ["node_modules", ".vscode-test"],
diff --git a/lib/lsp-server/Cargo.toml b/lib/lsp-server/Cargo.toml
index 01707d3019..d44b2d4e40 100644
--- a/lib/lsp-server/Cargo.toml
+++ b/lib/lsp-server/Cargo.toml
@@ -9,7 +9,7 @@ edition = "2021"
 [dependencies]
 log = "0.4.17"
 serde_json = "1.0.96"
-serde = { version = "1.0.156", features = ["derive"] }
+serde = "1.0.156"
 crossbeam-channel = "0.5.6"
 
 [dev-dependencies]
diff --git a/lib/lsp-server/src/msg.rs b/lib/lsp-server/src/msg.rs
index 730ad51f42..b241561f9c 100644
--- a/lib/lsp-server/src/msg.rs
+++ b/lib/lsp-server/src/msg.rs
@@ -265,7 +265,7 @@ fn read_msg_text(inp: &mut dyn BufRead) -> io::Result<Option<String>> {
         let header_name = parts.next().unwrap();
         let header_value =
             parts.next().ok_or_else(|| invalid_data!("malformed header: {:?}", buf))?;
-        if header_name.eq_ignore_ascii_case("Content-Length") {
+        if header_name == "Content-Length" {
             size = Some(header_value.parse::<usize>().map_err(invalid_data)?);
         }
     }


Test patch:
diff --git a/crates/hir-def/src/macro_expansion_tests/mod.rs b/crates/hir-def/src/macro_expansion_tests/mod.rs
index 1c15c1b7f0..836f0afb1d 100644
--- a/crates/hir-def/src/macro_expansion_tests/mod.rs
+++ b/crates/hir-def/src/macro_expansion_tests/mod.rs
@@ -20,8 +20,8 @@ use ::mbe::TokenMap;
 use base_db::{fixture::WithFixture, ProcMacro, SourceDatabase};
 use expect_test::Expect;
 use hir_expand::{
-    db::{DeclarativeMacroExpander, ExpandDatabase},
-    AstId, InFile, MacroFile,
+    db::{ExpandDatabase, TokenExpander},
+    AstId, InFile, MacroDefId, MacroDefKind, MacroFile,
 };
 use stdx::format_to;
 use syntax::{
@@ -100,29 +100,32 @@ pub fn identity_when_valid(_attr: TokenStream, item: TokenStream) -> TokenStream
         let call_offset = macro_.syntax().text_range().start().into();
         let file_ast_id = db.ast_id_map(source.file_id).ast_id(&macro_);
         let ast_id = AstId::new(source.file_id, file_ast_id.upcast());
+        let kind = MacroDefKind::Declarative(ast_id);
 
-        let DeclarativeMacroExpander { mac, def_site_token_map } =
-            &*db.decl_macro_expander(krate, ast_id);
-        assert_eq!(mac.err(), None);
-        let tt = match &macro_ {
-            ast::Macro::MacroRules(mac) => mac.token_tree().unwrap(),
-            ast::Macro::MacroDef(_) => unimplemented!(""),
-        };
+        let macro_def = db
+            .macro_def(MacroDefId { krate, kind, local_inner: false, allow_internal_unsafe: false })
+            .unwrap();
+        if let TokenExpander::DeclarativeMacro { mac, def_site_token_map } = &*macro_def {
+            let tt = match &macro_ {
+                ast::Macro::MacroRules(mac) => mac.token_tree().unwrap(),
+                ast::Macro::MacroDef(_) => unimplemented!(""),
+            };
 
-        let tt_start = tt.syntax().text_range().start();
-        tt.syntax().descendants_with_tokens().filter_map(SyntaxElement::into_token).for_each(
-            |token| {
-                let range = token.text_range().checked_sub(tt_start).unwrap();
-                if let Some(id) = def_site_token_map.token_by_range(range) {
-                    let offset = (range.end() + tt_start).into();
-                    text_edits.push((offset..offset, format!("#{}", id.0)));
-                }
-            },
-        );
-        text_edits.push((
-            call_offset..call_offset,
-            format!("// call ids will be shifted by {:?}\n", mac.shift()),
-        ));
+            let tt_start = tt.syntax().text_range().start();
+            tt.syntax().descendants_with_tokens().filter_map(SyntaxElement::into_token).for_each(
+                |token| {
+                    let range = token.text_range().checked_sub(tt_start).unwrap();
+                    if let Some(id) = def_site_token_map.token_by_range(range) {
+                        let offset = (range.end() + tt_start).into();
+                        text_edits.push((offset..offset, format!("#{}", id.0)));
+                    }
+                },
+            );
+            text_edits.push((
+                call_offset..call_offset,
+                format!("// call ids will be shifted by {:?}\n", mac.shift()),
+            ));
+        }
     }
 
     for macro_call in source_file.syntax().descendants().filter_map(ast::MacroCall::cast) {
diff --git a/crates/hir-ty/src/consteval/tests.rs b/crates/hir-ty/src/consteval/tests.rs
index 8e21272e14..35ecb89824 100644
--- a/crates/hir-ty/src/consteval/tests.rs
+++ b/crates/hir-ty/src/consteval/tests.rs
@@ -2494,28 +2494,6 @@ fn exec_limits() {
     );
 }
 
-#[test]
-fn memory_limit() {
-    check_fail(
-        r#"
-        extern "Rust" {
-            #[rustc_allocator]
-            fn __rust_alloc(size: usize, align: usize) -> *mut u8;
-        }
-
-        const GOAL: u8 = unsafe {
-            __rust_alloc(30_000_000_000, 1); // 30GB
-            2
-        };
-        "#,
-        |e| {
-            e == ConstEvalError::MirEvalError(MirEvalError::Panic(
-                "Memory allocation of 30000000000 bytes failed".to_string(),
-            ))
-        },
-    );
-}
-
 #[test]
 fn type_error() {
     check_fail(
diff --git a/crates/hir-ty/src/consteval/tests/intrinsics.rs b/crates/hir-ty/src/consteval/tests/intrinsics.rs
index cb8f1b5557..b74133e24f 100644
--- a/crates/hir-ty/src/consteval/tests/intrinsics.rs
+++ b/crates/hir-ty/src/consteval/tests/intrinsics.rs
@@ -163,24 +163,6 @@ fn transmute() {
     );
 }
 
-#[test]
-fn read_via_copy() {
-    check_number(
-        r#"
-        extern "rust-intrinsic" {
-            pub fn read_via_copy<T>(e: *const T) -> T;
-            pub fn volatile_load<T>(e: *const T) -> T;
-        }
-
-        const GOAL: i32 = {
-            let x = 2;
-            read_via_copy(&x) + volatile_load(&x)
-        };
-        "#,
-        4,
-    );
-}
-
 #[test]
 fn const_eval_select() {
     check_number(
@@ -602,41 +584,3 @@ fn rotate() {
         320192512,
     );
 }
-
-#[test]
-fn simd() {
-    check_number(
-        r#"
-        pub struct i8x16(
-            i8,i8,i8,i8,i8,i8,i8,i8,i8,i8,i8,i8,i8,i8,i8,i8,
-        );
-        extern "platform-intrinsic" {
-            pub fn simd_bitmask<T, U>(x: T) -> U;
-        }
-        const GOAL: u16 = simd_bitmask(i8x16(
-            0, 1, 0, 0, 2, 255, 100, 0, 50, 0, 1, 1, 0, 0, 0, 0
-        ));
-        "#,
-        0b0000110101110010,
-    );
-    check_number(
-        r#"
-        pub struct i8x16(
-            i8,i8,i8,i8,i8,i8,i8,i8,i8,i8,i8,i8,i8,i8,i8,i8,
-        );
-        extern "platform-intrinsic" {
-            pub fn simd_lt<T, U>(x: T, y: T) -> U;
-            pub fn simd_bitmask<T, U>(x: T) -> U;
-        }
-        const GOAL: u16 = simd_bitmask(simd_lt::<i8x16, i8x16>(
-            i8x16(
-                -105, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
-            ),
-            i8x16(
-                -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
-            ),
-        ));
-        "#,
-        0xFFFF,
-    );
-}
diff --git a/crates/hir-ty/src/mir/eval/tests.rs b/crates/hir-ty/src/mir/eval/tests.rs
index 03c083bac4..1129eaa549 100644
--- a/crates/hir-ty/src/mir/eval/tests.rs
+++ b/crates/hir-ty/src/mir/eval/tests.rs
@@ -613,34 +613,6 @@ fn main() {
     );
 }
 
-#[test]
-fn syscalls() {
-    check_pass(
-        r#"
-//- minicore: option
-
-extern "C" {
-    pub unsafe extern "C" fn syscall(num: i64, ...) -> i64;
-}
-
-const SYS_getrandom: i64 = 318;
-
-fn should_not_reach() {
-    _ // FIXME: replace this function with panic when that works
-}
-
-fn main() {
-    let mut x: i32 = 0;
-    let r = syscall(SYS_getrandom, &mut x, 4usize, 0);
-    if r != 4 {
-        should_not_reach();
-    }
-}
-
-"#,
-    )
-}
-
 #[test]
 fn posix_tls() {
     check_pass(
diff --git a/editors/code/tests/unit/index.ts b/editors/code/tests/unit/index.ts
index c231927bb0..2fa223bed4 100644
--- a/editors/code/tests/unit/index.ts
+++ b/editors/code/tests/unit/index.ts
@@ -1,4 +1,3 @@
-import * as assert from "node:assert/strict";
 import { readdir } from "fs/promises";
 import * as path from "path";
 
@@ -31,7 +30,6 @@ class Suite {
                 await test.promise;
                 ok(`  ✔ ${test.name}`);
             } catch (e) {
-                assert.ok(e instanceof Error);
                 error(`  ✖︎ ${test.name}\n  ${e.stack}`);
                 failed += 1;
             }
@@ -52,7 +50,6 @@ export class Context {
             await ctx.run();
             ok(`✔ ${name}`);
         } catch (e) {
-            assert.ok(e instanceof Error);
             error(`✖︎ ${name}\n  ${e.stack}`);
             throw e;
         }
diff --git a/editors/code/tests/unit/launch_config.test.ts b/editors/code/tests/unit/launch_config.test.ts
index eeb8608a42..0531e064d2 100644
--- a/editors/code/tests/unit/launch_config.test.ts
+++ b/editors/code/tests/unit/launch_config.test.ts
@@ -1,6 +1,6 @@
 import * as assert from "assert";
 import { Cargo } from "../../src/toolchain";
-import type { Context } from ".";
+import { Context } from ".";
 
 export async function getTests(ctx: Context) {
     await ctx.suite("Launch configuration/Lens", (suite) => {
diff --git a/editors/code/tests/unit/runnable_env.test.ts b/editors/code/tests/unit/runnable_env.test.ts
index b1407ce019..b7d59e399d 100644
--- a/editors/code/tests/unit/runnable_env.test.ts
+++ b/editors/code/tests/unit/runnable_env.test.ts
@@ -1,8 +1,8 @@
 import * as assert from "assert";
 import { prepareEnv } from "../../src/run";
-import type { RunnableEnvCfg } from "../../src/config";
-import type { Context } from ".";
-import type * as ra from "../../src/lsp_ext";
+import { RunnableEnvCfg } from "../../src/config";
+import { Context } from ".";
+import * as ra from "../../src/lsp_ext";
 
 function makeRunnable(label: string): ra.Runnable {
     return {
diff --git a/editors/code/tests/unit/settings.test.ts b/editors/code/tests/unit/settings.test.ts
index bafb9569a1..f171f5f74f 100644
--- a/editors/code/tests/unit/settings.test.ts
+++ b/editors/code/tests/unit/settings.test.ts
@@ -1,5 +1,5 @@
 import * as assert from "assert";
-import type { Context } from ".";
+import { Context } from ".";
 import { substituteVariablesInEnv } from "../../src/config";
 
 export async function getTests(ctx: Context) {