Repository: rust-analyzer/rust-analyzer
Pull request #8326 (2021-04-04 11:25:53)

Rewrite reorder fields assist to use mutable syntax trees
This also instead uses `Either` to use the typed `RecordPat` and `RecordExpr` nodes, this unfortunately gives a bit of code duplication


Patch:
diff --git a/Cargo.lock b/Cargo.lock
index 4531d8fb1c..4344f8df5a 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -37,9 +37,9 @@ dependencies = [
 
 [[package]]
 name = "anyhow"
-version = "1.0.40"
+version = "1.0.39"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "28b2cd92db5cbd74e8e5028f7e27dd7aa3090e89e4f2a197cc7c8dfb69c7063b"
+checksum = "81cddc5f91628367664cc7c69714ff08deee8a3efc54623011c772544d7b2767"
 
 [[package]]
 name = "anymap"
@@ -49,9 +49,9 @@ checksum = "33954243bd79057c2de7338850b85983a44588021f8a5fee574a8888c6de4344"
 
 [[package]]
 name = "arrayvec"
-version = "0.6.1"
+version = "0.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "269d0f5e68353a7cab87f81e7c736adc008d279a36ebc6a05dfe01193a89f0c9"
+checksum = "682f88bd1270f264991da8922b89ee1fb520b0da73f97c9f73cda54980123017"
 
 [[package]]
 name = "atty"
@@ -498,7 +498,6 @@ version = "0.0.0"
 dependencies = [
  "anymap",
  "base_db",
- "bitflags",
  "cfg",
  "cov-mark",
  "dashmap",
@@ -798,9 +797,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
 
 [[package]]
 name = "libc"
-version = "0.2.92"
+version = "0.2.91"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "56d855069fafbb9b344c0f962150cd2c1187975cb1c22c1522c240d8c4986714"
+checksum = "8916b1f6ca17130ec6568feccee27c156ad12037880833a3b842a823236502e7"
 
 [[package]]
 name = "libloading"
@@ -823,9 +822,9 @@ dependencies = [
 
 [[package]]
 name = "lock_api"
-version = "0.4.3"
+version = "0.4.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5a3c91c24eae6777794bb1997ad98bbb87daf92890acab859f7eaa4320333176"
+checksum = "dd96ffd135b2fd7b973ac026d28085defbe8983df057ced3eb4f2130b0831312"
 dependencies = [
  "scopeguard",
 ]
@@ -922,9 +921,9 @@ dependencies = [
 
 [[package]]
 name = "memoffset"
-version = "0.6.3"
+version = "0.6.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f83fb6581e8ed1f85fd45c116db8405483899489e38406156c25eb743554361d"
+checksum = "157b4208e3059a8f9e78d559edc658e13df41410cb3ae03979c83130067fdd87"
 dependencies = [
  "autocfg",
 ]
@@ -1158,9 +1157,9 @@ checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5"
 
 [[package]]
 name = "proc-macro2"
-version = "1.0.26"
+version = "1.0.24"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a152013215dca273577e18d2bf00fa862b89b24169fb78c4c95aeb07992c9cec"
+checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71"
 dependencies = [
  "unicode-xid",
 ]
@@ -1578,9 +1577,9 @@ dependencies = [
 
 [[package]]
 name = "syn"
-version = "1.0.68"
+version = "1.0.64"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3ce15dd3ed8aa2f8eeac4716d6ef5ab58b6b9256db41d7e1a0224c2788e8fd87"
+checksum = "3fd9d1e9976102a03c542daa2eff1b43f9d72306342f3f8b3ed5fb8908195d6f"
 dependencies = [
  "proc-macro2",
  "quote",
diff --git a/crates/hir/src/db.rs b/crates/hir/src/db.rs
index df57583423..1902a8d167 100644
--- a/crates/hir/src/db.rs
+++ b/crates/hir/src/db.rs
@@ -1,6 +1,14 @@
 //! FIXME: write short doc here
 
-pub use hir_def::db::*;
+pub use hir_def::db::{
+    AttrsQuery, BlockDefMapQuery, BodyQuery, BodyWithSourceMapQuery, ConstDataQuery,
+    CrateDefMapQueryQuery, CrateLangItemsQuery, DefDatabase, DefDatabaseStorage, EnumDataQuery,
+    ExprScopesQuery, FileItemTreeQuery, FunctionDataQuery, GenericParamsQuery, ImplDataQuery,
+    ImportMapQuery, InternConstQuery, InternDatabase, InternDatabaseStorage, InternEnumQuery,
+    InternFunctionQuery, InternImplQuery, InternStaticQuery, InternStructQuery, InternTraitQuery,
+    InternTypeAliasQuery, InternUnionQuery, LangItemQuery, StaticDataQuery, StructDataQuery,
+    TraitDataQuery, TypeAliasDataQuery, UnionDataQuery,
+};
 pub use hir_expand::db::{
     AstDatabase, AstDatabaseStorage, AstIdMapQuery, HygieneFrameQuery, InternEagerExpansionQuery,
     InternMacroQuery, MacroArgTextQuery, MacroDefQuery, MacroExpandQuery, ParseMacroExpansionQuery,
diff --git a/crates/hir/src/display.rs b/crates/hir/src/display.rs
index 559ea31a0a..ab04c55bc1 100644
--- a/crates/hir/src/display.rs
+++ b/crates/hir/src/display.rs
@@ -20,21 +20,22 @@ impl HirDisplay for Function {
     fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
         let data = f.db.function_data(self.id);
         write_visibility(self.module(f.db).id, self.visibility(f.db), f)?;
-        if data.is_default() {
+        let qual = &data.qualifier;
+        if qual.is_default {
             write!(f, "default ")?;
         }
-        if data.is_const() {
+        if qual.is_const {
             write!(f, "const ")?;
         }
-        if data.is_async() {
+        if qual.is_async {
             write!(f, "async ")?;
         }
-        if data.is_unsafe() {
+        if qual.is_unsafe {
             write!(f, "unsafe ")?;
         }
-        if let Some(abi) = &data.abi {
+        if let Some(abi) = &qual.abi {
             // FIXME: String escape?
-            write!(f, "extern \"{}\" ", &**abi)?;
+            write!(f, "extern \"{}\" ", abi)?;
         }
         write!(f, "fn {}", data.name)?;
 
@@ -67,7 +68,7 @@ impl HirDisplay for Function {
                 write!(f, ", ")?;
             } else {
                 first = false;
-                if data.has_self_param() {
+                if data.has_self_param {
                     write_self_param(type_ref, f)?;
                     continue;
                 }
@@ -87,7 +88,7 @@ impl HirDisplay for Function {
         // `FunctionData::ret_type` will be `::core::future::Future<Output = ...>` for async fns.
         // Use ugly pattern match to strip the Future trait.
         // Better way?
-        let ret_type = if !data.is_async() {
+        let ret_type = if !qual.is_async {
             &data.ret_type
         } else {
             match &*data.ret_type {
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index eb19e4b51a..29010191b5 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -832,7 +832,7 @@ impl Function {
     }
 
     pub fn self_param(self, db: &dyn HirDatabase) -> Option<SelfParam> {
-        if !db.function_data(self.id).has_self_param() {
+        if !db.function_data(self.id).has_self_param {
             return None;
         }
         Some(SelfParam { func: self.id })
@@ -864,7 +864,7 @@ impl Function {
     }
 
     pub fn is_unsafe(self, db: &dyn HirDatabase) -> bool {
-        db.function_data(self.id).is_unsafe()
+        db.function_data(self.id).qualifier.is_unsafe
     }
 
     pub fn diagnostics(self, db: &dyn HirDatabase, sink: &mut DiagnosticSink) {
@@ -878,7 +878,7 @@ impl Function {
     ///
     /// This is false in the case of required (not provided) trait methods.
     pub fn has_body(self, db: &dyn HirDatabase) -> bool {
-        db.function_data(self.id).has_body()
+        db.function_data(self.id).has_body
     }
 
     /// A textual representation of the HIR of this function for debugging purposes.
diff --git a/crates/hir_def/Cargo.toml b/crates/hir_def/Cargo.toml
index 60adb655c7..43324d8d9b 100644
--- a/crates/hir_def/Cargo.toml
+++ b/crates/hir_def/Cargo.toml
@@ -10,7 +10,6 @@ edition = "2018"
 doctest = false
 
 [dependencies]
-bitflags = "1.2.1"
 cov-mark = { version = "1.1", features = ["thread-local"] }
 dashmap = { version = "4.0.2", features = ["raw-api"] }
 log = "0.4.8"
diff --git a/crates/hir_def/src/attr.rs b/crates/hir_def/src/attr.rs
index 442c5fb5b3..2bab121d99 100644
--- a/crates/hir_def/src/attr.rs
+++ b/crates/hir_def/src/attr.rs
@@ -533,7 +533,7 @@ impl Attr {
             };
             Some(AttrInput::Literal(value))
         } else if let Some(tt) = ast.token_tree() {
-            Some(AttrInput::TokenTree(ast_to_token_tree(&tt).0))
+            Some(AttrInput::TokenTree(ast_to_token_tree(&tt)?.0))
         } else {
             None
         };
diff --git a/crates/hir_def/src/body.rs b/crates/hir_def/src/body.rs
index 96b959967f..1080d9c2c3 100644
--- a/crates/hir_def/src/body.rs
+++ b/crates/hir_def/src/body.rs
@@ -226,7 +226,7 @@ pub struct Body {
     /// The `ExprId` of the actual body expression.
     pub body_expr: ExprId,
     /// Block expressions in this body that may contain inner items.
-    block_scopes: Vec<BlockId>,
+    pub block_scopes: Vec<BlockId>,
     _c: Count<Self>,
 }
 
@@ -302,8 +302,7 @@ impl Body {
             }
         };
         let expander = Expander::new(db, file_id, module);
-        let (mut body, source_map) = Body::new(db, expander, params, body);
-        body.shrink_to_fit();
+        let (body, source_map) = Body::new(db, expander, params, body);
         (Arc::new(body), Arc::new(source_map))
     }
 
@@ -311,16 +310,6 @@ impl Body {
         db.body_with_source_map(def).0
     }
 
-    /// Returns an iterator over all block expressions in this body that define inner items.
-    pub fn blocks<'a>(
-        &'a self,
-        db: &'a dyn DefDatabase,
-    ) -> impl Iterator<Item = (BlockId, Arc<DefMap>)> + '_ {
-        self.block_scopes
-            .iter()
-            .map(move |block| (*block, db.block_def_map(*block).expect("block ID without DefMap")))
-    }
-
     fn new(
         db: &dyn DefDatabase,
         expander: Expander,
@@ -329,15 +318,6 @@ impl Body {
     ) -> (Body, BodySourceMap) {
         lower::lower(db, expander, params, body)
     }
-
-    fn shrink_to_fit(&mut self) {
-        let Self { _c: _, body_expr: _, block_scopes, exprs, labels, params, pats } = self;
-        block_scopes.shrink_to_fit();
-        exprs.shrink_to_fit();
-        labels.shrink_to_fit();
-        params.shrink_to_fit();
-        pats.shrink_to_fit();
-    }
 }
 
 impl Index<ExprId> for Body {
diff --git a/crates/hir_def/src/body/lower.rs b/crates/hir_def/src/body/lower.rs
index 63e89a1f42..229e81dd43 100644
--- a/crates/hir_def/src/body/lower.rs
+++ b/crates/hir_def/src/body/lower.rs
@@ -673,14 +673,12 @@ impl ExprCollector<'_> {
         let block_loc =
             BlockLoc { ast_id, module: self.expander.def_map.module_id(self.expander.module) };
         let block_id = self.db.intern_block(block_loc);
+        self.body.block_scopes.push(block_id);
 
-        let (module, def_map) = match self.db.block_def_map(block_id) {
-            Some(def_map) => {
-                self.body.block_scopes.push(block_id);
-                (def_map.root(), def_map)
-            }
-            None => (self.expander.module, self.expander.def_map.clone()),
-        };
+        let opt_def_map = self.db.block_def_map(block_id);
+        let has_def_map = opt_def_map.is_some();
+        let def_map = opt_def_map.unwrap_or_else(|| self.expander.def_map.clone());
+        let module = if has_def_map { def_map.root() } else { self.expander.module };
         let prev_def_map = mem::replace(&mut self.expander.def_map, def_map);
         let prev_local_module = mem::replace(&mut self.expander.module, module);
         let prev_statements = std::mem::take(&mut self.statements_in_scope);
diff --git a/crates/hir_def/src/child_by_source.rs b/crates/hir_def/src/child_by_source.rs
index f40a7f80d3..2a331dcaf9 100644
--- a/crates/hir_def/src/child_by_source.rs
+++ b/crates/hir_def/src/child_by_source.rs
@@ -160,7 +160,7 @@ impl ChildBySource for EnumId {
 impl ChildBySource for DefWithBodyId {
     fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap) {
         let body = db.body(*self);
-        for (_, def_map) in body.blocks(db) {
+        for def_map in body.block_scopes.iter().filter_map(|block| db.block_def_map(*block)) {
             // All block expressions are merged into the same map, because they logically all add
             // inner items to the containing `DefWithBodyId`.
             def_map[def_map.root()].scope.child_by_source_to(db, res);
diff --git a/crates/hir_def/src/data.rs b/crates/hir_def/src/data.rs
index b409fb45cd..31f9946819 100644
--- a/crates/hir_def/src/data.rs
+++ b/crates/hir_def/src/data.rs
@@ -10,7 +10,7 @@ use crate::{
     body::Expander,
     db::DefDatabase,
     intern::Interned,
-    item_tree::{AssocItem, FnFlags, ItemTreeId, ModItem, Param},
+    item_tree::{AssocItem, FunctionQualifier, ItemTreeId, ModItem, Param},
     type_ref::{TraitRef, TypeBound, TypeRef},
     visibility::RawVisibility,
     AssocContainerId, AssocItemId, ConstId, ConstLoc, FunctionId, FunctionLoc, HasModule, ImplId,
@@ -23,9 +23,14 @@ pub struct FunctionData {
     pub params: Vec<Interned<TypeRef>>,
     pub ret_type: Interned<TypeRef>,
     pub attrs: Attrs,
+    /// True if the first param is `self`. This is relevant to decide whether this
+    /// can be called as a method.
+    pub has_self_param: bool,
+    pub has_body: bool,
+    pub qualifier: FunctionQualifier,
+    pub is_in_extern_block: bool,
+    pub is_varargs: bool,
     pub visibility: RawVisibility,
-    pub abi: Option<Interned<str>>,
-    flags: FnFlags,
 }
 
 impl FunctionData {
@@ -48,11 +53,6 @@ impl FunctionData {
             .next_back()
             .map_or(false, |param| matches!(item_tree[param], Param::Varargs));
 
-        let mut flags = func.flags;
-        if is_varargs {
-            flags |= FnFlags::IS_VARARGS;
-        }
-
         Arc::new(FunctionData {
             name: func.name.clone(),
             params: enabled_params
@@ -64,45 +64,14 @@ impl FunctionData {
                 .collect(),
             ret_type: func.ret_type.clone(),
             attrs: item_tree.attrs(db, krate, ModItem::from(loc.id.value).into()),
+            has_self_param: func.has_self_param,
+            has_body: func.has_body,
+            qualifier: func.qualifier.clone(),
+            is_in_extern_block: func.is_in_extern_block,
+            is_varargs,
             visibility: item_tree[func.visibility].clone(),
-            abi: func.abi.clone(),
-            flags,
         })
     }
-
-    pub fn has_body(&self) -> bool {
-        self.flags.contains(FnFlags::HAS_BODY)
-    }
-
-    /// True if the first param is `self`. This is relevant to decide whether this
-    /// can be called as a method.
-    pub fn has_self_param(&self) -> bool {
-        self.flags.contains(FnFlags::HAS_SELF_PARAM)
-    }
-
-    pub fn is_default(&self) -> bool {
-        self.flags.contains(FnFlags::IS_DEFAULT)
-    }
-
-    pub fn is_const(&self) -> bool {
-        self.flags.contains(FnFlags::IS_CONST)
-    }
-
-    pub fn is_async(&self) -> bool {
-        self.flags.contains(FnFlags::IS_ASYNC)
-    }
-
-    pub fn is_unsafe(&self) -> bool {
-        self.flags.contains(FnFlags::IS_UNSAFE)
-    }
-
-    pub fn is_in_extern_block(&self) -> bool {
-        self.flags.contains(FnFlags::IS_IN_EXTERN_BLOCK)
-    }
-
-    pub fn is_varargs(&self) -> bool {
-        self.flags.contains(FnFlags::IS_VARARGS)
-    }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq)]
diff --git a/crates/hir_def/src/item_scope.rs b/crates/hir_def/src/item_scope.rs
index a8ee5eeac9..f3ebe7c727 100644
--- a/crates/hir_def/src/item_scope.rs
+++ b/crates/hir_def/src/item_scope.rs
@@ -285,28 +285,6 @@ impl ItemScope {
             buf.push('\n');
         }
     }
-
-    pub(crate) fn shrink_to_fit(&mut self) {
-        // Exhaustive match to require handling new fields.
-        let Self {
-            types,
-            values,
-            macros,
-            unresolved,
-            defs,
-            impls,
-            unnamed_trait_imports,
-            legacy_macros,
-        } = self;
-        types.shrink_to_fit();
-        values.shrink_to_fit();
-        macros.shrink_to_fit();
-        unresolved.shrink_to_fit();
-        defs.shrink_to_fit();
-        impls.shrink_to_fit();
-        unnamed_trait_imports.shrink_to_fit();
-        legacy_macros.shrink_to_fit();
-    }
 }
 
 impl PerNs {
diff --git a/crates/hir_def/src/item_tree.rs b/crates/hir_def/src/item_tree.rs
index c6d700977e..69a313c7e2 100644
--- a/crates/hir_def/src/item_tree.rs
+++ b/crates/hir_def/src/item_tree.rs
@@ -24,7 +24,7 @@ use la_arena::{Arena, Idx, RawIdx};
 use profile::Count;
 use rustc_hash::FxHashMap;
 use smallvec::SmallVec;
-use syntax::{ast, match_ast, SyntaxKind};
+use syntax::{ast, match_ast, SmolStr, SyntaxKind};
 
 use crate::{
     attr::{Attrs, RawAttrs},
@@ -529,7 +529,7 @@ impl<N: ItemTreeNode> Index<FileItemTreeId<N>> for ItemTree {
 /// A desugared `use` import.
 #[derive(Debug, Clone, Eq, PartialEq)]
 pub struct Import {
-    pub path: Interned<ModPath>,
+    pub path: ModPath,
     pub alias: Option<ImportAlias>,
     pub visibility: RawVisibilityId,
     pub is_glob: bool,
@@ -556,11 +556,15 @@ pub struct Function {
     pub name: Name,
     pub visibility: RawVisibilityId,
     pub generic_params: GenericParamsId,
-    pub abi: Option<Interned<str>>,
+    pub has_self_param: bool,
+    pub has_body: bool,
+    pub qualifier: FunctionQualifier,
+    /// Whether the function is located in an `extern` block (*not* whether it is an
+    /// `extern "abi" fn`).
+    pub is_in_extern_block: bool,
     pub params: IdRange<Param>,
     pub ret_type: Interned<TypeRef>,
     pub ast_id: FileAstId<ast::Fn>,
-    pub(crate) flags: FnFlags,
 }
 
 #[derive(Debug, Clone, Eq, PartialEq)]
@@ -569,20 +573,13 @@ pub enum Param {
     Varargs,
 }
 
-bitflags::bitflags! {
-    /// NOTE: Shared with `FunctionData`
-    pub(crate) struct FnFlags: u8 {
-        const HAS_SELF_PARAM = 1 << 0;
-        const HAS_BODY = 1 << 1;
-        const IS_DEFAULT = 1 << 2;
-        const IS_CONST = 1 << 3;
-        const IS_ASYNC = 1 << 4;
-        const IS_UNSAFE = 1 << 5;
-        /// Whether the function is located in an `extern` block (*not* whether it is an
-        /// `extern "abi" fn`).
-        const IS_IN_EXTERN_BLOCK = 1 << 6;
-        const IS_VARARGS = 1 << 7;
-    }
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub struct FunctionQualifier {
+    pub is_default: bool,
+    pub is_const: bool,
+    pub is_async: bool,
+    pub is_unsafe: bool,
+    pub abi: Option<SmolStr>,
 }
 
 #[derive(Debug, Clone, Eq, PartialEq)]
diff --git a/crates/hir_def/src/item_tree/lower.rs b/crates/hir_def/src/item_tree/lower.rs
index 39e8403b09..5247379c58 100644
--- a/crates/hir_def/src/item_tree/lower.rs
+++ b/crates/hir_def/src/item_tree/lower.rs
@@ -395,51 +395,39 @@ impl Ctx {
             ret_type
         };
 
-        let abi = func.abi().map(|abi| {
-            // FIXME: Abi::abi() -> Option<SyntaxToken>?
-            match abi.syntax().last_token() {
-                Some(tok) if tok.kind() == SyntaxKind::STRING => {
-                    // FIXME: Better way to unescape?
-                    Interned::new_str(tok.text().trim_matches('"'))
-                }
-                _ => {
-                    // `extern` default to be `extern "C"`.
-                    Interned::new_str("C")
-                }
-            }
-        });
+        let has_body = func.body().is_some();
 
         let ast_id = self.source_ast_id_map.ast_id(func);
-
-        let mut flags = FnFlags::empty();
-        if func.body().is_some() {
-            flags |= FnFlags::HAS_BODY;
-        }
-        if has_self_param {
-            flags |= FnFlags::HAS_SELF_PARAM;
-        }
-        if func.default_token().is_some() {
-            flags |= FnFlags::IS_DEFAULT;
-        }
-        if func.const_token().is_some() {
-            flags |= FnFlags::IS_CONST;
-        }
-        if func.async_token().is_some() {
-            flags |= FnFlags::IS_ASYNC;
-        }
-        if func.unsafe_token().is_some() {
-            flags |= FnFlags::IS_UNSAFE;
-        }
-
+        let qualifier = FunctionQualifier {
+            is_default: func.default_token().is_some(),
+            is_const: func.const_token().is_some(),
+            is_async: func.async_token().is_some(),
+            is_unsafe: func.unsafe_token().is_some(),
+            abi: func.abi().map(|abi| {
+                // FIXME: Abi::abi() -> Option<SyntaxToken>?
+                match abi.syntax().last_token() {
+                    Some(tok) if tok.kind() == SyntaxKind::STRING => {
+                        // FIXME: Better way to unescape?
+                        tok.text().trim_matches('"').into()
+                    }
+                    _ => {
+                        // `extern` default to be `extern "C"`.
+                        "C".into()
+                    }
+                }
+            }),
+        };
         let mut res = Function {
             name,
             visibility,
             generic_params: GenericParamsId::EMPTY,
-            abi,
+            has_self_param,
+            has_body,
+            qualifier,
+            is_in_extern_block: false,
             params,
             ret_type: Interned::new(ret_type),
             ast_id,
-            flags,
         };
         res.generic_params = self.lower_generic_params(GenericsOwner::Function(&res), func);
 
@@ -589,7 +577,7 @@ impl Ctx {
             &self.hygiene,
             |path, _use_tree, is_glob, alias| {
                 imports.push(id(tree.imports.alloc(Import {
-                    path: Interned::new(path),
+                    path,
                     alias,
                     visibility,
                     is_glob,
@@ -652,10 +640,8 @@ impl Ctx {
                         ast::ExternItem::Fn(ast) => {
                             let func_id = self.lower_function(&ast)?;
                             let func = &mut self.data().functions[func_id.index];
-                            if is_intrinsic_fn_unsafe(&func.name) {
-                                func.flags |= FnFlags::IS_UNSAFE;
-                            }
-                            func.flags |= FnFlags::IS_IN_EXTERN_BLOCK;
+                            func.qualifier.is_unsafe = is_intrinsic_fn_unsafe(&func.name);
+                            func.is_in_extern_block = true;
                             func_id.into()
                         }
                         ast::ExternItem::Static(ast) => {
diff --git a/crates/hir_def/src/nameres.rs b/crates/hir_def/src/nameres.rs
index 7dd68219fd..9e8e4e9ec6 100644
--- a/crates/hir_def/src/nameres.rs
+++ b/crates/hir_def/src/nameres.rs
@@ -409,31 +409,6 @@ impl DefMap {
             }
         }
     }
-
-    fn shrink_to_fit(&mut self) {
-        // Exhaustive match to require handling new fields.
-        let Self {
-            _c: _,
-            exported_proc_macros,
-            extern_prelude,
-            diagnostics,
-            modules,
-            block: _,
-            edition: _,
-            krate: _,
-            prelude: _,
-            root: _,
-        } = self;
-
-        extern_prelude.shrink_to_fit();
-        exported_proc_macros.shrink_to_fit();
-        diagnostics.shrink_to_fit();
-        modules.shrink_to_fit();
-        for (_, module) in modules.iter_mut() {
-            module.children.shrink_to_fit();
-            module.scope.shrink_to_fit();
-        }
-    }
 }
 
 impl ModuleData {
diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs
index 4ddc791ce9..c8f4947078 100644
--- a/crates/hir_def/src/nameres/collector.rs
+++ b/crates/hir_def/src/nameres/collector.rs
@@ -23,7 +23,6 @@ use crate::{
     attr::Attrs,
     db::DefDatabase,
     derive_macro_as_call_id,
-    intern::Interned,
     item_scope::{ImportType, PerNsGlobImports},
     item_tree::{
         self, FileItemTreeId, ItemTree, ItemTreeId, MacroCall, MacroDef, MacroRules, Mod, ModItem,
@@ -109,9 +108,7 @@ pub(super) fn collect_defs(
         }
     }
     collector.collect();
-    let mut def_map = collector.finish();
-    def_map.shrink_to_fit();
-    def_map
+    collector.finish()
 }
 
 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
@@ -142,7 +139,7 @@ enum ImportSource {
 
 #[derive(Clone, Debug, Eq, PartialEq)]
 struct Import {
-    path: Interned<ModPath>,
+    path: ModPath,
     alias: Option<ImportAlias>,
     visibility: RawVisibility,
     is_glob: bool,
@@ -184,10 +181,7 @@ impl Import {
         let attrs = &tree.attrs(db, krate, ModItem::from(id.value).into());
         let visibility = &tree[it.visibility];
         Self {
-            path: Interned::new(ModPath::from_segments(
-                PathKind::Plain,
-                iter::once(it.name.clone()),
-            )),
+            path: ModPath::from_segments(PathKind::Plain, iter::once(it.name.clone())),
             alias: it.alias.clone(),
             visibility: visibility.clone(),
             is_glob: false,
diff --git a/crates/hir_expand/src/builtin_macro.rs b/crates/hir_expand/src/builtin_macro.rs
index 75ec4196b6..3aa3d8997d 100644
--- a/crates/hir_expand/src/builtin_macro.rs
+++ b/crates/hir_expand/src/builtin_macro.rs
@@ -584,7 +584,7 @@ mod tests {
                 };
 
                 let args = macro_call.token_tree().unwrap();
-                let parsed_args = mbe::ast_to_token_tree(&args).0;
+                let parsed_args = mbe::ast_to_token_tree(&args).unwrap().0;
                 let call_id = AstId::new(file_id.into(), ast_id_map.ast_id(&macro_call));
 
                 let arg_id = db.intern_eager_expansion({
diff --git a/crates/hir_expand/src/db.rs b/crates/hir_expand/src/db.rs
index 10fe608215..c0ab70b607 100644
--- a/crates/hir_expand/src/db.rs
+++ b/crates/hir_expand/src/db.rs
@@ -119,7 +119,7 @@ pub fn expand_hypothetical(
     token_to_map: syntax::SyntaxToken,
 ) -> Option<(SyntaxNode, syntax::SyntaxToken)> {
     let macro_file = MacroFile { macro_call_id: actual_macro_call };
-    let (tt, tmap_1) = mbe::syntax_node_to_token_tree(hypothetical_args.syntax());
+    let (tt, tmap_1) = mbe::syntax_node_to_token_tree(hypothetical_args.syntax()).unwrap();
     let range =
         token_to_map.text_range().checked_sub(hypothetical_args.syntax().text_range().start())?;
     let token_id = tmap_1.token_by_range(range)?;
@@ -143,7 +143,10 @@ fn macro_def(db: &dyn AstDatabase, id: MacroDefId) -> Option<Arc<(TokenExpander,
         MacroDefKind::Declarative(ast_id) => match ast_id.to_node(db) {
             syntax::ast::Macro::MacroRules(macro_rules) => {
                 let arg = macro_rules.token_tree()?;
-                let (tt, tmap) = mbe::ast_to_token_tree(&arg);
+                let (tt, tmap) = mbe::ast_to_token_tree(&arg).or_else(|| {
+                    log::warn!("fail on macro_rules to token tree: {:#?}", arg);
+                    None
+                })?;
                 let rules = match MacroRules::parse(&tt) {
                     Ok(it) => it,
                     Err(err) => {
@@ -156,7 +159,10 @@ fn macro_def(db: &dyn AstDatabase, id: MacroDefId) -> Option<Arc<(TokenExpander,
             }
             syntax::ast::Macro::MacroDef(macro_def) => {
                 let arg = macro_def.body()?;
-                let (tt, tmap) = mbe::ast_to_token_tree(&arg);
+                let (tt, tmap) = mbe::ast_to_token_tree(&arg).or_else(|| {
+                    log::warn!("fail on macro_def to token tree: {:#?}", arg);
+                    None
+                })?;
                 let rules = match MacroDef::parse(&tt) {
                     Ok(it) => it,
                     Err(err) => {
@@ -196,7 +202,7 @@ fn macro_arg_text(db: &dyn AstDatabase, id: MacroCallId) -> Option<GreenNode> {
 
 fn macro_arg(db: &dyn AstDatabase, id: MacroCallId) -> Option<Arc<(tt::Subtree, mbe::TokenMap)>> {
     let arg = db.macro_arg_text(id)?;
-    let (tt, tmap) = mbe::syntax_node_to_token_tree(&SyntaxNode::new_root(arg));
+    let (tt, tmap) = mbe::syntax_node_to_token_tree(&SyntaxNode::new_root(arg))?;
     Some(Arc::new((tt, tmap)))
 }
 
diff --git a/crates/hir_expand/src/eager.rs b/crates/hir_expand/src/eager.rs
index 9705526fae..9eedc84614 100644
--- a/crates/hir_expand/src/eager.rs
+++ b/crates/hir_expand/src/eager.rs
@@ -106,7 +106,7 @@ pub fn expand_eager_macro(
     mut diagnostic_sink: &mut dyn FnMut(mbe::ExpandError),
 ) -> Result<EagerMacroId, ErrorEmitted> {
     let parsed_args = diagnostic_sink.option_with(
-        || Some(mbe::ast_to_token_tree(&macro_call.value.token_tree()?).0),
+        || Some(mbe::ast_to_token_tree(&macro_call.value.token_tree()?)?.0),
         || err("malformed macro invocation"),
     )?;
 
@@ -161,7 +161,7 @@ pub fn expand_eager_macro(
 }
 
 fn to_subtree(node: &SyntaxNode) -> Option<tt::Subtree> {
-    let mut subtree = mbe::syntax_node_to_token_tree(node).0;
+    let mut subtree = mbe::syntax_node_to_token_tree(node)?.0;
     subtree.delimiter = None;
     Some(subtree)
 }
diff --git a/crates/hir_ty/src/diagnostics/decl_check.rs b/crates/hir_ty/src/diagnostics/decl_check.rs
index 1c9f9ede76..33a0f4d7d4 100644
--- a/crates/hir_ty/src/diagnostics/decl_check.rs
+++ b/crates/hir_ty/src/diagnostics/decl_check.rs
@@ -91,7 +91,7 @@ impl<'a, 'b> DeclValidator<'a, 'b> {
 
     fn validate_func(&mut self, func: FunctionId) {
         let data = self.db.function_data(func);
-        if data.is_in_extern_block() {
+        if data.is_in_extern_block {
             cov_mark::hit!(extern_func_incorrect_case_ignored);
             return;
         }
@@ -99,7 +99,8 @@ impl<'a, 'b> DeclValidator<'a, 'b> {
         let body = self.db.body(func.into());
 
         // Recursively validate inner scope items, such as static variables and constants.
-        for (_, block_def_map) in body.blocks(self.db.upcast()) {
+        let db = self.db;
+        for block_def_map in body.block_scopes.iter().filter_map(|block| db.block_def_map(*block)) {
             for (_, module) in block_def_map.modules() {
                 for def_id in module.scope.declarations() {
                     let mut validator = DeclValidator::new(self.db, self.krate, self.sink);
diff --git a/crates/hir_ty/src/diagnostics/unsafe_check.rs b/crates/hir_ty/src/diagnostics/unsafe_check.rs
index b5efe9df5c..a71eebc6fa 100644
--- a/crates/hir_ty/src/diagnostics/unsafe_check.rs
+++ b/crates/hir_ty/src/diagnostics/unsafe_check.rs
@@ -32,7 +32,7 @@ impl<'a, 'b> UnsafeValidator<'a, 'b> {
         let def = self.owner;
         let unsafe_expressions = unsafe_expressions(db, self.infer.as_ref(), def);
         let is_unsafe = match self.owner {
-            DefWithBodyId::FunctionId(it) => db.function_data(it).is_unsafe(),
+            DefWithBodyId::FunctionId(it) => db.function_data(it).qualifier.is_unsafe,
             DefWithBodyId::StaticId(_) | DefWithBodyId::ConstId(_) => false,
         };
         if is_unsafe
@@ -86,7 +86,7 @@ fn walk_unsafe(
     match expr {
         &Expr::Call { callee, .. } => {
             if let Some(func) = infer[callee].as_fn_def(db) {
-                if db.function_data(func).is_unsafe() {
+                if db.function_data(func).qualifier.is_unsafe {
                     unsafe_exprs.push(UnsafeExpr { expr: current, inside_unsafe_block });
                 }
             }
@@ -103,7 +103,7 @@ fn walk_unsafe(
         Expr::MethodCall { .. } => {
             if infer
                 .method_resolution(current)
-                .map(|func| db.function_data(func).is_unsafe())
+                .map(|func| db.function_data(func).qualifier.is_unsafe)
                 .unwrap_or(false)
             {
                 unsafe_exprs.push(UnsafeExpr { expr: current, inside_unsafe_block });
diff --git a/crates/hir_ty/src/lower.rs b/crates/hir_ty/src/lower.rs
index e60d7c730d..f595683e5f 100644
--- a/crates/hir_ty/src/lower.rs
+++ b/crates/hir_ty/src/lower.rs
@@ -1054,7 +1054,7 @@ fn fn_sig_for_fn(db: &dyn HirDatabase, def: FunctionId) -> PolyFnSig {
     let ret = (&ctx_ret).lower_ty(&data.ret_type);
     let generics = generics(db.upcast(), def.into());
     let num_binders = generics.len();
-    Binders::new(num_binders, CallableSig::from_params_and_return(params, ret, data.is_varargs()))
+    Binders::new(num_binders, CallableSig::from_params_and_return(params, ret, data.is_varargs))
 }
 
 /// Build the declared type of a function. This should not need to look at the
diff --git a/crates/hir_ty/src/method_resolution.rs b/crates/hir_ty/src/method_resolution.rs
index c093fce201..338851fa81 100644
--- a/crates/hir_ty/src/method_resolution.rs
+++ b/crates/hir_ty/src/method_resolution.rs
@@ -675,7 +675,7 @@ fn is_valid_candidate(
                 }
             }
             if let Some(receiver_ty) = receiver_ty {
-                if !data.has_self_param() {
+                if !data.has_self_param {
                     return false;
                 }
                 let transformed_receiver_ty = match transform_receiver_ty(db, m, self_ty) {
diff --git a/crates/ide_assists/src/handlers/reorder_fields.rs b/crates/ide_assists/src/handlers/reorder_fields.rs
index 383ca6c473..1a95135ca1 100644
--- a/crates/ide_assists/src/handlers/reorder_fields.rs
+++ b/crates/ide_assists/src/handlers/reorder_fields.rs
@@ -1,6 +1,8 @@
+use either::Either;
+use itertools::Itertools;
 use rustc_hash::FxHashMap;
 
-use syntax::{algo, ast, match_ast, AstNode, SyntaxKind::*, SyntaxNode};
+use syntax::{ast, ted, AstNode};
 
 use crate::{AssistContext, AssistId, AssistKind, Assists};
 
@@ -22,60 +24,70 @@ use crate::{AssistContext, AssistId, AssistKind, Assists};
 pub(crate) fn reorder_fields(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
     let record = ctx
         .find_node_at_offset::<ast::RecordExpr>()
-        .map(|it| it.syntax().clone())
-        .or_else(|| ctx.find_node_at_offset::<ast::RecordPat>().map(|it| it.syntax().clone()))?;
-
-    let path = record.children().find_map(ast::Path::cast)?;
+        .map(Either::Left)
+        .or_else(|| ctx.find_node_at_offset::<ast::RecordPat>().map(Either::Right))?;
 
+    let path = record.as_ref().either(|it| it.path(), |it| it.path())?;
     let ranks = compute_fields_ranks(&path, &ctx)?;
+    let get_rank_of_field =
+        |of: Option<_>| *ranks.get(&of.unwrap_or_default()).unwrap_or(&usize::MAX);
 
-    let fields: Vec<SyntaxNode> = {
-        let field_kind = match record.kind() {
-            RECORD_EXPR => RECORD_EXPR_FIELD,
-            RECORD_PAT => RECORD_PAT_FIELD,
-            _ => {
-                stdx::never!();
-                return None;
-            }
-        };
-        record.children().flat_map(|n| n.children()).filter(|n| n.kind() == field_kind).collect()
+    let field_list = match &record {
+        Either::Left(it) => Either::Left(it.record_expr_field_list()?),
+        Either::Right(it) => Either::Right(it.record_pat_field_list()?),
     };
-
-    let sorted_fields = {
-        let mut fields = fields.clone();
-        fields.sort_by_key(|node| *ranks.get(&get_field_name(node)).unwrap_or(&usize::max_value()));
-        fields
+    let fields = match field_list {
+        Either::Left(it) => Either::Left((
+            it.fields()
+                .sorted_unstable_by_key(|field| {
+                    get_rank_of_field(field.field_name().map(|it| it.to_string()))
+                })
+                .collect::<Vec<_>>(),
+            it,
+        )),
+        Either::Right(it) => Either::Right((
+            it.fields()
+                .sorted_unstable_by_key(|field| {
+                    get_rank_of_field(field.field_name().map(|it| it.to_string()))
+                })
+                .collect::<Vec<_>>(),
+            it,
+        )),
     };
 
-    if sorted_fields == fields {
+    let is_sorted = fields.as_ref().either(
+        |(sorted, field_list)| field_list.fields().zip(sorted).all(|(a, b)| a == *b),
+        |(sorted, field_list)| field_list.fields().zip(sorted).all(|(a, b)| a == *b),
+    );
+    if is_sorted {
         cov_mark::hit!(reorder_sorted_fields);
         return None;
     }
-
-    let target = record.text_range();
+    let target = record.as_ref().either(AstNode::syntax, AstNode::syntax).text_range();
     acc.add(
         AssistId("reorder_fields", AssistKind::RefactorRewrite),
         "Reorder record fields",
         target,
-        |edit| {
-            let mut rewriter = algo::SyntaxRewriter::default();
-            for (old, new) in fields.iter().zip(&sorted_fields) {
-                rewriter.replace(old, new);
+        |builder| match fields {
+            Either::Left((sorted, field_list)) => {
+                replace(builder.make_ast_mut(field_list).fields(), sorted)
+            }
+            Either::Right((sorted, field_list)) => {
+                replace(builder.make_ast_mut(field_list).fields(), sorted)
             }
-            edit.rewrite(rewriter);
         },
     )
 }
 
-fn get_field_name(node: &SyntaxNode) -> String {
-    let res = match_ast! {
-        match node {
-            ast::RecordExprField(field) => field.field_name().map(|it| it.to_string()),
-            ast::RecordPatField(field) => field.field_name().map(|it| it.to_string()),
-            _ => None,
-        }
-    };
-    res.unwrap_or_default()
+fn replace<T: AstNode + PartialEq>(
+    fields: impl Iterator<Item = T>,
+    sorted_fields: impl IntoIterator<Item = T>,
+) {
+    fields.zip(sorted_fields).filter(|(field, sorted)| field != sorted).for_each(
+        |(field, sorted_field)| {
+            ted::replace(field.syntax(), sorted_field.syntax().clone_for_update());
+        },
+    );
 }
 
 fn compute_fields_ranks(path: &ast::Path, ctx: &AssistContext) -> Option<FxHashMap<String, usize>> {
@@ -86,7 +98,7 @@ fn compute_fields_ranks(path: &ast::Path, ctx: &AssistContext) -> Option<FxHashM
 
     let res = strukt
         .fields(ctx.db())
-        .iter()
+        .into_iter()
         .enumerate()
         .map(|(idx, field)| (field.name(ctx.db()).to_string(), idx))
         .collect();
@@ -137,7 +149,6 @@ const test: Foo = Foo { foo: 1, bar: 0 };
 "#,
         )
     }
-
     #[test]
     fn reorder_struct_pattern() {
         check_assist(
diff --git a/crates/mbe/src/benchmark.rs b/crates/mbe/src/benchmark.rs
index 38707ffa5b..ba814a2e1a 100644
--- a/crates/mbe/src/benchmark.rs
+++ b/crates/mbe/src/benchmark.rs
@@ -65,7 +65,7 @@ fn macro_rules_fixtures_tt() -> FxHashMap<String, tt::Subtree> {
         .filter_map(ast::MacroRules::cast)
         .map(|rule| {
             let id = rule.name().unwrap().to_string();
-            let (def_tt, _) = ast_to_token_tree(&rule.token_tree().unwrap());
+            let (def_tt, _) = ast_to_token_tree(&rule.token_tree().unwrap()).unwrap();
             (id, def_tt)
         })
         .collect()
diff --git a/crates/mbe/src/expander.rs b/crates/mbe/src/expander.rs
index bfef7f73d5..3197c834cf 100644
--- a/crates/mbe/src/expander.rs
+++ b/crates/mbe/src/expander.rs
@@ -159,7 +159,8 @@ mod tests {
         let macro_definition =
             source_file.syntax().descendants().find_map(ast::MacroRules::cast).unwrap();
 
-        let (definition_tt, _) = ast_to_token_tree(&macro_definition.token_tree().unwrap());
+        let (definition_tt, _) =
+            ast_to_token_tree(&macro_definition.token_tree().unwrap()).unwrap();
         crate::MacroRules::parse(&definition_tt).unwrap()
     }
 
@@ -168,7 +169,8 @@ mod tests {
         let macro_invocation =
             source_file.syntax().descendants().find_map(ast::MacroCall::cast).unwrap();
 
-        let (invocation_tt, _) = ast_to_token_tree(&macro_invocation.token_tree().unwrap());
+        let (invocation_tt, _) =
+            ast_to_token_tree(&macro_invocation.token_tree().unwrap()).unwrap();
 
         expand_rules(&rules.rules, &invocation_tt)
     }
diff --git a/crates/mbe/src/syntax_bridge.rs b/crates/mbe/src/syntax_bridge.rs
index 9ba98f7fba..ae0780072a 100644
--- a/crates/mbe/src/syntax_bridge.rs
+++ b/crates/mbe/src/syntax_bridge.rs
@@ -43,18 +43,18 @@ pub struct TokenMap {
 
 /// Convert the syntax tree (what user has written) to a `TokenTree` (what macro
 /// will consume).
-pub fn ast_to_token_tree(ast: &impl ast::AstNode) -> (tt::Subtree, TokenMap) {
+pub fn ast_to_token_tree(ast: &impl ast::AstNode) -> Option<(tt::Subtree, TokenMap)> {
     syntax_node_to_token_tree(ast.syntax())
 }
 
 /// Convert the syntax node to a `TokenTree` (what macro
 /// will consume).
-pub fn syntax_node_to_token_tree(node: &SyntaxNode) -> (tt::Subtree, TokenMap) {
+pub fn syntax_node_to_token_tree(node: &SyntaxNode) -> Option<(tt::Subtree, TokenMap)> {
     let global_offset = node.text_range().start();
     let mut c = Convertor::new(node, global_offset);
-    let subtree = c.go();
+    let subtree = c.go()?;
     c.id_alloc.map.entries.shrink_to_fit();
-    (subtree, c.id_alloc.map)
+    Some((subtree, c.id_alloc.map))
 }
 
 // The following items are what `rustc` macro can be parsed into :
@@ -108,7 +108,7 @@ pub fn parse_to_token_tree(text: &str) -> Option<(tt::Subtree, TokenMap)> {
         },
     };
 
-    let subtree = conv.go();
+    let subtree = conv.go()?;
     Some((subtree, conv.id_alloc.map))
 }
 
@@ -319,7 +319,7 @@ trait SrcToken: std::fmt::Debug {
 trait TokenConvertor {
     type Token: SrcToken;
 
-    fn go(&mut self) -> tt::Subtree {
+    fn go(&mut self) -> Option<tt::Subtree> {
         let mut subtree = tt::Subtree::default();
         subtree.delimiter = None;
         while self.peek().is_some() {
@@ -327,10 +327,10 @@ trait TokenConvertor {
         }
         if subtree.token_trees.len() == 1 {
             if let tt::TokenTree::Subtree(first) = &subtree.token_trees[0] {
-                return first.clone();
+                return Some(first.clone());
             }
         }
-        subtree
+        Some(subtree)
     }
 
     fn collect_leaf(&mut self, result: &mut Vec<tt::TokenTree>) {
@@ -858,7 +858,7 @@ mod tests {
         // - T!['}']
         // - WHITE_SPACE
         let token_tree = ast::TokenTree::cast(token_tree).unwrap();
-        let tt = ast_to_token_tree(&token_tree).0;
+        let tt = ast_to_token_tree(&token_tree).unwrap().0;
 
         assert_eq!(tt.delimiter_kind(), Some(tt::DelimiterKind::Brace));
     }
@@ -867,7 +867,7 @@ mod tests {
     fn test_token_tree_multi_char_punct() {
         let source_file = ast::SourceFile::parse("struct Foo { a: x::Y }").ok().unwrap();
         let struct_def = source_file.syntax().descendants().find_map(ast::Struct::cast).unwrap();
-        let tt = ast_to_token_tree(&struct_def).0;
+        let tt = ast_to_token_tree(&struct_def).unwrap().0;
         token_tree_to_syntax_node(&tt, FragmentKind::Item).unwrap();
     }
 }
diff --git a/crates/rust-analyzer/src/cargo_target_spec.rs b/crates/rust-analyzer/src/cargo_target_spec.rs
index 909c215322..5af0802a2f 100644
--- a/crates/rust-analyzer/src/cargo_target_spec.rs
+++ b/crates/rust-analyzer/src/cargo_target_spec.rs
@@ -201,7 +201,7 @@ mod tests {
         let cfg_expr = {
             let source_file = ast::SourceFile::parse(cfg).ok().unwrap();
             let tt = source_file.syntax().descendants().find_map(ast::TokenTree::cast).unwrap();
-            let (tt, _) = ast_to_token_tree(&tt);
+            let (tt, _) = ast_to_token_tree(&tt).unwrap();
             CfgExpr::parse(&tt)
         };
 
diff --git a/lib/arena/src/lib.rs b/lib/arena/src/lib.rs
index bce15c8679..230a502910 100644
--- a/lib/arena/src/lib.rs
+++ b/lib/arena/src/lib.rs
@@ -194,29 +194,6 @@ impl<T> Arena<T> {
         self.data.iter().enumerate().map(|(idx, value)| (Idx::from_raw(RawIdx(idx as u32)), value))
     }
 
-    /// Returns an iterator over the arena’s mutable elements.
-    ///
-    /// ```
-    /// let mut arena = la_arena::Arena::new();
-    /// let idx1 = arena.alloc(20);
-    ///
-    /// assert_eq!(arena[idx1], 20);
-    ///
-    /// let mut iterator = arena.iter_mut();
-    /// *iterator.next().unwrap().1 = 10;
-    /// drop(iterator);
-    ///
-    /// assert_eq!(arena[idx1], 10);
-    /// ```
-    pub fn iter_mut(
-        &mut self,
-    ) -> impl Iterator<Item = (Idx<T>, &mut T)> + ExactSizeIterator + DoubleEndedIterator {
-        self.data
-            .iter_mut()
-            .enumerate()
-            .map(|(idx, value)| (Idx::from_raw(RawIdx(idx as u32)), value))
-    }
-
     /// Reallocates the arena to make it take up as little space as possible.
     pub fn shrink_to_fit(&mut self) {
         self.data.shrink_to_fit();


Test patch:
diff --git a/crates/cfg/src/tests.rs b/crates/cfg/src/tests.rs
index d8736c893d..bd0f9ec483 100644
--- a/crates/cfg/src/tests.rs
+++ b/crates/cfg/src/tests.rs
@@ -8,7 +8,7 @@ fn assert_parse_result(input: &str, expected: CfgExpr) {
     let (tt, _) = {
         let source_file = ast::SourceFile::parse(input).ok().unwrap();
         let tt = source_file.syntax().descendants().find_map(ast::TokenTree::cast).unwrap();
-        ast_to_token_tree(&tt)
+        ast_to_token_tree(&tt).unwrap()
     };
     let cfg = CfgExpr::parse(&tt);
     assert_eq!(cfg, expected);
@@ -18,7 +18,7 @@ fn check_dnf(input: &str, expect: Expect) {
     let (tt, _) = {
         let source_file = ast::SourceFile::parse(input).ok().unwrap();
         let tt = source_file.syntax().descendants().find_map(ast::TokenTree::cast).unwrap();
-        ast_to_token_tree(&tt)
+        ast_to_token_tree(&tt).unwrap()
     };
     let cfg = CfgExpr::parse(&tt);
     let actual = format!("#![cfg({})]", DnfExpr::new(cfg));
@@ -29,7 +29,7 @@ fn check_why_inactive(input: &str, opts: &CfgOptions, expect: Expect) {
     let (tt, _) = {
         let source_file = ast::SourceFile::parse(input).ok().unwrap();
         let tt = source_file.syntax().descendants().find_map(ast::TokenTree::cast).unwrap();
-        ast_to_token_tree(&tt)
+        ast_to_token_tree(&tt).unwrap()
     };
     let cfg = CfgExpr::parse(&tt);
     let dnf = DnfExpr::new(cfg);
@@ -42,7 +42,7 @@ fn check_enable_hints(input: &str, opts: &CfgOptions, expected_hints: &[&str]) {
     let (tt, _) = {
         let source_file = ast::SourceFile::parse(input).ok().unwrap();
         let tt = source_file.syntax().descendants().find_map(ast::TokenTree::cast).unwrap();
-        ast_to_token_tree(&tt)
+        ast_to_token_tree(&tt).unwrap()
     };
     let cfg = CfgExpr::parse(&tt);
     let dnf = DnfExpr::new(cfg);
diff --git a/crates/hir_ty/src/tests.rs b/crates/hir_ty/src/tests.rs
index ccfb88c52d..ad283c1e04 100644
--- a/crates/hir_ty/src/tests.rs
+++ b/crates/hir_ty/src/tests.rs
@@ -288,7 +288,7 @@ fn visit_module(
     }
 
     fn visit_body(db: &TestDB, body: &Body, cb: &mut dyn FnMut(DefWithBodyId)) {
-        for (_, def_map) in body.blocks(db) {
+        for def_map in body.block_scopes.iter().filter_map(|block| db.block_def_map(*block)) {
             for (mod_id, _) in def_map.modules() {
                 visit_module(db, &def_map, mod_id, cb);
             }
diff --git a/crates/mbe/src/tests.rs b/crates/mbe/src/tests.rs
index 3698ff3f0f..6da18ecf4e 100644
--- a/crates/mbe/src/tests.rs
+++ b/crates/mbe/src/tests.rs
@@ -29,7 +29,8 @@ macro_rules! impl_fixture {
                 let macro_invocation =
                     source_file.syntax().descendants().find_map(ast::MacroCall::cast).unwrap();
 
-                let (invocation_tt, _) = ast_to_token_tree(&macro_invocation.token_tree().unwrap());
+                let (invocation_tt, _) = ast_to_token_tree(&macro_invocation.token_tree().unwrap())
+                    .ok_or_else(|| ExpandError::ConversionError)?;
 
                 self.rules.expand(&invocation_tt).result()
             }
@@ -100,7 +101,7 @@ macro_rules! impl_fixture {
                         .descendants()
                         .find_map(ast::TokenTree::cast)
                         .unwrap();
-                    let mut wrapped = ast_to_token_tree(&wrapped).0;
+                    let mut wrapped = ast_to_token_tree(&wrapped).unwrap().0;
                     wrapped.delimiter = None;
                     wrapped
                 };
@@ -150,7 +151,7 @@ pub(crate) fn parse_macro_error(ra_fixture: &str) -> ParseError {
 
 pub(crate) fn parse_to_token_tree_by_syntax(ra_fixture: &str) -> tt::Subtree {
     let source_file = ast::SourceFile::parse(ra_fixture).ok().unwrap();
-    let tt = syntax_node_to_token_tree(source_file.syntax()).0;
+    let tt = syntax_node_to_token_tree(source_file.syntax()).unwrap().0;
 
     let parsed = parse_to_token_tree(ra_fixture).unwrap().0;
     assert_eq!(tt, parsed);
@@ -163,7 +164,7 @@ fn parse_macro_rules_to_tt(ra_fixture: &str) -> tt::Subtree {
     let macro_definition =
         source_file.syntax().descendants().find_map(ast::MacroRules::cast).unwrap();
 
-    let (definition_tt, _) = ast_to_token_tree(&macro_definition.token_tree().unwrap());
+    let (definition_tt, _) = ast_to_token_tree(&macro_definition.token_tree().unwrap()).unwrap();
 
     let parsed = parse_to_token_tree(
         &ra_fixture[macro_definition.token_tree().unwrap().syntax().text_range()],
@@ -180,7 +181,7 @@ fn parse_macro_def_to_tt(ra_fixture: &str) -> tt::Subtree {
     let macro_definition =
         source_file.syntax().descendants().find_map(ast::MacroDef::cast).unwrap();
 
-    let (definition_tt, _) = ast_to_token_tree(&macro_definition.body().unwrap());
+    let (definition_tt, _) = ast_to_token_tree(&macro_definition.body().unwrap()).unwrap();
 
     let parsed =
         parse_to_token_tree(&ra_fixture[macro_definition.body().unwrap().syntax().text_range()])
diff --git a/crates/mbe/src/tests/rule.rs b/crates/mbe/src/tests/rule.rs
index 5c61a98fdf..bf48112b3a 100644
--- a/crates/mbe/src/tests/rule.rs
+++ b/crates/mbe/src/tests/rule.rs
@@ -44,6 +44,6 @@ fn parse_macro_arm(arm_definition: &str) -> Result<crate::MacroRules, ParseError
     let macro_definition =
         source_file.syntax().descendants().find_map(ast::MacroRules::cast).unwrap();
 
-    let (definition_tt, _) = ast_to_token_tree(&macro_definition.token_tree().unwrap());
+    let (definition_tt, _) = ast_to_token_tree(&macro_definition.token_tree().unwrap()).unwrap();
     crate::MacroRules::parse(&definition_tt)
 }