Repository: rust-lang/rust-analyzer
Pull request #12347 (2022-05-22 11:46:17)

fix(extract_module) resolving import panics and improve import resolution
- Should solve #11766 
- While adding a test case for this issue, I observed another issue:
For this test case:
```rust
            mod x {
                pub struct Foo;
                pub struct Bar;
            }

            use x::{Bar, Foo};

            $0type A = (Foo, Bar);$0
```
extract module should yield this:

```rust
            mod x {
                pub struct Foo;
                pub struct Bar;
            }

            use x::{};

            mod modname {
                use super::x::Bar;

                use super::x::Foo;

                pub(crate) type A = (Foo, Bar);
            }
```

instead it gave:

```rust
            mod x {
                pub struct Foo;
                pub struct Bar;
            }

            use x::{};

            mod modname {
                use x::Bar;

                use x::Foo;

                pub(crate) type A = (Foo, Bar);
            }
```

So fixed this problem with second commit


Patch:
diff --git a/Cargo.lock b/Cargo.lock
index f3bd3d6b76..917eed6d12 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -37,9 +37,9 @@ dependencies = [
 
 [[package]]
 name = "anyhow"
-version = "1.0.57"
+version = "1.0.56"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "08f9b8508dccb7687a1d6c4ce66b2b0ecef467c94667de27d8d7fe1f8d2a9cdc"
+checksum = "4361135be9122e0870de935d7c439aef945b9f9ddd4199a553b5270b49c82a27"
 
 [[package]]
 name = "anymap"
@@ -114,9 +114,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
 
 [[package]]
 name = "camino"
-version = "1.0.8"
+version = "1.0.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "07fd178c5af4d59e83498ef15cf3f154e1a6f9d091270cb86283c65ef44e9ef0"
+checksum = "6f3132262930b0522068049f5870a856ab8affc80c70d08b6ecb785771a6fc23"
 dependencies = [
  "serde",
 ]
@@ -316,9 +316,9 @@ dependencies = [
 
 [[package]]
 name = "dissimilar"
-version = "1.0.4"
+version = "1.0.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8c97b9233581d84b8e1e689cdd3a47b6f69770084fc246e86a7f78b0d9c1d4a5"
+checksum = "31ad93652f40969dead8d4bf897a41e9462095152eb21c56e5830537e41179dd"
 
 [[package]]
 name = "dot"
@@ -447,9 +447,9 @@ checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
 
 [[package]]
 name = "hashbrown"
-version = "0.12.1"
+version = "0.12.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "db0d4cf898abf0081f964436dc980e96670a0f36863e4b83aaacdb65c9d7ccc3"
+checksum = "8c21d40587b92fa6a6c6e3c1bdbf87d75511db5672f9c93175574b3a00df1758"
 
 [[package]]
 name = "heck"
@@ -533,7 +533,7 @@ dependencies = [
  "cov-mark",
  "either",
  "expect-test",
- "hashbrown 0.12.1",
+ "hashbrown 0.12.0",
  "itertools",
  "la-arena",
  "limit",
@@ -775,9 +775,9 @@ dependencies = [
 
 [[package]]
 name = "itoa"
-version = "1.0.2"
+version = "1.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "112c678d4050afce233f4f2852bb2eb519230b3cf12f33585275537d7e41578d"
+checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35"
 
 [[package]]
 name = "jod-thread"
@@ -787,9 +787,9 @@ checksum = "8b23360e99b8717f20aaa4598f5a6541efbe30630039fbc7706cf954a87947ae"
 
 [[package]]
 name = "kqueue"
-version = "1.0.6"
+version = "1.0.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4d6112e8f37b59803ac47a42d14f1f3a59bbf72fc6857ffc5be455e28a691f8e"
+checksum = "058a107a784f8be94c7d35c1300f4facced2e93d2fbe5b1452b44e905ddca4a9"
 dependencies = [
  "kqueue-sys",
  "libc",
@@ -817,9 +817,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
 
 [[package]]
 name = "libc"
-version = "0.2.126"
+version = "0.2.123"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836"
+checksum = "cb691a747a7ab48abc15c5b42066eaafde10dc427e3b6ee2a1cf43db04c763bd"
 
 [[package]]
 name = "libloading"
@@ -833,9 +833,9 @@ dependencies = [
 
 [[package]]
 name = "libmimalloc-sys"
-version = "0.1.25"
+version = "0.1.24"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "11ca136052550448f55df7898c6dbe651c6b574fe38a0d9ea687a9f8088a2e2c"
+checksum = "7705fc40f6ed493f73584abbb324e74f96b358ff60dfe5659a0f8fc12c590a69"
 dependencies = [
  "cc",
 ]
@@ -856,9 +856,9 @@ dependencies = [
 
 [[package]]
 name = "log"
-version = "0.4.17"
+version = "0.4.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
+checksum = "6389c490849ff5bc16be905ae24bc913a9c8892e19b2341dbc175e14c341c2b8"
 dependencies = [
  "cfg-if",
 ]
@@ -919,9 +919,9 @@ dependencies = [
 
 [[package]]
 name = "memchr"
-version = "2.5.0"
+version = "2.4.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
+checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
 
 [[package]]
 name = "memmap2"
@@ -943,9 +943,9 @@ dependencies = [
 
 [[package]]
 name = "mimalloc"
-version = "0.1.29"
+version = "0.1.28"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2f64ad83c969af2e732e907564deb0d0ed393cec4af80776f77dd77a1a427698"
+checksum = "b0dfa131390c2f6bdb3242f65ff271fcdaca5ff7b6c08f28398be7f2280e3926"
 dependencies = [
  "libmimalloc-sys",
 ]
@@ -961,14 +961,25 @@ dependencies = [
 
 [[package]]
 name = "mio"
-version = "0.8.3"
+version = "0.8.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "713d550d9b44d89174e066b7a6217ae06234c10cb47819a88290d2b353c31799"
+checksum = "52da4364ffb0e4fe33a9841a98a3f3014fb964045ce4f7a45a398243c8d6b0c9"
 dependencies = [
  "libc",
  "log",
+ "miow 0.3.7",
+ "ntapi",
  "wasi",
- "windows-sys 0.36.1",
+ "winapi",
+]
+
+[[package]]
+name = "miow"
+version = "0.3.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21"
+dependencies = [
+ "winapi",
 ]
 
 [[package]]
@@ -982,9 +993,9 @@ dependencies = [
 
 [[package]]
 name = "notify"
-version = "5.0.0-pre.15"
+version = "5.0.0-pre.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "553f9844ad0b0824605c20fb55a661679782680410abfb1a8144c2e7e437e7a7"
+checksum = "d13c22db70a63592e098fb51735bab36646821e6389a0ba171f3549facdf0b74"
 dependencies = [
  "bitflags",
  "crossbeam-channel",
@@ -998,6 +1009,15 @@ dependencies = [
  "winapi",
 ]
 
+[[package]]
+name = "ntapi"
+version = "0.3.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c28774a7fd2fbb4f0babd8237ce554b73af68021b5f695a3cebd6c59bac0980f"
+dependencies = [
+ "winapi",
+]
+
 [[package]]
 name = "num_cpus"
 version = "1.13.1"
@@ -1010,18 +1030,18 @@ dependencies = [
 
 [[package]]
 name = "object"
-version = "0.28.4"
+version = "0.28.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e42c982f2d955fac81dd7e1d0e1426a7d702acd9c98d19ab01083a6a0328c424"
+checksum = "40bec70ba014595f99f7aa110b84331ffe1ee9aece7fe6f387cc7e3ecda4d456"
 dependencies = [
  "memchr",
 ]
 
 [[package]]
 name = "once_cell"
-version = "1.11.0"
+version = "1.10.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7b10983b38c53aebdf33f542c6275b0f58a238129d00c4ae0e6fb59738d783ca"
+checksum = "87f3e037eac156d1775da914196f0f37741a274155e34a0b7e427c35d2a2ecb9"
 
 [[package]]
 name = "oorandom"
@@ -1047,7 +1067,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "87f5ec2493a61ac0506c0f4199f99070cbe83857b0337006a30f3e6719b8ef58"
 dependencies = [
  "lock_api",
- "parking_lot_core 0.9.3",
+ "parking_lot_core 0.9.2",
 ]
 
 [[package]]
@@ -1066,15 +1086,15 @@ dependencies = [
 
 [[package]]
 name = "parking_lot_core"
-version = "0.9.3"
+version = "0.9.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "09a279cbf25cb0757810394fbc1e359949b59e348145c643a939a525692e6929"
+checksum = "995f667a6c822200b0433ac218e05582f0e2efa1b922a3fd2fbaadc5f87bab37"
 dependencies = [
  "cfg-if",
  "libc",
  "redox_syscall",
  "smallvec",
- "windows-sys 0.36.1",
+ "windows-sys 0.34.0",
 ]
 
 [[package]]
@@ -1135,9 +1155,9 @@ dependencies = [
 
 [[package]]
 name = "pin-project-lite"
-version = "0.2.9"
+version = "0.2.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116"
+checksum = "e280fbe77cc62c91527259e9442153f4688736748d24660126286329742b4c6c"
 
 [[package]]
 name = "proc-macro-api"
@@ -1185,11 +1205,11 @@ version = "0.0.0"
 
 [[package]]
 name = "proc-macro2"
-version = "1.0.39"
+version = "1.0.37"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c54b25569025b7fc9651de43004ae593a75ad88543b17178aa5e1b9c4f15f56f"
+checksum = "ec757218438d5fda206afc041538b2f6d889286160d649a86a24d37e1235afd1"
 dependencies = [
- "unicode-ident",
+ "unicode-xid",
 ]
 
 [[package]]
@@ -1258,9 +1278,9 @@ dependencies = [
 
 [[package]]
 name = "rayon"
-version = "1.5.3"
+version = "1.5.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bd99e5772ead8baa5215278c9b15bf92087709e9c1b2d1f97cdb5a183c933a7d"
+checksum = "fd249e82c21598a9a426a4e00dd7adc1d640b22445ec8545feef801d1a74c221"
 dependencies = [
  "autocfg",
  "crossbeam-deque",
@@ -1270,9 +1290,9 @@ dependencies = [
 
 [[package]]
 name = "rayon-core"
-version = "1.9.3"
+version = "1.9.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "258bcdb5ac6dad48491bb2992db6b7cf74878b0384908af124823d118c99683f"
+checksum = "9f51245e1e62e1f1629cbfec37b5793bbabcaeb90f30e94d2ba03564687353e4"
 dependencies = [
  "crossbeam-channel",
  "crossbeam-deque",
@@ -1320,7 +1340,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "a4c1112d7b23c800be3a0dae244886b71d96b1461b57b31b56e4c679acbe614f"
 dependencies = [
  "countme",
- "hashbrown 0.12.1",
+ "hashbrown 0.12.0",
  "memoffset",
  "rustc-hash",
  "text-size",
@@ -1402,9 +1422,9 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
 
 [[package]]
 name = "ryu"
-version = "1.0.10"
+version = "1.0.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f3f6f92acf49d1b98f7a81226834412ada05458b7364277387724a237f062695"
+checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f"
 
 [[package]]
 name = "salsa"
@@ -1458,27 +1478,27 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
 
 [[package]]
 name = "semver"
-version = "1.0.9"
+version = "1.0.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8cb243bdfdb5936c8dc3c45762a19d12ab4550cdc753bc247637d4ec35a040fd"
+checksum = "d65bd28f48be7196d222d95b9243287f48d27aca604e08497513019ff0502cc4"
 dependencies = [
  "serde",
 ]
 
 [[package]]
 name = "serde"
-version = "1.0.137"
+version = "1.0.136"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "61ea8d54c77f8315140a05f4c7237403bf38b72704d031543aa1d16abbf517d1"
+checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789"
 dependencies = [
  "serde_derive",
 ]
 
 [[package]]
 name = "serde_derive"
-version = "1.0.137"
+version = "1.0.136"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1f26faba0c3959972377d3b2d306ee9f71faee9714294e41bb777f83f88578be"
+checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -1487,9 +1507,9 @@ dependencies = [
 
 [[package]]
 name = "serde_json"
-version = "1.0.81"
+version = "1.0.79"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9b7ce2b32a1aed03c558dc61a5cd328f15aff2dbc17daad8fb8af04d2100e15c"
+checksum = "8e8d9fa5c3b304765ce1fd9c4c8a3de2c8db365a5b91be52f186efc675681d95"
 dependencies = [
  "indexmap",
  "itoa",
@@ -1499,9 +1519,9 @@ dependencies = [
 
 [[package]]
 name = "serde_repr"
-version = "0.1.8"
+version = "0.1.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a2ad84e47328a31223de7fed7a4f5087f2d6ddfe586cf3ca25b7a165bc0a5aed"
+checksum = "98d0516900518c29efa217c298fa1f4e6c6ffc85ae29fd7f4ee48f176e1a9ed5"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -1552,19 +1572,19 @@ dependencies = [
  "always-assert",
  "backtrace",
  "libc",
- "miow",
+ "miow 0.4.0",
  "winapi",
 ]
 
 [[package]]
 name = "syn"
-version = "1.0.95"
+version = "1.0.91"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fbaf6116ab8924f39d52792136fb74fd60a80194cf1b1c6ffa6453eef1c3f942"
+checksum = "b683b2b825c8eef438b77c36a06dc262294da3d5a5813fac20da149241dcd44d"
 dependencies = [
  "proc-macro2",
  "quote",
- "unicode-ident",
+ "unicode-xid",
 ]
 
 [[package]]
@@ -1681,9 +1701,9 @@ dependencies = [
 
 [[package]]
 name = "tinyvec"
-version = "1.6.0"
+version = "1.5.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50"
+checksum = "2c1c1d5a42b6245520c249549ec267180beaffcc0615401ac8e31853d4b6d8d2"
 dependencies = [
  "tinyvec_macros",
 ]
@@ -1715,9 +1735,9 @@ dependencies = [
 
 [[package]]
 name = "tracing-attributes"
-version = "0.1.21"
+version = "0.1.20"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cc6b8ad3567499f98a1db7a752b07a7c8c7c7c34c332ec00effb2b0027974b7c"
+checksum = "2e65ce065b4b5c53e73bb28912318cb8c9e9ad3921f1d669eb0e68b4c8143a2b"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -1736,9 +1756,9 @@ dependencies = [
 
 [[package]]
 name = "tracing-log"
-version = "0.1.3"
+version = "0.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922"
+checksum = "a6923477a48e41c1951f1999ef8bb5a3023eb723ceadafe78ffb65dc366761e3"
 dependencies = [
  "lazy_static",
  "log",
@@ -1805,15 +1825,9 @@ dependencies = [
 
 [[package]]
 name = "unicode-bidi"
-version = "0.3.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992"
-
-[[package]]
-name = "unicode-ident"
-version = "1.0.0"
+version = "0.3.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d22af068fba1eb5edcb4aea19d382b2a3deb4c8f9d475c589b6ada9e0fd493ee"
+checksum = "1a01404663e3db436ed2746d9fefef640d868edae3cceb81c3b8d5732fda678f"
 
 [[package]]
 name = "unicode-normalization"
@@ -1832,9 +1846,9 @@ checksum = "7e8820f5d777f6224dc4be3632222971ac30164d4a258d595640799554ebfd99"
 
 [[package]]
 name = "unicode-xid"
-version = "0.2.3"
+version = "0.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "957e51f3646910546462e67d5f7599b9e4fb8acdd304b087a6494730f9eebf04"
+checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
 
 [[package]]
 name = "url"
@@ -1947,15 +1961,15 @@ dependencies = [
 
 [[package]]
 name = "windows-sys"
-version = "0.36.1"
+version = "0.34.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2"
+checksum = "5acdd78cb4ba54c0045ac14f62d8f94a03d10047904ae2a40afa1e99d8f70825"
 dependencies = [
- "windows_aarch64_msvc 0.36.1",
- "windows_i686_gnu 0.36.1",
- "windows_i686_msvc 0.36.1",
- "windows_x86_64_gnu 0.36.1",
- "windows_x86_64_msvc 0.36.1",
+ "windows_aarch64_msvc 0.34.0",
+ "windows_i686_gnu 0.34.0",
+ "windows_i686_msvc 0.34.0",
+ "windows_x86_64_gnu 0.34.0",
+ "windows_x86_64_msvc 0.34.0",
 ]
 
 [[package]]
@@ -1966,9 +1980,9 @@ checksum = "52695a41e536859d5308cc613b4a022261a274390b25bd29dfff4bf08505f3c2"
 
 [[package]]
 name = "windows_aarch64_msvc"
-version = "0.36.1"
+version = "0.34.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47"
+checksum = "17cffbe740121affb56fad0fc0e421804adf0ae00891205213b5cecd30db881d"
 
 [[package]]
 name = "windows_i686_gnu"
@@ -1978,9 +1992,9 @@ checksum = "f54725ac23affef038fecb177de6c9bf065787c2f432f79e3c373da92f3e1d8a"
 
 [[package]]
 name = "windows_i686_gnu"
-version = "0.36.1"
+version = "0.34.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6"
+checksum = "2564fde759adb79129d9b4f54be42b32c89970c18ebf93124ca8870a498688ed"
 
 [[package]]
 name = "windows_i686_msvc"
@@ -1990,9 +2004,9 @@ checksum = "51d5158a43cc43623c0729d1ad6647e62fa384a3d135fd15108d37c683461f64"
 
 [[package]]
 name = "windows_i686_msvc"
-version = "0.36.1"
+version = "0.34.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024"
+checksum = "9cd9d32ba70453522332c14d38814bceeb747d80b3958676007acadd7e166956"
 
 [[package]]
 name = "windows_x86_64_gnu"
@@ -2002,9 +2016,9 @@ checksum = "bc31f409f565611535130cfe7ee8e6655d3fa99c1c61013981e491921b5ce954"
 
 [[package]]
 name = "windows_x86_64_gnu"
-version = "0.36.1"
+version = "0.34.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1"
+checksum = "cfce6deae227ee8d356d19effc141a509cc503dfd1f850622ec4b0f84428e1f4"
 
 [[package]]
 name = "windows_x86_64_msvc"
@@ -2014,9 +2028,9 @@ checksum = "3f2b8c7cbd3bfdddd9ab98769f9746a7fad1bca236554cd032b78d768bc0e89f"
 
 [[package]]
 name = "windows_x86_64_msvc"
-version = "0.36.1"
+version = "0.34.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680"
+checksum = "d19538ccc21819d01deaf88d6a17eae6596a12e9aafdbb97916fb49896d89de9"
 
 [[package]]
 name = "write-json"
diff --git a/crates/base-db/src/fixture.rs b/crates/base-db/src/fixture.rs
index 69585b44a1..daa0e3f699 100644
--- a/crates/base-db/src/fixture.rs
+++ b/crates/base-db/src/fixture.rs
@@ -408,7 +408,6 @@ fn parse_crate(crate_str: String) -> (String, CrateOrigin, Option<String>) {
     } else {
         let crate_origin = match &*crate_str {
             "std" => CrateOrigin::Lang(LangCrateOrigin::Std),
-            "core" => CrateOrigin::Lang(LangCrateOrigin::Core),
             _ => CrateOrigin::CratesIo { repo: None },
         };
         (crate_str, crate_origin, None)
diff --git a/crates/hir-def/src/body/lower.rs b/crates/hir-def/src/body/lower.rs
index 5d7a1100cd..e8303ec40f 100644
--- a/crates/hir-def/src/body/lower.rs
+++ b/crates/hir-def/src/body/lower.rs
@@ -29,8 +29,8 @@ use crate::{
     builtin_type::{BuiltinFloat, BuiltinInt, BuiltinUint},
     db::DefDatabase,
     expr::{
-        dummy_expr_id, Array, BindingAnnotation, Expr, ExprId, FloatTypeWrapper, Label, LabelId,
-        Literal, MatchArm, Pat, PatId, RecordFieldPat, RecordLitField, Statement,
+        dummy_expr_id, Array, BindingAnnotation, Expr, ExprId, Label, LabelId, Literal, MatchArm,
+        Pat, PatId, RecordFieldPat, RecordLitField, Statement,
     },
     intern::Interned,
     item_scope::BuiltinShadowMode,
@@ -452,12 +452,7 @@ impl ExprCollector<'_> {
                     .map(|it| Interned::new(TypeRef::from_ast(&self.ctx(), it)));
                 let body = self.collect_expr_opt(e.body());
                 self.alloc_expr(
-                    Expr::Closure {
-                        args: args.into(),
-                        arg_types: arg_types.into(),
-                        ret_type,
-                        body,
-                    },
+                    Expr::Lambda { args: args.into(), arg_types: arg_types.into(), ret_type, body },
                     syntax_ptr,
                 )
             }
@@ -968,10 +963,7 @@ impl From<ast::LiteralKind> for Literal {
             // FIXME: these should have actual values filled in, but unsure on perf impact
             LiteralKind::IntNumber(lit) => {
                 if let builtin @ Some(_) = lit.suffix().and_then(BuiltinFloat::from_suffix) {
-                    Literal::Float(
-                        FloatTypeWrapper::new(lit.float_value().unwrap_or(Default::default())),
-                        builtin,
-                    )
+                    Literal::Float(Default::default(), builtin)
                 } else if let builtin @ Some(_) = lit.suffix().and_then(BuiltinInt::from_suffix) {
                     Literal::Int(lit.value().unwrap_or(0) as i128, builtin)
                 } else {
@@ -981,7 +973,7 @@ impl From<ast::LiteralKind> for Literal {
             }
             LiteralKind::FloatNumber(lit) => {
                 let ty = lit.suffix().and_then(BuiltinFloat::from_suffix);
-                Literal::Float(FloatTypeWrapper::new(lit.value().unwrap_or(Default::default())), ty)
+                Literal::Float(Default::default(), ty)
             }
             LiteralKind::ByteString(bs) => {
                 let text = bs.value().map(Box::from).unwrap_or_else(Default::default);
diff --git a/crates/hir-def/src/body/scope.rs b/crates/hir-def/src/body/scope.rs
index c9ab19e59b..fc36f1ae52 100644
--- a/crates/hir-def/src/body/scope.rs
+++ b/crates/hir-def/src/body/scope.rs
@@ -197,7 +197,7 @@ fn compute_expr_scopes(expr: ExprId, body: &Body, scopes: &mut ExprScopes, scope
             let mut scope = scopes.new_labeled_scope(*scope, make_label(label));
             compute_expr_scopes(*body_expr, body, scopes, &mut scope);
         }
-        Expr::Closure { args, body: body_expr, .. } => {
+        Expr::Lambda { args, body: body_expr, .. } => {
             let mut scope = scopes.new_scope(*scope);
             scopes.add_params_bindings(body, scope, args);
             compute_expr_scopes(*body_expr, body, scopes, &mut scope);
diff --git a/crates/hir-def/src/expr.rs b/crates/hir-def/src/expr.rs
index 97681abab1..4dca823888 100644
--- a/crates/hir-def/src/expr.rs
+++ b/crates/hir-def/src/expr.rs
@@ -38,24 +38,6 @@ pub struct Label {
 }
 pub type LabelId = Idx<Label>;
 
-// We convert float values into bits and that's how we don't need to deal with f32 and f64.
-// For PartialEq, bits comparison should work, as ordering is not important
-// https://github.com/rust-lang/rust-analyzer/issues/12380#issuecomment-1137284360
-#[derive(Default, Debug, Clone, Eq, PartialEq)]
-pub struct FloatTypeWrapper(u64);
-
-impl FloatTypeWrapper {
-    pub fn new(value: f64) -> Self {
-        Self(value.to_bits())
-    }
-}
-
-impl std::fmt::Display for FloatTypeWrapper {
-    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        write!(f, "{}", f64::from_bits(self.0))
-    }
-}
-
 #[derive(Debug, Clone, Eq, PartialEq)]
 pub enum Literal {
     String(Box<str>),
@@ -64,10 +46,7 @@ pub enum Literal {
     Bool(bool),
     Int(i128, Option<BuiltinInt>),
     Uint(u128, Option<BuiltinUint>),
-    // Here we are using a wrapper around float because f32 and f64 do not implement Eq, so they
-    // could not be used directly here, to understand how the wrapper works go to definition of
-    // FloatTypeWrapper
-    Float(FloatTypeWrapper, Option<BuiltinFloat>),
+    Float(u64, Option<BuiltinFloat>), // FIXME: f64 is not Eq
 }
 
 #[derive(Debug, Clone, Eq, PartialEq)]
@@ -186,7 +165,7 @@ pub enum Expr {
         base: ExprId,
         index: ExprId,
     },
-    Closure {
+    Lambda {
         args: Box<[PatId]>,
         arg_types: Box<[Option<Interned<TypeRef>>]>,
         ret_type: Option<Interned<TypeRef>>,
@@ -307,7 +286,7 @@ impl Expr {
                     f(expr);
                 }
             }
-            Expr::Closure { body, .. } => {
+            Expr::Lambda { body, .. } => {
                 f(*body);
             }
             Expr::BinaryOp { lhs, rhs, .. } => {
diff --git a/crates/hir-def/src/nameres/collector.rs b/crates/hir-def/src/nameres/collector.rs
index 7fea46bee3..a9705cf2dc 100644
--- a/crates/hir-def/src/nameres/collector.rs
+++ b/crates/hir-def/src/nameres/collector.rs
@@ -29,6 +29,7 @@ use crate::{
     attr_macro_as_call_id,
     db::DefDatabase,
     derive_macro_as_call_id,
+    intern::Interned,
     item_scope::{ImportType, PerNsGlobImports},
     item_tree::{
         self, Fields, FileItemTreeId, ImportKind, ItemTree, ItemTreeId, ItemTreeNode, MacroCall,
@@ -95,7 +96,7 @@ pub(super) fn collect_defs(db: &dyn DefDatabase, mut def_map: DefMap, tree_id: T
         deps,
         glob_imports: FxHashMap::default(),
         unresolved_imports: Vec::new(),
-        indeterminate_imports: Vec::new(),
+        resolved_imports: Vec::new(),
         unresolved_macros: Vec::new(),
         mod_dirs: FxHashMap::default(),
         cfg_options,
@@ -141,9 +142,9 @@ enum ImportSource {
     ExternCrate(ItemTreeId<item_tree::ExternCrate>),
 }
 
-#[derive(Debug, Eq, PartialEq)]
+#[derive(Clone, Debug, Eq, PartialEq)]
 struct Import {
-    path: ModPath,
+    path: Interned<ModPath>,
     alias: Option<ImportAlias>,
     visibility: RawVisibility,
     kind: ImportKind,
@@ -168,7 +169,7 @@ impl Import {
         let mut res = Vec::new();
         it.use_tree.expand(|idx, path, kind, alias| {
             res.push(Self {
-                path,
+                path: Interned::new(path), // FIXME this makes little sense
                 alias,
                 visibility: visibility.clone(),
                 kind,
@@ -191,7 +192,10 @@ impl Import {
         let attrs = &tree.attrs(db, krate, ModItem::from(id.value).into());
         let visibility = &tree[it.visibility];
         Self {
-            path: ModPath::from_segments(PathKind::Plain, iter::once(it.name.clone())),
+            path: Interned::new(ModPath::from_segments(
+                PathKind::Plain,
+                iter::once(it.name.clone()),
+            )),
             alias: it.alias.clone(),
             visibility: visibility.clone(),
             kind: ImportKind::Plain,
@@ -203,7 +207,7 @@ impl Import {
     }
 }
 
-#[derive(Debug, Eq, PartialEq)]
+#[derive(Clone, Debug, Eq, PartialEq)]
 struct ImportDirective {
     module_id: LocalModuleId,
     import: Import,
@@ -232,7 +236,7 @@ struct DefCollector<'a> {
     deps: FxHashMap<Name, ModuleId>,
     glob_imports: FxHashMap<LocalModuleId, Vec<(LocalModuleId, Visibility)>>,
     unresolved_imports: Vec<ImportDirective>,
-    indeterminate_imports: Vec<ImportDirective>,
+    resolved_imports: Vec<ImportDirective>,
     unresolved_macros: Vec<MacroDirective>,
     mod_dirs: FxHashMap<LocalModuleId, ModDir>,
     cfg_options: &'a CfgOptions,
@@ -348,32 +352,30 @@ impl DefCollector<'_> {
 
         // main name resolution fixed-point loop.
         let mut i = 0;
-        'resolve_attr: loop {
-            'resolve_macros: loop {
+        'outer: loop {
+            loop {
                 self.db.unwind_if_cancelled();
-
                 {
                     let _p = profile::span("resolve_imports loop");
-
-                    'resolve_imports: loop {
+                    loop {
                         if self.resolve_imports() == ReachedFixedPoint::Yes {
-                            break 'resolve_imports;
+                            break;
                         }
                     }
                 }
                 if self.resolve_macros() == ReachedFixedPoint::Yes {
-                    break 'resolve_macros;
+                    break;
                 }
 
                 i += 1;
                 if FIXED_POINT_LIMIT.check(i).is_err() {
                     tracing::error!("name resolution is stuck");
-                    break 'resolve_attr;
+                    break 'outer;
                 }
             }
 
             if self.reseed_with_unresolved_attribute() == ReachedFixedPoint::Yes {
-                break 'resolve_attr;
+                break;
             }
         }
     }
@@ -387,9 +389,14 @@ impl DefCollector<'_> {
         // As some of the macros will expand newly import shadowing partial resolved imports
         // FIXME: We maybe could skip this, if we handle the indeterminate imports in `resolve_imports`
         // correctly
-        let partial_resolved = self.indeterminate_imports.drain(..).filter_map(|mut directive| {
-            directive.status = PartialResolvedImport::Unresolved;
-            Some(directive)
+        let partial_resolved = self.resolved_imports.iter().filter_map(|directive| {
+            if let PartialResolvedImport::Indeterminate(_) = directive.status {
+                let mut directive = directive.clone();
+                directive.status = PartialResolvedImport::Unresolved;
+                Some(directive)
+            } else {
+                None
+            }
         });
         self.unresolved_imports.extend(partial_resolved);
         self.resolve_imports();
@@ -710,12 +717,15 @@ impl DefCollector<'_> {
                 match directive.status {
                     PartialResolvedImport::Indeterminate(_) => {
                         self.record_resolved_import(&directive);
-                        self.indeterminate_imports.push(directive);
+                        // FIXME: For avoid performance regression,
+                        // we consider an imported resolved if it is indeterminate (i.e not all namespace resolved)
+                        self.resolved_imports.push(directive);
                         res = ReachedFixedPoint::No;
                         None
                     }
                     PartialResolvedImport::Resolved(_) => {
                         self.record_resolved_import(&directive);
+                        self.resolved_imports.push(directive);
                         res = ReachedFixedPoint::No;
                         None
                     }
@@ -2092,7 +2102,7 @@ mod tests {
             deps: FxHashMap::default(),
             glob_imports: FxHashMap::default(),
             unresolved_imports: Vec::new(),
-            indeterminate_imports: Vec::new(),
+            resolved_imports: Vec::new(),
             unresolved_macros: Vec::new(),
             mod_dirs: FxHashMap::default(),
             cfg_options: &CfgOptions::default(),
diff --git a/crates/hir-expand/src/builtin_derive_macro.rs b/crates/hir-expand/src/builtin_derive_macro.rs
index 79989bc2e3..f7d5532df5 100644
--- a/crates/hir-expand/src/builtin_derive_macro.rs
+++ b/crates/hir-expand/src/builtin_derive_macro.rs
@@ -1,6 +1,5 @@
 //! Builtin derives.
 
-use base_db::{CrateOrigin, LangCrateOrigin};
 use tracing::debug;
 
 use syntax::{
@@ -161,11 +160,14 @@ fn find_builtin_crate(db: &dyn AstDatabase, id: MacroCallId) -> tt::TokenTree {
     let cg = db.crate_graph();
     let krate = db.lookup_intern_macro_call(id).krate;
 
-    let tt = if matches!(cg[krate].origin, CrateOrigin::Lang(LangCrateOrigin::Core)) {
+    // XXX
+    //  All crates except core itself should have a dependency on core,
+    //  We detect `core` by seeing whether it doesn't have such a dependency.
+    let tt = if cg[krate].dependencies.iter().any(|dep| &*dep.name == "core") {
+        quote! { core }
+    } else {
         cov_mark::hit!(test_copy_expand_in_core);
         quote! { crate }
-    } else {
-        quote! { core }
     };
 
     tt.token_trees[0].clone()
diff --git a/crates/hir-ty/src/infer/expr.rs b/crates/hir-ty/src/infer/expr.rs
index 2e645bf52b..2bb384ba22 100644
--- a/crates/hir-ty/src/infer/expr.rs
+++ b/crates/hir-ty/src/infer/expr.rs
@@ -218,7 +218,7 @@ impl<'a> InferenceContext<'a> {
                 self.diverges = Diverges::Maybe;
                 TyBuilder::unit()
             }
-            Expr::Closure { body, args, ret_type, arg_types } => {
+            Expr::Lambda { body, args, ret_type, arg_types } => {
                 assert_eq!(args.len(), arg_types.len());
 
                 let mut sig_tys = Vec::new();
@@ -1058,7 +1058,7 @@ impl<'a> InferenceContext<'a> {
             for (idx, ((&arg, param_ty), expected_ty)) in
                 args.iter().zip(param_iter).zip(expected_iter).enumerate()
             {
-                let is_closure = matches!(&self.body[arg], Expr::Closure { .. });
+                let is_closure = matches!(&self.body[arg], Expr::Lambda { .. });
                 if is_closure != check_closures {
                     continue;
                 }
diff --git a/crates/hir-ty/src/infer/pat.rs b/crates/hir-ty/src/infer/pat.rs
index c06d262f5e..f8131314c6 100644
--- a/crates/hir-ty/src/infer/pat.rs
+++ b/crates/hir-ty/src/infer/pat.rs
@@ -1,6 +1,6 @@
 //! Type inference for patterns.
 
-use std::iter::repeat_with;
+use std::iter::repeat;
 
 use chalk_ir::Mutability;
 use hir_def::{
@@ -42,7 +42,7 @@ impl<'a> InferenceContext<'a> {
             Some(idx) => subpats.split_at(idx),
             None => (subpats, &[][..]),
         };
-        let post_idx_offset = field_tys.iter().count().saturating_sub(post.len());
+        let post_idx_offset = field_tys.iter().count() - post.len();
 
         let pre_iter = pre.iter().enumerate();
         let post_iter = (post_idx_offset..).zip(post.iter());
@@ -140,28 +140,15 @@ impl<'a> InferenceContext<'a> {
                     }
                     None => ((&args[..], &[][..]), 0),
                 };
-                let mut expectations_iter = expectations
-                    .iter()
-                    .cloned()
-                    .map(|a| a.assert_ty_ref(Interner).clone())
-                    .chain(repeat_with(|| self.table.new_type_var()));
+                let err_ty = self.err_ty();
+                let mut expectations_iter =
+                    expectations.iter().map(|a| a.assert_ty_ref(Interner)).chain(repeat(&err_ty));
+                let mut infer_pat = |(&pat, ty)| self.infer_pat(pat, ty, default_bm);
 
                 let mut inner_tys = Vec::with_capacity(n_uncovered_patterns + args.len());
-
-                inner_tys
-                    .extend(expectations_iter.by_ref().take(n_uncovered_patterns + args.len()));
-
-                // Process pre
-                for (ty, pat) in inner_tys.iter_mut().zip(pre) {
-                    *ty = self.infer_pat(*pat, ty, default_bm);
-                }
-
-                // Process post
-                for (ty, pat) in
-                    inner_tys.iter_mut().skip(pre.len() + n_uncovered_patterns).zip(post)
-                {
-                    *ty = self.infer_pat(*pat, ty, default_bm);
-                }
+                inner_tys.extend(pre.iter().zip(expectations_iter.by_ref()).map(&mut infer_pat));
+                inner_tys.extend(expectations_iter.by_ref().take(n_uncovered_patterns).cloned());
+                inner_tys.extend(post.iter().zip(expectations_iter).map(infer_pat));
 
                 TyKind::Tuple(inner_tys.len(), Substitution::from_iter(Interner, inner_tys))
                     .intern(Interner)
diff --git a/crates/hir-ty/src/traits.rs b/crates/hir-ty/src/traits.rs
index 77afeb3217..b139edbee9 100644
--- a/crates/hir-ty/src/traits.rs
+++ b/crates/hir-ty/src/traits.rs
@@ -27,7 +27,7 @@ pub(crate) struct ChalkContext<'a> {
 
 fn create_chalk_solver() -> chalk_recursive::RecursiveSolver<Interner> {
     let overflow_depth =
-        var("CHALK_OVERFLOW_DEPTH").ok().and_then(|s| s.parse().ok()).unwrap_or(500);
+        var("CHALK_OVERFLOW_DEPTH").ok().and_then(|s| s.parse().ok()).unwrap_or(300);
     let max_size = var("CHALK_SOLVER_MAX_SIZE").ok().and_then(|s| s.parse().ok()).unwrap_or(150);
     chalk_recursive::RecursiveSolver::new(overflow_depth, max_size, Some(Cache::new()))
 }
diff --git a/crates/hir/src/has_source.rs b/crates/hir/src/has_source.rs
index f8b01db3e3..037f51ec8e 100644
--- a/crates/hir/src/has_source.rs
+++ b/crates/hir/src/has_source.rs
@@ -39,11 +39,6 @@ impl Module {
         }
     }
 
-    pub fn is_inline(self, db: &dyn HirDatabase) -> bool {
-        let def_map = self.id.def_map(db.upcast());
-        def_map[self.id.local_id].origin.is_inline()
-    }
-
     /// Returns a node which declares this module, either a `mod foo;` or a `mod foo {}`.
     /// `None` for the crate root.
     pub fn declaration_source(self, db: &dyn HirDatabase) -> Option<InFile<ast::Module>> {
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index 3f62a2cd33..12e06bf4ac 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -62,9 +62,9 @@ use hir_ty::{
     subst_prefix,
     traits::FnTrait,
     AliasEq, AliasTy, BoundVar, CallableDefId, CallableSig, Canonical, CanonicalVarKinds, Cast,
-    ClosureId, DebruijnIndex, GenericArgData, InEnvironment, Interner, ParamKind,
-    QuantifiedWhereClause, Scalar, Solution, Substitution, TraitEnvironment, TraitRefExt, Ty,
-    TyBuilder, TyDefId, TyExt, TyKind, TyVariableKind, WhereClause,
+    DebruijnIndex, GenericArgData, InEnvironment, Interner, ParamKind, QuantifiedWhereClause,
+    Scalar, Solution, Substitution, TraitEnvironment, TraitRefExt, Ty, TyBuilder, TyDefId, TyExt,
+    TyKind, TyVariableKind, WhereClause,
 };
 use itertools::Itertools;
 use nameres::diagnostics::DefDiagnosticKind;
@@ -2819,14 +2819,10 @@ impl Type {
     }
 
     pub fn as_callable(&self, db: &dyn HirDatabase) -> Option<Callable> {
-        let callee = match self.ty.kind(Interner) {
-            TyKind::Closure(id, _) => Callee::Closure(*id),
-            TyKind::Function(_) => Callee::FnPtr,
-            _ => Callee::Def(self.ty.callable_def(db)?),
-        };
+        let def = self.ty.callable_def(db);
 
         let sig = self.ty.callable_sig(db)?;
-        Some(Callable { ty: self.clone(), sig, callee, is_bound_method: false })
+        Some(Callable { ty: self.clone(), sig, def, is_bound_method: false })
     }
 
     pub fn is_closure(&self) -> bool {
@@ -3269,43 +3265,34 @@ impl Type {
     }
 }
 
+// FIXME: closures
 #[derive(Debug)]
 pub struct Callable {
     ty: Type,
     sig: CallableSig,
-    callee: Callee,
+    def: Option<CallableDefId>,
     pub(crate) is_bound_method: bool,
 }
 
-#[derive(Debug)]
-enum Callee {
-    Def(CallableDefId),
-    Closure(ClosureId),
-    FnPtr,
-}
-
 pub enum CallableKind {
     Function(Function),
     TupleStruct(Struct),
     TupleEnumVariant(Variant),
     Closure,
-    FnPtr,
 }
 
 impl Callable {
     pub fn kind(&self) -> CallableKind {
-        use Callee::*;
-        match self.callee {
-            Def(CallableDefId::FunctionId(it)) => CallableKind::Function(it.into()),
-            Def(CallableDefId::StructId(it)) => CallableKind::TupleStruct(it.into()),
-            Def(CallableDefId::EnumVariantId(it)) => CallableKind::TupleEnumVariant(it.into()),
-            Closure(_) => CallableKind::Closure,
-            FnPtr => CallableKind::FnPtr,
+        match self.def {
+            Some(CallableDefId::FunctionId(it)) => CallableKind::Function(it.into()),
+            Some(CallableDefId::StructId(it)) => CallableKind::TupleStruct(it.into()),
+            Some(CallableDefId::EnumVariantId(it)) => CallableKind::TupleEnumVariant(it.into()),
+            None => CallableKind::Closure,
         }
     }
     pub fn receiver_param(&self, db: &dyn HirDatabase) -> Option<ast::SelfParam> {
-        let func = match self.callee {
-            Callee::Def(CallableDefId::FunctionId(it)) if self.is_bound_method => it,
+        let func = match self.def {
+            Some(CallableDefId::FunctionId(it)) if self.is_bound_method => it,
             _ => return None,
         };
         let src = func.lookup(db.upcast()).source(db.upcast());
@@ -3325,9 +3312,8 @@ impl Callable {
             .iter()
             .skip(if self.is_bound_method { 1 } else { 0 })
             .map(|ty| self.ty.derived(ty.clone()));
-        let map_param = |it: ast::Param| it.pat().map(Either::Right);
-        let patterns = match self.callee {
-            Callee::Def(CallableDefId::FunctionId(func)) => {
+        let patterns = match self.def {
+            Some(CallableDefId::FunctionId(func)) => {
                 let src = func.lookup(db.upcast()).source(db.upcast());
                 src.value.param_list().map(|param_list| {
                     param_list
@@ -3335,20 +3321,9 @@ impl Callable {
                         .map(|it| Some(Either::Left(it)))
                         .filter(|_| !self.is_bound_method)
                         .into_iter()
-                        .chain(param_list.params().map(map_param))
+                        .chain(param_list.params().map(|it| it.pat().map(Either::Right)))
                 })
             }
-            Callee::Closure(closure_id) => match closure_source(db, closure_id) {
-                Some(src) => src.param_list().map(|param_list| {
-                    param_list
-                        .self_param()
-                        .map(|it| Some(Either::Left(it)))
-                        .filter(|_| !self.is_bound_method)
-                        .into_iter()
-                        .chain(param_list.params().map(map_param))
-                }),
-                None => None,
-            },
             _ => None,
         };
         patterns.into_iter().flatten().chain(iter::repeat(None)).zip(types).collect()
@@ -3358,18 +3333,6 @@ impl Callable {
     }
 }
 
-fn closure_source(db: &dyn HirDatabase, closure: ClosureId) -> Option<ast::ClosureExpr> {
-    let (owner, expr_id) = db.lookup_intern_closure(closure.into());
-    let (_, source_map) = db.body_with_source_map(owner);
-    let ast = source_map.expr_syntax(expr_id).ok()?;
-    let root = ast.file_syntax(db.upcast());
-    let expr = ast.value.to_node(&root);
-    match expr {
-        ast::Expr::ClosureExpr(it) => Some(it),
-        _ => None,
-    }
-}
-
 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
 pub enum BindingMode {
     Move,
diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs
index 282e9c0a4b..48661ec4eb 100644
--- a/crates/hir/src/semantics.rs
+++ b/crates/hir/src/semantics.rs
@@ -208,14 +208,14 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
         self.imp.descend_into_macros(token)
     }
 
-    /// Descend the token into macrocalls to all its mapped counterparts that have the same text as the input token.
+    /// Descend the token into macrocalls to all its mapped counterparts.
     ///
-    /// Returns the original non descended token if none of the mapped counterparts have the same text.
-    pub fn descend_into_macros_with_same_text(
+    /// Returns the original non descended token if none of the mapped counterparts have the same syntax kind.
+    pub fn descend_into_macros_with_same_kind(
         &self,
         token: SyntaxToken,
     ) -> SmallVec<[SyntaxToken; 1]> {
-        self.imp.descend_into_macros_with_same_text(token)
+        self.imp.descend_into_macros_with_same_kind(token)
     }
 
     /// Maps a node down by mapping its first and last token down.
@@ -666,11 +666,11 @@ impl<'db> SemanticsImpl<'db> {
         res
     }
 
-    fn descend_into_macros_with_same_text(&self, token: SyntaxToken) -> SmallVec<[SyntaxToken; 1]> {
-        let text = token.text();
+    fn descend_into_macros_with_same_kind(&self, token: SyntaxToken) -> SmallVec<[SyntaxToken; 1]> {
+        let kind = token.kind();
         let mut res = smallvec![];
         self.descend_into_macros_impl(token.clone(), &mut |InFile { value, .. }| {
-            if value.text() == text {
+            if value.kind() == kind {
                 res.push(value);
             }
             false
diff --git a/crates/ide-assists/src/handlers/add_attribute.rs b/crates/ide-assists/src/handlers/add_attribute.rs
new file mode 100644
index 0000000000..dcb52b151d
--- /dev/null
+++ b/crates/ide-assists/src/handlers/add_attribute.rs
@@ -0,0 +1,196 @@
+use ide_db::assists::{AssistId, AssistKind, GroupLabel};
+use syntax::{
+    ast::{self, HasAttrs},
+    match_ast, AstNode, SyntaxKind, TextSize,
+};
+
+use crate::assist_context::{AssistContext, Assists};
+
+// Assist: add_attribute
+//
+// Adds commonly used attributes to items.
+//
+// ```
+// struct Point {
+//     x: u32,
+//     y: u32,$0
+// }
+// ```
+// ->add_derive
+// ```
+// #[derive($0)]
+// struct Point {
+//     x: u32,
+//     y: u32,
+// }
+// ```
+pub(crate) fn add_attribute(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
+    let cap = ctx.config.snippet_cap?;
+
+    let (attr_owner, attrs) = ctx
+        .find_node_at_offset::<ast::AnyHasAttrs>()?
+        .syntax()
+        .ancestors()
+        .filter_map(ast::AnyHasAttrs::cast)
+        .find_map(|attr_owner| {
+            let node = attr_owner.syntax();
+            match_ast! {
+                match node {
+                    ast::Adt(_) => Some((attr_owner, ADT_ATTRS)),
+                    ast::Fn(_) => Some((attr_owner, FN_ATTRS)),
+                    _ => None,
+                }
+            }
+        })?;
+
+    let offset = attr_insertion_offset(&attr_owner)?;
+
+    for tpl in attrs {
+        let existing_offset = attr_owner.attrs().find_map(|attr| {
+            if attr.simple_name()? == tpl.name {
+                match attr.token_tree() {
+                    Some(tt) => {
+                        // Attribute like `#[derive(...)]`, position cursor right before the `)`
+                        return Some(tt.syntax().text_range().end() - TextSize::of(')'));
+                    }
+                    None => {
+                        // `#[key = value]`
+                        let tok = attr.syntax().last_token()?;
+                        if tok.kind() == SyntaxKind::R_BRACK {
+                            return Some(tok.text_range().end() - TextSize::of(']'));
+                        }
+                    }
+                }
+            }
+            None
+        });
+        acc.add_group(
+            &GroupLabel("Add attribute".into()),
+            AssistId(tpl.id, AssistKind::Generate),
+            format!("Add `#[{}]`", tpl.name),
+            attr_owner.syntax().text_range(),
+            |b| match existing_offset {
+                Some(offset) => {
+                    b.insert_snippet(cap, offset, "$0");
+                }
+                None => {
+                    b.insert_snippet(cap, offset, format!("#[{}]\n", tpl.snippet));
+                }
+            },
+        );
+    }
+
+    Some(())
+}
+
+fn attr_insertion_offset(nominal: &ast::AnyHasAttrs) -> Option<TextSize> {
+    let non_ws_child = nominal
+        .syntax()
+        .children_with_tokens()
+        .find(|it| it.kind() != SyntaxKind::COMMENT && it.kind() != SyntaxKind::WHITESPACE)?;
+    Some(non_ws_child.text_range().start())
+}
+
+static ADT_ATTRS: &[AttrTemplate] = &[
+    AttrTemplate { id: "add_derive", name: "derive", snippet: "derive($0)" },
+    AttrTemplate { id: "add_must_use", name: "must_use", snippet: "must_use$0" },
+];
+
+static FN_ATTRS: &[AttrTemplate] = &[
+    AttrTemplate { id: "add_inline", name: "inline", snippet: "inline$0" },
+    AttrTemplate { id: "add_must_use", name: "must_use", snippet: "must_use$0" },
+];
+
+struct AttrTemplate {
+    /// Assist ID.
+    id: &'static str,
+    /// User-facing attribute name.
+    name: &'static str,
+    /// Snippet to insert.
+    snippet: &'static str,
+}
+
+#[cfg(test)]
+mod tests {
+    use crate::tests::{check_assist_by_label, check_assist_target};
+
+    use super::add_attribute;
+
+    fn check_derive(ra_fixture_before: &str, ra_fixture_after: &str) {
+        check_assist_by_label(
+            add_attribute,
+            ra_fixture_before,
+            ra_fixture_after,
+            "Add `#[derive]`",
+        );
+    }
+
+    fn check_must_use(ra_fixture_before: &str, ra_fixture_after: &str) {
+        check_assist_by_label(
+            add_attribute,
+            ra_fixture_before,
+            ra_fixture_after,
+            "Add `#[must_use]`",
+        );
+    }
+
+    #[test]
+    fn add_derive_new() {
+        check_derive("struct Foo { a: i32, $0}", "#[derive($0)]\nstruct Foo { a: i32, }");
+        check_derive("struct Foo { $0 a: i32, }", "#[derive($0)]\nstruct Foo {  a: i32, }");
+    }
+
+    #[test]
+    fn add_derive_existing() {
+        check_derive(
+            "#[derive(Clone)]\nstruct Foo { a: i32$0, }",
+            "#[derive(Clone$0)]\nstruct Foo { a: i32, }",
+        );
+    }
+
+    #[test]
+    fn add_derive_new_with_doc_comment() {
+        check_derive(
+            "
+/// `Foo` is a pretty important struct.
+/// It does stuff.
+struct Foo { a: i32$0, }
+            ",
+            "
+/// `Foo` is a pretty important struct.
+/// It does stuff.
+#[derive($0)]
+struct Foo { a: i32, }
+            ",
+        );
+    }
+
+    #[test]
+    fn add_derive_target() {
+        check_assist_target(
+            add_attribute,
+            r#"
+struct SomeThingIrrelevant;
+/// `Foo` is a pretty important struct.
+/// It does stuff.
+struct Foo { a: i32$0, }
+struct EvenMoreIrrelevant;
+            "#,
+            "/// `Foo` is a pretty important struct.
+/// It does stuff.
+struct Foo { a: i32, }",
+        );
+    }
+
+    #[test]
+    fn insert_must_use() {
+        check_must_use("struct S$0;", "#[must_use$0]\nstruct S;");
+        check_must_use("$0fn f() {}", "#[must_use$0]\nfn f() {}");
+
+        check_must_use(r#"#[must_use = "bla"] struct S$0;"#, r#"#[must_use = "bla"$0] struct S;"#);
+        check_must_use(r#"#[must_use = ] struct S$0;"#, r#"#[must_use = $0] struct S;"#);
+
+        check_must_use(r#"#[must_use = "bla"] $0fn f() {}"#, r#"#[must_use = "bla"$0] fn f() {}"#);
+        check_must_use(r#"#[must_use = ] $0fn f() {}"#, r#"#[must_use = $0] fn f() {}"#);
+    }
+}
diff --git a/crates/ide-assists/src/handlers/add_missing_impl_members.rs b/crates/ide-assists/src/handlers/add_missing_impl_members.rs
index 573c362c81..6e700695fb 100644
--- a/crates/ide-assists/src/handlers/add_missing_impl_members.rs
+++ b/crates/ide-assists/src/handlers/add_missing_impl_members.rs
@@ -939,6 +939,7 @@ struct Foo(usize);
 
 impl FooB for Foo {
     $0fn foo< 'lt>(& 'lt self){}
+
 }
 "#,
         )
diff --git a/crates/ide-assists/src/handlers/extract_module.rs b/crates/ide-assists/src/handlers/extract_module.rs
index b5ed5699c9..11349b45d3 100644
--- a/crates/ide-assists/src/handlers/extract_module.rs
+++ b/crates/ide-assists/src/handlers/extract_module.rs
@@ -413,7 +413,10 @@ impl Module {
                                         ctx,
                                     )
                                 {
-                                    import_paths_to_be_removed.push(import_path);
+                                    check_intersection_and_push(
+                                        &mut import_paths_to_be_removed,
+                                        import_path,
+                                    );
                                 }
                             }
                         }
@@ -439,7 +442,10 @@ impl Module {
                                         ctx,
                                     )
                                 {
-                                    import_paths_to_be_removed.push(import_path);
+                                    check_intersection_and_push(
+                                        &mut import_paths_to_be_removed,
+                                        import_path,
+                                    );
                                 }
                             }
                         }
@@ -543,12 +549,25 @@ impl Module {
         } else if exists_inside_sel && !exists_outside_sel {
             //Changes to be made inside new module, and remove import from outside
 
-            if let Some((use_tree_str, text_range_opt)) =
+            if let Some((mut use_tree_str, text_range_opt)) =
                 self.process_use_stmt_for_import_resolve(use_stmt_opt, node_syntax)
             {
                 if let Some(text_range) = text_range_opt {
                     import_path_to_be_removed = Some(text_range);
                 }
+
+                if source_exists_outside_sel_in_same_mod {
+                    if let Some(first_path_in_use_tree) = use_tree_str.last() {
+                        let first_path_in_use_tree_str = first_path_in_use_tree.to_string();
+                        if !first_path_in_use_tree_str.contains("super")
+                            && !first_path_in_use_tree_str.contains("crate")
+                        {
+                            let super_path = make::ext::ident_path("super");
+                            use_tree_str.push(super_path);
+                        }
+                    }
+                }
+
                 use_tree_str_opt = Some(use_tree_str);
             } else if source_exists_outside_sel_in_same_mod {
                 self.make_use_stmt_of_node_with_super(node_syntax);
@@ -558,9 +577,16 @@ impl Module {
         if let Some(use_tree_str) = use_tree_str_opt {
             let mut use_tree_str = use_tree_str;
             use_tree_str.reverse();
-            if use_tree_str[0].to_string().contains("super") {
-                let super_path = make::ext::ident_path("super");
-                use_tree_str.insert(0, super_path)
+
+            if !(!exists_outside_sel && exists_inside_sel && source_exists_outside_sel_in_same_mod)
+            {
+                if let Some(first_path_in_use_tree) = use_tree_str.first() {
+                    let first_path_in_use_tree_str = first_path_in_use_tree.to_string();
+                    if first_path_in_use_tree_str.contains("super") {
+                        let super_path = make::ext::ident_path("super");
+                        use_tree_str.insert(0, super_path)
+                    }
+                }
             }
 
             let use_ =
@@ -621,6 +647,32 @@ impl Module {
     }
 }
 
+fn check_intersection_and_push(
+    import_paths_to_be_removed: &mut Vec<TextRange>,
+    import_path: TextRange,
+) {
+    if import_paths_to_be_removed.len() > 0 {
+        // Text ranges recieved here for imports are extended to the
+        // next/previous comma which can cause intersections among them
+        // and later deletion of these can cause panics similar
+        // to reported in #11766. So to mitigate it, we
+        // check for intersection between all current members
+        // and if it exists we combine both text ranges into
+        // one
+        let r = import_paths_to_be_removed
+            .into_iter()
+            .position(|it| it.intersect(import_path).is_some());
+        match r {
+            Some(it) => {
+                import_paths_to_be_removed[it] = import_paths_to_be_removed[it].cover(import_path)
+            }
+            None => import_paths_to_be_removed.push(import_path),
+        }
+    } else {
+        import_paths_to_be_removed.push(import_path);
+    }
+}
+
 fn does_source_exists_outside_sel_in_same_mod(
     def: Definition,
     ctx: &AssistContext,
@@ -1495,4 +1547,38 @@ mod modname {
         ",
         )
     }
+
+    #[test]
+    fn test_issue_11766() {
+        //https://github.com/rust-lang/rust-analyzer/issues/11766
+        check_assist(
+            extract_module,
+            r"
+            mod x {
+                pub struct Foo;
+                pub struct Bar;
+            }
+
+            use x::{Bar, Foo};
+
+            $0type A = (Foo, Bar);$0
+        ",
+            r"
+            mod x {
+                pub struct Foo;
+                pub struct Bar;
+            }
+
+            use x::{};
+
+            mod modname {
+                use super::x::Bar;
+
+                use super::x::Foo;
+
+                pub(crate) type A = (Foo, Bar);
+            }
+        ",
+        )
+    }
 }
diff --git a/crates/ide-assists/src/handlers/generate_derive.rs b/crates/ide-assists/src/handlers/generate_derive.rs
deleted file mode 100644
index 28483f795e..0000000000
--- a/crates/ide-assists/src/handlers/generate_derive.rs
+++ /dev/null
@@ -1,132 +0,0 @@
-use syntax::{
-    ast::{self, AstNode, HasAttrs},
-    SyntaxKind::{COMMENT, WHITESPACE},
-    TextSize,
-};
-
-use crate::{AssistContext, AssistId, AssistKind, Assists};
-
-// Assist: generate_derive
-//
-// Adds a new `#[derive()]` clause to a struct or enum.
-//
-// ```
-// struct Point {
-//     x: u32,
-//     y: u32,$0
-// }
-// ```
-// ->
-// ```
-// #[derive($0)]
-// struct Point {
-//     x: u32,
-//     y: u32,
-// }
-// ```
-pub(crate) fn generate_derive(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
-    let cap = ctx.config.snippet_cap?;
-    let nominal = ctx.find_node_at_offset::<ast::Adt>()?;
-    let node_start = derive_insertion_offset(&nominal)?;
-    let target = nominal.syntax().text_range();
-    acc.add(
-        AssistId("generate_derive", AssistKind::Generate),
-        "Add `#[derive]`",
-        target,
-        |builder| {
-            let derive_attr = nominal
-                .attrs()
-                .filter_map(|x| x.as_simple_call())
-                .filter(|(name, _arg)| name == "derive")
-                .map(|(_name, arg)| arg)
-                .next();
-            match derive_attr {
-                None => {
-                    builder.insert_snippet(cap, node_start, "#[derive($0)]\n");
-                }
-                Some(tt) => {
-                    // Just move the cursor.
-                    builder.insert_snippet(
-                        cap,
-                        tt.syntax().text_range().end() - TextSize::of(')'),
-                        "$0",
-                    )
-                }
-            };
-        },
-    )
-}
-
-// Insert `derive` after doc comments.
-fn derive_insertion_offset(nominal: &ast::Adt) -> Option<TextSize> {
-    let non_ws_child = nominal
-        .syntax()
-        .children_with_tokens()
-        .find(|it| it.kind() != COMMENT && it.kind() != WHITESPACE)?;
-    Some(non_ws_child.text_range().start())
-}
-
-#[cfg(test)]
-mod tests {
-    use crate::tests::{check_assist, check_assist_target};
-
-    use super::*;
-
-    #[test]
-    fn add_derive_new() {
-        check_assist(
-            generate_derive,
-            "struct Foo { a: i32, $0}",
-            "#[derive($0)]\nstruct Foo { a: i32, }",
-        );
-        check_assist(
-            generate_derive,
-            "struct Foo { $0 a: i32, }",
-            "#[derive($0)]\nstruct Foo {  a: i32, }",
-        );
-    }
-
-    #[test]
-    fn add_derive_existing() {
-        check_assist(
-            generate_derive,
-            "#[derive(Clone)]\nstruct Foo { a: i32$0, }",
-            "#[derive(Clone$0)]\nstruct Foo { a: i32, }",
-        );
-    }
-
-    #[test]
-    fn add_derive_new_with_doc_comment() {
-        check_assist(
-            generate_derive,
-            "
-/// `Foo` is a pretty important struct.
-/// It does stuff.
-struct Foo { a: i32$0, }
-            ",
-            "
-/// `Foo` is a pretty important struct.
-/// It does stuff.
-#[derive($0)]
-struct Foo { a: i32, }
-            ",
-        );
-    }
-
-    #[test]
-    fn add_derive_target() {
-        check_assist_target(
-            generate_derive,
-            "
-struct SomeThingIrrelevant;
-/// `Foo` is a pretty important struct.
-/// It does stuff.
-struct Foo { a: i32$0, }
-struct EvenMoreIrrelevant;
-            ",
-            "/// `Foo` is a pretty important struct.
-/// It does stuff.
-struct Foo { a: i32, }",
-        );
-    }
-}
diff --git a/crates/ide-assists/src/handlers/generate_enum_variant.rs b/crates/ide-assists/src/handlers/generate_enum_variant.rs
deleted file mode 100644
index b57076d999..0000000000
--- a/crates/ide-assists/src/handlers/generate_enum_variant.rs
+++ /dev/null
@@ -1,227 +0,0 @@
-use hir::{HasSource, InFile};
-use ide_db::assists::{AssistId, AssistKind};
-use syntax::{
-    ast::{self, edit::IndentLevel},
-    AstNode, TextSize,
-};
-
-use crate::assist_context::{AssistContext, Assists};
-
-// Assist: generate_enum_variant
-//
-// Adds a variant to an enum.
-//
-// ```
-// enum Countries {
-//     Ghana,
-// }
-//
-// fn main() {
-//     let country = Countries::Lesotho$0;
-// }
-// ```
-// ->
-// ```
-// enum Countries {
-//     Ghana,
-//     Lesotho,
-// }
-//
-// fn main() {
-//     let country = Countries::Lesotho;
-// }
-// ```
-pub(crate) fn generate_enum_variant(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
-    let path_expr: ast::PathExpr = ctx.find_node_at_offset()?;
-    let path = path_expr.path()?;
-
-    if ctx.sema.resolve_path(&path).is_some() {
-        // No need to generate anything if the path resolves
-        return None;
-    }
-
-    let name_ref = path.segment()?.name_ref()?;
-    if name_ref.text().starts_with(char::is_lowercase) {
-        // Don't suggest generating variant if the name starts with a lowercase letter
-        return None;
-    }
-
-    if let Some(hir::PathResolution::Def(hir::ModuleDef::Adt(hir::Adt::Enum(e)))) =
-        ctx.sema.resolve_path(&path.qualifier()?)
-    {
-        let target = path.syntax().text_range();
-        return add_variant_to_accumulator(acc, ctx, target, e, &name_ref);
-    }
-
-    None
-}
-
-fn add_variant_to_accumulator(
-    acc: &mut Assists,
-    ctx: &AssistContext,
-    target: syntax::TextRange,
-    adt: hir::Enum,
-    name_ref: &ast::NameRef,
-) -> Option<()> {
-    let db = ctx.db();
-    let InFile { file_id, value: enum_node } = adt.source(db)?.original_ast_node(db)?;
-    let enum_indent = IndentLevel::from_node(&enum_node.syntax());
-
-    let variant_list = enum_node.variant_list()?;
-    let offset = variant_list.syntax().text_range().end() - TextSize::of('}');
-    let empty_enum = variant_list.variants().next().is_none();
-
-    acc.add(
-        AssistId("generate_enum_variant", AssistKind::Generate),
-        "Generate variant",
-        target,
-        |builder| {
-            builder.edit_file(file_id.original_file(db));
-            let text = format!(
-                "{maybe_newline}{indent_1}{name},\n{enum_indent}",
-                maybe_newline = if empty_enum { "\n" } else { "" },
-                indent_1 = IndentLevel(1),
-                name = name_ref,
-                enum_indent = enum_indent
-            );
-            builder.insert(offset, text)
-        },
-    )
-}
-
-#[cfg(test)]
-mod tests {
-    use crate::tests::{check_assist, check_assist_not_applicable};
-
-    use super::*;
-
-    #[test]
-    fn generate_basic_enum_variant_in_empty_enum() {
-        check_assist(
-            generate_enum_variant,
-            r"
-enum Foo {}
-fn main() {
-    Foo::Bar$0
-}
-",
-            r"
-enum Foo {
-    Bar,
-}
-fn main() {
-    Foo::Bar
-}
-",
-        )
-    }
-
-    #[test]
-    fn generate_basic_enum_variant_in_non_empty_enum() {
-        check_assist(
-            generate_enum_variant,
-            r"
-enum Foo {
-    Bar,
-}
-fn main() {
-    Foo::Baz$0
-}
-",
-            r"
-enum Foo {
-    Bar,
-    Baz,
-}
-fn main() {
-    Foo::Baz
-}
-",
-        )
-    }
-
-    #[test]
-    fn generate_basic_enum_variant_in_different_file() {
-        check_assist(
-            generate_enum_variant,
-            r"
-//- /main.rs
-mod foo;
-use foo::Foo;
-
-fn main() {
-    Foo::Baz$0
-}
-
-//- /foo.rs
-enum Foo {
-    Bar,
-}
-",
-            r"
-enum Foo {
-    Bar,
-    Baz,
-}
-",
-        )
-    }
-
-    #[test]
-    fn not_applicable_for_existing_variant() {
-        check_assist_not_applicable(
-            generate_enum_variant,
-            r"
-enum Foo {
-    Bar,
-}
-fn main() {
-    Foo::Bar$0
-}
-",
-        )
-    }
-
-    #[test]
-    fn not_applicable_for_lowercase() {
-        check_assist_not_applicable(
-            generate_enum_variant,
-            r"
-enum Foo {
-    Bar,
-}
-fn main() {
-    Foo::new$0
-}
-",
-        )
-    }
-
-    #[test]
-    fn indentation_level_is_correct() {
-        check_assist(
-            generate_enum_variant,
-            r"
-mod m {
-    enum Foo {
-        Bar,
-    }
-}
-fn main() {
-    m::Foo::Baz$0
-}
-",
-            r"
-mod m {
-    enum Foo {
-        Bar,
-        Baz,
-    }
-}
-fn main() {
-    m::Foo::Baz
-}
-",
-        )
-    }
-}
diff --git a/crates/ide-assists/src/handlers/generate_function.rs b/crates/ide-assists/src/handlers/generate_function.rs
index c8650979e9..24cef5630f 100644
--- a/crates/ide-assists/src/handlers/generate_function.rs
+++ b/crates/ide-assists/src/handlers/generate_function.rs
@@ -71,13 +71,6 @@ fn gen_fn(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
                 get_fn_target(ctx, &target_module, call.clone())?
             }
             Some(hir::PathResolution::Def(hir::ModuleDef::Adt(adt))) => {
-                if let hir::Adt::Enum(_) = adt {
-                    // Don't suggest generating function if the name starts with an uppercase letter
-                    if name_ref.text().starts_with(char::is_uppercase) {
-                        return None;
-                    }
-                }
-
                 let current_module = ctx.sema.scope(call.syntax())?.module();
                 let module = adt.module(ctx.sema.db);
                 target_module = if current_module == module { None } else { Some(module) };
@@ -1742,45 +1735,6 @@ fn main() {
 fn foo(value: usize) ${0:-> _} {
     todo!()
 }
-",
-        )
-    }
-
-    #[test]
-    fn not_applicable_for_enum_variant() {
-        check_assist_not_applicable(
-            generate_function,
-            r"
-enum Foo {}
-fn main() {
-    Foo::Bar$0(true)
-}
-",
-        );
-    }
-
-    #[test]
-    fn applicable_for_enum_method() {
-        check_assist(
-            generate_function,
-            r"
-enum Foo {}
-fn main() {
-    Foo::new$0();
-}
-",
-            r"
-enum Foo {}
-fn main() {
-    Foo::new();
-}
-impl Foo {
-
-
-fn new() ${0:-> _} {
-    todo!()
-}
-}
 ",
         )
     }
diff --git a/crates/ide-assists/src/lib.rs b/crates/ide-assists/src/lib.rs
index 94fbaff400..f78dbf2ab8 100644
--- a/crates/ide-assists/src/lib.rs
+++ b/crates/ide-assists/src/lib.rs
@@ -106,6 +106,8 @@ mod handlers {
     mod add_explicit_type;
     mod add_lifetime_to_type;
     mod add_missing_impl_members;
+    mod add_missing_match_arms;
+    mod add_attribute;
     mod add_turbo_fish;
     mod apply_demorgan;
     mod auto_import;
@@ -126,7 +128,6 @@ mod handlers {
     mod extract_struct_from_enum_variant;
     mod extract_type_alias;
     mod extract_variable;
-    mod add_missing_match_arms;
     mod fix_visibility;
     mod flip_binexpr;
     mod flip_comma;
@@ -135,11 +136,9 @@ mod handlers {
     mod generate_default_from_enum_variant;
     mod generate_default_from_new;
     mod generate_deref;
-    mod generate_derive;
     mod generate_documentation_template;
     mod generate_enum_is_method;
     mod generate_enum_projection_method;
-    mod generate_enum_variant;
     mod generate_from_impl_for_enum;
     mod generate_function;
     mod generate_getter;
@@ -192,6 +191,7 @@ mod handlers {
     pub(crate) fn all() -> &'static [Handler] {
         &[
             // These are alphabetic for the foolish consistency
+            add_attribute::add_attribute,
             add_explicit_type::add_explicit_type,
             add_missing_match_arms::add_missing_match_arms,
             add_lifetime_to_type::add_lifetime_to_type,
@@ -222,13 +222,11 @@ mod handlers {
             generate_constant::generate_constant,
             generate_default_from_enum_variant::generate_default_from_enum_variant,
             generate_default_from_new::generate_default_from_new,
-            generate_derive::generate_derive,
             generate_documentation_template::generate_documentation_template,
             generate_documentation_template::generate_doc_example,
             generate_enum_is_method::generate_enum_is_method,
             generate_enum_projection_method::generate_enum_as_method,
             generate_enum_projection_method::generate_enum_try_into_method,
-            generate_enum_variant::generate_enum_variant,
             generate_from_impl_for_enum::generate_from_impl_for_enum,
             generate_function::generate_function,
             generate_impl::generate_impl,
diff --git a/crates/ide-completion/src/completions/dot.rs b/crates/ide-completion/src/completions/dot.rs
index 1e0b771166..9b5ececfd0 100644
--- a/crates/ide-completion/src/completions/dot.rs
+++ b/crates/ide-completion/src/completions/dot.rs
@@ -3,31 +3,30 @@
 use ide_db::FxHashSet;
 
 use crate::{
-    context::{
-        CompletionContext, DotAccess, DotAccessKind, NameRefContext, PathCompletionCtx, PathKind,
-    },
-    CompletionItem, CompletionItemKind, Completions,
+    context::{CompletionContext, DotAccess, NameRefContext, PathCompletionCtx, PathKind},
+    Completions,
 };
 
 /// Complete dot accesses, i.e. fields or methods.
 pub(crate) fn complete_dot(acc: &mut Completions, ctx: &CompletionContext) {
-    let (dot_access, receiver_ty) = match ctx.nameref_ctx() {
+    let (dot_access, dot_receiver) = match ctx.nameref_ctx() {
         Some(NameRefContext {
-            dot_access: Some(access @ DotAccess { receiver_ty: Some(receiver_ty), .. }),
+            dot_access:
+                Some(
+                    access @ (DotAccess::Method { receiver: Some(receiver), .. }
+                    | DotAccess::Field { receiver: Some(receiver), .. }),
+                ),
             ..
-        }) => (access, &receiver_ty.original),
+        }) => (access, receiver),
         _ => return complete_undotted_self(acc, ctx),
     };
 
-    // Suggest .await syntax for types that implement Future trait
-    if receiver_ty.impls_future(ctx.db) {
-        let mut item =
-            CompletionItem::new(CompletionItemKind::Keyword, ctx.source_range(), "await");
-        item.detail("expr.await");
-        item.add_to(acc);
-    }
+    let receiver_ty = match ctx.sema.type_of_expr(dot_receiver) {
+        Some(ty) => ty.original,
+        _ => return,
+    };
 
-    if let DotAccessKind::Method { .. } = dot_access.kind {
+    if let DotAccess::Method { .. } = dot_access {
         cov_mark::hit!(test_no_struct_field_completion_for_method_call);
     } else {
         complete_fields(
diff --git a/crates/ide-completion/src/completions/expr.rs b/crates/ide-completion/src/completions/expr.rs
index ae7b42e305..87fae18f4c 100644
--- a/crates/ide-completion/src/completions/expr.rs
+++ b/crates/ide-completion/src/completions/expr.rs
@@ -5,7 +5,7 @@ use ide_db::FxHashSet;
 use syntax::T;
 
 use crate::{
-    context::{NameRefContext, PathCompletionCtx, PathKind, PathQualifierCtx},
+    context::{PathCompletionCtx, PathKind, PathQualifierCtx},
     CompletionContext, Completions,
 };
 
@@ -15,25 +15,14 @@ pub(crate) fn complete_expr_path(acc: &mut Completions, ctx: &CompletionContext)
         return;
     }
 
-    let (is_absolute_path, qualifier, in_block_expr, in_loop_body, is_func_update) =
-        match ctx.nameref_ctx() {
-            Some(NameRefContext {
-                path_ctx:
-                    Some(PathCompletionCtx {
-                        kind: PathKind::Expr { in_block_expr, in_loop_body },
-                        is_absolute_path,
-                        qualifier,
-                        ..
-                    }),
-                record_expr,
+    let (is_absolute_path, qualifier, in_block_expr, in_loop_body, in_functional_update) =
+        match ctx.path_context() {
+            Some(&PathCompletionCtx {
+                kind: PathKind::Expr { in_block_expr, in_loop_body, in_functional_update },
+                is_absolute_path,
+                ref qualifier,
                 ..
-            }) => (
-                *is_absolute_path,
-                qualifier,
-                *in_block_expr,
-                *in_loop_body,
-                record_expr.as_ref().map_or(false, |&(_, it)| it),
-            ),
+            }) => (is_absolute_path, qualifier, in_block_expr, in_loop_body, in_functional_update),
             _ => return,
         };
 
@@ -176,7 +165,7 @@ pub(crate) fn complete_expr_path(acc: &mut Completions, ctx: &CompletionContext)
                 }
             });
 
-            if !is_func_update {
+            if !in_functional_update {
                 let mut add_keyword =
                     |kw, snippet| super::keyword::add_keyword(acc, ctx, kw, snippet);
 
diff --git a/crates/ide-completion/src/completions/flyimport.rs b/crates/ide-completion/src/completions/flyimport.rs
index 873db300b8..bbb50cb265 100644
--- a/crates/ide-completion/src/completions/flyimport.rs
+++ b/crates/ide-completion/src/completions/flyimport.rs
@@ -114,6 +114,7 @@ pub(crate) fn import_on_the_fly(acc: &mut Completions, ctx: &CompletionContext)
         || ctx.is_path_disallowed()
         || ctx.expects_item()
         || ctx.expects_assoc_item()
+        || ctx.expects_variant()
     {
         return None;
     }
diff --git a/crates/ide-completion/src/completions/item_list.rs b/crates/ide-completion/src/completions/item_list.rs
index edff146d8d..ebbc33c2da 100644
--- a/crates/ide-completion/src/completions/item_list.rs
+++ b/crates/ide-completion/src/completions/item_list.rs
@@ -8,18 +8,21 @@ use crate::{
 
 pub(crate) fn complete_item_list(acc: &mut Completions, ctx: &CompletionContext) {
     let _p = profile::span("complete_item_list");
+    if ctx.is_path_disallowed() || ctx.has_unfinished_impl_or_trait_prev_sibling() {
+        return;
+    }
 
-    let (&is_absolute_path, path_qualifier, _kind) = match ctx.path_context() {
+    let (&is_absolute_path, qualifier) = match ctx.path_context() {
         Some(PathCompletionCtx {
-            kind: PathKind::Item { kind },
+            kind: PathKind::Item { .. },
             is_absolute_path,
             qualifier,
             ..
-        }) => (is_absolute_path, qualifier, kind),
+        }) => (is_absolute_path, qualifier),
         _ => return,
     };
 
-    match path_qualifier {
+    match qualifier {
         Some(PathQualifierCtx { resolution, is_super_chain, .. }) => {
             if let Some(hir::PathResolution::Def(hir::ModuleDef::Module(module))) = resolution {
                 for (name, def) in module.scope(ctx.db, Some(ctx.module)) {
@@ -36,7 +39,7 @@ pub(crate) fn complete_item_list(acc: &mut Completions, ctx: &CompletionContext)
         None if is_absolute_path => {
             acc.add_crate_roots(ctx);
         }
-        None if ctx.qualifier_ctx.none() => {
+        None => {
             ctx.process_all_names(&mut |name, def| {
                 if let Some(def) = module_or_fn_macro(ctx.db, def) {
                     acc.add_resolution(ctx, name, def);
@@ -44,6 +47,5 @@ pub(crate) fn complete_item_list(acc: &mut Completions, ctx: &CompletionContext)
             });
             acc.add_nameref_keywords_with_colon(ctx);
         }
-        None => {}
     }
 }
diff --git a/crates/ide-completion/src/completions/keyword.rs b/crates/ide-completion/src/completions/keyword.rs
index 281e6e9783..14211f86ba 100644
--- a/crates/ide-completion/src/completions/keyword.rs
+++ b/crates/ide-completion/src/completions/keyword.rs
@@ -5,12 +5,12 @@
 use syntax::T;
 
 use crate::{
-    context::{NameRefContext, PathKind},
-    CompletionContext, CompletionItem, CompletionItemKind, Completions,
+    context::PathKind, patterns::ImmediateLocation, CompletionContext, CompletionItem,
+    CompletionItemKind, Completions,
 };
 
 pub(crate) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionContext) {
-    if matches!(ctx.nameref_ctx(), Some(NameRefContext { record_expr: Some(_), .. })) {
+    if matches!(ctx.completion_location, Some(ImmediateLocation::RecordExpr(_))) {
         cov_mark::hit!(no_keyword_completion_in_record_lit);
         return;
     }
@@ -51,7 +51,7 @@ pub(crate) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionConte
         return;
     }
 
-    if ctx.qualifier_ctx.vis_node.is_none()
+    if !ctx.has_visibility_prev_sibling()
         && (expects_item || ctx.expects_non_trait_assoc_item() || ctx.expect_field())
     {
         add_keyword("pub(crate)", "pub(crate)");
@@ -67,7 +67,7 @@ pub(crate) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionConte
     }
 
     if expects_item || has_block_expr_parent {
-        if ctx.qualifier_ctx.vis_node.is_none() {
+        if !ctx.has_visibility_prev_sibling() {
             add_keyword("impl", "impl $1 {\n    $0\n}");
             add_keyword("extern", "extern $0");
         }
diff --git a/crates/ide-completion/src/completions/pattern.rs b/crates/ide-completion/src/completions/pattern.rs
index ab35dadf92..211ca4e531 100644
--- a/crates/ide-completion/src/completions/pattern.rs
+++ b/crates/ide-completion/src/completions/pattern.rs
@@ -15,6 +15,7 @@ pub(crate) fn complete_pattern(acc: &mut Completions, ctx: &CompletionContext) {
         Some(ctx) => ctx,
         _ => return,
     };
+    let refutable = patctx.refutability == PatternRefutability::Refutable;
 
     if let Some(path_ctx) = ctx.path_context() {
         pattern_path_completion(acc, ctx, path_ctx);
@@ -46,11 +47,6 @@ pub(crate) fn complete_pattern(acc: &mut Completions, ctx: &CompletionContext) {
         }
     }
 
-    if patctx.record_pat.is_some() {
-        return;
-    }
-
-    let refutable = patctx.refutability == PatternRefutability::Refutable;
     let single_variant_enum = |enum_: hir::Enum| ctx.db.enum_data(enum_.into()).variants.len() == 1;
 
     if let Some(hir::Adt::Enum(e)) =
diff --git a/crates/ide-completion/src/completions/postfix.rs b/crates/ide-completion/src/completions/postfix.rs
index 4868225ce3..28256bd704 100644
--- a/crates/ide-completion/src/completions/postfix.rs
+++ b/crates/ide-completion/src/completions/postfix.rs
@@ -13,7 +13,7 @@ use text_edit::TextEdit;
 
 use crate::{
     completions::postfix::format_like::add_format_like_completions,
-    context::{CompletionContext, DotAccess, DotAccessKind, NameRefContext},
+    context::{CompletionContext, DotAccess, NameRefContext},
     item::{Builder, CompletionRelevancePostfixMatch},
     CompletionItem, CompletionItemKind, CompletionRelevance, Completions, SnippetScope,
 };
@@ -23,25 +23,34 @@ pub(crate) fn complete_postfix(acc: &mut Completions, ctx: &CompletionContext) {
         return;
     }
 
-    let (dot_receiver, receiver_ty, receiver_is_ambiguous_float_literal) = match ctx.nameref_ctx() {
+    let (dot_receiver, receiver_is_ambiguous_float_literal) = match ctx.nameref_ctx() {
         Some(NameRefContext {
-            dot_access: Some(DotAccess { receiver_ty: Some(ty), receiver: Some(it), kind, .. }),
+            dot_access: Some(DotAccess::Method { receiver: Some(it), .. }),
             ..
-        }) => (
-            it,
-            &ty.original,
-            match *kind {
-                DotAccessKind::Field { receiver_is_ambiguous_float_literal } => {
-                    receiver_is_ambiguous_float_literal
-                }
-                DotAccessKind::Method { .. } => false,
-            },
-        ),
+        }) => (it, false),
+        Some(NameRefContext {
+            dot_access:
+                Some(DotAccess::Field { receiver: Some(it), receiver_is_ambiguous_float_literal }),
+            ..
+        }) => (it, *receiver_is_ambiguous_float_literal),
         _ => return,
     };
 
     let receiver_text = get_receiver_text(dot_receiver, receiver_is_ambiguous_float_literal);
 
+    let receiver_ty = match ctx.sema.type_of_expr(dot_receiver) {
+        Some(it) => it.original,
+        None => return,
+    };
+
+    // Suggest .await syntax for types that implement Future trait
+    if receiver_ty.impls_future(ctx.db) {
+        let mut item =
+            CompletionItem::new(CompletionItemKind::Keyword, ctx.source_range(), "await");
+        item.detail("expr.await");
+        item.add_to(acc);
+    }
+
     let cap = match ctx.config.snippet_cap {
         Some(it) => it,
         None => return,
diff --git a/crates/ide-completion/src/completions/record.rs b/crates/ide-completion/src/completions/record.rs
index 6717ca0a0e..05fbe8513e 100644
--- a/crates/ide-completion/src/completions/record.rs
+++ b/crates/ide-completion/src/completions/record.rs
@@ -3,65 +3,67 @@ use ide_db::SymbolKind;
 use syntax::{ast::Expr, T};
 
 use crate::{
-    context::{NameRefContext, PatternContext},
-    CompletionContext, CompletionItem, CompletionItemKind, CompletionRelevance,
-    CompletionRelevancePostfixMatch, Completions,
+    patterns::ImmediateLocation, CompletionContext, CompletionItem, CompletionItemKind,
+    CompletionRelevance, CompletionRelevancePostfixMatch, Completions,
 };
 
 pub(crate) fn complete_record(acc: &mut Completions, ctx: &CompletionContext) -> Option<()> {
-    let missing_fields = if let Some(PatternContext { record_pat: Some(record_pat), .. }) =
-        &ctx.pattern_ctx
-    {
-        ctx.sema.record_pattern_missing_fields(record_pat)
-    } else if let Some(NameRefContext { record_expr: Some((record_expr, _)), .. }) =
-        ctx.nameref_ctx()
-    {
-        let ty = ctx.sema.type_of_expr(&Expr::RecordExpr(record_expr.clone()));
-
-        if let Some(hir::Adt::Union(un)) = ty.as_ref().and_then(|t| t.original.as_adt()) {
-            // ctx.sema.record_literal_missing_fields will always return
-            // an empty Vec on a union literal. This is normally
-            // reasonable, but here we'd like to present the full list
-            // of fields if the literal is empty.
-            let were_fields_specified =
-                record_expr.record_expr_field_list().and_then(|fl| fl.fields().next()).is_some();
-
-            match were_fields_specified {
-                false => un.fields(ctx.db).into_iter().map(|f| (f, f.ty(ctx.db))).collect(),
-                true => vec![],
+    let missing_fields = match &ctx.completion_location {
+        Some(
+            ImmediateLocation::RecordExpr(record_expr)
+            | ImmediateLocation::RecordExprUpdate(record_expr),
+        ) => {
+            let ty = ctx.sema.type_of_expr(&Expr::RecordExpr(record_expr.clone()));
+
+            if let Some(hir::Adt::Union(un)) = ty.as_ref().and_then(|t| t.original.as_adt()) {
+                // ctx.sema.record_literal_missing_fields will always return
+                // an empty Vec on a union literal. This is normally
+                // reasonable, but here we'd like to present the full list
+                // of fields if the literal is empty.
+                let were_fields_specified = record_expr
+                    .record_expr_field_list()
+                    .and_then(|fl| fl.fields().next())
+                    .is_some();
+
+                match were_fields_specified {
+                    false => un.fields(ctx.db).into_iter().map(|f| (f, f.ty(ctx.db))).collect(),
+                    true => vec![],
+                }
+            } else {
+                let missing_fields = ctx.sema.record_literal_missing_fields(record_expr);
+
+                let default_trait = ctx.famous_defs().core_default_Default();
+                let impl_default_trait =
+                    default_trait.zip(ty.as_ref()).map_or(false, |(default_trait, ty)| {
+                        ty.original.impls_trait(ctx.db, default_trait, &[])
+                    });
+
+                if impl_default_trait && !missing_fields.is_empty() && ctx.path_qual().is_none() {
+                    let completion_text = "..Default::default()";
+                    let mut item =
+                        CompletionItem::new(SymbolKind::Field, ctx.source_range(), completion_text);
+                    let completion_text =
+                        completion_text.strip_prefix(ctx.token.text()).unwrap_or(completion_text);
+                    item.insert_text(completion_text).set_relevance(CompletionRelevance {
+                        postfix_match: Some(CompletionRelevancePostfixMatch::Exact),
+                        ..Default::default()
+                    });
+                    item.add_to(acc);
+                }
+                if ctx.previous_token_is(T![.]) {
+                    let mut item =
+                        CompletionItem::new(CompletionItemKind::Snippet, ctx.source_range(), "..");
+                    item.insert_text(".");
+                    item.add_to(acc);
+                    return None;
+                }
+                missing_fields
             }
-        } else {
-            let missing_fields = ctx.sema.record_literal_missing_fields(record_expr);
-
-            let default_trait = ctx.famous_defs().core_default_Default();
-            let impl_default_trait =
-                default_trait.zip(ty.as_ref()).map_or(false, |(default_trait, ty)| {
-                    ty.original.impls_trait(ctx.db, default_trait, &[])
-                });
-
-            if impl_default_trait && !missing_fields.is_empty() && ctx.path_qual().is_none() {
-                let completion_text = "..Default::default()";
-                let mut item =
-                    CompletionItem::new(SymbolKind::Field, ctx.source_range(), completion_text);
-                let completion_text =
-                    completion_text.strip_prefix(ctx.token.text()).unwrap_or(completion_text);
-                item.insert_text(completion_text).set_relevance(CompletionRelevance {
-                    postfix_match: Some(CompletionRelevancePostfixMatch::Exact),
-                    ..Default::default()
-                });
-                item.add_to(acc);
-            }
-            if ctx.previous_token_is(T![.]) {
-                let mut item =
-                    CompletionItem::new(CompletionItemKind::Snippet, ctx.source_range(), "..");
-                item.insert_text(".");
-                item.add_to(acc);
-                return None;
-            }
-            missing_fields
         }
-    } else {
-        return None;
+        Some(ImmediateLocation::RecordPat(record_pat)) => {
+            ctx.sema.record_pattern_missing_fields(record_pat)
+        }
+        _ => return None,
     };
 
     for (field, ty) in missing_fields {
diff --git a/crates/ide-completion/src/completions/snippet.rs b/crates/ide-completion/src/completions/snippet.rs
index ebc3bb5a6f..2bae19c84f 100644
--- a/crates/ide-completion/src/completions/snippet.rs
+++ b/crates/ide-completion/src/completions/snippet.rs
@@ -2,6 +2,7 @@
 
 use hir::Documentation;
 use ide_db::{imports::insert_use::ImportScope, SnippetCap};
+use syntax::T;
 
 use crate::{
     context::{ItemListKind, PathCompletionCtx, PathKind},
@@ -51,10 +52,10 @@ pub(crate) fn complete_item_snippet(acc: &mut Completions, ctx: &CompletionConte
         }) => kind,
         _ => return,
     };
-    if !ctx.qualifier_ctx.none() {
+    if ctx.previous_token_is(T![unsafe]) || ctx.has_unfinished_impl_or_trait_prev_sibling() {
         return;
     }
-    if ctx.qualifier_ctx.vis_node.is_some() {
+    if ctx.has_visibility_prev_sibling() {
         return; // technically we could do some of these snippet completions if we were to put the
                 // attributes before the vis node.
     }
diff --git a/crates/ide-completion/src/completions/trait_impl.rs b/crates/ide-completion/src/completions/trait_impl.rs
index 54bd77526e..61c5d12649 100644
--- a/crates/ide-completion/src/completions/trait_impl.rs
+++ b/crates/ide-completion/src/completions/trait_impl.rs
@@ -32,12 +32,10 @@
 //! ```
 
 use hir::{self, HasAttrs};
-use ide_db::{
-    path_transform::PathTransform, syntax_helpers::insert_whitespace_into_node,
-    traits::get_missing_assoc_items, SymbolKind,
-};
+use ide_db::{path_transform::PathTransform, traits::get_missing_assoc_items, SymbolKind};
 use syntax::{
     ast::{self, edit_in_place::AttrsOwnerEdit},
+    display::function_declaration,
     AstNode, SyntaxElement, SyntaxKind, SyntaxNode, TextRange, T,
 };
 use text_edit::TextEdit;
@@ -181,7 +179,7 @@ fn add_function_impl(
                 _ => unreachable!(),
             };
 
-            let function_decl = function_declaration(&transformed_fn, source.file_id.is_macro());
+            let function_decl = function_declaration(&transformed_fn);
             match ctx.config.snippet_cap {
                 Some(cap) => {
                     let snippet = format!("{} {{\n    $0\n}}", function_decl);
@@ -262,7 +260,7 @@ fn add_const_impl(
                     _ => unreachable!(),
                 };
 
-                let label = make_const_compl_syntax(&transformed_const, source.file_id.is_macro());
+                let label = make_const_compl_syntax(&transformed_const);
                 let replacement = format!("{} ", label);
 
                 let mut item = CompletionItem::new(SymbolKind::Const, replacement_range, label);
@@ -285,18 +283,17 @@ fn add_const_impl(
     }
 }
 
-fn make_const_compl_syntax(const_: &ast::Const, needs_whitespace: bool) -> String {
+fn make_const_compl_syntax(const_: &ast::Const) -> String {
     const_.remove_attrs_and_docs();
-    let const_ = if needs_whitespace {
-        insert_whitespace_into_node::insert_ws_into(const_.syntax().clone())
-    } else {
-        const_.syntax().clone()
-    };
 
-    let start = const_.text_range().start();
-    let const_end = const_.text_range().end();
+    let const_start = const_.syntax().text_range().start();
+    let const_end = const_.syntax().text_range().end();
+
+    let start =
+        const_.syntax().first_child_or_token().map_or(const_start, |f| f.text_range().start());
 
     let end = const_
+        .syntax()
         .children_with_tokens()
         .find(|s| s.kind() == T![;] || s.kind() == T![=])
         .map_or(const_end, |f| f.text_range().start());
@@ -304,36 +301,11 @@ fn make_const_compl_syntax(const_: &ast::Const, needs_whitespace: bool) -> Strin
     let len = end - start;
     let range = TextRange::new(0.into(), len);
 
-    let syntax = const_.text().slice(range).to_string();
+    let syntax = const_.syntax().text().slice(range).to_string();
 
     format!("{} =", syntax.trim_end())
 }
 
-fn function_declaration(node: &ast::Fn, needs_whitespace: bool) -> String {
-    node.remove_attrs_and_docs();
-
-    let node = if needs_whitespace {
-        insert_whitespace_into_node::insert_ws_into(node.syntax().clone())
-    } else {
-        node.syntax().clone()
-    };
-
-    let start = node.text_range().start();
-    let end = node.text_range().end();
-
-    let end = node
-        .last_child_or_token()
-        .filter(|s| s.kind() == T![;] || s.kind() == SyntaxKind::BLOCK_EXPR)
-        .map_or(end, |f| f.text_range().start());
-
-    let len = end - start;
-    let range = TextRange::new(0.into(), len);
-
-    let syntax = node.text().slice(range).to_string();
-
-    syntax.trim_end().to_owned()
-}
-
 fn replacement_range(ctx: &CompletionContext, item: &SyntaxNode) -> TextRange {
     let first_child = item
         .children_with_tokens()
@@ -683,7 +655,8 @@ trait Test {
 struct T;
 
 impl Test for T {
-    fn foo<T>() where T: Into<String> {
+    fn foo<T>()
+where T: Into<String> {
     $0
 }
 }
@@ -1019,7 +992,7 @@ trait SomeTrait<T> {}
 
 trait Foo<T> {
     fn function()
-        where Self: SomeTrait<T>;
+    where Self: SomeTrait<T>;
 }
 struct Bar;
 
@@ -1032,13 +1005,13 @@ trait SomeTrait<T> {}
 
 trait Foo<T> {
     fn function()
-        where Self: SomeTrait<T>;
+    where Self: SomeTrait<T>;
 }
 struct Bar;
 
 impl Foo<u32> for Bar {
     fn function()
-        where Self: SomeTrait<u32> {
+where Self: SomeTrait<u32> {
     $0
 }
 }
@@ -1079,51 +1052,4 @@ impl Tr for () {
         "#]],
         );
     }
-
-    #[test]
-    fn fixes_up_macro_generated() {
-        check_edit(
-            "fn foo",
-            r#"
-macro_rules! noop {
-    ($($item: item)*) => {
-        $($item)*
-    }
-}
-
-noop! {
-    trait Foo {
-        fn foo(&mut self, bar: i64, baz: &mut u32) -> Result<(), u32>;
-    }
-}
-
-struct Test;
-
-impl Foo for Test {
-    $0
-}
-"#,
-            r#"
-macro_rules! noop {
-    ($($item: item)*) => {
-        $($item)*
-    }
-}
-
-noop! {
-    trait Foo {
-        fn foo(&mut self, bar: i64, baz: &mut u32) -> Result<(), u32>;
-    }
-}
-
-struct Test;
-
-impl Foo for Test {
-    fn foo(&mut self,bar:i64,baz: &mut u32) -> Result<(),u32> {
-    $0
-}
-}
-"#,
-        );
-    }
 }
diff --git a/crates/ide-completion/src/context.rs b/crates/ide-completion/src/context.rs
index b70d6f9e8d..e51ae0dc3b 100644
--- a/crates/ide-completion/src/context.rs
+++ b/crates/ide-completion/src/context.rs
@@ -48,6 +48,7 @@ pub(super) enum PathKind {
     Expr {
         in_block_expr: bool,
         in_loop_body: bool,
+        in_functional_update: bool,
     },
     Type,
     Attr {
@@ -75,18 +76,6 @@ pub(super) enum ItemListKind {
     ExternBlock,
 }
 
-#[derive(Debug, Default)]
-pub(super) struct QualifierCtx {
-    pub(super) unsafe_tok: Option<SyntaxToken>,
-    pub(super) vis_node: Option<ast::Visibility>,
-}
-
-impl QualifierCtx {
-    pub(super) fn none(&self) -> bool {
-        self.unsafe_tok.is_none() && self.vis_node.is_none()
-    }
-}
-
 #[derive(Debug)]
 pub(crate) struct PathCompletionCtx {
     /// If this is a call with () already there (or {} in case of record patterns)
@@ -126,8 +115,6 @@ pub(super) struct PatternContext {
     pub(super) parent_pat: Option<ast::Pat>,
     pub(super) ref_token: Option<SyntaxToken>,
     pub(super) mut_token: Option<SyntaxToken>,
-    /// The record pattern this name or ref is a field of
-    pub(super) record_pat: Option<ast::RecordPat>,
 }
 
 #[derive(Debug)]
@@ -179,11 +166,8 @@ pub(super) enum NameKind {
 pub(super) struct NameRefContext {
     /// NameRef syntax in the original file
     pub(super) nameref: Option<ast::NameRef>,
-    // FIXME: these fields are actually disjoint -> enum
     pub(super) dot_access: Option<DotAccess>,
     pub(super) path_ctx: Option<PathCompletionCtx>,
-    /// The record expression this nameref is a field of
-    pub(super) record_expr: Option<(ast::RecordExpr, bool)>,
 }
 
 #[derive(Debug)]
@@ -202,20 +186,15 @@ pub(super) enum IdentContext {
 }
 
 #[derive(Debug)]
-pub(super) struct DotAccess {
-    pub(super) receiver: Option<ast::Expr>,
-    pub(super) receiver_ty: Option<TypeInfo>,
-    pub(super) kind: DotAccessKind,
-}
-
-#[derive(Debug)]
-pub(super) enum DotAccessKind {
+pub(super) enum DotAccess {
     Field {
+        receiver: Option<ast::Expr>,
         /// True if the receiver is an integer and there is no ident in the original file after it yet
         /// like `0.$0`
         receiver_is_ambiguous_float_literal: bool,
     },
     Method {
+        receiver: Option<ast::Expr>,
         has_parens: bool,
     },
 }
@@ -265,7 +244,6 @@ pub(crate) struct CompletionContext<'a> {
     pub(super) ident_ctx: IdentContext,
 
     pub(super) pattern_ctx: Option<PatternContext>,
-    pub(super) qualifier_ctx: QualifierCtx,
 
     pub(super) existing_derives: FxHashSet<hir::Macro>,
 
@@ -320,9 +298,11 @@ impl<'a> CompletionContext<'a> {
 
     pub(crate) fn dot_receiver(&self) -> Option<&ast::Expr> {
         match self.nameref_ctx() {
-            Some(NameRefContext { dot_access: Some(DotAccess { receiver, .. }), .. }) => {
-                receiver.as_ref()
-            }
+            Some(NameRefContext {
+                dot_access:
+                    Some(DotAccess::Method { receiver, .. } | DotAccess::Field { receiver, .. }),
+                ..
+            }) => receiver.as_ref(),
             _ => None,
         }
     }
@@ -335,6 +315,10 @@ impl<'a> CompletionContext<'a> {
         matches!(self.completion_location, Some(ImmediateLocation::Trait | ImmediateLocation::Impl))
     }
 
+    pub(crate) fn expects_variant(&self) -> bool {
+        matches!(self.name_ctx(), Some(NameContext { kind: NameKind::Variant, .. }))
+    }
+
     pub(crate) fn expects_non_trait_assoc_item(&self) -> bool {
         matches!(self.completion_location, Some(ImmediateLocation::Impl))
     }
@@ -376,19 +360,28 @@ impl<'a> CompletionContext<'a> {
         matches!(self.prev_sibling, Some(ImmediatePrevSibling::ImplDefType))
     }
 
+    pub(crate) fn has_visibility_prev_sibling(&self) -> bool {
+        matches!(self.prev_sibling, Some(ImmediatePrevSibling::Visibility))
+    }
+
     pub(crate) fn after_if(&self) -> bool {
         matches!(self.prev_sibling, Some(ImmediatePrevSibling::IfExpr))
     }
 
     // FIXME: This shouldn't exist
     pub(crate) fn is_path_disallowed(&self) -> bool {
-        !self.qualifier_ctx.none()
-            || matches!(self.prev_sibling, Some(ImmediatePrevSibling::Visibility))
-            || (matches!(self.name_ctx(), Some(NameContext { .. })) && self.pattern_ctx.is_none())
-            || matches!(self.pattern_ctx, Some(PatternContext { record_pat: Some(_), .. }))
+        self.previous_token_is(T![unsafe])
             || matches!(
-                self.nameref_ctx(),
-                Some(NameRefContext { record_expr: Some((_, false)), .. })
+                self.prev_sibling,
+                Some(ImmediatePrevSibling::Attribute | ImmediatePrevSibling::Visibility)
+            )
+            || matches!(
+                self.completion_location,
+                Some(ImmediateLocation::RecordPat(_) | ImmediateLocation::RecordExpr(_))
+            )
+            || matches!(
+                self.name_ctx(),
+                Some(NameContext { kind: NameKind::Module(_) | NameKind::Rename, .. })
             )
     }
 
@@ -564,7 +557,6 @@ impl<'a> CompletionContext<'a> {
             // dummy value, will be overwritten
             ident_ctx: IdentContext::UnexpandedAttrTT { fake_attribute_under_caret: None },
             pattern_ctx: None,
-            qualifier_ctx: Default::default(),
             existing_derives: Default::default(),
             locals,
         };
@@ -875,7 +867,7 @@ impl<'a> CompletionContext<'a> {
         offset: TextSize,
         derive_ctx: Option<(SyntaxNode, SyntaxNode, TextSize, ast::Attr)>,
     ) -> Option<()> {
-        let fake_ident_token = file_with_fake_ident.token_at_offset(offset).right_biased()?;
+        let fake_ident_token = file_with_fake_ident.token_at_offset(offset).right_biased().unwrap();
         let syntax_element = NodeOrToken::Token(fake_ident_token);
         if is_in_token_of_for_loop(syntax_element.clone()) {
             // for pat $0
@@ -977,49 +969,7 @@ impl<'a> CompletionContext<'a> {
             ast::NameLike::NameRef(name_ref) => {
                 let parent = name_ref.syntax().parent()?;
                 let (nameref_ctx, pat_ctx) =
-                    Self::classify_name_ref(&self.sema, &original_file, name_ref, parent.clone());
-
-                // Extract qualifiers
-                if let Some(path_ctx) = &nameref_ctx.path_ctx {
-                    if path_ctx.qualifier.is_none() {
-                        let top = match path_ctx.kind {
-                            PathKind::Expr { in_block_expr: true, .. } => parent
-                                .ancestors()
-                                .find(|it| ast::PathExpr::can_cast(it.kind()))
-                                .and_then(|p| {
-                                    let parent = p.parent()?;
-                                    if ast::StmtList::can_cast(parent.kind()) {
-                                        Some(p)
-                                    } else if ast::ExprStmt::can_cast(parent.kind()) {
-                                        Some(parent)
-                                    } else {
-                                        None
-                                    }
-                                }),
-                            PathKind::Item { .. } => {
-                                parent.ancestors().find(|it| ast::MacroCall::can_cast(it.kind()))
-                            }
-                            _ => None,
-                        };
-                        if let Some(top) = top {
-                            if let Some(NodeOrToken::Node(error_node)) =
-                                syntax::algo::non_trivia_sibling(
-                                    top.into(),
-                                    syntax::Direction::Prev,
-                                )
-                            {
-                                if error_node.kind() == SyntaxKind::ERROR {
-                                    self.qualifier_ctx.unsafe_tok = error_node
-                                        .children_with_tokens()
-                                        .filter_map(NodeOrToken::into_token)
-                                        .find(|it| it.kind() == T![unsafe]);
-                                    self.qualifier_ctx.vis_node =
-                                        error_node.children().find_map(ast::Visibility::cast);
-                                }
-                            }
-                        }
-                    }
-                }
+                    Self::classify_name_ref(&self.sema, &original_file, name_ref, parent);
                 self.ident_ctx = IdentContext::NameRef(nameref_ctx);
                 self.pattern_ctx = pat_ctx;
             }
@@ -1073,13 +1023,14 @@ impl<'a> CompletionContext<'a> {
                 ast::Enum(_) => NameKind::Enum,
                 ast::Fn(_) => NameKind::Function,
                 ast::IdentPat(bind_pat) => {
-                    pat_ctx = Some({
-                        let mut pat_ctx = pattern_context_for(original_file, bind_pat.into());
-                        if let Some(record_field) = ast::RecordPatField::for_field_name(&name) {
-                            pat_ctx.record_pat = find_node_in_file_compensated(original_file, &record_field.parent_record_pat());
-                        }
-                        pat_ctx
-                    });
+                    let is_name_in_field_pat = bind_pat
+                        .syntax()
+                        .parent()
+                        .and_then(ast::RecordPatField::cast)
+                        .map_or(false, |pat_field| pat_field.name_ref().is_none());
+                    if !is_name_in_field_pat {
+                        pat_ctx = Some(pattern_context_for(original_file, bind_pat.into()));
+                    }
 
                     NameKind::IdentPat
                 },
@@ -1111,33 +1062,7 @@ impl<'a> CompletionContext<'a> {
     ) -> (NameRefContext, Option<PatternContext>) {
         let nameref = find_node_at_offset(&original_file, name_ref.syntax().text_range().start());
 
-        let mut nameref_ctx =
-            NameRefContext { dot_access: None, path_ctx: None, nameref, record_expr: None };
-
-        if let Some(record_field) = ast::RecordExprField::for_field_name(&name_ref) {
-            nameref_ctx.record_expr =
-                find_node_in_file_compensated(original_file, &record_field.parent_record_lit())
-                    .zip(Some(false));
-            return (nameref_ctx, None);
-        }
-        if let Some(record_field) = ast::RecordPatField::for_field_name_ref(&name_ref) {
-            let pat_ctx =
-                pattern_context_for(original_file, record_field.parent_record_pat().clone().into());
-            return (
-                nameref_ctx,
-                Some(PatternContext {
-                    param_ctx: None,
-                    has_type_ascription: false,
-                    ref_token: None,
-                    mut_token: None,
-                    record_pat: find_node_in_file_compensated(
-                        original_file,
-                        &record_field.parent_record_pat(),
-                    ),
-                    ..pat_ctx
-                }),
-            );
-        }
+        let mut nameref_ctx = NameRefContext { dot_access: None, path_ctx: None, nameref };
 
         let segment = match_ast! {
             match parent {
@@ -1151,20 +1076,16 @@ impl<'a> CompletionContext<'a> {
                         },
                         _ => false,
                     };
-                    nameref_ctx.dot_access = Some(DotAccess {
-                        receiver_ty: receiver.as_ref().and_then(|it| sema.type_of_expr(it)),
-                        kind: DotAccessKind::Field { receiver_is_ambiguous_float_literal },
-                        receiver
-                    });
+                    nameref_ctx.dot_access = Some(DotAccess::Field { receiver, receiver_is_ambiguous_float_literal });
                     return (nameref_ctx, None);
                 },
                 ast::MethodCallExpr(method) => {
-                    let receiver = find_in_original_file(method.receiver(), original_file);
-                    nameref_ctx.dot_access = Some(DotAccess {
-                        receiver_ty: receiver.as_ref().and_then(|it| sema.type_of_expr(it)),
-                        kind: DotAccessKind::Method { has_parens: method.arg_list().map_or(false, |it| it.l_paren_token().is_some()) },
-                        receiver
-                    });
+                    nameref_ctx.dot_access = Some(
+                        DotAccess::Method {
+                            receiver: find_in_original_file(method.receiver(), original_file),
+                            has_parens: method.arg_list().map_or(false, |it| it.l_paren_token().is_some())
+                        }
+                    );
                     return (nameref_ctx, None);
                 },
                 _ => return (nameref_ctx, None),
@@ -1190,45 +1111,8 @@ impl<'a> CompletionContext<'a> {
                 })
                 .unwrap_or(false)
         };
-        let mut fill_record_expr = |syn: &SyntaxNode| {
-            if let Some(record_expr) = syn.ancestors().nth(2).and_then(ast::RecordExpr::cast) {
-                nameref_ctx.record_expr =
-                    find_node_in_file_compensated(original_file, &record_expr).zip(Some(true));
-            }
-        };
-
-        // We do not want to generate path completions when we are sandwiched between an item decl signature and its body.
-        // ex. trait Foo $0 {}
-        // in these cases parser recovery usually kicks in for our inserted identifier, causing it
-        // to either be parsed as an ExprStmt or a MacroCall, depending on whether it is in a block
-        // expression or an item list.
-        // The following code checks if the body is missing, if it is we either cut off the body
-        // from the item or it was missing in the first place
-        let inbetween_body_and_decl_check = |node: SyntaxNode| {
-            if let Some(NodeOrToken::Node(n)) =
-                syntax::algo::non_trivia_sibling(node.into(), syntax::Direction::Prev)
-            {
-                if let Some(item) = ast::Item::cast(n) {
-                    match item {
-                        ast::Item::Const(it) => it.body().is_none(),
-                        ast::Item::Enum(it) => it.variant_list().is_none(),
-                        ast::Item::ExternBlock(it) => it.extern_item_list().is_none(),
-                        ast::Item::Fn(it) => it.body().is_none(),
-                        ast::Item::Impl(it) => it.assoc_item_list().is_none(),
-                        ast::Item::Module(it) => it.item_list().is_none(),
-                        ast::Item::Static(it) => it.body().is_none(),
-                        ast::Item::Struct(it) => it.field_list().is_none(),
-                        ast::Item::Trait(it) => it.assoc_item_list().is_none(),
-                        ast::Item::TypeAlias(it) => it.ty().is_none(),
-                        ast::Item::Union(it) => it.record_field_list().is_none(),
-                        _ => false,
-                    }
-                } else {
-                    false
-                }
-            } else {
-                false
-            }
+        let is_in_func_update = |it: &SyntaxNode| {
+            it.parent().map_or(false, |it| ast::RecordExprFieldList::can_cast(it.kind()))
         };
 
         let kind = path.syntax().ancestors().find_map(|it| {
@@ -1237,20 +1121,11 @@ impl<'a> CompletionContext<'a> {
                 match it {
                     ast::PathType(_) => Some(PathKind::Type),
                     ast::PathExpr(it) => {
-                        if let Some(p) = it.syntax().parent() {
-                            if ast::ExprStmt::can_cast(p.kind()) {
-                                if inbetween_body_and_decl_check(p) {
-                                    return Some(None);
-                                }
-                            }
-                        }
-
-                        fill_record_expr(it.syntax());
-
                         path_ctx.has_call_parens = it.syntax().parent().map_or(false, |it| ast::CallExpr::can_cast(it.kind()));
                         let in_block_expr = is_in_block(it.syntax());
                         let in_loop_body = is_in_loop_body(it.syntax());
-                        Some(PathKind::Expr { in_block_expr, in_loop_body })
+                        let in_functional_update = is_in_func_update(it.syntax());
+                        Some(PathKind::Expr { in_block_expr, in_loop_body, in_functional_update })
                     },
                     ast::TupleStructPat(it) => {
                         path_ctx.has_call_parens = true;
@@ -1267,10 +1142,6 @@ impl<'a> CompletionContext<'a> {
                         Some(PathKind::Pat)
                     },
                     ast::MacroCall(it) => {
-                        if inbetween_body_and_decl_check(it.syntax().clone()) {
-                            return Some(None);
-                        }
-
                         path_ctx.has_macro_bang = it.excl_token().is_some();
                         let parent = it.syntax().parent();
                         match parent.as_ref().map(|it| it.kind()) {
@@ -1288,8 +1159,8 @@ impl<'a> CompletionContext<'a> {
                                return Some(parent.and_then(ast::MacroExpr::cast).map(|it| {
                                     let in_loop_body = is_in_loop_body(it.syntax());
                                     let in_block_expr = is_in_block(it.syntax());
-                                    fill_record_expr(it.syntax());
-                                    PathKind::Expr { in_block_expr, in_loop_body }
+                                    let in_functional_update = is_in_func_update(it.syntax());
+                                    PathKind::Expr { in_block_expr, in_loop_body, in_functional_update }
                                 }));
                             },
                         }
@@ -1424,7 +1295,6 @@ fn pattern_context_for(original_file: &SyntaxNode, pat: ast::Pat) -> PatternCont
         parent_pat: pat.syntax().parent().and_then(ast::Pat::cast),
         mut_token,
         ref_token,
-        record_pat: None,
     }
 }
 
diff --git a/crates/ide-completion/src/lib.rs b/crates/ide-completion/src/lib.rs
index 9659efad61..991ab6a4b8 100644
--- a/crates/ide-completion/src/lib.rs
+++ b/crates/ide-completion/src/lib.rs
@@ -143,40 +143,36 @@ pub fn completions(
     db: &RootDatabase,
     config: &CompletionConfig,
     position: FilePosition,
-    trigger_character: Option<char>,
 ) -> Option<Completions> {
     let ctx = &CompletionContext::new(db, position, config)?;
     let mut acc = Completions::default();
 
     {
         let acc = &mut acc;
-        // prevent `(` from triggering unwanted completion noise
-        if trigger_character != Some('(') {
-            completions::attribute::complete_attribute(acc, ctx);
-            completions::attribute::complete_derive(acc, ctx);
-            completions::attribute::complete_known_attribute_input(acc, ctx);
-            completions::dot::complete_dot(acc, ctx);
-            completions::expr::complete_expr_path(acc, ctx);
-            completions::extern_abi::complete_extern_abi(acc, ctx);
-            completions::flyimport::import_on_the_fly(acc, ctx);
-            completions::fn_param::complete_fn_param(acc, ctx);
-            completions::format_string::format_string(acc, ctx);
-            completions::item_list::complete_item_list(acc, ctx);
-            completions::keyword::complete_expr_keyword(acc, ctx);
-            completions::lifetime::complete_label(acc, ctx);
-            completions::lifetime::complete_lifetime(acc, ctx);
-            completions::mod_::complete_mod(acc, ctx);
-            completions::pattern::complete_pattern(acc, ctx);
-            completions::postfix::complete_postfix(acc, ctx);
-            completions::record::complete_record_literal(acc, ctx);
-            completions::record::complete_record(acc, ctx);
-            completions::snippet::complete_expr_snippet(acc, ctx);
-            completions::snippet::complete_item_snippet(acc, ctx);
-            completions::trait_impl::complete_trait_impl(acc, ctx);
-            completions::r#type::complete_type_path(acc, ctx);
-            completions::r#type::complete_inferred_type(acc, ctx);
-            completions::use_::complete_use_tree(acc, ctx);
-        }
+        completions::attribute::complete_attribute(acc, ctx);
+        completions::attribute::complete_derive(acc, ctx);
+        completions::attribute::complete_known_attribute_input(acc, ctx);
+        completions::dot::complete_dot(acc, ctx);
+        completions::expr::complete_expr_path(acc, ctx);
+        completions::extern_abi::complete_extern_abi(acc, ctx);
+        completions::flyimport::import_on_the_fly(acc, ctx);
+        completions::fn_param::complete_fn_param(acc, ctx);
+        completions::format_string::format_string(acc, ctx);
+        completions::item_list::complete_item_list(acc, ctx);
+        completions::keyword::complete_expr_keyword(acc, ctx);
+        completions::lifetime::complete_label(acc, ctx);
+        completions::lifetime::complete_lifetime(acc, ctx);
+        completions::mod_::complete_mod(acc, ctx);
+        completions::pattern::complete_pattern(acc, ctx);
+        completions::postfix::complete_postfix(acc, ctx);
+        completions::record::complete_record_literal(acc, ctx);
+        completions::record::complete_record(acc, ctx);
+        completions::snippet::complete_expr_snippet(acc, ctx);
+        completions::snippet::complete_item_snippet(acc, ctx);
+        completions::trait_impl::complete_trait_impl(acc, ctx);
+        completions::r#type::complete_type_path(acc, ctx);
+        completions::r#type::complete_inferred_type(acc, ctx);
+        completions::use_::complete_use_tree(acc, ctx);
         completions::vis::complete_vis_path(acc, ctx);
     }
 
diff --git a/crates/ide-completion/src/patterns.rs b/crates/ide-completion/src/patterns.rs
index 0e146df712..07b2ac4297 100644
--- a/crates/ide-completion/src/patterns.rs
+++ b/crates/ide-completion/src/patterns.rs
@@ -24,6 +24,7 @@ pub(crate) enum ImmediatePrevSibling {
     TraitDefName,
     ImplDefType,
     Visibility,
+    Attribute,
 }
 
 #[derive(Clone, Debug, PartialEq, Eq)]
@@ -53,6 +54,19 @@ pub(crate) enum ImmediateLocation {
     // Only set from a type arg
     /// Original file ast node
     GenericArgList(ast::GenericArgList),
+    /// The record expr of the field name we are completing
+    ///
+    /// Original file ast node
+    RecordExpr(ast::RecordExpr),
+    /// The record expr of the functional update syntax we are completing
+    ///
+    /// Original file ast node
+    RecordExprUpdate(ast::RecordExpr),
+    /// The record pat of the field name we are completing
+    ///
+    /// Original file ast node
+    // FIXME: This should be moved to pattern_ctx
+    RecordPat(ast::RecordPat),
 }
 
 pub(crate) fn determine_prev_sibling(name_like: &ast::NameLike) -> Option<ImmediatePrevSibling> {
@@ -110,6 +124,7 @@ pub(crate) fn determine_prev_sibling(name_like: &ast::NameLike) -> Option<Immedi
                 } else {
                     return None
             },
+            ast::Attr(_) => ImmediatePrevSibling::Attribute,
             _ => return None,
         }
     };
@@ -123,8 +138,27 @@ pub(crate) fn determine_location(
     name_like: &ast::NameLike,
 ) -> Option<ImmediateLocation> {
     let node = match name_like {
-        ast::NameLike::NameRef(name_ref) => maximize_name_ref(name_ref),
-        ast::NameLike::Name(name) => name.syntax().clone(),
+        ast::NameLike::NameRef(name_ref) => {
+            if ast::RecordExprField::for_field_name(name_ref).is_some() {
+                return sema
+                    .find_node_at_offset_with_macros(original_file, offset)
+                    .map(ImmediateLocation::RecordExpr);
+            }
+            if ast::RecordPatField::for_field_name_ref(name_ref).is_some() {
+                return sema
+                    .find_node_at_offset_with_macros(original_file, offset)
+                    .map(ImmediateLocation::RecordPat);
+            }
+            maximize_name_ref(name_ref)
+        }
+        ast::NameLike::Name(name) => {
+            if ast::RecordPatField::for_field_name(name).is_some() {
+                return sema
+                    .find_node_at_offset_with_macros(original_file, offset)
+                    .map(ImmediateLocation::RecordPat);
+            }
+            name.syntax().clone()
+        }
         ast::NameLike::Lifetime(lt) => lt.syntax().clone(),
     };
 
@@ -167,6 +201,9 @@ pub(crate) fn determine_location(
             ast::SourceFile(_) => ImmediateLocation::ItemList,
             ast::ItemList(_) => ImmediateLocation::ItemList,
             ast::RefExpr(_) => ImmediateLocation::RefExpr,
+            ast::RecordExprFieldList(_) => sema
+                .find_node_at_offset_with_macros(original_file, offset)
+                .map(ImmediateLocation::RecordExprUpdate)?,
             ast::TupleField(_) => ImmediateLocation::TupleField,
             ast::TupleFieldList(_) => ImmediateLocation::TupleField,
             ast::TypeBound(_) => ImmediateLocation::TypeBound,
@@ -447,4 +484,9 @@ mod tests {
     fn test_vis_prev_sibling() {
         check_prev_sibling(r"pub w$0", ImmediatePrevSibling::Visibility);
     }
+
+    #[test]
+    fn test_attr_prev_sibling() {
+        check_prev_sibling(r"#[attr] w$0", ImmediatePrevSibling::Attribute);
+    }
 }
diff --git a/crates/ide-completion/src/render.rs b/crates/ide-completion/src/render.rs
index d51bc517d6..f509218385 100644
--- a/crates/ide-completion/src/render.rs
+++ b/crates/ide-completion/src/render.rs
@@ -410,7 +410,7 @@ mod tests {
 
     #[track_caller]
     fn check_relevance_for_kinds(ra_fixture: &str, kinds: &[CompletionItemKind], expect: Expect) {
-        let mut actual = get_all_items(TEST_CONFIG, ra_fixture, None);
+        let mut actual = get_all_items(TEST_CONFIG, ra_fixture);
         actual.retain(|it| kinds.contains(&it.kind()));
         actual.sort_by_key(|it| cmp::Reverse(it.relevance().score()));
         check_relevance_(actual, expect);
@@ -418,7 +418,7 @@ mod tests {
 
     #[track_caller]
     fn check_relevance(ra_fixture: &str, expect: Expect) {
-        let mut actual = get_all_items(TEST_CONFIG, ra_fixture, None);
+        let mut actual = get_all_items(TEST_CONFIG, ra_fixture);
         actual.retain(|it| it.kind() != CompletionItemKind::Snippet);
         actual.retain(|it| it.kind() != CompletionItemKind::Keyword);
         actual.retain(|it| it.kind() != CompletionItemKind::BuiltinType);
diff --git a/crates/ide-completion/src/render/function.rs b/crates/ide-completion/src/render/function.rs
index 5e1fbfa4a2..c47696bc41 100644
--- a/crates/ide-completion/src/render/function.rs
+++ b/crates/ide-completion/src/render/function.rs
@@ -7,9 +7,7 @@ use stdx::{format_to, to_lower_snake_case};
 use syntax::SmolStr;
 
 use crate::{
-    context::{
-        CompletionContext, DotAccess, DotAccessKind, NameRefContext, PathCompletionCtx, PathKind,
-    },
+    context::{CompletionContext, DotAccess, NameRefContext, PathCompletionCtx, PathKind},
     item::{Builder, CompletionItem, CompletionItemKind, CompletionRelevance},
     render::{compute_exact_name_match, compute_ref_match, compute_type_match, RenderContext},
     CallableSnippets,
@@ -211,10 +209,7 @@ fn should_add_parens(ctx: &CompletionContext) -> bool {
 
     if matches!(
         ctx.nameref_ctx(),
-        Some(NameRefContext {
-            dot_access: Some(DotAccess { kind: DotAccessKind::Method { has_parens: true }, .. }),
-            ..
-        })
+        Some(NameRefContext { dot_access: Some(DotAccess::Method { has_parens: true, .. }), .. })
     ) {
         return false;
     }
diff --git a/crates/ide-db/src/defs.rs b/crates/ide-db/src/defs.rs
index 540cc70dd5..bea6f24523 100644
--- a/crates/ide-db/src/defs.rs
+++ b/crates/ide-db/src/defs.rs
@@ -7,9 +7,9 @@
 
 use arrayvec::ArrayVec;
 use hir::{
-    Adt, AsAssocItem, AssocItem, BuiltinAttr, BuiltinType, Const, Crate, Field, Function,
-    GenericParam, HasVisibility, Impl, ItemInNs, Label, Local, Macro, Module, ModuleDef, Name,
-    PathResolution, Semantics, Static, ToolModule, Trait, TypeAlias, Variant, Visibility,
+    Adt, AsAssocItem, AssocItem, BuiltinAttr, BuiltinType, Const, Field, Function, GenericParam,
+    HasVisibility, Impl, ItemInNs, Label, Local, Macro, Module, ModuleDef, Name, PathResolution,
+    Semantics, Static, ToolModule, Trait, TypeAlias, Variant, Visibility,
 };
 use stdx::impl_from;
 use syntax::{
@@ -46,13 +46,6 @@ impl Definition {
         self.module(db).map(|it| it.path_to_root(db).into_iter().rev())
     }
 
-    pub fn krate(&self, db: &RootDatabase) -> Option<Crate> {
-        Some(match self {
-            Definition::Module(m) => m.krate(),
-            _ => self.module(db)?.krate(),
-        })
-    }
-
     pub fn module(&self, db: &RootDatabase) -> Option<Module> {
         let module = match self {
             Definition::Macro(it) => it.module(db),
diff --git a/crates/ide-db/src/rename.rs b/crates/ide-db/src/rename.rs
index 8f83496e93..589975406a 100644
--- a/crates/ide-db/src/rename.rs
+++ b/crates/ide-db/src/rename.rs
@@ -180,33 +180,15 @@ fn rename_mod(
     let InFile { file_id, value: def_source } = module.definition_source(sema.db);
     if let ModuleSource::SourceFile(..) = def_source {
         let anchor = file_id.original_file(sema.db);
-
-        let is_mod_rs = module.is_mod_rs(sema.db);
-        let has_detached_child = module.children(sema.db).any(|child| !child.is_inline(sema.db));
-
-        // Module exists in a named file
-        if !is_mod_rs {
+        // 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 })
-        }
-
-        // Rename the dir if:
-        //  - Module source is in mod.rs
-        //  - Module has submodules defined in separate files
-        let dir_paths = match (is_mod_rs, has_detached_child, module.name(sema.db)) {
-            // Go up one level since the anchor is inside the dir we're trying to rename
-            (true, _, Some(mod_name)) => {
-                Some((format!("../{}", mod_name), format!("../{}", new_name)))
-            }
-            // The anchor is on the same level as target dir
-            (false, true, Some(mod_name)) => Some((mod_name.to_string(), new_name.to_string())),
-            _ => None,
-        };
-
-        if let Some((src, dst)) = dir_paths {
-            let src = AnchoredPathBuf { anchor, path: src };
-            let dst = AnchoredPathBuf { anchor, path: 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,
diff --git a/crates/ide-db/src/symbol_index.rs b/crates/ide-db/src/symbol_index.rs
index 33e2001934..a812c838ac 100644
--- a/crates/ide-db/src/symbol_index.rs
+++ b/crates/ide-db/src/symbol_index.rs
@@ -217,6 +217,13 @@ pub fn crate_symbols(db: &RootDatabase, krate: Crate, query: Query) -> Vec<FileS
     query.search(&indices)
 }
 
+pub fn index_resolve(db: &RootDatabase, name: &str) -> Vec<FileSymbol> {
+    let mut query = Query::new(name.to_string());
+    query.exact();
+    query.limit(4);
+    world_symbols(db, query)
+}
+
 #[derive(Default)]
 pub struct SymbolIndex {
     symbols: Vec<FileSymbol>,
diff --git a/crates/ide-db/src/syntax_helpers/format_string.rs b/crates/ide-db/src/syntax_helpers/format_string.rs
index 819134a255..3c584a6cbc 100644
--- a/crates/ide-db/src/syntax_helpers/format_string.rs
+++ b/crates/ide-db/src/syntax_helpers/format_string.rs
@@ -1,7 +1,7 @@
 //! Tools to work with format string literals for the `format_args!` family of macros.
 use syntax::{
     ast::{self, IsString},
-    AstNode, AstToken, TextRange, TextSize,
+    AstNode, AstToken, TextRange,
 };
 
 pub fn is_format_string(string: &ast::String) -> bool {
@@ -48,7 +48,6 @@ pub enum FormatSpecifier {
     Dot,
     Asterisk,
     QuestionMark,
-    Escape,
 }
 
 pub fn lex_format_specifiers(
@@ -67,7 +66,7 @@ pub fn lex_format_specifiers(
             // Format specifier, see syntax at https://doc.rust-lang.org/std/fmt/index.html#syntax
             if let Some((_, '{')) = chars.peek() {
                 // Escaped format specifier, `{{`
-                read_escaped_format_specifier(&mut chars, &mut callback);
+                chars.next();
                 continue;
             }
 
@@ -239,11 +238,6 @@ pub fn lex_format_specifiers(
                 skip_char_and_emit(&mut chars, FormatSpecifier::Close, &mut callback);
             }
             continue;
-        } else if let '}' = first_char {
-            if let Some((_, '}')) = chars.peek() {
-                // Escaped format specifier, `}}`
-                read_escaped_format_specifier(&mut chars, &mut callback);
-            }
         }
     }
 
@@ -294,15 +288,4 @@ pub fn lex_format_specifiers(
         }
         callback(range, FormatSpecifier::Identifier);
     }
-
-    fn read_escaped_format_specifier<I, F>(chars: &mut std::iter::Peekable<I>, callback: &mut F)
-    where
-        I: Iterator<Item = (TextRange, char)>,
-        F: FnMut(TextRange, FormatSpecifier),
-    {
-        let (range, _) = chars.peek().unwrap();
-        let offset = TextSize::from(1);
-        callback(TextRange::new(range.start() - offset, range.end()), FormatSpecifier::Escape);
-        chars.next();
-    }
 }
diff --git a/crates/ide-db/src/syntax_helpers/insert_whitespace_into_node.rs b/crates/ide-db/src/syntax_helpers/insert_whitespace_into_node.rs
index a06f18543f..16e609b1a7 100644
--- a/crates/ide-db/src/syntax_helpers/insert_whitespace_into_node.rs
+++ b/crates/ide-db/src/syntax_helpers/insert_whitespace_into_node.rs
@@ -57,7 +57,7 @@ pub fn insert_ws_into(syn: SyntaxNode) -> SyntaxNode {
             |f: fn(SyntaxKind) -> bool, default| -> bool { last.map(f).unwrap_or(default) };
 
         match tok.kind() {
-            k if is_text(k) && is_next(|it| !it.is_punct() || it == UNDERSCORE, false) => {
+            k if is_text(k) && is_next(|it| !it.is_punct(), true) => {
                 mods.push(do_ws(after, tok));
             }
             L_CURLY if is_next(|it| it != R_CURLY, true) => {
@@ -114,13 +114,9 @@ pub fn insert_ws_into(syn: SyntaxNode) -> SyntaxNode {
         ted::insert(pos, insert);
     }
 
-    if let Some(it) = syn.last_token().filter(|it| it.kind() == SyntaxKind::WHITESPACE) {
-        ted::remove(it);
-    }
-
     syn
 }
 
 fn is_text(k: SyntaxKind) -> bool {
-    k.is_keyword() || k.is_literal() || k == IDENT || k == UNDERSCORE
+    k.is_keyword() || k.is_literal() || k == IDENT
 }
diff --git a/crates/ide/src/doc_links.rs b/crates/ide/src/doc_links.rs
index 60fad2d5db..9ad11b7a65 100644
--- a/crates/ide/src/doc_links.rs
+++ b/crates/ide/src/doc_links.rs
@@ -10,7 +10,7 @@ use pulldown_cmark_to_cmark::{cmark_resume_with_options, Options as CMarkOptions
 use stdx::format_to;
 use url::Url;
 
-use hir::{db::HirDatabase, Adt, AsAssocItem, AssocItem, AssocItemContainer, HasAttrs};
+use hir::{db::HirDatabase, Adt, AsAssocItem, AssocItem, AssocItemContainer, Crate, HasAttrs};
 use ide_db::{
     base_db::{CrateOrigin, LangCrateOrigin, SourceDatabase},
     defs::{Definition, NameClass, NameRefClass},
@@ -293,7 +293,8 @@ fn broken_link_clone_cb<'a>(link: BrokenLink<'a>) -> Option<(CowStr<'a>, CowStr<
 fn get_doc_link(db: &RootDatabase, def: Definition) -> Option<String> {
     let (target, file, frag) = filename_and_frag_for_def(db, def)?;
 
-    let mut url = get_doc_base_url(db, target)?;
+    let krate = crate_of_def(db, target)?;
+    let mut url = get_doc_base_url(db, krate)?;
 
     if let Some(path) = mod_path_of_def(db, target) {
         url = url.join(&path).ok()?;
@@ -314,7 +315,8 @@ fn rewrite_intra_doc_link(
     let (link, ns) = parse_intra_doc_link(target);
 
     let resolved = resolve_doc_path_for_def(db, def, link, ns)?;
-    let mut url = get_doc_base_url(db, resolved)?;
+    let krate = crate_of_def(db, resolved)?;
+    let mut url = get_doc_base_url(db, krate)?;
 
     let (_, file, frag) = filename_and_frag_for_def(db, resolved)?;
     if let Some(path) = mod_path_of_def(db, resolved) {
@@ -333,7 +335,8 @@ fn rewrite_url_link(db: &RootDatabase, def: Definition, target: &str) -> Option<
         return None;
     }
 
-    let mut url = get_doc_base_url(db, def)?;
+    let krate = crate_of_def(db, def)?;
+    let mut url = get_doc_base_url(db, krate)?;
     let (def, file, frag) = filename_and_frag_for_def(db, def)?;
 
     if let Some(path) = mod_path_of_def(db, def) {
@@ -345,6 +348,15 @@ fn rewrite_url_link(db: &RootDatabase, def: Definition, target: &str) -> Option<
     url.join(target).ok().map(Into::into)
 }
 
+fn crate_of_def(db: &RootDatabase, def: Definition) -> Option<Crate> {
+    let krate = match def {
+        // Definition::module gives back the parent module, we don't want that as it fails for root modules
+        Definition::Module(module) => module.krate(),
+        def => def.module(db)?.krate(),
+    };
+    Some(krate)
+}
+
 fn mod_path_of_def(db: &RootDatabase, def: Definition) -> Option<String> {
     def.canonical_module_path(db).map(|it| {
         let mut path = String::new();
@@ -398,20 +410,13 @@ fn map_links<'e>(
     })
 }
 
-/// Get the root URL for the documentation of a definition.
+/// Get the root URL for the documentation of a crate.
 ///
 /// ```ignore
 /// https://doc.rust-lang.org/std/iter/trait.Iterator.html#tymethod.next
 /// ^^^^^^^^^^^^^^^^^^^^^^^^^^
 /// ```
-fn get_doc_base_url(db: &RootDatabase, def: Definition) -> Option<Url> {
-    // special case base url of `BuiltinType` to core
-    // https://github.com/rust-lang/rust-analyzer/issues/12250
-    if let Definition::BuiltinType(..) = def {
-        return Url::parse("https://doc.rust-lang.org/nightly/core/").ok();
-    };
-
-    let krate = def.krate(db)?;
+fn get_doc_base_url(db: &RootDatabase, krate: Crate) -> Option<Url> {
     let display_name = krate.display_name(db)?;
 
     let base = match db.crate_graph()[krate.into()].origin {
diff --git a/crates/ide/src/expand_macro.rs b/crates/ide/src/expand_macro.rs
index 806f816898..e4061016e6 100644
--- a/crates/ide/src/expand_macro.rs
+++ b/crates/ide/src/expand_macro.rs
@@ -237,23 +237,6 @@ fn main() {
         );
     }
 
-    #[test]
-    fn macro_expand_underscore() {
-        check(
-            r#"
-macro_rules! bar {
-    ($i:tt) => { for _ in 0..$i {} }
-}
-fn main() {
-    ba$0r!(42);
-}
-"#,
-            expect![[r#"
-                bar
-                for _ in 0..42{}"#]],
-        );
-    }
-
     #[test]
     fn macro_expand_recursive_expansion() {
         check(
@@ -272,6 +255,7 @@ f$0oo!();
             expect![[r#"
                 foo
                 fn b(){}
+
             "#]],
         );
     }
@@ -295,7 +279,8 @@ f$0oo!();
                 fn some_thing() -> u32 {
                   let a = 0;
                   a+10
-                }"#]],
+                }
+            "#]],
         );
     }
 
@@ -356,7 +341,8 @@ fn main() {
 "#,
             expect![[r#"
                 match_ast
-                {}"#]],
+                {}
+            "#]],
         );
     }
 
@@ -399,7 +385,7 @@ fn main() {
 "#,
             expect![[r#"
                 foo
-                0"#]],
+                0 "#]],
         );
     }
 
@@ -417,7 +403,8 @@ fn main() {
 "#,
             expect![[r#"
                 foo
-                fn f<T>(_: &dyn ::std::marker::Copy){}"#]],
+                fn f<T>(_: &dyn ::std::marker::Copy){}
+            "#]],
         );
     }
 
@@ -435,6 +422,7 @@ struct Foo {}
             expect![[r#"
                 Clone
                 impl < >core::clone::Clone for Foo< >{}
+
             "#]],
         );
     }
@@ -452,6 +440,7 @@ struct Foo {}
             expect![[r#"
                 Copy
                 impl < >core::marker::Copy for Foo< >{}
+
             "#]],
         );
     }
@@ -468,6 +457,7 @@ struct Foo {}
             expect![[r#"
                 Copy
                 impl < >core::marker::Copy for Foo< >{}
+
             "#]],
         );
         check(
@@ -480,6 +470,7 @@ struct Foo {}
             expect![[r#"
                 Clone
                 impl < >core::clone::Clone for Foo< >{}
+
             "#]],
         );
     }
diff --git a/crates/ide/src/goto_declaration.rs b/crates/ide/src/goto_declaration.rs
index 926292c9b3..cb2cddc20d 100644
--- a/crates/ide/src/goto_declaration.rs
+++ b/crates/ide/src/goto_declaration.rs
@@ -10,9 +10,6 @@ use crate::{FilePosition, NavigationTarget, RangeInfo};
 // Feature: Go to Declaration
 //
 // Navigates to the declaration of an identifier.
-//
-// This is currently the same as `Go to Definition` with the exception of outline modules where it
-// will navigate to the `mod name;` item declaration.
 pub(crate) fn goto_declaration(
     db: &RootDatabase,
     position: FilePosition,
diff --git a/crates/ide/src/goto_definition.rs b/crates/ide/src/goto_definition.rs
index df73879aed..30f48819e6 100644
--- a/crates/ide/src/goto_definition.rs
+++ b/crates/ide/src/goto_definition.rs
@@ -15,8 +15,6 @@ use syntax::{ast, AstNode, AstToken, SyntaxKind::*, SyntaxToken, TextRange, T};
 //
 // Navigates to the definition of an identifier.
 //
-// For outline modules, this will navigate to the source file of the module.
-//
 // |===
 // | Editor  | Shortcut
 //
diff --git a/crates/ide/src/goto_implementation.rs b/crates/ide/src/goto_implementation.rs
index 1d2909fa28..a7d6bc2401 100644
--- a/crates/ide/src/goto_implementation.rs
+++ b/crates/ide/src/goto_implementation.rs
@@ -11,7 +11,7 @@ use crate::{FilePosition, NavigationTarget, RangeInfo, TryToNav};
 
 // Feature: Go to Implementation
 //
-// Navigates to the impl blocks of types.
+// Navigates to the impl block of structs, enums or traits. Also implemented as a code lens.
 //
 // |===
 // | Editor  | Shortcut
diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs
index d2d367c8c5..ae9be8adbd 100644
--- a/crates/ide/src/hover.rs
+++ b/crates/ide/src/hover.rs
@@ -115,7 +115,7 @@ pub(crate) fn hover(
         });
     }
 
-    let descended = sema.descend_into_macros_with_same_text(original_token.clone());
+    let descended = sema.descend_into_macros(original_token.clone());
 
     // FIXME: Definition should include known lints and the like instead of having this special case here
     let hovered_lint = descended.iter().find_map(|token| {
diff --git a/crates/ide/src/inlay_hints.rs b/crates/ide/src/inlay_hints.rs
index 116c1c480a..3cb60d9e44 100644
--- a/crates/ide/src/inlay_hints.rs
+++ b/crates/ide/src/inlay_hints.rs
@@ -21,23 +21,15 @@ pub struct InlayHintsConfig {
     pub parameter_hints: bool,
     pub chaining_hints: bool,
     pub reborrow_hints: ReborrowHints,
-    pub closure_return_type_hints: ClosureReturnTypeHints,
+    pub closure_return_type_hints: bool,
     pub binding_mode_hints: bool,
     pub lifetime_elision_hints: LifetimeElisionHints,
     pub param_names_for_lifetime_elision_hints: bool,
     pub hide_named_constructor_hints: bool,
-    pub hide_closure_initialization_hints: bool,
     pub max_length: Option<usize>,
     pub closing_brace_hints_min_lines: Option<usize>,
 }
 
-#[derive(Clone, Debug, PartialEq, Eq)]
-pub enum ClosureReturnTypeHints {
-    Always,
-    WithBlock,
-    Never,
-}
-
 #[derive(Clone, Debug, PartialEq, Eq)]
 pub enum LifetimeElisionHints {
     Always,
@@ -93,7 +85,7 @@ pub enum InlayTooltip {
 //
 // Optionally, one can enable additional hints for
 //
-// * return types of closure expressions
+// * return types of closure expressions with blocks
 // * elided lifetimes
 // * compiler inserted reborrows
 //
@@ -117,32 +109,33 @@ pub(crate) fn inlay_hints(
 
     let mut acc = Vec::new();
 
-    if let Some(scope) = sema.scope(&file) {
-        let famous_defs = FamousDefs(&sema, scope.krate());
-
-        let hints = |node| hints(&mut acc, &famous_defs, config, file_id, node);
-        match range_limit {
-            Some(FileRange { range, .. }) => match file.covering_element(range) {
-                NodeOrToken::Token(_) => return acc,
-                NodeOrToken::Node(n) => n
-                    .descendants()
-                    .filter(|descendant| range.intersect(descendant.text_range()).is_some())
-                    .for_each(hints),
-            },
-            None => file.descendants().for_each(hints),
-        };
-    }
+    let hints = |node| hints(&mut acc, &sema, config, file_id, node);
+    match range_limit {
+        Some(FileRange { range, .. }) => match file.covering_element(range) {
+            NodeOrToken::Token(_) => return acc,
+            NodeOrToken::Node(n) => n
+                .descendants()
+                .filter(|descendant| range.intersect(descendant.text_range()).is_some())
+                .for_each(hints),
+        },
+        None => file.descendants().for_each(hints),
+    };
 
     acc
 }
 
 fn hints(
     hints: &mut Vec<InlayHint>,
-    famous_defs @ FamousDefs(sema, _): &FamousDefs,
+    sema: &Semantics<RootDatabase>,
     config: &InlayHintsConfig,
     file_id: FileId,
     node: SyntaxNode,
 ) {
+    let famous_defs = match sema.scope(&node) {
+        Some(it) => FamousDefs(sema, it.krate()),
+        None => return,
+    };
+
     closing_brace_hints(hints, sema, config, file_id, node.clone());
     match_ast! {
         match node {
@@ -167,18 +160,8 @@ fn hints(
                 }
                 Some(())
             },
-            ast::Item(it) => match it {
-                // FIXME: record impl lifetimes so they aren't being reused in assoc item lifetime inlay hints
-                ast::Item::Impl(_) => None,
-                ast::Item::Fn(it) => fn_lifetime_fn_hints(hints, config, it),
-                // static type elisions
-                ast::Item::Static(it) => implicit_static_hints(hints, config, Either::Left(it)),
-                ast::Item::Const(it) => implicit_static_hints(hints, config, Either::Right(it)),
-                _ => None,
-            },
-            // FIXME: fn-ptr type, dyn fn type, and trait object type elisions
-            ast::Type(_) => None,
-            _ => None,
+            ast::Fn(it) => lifetime_fn_hints(hints, config, it),
+            _ => Some(()),
         }
     };
 }
@@ -288,39 +271,7 @@ fn closing_brace_hints(
     None
 }
 
-fn implicit_static_hints(
-    acc: &mut Vec<InlayHint>,
-    config: &InlayHintsConfig,
-    statik_or_const: Either<ast::Static, ast::Const>,
-) -> Option<()> {
-    if config.lifetime_elision_hints != LifetimeElisionHints::Always {
-        return None;
-    }
-
-    if let Either::Right(it) = &statik_or_const {
-        if ast::AssocItemList::can_cast(
-            it.syntax().parent().map_or(SyntaxKind::EOF, |it| it.kind()),
-        ) {
-            return None;
-        }
-    }
-
-    if let Some(ast::Type::RefType(ty)) = statik_or_const.either(|it| it.ty(), |it| it.ty()) {
-        if ty.lifetime().is_none() {
-            let t = ty.amp_token()?;
-            acc.push(InlayHint {
-                range: t.text_range(),
-                kind: InlayKind::LifetimeHint,
-                label: "'static".to_owned(),
-                tooltip: Some(InlayTooltip::String("Elided static lifetime".into())),
-            });
-        }
-    }
-
-    Some(())
-}
-
-fn fn_lifetime_fn_hints(
+fn lifetime_fn_hints(
     acc: &mut Vec<InlayHint>,
     config: &InlayHintsConfig,
     func: ast::Fn,
@@ -508,21 +459,14 @@ fn closure_ret_hints(
     file_id: FileId,
     closure: ast::ClosureExpr,
 ) -> Option<()> {
-    if config.closure_return_type_hints == ClosureReturnTypeHints::Never {
+    if !config.closure_return_type_hints {
         return None;
     }
 
-    if closure.ret_type().is_some() {
-        return None;
-    }
-
-    if !closure_has_block_body(&closure)
-        && config.closure_return_type_hints == ClosureReturnTypeHints::WithBlock
-    {
-        return None;
-    }
-
-    let param_list = closure.param_list()?;
+    let param_list = match closure.body() {
+        Some(ast::Expr::BlockExpr(_)) => closure.param_list()?,
+        _ => return None,
+    };
 
     let closure = sema.descend_node_into_attributes(closure.clone()).pop()?;
     let ty = sema.type_of_expr(&ast::Expr::ClosureExpr(closure))?.adjusted();
@@ -745,7 +689,7 @@ fn bind_pat_hints(
     let desc_pat = descended.as_ref().unwrap_or(pat);
     let ty = sema.type_of_pat(&desc_pat.clone().into())?.original;
 
-    if should_not_display_type_hint(sema, config, pat, &ty) {
+    if should_not_display_type_hint(sema, pat, &ty) {
         return None;
     }
 
@@ -900,7 +844,6 @@ fn pat_is_enum_variant(db: &RootDatabase, bind_pat: &ast::IdentPat, pat_ty: &hir
 
 fn should_not_display_type_hint(
     sema: &Semantics<RootDatabase>,
-    config: &InlayHintsConfig,
     bind_pat: &ast::IdentPat,
     pat_ty: &hir::Type,
 ) -> bool {
@@ -916,18 +859,6 @@ fn should_not_display_type_hint(
         }
     }
 
-    if config.hide_closure_initialization_hints {
-        if let Some(parent) = bind_pat.syntax().parent() {
-            if let Some(it) = ast::LetStmt::cast(parent.clone()) {
-                if let Some(ast::Expr::ClosureExpr(closure)) = it.initializer() {
-                    if closure_has_block_body(&closure) {
-                        return true;
-                    }
-                }
-            }
-        }
-    }
-
     for node in bind_pat.syntax().ancestors() {
         match_ast! {
             match node {
@@ -954,10 +885,6 @@ fn should_not_display_type_hint(
     false
 }
 
-fn closure_has_block_body(closure: &ast::ClosureExpr) -> bool {
-    matches!(closure.body(), Some(ast::Expr::BlockExpr(_)))
-}
-
 fn should_hide_param_name_hint(
     sema: &Semantics<RootDatabase>,
     callable: &hir::Callable,
@@ -1142,19 +1069,16 @@ mod tests {
     use crate::inlay_hints::ReborrowHints;
     use crate::{fixture, inlay_hints::InlayHintsConfig, LifetimeElisionHints};
 
-    use super::ClosureReturnTypeHints;
-
     const DISABLED_CONFIG: InlayHintsConfig = InlayHintsConfig {
         render_colons: false,
         type_hints: false,
         parameter_hints: false,
         chaining_hints: false,
         lifetime_elision_hints: LifetimeElisionHints::Never,
-        closure_return_type_hints: ClosureReturnTypeHints::Never,
+        closure_return_type_hints: false,
         reborrow_hints: ReborrowHints::Always,
         binding_mode_hints: false,
         hide_named_constructor_hints: false,
-        hide_closure_initialization_hints: false,
         param_names_for_lifetime_elision_hints: false,
         max_length: None,
         closing_brace_hints_min_lines: None,
@@ -1164,7 +1088,7 @@ mod tests {
         parameter_hints: true,
         chaining_hints: true,
         reborrow_hints: ReborrowHints::Always,
-        closure_return_type_hints: ClosureReturnTypeHints::WithBlock,
+        closure_return_type_hints: true,
         binding_mode_hints: true,
         lifetime_elision_hints: LifetimeElisionHints::Always,
         ..DISABLED_CONFIG
@@ -1245,23 +1169,6 @@ fn main() {
         );
     }
 
-    #[test]
-    fn param_hints_on_closure() {
-        check_params(
-            r#"
-fn main() {
-    let clo = |a: u8, b: u8| a + b;
-    clo(
-        1,
-      //^ a
-        2,
-      //^ b
-    );
-}
-            "#,
-        );
-    }
-
     #[test]
     fn param_name_similar_to_fn_name_still_hints() {
         check_params(
@@ -2093,8 +2000,7 @@ fn main() {
 
     ;
 
-    let _: i32 = multiply(1,  2);
-                        //^ a ^ b
+    let _: i32 = multiply(1, 2);
     let multiply_ref = &multiply;
       //^^^^^^^^^^^^ &|i32, i32| -> i32
 
@@ -2106,70 +2012,6 @@ fn main() {
         );
     }
 
-    #[test]
-    fn return_type_hints_for_closure_without_block() {
-        check_with_config(
-            InlayHintsConfig {
-                closure_return_type_hints: ClosureReturnTypeHints::Always,
-                ..DISABLED_CONFIG
-            },
-            r#"
-fn main() {
-    let a = || { 0 };
-          //^^ i32
-    let b = || 0;
-          //^^ i32
-}"#,
-        );
-    }
-
-    #[test]
-    fn skip_closure_type_hints() {
-        check_with_config(
-            InlayHintsConfig {
-                type_hints: true,
-                hide_closure_initialization_hints: true,
-                ..DISABLED_CONFIG
-            },
-            r#"
-//- minicore: fn
-fn main() {
-    let multiple_2 = |x: i32| { x * 2 };
-
-    let multiple_2 = |x: i32| x * 2;
-    //  ^^^^^^^^^^ |i32| -> i32
-
-    let (not) = (|x: bool| { !x });
-    //   ^^^ |bool| -> bool
-
-    let (is_zero, _b) = (|x: usize| { x == 0 }, false);
-    //   ^^^^^^^ |usize| -> bool
-    //            ^^ bool
-
-    let plus_one = |x| { x + 1 };
-    //              ^ u8
-    foo(plus_one);
-
-    let add_mul = bar(|x: u8| { x + 1 });
-    //  ^^^^^^^ impl FnOnce(u8) -> u8 + ?Sized
-
-    let closure = if let Some(6) = add_mul(2).checked_sub(1) {
-    //  ^^^^^^^ fn(i32) -> i32
-        |x: i32| { x * 2 }
-    } else {
-        |x: i32| { x * 3 }
-    };
-}
-
-fn foo(f: impl FnOnce(u8) -> u8) {}
-
-fn bar(f: impl FnOnce(u8) -> u8) -> impl FnOnce(u8) -> u8 {
-    move |x: u8| f(x) * 2
-}
-"#,
-        );
-    }
-
     #[test]
     fn hint_truncation() {
         check_with_config(
@@ -2634,30 +2476,6 @@ impl () {
         );
     }
 
-    #[test]
-    fn hints_lifetimes_static() {
-        check_with_config(
-            InlayHintsConfig {
-                lifetime_elision_hints: LifetimeElisionHints::Always,
-                ..TEST_CONFIG
-            },
-            r#"
-trait Trait {}
-static S: &str = "";
-//        ^'static
-const C: &str = "";
-//       ^'static
-const C: &dyn Trait = panic!();
-//       ^'static
-
-impl () {
-    const C: &str = "";
-    const C: &dyn Trait = panic!();
-}
-"#,
-        );
-    }
-
     #[test]
     fn hints_implicit_reborrow() {
         check_with_config(
diff --git a/crates/ide/src/lib.rs b/crates/ide/src/lib.rs
index aab5ceda36..0d87f4fcfa 100644
--- a/crates/ide/src/lib.rs
+++ b/crates/ide/src/lib.rs
@@ -81,8 +81,7 @@ pub use crate::{
     highlight_related::{HighlightRelatedConfig, HighlightedRange},
     hover::{HoverAction, HoverConfig, HoverDocFormat, HoverGotoTypeData, HoverResult},
     inlay_hints::{
-        ClosureReturnTypeHints, InlayHint, InlayHintsConfig, InlayKind, InlayTooltip,
-        LifetimeElisionHints, ReborrowHints,
+        InlayHint, InlayHintsConfig, InlayKind, InlayTooltip, LifetimeElisionHints, ReborrowHints,
     },
     join_lines::JoinLinesConfig,
     markup::Markup,
@@ -343,16 +342,11 @@ impl Analysis {
         &self,
         position: FilePosition,
         char_typed: char,
-        autoclose: bool,
     ) -> Cancellable<Option<SourceChange>> {
         // Fast path to not even parse the file.
         if !typing::TRIGGER_CHARS.contains(char_typed) {
             return Ok(None);
         }
-        if char_typed == '<' && !autoclose {
-            return Ok(None);
-        }
-
         self.with_db(|db| typing::on_char_typed(db, position, char_typed))
     }
 
@@ -548,11 +542,8 @@ impl Analysis {
         &self,
         config: &CompletionConfig,
         position: FilePosition,
-        trigger_character: Option<char>,
     ) -> Cancellable<Option<Vec<CompletionItem>>> {
-        self.with_db(|db| {
-            ide_completion::completions(db, config, position, trigger_character).map(Into::into)
-        })
+        self.with_db(|db| ide_completion::completions(db, config, position).map(Into::into))
     }
 
     /// Resolves additional completion data at the position given.
diff --git a/crates/ide/src/references.rs b/crates/ide/src/references.rs
index 626e8fe34a..0cd29c8432 100644
--- a/crates/ide/src/references.rs
+++ b/crates/ide/src/references.rs
@@ -122,7 +122,7 @@ pub(crate) fn find_defs<'a>(
         )
     });
     token.map(|token| {
-        sema.descend_into_macros_with_same_text(token)
+        sema.descend_into_macros_with_same_kind(token)
             .into_iter()
             .filter_map(|it| ast::NameLike::cast(it.parent()?))
             .filter_map(move |name_like| {
diff --git a/crates/ide/src/rename.rs b/crates/ide/src/rename.rs
index 0f8033611a..f5bff5fd91 100644
--- a/crates/ide/src/rename.rs
+++ b/crates/ide/src/rename.rs
@@ -973,7 +973,7 @@ mod fo$0o;
                                 anchor: FileId(
                                     1,
                                 ),
-                                path: "../foo",
+                                path: "foo",
                             },
                             src_id: FileId(
                                 1,
@@ -982,7 +982,7 @@ mod fo$0o;
                                 anchor: FileId(
                                     1,
                                 ),
-                                path: "../foo2",
+                                path: "foo2",
                             },
                         },
                     ],
@@ -1158,17 +1158,6 @@ mod quux;
                         },
                     },
                     file_system_edits: [
-                        MoveFile {
-                            src: FileId(
-                                1,
-                            ),
-                            dst: AnchoredPathBuf {
-                                anchor: FileId(
-                                    1,
-                                ),
-                                path: "foo2.rs",
-                            },
-                        },
                         MoveDir {
                             src: AnchoredPathBuf {
                                 anchor: FileId(
diff --git a/crates/ide/src/signature_help.rs b/crates/ide/src/signature_help.rs
index cb38f48f32..32e7c59b2a 100644
--- a/crates/ide/src/signature_help.rs
+++ b/crates/ide/src/signature_help.rs
@@ -149,7 +149,7 @@ fn signature_help_for_call(
                 variant.name(db)
             );
         }
-        hir::CallableKind::Closure | hir::CallableKind::FnPtr => (),
+        hir::CallableKind::Closure => (),
     }
 
     res.signature.push('(');
@@ -189,7 +189,7 @@ fn signature_help_for_call(
         hir::CallableKind::Function(func) if callable.return_type().contains_unknown() => {
             render(func.ret_type(db))
         }
-        hir::CallableKind::Function(_) | hir::CallableKind::Closure | hir::CallableKind::FnPtr => {
+        hir::CallableKind::Function(_) | hir::CallableKind::Closure => {
             render(callable.return_type())
         }
         hir::CallableKind::TupleStruct(_) | hir::CallableKind::TupleEnumVariant(_) => {}
@@ -914,8 +914,8 @@ fn main() {
 }
         "#,
             expect![[r#"
-                (s: S) -> i32
-                 ^^^^
+                (S) -> i32
+                 ^
             "#]],
         )
     }
diff --git a/crates/ide/src/static_index.rs b/crates/ide/src/static_index.rs
index 95a9635a06..01d7213630 100644
--- a/crates/ide/src/static_index.rs
+++ b/crates/ide/src/static_index.rs
@@ -109,11 +109,10 @@ impl StaticIndex<'_> {
                     type_hints: true,
                     parameter_hints: true,
                     chaining_hints: true,
-                    closure_return_type_hints: crate::ClosureReturnTypeHints::WithBlock,
+                    closure_return_type_hints: true,
                     lifetime_elision_hints: crate::LifetimeElisionHints::Never,
                     reborrow_hints: crate::ReborrowHints::Never,
                     hide_named_constructor_hints: false,
-                    hide_closure_initialization_hints: false,
                     param_names_for_lifetime_elision_hints: false,
                     binding_mode_hints: false,
                     max_length: Some(25),
diff --git a/crates/ide/src/syntax_highlighting.rs b/crates/ide/src/syntax_highlighting.rs
index 1d22c43317..f6754e44f3 100644
--- a/crates/ide/src/syntax_highlighting.rs
+++ b/crates/ide/src/syntax_highlighting.rs
@@ -206,8 +206,9 @@ fn traverse(
     let is_unlinked = sema.to_module_def(file_id).is_none();
     let mut bindings_shadow_count: FxHashMap<Name, u32> = FxHashMap::default();
 
-    let mut tt_level = 0;
-    let mut attr_or_derive_item = None;
+    let mut current_macro_call: Option<ast::MacroCall> = None;
+    let mut current_attr_call = None;
+    let mut current_derive_call = None;
     let mut current_macro: Option<ast::Macro> = None;
     let mut macro_highlighter = MacroHighlighter::default();
     let mut inside_attribute = false;
@@ -215,10 +216,8 @@ fn traverse(
     // Walk all nodes, keeping track of whether we are inside a macro or not.
     // If in macro, expand it first and highlight the expanded code.
     for event in root.preorder_with_tokens() {
-        use WalkEvent::{Enter, Leave};
-
         let range = match &event {
-            Enter(it) | Leave(it) => it.text_range(),
+            WalkEvent::Enter(it) | WalkEvent::Leave(it) => it.text_range(),
         };
 
         // Element outside of the viewport, no need to highlight
@@ -228,84 +227,78 @@ fn traverse(
 
         // set macro and attribute highlighting states
         match event.clone() {
-            Enter(NodeOrToken::Node(node)) if ast::TokenTree::can_cast(node.kind()) => {
-                tt_level += 1;
-            }
-            Leave(NodeOrToken::Node(node)) if ast::TokenTree::can_cast(node.kind()) => {
-                tt_level -= 1;
-            }
-            Enter(NodeOrToken::Node(node)) if ast::Attr::can_cast(node.kind()) => {
-                inside_attribute = true
-            }
-            Leave(NodeOrToken::Node(node)) if ast::Attr::can_cast(node.kind()) => {
-                inside_attribute = false
-            }
-
-            Enter(NodeOrToken::Node(node)) if ast::Item::can_cast(node.kind()) => {
-                match ast::Item::cast(node.clone()) {
-                    Some(ast::Item::MacroRules(mac)) => {
-                        macro_highlighter.init();
-                        current_macro = Some(mac.into());
-                        continue;
-                    }
-                    Some(ast::Item::MacroDef(mac)) => {
-                        macro_highlighter.init();
-                        current_macro = Some(mac.into());
-                        continue;
+            WalkEvent::Enter(NodeOrToken::Node(node)) => match ast::Item::cast(node.clone()) {
+                Some(ast::Item::MacroCall(mcall)) => {
+                    current_macro_call = Some(mcall);
+                    continue;
+                }
+                Some(ast::Item::MacroRules(mac)) => {
+                    macro_highlighter.init();
+                    current_macro = Some(mac.into());
+                    continue;
+                }
+                Some(ast::Item::MacroDef(mac)) => {
+                    macro_highlighter.init();
+                    current_macro = Some(mac.into());
+                    continue;
+                }
+                Some(item) => {
+                    if matches!(node.kind(), FN | CONST | STATIC) {
+                        bindings_shadow_count.clear();
                     }
-                    Some(item) => {
-                        if matches!(node.kind(), FN | CONST | STATIC) {
-                            bindings_shadow_count.clear();
-                        }
 
-                        if attr_or_derive_item.is_none() {
-                            if sema.is_attr_macro_call(&item) {
-                                attr_or_derive_item = Some(item);
-                            } else {
-                                let adt = match item {
-                                    ast::Item::Enum(it) => Some(ast::Adt::Enum(it)),
-                                    ast::Item::Struct(it) => Some(ast::Adt::Struct(it)),
-                                    ast::Item::Union(it) => Some(ast::Adt::Union(it)),
-                                    _ => None,
-                                };
-                                match adt {
-                                    Some(adt) if sema.is_derive_annotated(&adt) => {
-                                        attr_or_derive_item = Some(ast::Item::from(adt));
-                                    }
-                                    _ => (),
-                                }
+                    if sema.is_attr_macro_call(&item) {
+                        current_attr_call = Some(item);
+                    } else if current_attr_call.is_none() {
+                        let adt = match item {
+                            ast::Item::Enum(it) => Some(ast::Adt::Enum(it)),
+                            ast::Item::Struct(it) => Some(ast::Adt::Struct(it)),
+                            ast::Item::Union(it) => Some(ast::Adt::Union(it)),
+                            _ => None,
+                        };
+                        match adt {
+                            Some(adt) if sema.is_derive_annotated(&adt) => {
+                                current_derive_call = Some(ast::Item::from(adt));
                             }
+                            _ => (),
                         }
                     }
-                    _ => (),
                 }
-            }
-            Leave(NodeOrToken::Node(node)) if ast::Item::can_cast(node.kind()) => {
-                match ast::Item::cast(node.clone()) {
-                    Some(ast::Item::MacroRules(mac)) => {
-                        assert_eq!(current_macro, Some(mac.into()));
-                        current_macro = None;
-                        macro_highlighter = MacroHighlighter::default();
-                    }
-                    Some(ast::Item::MacroDef(mac)) => {
-                        assert_eq!(current_macro, Some(mac.into()));
-                        current_macro = None;
-                        macro_highlighter = MacroHighlighter::default();
-                    }
-                    Some(item) if attr_or_derive_item.as_ref().map_or(false, |it| *it == item) => {
-                        attr_or_derive_item = None;
-                    }
-                    _ => (),
+                None if ast::Attr::can_cast(node.kind()) => inside_attribute = true,
+                _ => (),
+            },
+            WalkEvent::Leave(NodeOrToken::Node(node)) => match ast::Item::cast(node.clone()) {
+                Some(ast::Item::MacroCall(mcall)) => {
+                    assert_eq!(current_macro_call, Some(mcall));
+                    current_macro_call = None;
                 }
-            }
+                Some(ast::Item::MacroRules(mac)) => {
+                    assert_eq!(current_macro, Some(mac.into()));
+                    current_macro = None;
+                    macro_highlighter = MacroHighlighter::default();
+                }
+                Some(ast::Item::MacroDef(mac)) => {
+                    assert_eq!(current_macro, Some(mac.into()));
+                    current_macro = None;
+                    macro_highlighter = MacroHighlighter::default();
+                }
+                Some(item) if current_attr_call.as_ref().map_or(false, |it| *it == item) => {
+                    current_attr_call = None;
+                }
+                Some(item) if current_derive_call.as_ref().map_or(false, |it| *it == item) => {
+                    current_derive_call = None;
+                }
+                None if ast::Attr::can_cast(node.kind()) => inside_attribute = false,
+                _ => (),
+            },
             _ => (),
         }
 
         let element = match event {
-            Enter(NodeOrToken::Token(tok)) if tok.kind() == WHITESPACE => continue,
-            Enter(it) => it,
-            Leave(NodeOrToken::Token(_)) => continue,
-            Leave(NodeOrToken::Node(node)) => {
+            WalkEvent::Enter(NodeOrToken::Token(tok)) if tok.kind() == WHITESPACE => continue,
+            WalkEvent::Enter(it) => it,
+            WalkEvent::Leave(NodeOrToken::Token(_)) => continue,
+            WalkEvent::Leave(NodeOrToken::Node(node)) => {
                 // Doc comment highlighting injection, we do this when leaving the node
                 // so that we overwrite the highlighting of the doc comment itself.
                 inject::doc_comment(hl, sema, InFile::new(file_id.into(), &node));
@@ -330,25 +323,38 @@ fn traverse(
 
         // Descending tokens into macros is expensive even if no descending occurs, so make sure
         // that we actually are in a position where descending is possible.
-        let in_macro = tt_level > 0 || attr_or_derive_item.is_some();
+        let in_macro = current_macro_call.is_some()
+            || current_derive_call.is_some()
+            || current_attr_call.is_some();
         let descended_element = if in_macro {
             // Attempt to descend tokens into macro-calls.
             match element {
                 NodeOrToken::Token(token) if token.kind() != COMMENT => {
-                    let token = sema.descend_into_macros_single(token);
-                    match token.parent().and_then(ast::NameLike::cast) {
-                        // Remap the token into the wrapping single token nodes
-                        // FIXME: if the node doesn't resolve, we also won't do token based highlighting!
-                        Some(parent) => match (token.kind(), parent.syntax().kind()) {
-                            (T![self] | T![ident], NAME | NAME_REF) => NodeOrToken::Node(parent),
-                            (T![self] | T![super] | T![crate] | T![Self], NAME_REF) => {
-                                NodeOrToken::Node(parent)
-                            }
-                            (INT_NUMBER, NAME_REF) => NodeOrToken::Node(parent),
-                            (LIFETIME_IDENT, LIFETIME) => NodeOrToken::Node(parent),
-                            _ => NodeOrToken::Token(token),
-                        },
-                        None => NodeOrToken::Token(token),
+                    // For function-like macro calls and derive attributes, only attempt to descend if
+                    // we are inside their token-trees.
+                    let in_tt = current_attr_call.is_some()
+                        || token.parent().as_ref().map(SyntaxNode::kind) == Some(TOKEN_TREE);
+
+                    if in_tt {
+                        let token = sema.descend_into_macros_single(token);
+                        match token.parent().and_then(ast::NameLike::cast) {
+                            // Remap the token into the wrapping single token nodes
+                            // FIXME: if the node doesn't resolve, we also won't do token based highlighting!
+                            Some(parent) => match (token.kind(), parent.syntax().kind()) {
+                                (T![self] | T![ident], NAME | NAME_REF) => {
+                                    NodeOrToken::Node(parent)
+                                }
+                                (T![self] | T![super] | T![crate] | T![Self], NAME_REF) => {
+                                    NodeOrToken::Node(parent)
+                                }
+                                (INT_NUMBER, NAME_REF) => NodeOrToken::Node(parent),
+                                (LIFETIME_IDENT, LIFETIME) => NodeOrToken::Node(parent),
+                                _ => NodeOrToken::Token(token),
+                            },
+                            None => NodeOrToken::Token(token),
+                        }
+                    } else {
+                        NodeOrToken::Token(token)
                     }
                 }
                 e => e,
diff --git a/crates/ide/src/syntax_highlighting/format.rs b/crates/ide/src/syntax_highlighting/format.rs
index 2ed57e2013..2d5f5f00e1 100644
--- a/crates/ide/src/syntax_highlighting/format.rs
+++ b/crates/ide/src/syntax_highlighting/format.rs
@@ -45,6 +45,5 @@ fn highlight_format_specifier(kind: FormatSpecifier) -> Option<HlTag> {
         FormatSpecifier::Integer | FormatSpecifier::Zero => HlTag::NumericLiteral,
 
         FormatSpecifier::Identifier => HlTag::Symbol(SymbolKind::Local),
-        FormatSpecifier::Escape => HlTag::EscapeSequence,
     })
 }
diff --git a/crates/ide/src/syntax_highlighting/highlight.rs b/crates/ide/src/syntax_highlighting/highlight.rs
index 198e17db53..e04fd5a7c7 100644
--- a/crates/ide/src/syntax_highlighting/highlight.rs
+++ b/crates/ide/src/syntax_highlighting/highlight.rs
@@ -466,7 +466,10 @@ fn highlight_def(sema: &Semantics<RootDatabase>, krate: hir::Crate, def: Definit
         Definition::ToolModule(_) => Highlight::new(HlTag::Symbol(SymbolKind::ToolModule)),
     };
 
-    let def_crate = def.krate(db);
+    let def_crate = def.module(db).map(hir::Module::krate).or_else(|| match def {
+        Definition::Module(module) => Some(module.krate()),
+        _ => None,
+    });
     let is_from_other_crate = def_crate != Some(krate);
     let is_from_builtin_crate = def_crate.map_or(false, |def_crate| def_crate.is_builtin(db));
     let is_builtin_type = matches!(def, Definition::BuiltinType(_));
diff --git a/crates/ide/src/typing.rs b/crates/ide/src/typing.rs
index 9118f3c699..a75e6be8b8 100644
--- a/crates/ide/src/typing.rs
+++ b/crates/ide/src/typing.rs
@@ -20,9 +20,9 @@ use ide_db::{
     RootDatabase,
 };
 use syntax::{
-    algo::{ancestors_at_offset, find_node_at_offset},
+    algo::find_node_at_offset,
     ast::{self, edit::IndentLevel, AstToken},
-    AstNode, Parse, SourceFile, SyntaxKind, TextRange, TextSize, T,
+    AstNode, Parse, SourceFile, SyntaxKind, TextRange, TextSize,
 };
 
 use text_edit::{Indel, TextEdit};
@@ -32,12 +32,7 @@ use crate::SourceChange;
 pub(crate) use on_enter::on_enter;
 
 // Don't forget to add new trigger characters to `server_capabilities` in `caps.rs`.
-pub(crate) const TRIGGER_CHARS: &str = ".=<>{";
-
-struct ExtendedTextEdit {
-    edit: TextEdit,
-    is_snippet: bool,
-}
+pub(crate) const TRIGGER_CHARS: &str = ".=>{";
 
 // Feature: On Typing Assists
 //
@@ -73,30 +68,23 @@ pub(crate) fn on_char_typed(
         return None;
     }
     let edit = on_char_typed_inner(file, position.offset, char_typed)?;
-    let mut sc = SourceChange::from_text_edit(position.file_id, edit.edit);
-    sc.is_snippet = edit.is_snippet;
-    Some(sc)
+    Some(SourceChange::from_text_edit(position.file_id, edit))
 }
 
 fn on_char_typed_inner(
     file: &Parse<SourceFile>,
     offset: TextSize,
     char_typed: char,
-) -> Option<ExtendedTextEdit> {
+) -> Option<TextEdit> {
     if !stdx::always!(TRIGGER_CHARS.contains(char_typed)) {
         return None;
     }
-    return match char_typed {
-        '.' => conv(on_dot_typed(&file.tree(), offset)),
-        '=' => conv(on_eq_typed(&file.tree(), offset)),
-        '<' => on_left_angle_typed(&file.tree(), offset),
-        '>' => conv(on_right_angle_typed(&file.tree(), offset)),
-        '{' => conv(on_opening_brace_typed(file, offset)),
-        _ => return None,
-    };
-
-    fn conv(text_edit: Option<TextEdit>) -> Option<ExtendedTextEdit> {
-        Some(ExtendedTextEdit { edit: text_edit?, is_snippet: false })
+    match char_typed {
+        '.' => on_dot_typed(&file.tree(), offset),
+        '=' => on_eq_typed(&file.tree(), offset),
+        '>' => on_arrow_typed(&file.tree(), offset),
+        '{' => on_opening_brace_typed(file, offset),
+        _ => unreachable!(),
     }
 }
 
@@ -314,49 +302,8 @@ fn on_dot_typed(file: &SourceFile, offset: TextSize) -> Option<TextEdit> {
     Some(TextEdit::replace(TextRange::new(offset - current_indent_len, offset), target_indent))
 }
 
-/// Add closing `>` for generic arguments/parameters.
-fn on_left_angle_typed(file: &SourceFile, offset: TextSize) -> Option<ExtendedTextEdit> {
-    let file_text = file.syntax().text();
-    if !stdx::always!(file_text.char_at(offset) == Some('<')) {
-        return None;
-    }
-
-    // Find the next non-whitespace char in the line.
-    let mut next_offset = offset + TextSize::of('<');
-    while file_text.char_at(next_offset) == Some(' ') {
-        next_offset += TextSize::of(' ')
-    }
-    if file_text.char_at(next_offset) == Some('>') {
-        return None;
-    }
-
-    let range = TextRange::at(offset, TextSize::of('<'));
-    if let Some(t) = file.syntax().token_at_offset(offset).left_biased() {
-        if T![impl] == t.kind() {
-            return Some(ExtendedTextEdit {
-                edit: TextEdit::replace(range, "<$0>".to_string()),
-                is_snippet: true,
-            });
-        }
-    }
-
-    if ancestors_at_offset(file.syntax(), offset)
-        .find(|n| {
-            ast::GenericParamList::can_cast(n.kind()) || ast::GenericArgList::can_cast(n.kind())
-        })
-        .is_some()
-    {
-        return Some(ExtendedTextEdit {
-            edit: TextEdit::replace(range, "<$0>".to_string()),
-            is_snippet: true,
-        });
-    }
-
-    None
-}
-
 /// Adds a space after an arrow when `fn foo() { ... }` is turned into `fn foo() -> { ... }`
-fn on_right_angle_typed(file: &SourceFile, offset: TextSize) -> Option<TextEdit> {
+fn on_arrow_typed(file: &SourceFile, offset: TextSize) -> Option<TextEdit> {
     let file_text = file.syntax().text();
     if !stdx::always!(file_text.char_at(offset) == Some('>')) {
         return None;
@@ -378,12 +325,6 @@ mod tests {
 
     use super::*;
 
-    impl ExtendedTextEdit {
-        fn apply(&self, text: &mut String) {
-            self.edit.apply(text);
-        }
-    }
-
     fn do_type_char(char_typed: char, before: &str) -> Option<String> {
         let (offset, mut before) = extract_offset(before);
         let edit = TextEdit::insert(offset, char_typed.to_string());
@@ -928,255 +869,6 @@ use some::pa$0th::to::Item;
         );
     }
 
-    #[test]
-    fn adds_closing_angle_bracket_for_generic_args() {
-        type_char(
-            '<',
-            r#"
-fn foo() {
-    bar::$0
-}
-            "#,
-            r#"
-fn foo() {
-    bar::<$0>
-}
-            "#,
-        );
-
-        type_char(
-            '<',
-            r#"
-fn foo(bar: &[u64]) {
-    bar.iter().collect::$0();
-}
-            "#,
-            r#"
-fn foo(bar: &[u64]) {
-    bar.iter().collect::<$0>();
-}
-            "#,
-        );
-    }
-
-    #[test]
-    fn adds_closing_angle_bracket_for_generic_params() {
-        type_char(
-            '<',
-            r#"
-fn foo$0() {}
-            "#,
-            r#"
-fn foo<$0>() {}
-            "#,
-        );
-        type_char(
-            '<',
-            r#"
-fn foo$0
-            "#,
-            r#"
-fn foo<$0>
-            "#,
-        );
-        type_char(
-            '<',
-            r#"
-struct Foo$0 {}
-            "#,
-            r#"
-struct Foo<$0> {}
-            "#,
-        );
-        type_char(
-            '<',
-            r#"
-struct Foo$0();
-            "#,
-            r#"
-struct Foo<$0>();
-            "#,
-        );
-        type_char(
-            '<',
-            r#"
-struct Foo$0
-            "#,
-            r#"
-struct Foo<$0>
-            "#,
-        );
-        type_char(
-            '<',
-            r#"
-enum Foo$0
-            "#,
-            r#"
-enum Foo<$0>
-            "#,
-        );
-        type_char(
-            '<',
-            r#"
-trait Foo$0
-            "#,
-            r#"
-trait Foo<$0>
-            "#,
-        );
-        type_char(
-            '<',
-            r#"
-type Foo$0 = Bar;
-            "#,
-            r#"
-type Foo<$0> = Bar;
-            "#,
-        );
-        type_char(
-            '<',
-            r#"
-impl$0 Foo {}
-            "#,
-            r#"
-impl<$0> Foo {}
-            "#,
-        );
-        type_char(
-            '<',
-            r#"
-impl<T> Foo$0 {}
-            "#,
-            r#"
-impl<T> Foo<$0> {}
-            "#,
-        );
-        type_char(
-            '<',
-            r#"
-impl Foo$0 {}
-            "#,
-            r#"
-impl Foo<$0> {}
-            "#,
-        );
-    }
-
-    #[test]
-    fn dont_add_closing_angle_bracket_for_comparison() {
-        type_char_noop(
-            '<',
-            r#"
-fn main() {
-    42$0
-}
-            "#,
-        );
-        type_char_noop(
-            '<',
-            r#"
-fn main() {
-    42 $0
-}
-            "#,
-        );
-        type_char_noop(
-            '<',
-            r#"
-fn main() {
-    let foo = 42;
-    foo $0
-}
-            "#,
-        );
-    }
-
-    #[test]
-    fn dont_add_closing_angle_bracket_if_it_is_already_there() {
-        type_char_noop(
-            '<',
-            r#"
-fn foo() {
-    bar::$0>
-}
-            "#,
-        );
-        type_char_noop(
-            '<',
-            r#"
-fn foo(bar: &[u64]) {
-    bar.iter().collect::$0   >();
-}
-            "#,
-        );
-        type_char_noop(
-            '<',
-            r#"
-fn foo$0>() {}
-            "#,
-        );
-        type_char_noop(
-            '<',
-            r#"
-fn foo$0>
-            "#,
-        );
-        type_char_noop(
-            '<',
-            r#"
-struct Foo$0> {}
-            "#,
-        );
-        type_char_noop(
-            '<',
-            r#"
-struct Foo$0>();
-            "#,
-        );
-        type_char_noop(
-            '<',
-            r#"
-struct Foo$0>
-            "#,
-        );
-        type_char_noop(
-            '<',
-            r#"
-enum Foo$0>
-            "#,
-        );
-        type_char_noop(
-            '<',
-            r#"
-trait Foo$0>
-            "#,
-        );
-        type_char_noop(
-            '<',
-            r#"
-type Foo$0> = Bar;
-            "#,
-        );
-        type_char_noop(
-            '<',
-            r#"
-impl$0> Foo {}
-            "#,
-        );
-        type_char_noop(
-            '<',
-            r#"
-impl<T> Foo$0> {}
-            "#,
-        );
-        type_char_noop(
-            '<',
-            r#"
-impl Foo$0> {}
-            "#,
-        );
-    }
-
     #[test]
     fn regression_629() {
         type_char_noop(
diff --git a/crates/project-model/src/build_scripts.rs b/crates/project-model/src/build_scripts.rs
index e0e29552ac..5aa23331a1 100644
--- a/crates/project-model/src/build_scripts.rs
+++ b/crates/project-model/src/build_scripts.rs
@@ -6,7 +6,11 @@
 //! This module implements this second part. We use "build script" terminology
 //! here, but it covers procedural macros as well.
 
-use std::{cell::RefCell, io, path::PathBuf, process::Command};
+use std::{
+    io,
+    path::PathBuf,
+    process::{Command, Stdio},
+};
 
 use cargo_metadata::{camino::Utf8Path, Message};
 use la_arena::ArenaMap;
@@ -90,6 +94,8 @@ impl WorkspaceBuildScripts {
 
         cmd.current_dir(workspace.workspace_root());
 
+        cmd.stdout(Stdio::piped()).stderr(Stdio::piped()).stdin(Stdio::null());
+
         let mut res = WorkspaceBuildScripts::default();
         // NB: Cargo.toml could have been modified between `cargo metadata` and
         // `cargo check`. We shouldn't assume that package ids we see here are
@@ -101,17 +107,15 @@ impl WorkspaceBuildScripts {
             by_id.insert(workspace[package].id.clone(), package);
         }
 
-        let errors = RefCell::new(String::new());
-        let push_err = |err: &str| {
-            let mut e = errors.borrow_mut();
-            e.push_str(err);
-            e.push('\n');
-        };
-
-        tracing::info!("Running build scripts: {:?}", cmd);
+        let mut cfg_err = None;
+        let mut stderr = String::new();
         let output = stdx::process::streaming_output(
             cmd,
             &mut |line| {
+                if cfg_err.is_some() {
+                    return;
+                }
+
                 // Copy-pasted from existing cargo_metadata. It seems like we
                 // should be using serde_stacker here?
                 let mut deserializer = serde_json::Deserializer::from_str(line);
@@ -131,7 +135,7 @@ impl WorkspaceBuildScripts {
                                 match cfg.parse::<CfgFlag>() {
                                     Ok(it) => acc.push(it),
                                     Err(err) => {
-                                        push_err(&format!(
+                                        cfg_err = Some(format!(
                                             "invalid cfg from cargo-metadata: {}",
                                             err
                                         ));
@@ -173,10 +177,6 @@ impl WorkspaceBuildScripts {
                     }
                     Message::CompilerMessage(message) => {
                         progress(message.target.name);
-
-                        if let Some(diag) = message.message.rendered.as_deref() {
-                            push_err(diag);
-                        }
                     }
                     Message::BuildFinished(_) => {}
                     Message::TextLine(_) => {}
@@ -184,7 +184,8 @@ impl WorkspaceBuildScripts {
                 }
             },
             &mut |line| {
-                push_err(line);
+                stderr.push_str(line);
+                stderr.push('\n');
             },
         )?;
 
@@ -204,12 +205,16 @@ impl WorkspaceBuildScripts {
             }
         }
 
-        let mut errors = errors.into_inner();
+        if let Some(cfg_err) = cfg_err {
+            stderr.push_str(&cfg_err);
+            stderr.push('\n');
+        }
+
         if !output.status.success() {
-            if errors.is_empty() {
-                errors = "cargo check failed".to_string();
+            if stderr.is_empty() {
+                stderr = "cargo check failed".to_string();
             }
-            res.error = Some(errors);
+            res.error = Some(stderr)
         }
 
         Ok(res)
diff --git a/crates/project-model/src/workspace.rs b/crates/project-model/src/workspace.rs
index ace1d455c4..93255705be 100644
--- a/crates/project-model/src/workspace.rs
+++ b/crates/project-model/src/workspace.rs
@@ -389,10 +389,14 @@ impl ProjectWorkspace {
 
     pub fn to_crate_graph(
         &self,
-        load_proc_macro: &mut dyn FnMut(&str, &AbsPath) -> Vec<ProcMacro>,
+        dummy_replace: &FxHashMap<Box<str>, Box<[Box<str>]>>,
+        load_proc_macro: &mut dyn FnMut(&AbsPath, &[Box<str>]) -> Vec<ProcMacro>,
         load: &mut dyn FnMut(&AbsPath) -> Option<FileId>,
     ) -> CrateGraph {
         let _p = profile::span("ProjectWorkspace::to_crate_graph");
+        let load_proc_macro = &mut |crate_name: &_, path: &_| {
+            load_proc_macro(path, dummy_replace.get(crate_name).map(|it| &**it).unwrap_or_default())
+        };
 
         let mut crate_graph = match self {
             ProjectWorkspace::Json { project, sysroot, rustc_cfg } => project_json_to_crate_graph(
diff --git a/crates/rust-analyzer/src/caps.rs b/crates/rust-analyzer/src/caps.rs
index 7bff6a8b0e..a653ec289b 100644
--- a/crates/rust-analyzer/src/caps.rs
+++ b/crates/rust-analyzer/src/caps.rs
@@ -29,12 +29,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()),
-            trigger_characters: Some(vec![
-                ":".to_string(),
-                ".".to_string(),
-                "'".to_string(),
-                "(".to_string(),
-            ]),
+            trigger_characters: Some(vec![":".to_string(), ".".to_string(), "'".to_string()]),
             all_commit_characters: None,
             completion_item: None,
             work_done_progress_options: WorkDoneProgressOptions { work_done_progress: None },
@@ -61,7 +56,7 @@ pub fn server_capabilities(config: &Config) -> ServerCapabilities {
         },
         document_on_type_formatting_provider: Some(DocumentOnTypeFormattingOptions {
             first_trigger_character: "=".to_string(),
-            more_trigger_character: Some(more_trigger_character(&config)),
+            more_trigger_character: Some(vec![".".to_string(), ">".to_string(), "{".to_string()]),
         }),
         selection_range_provider: Some(SelectionRangeProviderCapability::Simple(true)),
         folding_range_provider: Some(FoldingRangeProviderCapability::Simple(true)),
@@ -194,11 +189,3 @@ fn code_action_capabilities(client_caps: &ClientCapabilities) -> CodeActionProvi
             })
         })
 }
-
-fn more_trigger_character(config: &Config) -> Vec<String> {
-    let mut res = vec![".".to_string(), ">".to_string(), "{".to_string()];
-    if config.snippet_cap() {
-        res.push("<".to_string());
-    }
-    res
-}
diff --git a/crates/rust-analyzer/src/cli/load_cargo.rs b/crates/rust-analyzer/src/cli/load_cargo.rs
index 4243af25ff..490aef50f3 100644
--- a/crates/rust-analyzer/src/cli/load_cargo.rs
+++ b/crates/rust-analyzer/src/cli/load_cargo.rs
@@ -66,7 +66,8 @@ pub fn load_workspace(
     };
 
     let crate_graph = ws.to_crate_graph(
-        &mut |_, path: &AbsPath| load_proc_macro(proc_macro_client.as_ref(), path, &[]),
+        &Default::default(),
+        &mut |path: &AbsPath, _| load_proc_macro(proc_macro_client.as_ref(), path, &[]),
         &mut |path: &AbsPath| {
             let contents = loader.load_sync(path);
             let path = vfs::VfsPath::from(path.to_path_buf());
diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs
index 9fd1958999..304254c3e2 100644
--- a/crates/rust-analyzer/src/config.rs
+++ b/crates/rust-analyzer/src/config.rs
@@ -59,7 +59,7 @@ config_data! {
 
         /// Warm up caches on project load.
         cachePriming_enable: bool = "true",
-        /// How many worker threads to handle priming caches. The default `0` means to pick automatically.
+        /// How many worker threads to to handle priming caches. The default `0` means to pick automatically.
         cachePriming_numThreads: ParallelCachePrimingNumThreads = "0",
 
         /// Automatically refresh project info via `cargo metadata` on
@@ -264,8 +264,8 @@ config_data! {
         /// Minimum number of lines required before the `}` until the hint is shown (set to 0 or 1
         /// to always show them).
         inlayHints_closingBraceHints_minLines: usize               = "25",
-        /// Whether to show inlay type hints for return types of closures.
-        inlayHints_closureReturnTypeHints_enable: ClosureReturnTypeHintsDef  = "\"never\"",
+        /// Whether to show inlay type hints for return types of closures with blocks.
+        inlayHints_closureReturnTypeHints_enable: bool             = "false",
         /// Whether to show inlay type hints for elided lifetimes in function signatures.
         inlayHints_lifetimeElisionHints_enable: LifetimeElisionDef = "\"never\"",
         /// Whether to prefer using parameter names as the name for elided lifetime hints if possible.
@@ -281,9 +281,6 @@ config_data! {
         inlayHints_renderColons: bool                              = "true",
         /// Whether to show inlay type hints for variables.
         inlayHints_typeHints_enable: bool                          = "true",
-        /// Whether to hide inlay type hints for `let` statements that initialize to a closure.
-        /// Only applies to closures with blocks, same as `#rust-analyzer.inlayHints.closureReturnTypeHints.enable#`.
-        inlayHints_typeHints_hideClosureInitialization: bool       = "false",
         /// Whether to hide inlay type hints for constructors.
         inlayHints_typeHints_hideNamedConstructor: bool            = "false",
 
@@ -386,9 +383,6 @@ config_data! {
         /// Show documentation.
         signatureInfo_documentation_enable: bool                       = "true",
 
-        /// Whether to insert closing angle brackets when typing an opening angle bracket of a generic argument list.
-        typing_autoClosingAngleBrackets_enable: bool = "false",
-
         /// Workspace symbol search kind.
         workspace_symbol_search_kind: WorkspaceSymbolSearchKindDef = "\"only_types\"",
         /// Limits the number of items returned from a workspace symbol search (Defaults to 128).
@@ -697,22 +691,7 @@ impl Config {
         match self.data.linkedProjects.as_slice() {
             [] => match self.discovered_projects.as_ref() {
                 Some(discovered_projects) => {
-                    let exclude_dirs: Vec<_> = self
-                        .data
-                        .files_excludeDirs
-                        .iter()
-                        .map(|p| self.root_path.join(p))
-                        .collect();
-                    discovered_projects
-                        .iter()
-                        .filter(|p| {
-                            let (ProjectManifest::ProjectJson(path)
-                            | ProjectManifest::CargoToml(path)) = p;
-                            !exclude_dirs.iter().any(|p| path.starts_with(p))
-                        })
-                        .cloned()
-                        .map(LinkedProject::from)
-                        .collect()
+                    discovered_projects.iter().cloned().map(LinkedProject::from).collect()
                 }
                 None => Vec::new(),
             },
@@ -1014,20 +993,13 @@ impl Config {
             type_hints: self.data.inlayHints_typeHints_enable,
             parameter_hints: self.data.inlayHints_parameterHints_enable,
             chaining_hints: self.data.inlayHints_chainingHints_enable,
-            closure_return_type_hints: match self.data.inlayHints_closureReturnTypeHints_enable {
-                ClosureReturnTypeHintsDef::Always => ide::ClosureReturnTypeHints::Always,
-                ClosureReturnTypeHintsDef::Never => ide::ClosureReturnTypeHints::Never,
-                ClosureReturnTypeHintsDef::WithBlock => ide::ClosureReturnTypeHints::WithBlock,
-            },
+            closure_return_type_hints: self.data.inlayHints_closureReturnTypeHints_enable,
             lifetime_elision_hints: match self.data.inlayHints_lifetimeElisionHints_enable {
                 LifetimeElisionDef::Always => ide::LifetimeElisionHints::Always,
                 LifetimeElisionDef::Never => ide::LifetimeElisionHints::Never,
                 LifetimeElisionDef::SkipTrivial => ide::LifetimeElisionHints::SkipTrivial,
             },
             hide_named_constructor_hints: self.data.inlayHints_typeHints_hideNamedConstructor,
-            hide_closure_initialization_hints: self
-                .data
-                .inlayHints_typeHints_hideClosureInitialization,
             reborrow_hints: match self.data.inlayHints_reborrowHints_enable {
                 ReborrowHintsDef::Always => ide::ReborrowHints::Always,
                 ReborrowHintsDef::Never => ide::ReborrowHints::Never,
@@ -1092,10 +1064,6 @@ impl Config {
         }
     }
 
-    pub fn snippet_cap(&self) -> bool {
-        self.experimental("snippetTextEdit")
-    }
-
     pub fn assist(&self) -> AssistConfig {
         AssistConfig {
             snippet_cap: SnippetCap::new(self.experimental("snippetTextEdit")),
@@ -1242,10 +1210,6 @@ impl Config {
             n => n,
         }
     }
-
-    pub fn typing_autoclose_angle(&self) -> bool {
-        self.data.typing_autoClosingAngleBrackets_enable
-    }
 }
 // Deserialization definitions
 
@@ -1346,7 +1310,6 @@ mod de_unit_v {
     named_unit_variant!(all);
     named_unit_variant!(skip_trivial);
     named_unit_variant!(mutable);
-    named_unit_variant!(with_block);
 }
 
 #[derive(Deserialize, Debug, Clone, Copy)]
@@ -1459,17 +1422,6 @@ enum LifetimeElisionDef {
     SkipTrivial,
 }
 
-#[derive(Deserialize, Debug, Clone)]
-#[serde(untagged)]
-enum ClosureReturnTypeHintsDef {
-    #[serde(deserialize_with = "true_or_always")]
-    Always,
-    #[serde(deserialize_with = "false_or_never")]
-    Never,
-    #[serde(deserialize_with = "de_unit_v::with_block")]
-    WithBlock,
-}
-
 #[derive(Deserialize, Debug, Clone)]
 #[serde(untagged)]
 enum ReborrowHintsDef {
@@ -1756,19 +1708,6 @@ fn field_props(field: &str, ty: &str, doc: &[&str], default: &str) -> serde_json
                 "Only show lifetime elision hints if a return type is involved."
             ]
         },
-        "ClosureReturnTypeHintsDef" => set! {
-            "type": "string",
-            "enum": [
-                "always",
-                "never",
-                "with_block"
-            ],
-            "enumDescriptions": [
-                "Always show type hints for return types of closures.",
-                "Never show type hints for return types of closures.",
-                "Only show type hints for return types of closures with blocks."
-            ]
-        },
         "ReborrowHintsDef" => set! {
             "type": "string",
             "enum": [
diff --git a/crates/rust-analyzer/src/diagnostics.rs b/crates/rust-analyzer/src/diagnostics.rs
index 202a01adf7..56b3afce98 100644
--- a/crates/rust-analyzer/src/diagnostics.rs
+++ b/crates/rust-analyzer/src/diagnostics.rs
@@ -40,11 +40,6 @@ impl DiagnosticCollection {
         self.changes.extend(self.check.drain().map(|(key, _value)| key))
     }
 
-    pub(crate) fn clear_native_for(&mut self, file_id: FileId) {
-        self.native.remove(&file_id);
-        self.changes.insert(file_id);
-    }
-
     pub(crate) fn add_check_diagnostic(
         &mut self,
         file_id: FileId,
diff --git a/crates/rust-analyzer/src/diagnostics/to_proto.rs b/crates/rust-analyzer/src/diagnostics/to_proto.rs
index aac8e9222d..02621f54df 100644
--- a/crates/rust-analyzer/src/diagnostics/to_proto.rs
+++ b/crates/rust-analyzer/src/diagnostics/to_proto.rs
@@ -3,13 +3,18 @@
 use std::collections::HashMap;
 
 use flycheck::{Applicability, DiagnosticLevel, DiagnosticSpan};
+use ide::TextRange;
 use itertools::Itertools;
 use stdx::format_to;
 use vfs::{AbsPath, AbsPathBuf};
 
 use crate::{
-    global_state::GlobalStateSnapshot, line_index::OffsetEncoding, lsp_ext,
-    to_proto::url_from_abs_path,
+    from_proto,
+    global_state::GlobalStateSnapshot,
+    line_index::OffsetEncoding,
+    lsp_ext,
+    to_proto::{self, url_from_abs_path},
+    Result,
 };
 
 use super::{DiagnosticsMapConfig, Fix};
@@ -65,16 +70,28 @@ fn location(
     let file_name = resolve_path(config, workspace_root, &span.file_name);
     let uri = url_from_abs_path(&file_name);
 
-    let range = {
+    let range = range(span, snap, &uri).unwrap_or_else(|_| {
         let offset_encoding = snap.config.offset_encoding();
         lsp_types::Range::new(
             position(&offset_encoding, span, span.line_start, span.column_start),
             position(&offset_encoding, span, span.line_end, span.column_end),
         )
-    };
+    });
     lsp_types::Location::new(uri, range)
 }
 
+fn range(
+    span: &DiagnosticSpan,
+    snap: &GlobalStateSnapshot,
+    uri: &lsp_types::Url,
+) -> Result<lsp_types::Range> {
+    let file_id = from_proto::file_id(snap, &uri)?;
+    let line_index = snap.file_line_index(file_id)?;
+    let range =
+        to_proto::range(&line_index, TextRange::new(span.byte_start.into(), span.byte_end.into()));
+    Ok(range)
+}
+
 fn position(
     offset_encoding: &OffsetEncoding,
     span: &DiagnosticSpan,
@@ -86,7 +103,7 @@ fn position(
     let mut true_column_offset = column_offset;
     if let Some(line) = span.text.get(line_index) {
         if line.text.chars().count() == line.text.len() {
-            // all one byte utf-8 char
+            // all utf-8
             return lsp_types::Position {
                 line: (line_offset as u32).saturating_sub(1),
                 character: (column_offset as u32).saturating_sub(1),
diff --git a/crates/rust-analyzer/src/global_state.rs b/crates/rust-analyzer/src/global_state.rs
index 4af60035a2..d2b4fac5dc 100644
--- a/crates/rust-analyzer/src/global_state.rs
+++ b/crates/rust-analyzer/src/global_state.rs
@@ -201,10 +201,6 @@ impl GlobalState {
                     }
                 }
 
-                if !file.exists() {
-                    self.diagnostics.clear_native_for(file.file_id);
-                }
-
                 let text = if file.exists() {
                     let bytes = vfs.file_contents(file.file_id).to_vec();
                     String::from_utf8(bytes).ok().and_then(|text| {
diff --git a/crates/rust-analyzer/src/handlers.rs b/crates/rust-analyzer/src/handlers.rs
index ff61081aa8..261c02816d 100644
--- a/crates/rust-analyzer/src/handlers.rs
+++ b/crates/rust-analyzer/src/handlers.rs
@@ -276,7 +276,7 @@ pub(crate) fn handle_on_enter(
 pub(crate) fn handle_on_type_formatting(
     snap: GlobalStateSnapshot,
     params: lsp_types::DocumentOnTypeFormattingParams,
-) -> Result<Option<Vec<lsp_ext::SnippetTextEdit>>> {
+) -> Result<Option<Vec<lsp_types::TextEdit>>> {
     let _p = profile::span("handle_on_type_formatting");
     let mut position = from_proto::file_position(&snap, params.text_document_position)?;
     let line_index = snap.file_line_index(position.file_id)?;
@@ -299,17 +299,16 @@ pub(crate) fn handle_on_type_formatting(
         return Ok(None);
     }
 
-    let edit =
-        snap.analysis.on_char_typed(position, char_typed, snap.config.typing_autoclose_angle())?;
+    let edit = snap.analysis.on_char_typed(position, char_typed)?;
     let edit = match edit {
         Some(it) => it,
         None => return Ok(None),
     };
 
     // This should be a single-file edit
-    let (_, text_edit) = edit.source_file_edits.into_iter().next().unwrap();
+    let (_, edit) = edit.source_file_edits.into_iter().next().unwrap();
 
-    let change = to_proto::snippet_text_edit_vec(&line_index, edit.is_snippet, text_edit);
+    let change = to_proto::text_edit_vec(&line_index, edit);
     Ok(Some(change))
 }
 
@@ -796,27 +795,27 @@ pub(crate) fn handle_completion(
     let _p = profile::span("handle_completion");
     let text_document_position = params.text_document_position.clone();
     let position = from_proto::file_position(&snap, params.text_document_position)?;
-    let completion_trigger_character =
-        params.context.and_then(|ctx| ctx.trigger_character).and_then(|s| s.chars().next());
-
-    if Some(':') == completion_trigger_character {
-        let source_file = snap.analysis.parse(position.file_id)?;
-        let left_token = source_file.syntax().token_at_offset(position.offset).left_biased();
-        let completion_triggered_after_single_colon = match left_token {
-            Some(left_token) => left_token.kind() == T![:],
-            None => true,
-        };
-        if completion_triggered_after_single_colon {
-            return Ok(None);
+    let completion_triggered_after_single_colon = {
+        let mut res = false;
+        if let Some(ctx) = params.context {
+            if ctx.trigger_character.as_deref() == Some(":") {
+                let source_file = snap.analysis.parse(position.file_id)?;
+                let left_token =
+                    source_file.syntax().token_at_offset(position.offset).left_biased();
+                match left_token {
+                    Some(left_token) => res = left_token.kind() == T![:],
+                    None => res = true,
+                }
+            }
         }
+        res
+    };
+    if completion_triggered_after_single_colon {
+        return Ok(None);
     }
 
     let completion_config = &snap.config.completion();
-    let items = match snap.analysis.completions(
-        completion_config,
-        position,
-        completion_trigger_character,
-    )? {
+    let items = match snap.analysis.completions(completion_config, position)? {
         None => return Ok(None),
         Some(items) => items,
     };
diff --git a/crates/rust-analyzer/src/integrated_benchmarks.rs b/crates/rust-analyzer/src/integrated_benchmarks.rs
index 47cdd8dfc7..5f110274b2 100644
--- a/crates/rust-analyzer/src/integrated_benchmarks.rs
+++ b/crates/rust-analyzer/src/integrated_benchmarks.rs
@@ -148,7 +148,7 @@ fn integrated_completion_benchmark() {
         };
         let position =
             FilePosition { file_id, offset: TextSize::try_from(completion_offset).unwrap() };
-        analysis.completions(&config, position, None).unwrap();
+        analysis.completions(&config, position).unwrap();
     }
 
     let completion_offset = {
@@ -185,7 +185,7 @@ fn integrated_completion_benchmark() {
         };
         let position =
             FilePosition { file_id, offset: TextSize::try_from(completion_offset).unwrap() };
-        analysis.completions(&config, position, None).unwrap();
+        analysis.completions(&config, position).unwrap();
     }
 }
 
diff --git a/crates/rust-analyzer/src/lsp_ext.rs b/crates/rust-analyzer/src/lsp_ext.rs
index 5f0e108624..c1b230bd9d 100644
--- a/crates/rust-analyzer/src/lsp_ext.rs
+++ b/crates/rust-analyzer/src/lsp_ext.rs
@@ -4,8 +4,8 @@ use std::{collections::HashMap, path::PathBuf};
 
 use lsp_types::request::Request;
 use lsp_types::{
-    notification::Notification, CodeActionKind, DocumentOnTypeFormattingParams,
-    PartialResultParams, Position, Range, TextDocumentIdentifier, WorkDoneProgressParams,
+    notification::Notification, CodeActionKind, PartialResultParams, Position, Range,
+    TextDocumentIdentifier, WorkDoneProgressParams,
 };
 use serde::{Deserialize, Serialize};
 
@@ -512,19 +512,6 @@ pub enum WorkspaceSymbolSearchKind {
     AllSymbols,
 }
 
-/// The document on type formatting request is sent from the client to
-/// the server to format parts of the document during typing.  This is
-/// almost same as lsp_types::request::OnTypeFormatting, but the
-/// result has SnippetTextEdit in it instead of TextEdit.
-#[derive(Debug)]
-pub enum OnTypeFormatting {}
-
-impl Request for OnTypeFormatting {
-    type Params = DocumentOnTypeFormattingParams;
-    type Result = Option<Vec<SnippetTextEdit>>;
-    const METHOD: &'static str = "textDocument/onTypeFormatting";
-}
-
 #[derive(Debug, Serialize, Deserialize)]
 pub struct CompletionResolveData {
     pub position: lsp_types::TextDocumentPositionParams,
diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs
index 3c87968743..b5ac55e60d 100644
--- a/crates/rust-analyzer/src/main_loop.rs
+++ b/crates/rust-analyzer/src/main_loop.rs
@@ -605,7 +605,7 @@ impl GlobalState {
             .on::<lsp_ext::OpenCargoToml>(handlers::handle_open_cargo_toml)
             .on::<lsp_ext::MoveItem>(handlers::handle_move_item)
             .on::<lsp_ext::WorkspaceSymbol>(handlers::handle_workspace_symbol)
-            .on::<lsp_ext::OnTypeFormatting>(handlers::handle_on_type_formatting)
+            .on::<lsp_types::request::OnTypeFormatting>(handlers::handle_on_type_formatting)
             .on::<lsp_types::request::DocumentSymbolRequest>(handlers::handle_document_symbol)
             .on::<lsp_types::request::GotoDefinition>(handlers::handle_goto_definition)
             .on::<lsp_types::request::GotoDeclaration>(handlers::handle_goto_declaration)
diff --git a/crates/rust-analyzer/src/reload.rs b/crates/rust-analyzer/src/reload.rs
index efa9afcbb4..c2a521bbf5 100644
--- a/crates/rust-analyzer/src/reload.rs
+++ b/crates/rust-analyzer/src/reload.rs
@@ -1,17 +1,4 @@
-//! Project loading & configuration updates.
-//!
-//! This is quite tricky. The main problem is time and changes -- there's no
-//! fixed "project" rust-analyzer is working with, "current project" is itself
-//! mutable state. For example, when the user edits `Cargo.toml` by adding a new
-//! dependency, project model changes. What's more, switching project model is
-//! not instantaneous -- it takes time to run `cargo metadata` and (for proc
-//! macros) `cargo check`.
-//!
-//! The main guiding principle here is, as elsewhere in rust-analyzer,
-//! robustness. We try not to assume that the project model exists or is
-//! correct. Instead, we try to provide a best-effort service. Even if the
-//! project is currently loading and we don't have a full project model, we
-//! still want to respond to various  requests.
+//! Project loading & configuration updates
 use std::{mem, sync::Arc};
 
 use flycheck::{FlycheckConfig, FlycheckHandle};
@@ -332,13 +319,8 @@ impl GlobalState {
         // Create crate graph from all the workspaces
         let crate_graph = {
             let proc_macro_client = self.proc_macro_client.as_ref();
-            let dummy_replacements = self.config.dummy_replacements();
-            let mut load_proc_macro = move |crate_name: &str, path: &AbsPath| {
-                load_proc_macro(
-                    proc_macro_client,
-                    path,
-                    dummy_replacements.get(crate_name).map(|v| &**v).unwrap_or_default(),
-                )
+            let mut load_proc_macro = move |path: &AbsPath, dummy_replace: &_| {
+                load_proc_macro(proc_macro_client, path, dummy_replace)
             };
 
             let vfs = &mut self.vfs.write().0;
@@ -360,7 +342,11 @@ impl GlobalState {
 
             let mut crate_graph = CrateGraph::default();
             for ws in self.workspaces.iter() {
-                crate_graph.extend(ws.to_crate_graph(&mut load_proc_macro, &mut load));
+                crate_graph.extend(ws.to_crate_graph(
+                    self.config.dummy_replacements(),
+                    &mut load_proc_macro,
+                    &mut load,
+                ));
             }
             crate_graph
         };
@@ -417,7 +403,6 @@ impl GlobalState {
             Some(it) => it,
             None => {
                 self.flycheck = Vec::new();
-                self.diagnostics.clear_check();
                 return;
             }
         };
diff --git a/crates/syntax/src/ast/node_ext.rs b/crates/syntax/src/ast/node_ext.rs
index 2a41d0a701..f2153ca921 100644
--- a/crates/syntax/src/ast/node_ext.rs
+++ b/crates/syntax/src/ast/node_ext.rs
@@ -432,13 +432,6 @@ impl NameLike {
             _ => None,
         }
     }
-    pub fn text(&self) -> TokenText {
-        match self {
-            NameLike::NameRef(name_ref) => name_ref.text(),
-            NameLike::Name(name) => name.text(),
-            NameLike::Lifetime(lifetime) => lifetime.text(),
-        }
-    }
 }
 
 impl ast::AstNode for NameLike {
@@ -510,10 +503,6 @@ impl ast::RecordPatField {
         }
     }
 
-    pub fn parent_record_pat(&self) -> ast::RecordPat {
-        self.syntax().ancestors().find_map(ast::RecordPat::cast).unwrap()
-    }
-
     /// Deals with field init shorthand
     pub fn field_name(&self) -> Option<NameOrNameRef> {
         if let Some(name_ref) = self.name_ref() {
diff --git a/crates/syntax/src/ast/token_ext.rs b/crates/syntax/src/ast/token_ext.rs
index 28976d837b..4b6dc236b5 100644
--- a/crates/syntax/src/ast/token_ext.rs
+++ b/crates/syntax/src/ast/token_ext.rs
@@ -319,49 +319,17 @@ impl ast::IntNumber {
             Some(suffix)
         }
     }
-
-    pub fn float_value(&self) -> Option<f64> {
-        let (_, text, _) = self.split_into_parts();
-        text.parse::<f64>().ok()
-    }
 }
 
 impl ast::FloatNumber {
-    pub fn split_into_parts(&self) -> (&str, &str) {
+    pub fn suffix(&self) -> Option<&str> {
         let text = self.text();
-        let mut float_text = self.text();
-        let mut suffix = "";
         let mut indices = text.char_indices();
-        if let Some((mut suffix_start, c)) = indices.by_ref().find(|(_, c)| c.is_ascii_alphabetic())
-        {
-            if c == 'e' || c == 'E' {
-                if let Some(suffix_start_tuple) = indices.find(|(_, c)| c.is_ascii_alphabetic()) {
-                    suffix_start = suffix_start_tuple.0;
-
-                    float_text = &text[..suffix_start];
-                    suffix = &text[suffix_start..];
-                }
-            } else {
-                float_text = &text[..suffix_start];
-                suffix = &text[suffix_start..];
-            }
+        let (mut suffix_start, c) = indices.by_ref().find(|(_, c)| c.is_ascii_alphabetic())?;
+        if c == 'e' || c == 'E' {
+            suffix_start = indices.find(|(_, c)| c.is_ascii_alphabetic())?.0;
         }
-
-        (float_text, suffix)
-    }
-
-    pub fn suffix(&self) -> Option<&str> {
-        let (_, suffix) = self.split_into_parts();
-        if suffix.is_empty() {
-            None
-        } else {
-            Some(suffix)
-        }
-    }
-
-    pub fn value(&self) -> Option<f64> {
-        let (text, _) = self.split_into_parts();
-        text.parse::<f64>().ok()
+        Some(&text[suffix_start..])
     }
 }
 
diff --git a/crates/syntax/src/display.rs b/crates/syntax/src/display.rs
new file mode 100644
index 0000000000..f7322656a3
--- /dev/null
+++ b/crates/syntax/src/display.rs
@@ -0,0 +1,51 @@
+//! This module contains utilities for rendering syntax nodes into a string representing their signature.
+
+use crate::ast::{self, HasGenericParams, HasName};
+
+use ast::HasVisibility;
+use stdx::format_to;
+
+pub fn function_declaration(node: &ast::Fn) -> String {
+    let mut buf = String::new();
+    if let Some(vis) = node.visibility() {
+        format_to!(buf, "{} ", vis);
+    }
+    if node.async_token().is_some() {
+        format_to!(buf, "async ");
+    }
+    if node.const_token().is_some() {
+        format_to!(buf, "const ");
+    }
+    if node.unsafe_token().is_some() {
+        format_to!(buf, "unsafe ");
+    }
+    if let Some(abi) = node.abi() {
+        // Keyword `extern` is included in the string.
+        format_to!(buf, "{} ", abi);
+    }
+    if let Some(name) = node.name() {
+        format_to!(buf, "fn {}", name);
+    }
+    if let Some(type_params) = node.generic_param_list() {
+        format_to!(buf, "{}", type_params);
+    }
+    if let Some(param_list) = node.param_list() {
+        let params: Vec<String> = param_list
+            .self_param()
+            .into_iter()
+            .map(|self_param| self_param.to_string())
+            .chain(param_list.params().map(|param| param.to_string()))
+            .collect();
+        // Useful to inline parameters
+        format_to!(buf, "({})", params.join(", "));
+    }
+    if let Some(ret_type) = node.ret_type() {
+        if ret_type.ty().is_some() {
+            format_to!(buf, " {}", ret_type);
+        }
+    }
+    if let Some(where_clause) = node.where_clause() {
+        format_to!(buf, "\n{}", where_clause);
+    }
+    buf
+}
diff --git a/crates/syntax/src/lib.rs b/crates/syntax/src/lib.rs
index e0309756b8..e30f6cd79c 100644
--- a/crates/syntax/src/lib.rs
+++ b/crates/syntax/src/lib.rs
@@ -33,6 +33,7 @@ mod token_text;
 #[cfg(test)]
 mod tests;
 
+pub mod display;
 pub mod algo;
 pub mod ast;
 #[doc(hidden)]
diff --git a/crates/vfs-notify/Cargo.toml b/crates/vfs-notify/Cargo.toml
index d9ac83af59..a13a85f92f 100644
--- a/crates/vfs-notify/Cargo.toml
+++ b/crates/vfs-notify/Cargo.toml
@@ -14,7 +14,7 @@ tracing = "0.1.32"
 jod-thread = "0.1.2"
 walkdir = "2.3.2"
 crossbeam-channel = "0.5.4"
-notify = "=5.0.0-pre.15"
+notify = "=5.0.0-pre.14"
 
 vfs = { path = "../vfs", version = "0.0.0" }
 paths = { path = "../paths", version = "0.0.0" }
diff --git a/docs/dev/lsp-extensions.md b/docs/dev/lsp-extensions.md
index 983d8e1ac0..875561608d 100644
--- a/docs/dev/lsp-extensions.md
+++ b/docs/dev/lsp-extensions.md
@@ -1,5 +1,5 @@
 <!---
-lsp_ext.rs hash: 2a188defec26cc7c
+lsp_ext.rs hash: 44e8238e4fbd4128
 
 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:
@@ -47,7 +47,7 @@ If a language client does not know about `rust-analyzer`'s configuration options
 
 **Experimental Client Capability:** `{ "snippetTextEdit": boolean }`
 
-If this capability is set, `WorkspaceEdit`s returned from `codeAction` requests and `TextEdit`s returned from `textDocument/onTypeFormatting` requests might contain `SnippetTextEdit`s instead of usual `TextEdit`s:
+If this capability is set, `WorkspaceEdit`s returned from `codeAction` requests might contain `SnippetTextEdit`s instead of usual `TextEdit`s:
 
 ```typescript
 interface SnippetTextEdit extends TextEdit {
@@ -63,7 +63,7 @@ export interface TextDocumentEdit {
 }
 ```
 
-When applying such code action or text edit, the editor should insert snippet, with tab stops and placeholder.
+When applying such code action, the editor should insert snippet, with tab stops and placeholder.
 At the moment, rust-analyzer guarantees that only a single edit will have `InsertTextFormat.Snippet`.
 
 ### Example
diff --git a/docs/dev/style.md b/docs/dev/style.md
index 82b6c749e4..13da88044c 100644
--- a/docs/dev/style.md
+++ b/docs/dev/style.md
@@ -69,11 +69,11 @@ After you are happy with the state of the code, please use [interactive rebase](
 Avoid @mentioning people in commit messages and pull request descriptions(they are added to commit message by bors).
 Such messages create a lot of duplicate notification traffic during rebases.
 
-If possible, write Pull Request titles and descriptions from the user's perspective:
+If possible, write commit messages from user's perspective:
 
 ```
 # GOOD
-Make goto definition work inside macros
+Goto definition works inside macros
 
 # BAD
 Use original span for FileId
diff --git a/docs/user/generated_config.adoc b/docs/user/generated_config.adoc
index 981132f9c4..d8585ffb1d 100644
--- a/docs/user/generated_config.adoc
+++ b/docs/user/generated_config.adoc
@@ -11,7 +11,7 @@ Warm up caches on project load.
 [[rust-analyzer.cachePriming.numThreads]]rust-analyzer.cachePriming.numThreads (default: `0`)::
 +
 --
-How many worker threads to handle priming caches. The default `0` means to pick automatically.
+How many worker threads to to handle priming caches. The default `0` means to pick automatically.
 --
 [[rust-analyzer.cargo.autoreload]]rust-analyzer.cargo.autoreload (default: `true`)::
 +
@@ -366,10 +366,10 @@ Whether to show inlay hints after a closing `}` to indicate what item it belongs
 Minimum number of lines required before the `}` until the hint is shown (set to 0 or 1
 to always show them).
 --
-[[rust-analyzer.inlayHints.closureReturnTypeHints.enable]]rust-analyzer.inlayHints.closureReturnTypeHints.enable (default: `"never"`)::
+[[rust-analyzer.inlayHints.closureReturnTypeHints.enable]]rust-analyzer.inlayHints.closureReturnTypeHints.enable (default: `false`)::
 +
 --
-Whether to show inlay type hints for return types of closures.
+Whether to show inlay type hints for return types of closures with blocks.
 --
 [[rust-analyzer.inlayHints.lifetimeElisionHints.enable]]rust-analyzer.inlayHints.lifetimeElisionHints.enable (default: `"never"`)::
 +
@@ -407,12 +407,6 @@ Whether to render leading colons for type hints, and trailing colons for paramet
 --
 Whether to show inlay type hints for variables.
 --
-[[rust-analyzer.inlayHints.typeHints.hideClosureInitialization]]rust-analyzer.inlayHints.typeHints.hideClosureInitialization (default: `false`)::
-+
---
-Whether to hide inlay type hints for `let` statements that initialize to a closure.
-Only applies to closures with blocks, same as `#rust-analyzer.inlayHints.closureReturnTypeHints.enable#`.
---
 [[rust-analyzer.inlayHints.typeHints.hideNamedConstructor]]rust-analyzer.inlayHints.typeHints.hideNamedConstructor (default: `false`)::
 +
 --
@@ -593,11 +587,6 @@ Show full signature of the callable. Only shows parameters if disabled.
 --
 Show documentation.
 --
-[[rust-analyzer.typing.autoClosingAngleBrackets.enable]]rust-analyzer.typing.autoClosingAngleBrackets.enable (default: `false`)::
-+
---
-Whether to insert closing angle brackets when typing an opening angle bracket of a generic argument list.
---
 [[rust-analyzer.workspace.symbol.search.kind]]rust-analyzer.workspace.symbol.search.kind (default: `"only_types"`)::
 +
 --
diff --git a/docs/user/manual.adoc b/docs/user/manual.adoc
index c1496998ea..e8520c66f4 100644
--- a/docs/user/manual.adoc
+++ b/docs/user/manual.adoc
@@ -763,7 +763,7 @@ Most themes doesn't support styling unsafe operations differently yet. You can f
    "editor.semanticTokenColorCustomizations": {
          "rules": {
              "operator.unsafe": "#ff6600",
-             "function.unsafe": "#ff6600",
+             "function.unsafe": "#ff6600"
              "method.unsafe": "#ff6600"
          }
     },
diff --git a/editors/code/package.json b/editors/code/package.json
index 03ec18a568..02899b6d17 100644
--- a/editors/code/package.json
+++ b/editors/code/package.json
@@ -308,12 +308,6 @@
                         "null",
                         "object"
                     ],
-                    "additionalProperties": {
-                        "type": [
-                            "string",
-                            "number"
-                        ]
-                    },
                     "default": null,
                     "markdownDescription": "Extra environment variables that will be passed to the rust-analyzer executable. Useful for passing e.g. `RA_LOG` for debugging."
                 },
@@ -394,7 +388,7 @@
                     "type": "boolean"
                 },
                 "rust-analyzer.cachePriming.numThreads": {
-                    "markdownDescription": "How many worker threads to handle priming caches. The default `0` means to pick automatically.",
+                    "markdownDescription": "How many worker threads to to handle priming caches. The default `0` means to pick automatically.",
                     "default": 0,
                     "type": "number",
                     "minimum": 0,
@@ -811,19 +805,9 @@
                     "minimum": 0
                 },
                 "rust-analyzer.inlayHints.closureReturnTypeHints.enable": {
-                    "markdownDescription": "Whether to show inlay type hints for return types of closures.",
-                    "default": "never",
-                    "type": "string",
-                    "enum": [
-                        "always",
-                        "never",
-                        "with_block"
-                    ],
-                    "enumDescriptions": [
-                        "Always show type hints for return types of closures.",
-                        "Never show type hints for return types of closures.",
-                        "Only show type hints for return types of closures with blocks."
-                    ]
+                    "markdownDescription": "Whether to show inlay type hints for return types of closures with blocks.",
+                    "default": false,
+                    "type": "boolean"
                 },
                 "rust-analyzer.inlayHints.lifetimeElisionHints.enable": {
                     "markdownDescription": "Whether to show inlay type hints for elided lifetimes in function signatures.",
@@ -884,11 +868,6 @@
                     "default": true,
                     "type": "boolean"
                 },
-                "rust-analyzer.inlayHints.typeHints.hideClosureInitialization": {
-                    "markdownDescription": "Whether to hide inlay type hints for `let` statements that initialize to a closure.\nOnly applies to closures with blocks, same as `#rust-analyzer.inlayHints.closureReturnTypeHints.enable#`.",
-                    "default": false,
-                    "type": "boolean"
-                },
                 "rust-analyzer.inlayHints.typeHints.hideNamedConstructor": {
                     "markdownDescription": "Whether to hide inlay type hints for constructors.",
                     "default": false,
@@ -1078,11 +1057,6 @@
                     "default": true,
                     "type": "boolean"
                 },
-                "rust-analyzer.typing.autoClosingAngleBrackets.enable": {
-                    "markdownDescription": "Whether to insert closing angle brackets when typing an opening angle bracket of a generic argument list.",
-                    "default": false,
-                    "type": "boolean"
-                },
                 "rust-analyzer.workspace.symbol.search.kind": {
                     "markdownDescription": "Workspace symbol search kind.",
                     "default": "only_types",
diff --git a/editors/code/src/commands.ts b/editors/code/src/commands.ts
index bb4d2151ad..ee8fa2eb51 100644
--- a/editors/code/src/commands.ts
+++ b/editors/code/src/commands.ts
@@ -125,9 +125,8 @@ export function joinLines(ctx: Ctx): Cmd {
                 editor.document
             ),
         });
-        const textEdits = await client.protocol2CodeConverter.asTextEdits(items);
-        await editor.edit((builder) => {
-            textEdits.forEach((edit: any) => {
+        await editor.edit(async (builder) => {
+            (await client.protocol2CodeConverter.asTextEdits(items)).forEach((edit: any) => {
                 builder.replace(edit.range, edit.newText);
             });
         });
diff --git a/editors/code/src/config.ts b/editors/code/src/config.ts
index d07e47c8de..592ebe0ce3 100644
--- a/editors/code/src/config.ts
+++ b/editors/code/src/config.ts
@@ -100,12 +100,8 @@ export class Config {
     get serverPath() {
         return this.get<null | string>("server.path") ?? this.get<null | string>("serverPath");
     }
-    get serverExtraEnv(): Env {
-        const extraEnv =
-            this.get<{ [key: string]: string | number } | null>("server.extraEnv") ?? {};
-        return Object.fromEntries(
-            Object.entries(extraEnv).map(([k, v]) => [k, typeof v !== "string" ? v.toString() : v])
-        );
+    get serverExtraEnv() {
+        return this.get<Env | null>("server.extraEnv") ?? {};
     }
     get traceExtension() {
         return this.get<boolean>("trace.extension");
diff --git a/editors/code/src/ctx.ts b/editors/code/src/ctx.ts
index b03424dbb3..fb2268f89f 100644
--- a/editors/code/src/ctx.ts
+++ b/editors/code/src/ctx.ts
@@ -86,19 +86,13 @@ export class Ctx {
             case "warning":
                 this.statusBar.tooltip += "\nClick to reload.";
                 this.statusBar.command = "rust-analyzer.reloadWorkspace";
-                this.statusBar.color = new vscode.ThemeColor("statusBarItem.warningForeground");
-                this.statusBar.backgroundColor = new vscode.ThemeColor(
-                    "statusBarItem.warningBackground"
-                );
+                this.statusBar.color = new vscode.ThemeColor("notificationsWarningIcon.foreground");
                 icon = "$(warning) ";
                 break;
             case "error":
                 this.statusBar.tooltip += "\nClick to reload.";
                 this.statusBar.command = "rust-analyzer.reloadWorkspace";
-                this.statusBar.color = new vscode.ThemeColor("statusBarItem.errorForeground");
-                this.statusBar.backgroundColor = new vscode.ThemeColor(
-                    "statusBarItem.errorBackground"
-                );
+                this.statusBar.color = new vscode.ThemeColor("notificationsErrorIcon.foreground");
                 icon = "$(error) ";
                 break;
         }
diff --git a/editors/code/src/run.ts b/editors/code/src/run.ts
index 22e5eda682..b3dff3db5d 100644
--- a/editors/code/src/run.ts
+++ b/editors/code/src/run.ts
@@ -8,7 +8,7 @@ import { makeDebugConfig } from "./debug";
 import { Config, RunnableEnvCfg } from "./config";
 
 const quickPickButtons = [
-    { iconPath: new vscode.ThemeIcon("save"), tooltip: "Save as a launch.json configuration." },
+    { iconPath: new vscode.ThemeIcon("save"), tooltip: "Save as a launch.json configurtation." },
 ];
 
 export async function selectRunnable(
diff --git a/editors/code/src/tasks.ts b/editors/code/src/tasks.ts
index e6239deeb2..8aa6bcee19 100644
--- a/editors/code/src/tasks.ts
+++ b/editors/code/src/tasks.ts
@@ -32,7 +32,6 @@ class CargoTaskProvider implements vscode.TaskProvider {
         const defs = [
             { command: "build", group: vscode.TaskGroup.Build },
             { command: "check", group: vscode.TaskGroup.Build },
-            { command: "clippy", group: vscode.TaskGroup.Build },
             { command: "test", group: vscode.TaskGroup.Test },
             { command: "clean", group: vscode.TaskGroup.Clean },
             { command: "run", group: undefined },


Test patch:
diff --git a/crates/hir-def/src/macro_expansion_tests/builtin_derive_macro.rs b/crates/hir-def/src/macro_expansion_tests/builtin_derive_macro.rs
index 6819e9114a..8ee33101e4 100644
--- a/crates/hir-def/src/macro_expansion_tests/builtin_derive_macro.rs
+++ b/crates/hir-def/src/macro_expansion_tests/builtin_derive_macro.rs
@@ -25,7 +25,6 @@ fn test_copy_expand_in_core() {
     cov_mark::check!(test_copy_expand_in_core);
     check(
         r#"
-//- /lib.rs crate:core
 #[rustc_builtin_macro]
 macro derive {}
 #[rustc_builtin_macro]
diff --git a/crates/hir-ty/src/tests/patterns.rs b/crates/hir-ty/src/tests/patterns.rs
index 399553356b..acdd8f50ef 100644
--- a/crates/hir-ty/src/tests/patterns.rs
+++ b/crates/hir-ty/src/tests/patterns.rs
@@ -969,23 +969,3 @@ fn main() {
     "#,
     );
 }
-
-#[test]
-fn tuple_wildcard() {
-    check_types(
-        r#"
-fn main() {
-    enum Option<T> {Some(T), None}
-    use Option::*;
-
-    let mut x = None;
-    x;
-  //^ Option<(i32, i32)>
-
-    if let Some((_, _a)) = x {}
-
-    x = Some((1, 2));
-}
-        "#,
-    );
-}
diff --git a/crates/hir-ty/src/tests/regression.rs b/crates/hir-ty/src/tests/regression.rs
index 93f765f703..ef27667ffa 100644
--- a/crates/hir-ty/src/tests/regression.rs
+++ b/crates/hir-ty/src/tests/regression.rs
@@ -1620,30 +1620,3 @@ pub trait Destruct {}
 "#,
     );
 }
-
-#[test]
-fn tuple_struct_pattern_with_unmatched_args_crash() {
-    check_infer(
-        r#"
-struct S(usize);
-fn main() {
-    let S(.., a, b) = S(1);
-    let (.., a, b) = (1,);
-}
-        "#,
-        expect![[r#"
-        27..85 '{     ...1,); }': ()
-        37..48 'S(.., a, b)': S
-        43..44 'a': usize
-        46..47 'b': {unknown}
-        51..52 'S': S(usize) -> S
-        51..55 'S(1)': S
-        53..54 '1': usize
-        65..75 '(.., a, b)': (i32, {unknown})
-        70..71 'a': i32
-        73..74 'b': {unknown}
-        78..82 '(1,)': (i32,)
-        79..80 '1': i32
-        "#]],
-    );
-}
diff --git a/crates/ide-assists/src/tests.rs b/crates/ide-assists/src/tests.rs
index a8d5f85ba6..ad2066a2ac 100644
--- a/crates/ide-assists/src/tests.rs
+++ b/crates/ide-assists/src/tests.rs
@@ -251,6 +251,7 @@ pub fn test_some_range(a: int) -> bool {
         Extract into variable
         Extract into function
         Replace if let with match
+        Add attribute
     "#]]
     .assert_eq(&expected);
 }
diff --git a/crates/ide-assists/src/tests/generated.rs b/crates/ide-assists/src/tests/generated.rs
index 2d57101409..69d754d4f7 100644
--- a/crates/ide-assists/src/tests/generated.rs
+++ b/crates/ide-assists/src/tests/generated.rs
@@ -2,6 +2,26 @@
 
 use super::check_doc_test;
 
+#[test]
+fn doctest_add_attribute() {
+    check_doc_test(
+        "add_derive",
+        r#####"
+struct Point {
+    x: u32,
+    y: u32,$0
+}
+"#####,
+        r#####"
+#[derive($0)]
+struct Point {
+    x: u32,
+    y: u32,
+}
+"#####,
+    )
+}
+
 #[test]
 fn doctest_add_explicit_type() {
     check_doc_test(
@@ -842,26 +862,6 @@ impl core::ops::Deref for B {
     )
 }
 
-#[test]
-fn doctest_generate_derive() {
-    check_doc_test(
-        "generate_derive",
-        r#####"
-struct Point {
-    x: u32,
-    y: u32,$0
-}
-"#####,
-        r#####"
-#[derive($0)]
-struct Point {
-    x: u32,
-    y: u32,
-}
-"#####,
-    )
-}
-
 #[test]
 fn doctest_generate_doc_example() {
     check_doc_test(
@@ -1006,32 +1006,6 @@ impl Value {
     )
 }
 
-#[test]
-fn doctest_generate_enum_variant() {
-    check_doc_test(
-        "generate_enum_variant",
-        r#####"
-enum Countries {
-    Ghana,
-}
-
-fn main() {
-    let country = Countries::Lesotho$0;
-}
-"#####,
-        r#####"
-enum Countries {
-    Ghana,
-    Lesotho,
-}
-
-fn main() {
-    let country = Countries::Lesotho;
-}
-"#####,
-    )
-}
-
 #[test]
 fn doctest_generate_from_impl_for_enum() {
     check_doc_test(
diff --git a/crates/ide-assists/src/tests/sourcegen.rs b/crates/ide-assists/src/tests/sourcegen.rs
index d45e54186b..577bc0894e 100644
--- a/crates/ide-assists/src/tests/sourcegen.rs
+++ b/crates/ide-assists/src/tests/sourcegen.rs
@@ -31,7 +31,7 @@ r#####"
 }}
 "######,
                     &test_id,
-                    &assist.id,
+                    &section.assist_id,
                     reveal_hash_comments(&section.before),
                     reveal_hash_comments(&section.after)
                 );
@@ -61,6 +61,7 @@ r#####"
 }
 #[derive(Debug)]
 struct Section {
+    assist_id: String,
     doc: String,
     before: String,
     after: String,
@@ -111,11 +112,13 @@ impl Assist {
 
                     let before = take_until(lines.by_ref(), "```");
 
-                    assert_eq!(lines.next().unwrap().as_str(), "->");
+                    let arrow = lines.next().unwrap();
+                    assert!(arrow.starts_with("->"));
+                    let id = if arrow[2..].is_empty() { &assist.id } else { &arrow[2..] };
                     assert_eq!(lines.next().unwrap().as_str(), "```");
                     let after = take_until(lines.by_ref(), "```");
 
-                    assist.sections.push(Section { doc, before, after });
+                    assist.sections.push(Section { assist_id: id.to_string(), doc, before, after });
                 }
 
                 acc.push(assist)
diff --git a/crates/ide-completion/src/tests.rs b/crates/ide-completion/src/tests.rs
index d30ff77bab..742368ce81 100644
--- a/crates/ide-completion/src/tests.rs
+++ b/crates/ide-completion/src/tests.rs
@@ -79,28 +79,20 @@ pub(crate) const TEST_CONFIG: CompletionConfig = CompletionConfig {
 };
 
 pub(crate) fn completion_list(ra_fixture: &str) -> String {
-    completion_list_with_config(TEST_CONFIG, ra_fixture, true, None)
+    completion_list_with_config(TEST_CONFIG, ra_fixture, true)
 }
 
 pub(crate) fn completion_list_no_kw(ra_fixture: &str) -> String {
-    completion_list_with_config(TEST_CONFIG, ra_fixture, false, None)
-}
-
-pub(crate) fn completion_list_with_trigger_character(
-    ra_fixture: &str,
-    trigger_character: Option<char>,
-) -> String {
-    completion_list_with_config(TEST_CONFIG, ra_fixture, true, trigger_character)
+    completion_list_with_config(TEST_CONFIG, ra_fixture, false)
 }
 
 fn completion_list_with_config(
     config: CompletionConfig,
     ra_fixture: &str,
     include_keywords: bool,
-    trigger_character: Option<char>,
 ) -> String {
     // filter out all but one builtintype completion for smaller test outputs
-    let items = get_all_items(config, ra_fixture, trigger_character);
+    let items = get_all_items(config, ra_fixture);
     let mut bt_seen = false;
     let items = items
         .into_iter()
@@ -134,7 +126,7 @@ pub(crate) fn do_completion_with_config(
     code: &str,
     kind: CompletionItemKind,
 ) -> Vec<CompletionItem> {
-    get_all_items(config, code, None)
+    get_all_items(config, code)
         .into_iter()
         .filter(|c| c.kind() == kind)
         .sorted_by(|l, r| l.label().cmp(r.label()))
@@ -181,7 +173,7 @@ pub(crate) fn check_edit_with_config(
     let ra_fixture_after = trim_indent(ra_fixture_after);
     let (db, position) = position(ra_fixture_before);
     let completions: Vec<CompletionItem> =
-        crate::completions(&db, &config, position, None).unwrap().into();
+        crate::completions(&db, &config, position).unwrap().into();
     let (completion,) = completions
         .iter()
         .filter(|it| it.lookup() == what)
@@ -222,14 +214,9 @@ pub(crate) fn check_pattern_is_applicable(code: &str, check: impl FnOnce(SyntaxE
     assert!(check(NodeOrToken::Token(token)));
 }
 
-pub(crate) fn get_all_items(
-    config: CompletionConfig,
-    code: &str,
-    trigger_character: Option<char>,
-) -> Vec<CompletionItem> {
+pub(crate) fn get_all_items(config: CompletionConfig, code: &str) -> Vec<CompletionItem> {
     let (db, position) = position(code);
-    let res = crate::completions(&db, &config, position, trigger_character)
-        .map_or_else(Vec::default, Into::into);
+    let res = crate::completions(&db, &config, position).map_or_else(Vec::default, Into::into);
     // validate
     res.iter().for_each(|it| {
         let sr = it.source_range();
diff --git a/crates/ide-completion/src/tests/fn_param.rs b/crates/ide-completion/src/tests/fn_param.rs
index f5a5b5bae6..f8e145c747 100644
--- a/crates/ide-completion/src/tests/fn_param.rs
+++ b/crates/ide-completion/src/tests/fn_param.rs
@@ -1,17 +1,12 @@
 use expect_test::{expect, Expect};
 
-use crate::tests::{completion_list, completion_list_with_trigger_character};
+use crate::tests::completion_list;
 
 fn check(ra_fixture: &str, expect: Expect) {
     let actual = completion_list(ra_fixture);
     expect.assert_eq(&actual);
 }
 
-fn check_with_trigger_character(ra_fixture: &str, trigger_character: char, expect: Expect) {
-    let actual = completion_list_with_trigger_character(ra_fixture, Some(trigger_character));
-    expect.assert_eq(&actual)
-}
-
 #[test]
 fn only_param() {
     check(
@@ -118,17 +113,6 @@ fn outer(text: &str) {
     )
 }
 
-#[test]
-fn trigger_by_l_paren() {
-    check_with_trigger_character(
-        r#"
-fn foo($0)
-"#,
-        '(',
-        expect![[]],
-    )
-}
-
 #[test]
 fn shows_non_ident_pat_param() {
     check(
diff --git a/crates/ide-completion/src/tests/item.rs b/crates/ide-completion/src/tests/item.rs
index 537c9a7fa2..e4b70f97e3 100644
--- a/crates/ide-completion/src/tests/item.rs
+++ b/crates/ide-completion/src/tests/item.rs
@@ -92,7 +92,10 @@ fn after_struct_name() {
     check(
         r"struct Struct $0",
         expect![[r#"
+            ma makro!(…)           macro_rules! makro
+            md module
             kw const
+            kw crate::
             kw enum
             kw extern
             kw fn
@@ -101,13 +104,18 @@ fn after_struct_name() {
             kw pub
             kw pub(crate)
             kw pub(super)
+            kw self::
             kw static
             kw struct
+            kw super::
             kw trait
             kw type
             kw union
             kw unsafe
             kw use
+            sn macro_rules
+            sn tfn (Test function)
+            sn tmod (Test module)
         "#]],
     );
 }
@@ -118,7 +126,10 @@ fn after_fn_name() {
     check(
         r"fn func() $0",
         expect![[r#"
+            ma makro!(…)           macro_rules! makro
+            md module
             kw const
+            kw crate::
             kw enum
             kw extern
             kw fn
@@ -127,13 +138,18 @@ fn after_fn_name() {
             kw pub
             kw pub(crate)
             kw pub(super)
+            kw self::
             kw static
             kw struct
+            kw super::
             kw trait
             kw type
             kw union
             kw unsafe
             kw use
+            sn macro_rules
+            sn tfn (Test function)
+            sn tmod (Test module)
         "#]],
     );
 }
diff --git a/crates/ide-completion/src/tests/item_list.rs b/crates/ide-completion/src/tests/item_list.rs
index d03a4fd5cd..f320812936 100644
--- a/crates/ide-completion/src/tests/item_list.rs
+++ b/crates/ide-completion/src/tests/item_list.rs
@@ -78,10 +78,7 @@ fn in_item_list_after_attr() {
     check(
         r#"#[attr] $0"#,
         expect![[r#"
-            ma makro!(…)           macro_rules! makro
-            md module
             kw const
-            kw crate::
             kw enum
             kw extern
             kw fn
@@ -90,10 +87,8 @@ fn in_item_list_after_attr() {
             kw pub
             kw pub(crate)
             kw pub(super)
-            kw self::
             kw static
             kw struct
-            kw super::
             kw trait
             kw type
             kw union
@@ -189,16 +184,11 @@ fn in_impl_assoc_item_list_after_attr() {
     check(
         r#"impl Struct { #[attr] $0 }"#,
         expect![[r#"
-            ma makro!(…)  macro_rules! makro
-            md module
             kw const
-            kw crate::
             kw fn
             kw pub
             kw pub(crate)
             kw pub(super)
-            kw self::
-            kw super::
             kw type
             kw unsafe
         "#]],
diff --git a/crates/ide-completion/src/tests/pattern.rs b/crates/ide-completion/src/tests/pattern.rs
index bf88070769..3ecb2f1637 100644
--- a/crates/ide-completion/src/tests/pattern.rs
+++ b/crates/ide-completion/src/tests/pattern.rs
@@ -338,10 +338,7 @@ struct Foo { bar: Bar }
 struct Bar(u32);
 fn outer(Foo { bar$0 }: Foo) {}
 "#,
-        expect![[r#"
-            kw mut
-            kw ref
-        "#]],
+        expect![[r#""#]],
     )
 }
 
diff --git a/crates/ide-completion/src/tests/record.rs b/crates/ide-completion/src/tests/record.rs
index 9e442dbbc5..2c49761748 100644
--- a/crates/ide-completion/src/tests/record.rs
+++ b/crates/ide-completion/src/tests/record.rs
@@ -41,8 +41,6 @@ fn foo(s: Struct) {
 "#,
         expect![[r#"
             fd bar u32
-            kw mut
-            kw ref
         "#]],
     );
 }
@@ -60,8 +58,6 @@ fn foo(e: Enum) {
 "#,
         expect![[r#"
             fd bar u32
-            kw mut
-            kw ref
         "#]],
     );
 }
@@ -97,8 +93,6 @@ fn foo(f: Struct) {
 ",
         expect![[r#"
             fd field u32
-            kw mut
-            kw ref
         "#]],
     );
 }
diff --git a/crates/ide-completion/src/tests/visibility.rs b/crates/ide-completion/src/tests/visibility.rs
index 151dd6a7e8..b77c595eee 100644
--- a/crates/ide-completion/src/tests/visibility.rs
+++ b/crates/ide-completion/src/tests/visibility.rs
@@ -1,26 +1,20 @@
 //! Completion tests for visibility modifiers.
 use expect_test::{expect, Expect};
 
-use crate::tests::{completion_list, completion_list_with_trigger_character};
+use crate::tests::completion_list;
 
 fn check(ra_fixture: &str, expect: Expect) {
     let actual = completion_list(ra_fixture);
     expect.assert_eq(&actual)
 }
 
-fn check_with_trigger_character(ra_fixture: &str, trigger_character: char, expect: Expect) {
-    let actual = completion_list_with_trigger_character(ra_fixture, Some(trigger_character));
-    expect.assert_eq(&actual)
-}
-
 #[test]
 fn empty_pub() {
     cov_mark::check!(kw_completion_in);
-    check_with_trigger_character(
+    check(
         r#"
 pub($0)
 "#,
-        '(',
         expect![[r#"
             kw crate
             kw in
diff --git a/crates/ide/src/hover/tests.rs b/crates/ide/src/hover/tests.rs
index 07f224da66..74c5c98689 100644
--- a/crates/ide/src/hover/tests.rs
+++ b/crates/ide/src/hover/tests.rs
@@ -3595,72 +3595,6 @@ const FOO$0: u8 = b'\x61';
 
             ---
 
-            This is a doc
-        "#]],
-    );
-    // show float literal
-    check(
-        r#"
-    /// This is a doc
-    const FOO$0: f64 = 1.0234;
-    "#,
-        expect![[r#"
-            *FOO*
-
-            ```rust
-            test
-            ```
-
-            ```rust
-            const FOO: f64 = 1.0234
-            ```
-
-            ---
-
-            This is a doc
-        "#]],
-    );
-    //show float typecasted from int
-    check(
-        r#"
-/// This is a doc
-const FOO$0: f32 = 1f32;
-"#,
-        expect![[r#"
-            *FOO*
-
-            ```rust
-            test
-            ```
-
-            ```rust
-            const FOO: f32 = 1
-            ```
-
-            ---
-
-            This is a doc
-        "#]],
-    );
-    //show f64 typecasted from float
-    check(
-        r#"
-/// This is a doc
-const FOO$0: f64 = 1.0f64;
-"#,
-        expect![[r#"
-            *FOO*
-
-            ```rust
-            test
-            ```
-
-            ```rust
-            const FOO: f64 = 1
-            ```
-
-            ---
-
             This is a doc
         "#]],
     );
@@ -3862,7 +3796,6 @@ cosnt _: &str$0 = ""; }
 
 //- /libstd.rs crate:std
 /// Docs for prim_str
-/// [`foo`](../std/keyword.foo.html)
 mod prim_str {}
 "#,
         expect![[r#"
@@ -3875,7 +3808,6 @@ mod prim_str {}
                 ---
 
                 Docs for prim_str
-                [`foo`](https://doc.rust-lang.org/nightly/std/keyword.foo.html)
             "#]],
     );
 }
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html b/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html
index c627bc9b09..60bc290121 100644
--- a/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html
+++ b/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html
@@ -93,7 +93,6 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 <span class="brace">}</span>
 
 <span class="keyword">fn</span> <span class="function declaration">main</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span>
-    <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal">"Hello </span><span class="escape_sequence">{{</span><span class="string_literal">Hello</span><span class="escape_sequence">}}</span><span class="string_literal">"</span><span class="parenthesis">)</span><span class="semicolon">;</span>
     <span class="comment">// from https://doc.rust-lang.org/std/fmt/index.html</span>
     <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal">"Hello"</span><span class="parenthesis">)</span><span class="semicolon">;</span>                 <span class="comment">// =&gt; "Hello"</span>
     <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal">"Hello, </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal">!"</span><span class="comma">,</span> <span class="string_literal">"world"</span><span class="parenthesis">)</span><span class="semicolon">;</span>   <span class="comment">// =&gt; "Hello, world!"</span>
@@ -106,7 +105,7 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
     <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal">"</span><span class="format_specifier">{</span><span class="variable">argument</span><span class="format_specifier">}</span><span class="string_literal">"</span><span class="comma">,</span> argument <span class="operator">=</span> <span class="string_literal">"test"</span><span class="parenthesis">)</span><span class="semicolon">;</span>   <span class="comment">// =&gt; "test"</span>
     <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal">"</span><span class="format_specifier">{</span><span class="variable">name</span><span class="format_specifier">}</span><span class="string_literal"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal">"</span><span class="comma">,</span> <span class="numeric_literal">1</span><span class="comma">,</span> name <span class="operator">=</span> <span class="numeric_literal">2</span><span class="parenthesis">)</span><span class="semicolon">;</span>          <span class="comment">// =&gt; "2 1"</span>
     <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal">"</span><span class="format_specifier">{</span><span class="variable">a</span><span class="format_specifier">}</span><span class="string_literal"> </span><span class="format_specifier">{</span><span class="variable">c</span><span class="format_specifier">}</span><span class="string_literal"> </span><span class="format_specifier">{</span><span class="variable">b</span><span class="format_specifier">}</span><span class="string_literal">"</span><span class="comma">,</span> a<span class="operator">=</span><span class="string_literal">"a"</span><span class="comma">,</span> b<span class="operator">=</span><span class="char_literal">'b'</span><span class="comma">,</span> c<span class="operator">=</span><span class="numeric_literal">3</span><span class="parenthesis">)</span><span class="semicolon">;</span>  <span class="comment">// =&gt; "a 3 b"</span>
-    <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal">"</span><span class="escape_sequence">{{</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="escape_sequence">}}</span><span class="string_literal">"</span><span class="comma">,</span> <span class="numeric_literal">2</span><span class="parenthesis">)</span><span class="semicolon">;</span>                       <span class="comment">// =&gt; "{2}"</span>
+    <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal">"{{</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal">}}"</span><span class="comma">,</span> <span class="numeric_literal">2</span><span class="parenthesis">)</span><span class="semicolon">;</span>                       <span class="comment">// =&gt; "{2}"</span>
     <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal">!"</span><span class="comma">,</span> <span class="string_literal">"x"</span><span class="parenthesis">)</span><span class="semicolon">;</span>
     <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="numeric_literal">1</span><span class="format_specifier">$</span><span class="format_specifier">}</span><span class="string_literal">!"</span><span class="comma">,</span> <span class="string_literal">"x"</span><span class="comma">,</span> <span class="numeric_literal">5</span><span class="parenthesis">)</span><span class="semicolon">;</span>
     <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal">"Hello </span><span class="format_specifier">{</span><span class="numeric_literal">1</span><span class="format_specifier">:</span><span class="numeric_literal">0</span><span class="format_specifier">$</span><span class="format_specifier">}</span><span class="string_literal">!"</span><span class="comma">,</span> <span class="numeric_literal">5</span><span class="comma">,</span> <span class="string_literal">"x"</span><span class="parenthesis">)</span><span class="semicolon">;</span>
@@ -129,17 +128,8 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
     <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal">, `</span><span class="format_specifier">{</span><span class="variable">name</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="format_specifier">*</span><span class="format_specifier">}</span><span class="string_literal">` has 3 fractional digits"</span><span class="comma">,</span> <span class="string_literal">"Hello"</span><span class="comma">,</span> <span class="numeric_literal">3</span><span class="comma">,</span> name<span class="operator">=</span><span class="numeric_literal">1234.56</span><span class="parenthesis">)</span><span class="semicolon">;</span>
     <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal">, `</span><span class="format_specifier">{</span><span class="variable">name</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="format_specifier">*</span><span class="format_specifier">}</span><span class="string_literal">` has 3 characters"</span><span class="comma">,</span> <span class="string_literal">"Hello"</span><span class="comma">,</span> <span class="numeric_literal">3</span><span class="comma">,</span> name<span class="operator">=</span><span class="string_literal">"1234.56"</span><span class="parenthesis">)</span><span class="semicolon">;</span>
     <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal">, `</span><span class="format_specifier">{</span><span class="variable">name</span><span class="format_specifier">:</span><span class="format_specifier">&gt;</span><span class="numeric_literal">8</span><span class="format_specifier">.</span><span class="format_specifier">*</span><span class="format_specifier">}</span><span class="string_literal">` has 3 right-aligned characters"</span><span class="comma">,</span> <span class="string_literal">"Hello"</span><span class="comma">,</span> <span class="numeric_literal">3</span><span class="comma">,</span> name<span class="operator">=</span><span class="string_literal">"1234.56"</span><span class="parenthesis">)</span><span class="semicolon">;</span>
-
-    <span class="keyword">let</span> <span class="punctuation">_</span> <span class="operator">=</span> <span class="string_literal">"{}"</span>
-    <span class="keyword">let</span> <span class="punctuation">_</span> <span class="operator">=</span> <span class="string_literal">"{{}}"</span><span class="semicolon">;</span>
-
-    <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal">"Hello </span><span class="escape_sequence">{{</span><span class="escape_sequence">}}</span><span class="string_literal">"</span><span class="parenthesis">)</span><span class="semicolon">;</span>
-    <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal">"</span><span class="escape_sequence">{{</span><span class="string_literal"> Hello"</span><span class="parenthesis">)</span><span class="semicolon">;</span>
-    <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal">"Hello </span><span class="escape_sequence">}}</span><span class="string_literal">"</span><span class="parenthesis">)</span><span class="semicolon">;</span>
-    <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal">"</span><span class="escape_sequence">{{</span><span class="string_literal">Hello</span><span class="escape_sequence">}}</span><span class="string_literal">"</span><span class="parenthesis">)</span><span class="semicolon">;</span>
-    <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal">"</span><span class="escape_sequence">{{</span><span class="string_literal"> Hello </span><span class="escape_sequence">}}</span><span class="string_literal">"</span><span class="parenthesis">)</span><span class="semicolon">;</span>
-    <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal">"</span><span class="escape_sequence">{{</span><span class="string_literal">Hello </span><span class="escape_sequence">}}</span><span class="string_literal">"</span><span class="parenthesis">)</span><span class="semicolon">;</span>
-    <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal">"</span><span class="escape_sequence">{{</span><span class="string_literal"> Hello</span><span class="escape_sequence">}}</span><span class="string_literal">"</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal">"Hello {{}}"</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal">"{{ Hello"</span><span class="parenthesis">)</span><span class="semicolon">;</span>
 
     <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal">r"Hello, </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal">!"</span><span class="comma">,</span> <span class="string_literal">"world"</span><span class="parenthesis">)</span><span class="semicolon">;</span>
 
diff --git a/crates/ide/src/syntax_highlighting/tests.rs b/crates/ide/src/syntax_highlighting/tests.rs
index 83bdca295d..e436a0574b 100644
--- a/crates/ide/src/syntax_highlighting/tests.rs
+++ b/crates/ide/src/syntax_highlighting/tests.rs
@@ -421,7 +421,6 @@ macro_rules! toho {
 }
 
 fn main() {
-    println!("Hello {{Hello}}");
     // from https://doc.rust-lang.org/std/fmt/index.html
     println!("Hello");                 // => "Hello"
     println!("Hello, {}!", "world");   // => "Hello, world!"
@@ -457,17 +456,8 @@ fn main() {
     println!("{}, `{name:.*}` has 3 fractional digits", "Hello", 3, name=1234.56);
     println!("{}, `{name:.*}` has 3 characters", "Hello", 3, name="1234.56");
     println!("{}, `{name:>8.*}` has 3 right-aligned characters", "Hello", 3, name="1234.56");
-
-    let _ = "{}"
-    let _ = "{{}}";
-
     println!("Hello {{}}");
     println!("{{ Hello");
-    println!("Hello }}");
-    println!("{{Hello}}");
-    println!("{{ Hello }}");
-    println!("{{Hello }}");
-    println!("{{ Hello}}");
 
     println!(r"Hello, {}!", "world");
 
diff --git a/crates/project-model/src/tests.rs b/crates/project-model/src/tests.rs
index e72903e55f..3d089b61b5 100644
--- a/crates/project-model/src/tests.rs
+++ b/crates/project-model/src/tests.rs
@@ -88,7 +88,7 @@ fn rooted_project_json(data: ProjectJsonData) -> ProjectJson {
 }
 
 fn to_crate_graph(project_workspace: ProjectWorkspace) -> CrateGraph {
-    project_workspace.to_crate_graph(&mut |_, _| Vec::new(), &mut {
+    project_workspace.to_crate_graph(&Default::default(), &mut |_, _| Vec::new(), &mut {
         let mut counter = 0;
         move |_path| {
             counter += 1;
diff --git a/crates/rust-analyzer/tests/slow-tests/main.rs b/crates/rust-analyzer/tests/slow-tests/main.rs
index 6d2788d337..5bb925f62b 100644
--- a/crates/rust-analyzer/tests/slow-tests/main.rs
+++ b/crates/rust-analyzer/tests/slow-tests/main.rs
@@ -20,7 +20,7 @@ use lsp_types::{
     notification::DidOpenTextDocument,
     request::{
         CodeActionRequest, Completion, Formatting, GotoTypeDefinition, HoverRequest,
-        WillRenameFiles, WorkspaceSymbol,
+        WillRenameFiles,
     },
     CodeActionContext, CodeActionParams, CompletionParams, DidOpenTextDocumentParams,
     DocumentFormattingParams, FileRename, FormattingOptions, GotoDefinitionParams, HoverParams,
@@ -1056,41 +1056,3 @@ fn main() {}
         }),
     );
 }
-
-#[test]
-fn test_exclude_config_works() {
-    if skip_slow_tests() {
-        return;
-    }
-
-    let server = Project::with_fixture(
-        r#"
-//- /foo/Cargo.toml
-[package]
-name = "foo"
-version = "0.0.0"
-
-//- /foo/src/lib.rs
-pub fn foo() {}
-
-//- /bar/Cargo.toml
-[package]
-name = "bar"
-version = "0.0.0"
-
-//- /bar/src/lib.rs
-pub fn bar() {}
-"#,
-    )
-    .root("foo")
-    .root("bar")
-    .with_config(json!({
-       "files": {
-           "excludeDirs": ["foo", "bar"]
-        }
-    }))
-    .server()
-    .wait_until_workspace_is_loaded();
-
-    server.request::<WorkspaceSymbol>(Default::default(), json!([]));
-}