Repository: rust-analyzer/rust-analyzer
Pull request #7075 (2020-12-29 11:29:10)

format-postfix completion takes format instead of fmt
See https://github.com/rust-analyzer/rust-analyzer/issues/6843
this brings it back in line with the documentation


Patch:
diff --git a/Cargo.lock b/Cargo.lock
index fd04ec3c52..891cff55e3 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -168,9 +168,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
 
 [[package]]
 name = "chalk-derive"
-version = "0.45.0"
+version = "0.43.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ec7dacf94958d1a930b95d049d9443860859af59eadc77849392093eb577bcee"
+checksum = "e2d9e0c8adcced1ab0fea5cb8a38647922893d5b495e363e1814299fd380469b"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -180,20 +180,19 @@ dependencies = [
 
 [[package]]
 name = "chalk-ir"
-version = "0.45.0"
+version = "0.43.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a1a5b38ede247def17da87f4badb62396a5753db6048e2011d3089d8b3796c67"
+checksum = "c5218266a5709bc4943de997e64d3fab41c9e9f68efd54a898de53135e987bd3"
 dependencies = [
- "bitflags",
  "chalk-derive",
  "lazy_static",
 ]
 
 [[package]]
 name = "chalk-recursive"
-version = "0.45.0"
+version = "0.43.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7a18db146d7a023edc20ad094e8c2284451f7888719645004979617d1f17c041"
+checksum = "ed8f34f13fd4f30251f9f6f1dc56f80363201390ecbcac2fdfc8e33036cd9c4a"
 dependencies = [
  "chalk-derive",
  "chalk-ir",
@@ -204,9 +203,9 @@ dependencies = [
 
 [[package]]
 name = "chalk-solve"
-version = "0.45.0"
+version = "0.43.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7f73e0de04a0f394e47ed8118e00541bcf681d7c3c2ef500fa743eb4cf3a4850"
+checksum = "379c9f584488346044709d4c638c38d61a06fe593d4de2ac5f15fd2b0ba4cd9d"
 dependencies = [
  "chalk-derive",
  "chalk-ir",
@@ -508,9 +507,9 @@ checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04"
 
 [[package]]
 name = "heck"
-version = "0.3.2"
+version = "0.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "87cbf45460356b7deeb5e3415b5563308c0a9b057c85e12b06ad551f98d0a6ac"
+checksum = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205"
 dependencies = [
  "unicode-segmentation",
 ]
@@ -1075,9 +1074,9 @@ dependencies = [
 
 [[package]]
 name = "parking_lot_core"
-version = "0.8.2"
+version = "0.8.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9ccb628cad4f84851442432c60ad8e1f607e29752d0bf072cbd0baf28aa34272"
+checksum = "d7c6d9b8427445284a09c55be860a15855ab580a417ccad9da88f5a06787ced0"
 dependencies = [
  "cfg-if 1.0.0",
  "instant",
@@ -1359,7 +1358,6 @@ dependencies = [
  "rustc-hash",
  "serde",
  "serde_json",
- "serde_path_to_error",
  "ssr",
  "stdx",
  "syntax",
@@ -1378,9 +1376,9 @@ dependencies = [
 
 [[package]]
 name = "rustc-ap-rustc_lexer"
-version = "695.0.0"
+version = "691.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "390bad134705b0bff02cd9541ac66df751a91c3cc734c3369cd6151ca269caed"
+checksum = "44bc89d9ca7a78fb82e103b389362c55f03800745f8ba14e068b805cfaf783ec"
 dependencies = [
  "unicode-xid",
 ]
@@ -1528,15 +1526,6 @@ dependencies = [
  "serde",
 ]
 
-[[package]]
-name = "serde_path_to_error"
-version = "0.1.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "42f6109f0506e20f7e0f910e51a0079acf41da8e0694e6442527c4ddf5a2b158"
-dependencies = [
- "serde",
-]
-
 [[package]]
 name = "serde_repr"
 version = "0.1.6"
diff --git a/crates/assists/src/assist_context.rs b/crates/assists/src/assist_context.rs
index 4f59d39a96..80cf9aba11 100644
--- a/crates/assists/src/assist_context.rs
+++ b/crates/assists/src/assist_context.rs
@@ -19,7 +19,7 @@ use text_edit::{TextEdit, TextEditBuilder};
 
 use crate::{
     assist_config::{AssistConfig, SnippetCap},
-    Assist, AssistId, AssistKind, GroupLabel,
+    Assist, AssistId, AssistKind, GroupLabel, ResolvedAssist,
 };
 
 /// `AssistContext` allows to apply an assist or check if it could be applied.
@@ -105,23 +105,46 @@ impl<'a> AssistContext<'a> {
 pub(crate) struct Assists {
     resolve: bool,
     file: FileId,
-    buf: Vec<Assist>,
+    buf: Vec<(Assist, Option<SourceChange>)>,
     allowed: Option<Vec<AssistKind>>,
 }
 
 impl Assists {
-    pub(crate) fn new(ctx: &AssistContext, resolve: bool) -> Assists {
+    pub(crate) fn new_resolved(ctx: &AssistContext) -> Assists {
         Assists {
-            resolve,
+            resolve: true,
             file: ctx.frange.file_id,
             buf: Vec::new(),
             allowed: ctx.config.allowed.clone(),
         }
     }
 
-    pub(crate) fn finish(mut self) -> Vec<Assist> {
-        self.buf.sort_by_key(|assist| assist.target.len());
-        self.buf
+    pub(crate) fn new_unresolved(ctx: &AssistContext) -> Assists {
+        Assists {
+            resolve: false,
+            file: ctx.frange.file_id,
+            buf: Vec::new(),
+            allowed: ctx.config.allowed.clone(),
+        }
+    }
+
+    pub(crate) fn finish_unresolved(self) -> Vec<Assist> {
+        assert!(!self.resolve);
+        self.finish()
+            .into_iter()
+            .map(|(label, edit)| {
+                assert!(edit.is_none());
+                label
+            })
+            .collect()
+    }
+
+    pub(crate) fn finish_resolved(self) -> Vec<ResolvedAssist> {
+        assert!(self.resolve);
+        self.finish()
+            .into_iter()
+            .map(|(label, edit)| ResolvedAssist { assist: label, source_change: edit.unwrap() })
+            .collect()
     }
 
     pub(crate) fn add(
@@ -135,7 +158,7 @@ impl Assists {
             return None;
         }
         let label = Label::new(label.into());
-        let assist = Assist { id, label, group: None, target, source_change: None };
+        let assist = Assist { id, label, group: None, target };
         self.add_impl(assist, f)
     }
 
@@ -151,11 +174,11 @@ impl Assists {
             return None;
         }
         let label = Label::new(label.into());
-        let assist = Assist { id, label, group: Some(group.clone()), target, source_change: None };
+        let assist = Assist { id, label, group: Some(group.clone()), target };
         self.add_impl(assist, f)
     }
 
-    fn add_impl(&mut self, mut assist: Assist, f: impl FnOnce(&mut AssistBuilder)) -> Option<()> {
+    fn add_impl(&mut self, assist: Assist, f: impl FnOnce(&mut AssistBuilder)) -> Option<()> {
         let source_change = if self.resolve {
             let mut builder = AssistBuilder::new(self.file);
             f(&mut builder);
@@ -163,12 +186,16 @@ impl Assists {
         } else {
             None
         };
-        assist.source_change = source_change.clone();
 
-        self.buf.push(assist);
+        self.buf.push((assist, source_change));
         Some(())
     }
 
+    fn finish(mut self) -> Vec<(Assist, Option<SourceChange>)> {
+        self.buf.sort_by_key(|(label, _edit)| label.target.len());
+        self.buf
+    }
+
     fn is_allowed(&self, id: &AssistId) -> bool {
         match &self.allowed {
             Some(allowed) => allowed.iter().any(|kind| kind.contains(id.1)),
diff --git a/crates/assists/src/handlers/add_missing_impl_members.rs b/crates/assists/src/handlers/add_missing_impl_members.rs
index 7df05b8412..e413505d3e 100644
--- a/crates/assists/src/handlers/add_missing_impl_members.rs
+++ b/crates/assists/src/handlers/add_missing_impl_members.rs
@@ -15,7 +15,7 @@ use crate::{
 //
 // ```
 // trait Trait<T> {
-//     type X;
+//     Type X;
 //     fn foo(&self) -> T;
 //     fn bar(&self) {}
 // }
@@ -27,16 +27,14 @@ use crate::{
 // ->
 // ```
 // trait Trait<T> {
-//     type X;
+//     Type X;
 //     fn foo(&self) -> T;
 //     fn bar(&self) {}
 // }
 //
 // impl Trait<u32> for () {
-//     $0type X;
-//
 //     fn foo(&self) -> u32 {
-//         todo!()
+//         ${0:todo!()}
 //     }
 // }
 // ```
@@ -56,13 +54,13 @@ pub(crate) fn add_missing_impl_members(acc: &mut Assists, ctx: &AssistContext) -
 //
 // ```
 // trait Trait {
-//     type X;
+//     Type X;
 //     fn foo(&self);
 //     fn bar(&self) {}
 // }
 //
 // impl Trait for () {
-//     type X = ();
+//     Type X = ();
 //     fn foo(&self) {}<|>
 //
 // }
@@ -70,13 +68,13 @@ pub(crate) fn add_missing_impl_members(acc: &mut Assists, ctx: &AssistContext) -
 // ->
 // ```
 // trait Trait {
-//     type X;
+//     Type X;
 //     fn foo(&self);
 //     fn bar(&self) {}
 // }
 //
 // impl Trait for () {
-//     type X = ();
+//     Type X = ();
 //     fn foo(&self) {}
 //
 //     $0fn bar(&self) {}
diff --git a/crates/assists/src/lib.rs b/crates/assists/src/lib.rs
index fdec886e9d..6b89b2d044 100644
--- a/crates/assists/src/lib.rs
+++ b/crates/assists/src/lib.rs
@@ -73,32 +73,45 @@ pub struct Assist {
     /// Target ranges are used to sort assists: the smaller the target range,
     /// the more specific assist is, and so it should be sorted first.
     pub target: TextRange,
-    /// Computing source change sometimes is much more costly then computing the
-    /// other fields. Additionally, the actual change is not required to show
-    /// the lightbulb UI, it only is needed when the user tries to apply an
-    /// assist. So, we compute it lazily: the API allow requesting assists with
-    /// or without source change. We could (and in fact, used to) distinguish
-    /// between resolved and unresolved assists at the type level, but this is
-    /// cumbersome, especially if you want to embed an assist into another data
-    /// structure, such as a diagnostic.
-    pub source_change: Option<SourceChange>,
+}
+
+#[derive(Debug, Clone)]
+pub struct ResolvedAssist {
+    pub assist: Assist,
+    pub source_change: SourceChange,
 }
 
 impl Assist {
     /// Return all the assists applicable at the given position.
-    pub fn get(
+    ///
+    /// Assists are returned in the "unresolved" state, that is only labels are
+    /// returned, without actual edits.
+    pub fn unresolved(db: &RootDatabase, config: &AssistConfig, range: FileRange) -> Vec<Assist> {
+        let sema = Semantics::new(db);
+        let ctx = AssistContext::new(sema, config, range);
+        let mut acc = Assists::new_unresolved(&ctx);
+        handlers::all().iter().for_each(|handler| {
+            handler(&mut acc, &ctx);
+        });
+        acc.finish_unresolved()
+    }
+
+    /// Return all the assists applicable at the given position.
+    ///
+    /// Assists are returned in the "resolved" state, that is with edit fully
+    /// computed.
+    pub fn resolved(
         db: &RootDatabase,
         config: &AssistConfig,
-        resolve: bool,
         range: FileRange,
-    ) -> Vec<Assist> {
+    ) -> Vec<ResolvedAssist> {
         let sema = Semantics::new(db);
         let ctx = AssistContext::new(sema, config, range);
-        let mut acc = Assists::new(&ctx, resolve);
+        let mut acc = Assists::new_resolved(&ctx);
         handlers::all().iter().for_each(|handler| {
             handler(&mut acc, &ctx);
         });
-        acc.finish()
+        acc.finish_resolved()
     }
 }
 
diff --git a/crates/base_db/src/input.rs b/crates/base_db/src/input.rs
index 9567bcc424..cda5e57dc7 100644
--- a/crates/base_db/src/input.rs
+++ b/crates/base_db/src/input.rs
@@ -6,12 +6,12 @@
 //! actual IO. See `vfs` and `project_model` in the `rust-analyzer` crate for how
 //! actual IO is done and lowered to input.
 
-use std::{fmt, iter::FromIterator, ops, panic::RefUnwindSafe, str::FromStr, sync::Arc};
+use std::{fmt, iter::FromIterator, ops, str::FromStr, sync::Arc};
 
 use cfg::CfgOptions;
 use rustc_hash::{FxHashMap, FxHashSet};
 use syntax::SmolStr;
-use tt::{ExpansionError, Subtree};
+use tt::TokenExpander;
 use vfs::{file_set::FileSet, FileId, VfsPath};
 
 /// Files are grouped into source roots. A source root is a directory on the
@@ -150,20 +150,11 @@ pub enum ProcMacroKind {
     Attr,
 }
 
-pub trait ProcMacroExpander: fmt::Debug + Send + Sync + RefUnwindSafe {
-    fn expand(
-        &self,
-        subtree: &Subtree,
-        attrs: Option<&Subtree>,
-        env: &Env,
-    ) -> Result<Subtree, ExpansionError>;
-}
-
 #[derive(Debug, Clone)]
 pub struct ProcMacro {
     pub name: SmolStr,
     pub kind: ProcMacroKind,
-    pub expander: Arc<dyn ProcMacroExpander>,
+    pub expander: Arc<dyn TokenExpander>,
 }
 
 impl Eq for ProcMacro {}
@@ -422,10 +413,6 @@ impl Env {
     pub fn get(&self, env: &str) -> Option<String> {
         self.entries.get(env).cloned()
     }
-
-    pub fn iter(&self) -> impl Iterator<Item = (&str, &str)> {
-        self.entries.iter().map(|(k, v)| (k.as_str(), v.as_str()))
-    }
 }
 
 #[derive(Debug)]
diff --git a/crates/base_db/src/lib.rs b/crates/base_db/src/lib.rs
index 5f77a0b1f0..595f28adae 100644
--- a/crates/base_db/src/lib.rs
+++ b/crates/base_db/src/lib.rs
@@ -14,7 +14,7 @@ pub use crate::{
     change::Change,
     input::{
         CrateData, CrateDisplayName, CrateGraph, CrateId, CrateName, Dependency, Edition, Env,
-        ProcMacro, ProcMacroExpander, ProcMacroId, ProcMacroKind, SourceRoot, SourceRootId,
+        ProcMacro, ProcMacroId, ProcMacroKind, SourceRoot, SourceRootId,
     },
 };
 pub use salsa;
diff --git a/crates/completion/src/completions/postfix.rs b/crates/completion/src/completions/postfix.rs
index d6db82a93b..3883d6d214 100644
--- a/crates/completion/src/completions/postfix.rs
+++ b/crates/completion/src/completions/postfix.rs
@@ -502,7 +502,7 @@ fn main() {
     #[test]
     fn postfix_completion_for_format_like_strings() {
         check_edit(
-            "fmt",
+            "format",
             r#"fn main() { "{some_var:?}".<|> }"#,
             r#"fn main() { format!("{:?}", some_var) }"#,
         );
diff --git a/crates/completion/src/completions/postfix/format_like.rs b/crates/completion/src/completions/postfix/format_like.rs
index 88ba86acb6..ea41e01c50 100644
--- a/crates/completion/src/completions/postfix/format_like.rs
+++ b/crates/completion/src/completions/postfix/format_like.rs
@@ -22,7 +22,7 @@ use syntax::ast::{self, AstToken};
 
 /// Mapping ("postfix completion item" => "macro to use")
 static KINDS: &[(&str, &str)] = &[
-    ("fmt", "format!"),
+    ("format", "format!"),
     ("panic", "panic!"),
     ("println", "println!"),
     ("eprintln", "eprintln!"),
diff --git a/crates/hir/src/code_model.rs b/crates/hir/src/code_model.rs
index b7ded34788..1d7e5ddd7f 100644
--- a/crates/hir/src/code_model.rs
+++ b/crates/hir/src/code_model.rs
@@ -9,7 +9,7 @@ use hir_def::{
     adt::StructKind,
     adt::VariantData,
     builtin_type::BuiltinType,
-    expr::{BindingAnnotation, LabelId, Pat, PatId},
+    expr::{BindingAnnotation, Pat, PatId},
     import_map,
     item_tree::ItemTreeNode,
     lang_item::LangItemTarget,
@@ -374,6 +374,8 @@ impl Module {
         let crate_def_map = db.crate_def_map(self.id.krate);
         crate_def_map.add_diagnostics(db.upcast(), self.id.local_id, sink);
         for decl in self.declarations(db) {
+            decl.diagnostics(db, sink);
+
             match decl {
                 crate::ModuleDef::Function(f) => f.diagnostics(db, sink),
                 crate::ModuleDef::Module(m) => {
@@ -382,9 +384,7 @@ impl Module {
                         m.diagnostics(db, sink)
                     }
                 }
-                _ => {
-                    decl.diagnostics(db, sink);
-                }
+                _ => (),
             }
         }
 
@@ -1205,34 +1205,6 @@ impl Local {
     }
 }
 
-#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
-pub struct Label {
-    pub(crate) parent: DefWithBodyId,
-    pub(crate) label_id: LabelId,
-}
-
-impl Label {
-    pub fn module(self, db: &dyn HirDatabase) -> Module {
-        self.parent(db).module(db)
-    }
-
-    pub fn parent(self, _db: &dyn HirDatabase) -> DefWithBody {
-        self.parent.into()
-    }
-
-    pub fn name(self, db: &dyn HirDatabase) -> Name {
-        let body = db.body(self.parent.into());
-        body[self.label_id].name.clone()
-    }
-
-    pub fn source(self, db: &dyn HirDatabase) -> InFile<ast::Label> {
-        let (_body, source_map) = db.body_with_source_map(self.parent.into());
-        let src = source_map.label_syntax(self.label_id);
-        let root = src.file_syntax(db.upcast());
-        src.map(|ast| ast.to_node(&root))
-    }
-}
-
 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
 pub enum GenericParam {
     TypeParam(TypeParam),
diff --git a/crates/hir/src/from_id.rs b/crates/hir/src/from_id.rs
index a0792b9a66..8e0c571b85 100644
--- a/crates/hir/src/from_id.rs
+++ b/crates/hir/src/from_id.rs
@@ -4,15 +4,12 @@
 //! are splitting the hir.
 
 use hir_def::{
-    expr::{LabelId, PatId},
-    item_scope::ItemInNs,
-    AdtId, AssocItemId, DefWithBodyId, EnumVariantId, FieldId, GenericDefId, ModuleDefId,
-    VariantId,
+    expr::PatId, item_scope::ItemInNs, AdtId, AssocItemId, DefWithBodyId, EnumVariantId, FieldId,
+    GenericDefId, ModuleDefId, VariantId,
 };
 
 use crate::{
-    Adt, AssocItem, DefWithBody, Field, GenericDef, Label, Local, MacroDef, ModuleDef, Variant,
-    VariantDef,
+    Adt, AssocItem, DefWithBody, Field, GenericDef, Local, MacroDef, ModuleDef, Variant, VariantDef,
 };
 
 macro_rules! from_id {
@@ -231,12 +228,6 @@ impl From<(DefWithBodyId, PatId)> for Local {
     }
 }
 
-impl From<(DefWithBodyId, LabelId)> for Label {
-    fn from((parent, label_id): (DefWithBodyId, LabelId)) -> Self {
-        Label { parent, label_id }
-    }
-}
-
 impl From<MacroDef> for ItemInNs {
     fn from(macro_def: MacroDef) -> Self {
         ItemInNs::Macros(macro_def.into())
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index 7ac9fd5079..bdd270c58d 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -35,8 +35,8 @@ pub use crate::{
     code_model::{
         Access, Adt, AsAssocItem, AssocItem, AssocItemContainer, Callable, CallableKind, Const,
         Crate, CrateDependency, DefWithBody, Enum, Field, FieldSource, Function, GenericDef,
-        HasVisibility, Impl, Label, LifetimeParam, Local, MacroDef, Module, ModuleDef, ScopeDef,
-        Static, Struct, Trait, Type, TypeAlias, TypeParam, Union, Variant, VariantDef,
+        HasVisibility, Impl, LifetimeParam, Local, MacroDef, Module, ModuleDef, ScopeDef, Static,
+        Struct, Trait, Type, TypeAlias, TypeParam, Union, Variant, VariantDef,
     },
     has_source::HasSource,
     semantics::{PathResolution, Semantics, SemanticsScope},
diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs
index 67cd16e311..25ebf73d88 100644
--- a/crates/hir/src/semantics.rs
+++ b/crates/hir/src/semantics.rs
@@ -15,7 +15,7 @@ use itertools::Itertools;
 use rustc_hash::{FxHashMap, FxHashSet};
 use syntax::{
     algo::find_node_at_offset,
-    ast::{self, GenericParamsOwner, LoopBodyOwner},
+    ast::{self, GenericParamsOwner},
     match_ast, AstNode, SyntaxNode, SyntaxToken, TextSize,
 };
 
@@ -25,8 +25,8 @@ use crate::{
     diagnostics::Diagnostic,
     semantics::source_to_def::{ChildContainer, SourceToDefCache, SourceToDefCtx},
     source_analyzer::{resolve_hir_path, SourceAnalyzer},
-    AssocItem, Callable, Crate, Field, Function, HirFileId, Impl, InFile, Label, LifetimeParam,
-    Local, MacroDef, Module, ModuleDef, Name, Path, ScopeDef, Trait, Type, TypeAlias, TypeParam,
+    AssocItem, Callable, Crate, Field, Function, HirFileId, Impl, InFile, LifetimeParam, Local,
+    MacroDef, Module, ModuleDef, Name, Path, ScopeDef, Trait, Type, TypeAlias, TypeParam,
     VariantDef,
 };
 
@@ -182,10 +182,6 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
         self.imp.resolve_lifetime_param(lifetime)
     }
 
-    pub fn resolve_label(&self, lifetime: &ast::Lifetime) -> Option<Label> {
-        self.imp.resolve_label(lifetime)
-    }
-
     pub fn type_of_expr(&self, expr: &ast::Expr) -> Option<Type> {
         self.imp.type_of_expr(expr)
     }
@@ -429,28 +425,6 @@ impl<'db> SemanticsImpl<'db> {
         ToDef::to_def(self, src)
     }
 
-    fn resolve_label(&self, lifetime: &ast::Lifetime) -> Option<Label> {
-        let text = lifetime.text();
-        let label = lifetime.syntax().ancestors().find_map(|syn| {
-            let label = match_ast! {
-                match syn {
-                    ast::ForExpr(it) => it.label(),
-                    ast::WhileExpr(it) => it.label(),
-                    ast::LoopExpr(it) => it.label(),
-                    ast::EffectExpr(it) => it.label(),
-                    _ => None,
-                }
-            };
-            label.filter(|l| {
-                l.lifetime()
-                    .and_then(|lt| lt.lifetime_ident_token())
-                    .map_or(false, |lt| lt.text() == text)
-            })
-        })?;
-        let src = self.find_file(label.syntax().clone()).with_value(label);
-        ToDef::to_def(self, src)
-    }
-
     fn type_of_expr(&self, expr: &ast::Expr) -> Option<Type> {
         self.analyze(expr.syntax()).type_of_expr(self.db, expr)
     }
@@ -746,7 +720,6 @@ to_def_impls![
     (crate::LifetimeParam, ast::LifetimeParam, lifetime_param_to_def),
     (crate::MacroDef, ast::MacroRules, macro_rules_to_def),
     (crate::Local, ast::IdentPat, bind_pat_to_def),
-    (crate::Label, ast::Label, label_to_def),
 ];
 
 fn find_root(node: &SyntaxNode) -> SyntaxNode {
diff --git a/crates/hir/src/semantics/source_to_def.rs b/crates/hir/src/semantics/source_to_def.rs
index 424e6e8a94..3efca5baa5 100644
--- a/crates/hir/src/semantics/source_to_def.rs
+++ b/crates/hir/src/semantics/source_to_def.rs
@@ -4,7 +4,7 @@ use base_db::FileId;
 use hir_def::{
     child_by_source::ChildBySource,
     dyn_map::DynMap,
-    expr::{LabelId, PatId},
+    expr::PatId,
     keys::{self, Key},
     ConstId, DefWithBodyId, EnumId, EnumVariantId, FieldId, FunctionId, GenericDefId, ImplId,
     LifetimeParamId, ModuleId, StaticId, StructId, TraitId, TypeAliasId, TypeParamId, UnionId,
@@ -108,21 +108,12 @@ impl SourceToDefCtx<'_, '_> {
         &mut self,
         src: InFile<ast::IdentPat>,
     ) -> Option<(DefWithBodyId, PatId)> {
-        let container = self.find_pat_or_label_container(src.as_ref().map(|it| it.syntax()))?;
+        let container = self.find_pat_container(src.as_ref().map(|it| it.syntax()))?;
         let (_body, source_map) = self.db.body_with_source_map(container);
         let src = src.map(ast::Pat::from);
         let pat_id = source_map.node_pat(src.as_ref())?;
         Some((container, pat_id))
     }
-    pub(super) fn label_to_def(
-        &mut self,
-        src: InFile<ast::Label>,
-    ) -> Option<(DefWithBodyId, LabelId)> {
-        let container = self.find_pat_or_label_container(src.as_ref().map(|it| it.syntax()))?;
-        let (_body, source_map) = self.db.body_with_source_map(container);
-        let label_id = source_map.node_label(src.as_ref())?;
-        Some((container, label_id))
-    }
 
     fn to_def<Ast: AstNode + 'static, ID: Copy + 'static>(
         &mut self,
@@ -246,7 +237,7 @@ impl SourceToDefCtx<'_, '_> {
         None
     }
 
-    fn find_pat_or_label_container(&mut self, src: InFile<&SyntaxNode>) -> Option<DefWithBodyId> {
+    fn find_pat_container(&mut self, src: InFile<&SyntaxNode>) -> Option<DefWithBodyId> {
         for container in src.cloned().ancestors_with_macros(self.db.upcast()).skip(1) {
             let res: DefWithBodyId = match_ast! {
                 match (container.value) {
diff --git a/crates/hir_def/src/body.rs b/crates/hir_def/src/body.rs
index d07004b9d7..998b826010 100644
--- a/crates/hir_def/src/body.rs
+++ b/crates/hir_def/src/body.rs
@@ -26,7 +26,7 @@ pub(crate) use lower::LowerCtx;
 use crate::{
     attr::{Attrs, RawAttrs},
     db::DefDatabase,
-    expr::{Expr, ExprId, Label, LabelId, Pat, PatId},
+    expr::{Expr, ExprId, Pat, PatId},
     item_scope::BuiltinShadowMode,
     item_scope::ItemScope,
     nameres::CrateDefMap,
@@ -226,7 +226,6 @@ pub(crate) struct Mark {
 pub struct Body {
     pub exprs: Arena<Expr>,
     pub pats: Arena<Pat>,
-    pub labels: Arena<Label>,
     /// The patterns for the function's parameters. While the parameter types are
     /// part of the function signature, the patterns are not (they don't change
     /// the external type of the function).
@@ -245,8 +244,6 @@ pub type ExprSource = InFile<ExprPtr>;
 pub type PatPtr = Either<AstPtr<ast::Pat>, AstPtr<ast::SelfParam>>;
 pub type PatSource = InFile<PatPtr>;
 
-pub type LabelPtr = AstPtr<ast::Label>;
-pub type LabelSource = InFile<LabelPtr>;
 /// An item body together with the mapping from syntax nodes to HIR expression
 /// IDs. This is needed to go from e.g. a position in a file to the HIR
 /// expression containing it; but for type inference etc., we want to operate on
@@ -264,8 +261,6 @@ pub struct BodySourceMap {
     expr_map_back: ArenaMap<ExprId, Result<ExprSource, SyntheticSyntax>>,
     pat_map: FxHashMap<PatSource, PatId>,
     pat_map_back: ArenaMap<PatId, Result<PatSource, SyntheticSyntax>>,
-    label_map: FxHashMap<LabelSource, LabelId>,
-    label_map_back: ArenaMap<LabelId, LabelSource>,
     field_map: FxHashMap<(ExprId, usize), InFile<AstPtr<ast::RecordExprField>>>,
     expansions: FxHashMap<InFile<AstPtr<ast::MacroCall>>, HirFileId>,
 
@@ -339,14 +334,6 @@ impl Index<PatId> for Body {
     }
 }
 
-impl Index<LabelId> for Body {
-    type Output = Label;
-
-    fn index(&self, label: LabelId) -> &Label {
-        &self.labels[label]
-    }
-}
-
 impl BodySourceMap {
     pub fn expr_syntax(&self, expr: ExprId) -> Result<ExprSource, SyntheticSyntax> {
         self.expr_map_back[expr].clone()
@@ -376,15 +363,6 @@ impl BodySourceMap {
         self.pat_map.get(&src).cloned()
     }
 
-    pub fn label_syntax(&self, label: LabelId) -> LabelSource {
-        self.label_map_back[label].clone()
-    }
-
-    pub fn node_label(&self, node: InFile<&ast::Label>) -> Option<LabelId> {
-        let src = node.map(|it| AstPtr::new(it));
-        self.label_map.get(&src).cloned()
-    }
-
     pub fn field_syntax(&self, expr: ExprId, field: usize) -> InFile<AstPtr<ast::RecordExprField>> {
         self.field_map[&(expr, field)].clone()
     }
diff --git a/crates/hir_def/src/body/lower.rs b/crates/hir_def/src/body/lower.rs
index 17c72779ba..978c3a3249 100644
--- a/crates/hir_def/src/body/lower.rs
+++ b/crates/hir_def/src/body/lower.rs
@@ -22,14 +22,13 @@ use test_utils::mark;
 
 use crate::{
     adt::StructKind,
-    body::{Body, BodySourceMap, Expander, LabelSource, PatPtr, SyntheticSyntax},
+    body::{Body, BodySourceMap, Expander, PatPtr, SyntheticSyntax},
     builtin_type::{BuiltinFloat, BuiltinInt},
     db::DefDatabase,
     diagnostics::{InactiveCode, MacroError, UnresolvedProcMacro},
     expr::{
-        dummy_expr_id, ArithOp, Array, BinaryOp, BindingAnnotation, CmpOp, Expr, ExprId, Label,
-        LabelId, Literal, LogicOp, MatchArm, Ordering, Pat, PatId, RecordFieldPat, RecordLitField,
-        Statement,
+        dummy_expr_id, ArithOp, Array, BinaryOp, BindingAnnotation, CmpOp, Expr, ExprId, Literal,
+        LogicOp, MatchArm, Ordering, Pat, PatId, RecordFieldPat, RecordLitField, Statement,
     },
     item_scope::BuiltinShadowMode,
     item_tree::{ItemTree, ItemTreeId, ItemTreeNode},
@@ -73,7 +72,6 @@ pub(super) fn lower(
         body: Body {
             exprs: Arena::default(),
             pats: Arena::default(),
-            labels: Arena::default(),
             params: Vec::new(),
             body_expr: dummy_expr_id(),
             item_scope: Default::default(),
@@ -177,18 +175,6 @@ impl ExprCollector<'_> {
         id
     }
 
-    fn alloc_label(&mut self, label: Label, ptr: AstPtr<ast::Label>) -> LabelId {
-        let src = self.expander.to_source(ptr);
-        let id = self.make_label(label, src.clone());
-        self.source_map.label_map.insert(src, id);
-        id
-    }
-    fn make_label(&mut self, label: Label, src: LabelSource) -> LabelId {
-        let id = self.body.labels.alloc(label);
-        self.source_map.label_map_back.insert(id, src);
-        id
-    }
-
     fn collect_expr(&mut self, expr: ast::Expr) -> ExprId {
         let syntax_ptr = AstPtr::new(&expr);
         if self.check_cfg(&expr).is_none() {
@@ -242,40 +228,37 @@ impl ExprCollector<'_> {
                     self.alloc_expr(Expr::Unsafe { body }, syntax_ptr)
                 }
                 // FIXME: we need to record these effects somewhere...
-                ast::Effect::Label(label) => {
-                    let label = self.collect_label(label);
-                    match e.block_expr() {
-                        Some(block) => {
-                            let res = self.collect_block(block);
-                            match &mut self.body.exprs[res] {
-                                Expr::Block { label: block_label, .. } => {
-                                    *block_label = Some(label);
-                                }
-                                _ => unreachable!(),
+                ast::Effect::Label(label) => match e.block_expr() {
+                    Some(block) => {
+                        let res = self.collect_block(block);
+                        match &mut self.body.exprs[res] {
+                            Expr::Block { label: block_label, .. } => {
+                                *block_label = label.lifetime().map(|t| Name::new_lifetime(&t))
                             }
-                            res
+                            _ => unreachable!(),
                         }
-                        None => self.missing_expr(),
+                        res
                     }
-                }
+                    None => self.missing_expr(),
+                },
                 // FIXME: we need to record these effects somewhere...
                 ast::Effect::Async(_) => {
                     let body = self.collect_block_opt(e.block_expr());
                     self.alloc_expr(Expr::Async { body }, syntax_ptr)
                 }
-                ast::Effect::Const(_) => {
-                    let body = self.collect_block_opt(e.block_expr());
-                    self.alloc_expr(Expr::Const { body }, syntax_ptr)
-                }
             },
             ast::Expr::BlockExpr(e) => self.collect_block(e),
             ast::Expr::LoopExpr(e) => {
-                let label = e.label().map(|label| self.collect_label(label));
                 let body = self.collect_block_opt(e.loop_body());
-                self.alloc_expr(Expr::Loop { body, label }, syntax_ptr)
+                self.alloc_expr(
+                    Expr::Loop {
+                        body,
+                        label: e.label().and_then(|l| l.lifetime()).map(|l| Name::new_lifetime(&l)),
+                    },
+                    syntax_ptr,
+                )
             }
             ast::Expr::WhileExpr(e) => {
-                let label = e.label().map(|label| self.collect_label(label));
                 let body = self.collect_block_opt(e.loop_body());
 
                 let condition = match e.condition() {
@@ -296,20 +279,42 @@ impl ExprCollector<'_> {
                             ];
                             let match_expr =
                                 self.alloc_expr_desugared(Expr::Match { expr: match_expr, arms });
-                            return self
-                                .alloc_expr(Expr::Loop { body: match_expr, label }, syntax_ptr);
+                            return self.alloc_expr(
+                                Expr::Loop {
+                                    body: match_expr,
+                                    label: e
+                                        .label()
+                                        .and_then(|l| l.lifetime())
+                                        .map(|l| Name::new_lifetime(&l)),
+                                },
+                                syntax_ptr,
+                            );
                         }
                     },
                 };
 
-                self.alloc_expr(Expr::While { condition, body, label }, syntax_ptr)
+                self.alloc_expr(
+                    Expr::While {
+                        condition,
+                        body,
+                        label: e.label().and_then(|l| l.lifetime()).map(|l| Name::new_lifetime(&l)),
+                    },
+                    syntax_ptr,
+                )
             }
             ast::Expr::ForExpr(e) => {
-                let label = e.label().map(|label| self.collect_label(label));
                 let iterable = self.collect_expr_opt(e.iterable());
                 let pat = self.collect_pat_opt(e.pat());
                 let body = self.collect_block_opt(e.loop_body());
-                self.alloc_expr(Expr::For { iterable, pat, body, label }, syntax_ptr)
+                self.alloc_expr(
+                    Expr::For {
+                        iterable,
+                        pat,
+                        body,
+                        label: e.label().and_then(|l| l.lifetime()).map(|l| Name::new_lifetime(&l)),
+                    },
+                    syntax_ptr,
+                )
             }
             ast::Expr::CallExpr(e) => {
                 let callee = self.collect_expr_opt(e.expr());
@@ -809,13 +814,6 @@ impl ExprCollector<'_> {
         }
     }
 
-    fn collect_label(&mut self, ast_label: ast::Label) -> LabelId {
-        let label = Label {
-            name: ast_label.lifetime().as_ref().map_or_else(Name::missing, Name::new_lifetime),
-        };
-        self.alloc_label(label, AstPtr::new(&ast_label))
-    }
-
     fn collect_pat(&mut self, pat: ast::Pat) -> PatId {
         let pattern = match &pat {
             ast::Pat::IdentPat(bp) => {
@@ -934,16 +932,10 @@ impl ExprCollector<'_> {
                 let inner = self.collect_pat_opt(boxpat.pat());
                 Pat::Box { inner }
             }
-            ast::Pat::ConstBlockPat(const_block_pat) => {
-                if let Some(expr) = const_block_pat.block_expr() {
-                    let expr_id = self.collect_block(expr);
-                    Pat::ConstBlock(expr_id)
-                } else {
-                    Pat::Missing
-                }
-            }
             // FIXME: implement
-            ast::Pat::RangePat(_) | ast::Pat::MacroPat(_) => Pat::Missing,
+            ast::Pat::RangePat(_) | ast::Pat::MacroPat(_) | ast::Pat::ConstBlockPat(_) => {
+                Pat::Missing
+            }
         };
         let ptr = AstPtr::new(&pat);
         self.alloc_pat(pattern, Either::Left(ptr))
diff --git a/crates/hir_def/src/expr.rs b/crates/hir_def/src/expr.rs
index 6a481769db..e5d740a365 100644
--- a/crates/hir_def/src/expr.rs
+++ b/crates/hir_def/src/expr.rs
@@ -29,12 +29,6 @@ pub(crate) fn dummy_expr_id() -> ExprId {
 
 pub type PatId = Idx<Pat>;
 
-#[derive(Debug, Clone, Eq, PartialEq)]
-pub struct Label {
-    pub name: Name,
-}
-pub type LabelId = Idx<Label>;
-
 #[derive(Debug, Clone, Eq, PartialEq)]
 pub enum Literal {
     String(String),
@@ -58,22 +52,22 @@ pub enum Expr {
     Block {
         statements: Vec<Statement>,
         tail: Option<ExprId>,
-        label: Option<LabelId>,
+        label: Option<Name>,
     },
     Loop {
         body: ExprId,
-        label: Option<LabelId>,
+        label: Option<Name>,
     },
     While {
         condition: ExprId,
         body: ExprId,
-        label: Option<LabelId>,
+        label: Option<Name>,
     },
     For {
         iterable: ExprId,
         pat: PatId,
         body: ExprId,
-        label: Option<LabelId>,
+        label: Option<Name>,
     },
     Call {
         callee: ExprId,
@@ -120,9 +114,6 @@ pub enum Expr {
     Async {
         body: ExprId,
     },
-    Const {
-        body: ExprId,
-    },
     Cast {
         expr: ExprId,
         type_ref: TypeRef,
@@ -262,10 +253,7 @@ impl Expr {
                     f(*expr);
                 }
             }
-            Expr::TryBlock { body }
-            | Expr::Unsafe { body }
-            | Expr::Async { body }
-            | Expr::Const { body } => f(*body),
+            Expr::TryBlock { body } | Expr::Unsafe { body } | Expr::Async { body } => f(*body),
             Expr::Loop { body, .. } => f(*body),
             Expr::While { condition, body, .. } => {
                 f(*condition);
@@ -411,18 +399,12 @@ pub enum Pat {
     TupleStruct { path: Option<Path>, args: Vec<PatId>, ellipsis: Option<usize> },
     Ref { pat: PatId, mutability: Mutability },
     Box { inner: PatId },
-    ConstBlock(ExprId),
 }
 
 impl Pat {
     pub fn walk_child_pats(&self, mut f: impl FnMut(PatId)) {
         match self {
-            Pat::Range { .. }
-            | Pat::Lit(..)
-            | Pat::Path(..)
-            | Pat::ConstBlock(..)
-            | Pat::Wild
-            | Pat::Missing => {}
+            Pat::Range { .. } | Pat::Lit(..) | Pat::Path(..) | Pat::Wild | Pat::Missing => {}
             Pat::Bind { subpat, .. } => {
                 subpat.iter().copied().for_each(f);
             }
diff --git a/crates/hir_expand/src/db.rs b/crates/hir_expand/src/db.rs
index 06f0a3ed9c..077de37270 100644
--- a/crates/hir_expand/src/db.rs
+++ b/crates/hir_expand/src/db.rs
@@ -271,7 +271,7 @@ fn expand_proc_macro(
         _ => unreachable!(),
     };
 
-    expander.expand(db, loc.krate, &macro_arg.0)
+    expander.expand(db, lazy_id, &macro_arg.0)
 }
 
 fn parse_or_expand(db: &dyn AstDatabase, file_id: HirFileId) -> Option<SyntaxNode> {
diff --git a/crates/hir_expand/src/proc_macro.rs b/crates/hir_expand/src/proc_macro.rs
index 7c77f6ce0a..38882d2b68 100644
--- a/crates/hir_expand/src/proc_macro.rs
+++ b/crates/hir_expand/src/proc_macro.rs
@@ -1,6 +1,6 @@
 //! Proc Macro Expander stub
 
-use crate::db::AstDatabase;
+use crate::{db::AstDatabase, LazyMacroId};
 use base_db::{CrateId, ProcMacroId};
 use tt::buffer::{Cursor, TokenBuffer};
 
@@ -32,7 +32,7 @@ impl ProcMacroExpander {
     pub fn expand(
         self,
         db: &dyn AstDatabase,
-        calling_crate: CrateId,
+        _id: LazyMacroId,
         tt: &tt::Subtree,
     ) -> Result<tt::Subtree, mbe::ExpandError> {
         match self.proc_macro_id {
@@ -47,10 +47,7 @@ impl ProcMacroExpander {
                 let tt = remove_derive_attrs(tt)
                     .ok_or_else(|| err!("Fail to remove derive for custom derive"))?;
 
-                // Proc macros have access to the environment variables of the invoking crate.
-                let env = &krate_graph[calling_crate].env;
-
-                proc_macro.expander.expand(&tt, None, &env).map_err(mbe::ExpandError::from)
+                proc_macro.expander.expand(&tt, None).map_err(mbe::ExpandError::from)
             }
             None => Err(mbe::ExpandError::UnresolvedProcMacro),
         }
diff --git a/crates/hir_ty/Cargo.toml b/crates/hir_ty/Cargo.toml
index 965c1780a7..289e812fe5 100644
--- a/crates/hir_ty/Cargo.toml
+++ b/crates/hir_ty/Cargo.toml
@@ -17,9 +17,9 @@ ena = "0.14.0"
 log = "0.4.8"
 rustc-hash = "1.1.0"
 scoped-tls = "1"
-chalk-solve = { version = "0.45", default-features = false }
-chalk-ir = "0.45"
-chalk-recursive = "0.45"
+chalk-solve = { version = "0.43", default-features = false }
+chalk-ir = "0.43"
+chalk-recursive = "0.43"
 
 stdx = { path = "../stdx", version = "0.0.0" }
 hir_def = { path = "../hir_def", version = "0.0.0" }
diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs
index 70a3f3075c..2cdce2cefc 100644
--- a/crates/hir_ty/src/infer/expr.rs
+++ b/crates/hir_ty/src/infer/expr.rs
@@ -143,7 +143,7 @@ impl<'a> InferenceContext<'a> {
                     self.breakables.push(BreakableContext {
                         may_break: false,
                         break_ty: break_ty.clone(),
-                        label: label.map(|label| self.body[label].name.clone()),
+                        label: label.clone(),
                     });
                     let ty = self.infer_block(statements, *tail, &Expectation::has_type(break_ty));
                     let ctxt = self.breakables.pop().expect("breakable stack broken");
@@ -155,7 +155,7 @@ impl<'a> InferenceContext<'a> {
                 }
                 None => self.infer_block(statements, *tail, expected),
             },
-            Expr::Unsafe { body } | Expr::Const { body } => self.infer_expr(*body, expected),
+            Expr::Unsafe { body } => self.infer_expr(*body, expected),
             Expr::TryBlock { body } => {
                 let _inner = self.infer_expr(*body, expected);
                 // FIXME should be std::result::Result<{inner}, _>
@@ -172,7 +172,7 @@ impl<'a> InferenceContext<'a> {
                 self.breakables.push(BreakableContext {
                     may_break: false,
                     break_ty: self.table.new_type_var(),
-                    label: label.map(|label| self.body[label].name.clone()),
+                    label: label.clone(),
                 });
                 self.infer_expr(*body, &Expectation::has_type(Ty::unit()));
 
@@ -191,7 +191,7 @@ impl<'a> InferenceContext<'a> {
                 self.breakables.push(BreakableContext {
                     may_break: false,
                     break_ty: Ty::Unknown,
-                    label: label.map(|label| self.body[label].name.clone()),
+                    label: label.clone(),
                 });
                 // while let is desugared to a match loop, so this is always simple while
                 self.infer_expr(*condition, &Expectation::has_type(Ty::simple(TypeCtor::Bool)));
@@ -207,7 +207,7 @@ impl<'a> InferenceContext<'a> {
                 self.breakables.push(BreakableContext {
                     may_break: false,
                     break_ty: Ty::Unknown,
-                    label: label.map(|label| self.body[label].name.clone()),
+                    label: label.clone(),
                 });
                 let pat_ty =
                     self.resolve_associated_type(iterable_ty, self.resolve_into_iter_item());
diff --git a/crates/hir_ty/src/infer/pat.rs b/crates/hir_ty/src/infer/pat.rs
index d974f805b5..b70ec55eb5 100644
--- a/crates/hir_ty/src/infer/pat.rs
+++ b/crates/hir_ty/src/infer/pat.rs
@@ -243,9 +243,6 @@ impl<'a> InferenceContext<'a> {
                 }
                 None => Ty::Unknown,
             },
-            Pat::ConstBlock(expr) => {
-                self.infer_expr(*expr, &Expectation::has_type(expected.clone()))
-            }
             Pat::Missing => Ty::Unknown,
         };
         // use a new type variable if we got Ty::Unknown here
@@ -267,9 +264,8 @@ fn is_non_ref_pat(body: &hir_def::body::Body, pat: PatId) -> bool {
         | Pat::Range { .. }
         | Pat::Slice { .. } => true,
         Pat::Or(pats) => pats.iter().all(|p| is_non_ref_pat(body, *p)),
-        // FIXME: ConstBlock/Path/Lit might actually evaluate to ref, but inference is unimplemented.
+        // FIXME: Path/Lit might actually evaluate to ref, but inference is unimplemented.
         Pat::Path(..) => true,
-        Pat::ConstBlock(..) => true,
         Pat::Lit(expr) => match body[*expr] {
             Expr::Literal(Literal::String(..)) => false,
             _ => true,
diff --git a/crates/hir_ty/src/traits/chalk.rs b/crates/hir_ty/src/traits/chalk.rs
index 2196af6776..69eae6f79c 100644
--- a/crates/hir_ty/src/traits/chalk.rs
+++ b/crates/hir_ty/src/traits/chalk.rs
@@ -56,13 +56,8 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
     fn adt_datum(&self, struct_id: AdtId) -> Arc<StructDatum> {
         self.db.struct_datum(self.krate, struct_id)
     }
-    fn adt_repr(&self, _struct_id: AdtId) -> Arc<rust_ir::AdtRepr<Interner>> {
-        // FIXME: keep track of these
-        Arc::new(rust_ir::AdtRepr { c: false, packed: false, int: None })
-    }
-    fn discriminant_type(&self, _ty: chalk_ir::Ty<Interner>) -> chalk_ir::Ty<Interner> {
-        // FIXME: keep track of this
-        chalk_ir::TyKind::Scalar(chalk_ir::Scalar::Uint(chalk_ir::UintTy::U32)).intern(&Interner)
+    fn adt_repr(&self, _struct_id: AdtId) -> rust_ir::AdtRepr {
+        rust_ir::AdtRepr { repr_c: false, repr_packed: false }
     }
     fn impl_datum(&self, impl_id: ImplId) -> Arc<ImplDatum> {
         self.db.impl_datum(self.krate, impl_id)
@@ -462,7 +457,6 @@ fn well_known_trait_from_lang_attr(name: &str) -> Option<WellKnownTrait> {
         "fn" => WellKnownTrait::Fn,
         "unsize" => WellKnownTrait::Unsize,
         "coerce_unsized" => WellKnownTrait::CoerceUnsized,
-        "discriminant_kind" => WellKnownTrait::DiscriminantKind,
         _ => return None,
     })
 }
@@ -479,7 +473,6 @@ fn lang_attr_from_well_known_trait(attr: WellKnownTrait) -> &'static str {
         WellKnownTrait::Unsize => "unsize",
         WellKnownTrait::Unpin => "unpin",
         WellKnownTrait::CoerceUnsized => "coerce_unsized",
-        WellKnownTrait::DiscriminantKind => "discriminant_kind",
     }
 }
 
diff --git a/crates/ide/src/diagnostics.rs b/crates/ide/src/diagnostics.rs
index 0382737503..3ad30f0c9e 100644
--- a/crates/ide/src/diagnostics.rs
+++ b/crates/ide/src/diagnostics.rs
@@ -248,7 +248,7 @@ mod tests {
     ///  * a diagnostic is produced
     ///  * this diagnostic fix trigger range touches the input cursor position
     ///  * that the contents of the file containing the cursor match `after` after the diagnostic fix is applied
-    pub(crate) fn check_fix(ra_fixture_before: &str, ra_fixture_after: &str) {
+    pub(super) fn check_fix(ra_fixture_before: &str, ra_fixture_after: &str) {
         let after = trim_indent(ra_fixture_after);
 
         let (analysis, file_position) = fixture::position(ra_fixture_before);
@@ -257,13 +257,39 @@ mod tests {
             .unwrap()
             .pop()
             .unwrap();
-        let fix = diagnostic.fix.unwrap();
+        let mut fix = diagnostic.fix.unwrap();
+        let edit = fix.source_change.source_file_edits.pop().unwrap().edit;
+        let target_file_contents = analysis.file_text(file_position.file_id).unwrap();
         let actual = {
-            let file_id = fix.source_change.source_file_edits.first().unwrap().file_id;
-            let mut actual = analysis.file_text(file_id).unwrap().to_string();
+            let mut actual = target_file_contents.to_string();
+            edit.apply(&mut actual);
+            actual
+        };
+
+        assert_eq_text!(&after, &actual);
+        assert!(
+            fix.fix_trigger_range.contains_inclusive(file_position.offset),
+            "diagnostic fix range {:?} does not touch cursor position {:?}",
+            fix.fix_trigger_range,
+            file_position.offset
+        );
+    }
 
+    /// Similar to `check_fix`, but applies all the available fixes.
+    fn check_fixes(ra_fixture_before: &str, ra_fixture_after: &str) {
+        let after = trim_indent(ra_fixture_after);
+
+        let (analysis, file_position) = fixture::position(ra_fixture_before);
+        let diagnostic = analysis
+            .diagnostics(&DiagnosticsConfig::default(), file_position.file_id)
+            .unwrap()
+            .pop()
+            .unwrap();
+        let fix = diagnostic.fix.unwrap();
+        let target_file_contents = analysis.file_text(file_position.file_id).unwrap();
+        let actual = {
+            let mut actual = target_file_contents.to_string();
             // Go from the last one to the first one, so that ranges won't be affected by previous edits.
-            // FIXME: https://github.com/rust-analyzer/rust-analyzer/issues/4901#issuecomment-644675309
             for edit in fix.source_change.source_file_edits.iter().rev() {
                 edit.edit.apply(&mut actual);
             }
@@ -279,6 +305,29 @@ mod tests {
         );
     }
 
+    /// Checks that a diagnostic applies to the file containing the `<|>` cursor marker
+    /// which has a fix that can apply to other files.
+    fn check_apply_diagnostic_fix_in_other_file(ra_fixture_before: &str, ra_fixture_after: &str) {
+        let ra_fixture_after = &trim_indent(ra_fixture_after);
+        let (analysis, file_pos) = fixture::position(ra_fixture_before);
+        let current_file_id = file_pos.file_id;
+        let diagnostic = analysis
+            .diagnostics(&DiagnosticsConfig::default(), current_file_id)
+            .unwrap()
+            .pop()
+            .unwrap();
+        let mut fix = diagnostic.fix.unwrap();
+        let edit = fix.source_change.source_file_edits.pop().unwrap();
+        let changed_file_id = edit.file_id;
+        let before = analysis.file_text(changed_file_id).unwrap();
+        let actual = {
+            let mut actual = before.to_string();
+            edit.edit.apply(&mut actual);
+            actual
+        };
+        assert_eq_text!(ra_fixture_after, &actual);
+    }
+
     /// Takes a multi-file input fixture with annotated cursor position and checks that no diagnostics
     /// apply to the file containing the cursor.
     pub(crate) fn check_no_diagnostics(ra_fixture: &str) {
@@ -715,25 +764,25 @@ struct Foo {
 
     #[test]
     fn test_add_field_in_other_file_from_usage() {
-        check_fix(
-            r#"
-//- /main.rs
-mod foo;
+        check_apply_diagnostic_fix_in_other_file(
+            r"
+            //- /main.rs
+            mod foo;
 
-fn main() {
-    foo::Foo { bar: 3, <|>baz: false};
-}
-//- /foo.rs
-struct Foo {
-    bar: i32
-}
-"#,
-            r#"
-struct Foo {
-    bar: i32,
-    pub(crate) baz: bool
-}
-"#,
+            fn main() {
+                <|>foo::Foo { bar: 3, baz: false};
+            }
+            //- /foo.rs
+            struct Foo {
+                bar: i32
+            }
+            ",
+            r"
+            struct Foo {
+                bar: i32,
+                pub(crate) baz: bool
+            }
+            ",
         )
     }
 
@@ -753,7 +802,7 @@ struct Foo {
 
     #[test]
     fn test_rename_incorrect_case() {
-        check_fix(
+        check_fixes(
             r#"
 pub struct test_struct<|> { one: i32 }
 
@@ -770,7 +819,7 @@ pub fn some_fn(val: TestStruct) -> TestStruct {
 "#,
         );
 
-        check_fix(
+        check_fixes(
             r#"
 pub fn some_fn(NonSnakeCase<|>: u8) -> u8 {
     NonSnakeCase
@@ -783,7 +832,7 @@ pub fn some_fn(non_snake_case: u8) -> u8 {
 "#,
         );
 
-        check_fix(
+        check_fixes(
             r#"
 pub fn SomeFn<|>(val: u8) -> u8 {
     if val != 0 { SomeFn(val - 1) } else { val }
@@ -796,7 +845,7 @@ pub fn some_fn(val: u8) -> u8 {
 "#,
         );
 
-        check_fix(
+        check_fixes(
             r#"
 fn some_fn() {
     let whatAWeird_Formatting<|> = 10;
@@ -825,7 +874,7 @@ fn foo() {
 
     #[test]
     fn test_rename_incorrect_case_struct_method() {
-        check_fix(
+        check_fixes(
             r#"
 pub struct TestStruct;
 
@@ -846,17 +895,4 @@ impl TestStruct {
 "#,
         );
     }
-
-    #[test]
-    fn test_single_incorrect_case_diagnostic_in_function_name_issue_6970() {
-        let input = r#"fn FOO<|>() {}"#;
-        let expected = r#"fn foo() {}"#;
-
-        let (analysis, file_position) = fixture::position(input);
-        let diagnostics =
-            analysis.diagnostics(&DiagnosticsConfig::default(), file_position.file_id).unwrap();
-        assert_eq!(diagnostics.len(), 1);
-
-        check_fix(input, expected);
-    }
 }
diff --git a/crates/ide/src/display/navigation_target.rs b/crates/ide/src/display/navigation_target.rs
index 6431e7d6db..cd8ec54fa7 100644
--- a/crates/ide/src/display/navigation_target.rs
+++ b/crates/ide/src/display/navigation_target.rs
@@ -5,7 +5,7 @@ use std::fmt;
 use either::Either;
 use hir::{AssocItem, Documentation, FieldSource, HasAttrs, HasSource, InFile, ModuleSource};
 use ide_db::{
-    base_db::{FileId, FileRange, SourceDatabase},
+    base_db::{FileId, SourceDatabase},
     symbol_index::FileSymbolKind,
 };
 use ide_db::{defs::Definition, RootDatabase};
@@ -28,7 +28,6 @@ pub enum SymbolKind {
     ValueParam,
     SelfParam,
     Local,
-    Label,
     Function,
     Const,
     Static,
@@ -224,7 +223,6 @@ impl TryToNav for Definition {
             Definition::Local(it) => Some(it.to_nav(db)),
             Definition::TypeParam(it) => Some(it.to_nav(db)),
             Definition::LifetimeParam(it) => Some(it.to_nav(db)),
-            Definition::Label(it) => Some(it.to_nav(db)),
         }
     }
 }
@@ -423,27 +421,6 @@ impl ToNav for hir::Local {
     }
 }
 
-impl ToNav for hir::Label {
-    fn to_nav(&self, db: &RootDatabase) -> NavigationTarget {
-        let src = self.source(db);
-        let node = src.value.syntax();
-        let FileRange { file_id, range } = src.with_value(node).original_file_range(db);
-        let focus_range =
-            src.value.lifetime().and_then(|lt| lt.lifetime_ident_token()).map(|lt| lt.text_range());
-        let name = self.name(db).to_string().into();
-        NavigationTarget {
-            file_id,
-            name,
-            kind: Some(SymbolKind::Label),
-            full_range: range,
-            focus_range,
-            container_name: None,
-            description: None,
-            docs: None,
-        }
-    }
-}
-
 impl ToNav for hir::TypeParam {
     fn to_nav(&self, db: &RootDatabase) -> NavigationTarget {
         let src = self.source(db);
diff --git a/crates/ide/src/doc_links.rs b/crates/ide/src/doc_links.rs
index e10516f43a..b61ea0b3e4 100644
--- a/crates/ide/src/doc_links.rs
+++ b/crates/ide/src/doc_links.rs
@@ -193,8 +193,7 @@ fn rewrite_intra_doc_link(
         Definition::SelfType(_)
         | Definition::Local(_)
         | Definition::TypeParam(_)
-        | Definition::LifetimeParam(_)
-        | Definition::Label(_) => return None,
+        | Definition::LifetimeParam(_) => return None,
     }?;
     let krate = resolved.module(db)?.krate();
     let canonical_path = resolved.canonical_path(db)?;
diff --git a/crates/ide/src/goto_definition.rs b/crates/ide/src/goto_definition.rs
index 912144f8b9..47dd85cebd 100644
--- a/crates/ide/src/goto_definition.rs
+++ b/crates/ide/src/goto_definition.rs
@@ -1130,19 +1130,4 @@ fn foo<T>() where T: for<'a> Foo<&'a<|> (u8, u16)>, {}
 "#,
         );
     }
-
-    #[test]
-    fn goto_label() {
-        check(
-            r#"
-fn foo<'foo>(_: &'foo ()) {
-    'foo: {
-  //^^^^
-        'bar: loop {
-            break 'foo<|>;
-        }
-    }
-}"#,
-        )
-    }
 }
diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs
index 73245fbe75..52f993cc92 100644
--- a/crates/ide/src/hover.rs
+++ b/crates/ide/src/hover.rs
@@ -370,7 +370,7 @@ fn hover_for_definition(db: &RootDatabase, def: Definition) -> Option<Markup> {
                 Adt::Enum(it) => from_def_source(db, it, mod_path),
             })
         }
-        Definition::TypeParam(_) | Definition::LifetimeParam(_) | Definition::Label(_) => {
+        Definition::TypeParam(_) | Definition::LifetimeParam(_) => {
             // FIXME: Hover for generic param
             None
         }
diff --git a/crates/ide/src/lib.rs b/crates/ide/src/lib.rs
index 41eb139d16..dbad9a84f6 100644
--- a/crates/ide/src/lib.rs
+++ b/crates/ide/src/lib.rs
@@ -79,7 +79,7 @@ pub use crate::{
         HighlightedRange,
     },
 };
-pub use assists::{Assist, AssistConfig, AssistId, AssistKind};
+pub use assists::{Assist, AssistConfig, AssistId, AssistKind, ResolvedAssist};
 pub use completion::{
     CompletionConfig, CompletionItem, CompletionItemKind, CompletionResolveCapability,
     CompletionScore, ImportEdit, InsertTextFormat,
@@ -490,17 +490,23 @@ impl Analysis {
             .unwrap_or_default())
     }
 
-    /// Computes assists (aka code actions aka intentions) for the given
-    /// position. If `resolve == false`, computes enough info to show the
-    /// lightbulb list in the editor, but doesn't compute actual edits, to
-    /// improve performance.
-    pub fn assists(
+    /// Computes resolved assists with source changes for the given position.
+    pub fn resolved_assists(
+        &self,
+        config: &AssistConfig,
+        frange: FileRange,
+    ) -> Cancelable<Vec<ResolvedAssist>> {
+        self.with_db(|db| assists::Assist::resolved(db, config, frange))
+    }
+
+    /// Computes unresolved assists (aka code actions aka intentions) for the given
+    /// position.
+    pub fn unresolved_assists(
         &self,
         config: &AssistConfig,
-        resolve: bool,
         frange: FileRange,
     ) -> Cancelable<Vec<Assist>> {
-        self.with_db(|db| Assist::get(db, config, resolve, frange))
+        self.with_db(|db| Assist::unresolved(db, config, frange))
     }
 
     /// Computes the set of diagnostics for the given file.
@@ -529,14 +535,6 @@ impl Analysis {
         self.with_db(|db| references::rename::prepare_rename(db, position))
     }
 
-    pub fn will_rename_file(
-        &self,
-        file_id: FileId,
-        new_name_stem: &str,
-    ) -> Cancelable<Option<SourceChange>> {
-        self.with_db(|db| references::rename::will_rename_file(db, file_id, new_name_stem))
-    }
-
     pub fn structural_search_replace(
         &self,
         query: &str,
diff --git a/crates/ide/src/references.rs b/crates/ide/src/references.rs
index 21b2d7ca1c..33b7358f72 100644
--- a/crates/ide/src/references.rs
+++ b/crates/ide/src/references.rs
@@ -130,7 +130,7 @@ pub(crate) fn find_all_refs(
                 kind = ReferenceKind::FieldShorthandForLocal;
             }
         }
-    } else if matches!(def, Definition::LifetimeParam(_) | Definition::Label(_)) {
+    } else if let Definition::LifetimeParam(_) = def {
         kind = ReferenceKind::Lifetime;
     };
 
@@ -1122,26 +1122,4 @@ fn main() {
             "#]],
         );
     }
-
-    #[test]
-    fn test_find_labels() {
-        check(
-            r#"
-fn foo<'a>() -> &'a () {
-    'a: loop {
-        'b: loop {
-            continue 'a<|>;
-        }
-        break 'a;
-    }
-}
-"#,
-            expect![[r#"
-                'a Label FileId(0) 29..32 29..31 Lifetime
-
-                FileId(0) 80..82 Lifetime
-                FileId(0) 108..110 Lifetime
-            "#]],
-        );
-    }
 }
diff --git a/crates/ide/src/references/rename.rs b/crates/ide/src/references/rename.rs
index 854bf194eb..cd721b7ebc 100644
--- a/crates/ide/src/references/rename.rs
+++ b/crates/ide/src/references/rename.rs
@@ -6,7 +6,7 @@ use std::{
 };
 
 use hir::{Module, ModuleDef, ModuleSource, Semantics};
-use ide_db::base_db::{AnchoredPathBuf, FileId, FileRange, SourceDatabaseExt};
+use ide_db::base_db::{AnchoredPathBuf, FileRange, SourceDatabaseExt};
 use ide_db::{
     defs::{Definition, NameClass, NameRefClass},
     RootDatabase,
@@ -110,23 +110,6 @@ pub(crate) fn rename_with_semantics(
     }
 }
 
-pub(crate) fn will_rename_file(
-    db: &RootDatabase,
-    file_id: FileId,
-    new_name_stem: &str,
-) -> Option<SourceChange> {
-    let sema = Semantics::new(db);
-    let module = sema.to_module_def(file_id)?;
-
-    let decl = module.declaration_source(db)?;
-    let range = decl.value.name()?.syntax().text_range();
-
-    let position = FilePosition { file_id: decl.file_id.original_file(db), offset: range.start() };
-    let mut change = rename_mod(&sema, position, module, new_name_stem).ok()?.info;
-    change.file_system_edits.clear();
-    Some(change)
-}
-
 fn find_module_at_offset(
     sema: &Semantics<RootDatabase>,
     position: FilePosition,
@@ -1540,29 +1523,4 @@ fn main() {
 }"#,
         );
     }
-
-    #[test]
-    fn test_rename_label() {
-        check(
-            "'foo",
-            r#"
-fn foo<'a>() -> &'a () {
-    'a: {
-        'b: loop {
-            break 'a<|>;
-        }
-    }
-}
-"#,
-            r#"
-fn foo<'a>() -> &'a () {
-    'foo: {
-        'b: loop {
-            break 'foo;
-        }
-    }
-}
-"#,
-        )
-    }
 }
diff --git a/crates/ide/src/runnables.rs b/crates/ide/src/runnables.rs
index 8911832660..2f2b99130e 100644
--- a/crates/ide/src/runnables.rs
+++ b/crates/ide/src/runnables.rs
@@ -193,7 +193,7 @@ fn module_def_doctest(sema: &Semantics<RootDatabase>, def: hir::ModuleDef) -> Op
                 if let hir::AssocItemContainer::Impl(imp) = assoc_def.container(sema.db) {
                     if let Some(adt) = imp.target_ty(sema.db).as_adt() {
                         let name = adt.name(sema.db).to_string();
-                        let idx = path.rfind(':').map_or(0, |idx| idx + 1);
+                        let idx = path.rfind(':').unwrap_or(0);
                         let (prefix, suffix) = path.split_at(idx);
                         return format!("{}{}::{}", prefix, name, suffix);
                     }
@@ -931,42 +931,4 @@ mod test_mod {
             "#]],
         );
     }
-
-    #[test]
-    fn test_doc_runnables_impl_mod() {
-        check(
-            r#"
-//- /lib.rs
-mod foo;
-//- /foo.rs
-struct Foo;<|>
-impl Foo {
-    /// ```
-    /// let x = 5;
-    /// ```
-    fn foo() {}
-}
-        "#,
-            &[&DOCTEST],
-            expect![[r#"
-                [
-                    Runnable {
-                        nav: NavigationTarget {
-                            file_id: FileId(
-                                1,
-                            ),
-                            full_range: 27..81,
-                            name: "foo",
-                        },
-                        kind: DocTest {
-                            test_id: Path(
-                                "foo::Foo::foo",
-                            ),
-                        },
-                        cfg: None,
-                    },
-                ]
-            "#]],
-        );
-    }
 }
diff --git a/crates/ide/src/syntax_highlighting.rs b/crates/ide/src/syntax_highlighting.rs
index 5ad96581bd..00c717c7c7 100644
--- a/crates/ide/src/syntax_highlighting.rs
+++ b/crates/ide/src/syntax_highlighting.rs
@@ -560,20 +560,10 @@ fn highlight_element(
         CHAR => HighlightTag::CharLiteral.into(),
         QUESTION => Highlight::new(HighlightTag::Operator) | HighlightModifier::ControlFlow,
         LIFETIME => {
-            let lifetime = element.into_node().and_then(ast::Lifetime::cast).unwrap();
-
-            match NameClass::classify_lifetime(sema, &lifetime) {
-                Some(NameClass::Definition(def)) => {
-                    highlight_def(db, def) | HighlightModifier::Definition
-                }
-                None => match NameRefClass::classify_lifetime(sema, &lifetime) {
-                    Some(NameRefClass::Definition(def)) => highlight_def(db, def),
-                    _ => Highlight::new(HighlightTag::Symbol(SymbolKind::LifetimeParam)),
-                },
-                _ => {
-                    Highlight::new(HighlightTag::Symbol(SymbolKind::LifetimeParam))
-                        | HighlightModifier::Definition
-                }
+            let h = Highlight::new(HighlightTag::Symbol(SymbolKind::LifetimeParam));
+            match element.parent().map(|it| it.kind()) {
+                Some(LIFETIME_PARAM) | Some(LABEL) => h | HighlightModifier::Definition,
+                _ => h,
             }
         }
         p if p.is_punct() => match p {
@@ -835,7 +825,6 @@ fn highlight_def(db: &RootDatabase, def: Definition) -> Highlight {
             return h;
         }
         Definition::LifetimeParam(_) => HighlightTag::Symbol(SymbolKind::LifetimeParam),
-        Definition::Label(_) => HighlightTag::Symbol(SymbolKind::Label),
     }
     .into()
 }
diff --git a/crates/ide/src/syntax_highlighting/html.rs b/crates/ide/src/syntax_highlighting/html.rs
index 99ba3a59d3..abcc5cccc7 100644
--- a/crates/ide/src/syntax_highlighting/html.rs
+++ b/crates/ide/src/syntax_highlighting/html.rs
@@ -64,7 +64,6 @@ body                { margin: 0; }
 pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padding: 0.4em; }
 
 .lifetime           { color: #DFAF8F; font-style: italic; }
-.label              { color: #DFAF8F; font-style: italic; }
 .comment            { color: #7F9F7F; }
 .documentation      { color: #629755; }
 .injected           { opacity: 0.65 ; }
diff --git a/crates/ide/src/syntax_highlighting/tags.rs b/crates/ide/src/syntax_highlighting/tags.rs
index 2a6cc0cab6..974f54fa01 100644
--- a/crates/ide/src/syntax_highlighting/tags.rs
+++ b/crates/ide/src/syntax_highlighting/tags.rs
@@ -80,7 +80,6 @@ impl HighlightTag {
                 SymbolKind::LifetimeParam => "lifetime",
                 SymbolKind::Macro => "macro",
                 SymbolKind::Local => "variable",
-                SymbolKind::Label => "label",
                 SymbolKind::ValueParam => "value_param",
                 SymbolKind::SelfParam => "self_keyword",
                 SymbolKind::Impl => "self_type",
diff --git a/crates/ide_db/src/defs.rs b/crates/ide_db/src/defs.rs
index d33a6cb863..9d7dce1d47 100644
--- a/crates/ide_db/src/defs.rs
+++ b/crates/ide_db/src/defs.rs
@@ -6,8 +6,8 @@
 // FIXME: this badly needs rename/rewrite (matklad, 2020-02-06).
 
 use hir::{
-    db::HirDatabase, Crate, Field, HasVisibility, Impl, Label, LifetimeParam, Local, MacroDef,
-    Module, ModuleDef, Name, PathResolution, Semantics, TypeParam, Visibility,
+    db::HirDatabase, Crate, Field, HasVisibility, Impl, LifetimeParam, Local, MacroDef, Module,
+    ModuleDef, Name, PathResolution, Semantics, TypeParam, Visibility,
 };
 use syntax::{
     ast::{self, AstNode},
@@ -26,7 +26,7 @@ pub enum Definition {
     Local(Local),
     TypeParam(TypeParam),
     LifetimeParam(LifetimeParam),
-    Label(Label),
+    // FIXME: Label
 }
 
 impl Definition {
@@ -39,7 +39,6 @@ impl Definition {
             Definition::Local(it) => Some(it.module(db)),
             Definition::TypeParam(it) => Some(it.module(db)),
             Definition::LifetimeParam(it) => Some(it.module(db)),
-            Definition::Label(it) => Some(it.module(db)),
         }
     }
 
@@ -52,7 +51,6 @@ impl Definition {
             Definition::Local(_) => None,
             Definition::TypeParam(_) => None,
             Definition::LifetimeParam(_) => None,
-            Definition::Label(_) => None,
         }
     }
 
@@ -79,7 +77,6 @@ impl Definition {
             Definition::Local(it) => it.name(db)?,
             Definition::TypeParam(it) => it.name(db),
             Definition::LifetimeParam(it) => it.name(db),
-            Definition::Label(it) => it.name(db),
         };
         Some(name)
     }
@@ -251,10 +248,7 @@ impl NameClass {
                     let def = sema.to_def(&it)?;
                     Some(NameClass::Definition(Definition::LifetimeParam(def)))
                 },
-                ast::Label(it) => {
-                    let def = sema.to_def(&it)?;
-                    Some(NameClass::Definition(Definition::Label(def)))
-                },
+                ast::Label(_it) => None,
                 _ => None,
             }
         }
@@ -376,9 +370,6 @@ impl NameRefClass {
         let _p = profile::span("classify_lifetime_ref").detail(|| lifetime.to_string());
         let parent = lifetime.syntax().parent()?;
         match parent.kind() {
-            SyntaxKind::BREAK_EXPR | SyntaxKind::CONTINUE_EXPR => {
-                sema.resolve_label(lifetime).map(Definition::Label).map(NameRefClass::Definition)
-            }
             SyntaxKind::LIFETIME_ARG
             | SyntaxKind::SELF_PARAM
             | SyntaxKind::TYPE_BOUND
@@ -396,6 +387,7 @@ impl NameRefClass {
                     .map(Definition::LifetimeParam)
                     .map(NameRefClass::Definition)
             }
+            SyntaxKind::BREAK_EXPR | SyntaxKind::CONTINUE_EXPR => None,
             _ => None,
         }
     }
diff --git a/crates/mbe/src/mbe_expander/matcher.rs b/crates/mbe/src/mbe_expander/matcher.rs
index 44722c0f1a..7aeef7be5c 100644
--- a/crates/mbe/src/mbe_expander/matcher.rs
+++ b/crates/mbe/src/mbe_expander/matcher.rs
@@ -240,26 +240,26 @@ impl<'a> TtIter<'a> {
                 let tt3 = self.next().unwrap().clone();
                 Ok(tt::Subtree { delimiter: None, token_trees: vec![tt, tt2, tt3] }.into())
             }
-            ('-', '=', _)
-            | ('-', '>', _)
-            | (':', ':', _)
-            | ('!', '=', _)
-            | ('.', '.', _)
-            | ('*', '=', _)
-            | ('/', '=', _)
-            | ('&', '&', _)
-            | ('&', '=', _)
-            | ('%', '=', _)
-            | ('^', '=', _)
-            | ('+', '=', _)
-            | ('<', '<', _)
-            | ('<', '=', _)
-            | ('=', '=', _)
-            | ('=', '>', _)
-            | ('>', '=', _)
-            | ('>', '>', _)
-            | ('|', '=', _)
-            | ('|', '|', _) => {
+            ('-', '=', None)
+            | ('-', '>', None)
+            | (':', ':', None)
+            | ('!', '=', None)
+            | ('.', '.', None)
+            | ('*', '=', None)
+            | ('/', '=', None)
+            | ('&', '&', None)
+            | ('&', '=', None)
+            | ('%', '=', None)
+            | ('^', '=', None)
+            | ('+', '=', None)
+            | ('<', '<', None)
+            | ('<', '=', None)
+            | ('=', '=', None)
+            | ('=', '>', None)
+            | ('>', '=', None)
+            | ('>', '>', None)
+            | ('|', '=', None)
+            | ('|', '|', None) => {
                 let tt2 = self.next().unwrap().clone();
                 Ok(tt::Subtree { delimiter: None, token_trees: vec![tt, tt2] }.into())
             }
diff --git a/crates/mbe/src/parser.rs b/crates/mbe/src/parser.rs
index d681905f57..c3fdd40404 100644
--- a/crates/mbe/src/parser.rs
+++ b/crates/mbe/src/parser.rs
@@ -101,15 +101,8 @@ fn next_op<'a>(
                     Op::Repeat { subtree, separator, kind }
                 }
                 tt::TokenTree::Leaf(leaf) => match leaf {
-                    tt::Leaf::Punct(punct) => {
-                        static UNDERSCORE: SmolStr = SmolStr::new_inline("_");
-
-                        if punct.char != '_' {
-                            return Err(ExpandError::UnexpectedToken);
-                        }
-                        let name = &UNDERSCORE;
-                        let kind = eat_fragment_kind(src, mode)?;
-                        Op::Var { name, kind }
+                    tt::Leaf::Punct(_) => {
+                        return Err(ExpandError::UnexpectedToken);
                     }
                     tt::Leaf::Ident(ident) => {
                         let name = &ident.text;
diff --git a/crates/mbe/src/syntax_bridge.rs b/crates/mbe/src/syntax_bridge.rs
index 265c0d63d8..2bec7fd495 100644
--- a/crates/mbe/src/syntax_bridge.rs
+++ b/crates/mbe/src/syntax_bridge.rs
@@ -313,7 +313,7 @@ trait TokenConvertor {
             return;
         }
 
-        result.push(if k.is_punct() {
+        result.push(if k.is_punct() && k != UNDERSCORE {
             assert_eq!(range.len(), TextSize::of('.'));
             let delim = match k {
                 T!['('] => Some((tt::DelimiterKind::Parenthesis, T![')'])),
@@ -378,6 +378,7 @@ trait TokenConvertor {
             let leaf: tt::Leaf = match k {
                 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 => {
diff --git a/crates/parser/src/grammar.rs b/crates/parser/src/grammar.rs
index 63cc900272..f08c8bab74 100644
--- a/crates/parser/src/grammar.rs
+++ b/crates/parser/src/grammar.rs
@@ -59,7 +59,7 @@ pub(crate) mod fragments {
     };
 
     pub(crate) fn expr(p: &mut Parser) {
-        let _ = expressions::expr_with_attrs(p);
+        let _ = expressions::expr(p);
     }
 
     pub(crate) fn stmt(p: &mut Parser) {
diff --git a/crates/parser/src/grammar/items.rs b/crates/parser/src/grammar/items.rs
index cf4168d321..72b73f8917 100644
--- a/crates/parser/src/grammar/items.rs
+++ b/crates/parser/src/grammar/items.rs
@@ -389,15 +389,10 @@ fn macro_rules(p: &mut Parser, m: Marker) {
     }
 
     match p.current() {
-        // test macro_rules_non_brace
-        // macro_rules! m ( ($i:ident) => {} );
-        // macro_rules! m [ ($i:ident) => {} ];
-        T!['['] | T!['('] => {
+        T!['{'] => {
             token_tree(p);
-            p.expect(T![;]);
         }
-        T!['{'] => token_tree(p),
-        _ => p.error("expected `{`, `[`, `(`"),
+        _ => p.error("expected `{`"),
     }
     m.complete(p, MACRO_RULES);
 }
diff --git a/crates/proc_macro_api/src/lib.rs b/crates/proc_macro_api/src/lib.rs
index 2ea456fb09..0d061fd536 100644
--- a/crates/proc_macro_api/src/lib.rs
+++ b/crates/proc_macro_api/src/lib.rs
@@ -16,7 +16,7 @@ use std::{
     sync::Arc,
 };
 
-use base_db::{Env, ProcMacro};
+use base_db::ProcMacro;
 use tt::{SmolStr, Subtree};
 
 use crate::process::{ProcMacroProcessSrv, ProcMacroProcessThread};
@@ -39,19 +39,17 @@ impl PartialEq for ProcMacroProcessExpander {
     }
 }
 
-impl base_db::ProcMacroExpander for ProcMacroProcessExpander {
+impl tt::TokenExpander for ProcMacroProcessExpander {
     fn expand(
         &self,
         subtree: &Subtree,
         attr: Option<&Subtree>,
-        env: &Env,
     ) -> Result<Subtree, tt::ExpansionError> {
         let task = ExpansionTask {
             macro_body: subtree.clone(),
             macro_name: self.name.to_string(),
             attributes: attr.cloned(),
             lib: self.dylib_path.to_path_buf(),
-            env: env.iter().map(|(k, v)| (k.to_string(), v.to_string())).collect(),
         };
 
         let result: ExpansionResult = self.process.send_task(msg::Request::ExpansionMacro(task))?;
@@ -92,7 +90,7 @@ impl ProcMacroClient {
                     ProcMacroKind::FuncLike => base_db::ProcMacroKind::FuncLike,
                     ProcMacroKind::Attr => base_db::ProcMacroKind::Attr,
                 };
-                let expander = Arc::new(ProcMacroProcessExpander {
+                let expander: Arc<dyn tt::TokenExpander> = Arc::new(ProcMacroProcessExpander {
                     process: self.process.clone(),
                     name: name.clone(),
                     dylib_path: dylib_path.into(),
diff --git a/crates/proc_macro_api/src/rpc.rs b/crates/proc_macro_api/src/rpc.rs
index cf830b59f1..b85f92eead 100644
--- a/crates/proc_macro_api/src/rpc.rs
+++ b/crates/proc_macro_api/src/rpc.rs
@@ -51,9 +51,6 @@ pub struct ExpansionTask {
     pub attributes: Option<Subtree>,
 
     pub lib: PathBuf,
-
-    /// Environment variables to set during macro expansion.
-    pub env: Vec<(String, String)>,
 }
 
 #[derive(Clone, Eq, PartialEq, Debug, Default, Serialize, Deserialize)]
@@ -254,7 +251,6 @@ mod tests {
             macro_name: Default::default(),
             attributes: None,
             lib: Default::default(),
-            env: Default::default(),
         };
 
         let json = serde_json::to_string(&task).unwrap();
diff --git a/crates/proc_macro_srv/src/dylib.rs b/crates/proc_macro_srv/src/dylib.rs
index 4e719f3aa0..2afb973cc2 100644
--- a/crates/proc_macro_srv/src/dylib.rs
+++ b/crates/proc_macro_srv/src/dylib.rs
@@ -136,7 +136,6 @@ impl Expander {
                         &crate::proc_macro::bridge::server::SameThread,
                         crate::rustc_server::Rustc::default(),
                         parsed_body,
-                        false,
                     );
                     return res.map(|it| it.subtree);
                 }
@@ -145,7 +144,6 @@ impl Expander {
                         &crate::proc_macro::bridge::server::SameThread,
                         crate::rustc_server::Rustc::default(),
                         parsed_body,
-                        false,
                     );
                     return res.map(|it| it.subtree);
                 }
@@ -155,7 +153,6 @@ impl Expander {
                         crate::rustc_server::Rustc::default(),
                         parsed_attributes,
                         parsed_body,
-                        false,
                     );
                     return res.map(|it| it.subtree);
                 }
diff --git a/crates/proc_macro_srv/src/lib.rs b/crates/proc_macro_srv/src/lib.rs
index d4f04ee069..9cca969944 100644
--- a/crates/proc_macro_srv/src/lib.rs
+++ b/crates/proc_macro_srv/src/lib.rs
@@ -24,7 +24,7 @@ use proc_macro::bridge::client::TokenStream;
 use proc_macro_api::{ExpansionResult, ExpansionTask, ListMacrosResult, ListMacrosTask};
 use std::{
     collections::{hash_map::Entry, HashMap},
-    env, fs,
+    fs,
     path::{Path, PathBuf},
     time::SystemTime,
 };
@@ -37,23 +37,7 @@ pub(crate) struct ProcMacroSrv {
 impl ProcMacroSrv {
     pub fn expand(&mut self, task: &ExpansionTask) -> Result<ExpansionResult, String> {
         let expander = self.expander(&task.lib)?;
-
-        let mut prev_env = HashMap::new();
-        for (k, v) in &task.env {
-            prev_env.insert(k.as_str(), env::var_os(k));
-            env::set_var(k, v);
-        }
-
-        let result = expander.expand(&task.macro_name, &task.macro_body, task.attributes.as_ref());
-
-        for (k, _) in &task.env {
-            match &prev_env[k.as_str()] {
-                Some(v) => env::set_var(k, v),
-                None => env::remove_var(k),
-            }
-        }
-
-        match result {
+        match expander.expand(&task.macro_name, &task.macro_body, task.attributes.as_ref()) {
             Ok(expansion) => Ok(ExpansionResult { expansion }),
             Err(msg) => {
                 let msg = msg.as_str().unwrap_or("<unknown error>");
diff --git a/crates/proc_macro_srv/src/proc_macro/bridge/client.rs b/crates/proc_macro_srv/src/proc_macro/bridge/client.rs
index ca6749b9bc..55d6330cc3 100644
--- a/crates/proc_macro_srv/src/proc_macro/bridge/client.rs
+++ b/crates/proc_macro_srv/src/proc_macro/bridge/client.rs
@@ -303,21 +303,17 @@ impl BridgeState<'_> {
 
 impl Bridge<'_> {
     fn enter<R>(self, f: impl FnOnce() -> R) -> R {
-        let force_show_panics = self.force_show_panics;
-
         // Hide the default panic output within `proc_macro` expansions.
         // NB. the server can't do this because it may use a different libstd.
         static HIDE_PANICS_DURING_EXPANSION: Once = Once::new();
         HIDE_PANICS_DURING_EXPANSION.call_once(|| {
             let prev = panic::take_hook();
             panic::set_hook(Box::new(move |info| {
-                let show = BridgeState::with(|state| match state {
-                    BridgeState::NotConnected => true,
-                    // Something weird is going on, so don't suppress any backtraces
-                    BridgeState::InUse => true,
-                    BridgeState::Connected(bridge) => force_show_panics,
+                let hide = BridgeState::with(|state| match state {
+                    BridgeState::NotConnected => false,
+                    BridgeState::Connected(_) | BridgeState::InUse => true,
                 });
-                if show {
+                if !hide {
                     prev(info)
                 }
             }));
diff --git a/crates/proc_macro_srv/src/proc_macro/bridge/mod.rs b/crates/proc_macro_srv/src/proc_macro/bridge/mod.rs
index e4006a5ab0..b97886eb94 100644
--- a/crates/proc_macro_srv/src/proc_macro/bridge/mod.rs
+++ b/crates/proc_macro_srv/src/proc_macro/bridge/mod.rs
@@ -225,9 +225,6 @@ pub struct Bridge<'a> {
 
     /// Server-side function that the client uses to make requests.
     dispatch: closure::Closure<'a, Buffer<u8>, Buffer<u8>>,
-
-    /// If 'true', always invoke the default panic hook
-    force_show_panics: bool,
 }
 
 // impl<'a> !Sync for Bridge<'a> {}
diff --git a/crates/proc_macro_srv/src/proc_macro/bridge/server.rs b/crates/proc_macro_srv/src/proc_macro/bridge/server.rs
index 88fbdc078c..3acb239af6 100644
--- a/crates/proc_macro_srv/src/proc_macro/bridge/server.rs
+++ b/crates/proc_macro_srv/src/proc_macro/bridge/server.rs
@@ -138,7 +138,6 @@ pub trait ExecutionStrategy {
         input: Buffer<u8>,
         run_client: extern "C" fn(Bridge<'_>, D) -> Buffer<u8>,
         client_data: D,
-        force_show_panics: bool,
     ) -> Buffer<u8>;
 }
 
@@ -151,14 +150,10 @@ impl ExecutionStrategy for SameThread {
         input: Buffer<u8>,
         run_client: extern "C" fn(Bridge<'_>, D) -> Buffer<u8>,
         client_data: D,
-        force_show_panics: bool,
     ) -> Buffer<u8> {
         let mut dispatch = |b| dispatcher.dispatch(b);
 
-        run_client(
-            Bridge { cached_buffer: input, dispatch: (&mut dispatch).into(), force_show_panics },
-            client_data,
-        )
+        run_client(Bridge { cached_buffer: input, dispatch: (&mut dispatch).into() }, client_data)
     }
 }
 
@@ -174,7 +169,6 @@ impl ExecutionStrategy for CrossThread1 {
         input: Buffer<u8>,
         run_client: extern "C" fn(Bridge<'_>, D) -> Buffer<u8>,
         client_data: D,
-        force_show_panics: bool,
     ) -> Buffer<u8> {
         use std::sync::mpsc::channel;
 
@@ -188,11 +182,7 @@ impl ExecutionStrategy for CrossThread1 {
             };
 
             run_client(
-                Bridge {
-                    cached_buffer: input,
-                    dispatch: (&mut dispatch).into(),
-                    force_show_panics,
-                },
+                Bridge { cached_buffer: input, dispatch: (&mut dispatch).into() },
                 client_data,
             )
         });
@@ -214,7 +204,6 @@ impl ExecutionStrategy for CrossThread2 {
         input: Buffer<u8>,
         run_client: extern "C" fn(Bridge<'_>, D) -> Buffer<u8>,
         client_data: D,
-        force_show_panics: bool,
     ) -> Buffer<u8> {
         use std::sync::{Arc, Mutex};
 
@@ -240,11 +229,7 @@ impl ExecutionStrategy for CrossThread2 {
             };
 
             let r = run_client(
-                Bridge {
-                    cached_buffer: input,
-                    dispatch: (&mut dispatch).into(),
-                    force_show_panics,
-                },
+                Bridge { cached_buffer: input, dispatch: (&mut dispatch).into() },
                 client_data,
             );
 
@@ -283,7 +268,6 @@ fn run_server<
     input: I,
     run_client: extern "C" fn(Bridge<'_>, D) -> Buffer<u8>,
     client_data: D,
-    force_show_panics: bool,
 ) -> Result<O, PanicMessage> {
     let mut dispatcher =
         Dispatcher { handle_store: HandleStore::new(handle_counters), server: MarkedTypes(server) };
@@ -291,13 +275,7 @@ fn run_server<
     let mut b = Buffer::new();
     input.encode(&mut b, &mut dispatcher.handle_store);
 
-    b = strategy.run_bridge_and_client(
-        &mut dispatcher,
-        b,
-        run_client,
-        client_data,
-        force_show_panics,
-    );
+    b = strategy.run_bridge_and_client(&mut dispatcher, b, run_client, client_data);
 
     Result::decode(&mut &b[..], &mut dispatcher.handle_store)
 }
@@ -308,7 +286,6 @@ impl client::Client<fn(crate::TokenStream) -> crate::TokenStream> {
         strategy: &impl ExecutionStrategy,
         server: S,
         input: S::TokenStream,
-        force_show_panics: bool,
     ) -> Result<S::TokenStream, PanicMessage> {
         let client::Client { get_handle_counters, run, f } = *self;
         run_server(
@@ -318,7 +295,6 @@ impl client::Client<fn(crate::TokenStream) -> crate::TokenStream> {
             <MarkedTypes<S> as Types>::TokenStream::mark(input),
             run,
             f,
-            force_show_panics,
         )
         .map(<MarkedTypes<S> as Types>::TokenStream::unmark)
     }
@@ -331,7 +307,6 @@ impl client::Client<fn(crate::TokenStream, crate::TokenStream) -> crate::TokenSt
         server: S,
         input: S::TokenStream,
         input2: S::TokenStream,
-        force_show_panics: bool,
     ) -> Result<S::TokenStream, PanicMessage> {
         let client::Client { get_handle_counters, run, f } = *self;
         run_server(
@@ -344,7 +319,6 @@ impl client::Client<fn(crate::TokenStream, crate::TokenStream) -> crate::TokenSt
             ),
             run,
             f,
-            force_show_panics,
         )
         .map(<MarkedTypes<S> as Types>::TokenStream::unmark)
     }
diff --git a/crates/rust-analyzer/Cargo.toml b/crates/rust-analyzer/Cargo.toml
index 53e70eaf7b..0b4d3f4ebb 100644
--- a/crates/rust-analyzer/Cargo.toml
+++ b/crates/rust-analyzer/Cargo.toml
@@ -28,7 +28,6 @@ oorandom = "11.1.2"
 rustc-hash = "1.1.0"
 serde = { version = "1.0.106", features = ["derive"] }
 serde_json = { version = "1.0.48", features = ["preserve_order"] }
-serde_path_to_error = "0.1"
 threadpool = "1.7.1"
 rayon = "1.5"
 mimalloc = { version = "0.1.19", default-features = false, optional = true }
diff --git a/crates/rust-analyzer/src/caps.rs b/crates/rust-analyzer/src/caps.rs
index 80e46bf7f1..de5eb93b50 100644
--- a/crates/rust-analyzer/src/caps.rs
+++ b/crates/rust-analyzer/src/caps.rs
@@ -5,14 +5,12 @@ use ide::CompletionResolveCapability;
 use lsp_types::{
     CallHierarchyServerCapability, ClientCapabilities, CodeActionKind, CodeActionOptions,
     CodeActionProviderCapability, CodeLensOptions, CompletionOptions,
-    DocumentOnTypeFormattingOptions, FileOperationFilter, FileOperationPattern,
-    FileOperationPatternKind, FileOperationRegistrationOptions, FoldingRangeProviderCapability,
-    HoverProviderCapability, ImplementationProviderCapability, OneOf, RenameOptions, SaveOptions,
+    DocumentOnTypeFormattingOptions, FoldingRangeProviderCapability, HoverProviderCapability,
+    ImplementationProviderCapability, OneOf, RenameOptions, SaveOptions,
     SelectionRangeProviderCapability, SemanticTokensFullOptions, SemanticTokensLegend,
     SemanticTokensOptions, ServerCapabilities, SignatureHelpOptions, TextDocumentSyncCapability,
     TextDocumentSyncKind, TextDocumentSyncOptions, TypeDefinitionProviderCapability,
-    WorkDoneProgressOptions, WorkspaceFileOperationsServerCapabilities,
-    WorkspaceServerCapabilities,
+    WorkDoneProgressOptions,
 };
 use rustc_hash::FxHashSet;
 use serde_json::json;
@@ -70,26 +68,7 @@ pub fn server_capabilities(client_caps: &ClientCapabilities) -> ServerCapabiliti
         document_link_provider: None,
         color_provider: None,
         execute_command_provider: None,
-        workspace: Some(WorkspaceServerCapabilities {
-            workspace_folders: None,
-            file_operations: Some(WorkspaceFileOperationsServerCapabilities {
-                did_create: None,
-                will_create: None,
-                did_rename: None,
-                will_rename: Some(FileOperationRegistrationOptions {
-                    filters: vec![FileOperationFilter {
-                        scheme: Some(String::from("file")),
-                        pattern: FileOperationPattern {
-                            glob: String::from("**/*.rs"),
-                            matches: Some(FileOperationPatternKind::File),
-                            options: None,
-                        },
-                    }],
-                }),
-                did_delete: None,
-                will_delete: None,
-            }),
-        }),
+        workspace: None,
         call_hierarchy_provider: Some(CallHierarchyServerCapability::Simple(true)),
         semantic_tokens_provider: Some(
             SemanticTokensOptions {
diff --git a/crates/rust-analyzer/src/cli/progress_report.rs b/crates/rust-analyzer/src/cli/progress_report.rs
index 5a2dc39d52..bdbe565e60 100644
--- a/crates/rust-analyzer/src/cli/progress_report.rs
+++ b/crates/rust-analyzer/src/cli/progress_report.rs
@@ -1,7 +1,7 @@
 //! A simple progress bar
 //!
 //! A single thread non-optimized progress bar
-use std::io::{self, Write};
+use std::io::Write;
 
 /// A Simple ASCII Progress Bar
 pub(crate) struct ProgressReport {
@@ -97,8 +97,8 @@ impl ProgressReport {
             }
         }
 
-        let _ = io::stdout().write(output.as_bytes());
-        let _ = io::stdout().flush();
+        let _ = std::io::stdout().write(output.as_bytes());
+        let _ = std::io::stdout().flush();
         self.text = text.to_string();
     }
 
@@ -115,8 +115,6 @@ impl ProgressReport {
         let spaces = " ".repeat(self.text.len());
         let backspaces = "\x08".repeat(self.text.len());
         print!("{}{}{}", backspaces, spaces, backspaces);
-        let _ = io::stdout().flush();
-
         self.text = String::new();
     }
 }
diff --git a/crates/rust-analyzer/src/handlers.rs b/crates/rust-analyzer/src/handlers.rs
index 374fb5302b..66f8bee991 100644
--- a/crates/rust-analyzer/src/handlers.rs
+++ b/crates/rust-analyzer/src/handlers.rs
@@ -5,13 +5,11 @@
 use std::{
     io::Write as _,
     process::{self, Stdio},
-    sync::Arc,
 };
 
 use ide::{
-    AssistConfig, CompletionResolveCapability, FileId, FilePosition, FileRange, HoverAction,
-    HoverGotoTypeData, LineIndex, NavigationTarget, Query, RangeInfo, Runnable, RunnableKind,
-    SearchScope, SourceChange, SymbolKind, TextEdit,
+    CompletionResolveCapability, FileId, FilePosition, FileRange, HoverAction, HoverGotoTypeData,
+    NavigationTarget, Query, RangeInfo, Runnable, RunnableKind, SearchScope, SymbolKind, TextEdit,
 };
 use itertools::Itertools;
 use lsp_server::ErrorCode;
@@ -402,45 +400,6 @@ pub(crate) fn handle_workspace_symbol(
     }
 }
 
-pub(crate) fn handle_will_rename_files(
-    snap: GlobalStateSnapshot,
-    params: lsp_types::RenameFilesParams,
-) -> Result<Option<lsp_types::WorkspaceEdit>> {
-    let _p = profile::span("handle_will_rename_files");
-
-    let source_changes: Vec<SourceChange> = params
-        .files
-        .into_iter()
-        .filter_map(|file_rename| {
-            let from = Url::parse(&file_rename.old_uri).ok()?;
-            let to = Url::parse(&file_rename.new_uri).ok()?;
-
-            let from_path = from.to_file_path().ok()?;
-            let to_path = to.to_file_path().ok()?;
-
-            // Limit to single-level moves for now.
-            match (from_path.parent(), to_path.parent()) {
-                (Some(p1), Some(p2)) if p1 == p2 => {
-                    let new_name = to_path.file_stem()?;
-                    let new_name = new_name.to_str()?;
-                    Some((snap.url_to_file_id(&from).ok()?, new_name.to_string()))
-                }
-                _ => None,
-            }
-        })
-        .filter_map(|(file_id, new_name)| {
-            snap.analysis.will_rename_file(file_id, &new_name).ok()?
-        })
-        .collect();
-
-    // Drop file system edits since we're just renaming things on the same level
-    let edits = source_changes.into_iter().map(|it| it.source_file_edits).flatten().collect();
-    let source_change = SourceChange::from_edits(edits, Vec::new());
-
-    let workspace_edit = to_proto::workspace_edit(&snap, source_change)?;
-    Ok(Some(workspace_edit))
-}
-
 pub(crate) fn handle_goto_definition(
     snap: GlobalStateSnapshot,
     params: lsp_types::GotoDefinitionParams,
@@ -906,8 +865,58 @@ pub(crate) fn handle_formatting(
     }
 }
 
+fn handle_fixes(
+    snap: &GlobalStateSnapshot,
+    params: &lsp_types::CodeActionParams,
+    res: &mut Vec<lsp_ext::CodeAction>,
+) -> Result<()> {
+    let file_id = from_proto::file_id(&snap, &params.text_document.uri)?;
+    let line_index = snap.analysis.file_line_index(file_id)?;
+    let range = from_proto::text_range(&line_index, params.range);
+
+    match &params.context.only {
+        Some(v) => {
+            if !v.iter().any(|it| {
+                it == &lsp_types::CodeActionKind::EMPTY
+                    || it == &lsp_types::CodeActionKind::QUICKFIX
+            }) {
+                return Ok(());
+            }
+        }
+        None => {}
+    };
+
+    let diagnostics = snap.analysis.diagnostics(&snap.config.diagnostics, file_id)?;
+
+    for fix in diagnostics
+        .into_iter()
+        .filter_map(|d| d.fix)
+        .filter(|fix| fix.fix_trigger_range.intersect(range).is_some())
+    {
+        let edit = to_proto::snippet_workspace_edit(&snap, fix.source_change)?;
+        let action = lsp_ext::CodeAction {
+            title: fix.label.to_string(),
+            group: None,
+            kind: Some(CodeActionKind::QUICKFIX),
+            edit: Some(edit),
+            is_preferred: Some(false),
+            data: None,
+        };
+        res.push(action);
+    }
+
+    for fix in snap.check_fixes.get(&file_id).into_iter().flatten() {
+        let fix_range = from_proto::text_range(&line_index, fix.range);
+        if fix_range.intersect(range).is_none() {
+            continue;
+        }
+        res.push(fix.action.clone());
+    }
+    Ok(())
+}
+
 pub(crate) fn handle_code_action(
-    snap: GlobalStateSnapshot,
+    mut snap: GlobalStateSnapshot,
     params: lsp_types::CodeActionParams,
 ) -> Result<Option<Vec<lsp_ext::CodeAction>>> {
     let _p = profile::span("handle_code_action");
@@ -923,35 +932,24 @@ pub(crate) fn handle_code_action(
     let range = from_proto::text_range(&line_index, params.range);
     let frange = FileRange { file_id, range };
 
-    let assists_config = AssistConfig {
-        allowed: params
-            .clone()
-            .context
-            .only
-            .map(|it| it.into_iter().filter_map(from_proto::assist_kind).collect()),
-        ..snap.config.assist
-    };
+    snap.config.assist.allowed = params
+        .clone()
+        .context
+        .only
+        .map(|it| it.into_iter().filter_map(from_proto::assist_kind).collect());
 
     let mut res: Vec<lsp_ext::CodeAction> = Vec::new();
 
-    let include_quick_fixes = match &params.context.only {
-        Some(v) => v.iter().any(|it| {
-            it == &lsp_types::CodeActionKind::EMPTY || it == &lsp_types::CodeActionKind::QUICKFIX
-        }),
-        None => true,
-    };
-    if include_quick_fixes {
-        add_quick_fixes(&snap, frange, &line_index, &mut res)?;
-    }
+    handle_fixes(&snap, &params, &mut res)?;
 
     if snap.config.client_caps.code_action_resolve {
         for (index, assist) in
-            snap.analysis.assists(&assists_config, false, frange)?.into_iter().enumerate()
+            snap.analysis.unresolved_assists(&snap.config.assist, frange)?.into_iter().enumerate()
         {
             res.push(to_proto::unresolved_code_action(&snap, params.clone(), assist, index)?);
         }
     } else {
-        for assist in snap.analysis.assists(&assists_config, true, frange)?.into_iter() {
+        for assist in snap.analysis.resolved_assists(&snap.config.assist, frange)?.into_iter() {
             res.push(to_proto::resolved_code_action(&snap, assist)?);
         }
     }
@@ -959,40 +957,6 @@ pub(crate) fn handle_code_action(
     Ok(Some(res))
 }
 
-fn add_quick_fixes(
-    snap: &GlobalStateSnapshot,
-    frange: FileRange,
-    line_index: &Arc<LineIndex>,
-    acc: &mut Vec<lsp_ext::CodeAction>,
-) -> Result<()> {
-    let diagnostics = snap.analysis.diagnostics(&snap.config.diagnostics, frange.file_id)?;
-
-    for fix in diagnostics
-        .into_iter()
-        .filter_map(|d| d.fix)
-        .filter(|fix| fix.fix_trigger_range.intersect(frange.range).is_some())
-    {
-        let edit = to_proto::snippet_workspace_edit(&snap, fix.source_change)?;
-        let action = lsp_ext::CodeAction {
-            title: fix.label.to_string(),
-            group: None,
-            kind: Some(CodeActionKind::QUICKFIX),
-            edit: Some(edit),
-            is_preferred: Some(false),
-            data: None,
-        };
-        acc.push(action);
-    }
-
-    for fix in snap.check_fixes.get(&frange.file_id).into_iter().flatten() {
-        let fix_range = from_proto::text_range(&line_index, fix.range);
-        if fix_range.intersect(frange.range).is_some() {
-            acc.push(fix.action.clone());
-        }
-    }
-    Ok(())
-}
-
 pub(crate) fn handle_code_action_resolve(
     mut snap: GlobalStateSnapshot,
     mut code_action: lsp_ext::CodeAction,
@@ -1014,11 +978,11 @@ pub(crate) fn handle_code_action_resolve(
         .only
         .map(|it| it.into_iter().filter_map(from_proto::assist_kind).collect());
 
-    let assists = snap.analysis.assists(&snap.config.assist, true, frange)?;
+    let assists = snap.analysis.resolved_assists(&snap.config.assist, frange)?;
     let (id, index) = split_once(&params.id, ':').unwrap();
     let index = index.parse::<usize>().unwrap();
     let assist = &assists[index];
-    assert!(assist.id.0 == id);
+    assert!(assist.assist.id.0 == id);
     let edit = to_proto::resolved_code_action(&snap, assist.clone())?.edit;
     code_action.edit = edit;
     Ok(code_action)
diff --git a/crates/rust-analyzer/src/lib.rs b/crates/rust-analyzer/src/lib.rs
index d538ad69a1..79fe30e530 100644
--- a/crates/rust-analyzer/src/lib.rs
+++ b/crates/rust-analyzer/src/lib.rs
@@ -46,7 +46,7 @@ pub type Error = Box<dyn std::error::Error + Send + Sync>;
 pub type Result<T, E = Error> = std::result::Result<T, E>;
 
 pub fn from_json<T: DeserializeOwned>(what: &'static str, json: serde_json::Value) -> Result<T> {
-    let res = serde_path_to_error::deserialize(&json)
+    let res = T::deserialize(&json)
         .map_err(|e| format!("Failed to deserialize {}: {}; {}", what, e, json))?;
     Ok(res)
 }
diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs
index 5d55dc96e2..ec3d5e0600 100644
--- a/crates/rust-analyzer/src/main_loop.rs
+++ b/crates/rust-analyzer/src/main_loop.rs
@@ -485,7 +485,6 @@ impl GlobalState {
             .on::<lsp_types::request::SemanticTokensRangeRequest>(
                 handlers::handle_semantic_tokens_range,
             )
-            .on::<lsp_types::request::WillRenameFiles>(handlers::handle_will_rename_files)
             .on::<lsp_ext::Ssr>(handlers::handle_ssr)
             .finish();
         Ok(())
diff --git a/crates/rust-analyzer/src/semantic_tokens.rs b/crates/rust-analyzer/src/semantic_tokens.rs
index c2f6a655d4..1daad1c989 100644
--- a/crates/rust-analyzer/src/semantic_tokens.rs
+++ b/crates/rust-analyzer/src/semantic_tokens.rs
@@ -45,7 +45,6 @@ define_semantic_token_types![
     (FORMAT_SPECIFIER, "formatSpecifier"),
     (GENERIC, "generic"),
     (LIFETIME, "lifetime"),
-    (LABEL, "label"),
     (PUNCTUATION, "punctuation"),
     (SELF_KEYWORD, "selfKeyword"),
     (TYPE_ALIAS, "typeAlias"),
diff --git a/crates/rust-analyzer/src/to_proto.rs b/crates/rust-analyzer/src/to_proto.rs
index 1a38e79f08..5a1ae96aa0 100644
--- a/crates/rust-analyzer/src/to_proto.rs
+++ b/crates/rust-analyzer/src/to_proto.rs
@@ -8,8 +8,8 @@ use ide::{
     Assist, AssistKind, CallInfo, CompletionItem, CompletionItemKind, Documentation, FileId,
     FileRange, FileSystemEdit, Fold, FoldKind, Highlight, HighlightModifier, HighlightTag,
     HighlightedRange, Indel, InlayHint, InlayKind, InsertTextFormat, LineIndex, Markup,
-    NavigationTarget, ReferenceAccess, Runnable, Severity, SourceChange, SourceFileEdit,
-    SymbolKind, TextEdit, TextRange, TextSize,
+    NavigationTarget, ReferenceAccess, ResolvedAssist, Runnable, Severity, SourceChange,
+    SourceFileEdit, SymbolKind, TextEdit, TextRange, TextSize,
 };
 use itertools::Itertools;
 
@@ -46,8 +46,7 @@ pub(crate) fn symbol_kind(symbol_kind: SymbolKind) -> lsp_types::SymbolKind {
         SymbolKind::Local
         | SymbolKind::SelfParam
         | SymbolKind::LifetimeParam
-        | SymbolKind::ValueParam
-        | SymbolKind::Label => lsp_types::SymbolKind::Variable,
+        | SymbolKind::ValueParam => lsp_types::SymbolKind::Variable,
         SymbolKind::Union => lsp_types::SymbolKind::Struct,
     }
 }
@@ -379,7 +378,6 @@ fn semantic_token_type_and_modifiers(
             SymbolKind::Field => lsp_types::SemanticTokenType::PROPERTY,
             SymbolKind::TypeParam => lsp_types::SemanticTokenType::TYPE_PARAMETER,
             SymbolKind::LifetimeParam => semantic_tokens::LIFETIME,
-            SymbolKind::Label => semantic_tokens::LABEL,
             SymbolKind::ValueParam => lsp_types::SemanticTokenType::PARAMETER,
             SymbolKind::SelfParam => semantic_tokens::SELF_KEYWORD,
             SymbolKind::Local => lsp_types::SemanticTokenType::VARIABLE,
@@ -780,7 +778,6 @@ pub(crate) fn unresolved_code_action(
     assist: Assist,
     index: usize,
 ) -> Result<lsp_ext::CodeAction> {
-    assert!(assist.source_change.is_none());
     let res = lsp_ext::CodeAction {
         title: assist.label.to_string(),
         group: assist.group.filter(|_| snap.config.client_caps.code_action_group).map(|gr| gr.0),
@@ -797,14 +794,18 @@ pub(crate) fn unresolved_code_action(
 
 pub(crate) fn resolved_code_action(
     snap: &GlobalStateSnapshot,
-    assist: Assist,
+    assist: ResolvedAssist,
 ) -> Result<lsp_ext::CodeAction> {
-    let change = assist.source_change.unwrap();
+    let change = assist.source_change;
     let res = lsp_ext::CodeAction {
         edit: Some(snippet_workspace_edit(snap, change)?),
-        title: assist.label.to_string(),
-        group: assist.group.filter(|_| snap.config.client_caps.code_action_group).map(|gr| gr.0),
-        kind: Some(code_action_kind(assist.id.1)),
+        title: assist.assist.label.to_string(),
+        group: assist
+            .assist
+            .group
+            .filter(|_| snap.config.client_caps.code_action_group)
+            .map(|gr| gr.0),
+        kind: Some(code_action_kind(assist.assist.id.1)),
         is_preferred: None,
         data: None,
     };
diff --git a/crates/syntax/Cargo.toml b/crates/syntax/Cargo.toml
index 21015591c7..c6a6f11e13 100644
--- a/crates/syntax/Cargo.toml
+++ b/crates/syntax/Cargo.toml
@@ -13,7 +13,7 @@ doctest = false
 [dependencies]
 itertools = "0.9.0"
 rowan = "0.10.0"
-rustc_lexer = { version = "695.0.0", package = "rustc-ap-rustc_lexer" }
+rustc_lexer = { version = "691.0.0", package = "rustc-ap-rustc_lexer" }
 rustc-hash = "1.1.0"
 arrayvec = "0.5.1"
 once_cell = "1.3.1"
diff --git a/crates/syntax/src/ast/expr_ext.rs b/crates/syntax/src/ast/expr_ext.rs
index 636ce166d7..e4a9b945c9 100644
--- a/crates/syntax/src/ast/expr_ext.rs
+++ b/crates/syntax/src/ast/expr_ext.rs
@@ -358,7 +358,6 @@ pub enum Effect {
     Async(SyntaxToken),
     Unsafe(SyntaxToken),
     Try(SyntaxToken),
-    Const(SyntaxToken),
     // Very much not an effect, but we stuff it into this node anyway
     Label(ast::Label),
 }
@@ -374,9 +373,6 @@ impl ast::EffectExpr {
         if let Some(token) = self.try_token() {
             return Effect::Try(token);
         }
-        if let Some(token) = self.const_token() {
-            return Effect::Const(token);
-        }
         if let Some(label) = self.label() {
             return Effect::Label(label);
         }
diff --git a/crates/tt/src/lib.rs b/crates/tt/src/lib.rs
index 8301dc28a0..6c1bf8d092 100644
--- a/crates/tt/src/lib.rs
+++ b/crates/tt/src/lib.rs
@@ -1,7 +1,7 @@
 //! `tt` crate defines a `TokenTree` data structure: this is the interface (both
 //! input and output) of macros. It closely mirrors `proc_macro` crate's
 //! `TokenTree`.
-use std::fmt;
+use std::{fmt, panic::RefUnwindSafe};
 
 use stdx::impl_from;
 
@@ -247,3 +247,8 @@ impl fmt::Display for ExpansionError {
         }
     }
 }
+
+pub trait TokenExpander: fmt::Debug + Send + Sync + RefUnwindSafe {
+    fn expand(&self, subtree: &Subtree, attrs: Option<&Subtree>)
+        -> Result<Subtree, ExpansionError>;
+}
diff --git a/docs/dev/style.md b/docs/dev/style.md
index 58b3093798..13c6a2a167 100644
--- a/docs/dev/style.md
+++ b/docs/dev/style.md
@@ -63,18 +63,6 @@ After you are happy with the state of the code, please use [interactive rebase](
 Avoid @mentioning people in commit messages and pull request descriptions(they are added to commit message by bors).
 Such messages create a lot of duplicate notification traffic during rebases.
 
-If possible, write commit messages from user's perspective:
-
-```
-# Good
-Goto definition works inside macros
-
-# Not as good
-Use original span for FileId
-```
-
-This makes it easier to prepare a changelog.
-
 ## Clippy
 
 We don't enforce Clippy.
diff --git a/docs/user/manual.adoc b/docs/user/manual.adoc
index d4121b4011..e3082d5842 100644
--- a/docs/user/manual.adoc
+++ b/docs/user/manual.adoc
@@ -218,7 +218,7 @@ The are several LSP client implementations for vim or neovim:
    * automatically install and upgrade stable/nightly releases
    * same configurations as VSCode extension, `rust-analyzer.serverPath`, `rust-analyzer.cargo.features` etc.
    * same commands too, `rust-analyzer.analyzerStatus`, `rust-analyzer.ssr` etc.
-   * inlay hints for variables and method chaining, _Neovim Only_
+   * inlay hints for method chaining support, _Neovim Only_
    * semantic highlighting is not implemented yet
 
 ==== LanguageClient-neovim


Test patch:
diff --git a/crates/assists/src/tests.rs b/crates/assists/src/tests.rs
index 21e448fb86..b41f4874a5 100644
--- a/crates/assists/src/tests.rs
+++ b/crates/assists/src/tests.rs
@@ -48,25 +48,24 @@ fn check_doc_test(assist_id: &str, before: &str, after: &str) {
     let before = db.file_text(file_id).to_string();
     let frange = FileRange { file_id, range: selection.into() };
 
-    let assist = Assist::get(&db, &AssistConfig::default(), true, frange)
+    let assist = Assist::resolved(&db, &AssistConfig::default(), frange)
         .into_iter()
-        .find(|assist| assist.id.0 == assist_id)
+        .find(|assist| assist.assist.id.0 == assist_id)
         .unwrap_or_else(|| {
             panic!(
                 "\n\nAssist is not applicable: {}\nAvailable assists: {}",
                 assist_id,
-                Assist::get(&db, &AssistConfig::default(), false, frange)
+                Assist::resolved(&db, &AssistConfig::default(), frange)
                     .into_iter()
-                    .map(|assist| assist.id.0)
+                    .map(|assist| assist.assist.id.0)
                     .collect::<Vec<_>>()
                     .join(", ")
             )
         });
 
     let actual = {
-        let source_change = assist.source_change.unwrap();
         let mut actual = before;
-        for source_file_edit in source_change.source_file_edits {
+        for source_file_edit in assist.source_change.source_file_edits {
             if source_file_edit.file_id == file_id {
                 source_file_edit.edit.apply(&mut actual)
             }
@@ -91,18 +90,18 @@ fn check(handler: Handler, before: &str, expected: ExpectedResult, assist_label:
     let sema = Semantics::new(&db);
     let config = AssistConfig::default();
     let ctx = AssistContext::new(sema, &config, frange);
-    let mut acc = Assists::new(&ctx, true);
+    let mut acc = Assists::new_resolved(&ctx);
     handler(&mut acc, &ctx);
-    let mut res = acc.finish();
+    let mut res = acc.finish_resolved();
 
     let assist = match assist_label {
-        Some(label) => res.into_iter().find(|resolved| resolved.label == label),
+        Some(label) => res.into_iter().find(|resolved| resolved.assist.label == label),
         None => res.pop(),
     };
 
     match (assist, expected) {
         (Some(assist), ExpectedResult::After(after)) => {
-            let mut source_change = assist.source_change.unwrap();
+            let mut source_change = assist.source_change;
             assert!(!source_change.source_file_edits.is_empty());
             let skip_header = source_change.source_file_edits.len() == 1
                 && source_change.file_system_edits.len() == 0;
@@ -139,7 +138,7 @@ fn check(handler: Handler, before: &str, expected: ExpectedResult, assist_label:
             assert_eq_text!(after, &buf);
         }
         (Some(assist), ExpectedResult::Target(target)) => {
-            let range = assist.target;
+            let range = assist.assist.target;
             assert_eq_text!(&text_without_caret[range], target);
         }
         (Some(_), ExpectedResult::NotApplicable) => panic!("assist should not be applicable!"),
@@ -156,11 +155,14 @@ fn assist_order_field_struct() {
     let (before_cursor_pos, before) = extract_offset(before);
     let (db, file_id) = with_single_file(&before);
     let frange = FileRange { file_id, range: TextRange::empty(before_cursor_pos) };
-    let assists = Assist::get(&db, &AssistConfig::default(), false, frange);
+    let assists = Assist::resolved(&db, &AssistConfig::default(), frange);
     let mut assists = assists.iter();
 
-    assert_eq!(assists.next().expect("expected assist").label, "Change visibility to pub(crate)");
-    assert_eq!(assists.next().expect("expected assist").label, "Add `#[derive]`");
+    assert_eq!(
+        assists.next().expect("expected assist").assist.label,
+        "Change visibility to pub(crate)"
+    );
+    assert_eq!(assists.next().expect("expected assist").assist.label, "Add `#[derive]`");
 }
 
 #[test]
@@ -176,11 +178,11 @@ fn assist_order_if_expr() {
     let (range, before) = extract_range(before);
     let (db, file_id) = with_single_file(&before);
     let frange = FileRange { file_id, range };
-    let assists = Assist::get(&db, &AssistConfig::default(), false, frange);
+    let assists = Assist::resolved(&db, &AssistConfig::default(), frange);
     let mut assists = assists.iter();
 
-    assert_eq!(assists.next().expect("expected assist").label, "Extract into variable");
-    assert_eq!(assists.next().expect("expected assist").label, "Replace with match");
+    assert_eq!(assists.next().expect("expected assist").assist.label, "Extract into variable");
+    assert_eq!(assists.next().expect("expected assist").assist.label, "Replace with match");
 }
 
 #[test]
@@ -201,27 +203,27 @@ fn assist_filter_works() {
         let mut cfg = AssistConfig::default();
         cfg.allowed = Some(vec![AssistKind::Refactor]);
 
-        let assists = Assist::get(&db, &cfg, false, frange);
+        let assists = Assist::resolved(&db, &cfg, frange);
         let mut assists = assists.iter();
 
-        assert_eq!(assists.next().expect("expected assist").label, "Extract into variable");
-        assert_eq!(assists.next().expect("expected assist").label, "Replace with match");
+        assert_eq!(assists.next().expect("expected assist").assist.label, "Extract into variable");
+        assert_eq!(assists.next().expect("expected assist").assist.label, "Replace with match");
     }
 
     {
         let mut cfg = AssistConfig::default();
         cfg.allowed = Some(vec![AssistKind::RefactorExtract]);
-        let assists = Assist::get(&db, &cfg, false, frange);
+        let assists = Assist::resolved(&db, &cfg, frange);
         assert_eq!(assists.len(), 1);
 
         let mut assists = assists.iter();
-        assert_eq!(assists.next().expect("expected assist").label, "Extract into variable");
+        assert_eq!(assists.next().expect("expected assist").assist.label, "Extract into variable");
     }
 
     {
         let mut cfg = AssistConfig::default();
         cfg.allowed = Some(vec![AssistKind::QuickFix]);
-        let assists = Assist::get(&db, &cfg, false, frange);
+        let assists = Assist::resolved(&db, &cfg, frange);
         assert!(assists.is_empty(), "All asserts but quickfixes should be filtered out");
     }
 }
diff --git a/crates/assists/src/tests/generated.rs b/crates/assists/src/tests/generated.rs
index d3dfe24e7c..e9093ec536 100644
--- a/crates/assists/src/tests/generated.rs
+++ b/crates/assists/src/tests/generated.rs
@@ -42,26 +42,26 @@ fn doctest_add_impl_default_members() {
         "add_impl_default_members",
         r#####"
 trait Trait {
-    type X;
+    Type X;
     fn foo(&self);
     fn bar(&self) {}
 }
 
 impl Trait for () {
-    type X = ();
+    Type X = ();
     fn foo(&self) {}<|>
 
 }
 "#####,
         r#####"
 trait Trait {
-    type X;
+    Type X;
     fn foo(&self);
     fn bar(&self) {}
 }
 
 impl Trait for () {
-    type X = ();
+    Type X = ();
     fn foo(&self) {}
 
     $0fn bar(&self) {}
@@ -76,7 +76,7 @@ fn doctest_add_impl_missing_members() {
         "add_impl_missing_members",
         r#####"
 trait Trait<T> {
-    type X;
+    Type X;
     fn foo(&self) -> T;
     fn bar(&self) {}
 }
@@ -87,16 +87,14 @@ impl Trait<u32> for () {<|>
 "#####,
         r#####"
 trait Trait<T> {
-    type X;
+    Type X;
     fn foo(&self) -> T;
     fn bar(&self) {}
 }
 
 impl Trait<u32> for () {
-    $0type X;
-
     fn foo(&self) -> u32 {
-        todo!()
+        ${0:todo!()}
     }
 }
 "#####,
diff --git a/crates/hir_def/src/nameres/tests/macros.rs b/crates/hir_def/src/nameres/tests/macros.rs
index e5e9e8ca16..f9bf5bc725 100644
--- a/crates/hir_def/src/nameres/tests/macros.rs
+++ b/crates/hir_def/src/nameres/tests/macros.rs
@@ -677,7 +677,7 @@ fn macro_expansion_overflow() {
         r#"
 macro_rules! a {
     ($e:expr; $($t:tt)*) => {
-        b!(static = (); $($t)*);
+        b!($($t)*);
     };
     () => {};
 }
@@ -689,7 +689,7 @@ macro_rules! b {
     () => {};
 }
 
-b! { static = #[] ();}
+b! { static = #[] (); }
 "#,
         expect![[r#"
             crate
diff --git a/crates/hir_ty/src/tests/patterns.rs b/crates/hir_ty/src/tests/patterns.rs
index 2053d8f56e..5a5f48fd05 100644
--- a/crates/hir_ty/src/tests/patterns.rs
+++ b/crates/hir_ty/src/tests/patterns.rs
@@ -774,33 +774,3 @@ fn foo(tuple: Tuple) {
         "#]],
     );
 }
-
-#[test]
-fn const_block_pattern() {
-    check_infer(
-        r#"
-struct Foo(usize);
-fn foo(foo: Foo) {
-    match foo {
-        const { Foo(15 + 32) } => {},
-        _ => {}
-    }
-}"#,
-        expect![[r#"
-            26..29 'foo': Foo
-            36..115 '{     ...   } }': ()
-            42..113 'match ...     }': ()
-            48..51 'foo': Foo
-            62..84 'const ... 32) }': Foo
-            68..84 '{ Foo(... 32) }': Foo
-            70..73 'Foo': Foo(usize) -> Foo
-            70..82 'Foo(15 + 32)': Foo
-            74..76 '15': usize
-            74..81 '15 + 32': usize
-            79..81 '32': usize
-            88..90 '{}': ()
-            100..101 '_': Foo
-            105..107 '{}': ()
-        "#]],
-    );
-}
diff --git a/crates/hir_ty/src/tests/simple.rs b/crates/hir_ty/src/tests/simple.rs
index a61282d5a7..a569223b4b 100644
--- a/crates/hir_ty/src/tests/simple.rs
+++ b/crates/hir_ty/src/tests/simple.rs
@@ -1894,7 +1894,6 @@ fn effects_smoke_test() {
             let x = unsafe { 92 };
             let y = async { async { () }.await };
             let z = try { () };
-            let w = const { 92 };
             let t = 'a: { 92 };
         }
 
@@ -1906,7 +1905,7 @@ fn effects_smoke_test() {
         }
         "#,
         expect![[r#"
-            16..162 '{     ...2 }; }': ()
+            16..136 '{     ...2 }; }': ()
             26..27 'x': i32
             30..43 'unsafe { 92 }': i32
             37..43 '{ 92 }': i32
@@ -1922,13 +1921,9 @@ fn effects_smoke_test() {
             99..109 'try { () }': {unknown}
             103..109 '{ () }': ()
             105..107 '()': ()
-            119..120 'w': i32
-            123..135 'const { 92 }': i32
-            129..135 '{ 92 }': i32
-            131..133 '92': i32
-            145..146 't': i32
-            153..159 '{ 92 }': i32
-            155..157 '92': i32
+            119..120 't': i32
+            127..133 '{ 92 }': i32
+            129..131 '92': i32
         "#]],
     )
 }
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_assoc_functions.html b/crates/ide/src/syntax_highlighting/test_data/highlight_assoc_functions.html
index 506ebe60e7..db6f32d339 100644
--- a/crates/ide/src/syntax_highlighting/test_data/highlight_assoc_functions.html
+++ b/crates/ide/src/syntax_highlighting/test_data/highlight_assoc_functions.html
@@ -4,7 +4,6 @@ body                { margin: 0; }
 pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padding: 0.4em; }
 
 .lifetime           { color: #DFAF8F; font-style: italic; }
-.label              { color: #DFAF8F; font-style: italic; }
 .comment            { color: #7F9F7F; }
 .documentation      { color: #629755; }
 .injected           { opacity: 0.65 ; }
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html b/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html
index 4dd7413ba0..4e511baa93 100644
--- a/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html
+++ b/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html
@@ -4,7 +4,6 @@ body                { margin: 0; }
 pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padding: 0.4em; }
 
 .lifetime           { color: #DFAF8F; font-style: italic; }
-.label              { color: #DFAF8F; font-style: italic; }
 .comment            { color: #7F9F7F; }
 .documentation      { color: #629755; }
 .injected           { opacity: 0.65 ; }
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_extern_crate.html b/crates/ide/src/syntax_highlighting/test_data/highlight_extern_crate.html
index ed452586ad..800d894c76 100644
--- a/crates/ide/src/syntax_highlighting/test_data/highlight_extern_crate.html
+++ b/crates/ide/src/syntax_highlighting/test_data/highlight_extern_crate.html
@@ -4,7 +4,6 @@ body                { margin: 0; }
 pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padding: 0.4em; }
 
 .lifetime           { color: #DFAF8F; font-style: italic; }
-.label              { color: #DFAF8F; font-style: italic; }
 .comment            { color: #7F9F7F; }
 .documentation      { color: #629755; }
 .injected           { opacity: 0.65 ; }
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_injection.html b/crates/ide/src/syntax_highlighting/test_data/highlight_injection.html
index 92e7dc3e4f..7f18ad297f 100644
--- a/crates/ide/src/syntax_highlighting/test_data/highlight_injection.html
+++ b/crates/ide/src/syntax_highlighting/test_data/highlight_injection.html
@@ -4,7 +4,6 @@ body                { margin: 0; }
 pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padding: 0.4em; }
 
 .lifetime           { color: #DFAF8F; font-style: italic; }
-.label              { color: #DFAF8F; font-style: italic; }
 .comment            { color: #7F9F7F; }
 .documentation      { color: #629755; }
 .injected           { opacity: 0.65 ; }
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html b/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html
index 31dad5d429..c843b5085d 100644
--- a/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html
+++ b/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html
@@ -4,7 +4,6 @@ body                { margin: 0; }
 pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padding: 0.4em; }
 
 .lifetime           { color: #DFAF8F; font-style: italic; }
-.label              { color: #DFAF8F; font-style: italic; }
 .comment            { color: #7F9F7F; }
 .documentation      { color: #629755; }
 .injected           { opacity: 0.65 ; }
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html b/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html
index e3a0aa317d..d26f485162 100644
--- a/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html
+++ b/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html
@@ -4,7 +4,6 @@ body                { margin: 0; }
 pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padding: 0.4em; }
 
 .lifetime           { color: #DFAF8F; font-style: italic; }
-.label              { color: #DFAF8F; font-style: italic; }
 .comment            { color: #7F9F7F; }
 .documentation      { color: #629755; }
 .injected           { opacity: 0.65 ; }
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlighting.html b/crates/ide/src/syntax_highlighting/test_data/highlighting.html
index 72ff9dd40e..588e86a34f 100644
--- a/crates/ide/src/syntax_highlighting/test_data/highlighting.html
+++ b/crates/ide/src/syntax_highlighting/test_data/highlighting.html
@@ -4,7 +4,6 @@ body                { margin: 0; }
 pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padding: 0.4em; }
 
 .lifetime           { color: #DFAF8F; font-style: italic; }
-.label              { color: #DFAF8F; font-style: italic; }
 .comment            { color: #7F9F7F; }
 .documentation      { color: #629755; }
 .injected           { opacity: 0.65 ; }
@@ -195,11 +194,6 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
     <span class="keyword">let</span> <span class="variable declaration">baz</span> <span class="operator">=</span> <span class="operator">-</span><span class="variable">baz</span><span class="punctuation">;</span>
 
     <span class="keyword">let</span> <span class="punctuation">_</span> <span class="operator">=</span> <span class="operator">!</span><span class="bool_literal">true</span><span class="punctuation">;</span>
-
-    <span class="label declaration">'foo</span><span class="punctuation">:</span> <span class="keyword control">loop</span> <span class="punctuation">{</span>
-        <span class="keyword control">break</span> <span class="label">'foo</span><span class="punctuation">;</span>
-        <span class="keyword control">continue</span> <span class="label">'foo</span><span class="punctuation">;</span>
-    <span class="punctuation">}</span>
 <span class="punctuation">}</span>
 
 <span class="keyword">enum</span> <span class="enum declaration">Option</span><span class="punctuation">&lt;</span><span class="type_param declaration">T</span><span class="punctuation">&gt;</span> <span class="punctuation">{</span>
diff --git a/crates/ide/src/syntax_highlighting/test_data/rainbow_highlighting.html b/crates/ide/src/syntax_highlighting/test_data/rainbow_highlighting.html
index 8b3dfa69f9..c7589605fa 100644
--- a/crates/ide/src/syntax_highlighting/test_data/rainbow_highlighting.html
+++ b/crates/ide/src/syntax_highlighting/test_data/rainbow_highlighting.html
@@ -4,7 +4,6 @@ body                { margin: 0; }
 pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padding: 0.4em; }
 
 .lifetime           { color: #DFAF8F; font-style: italic; }
-.label              { color: #DFAF8F; font-style: italic; }
 .comment            { color: #7F9F7F; }
 .documentation      { color: #629755; }
 .injected           { opacity: 0.65 ; }
diff --git a/crates/ide/src/syntax_highlighting/tests.rs b/crates/ide/src/syntax_highlighting/tests.rs
index e0df0d2b52..f53d2c3ba4 100644
--- a/crates/ide/src/syntax_highlighting/tests.rs
+++ b/crates/ide/src/syntax_highlighting/tests.rs
@@ -168,11 +168,6 @@ fn main() {
     let baz = -baz;
 
     let _ = !true;
-
-    'foo: loop {
-        break 'foo;
-        continue 'foo;
-    }
 }
 
 enum Option<T> {
diff --git a/crates/mbe/src/tests.rs b/crates/mbe/src/tests.rs
index 1d9afb4fb8..451fa1456a 100644
--- a/crates/mbe/src/tests.rs
+++ b/crates/mbe/src/tests.rs
@@ -760,18 +760,6 @@ fn test_last_expr() {
     );
 }
 
-#[test]
-fn test_expr_with_attr() {
-    parse_macro(
-        r#"
-macro_rules! m {
-    ($a:expr) => {0}
-}
-"#,
-    )
-    .assert_expand_items("m!(#[allow(a)]())", "0");
-}
-
 #[test]
 fn test_ty() {
     parse_macro(
@@ -1003,22 +991,6 @@ fn test_tt_composite2() {
     );
 }
 
-#[test]
-fn test_tt_with_composite_without_space() {
-    parse_macro(
-        r#"
-        macro_rules! foo {
-            ($ op:tt, $j:path) => (
-                0
-            )
-        }
-"#,
-    )
-    // Test macro input without any spaces
-    // See https://github.com/rust-analyzer/rust-analyzer/issues/6692
-    .assert_expand_items("foo!(==,Foo::Bool)", "0");
-}
-
 #[test]
 fn test_underscore() {
     parse_macro(
@@ -1031,42 +1003,6 @@ fn test_underscore() {
     .assert_expand_items(r#"foo! { => }"#, r#"0"#);
 }
 
-#[test]
-fn test_underscore_not_greedily() {
-    parse_macro(
-        r#"
-macro_rules! q {
-    ($($a:ident)* _) => {0};
-}
-"#,
-    )
-    // `_` overlaps with `$a:ident` but rustc matches it under the `_` token
-    .assert_expand_items(r#"q![a b c d _]"#, r#"0"#);
-
-    parse_macro(
-        r#"
-macro_rules! q {
-    ($($a:expr => $b:ident)* _ => $c:expr) => {0};
-}
-"#,
-    )
-    // `_ => ou` overlaps with `$a:expr => $b:ident` but rustc matches it under `_ => $c:expr`
-    .assert_expand_items(r#"q![a => b c => d _ => ou]"#, r#"0"#);
-}
-
-#[test]
-fn test_underscore_as_type() {
-    parse_macro(
-        r#"
-macro_rules! q {
-    ($a:ty) => {0};
-}
-"#,
-    )
-    // Underscore is a type
-    .assert_expand_items(r#"q![_]"#, r#"0"#);
-}
-
 #[test]
 fn test_vertical_bar_with_pat() {
     parse_macro(
diff --git a/crates/syntax/test_data/parser/inline/ok/0158_macro_rules_non_brace.rast b/crates/syntax/test_data/parser/inline/ok/0158_macro_rules_non_brace.rast
deleted file mode 100644
index 4a1f712aa7..0000000000
--- a/crates/syntax/test_data/parser/inline/ok/0158_macro_rules_non_brace.rast
+++ /dev/null
@@ -1,57 +0,0 @@
-SOURCE_FILE@0..74
-  MACRO_RULES@0..36
-    MACRO_RULES_KW@0..11 "macro_rules"
-    BANG@11..12 "!"
-    WHITESPACE@12..13 " "
-    NAME@13..14
-      IDENT@13..14 "m"
-    WHITESPACE@14..15 " "
-    TOKEN_TREE@15..35
-      L_PAREN@15..16 "("
-      WHITESPACE@16..17 " "
-      TOKEN_TREE@17..27
-        L_PAREN@17..18 "("
-        DOLLAR@18..19 "$"
-        IDENT@19..20 "i"
-        COLON@20..21 ":"
-        IDENT@21..26 "ident"
-        R_PAREN@26..27 ")"
-      WHITESPACE@27..28 " "
-      EQ@28..29 "="
-      R_ANGLE@29..30 ">"
-      WHITESPACE@30..31 " "
-      TOKEN_TREE@31..33
-        L_CURLY@31..32 "{"
-        R_CURLY@32..33 "}"
-      WHITESPACE@33..34 " "
-      R_PAREN@34..35 ")"
-    SEMICOLON@35..36 ";"
-  WHITESPACE@36..37 "\n"
-  MACRO_RULES@37..73
-    MACRO_RULES_KW@37..48 "macro_rules"
-    BANG@48..49 "!"
-    WHITESPACE@49..50 " "
-    NAME@50..51
-      IDENT@50..51 "m"
-    WHITESPACE@51..52 " "
-    TOKEN_TREE@52..72
-      L_BRACK@52..53 "["
-      WHITESPACE@53..54 " "
-      TOKEN_TREE@54..64
-        L_PAREN@54..55 "("
-        DOLLAR@55..56 "$"
-        IDENT@56..57 "i"
-        COLON@57..58 ":"
-        IDENT@58..63 "ident"
-        R_PAREN@63..64 ")"
-      WHITESPACE@64..65 " "
-      EQ@65..66 "="
-      R_ANGLE@66..67 ">"
-      WHITESPACE@67..68 " "
-      TOKEN_TREE@68..70
-        L_CURLY@68..69 "{"
-        R_CURLY@69..70 "}"
-      WHITESPACE@70..71 " "
-      R_BRACK@71..72 "]"
-    SEMICOLON@72..73 ";"
-  WHITESPACE@73..74 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0158_macro_rules_non_brace.rs b/crates/syntax/test_data/parser/inline/ok/0158_macro_rules_non_brace.rs
deleted file mode 100644
index 6033a28cd6..0000000000
--- a/crates/syntax/test_data/parser/inline/ok/0158_macro_rules_non_brace.rs
+++ /dev/null
@@ -1,2 +0,0 @@
-macro_rules! m ( ($i:ident) => {} );
-macro_rules! m [ ($i:ident) => {} ];