Repository: rust-lang/rust-analyzer
Pull request #11997 (2022-04-15 15:16:44)

minor: Bump target JS version


Patch:
diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml
index 32fc63a795..baefd8bc1f 100644
--- a/.github/workflows/ci.yaml
+++ b/.github/workflows/ci.yaml
@@ -1,13 +1,11 @@
-# Please make sure that the `needs` fields for both `end-success` and `end-failure`
-# are updated when adding new jobs!
-
 name: CI
 on:
   pull_request:
   push:
     branches:
-    - auto
-    - try
+    - master
+    - staging
+    - trying
 
 env:
   CARGO_INCREMENTAL: 0
@@ -19,7 +17,7 @@ env:
 
 jobs:
   rust:
-    if: github.repository == 'rust-lang/rust-analyzer'
+    if: github.repository == 'rust-analyzer/rust-analyzer'
     name: Rust
     runs-on: ${{ matrix.os }}
     env:
@@ -64,7 +62,7 @@ jobs:
 
   # Weird targets to catch non-portable code
   rust-cross:
-    if: github.repository == 'rust-lang/rust-analyzer'
+    if: github.repository == 'rust-analyzer/rust-analyzer'
     name: Rust Cross
     runs-on: ubuntu-latest
 
@@ -101,7 +99,7 @@ jobs:
         done
 
   typescript:
-    if: github.repository == 'rust-lang/rust-analyzer'
+    if: github.repository == 'rust-analyzer/rust-analyzer'
     name: TypeScript
     strategy:
       fail-fast: false
@@ -152,21 +150,3 @@ jobs:
 
     - run: npm run package --scripts-prepend-node-path
       working-directory: ./editors/code
-
-  end-success:
-    name: bors build finished
-    if: github.event.pusher.name == 'bors' && success()
-    runs-on: ubuntu-latest
-    needs: [rust, rust-cross, typescript]
-    steps:
-      - name: Mark the job as successful
-        run: exit 0
-
-  end-failure:
-    name: bors build finished
-    if: github.event.pusher.name == 'bors' && (failure() || cancelled())
-    runs-on: ubuntu-latest
-    needs: [rust, rust-cross, typescript]
-    steps:
-      - name: Mark the job as a failure
-        run: exit 1
diff --git a/.github/workflows/metrics.yaml b/.github/workflows/metrics.yaml
index ecd3993e3f..f4412ef657 100644
--- a/.github/workflows/metrics.yaml
+++ b/.github/workflows/metrics.yaml
@@ -12,7 +12,7 @@ env:
 
 jobs:
   metrics:
-    if: github.repository == 'rust-lang/rust-analyzer'
+    if: github.repository == 'rust-analyzer/rust-analyzer'
     runs-on: ubuntu-latest
 
     steps:
diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml
index b1da921610..4ee7add1de 100644
--- a/.github/workflows/release.yaml
+++ b/.github/workflows/release.yaml
@@ -247,12 +247,12 @@ jobs:
         working-directory: ./editors/code
 
       - name: Publish Extension (release)
-        if: github.ref == 'refs/heads/release' && (github.repository == 'rust-analyzer/rust-analyzer' || github.repository == 'rust-lang/rust-analyzer')
+        if: github.ref == 'refs/heads/release' && github.repository == 'rust-analyzer/rust-analyzer'
         working-directory: ./editors/code
         # token from https://dev.azure.com/rust-analyzer/
         run: npx vsce publish --pat ${{ secrets.MARKETPLACE_TOKEN }} --packagePath ../../dist/rust-analyzer-*.vsix
 
       - name: Publish Extension (nightly)
-        if: github.ref != 'refs/heads/release' && (github.repository == 'rust-analyzer/rust-analyzer' || github.repository == 'rust-lang/rust-analyzer')
+        if: github.ref != 'refs/heads/release' && github.repository == 'rust-analyzer/rust-analyzer'
         working-directory: ./editors/code
         run: npx vsce publish --pat ${{ secrets.MARKETPLACE_TOKEN }} --packagePath ../../dist/rust-analyzer-*.vsix --pre-release
diff --git a/.github/workflows/rustdoc.yaml b/.github/workflows/rustdoc.yaml
index 2fd7ed4343..ac69adb947 100644
--- a/.github/workflows/rustdoc.yaml
+++ b/.github/workflows/rustdoc.yaml
@@ -12,7 +12,7 @@ env:
 
 jobs:
   rustdoc:
-    if: github.repository == 'rust-lang/rust-analyzer'
+    if: github.repository == 'rust-analyzer/rust-analyzer'
     runs-on: ubuntu-latest
 
     steps:
diff --git a/Cargo.lock b/Cargo.lock
index cea8540936..aeea1d9efa 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -171,9 +171,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
 
 [[package]]
 name = "chalk-derive"
-version = "0.82.0"
+version = "0.81.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ee9cd790d543c29ce953abcb28d54b9fbaf9c4033bfd3024de99b1aa0f3c3ada"
+checksum = "0bb2ca8aa9da8210effebb51e49b4bd8bc25c06df38220d58a60df35a08a84af"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -183,9 +183,9 @@ dependencies = [
 
 [[package]]
 name = "chalk-ir"
-version = "0.82.0"
+version = "0.81.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dddf2c11f9de666c08c7591eb113efcdc740bd8ac602915475b045bcbe7f27a5"
+checksum = "e128fa3652ef2cdd5a7e64e0cc5a89f40170f80dd9f6357ba4a82cf027abd0d5"
 dependencies = [
  "bitflags",
  "chalk-derive",
@@ -194,9 +194,9 @@ dependencies = [
 
 [[package]]
 name = "chalk-recursive"
-version = "0.82.0"
+version = "0.81.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a60d5b35598702963ffd145b8bfa0d8d8ae9da3a731e4e0814aa21541b85c2d5"
+checksum = "ea6fcba1e8b66a291430b6aa18368a95da0577d7f126653baae71c0cb0f3d093"
 dependencies = [
  "chalk-derive",
  "chalk-ir",
@@ -207,9 +207,9 @@ dependencies = [
 
 [[package]]
 name = "chalk-solve"
-version = "0.82.0"
+version = "0.81.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d99da4fa3b224c07f6c2506e6905bca9d6aad665f11d25364e6818a7ea149215"
+checksum = "43151ddc627d8dfbde6af44405cb8e98a15828f66a3d4a3da6a1fad6c5dc4687"
 dependencies = [
  "chalk-derive",
  "chalk-ir",
diff --git a/README.md b/README.md
index 8bb0517ed5..9732b05801 100644
--- a/README.md
+++ b/README.md
@@ -38,7 +38,7 @@ https://rust-lang.zulipchat.com/#narrow/stream/185405-t-compiler.2Frust-analyzer
 
 * Website: https://rust-analyzer.github.io/
 * Metrics: https://rust-analyzer.github.io/metrics/
-* API docs: https://rust-lang.github.io/rust-analyzer/ide/
+* API docs: https://rust-analyzer.github.io/rust-analyzer/ide/
 * Changelog: https://rust-analyzer.github.io/thisweek
 
 ## License
diff --git a/crates/flycheck/src/lib.rs b/crates/flycheck/src/lib.rs
index 2cd1995267..4c84c62016 100644
--- a/crates/flycheck/src/lib.rs
+++ b/crates/flycheck/src/lib.rs
@@ -329,7 +329,7 @@ impl CargoActor {
             Ok(output) if output.status.success() => Ok(()),
             Ok(output)  => {
                 Err(io::Error::new(io::ErrorKind::Other, format!(
-                    "Cargo watcher failed, the command produced no valid metadata (exit code: {:?}):\n{}",
+                    "Cargo watcher failed, the command produced no valid metadata (exit code: {:?})\nCargo's stderr output:\n{}",
                     output.status, error
                 )))
             }
diff --git a/crates/hir_def/src/builtin_type.rs b/crates/hir_def/src/builtin_type.rs
index 25a408036f..7cbaf30b85 100644
--- a/crates/hir_def/src/builtin_type.rs
+++ b/crates/hir_def/src/builtin_type.rs
@@ -68,10 +68,6 @@ impl BuiltinType {
         (name![f32], BuiltinType::Float(BuiltinFloat::F32)),
         (name![f64], BuiltinType::Float(BuiltinFloat::F64)),
     ];
-
-    pub fn by_name(name: &Name) -> Option<Self> {
-        Self::ALL.iter().find_map(|(n, ty)| if n == name { Some(*ty) } else { None })
-    }
 }
 
 impl AsName for BuiltinType {
diff --git a/crates/hir_def/src/item_tree/pretty.rs b/crates/hir_def/src/item_tree/pretty.rs
index f12d9a1273..b24ba61ea0 100644
--- a/crates/hir_def/src/item_tree/pretty.rs
+++ b/crates/hir_def/src/item_tree/pretty.rs
@@ -90,10 +90,11 @@ impl<'a> Printer<'a> {
         for attr in &**attrs {
             wln!(
                 self,
-                "#{}[{}{}]",
+                "#{}[{}{}]  // {:?}",
                 inner,
                 attr.path,
                 attr.input.as_ref().map(|it| it.to_string()).unwrap_or_default(),
+                attr.id,
             );
         }
     }
@@ -241,19 +242,10 @@ impl<'a> Printer<'a> {
                     ast_id: _,
                     flags,
                 } = &self.tree[it];
-                self.print_visibility(*visibility);
-                if flags.contains(FnFlags::HAS_DEFAULT_KW) {
-                    w!(self, "default ");
-                }
-                if flags.contains(FnFlags::HAS_CONST_KW) {
-                    w!(self, "const ");
-                }
-                if flags.contains(FnFlags::HAS_ASYNC_KW) {
-                    w!(self, "async ");
-                }
-                if flags.contains(FnFlags::HAS_UNSAFE_KW) {
-                    w!(self, "unsafe ");
+                if flags.bits != 0 {
+                    wln!(self, "// flags = 0x{:X}", flags.bits);
                 }
+                self.print_visibility(*visibility);
                 if let Some(abi) = abi {
                     w!(self, "extern \"{}\" ", abi);
                 }
@@ -262,7 +254,7 @@ impl<'a> Printer<'a> {
                 w!(self, "(");
                 if !params.is_empty() {
                     self.indented(|this| {
-                        for (i, param) in params.clone().enumerate() {
+                        for param in params.clone() {
                             this.print_attrs_of(param);
                             match &this.tree[param] {
                                 Param::Normal(name, ty) => {
@@ -271,12 +263,7 @@ impl<'a> Printer<'a> {
                                         None => w!(this, "_: "),
                                     }
                                     this.print_type_ref(ty);
-                                    w!(this, ",");
-                                    if flags.contains(FnFlags::HAS_SELF_PARAM) && i == 0 {
-                                        wln!(this, "  // self");
-                                    } else {
-                                        wln!(this);
-                                    }
+                                    wln!(this, ",");
                                 }
                                 Param::Varargs => {
                                     wln!(this, "...");
@@ -288,11 +275,7 @@ impl<'a> Printer<'a> {
                 w!(self, ") -> ");
                 self.print_type_ref(ret_type);
                 self.print_where_clause(explicit_generic_params);
-                if flags.contains(FnFlags::HAS_BODY) {
-                    wln!(self, " {{ ... }}");
-                } else {
-                    wln!(self, ";");
-                }
+                wln!(self, ";");
             }
             ModItem::Struct(it) => {
                 let Struct { visibility, name, fields, generic_params, ast_id: _ } = &self.tree[it];
diff --git a/crates/hir_def/src/resolver.rs b/crates/hir_def/src/resolver.rs
index 2a990765ea..fe0100fb8c 100644
--- a/crates/hir_def/src/resolver.rs
+++ b/crates/hir_def/src/resolver.rs
@@ -317,18 +317,6 @@ impl Resolver {
             }
         }
 
-        // If a path of the shape `u16::from_le_bytes` failed to resolve at all, then we fall back
-        // to resolving to the primitive type, to allow this to still work in the presence of
-        // `use core::u16;`.
-        if path.kind == PathKind::Plain && path.segments().len() > 1 {
-            match BuiltinType::by_name(&path.segments()[0]) {
-                Some(builtin) => {
-                    return Some(ResolveValueResult::Partial(TypeNs::BuiltinType(builtin), 1));
-                }
-                None => {}
-            }
-        }
-
         None
     }
 
diff --git a/crates/hir_expand/src/db.rs b/crates/hir_expand/src/db.rs
index 8c08fdcd2e..e14c669b4c 100644
--- a/crates/hir_expand/src/db.rs
+++ b/crates/hir_expand/src/db.rs
@@ -263,7 +263,7 @@ fn parse_macro_expansion(
                 .collect::<Vec<_>>()
                 .join("\n");
 
-        tracing::debug!(
+        tracing::warn!(
             "fail on macro_parse: (reason: {:?} macro_call: {:#}) parents: {}",
             err,
             node.value,
diff --git a/crates/hir_ty/Cargo.toml b/crates/hir_ty/Cargo.toml
index 1fe5788253..efcd5ffc5e 100644
--- a/crates/hir_ty/Cargo.toml
+++ b/crates/hir_ty/Cargo.toml
@@ -18,9 +18,9 @@ ena = "0.14.0"
 tracing = "0.1.32"
 rustc-hash = "1.1.0"
 scoped-tls = "1.0.0"
-chalk-solve = { version = "0.82.0", default-features = false }
-chalk-ir = "0.82.0"
-chalk-recursive = { version = "0.82.0", default-features = false }
+chalk-solve = { version = "0.81.0", default-features = false }
+chalk-ir = "0.81.0"
+chalk-recursive = { version = "0.81.0", default-features = false }
 la-arena = { version = "0.3.0", path = "../../lib/arena" }
 once_cell = "1.10.0"
 typed-arena = "2.0.1"
diff --git a/crates/hir_ty/src/utils.rs b/crates/hir_ty/src/utils.rs
index bdb7677f5d..0ffd428cff 100644
--- a/crates/hir_ty/src/utils.rs
+++ b/crates/hir_ty/src/utils.rs
@@ -176,22 +176,13 @@ pub(super) fn associated_type_by_name_including_super_traits(
 pub(crate) fn generics(db: &dyn DefDatabase, def: GenericDefId) -> Generics {
     let parent_generics = parent_generic_def(db, def).map(|def| Box::new(generics(db, def)));
     if parent_generics.is_some() && matches!(def, GenericDefId::TypeAliasId(_)) {
-        let params = db.generic_params(def);
-        if params
-            .type_or_consts
-            .iter()
-            .any(|(_, x)| matches!(x, TypeOrConstParamData::ConstParamData(_)))
-        {
-            // XXX: treat const generic associated types as not existing to avoid crashes (#11769)
-            //
-            // Chalk expects the inner associated type's parameters to come
-            // *before*, not after the trait's generics as we've always done it.
-            // Adapting to this requires a larger refactoring
-            cov_mark::hit!(ignore_gats);
-            return Generics { def, params: Interned::new(Default::default()), parent_generics };
-        } else {
-            return Generics { def, params, parent_generics };
-        }
+        // XXX: treat generic associated types as not existing to avoid crashes (#)
+        //
+        // Chalk expects the inner associated type's parameters to come
+        // *before*, not after the trait's generics as we've always done it.
+        // Adapting to this requires a larger refactoring
+        cov_mark::hit!(ignore_gats);
+        return Generics { def, params: Interned::new(Default::default()), parent_generics };
     }
     Generics { def, params: db.generic_params(def), parent_generics }
 }
diff --git a/crates/ide/src/rename.rs b/crates/ide/src/rename.rs
index f5bff5fd91..1bb3cdb907 100644
--- a/crates/ide/src/rename.rs
+++ b/crates/ide/src/rename.rs
@@ -968,21 +968,15 @@ mod fo$0o;
                         },
                     },
                     file_system_edits: [
-                        MoveDir {
-                            src: AnchoredPathBuf {
-                                anchor: FileId(
-                                    1,
-                                ),
-                                path: "foo",
-                            },
-                            src_id: FileId(
+                        MoveFile {
+                            src: FileId(
                                 1,
                             ),
                             dst: AnchoredPathBuf {
                                 anchor: FileId(
                                     1,
                                 ),
-                                path: "foo2",
+                                path: "../foo2/mod.rs",
                             },
                         },
                     ],
@@ -1119,68 +1113,6 @@ pub mod foo$0;
         );
     }
 
-    #[test]
-    fn test_rename_mod_recursive() {
-        check_expect(
-            "foo2",
-            r#"
-//- /lib.rs
-mod foo$0;
-
-//- /foo.rs
-mod bar;
-mod corge;
-
-//- /foo/bar.rs
-mod qux;
-
-//- /foo/bar/qux.rs
-mod quux;
-
-//- /foo/bar/qux/quux/mod.rs
-// empty
-
-//- /foo/corge.rs
-// empty
-"#,
-            expect![[r#"
-                SourceChange {
-                    source_file_edits: {
-                        FileId(
-                            0,
-                        ): TextEdit {
-                            indels: [
-                                Indel {
-                                    insert: "foo2",
-                                    delete: 4..7,
-                                },
-                            ],
-                        },
-                    },
-                    file_system_edits: [
-                        MoveDir {
-                            src: AnchoredPathBuf {
-                                anchor: FileId(
-                                    1,
-                                ),
-                                path: "foo",
-                            },
-                            src_id: FileId(
-                                1,
-                            ),
-                            dst: AnchoredPathBuf {
-                                anchor: FileId(
-                                    1,
-                                ),
-                                path: "foo2",
-                            },
-                        },
-                    ],
-                    is_snippet: false,
-                }
-            "#]],
-        )
-    }
     #[test]
     fn test_rename_mod_ref_by_super() {
         check(
diff --git a/crates/ide/src/typing.rs b/crates/ide/src/typing.rs
index a75e6be8b8..0095012791 100644
--- a/crates/ide/src/typing.rs
+++ b/crates/ide/src/typing.rs
@@ -39,11 +39,8 @@ pub(crate) const TRIGGER_CHARS: &str = ".=>{";
 // Some features trigger on typing certain characters:
 //
 // - typing `let =` tries to smartly add `;` if `=` is followed by an existing expression
-// - typing `=` between two expressions adds `;` when in statement position
-// - typing `=` to turn an assignment into an equality comparison removes `;` when in expression position
 // - typing `.` in a chain method call auto-indents
 // - typing `{` in front of an expression inserts a closing `}` after the expression
-// - typing `{` in a use item adds a closing `}` in the right place
 //
 // VS Code::
 //
@@ -169,73 +166,11 @@ fn on_eq_typed(file: &SourceFile, offset: TextSize) -> Option<TextEdit> {
     if !stdx::always!(file.syntax().text().char_at(offset) == Some('=')) {
         return None;
     }
-
-    if let Some(edit) = let_stmt(file, offset) {
-        return Some(edit);
-    }
-    if let Some(edit) = assign_expr(file, offset) {
-        return Some(edit);
-    }
-    if let Some(edit) = assign_to_eq(file, offset) {
-        return Some(edit);
-    }
-
-    return None;
-
-    fn assign_expr(file: &SourceFile, offset: TextSize) -> Option<TextEdit> {
-        let binop: ast::BinExpr = find_node_at_offset(file.syntax(), offset)?;
-        if !matches!(binop.op_kind(), Some(ast::BinaryOp::Assignment { op: None })) {
-            return None;
-        }
-
-        // Parent must be `ExprStmt` or `StmtList` for `;` to be valid.
-        if let Some(expr_stmt) = ast::ExprStmt::cast(binop.syntax().parent()?) {
-            if expr_stmt.semicolon_token().is_some() {
-                return None;
-            }
-        } else {
-            if !ast::StmtList::can_cast(binop.syntax().parent()?.kind()) {
-                return None;
-            }
-        }
-
-        let expr = binop.rhs()?;
-        let expr_range = expr.syntax().text_range();
-        if expr_range.contains(offset) && offset != expr_range.start() {
-            return None;
-        }
-        if file.syntax().text().slice(offset..expr_range.start()).contains_char('\n') {
-            return None;
-        }
-        let offset = expr.syntax().text_range().end();
-        Some(TextEdit::insert(offset, ";".to_string()))
-    }
-
-    /// `a =$0 b;` removes the semicolon if an expression is valid in this context.
-    fn assign_to_eq(file: &SourceFile, offset: TextSize) -> Option<TextEdit> {
-        let binop: ast::BinExpr = find_node_at_offset(file.syntax(), offset)?;
-        if !matches!(binop.op_kind(), Some(ast::BinaryOp::CmpOp(ast::CmpOp::Eq { negated: false })))
-        {
-            return None;
-        }
-
-        let expr_stmt = ast::ExprStmt::cast(binop.syntax().parent()?)?;
-        let semi = expr_stmt.semicolon_token()?;
-
-        if expr_stmt.syntax().next_sibling().is_some() {
-            // Not the last statement in the list.
-            return None;
-        }
-
-        Some(TextEdit::delete(semi.text_range()))
+    let let_stmt: ast::LetStmt = find_node_at_offset(file.syntax(), offset)?;
+    if let_stmt.semicolon_token().is_some() {
+        return None;
     }
-
-    fn let_stmt(file: &SourceFile, offset: TextSize) -> Option<TextEdit> {
-        let let_stmt: ast::LetStmt = find_node_at_offset(file.syntax(), offset)?;
-        if let_stmt.semicolon_token().is_some() {
-            return None;
-        }
-        let expr = let_stmt.initializer()?;
+    if let Some(expr) = let_stmt.initializer() {
         let expr_range = expr.syntax().text_range();
         if expr_range.contains(offset) && offset != expr_range.start() {
             return None;
@@ -243,9 +178,11 @@ fn on_eq_typed(file: &SourceFile, offset: TextSize) -> Option<TextEdit> {
         if file.syntax().text().slice(offset..expr_range.start()).contains_char('\n') {
             return None;
         }
-        let offset = let_stmt.syntax().text_range().end();
-        Some(TextEdit::insert(offset, ";".to_string()))
+    } else {
+        return None;
     }
+    let offset = let_stmt.syntax().text_range().end();
+    Some(TextEdit::insert(offset, ";".to_string()))
 }
 
 /// Returns an edit which should be applied when a dot ('.') is typed on a blank line, indenting the line appropriately.
@@ -349,7 +286,7 @@ mod tests {
     }
 
     #[test]
-    fn test_semi_after_let() {
+    fn test_on_eq_typed() {
         //     do_check(r"
         // fn foo() {
         //     let foo =$0
@@ -385,117 +322,6 @@ fn foo() {
         // ");
     }
 
-    #[test]
-    fn test_semi_after_assign() {
-        type_char(
-            '=',
-            r#"
-fn f() {
-    i $0 0
-}
-"#,
-            r#"
-fn f() {
-    i = 0;
-}
-"#,
-        );
-        type_char(
-            '=',
-            r#"
-fn f() {
-    i $0 0
-    i
-}
-"#,
-            r#"
-fn f() {
-    i = 0;
-    i
-}
-"#,
-        );
-        type_char_noop(
-            '=',
-            r#"
-fn f(x: u8) {
-    if x $0
-}
-"#,
-        );
-        type_char_noop(
-            '=',
-            r#"
-fn f(x: u8) {
-    if x $0 {}
-}
-"#,
-        );
-        type_char_noop(
-            '=',
-            r#"
-fn f(x: u8) {
-    if x $0 0 {}
-}
-"#,
-        );
-        type_char_noop(
-            '=',
-            r#"
-fn f() {
-    g(i $0 0);
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn assign_to_eq() {
-        type_char(
-            '=',
-            r#"
-fn f(a: u8) {
-    a =$0 0;
-}
-"#,
-            r#"
-fn f(a: u8) {
-    a == 0
-}
-"#,
-        );
-        type_char(
-            '=',
-            r#"
-fn f(a: u8) {
-    a $0= 0;
-}
-"#,
-            r#"
-fn f(a: u8) {
-    a == 0
-}
-"#,
-        );
-        type_char_noop(
-            '=',
-            r#"
-fn f(a: u8) {
-    let e = a =$0 0;
-}
-"#,
-        );
-        type_char_noop(
-            '=',
-            r#"
-fn f(a: u8) {
-    let e = a =$0 0;
-    e
-}
-"#,
-        );
-    }
-
     #[test]
     fn indents_new_chain_call() {
         type_char(
diff --git a/crates/ide_assists/src/handlers/expand_glob_import.rs b/crates/ide_assists/src/handlers/expand_glob_import.rs
index ba5a47f4df..3566b1be89 100644
--- a/crates/ide_assists/src/handlers/expand_glob_import.rs
+++ b/crates/ide_assists/src/handlers/expand_glob_import.rs
@@ -52,7 +52,7 @@ pub(crate) fn expand_glob_import(acc: &mut Assists, ctx: &AssistContext) -> Opti
     let current_scope = ctx.sema.scope(&star.parent()?)?;
     let current_module = current_scope.module();
 
-    let refs_in_target = find_refs_in_mod(ctx, target_module, current_module)?;
+    let refs_in_target = find_refs_in_mod(ctx, target_module, Some(current_module))?;
     let imported_defs = find_imported_defs(ctx, star)?;
 
     let target = parent.either(|n| n.syntax().clone(), |n| n.syntax().clone());
@@ -168,12 +168,18 @@ impl Refs {
     }
 }
 
-fn find_refs_in_mod(ctx: &AssistContext, module: Module, visible_from: Module) -> Option<Refs> {
-    if !is_mod_visible_from(ctx, module, visible_from) {
-        return None;
+fn find_refs_in_mod(
+    ctx: &AssistContext,
+    module: Module,
+    visible_from: Option<Module>,
+) -> Option<Refs> {
+    if let Some(from) = visible_from {
+        if !is_mod_visible_from(ctx, module, from) {
+            return None;
+        }
     }
 
-    let module_scope = module.scope(ctx.db(), Some(visible_from));
+    let module_scope = module.scope(ctx.db(), visible_from);
     let refs = module_scope.into_iter().filter_map(|(n, d)| Ref::from_scope_def(n, d)).collect();
     Some(Refs(refs))
 }
@@ -723,34 +729,37 @@ fn qux(bar: Bar, baz: Baz) {
 
     #[test]
     fn expanding_glob_import_with_macro_defs() {
-        check_assist(
-            expand_glob_import,
-            r#"
-//- /lib.rs crate:foo
-#[macro_export]
-macro_rules! bar {
-    () => ()
-}
-
-pub fn baz() {}
-
-//- /main.rs crate:main deps:foo
-use foo::*$0;
-
-fn main() {
-    bar!();
-    baz();
-}
-"#,
-            r#"
-use foo::{bar, baz};
-
-fn main() {
-    bar!();
-    baz();
-}
-"#,
-        );
+        // FIXME: this is currently fails because `Definition::find_usages` ignores macros
+        //       https://github.com/rust-analyzer/rust-analyzer/issues/3484
+        //
+        //         check_assist(
+        //             expand_glob_import,
+        //             r"
+        // //- /lib.rs crate:foo
+        // #[macro_export]
+        // macro_rules! bar {
+        //     () => ()
+        // }
+
+        // pub fn baz() {}
+
+        // //- /main.rs crate:main deps:foo
+        // use foo::*$0;
+
+        // fn main() {
+        //     bar!();
+        //     baz();
+        // }
+        // ",
+        //             r"
+        // use foo::{bar, baz};
+
+        // fn main() {
+        //     bar!();
+        //     baz();
+        // }
+        // ",
+        //         )
     }
 
     #[test]
diff --git a/crates/ide_completion/src/completions.rs b/crates/ide_completion/src/completions.rs
index b8a904a3a0..7dbc511395 100644
--- a/crates/ide_completion/src/completions.rs
+++ b/crates/ide_completion/src/completions.rs
@@ -126,7 +126,7 @@ impl Completions {
             cov_mark::hit!(qualified_path_doc_hidden);
             return;
         }
-        self.add(render_resolution(RenderContext::new(ctx), local_name, resolution).build());
+        self.add(render_resolution(RenderContext::new(ctx), local_name, resolution));
     }
 
     pub(crate) fn add_resolution_simple(
@@ -138,7 +138,7 @@ impl Completions {
         if ctx.is_scope_def_hidden(resolution) {
             return;
         }
-        self.add(render_resolution_simple(RenderContext::new(ctx), local_name, resolution).build());
+        self.add(render_resolution_simple(RenderContext::new(ctx), local_name, resolution));
     }
 
     pub(crate) fn add_macro(
@@ -152,14 +152,11 @@ impl Completions {
             Visible::Editable => true,
             Visible::No => return,
         };
-        self.add(
-            render_macro(
-                RenderContext::new(ctx).private_editable(is_private_editable),
-                local_name,
-                mac,
-            )
-            .build(),
-        );
+        self.add(render_macro(
+            RenderContext::new(ctx).private_editable(is_private_editable),
+            local_name,
+            mac,
+        ));
     }
 
     pub(crate) fn add_function(
@@ -173,14 +170,11 @@ impl Completions {
             Visible::Editable => true,
             Visible::No => return,
         };
-        self.add(
-            render_fn(
-                RenderContext::new(ctx).private_editable(is_private_editable),
-                local_name,
-                func,
-            )
-            .build(),
-        );
+        self.add(render_fn(
+            RenderContext::new(ctx).private_editable(is_private_editable),
+            local_name,
+            func,
+        ));
     }
 
     pub(crate) fn add_method(
@@ -195,15 +189,12 @@ impl Completions {
             Visible::Editable => true,
             Visible::No => return,
         };
-        self.add(
-            render_method(
-                RenderContext::new(ctx).private_editable(is_private_editable),
-                receiver,
-                local_name,
-                func,
-            )
-            .build(),
-        );
+        self.add(render_method(
+            RenderContext::new(ctx).private_editable(is_private_editable),
+            receiver,
+            local_name,
+            func,
+        ));
     }
 
     pub(crate) fn add_const(&mut self, ctx: &CompletionContext, konst: hir::Const) {
@@ -244,11 +235,7 @@ impl Completions {
         variant: hir::Variant,
         path: hir::ModPath,
     ) {
-        if let Some(builder) =
-            render_variant_lit(RenderContext::new(ctx), None, variant, Some(path))
-        {
-            self.add(builder.build());
-        }
+        self.add_opt(render_variant_lit(RenderContext::new(ctx), None, variant, Some(path)));
     }
 
     pub(crate) fn add_enum_variant(
@@ -257,11 +244,7 @@ impl Completions {
         variant: hir::Variant,
         local_name: Option<hir::Name>,
     ) {
-        if let Some(builder) =
-            render_variant_lit(RenderContext::new(ctx), local_name, variant, None)
-        {
-            self.add(builder.build());
-        }
+        self.add_opt(render_variant_lit(RenderContext::new(ctx), local_name, variant, None));
     }
 
     pub(crate) fn add_field(
@@ -292,11 +275,8 @@ impl Completions {
         path: Option<hir::ModPath>,
         local_name: Option<hir::Name>,
     ) {
-        if let Some(builder) =
-            render_struct_literal(RenderContext::new(ctx), strukt, path, local_name)
-        {
-            self.add(builder.build());
-        }
+        let item = render_struct_literal(RenderContext::new(ctx), strukt, path, local_name);
+        self.add_opt(item);
     }
 
     pub(crate) fn add_union_literal(
diff --git a/crates/ide_completion/src/completions/flyimport.rs b/crates/ide_completion/src/completions/flyimport.rs
index 76d708ae51..fb857aeccd 100644
--- a/crates/ide_completion/src/completions/flyimport.rs
+++ b/crates/ide_completion/src/completions/flyimport.rs
@@ -205,8 +205,7 @@ pub(crate) fn import_on_the_fly(acc: &mut Completions, ctx: &CompletionContext)
                     &user_input_lowercased,
                 )
             })
-            .filter_map(|import| render_resolution_with_import(RenderContext::new(ctx), import))
-            .map(|builder| builder.build()),
+            .filter_map(|import| render_resolution_with_import(RenderContext::new(ctx), import)),
     );
     Some(())
 }
diff --git a/crates/ide_completion/src/completions/keyword.rs b/crates/ide_completion/src/completions/keyword.rs
index 51405e3523..ac782352fc 100644
--- a/crates/ide_completion/src/completions/keyword.rs
+++ b/crates/ide_completion/src/completions/keyword.rs
@@ -86,7 +86,7 @@ pub(crate) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionConte
         add_keyword("mod", "mod $0");
     }
 
-    if expects_item || has_block_expr_parent {
+    if expects_item {
         add_keyword("enum", "enum $1 {\n    $0\n}");
         add_keyword("struct", "struct $0");
         add_keyword("union", "union $1 {\n    $0\n}");
diff --git a/crates/ide_completion/src/completions/trait_impl.rs b/crates/ide_completion/src/completions/trait_impl.rs
index 43428f777f..13e05049e2 100644
--- a/crates/ide_completion/src/completions/trait_impl.rs
+++ b/crates/ide_completion/src/completions/trait_impl.rs
@@ -167,7 +167,7 @@ fn add_function_impl(
     };
 
     let mut item = CompletionItem::new(completion_kind, replacement_range, label);
-    item.lookup_by(format!("fn {}", fn_name))
+    item.lookup_by(fn_name)
         .set_documentation(func.docs(ctx.db))
         .set_relevance(CompletionRelevance { is_item_from_trait: true, ..Default::default() });
 
@@ -228,17 +228,13 @@ fn add_type_alias_impl(
     let alias_name = type_alias.name(ctx.db).to_smol_str();
 
     let label = format!("type {} =", alias_name);
-    let replacement = format!("type {} = ", alias_name);
+    let snippet = format!("type {} = ", alias_name);
 
     let mut item = CompletionItem::new(SymbolKind::TypeAlias, replacement_range, label);
-    item.lookup_by(format!("type {}", alias_name))
+    item.text_edit(TextEdit::replace(replacement_range, snippet))
+        .lookup_by(alias_name)
         .set_documentation(type_alias.docs(ctx.db))
         .set_relevance(CompletionRelevance { is_item_from_trait: true, ..Default::default() });
-    match ctx.config.snippet_cap {
-        Some(cap) => item
-            .snippet_edit(cap, TextEdit::replace(replacement_range, format!("{}$0;", replacement))),
-        None => item.text_edit(TextEdit::replace(replacement_range, replacement)),
-    };
     item.add_to(acc);
 }
 
@@ -261,22 +257,16 @@ fn add_const_impl(
                 };
 
                 let label = make_const_compl_syntax(&transformed_const);
-                let replacement = format!("{} ", label);
+                let snippet = format!("{} ", label);
 
                 let mut item = CompletionItem::new(SymbolKind::Const, replacement_range, label);
-                item.lookup_by(format!("const {}", const_name))
+                item.text_edit(TextEdit::replace(replacement_range, snippet))
+                    .lookup_by(const_name)
                     .set_documentation(const_.docs(ctx.db))
                     .set_relevance(CompletionRelevance {
                         is_item_from_trait: true,
                         ..Default::default()
                     });
-                match ctx.config.snippet_cap {
-                    Some(cap) => item.snippet_edit(
-                        cap,
-                        TextEdit::replace(replacement_range, format!("{}$0;", replacement)),
-                    ),
-                    None => item.text_edit(TextEdit::replace(replacement_range, replacement)),
-                };
                 item.add_to(acc);
             }
         }
@@ -559,7 +549,7 @@ impl Test for T {
     #[test]
     fn name_ref_single_function() {
         check_edit(
-            "fn test",
+            "test",
             r#"
 trait Test {
     fn test();
@@ -588,7 +578,7 @@ impl Test for T {
     #[test]
     fn single_function() {
         check_edit(
-            "fn test",
+            "test",
             r#"
 trait Test {
     fn test();
@@ -617,7 +607,7 @@ impl Test for T {
     #[test]
     fn generic_fn() {
         check_edit(
-            "fn foo",
+            "foo",
             r#"
 trait Test {
     fn foo<T>();
@@ -642,7 +632,7 @@ impl Test for T {
 "#,
         );
         check_edit(
-            "fn foo",
+            "foo",
             r#"
 trait Test {
     fn foo<T>() where T: Into<String>;
@@ -672,7 +662,7 @@ where T: Into<String> {
     #[test]
     fn associated_type() {
         check_edit(
-            "type SomeType",
+            "SomeType",
             r#"
 trait Test {
     type SomeType;
@@ -688,7 +678,7 @@ trait Test {
 }
 
 impl Test for () {
-    type SomeType = $0;\n\
+    type SomeType = \n\
 }
 ",
         );
@@ -697,7 +687,7 @@ impl Test for () {
     #[test]
     fn associated_const() {
         check_edit(
-            "const SOME_CONST",
+            "SOME_CONST",
             r#"
 trait Test {
     const SOME_CONST: u16;
@@ -713,13 +703,13 @@ trait Test {
 }
 
 impl Test for () {
-    const SOME_CONST: u16 = $0;\n\
+    const SOME_CONST: u16 = \n\
 }
 ",
         );
 
         check_edit(
-            "const SOME_CONST",
+            "SOME_CONST",
             r#"
 trait Test {
     const SOME_CONST: u16 = 92;
@@ -735,7 +725,7 @@ trait Test {
 }
 
 impl Test for () {
-    const SOME_CONST: u16 = $0;\n\
+    const SOME_CONST: u16 = \n\
 }
 ",
         );
@@ -793,9 +783,9 @@ impl Test for T {{
             "default type OtherType = i32;",
             "default const OTHER_CONST: i32 = 0;",
         ] {
-            test("fn bar", "fn $0", "fn bar() {\n    $0\n}", next_sibling);
-            test("type Foo", "type $0", "type Foo = $0;", next_sibling);
-            test("const CONST", "const $0", "const CONST: u16 = $0;", next_sibling);
+            test("bar", "fn $0", "fn bar() {\n    $0\n}", next_sibling);
+            test("Foo", "type $0", "type Foo = ", next_sibling);
+            test("CONST", "const $0", "const CONST: u16 = ", next_sibling);
         }
     }
 
@@ -840,15 +830,15 @@ impl Foo for T {{
                 ),
             )
         };
-        test("fn function", "fn f$0", "fn function() {\n    $0\n}");
-        test("type Type", "type T$0", "type Type = $0;");
-        test("const CONST", "const C$0", "const CONST: i32 = $0;");
+        test("function", "fn f$0", "fn function() {\n    $0\n}");
+        test("Type", "type T$0", "type Type = ");
+        test("CONST", "const C$0", "const CONST: i32 = ");
     }
 
     #[test]
     fn generics_are_inlined_in_return_type() {
         check_edit(
-            "fn function",
+            "function",
             r#"
 trait Foo<T> {
     fn function() -> T;
@@ -877,7 +867,7 @@ impl Foo<u32> for Bar {
     #[test]
     fn generics_are_inlined_in_parameter() {
         check_edit(
-            "fn function",
+            "function",
             r#"
 trait Foo<T> {
     fn function(bar: T);
@@ -906,7 +896,7 @@ impl Foo<u32> for Bar {
     #[test]
     fn generics_are_inlined_when_part_of_other_types() {
         check_edit(
-            "fn function",
+            "function",
             r#"
 trait Foo<T> {
     fn function(bar: Vec<T>);
@@ -935,7 +925,7 @@ impl Foo<u32> for Bar {
     #[test]
     fn generics_are_inlined_complex() {
         check_edit(
-            "fn function",
+            "function",
             r#"
 trait Foo<T, U, V> {
     fn function(bar: Vec<T>, baz: U) -> Arc<Vec<V>>;
@@ -964,7 +954,7 @@ impl Foo<u32, Vec<usize>, u8> for Bar {
     #[test]
     fn generics_are_inlined_in_associated_const() {
         check_edit(
-            "const BAR",
+            "BAR",
             r#"
 trait Foo<T> {
     const BAR: T;
@@ -972,7 +962,7 @@ trait Foo<T> {
 struct Bar;
 
 impl Foo<u32> for Bar {
-    const B$0
+    const B$0;
 }
 "#,
             r#"
@@ -982,7 +972,7 @@ trait Foo<T> {
 struct Bar;
 
 impl Foo<u32> for Bar {
-    const BAR: u32 = $0;
+    const BAR: u32 = ;
 }
 "#,
         )
@@ -991,7 +981,7 @@ impl Foo<u32> for Bar {
     #[test]
     fn generics_are_inlined_in_where_clause() {
         check_edit(
-            "fn function",
+            "function",
             r#"
 trait SomeTrait<T> {}
 
diff --git a/crates/ide_completion/src/completions/use_.rs b/crates/ide_completion/src/completions/use_.rs
index 3f757f9816..d7c279f9d9 100644
--- a/crates/ide_completion/src/completions/use_.rs
+++ b/crates/ide_completion/src/completions/use_.rs
@@ -1,13 +1,11 @@
 //! Completion for use trees
 
 use hir::ScopeDef;
-use rustc_hash::FxHashSet;
 use syntax::{ast, AstNode};
 
 use crate::{
     context::{CompletionContext, PathCompletionCtx, PathKind, PathQualifierCtx},
-    item::Builder,
-    CompletionRelevance, Completions,
+    Completions,
 };
 
 pub(crate) fn complete_use_tree(acc: &mut Completions, ctx: &CompletionContext) {
@@ -41,22 +39,6 @@ pub(crate) fn complete_use_tree(acc: &mut Completions, ctx: &CompletionContext)
                 None => return,
             };
 
-            let mut already_imported_names = FxHashSet::default();
-            if let Some(list) = ctx.token.ancestors().find_map(ast::UseTreeList::cast) {
-                let use_tree = list.parent_use_tree();
-                if use_tree.path().as_ref() == Some(path) {
-                    for tree in list.use_trees() {
-                        if tree.is_simple_path() {
-                            if let Some(name) =
-                                tree.path().and_then(|path| path.as_single_name_ref())
-                            {
-                                already_imported_names.insert(name.to_string());
-                            }
-                        }
-                    }
-                }
-            }
-
             match resolution {
                 hir::PathResolution::Def(hir::ModuleDef::Module(module)) => {
                     let module_scope = module.scope(ctx.db, Some(ctx.module));
@@ -68,9 +50,6 @@ pub(crate) fn complete_use_tree(acc: &mut Completions, ctx: &CompletionContext)
                         )
                     };
                     for (name, def) in module_scope {
-                        let is_name_already_imported =
-                            already_imported_names.contains(name.as_text().unwrap().as_str());
-
                         let add_resolution = match def {
                             ScopeDef::Unknown if unknown_is_current(&name) => {
                                 // for `use self::foo$0`, don't suggest `foo` as a completion
@@ -82,12 +61,7 @@ pub(crate) fn complete_use_tree(acc: &mut Completions, ctx: &CompletionContext)
                         };
 
                         if add_resolution {
-                            let mut builder = Builder::from_resolution(ctx, name, def);
-                            builder.set_relevance(CompletionRelevance {
-                                is_name_already_imported,
-                                ..Default::default()
-                            });
-                            acc.add(builder.build());
+                            acc.add_resolution(ctx, name, def);
                         }
                     }
                 }
diff --git a/crates/ide_completion/src/item.rs b/crates/ide_completion/src/item.rs
index 41fae38da1..2fa8f77264 100644
--- a/crates/ide_completion/src/item.rs
+++ b/crates/ide_completion/src/item.rs
@@ -9,11 +9,6 @@ use stdx::{impl_from, never};
 use syntax::{SmolStr, TextRange};
 use text_edit::TextEdit;
 
-use crate::{
-    context::CompletionContext,
-    render::{render_resolution, RenderContext},
-};
-
 /// `CompletionItem` describes a single completion variant in the editor pop-up.
 /// It is basically a POD with various properties. To construct a
 /// `CompletionItem`, use `new` method and the `Builder` struct.
@@ -139,8 +134,6 @@ pub struct CompletionRelevance {
     pub is_local: bool,
     /// This is set when trait items are completed in an impl of that trait.
     pub is_item_from_trait: bool,
-    /// This is set when an import is suggested whose name is already imported.
-    pub is_name_already_imported: bool,
     /// Set for method completions of the `core::ops` and `core::cmp` family.
     pub is_op_method: bool,
     /// Set for item completions that are private but in the workspace.
@@ -207,7 +200,6 @@ impl CompletionRelevance {
             type_match,
             is_local,
             is_item_from_trait,
-            is_name_already_imported,
             is_op_method,
             is_private_editable,
             postfix_match,
@@ -222,10 +214,6 @@ impl CompletionRelevance {
         if !is_op_method {
             score += 10;
         }
-        // lower rank for conflicting import names
-        if !is_name_already_imported {
-            score += 1;
-        }
         if exact_name_match {
             score += 10;
         }
@@ -336,7 +324,7 @@ impl CompletionItem {
             kind: kind.into(),
             text_edit: None,
             deprecated: false,
-            trigger_call_info: false,
+            trigger_call_info: None,
             relevance: CompletionRelevance::default(),
             ref_match: None,
             imports_to_add: Default::default(),
@@ -419,20 +407,12 @@ pub(crate) struct Builder {
     kind: CompletionItemKind,
     text_edit: Option<TextEdit>,
     deprecated: bool,
-    trigger_call_info: bool,
+    trigger_call_info: Option<bool>,
     relevance: CompletionRelevance,
     ref_match: Option<Mutability>,
 }
 
 impl Builder {
-    pub(crate) fn from_resolution(
-        ctx: &CompletionContext,
-        local_name: hir::Name,
-        resolution: hir::ScopeDef,
-    ) -> Self {
-        render_resolution(RenderContext::new(ctx), local_name, resolution)
-    }
-
     pub(crate) fn build(self) -> CompletionItem {
         let _p = profile::span("item::Builder::build");
 
@@ -465,7 +445,7 @@ impl Builder {
             lookup,
             kind: self.kind,
             deprecated: self.deprecated,
-            trigger_call_info: self.trigger_call_info,
+            trigger_call_info: self.trigger_call_info.unwrap_or(false),
             relevance: self.relevance,
             ref_match: self.ref_match,
             import_to_add: self.imports_to_add,
@@ -533,7 +513,7 @@ impl Builder {
         self
     }
     pub(crate) fn trigger_call_info(&mut self) -> &mut Builder {
-        self.trigger_call_info = true;
+        self.trigger_call_info = Some(true);
         self
     }
     pub(crate) fn add_import(&mut self, import_to_add: LocatedImport) -> &mut Builder {
diff --git a/crates/ide_completion/src/render.rs b/crates/ide_completion/src/render.rs
index 810ef63ec3..5b0257f6b4 100644
--- a/crates/ide_completion/src/render.rs
+++ b/crates/ide_completion/src/render.rs
@@ -18,7 +18,7 @@ use syntax::{SmolStr, SyntaxKind, TextRange};
 
 use crate::{
     context::{PathCompletionCtx, PathKind},
-    item::{Builder, CompletionRelevanceTypeMatch},
+    item::CompletionRelevanceTypeMatch,
     render::{function::render_fn, literal::render_variant_lit, macro_::render_macro},
     CompletionContext, CompletionItem, CompletionItemKind, CompletionRelevance,
 };
@@ -144,7 +144,7 @@ pub(crate) fn render_resolution(
     ctx: RenderContext<'_>,
     local_name: hir::Name,
     resolution: ScopeDef,
-) -> Builder {
+) -> CompletionItem {
     render_resolution_(ctx, local_name, None, resolution)
 }
 
@@ -152,14 +152,14 @@ pub(crate) fn render_resolution_simple(
     ctx: RenderContext<'_>,
     local_name: hir::Name,
     resolution: ScopeDef,
-) -> Builder {
+) -> CompletionItem {
     render_resolution_simple_(ctx, local_name, None, resolution)
 }
 
 pub(crate) fn render_resolution_with_import(
     ctx: RenderContext<'_>,
     import_edit: LocatedImport,
-) -> Option<Builder> {
+) -> Option<CompletionItem> {
     let resolution = ScopeDef::from(import_edit.original_item);
     let local_name = match resolution {
         ScopeDef::ModuleDef(hir::ModuleDef::Function(f)) => f.name(ctx.completion.db),
@@ -182,7 +182,7 @@ fn render_resolution_(
     local_name: hir::Name,
     import_to_add: Option<LocatedImport>,
     resolution: ScopeDef,
-) -> Builder {
+) -> CompletionItem {
     let _p = profile::span("render_resolution");
     use hir::ModuleDef::*;
 
@@ -211,7 +211,7 @@ fn render_resolution_simple_(
     local_name: hir::Name,
     import_to_add: Option<LocatedImport>,
     resolution: ScopeDef,
-) -> Builder {
+) -> CompletionItem {
     let _p = profile::span("render_resolution");
     use hir::ModuleDef::*;
 
@@ -292,7 +292,7 @@ fn render_resolution_simple_(
     if let Some(import_to_add) = ctx.import_to_add {
         item.add_import(import_to_add);
     }
-    item
+    item.build()
 }
 
 fn scope_def_docs(db: &RootDatabase, resolution: ScopeDef) -> Option<hir::Documentation> {
@@ -625,7 +625,6 @@ fn main() { let _: m::Spam = S$0 }
                             ),
                             is_local: false,
                             is_item_from_trait: false,
-                            is_name_already_imported: false,
                             is_op_method: false,
                             is_private_editable: false,
                             postfix_match: None,
@@ -649,7 +648,6 @@ fn main() { let _: m::Spam = S$0 }
                             ),
                             is_local: false,
                             is_item_from_trait: false,
-                            is_name_already_imported: false,
                             is_op_method: false,
                             is_private_editable: false,
                             postfix_match: None,
@@ -739,7 +737,6 @@ fn foo() { A { the$0 } }
                             ),
                             is_local: false,
                             is_item_from_trait: false,
-                            is_name_already_imported: false,
                             is_op_method: false,
                             is_private_editable: false,
                             postfix_match: None,
diff --git a/crates/ide_completion/src/render/function.rs b/crates/ide_completion/src/render/function.rs
index 38520e1832..211aa432c7 100644
--- a/crates/ide_completion/src/render/function.rs
+++ b/crates/ide_completion/src/render/function.rs
@@ -22,7 +22,7 @@ pub(crate) fn render_fn(
     ctx: RenderContext<'_>,
     local_name: Option<hir::Name>,
     func: hir::Function,
-) -> Builder {
+) -> CompletionItem {
     let _p = profile::span("render_fn");
     render(ctx, local_name, func, FuncKind::Function)
 }
@@ -32,7 +32,7 @@ pub(crate) fn render_method(
     receiver: Option<hir::Name>,
     local_name: Option<hir::Name>,
     func: hir::Function,
-) -> Builder {
+) -> CompletionItem {
     let _p = profile::span("render_method");
     render(ctx, local_name, func, FuncKind::Method(receiver))
 }
@@ -42,7 +42,7 @@ fn render(
     local_name: Option<hir::Name>,
     func: hir::Function,
     func_kind: FuncKind,
-) -> Builder {
+) -> CompletionItem {
     let db = completion.db;
 
     let name = local_name.unwrap_or_else(|| func.name(db));
@@ -107,7 +107,7 @@ fn render(
             }
         }
     }
-    item
+    item.build()
 }
 
 pub(super) fn add_call_parens<'b>(
diff --git a/crates/ide_completion/src/render/literal.rs b/crates/ide_completion/src/render/literal.rs
index f1773137fe..e65631712e 100644
--- a/crates/ide_completion/src/render/literal.rs
+++ b/crates/ide_completion/src/render/literal.rs
@@ -5,7 +5,7 @@ use ide_db::SymbolKind;
 
 use crate::{
     context::{CompletionContext, PathCompletionCtx},
-    item::{Builder, CompletionItem},
+    item::CompletionItem,
     render::{
         compute_ref_match, compute_type_match,
         variant::{
@@ -22,7 +22,7 @@ pub(crate) fn render_variant_lit(
     local_name: Option<hir::Name>,
     variant: hir::Variant,
     path: Option<hir::ModPath>,
-) -> Option<Builder> {
+) -> Option<CompletionItem> {
     let _p = profile::span("render_enum_variant");
     let db = ctx.db();
 
@@ -35,7 +35,7 @@ pub(crate) fn render_struct_literal(
     strukt: hir::Struct,
     path: Option<hir::ModPath>,
     local_name: Option<hir::Name>,
-) -> Option<Builder> {
+) -> Option<CompletionItem> {
     let _p = profile::span("render_struct_literal");
     let db = ctx.db();
 
@@ -48,7 +48,7 @@ fn render(
     thing: Variant,
     name: hir::Name,
     path: Option<hir::ModPath>,
-) -> Option<Builder> {
+) -> Option<CompletionItem> {
     let db = completion.db;
     let kind = thing.kind(db);
     let has_call_parens =
@@ -112,7 +112,7 @@ fn render(
     if let Some(import_to_add) = ctx.import_to_add {
         item.add_import(import_to_add);
     }
-    Some(item)
+    Some(item.build())
 }
 
 #[derive(Clone, Copy)]
diff --git a/crates/ide_completion/src/render/macro_.rs b/crates/ide_completion/src/render/macro_.rs
index ba18e5d216..9f848febeb 100644
--- a/crates/ide_completion/src/render/macro_.rs
+++ b/crates/ide_completion/src/render/macro_.rs
@@ -4,13 +4,13 @@ use hir::{Documentation, HirDisplay};
 use ide_db::SymbolKind;
 use syntax::SmolStr;
 
-use crate::{
-    context::PathKind,
-    item::{Builder, CompletionItem},
-    render::RenderContext,
-};
+use crate::{context::PathKind, item::CompletionItem, render::RenderContext};
 
-pub(crate) fn render_macro(ctx: RenderContext<'_>, name: hir::Name, macro_: hir::Macro) -> Builder {
+pub(crate) fn render_macro(
+    ctx: RenderContext<'_>,
+    name: hir::Name,
+    macro_: hir::Macro,
+) -> CompletionItem {
     let _p = profile::span("render_macro");
     render(ctx, name, macro_)
 }
@@ -19,7 +19,7 @@ fn render(
     ctx @ RenderContext { completion, .. }: RenderContext<'_>,
     name: hir::Name,
     macro_: hir::Macro,
-) -> Builder {
+) -> CompletionItem {
     let source_range = if completion.is_immediately_after_macro_bang() {
         cov_mark::hit!(completes_macro_call_if_cursor_at_bang_token);
         completion.token.parent().map_or_else(|| ctx.source_range(), |it| it.text_range())
@@ -66,7 +66,7 @@ fn render(
         item.add_import(import_to_add);
     }
 
-    item
+    item.build()
 }
 
 fn label(
diff --git a/crates/ide_db/src/rename.rs b/crates/ide_db/src/rename.rs
index 589975406a..13234a817b 100644
--- a/crates/ide_db/src/rename.rs
+++ b/crates/ide_db/src/rename.rs
@@ -178,23 +178,17 @@ fn rename_mod(
     let mut source_change = SourceChange::default();
 
     let InFile { file_id, value: def_source } = module.definition_source(sema.db);
+    let file_id = file_id.original_file(sema.db);
     if let ModuleSource::SourceFile(..) = def_source {
-        let anchor = file_id.original_file(sema.db);
-        // not mod.rs and doesn't has children, rename file only
-        if !module.is_mod_rs(sema.db) && module.children(sema.db).next().is_none() {
-            let path = format!("{}.rs", new_name);
-            let dst = AnchoredPathBuf { anchor, path };
-            source_change.push_file_system_edit(FileSystemEdit::MoveFile { src: anchor, dst })
-        } else if let Some(mod_name) = module.name(sema.db) {
-            // is mod.rs or has children, rename dir
-            let src = AnchoredPathBuf { anchor, path: mod_name.to_string() };
-            let dst = AnchoredPathBuf { anchor, path: new_name.to_string() };
-            source_change.push_file_system_edit(FileSystemEdit::MoveDir {
-                src,
-                src_id: anchor,
-                dst,
-            })
-        }
+        // mod is defined in path/to/dir/mod.rs
+        let path = if module.is_mod_rs(sema.db) {
+            format!("../{}/mod.rs", new_name)
+        } else {
+            format!("{}.rs", new_name)
+        };
+        let dst = AnchoredPathBuf { anchor: file_id, path };
+        let move_file = FileSystemEdit::MoveFile { src: file_id, dst };
+        source_change.push_file_system_edit(move_file);
     }
 
     if let Some(src) = module.declaration_source(sema.db) {
diff --git a/crates/ide_db/src/source_change.rs b/crates/ide_db/src/source_change.rs
index 8132c73ef2..aa910eb325 100644
--- a/crates/ide_db/src/source_change.rs
+++ b/crates/ide_db/src/source_change.rs
@@ -85,7 +85,6 @@ impl From<FxHashMap<FileId, TextEdit>> for SourceChange {
 pub enum FileSystemEdit {
     CreateFile { dst: AnchoredPathBuf, initial_contents: String },
     MoveFile { src: FileId, dst: AnchoredPathBuf },
-    MoveDir { src: AnchoredPathBuf, src_id: FileId, dst: AnchoredPathBuf },
 }
 
 impl From<FileSystemEdit> for SourceChange {
diff --git a/crates/ide_ssr/Cargo.toml b/crates/ide_ssr/Cargo.toml
index db6991d4e5..9135857c38 100644
--- a/crates/ide_ssr/Cargo.toml
+++ b/crates/ide_ssr/Cargo.toml
@@ -3,7 +3,7 @@ name = "ide_ssr"
 version = "0.0.0"
 description = "Structural search and replace of Rust code"
 license = "MIT OR Apache-2.0"
-repository = "https://github.com/rust-lang/rust-analyzer"
+repository = "https://github.com/rust-analyzer/rust-analyzer"
 edition = "2021"
 rust-version = "1.57"
 
diff --git a/crates/project_model/src/build_scripts.rs b/crates/project_model/src/build_scripts.rs
index 5aa23331a1..6b601c34a2 100644
--- a/crates/project_model/src/build_scripts.rs
+++ b/crates/project_model/src/build_scripts.rs
@@ -7,11 +7,11 @@
 //! here, but it covers procedural macros as well.
 
 use std::{
-    io,
     path::PathBuf,
     process::{Command, Stdio},
 };
 
+use anyhow::Result;
 use cargo_metadata::{camino::Utf8Path, Message};
 use la_arena::ArenaMap;
 use paths::AbsPathBuf;
@@ -42,15 +42,22 @@ pub(crate) struct BuildScriptOutput {
 }
 
 impl WorkspaceBuildScripts {
-    fn build_command(config: &CargoConfig) -> Command {
-        if let Some([program, args @ ..]) = config.run_build_script_command.as_deref() {
-            let mut cmd = Command::new(program);
-            cmd.args(args);
-            return cmd;
-        }
-
+    pub(crate) fn run(
+        config: &CargoConfig,
+        workspace: &CargoWorkspace,
+        progress: &dyn Fn(String),
+    ) -> Result<WorkspaceBuildScripts> {
         let mut cmd = Command::new(toolchain::cargo());
 
+        if config.wrap_rustc_in_build_scripts {
+            // Setup RUSTC_WRAPPER to point to `rust-analyzer` binary itself. We use
+            // that to compile only proc macros and build scripts during the initial
+            // `cargo check`.
+            let myself = std::env::current_exe()?;
+            cmd.env("RUSTC_WRAPPER", myself);
+            cmd.env("RA_RUSTC_WRAPPER", "1");
+        }
+        cmd.current_dir(workspace.workspace_root());
         cmd.args(&["check", "--quiet", "--workspace", "--message-format=json"]);
 
         // --all-targets includes tests, benches and examples in addition to the
@@ -74,26 +81,6 @@ impl WorkspaceBuildScripts {
             }
         }
 
-        cmd
-    }
-    pub(crate) fn run(
-        config: &CargoConfig,
-        workspace: &CargoWorkspace,
-        progress: &dyn Fn(String),
-    ) -> io::Result<WorkspaceBuildScripts> {
-        let mut cmd = Self::build_command(config);
-
-        if config.wrap_rustc_in_build_scripts {
-            // Setup RUSTC_WRAPPER to point to `rust-analyzer` binary itself. We use
-            // that to compile only proc macros and build scripts during the initial
-            // `cargo check`.
-            let myself = std::env::current_exe()?;
-            cmd.env("RUSTC_WRAPPER", myself);
-            cmd.env("RA_RUSTC_WRAPPER", "1");
-        }
-
-        cmd.current_dir(workspace.workspace_root());
-
         cmd.stdout(Stdio::piped()).stderr(Stdio::piped()).stdin(Stdio::null());
 
         let mut res = WorkspaceBuildScripts::default();
@@ -107,17 +94,17 @@ impl WorkspaceBuildScripts {
             by_id.insert(workspace[package].id.clone(), package);
         }
 
-        let mut cfg_err = None;
+        let mut callback_err = None;
         let mut stderr = String::new();
         let output = stdx::process::streaming_output(
             cmd,
             &mut |line| {
-                if cfg_err.is_some() {
+                if callback_err.is_some() {
                     return;
                 }
 
                 // Copy-pasted from existing cargo_metadata. It seems like we
-                // should be using serde_stacker here?
+                // should be using sered_stacker here?
                 let mut deserializer = serde_json::Deserializer::from_str(line);
                 deserializer.disable_recursion_limit();
                 let message = Message::deserialize(&mut deserializer)
@@ -126,7 +113,7 @@ impl WorkspaceBuildScripts {
                 match message {
                     Message::BuildScriptExecuted(message) => {
                         let package = match by_id.get(&message.package_id.repr) {
-                            Some(&it) => it,
+                            Some(it) => *it,
                             None => return,
                         };
                         let cfgs = {
@@ -135,7 +122,7 @@ impl WorkspaceBuildScripts {
                                 match cfg.parse::<CfgFlag>() {
                                     Ok(it) => acc.push(it),
                                     Err(err) => {
-                                        cfg_err = Some(format!(
+                                        callback_err = Some(anyhow::format_err!(
                                             "invalid cfg from cargo-metadata: {}",
                                             err
                                         ));
@@ -191,11 +178,6 @@ impl WorkspaceBuildScripts {
 
         for package in workspace.packages() {
             let package_build_data = &mut res.outputs[package];
-            tracing::info!(
-                "{} BuildScriptOutput: {:?}",
-                workspace[package].manifest.parent().display(),
-                package_build_data,
-            );
             // inject_cargo_env(package, package_build_data);
             if let Some(out_dir) = &package_build_data.out_dir {
                 // NOTE: cargo and rustc seem to hide non-UTF-8 strings from env! and option_env!()
@@ -205,11 +187,6 @@ impl WorkspaceBuildScripts {
             }
         }
 
-        if let Some(cfg_err) = cfg_err {
-            stderr.push_str(&cfg_err);
-            stderr.push('\n');
-        }
-
         if !output.status.success() {
             if stderr.is_empty() {
                 stderr = "cargo check failed".to_string();
diff --git a/crates/project_model/src/cargo_workspace.rs b/crates/project_model/src/cargo_workspace.rs
index 76ef44e147..48051e4b5e 100644
--- a/crates/project_model/src/cargo_workspace.rs
+++ b/crates/project_model/src/cargo_workspace.rs
@@ -96,8 +96,6 @@ pub struct CargoConfig {
     pub unset_test_crates: UnsetTestCrates,
 
     pub wrap_rustc_in_build_scripts: bool,
-
-    pub run_build_script_command: Option<Vec<String>>,
 }
 
 impl CargoConfig {
diff --git a/crates/project_model/src/workspace.rs b/crates/project_model/src/workspace.rs
index 1330a86950..e33ae60862 100644
--- a/crates/project_model/src/workspace.rs
+++ b/crates/project_model/src/workspace.rs
@@ -256,9 +256,7 @@ impl ProjectWorkspace {
     ) -> Result<WorkspaceBuildScripts> {
         match self {
             ProjectWorkspace::Cargo { cargo, .. } => {
-                WorkspaceBuildScripts::run(config, cargo, progress).with_context(|| {
-                    format!("Failed to run build scripts for {}", &cargo.workspace_root().display())
-                })
+                WorkspaceBuildScripts::run(config, cargo, progress)
             }
             ProjectWorkspace::Json { .. } | ProjectWorkspace::DetachedFiles { .. } => {
                 Ok(WorkspaceBuildScripts::default())
@@ -665,7 +663,6 @@ fn cargo_to_crate_graph(
                 load,
                 &mut crate_graph,
                 &cfg_options,
-                override_cfg,
                 load_proc_macro,
                 &mut pkg_to_lib_crate,
                 &public_deps,
@@ -726,7 +723,6 @@ fn handle_rustc_crates(
     load: &mut dyn FnMut(&AbsPath) -> Option<FileId>,
     crate_graph: &mut CrateGraph,
     cfg_options: &CfgOptions,
-    override_cfg: &CfgOverrides,
     load_proc_macro: &mut dyn FnMut(&str, &AbsPath) -> Vec<ProcMacro>,
     pkg_to_lib_crate: &mut FxHashMap<la_arena::Idx<crate::PackageData>, CrateId>,
     public_deps: &SysrootPublicDeps,
@@ -753,28 +749,6 @@ fn handle_rustc_crates(
             for dep in &rustc_workspace[pkg].dependencies {
                 queue.push_back(dep.pkg);
             }
-
-            let mut cfg_options = cfg_options;
-            let mut replaced_cfg_options;
-
-            let overrides = match override_cfg {
-                CfgOverrides::Wildcard(cfg_diff) => Some(cfg_diff),
-                CfgOverrides::Selective(cfg_overrides) => cfg_overrides.get(&cargo[pkg].name),
-            };
-
-            if let Some(overrides) = overrides {
-                // FIXME: this is sort of a hack to deal with #![cfg(not(test))] vanishing such as seen
-                // in ed25519_dalek (#7243), and libcore (#9203) (although you only hit that one while
-                // working on rust-lang/rust as that's the only time it appears outside sysroot).
-                //
-                // A more ideal solution might be to reanalyze crates based on where the cursor is and
-                // figure out the set of cfgs that would have to apply to make it active.
-
-                replaced_cfg_options = cfg_options.clone();
-                replaced_cfg_options.apply_diff(overrides.clone());
-                cfg_options = &replaced_cfg_options;
-            };
-
             for &tgt in rustc_workspace[pkg].targets.iter() {
                 if rustc_workspace[tgt].kind != TargetKind::Lib {
                     continue;
diff --git a/crates/rust-analyzer/src/bin/main.rs b/crates/rust-analyzer/src/bin/main.rs
index 15ae0e6480..9a2e435591 100644
--- a/crates/rust-analyzer/src/bin/main.rs
+++ b/crates/rust-analyzer/src/bin/main.rs
@@ -119,9 +119,7 @@ fn setup_logging(log_file: Option<&Path>) -> Result<()> {
         None => None,
     };
     let filter = env::var("RA_LOG").ok();
-    // deliberately enable all `error` logs if the user has not set RA_LOG, as there is usually useful
-    // information in there for debugging
-    logger::Logger::new(log_file, filter.as_deref().or(Some("error"))).install()?;
+    logger::Logger::new(log_file, filter.as_deref()).install()?;
 
     profile::init();
 
@@ -152,17 +150,7 @@ fn run_server() -> Result<()> {
 
     let mut config = Config::new(root_path, initialize_params.capabilities);
     if let Some(json) = initialize_params.initialization_options {
-        if let Err(e) = config.update(json) {
-            use lsp_types::{
-                notification::{Notification, ShowMessage},
-                MessageType, ShowMessageParams,
-            };
-            let not = lsp_server::Notification::new(
-                ShowMessage::METHOD.to_string(),
-                ShowMessageParams { typ: MessageType::WARNING, message: e.to_string() },
-            );
-            connection.sender.send(lsp_server::Message::Notification(not)).unwrap();
-        }
+        let _ = config.update(json);
     }
 
     let server_capabilities = rust_analyzer::server_capabilities(&config);
@@ -173,11 +161,7 @@ fn run_server() -> Result<()> {
             name: String::from("rust-analyzer"),
             version: Some(String::from(env!("REV"))),
         }),
-        offset_encoding: if supports_utf8(config.caps()) {
-            Some("utf-8".to_string())
-        } else {
-            None
-        },
+        offset_encoding: if supports_utf8(&config.caps) { Some("utf-8".to_string()) } else { None },
     };
 
     let initialize_result = serde_json::to_value(initialize_result).unwrap();
@@ -199,7 +183,7 @@ fn run_server() -> Result<()> {
                     .collect::<Vec<_>>()
             })
             .filter(|workspaces| !workspaces.is_empty())
-            .unwrap_or_else(|| vec![config.root_path().clone()]);
+            .unwrap_or_else(|| vec![config.root_path.clone()]);
 
         let discovered = ProjectManifest::discover_all(&workspace_roots);
         tracing::info!("discovered projects: {:?}", discovered);
diff --git a/crates/rust-analyzer/src/caps.rs b/crates/rust-analyzer/src/caps.rs
index 85e3d50053..8c19f584f0 100644
--- a/crates/rust-analyzer/src/caps.rs
+++ b/crates/rust-analyzer/src/caps.rs
@@ -27,7 +27,7 @@ pub fn server_capabilities(config: &Config) -> ServerCapabilities {
         })),
         hover_provider: Some(HoverProviderCapability::Simple(true)),
         completion_provider: Some(CompletionOptions {
-            resolve_provider: completions_resolve_provider(config.caps()),
+            resolve_provider: completions_resolve_provider(&config.caps),
             trigger_characters: Some(vec![":".to_string(), ".".to_string(), "'".to_string()]),
             all_commit_characters: None,
             completion_item: None,
@@ -46,7 +46,7 @@ pub fn server_capabilities(config: &Config) -> ServerCapabilities {
         document_highlight_provider: Some(OneOf::Left(true)),
         document_symbol_provider: Some(OneOf::Left(true)),
         workspace_symbol_provider: Some(OneOf::Left(true)),
-        code_action_provider: Some(code_action_capabilities(config.caps())),
+        code_action_provider: Some(code_action_capabilities(&config.caps)),
         code_lens_provider: Some(CodeLensOptions { resolve_provider: Some(true) }),
         document_formatting_provider: Some(OneOf::Left(true)),
         document_range_formatting_provider: match config.rustfmt() {
@@ -112,10 +112,11 @@ pub fn server_capabilities(config: &Config) -> ServerCapabilities {
             .into(),
         ),
         moniker_provider: None,
-        inlay_hint_provider: Some(OneOf::Left(true)),
+        inlay_hint_provider: None,
         experimental: Some(json!({
             "externalDocs": true,
             "hoverRange": true,
+            "inlayHints": true,
             "joinLines": true,
             "matchingBrace": true,
             "moveItem": true,
diff --git a/crates/rust-analyzer/src/cargo_target_spec.rs b/crates/rust-analyzer/src/cargo_target_spec.rs
index 35f8f61ef4..ec5dd16d00 100644
--- a/crates/rust-analyzer/src/cargo_target_spec.rs
+++ b/crates/rust-analyzer/src/cargo_target_spec.rs
@@ -123,7 +123,7 @@ impl CargoTargetSpec {
         file_id: FileId,
     ) -> Result<Option<CargoTargetSpec>> {
         let crate_id = match global_state_snapshot.analysis.crate_for(file_id)?.first() {
-            Some(&crate_id) => crate_id,
+            Some(crate_id) => *crate_id,
             None => return Ok(None),
         };
         let (cargo_ws, target) = match global_state_snapshot.cargo_target_for_crate_root(crate_id) {
diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs
index 833ee31eed..958ff1fcee 100644
--- a/crates/rust-analyzer/src/config.rs
+++ b/crates/rust-analyzer/src/config.rs
@@ -7,7 +7,7 @@
 //! configure the server itself, feature flags are passed into analysis, and
 //! tweak things like automatic insertion of `()` in completions.
 
-use std::{ffi::OsString, fmt, iter, path::PathBuf};
+use std::{ffi::OsString, iter, path::PathBuf};
 
 use flycheck::FlycheckConfig;
 use ide::{
@@ -19,7 +19,6 @@ use ide_db::{
     imports::insert_use::{ImportGranularity, InsertUseConfig, PrefixKind},
     SnippetCap,
 };
-use itertools::Itertools;
 use lsp_types::{ClientCapabilities, MarkupKind};
 use project_model::{
     CargoConfig, ProjectJson, ProjectJsonData, ProjectManifest, RustcSource, UnsetTestCrates,
@@ -32,7 +31,9 @@ use crate::{
     caps::completion_item_edit_resolve,
     diagnostics::DiagnosticsMapConfig,
     line_index::OffsetEncoding,
-    lsp_ext::{self, supports_utf8, WorkspaceSymbolSearchKind, WorkspaceSymbolSearchScope},
+    lsp_ext::supports_utf8,
+    lsp_ext::WorkspaceSymbolSearchScope,
+    lsp_ext::{self, WorkspaceSymbolSearchKind},
 };
 
 // Defines the server-side configuration of the rust-analyzer. We generate
@@ -78,10 +79,6 @@ config_data! {
         /// Run build scripts (`build.rs`) for more precise code analysis.
         cargo_runBuildScripts |
         cargo_loadOutDirsFromCheck: bool = "true",
-        /// Advanced option, fully override the command rust-analyzer uses to
-        /// run build scripts and build procedural macros. The command should
-        /// include `--message-format=json` or a similar option.
-        cargo_runBuildScriptsCommand: Option<Vec<String>> = "null",
         /// Use `RUSTC_WRAPPER=rust-analyzer` when running build scripts to
         /// avoid compiling unnecessary things.
         cargo_useRustcWrapperForBuildScripts: bool = "true",
@@ -372,16 +369,14 @@ impl Default for ConfigData {
 
 #[derive(Debug, Clone)]
 pub struct Config {
-    pub discovered_projects: Option<Vec<ProjectManifest>>,
-    caps: lsp_types::ClientCapabilities,
-    root_path: AbsPathBuf,
+    pub caps: lsp_types::ClientCapabilities,
     data: ConfigData,
     detached_files: Vec<AbsPathBuf>,
+    pub discovered_projects: Option<Vec<ProjectManifest>>,
+    pub root_path: AbsPathBuf,
     snippets: Vec<Snippet>,
 }
 
-type ParallelPrimeCachesNumThreads = u8;
-
 #[derive(Debug, Clone, Eq, PartialEq)]
 pub enum LinkedProject {
     ProjectManifest(ProjectManifest),
@@ -402,14 +397,9 @@ impl From<ProjectJson> for LinkedProject {
 
 #[derive(Clone, Debug, PartialEq, Eq)]
 pub struct LensConfig {
-    // runnables
     pub run: bool,
     pub debug: bool,
-
-    // implementations
     pub implementations: bool,
-
-    // references
     pub method_refs: bool,
     pub refs: bool, // for Struct, Enum, Union and Trait
     pub enum_variant_refs: bool,
@@ -417,12 +407,7 @@ pub struct LensConfig {
 
 impl LensConfig {
     pub fn any(&self) -> bool {
-        self.run
-            || self.debug
-            || self.implementations
-            || self.method_refs
-            || self.refs
-            || self.enum_variant_refs
+        self.implementations || self.runnable() || self.references()
     }
 
     pub fn none(&self) -> bool {
@@ -520,27 +505,6 @@ pub struct ClientCommandsConfig {
     pub trigger_parameter_hints: bool,
 }
 
-pub struct ConfigUpdateError {
-    errors: Vec<(String, serde_json::Error)>,
-}
-
-impl fmt::Display for ConfigUpdateError {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        let errors = self.errors.iter().format_with("\n", |(key, e), f| {
-            f(key)?;
-            f(&": ")?;
-            f(e)
-        });
-        write!(
-            f,
-            "rust-analyzer found {} invalid config value{}:\n{}",
-            self.errors.len(),
-            if self.errors.len() == 1 { "" } else { "s" },
-            errors
-        )
-    }
-}
-
 impl Config {
     pub fn new(root_path: AbsPathBuf, caps: ClientCapabilities) -> Self {
         Config {
@@ -552,8 +516,10 @@ impl Config {
             snippets: Default::default(),
         }
     }
-
-    pub fn update(&mut self, mut json: serde_json::Value) -> Result<(), ConfigUpdateError> {
+    pub fn update(
+        &mut self,
+        mut json: serde_json::Value,
+    ) -> Result<(), Vec<(String, serde_json::Error)>> {
         tracing::info!("updating config from JSON: {:#}", json);
         if json.is_null() || json.as_object().map_or(false, |it| it.is_empty()) {
             return Ok(());
@@ -587,41 +553,16 @@ impl Config {
                 None => tracing::info!("Invalid snippet {}", name),
             }
         }
-
-        self.validate(&mut errors);
-
         if errors.is_empty() {
             Ok(())
         } else {
-            Err(ConfigUpdateError { errors })
-        }
-    }
-
-    fn validate(&self, error_sink: &mut Vec<(String, serde_json::Error)>) {
-        use serde::de::Error;
-        if self.data.checkOnSave_command.is_empty() {
-            error_sink.push((
-                "/checkOnSave/command".to_string(),
-                serde_json::Error::custom("expected a non-empty string"),
-            ));
+            Err(errors)
         }
     }
 
     pub fn json_schema() -> serde_json::Value {
         ConfigData::json_schema()
     }
-
-    pub fn root_path(&self) -> &AbsPathBuf {
-        &self.root_path
-    }
-
-    pub fn caps(&self) -> &lsp_types::ClientCapabilities {
-        &self.caps
-    }
-
-    pub fn detached_files(&self) -> &[AbsPathBuf] {
-        &self.detached_files
-    }
 }
 
 macro_rules! try_ {
@@ -635,47 +576,54 @@ macro_rules! try_or {
     };
 }
 
-macro_rules! try_or_def {
-    ($expr:expr) => {
-        try_!($expr).unwrap_or_default()
-    };
-}
-
 impl Config {
     pub fn linked_projects(&self) -> Vec<LinkedProject> {
-        match self.data.linkedProjects.as_slice() {
-            [] => match self.discovered_projects.as_ref() {
-                Some(discovered_projects) => {
-                    discovered_projects.iter().cloned().map(LinkedProject::from).collect()
-                }
-                None => Vec::new(),
-            },
-            linked_projects => linked_projects
+        if self.data.linkedProjects.is_empty() {
+            self.discovered_projects
+                .as_ref()
+                .into_iter()
+                .flatten()
+                .cloned()
+                .map(LinkedProject::from)
+                .collect()
+        } else {
+            self.data
+                .linkedProjects
                 .iter()
-                .filter_map(|linked_project| match linked_project {
-                    ManifestOrProjectJson::Manifest(it) => {
-                        let path = self.root_path.join(it);
-                        ProjectManifest::from_manifest_file(path)
-                            .map_err(|e| tracing::error!("failed to load linked project: {}", e))
-                            .ok()
-                            .map(Into::into)
-                    }
-                    ManifestOrProjectJson::ProjectJson(it) => {
-                        Some(ProjectJson::new(&self.root_path, it.clone()).into())
-                    }
+                .filter_map(|linked_project| {
+                    let res = match linked_project {
+                        ManifestOrProjectJson::Manifest(it) => {
+                            let path = self.root_path.join(it);
+                            ProjectManifest::from_manifest_file(path)
+                                .map_err(|e| {
+                                    tracing::error!("failed to load linked project: {}", e)
+                                })
+                                .ok()?
+                                .into()
+                        }
+                        ManifestOrProjectJson::ProjectJson(it) => {
+                            ProjectJson::new(&self.root_path, it.clone()).into()
+                        }
+                    };
+                    Some(res)
                 })
-                .collect(),
+                .collect()
         }
     }
 
+    pub fn detached_files(&self) -> &[AbsPathBuf] {
+        &self.detached_files
+    }
+
     pub fn did_save_text_document_dynamic_registration(&self) -> bool {
-        let caps = try_or_def!(self.caps.text_document.as_ref()?.synchronization.clone()?);
+        let caps =
+            try_or!(self.caps.text_document.as_ref()?.synchronization.clone()?, Default::default());
         caps.did_save == Some(true) && caps.dynamic_registration == Some(true)
     }
-
     pub fn did_change_watched_files_dynamic_registration(&self) -> bool {
-        try_or_def!(
-            self.caps.workspace.as_ref()?.did_change_watched_files.as_ref()?.dynamic_registration?
+        try_or!(
+            self.caps.workspace.as_ref()?.did_change_watched_files.as_ref()?.dynamic_registration?,
+            false
         )
     }
 
@@ -684,24 +632,22 @@ impl Config {
     }
 
     pub fn location_link(&self) -> bool {
-        try_or_def!(self.caps.text_document.as_ref()?.definition?.link_support?)
+        try_or!(self.caps.text_document.as_ref()?.definition?.link_support?, false)
     }
-
     pub fn line_folding_only(&self) -> bool {
-        try_or_def!(self.caps.text_document.as_ref()?.folding_range.as_ref()?.line_folding_only?)
+        try_or!(self.caps.text_document.as_ref()?.folding_range.as_ref()?.line_folding_only?, false)
     }
-
     pub fn hierarchical_symbols(&self) -> bool {
-        try_or_def!(
+        try_or!(
             self.caps
                 .text_document
                 .as_ref()?
                 .document_symbol
                 .as_ref()?
-                .hierarchical_document_symbol_support?
+                .hierarchical_document_symbol_support?,
+            false
         )
     }
-
     pub fn code_action_literals(&self) -> bool {
         try_!(self
             .caps
@@ -713,15 +659,12 @@ impl Config {
             .as_ref()?)
         .is_some()
     }
-
     pub fn work_done_progress(&self) -> bool {
-        try_or_def!(self.caps.window.as_ref()?.work_done_progress?)
+        try_or!(self.caps.window.as_ref()?.work_done_progress?, false)
     }
-
     pub fn will_rename(&self) -> bool {
-        try_or_def!(self.caps.workspace.as_ref()?.file_operations.as_ref()?.will_rename?)
+        try_or!(self.caps.workspace.as_ref()?.file_operations.as_ref()?.will_rename?, false)
     }
-
     pub fn change_annotation_support(&self) -> bool {
         try_!(self
             .caps
@@ -733,24 +676,24 @@ impl Config {
             .as_ref()?)
         .is_some()
     }
-
     pub fn code_action_resolve(&self) -> bool {
-        try_or_def!(self
-            .caps
-            .text_document
-            .as_ref()?
-            .code_action
-            .as_ref()?
-            .resolve_support
-            .as_ref()?
-            .properties
-            .as_slice())
+        try_or!(
+            self.caps
+                .text_document
+                .as_ref()?
+                .code_action
+                .as_ref()?
+                .resolve_support
+                .as_ref()?
+                .properties
+                .as_slice(),
+            &[]
+        )
         .iter()
         .any(|it| it == "edit")
     }
-
     pub fn signature_help_label_offsets(&self) -> bool {
-        try_or_def!(
+        try_or!(
             self.caps
                 .text_document
                 .as_ref()?
@@ -760,10 +703,10 @@ impl Config {
                 .as_ref()?
                 .parameter_information
                 .as_ref()?
-                .label_offset_support?
+                .label_offset_support?,
+            false
         )
     }
-
     pub fn offset_encoding(&self) -> OffsetEncoding {
         if supports_utf8(&self.caps) {
             OffsetEncoding::Utf8
@@ -773,13 +716,11 @@ impl Config {
     }
 
     fn experimental(&self, index: &'static str) -> bool {
-        try_or_def!(self.caps.experimental.as_ref()?.get(index)?.as_bool()?)
+        try_or!(self.caps.experimental.as_ref()?.get(index)?.as_bool()?, false)
     }
-
     pub fn code_action_group(&self) -> bool {
         self.experimental("codeActionGroup")
     }
-
     pub fn server_status_notification(&self) -> bool {
         self.experimental("serverStatusNotification")
     }
@@ -787,7 +728,6 @@ impl Config {
     pub fn publish_diagnostics(&self) -> bool {
         self.data.diagnostics_enable
     }
-
     pub fn diagnostics(&self) -> DiagnosticsConfig {
         DiagnosticsConfig {
             disable_experimental: !self.data.diagnostics_enableExperimental,
@@ -798,7 +738,6 @@ impl Config {
             },
         }
     }
-
     pub fn diagnostics_map(&self) -> DiagnosticsMapConfig {
         DiagnosticsMapConfig {
             remap_prefix: self.data.diagnostics_remapPrefix.clone(),
@@ -806,11 +745,9 @@ impl Config {
             warnings_as_hint: self.data.diagnostics_warningsAsHint.clone(),
         }
     }
-
     pub fn lru_capacity(&self) -> Option<usize> {
         self.data.lruCapacity
     }
-
     pub fn proc_macro_srv(&self) -> Option<(AbsPathBuf, Vec<OsString>)> {
         if !self.data.procMacro_enable {
             return None;
@@ -821,15 +758,12 @@ impl Config {
         };
         Some((path, vec!["proc-macro".into()]))
     }
-
     pub fn dummy_replacements(&self) -> &FxHashMap<Box<str>, Box<[Box<str>]>> {
         &self.data.procMacro_ignored
     }
-
     pub fn expand_proc_attr_macros(&self) -> bool {
         self.data.experimental_procAttrMacros
     }
-
     pub fn files(&self) -> FilesConfig {
         FilesConfig {
             watcher: match self.data.files_watcher.as_str() {
@@ -842,19 +776,15 @@ impl Config {
             exclude: self.data.files_excludeDirs.iter().map(|it| self.root_path.join(it)).collect(),
         }
     }
-
     pub fn notifications(&self) -> NotificationsConfig {
         NotificationsConfig { cargo_toml_not_found: self.data.notifications_cargoTomlNotFound }
     }
-
     pub fn cargo_autoreload(&self) -> bool {
         self.data.cargo_autoreload
     }
-
     pub fn run_build_scripts(&self) -> bool {
         self.data.cargo_runBuildScripts || self.data.procMacro_enable
     }
-
     pub fn cargo(&self) -> CargoConfig {
         let rustc_source = self.data.rustcSource.as_ref().map(|rustc_src| {
             if rustc_src == "discover" {
@@ -873,7 +803,6 @@ impl Config {
             rustc_source,
             unset_test_crates: UnsetTestCrates::Only(self.data.cargo_unsetTest.clone()),
             wrap_rustc_in_build_scripts: self.data.cargo_useRustcWrapperForBuildScripts,
-            run_build_script_command: self.data.cargo_runBuildScriptsCommand.clone(),
         }
     }
 
@@ -890,7 +819,6 @@ impl Config {
             },
         }
     }
-
     pub fn flycheck(&self) -> Option<FlycheckConfig> {
         if !self.data.checkOnSave_enable {
             return None;
@@ -927,14 +855,12 @@ impl Config {
         };
         Some(flycheck_config)
     }
-
     pub fn runnables(&self) -> RunnablesConfig {
         RunnablesConfig {
             override_cargo: self.data.runnables_overrideCargo.clone(),
             cargo_extra_args: self.data.runnables_cargoExtraArgs.clone(),
         }
     }
-
     pub fn inlay_hints(&self) -> InlayHintsConfig {
         InlayHintsConfig {
             render_colons: self.data.inlayHints_renderColons,
@@ -955,7 +881,6 @@ impl Config {
             max_length: self.data.inlayHints_maxLength,
         }
     }
-
     fn insert_use_config(&self) -> InsertUseConfig {
         InsertUseConfig {
             granularity: match self.data.assist_importGranularity {
@@ -974,7 +899,6 @@ impl Config {
             skip_glob_imports: !self.data.assist_allowMergingIntoGlobImports,
         }
     }
-
     pub fn completion(&self) -> CompletionConfig {
         CompletionConfig {
             enable_postfix_completions: self.data.completion_postfix_enable,
@@ -985,7 +909,7 @@ impl Config {
             add_call_parenthesis: self.data.completion_addCallParenthesis,
             add_call_argument_snippets: self.data.completion_addCallArgumentSnippets,
             insert_use: self.insert_use_config(),
-            snippet_cap: SnippetCap::new(try_or_def!(
+            snippet_cap: SnippetCap::new(try_or!(
                 self.caps
                     .text_document
                     .as_ref()?
@@ -993,12 +917,12 @@ impl Config {
                     .as_ref()?
                     .completion_item
                     .as_ref()?
-                    .snippet_support?
+                    .snippet_support?,
+                false
             )),
             snippets: self.snippets.clone(),
         }
     }
-
     pub fn assist(&self) -> AssistConfig {
         AssistConfig {
             snippet_cap: SnippetCap::new(self.experimental("snippetTextEdit")),
@@ -1006,7 +930,6 @@ impl Config {
             insert_use: self.insert_use_config(),
         }
     }
-
     pub fn join_lines(&self) -> JoinLinesConfig {
         JoinLinesConfig {
             join_else_if: self.data.joinLines_joinElseIf,
@@ -1015,11 +938,9 @@ impl Config {
             join_assignments: self.data.joinLines_joinAssignments,
         }
     }
-
     pub fn call_info_full(&self) -> bool {
         self.data.callInfo_full
     }
-
     pub fn lens(&self) -> LensConfig {
         LensConfig {
             run: self.data.lens_enable && self.data.lens_run,
@@ -1030,7 +951,6 @@ impl Config {
             enum_variant_refs: self.data.lens_enable && self.data.lens_enumVariantReferences,
         }
     }
-
     pub fn hover_actions(&self) -> HoverActionsConfig {
         let enable = self.experimental("hoverActions") && self.data.hoverActions_enable;
         HoverActionsConfig {
@@ -1041,24 +961,24 @@ impl Config {
             goto_type_def: enable && self.data.hoverActions_gotoTypeDef,
         }
     }
-
     pub fn highlighting_strings(&self) -> bool {
         self.data.highlighting_strings
     }
-
     pub fn hover(&self) -> HoverConfig {
         HoverConfig {
             links_in_hover: self.data.hover_linksInHover,
             documentation: self.data.hover_documentation.then(|| {
-                let is_markdown = try_or_def!(self
-                    .caps
-                    .text_document
-                    .as_ref()?
-                    .hover
-                    .as_ref()?
-                    .content_format
-                    .as_ref()?
-                    .as_slice())
+                let is_markdown = try_or!(
+                    self.caps
+                        .text_document
+                        .as_ref()?
+                        .hover
+                        .as_ref()?
+                        .content_format
+                        .as_ref()?
+                        .as_slice(),
+                    &[]
+                )
                 .contains(&MarkupKind::Markdown);
                 if is_markdown {
                     HoverDocFormat::Markdown
@@ -1086,15 +1006,13 @@ impl Config {
     }
 
     pub fn semantic_tokens_refresh(&self) -> bool {
-        try_or_def!(self.caps.workspace.as_ref()?.semantic_tokens.as_ref()?.refresh_support?)
+        try_or!(self.caps.workspace.as_ref()?.semantic_tokens.as_ref()?.refresh_support?, false)
     }
-
     pub fn code_lens_refresh(&self) -> bool {
-        try_or_def!(self.caps.workspace.as_ref()?.code_lens.as_ref()?.refresh_support?)
+        try_or!(self.caps.workspace.as_ref()?.code_lens.as_ref()?.refresh_support?, false)
     }
-
     pub fn insert_replace_support(&self) -> bool {
-        try_or_def!(
+        try_or!(
             self.caps
                 .text_document
                 .as_ref()?
@@ -1102,10 +1020,10 @@ impl Config {
                 .as_ref()?
                 .completion_item
                 .as_ref()?
-                .insert_replace_support?
+                .insert_replace_support?,
+            false
         )
     }
-
     pub fn client_commands(&self) -> ClientCommandsConfig {
         let commands =
             try_or!(self.caps.experimental.as_ref()?.get("commands")?, &serde_json::Value::Null);
@@ -1142,8 +1060,6 @@ impl Config {
     }
 }
 
-// Deserialization definitions
-
 #[derive(Deserialize, Debug, Clone, Copy)]
 #[serde(rename_all = "snake_case")]
 enum SnippetScopeDef {
@@ -1266,6 +1182,8 @@ enum WorkspaceSymbolSearchKindDef {
     AllSymbols,
 }
 
+type ParallelPrimeCachesNumThreads = u8;
+
 macro_rules! _config_data {
     (struct $name:ident {
         $(
diff --git a/crates/rust-analyzer/src/global_state.rs b/crates/rust-analyzer/src/global_state.rs
index 8b47ef0283..02482d5889 100644
--- a/crates/rust-analyzer/src/global_state.rs
+++ b/crates/rust-analyzer/src/global_state.rs
@@ -190,7 +190,6 @@ impl GlobalState {
 
             for file in changed_files {
                 if !file.is_created_or_deleted() {
-                    // FIXME: https://github.com/rust-analyzer/rust-analyzer/issues/11357
                     let crates = self.analysis_host.raw_database().relevant_crates(file.file_id);
                     let crate_graph = self.analysis_host.raw_database().crate_graph();
 
@@ -256,7 +255,6 @@ impl GlobalState {
         let request = self.req_queue.outgoing.register(R::METHOD.to_string(), params, handler);
         self.send(request.into());
     }
-
     pub(crate) fn complete_request(&mut self, response: lsp_server::Response) {
         let handler = self
             .req_queue
@@ -283,7 +281,6 @@ impl GlobalState {
             .incoming
             .register(request.id.clone(), (request.method.clone(), request_received));
     }
-
     pub(crate) fn respond(&mut self, response: lsp_server::Response) {
         if let Some((method, start)) = self.req_queue.incoming.complete(response.id.clone()) {
             if let Some(err) = &response.error {
@@ -297,7 +294,6 @@ impl GlobalState {
             self.send(response.into());
         }
     }
-
     pub(crate) fn cancel(&mut self, request_id: lsp_server::RequestId) {
         if let Some(response) = self.req_queue.incoming.cancel(request_id) {
             self.send(response.into());
@@ -311,7 +307,7 @@ impl GlobalState {
 
 impl Drop for GlobalState {
     fn drop(&mut self) {
-        self.analysis_host.request_cancellation();
+        self.analysis_host.request_cancellation()
     }
 }
 
diff --git a/crates/rust-analyzer/src/handlers.rs b/crates/rust-analyzer/src/handlers.rs
index fb64eeea4f..78118764fa 100644
--- a/crates/rust-analyzer/src/handlers.rs
+++ b/crates/rust-analyzer/src/handlers.rs
@@ -19,11 +19,11 @@ use lsp_types::{
     CallHierarchyIncomingCall, CallHierarchyIncomingCallsParams, CallHierarchyItem,
     CallHierarchyOutgoingCall, CallHierarchyOutgoingCallsParams, CallHierarchyPrepareParams,
     CodeLens, CompletionItem, Diagnostic, DiagnosticTag, DocumentFormattingParams, FoldingRange,
-    FoldingRangeParams, HoverContents, InlayHint, InlayHintParams, Location, LocationLink,
-    NumberOrString, Position, PrepareRenameResponse, Range, RenameParams,
-    SemanticTokensDeltaParams, SemanticTokensFullDeltaResult, SemanticTokensParams,
-    SemanticTokensRangeParams, SemanticTokensRangeResult, SemanticTokensResult, SymbolInformation,
-    SymbolTag, TextDocumentIdentifier, Url, WorkspaceEdit,
+    FoldingRangeParams, HoverContents, Location, LocationLink, NumberOrString, Position,
+    PrepareRenameResponse, Range, RenameParams, SemanticTokensDeltaParams,
+    SemanticTokensFullDeltaResult, SemanticTokensParams, SemanticTokensRangeParams,
+    SemanticTokensRangeResult, SemanticTokensResult, SymbolInformation, SymbolTag,
+    TextDocumentIdentifier, Url, WorkspaceEdit,
 };
 use project_model::{ManifestPath, ProjectWorkspace, TargetKind};
 use serde_json::json;
@@ -38,7 +38,10 @@ use crate::{
     from_proto,
     global_state::{GlobalState, GlobalStateSnapshot},
     line_index::LineEndings,
-    lsp_ext::{self, PositionOrRange, ViewCrateGraphParams, WorkspaceSymbolParams},
+    lsp_ext::{
+        self, InlayHint, InlayHintsParams, PositionOrRange, ViewCrateGraphParams,
+        WorkspaceSymbolParams,
+    },
     lsp_utils::{all_edits_are_disjoint, invalid_params_error},
     to_proto, LspError, Result,
 };
@@ -1319,25 +1322,29 @@ pub(crate) fn publish_diagnostics(
 
 pub(crate) fn handle_inlay_hints(
     snap: GlobalStateSnapshot,
-    params: InlayHintParams,
-) -> Result<Option<Vec<InlayHint>>> {
+    params: InlayHintsParams,
+) -> Result<Vec<InlayHint>> {
     let _p = profile::span("handle_inlay_hints");
     let document_uri = &params.text_document.uri;
     let file_id = from_proto::file_id(&snap, document_uri)?;
     let line_index = snap.file_line_index(file_id)?;
-    let range = from_proto::file_range(
-        &snap,
-        TextDocumentIdentifier::new(document_uri.to_owned()),
-        params.range,
-    )?;
+    let range = params
+        .range
+        .map(|range| {
+            from_proto::file_range(
+                &snap,
+                TextDocumentIdentifier::new(document_uri.to_owned()),
+                range,
+            )
+        })
+        .transpose()?;
     let inlay_hints_config = snap.config.inlay_hints();
-    Ok(Some(
-        snap.analysis
-            .inlay_hints(&inlay_hints_config, file_id, Some(range))?
-            .into_iter()
-            .map(|it| to_proto::inlay_hint(inlay_hints_config.render_colons, &line_index, it))
-            .collect(),
-    ))
+    Ok(snap
+        .analysis
+        .inlay_hints(&inlay_hints_config, file_id, range)?
+        .into_iter()
+        .map(|it| to_proto::inlay_hint(inlay_hints_config.render_colons, &line_index, it))
+        .collect())
 }
 
 pub(crate) fn handle_call_hierarchy_prepare(
diff --git a/crates/rust-analyzer/src/lsp_ext.rs b/crates/rust-analyzer/src/lsp_ext.rs
index 489a233a0a..b638a57111 100644
--- a/crates/rust-analyzer/src/lsp_ext.rs
+++ b/crates/rust-analyzer/src/lsp_ext.rs
@@ -236,6 +236,14 @@ pub struct TestInfo {
     pub runnable: Runnable,
 }
 
+pub enum InlayHints {}
+
+impl Request for InlayHints {
+    type Params = InlayHintsParams;
+    type Result = Vec<InlayHint>;
+    const METHOD: &'static str = "experimental/inlayHints";
+}
+
 #[derive(Serialize, Deserialize, Debug)]
 #[serde(rename_all = "camelCase")]
 pub struct InlayHintsParams {
@@ -243,6 +251,44 @@ pub struct InlayHintsParams {
     pub range: Option<lsp_types::Range>,
 }
 
+#[derive(Eq, PartialEq, Debug, Copy, Clone, Serialize, Deserialize)]
+#[serde(transparent)]
+pub struct InlayHintKind(u8);
+
+impl InlayHintKind {
+    pub const TYPE: InlayHintKind = InlayHintKind(1);
+    pub const PARAMETER: InlayHintKind = InlayHintKind(2);
+}
+
+#[derive(Debug, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct InlayHint {
+    pub label: InlayHintLabel,
+    pub position: Position,
+    pub kind: Option<InlayHintKind>,
+    pub tooltip: Option<String>,
+    pub padding_left: Option<bool>,
+    pub padding_right: Option<bool>,
+}
+
+#[derive(Debug, Deserialize, Serialize)]
+#[serde(untagged)]
+pub enum InlayHintLabel {
+    String(String),
+    Parts(Vec<InlayHintLabelPart>),
+}
+
+#[derive(Debug, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct InlayHintLabelPart {
+    pub value: String,
+    #[serde(skip_serializing_if = "Option::is_none")]
+    pub tooltip: Option<String>,
+    #[serde(skip_serializing_if = "Option::is_none")]
+    pub location: Option<lsp_types::LocationLink>,
+    #[serde(skip_serializing_if = "Option::is_none")]
+    pub command: Option<lsp_types::Command>,
+}
 pub enum Ssr {}
 
 impl Request for Ssr {
diff --git a/crates/rust-analyzer/src/lsp_utils.rs b/crates/rust-analyzer/src/lsp_utils.rs
index 460ae4ef4d..b09c411908 100644
--- a/crates/rust-analyzer/src/lsp_utils.rs
+++ b/crates/rust-analyzer/src/lsp_utils.rs
@@ -47,26 +47,6 @@ impl GlobalState {
         )
     }
 
-    /// Sends a notification to the client containing the error `message`.
-    /// If `additional_info` is [`Some`], appends a note to the notification telling to check the logs.
-    /// This will always log `message` + `additional_info` to the server's error log.
-    pub(crate) fn show_and_log_error(&mut self, message: String, additional_info: Option<String>) {
-        let mut message = message;
-        match additional_info {
-            Some(additional_info) => {
-                tracing::error!("{}\n\n{}", &message, &additional_info);
-                if tracing::enabled!(tracing::Level::ERROR) {
-                    message.push_str("\n\nCheck the server logs for additional info.");
-                }
-            }
-            None => tracing::error!("{}", &message),
-        }
-
-        self.send_notification::<lsp_types::notification::ShowMessage>(
-            lsp_types::ShowMessageParams { typ: lsp_types::MessageType::ERROR, message },
-        )
-    }
-
     /// rust-analyzer is resilient -- if it fails, this doesn't usually affect
     /// the user experience. Part of that is that we deliberately hide panics
     /// from the user.
diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs
index de44ba5e07..2d898d76a6 100644
--- a/crates/rust-analyzer/src/main_loop.rs
+++ b/crates/rust-analyzer/src/main_loop.rs
@@ -9,6 +9,7 @@ use std::{
 use always_assert::always;
 use crossbeam_channel::{select, Receiver};
 use ide_db::base_db::{SourceDatabaseExt, VfsPath};
+use itertools::Itertools;
 use lsp_server::{Connection, Notification, Request};
 use lsp_types::notification::Notification as _;
 use vfs::{ChangeKind, FileId};
@@ -111,7 +112,10 @@ impl GlobalState {
             && self.config.detached_files().is_empty()
             && self.config.notifications().cargo_toml_not_found
         {
-            self.show_and_log_error("rust-analyzer failed to discover workspace".to_string(), None);
+            self.show_message(
+                lsp_types::MessageType::ERROR,
+                "rust-analyzer failed to discover workspace".to_string(),
+            );
         };
 
         if self.config.did_save_text_document_dynamic_registration() {
@@ -187,7 +191,7 @@ impl GlobalState {
         // NOTE: don't count blocking select! call as a loop-turn time
         let _p = profile::span("GlobalState::handle_event");
 
-        tracing::debug!("handle_event({:?})", event);
+        tracing::info!("handle_event({:?})", event);
         let task_queue_len = self.task_pool.handle.len();
         if task_queue_len > 0 {
             tracing::info!("task queue len: {}", task_queue_len);
@@ -403,9 +407,9 @@ impl GlobalState {
                                 flycheck::Progress::DidCancel => (Progress::End, None),
                                 flycheck::Progress::DidFinish(result) => {
                                     if let Err(err) = result {
-                                        self.show_and_log_error(
-                                            "cargo check failed".to_string(),
-                                            Some(err.to_string()),
+                                        self.show_message(
+                                            lsp_types::MessageType::ERROR,
+                                            format!("cargo check failed: {}", err),
                                         );
                                     }
                                     (Progress::End, None)
@@ -561,6 +565,7 @@ impl GlobalState {
         if self.workspaces.is_empty() && !self.is_quiescent() {
             self.respond(lsp_server::Response::new_err(
                 req.id,
+                // FIXME: i32 should impl From<ErrorCode> (from() guarantees lossless conversion)
                 lsp_server::ErrorCode::ContentModified as i32,
                 "waiting for cargo metadata or cargo check".to_owned(),
             ));
@@ -592,6 +597,7 @@ impl GlobalState {
             .on::<lsp_ext::ParentModule>(handlers::handle_parent_module)
             .on::<lsp_ext::Runnables>(handlers::handle_runnables)
             .on::<lsp_ext::RelatedTests>(handlers::handle_related_tests)
+            .on::<lsp_ext::InlayHints>(handlers::handle_inlay_hints)
             .on::<lsp_ext::CodeActionRequest>(handlers::handle_code_action)
             .on::<lsp_ext::CodeActionResolveRequest>(handlers::handle_code_action_resolve)
             .on::<lsp_ext::HoverRequest>(handlers::handle_hover)
@@ -605,7 +611,6 @@ impl GlobalState {
             .on::<lsp_types::request::GotoDeclaration>(handlers::handle_goto_declaration)
             .on::<lsp_types::request::GotoImplementation>(handlers::handle_goto_implementation)
             .on::<lsp_types::request::GotoTypeDefinition>(handlers::handle_goto_type_definition)
-            .on::<lsp_types::request::InlayHintRequest>(handlers::handle_inlay_hints)
             .on::<lsp_types::request::Completion>(handlers::handle_completion)
             .on::<lsp_types::request::ResolveCompletionItem>(handlers::handle_completion_resolve)
             .on::<lsp_types::request::CodeLensRequest>(handlers::handle_code_lens)
@@ -742,8 +747,16 @@ impl GlobalState {
                                     // Note that json can be null according to the spec if the client can't
                                     // provide a configuration. This is handled in Config::update below.
                                     let mut config = Config::clone(&*this.config);
-                                    if let Err(error) = config.update(json.take()) {
-                                        this.show_message(lsp_types::MessageType::WARNING, error.to_string());
+                                    if let Err(errors) = config.update(json.take()) {
+                                        let errors = errors
+                                            .iter()
+                                            .format_with("\n", |(key, e),f| {
+                                                f(key)?;
+                                                f(&": ")?;
+                                                f(e)
+                                            });
+                                        let msg= format!("Failed to deserialize config key(s):\n{}", errors);
+                                        this.show_message(lsp_types::MessageType::WARNING, msg);
                                     }
                                     this.update_configuration(config);
                                 }
diff --git a/crates/rust-analyzer/src/reload.rs b/crates/rust-analyzer/src/reload.rs
index 5189d94eae..eecc83e02a 100644
--- a/crates/rust-analyzer/src/reload.rs
+++ b/crates/rust-analyzer/src/reload.rs
@@ -72,10 +72,9 @@ impl GlobalState {
             status.message =
                 Some("Reload required due to source changes of a procedural macro.".into())
         }
-        if let Err(_) = self.fetch_build_data_error() {
+        if let Some(error) = self.fetch_build_data_error() {
             status.health = lsp_ext::Health::Warning;
-            status.message =
-                Some("Failed to run build scripts of some packages, check the logs.".to_string());
+            status.message = Some(error)
         }
         if !self.config.cargo_autoreload()
             && self.is_quiescent()
@@ -85,7 +84,7 @@ impl GlobalState {
             status.message = Some("Workspace reload required".to_string())
         }
 
-        if let Err(error) = self.fetch_workspace_error() {
+        if let Some(error) = self.fetch_workspace_error() {
             status.health = lsp_ext::Health::Error;
             status.message = Some(error)
         }
@@ -168,8 +167,8 @@ impl GlobalState {
         let _p = profile::span("GlobalState::switch_workspaces");
         tracing::info!("will switch workspaces");
 
-        if let Err(error_message) = self.fetch_workspace_error() {
-            self.show_and_log_error(error_message, None);
+        if let Some(error_message) = self.fetch_workspace_error() {
+            tracing::error!("failed to switch workspaces: {}", error_message);
             if !self.workspaces.is_empty() {
                 // It only makes sense to switch to a partially broken workspace
                 // if we don't have any workspace at all yet.
@@ -177,11 +176,8 @@ impl GlobalState {
             }
         }
 
-        if let Err(error) = self.fetch_build_data_error() {
-            self.show_and_log_error(
-                "rust-analyzer failed to run build scripts".to_string(),
-                Some(error),
-            );
+        if let Some(error_message) = self.fetch_build_data_error() {
+            tracing::error!("failed to switch build data: {}", error_message);
         }
 
         let workspaces = self
@@ -281,18 +277,20 @@ impl GlobalState {
         let project_folders = ProjectFolders::new(&self.workspaces, &files_config.exclude);
 
         if self.proc_macro_client.is_none() {
-            if let Some((path, args)) = self.config.proc_macro_srv() {
-                match ProcMacroServer::spawn(path.clone(), args) {
-                    Ok(it) => self.proc_macro_client = Some(it),
+            self.proc_macro_client = match self.config.proc_macro_srv() {
+                None => None,
+                Some((path, args)) => match ProcMacroServer::spawn(path.clone(), args) {
+                    Ok(it) => Some(it),
                     Err(err) => {
                         tracing::error!(
                             "Failed to run proc_macro_srv from path {}, error: {:?}",
                             path.display(),
                             err
                         );
+                        None
                     }
-                }
-            }
+                },
+            };
         }
 
         let watch = match files_config.watcher {
@@ -350,7 +348,7 @@ impl GlobalState {
         tracing::info!("did switch workspaces");
     }
 
-    fn fetch_workspace_error(&self) -> Result<(), String> {
+    fn fetch_workspace_error(&self) -> Option<String> {
         let mut buf = String::new();
 
         for ws in self.fetch_workspaces_queue.last_op_result() {
@@ -360,30 +358,35 @@ impl GlobalState {
         }
 
         if buf.is_empty() {
-            return Ok(());
+            return None;
         }
 
-        Err(buf)
+        Some(buf)
     }
 
-    fn fetch_build_data_error(&self) -> Result<(), String> {
-        let mut buf = String::new();
+    fn fetch_build_data_error(&self) -> Option<String> {
+        let mut buf = "rust-analyzer failed to run build scripts:\n".to_string();
+        let mut has_errors = false;
 
         for ws in &self.fetch_build_data_queue.last_op_result().1 {
             match ws {
-                Ok(data) => match data.error() {
-                    Some(stderr) => stdx::format_to!(buf, "{:#}\n", stderr),
-                    _ => (),
-                },
-                // io errors
-                Err(err) => stdx::format_to!(buf, "{:#}\n", err),
+                Ok(data) => {
+                    if let Some(err) = data.error() {
+                        has_errors = true;
+                        stdx::format_to!(buf, "{:#}\n", err);
+                    }
+                }
+                Err(err) => {
+                    has_errors = true;
+                    stdx::format_to!(buf, "{:#}\n", err);
+                }
             }
         }
 
-        if buf.is_empty() {
-            Ok(())
+        if has_errors {
+            Some(buf)
         } else {
-            Err(buf)
+            None
         }
     }
 
diff --git a/crates/rust-analyzer/src/to_proto.rs b/crates/rust-analyzer/src/to_proto.rs
index 3d83f090e2..e52505d8a1 100644
--- a/crates/rust-analyzer/src/to_proto.rs
+++ b/crates/rust-analyzer/src/to_proto.rs
@@ -418,8 +418,14 @@ pub(crate) fn inlay_hint(
     render_colons: bool,
     line_index: &LineIndex,
     inlay_hint: InlayHint,
-) -> lsp_types::InlayHint {
-    lsp_types::InlayHint {
+) -> lsp_ext::InlayHint {
+    lsp_ext::InlayHint {
+        label: lsp_ext::InlayHintLabel::String(match inlay_hint.kind {
+            InlayKind::ParameterHint if render_colons => format!("{}:", inlay_hint.label),
+            InlayKind::TypeHint if render_colons => format!(": {}", inlay_hint.label),
+            InlayKind::ClosureReturnTypeHint => format!(" -> {}", inlay_hint.label),
+            _ => inlay_hint.label.to_string(),
+        }),
         position: match inlay_hint.kind {
             // before annotated thing
             InlayKind::ParameterHint | InlayKind::ImplicitReborrow => {
@@ -432,16 +438,10 @@ pub(crate) fn inlay_hint(
             | InlayKind::GenericParamListHint
             | InlayKind::LifetimeHint => position(line_index, inlay_hint.range.end()),
         },
-        label: lsp_types::InlayHintLabel::String(match inlay_hint.kind {
-            InlayKind::ParameterHint if render_colons => format!("{}:", inlay_hint.label),
-            InlayKind::TypeHint if render_colons => format!(": {}", inlay_hint.label),
-            InlayKind::ClosureReturnTypeHint => format!(" -> {}", inlay_hint.label),
-            _ => inlay_hint.label.to_string(),
-        }),
         kind: match inlay_hint.kind {
-            InlayKind::ParameterHint => Some(lsp_types::InlayHintKind::PARAMETER),
+            InlayKind::ParameterHint => Some(lsp_ext::InlayHintKind::PARAMETER),
             InlayKind::ClosureReturnTypeHint | InlayKind::TypeHint | InlayKind::ChainingHint => {
-                Some(lsp_types::InlayHintKind::TYPE)
+                Some(lsp_ext::InlayHintKind::TYPE)
             }
             InlayKind::GenericParamListHint
             | InlayKind::LifetimeHint
@@ -465,7 +465,6 @@ pub(crate) fn inlay_hint(
             InlayKind::GenericParamListHint => false,
             InlayKind::ImplicitReborrow => false,
         }),
-        text_edits: None,
     }
 }
 
@@ -866,20 +865,6 @@ pub(crate) fn snippet_text_document_ops(
                 rename_file,
             )))
         }
-        FileSystemEdit::MoveDir { src, src_id, dst } => {
-            let old_uri = snap.anchored_path(&src);
-            let new_uri = snap.anchored_path(&dst);
-            let mut rename_file =
-                lsp_types::RenameFile { old_uri, new_uri, options: None, annotation_id: None };
-            if snap.analysis.is_library_file(src_id).ok() == Some(true)
-                && snap.config.change_annotation_support()
-            {
-                rename_file.annotation_id = Some(outside_workspace_annotation_id())
-            }
-            ops.push(lsp_ext::SnippetDocumentChangeOperation::Op(lsp_types::ResourceOp::Rename(
-                rename_file,
-            )))
-        }
     }
     Ok(ops)
 }
diff --git a/crates/syntax/Cargo.toml b/crates/syntax/Cargo.toml
index 99bc30f076..bb4d10207d 100644
--- a/crates/syntax/Cargo.toml
+++ b/crates/syntax/Cargo.toml
@@ -3,7 +3,7 @@ name = "syntax"
 version = "0.0.0"
 description = "Comment and whitespace preserving parser for the Rust language"
 license = "MIT OR Apache-2.0"
-repository = "https://github.com/rust-lang/rust-analyzer"
+repository = "https://github.com/rust-analyzer/rust-analyzer"
 edition = "2021"
 rust-version = "1.57"
 
diff --git a/docs/dev/README.md b/docs/dev/README.md
index 4a047e57a0..8d4d1d7a25 100644
--- a/docs/dev/README.md
+++ b/docs/dev/README.md
@@ -66,7 +66,7 @@ If `cargo test` passes locally, that's a good sign that CI will be green as well
 The only exception is that some long-running tests are skipped locally by default.
 Use `env RUN_SLOW_TESTS=1 cargo test` to run the full suite.
 
-We use bors to enforce the [not rocket science](https://graydon2.dreamwidth.org/1597.html) rule.
+We use bors-ng to enforce the [not rocket science](https://graydon2.dreamwidth.org/1597.html) rule.
 
 ## Launching rust-analyzer
 
diff --git a/docs/dev/lsp-extensions.md b/docs/dev/lsp-extensions.md
index 46193a6ff3..516d1caccc 100644
--- a/docs/dev/lsp-extensions.md
+++ b/docs/dev/lsp-extensions.md
@@ -1,5 +1,5 @@
 <!---
-lsp_ext.rs hash: 326ad62235135223
+lsp_ext.rs hash: a61de7db4504a4d1
 
 If you need to change the above hash to make the test pass, please check if you
 need to adjust this doc as well and ping this issue:
@@ -571,6 +571,36 @@ interface ExpandedMacro {
 
 Expands macro call at a given position.
 
+## Inlay Hints
+
+**Method:** `experimental/inlayHints`
+
+This request is sent from client to server to render "inlay hints" -- virtual text inserted into editor to show things like inferred types.
+Generally, the client should re-query inlay hints after every modification.
+Until it gets upstreamed, this follows the VS Code API.
+Upstream issues: https://github.com/microsoft/language-server-protocol/issues/956 , https://github.com/rust-analyzer/rust-analyzer/issues/2797
+
+**Request:**
+
+```typescript
+interface InlayHintsParams {
+    textDocument: TextDocumentIdentifier,
+}
+```
+
+**Response:** `InlayHint[]`
+
+```typescript
+interface InlayHint {
+    position: Position;
+    label: string | InlayHintLabelPart[];
+    tooltip?: string | MarkdownString | undefined;
+    kind?: InlayHintKind;
+    paddingLeft?: boolean;
+    paddingRight?: boolean;
+}
+```
+
 ## Hover Actions
 
 **Experimental Client Capability:** `{ "hoverActions": boolean }`
diff --git a/docs/user/generated_config.adoc b/docs/user/generated_config.adoc
index ace74f8e08..d552982768 100644
--- a/docs/user/generated_config.adoc
+++ b/docs/user/generated_config.adoc
@@ -64,13 +64,6 @@ List of features to activate.
 --
 Run build scripts (`build.rs`) for more precise code analysis.
 --
-[[rust-analyzer.cargo.runBuildScriptsCommand]]rust-analyzer.cargo.runBuildScriptsCommand (default: `null`)::
-+
---
-Advanced option, fully override the command rust-analyzer uses to
-run build scripts and build procedural macros. The command should
-include `--message-format=json` or a similar option.
---
 [[rust-analyzer.cargo.useRustcWrapperForBuildScripts]]rust-analyzer.cargo.useRustcWrapperForBuildScripts (default: `true`)::
 +
 --
diff --git a/editors/code/package-lock.json b/editors/code/package-lock.json
index 3c7c643798..61490d0e47 100644
--- a/editors/code/package-lock.json
+++ b/editors/code/package-lock.json
@@ -11,11 +11,11 @@
             "dependencies": {
                 "d3": "^7.3.0",
                 "d3-graphviz": "^4.1.0",
-                "vscode-languageclient": "8.0.0-next.14"
+                "vscode-languageclient": "8.0.0-next.12"
             },
             "devDependencies": {
                 "@types/node": "~14.17.5",
-                "@types/vscode": "~1.66.0",
+                "@types/vscode": "~1.65.0",
                 "@typescript-eslint/eslint-plugin": "^5.16.0",
                 "@typescript-eslint/parser": "^5.16.0",
                 "@vscode/test-electron": "^2.1.3",
@@ -138,9 +138,9 @@
             "dev": true
         },
         "node_modules/@types/vscode": {
-            "version": "1.66.0",
-            "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.66.0.tgz",
-            "integrity": "sha512-ZfJck4M7nrGasfs4A4YbUoxis3Vu24cETw3DERsNYtDZmYSYtk6ljKexKFKhImO/ZmY6ZMsmegu2FPkXoUFImA==",
+            "version": "1.65.0",
+            "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.65.0.tgz",
+            "integrity": "sha512-wQhExnh2nEzpjDMSKhUvnNmz3ucpd3E+R7wJkOhBNK3No6fG3VUdmVmMOKD0A8NDZDDDiQcLNxe3oGmX5SjJ5w==",
             "dev": true
         },
         "node_modules/@typescript-eslint/eslint-plugin": {
@@ -3915,39 +3915,39 @@
             }
         },
         "node_modules/vscode-jsonrpc": {
-            "version": "8.0.0-next.7",
-            "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.0.0-next.7.tgz",
-            "integrity": "sha512-JX/F31LEsims0dAlOTKFE4E+AJMiJvdRSRViifFJSqSN7EzeYyWlfuDchF7g91oRNPZOIWfibTkDf3/UMsQGzQ==",
+            "version": "8.0.0-next.6",
+            "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.0.0-next.6.tgz",
+            "integrity": "sha512-6Ld3RYjygn5Ih7CkAtcAwiDQC+rakj2O+PnASfNyYv3sLmm44eJpEKzuPUN30Iy2UB09AZg8T6LBKWTJTEJDVw==",
             "engines": {
                 "node": ">=14.0.0"
             }
         },
         "node_modules/vscode-languageclient": {
-            "version": "8.0.0-next.14",
-            "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-8.0.0-next.14.tgz",
-            "integrity": "sha512-NqjkOuDTMu8uo+PhoMsV72VO9Gd3wBi/ZpOrkRUOrWKQo7yUdiIw183g8wjH8BImgbK9ZP51HM7TI0ZhCnI1Mw==",
+            "version": "8.0.0-next.12",
+            "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-8.0.0-next.12.tgz",
+            "integrity": "sha512-4+kr1BQcoh+sA5/4XJDJXrQXGQ5Yz/x+WpsVGGzK/TOB7RwQ63ooxG6Ej7i/+aOQM4/QdmcYWmipDtG7vqcOiw==",
             "dependencies": {
                 "minimatch": "^3.0.4",
                 "semver": "^7.3.5",
-                "vscode-languageserver-protocol": "3.17.0-next.16"
+                "vscode-languageserver-protocol": "3.17.0-next.14"
             },
             "engines": {
-                "vscode": "^1.66.0"
+                "vscode": "^1.63.0"
             }
         },
         "node_modules/vscode-languageserver-protocol": {
-            "version": "3.17.0-next.16",
-            "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.0-next.16.tgz",
-            "integrity": "sha512-tx4DnXw9u3N7vw+bx6n2NKp6FoxoNwiP/biH83AS30I2AnTGyLd7afSeH6Oewn2E8jvB7K15bs12sMppkKOVeQ==",
+            "version": "3.17.0-next.14",
+            "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.0-next.14.tgz",
+            "integrity": "sha512-iangobY8dL6sFZkOx4OhRPJM9gN0I1caUsOVR+MnPozsqQUtwMXmbIcfaIf0Akp0pd3KhJDPf/tdwRX68QGeeA==",
             "dependencies": {
-                "vscode-jsonrpc": "8.0.0-next.7",
-                "vscode-languageserver-types": "3.17.0-next.9"
+                "vscode-jsonrpc": "8.0.0-next.6",
+                "vscode-languageserver-types": "3.17.0-next.7"
             }
         },
         "node_modules/vscode-languageserver-types": {
-            "version": "3.17.0-next.9",
-            "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.0-next.9.tgz",
-            "integrity": "sha512-9/PeDNPYduaoXRUzYpqmu4ZV9L01HGo0wH9FUt+sSHR7IXwA7xoXBfNUlv8gB9H0D2WwEmMomSy1NmhjKQyn3A=="
+            "version": "3.17.0-next.7",
+            "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.0-next.7.tgz",
+            "integrity": "sha512-KH4zdG1qBXxoso61ChgpeoZYyHGJo8bV7Jv4I+fwQ1Ryy59JAxoZ9GAbhR5TeeafHctLcg6RFvY3m8Jqfu17cg=="
         },
         "node_modules/which": {
             "version": "2.0.2",
@@ -4214,9 +4214,9 @@
             "dev": true
         },
         "@types/vscode": {
-            "version": "1.66.0",
-            "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.66.0.tgz",
-            "integrity": "sha512-ZfJck4M7nrGasfs4A4YbUoxis3Vu24cETw3DERsNYtDZmYSYtk6ljKexKFKhImO/ZmY6ZMsmegu2FPkXoUFImA==",
+            "version": "1.65.0",
+            "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.65.0.tgz",
+            "integrity": "sha512-wQhExnh2nEzpjDMSKhUvnNmz3ucpd3E+R7wJkOhBNK3No6fG3VUdmVmMOKD0A8NDZDDDiQcLNxe3oGmX5SjJ5w==",
             "dev": true
         },
         "@typescript-eslint/eslint-plugin": {
@@ -6958,33 +6958,33 @@
             }
         },
         "vscode-jsonrpc": {
-            "version": "8.0.0-next.7",
-            "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.0.0-next.7.tgz",
-            "integrity": "sha512-JX/F31LEsims0dAlOTKFE4E+AJMiJvdRSRViifFJSqSN7EzeYyWlfuDchF7g91oRNPZOIWfibTkDf3/UMsQGzQ=="
+            "version": "8.0.0-next.6",
+            "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.0.0-next.6.tgz",
+            "integrity": "sha512-6Ld3RYjygn5Ih7CkAtcAwiDQC+rakj2O+PnASfNyYv3sLmm44eJpEKzuPUN30Iy2UB09AZg8T6LBKWTJTEJDVw=="
         },
         "vscode-languageclient": {
-            "version": "8.0.0-next.14",
-            "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-8.0.0-next.14.tgz",
-            "integrity": "sha512-NqjkOuDTMu8uo+PhoMsV72VO9Gd3wBi/ZpOrkRUOrWKQo7yUdiIw183g8wjH8BImgbK9ZP51HM7TI0ZhCnI1Mw==",
+            "version": "8.0.0-next.12",
+            "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-8.0.0-next.12.tgz",
+            "integrity": "sha512-4+kr1BQcoh+sA5/4XJDJXrQXGQ5Yz/x+WpsVGGzK/TOB7RwQ63ooxG6Ej7i/+aOQM4/QdmcYWmipDtG7vqcOiw==",
             "requires": {
                 "minimatch": "^3.0.4",
                 "semver": "^7.3.5",
-                "vscode-languageserver-protocol": "3.17.0-next.16"
+                "vscode-languageserver-protocol": "3.17.0-next.14"
             }
         },
         "vscode-languageserver-protocol": {
-            "version": "3.17.0-next.16",
-            "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.0-next.16.tgz",
-            "integrity": "sha512-tx4DnXw9u3N7vw+bx6n2NKp6FoxoNwiP/biH83AS30I2AnTGyLd7afSeH6Oewn2E8jvB7K15bs12sMppkKOVeQ==",
+            "version": "3.17.0-next.14",
+            "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.0-next.14.tgz",
+            "integrity": "sha512-iangobY8dL6sFZkOx4OhRPJM9gN0I1caUsOVR+MnPozsqQUtwMXmbIcfaIf0Akp0pd3KhJDPf/tdwRX68QGeeA==",
             "requires": {
-                "vscode-jsonrpc": "8.0.0-next.7",
-                "vscode-languageserver-types": "3.17.0-next.9"
+                "vscode-jsonrpc": "8.0.0-next.6",
+                "vscode-languageserver-types": "3.17.0-next.7"
             }
         },
         "vscode-languageserver-types": {
-            "version": "3.17.0-next.9",
-            "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.0-next.9.tgz",
-            "integrity": "sha512-9/PeDNPYduaoXRUzYpqmu4ZV9L01HGo0wH9FUt+sSHR7IXwA7xoXBfNUlv8gB9H0D2WwEmMomSy1NmhjKQyn3A=="
+            "version": "3.17.0-next.7",
+            "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.0-next.7.tgz",
+            "integrity": "sha512-KH4zdG1qBXxoso61ChgpeoZYyHGJo8bV7Jv4I+fwQ1Ryy59JAxoZ9GAbhR5TeeafHctLcg6RFvY3m8Jqfu17cg=="
         },
         "which": {
             "version": "2.0.2",
diff --git a/editors/code/package.json b/editors/code/package.json
index 7860d18758..c78f27b8d8 100644
--- a/editors/code/package.json
+++ b/editors/code/package.json
@@ -21,13 +21,13 @@
         "Programming Languages"
     ],
     "engines": {
-        "vscode": "^1.66.0"
+        "vscode": "^1.65.0"
     },
     "enabledApiProposals": [],
     "scripts": {
         "vscode:prepublish": "npm run build-base -- --minify",
         "package": "vsce package -o rust-analyzer.vsix",
-        "build-base": "esbuild ./src/main.ts --bundle --outfile=out/main.js --external:vscode --format=cjs --platform=node --target=node14",
+        "build-base": "esbuild ./src/main.ts --bundle --outfile=out/main.js --external:vscode --format=cjs --platform=node --target=node16",
         "build": "npm run build-base -- --sourcemap",
         "watch": "npm run build-base -- --sourcemap --watch",
         "lint": "tsfmt --verify && eslint -c .eslintrc.js --ext ts ./src ./tests",
@@ -36,13 +36,13 @@
         "test": "node ./out/tests/runTests.js"
     },
     "dependencies": {
-        "vscode-languageclient": "8.0.0-next.14",
+        "vscode-languageclient": "8.0.0-next.12",
         "d3": "^7.3.0",
         "d3-graphviz": "^4.1.0"
     },
     "devDependencies": {
         "@types/node": "~14.17.5",
-        "@types/vscode": "~1.66.0",
+        "@types/vscode": "~1.65.0",
         "@typescript-eslint/eslint-plugin": "^5.16.0",
         "@typescript-eslint/parser": "^5.16.0",
         "@vscode/test-electron": "^2.1.3",
@@ -476,17 +476,6 @@
                     "default": true,
                     "type": "boolean"
                 },
-                "rust-analyzer.cargo.runBuildScriptsCommand": {
-                    "markdownDescription": "Advanced option, fully override the command rust-analyzer uses to\nrun build scripts and build procedural macros. The command should\ninclude `--message-format=json` or a similar option.",
-                    "default": null,
-                    "type": [
-                        "null",
-                        "array"
-                    ],
-                    "items": {
-                        "type": "string"
-                    }
-                },
                 "rust-analyzer.cargo.useRustcWrapperForBuildScripts": {
                     "markdownDescription": "Use `RUSTC_WRAPPER=rust-analyzer` when running build scripts to\navoid compiling unnecessary things.",
                     "default": true,
diff --git a/editors/code/src/client.ts b/editors/code/src/client.ts
index f7520f6c43..26567c6df3 100644
--- a/editors/code/src/client.ts
+++ b/editors/code/src/client.ts
@@ -90,9 +90,9 @@ export function createClient(serverPath: string, workspace: Workspace, extraEnv:
                 const params: lc.CodeActionParams = {
                     textDocument: client.code2ProtocolConverter.asTextDocumentIdentifier(document),
                     range: client.code2ProtocolConverter.asRange(range),
-                    context: await client.code2ProtocolConverter.asCodeActionContext(context, token)
+                    context: client.code2ProtocolConverter.asCodeActionContext(context)
                 };
-                return client.sendRequest(lc.CodeActionRequest.type, params, token).then(async (values) => {
+                return client.sendRequest(lc.CodeActionRequest.type, params, token).then((values) => {
                     if (values === null) return undefined;
                     const result: (vscode.CodeAction | vscode.Command)[] = [];
                     const groups = new Map<string, { index: number; items: vscode.CodeAction[] }>();
@@ -100,7 +100,7 @@ export function createClient(serverPath: string, workspace: Workspace, extraEnv:
                         // In our case we expect to get code edits only from diagnostics
                         if (lc.CodeAction.is(item)) {
                             assert(!item.command, "We don't expect to receive commands in CodeActions");
-                            const action = await client.protocol2CodeConverter.asCodeAction(item, token);
+                            const action = client.protocol2CodeConverter.asCodeAction(item);
                             result.push(action);
                             continue;
                         }
diff --git a/editors/code/src/commands.ts b/editors/code/src/commands.ts
index 4b2ac44801..5581aac22f 100644
--- a/editors/code/src/commands.ts
+++ b/editors/code/src/commands.ts
@@ -127,8 +127,8 @@ export function joinLines(ctx: Ctx): Cmd {
             ranges: editor.selections.map((it) => client.code2ProtocolConverter.asRange(it)),
             textDocument: ctx.client.code2ProtocolConverter.asTextDocumentIdentifier(editor.document),
         });
-        await editor.edit(async (builder) => {
-            (await client.protocol2CodeConverter.asTextEdits(items)).forEach((edit: any) => {
+        await editor.edit((builder) => {
+            client.protocol2CodeConverter.asTextEdits(items).forEach((edit: any) => {
                 builder.replace(edit.range, edit.newText);
             });
         });
@@ -157,7 +157,7 @@ export function moveItem(ctx: Ctx, direction: ra.Direction): Cmd {
 
         if (!lcEdits) return;
 
-        const edits = await client.protocol2CodeConverter.asTextEdits(lcEdits);
+        const edits = client.protocol2CodeConverter.asTextEdits(lcEdits);
         await applySnippetTextEdits(editor, edits);
     };
 }
@@ -180,7 +180,7 @@ export function onEnter(ctx: Ctx): Cmd {
         });
         if (!lcEdits) return false;
 
-        const edits = await client.protocol2CodeConverter.asTextEdits(lcEdits);
+        const edits = client.protocol2CodeConverter.asTextEdits(lcEdits);
         await applySnippetTextEdits(editor, edits);
         return true;
     }
@@ -277,12 +277,12 @@ export function ssr(ctx: Ctx): Cmd {
             location: vscode.ProgressLocation.Notification,
             title: "Structured search replace in progress...",
             cancellable: false,
-        }, async (_progress, token) => {
+        }, async (_progress, _token) => {
             const edit = await client.sendRequest(ra.ssr, {
                 query: request, parseOnly: false, textDocument, position, selections,
             });
 
-            await vscode.workspace.applyEdit(await client.protocol2CodeConverter.asWorkspaceEdit(edit, token));
+            await vscode.workspace.applyEdit(client.protocol2CodeConverter.asWorkspaceEdit(edit));
         });
     };
 }
@@ -728,11 +728,11 @@ export function resolveCodeAction(ctx: Ctx): Cmd {
             return;
         }
         const itemEdit = item.edit;
-        const edit = await client.protocol2CodeConverter.asWorkspaceEdit(itemEdit);
+        const edit = client.protocol2CodeConverter.asWorkspaceEdit(itemEdit);
         // filter out all text edits and recreate the WorkspaceEdit without them so we can apply
         // snippet edits on our own
         const lcFileSystemEdit = { ...itemEdit, documentChanges: itemEdit.documentChanges?.filter(change => "kind" in change) };
-        const fileSystemEdit = await client.protocol2CodeConverter.asWorkspaceEdit(lcFileSystemEdit);
+        const fileSystemEdit = client.protocol2CodeConverter.asWorkspaceEdit(lcFileSystemEdit);
         await vscode.workspace.applyEdit(fileSystemEdit);
         await applySnippetWorkspaceEdit(edit);
     };
diff --git a/editors/code/src/inlay_hints.ts b/editors/code/src/inlay_hints.ts
new file mode 100644
index 0000000000..3f7ddedddf
--- /dev/null
+++ b/editors/code/src/inlay_hints.ts
@@ -0,0 +1,55 @@
+import * as vscode from 'vscode';
+import * as ra from './lsp_ext';
+
+import { Ctx, Disposable } from './ctx';
+import { sendRequestWithRetry, isRustDocument } from './util';
+
+export function activateInlayHints(ctx: Ctx) {
+    const maybeUpdater = {
+        hintsProvider: null as Disposable | null,
+        updateHintsEventEmitter: new vscode.EventEmitter<void>(),
+
+        async onConfigChange() {
+            this.dispose();
+
+            const anyEnabled = ctx.config.inlayHints.typeHints
+                || ctx.config.inlayHints.parameterHints
+                || ctx.config.inlayHints.chainingHints
+                || ctx.config.inlayHints.closureReturnTypeHints;
+            const enabled = ctx.config.inlayHints.enable && anyEnabled;
+            if (!enabled) return;
+
+            const event = this.updateHintsEventEmitter.event;
+            this.hintsProvider = vscode.languages.registerInlayHintsProvider({ scheme: 'file', language: 'rust' }, new class implements vscode.InlayHintsProvider {
+                onDidChangeInlayHints = event;
+                async provideInlayHints(document: vscode.TextDocument, range: vscode.Range, token: vscode.CancellationToken): Promise<vscode.InlayHint[]> {
+                    const request = { textDocument: { uri: document.uri.toString() }, range: { start: range.start, end: range.end } };
+                    const hints = await sendRequestWithRetry(ctx.client, ra.inlayHints, request, token).catch(_ => null);
+                    if (hints == null) {
+                        return [];
+                    } else {
+                        return hints;
+                    }
+                }
+            });
+        },
+
+        onDidChangeTextDocument({ contentChanges, document }: vscode.TextDocumentChangeEvent) {
+            if (contentChanges.length === 0 || !isRustDocument(document)) return;
+            this.updateHintsEventEmitter.fire();
+        },
+
+        dispose() {
+            this.hintsProvider?.dispose();
+            this.hintsProvider = null;
+            this.updateHintsEventEmitter.dispose();
+        },
+    };
+
+    ctx.pushCleanup(maybeUpdater);
+
+    vscode.workspace.onDidChangeConfiguration(maybeUpdater.onConfigChange, maybeUpdater, ctx.subscriptions);
+    vscode.workspace.onDidChangeTextDocument(maybeUpdater.onDidChangeTextDocument, maybeUpdater, ctx.subscriptions);
+
+    maybeUpdater.onConfigChange().catch(console.error);
+}
diff --git a/editors/code/src/lsp_ext.ts b/editors/code/src/lsp_ext.ts
index 61078b58c7..0ae5e93a73 100644
--- a/editors/code/src/lsp_ext.ts
+++ b/editors/code/src/lsp_ext.ts
@@ -2,6 +2,7 @@
  * This file mirrors `crates/rust-analyzer/src/lsp_ext.rs` declarations.
  */
 
+import { InlayHint } from "vscode";
 import * as lc from "vscode-languageclient";
 
 export interface AnalyzerStatusParams {
@@ -101,6 +102,12 @@ export interface TestInfo {
 
 export const relatedTests = new lc.RequestType<lc.TextDocumentPositionParams, TestInfo[], void>("rust-analyzer/relatedTests");
 
+export interface InlayHintsParams {
+    textDocument: lc.TextDocumentIdentifier;
+    range: lc.Range;
+}
+export const inlayHints = new lc.RequestType<InlayHintsParams, InlayHint[], void>("experimental/inlayHints");
+
 export interface SsrParams {
     query: string;
     parseOnly: boolean;
diff --git a/editors/code/src/main.ts b/editors/code/src/main.ts
index 0451e4c3d6..36a095bdd3 100644
--- a/editors/code/src/main.ts
+++ b/editors/code/src/main.ts
@@ -2,6 +2,7 @@ import * as vscode from 'vscode';
 import * as os from "os";
 
 import * as commands from './commands';
+import { activateInlayHints } from './inlay_hints';
 import { Ctx } from './ctx';
 import { Config } from './config';
 import { log, isValidExecutable, isRustDocument } from './util';
@@ -53,6 +54,7 @@ async function tryActivate(context: vscode.ExtensionContext) {
     }
     await initCommonContext(context, ctx);
 
+    activateInlayHints(ctx);
     warnAboutExtensionConflicts();
 
     ctx.pushCleanup(configureLanguage());
diff --git a/editors/code/tsconfig.json b/editors/code/tsconfig.json
index 7c4fbd21eb..e2ba2f231a 100644
--- a/editors/code/tsconfig.json
+++ b/editors/code/tsconfig.json
@@ -1,10 +1,10 @@
 {
     "compilerOptions": {
         "module": "commonjs",
-        "target": "es2019",
+        "target": "es2021",
         "outDir": "out",
         "lib": [
-            "es2019"
+            "es2021"
         ],
         "sourceMap": true,
         "rootDir": ".",
diff --git a/lib/arena/Cargo.toml b/lib/arena/Cargo.toml
index 2d3243a29b..39b005d094 100644
--- a/lib/arena/Cargo.toml
+++ b/lib/arena/Cargo.toml
@@ -3,7 +3,7 @@ name = "la-arena"
 version = "0.3.0"
 description = "Simple index-based arena without deletion."
 license = "MIT OR Apache-2.0"
-repository = "https://github.com/rust-lang/rust-analyzer"
+repository = "https://github.com/rust-analyzer/rust-analyzer"
 documentation = "https://docs.rs/la-arena"
 categories = ["data-structures", "memory-management", "rust-patterns"]
 edition = "2021"


Test patch:
diff --git a/crates/hir_def/src/item_tree/tests.rs b/crates/hir_def/src/item_tree/tests.rs
index fb3811dbd5..65352e7444 100644
--- a/crates/hir_def/src/item_tree/tests.rs
+++ b/crates/hir_def/src/item_tree/tests.rs
@@ -30,9 +30,9 @@ use crate::{A, B};
 use a::{c, d::{e}};
         "#,
         expect![[r##"
-            #![doc = " file comment"]
-            #![no_std]
-            #![doc = " another file comment"]
+            #![doc = " file comment"]  // AttrId { ast_index: 0 }
+            #![no_std]  // AttrId { ast_index: 1 }
+            #![doc = " another file comment"]  // AttrId { ast_index: 2 }
 
             pub(self) extern crate self as renamed;
 
@@ -42,7 +42,7 @@ use a::{c, d::{e}};
 
             pub(self) use globs::*;
 
-            #[doc = " docs on import"]
+            #[doc = " docs on import"]  // AttrId { ast_index: 0 }
             pub(self) use crate::{A, B};
 
             pub(self) use a::{c, d::{e}};
@@ -67,15 +67,15 @@ extern "C" {
 }
         "#,
         expect![[r##"
-            #[on_extern_block]
+            #[on_extern_block]  // AttrId { ast_index: 0 }
             extern "C" {
-                #[on_extern_type]
+                #[on_extern_type]  // AttrId { ast_index: 0 }
                 pub(self) type ExType;
 
-                #[on_extern_static]
+                #[on_extern_static]  // AttrId { ast_index: 0 }
                 pub(self) static EX_STATIC: u8 = _;
 
-                #[on_extern_fn]
+                #[on_extern_fn]  // AttrId { ast_index: 0 }
                 pub(self) fn ex_fn() -> ();
             }
         "##]],
@@ -115,14 +115,14 @@ enum E {
         expect![[r##"
             pub(self) struct Unit;
 
-            #[derive(Debug)]
+            #[derive(Debug)]  // AttrId { ast_index: 0 }
             pub(self) struct Struct {
-                #[doc = " fld docs"]
+                #[doc = " fld docs"]  // AttrId { ast_index: 0 }
                 pub(self) fld: (),
             }
 
             pub(self) struct Tuple(
-                #[attr]
+                #[attr]  // AttrId { ast_index: 0 }
                 pub(self) 0: u8,
             );
 
@@ -132,14 +132,14 @@ enum E {
             }
 
             pub(self) enum E {
-                #[doc = " comment on Unit"]
+                #[doc = " comment on Unit"]  // AttrId { ast_index: 0 }
                 Unit,
-                #[doc = " comment on Tuple"]
+                #[doc = " comment on Tuple"]  // AttrId { ast_index: 0 }
                 Tuple(
                     pub(self) 0: u8,
                 ),
                 Struct {
-                    #[doc = " comment on a: u8"]
+                    #[doc = " comment on a: u8"]  // AttrId { ast_index: 0 }
                     pub(self) a: u8,
                 },
             }
@@ -170,13 +170,14 @@ trait Tr: SuperTrait + 'lifetime {
 
             pub(self) const _: Anon = _;
 
-            #[attr]
-            #[inner_attr_in_fn]
+            #[attr]  // AttrId { ast_index: 0 }
+            #[inner_attr_in_fn]  // AttrId { ast_index: 1 }
+            // flags = 0x2
             pub(self) fn f(
-                #[attr]
+                #[attr]  // AttrId { ast_index: 0 }
                 arg: u8,
                 _: (),
-            ) -> () { ... }
+            ) -> ();
 
             pub(self) trait Tr<Self>
             where
@@ -185,8 +186,9 @@ trait Tr: SuperTrait + 'lifetime {
             {
                 pub(self) type Assoc: AssocBound = Default;
 
+                // flags = 0x1
                 pub(self) fn method(
-                    _: &Self,  // self
+                    _: &Self,
                 ) -> ();
             }
         "##]],
@@ -209,12 +211,13 @@ mod inline {
 mod outline;
         "#,
         expect![[r##"
-            #[doc = " outer"]
-            #[doc = " inner"]
+            #[doc = " outer"]  // AttrId { ast_index: 0 }
+            #[doc = " inner"]  // AttrId { ast_index: 1 }
             pub(self) mod inline {
                 pub(self) use super::*;
 
-                pub(self) fn fn_in_module() -> () { ... }
+                // flags = 0x2
+                pub(self) fn fn_in_module() -> ();
             }
 
             pub(self) mod outline;
@@ -335,11 +338,12 @@ trait Tr<'a, T: 'a>: Super where Self: for<'a> Tr<'a, T> {}
                 T: 'a,
                 T: 'b
             {
+                // flags = 0x2
                 pub(self) fn f<G>(
                     arg: impl Copy,
                 ) -> impl Copy
                 where
-                    G: 'a { ... }
+                    G: 'a;
             }
 
             pub(self) enum Enum<'a, T, const U: u8> {
@@ -388,9 +392,10 @@ pub(crate) trait Tr {
             pub(crate) trait Tr<Self> {
                 pub(crate) fn f() -> ();
 
+                // flags = 0x3
                 pub(crate) fn method(
-                    _: &Self,  // self
-                ) -> () { ... }
+                    _: &Self,
+                ) -> ();
             }
         "#]],
     )
diff --git a/crates/hir_ty/src/tests/method_resolution.rs b/crates/hir_ty/src/tests/method_resolution.rs
index 68463dc068..d97147541a 100644
--- a/crates/hir_ty/src/tests/method_resolution.rs
+++ b/crates/hir_ty/src/tests/method_resolution.rs
@@ -1767,26 +1767,3 @@ fn foo() {
 "#,
     );
 }
-
-#[test]
-fn primitive_assoc_fn_shadowed_by_use() {
-    check_types(
-        r#"
-//- /lib.rs crate:lib deps:core
-use core::u16;
-
-fn f() -> u16 {
-    let x = u16::from_le_bytes();
-      x
-    //^ u16
-}
-
-//- /core.rs crate:core
-pub mod u16 {}
-
-impl u16 {
-    pub fn from_le_bytes() -> Self { 0 }
-}
-        "#,
-    )
-}
diff --git a/crates/hir_ty/src/tests/regression.rs b/crates/hir_ty/src/tests/regression.rs
index c3c934c468..a02ec6f85c 100644
--- a/crates/hir_ty/src/tests/regression.rs
+++ b/crates/hir_ty/src/tests/regression.rs
@@ -1471,7 +1471,7 @@ fn regression_11688_3() {
 }
 
 #[test]
-fn gat_crash_1() {
+fn gat_crash() {
     cov_mark::check!(ignore_gats);
     check_no_mismatches(
         r#"
@@ -1489,26 +1489,6 @@ fn test<T: Crash>() {
     );
 }
 
-#[test]
-fn gat_crash_2() {
-    check_no_mismatches(
-        r#"
-pub struct InlineStorage {}
-
-pub struct InlineStorageHandle<T: ?Sized> {}
-
-pub unsafe trait Storage {
-    type Handle<T: ?Sized>;
-    fn create<T: ?Sized>() -> Self::Handle<T>;
-}
-
-unsafe impl Storage for InlineStorage {
-    type Handle<T: ?Sized> = InlineStorageHandle<T>;
-}
-"#,
-    );
-}
-
 #[test]
 fn cfgd_out_self_param() {
     cov_mark::check!(cfgd_out_self_param);
diff --git a/crates/ide_assists/src/tests.rs b/crates/ide_assists/src/tests.rs
index b3a0bd2773..09260c12ed 100644
--- a/crates/ide_assists/src/tests.rs
+++ b/crates/ide_assists/src/tests.rs
@@ -162,10 +162,6 @@ fn check(handler: Handler, before: &str, expected: ExpectedResult, assist_label:
                     FileSystemEdit::MoveFile { src, dst } => {
                         (dst, db.file_text(src).as_ref().to_owned())
                     }
-                    FileSystemEdit::MoveDir { src, src_id, dst } => {
-                        // temporary placeholder for MoveDir since we are not using MoveDir in ide assists yet.
-                        (dst, format!("{:?}\n{:?}", src_id, src))
-                    }
                 };
                 let sr = db.file_source_root(dst.anchor);
                 let sr = db.source_root(sr);
diff --git a/crates/ide_completion/src/tests/expression.rs b/crates/ide_completion/src/tests/expression.rs
index f1950235d4..de283c705d 100644
--- a/crates/ide_completion/src/tests/expression.rs
+++ b/crates/ide_completion/src/tests/expression.rs
@@ -137,9 +137,6 @@ impl Unit {
             kw trait
             kw static
             kw mod
-            kw enum
-            kw struct
-            kw union
             kw match
             kw while
             kw while let
@@ -230,9 +227,6 @@ fn complete_in_block() {
             kw trait
             kw static
             kw mod
-            kw enum
-            kw struct
-            kw union
             kw match
             kw while
             kw while let
@@ -275,9 +269,6 @@ fn complete_after_if_expr() {
             kw trait
             kw static
             kw mod
-            kw enum
-            kw struct
-            kw union
             kw match
             kw while
             kw while let
@@ -348,9 +339,6 @@ fn completes_in_loop_ctx() {
             kw trait
             kw static
             kw mod
-            kw enum
-            kw struct
-            kw union
             kw match
             kw while
             kw while let
diff --git a/crates/rust-analyzer/tests/slow-tests/tidy.rs b/crates/rust-analyzer/tests/slow-tests/tidy.rs
index 4a2f45fd51..1d04caa28a 100644
--- a/crates/rust-analyzer/tests/slow-tests/tidy.rs
+++ b/crates/rust-analyzer/tests/slow-tests/tidy.rs
@@ -146,7 +146,7 @@ fn check_cargo_toml(path: &Path, text: String) {
 fn check_merge_commits() {
     let sh = &Shell::new().unwrap();
 
-    let bors = cmd!(sh, "git rev-list --merges --author 'bors' HEAD~19..").read().unwrap();
+    let bors = cmd!(sh, "git rev-list --merges --author 'bors\\[bot\\]' HEAD~19..").read().unwrap();
     let all = cmd!(sh, "git rev-list --merges HEAD~19..").read().unwrap();
     if bors != all {
         panic!(