Repository: rust-analyzer/rust-analyzer
Pull request #7038 (2020-12-25 17:16:58)

Fix type typo in add_missing_impl_members doc
bors r+


Patch:
diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml
index 7b9fbe6b80..09752b817f 100644
--- a/.github/workflows/release.yaml
+++ b/.github/workflows/release.yaml
@@ -18,8 +18,6 @@ jobs:
   dist-windows:
     name: dist (Windows)
     runs-on: windows-latest
-    env:
-      RA_TARGET: x86_64-pc-windows-msvc
 
     steps:
     - name: Checkout repository
@@ -41,6 +39,8 @@ jobs:
 
     - name: Dist
       run: cargo xtask dist
+      env:
+        RA_TARGET: x86_64-pc-windows-msvc
 
     - name: Upload artifacts
       uses: actions/upload-artifact@v1
@@ -51,8 +51,6 @@ jobs:
   dist-ubuntu:
     name: dist (Ubuntu 16.04)
     runs-on: ubuntu-16.04
-    env:
-      RA_TARGET: x86_64-unknown-linux-gnu
 
     steps:
     - name: Checkout repository
@@ -73,14 +71,18 @@ jobs:
     - name: Dist
       if: github.ref == 'refs/heads/release'
       run: cargo xtask dist --client 0.2.$GITHUB_RUN_NUMBER
+      env:
+        RA_TARGET: x86_64-unknown-linux-gnu
 
     - name: Dist
       if: github.ref != 'refs/heads/release'
       run: cargo xtask dist --nightly --client 0.3.$GITHUB_RUN_NUMBER-nightly
+      env:
+        RA_TARGET: x86_64-unknown-linux-gnu
 
     - name: Nightly analysis-stats check
       if: github.ref != 'refs/heads/release'
-      run: target/${{ env.RA_TARGET }}/release/rust-analyzer analysis-stats .
+      run: ./dist/rust-analyzer-x86_64-unknown-linux-gnu analysis-stats .
 
     - name: Upload artifacts
       uses: actions/upload-artifact@v1
@@ -91,8 +93,6 @@ jobs:
   dist-macos-latest:
     name: dist (MacOS latest)
     runs-on: macos-latest
-    env:
-      RA_TARGET: x86_64-apple-darwin
 
     steps:
     - name: Checkout repository
@@ -107,6 +107,8 @@ jobs:
 
     - name: Dist
       run: cargo xtask dist
+      env:
+        RA_TARGET: x86_64-apple-darwin
 
     - name: Upload artifacts
       uses: actions/upload-artifact@v1
@@ -117,8 +119,6 @@ jobs:
   dist-macos-11:
     name: dist (MacOS 11.0)
     runs-on: macos-11.0
-    env:
-      RA_TARGET: aarch64-apple-darwin
 
     steps:
     - name: Checkout repository
@@ -134,6 +134,8 @@ jobs:
 
     - name: Dist
       run: cargo xtask dist
+      env:
+        RA_TARGET: aarch64-apple-darwin
 
     - name: Upload artifacts
       uses: actions/upload-artifact@v1
diff --git a/Cargo.lock b/Cargo.lock
index fd04ec3c52..fbb79e01fc 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"
@@ -1838,9 +1827,9 @@ checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c"
 
 [[package]]
 name = "ungrammar"
-version = "1.5.0"
+version = "1.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c11bffada52edc8f2a56160b286ea4640acf90ffcb21bded361ccb8ed43a1457"
+checksum = "68951379f3ced25754472ca5addbf74d7dab58c9818f49290a3d8caa3ab44fb7"
 
 [[package]]
 name = "unicase"
diff --git a/crates/assists/src/handlers/add_missing_impl_members.rs b/crates/assists/src/handlers/add_missing_impl_members.rs
index e413505d3e..7df05b8412 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,14 +27,16 @@ 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 {
-//         ${0:todo!()}
+//         todo!()
 //     }
 // }
 // ```
@@ -54,13 +56,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) {}<|>
 //
 // }
@@ -68,13 +70,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/handlers/extract_module_to_file.rs b/crates/assists/src/handlers/extract_module_to_file.rs
index 50bf67ef77..5fc190fa67 100644
--- a/crates/assists/src/handlers/extract_module_to_file.rs
+++ b/crates/assists/src/handlers/extract_module_to_file.rs
@@ -1,5 +1,5 @@
 use ast::edit::IndentLevel;
-use ide_db::base_db::AnchoredPathBuf;
+use ide_db::base_db::{AnchoredPathBuf, SourceDatabaseExt};
 use syntax::{
     ast::{self, edit::AstNodeEdit, NameOwner},
     AstNode,
@@ -21,44 +21,43 @@ use crate::{AssistContext, AssistId, AssistKind, Assists};
 // mod foo;
 // ```
 pub(crate) fn extract_module_to_file(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
+    let assist_id = AssistId("extract_module_to_file", AssistKind::RefactorExtract);
+    let assist_label = "Extract module to file";
+    let db = ctx.db();
     let module_ast = ctx.find_node_at_offset::<ast::Module>()?;
-    let module_name = module_ast.name()?;
-
-    let module_def = ctx.sema.to_def(&module_ast)?;
-    let parent_module = module_def.parent(ctx.db())?;
-
     let module_items = module_ast.item_list()?;
+    let dedent_module_items_text = module_items.dedent(IndentLevel(1)).to_string();
+    let module_name = module_ast.name()?;
     let target = module_ast.syntax().text_range();
     let anchor_file_id = ctx.frange.file_id;
+    let sr = db.file_source_root(anchor_file_id);
+    let sr = db.source_root(sr);
+    let file_path = sr.path_for_file(&anchor_file_id)?;
+    let (file_name, file_ext) = file_path.name_and_extension()?;
+    acc.add(assist_id, assist_label, target, |builder| {
+        builder.replace(target, format!("mod {};", module_name));
+        let path = if is_main_or_lib(file_name) {
+            format!("./{}.{}", module_name, file_ext.unwrap())
+        } else {
+            format!("./{}/{}.{}", file_name, module_name, file_ext.unwrap())
+        };
+        let dst = AnchoredPathBuf { anchor: anchor_file_id, path };
+        let contents = update_module_items_string(dedent_module_items_text);
+        builder.create_file(dst, contents);
+    })
+}
+fn is_main_or_lib(file_name: &str) -> bool {
+    file_name == "main".to_string() || file_name == "lib".to_string()
+}
+fn update_module_items_string(items_str: String) -> String {
+    let mut items_string_lines: Vec<&str> = items_str.lines().collect();
+    items_string_lines.pop(); // Delete last line
+    items_string_lines.reverse();
+    items_string_lines.pop(); // Delete first line
+    items_string_lines.reverse();
 
-    acc.add(
-        AssistId("extract_module_to_file", AssistKind::RefactorExtract),
-        "Extract module to file",
-        target,
-        |builder| {
-            let path = {
-                let dir = match parent_module.name(ctx.db()) {
-                    Some(name) if !parent_module.is_mod_rs(ctx.db()) => format!("{}/", name),
-                    _ => String::new(),
-                };
-                format!("./{}{}.rs", dir, module_name)
-            };
-            let contents = {
-                let items = module_items.dedent(IndentLevel(1)).to_string();
-                let mut items =
-                    items.trim_start_matches('{').trim_end_matches('}').trim().to_string();
-                if !items.is_empty() {
-                    items.push('\n');
-                }
-                items
-            };
-
-            builder.replace(target, format!("mod {};", module_name));
-
-            let dst = AnchoredPathBuf { anchor: anchor_file_id, path };
-            builder.create_file(dst, contents);
-        },
-    )
+    let string = items_string_lines.join("\n");
+    format!("{}", string)
 }
 
 #[cfg(test)]
@@ -68,66 +67,104 @@ mod tests {
     use super::*;
 
     #[test]
-    fn extract_from_root() {
+    fn extract_module_to_file_with_basic_module() {
         check_assist(
             extract_module_to_file,
             r#"
+//- /foo.rs crate:foo
 mod tests {<|>
     #[test] fn t() {}
 }
 "#,
             r#"
-//- /main.rs
+//- /foo.rs
 mod tests;
-//- /tests.rs
-#[test] fn t() {}
-"#,
-        );
+//- /foo/tests.rs
+#[test] fn t() {}"#,
+        )
     }
 
     #[test]
-    fn extract_from_submodule() {
+    fn extract_module_to_file_with_file_path() {
         check_assist(
             extract_module_to_file,
             r#"
-//- /main.rs
-mod submod;
-//- /submod.rs
-mod inner<|> {
-    fn f() {}
+//- /src/foo.rs crate:foo
+mod bar {<|>
+    fn f() {
+
+    }
+}
+fn main() {
+    println!("Hello, world!");
 }
-fn g() {}
 "#,
             r#"
-//- /submod.rs
-mod inner;
-fn g() {}
-//- /submod/inner.rs
-fn f() {}
-"#,
-        );
+//- /src/foo.rs
+mod bar;
+fn main() {
+    println!("Hello, world!");
+}
+//- /src/foo/bar.rs
+fn f() {
+
+}"#,
+        )
     }
 
     #[test]
-    fn extract_from_mod_rs() {
+    fn extract_module_to_file_with_main_filw() {
         check_assist(
             extract_module_to_file,
             r#"
 //- /main.rs
-mod submodule;
-//- /submodule/mod.rs
-mod inner<|> {
-    fn f() {}
+mod foo {<|>
+    fn f() {
+
+    }
+}
+fn main() {
+    println!("Hello, world!");
 }
-fn g() {}
 "#,
             r#"
-//- /submodule/mod.rs
-mod inner;
-fn g() {}
-//- /submodule/inner.rs
-fn f() {}
+//- /main.rs
+mod foo;
+fn main() {
+    println!("Hello, world!");
+}
+//- /foo.rs
+fn f() {
+
+}"#,
+        )
+    }
+
+    #[test]
+    fn extract_module_to_file_with_lib_file() {
+        check_assist(
+            extract_module_to_file,
+            r#"
+//- /lib.rs
+mod foo {<|>
+    fn f() {
+
+    }
+}
+fn main() {
+    println!("Hello, world!");
+}
 "#,
-        );
+            r#"
+//- /lib.rs
+mod foo;
+fn main() {
+    println!("Hello, world!");
+}
+//- /foo.rs
+fn f() {
+
+}"#,
+        )
     }
 }
diff --git a/crates/completion/src/completions.rs b/crates/completion/src/completions.rs
index d9fe134855..1ef6b5f48f 100644
--- a/crates/completion/src/completions.rs
+++ b/crates/completion/src/completions.rs
@@ -19,14 +19,9 @@ use hir::{ModPath, ScopeDef, Type};
 use crate::{
     item::Builder,
     render::{
-        const_::render_const,
-        enum_variant::render_variant,
-        function::render_fn,
-        macro_::render_macro,
-        pattern::{render_struct_pat, render_variant_pat},
-        render_field, render_resolution, render_tuple_field,
-        type_alias::render_type_alias,
-        RenderContext,
+        const_::render_const, enum_variant::render_variant, function::render_fn,
+        macro_::render_macro, render_field, render_resolution, render_tuple_field,
+        type_alias::render_type_alias, RenderContext,
     },
     CompletionContext, CompletionItem,
 };
@@ -110,28 +105,6 @@ impl Completions {
         self.add(item)
     }
 
-    pub(crate) fn add_variant_pat(
-        &mut self,
-        ctx: &CompletionContext,
-        variant: hir::Variant,
-        local_name: Option<hir::Name>,
-    ) {
-        if let Some(item) = render_variant_pat(RenderContext::new(ctx), variant, local_name) {
-            self.add(item);
-        }
-    }
-
-    pub(crate) fn add_struct_pat(
-        &mut self,
-        ctx: &CompletionContext,
-        strukt: hir::Struct,
-        local_name: Option<hir::Name>,
-    ) {
-        if let Some(item) = render_struct_pat(RenderContext::new(ctx), strukt, local_name) {
-            self.add(item);
-        }
-    }
-
     pub(crate) fn add_const(&mut self, ctx: &CompletionContext, constant: hir::Const) {
         if let Some(item) = render_const(RenderContext::new(ctx), constant) {
             self.add(item);
diff --git a/crates/completion/src/completions/pattern.rs b/crates/completion/src/completions/pattern.rs
index eee31098d1..4d56731ec6 100644
--- a/crates/completion/src/completions/pattern.rs
+++ b/crates/completion/src/completions/pattern.rs
@@ -2,9 +2,9 @@
 
 use crate::{CompletionContext, Completions};
 
-/// Completes constants and paths in patterns.
+/// Completes constats and paths in patterns.
 pub(crate) fn complete_pattern(acc: &mut Completions, ctx: &CompletionContext) {
-    if !(ctx.is_pat_binding_or_const || ctx.is_irrefutable_pat_binding) {
+    if !(ctx.is_pat_binding_or_const || ctx.is_irrefutable_let_pat_binding) {
         return;
     }
     if ctx.record_pat_syntax.is_some() {
@@ -15,21 +15,20 @@ pub(crate) fn complete_pattern(acc: &mut Completions, ctx: &CompletionContext) {
     // suggest variants + auto-imports
     ctx.scope.process_all_names(&mut |name, res| {
         let add_resolution = match &res {
-            hir::ScopeDef::ModuleDef(def) => match def {
-                hir::ModuleDef::Adt(hir::Adt::Struct(strukt)) => {
-                    acc.add_struct_pat(ctx, strukt.clone(), Some(name.clone()));
-                    true
+            hir::ScopeDef::ModuleDef(def) => {
+                if ctx.is_irrefutable_let_pat_binding {
+                    matches!(def, hir::ModuleDef::Adt(hir::Adt::Struct(_)))
+                } else {
+                    matches!(
+                        def,
+                        hir::ModuleDef::Adt(hir::Adt::Enum(..))
+                            | hir::ModuleDef::Adt(hir::Adt::Struct(..))
+                            | hir::ModuleDef::Variant(..)
+                            | hir::ModuleDef::Const(..)
+                            | hir::ModuleDef::Module(..)
+                    )
                 }
-                hir::ModuleDef::Variant(variant) if !ctx.is_irrefutable_pat_binding => {
-                    acc.add_variant_pat(ctx, variant.clone(), Some(name.clone()));
-                    true
-                }
-                hir::ModuleDef::Adt(hir::Adt::Enum(..))
-                | hir::ModuleDef::Variant(..)
-                | hir::ModuleDef::Const(..)
-                | hir::ModuleDef::Module(..) => !ctx.is_irrefutable_pat_binding,
-                _ => false,
-            },
+            }
             hir::ScopeDef::MacroDef(_) => true,
             _ => false,
         };
@@ -43,21 +42,13 @@ pub(crate) fn complete_pattern(acc: &mut Completions, ctx: &CompletionContext) {
 mod tests {
     use expect_test::{expect, Expect};
 
-    use crate::{
-        test_utils::{check_edit, completion_list},
-        CompletionKind,
-    };
+    use crate::{test_utils::completion_list, CompletionKind};
 
     fn check(ra_fixture: &str, expect: Expect) {
         let actual = completion_list(ra_fixture, CompletionKind::Reference);
         expect.assert_eq(&actual)
     }
 
-    fn check_snippet(ra_fixture: &str, expect: Expect) {
-        let actual = completion_list(ra_fixture, CompletionKind::Snippet);
-        expect.assert_eq(&actual)
-    }
-
     #[test]
     fn completes_enum_variants_and_modules() {
         check(
@@ -78,7 +69,7 @@ fn foo() {
                 en E
                 ct Z
                 st Bar
-                ev X
+                ev X   ()
                 md m
             "#]],
         );
@@ -123,139 +114,4 @@ fn foo() {
             "#]],
         );
     }
-
-    #[test]
-    fn completes_in_param() {
-        check(
-            r#"
-enum E { X }
-
-static FOO: E = E::X;
-struct Bar { f: u32 }
-
-fn foo(<|>) {
-}
-"#,
-            expect![[r#"
-                st Bar
-            "#]],
-        );
-    }
-
-    #[test]
-    fn completes_pat_in_let() {
-        check_snippet(
-            r#"
-struct Bar { f: u32 }
-
-fn foo() {
-   let <|>
-}
-"#,
-            expect![[r#"
-                bn Bar Bar { f$1 }$0
-            "#]],
-        );
-    }
-
-    #[test]
-    fn completes_param_pattern() {
-        check_snippet(
-            r#"
-struct Foo { bar: String, baz: String }
-struct Bar(String, String);
-struct Baz;
-fn outer(<|>) {}
-"#,
-            expect![[r#"
-                bn Foo Foo { bar$1, baz$2 }: Foo$0
-                bn Bar Bar($1, $2): Bar$0
-            "#]],
-        )
-    }
-
-    #[test]
-    fn completes_let_pattern() {
-        check_snippet(
-            r#"
-struct Foo { bar: String, baz: String }
-struct Bar(String, String);
-struct Baz;
-fn outer() {
-    let <|>
-}
-"#,
-            expect![[r#"
-                bn Foo Foo { bar$1, baz$2 }$0
-                bn Bar Bar($1, $2)$0
-            "#]],
-        )
-    }
-
-    #[test]
-    fn completes_refutable_pattern() {
-        check_snippet(
-            r#"
-struct Foo { bar: i32, baz: i32 }
-struct Bar(String, String);
-struct Baz;
-fn outer() {
-    match () {
-        <|>
-    }
-}
-"#,
-            expect![[r#"
-                bn Foo Foo { bar$1, baz$2 }$0
-                bn Bar Bar($1, $2)$0
-            "#]],
-        )
-    }
-
-    #[test]
-    fn omits_private_fields_pat() {
-        check_snippet(
-            r#"
-mod foo {
-    pub struct Foo { pub bar: i32, baz: i32 }
-    pub struct Bar(pub String, String);
-    pub struct Invisible(String, String);
-}
-use foo::*;
-
-fn outer() {
-    match () {
-        <|>
-    }
-}
-"#,
-            expect![[r#"
-                bn Foo Foo { bar$1, .. }$0
-                bn Bar Bar($1, ..)$0
-            "#]],
-        )
-    }
-
-    #[test]
-    fn only_shows_ident_completion() {
-        check_edit(
-            "Foo",
-            r#"
-struct Foo(i32);
-fn main() {
-    match Foo(92) {
-        <|>(92) => (),
-    }
-}
-"#,
-            r#"
-struct Foo(i32);
-fn main() {
-    match Foo(92) {
-        Foo(92) => (),
-    }
-}
-"#,
-        );
-    }
 }
diff --git a/crates/completion/src/completions/qualified_path.rs b/crates/completion/src/completions/qualified_path.rs
index 882c4dcbce..1300f00b2f 100644
--- a/crates/completion/src/completions/qualified_path.rs
+++ b/crates/completion/src/completions/qualified_path.rs
@@ -118,12 +118,6 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
                     _ => return,
                 };
 
-                if let Some(Adt::Enum(e)) = ty.as_adt() {
-                    for variant in e.variants(ctx.db) {
-                        acc.add_enum_variant(ctx, variant, None);
-                    }
-                }
-
                 let traits_in_scope = ctx.scope.traits_in_scope();
                 let mut seen = FxHashSet::default();
                 ty.iterate_path_candidates(ctx.db, krate, &traits_in_scope, None, |_ty, item| {
@@ -758,27 +752,4 @@ fn main() {
             "#]],
         );
     }
-
-    #[test]
-    fn completes_self_enum() {
-        check(
-            r#"
-enum Foo {
-    Bar,
-    Baz,
-}
-
-impl Foo {
-    fn foo(self) {
-        Self::<|>
-    }
-}
-"#,
-            expect![[r#"
-                ev Bar    ()
-                ev Baz    ()
-                me foo(…) fn foo(self)
-            "#]],
-        );
-    }
 }
diff --git a/crates/completion/src/completions/unqualified_path.rs b/crates/completion/src/completions/unqualified_path.rs
index d098497520..099ffb4d48 100644
--- a/crates/completion/src/completions/unqualified_path.rs
+++ b/crates/completion/src/completions/unqualified_path.rs
@@ -1,7 +1,5 @@
 //! Completion of names from the current scope, e.g. locals and imported items.
 
-use std::iter;
-
 use either::Either;
 use hir::{Adt, ModPath, ModuleDef, ScopeDef, Type};
 use ide_db::helpers::insert_use::ImportScope;
@@ -52,9 +50,7 @@ pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionC
 }
 
 fn complete_enum_variants(acc: &mut Completions, ctx: &CompletionContext, ty: &Type) {
-    if let Some(Adt::Enum(enum_data)) =
-        iter::successors(Some(ty.clone()), |ty| ty.remove_ref()).last().and_then(|ty| ty.as_adt())
-    {
+    if let Some(Adt::Enum(enum_data)) = ty.as_adt() {
         let variants = enum_data.variants(ctx.db);
 
         let module = if let Some(module) = ctx.scope.module() {
@@ -705,7 +701,6 @@ fn main() { <|> }
             "#]],
         );
     }
-
     #[test]
     fn completes_enum_variant_matcharm() {
         check(
@@ -726,26 +721,6 @@ fn main() {
         )
     }
 
-    #[test]
-    fn completes_enum_variant_matcharm_ref() {
-        check(
-            r#"
-enum Foo { Bar, Baz, Quux }
-
-fn main() {
-    let foo = Foo::Quux;
-    match &foo { Qu<|> }
-}
-"#,
-            expect![[r#"
-                ev Foo::Bar  ()
-                ev Foo::Baz  ()
-                ev Foo::Quux ()
-                en Foo
-            "#]],
-        )
-    }
-
     #[test]
     fn completes_enum_variant_iflet() {
         check(
diff --git a/crates/completion/src/context.rs b/crates/completion/src/context.rs
index 41de324d8d..5cd11cf775 100644
--- a/crates/completion/src/context.rs
+++ b/crates/completion/src/context.rs
@@ -51,7 +51,7 @@ pub(crate) struct CompletionContext<'a> {
     /// If a name-binding or reference to a const in a pattern.
     /// Irrefutable patterns (like let) are excluded.
     pub(super) is_pat_binding_or_const: bool,
-    pub(super) is_irrefutable_pat_binding: bool,
+    pub(super) is_irrefutable_let_pat_binding: bool,
     /// A single-indent path, like `foo`. `::foo` should not be considered a trivial path.
     pub(super) is_trivial_path: bool,
     /// If not a trivial path, the prefix (qualifier).
@@ -147,7 +147,7 @@ impl<'a> CompletionContext<'a> {
             active_parameter: ActiveParameter::at(db, position),
             is_param: false,
             is_pat_binding_or_const: false,
-            is_irrefutable_pat_binding: false,
+            is_irrefutable_let_pat_binding: false,
             is_trivial_path: false,
             path_qual: None,
             after_if: false,
@@ -327,19 +327,14 @@ impl<'a> CompletionContext<'a> {
                 if bind_pat.syntax().parent().and_then(ast::RecordPatFieldList::cast).is_some() {
                     self.is_pat_binding_or_const = false;
                 }
-                if let Some(Some(pat)) = bind_pat.syntax().ancestors().find_map(|node| {
-                    match_ast! {
-                        match node {
-                            ast::LetStmt(it) => Some(it.pat()),
-                            ast::Param(it) => Some(it.pat()),
-                            _ => None,
+                if let Some(let_stmt) = bind_pat.syntax().ancestors().find_map(ast::LetStmt::cast) {
+                    if let Some(pat) = let_stmt.pat() {
+                        if pat.syntax().text_range().contains_range(bind_pat.syntax().text_range())
+                        {
+                            self.is_pat_binding_or_const = false;
+                            self.is_irrefutable_let_pat_binding = true;
                         }
                     }
-                }) {
-                    if pat.syntax().text_range().contains_range(bind_pat.syntax().text_range()) {
-                        self.is_pat_binding_or_const = false;
-                        self.is_irrefutable_pat_binding = true;
-                    }
                 }
             }
             if is_node::<ast::Param>(name.syntax()) {
diff --git a/crates/completion/src/render.rs b/crates/completion/src/render.rs
index 1ba7201a13..1092a48256 100644
--- a/crates/completion/src/render.rs
+++ b/crates/completion/src/render.rs
@@ -5,7 +5,6 @@ pub(crate) mod macro_;
 pub(crate) mod function;
 pub(crate) mod enum_variant;
 pub(crate) mod const_;
-pub(crate) mod pattern;
 pub(crate) mod type_alias;
 
 mod builder_ext;
@@ -160,12 +159,6 @@ impl<'a> Render<'a> {
                 let item = render_fn(self.ctx, import_to_add, Some(local_name), *func);
                 return Some(item);
             }
-            ScopeDef::ModuleDef(Variant(_))
-                if self.ctx.completion.is_pat_binding_or_const
-                    | self.ctx.completion.is_irrefutable_pat_binding =>
-            {
-                CompletionItemKind::EnumVariant
-            }
             ScopeDef::ModuleDef(Variant(var)) => {
                 let item = render_variant(self.ctx, import_to_add, Some(local_name), *var, None);
                 return Some(item);
diff --git a/crates/completion/src/render/builder_ext.rs b/crates/completion/src/render/builder_ext.rs
index d053a988bc..ce8718bd54 100644
--- a/crates/completion/src/render/builder_ext.rs
+++ b/crates/completion/src/render/builder_ext.rs
@@ -34,6 +34,7 @@ impl Builder {
             return false;
         }
         if ctx.is_pattern_call {
+            mark::hit!(dont_duplicate_pattern_parens);
             return false;
         }
         if ctx.is_call {
diff --git a/crates/completion/src/render/enum_variant.rs b/crates/completion/src/render/enum_variant.rs
index 732e139eca..7176fd9b3d 100644
--- a/crates/completion/src/render/enum_variant.rs
+++ b/crates/completion/src/render/enum_variant.rs
@@ -124,6 +124,51 @@ use Option::*;
 fn main() -> Option<i32> {
     Some($0)
 }
+"#,
+        );
+        check_edit(
+            "Some",
+            r#"
+enum Option<T> { Some(T), None }
+use Option::*;
+fn main(value: Option<i32>) {
+    match value {
+        Som<|>
+    }
+}
+"#,
+            r#"
+enum Option<T> { Some(T), None }
+use Option::*;
+fn main(value: Option<i32>) {
+    match value {
+        Some($0)
+    }
+}
+"#,
+        );
+    }
+
+    #[test]
+    fn dont_duplicate_pattern_parens() {
+        mark::check!(dont_duplicate_pattern_parens);
+        check_edit(
+            "Var",
+            r#"
+enum E { Var(i32) }
+fn main() {
+    match E::Var(92) {
+        E::<|>(92) => (),
+    }
+}
+"#,
+            r#"
+enum E { Var(i32) }
+fn main() {
+    match E::Var(92) {
+        E::Var(92) => (),
+    }
+}
 "#,
         );
     }
diff --git a/crates/completion/src/render/pattern.rs b/crates/completion/src/render/pattern.rs
deleted file mode 100644
index a3b6a3cac7..0000000000
--- a/crates/completion/src/render/pattern.rs
+++ /dev/null
@@ -1,148 +0,0 @@
-//! Renderer for patterns.
-
-use hir::{db::HirDatabase, HasAttrs, HasVisibility, Name, StructKind};
-use itertools::Itertools;
-
-use crate::{
-    config::SnippetCap, item::CompletionKind, render::RenderContext, CompletionItem,
-    CompletionItemKind,
-};
-
-fn visible_fields(
-    ctx: &RenderContext<'_>,
-    fields: &[hir::Field],
-    item: impl HasAttrs,
-) -> Option<(Vec<hir::Field>, bool)> {
-    let module = ctx.completion.scope.module()?;
-    let n_fields = fields.len();
-    let fields = fields
-        .into_iter()
-        .filter(|field| field.is_visible_from(ctx.db(), module))
-        .copied()
-        .collect::<Vec<_>>();
-
-    let fields_omitted =
-        n_fields - fields.len() > 0 || item.attrs(ctx.db()).by_key("non_exhaustive").exists();
-    Some((fields, fields_omitted))
-}
-
-pub(crate) fn render_struct_pat(
-    ctx: RenderContext<'_>,
-    strukt: hir::Struct,
-    local_name: Option<Name>,
-) -> Option<CompletionItem> {
-    let _p = profile::span("render_struct_pat");
-
-    let fields = strukt.fields(ctx.db());
-    let (visible_fields, fields_omitted) = visible_fields(&ctx, &fields, strukt)?;
-
-    if visible_fields.is_empty() {
-        // Matching a struct without matching its fields is pointless, unlike matching a Variant without its fields
-        return None;
-    }
-
-    let name = local_name.unwrap_or_else(|| strukt.name(ctx.db())).to_string();
-    let pat = render_pat(&ctx, &name, strukt.kind(ctx.db()), &visible_fields, fields_omitted)?;
-
-    Some(build_completion(ctx, name, pat, strukt))
-}
-
-pub(crate) fn render_variant_pat(
-    ctx: RenderContext<'_>,
-    variant: hir::Variant,
-    local_name: Option<Name>,
-) -> Option<CompletionItem> {
-    let _p = profile::span("render_variant_pat");
-
-    let fields = variant.fields(ctx.db());
-    let (visible_fields, fields_omitted) = visible_fields(&ctx, &fields, variant)?;
-
-    let name = local_name.unwrap_or_else(|| variant.name(ctx.db())).to_string();
-    let pat = render_pat(&ctx, &name, variant.kind(ctx.db()), &visible_fields, fields_omitted)?;
-
-    Some(build_completion(ctx, name, pat, variant))
-}
-
-fn build_completion(
-    ctx: RenderContext<'_>,
-    name: String,
-    pat: String,
-    item: impl HasAttrs + Copy,
-) -> CompletionItem {
-    let completion = CompletionItem::new(CompletionKind::Snippet, ctx.source_range(), name)
-        .kind(CompletionItemKind::Binding)
-        .set_documentation(ctx.docs(item))
-        .set_deprecated(ctx.is_deprecated(item))
-        .detail(&pat);
-    let completion = if let Some(snippet_cap) = ctx.snippet_cap() {
-        completion.insert_snippet(snippet_cap, pat)
-    } else {
-        completion.insert_text(pat)
-    };
-    completion.build()
-}
-
-fn render_pat(
-    ctx: &RenderContext<'_>,
-    name: &str,
-    kind: StructKind,
-    fields: &[hir::Field],
-    fields_omitted: bool,
-) -> Option<String> {
-    let mut pat = match kind {
-        StructKind::Tuple if ctx.snippet_cap().is_some() => {
-            render_tuple_as_pat(&fields, &name, fields_omitted)
-        }
-        StructKind::Record => {
-            render_record_as_pat(ctx.db(), ctx.snippet_cap(), &fields, &name, fields_omitted)
-        }
-        _ => return None,
-    };
-
-    if ctx.completion.is_param {
-        pat.push(':');
-        pat.push(' ');
-        pat.push_str(&name);
-    }
-    if ctx.snippet_cap().is_some() {
-        pat.push_str("$0");
-    }
-    Some(pat)
-}
-
-fn render_record_as_pat(
-    db: &dyn HirDatabase,
-    snippet_cap: Option<SnippetCap>,
-    fields: &[hir::Field],
-    name: &str,
-    fields_omitted: bool,
-) -> String {
-    let fields = fields.iter();
-    if snippet_cap.is_some() {
-        format!(
-            "{name} {{ {}{} }}",
-            fields
-                .enumerate()
-                .map(|(idx, field)| format!("{}${}", field.name(db), idx + 1))
-                .format(", "),
-            if fields_omitted { ", .." } else { "" },
-            name = name
-        )
-    } else {
-        format!(
-            "{name} {{ {}{} }}",
-            fields.map(|field| field.name(db)).format(", "),
-            if fields_omitted { ", .." } else { "" },
-            name = name
-        )
-    }
-}
-
-fn render_tuple_as_pat(fields: &[hir::Field], name: &str, fields_omitted: bool) -> String {
-    format!(
-        "{name}({}{})",
-        fields.iter().enumerate().map(|(idx, _)| format!("${}", idx + 1)).format(", "),
-        if fields_omitted { ", .." } else { "" },
-        name = name
-    )
-}
diff --git a/crates/hir/src/code_model.rs b/crates/hir/src/code_model.rs
index b7ded34788..73ca6ba9f4 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);
-                }
+                _ => (),
             }
         }
 
@@ -511,10 +511,6 @@ impl Struct {
         db.struct_data(self.id).repr.clone()
     }
 
-    pub fn kind(self, db: &dyn HirDatabase) -> StructKind {
-        self.variant_data(db).kind()
-    }
-
     fn variant_data(self, db: &dyn HirDatabase) -> Arc<VariantData> {
         db.struct_data(self.id).variant_data.clone()
     }
@@ -1205,34 +1201,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..0f404be1b7 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,14 +932,6 @@ 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,
         };
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_def/src/nameres/mod_resolution.rs b/crates/hir_def/src/nameres/mod_resolution.rs
index af32624396..b4ccd4488b 100644
--- a/crates/hir_def/src/nameres/mod_resolution.rs
+++ b/crates/hir_def/src/nameres/mod_resolution.rs
@@ -79,7 +79,7 @@ impl ModDir {
         for candidate in candidate_files.iter() {
             let path = AnchoredPath { anchor: file_id, path: candidate.as_str() };
             if let Some(file_id) = db.resolve_path(path) {
-                let is_mod_rs = candidate.ends_with("/mod.rs");
+                let is_mod_rs = candidate.ends_with("mod.rs");
 
                 let (dir_path, root_non_dir_owner) = if is_mod_rs || attr_path.is_some() {
                     (DirPath::empty(), false)
diff --git a/crates/hir_expand/src/builtin_macro.rs b/crates/hir_expand/src/builtin_macro.rs
index 6382521fbb..dddbbcdac4 100644
--- a/crates/hir_expand/src/builtin_macro.rs
+++ b/crates/hir_expand/src/builtin_macro.rs
@@ -563,7 +563,6 @@ mod tests {
 
                 let args = macro_call.token_tree().unwrap();
                 let parsed_args = mbe::ast_to_token_tree(&args).unwrap().0;
-                let call_id = AstId::new(file_id.into(), ast_id_map.ast_id(&macro_call));
 
                 let arg_id = db.intern_eager_expansion({
                     EagerCallLoc {
@@ -571,7 +570,7 @@ mod tests {
                         fragment: FragmentKind::Expr,
                         subtree: Arc::new(parsed_args.clone()),
                         krate,
-                        call: call_id,
+                        file_id: file_id.into(),
                     }
                 });
 
@@ -581,7 +580,7 @@ mod tests {
                     fragment,
                     subtree: Arc::new(subtree),
                     krate,
-                    call: call_id,
+                    file_id: file_id.into(),
                 };
 
                 let id: MacroCallId = db.intern_eager_expansion(eager).into();
diff --git a/crates/hir_expand/src/db.rs b/crates/hir_expand/src/db.rs
index 077de37270..4477d867f7 100644
--- a/crates/hir_expand/src/db.rs
+++ b/crates/hir_expand/src/db.rs
@@ -5,7 +5,7 @@ use std::sync::Arc;
 use base_db::{salsa, SourceDatabase};
 use mbe::{ExpandError, ExpandResult, MacroRules};
 use parser::FragmentKind;
-use syntax::{algo::diff, ast::NameOwner, AstNode, GreenNode, Parse, SyntaxKind::*, SyntaxNode};
+use syntax::{algo::diff, AstNode, GreenNode, Parse, SyntaxKind::*, SyntaxNode};
 
 use crate::{
     ast_id_map::AstIdMap, BuiltinDeriveExpander, BuiltinFnLikeExpander, EagerCallLoc, EagerMacroId,
@@ -129,11 +129,11 @@ fn ast_id_map(db: &dyn AstDatabase, file_id: HirFileId) -> Arc<AstIdMap> {
 fn macro_def(db: &dyn AstDatabase, id: MacroDefId) -> Option<Arc<(TokenExpander, mbe::TokenMap)>> {
     match id.kind {
         MacroDefKind::Declarative => {
-            let macro_rules = match id.ast_id?.to_node(db) {
+            let macro_call = match id.ast_id?.to_node(db) {
                 syntax::ast::Macro::MacroRules(mac) => mac,
                 syntax::ast::Macro::MacroDef(_) => return None,
             };
-            let arg = macro_rules.token_tree()?;
+            let arg = macro_call.token_tree()?;
             let (tt, tmap) = mbe::ast_to_token_tree(&arg).or_else(|| {
                 log::warn!("fail on macro_def to token tree: {:#?}", arg);
                 None
@@ -141,8 +141,7 @@ fn macro_def(db: &dyn AstDatabase, id: MacroDefId) -> Option<Arc<(TokenExpander,
             let rules = match MacroRules::parse(&tt) {
                 Ok(it) => it,
                 Err(err) => {
-                    let name = macro_rules.name().map(|n| n.to_string()).unwrap_or_default();
-                    log::warn!("fail on macro_def parse ({}): {:?} {:#?}", name, err, tt);
+                    log::warn!("fail on macro_def parse: error: {:#?} {:#?}", err, tt);
                     return None;
                 }
             };
diff --git a/crates/hir_expand/src/eager.rs b/crates/hir_expand/src/eager.rs
index 6354b090d8..0229a836ec 100644
--- a/crates/hir_expand/src/eager.rs
+++ b/crates/hir_expand/src/eager.rs
@@ -110,9 +110,6 @@ pub fn expand_eager_macro(
         || err("malformed macro invocation"),
     )?;
 
-    let ast_map = db.ast_id_map(macro_call.file_id);
-    let call_id = InFile::new(macro_call.file_id, ast_map.ast_id(&macro_call.value));
-
     // Note:
     // When `lazy_expand` is called, its *parent* file must be already exists.
     // Here we store an eager macro id for the argument expanded subtree here
@@ -123,7 +120,7 @@ pub fn expand_eager_macro(
             fragment: FragmentKind::Expr,
             subtree: Arc::new(parsed_args.clone()),
             krate,
-            call: call_id,
+            file_id: macro_call.file_id,
         }
     });
     let arg_file_id: MacroCallId = arg_id.into();
@@ -144,8 +141,13 @@ pub fn expand_eager_macro(
         let res = eager.expand(db, arg_id, &subtree);
 
         let (subtree, fragment) = diagnostic_sink.expand_result_option(res)?;
-        let eager =
-            EagerCallLoc { def, fragment, subtree: Arc::new(subtree), krate, call: call_id };
+        let eager = EagerCallLoc {
+            def,
+            fragment,
+            subtree: Arc::new(subtree),
+            krate,
+            file_id: macro_call.file_id,
+        };
 
         Ok(db.intern_eager_expansion(eager))
     } else {
diff --git a/crates/hir_expand/src/lib.rs b/crates/hir_expand/src/lib.rs
index 3fa1b1d776..d486186e59 100644
--- a/crates/hir_expand/src/lib.rs
+++ b/crates/hir_expand/src/lib.rs
@@ -83,7 +83,7 @@ impl HirFileId {
                     }
                     MacroCallId::EagerMacro(id) => {
                         let loc = db.lookup_intern_eager_expansion(id);
-                        loc.call.file_id
+                        loc.file_id
                     }
                 };
                 file_id.original_file(db)
@@ -103,7 +103,7 @@ impl HirFileId {
                 }
                 MacroCallId::EagerMacro(id) => {
                     let loc = db.lookup_intern_eager_expansion(id);
-                    loc.call.file_id
+                    loc.file_id
                 }
             };
         }
@@ -114,16 +114,17 @@ impl HirFileId {
     pub fn call_node(self, db: &dyn db::AstDatabase) -> Option<InFile<SyntaxNode>> {
         match self.0 {
             HirFileIdRepr::FileId(_) => None,
-            HirFileIdRepr::MacroFile(macro_file) => match macro_file.macro_call_id {
-                MacroCallId::LazyMacro(lazy_id) => {
-                    let loc: MacroCallLoc = db.lookup_intern_macro(lazy_id);
-                    Some(loc.kind.node(db))
-                }
-                MacroCallId::EagerMacro(id) => {
-                    let loc: EagerCallLoc = db.lookup_intern_eager_expansion(id);
-                    Some(loc.call.with_value(loc.call.to_node(db).syntax().clone()))
-                }
-            },
+            HirFileIdRepr::MacroFile(macro_file) => {
+                let lazy_id = match macro_file.macro_call_id {
+                    MacroCallId::LazyMacro(id) => id,
+                    MacroCallId::EagerMacro(_id) => {
+                        // FIXME: handle call node for eager macro
+                        return None;
+                    }
+                };
+                let loc = db.lookup_intern_macro(lazy_id);
+                Some(loc.kind.node(db))
+            }
         }
     }
 
@@ -303,7 +304,7 @@ pub struct EagerCallLoc {
     pub(crate) fragment: FragmentKind,
     pub(crate) subtree: Arc<tt::Subtree>,
     pub(crate) krate: CrateId,
-    pub(crate) call: AstId<ast::MacroCall>,
+    pub(crate) file_id: HirFileId,
 }
 
 /// ExpansionInfo mainly describes how to map text range between src and expanded macro
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..431da5d9c7 100644
--- a/crates/ide/src/goto_definition.rs
+++ b/crates/ide/src/goto_definition.rs
@@ -749,31 +749,6 @@ fn test() {
         );
     }
 
-    #[test]
-    fn goto_through_included_file() {
-        check(
-            r#"
-//- /main.rs
-#[rustc_builtin_macro]
-macro_rules! include {}
-
-  include!("foo.rs");
-//^^^^^^^^^^^^^^^^^^^
-
-fn f() {
-    foo<|>();
-}
-
-mod confuse_index {
-    pub fn foo() {}
-}
-
-//- /foo.rs
-fn foo() {}
-        "#,
-        );
-    }
-
     #[test]
     fn goto_for_type_param() {
         check(
@@ -1130,19 +1105,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 a75cc85b6e..dbad9a84f6 100644
--- a/crates/ide/src/lib.rs
+++ b/crates/ide/src/lib.rs
@@ -490,18 +490,8 @@ impl Analysis {
             .unwrap_or_default())
     }
 
-    /// Computes assists (aka code actions aka intentions) for the given
-    /// position. Computes enough info to show the lightbulb list in the editor,
-    /// but doesn't compute actual edits, to improve performance.
-    ///
-    /// When the user clicks on the assist, call `resolve_assists` to get the
-    /// edit.
-    pub fn assists(&self, config: &AssistConfig, frange: FileRange) -> Cancelable<Vec<Assist>> {
-        self.with_db(|db| Assist::unresolved(db, config, frange))
-    }
-
     /// Computes resolved assists with source changes for the given position.
-    pub fn resolve_assists(
+    pub fn resolved_assists(
         &self,
         config: &AssistConfig,
         frange: FileRange,
@@ -509,6 +499,16 @@ impl Analysis {
         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,
+        frange: FileRange,
+    ) -> Cancelable<Vec<Assist>> {
+        self.with_db(|db| Assist::unresolved(db, config, frange))
+    }
+
     /// Computes the set of diagnostics for the given file.
     pub fn diagnostics(
         &self,
@@ -535,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/parser/src/grammar/expressions/atom.rs b/crates/parser/src/grammar/expressions/atom.rs
index c7a3556a77..e897d5a52f 100644
--- a/crates/parser/src/grammar/expressions/atom.rs
+++ b/crates/parser/src/grammar/expressions/atom.rs
@@ -46,7 +46,6 @@ pub(super) const ATOM_EXPR_FIRST: TokenSet =
         T![continue],
         T![async],
         T![try],
-        T![const],
         T![loop],
         T![for],
         LIFETIME_IDENT,
@@ -116,14 +115,6 @@ pub(super) fn atom_expr(p: &mut Parser, r: Restrictions) -> Option<(CompletedMar
             block_expr(p);
             m.complete(p, EFFECT_EXPR)
         }
-        // test const_block
-        // fn f() { const { } }
-        T![const] if la == T!['{'] => {
-            let m = p.start();
-            p.bump(T![const]);
-            block_expr(p);
-            m.complete(p, EFFECT_EXPR)
-        }
         T!['{'] => {
             // test for_range_from
             // fn foo() {
diff --git a/crates/parser/src/grammar/items.rs b/crates/parser/src/grammar/items.rs
index cf4168d321..8999829b43 100644
--- a/crates/parser/src/grammar/items.rs
+++ b/crates/parser/src/grammar/items.rs
@@ -96,10 +96,7 @@ pub(super) fn maybe_item(p: &mut Parser, m: Marker) -> Result<(), Marker> {
     let mut has_mods = false;
 
     // modifiers
-    if p.at(T![const]) && p.nth(1) != T!['{'] {
-        p.eat(T![const]);
-        has_mods = true;
-    }
+    has_mods |= p.eat(T![const]);
 
     // test_err async_without_semicolon
     // fn foo() { let _ = async {} }
@@ -170,7 +167,7 @@ pub(super) fn maybe_item(p: &mut Parser, m: Marker) -> Result<(), Marker> {
             m.complete(p, TRAIT);
         }
 
-        T![const] if p.nth(1) != T!['{'] => {
+        T![const] => {
             consts::konst(p, m);
         }
 
@@ -389,15 +386,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/parser/src/grammar/patterns.rs b/crates/parser/src/grammar/patterns.rs
index b53d5749f4..7e7f73deea 100644
--- a/crates/parser/src/grammar/patterns.rs
+++ b/crates/parser/src/grammar/patterns.rs
@@ -89,7 +89,6 @@ fn atom_pat(p: &mut Parser, recovery_set: TokenSet) -> Option<CompletedMarker> {
     let m = match p.nth(0) {
         T![box] => box_pat(p),
         T![ref] | T![mut] => ident_pat(p, true),
-        T![const] => const_block_pat(p),
         IDENT => match p.nth(1) {
             // Checks the token after an IDENT to see if a pattern is a path (Struct { .. }) or macro
             // (T![x]).
@@ -387,16 +386,3 @@ fn box_pat(p: &mut Parser) -> CompletedMarker {
     pattern_single(p);
     m.complete(p, BOX_PAT)
 }
-
-// test const_block_pat
-// fn main() {
-//     let const { 15 } = ();
-//     let const { foo(); bar() } = ();
-// }
-fn const_block_pat(p: &mut Parser) -> CompletedMarker {
-    assert!(p.at(T![const]));
-    let m = p.start();
-    p.bump(T![const]);
-    expressions::block_expr(p);
-    m.complete(p, CONST_BLOCK_PAT)
-}
diff --git a/crates/parser/src/syntax_kind/generated.rs b/crates/parser/src/syntax_kind/generated.rs
index f69e71bdba..980aa59794 100644
--- a/crates/parser/src/syntax_kind/generated.rs
+++ b/crates/parser/src/syntax_kind/generated.rs
@@ -170,7 +170,6 @@ pub enum SyntaxKind {
     RANGE_PAT,
     LITERAL_PAT,
     MACRO_PAT,
-    CONST_BLOCK_PAT,
     TUPLE_EXPR,
     ARRAY_EXPR,
     PAREN_EXPR,
diff --git a/crates/proc_macro_srv/Cargo.toml b/crates/proc_macro_srv/Cargo.toml
index df9a55c10e..1bfa6c3fcb 100644
--- a/crates/proc_macro_srv/Cargo.toml
+++ b/crates/proc_macro_srv/Cargo.toml
@@ -10,7 +10,7 @@ edition = "2018"
 doctest = false
 
 [dependencies]
-object = { version = "0.23", default-features = false, features = ["std", "read_core", "elf", "macho", "pe"] }
+object = { version = "0.23", default-features = false, features = ["std", "read_core", "elf", "macho", "pe", "unaligned"] }
 libloading = "0.6.0"
 memmap = "0.7"
 
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/config.rs b/crates/rust-analyzer/src/config.rs
index 1db5b4e7dd..1f4b5c24c5 100644
--- a/crates/rust-analyzer/src/config.rs
+++ b/crates/rust-analyzer/src/config.rs
@@ -33,7 +33,7 @@ config_data! {
         callInfo_full: bool = "true",
 
         /// Automatically refresh project info via `cargo metadata` on
-        /// `Cargo.toml` changes.
+        /// Cargo.toml changes.
         cargo_autoreload: bool           = "true",
         /// Activate all available features.
         cargo_allFeatures: bool          = "false",
@@ -52,7 +52,7 @@ config_data! {
         /// Run specified `cargo check` command for diagnostics on save.
         checkOnSave_enable: bool                         = "true",
         /// Check with all features (will be passed as `--all-features`).
-        /// Defaults to `#rust-analyzer.cargo.allFeatures#`.
+        /// Defaults to `rust-analyzer.cargo.allFeatures`.
         checkOnSave_allFeatures: Option<bool>            = "null",
         /// Check all targets and tests (will be passed as `--all-targets`).
         checkOnSave_allTargets: bool                     = "true",
@@ -61,12 +61,12 @@ config_data! {
         /// Do not activate the `default` feature.
         checkOnSave_noDefaultFeatures: Option<bool>      = "null",
         /// Check for a specific target. Defaults to
-        /// `#rust-analyzer.cargo.target#`.
+        /// `rust-analyzer.cargo.target`.
         checkOnSave_target: Option<String>               = "null",
         /// Extra arguments for `cargo check`.
         checkOnSave_extraArgs: Vec<String>               = "[]",
         /// List of features to activate. Defaults to
-        /// `#rust-analyzer.cargo.features#`.
+        /// `rust-analyzer.cargo.features`.
         checkOnSave_features: Option<Vec<String>>        = "null",
         /// Advanced option, fully override the command rust-analyzer uses for
         /// checking. The command should include `--message-format=json` or
@@ -80,7 +80,7 @@ config_data! {
         /// Whether to show postfix snippets like `dbg`, `if`, `not`, etc.
         completion_postfix_enable: bool          = "true",
         /// Toggles the additional completions that automatically add imports when completed.
-        /// Note that your client must specify the `additionalTextEdits` LSP client capability to truly have this feature enabled.
+        /// Note that your client have to specify the `additionalTextEdits` LSP client capability to truly have this feature enabled.
         completion_autoimport_enable: bool       = "true",
 
         /// Whether to show native rust-analyzer diagnostics.
@@ -90,13 +90,13 @@ config_data! {
         diagnostics_enableExperimental: bool    = "true",
         /// List of rust-analyzer diagnostics to disable.
         diagnostics_disabled: FxHashSet<String> = "[]",
-        /// List of warnings that should be displayed with info severity.\n\nThe
+        /// List of warnings that should be displayed with info severity.\nThe
         /// warnings will be indicated by a blue squiggly underline in code and
-        /// a blue icon in the `Problems Panel`.
+        /// a blue icon in the problems panel.
         diagnostics_warningsAsHint: Vec<String> = "[]",
-        /// List of warnings that should be displayed with hint severity.\n\nThe
+        /// List of warnings that should be displayed with hint severity.\nThe
         /// warnings will be indicated by faded text or three dots in code and
-        /// will not show up in the `Problems Panel`.
+        /// will not show up in the problems panel.
         diagnostics_warningsAsInfo: Vec<String> = "[]",
 
         /// Controls file watching implementation.
@@ -121,7 +121,7 @@ config_data! {
 
         /// Whether to show inlay type hints for method chains.
         inlayHints_chainingHints: bool      = "true",
-        /// Maximum length for inlay hints. Default is unlimited.
+        /// Maximum length for inlay hints.
         inlayHints_maxLength: Option<usize> = "null",
         /// Whether to show function parameter name inlay hints at the call
         /// site.
@@ -145,27 +145,27 @@ config_data! {
         lens_methodReferences: bool = "false",
 
         /// Disable project auto-discovery in favor of explicitly specified set
-        /// of projects.\n\nElements must be paths pointing to `Cargo.toml`,
-        /// `rust-project.json`, or JSON objects in `rust-project.json` format.
+        /// of projects.  \nElements must be paths pointing to Cargo.toml,
+        /// rust-project.json, or JSON objects in rust-project.json format.
         linkedProjects: Vec<ManifestOrProjectJson> = "[]",
-        /// Number of syntax trees rust-analyzer keeps in memory.  Defaults to 128.
+        /// Number of syntax trees rust-analyzer keeps in memory.
         lruCapacity: Option<usize>                 = "null",
         /// Whether to show `can't find Cargo.toml` error message.
         notifications_cargoTomlNotFound: bool      = "true",
-        /// Enable Proc macro support, `#rust-analyzer.cargo.loadOutDirsFromCheck#` must be
+        /// Enable Proc macro support, cargo.loadOutDirsFromCheck must be
         /// enabled.
         procMacro_enable: bool                     = "false",
 
         /// Command to be executed instead of 'cargo' for runnables.
         runnables_overrideCargo: Option<String> = "null",
         /// Additional arguments to be passed to cargo for runnables such as
-        /// tests or binaries.\nFor example, it may be `--release`.
+        /// tests or binaries.\nFor example, it may be '--release'.
         runnables_cargoExtraArgs: Vec<String>   = "[]",
 
         /// Path to the rust compiler sources, for usage in rustc_private projects.
         rustcSource : Option<String> = "null",
 
-        /// Additional arguments to `rustfmt`.
+        /// Additional arguments to rustfmt.
         rustfmt_extraArgs: Vec<String>               = "[]",
         /// Advanced option, fully override the command rust-analyzer uses for
         /// formatting.
@@ -349,12 +349,12 @@ impl Config {
         res
     }
     pub fn update(&mut self, json: serde_json::Value) {
-        log::info!("updating config from JSON: {:#}", json);
+        log::info!("Config::update({:#})", json);
         if json.is_null() || json.as_object().map_or(false, |it| it.is_empty()) {
             return;
         }
         self.do_update(json);
-        log::info!("updated config: {:#?}", self);
+        log::info!("Config::update() = {:#?}", self);
     }
     fn do_update(&mut self, json: serde_json::Value) {
         let data = ConfigData::from_json(json);
@@ -758,7 +758,7 @@ fn field_props(field: &str, ty: &str, doc: &[&str], default: &str) -> serde_json
             ],
             "enumDescriptions": [
                 "Insert import paths relative to the current module, using up to one `super` prefix if the parent module contains the requested item.",
-                "Prefix all import paths with `self` if they don't begin with `self`, `super`, `crate` or a crate name.",
+                "Prefix all import paths with `self` if they don't begin with `self`, `super`, `crate` or a crate name",
                 "Force import paths to be absolute by always starting them with `crate` or the crate name they refer to."
             ],
         },
diff --git a/crates/rust-analyzer/src/handlers.rs b/crates/rust-analyzer/src/handlers.rs
index 1207b31c48..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, 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.resolve_assists(&assists_config, 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,7 +978,7 @@ pub(crate) fn handle_code_action_resolve(
         .only
         .map(|it| it.into_iter().filter_map(from_proto::assist_kind).collect());
 
-    let assists = snap.analysis.resolve_assists(&snap.config.assist, 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];
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 753aad6286..5a1ae96aa0 100644
--- a/crates/rust-analyzer/src/to_proto.rs
+++ b/crates/rust-analyzer/src/to_proto.rs
@@ -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,
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/syntax/src/ast/generated/nodes.rs b/crates/syntax/src/ast/generated/nodes.rs
index c5b80bffe7..1588ba93ea 100644
--- a/crates/syntax/src/ast/generated/nodes.rs
+++ b/crates/syntax/src/ast/generated/nodes.rs
@@ -763,7 +763,6 @@ impl EffectExpr {
     pub fn try_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![try]) }
     pub fn unsafe_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![unsafe]) }
     pub fn async_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![async]) }
-    pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) }
     pub fn block_expr(&self) -> Option<BlockExpr> { support::child(&self.syntax) }
 }
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -1252,14 +1251,6 @@ impl TupleStructPat {
     pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
 }
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct ConstBlockPat {
-    pub(crate) syntax: SyntaxNode,
-}
-impl ConstBlockPat {
-    pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) }
-    pub fn block_expr(&self) -> Option<BlockExpr> { support::child(&self.syntax) }
-}
-#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub struct RecordPatFieldList {
     pub(crate) syntax: SyntaxNode,
 }
@@ -1378,7 +1369,6 @@ pub enum Pat {
     SlicePat(SlicePat),
     TuplePat(TuplePat),
     TupleStructPat(TupleStructPat),
-    ConstBlockPat(ConstBlockPat),
 }
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub enum FieldList {
@@ -2782,17 +2772,6 @@ impl AstNode for TupleStructPat {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for ConstBlockPat {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == CONST_BLOCK_PAT }
-    fn cast(syntax: SyntaxNode) -> Option<Self> {
-        if Self::can_cast(syntax.kind()) {
-            Some(Self { syntax })
-        } else {
-            None
-        }
-    }
-    fn syntax(&self) -> &SyntaxNode { &self.syntax }
-}
 impl AstNode for RecordPatFieldList {
     fn can_cast(kind: SyntaxKind) -> bool { kind == RECORD_PAT_FIELD_LIST }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -3263,15 +3242,12 @@ impl From<TuplePat> for Pat {
 impl From<TupleStructPat> for Pat {
     fn from(node: TupleStructPat) -> Pat { Pat::TupleStructPat(node) }
 }
-impl From<ConstBlockPat> for Pat {
-    fn from(node: ConstBlockPat) -> Pat { Pat::ConstBlockPat(node) }
-}
 impl AstNode for Pat {
     fn can_cast(kind: SyntaxKind) -> bool {
         match kind {
             IDENT_PAT | BOX_PAT | REST_PAT | LITERAL_PAT | MACRO_PAT | OR_PAT | PAREN_PAT
             | PATH_PAT | WILDCARD_PAT | RANGE_PAT | RECORD_PAT | REF_PAT | SLICE_PAT
-            | TUPLE_PAT | TUPLE_STRUCT_PAT | CONST_BLOCK_PAT => true,
+            | TUPLE_PAT | TUPLE_STRUCT_PAT => true,
             _ => false,
         }
     }
@@ -3292,7 +3268,6 @@ impl AstNode for Pat {
             SLICE_PAT => Pat::SlicePat(SlicePat { syntax }),
             TUPLE_PAT => Pat::TuplePat(TuplePat { syntax }),
             TUPLE_STRUCT_PAT => Pat::TupleStructPat(TupleStructPat { syntax }),
-            CONST_BLOCK_PAT => Pat::ConstBlockPat(ConstBlockPat { syntax }),
             _ => return None,
         };
         Some(res)
@@ -3314,7 +3289,6 @@ impl AstNode for Pat {
             Pat::SlicePat(it) => &it.syntax,
             Pat::TuplePat(it) => &it.syntax,
             Pat::TupleStructPat(it) => &it.syntax,
-            Pat::ConstBlockPat(it) => &it.syntax,
         }
     }
 }
@@ -4163,11 +4137,6 @@ impl std::fmt::Display for TupleStructPat {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for ConstBlockPat {
-    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        std::fmt::Display::fmt(self.syntax(), f)
-    }
-}
 impl std::fmt::Display for RecordPatFieldList {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
diff --git a/crates/syntax/src/ast/make.rs b/crates/syntax/src/ast/make.rs
index cafa4c1989..ba7e5d2fb1 100644
--- a/crates/syntax/src/ast/make.rs
+++ b/crates/syntax/src/ast/make.rs
@@ -4,11 +4,6 @@
 //! Note that all functions here intended to be stupid constructors, which just
 //! assemble a finish node from immediate children. If you want to do something
 //! smarter than that, it probably doesn't belong in this module.
-//!
-//! Keep in mind that `from_text` functions should be kept private. The public
-//! API should require to assemble every node piecewise. The trick of
-//! `parse(format!())` we use internally is an implementation detail -- long
-//! term, it will be replaced with direct tree manipulation.
 use itertools::Itertools;
 use stdx::format_to;
 
@@ -21,8 +16,7 @@ pub fn name(text: &str) -> ast::Name {
 pub fn name_ref(text: &str) -> ast::NameRef {
     ast_from_text(&format!("fn f() {{ {}; }}", text))
 }
-// FIXME: replace stringly-typed constructor with a family of typed ctors, a-la
-// `expr_xxx`.
+
 pub fn ty(text: &str) -> ast::Type {
     ast_from_text(&format!("impl {} for D {{}};", text))
 }
diff --git a/docs/user/generated_config.adoc b/docs/user/generated_config.adoc
index 3025dc8d69..cb2ae6fc10 100644
--- a/docs/user/generated_config.adoc
+++ b/docs/user/generated_config.adoc
@@ -5,7 +5,7 @@ rust-analyzer.assist.importPrefix (default: `"plain"`)::
 rust-analyzer.callInfo.full (default: `true`)::
  Show function name and docs in parameter hints.
 rust-analyzer.cargo.autoreload (default: `true`)::
- Automatically refresh project info via `cargo metadata` on  `Cargo.toml` changes.
+ Automatically refresh project info via `cargo metadata` on  Cargo.toml changes.
 rust-analyzer.cargo.allFeatures (default: `false`)::
  Activate all available features.
 rust-analyzer.cargo.features (default: `[]`)::
@@ -21,7 +21,7 @@ rust-analyzer.cargo.noSysroot (default: `false`)::
 rust-analyzer.checkOnSave.enable (default: `true`)::
  Run specified `cargo check` command for diagnostics on save.
 rust-analyzer.checkOnSave.allFeatures (default: `null`)::
- Check with all features (will be passed as `--all-features`).  Defaults to `#rust-analyzer.cargo.allFeatures#`.
+ Check with all features (will be passed as `--all-features`).  Defaults to `rust-analyzer.cargo.allFeatures`.
 rust-analyzer.checkOnSave.allTargets (default: `true`)::
  Check all targets and tests (will be passed as `--all-targets`).
 rust-analyzer.checkOnSave.command (default: `"check"`)::
@@ -29,11 +29,11 @@ rust-analyzer.checkOnSave.command (default: `"check"`)::
 rust-analyzer.checkOnSave.noDefaultFeatures (default: `null`)::
  Do not activate the `default` feature.
 rust-analyzer.checkOnSave.target (default: `null`)::
- Check for a specific target. Defaults to  `#rust-analyzer.cargo.target#`.
+ Check for a specific target. Defaults to  `rust-analyzer.cargo.target`.
 rust-analyzer.checkOnSave.extraArgs (default: `[]`)::
  Extra arguments for `cargo check`.
 rust-analyzer.checkOnSave.features (default: `null`)::
- List of features to activate. Defaults to  `#rust-analyzer.cargo.features#`.
+ List of features to activate. Defaults to  `rust-analyzer.cargo.features`.
 rust-analyzer.checkOnSave.overrideCommand (default: `null`)::
  Advanced option, fully override the command rust-analyzer uses for  checking. The command should include `--message-format=json` or  similar option.
 rust-analyzer.completion.addCallArgumentSnippets (default: `true`)::
@@ -43,7 +43,7 @@ rust-analyzer.completion.addCallParenthesis (default: `true`)::
 rust-analyzer.completion.postfix.enable (default: `true`)::
  Whether to show postfix snippets like `dbg`, `if`, `not`, etc.
 rust-analyzer.completion.autoimport.enable (default: `true`)::
- Toggles the additional completions that automatically add imports when completed.  Note that your client must specify the `additionalTextEdits` LSP client capability to truly have this feature enabled.
+ Toggles the additional completions that automatically add imports when completed.  Note that your client have to specify the `additionalTextEdits` LSP client capability to truly have this feature enabled.
 rust-analyzer.diagnostics.enable (default: `true`)::
  Whether to show native rust-analyzer diagnostics.
 rust-analyzer.diagnostics.enableExperimental (default: `true`)::
@@ -51,9 +51,9 @@ rust-analyzer.diagnostics.enableExperimental (default: `true`)::
 rust-analyzer.diagnostics.disabled (default: `[]`)::
  List of rust-analyzer diagnostics to disable.
 rust-analyzer.diagnostics.warningsAsHint (default: `[]`)::
- List of warnings that should be displayed with info severity.\n\nThe  warnings will be indicated by a blue squiggly underline in code and  a blue icon in the `Problems Panel`.
+ List of warnings that should be displayed with info severity.\nThe  warnings will be indicated by a blue squiggly underline in code and  a blue icon in the problems panel.
 rust-analyzer.diagnostics.warningsAsInfo (default: `[]`)::
- List of warnings that should be displayed with hint severity.\n\nThe  warnings will be indicated by faded text or three dots in code and  will not show up in the `Problems Panel`.
+ List of warnings that should be displayed with hint severity.\nThe  warnings will be indicated by faded text or three dots in code and  will not show up in the problems panel.
 rust-analyzer.files.watcher (default: `"client"`)::
  Controls file watching implementation.
 rust-analyzer.hoverActions.debug (default: `true`)::
@@ -71,7 +71,7 @@ rust-analyzer.hoverActions.linksInHover (default: `true`)::
 rust-analyzer.inlayHints.chainingHints (default: `true`)::
  Whether to show inlay type hints for method chains.
 rust-analyzer.inlayHints.maxLength (default: `null`)::
- Maximum length for inlay hints. Default is unlimited.
+ Maximum length for inlay hints.
 rust-analyzer.inlayHints.parameterHints (default: `true`)::
  Whether to show function parameter name inlay hints at the call  site.
 rust-analyzer.inlayHints.typeHints (default: `true`)::
@@ -87,20 +87,20 @@ rust-analyzer.lens.run (default: `true`)::
 rust-analyzer.lens.methodReferences (default: `false`)::
  Whether to show `Method References` lens. Only applies when  `#rust-analyzer.lens.enable#` is set.
 rust-analyzer.linkedProjects (default: `[]`)::
- Disable project auto-discovery in favor of explicitly specified set  of projects.\n\nElements must be paths pointing to `Cargo.toml`,  `rust-project.json`, or JSON objects in `rust-project.json` format.
+ Disable project auto-discovery in favor of explicitly specified set  of projects.  \nElements must be paths pointing to Cargo.toml,  rust-project.json, or JSON objects in rust-project.json format.
 rust-analyzer.lruCapacity (default: `null`)::
- Number of syntax trees rust-analyzer keeps in memory.  Defaults to 128.
+ Number of syntax trees rust-analyzer keeps in memory.
 rust-analyzer.notifications.cargoTomlNotFound (default: `true`)::
  Whether to show `can't find Cargo.toml` error message.
 rust-analyzer.procMacro.enable (default: `false`)::
- Enable Proc macro support, `#rust-analyzer.cargo.loadOutDirsFromCheck#` must be  enabled.
+ Enable Proc macro support, cargo.loadOutDirsFromCheck must be  enabled.
 rust-analyzer.runnables.overrideCargo (default: `null`)::
  Command to be executed instead of 'cargo' for runnables.
 rust-analyzer.runnables.cargoExtraArgs (default: `[]`)::
- Additional arguments to be passed to cargo for runnables such as  tests or binaries.\nFor example, it may be `--release`.
+ Additional arguments to be passed to cargo for runnables such as  tests or binaries.\nFor example, it may be '--release'.
 rust-analyzer.rustcSource (default: `null`)::
  Path to the rust compiler sources, for usage in rustc_private projects.
 rust-analyzer.rustfmt.extraArgs (default: `[]`)::
- Additional arguments to `rustfmt`.
+ Additional arguments to rustfmt.
 rust-analyzer.rustfmt.overrideCommand (default: `null`)::
  Advanced option, fully override the command rust-analyzer uses for  formatting.
diff --git a/docs/user/manual.adoc b/docs/user/manual.adoc
index d4121b4011..40f10972f4 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
@@ -302,9 +302,6 @@ If the LSP binary is not available, GNOME Builder can install it when opening a
 rust-analyzer is configured via LSP messages, which means that it's up to the editor to decide on the exact format and location of configuration files.
 Please consult your editor's documentation to learn how to configure LSP servers.
 
-To verify which configuration is actually used by rust-analyzer, set `RA_LOG` environment variable to `rust_analyzer=info` and look for config-related messages.
-Logs should show both the JSON that rust-analyzer sees as well as the updated config.
-
 This is the list of config options rust-analyzer supports:
 
 include::./generated_config.adoc[]
diff --git a/editors/code/package.json b/editors/code/package.json
index 13749a0849..abcc84edac 100644
--- a/editors/code/package.json
+++ b/editors/code/package.json
@@ -250,12 +250,12 @@
                         }
                     ],
                     "default": null,
-                    "markdownDescription": "Environment variables passed to the runnable launched using `Test` or `Debug` lens or `rust-analyzer.run` command."
+                    "description": "Environment variables passed to the runnable launched using `Test ` or `Debug` lens or `rust-analyzer.run` command."
                 },
                 "rust-analyzer.inlayHints.enable": {
                     "type": "boolean",
                     "default": true,
-                    "description": "Whether to show inlay hints."
+                    "description": "Whether to show inlay hints"
                 },
                 "rust-analyzer.updates.channel": {
                     "type": "string",
@@ -265,15 +265,15 @@
                     ],
                     "default": "stable",
                     "markdownEnumDescriptions": [
-                        "`stable` updates are shipped weekly, they don't contain cutting-edge features from VSCode proposed APIs but have less bugs in general.",
-                        "`nightly` updates are shipped daily (extension updates automatically by downloading artifacts directly from GitHub), they contain cutting-edge features and latest bug fixes. These releases help us get your feedback very quickly and speed up rust-analyzer development **drastically**."
+                        "`\"stable\"` updates are shipped weekly, they don't contain cutting-edge features from VSCode proposed APIs but have less bugs in general",
+                        "`\"nightly\"` updates are shipped daily (extension updates automatically by downloading artifacts directly from GitHub), they contain cutting-edge features and latest bug fixes. These releases help us get your feedback very quickly and speed up rust-analyzer development **drastically**"
                     ],
-                    "markdownDescription": "Choose `nightly` updates to get the latest features and bug fixes every day. While `stable` releases occur weekly and don't contain cutting-edge features from VSCode proposed APIs."
+                    "markdownDescription": "Choose `\"nightly\"` updates to get the latest features and bug fixes every day. While `\"stable\"` releases occur weekly and don't contain cutting-edge features from VSCode proposed APIs"
                 },
                 "rust-analyzer.updates.askBeforeDownload": {
                     "type": "boolean",
                     "default": true,
-                    "description": "Whether to ask for permission before downloading any files from the Internet."
+                    "description": "Whether to ask for permission before downloading any files from the Internet"
                 },
                 "rust-analyzer.serverPath": {
                     "type": [
@@ -281,7 +281,7 @@
                         "string"
                     ],
                     "default": null,
-                    "markdownDescription": "Path to rust-analyzer executable (points to bundled binary by default). If this is set, then `#rust-analyzer.updates.channel#` setting is not used"
+                    "description": "Path to rust-analyzer executable (points to bundled binary by default). If this is set, then \"rust-analyzer.updates.channel\" setting is not used"
                 },
                 "rust-analyzer.trace.server": {
                     "type": "string",
@@ -297,10 +297,10 @@
                         "Full log"
                     ],
                     "default": "off",
-                    "description": "Trace requests to the rust-analyzer (this is usually overly verbose and not recommended for regular users)."
+                    "description": "Trace requests to the rust-analyzer (this is usually overly verbose and not recommended for regular users)"
                 },
                 "rust-analyzer.trace.extension": {
-                    "description": "Enable logging of VS Code extensions itself.",
+                    "description": "Enable logging of VS Code extensions itself",
                     "type": "boolean",
                     "default": false
                 },
@@ -327,14 +327,14 @@
                     }
                 },
                 "rust-analyzer.debug.openDebugPane": {
-                    "markdownDescription": "Whether to open up the `Debug Panel` on debugging start.",
+                    "description": "Whether to open up the Debug Pane on debugging start.",
                     "type": "boolean",
                     "default": false
                 },
                 "rust-analyzer.debug.engineSettings": {
                     "type": "object",
                     "default": {},
-                    "markdownDescription": "Optional settings passed to the debug engine. Example: `{ \"lldb\": { \"terminal\":\"external\"} }`"
+                    "description": "Optional settings passed to the debug engine. Example:\n{ \"lldb\": { \"terminal\":\"external\"} }"
                 },
                 "rust-analyzer.assist.importMergeBehaviour": {
                     "markdownDescription": "The strategy to use when inserting new imports or merging imports.",
@@ -362,7 +362,7 @@
                     ],
                     "enumDescriptions": [
                         "Insert import paths relative to the current module, using up to one `super` prefix if the parent module contains the requested item.",
-                        "Prefix all import paths with `self` if they don't begin with `self`, `super`, `crate` or a crate name.",
+                        "Prefix all import paths with `self` if they don't begin with `self`, `super`, `crate` or a crate name",
                         "Force import paths to be absolute by always starting them with `crate` or the crate name they refer to."
                     ]
                 },
@@ -372,7 +372,7 @@
                     "type": "boolean"
                 },
                 "rust-analyzer.cargo.autoreload": {
-                    "markdownDescription": "Automatically refresh project info via `cargo metadata` on `Cargo.toml` changes.",
+                    "markdownDescription": "Automatically refresh project info via `cargo metadata` on Cargo.toml changes.",
                     "default": true,
                     "type": "boolean"
                 },
@@ -418,7 +418,7 @@
                     "type": "boolean"
                 },
                 "rust-analyzer.checkOnSave.allFeatures": {
-                    "markdownDescription": "Check with all features (will be passed as `--all-features`). Defaults to `#rust-analyzer.cargo.allFeatures#`.",
+                    "markdownDescription": "Check with all features (will be passed as `--all-features`). Defaults to `rust-analyzer.cargo.allFeatures`.",
                     "default": null,
                     "type": [
                         "null",
@@ -444,7 +444,7 @@
                     ]
                 },
                 "rust-analyzer.checkOnSave.target": {
-                    "markdownDescription": "Check for a specific target. Defaults to `#rust-analyzer.cargo.target#`.",
+                    "markdownDescription": "Check for a specific target. Defaults to `rust-analyzer.cargo.target`.",
                     "default": null,
                     "type": [
                         "null",
@@ -460,7 +460,7 @@
                     }
                 },
                 "rust-analyzer.checkOnSave.features": {
-                    "markdownDescription": "List of features to activate. Defaults to `#rust-analyzer.cargo.features#`.",
+                    "markdownDescription": "List of features to activate. Defaults to `rust-analyzer.cargo.features`.",
                     "default": null,
                     "type": [
                         "null",
@@ -497,7 +497,7 @@
                     "type": "boolean"
                 },
                 "rust-analyzer.completion.autoimport.enable": {
-                    "markdownDescription": "Toggles the additional completions that automatically add imports when completed. Note that your client must specify the `additionalTextEdits` LSP client capability to truly have this feature enabled.",
+                    "markdownDescription": "Toggles the additional completions that automatically add imports when completed. Note that your client have to specify the `additionalTextEdits` LSP client capability to truly have this feature enabled.",
                     "default": true,
                     "type": "boolean"
                 },
@@ -521,7 +521,7 @@
                     "uniqueItems": true
                 },
                 "rust-analyzer.diagnostics.warningsAsHint": {
-                    "markdownDescription": "List of warnings that should be displayed with info severity.\\n\\nThe warnings will be indicated by a blue squiggly underline in code and a blue icon in the `Problems Panel`.",
+                    "markdownDescription": "List of warnings that should be displayed with info severity.\\nThe warnings will be indicated by a blue squiggly underline in code and a blue icon in the problems panel.",
                     "default": [],
                     "type": "array",
                     "items": {
@@ -529,7 +529,7 @@
                     }
                 },
                 "rust-analyzer.diagnostics.warningsAsInfo": {
-                    "markdownDescription": "List of warnings that should be displayed with hint severity.\\n\\nThe warnings will be indicated by faded text or three dots in code and will not show up in the `Problems Panel`.",
+                    "markdownDescription": "List of warnings that should be displayed with hint severity.\\nThe warnings will be indicated by faded text or three dots in code and will not show up in the problems panel.",
                     "default": [],
                     "type": "array",
                     "items": {
@@ -577,7 +577,7 @@
                     "type": "boolean"
                 },
                 "rust-analyzer.inlayHints.maxLength": {
-                    "markdownDescription": "Maximum length for inlay hints. Default is unlimited.",
+                    "markdownDescription": "Maximum length for inlay hints.",
                     "default": null,
                     "type": [
                         "null",
@@ -621,7 +621,7 @@
                     "type": "boolean"
                 },
                 "rust-analyzer.linkedProjects": {
-                    "markdownDescription": "Disable project auto-discovery in favor of explicitly specified set of projects.\\n\\nElements must be paths pointing to `Cargo.toml`, `rust-project.json`, or JSON objects in `rust-project.json` format.",
+                    "markdownDescription": "Disable project auto-discovery in favor of explicitly specified set of projects.  \\nElements must be paths pointing to Cargo.toml, rust-project.json, or JSON objects in rust-project.json format.",
                     "default": [],
                     "type": "array",
                     "items": {
@@ -632,7 +632,7 @@
                     }
                 },
                 "rust-analyzer.lruCapacity": {
-                    "markdownDescription": "Number of syntax trees rust-analyzer keeps in memory.  Defaults to 128.",
+                    "markdownDescription": "Number of syntax trees rust-analyzer keeps in memory.",
                     "default": null,
                     "type": [
                         "null",
@@ -646,7 +646,7 @@
                     "type": "boolean"
                 },
                 "rust-analyzer.procMacro.enable": {
-                    "markdownDescription": "Enable Proc macro support, `#rust-analyzer.cargo.loadOutDirsFromCheck#` must be enabled.",
+                    "markdownDescription": "Enable Proc macro support, cargo.loadOutDirsFromCheck must be enabled.",
                     "default": false,
                     "type": "boolean"
                 },
@@ -659,7 +659,7 @@
                     ]
                 },
                 "rust-analyzer.runnables.cargoExtraArgs": {
-                    "markdownDescription": "Additional arguments to be passed to cargo for runnables such as tests or binaries.\\nFor example, it may be `--release`.",
+                    "markdownDescription": "Additional arguments to be passed to cargo for runnables such as tests or binaries.\\nFor example, it may be '--release'.",
                     "default": [],
                     "type": "array",
                     "items": {
@@ -675,7 +675,7 @@
                     ]
                 },
                 "rust-analyzer.rustfmt.extraArgs": {
-                    "markdownDescription": "Additional arguments to `rustfmt`.",
+                    "markdownDescription": "Additional arguments to rustfmt.",
                     "default": [],
                     "type": "array",
                     "items": {
diff --git a/editors/code/src/main.ts b/editors/code/src/main.ts
index 282240d845..4b2d3c8a55 100644
--- a/editors/code/src/main.ts
+++ b/editors/code/src/main.ts
@@ -131,7 +131,7 @@ async function tryActivate(context: vscode.ExtensionContext) {
     ctx.pushCleanup(activateTaskProvider(workspaceFolder, ctx.config));
 
     activateInlayHints(ctx);
-    warnAboutExtensionConflicts();
+    warnAboutRustLangExtensionConflict();
 
     vscode.workspace.onDidChangeConfiguration(
         _ => ctx?.client?.sendNotification('workspace/didChangeConfiguration', { settings: "" }),
@@ -287,14 +287,12 @@ async function getServer(config: Config, state: PersistentState): Promise<string
     if (config.package.releaseTag === null) return "rust-analyzer";
 
     let platform: string | undefined;
-    if ((process.arch === "x64" || process.arch === "ia32") && process.platform === "win32") {
-        platform = "x86_64-pc-windows-msvc";
-    } else if (process.arch === "x64" && process.platform === "linux") {
-        platform = "x86_64-unknown-linux-gnu";
-    } else if (process.arch === "x64" && process.platform === "darwin") {
-        platform = "x86_64-apple-darwin";
+    if (process.arch === "x64" || process.arch === "ia32") {
+        if (process.platform === "linux") platform = "linux";
+        if (process.platform === "darwin") platform = "mac";
+        if (process.platform === "win32") platform = "windows";
     } else if (process.arch === "arm64" && process.platform === "darwin") {
-        platform = "aarch64-apple-darwin";
+        platform = "mac";
     }
     if (platform === undefined) {
         vscode.window.showErrorMessage(
@@ -307,7 +305,7 @@ async function getServer(config: Config, state: PersistentState): Promise<string
         );
         return undefined;
     }
-    const ext = platform.indexOf("-windows-") !== -1 ? ".exe" : "";
+    const ext = platform === "windows" ? ".exe" : "";
     const dest = path.join(config.globalStoragePath, `rust-analyzer-${platform}${ext}`);
     const exists = await fs.stat(dest).then(() => true, () => false);
     if (!exists) {
@@ -413,21 +411,11 @@ async function queryForGithubToken(state: PersistentState): Promise<void> {
     }
 }
 
-function warnAboutExtensionConflicts() {
-    const conflicting = [
-        ["rust-analyzer", "matklad.rust-analyzer"],
-        ["Rust", "rust-lang.rust"],
-        ["Rust", "kalitaalexey.vscode-rust"],
-    ];
-
-    const found = conflicting.filter(
-        nameId => vscode.extensions.getExtension(nameId[1]) !== undefined);
-
-    if (found.length > 1) {
-        const fst = found[0];
-        const sec = found[1];
+function warnAboutRustLangExtensionConflict() {
+    const rustLangExt = vscode.extensions.getExtension("rust-lang.rust");
+    if (rustLangExt !== undefined) {
         vscode.window.showWarningMessage(
-            `You have both the ${fst[0]} (${fst[1]}) and ${sec[0]} (${sec[1]}) ` +
+            "You have both rust-analyzer (matklad.rust-analyzer) and Rust (rust-lang.rust) " +
             "plugins enabled. These are known to conflict and cause various functions of " +
             "both plugins to not work correctly. You should disable one of them.", "Got it");
     };
diff --git a/xtask/Cargo.toml b/xtask/Cargo.toml
index 96b4ea448d..78a0b54ba6 100644
--- a/xtask/Cargo.toml
+++ b/xtask/Cargo.toml
@@ -15,7 +15,7 @@ flate2 = "1.0"
 pico-args = "0.3.1"
 proc-macro2 = "1.0.8"
 quote = "1.0.2"
-ungrammar = "1.5"
+ungrammar = "1.4"
 walkdir = "2.3.1"
 write-json = "0.1.0"
 xshell = "0.1"
diff --git a/xtask/src/ast_src.rs b/xtask/src/ast_src.rs
index 2b8012bdd5..a69ced5ccf 100644
--- a/xtask/src/ast_src.rs
+++ b/xtask/src/ast_src.rs
@@ -132,7 +132,6 @@ pub(crate) const KINDS_SRC: KindsSrc = KindsSrc {
         "RANGE_PAT",
         "LITERAL_PAT",
         "MACRO_PAT",
-        "CONST_BLOCK_PAT",
         // atoms
         "TUPLE_EXPR",
         "ARRAY_EXPR",
diff --git a/xtask/src/dist.rs b/xtask/src/dist.rs
index d59b88131a..d07ad94204 100644
--- a/xtask/src/dist.rs
+++ b/xtask/src/dist.rs
@@ -70,6 +70,7 @@ fn dist_server() -> Result<()> {
     let src =
         Path::new("target").join(&target).join("release").join(format!("rust-analyzer{}", suffix));
     let dst = Path::new("dist").join(format!("rust-analyzer-{}{}", target, suffix));
+    cp(&src, &dst)?;
     gzip(&src, &dst.with_extension("gz"))?;
 
     // FIXME: the old names are temporarily kept for client compatibility, but they should be removed


Test patch:
diff --git a/crates/assists/src/tests/generated.rs b/crates/assists/src/tests/generated.rs
index e9093ec536..d3dfe24e7c 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,14 +87,16 @@ 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 {
-        ${0:todo!()}
+        todo!()
     }
 }
 "#####,
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/syntax/test_data/parser/inline/ok/0156_const_block_pat.rast b/crates/syntax/test_data/parser/inline/ok/0156_const_block_pat.rast
deleted file mode 100644
index 8ff4822c4e..0000000000
--- a/crates/syntax/test_data/parser/inline/ok/0156_const_block_pat.rast
+++ /dev/null
@@ -1,76 +0,0 @@
-SOURCE_FILE@0..78
-  FN@0..77
-    FN_KW@0..2 "fn"
-    WHITESPACE@2..3 " "
-    NAME@3..7
-      IDENT@3..7 "main"
-    PARAM_LIST@7..9
-      L_PAREN@7..8 "("
-      R_PAREN@8..9 ")"
-    WHITESPACE@9..10 " "
-    BLOCK_EXPR@10..77
-      L_CURLY@10..11 "{"
-      WHITESPACE@11..16 "\n    "
-      LET_STMT@16..38
-        LET_KW@16..19 "let"
-        WHITESPACE@19..20 " "
-        CONST_BLOCK_PAT@20..32
-          CONST_KW@20..25 "const"
-          WHITESPACE@25..26 " "
-          BLOCK_EXPR@26..32
-            L_CURLY@26..27 "{"
-            WHITESPACE@27..28 " "
-            LITERAL@28..30
-              INT_NUMBER@28..30 "15"
-            WHITESPACE@30..31 " "
-            R_CURLY@31..32 "}"
-        WHITESPACE@32..33 " "
-        EQ@33..34 "="
-        WHITESPACE@34..35 " "
-        TUPLE_EXPR@35..37
-          L_PAREN@35..36 "("
-          R_PAREN@36..37 ")"
-        SEMICOLON@37..38 ";"
-      WHITESPACE@38..43 "\n    "
-      LET_STMT@43..75
-        LET_KW@43..46 "let"
-        WHITESPACE@46..47 " "
-        CONST_BLOCK_PAT@47..69
-          CONST_KW@47..52 "const"
-          WHITESPACE@52..53 " "
-          BLOCK_EXPR@53..69
-            L_CURLY@53..54 "{"
-            WHITESPACE@54..55 " "
-            EXPR_STMT@55..61
-              CALL_EXPR@55..60
-                PATH_EXPR@55..58
-                  PATH@55..58
-                    PATH_SEGMENT@55..58
-                      NAME_REF@55..58
-                        IDENT@55..58 "foo"
-                ARG_LIST@58..60
-                  L_PAREN@58..59 "("
-                  R_PAREN@59..60 ")"
-              SEMICOLON@60..61 ";"
-            WHITESPACE@61..62 " "
-            CALL_EXPR@62..67
-              PATH_EXPR@62..65
-                PATH@62..65
-                  PATH_SEGMENT@62..65
-                    NAME_REF@62..65
-                      IDENT@62..65 "bar"
-              ARG_LIST@65..67
-                L_PAREN@65..66 "("
-                R_PAREN@66..67 ")"
-            WHITESPACE@67..68 " "
-            R_CURLY@68..69 "}"
-        WHITESPACE@69..70 " "
-        EQ@70..71 "="
-        WHITESPACE@71..72 " "
-        TUPLE_EXPR@72..74
-          L_PAREN@72..73 "("
-          R_PAREN@73..74 ")"
-        SEMICOLON@74..75 ";"
-      WHITESPACE@75..76 "\n"
-      R_CURLY@76..77 "}"
-  WHITESPACE@77..78 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0156_const_block_pat.rs b/crates/syntax/test_data/parser/inline/ok/0156_const_block_pat.rs
deleted file mode 100644
index dce9defac2..0000000000
--- a/crates/syntax/test_data/parser/inline/ok/0156_const_block_pat.rs
+++ /dev/null
@@ -1,4 +0,0 @@
-fn main() {
-    let const { 15 } = ();
-    let const { foo(); bar() } = ();
-}
diff --git a/crates/syntax/test_data/parser/inline/ok/0157_const_block.rast b/crates/syntax/test_data/parser/inline/ok/0157_const_block.rast
deleted file mode 100644
index d5d2c8fe30..0000000000
--- a/crates/syntax/test_data/parser/inline/ok/0157_const_block.rast
+++ /dev/null
@@ -1,23 +0,0 @@
-SOURCE_FILE@0..21
-  FN@0..20
-    FN_KW@0..2 "fn"
-    WHITESPACE@2..3 " "
-    NAME@3..4
-      IDENT@3..4 "f"
-    PARAM_LIST@4..6
-      L_PAREN@4..5 "("
-      R_PAREN@5..6 ")"
-    WHITESPACE@6..7 " "
-    BLOCK_EXPR@7..20
-      L_CURLY@7..8 "{"
-      WHITESPACE@8..9 " "
-      EFFECT_EXPR@9..18
-        CONST_KW@9..14 "const"
-        WHITESPACE@14..15 " "
-        BLOCK_EXPR@15..18
-          L_CURLY@15..16 "{"
-          WHITESPACE@16..17 " "
-          R_CURLY@17..18 "}"
-      WHITESPACE@18..19 " "
-      R_CURLY@19..20 "}"
-  WHITESPACE@20..21 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0157_const_block.rs b/crates/syntax/test_data/parser/inline/ok/0157_const_block.rs
deleted file mode 100644
index a2e3565a32..0000000000
--- a/crates/syntax/test_data/parser/inline/ok/0157_const_block.rs
+++ /dev/null
@@ -1,1 +0,0 @@
-fn f() { const { } }
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) => {} ];