mirror of
https://github.com/rust-lang/rust-analyzer
synced 2025-01-01 07:48:45 +00:00
Merge from rustc
This commit is contained in:
commit
2016e149f5
213 changed files with 3973 additions and 2614 deletions
5
.github/workflows/publish-libs.yaml
vendored
5
.github/workflows/publish-libs.yaml
vendored
|
@ -30,7 +30,6 @@ jobs:
|
|||
run: |
|
||||
git config --global user.email "runner@gha.local"
|
||||
git config --global user.name "GitHub Action"
|
||||
# Remove r-a crates from the workspaces so we don't auto-publish them as well
|
||||
sed -i 's/ "crates\/\*"//' ./Cargo.toml
|
||||
sed -i 's/ "xtask\/"//' ./Cargo.toml
|
||||
# Only publish the crates under lib/
|
||||
sed -i 's|^members = .*$|members = ["lib/*"]|' Cargo.toml
|
||||
cargo workspaces publish --yes --exact --from-git --no-git-commit --allow-dirty
|
||||
|
|
370
Cargo.lock
generated
370
Cargo.lock
generated
|
@ -52,16 +52,16 @@ checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
|
|||
|
||||
[[package]]
|
||||
name = "backtrace"
|
||||
version = "0.3.72"
|
||||
version = "0.3.73"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "17c6a35df3749d2e8bb1b7b21a976d82b15548788d2735b9d82f329268f71a11"
|
||||
checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a"
|
||||
dependencies = [
|
||||
"addr2line",
|
||||
"cc",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"miniz_oxide",
|
||||
"object 0.35.0",
|
||||
"object 0.36.3",
|
||||
"rustc-demangle",
|
||||
]
|
||||
|
||||
|
@ -92,9 +92,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
|||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.5.0"
|
||||
version = "2.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1"
|
||||
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
|
@ -136,9 +136,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.98"
|
||||
version = "1.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "41c270e7540d725e65ac7f1b212ac8ce349719624d7bcff99f8e2e488e8cf03f"
|
||||
checksum = "e9e8aabfac534be767c909e0690571677d49f41bd8465ae876fe043d52ba5292"
|
||||
|
||||
[[package]]
|
||||
name = "cfg"
|
||||
|
@ -148,10 +148,10 @@ dependencies = [
|
|||
"derive_arbitrary",
|
||||
"expect-test",
|
||||
"intern",
|
||||
"mbe",
|
||||
"oorandom",
|
||||
"rustc-hash",
|
||||
"syntax",
|
||||
"syntax-bridge",
|
||||
"tt",
|
||||
]
|
||||
|
||||
|
@ -185,7 +185,7 @@ version = "0.98.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d5f2eb1cd6054da221bd1ac0197fb2fe5e2caf3dcb93619398fc1433f8f09093"
|
||||
dependencies = [
|
||||
"bitflags 2.5.0",
|
||||
"bitflags 2.6.0",
|
||||
"chalk-derive",
|
||||
]
|
||||
|
||||
|
@ -226,9 +226,9 @@ checksum = "7704b5fdd17b18ae31c4c1da5a2e0305a2bf17b5249300a9ee9ed7b72114c636"
|
|||
|
||||
[[package]]
|
||||
name = "cov-mark"
|
||||
version = "2.0.0-pre.1"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0d48d8f76bd9331f19fe2aaf3821a9f9fb32c3963e1e3d6ce82a8c09cef7444a"
|
||||
checksum = "0570650661aa447e7335f1d5e4f499d8e58796e617bedc9267d971e51c8b49d4"
|
||||
|
||||
[[package]]
|
||||
name = "crc32fast"
|
||||
|
@ -366,9 +366,9 @@ checksum = "9bda8e21c04aca2ae33ffc2fd8c23134f3cac46db123ba97bd9d3f3b8a4a85e1"
|
|||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.12.0"
|
||||
version = "1.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b"
|
||||
checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
|
||||
|
||||
[[package]]
|
||||
name = "ena"
|
||||
|
@ -397,14 +397,14 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "filetime"
|
||||
version = "0.2.23"
|
||||
version = "0.2.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd"
|
||||
checksum = "bf401df4a4e3872c4fe8151134cf483738e74b67fc934d6532c882b3d24a4550"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"redox_syscall 0.4.1",
|
||||
"windows-sys 0.52.0",
|
||||
"libredox",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -415,31 +415,14 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
|
|||
|
||||
[[package]]
|
||||
name = "flate2"
|
||||
version = "1.0.30"
|
||||
version = "1.0.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae"
|
||||
checksum = "7f211bbe8e69bbd0cfdea405084f128ae8b4aaa6b0b522fc8f2b009084797920"
|
||||
dependencies = [
|
||||
"crc32fast",
|
||||
"miniz_oxide",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "flycheck"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"cargo_metadata",
|
||||
"crossbeam-channel",
|
||||
"paths",
|
||||
"process-wrap",
|
||||
"project-model",
|
||||
"rustc-hash",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"stdx",
|
||||
"toolchain",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "form_urlencoded"
|
||||
version = "1.2.1"
|
||||
|
@ -529,7 +512,7 @@ version = "0.0.0"
|
|||
dependencies = [
|
||||
"arrayvec",
|
||||
"base-db",
|
||||
"bitflags 2.5.0",
|
||||
"bitflags 2.6.0",
|
||||
"cfg",
|
||||
"cov-mark",
|
||||
"dashmap",
|
||||
|
@ -554,6 +537,7 @@ dependencies = [
|
|||
"span",
|
||||
"stdx",
|
||||
"syntax",
|
||||
"syntax-bridge",
|
||||
"test-fixture",
|
||||
"test-utils",
|
||||
"tracing",
|
||||
|
@ -582,6 +566,7 @@ dependencies = [
|
|||
"span",
|
||||
"stdx",
|
||||
"syntax",
|
||||
"syntax-bridge",
|
||||
"tracing",
|
||||
"triomphe",
|
||||
"tt",
|
||||
|
@ -593,7 +578,7 @@ version = "0.0.0"
|
|||
dependencies = [
|
||||
"arrayvec",
|
||||
"base-db",
|
||||
"bitflags 2.5.0",
|
||||
"bitflags 2.6.0",
|
||||
"chalk-derive",
|
||||
"chalk-ir",
|
||||
"chalk-recursive",
|
||||
|
@ -722,7 +707,7 @@ version = "0.0.0"
|
|||
dependencies = [
|
||||
"arrayvec",
|
||||
"base-db",
|
||||
"bitflags 2.5.0",
|
||||
"bitflags 2.6.0",
|
||||
"cov-mark",
|
||||
"crossbeam-channel",
|
||||
"either",
|
||||
|
@ -803,9 +788,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "2.2.6"
|
||||
version = "2.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26"
|
||||
checksum = "de3fc2e30ba82dd1b3911c8de1ffc143c74a914a14e99514d7637e3099df5ea0"
|
||||
dependencies = [
|
||||
"equivalent",
|
||||
"hashbrown",
|
||||
|
@ -895,9 +880,9 @@ checksum = "3752f229dcc5a481d60f385fa479ff46818033d881d2d801aa27dffcfb5e8306"
|
|||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.4.0"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
|
@ -907,19 +892,19 @@ checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
|
|||
|
||||
[[package]]
|
||||
name = "libloading"
|
||||
version = "0.8.3"
|
||||
version = "0.8.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19"
|
||||
checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"windows-targets 0.52.5",
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libmimalloc-sys"
|
||||
version = "0.1.38"
|
||||
version = "0.1.39"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0e7bb23d733dfcc8af652a78b7bf232f0e967710d044732185e561e47c0336b6"
|
||||
checksum = "23aa6811d3bd4deb8a84dde645f943476d13b248d818edcf8ce0b2f37f036b44"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
|
@ -931,8 +916,9 @@ version = "0.1.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d"
|
||||
dependencies = [
|
||||
"bitflags 2.5.0",
|
||||
"bitflags 2.6.0",
|
||||
"libc",
|
||||
"redox_syscall",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -996,9 +982,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.21"
|
||||
version = "0.4.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c"
|
||||
checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
|
||||
|
||||
[[package]]
|
||||
name = "lsp-server"
|
||||
|
@ -1056,6 +1042,7 @@ dependencies = [
|
|||
"span",
|
||||
"stdx",
|
||||
"syntax",
|
||||
"syntax-bridge",
|
||||
"test-utils",
|
||||
"tracing",
|
||||
"tt",
|
||||
|
@ -1063,9 +1050,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.7.2"
|
||||
version = "2.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d"
|
||||
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
|
||||
|
||||
[[package]]
|
||||
name = "memmap2"
|
||||
|
@ -1087,18 +1074,18 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "mimalloc"
|
||||
version = "0.1.42"
|
||||
version = "0.1.43"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e9186d86b79b52f4a77af65604b51225e8db1d6ee7e3f41aec1e40829c71a176"
|
||||
checksum = "68914350ae34959d83f732418d51e2427a794055d0b9529f48259ac07af65633"
|
||||
dependencies = [
|
||||
"libmimalloc-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.7.3"
|
||||
version = "0.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "87dfd01fe195c66b572b37921ad8803d010623c0aca821bea2302239d155cdae"
|
||||
checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08"
|
||||
dependencies = [
|
||||
"adler",
|
||||
]
|
||||
|
@ -1130,7 +1117,7 @@ version = "0.28.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4"
|
||||
dependencies = [
|
||||
"bitflags 2.5.0",
|
||||
"bitflags 2.6.0",
|
||||
"cfg-if",
|
||||
"cfg_aliases",
|
||||
"libc",
|
||||
|
@ -1148,7 +1135,7 @@ version = "6.1.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6205bd8bb1e454ad2e27422015fb5e4f2bcc7e08fa8f27058670d208324a4d2d"
|
||||
dependencies = [
|
||||
"bitflags 2.5.0",
|
||||
"bitflags 2.6.0",
|
||||
"crossbeam-channel",
|
||||
"filetime",
|
||||
"fsevent-sys",
|
||||
|
@ -1163,11 +1150,11 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "nu-ansi-term"
|
||||
version = "0.50.0"
|
||||
version = "0.50.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd2800e1520bdc966782168a627aa5d1ad92e33b984bf7c7615d31280c83ff14"
|
||||
checksum = "d4a28e057d01f97e61255210fcff094d74ed0466038633e95017f5beb68e4399"
|
||||
dependencies = [
|
||||
"windows-sys 0.48.0",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1197,9 +1184,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "object"
|
||||
version = "0.35.0"
|
||||
version = "0.36.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b8ec7ab813848ba4522158d5517a6093db1ded27575b070f4177b8d12b41db5e"
|
||||
checksum = "27b64972346851a39438c60b341ebc01bba47464ae329e55cf343eb93964efd9"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
@ -1212,9 +1199,9 @@ checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
|
|||
|
||||
[[package]]
|
||||
name = "oorandom"
|
||||
version = "11.1.3"
|
||||
version = "11.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575"
|
||||
checksum = "b410bbe7e14ab526a0e86877eb47c6996a2bd7746f027ba551028c925390e4e9"
|
||||
|
||||
[[package]]
|
||||
name = "option-ext"
|
||||
|
@ -1240,9 +1227,9 @@ checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8"
|
|||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"redox_syscall 0.5.1",
|
||||
"redox_syscall",
|
||||
"smallvec",
|
||||
"windows-targets 0.52.5",
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1268,6 +1255,7 @@ name = "paths"
|
|||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"camino",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1319,9 +1307,12 @@ checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
|
|||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.17"
|
||||
version = "0.2.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
|
||||
checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04"
|
||||
dependencies = [
|
||||
"zerocopy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-api"
|
||||
|
@ -1330,14 +1321,12 @@ dependencies = [
|
|||
"base-db",
|
||||
"indexmap",
|
||||
"intern",
|
||||
"la-arena 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"paths",
|
||||
"rustc-hash",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"span",
|
||||
"stdx",
|
||||
"text-size",
|
||||
"tracing",
|
||||
"tt",
|
||||
]
|
||||
|
@ -1350,7 +1339,6 @@ dependencies = [
|
|||
"expect-test",
|
||||
"intern",
|
||||
"libloading",
|
||||
"mbe",
|
||||
"memmap2",
|
||||
"object 0.33.0",
|
||||
"paths",
|
||||
|
@ -1360,6 +1348,7 @@ dependencies = [
|
|||
"snap",
|
||||
"span",
|
||||
"stdx",
|
||||
"syntax-bridge",
|
||||
"tt",
|
||||
]
|
||||
|
||||
|
@ -1380,9 +1369,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.85"
|
||||
version = "1.0.86"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23"
|
||||
checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
@ -1460,7 +1449,7 @@ version = "0.9.6"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "57206b407293d2bcd3af849ce869d52068623f19e1b5ff8e8778e3309439682b"
|
||||
dependencies = [
|
||||
"bitflags 2.5.0",
|
||||
"bitflags 2.6.0",
|
||||
"memchr",
|
||||
"unicase",
|
||||
]
|
||||
|
@ -1485,20 +1474,20 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "ra-ap-rustc_abi"
|
||||
version = "0.53.0"
|
||||
version = "0.63.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "80b1d613eee933486c0613a7bc26e515e46f43adf479d1edd5e537f983e9ce46"
|
||||
checksum = "b011c39d409940a890414e3a7b239762ac16d88029ad71b050a8374831b93790"
|
||||
dependencies = [
|
||||
"bitflags 2.5.0",
|
||||
"bitflags 2.6.0",
|
||||
"ra-ap-rustc_index",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ra-ap-rustc_index"
|
||||
version = "0.53.0"
|
||||
version = "0.63.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f072060ac77e9e1a02cc20028095993af7e72cc0804779c68bcbf47b16de49c9"
|
||||
checksum = "9027acdee649b0b27eb10b7db5be833efee3362d394935c5eed8f0745a9d43ce"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"ra-ap-rustc_index_macros",
|
||||
|
@ -1507,21 +1496,20 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "ra-ap-rustc_index_macros"
|
||||
version = "0.53.0"
|
||||
version = "0.63.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "82f3d6dcb30a66905388e14756b8f2216131d9f8004922c07f13335840e058d1"
|
||||
checksum = "540b86dc0384141ac8e825fc2874cd44bffd4277d99d8ec63ee416f1a98d5997"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"synstructure",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ra-ap-rustc_lexer"
|
||||
version = "0.53.0"
|
||||
version = "0.63.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dbd8a2b0bdcba9892cbce0b25f6c953d31b0febc1f3420fc692884fce5a23ad8"
|
||||
checksum = "3bdf98bb457b47b9ae4aeebf867d0ca440c86925e0b6381658c4a02589748c9d"
|
||||
dependencies = [
|
||||
"unicode-properties",
|
||||
"unicode-xid",
|
||||
|
@ -1529,9 +1517,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "ra-ap-rustc_parse_format"
|
||||
version = "0.53.0"
|
||||
version = "0.63.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "70dad7a491c2554590222e0c9212dcb7c2e7aceb668875075012a35ea780d135"
|
||||
checksum = "e8fe3556ab6311bb775220563a300e2bf62ec56404521fe0c511a583937683d5"
|
||||
dependencies = [
|
||||
"ra-ap-rustc_index",
|
||||
"ra-ap-rustc_lexer",
|
||||
|
@ -1539,9 +1527,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "ra-ap-rustc_pattern_analysis"
|
||||
version = "0.53.0"
|
||||
version = "0.63.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "34768e1faf88c31f2e9ad57b48318a52b507dafac0cddbf01b5d63bfc0b0a365"
|
||||
checksum = "1709080fdeb5db630e1c2644026c2962aaa32416cd92f0190c04b0c21e114b91"
|
||||
dependencies = [
|
||||
"ra-ap-rustc_index",
|
||||
"rustc-hash",
|
||||
|
@ -1602,20 +1590,11 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.4.1"
|
||||
version = "0.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa"
|
||||
checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "469052894dcb553421e483e4209ee581a45100d31b4018de03e5a7ad86374a7e"
|
||||
dependencies = [
|
||||
"bitflags 2.5.0",
|
||||
"bitflags 2.6.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1648,12 +1627,12 @@ version = "0.0.0"
|
|||
dependencies = [
|
||||
"always-assert",
|
||||
"anyhow",
|
||||
"cargo_metadata",
|
||||
"cfg",
|
||||
"crossbeam-channel",
|
||||
"dirs",
|
||||
"dissimilar",
|
||||
"expect-test",
|
||||
"flycheck",
|
||||
"hir",
|
||||
"hir-def",
|
||||
"hir-ty",
|
||||
|
@ -1665,7 +1644,6 @@ dependencies = [
|
|||
"load-cargo",
|
||||
"lsp-server 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lsp-types",
|
||||
"mbe",
|
||||
"memchr",
|
||||
"mimalloc",
|
||||
"nohash-hasher",
|
||||
|
@ -1675,6 +1653,7 @@ dependencies = [
|
|||
"parser",
|
||||
"paths",
|
||||
"proc-macro-api",
|
||||
"process-wrap",
|
||||
"profile",
|
||||
"project-model",
|
||||
"rayon",
|
||||
|
@ -1685,6 +1664,7 @@ dependencies = [
|
|||
"serde_json",
|
||||
"stdx",
|
||||
"syntax",
|
||||
"syntax-bridge",
|
||||
"test-fixture",
|
||||
"test-utils",
|
||||
"tikv-jemallocator",
|
||||
|
@ -1716,9 +1696,9 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
|
|||
|
||||
[[package]]
|
||||
name = "rustc_apfloat"
|
||||
version = "0.2.0+llvm-462a31f5a5ab"
|
||||
version = "0.2.1+llvm-462a31f5a5ab"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "465187772033a5ee566f69fe008df03628fce549a0899aae76f0a0c2e34696be"
|
||||
checksum = "886d94c63c812a8037c4faca2607453a0fa4cf82f734665266876b022244543f"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"smallvec",
|
||||
|
@ -1801,18 +1781,18 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.203"
|
||||
version = "1.0.206"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094"
|
||||
checksum = "5b3e4cd94123dd520a128bcd11e34d9e9e423e7e3e50425cb1b4b1e3549d0284"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.203"
|
||||
version = "1.0.206"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba"
|
||||
checksum = "fabfb6138d2383ea8208cf98ccf69cdfb1aff4088460681d84189aa259762f97"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -1821,12 +1801,13 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.117"
|
||||
version = "1.0.124"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3"
|
||||
checksum = "66ad62847a56b3dba58cc891acd13884b9c61138d330c0d7b6181713d4fce38d"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"itoa",
|
||||
"memchr",
|
||||
"ryu",
|
||||
"serde",
|
||||
]
|
||||
|
@ -1844,9 +1825,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "serde_spanned"
|
||||
version = "0.6.6"
|
||||
version = "0.6.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "79e674e01f999af37c49f70a6ede167a8a60b2503e56c5599532a65baa5969a0"
|
||||
checksum = "eb5b1b31579f3811bf615c144393417496f152e12ac8b7663bf664f4a815306d"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
@ -1923,9 +1904,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.66"
|
||||
version = "2.0.74"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5"
|
||||
checksum = "1fceb41e3d546d0bd83421d3409b1460cc7444cd389341a4c880fe7a042cb3d7"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -1967,6 +1948,21 @@ dependencies = [
|
|||
"triomphe",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syntax-bridge"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"intern",
|
||||
"parser",
|
||||
"rustc-hash",
|
||||
"span",
|
||||
"stdx",
|
||||
"syntax",
|
||||
"test-utils",
|
||||
"tracing",
|
||||
"tt",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "test-fixture"
|
||||
version = "0.0.0"
|
||||
|
@ -1987,6 +1983,7 @@ name = "test-utils"
|
|||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"dissimilar",
|
||||
"paths",
|
||||
"profile",
|
||||
"rustc-hash",
|
||||
"stdx",
|
||||
|
@ -2010,18 +2007,18 @@ checksum = "f18aa187839b2bdb1ad2fa35ead8c4c2976b64e4363c386d45ac0f7ee85c9233"
|
|||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.61"
|
||||
version = "1.0.63"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709"
|
||||
checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.61"
|
||||
version = "1.0.63"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533"
|
||||
checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -2090,9 +2087,9 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3"
|
|||
|
||||
[[package]]
|
||||
name = "tinyvec"
|
||||
version = "1.6.0"
|
||||
version = "1.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50"
|
||||
checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938"
|
||||
dependencies = [
|
||||
"tinyvec_macros",
|
||||
]
|
||||
|
@ -2105,9 +2102,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
|
|||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.8.14"
|
||||
version = "0.8.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6f49eb2ab21d2f26bd6db7bf383edc527a7ebaee412d17af4d40fdccd442f335"
|
||||
checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_spanned",
|
||||
|
@ -2117,18 +2114,18 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "toml_datetime"
|
||||
version = "0.6.6"
|
||||
version = "0.6.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf"
|
||||
checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml_edit"
|
||||
version = "0.22.14"
|
||||
version = "0.22.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f21c7aaf97f1bd9ca9d4f9e73b0a6c74bd5afef56f2bc931943a6e1c37e04e38"
|
||||
checksum = "583c44c02ad26b0c3f3066fe629275e50627026c51ac2e595cca4c230ce1ce1d"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"serde",
|
||||
|
@ -2214,9 +2211,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "triomphe"
|
||||
version = "0.1.12"
|
||||
version = "0.1.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1b2cb4fbb9995eeb36ac86fadf24031ccd58f99d6b4b2d7b911db70bddb80d90"
|
||||
checksum = "e6631e42e10b40c0690bf92f404ebcfe6e1fdb480391d15f17cc8e96eeed5369"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"stable_deref_trait",
|
||||
|
@ -2289,9 +2286,9 @@ checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
|
|||
|
||||
[[package]]
|
||||
name = "url"
|
||||
version = "2.5.0"
|
||||
version = "2.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633"
|
||||
checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c"
|
||||
dependencies = [
|
||||
"form_urlencoded",
|
||||
"idna",
|
||||
|
@ -2307,14 +2304,15 @@ checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
|
|||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.4"
|
||||
version = "0.9.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
||||
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
|
||||
|
||||
[[package]]
|
||||
name = "vfs"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"crossbeam-channel",
|
||||
"fst",
|
||||
"indexmap",
|
||||
"nohash-hasher",
|
||||
|
@ -2331,6 +2329,8 @@ dependencies = [
|
|||
"crossbeam-channel",
|
||||
"notify",
|
||||
"paths",
|
||||
"rayon",
|
||||
"rustc-hash",
|
||||
"stdx",
|
||||
"tracing",
|
||||
"vfs",
|
||||
|
@ -2355,11 +2355,11 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
|||
|
||||
[[package]]
|
||||
name = "winapi-util"
|
||||
version = "0.1.8"
|
||||
version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b"
|
||||
checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
|
||||
dependencies = [
|
||||
"windows-sys 0.52.0",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2369,7 +2369,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "1de69df01bdf1ead2f4ac895dc77c9351aefff65b2f3db429a343f9cbf05e132"
|
||||
dependencies = [
|
||||
"windows-core",
|
||||
"windows-targets 0.52.5",
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2381,7 +2381,7 @@ dependencies = [
|
|||
"windows-implement",
|
||||
"windows-interface",
|
||||
"windows-result",
|
||||
"windows-targets 0.52.5",
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2408,11 +2408,11 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "windows-result"
|
||||
version = "0.1.1"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "749f0da9cc72d82e600d8d2e44cadd0b9eedb9038f71a1c58556ac1c5791813b"
|
||||
checksum = "5e383302e8ec8515204254685643de10811af0ed97ea37210dc26fb0032647f8"
|
||||
dependencies = [
|
||||
"windows-targets 0.52.5",
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2430,7 +2430,16 @@ version = "0.52.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
|
||||
dependencies = [
|
||||
"windows-targets 0.52.5",
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.59.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
|
||||
dependencies = [
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2450,18 +2459,18 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.52.5"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb"
|
||||
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm 0.52.5",
|
||||
"windows_aarch64_msvc 0.52.5",
|
||||
"windows_i686_gnu 0.52.5",
|
||||
"windows_aarch64_gnullvm 0.52.6",
|
||||
"windows_aarch64_msvc 0.52.6",
|
||||
"windows_i686_gnu 0.52.6",
|
||||
"windows_i686_gnullvm",
|
||||
"windows_i686_msvc 0.52.5",
|
||||
"windows_x86_64_gnu 0.52.5",
|
||||
"windows_x86_64_gnullvm 0.52.5",
|
||||
"windows_x86_64_msvc 0.52.5",
|
||||
"windows_i686_msvc 0.52.6",
|
||||
"windows_x86_64_gnu 0.52.6",
|
||||
"windows_x86_64_gnullvm 0.52.6",
|
||||
"windows_x86_64_msvc 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2472,9 +2481,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
|
|||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.52.5"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263"
|
||||
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
|
@ -2484,9 +2493,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
|
|||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.52.5"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6"
|
||||
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
|
@ -2496,15 +2505,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
|
|||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.52.5"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670"
|
||||
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnullvm"
|
||||
version = "0.52.5"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9"
|
||||
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
|
@ -2514,9 +2523,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
|
|||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.52.5"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf"
|
||||
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
|
@ -2526,9 +2535,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
|
|||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.52.5"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9"
|
||||
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
|
@ -2538,9 +2547,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
|
|||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.52.5"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596"
|
||||
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
|
@ -2550,15 +2559,15 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
|
|||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.52.5"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0"
|
||||
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
||||
|
||||
[[package]]
|
||||
name = "winnow"
|
||||
version = "0.6.11"
|
||||
version = "0.6.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "56c52728401e1dc672a56e81e593e912aa54c78f40246869f78359a2bf24d29d"
|
||||
checksum = "68a9bda4691f099d435ad181000724da8e5899daa10713c2d432552b9ccd3a6f"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
@ -2618,6 +2627,27 @@ dependencies = [
|
|||
"zip",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy"
|
||||
version = "0.7.35"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"zerocopy-derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy-derive"
|
||||
version = "0.7.35"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zip"
|
||||
version = "0.6.6"
|
||||
|
|
26
Cargo.toml
26
Cargo.toml
|
@ -4,10 +4,11 @@ exclude = ["crates/proc-macro-srv/proc-macro-test/imp"]
|
|||
resolver = "2"
|
||||
|
||||
[workspace.package]
|
||||
rust-version = "1.78"
|
||||
rust-version = "1.80"
|
||||
edition = "2021"
|
||||
license = "MIT OR Apache-2.0"
|
||||
authors = ["rust-analyzer team"]
|
||||
repository = "https://github.com/rust-lang/rust-analyzer"
|
||||
|
||||
[profile.dev]
|
||||
debug = 1
|
||||
|
@ -51,7 +52,6 @@ debug = 2
|
|||
# local crates
|
||||
base-db = { path = "./crates/base-db", version = "0.0.0" }
|
||||
cfg = { path = "./crates/cfg", version = "0.0.0", features = ["tt"] }
|
||||
flycheck = { path = "./crates/flycheck", version = "0.0.0" }
|
||||
hir = { path = "./crates/hir", version = "0.0.0" }
|
||||
hir-def = { path = "./crates/hir-def", version = "0.0.0" }
|
||||
hir-expand = { path = "./crates/hir-expand", version = "0.0.0" }
|
||||
|
@ -77,17 +77,18 @@ salsa = { path = "./crates/salsa", version = "0.0.0" }
|
|||
span = { path = "./crates/span", version = "0.0.0" }
|
||||
stdx = { path = "./crates/stdx", version = "0.0.0" }
|
||||
syntax = { path = "./crates/syntax", version = "0.0.0" }
|
||||
syntax-bridge = { path = "./crates/syntax-bridge", version = "0.0.0" }
|
||||
text-edit = { path = "./crates/text-edit", version = "0.0.0" }
|
||||
toolchain = { path = "./crates/toolchain", version = "0.0.0" }
|
||||
tt = { path = "./crates/tt", version = "0.0.0" }
|
||||
vfs-notify = { path = "./crates/vfs-notify", version = "0.0.0" }
|
||||
vfs = { path = "./crates/vfs", version = "0.0.0" }
|
||||
|
||||
ra-ap-rustc_lexer = { version = "0.53.0", default-features = false }
|
||||
ra-ap-rustc_parse_format = { version = "0.53.0", default-features = false }
|
||||
ra-ap-rustc_index = { version = "0.53.0", default-features = false }
|
||||
ra-ap-rustc_abi = { version = "0.53.0", default-features = false }
|
||||
ra-ap-rustc_pattern_analysis = { version = "0.53.0", default-features = false }
|
||||
ra-ap-rustc_lexer = { version = "0.63.0", default-features = false }
|
||||
ra-ap-rustc_parse_format = { version = "0.63.0", default-features = false }
|
||||
ra-ap-rustc_index = { version = "0.63.0", default-features = false }
|
||||
ra-ap-rustc_abi = { version = "0.63.0", default-features = false }
|
||||
ra-ap-rustc_pattern_analysis = { version = "0.63.0", default-features = false }
|
||||
|
||||
# local crates that aren't published to crates.io. These should not have versions.
|
||||
test-fixture = { path = "./crates/test-fixture" }
|
||||
|
@ -124,11 +125,11 @@ memmap2 = "0.5.4"
|
|||
nohash-hasher = "0.2.0"
|
||||
oorandom = "11.1.3"
|
||||
object = { version = "0.33.0", default-features = false, features = [
|
||||
"std",
|
||||
"read_core",
|
||||
"elf",
|
||||
"macho",
|
||||
"pe",
|
||||
"std",
|
||||
"read_core",
|
||||
"elf",
|
||||
"macho",
|
||||
"pe",
|
||||
] }
|
||||
process-wrap = { version = "8.0.2", features = ["std"] }
|
||||
pulldown-cmark-to-cmark = "10.0.4"
|
||||
|
@ -158,7 +159,6 @@ url = "2.3.1"
|
|||
xshell = "0.2.5"
|
||||
|
||||
|
||||
|
||||
# We need to freeze the version of the crate, as the raw-api feature is considered unstable
|
||||
dashmap = { version = "=5.5.3", features = ["raw-api"] }
|
||||
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
[package]
|
||||
name = "base-db"
|
||||
version = "0.0.0"
|
||||
description = "TBD"
|
||||
repository.workspace = true
|
||||
description = "Basic database traits for rust-analyzer. The concrete DB is defined by `ide` (aka `ra_ap_ide`)."
|
||||
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
|
|
|
@ -7,7 +7,7 @@ use salsa::Durability;
|
|||
use triomphe::Arc;
|
||||
use vfs::FileId;
|
||||
|
||||
use crate::{CrateGraph, SourceDatabaseExt, SourceDatabaseExt2, SourceRoot, SourceRootId};
|
||||
use crate::{CrateGraph, SourceDatabaseFileInputExt, SourceRoot, SourceRootDatabase, SourceRootId};
|
||||
|
||||
/// Encapsulate a bunch of raw `.set` calls on the database.
|
||||
#[derive(Default)]
|
||||
|
@ -50,7 +50,7 @@ impl FileChange {
|
|||
self.crate_graph = Some(graph);
|
||||
}
|
||||
|
||||
pub fn apply(self, db: &mut dyn SourceDatabaseExt) {
|
||||
pub fn apply(self, db: &mut dyn SourceRootDatabase) {
|
||||
let _p = tracing::info_span!("FileChange::apply").entered();
|
||||
if let Some(roots) = self.roots {
|
||||
for (idx, root) in roots.into_iter().enumerate() {
|
||||
|
|
|
@ -690,6 +690,14 @@ impl Env {
|
|||
pub fn extend_from_other(&mut self, other: &Env) {
|
||||
self.entries.extend(other.entries.iter().map(|(x, y)| (x.to_owned(), y.to_owned())));
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.entries.is_empty()
|
||||
}
|
||||
|
||||
pub fn insert(&mut self, k: impl Into<String>, v: impl Into<String>) -> Option<String> {
|
||||
self.entries.insert(k.into(), v.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Env> for Vec<(String, String)> {
|
||||
|
@ -700,6 +708,15 @@ impl From<Env> for Vec<(String, String)> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a> IntoIterator for &'a Env {
|
||||
type Item = (&'a String, &'a String);
|
||||
type IntoIter = std::collections::hash_map::Iter<'a, String, String>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
self.entries.iter()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct CyclicDependenciesError {
|
||||
path: Vec<(CrateId, Option<CrateDisplayName>)>,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
//! base_db defines basic database traits. The concrete DB is defined by ide.
|
||||
|
||||
// FIXME: Rename this crate, base db is non descriptive
|
||||
mod change;
|
||||
mod input;
|
||||
|
||||
|
@ -47,8 +47,6 @@ pub const DEFAULT_PARSE_LRU_CAP: u16 = 128;
|
|||
pub const DEFAULT_BORROWCK_LRU_CAP: u16 = 2024;
|
||||
|
||||
pub trait FileLoader {
|
||||
/// Text of the file.
|
||||
fn file_text(&self, file_id: FileId) -> Arc<str>;
|
||||
fn resolve_path(&self, path: AnchoredPath<'_>) -> Option<FileId>;
|
||||
/// Crates whose root's source root is the same as the source root of `file_id`
|
||||
fn relevant_crates(&self, file_id: FileId) -> Arc<[CrateId]>;
|
||||
|
@ -58,6 +56,13 @@ pub trait FileLoader {
|
|||
/// model. Everything else in rust-analyzer is derived from these queries.
|
||||
#[salsa::query_group(SourceDatabaseStorage)]
|
||||
pub trait SourceDatabase: FileLoader + std::fmt::Debug {
|
||||
#[salsa::input]
|
||||
fn compressed_file_text(&self, file_id: FileId) -> Arc<[u8]>;
|
||||
|
||||
/// Text of the file.
|
||||
#[salsa::lru]
|
||||
fn file_text(&self, file_id: FileId) -> Arc<str>;
|
||||
|
||||
/// Parses the file into the syntax tree.
|
||||
#[salsa::lru]
|
||||
fn parse(&self, file_id: EditionedFileId) -> Parse<ast::SourceFile>;
|
||||
|
@ -99,16 +104,18 @@ fn parse_errors(db: &dyn SourceDatabase, file_id: EditionedFileId) -> Option<Arc
|
|||
}
|
||||
}
|
||||
|
||||
fn file_text(db: &dyn SourceDatabase, file_id: FileId) -> Arc<str> {
|
||||
let bytes = db.compressed_file_text(file_id);
|
||||
let bytes =
|
||||
lz4_flex::decompress_size_prepended(&bytes).expect("lz4 decompression should not fail");
|
||||
let text = std::str::from_utf8(&bytes).expect("file contents should be valid UTF-8");
|
||||
Arc::from(text)
|
||||
}
|
||||
|
||||
/// We don't want to give HIR knowledge of source roots, hence we extract these
|
||||
/// methods into a separate DB.
|
||||
#[salsa::query_group(SourceDatabaseExtStorage)]
|
||||
pub trait SourceDatabaseExt: SourceDatabase {
|
||||
#[salsa::input]
|
||||
fn compressed_file_text(&self, file_id: FileId) -> Arc<[u8]>;
|
||||
|
||||
#[salsa::lru]
|
||||
fn file_text(&self, file_id: FileId) -> Arc<str>;
|
||||
|
||||
#[salsa::query_group(SourceRootDatabaseStorage)]
|
||||
pub trait SourceRootDatabase: SourceDatabase {
|
||||
/// Path to a file, relative to the root of its source root.
|
||||
/// Source root of the file.
|
||||
#[salsa::input]
|
||||
|
@ -121,15 +128,7 @@ pub trait SourceDatabaseExt: SourceDatabase {
|
|||
fn source_root_crates(&self, id: SourceRootId) -> Arc<[CrateId]>;
|
||||
}
|
||||
|
||||
fn file_text(db: &dyn SourceDatabaseExt, file_id: FileId) -> Arc<str> {
|
||||
let bytes = db.compressed_file_text(file_id);
|
||||
let bytes =
|
||||
lz4_flex::decompress_size_prepended(&bytes).expect("lz4 decompression should not fail");
|
||||
let text = std::str::from_utf8(&bytes).expect("file contents should be valid UTF-8");
|
||||
Arc::from(text)
|
||||
}
|
||||
|
||||
pub trait SourceDatabaseExt2 {
|
||||
pub trait SourceDatabaseFileInputExt {
|
||||
fn set_file_text(&mut self, file_id: FileId, text: &str) {
|
||||
self.set_file_text_with_durability(file_id, text, Durability::LOW);
|
||||
}
|
||||
|
@ -142,7 +141,7 @@ pub trait SourceDatabaseExt2 {
|
|||
);
|
||||
}
|
||||
|
||||
impl<Db: ?Sized + SourceDatabaseExt> SourceDatabaseExt2 for Db {
|
||||
impl<Db: ?Sized + SourceRootDatabase> SourceDatabaseFileInputExt for Db {
|
||||
fn set_file_text_with_durability(
|
||||
&mut self,
|
||||
file_id: FileId,
|
||||
|
@ -159,7 +158,7 @@ impl<Db: ?Sized + SourceDatabaseExt> SourceDatabaseExt2 for Db {
|
|||
}
|
||||
}
|
||||
|
||||
fn source_root_crates(db: &dyn SourceDatabaseExt, id: SourceRootId) -> Arc<[CrateId]> {
|
||||
fn source_root_crates(db: &dyn SourceRootDatabase, id: SourceRootId) -> Arc<[CrateId]> {
|
||||
let graph = db.crate_graph();
|
||||
let mut crates = graph
|
||||
.iter()
|
||||
|
@ -173,13 +172,12 @@ fn source_root_crates(db: &dyn SourceDatabaseExt, id: SourceRootId) -> Arc<[Crat
|
|||
crates.into_iter().collect()
|
||||
}
|
||||
|
||||
/// Silly workaround for cyclic deps between the traits
|
||||
// FIXME: Would be nice to get rid of this somehow
|
||||
/// Silly workaround for cyclic deps due to the SourceRootDatabase and SourceDatabase split
|
||||
/// regarding FileLoader
|
||||
pub struct FileLoaderDelegate<T>(pub T);
|
||||
|
||||
impl<T: SourceDatabaseExt> FileLoader for FileLoaderDelegate<&'_ T> {
|
||||
fn file_text(&self, file_id: FileId) -> Arc<str> {
|
||||
SourceDatabaseExt::file_text(self.0, file_id)
|
||||
}
|
||||
impl<T: SourceRootDatabase> FileLoader for FileLoaderDelegate<&'_ T> {
|
||||
fn resolve_path(&self, path: AnchoredPath<'_>) -> Option<FileId> {
|
||||
// FIXME: this *somehow* should be platform agnostic...
|
||||
let source_root = self.0.file_source_root(path.anchor);
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
[package]
|
||||
name = "cfg"
|
||||
version = "0.0.0"
|
||||
description = "TBD"
|
||||
repository.workspace = true
|
||||
description = "Conditional compiling options, `cfg` attribute parser and evaluator for rust-analyzer."
|
||||
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
|
@ -28,7 +29,7 @@ arbitrary = "1.3.2"
|
|||
derive_arbitrary = "1.3.2"
|
||||
|
||||
# local deps
|
||||
mbe.workspace = true
|
||||
syntax-bridge.workspace = true
|
||||
syntax.workspace = true
|
||||
|
||||
[lints]
|
||||
|
|
|
@ -108,6 +108,14 @@ impl<'a> IntoIterator for &'a CfgOptions {
|
|||
}
|
||||
}
|
||||
|
||||
impl FromIterator<CfgAtom> for CfgOptions {
|
||||
fn from_iter<T: IntoIterator<Item = CfgAtom>>(iter: T) -> Self {
|
||||
let mut options = CfgOptions::default();
|
||||
options.extend(iter);
|
||||
options
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default, Clone, Debug, PartialEq, Eq)]
|
||||
pub struct CfgDiff {
|
||||
// Invariants: No duplicates, no atom that's both in `enable` and `disable`.
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
use arbitrary::{Arbitrary, Unstructured};
|
||||
use expect_test::{expect, Expect};
|
||||
use intern::Symbol;
|
||||
use mbe::{syntax_node_to_token_tree, DocCommentDesugarMode, DummyTestSpanMap, DUMMY};
|
||||
use syntax::{ast, AstNode, Edition};
|
||||
use syntax_bridge::{
|
||||
dummy_test_span_utils::{DummyTestSpanMap, DUMMY},
|
||||
syntax_node_to_token_tree, DocCommentDesugarMode,
|
||||
};
|
||||
|
||||
use crate::{CfgAtom, CfgExpr, CfgOptions, DnfExpr};
|
||||
|
||||
|
|
|
@ -1,30 +0,0 @@
|
|||
[package]
|
||||
name = "flycheck"
|
||||
version = "0.0.0"
|
||||
description = "TBD"
|
||||
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
rust-version.workspace = true
|
||||
|
||||
[lib]
|
||||
doctest = false
|
||||
|
||||
[dependencies]
|
||||
cargo_metadata.workspace = true
|
||||
crossbeam-channel.workspace = true
|
||||
tracing.workspace = true
|
||||
rustc-hash.workspace = true
|
||||
serde_json.workspace = true
|
||||
serde.workspace = true
|
||||
process-wrap.workspace = true
|
||||
|
||||
# local deps
|
||||
paths.workspace = true
|
||||
stdx.workspace = true
|
||||
toolchain.workspace = true
|
||||
project-model.workspace = true
|
||||
|
||||
[lints]
|
||||
workspace = true
|
|
@ -1,7 +1,8 @@
|
|||
[package]
|
||||
name = "hir-def"
|
||||
version = "0.0.0"
|
||||
description = "TBD"
|
||||
repository.workspace = true
|
||||
description = "RPC Api for the `proc-macro-srv` crate of rust-analyzer."
|
||||
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
|
@ -52,7 +53,7 @@ expect-test.workspace = true
|
|||
# local deps
|
||||
test-utils.workspace = true
|
||||
test-fixture.workspace = true
|
||||
|
||||
syntax-bridge.workspace = true
|
||||
[features]
|
||||
in-rust-tree = ["hir-expand/in-rust-tree"]
|
||||
|
||||
|
|
|
@ -657,9 +657,9 @@ mod tests {
|
|||
use triomphe::Arc;
|
||||
|
||||
use hir_expand::span_map::{RealSpanMap, SpanMap};
|
||||
use mbe::{syntax_node_to_token_tree, DocCommentDesugarMode};
|
||||
use span::FileId;
|
||||
use syntax::{ast, AstNode, TextRange};
|
||||
use syntax_bridge::{syntax_node_to_token_tree, DocCommentDesugarMode};
|
||||
|
||||
use crate::attr::{DocAtom, DocExpr};
|
||||
|
||||
|
|
|
@ -118,6 +118,7 @@ pub enum BodyDiagnostic {
|
|||
MacroError { node: InFile<AstPtr<ast::MacroCall>>, err: ExpandError },
|
||||
UnresolvedMacroCall { node: InFile<AstPtr<ast::MacroCall>>, path: ModPath },
|
||||
UnreachableLabel { node: InFile<AstPtr<ast::Lifetime>>, name: Name },
|
||||
AwaitOutsideOfAsync { node: InFile<AstPtr<ast::AwaitExpr>>, location: String },
|
||||
UndeclaredLabel { node: InFile<AstPtr<ast::Lifetime>>, name: Name },
|
||||
}
|
||||
|
||||
|
@ -157,7 +158,7 @@ impl Body {
|
|||
}),
|
||||
)
|
||||
});
|
||||
is_async_fn = data.has_async_kw();
|
||||
is_async_fn = data.is_async();
|
||||
src.map(|it| it.body().map(ast::Expr::from))
|
||||
}
|
||||
DefWithBodyId::ConstId(c) => {
|
||||
|
|
|
@ -72,6 +72,7 @@ pub(super) fn lower(
|
|||
is_lowering_coroutine: false,
|
||||
label_ribs: Vec::new(),
|
||||
current_binding_owner: None,
|
||||
awaitable_context: None,
|
||||
}
|
||||
.collect(params, body, is_async_fn)
|
||||
}
|
||||
|
@ -100,6 +101,8 @@ struct ExprCollector<'a> {
|
|||
// resolution
|
||||
label_ribs: Vec<LabelRib>,
|
||||
current_binding_owner: Option<ExprId>,
|
||||
|
||||
awaitable_context: Option<Awaitable>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
|
@ -135,6 +138,11 @@ impl RibKind {
|
|||
}
|
||||
}
|
||||
|
||||
enum Awaitable {
|
||||
Yes,
|
||||
No(&'static str),
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
struct BindingList {
|
||||
map: FxHashMap<Name, BindingId>,
|
||||
|
@ -180,6 +188,18 @@ impl ExprCollector<'_> {
|
|||
body: Option<ast::Expr>,
|
||||
is_async_fn: bool,
|
||||
) -> (Body, BodySourceMap) {
|
||||
self.awaitable_context.replace(if is_async_fn {
|
||||
Awaitable::Yes
|
||||
} else {
|
||||
match self.owner {
|
||||
DefWithBodyId::FunctionId(..) => Awaitable::No("non-async function"),
|
||||
DefWithBodyId::StaticId(..) => Awaitable::No("static"),
|
||||
DefWithBodyId::ConstId(..) | DefWithBodyId::InTypeConstId(..) => {
|
||||
Awaitable::No("constant")
|
||||
}
|
||||
DefWithBodyId::VariantId(..) => Awaitable::No("enum variant"),
|
||||
}
|
||||
});
|
||||
if let Some((param_list, mut attr_enabled)) = param_list {
|
||||
let mut params = vec![];
|
||||
if let Some(self_param) =
|
||||
|
@ -280,31 +300,40 @@ impl ExprCollector<'_> {
|
|||
}
|
||||
Some(ast::BlockModifier::Async(_)) => {
|
||||
self.with_label_rib(RibKind::Closure, |this| {
|
||||
this.collect_block_(e, |id, statements, tail| Expr::Async {
|
||||
id,
|
||||
statements,
|
||||
tail,
|
||||
this.with_awaitable_block(Awaitable::Yes, |this| {
|
||||
this.collect_block_(e, |id, statements, tail| Expr::Async {
|
||||
id,
|
||||
statements,
|
||||
tail,
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
Some(ast::BlockModifier::Const(_)) => {
|
||||
self.with_label_rib(RibKind::Constant, |this| {
|
||||
let (result_expr_id, prev_binding_owner) =
|
||||
this.initialize_binding_owner(syntax_ptr);
|
||||
let inner_expr = this.collect_block(e);
|
||||
let it = this.db.intern_anonymous_const(ConstBlockLoc {
|
||||
parent: this.owner,
|
||||
root: inner_expr,
|
||||
});
|
||||
this.body.exprs[result_expr_id] = Expr::Const(it);
|
||||
this.current_binding_owner = prev_binding_owner;
|
||||
result_expr_id
|
||||
this.with_awaitable_block(Awaitable::No("constant block"), |this| {
|
||||
let (result_expr_id, prev_binding_owner) =
|
||||
this.initialize_binding_owner(syntax_ptr);
|
||||
let inner_expr = this.collect_block(e);
|
||||
let it = this.db.intern_anonymous_const(ConstBlockLoc {
|
||||
parent: this.owner,
|
||||
root: inner_expr,
|
||||
});
|
||||
this.body.exprs[result_expr_id] = Expr::Const(it);
|
||||
this.current_binding_owner = prev_binding_owner;
|
||||
result_expr_id
|
||||
})
|
||||
})
|
||||
}
|
||||
// FIXME
|
||||
Some(ast::BlockModifier::AsyncGen(_)) | Some(ast::BlockModifier::Gen(_)) | None => {
|
||||
self.collect_block(e)
|
||||
Some(ast::BlockModifier::AsyncGen(_)) => {
|
||||
self.with_awaitable_block(Awaitable::Yes, |this| this.collect_block(e))
|
||||
}
|
||||
Some(ast::BlockModifier::Gen(_)) => self
|
||||
.with_awaitable_block(Awaitable::No("non-async gen block"), |this| {
|
||||
this.collect_block(e)
|
||||
}),
|
||||
None => self.collect_block(e),
|
||||
},
|
||||
ast::Expr::LoopExpr(e) => {
|
||||
let label = e.label().map(|label| self.collect_label(label));
|
||||
|
@ -469,6 +498,12 @@ impl ExprCollector<'_> {
|
|||
}
|
||||
ast::Expr::AwaitExpr(e) => {
|
||||
let expr = self.collect_expr_opt(e.expr());
|
||||
if let Awaitable::No(location) = self.is_lowering_awaitable_block() {
|
||||
self.source_map.diagnostics.push(BodyDiagnostic::AwaitOutsideOfAsync {
|
||||
node: InFile::new(self.expander.current_file_id(), AstPtr::new(&e)),
|
||||
location: location.to_string(),
|
||||
});
|
||||
}
|
||||
self.alloc_expr(Expr::Await { expr }, syntax_ptr)
|
||||
}
|
||||
ast::Expr::TryExpr(e) => self.collect_try_operator(syntax_ptr, e),
|
||||
|
@ -527,7 +562,13 @@ impl ExprCollector<'_> {
|
|||
let prev_is_lowering_coroutine = mem::take(&mut this.is_lowering_coroutine);
|
||||
let prev_try_block_label = this.current_try_block_label.take();
|
||||
|
||||
let body = this.collect_expr_opt(e.body());
|
||||
let awaitable = if e.async_token().is_some() {
|
||||
Awaitable::Yes
|
||||
} else {
|
||||
Awaitable::No("non-async closure")
|
||||
};
|
||||
let body =
|
||||
this.with_awaitable_block(awaitable, |this| this.collect_expr_opt(e.body()));
|
||||
|
||||
let closure_kind = if this.is_lowering_coroutine {
|
||||
let movability = if e.static_token().is_some() {
|
||||
|
@ -2082,6 +2123,21 @@ impl ExprCollector<'_> {
|
|||
fn alloc_label_desugared(&mut self, label: Label) -> LabelId {
|
||||
self.body.labels.alloc(label)
|
||||
}
|
||||
|
||||
fn is_lowering_awaitable_block(&self) -> &Awaitable {
|
||||
self.awaitable_context.as_ref().unwrap_or(&Awaitable::No("unknown"))
|
||||
}
|
||||
|
||||
fn with_awaitable_block<T>(
|
||||
&mut self,
|
||||
awaitable: Awaitable,
|
||||
f: impl FnOnce(&mut Self) -> T,
|
||||
) -> T {
|
||||
let orig = self.awaitable_context.replace(awaitable);
|
||||
let res = f(self);
|
||||
self.awaitable_context = orig;
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
fn comma_follows_token(t: Option<syntax::SyntaxToken>) -> bool {
|
||||
|
|
|
@ -94,6 +94,12 @@ impl FunctionData {
|
|||
.filter(|it| !it.is_empty())
|
||||
.map(Box::new);
|
||||
let rustc_allow_incoherent_impl = attrs.by_key(&sym::rustc_allow_incoherent_impl).exists();
|
||||
if flags.contains(FnFlags::HAS_UNSAFE_KW)
|
||||
&& !crate_graph[krate].edition.at_least_2024()
|
||||
&& attrs.by_key(&sym::rustc_deprecated_safe_2024).exists()
|
||||
{
|
||||
flags.remove(FnFlags::HAS_UNSAFE_KW);
|
||||
}
|
||||
|
||||
Arc::new(FunctionData {
|
||||
name: func.name.clone(),
|
||||
|
@ -126,19 +132,19 @@ impl FunctionData {
|
|||
self.flags.contains(FnFlags::HAS_SELF_PARAM)
|
||||
}
|
||||
|
||||
pub fn has_default_kw(&self) -> bool {
|
||||
pub fn is_default(&self) -> bool {
|
||||
self.flags.contains(FnFlags::HAS_DEFAULT_KW)
|
||||
}
|
||||
|
||||
pub fn has_const_kw(&self) -> bool {
|
||||
pub fn is_const(&self) -> bool {
|
||||
self.flags.contains(FnFlags::HAS_CONST_KW)
|
||||
}
|
||||
|
||||
pub fn has_async_kw(&self) -> bool {
|
||||
pub fn is_async(&self) -> bool {
|
||||
self.flags.contains(FnFlags::HAS_ASYNC_KW)
|
||||
}
|
||||
|
||||
pub fn has_unsafe_kw(&self) -> bool {
|
||||
pub fn is_unsafe(&self) -> bool {
|
||||
self.flags.contains(FnFlags::HAS_UNSAFE_KW)
|
||||
}
|
||||
|
||||
|
|
|
@ -160,7 +160,7 @@ pub trait DefDatabase: InternDatabase + ExpandDatabase + Upcast<dyn ExpandDataba
|
|||
fn const_data(&self, konst: ConstId) -> Arc<ConstData>;
|
||||
|
||||
#[salsa::invoke(StaticData::static_data_query)]
|
||||
fn static_data(&self, konst: StaticId) -> Arc<StaticData>;
|
||||
fn static_data(&self, statik: StaticId) -> Arc<StaticData>;
|
||||
|
||||
#[salsa::invoke(Macro2Data::macro2_data_query)]
|
||||
fn macro2_data(&self, makro: Macro2Id) -> Arc<Macro2Data>;
|
||||
|
@ -240,14 +240,14 @@ pub trait DefDatabase: InternDatabase + ExpandDatabase + Upcast<dyn ExpandDataba
|
|||
|
||||
fn crate_supports_no_std(&self, crate_id: CrateId) -> bool;
|
||||
|
||||
fn include_macro_invoc(&self, crate_id: CrateId) -> Vec<(MacroCallId, EditionedFileId)>;
|
||||
fn include_macro_invoc(&self, crate_id: CrateId) -> Arc<[(MacroCallId, EditionedFileId)]>;
|
||||
}
|
||||
|
||||
// return: macro call id and include file id
|
||||
fn include_macro_invoc(
|
||||
db: &dyn DefDatabase,
|
||||
krate: CrateId,
|
||||
) -> Vec<(MacroCallId, EditionedFileId)> {
|
||||
) -> Arc<[(MacroCallId, EditionedFileId)]> {
|
||||
db.crate_def_map(krate)
|
||||
.modules
|
||||
.values()
|
||||
|
|
|
@ -50,13 +50,13 @@ pub fn find_path(
|
|||
prefix: prefix_kind,
|
||||
cfg,
|
||||
ignore_local_imports,
|
||||
is_std_item: db.crate_graph()[item_module.krate()].origin.is_lang(),
|
||||
from,
|
||||
from_def_map: &from.def_map(db),
|
||||
fuel: Cell::new(FIND_PATH_FUEL),
|
||||
},
|
||||
item,
|
||||
MAX_PATH_LEN,
|
||||
db.crate_graph()[item_module.krate()].origin.is_lang(),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -98,20 +98,16 @@ struct FindPathCtx<'db> {
|
|||
prefix: PrefixKind,
|
||||
cfg: ImportPathConfig,
|
||||
ignore_local_imports: bool,
|
||||
is_std_item: bool,
|
||||
from: ModuleId,
|
||||
from_def_map: &'db DefMap,
|
||||
fuel: Cell<usize>,
|
||||
}
|
||||
|
||||
/// Attempts to find a path to refer to the given `item` visible from the `from` ModuleId
|
||||
fn find_path_inner(
|
||||
ctx: &FindPathCtx<'_>,
|
||||
item: ItemInNs,
|
||||
max_len: usize,
|
||||
is_std_item: bool,
|
||||
) -> Option<ModPath> {
|
||||
fn find_path_inner(ctx: &FindPathCtx<'_>, item: ItemInNs, max_len: usize) -> Option<ModPath> {
|
||||
// - if the item is a module, jump straight to module search
|
||||
if !is_std_item {
|
||||
if !ctx.is_std_item {
|
||||
if let ItemInNs::Types(ModuleDefId::ModuleId(module_id)) = item {
|
||||
return find_path_for_module(ctx, &mut FxHashSet::default(), module_id, true, max_len)
|
||||
.map(|choice| choice.path);
|
||||
|
@ -138,12 +134,9 @@ fn find_path_inner(
|
|||
|
||||
if let Some(ModuleDefId::EnumVariantId(variant)) = item.as_module_def_id() {
|
||||
// - if the item is an enum variant, refer to it via the enum
|
||||
if let Some(mut path) = find_path_inner(
|
||||
ctx,
|
||||
ItemInNs::Types(variant.lookup(ctx.db).parent.into()),
|
||||
max_len,
|
||||
is_std_item,
|
||||
) {
|
||||
if let Some(mut path) =
|
||||
find_path_inner(ctx, ItemInNs::Types(variant.lookup(ctx.db).parent.into()), max_len)
|
||||
{
|
||||
path.push_segment(ctx.db.enum_variant_data(variant).name.clone());
|
||||
return Some(path);
|
||||
}
|
||||
|
@ -152,16 +145,6 @@ fn find_path_inner(
|
|||
// variant somewhere
|
||||
}
|
||||
|
||||
if is_std_item {
|
||||
// The item we are searching for comes from the sysroot libraries, so skip prefer looking in
|
||||
// the sysroot libraries directly.
|
||||
// We do need to fallback as the item in question could be re-exported by another crate
|
||||
// while not being a transitive dependency of the current crate.
|
||||
if let Some(choice) = find_in_sysroot(ctx, &mut FxHashSet::default(), item, max_len) {
|
||||
return Some(choice.path);
|
||||
}
|
||||
}
|
||||
|
||||
let mut best_choice = None;
|
||||
calculate_best_path(ctx, &mut FxHashSet::default(), item, max_len, &mut best_choice);
|
||||
best_choice.map(|choice| choice.path)
|
||||
|
@ -366,6 +349,12 @@ fn calculate_best_path(
|
|||
// Item was defined in the same crate that wants to import it. It cannot be found in any
|
||||
// dependency in this case.
|
||||
calculate_best_path_local(ctx, visited_modules, item, max_len, best_choice)
|
||||
} else if ctx.is_std_item {
|
||||
// The item we are searching for comes from the sysroot libraries, so skip prefer looking in
|
||||
// the sysroot libraries directly.
|
||||
// We do need to fallback as the item in question could be re-exported by another crate
|
||||
// while not being a transitive dependency of the current crate.
|
||||
find_in_sysroot(ctx, visited_modules, item, max_len, best_choice)
|
||||
} else {
|
||||
// Item was defined in some upstream crate. This means that it must be exported from one,
|
||||
// too (unless we can't name it at all). It could *also* be (re)exported by the same crate
|
||||
|
@ -382,10 +371,10 @@ fn find_in_sysroot(
|
|||
visited_modules: &mut FxHashSet<(ItemInNs, ModuleId)>,
|
||||
item: ItemInNs,
|
||||
max_len: usize,
|
||||
) -> Option<Choice> {
|
||||
best_choice: &mut Option<Choice>,
|
||||
) {
|
||||
let crate_graph = ctx.db.crate_graph();
|
||||
let dependencies = &crate_graph[ctx.from.krate].dependencies;
|
||||
let mut best_choice = None;
|
||||
let mut search = |lang, best_choice: &mut _| {
|
||||
if let Some(dep) = dependencies.iter().filter(|it| it.is_sysroot()).find(|dep| {
|
||||
match crate_graph[dep.crate_id].origin {
|
||||
|
@ -397,29 +386,31 @@ fn find_in_sysroot(
|
|||
}
|
||||
};
|
||||
if ctx.cfg.prefer_no_std {
|
||||
search(LangCrateOrigin::Core, &mut best_choice);
|
||||
search(LangCrateOrigin::Core, best_choice);
|
||||
if matches!(best_choice, Some(Choice { stability: Stable, .. })) {
|
||||
return best_choice;
|
||||
return;
|
||||
}
|
||||
search(LangCrateOrigin::Std, &mut best_choice);
|
||||
search(LangCrateOrigin::Std, best_choice);
|
||||
if matches!(best_choice, Some(Choice { stability: Stable, .. })) {
|
||||
return best_choice;
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
search(LangCrateOrigin::Std, &mut best_choice);
|
||||
search(LangCrateOrigin::Std, best_choice);
|
||||
if matches!(best_choice, Some(Choice { stability: Stable, .. })) {
|
||||
return best_choice;
|
||||
return;
|
||||
}
|
||||
search(LangCrateOrigin::Core, &mut best_choice);
|
||||
search(LangCrateOrigin::Core, best_choice);
|
||||
if matches!(best_choice, Some(Choice { stability: Stable, .. })) {
|
||||
return best_choice;
|
||||
return;
|
||||
}
|
||||
}
|
||||
let mut best_choice = None;
|
||||
dependencies.iter().filter(|it| it.is_sysroot()).for_each(|dep| {
|
||||
find_in_dep(ctx, visited_modules, item, max_len, &mut best_choice, dep.crate_id);
|
||||
});
|
||||
best_choice
|
||||
dependencies
|
||||
.iter()
|
||||
.filter(|it| it.is_sysroot())
|
||||
.chain(dependencies.iter().filter(|it| !it.is_sysroot()))
|
||||
.for_each(|dep| {
|
||||
find_in_dep(ctx, visited_modules, item, max_len, best_choice, dep.crate_id);
|
||||
});
|
||||
}
|
||||
|
||||
fn find_in_dep(
|
||||
|
@ -491,6 +482,7 @@ fn calculate_best_path_local(
|
|||
);
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Choice {
|
||||
path: ModPath,
|
||||
/// The length in characters of the path
|
||||
|
@ -676,6 +668,7 @@ mod tests {
|
|||
path: &str,
|
||||
prefer_prelude: bool,
|
||||
prefer_absolute: bool,
|
||||
prefer_no_std: bool,
|
||||
expect: Expect,
|
||||
) {
|
||||
let (db, pos) = TestDB::with_position(ra_fixture);
|
||||
|
@ -717,7 +710,7 @@ mod tests {
|
|||
module,
|
||||
prefix,
|
||||
ignore_local_imports,
|
||||
ImportPathConfig { prefer_no_std: false, prefer_prelude, prefer_absolute },
|
||||
ImportPathConfig { prefer_no_std, prefer_prelude, prefer_absolute },
|
||||
);
|
||||
format_to!(
|
||||
res,
|
||||
|
@ -732,15 +725,19 @@ mod tests {
|
|||
}
|
||||
|
||||
fn check_found_path(ra_fixture: &str, path: &str, expect: Expect) {
|
||||
check_found_path_(ra_fixture, path, false, false, expect);
|
||||
check_found_path_(ra_fixture, path, false, false, false, expect);
|
||||
}
|
||||
|
||||
fn check_found_path_prelude(ra_fixture: &str, path: &str, expect: Expect) {
|
||||
check_found_path_(ra_fixture, path, true, false, expect);
|
||||
check_found_path_(ra_fixture, path, true, false, false, expect);
|
||||
}
|
||||
|
||||
fn check_found_path_absolute(ra_fixture: &str, path: &str, expect: Expect) {
|
||||
check_found_path_(ra_fixture, path, false, true, expect);
|
||||
check_found_path_(ra_fixture, path, false, true, false, expect);
|
||||
}
|
||||
|
||||
fn check_found_path_prefer_no_std(ra_fixture: &str, path: &str, expect: Expect) {
|
||||
check_found_path_(ra_fixture, path, false, false, true, expect);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -1361,9 +1358,66 @@ pub mod sync {
|
|||
"#]],
|
||||
);
|
||||
}
|
||||
#[test]
|
||||
fn prefer_core_paths_over_std_for_mod_reexport() {
|
||||
check_found_path_prefer_no_std(
|
||||
r#"
|
||||
//- /main.rs crate:main deps:core,std
|
||||
|
||||
$0
|
||||
|
||||
//- /stdlib.rs crate:std deps:core
|
||||
|
||||
pub use core::pin;
|
||||
|
||||
//- /corelib.rs crate:core
|
||||
|
||||
pub mod pin {
|
||||
pub struct Pin;
|
||||
}
|
||||
"#,
|
||||
"std::pin::Pin",
|
||||
expect![[r#"
|
||||
Plain (imports ✔): core::pin::Pin
|
||||
Plain (imports ✖): core::pin::Pin
|
||||
ByCrate(imports ✔): core::pin::Pin
|
||||
ByCrate(imports ✖): core::pin::Pin
|
||||
BySelf (imports ✔): core::pin::Pin
|
||||
BySelf (imports ✖): core::pin::Pin
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn prefer_core_paths_over_std() {
|
||||
check_found_path_prefer_no_std(
|
||||
r#"
|
||||
//- /main.rs crate:main deps:core,std
|
||||
|
||||
$0
|
||||
|
||||
//- /std.rs crate:std deps:core
|
||||
|
||||
pub mod fmt {
|
||||
pub use core::fmt::Error;
|
||||
}
|
||||
|
||||
//- /zzz.rs crate:core
|
||||
|
||||
pub mod fmt {
|
||||
pub struct Error;
|
||||
}
|
||||
"#,
|
||||
"core::fmt::Error",
|
||||
expect![[r#"
|
||||
Plain (imports ✔): core::fmt::Error
|
||||
Plain (imports ✖): core::fmt::Error
|
||||
ByCrate(imports ✔): core::fmt::Error
|
||||
ByCrate(imports ✖): core::fmt::Error
|
||||
BySelf (imports ✔): core::fmt::Error
|
||||
BySelf (imports ✖): core::fmt::Error
|
||||
"#]],
|
||||
);
|
||||
check_found_path(
|
||||
r#"
|
||||
//- /main.rs crate:main deps:core,std
|
||||
|
@ -1878,10 +1932,9 @@ pub mod ops {
|
|||
|
||||
#[test]
|
||||
fn respect_unstable_modules() {
|
||||
check_found_path(
|
||||
check_found_path_prefer_no_std(
|
||||
r#"
|
||||
//- /main.rs crate:main deps:std,core
|
||||
#![no_std]
|
||||
extern crate std;
|
||||
$0
|
||||
//- /longer.rs crate:std deps:core
|
||||
|
|
|
@ -105,7 +105,7 @@ use crate::{
|
|||
|
||||
type FxIndexMap<K, V> =
|
||||
indexmap::IndexMap<K, V, std::hash::BuildHasherDefault<rustc_hash::FxHasher>>;
|
||||
/// A wrapper around two booleans, [`ImportPathConfig::prefer_no_std`] and [`ImportPathConfig::prefer_prelude`].
|
||||
/// A wrapper around three booleans
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, Copy)]
|
||||
pub struct ImportPathConfig {
|
||||
/// If true, prefer to unconditionally use imports of the `core` and `alloc` crate
|
||||
|
|
|
@ -1201,7 +1201,6 @@ macro_rules! m {
|
|||
|
||||
#[test]
|
||||
fn test_meta_doc_comments() {
|
||||
cov_mark::check!(test_meta_doc_comments);
|
||||
check(
|
||||
r#"
|
||||
macro_rules! m {
|
||||
|
|
|
@ -317,9 +317,9 @@ impl ProcMacroExpander for IdentityWhenValidProcMacroExpander {
|
|||
_: Span,
|
||||
_: Span,
|
||||
) -> Result<Subtree, ProcMacroExpansionError> {
|
||||
let (parse, _) = ::mbe::token_tree_to_syntax_node(
|
||||
let (parse, _) = syntax_bridge::token_tree_to_syntax_node(
|
||||
subtree,
|
||||
::mbe::TopEntryPoint::MacroItems,
|
||||
syntax_bridge::TopEntryPoint::MacroItems,
|
||||
span::Edition::CURRENT,
|
||||
);
|
||||
if parse.errors().is_empty() {
|
||||
|
|
|
@ -56,7 +56,6 @@ use crate::{
|
|||
};
|
||||
|
||||
static GLOB_RECURSION_LIMIT: Limit = Limit::new(100);
|
||||
static EXPANSION_DEPTH_LIMIT: Limit = Limit::new(128);
|
||||
static FIXED_POINT_LIMIT: Limit = Limit::new(8192);
|
||||
|
||||
pub(super) fn collect_defs(db: &dyn DefDatabase, def_map: DefMap, tree_id: TreeId) -> DefMap {
|
||||
|
@ -1440,7 +1439,14 @@ impl DefCollector<'_> {
|
|||
depth: usize,
|
||||
container: ItemContainerId,
|
||||
) {
|
||||
if EXPANSION_DEPTH_LIMIT.check(depth).is_err() {
|
||||
let recursion_limit = self.def_map.recursion_limit() as usize;
|
||||
let recursion_limit = Limit::new(if cfg!(test) {
|
||||
// Without this, `body::tests::your_stack_belongs_to_me` stack-overflows in debug
|
||||
std::cmp::min(32, recursion_limit)
|
||||
} else {
|
||||
recursion_limit
|
||||
});
|
||||
if recursion_limit.check(depth).is_err() {
|
||||
cov_mark::hit!(macro_expansion_overflow);
|
||||
tracing::warn!("macro expansion is too deep");
|
||||
return;
|
||||
|
@ -2003,7 +2009,7 @@ impl ModCollector<'_, '_> {
|
|||
Err(cfg) => {
|
||||
self.emit_unconfigured_diagnostic(
|
||||
self.tree_id,
|
||||
AttrOwner::TopLevel,
|
||||
AttrOwner::ModItem(module_id.into()),
|
||||
&cfg,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use base_db::{SourceDatabase, SourceDatabaseExt2 as _};
|
||||
use base_db::{SourceDatabase, SourceDatabaseFileInputExt as _};
|
||||
use test_fixture::WithFixture;
|
||||
|
||||
use crate::{db::DefDatabase, nameres::tests::TestDB, AdtId, ModuleDefId};
|
||||
|
|
|
@ -194,6 +194,11 @@ pub(super) fn lower_generic_args(
|
|||
match generic_arg {
|
||||
ast::GenericArg::TypeArg(type_arg) => {
|
||||
let type_ref = TypeRef::from_ast_opt(lower_ctx, type_arg.ty());
|
||||
type_ref.walk(&mut |tr| {
|
||||
if let TypeRef::ImplTrait(bounds) = tr {
|
||||
lower_ctx.update_impl_traits_bounds(bounds.clone());
|
||||
}
|
||||
});
|
||||
args.push(GenericArg::Type(type_ref));
|
||||
}
|
||||
ast::GenericArg::AssocTypeArg(assoc_type_arg) => {
|
||||
|
|
|
@ -19,7 +19,7 @@ use crate::{
|
|||
};
|
||||
|
||||
#[salsa::database(
|
||||
base_db::SourceDatabaseExtStorage,
|
||||
base_db::SourceRootDatabaseStorage,
|
||||
base_db::SourceDatabaseStorage,
|
||||
hir_expand::db::ExpandDatabaseStorage,
|
||||
crate::db::InternDatabaseStorage,
|
||||
|
@ -69,9 +69,6 @@ impl fmt::Debug for TestDB {
|
|||
impl panic::RefUnwindSafe for TestDB {}
|
||||
|
||||
impl FileLoader for TestDB {
|
||||
fn file_text(&self, file_id: FileId) -> Arc<str> {
|
||||
FileLoaderDelegate(self).file_text(file_id)
|
||||
}
|
||||
fn resolve_path(&self, path: AnchoredPath<'_>) -> Option<FileId> {
|
||||
FileLoaderDelegate(self).resolve_path(path)
|
||||
}
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
[package]
|
||||
name = "hir-expand"
|
||||
version = "0.0.0"
|
||||
description = "TBD"
|
||||
repository.workspace = true
|
||||
description = "Macro expansion for rust-analyzer."
|
||||
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
|
@ -33,6 +34,7 @@ mbe.workspace = true
|
|||
limit.workspace = true
|
||||
span.workspace = true
|
||||
parser.workspace = true
|
||||
syntax-bridge.workspace = true
|
||||
|
||||
[dev-dependencies]
|
||||
expect-test = "1.4.0"
|
||||
|
|
|
@ -6,14 +6,12 @@ use cfg::CfgExpr;
|
|||
use either::Either;
|
||||
use intern::{sym, Interned, Symbol};
|
||||
|
||||
use mbe::{
|
||||
desugar_doc_comment_text, syntax_node_to_token_tree, DelimiterKind, DocCommentDesugarMode,
|
||||
Punct,
|
||||
};
|
||||
use mbe::{DelimiterKind, Punct};
|
||||
use smallvec::{smallvec, SmallVec};
|
||||
use span::{Span, SyntaxContextId};
|
||||
use syntax::unescape;
|
||||
use syntax::{ast, match_ast, AstNode, AstToken, SyntaxNode};
|
||||
use syntax_bridge::{desugar_doc_comment_text, syntax_node_to_token_tree, DocCommentDesugarMode};
|
||||
use triomphe::ThinArc;
|
||||
|
||||
use crate::name::Name;
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
|
||||
use intern::sym;
|
||||
use itertools::izip;
|
||||
use mbe::DocCommentDesugarMode;
|
||||
use rustc_hash::FxHashSet;
|
||||
use span::{MacroCallId, Span};
|
||||
use stdx::never;
|
||||
use syntax_bridge::DocCommentDesugarMode;
|
||||
use tracing::debug;
|
||||
|
||||
use crate::{
|
||||
|
@ -209,9 +209,9 @@ struct BasicAdtInfo {
|
|||
}
|
||||
|
||||
fn parse_adt(tt: &tt::Subtree, call_site: Span) -> Result<BasicAdtInfo, ExpandError> {
|
||||
let (parsed, tm) = &mbe::token_tree_to_syntax_node(
|
||||
let (parsed, tm) = &syntax_bridge::token_tree_to_syntax_node(
|
||||
tt,
|
||||
mbe::TopEntryPoint::MacroItems,
|
||||
syntax_bridge::TopEntryPoint::MacroItems,
|
||||
parser::Edition::CURRENT_FIXME,
|
||||
);
|
||||
let macro_items = ast::MacroItems::cast(parsed.syntax_node())
|
||||
|
@ -268,7 +268,7 @@ fn parse_adt(tt: &tt::Subtree, call_site: Span) -> Result<BasicAdtInfo, ExpandEr
|
|||
match this {
|
||||
Some(it) => {
|
||||
param_type_set.insert(it.as_name());
|
||||
mbe::syntax_node_to_token_tree(
|
||||
syntax_bridge::syntax_node_to_token_tree(
|
||||
it.syntax(),
|
||||
tm,
|
||||
call_site,
|
||||
|
@ -282,7 +282,7 @@ fn parse_adt(tt: &tt::Subtree, call_site: Span) -> Result<BasicAdtInfo, ExpandEr
|
|||
};
|
||||
let bounds = match ¶m {
|
||||
ast::TypeOrConstParam::Type(it) => it.type_bound_list().map(|it| {
|
||||
mbe::syntax_node_to_token_tree(
|
||||
syntax_bridge::syntax_node_to_token_tree(
|
||||
it.syntax(),
|
||||
tm,
|
||||
call_site,
|
||||
|
@ -295,7 +295,7 @@ fn parse_adt(tt: &tt::Subtree, call_site: Span) -> Result<BasicAdtInfo, ExpandEr
|
|||
let ty = param
|
||||
.ty()
|
||||
.map(|ty| {
|
||||
mbe::syntax_node_to_token_tree(
|
||||
syntax_bridge::syntax_node_to_token_tree(
|
||||
ty.syntax(),
|
||||
tm,
|
||||
call_site,
|
||||
|
@ -316,7 +316,7 @@ fn parse_adt(tt: &tt::Subtree, call_site: Span) -> Result<BasicAdtInfo, ExpandEr
|
|||
let where_clause = if let Some(w) = where_clause {
|
||||
w.predicates()
|
||||
.map(|it| {
|
||||
mbe::syntax_node_to_token_tree(
|
||||
syntax_bridge::syntax_node_to_token_tree(
|
||||
it.syntax(),
|
||||
tm,
|
||||
call_site,
|
||||
|
@ -353,7 +353,7 @@ fn parse_adt(tt: &tt::Subtree, call_site: Span) -> Result<BasicAdtInfo, ExpandEr
|
|||
param_type_set.contains(&name).then_some(p)
|
||||
})
|
||||
.map(|it| {
|
||||
mbe::syntax_node_to_token_tree(
|
||||
syntax_bridge::syntax_node_to_token_tree(
|
||||
it.syntax(),
|
||||
tm,
|
||||
call_site,
|
||||
|
|
|
@ -4,13 +4,14 @@ use base_db::AnchoredPath;
|
|||
use cfg::CfgExpr;
|
||||
use either::Either;
|
||||
use intern::{sym, Symbol};
|
||||
use mbe::{parse_exprs_with_sep, parse_to_token_tree, DelimiterKind};
|
||||
use mbe::{expect_fragment, DelimiterKind};
|
||||
use span::{Edition, EditionedFileId, Span, SpanAnchor, SyntaxContextId, ROOT_ERASED_FILE_AST_ID};
|
||||
use stdx::format_to;
|
||||
use syntax::{
|
||||
format_smolstr,
|
||||
unescape::{unescape_byte, unescape_char, unescape_unicode, Mode},
|
||||
};
|
||||
use syntax_bridge::parse_to_token_tree;
|
||||
|
||||
use crate::{
|
||||
builtin::quote::{dollar_crate, quote},
|
||||
|
@ -228,20 +229,22 @@ fn assert_expand(
|
|||
span: Span,
|
||||
) -> ExpandResult<tt::Subtree> {
|
||||
let call_site_span = span_with_call_site_ctxt(db, span, id);
|
||||
let args = parse_exprs_with_sep(tt, ',', call_site_span, Edition::CURRENT_FIXME);
|
||||
|
||||
let mut iter = ::tt::iter::TtIter::new(tt);
|
||||
|
||||
let cond = expect_fragment(
|
||||
&mut iter,
|
||||
parser::PrefixEntryPoint::Expr,
|
||||
db.crate_graph()[id.lookup(db).krate].edition,
|
||||
tt::DelimSpan { open: tt.delimiter.open, close: tt.delimiter.close },
|
||||
);
|
||||
_ = iter.expect_char(',');
|
||||
let rest = iter.as_slice();
|
||||
|
||||
let dollar_crate = dollar_crate(span);
|
||||
let expanded = match &*args {
|
||||
[cond, panic_args @ ..] => {
|
||||
let comma = tt::Subtree {
|
||||
delimiter: tt::Delimiter::invisible_spanned(call_site_span),
|
||||
token_trees: Box::new([tt::TokenTree::Leaf(tt::Leaf::Punct(tt::Punct {
|
||||
char: ',',
|
||||
spacing: tt::Spacing::Alone,
|
||||
span: call_site_span,
|
||||
}))]),
|
||||
};
|
||||
let cond = cond.clone();
|
||||
let panic_args = itertools::Itertools::intersperse(panic_args.iter().cloned(), comma);
|
||||
let expanded = match cond.value {
|
||||
Some(cond) => {
|
||||
let panic_args = rest.iter().cloned();
|
||||
let mac = if use_panic_2021(db, span) {
|
||||
quote! {call_site_span => #dollar_crate::panic::panic_2021!(##panic_args) }
|
||||
} else {
|
||||
|
@ -253,10 +256,13 @@ fn assert_expand(
|
|||
}
|
||||
}}
|
||||
}
|
||||
[] => quote! {call_site_span =>{}},
|
||||
None => quote! {call_site_span =>{}},
|
||||
};
|
||||
|
||||
ExpandResult::ok(expanded)
|
||||
match cond.err {
|
||||
Some(err) => ExpandResult::new(expanded, err.into()),
|
||||
None => ExpandResult::ok(expanded),
|
||||
}
|
||||
}
|
||||
|
||||
fn file_expand(
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
//! Defines a unit of change that can applied to the database to get the next
|
||||
//! state. Changes are transactional.
|
||||
use base_db::{
|
||||
salsa::Durability, CrateGraph, CrateId, FileChange, SourceDatabaseExt, SourceRoot,
|
||||
salsa::Durability, CrateGraph, CrateId, FileChange, SourceRoot, SourceRootDatabase,
|
||||
TargetLayoutLoadResult, Version,
|
||||
};
|
||||
use la_arena::RawIdx;
|
||||
|
@ -23,7 +23,7 @@ impl ChangeWithProcMacros {
|
|||
Self::default()
|
||||
}
|
||||
|
||||
pub fn apply(self, db: &mut (impl ExpandDatabase + SourceDatabaseExt)) {
|
||||
pub fn apply(self, db: &mut (impl ExpandDatabase + SourceRootDatabase)) {
|
||||
self.source_change.apply(db);
|
||||
if let Some(proc_macros) = self.proc_macros {
|
||||
db.set_proc_macros_with_durability(Arc::new(proc_macros), Durability::HIGH);
|
||||
|
|
|
@ -3,10 +3,11 @@
|
|||
use base_db::{salsa, CrateId, SourceDatabase};
|
||||
use either::Either;
|
||||
use limit::Limit;
|
||||
use mbe::{syntax_node_to_token_tree, DocCommentDesugarMode, MatchedArmIndex};
|
||||
use mbe::MatchedArmIndex;
|
||||
use rustc_hash::FxHashSet;
|
||||
use span::{AstIdMap, EditionedFileId, Span, SyntaxContextData, SyntaxContextId};
|
||||
use syntax::{ast, AstNode, Parse, SyntaxElement, SyntaxError, SyntaxNode, SyntaxToken, T};
|
||||
use syntax_bridge::{syntax_node_to_token_tree, DocCommentDesugarMode};
|
||||
use triomphe::Arc;
|
||||
|
||||
use crate::{
|
||||
|
@ -165,7 +166,7 @@ pub fn expand_speculative(
|
|||
// Build the subtree and token mapping for the speculative args
|
||||
let (mut tt, undo_info) = match loc.kind {
|
||||
MacroCallKind::FnLike { .. } => (
|
||||
mbe::syntax_node_to_token_tree(
|
||||
syntax_bridge::syntax_node_to_token_tree(
|
||||
speculative_args,
|
||||
span_map,
|
||||
span,
|
||||
|
@ -178,7 +179,7 @@ pub fn expand_speculative(
|
|||
SyntaxFixupUndoInfo::NONE,
|
||||
),
|
||||
MacroCallKind::Attr { .. } if loc.def.is_attribute_derive() => (
|
||||
mbe::syntax_node_to_token_tree(
|
||||
syntax_bridge::syntax_node_to_token_tree(
|
||||
speculative_args,
|
||||
span_map,
|
||||
span,
|
||||
|
@ -213,7 +214,7 @@ pub fn expand_speculative(
|
|||
fixups.remove.extend(censor_cfg);
|
||||
|
||||
(
|
||||
mbe::syntax_node_to_token_tree_modified(
|
||||
syntax_bridge::syntax_node_to_token_tree_modified(
|
||||
speculative_args,
|
||||
span_map,
|
||||
fixups.append,
|
||||
|
@ -459,7 +460,7 @@ fn macro_arg(db: &dyn ExpandDatabase, id: MacroCallId) -> MacroArgResult {
|
|||
return dummy_tt(kind);
|
||||
}
|
||||
|
||||
let mut tt = mbe::syntax_node_to_token_tree(
|
||||
let mut tt = syntax_bridge::syntax_node_to_token_tree(
|
||||
tt.syntax(),
|
||||
map.as_ref(),
|
||||
span,
|
||||
|
@ -515,7 +516,7 @@ fn macro_arg(db: &dyn ExpandDatabase, id: MacroCallId) -> MacroArgResult {
|
|||
fixups.remove.extend(censor_cfg);
|
||||
|
||||
(
|
||||
mbe::syntax_node_to_token_tree_modified(
|
||||
syntax_bridge::syntax_node_to_token_tree_modified(
|
||||
syntax,
|
||||
map,
|
||||
fixups.append,
|
||||
|
@ -720,13 +721,13 @@ fn token_tree_to_syntax_node(
|
|||
edition: parser::Edition,
|
||||
) -> (Parse<SyntaxNode>, ExpansionSpanMap) {
|
||||
let entry_point = match expand_to {
|
||||
ExpandTo::Statements => mbe::TopEntryPoint::MacroStmts,
|
||||
ExpandTo::Items => mbe::TopEntryPoint::MacroItems,
|
||||
ExpandTo::Pattern => mbe::TopEntryPoint::Pattern,
|
||||
ExpandTo::Type => mbe::TopEntryPoint::Type,
|
||||
ExpandTo::Expr => mbe::TopEntryPoint::Expr,
|
||||
ExpandTo::Statements => syntax_bridge::TopEntryPoint::MacroStmts,
|
||||
ExpandTo::Items => syntax_bridge::TopEntryPoint::MacroItems,
|
||||
ExpandTo::Pattern => syntax_bridge::TopEntryPoint::Pattern,
|
||||
ExpandTo::Type => syntax_bridge::TopEntryPoint::Type,
|
||||
ExpandTo::Expr => syntax_bridge::TopEntryPoint::Expr,
|
||||
};
|
||||
mbe::token_tree_to_syntax_node(tt, entry_point, edition)
|
||||
syntax_bridge::token_tree_to_syntax_node(tt, entry_point, edition)
|
||||
}
|
||||
|
||||
fn check_tt_count(tt: &tt::Subtree) -> Result<(), ExpandResult<()>> {
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
|
||||
use base_db::CrateId;
|
||||
use intern::sym;
|
||||
use mbe::DocCommentDesugarMode;
|
||||
use span::{Edition, MacroCallId, Span, SyntaxContextId};
|
||||
use stdx::TupleExt;
|
||||
use syntax::{ast, AstNode};
|
||||
use syntax_bridge::DocCommentDesugarMode;
|
||||
use triomphe::Arc;
|
||||
|
||||
use crate::{
|
||||
|
@ -112,7 +112,7 @@ impl DeclarativeMacroExpander {
|
|||
ast::Macro::MacroRules(macro_rules) => (
|
||||
match macro_rules.token_tree() {
|
||||
Some(arg) => {
|
||||
let tt = mbe::syntax_node_to_token_tree(
|
||||
let tt = syntax_bridge::syntax_node_to_token_tree(
|
||||
arg.syntax(),
|
||||
map.as_ref(),
|
||||
map.span_for_range(
|
||||
|
@ -135,14 +135,14 @@ impl DeclarativeMacroExpander {
|
|||
let span =
|
||||
map.span_for_range(macro_def.macro_token().unwrap().text_range());
|
||||
let args = macro_def.args().map(|args| {
|
||||
mbe::syntax_node_to_token_tree(
|
||||
syntax_bridge::syntax_node_to_token_tree(
|
||||
args.syntax(),
|
||||
map.as_ref(),
|
||||
span,
|
||||
DocCommentDesugarMode::Mbe,
|
||||
)
|
||||
});
|
||||
let body = mbe::syntax_node_to_token_tree(
|
||||
let body = syntax_bridge::syntax_node_to_token_tree(
|
||||
body.syntax(),
|
||||
map.as_ref(),
|
||||
span,
|
||||
|
|
|
@ -19,9 +19,9 @@
|
|||
//!
|
||||
//! See the full discussion : <https://rust-lang.zulipchat.com/#narrow/stream/131828-t-compiler/topic/Eager.20expansion.20of.20built-in.20macros>
|
||||
use base_db::CrateId;
|
||||
use mbe::DocCommentDesugarMode;
|
||||
use span::SyntaxContextId;
|
||||
use syntax::{ted, Parse, SyntaxElement, SyntaxNode, TextSize, WalkEvent};
|
||||
use syntax_bridge::DocCommentDesugarMode;
|
||||
use triomphe::Arc;
|
||||
|
||||
use crate::{
|
||||
|
@ -82,7 +82,7 @@ pub fn expand_eager_macro_input(
|
|||
return ExpandResult { value: None, err };
|
||||
};
|
||||
|
||||
let mut subtree = mbe::syntax_node_to_token_tree(
|
||||
let mut subtree = syntax_bridge::syntax_node_to_token_tree(
|
||||
&expanded_eager_input,
|
||||
arg_map,
|
||||
span,
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
//! fix up syntax errors in the code we're passing to them.
|
||||
|
||||
use intern::sym;
|
||||
use mbe::DocCommentDesugarMode;
|
||||
use rustc_hash::{FxHashMap, FxHashSet};
|
||||
use smallvec::SmallVec;
|
||||
use span::{
|
||||
|
@ -14,6 +13,7 @@ use syntax::{
|
|||
ast::{self, AstNode, HasLoopBody},
|
||||
match_ast, SyntaxElement, SyntaxKind, SyntaxNode, TextRange, TextSize,
|
||||
};
|
||||
use syntax_bridge::DocCommentDesugarMode;
|
||||
use triomphe::Arc;
|
||||
use tt::Spacing;
|
||||
|
||||
|
@ -76,7 +76,8 @@ pub(crate) fn fixup_syntax(
|
|||
if can_handle_error(&node) && has_error_to_handle(&node) {
|
||||
remove.insert(node.clone().into());
|
||||
// the node contains an error node, we have to completely replace it by something valid
|
||||
let original_tree = mbe::syntax_node_to_token_tree(&node, span_map, call_site, mode);
|
||||
let original_tree =
|
||||
syntax_bridge::syntax_node_to_token_tree(&node, span_map, call_site, mode);
|
||||
let idx = original.len() as u32;
|
||||
original.push(original_tree);
|
||||
let span = span_map.span_for_range(node_range);
|
||||
|
@ -434,9 +435,9 @@ fn reverse_fixups_(tt: &mut Subtree, undo_info: &[Subtree]) {
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use expect_test::{expect, Expect};
|
||||
use mbe::DocCommentDesugarMode;
|
||||
use span::{Edition, EditionedFileId, FileId};
|
||||
use syntax::TextRange;
|
||||
use syntax_bridge::DocCommentDesugarMode;
|
||||
use triomphe::Arc;
|
||||
|
||||
use crate::{
|
||||
|
@ -483,7 +484,7 @@ mod tests {
|
|||
span_map.span_for_range(TextRange::empty(0.into())),
|
||||
DocCommentDesugarMode::Mbe,
|
||||
);
|
||||
let mut tt = mbe::syntax_node_to_token_tree_modified(
|
||||
let mut tt = syntax_bridge::syntax_node_to_token_tree_modified(
|
||||
&parsed.syntax_node(),
|
||||
span_map.as_ref(),
|
||||
fixups.append,
|
||||
|
@ -498,9 +499,9 @@ mod tests {
|
|||
expect.assert_eq(&actual);
|
||||
|
||||
// the fixed-up tree should be syntactically valid
|
||||
let (parse, _) = mbe::token_tree_to_syntax_node(
|
||||
let (parse, _) = syntax_bridge::token_tree_to_syntax_node(
|
||||
&tt,
|
||||
::mbe::TopEntryPoint::MacroItems,
|
||||
syntax_bridge::TopEntryPoint::MacroItems,
|
||||
parser::Edition::CURRENT,
|
||||
);
|
||||
assert!(
|
||||
|
@ -513,7 +514,7 @@ mod tests {
|
|||
|
||||
// the fixed-up + reversed version should be equivalent to the original input
|
||||
// modulo token IDs and `Punct`s' spacing.
|
||||
let original_as_tt = mbe::syntax_node_to_token_tree(
|
||||
let original_as_tt = syntax_bridge::syntax_node_to_token_tree(
|
||||
&parsed.syntax_node(),
|
||||
span_map.as_ref(),
|
||||
span_map.span_for_range(TextRange::empty(0.into())),
|
||||
|
|
|
@ -176,7 +176,12 @@ impl ExpandErrorKind {
|
|||
&ExpandErrorKind::MissingProcMacroExpander(def_crate) => {
|
||||
match db.proc_macros().get_error_for_crate(def_crate) {
|
||||
Some((e, hard_err)) => (e.to_owned(), hard_err),
|
||||
None => ("missing expander".to_owned(), true),
|
||||
None => (
|
||||
format!(
|
||||
"internal error: proc-macro map is missing error entry for crate {def_crate:?}"
|
||||
),
|
||||
true,
|
||||
),
|
||||
}
|
||||
}
|
||||
ExpandErrorKind::MacroDefinition => {
|
||||
|
|
|
@ -28,13 +28,13 @@ pub enum SpanMapRef<'a> {
|
|||
RealSpanMap(&'a RealSpanMap),
|
||||
}
|
||||
|
||||
impl mbe::SpanMapper<Span> for SpanMap {
|
||||
impl syntax_bridge::SpanMapper<Span> for SpanMap {
|
||||
fn span_for(&self, range: TextRange) -> Span {
|
||||
self.span_for_range(range)
|
||||
}
|
||||
}
|
||||
|
||||
impl mbe::SpanMapper<Span> for SpanMapRef<'_> {
|
||||
impl syntax_bridge::SpanMapper<Span> for SpanMapRef<'_> {
|
||||
fn span_for(&self, range: TextRange) -> Span {
|
||||
self.span_for_range(range)
|
||||
}
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
[package]
|
||||
name = "hir-ty"
|
||||
version = "0.0.0"
|
||||
description = "TBD"
|
||||
repository.workspace = true
|
||||
description = "The type system for rust-analyzer."
|
||||
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
|
|
|
@ -275,7 +275,7 @@ impl chalk_solve::RustIrDatabase<Interner> for ChalkContext<'_> {
|
|||
};
|
||||
chalk_ir::Binders::new(binders, bound)
|
||||
}
|
||||
crate::ImplTraitId::AssociatedTypeImplTrait(alias, idx) => {
|
||||
crate::ImplTraitId::TypeAliasImplTrait(alias, idx) => {
|
||||
let datas = self
|
||||
.db
|
||||
.type_alias_impl_traits(alias)
|
||||
|
|
|
@ -276,7 +276,7 @@ impl TyExt for Ty {
|
|||
data.substitute(Interner, &subst).into_value_and_skipped_binders().0
|
||||
})
|
||||
}
|
||||
ImplTraitId::AssociatedTypeImplTrait(alias, idx) => {
|
||||
ImplTraitId::TypeAliasImplTrait(alias, idx) => {
|
||||
db.type_alias_impl_traits(alias).map(|it| {
|
||||
let data =
|
||||
(*it).as_ref().map(|rpit| rpit.impl_traits[idx].bounds.clone());
|
||||
|
@ -295,7 +295,7 @@ impl TyExt for Ty {
|
|||
data.substitute(Interner, &opaque_ty.substitution)
|
||||
})
|
||||
}
|
||||
ImplTraitId::AssociatedTypeImplTrait(alias, idx) => {
|
||||
ImplTraitId::TypeAliasImplTrait(alias, idx) => {
|
||||
db.type_alias_impl_traits(alias).map(|it| {
|
||||
let data =
|
||||
(*it).as_ref().map(|rpit| rpit.impl_traits[idx].bounds.clone());
|
||||
|
|
|
@ -4,20 +4,25 @@
|
|||
|
||||
use std::fmt;
|
||||
|
||||
use chalk_solve::rust_ir::AdtKind;
|
||||
use either::Either;
|
||||
use hir_def::lang_item::LangItem;
|
||||
use hir_def::{resolver::HasResolver, AdtId, AssocItemId, DefWithBodyId, HasModule};
|
||||
use hir_def::{ItemContainerId, Lookup};
|
||||
use hir_def::{
|
||||
lang_item::LangItem,
|
||||
resolver::{HasResolver, ValueNs},
|
||||
AdtId, AssocItemId, DefWithBodyId, HasModule, ItemContainerId, Lookup,
|
||||
};
|
||||
use intern::sym;
|
||||
use itertools::Itertools;
|
||||
use rustc_hash::FxHashSet;
|
||||
use rustc_pattern_analysis::constructor::Constructor;
|
||||
use syntax::{ast, AstNode};
|
||||
use syntax::{
|
||||
ast::{self, UnaryOp},
|
||||
AstNode,
|
||||
};
|
||||
use tracing::debug;
|
||||
use triomphe::Arc;
|
||||
use typed_arena::Arena;
|
||||
|
||||
use crate::Interner;
|
||||
use crate::{
|
||||
db::HirDatabase,
|
||||
diagnostics::match_check::{
|
||||
|
@ -25,7 +30,7 @@ use crate::{
|
|||
pat_analysis::{self, DeconstructedPat, MatchCheckCtx, WitnessPat},
|
||||
},
|
||||
display::HirDisplay,
|
||||
InferenceResult, Ty, TyExt,
|
||||
Adjust, InferenceResult, Interner, Ty, TyExt, TyKind,
|
||||
};
|
||||
|
||||
pub(crate) use hir_def::{
|
||||
|
@ -117,7 +122,7 @@ impl ExprValidator {
|
|||
Expr::If { .. } => {
|
||||
self.check_for_unnecessary_else(id, expr, db);
|
||||
}
|
||||
Expr::Block { .. } => {
|
||||
Expr::Block { .. } | Expr::Async { .. } | Expr::Unsafe { .. } => {
|
||||
self.validate_block(db, expr);
|
||||
}
|
||||
_ => {}
|
||||
|
@ -236,7 +241,12 @@ impl ExprValidator {
|
|||
return;
|
||||
}
|
||||
|
||||
let report = match cx.compute_match_usefulness(m_arms.as_slice(), scrut_ty.clone()) {
|
||||
let known_valid_scrutinee = Some(self.is_known_valid_scrutinee(scrutinee_expr, db));
|
||||
let report = match cx.compute_match_usefulness(
|
||||
m_arms.as_slice(),
|
||||
scrut_ty.clone(),
|
||||
known_valid_scrutinee,
|
||||
) {
|
||||
Ok(report) => report,
|
||||
Err(()) => return,
|
||||
};
|
||||
|
@ -253,8 +263,52 @@ impl ExprValidator {
|
|||
}
|
||||
}
|
||||
|
||||
// [rustc's `is_known_valid_scrutinee`](https://github.com/rust-lang/rust/blob/c9bd03cb724e13cca96ad320733046cbdb16fbbe/compiler/rustc_mir_build/src/thir/pattern/check_match.rs#L288)
|
||||
//
|
||||
// While the above function in rustc uses thir exprs, r-a doesn't have them.
|
||||
// So, the logic here is getting same result as "hir lowering + match with lowered thir"
|
||||
// with "hir only"
|
||||
fn is_known_valid_scrutinee(&self, scrutinee_expr: ExprId, db: &dyn HirDatabase) -> bool {
|
||||
if self
|
||||
.infer
|
||||
.expr_adjustments
|
||||
.get(&scrutinee_expr)
|
||||
.is_some_and(|adjusts| adjusts.iter().any(|a| matches!(a.kind, Adjust::Deref(..))))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
match &self.body[scrutinee_expr] {
|
||||
Expr::UnaryOp { op: UnaryOp::Deref, .. } => false,
|
||||
Expr::Path(path) => {
|
||||
let value_or_partial = self
|
||||
.owner
|
||||
.resolver(db.upcast())
|
||||
.resolve_path_in_value_ns_fully(db.upcast(), path);
|
||||
value_or_partial.map_or(true, |v| !matches!(v, ValueNs::StaticId(_)))
|
||||
}
|
||||
Expr::Field { expr, .. } => match self.infer.type_of_expr[*expr].kind(Interner) {
|
||||
TyKind::Adt(adt, ..)
|
||||
if db.adt_datum(self.owner.krate(db.upcast()), *adt).kind == AdtKind::Union =>
|
||||
{
|
||||
false
|
||||
}
|
||||
_ => self.is_known_valid_scrutinee(*expr, db),
|
||||
},
|
||||
Expr::Index { base, .. } => self.is_known_valid_scrutinee(*base, db),
|
||||
Expr::Cast { expr, .. } => self.is_known_valid_scrutinee(*expr, db),
|
||||
Expr::Missing => false,
|
||||
_ => true,
|
||||
}
|
||||
}
|
||||
|
||||
fn validate_block(&mut self, db: &dyn HirDatabase, expr: &Expr) {
|
||||
let Expr::Block { statements, .. } = expr else { return };
|
||||
let (Expr::Block { statements, .. }
|
||||
| Expr::Async { statements, .. }
|
||||
| Expr::Unsafe { statements, .. }) = expr
|
||||
else {
|
||||
return;
|
||||
};
|
||||
let pattern_arena = Arena::new();
|
||||
let cx = MatchCheckCtx::new(self.owner.module(db.upcast()), self.owner, db);
|
||||
for stmt in &**statements {
|
||||
|
@ -280,7 +334,7 @@ impl ExprValidator {
|
|||
has_guard: false,
|
||||
arm_data: (),
|
||||
};
|
||||
let report = match cx.compute_match_usefulness(&[match_arm], ty.clone()) {
|
||||
let report = match cx.compute_match_usefulness(&[match_arm], ty.clone(), None) {
|
||||
Ok(v) => v,
|
||||
Err(e) => {
|
||||
debug!(?e, "match usefulness error");
|
||||
|
|
|
@ -69,22 +69,20 @@ pub(crate) struct MatchCheckCtx<'db> {
|
|||
body: DefWithBodyId,
|
||||
pub(crate) db: &'db dyn HirDatabase,
|
||||
exhaustive_patterns: bool,
|
||||
min_exhaustive_patterns: bool,
|
||||
}
|
||||
|
||||
impl<'db> MatchCheckCtx<'db> {
|
||||
pub(crate) fn new(module: ModuleId, body: DefWithBodyId, db: &'db dyn HirDatabase) -> Self {
|
||||
let def_map = db.crate_def_map(module.krate());
|
||||
let exhaustive_patterns = def_map.is_unstable_feature_enabled(&sym::exhaustive_patterns);
|
||||
let min_exhaustive_patterns =
|
||||
def_map.is_unstable_feature_enabled(&sym::min_exhaustive_patterns);
|
||||
Self { module, body, db, exhaustive_patterns, min_exhaustive_patterns }
|
||||
Self { module, body, db, exhaustive_patterns }
|
||||
}
|
||||
|
||||
pub(crate) fn compute_match_usefulness(
|
||||
&self,
|
||||
arms: &[MatchArm<'db>],
|
||||
scrut_ty: Ty,
|
||||
known_valid_scrutinee: Option<bool>,
|
||||
) -> Result<UsefulnessReport<'db, Self>, ()> {
|
||||
if scrut_ty.contains_unknown() {
|
||||
return Err(());
|
||||
|
@ -95,8 +93,7 @@ impl<'db> MatchCheckCtx<'db> {
|
|||
}
|
||||
}
|
||||
|
||||
// FIXME: Determine place validity correctly. For now, err on the safe side.
|
||||
let place_validity = PlaceValidity::MaybeInvalid;
|
||||
let place_validity = PlaceValidity::from_bool(known_valid_scrutinee.unwrap_or(true));
|
||||
// Measured to take ~100ms on modern hardware.
|
||||
let complexity_limit = Some(500000);
|
||||
compute_match_usefulness(self, arms, scrut_ty, place_validity, complexity_limit)
|
||||
|
@ -307,7 +304,8 @@ impl<'db> MatchCheckCtx<'db> {
|
|||
&Str(void) => match void {},
|
||||
Wildcard | NonExhaustive | Hidden | PrivateUninhabited => PatKind::Wild,
|
||||
Never => PatKind::Never,
|
||||
Missing | F32Range(..) | F64Range(..) | Opaque(..) | Or => {
|
||||
Missing | F16Range(..) | F32Range(..) | F64Range(..) | F128Range(..) | Opaque(..)
|
||||
| Or => {
|
||||
never!("can't convert to pattern: {:?}", pat.ctor());
|
||||
PatKind::Wild
|
||||
}
|
||||
|
@ -327,9 +325,6 @@ impl<'db> PatCx for MatchCheckCtx<'db> {
|
|||
fn is_exhaustive_patterns_feature_on(&self) -> bool {
|
||||
self.exhaustive_patterns
|
||||
}
|
||||
fn is_min_exhaustive_patterns_feature_on(&self) -> bool {
|
||||
self.min_exhaustive_patterns
|
||||
}
|
||||
|
||||
fn ctor_arity(
|
||||
&self,
|
||||
|
@ -356,8 +351,9 @@ impl<'db> PatCx for MatchCheckCtx<'db> {
|
|||
},
|
||||
Ref => 1,
|
||||
Slice(..) => unimplemented!(),
|
||||
Never | Bool(..) | IntRange(..) | F32Range(..) | F64Range(..) | Str(..)
|
||||
| Opaque(..) | NonExhaustive | PrivateUninhabited | Hidden | Missing | Wildcard => 0,
|
||||
Never | Bool(..) | IntRange(..) | F16Range(..) | F32Range(..) | F64Range(..)
|
||||
| F128Range(..) | Str(..) | Opaque(..) | NonExhaustive | PrivateUninhabited
|
||||
| Hidden | Missing | Wildcard => 0,
|
||||
Or => {
|
||||
never!("The `Or` constructor doesn't have a fixed arity");
|
||||
0
|
||||
|
@ -419,8 +415,9 @@ impl<'db> PatCx for MatchCheckCtx<'db> {
|
|||
}
|
||||
},
|
||||
Slice(_) => unreachable!("Found a `Slice` constructor in match checking"),
|
||||
Never | Bool(..) | IntRange(..) | F32Range(..) | F64Range(..) | Str(..)
|
||||
| Opaque(..) | NonExhaustive | PrivateUninhabited | Hidden | Missing | Wildcard => {
|
||||
Never | Bool(..) | IntRange(..) | F16Range(..) | F32Range(..) | F64Range(..)
|
||||
| F128Range(..) | Str(..) | Opaque(..) | NonExhaustive | PrivateUninhabited
|
||||
| Hidden | Missing | Wildcard => {
|
||||
smallvec![]
|
||||
}
|
||||
Or => {
|
||||
|
|
|
@ -17,7 +17,7 @@ pub fn missing_unsafe(db: &dyn HirDatabase, def: DefWithBodyId) -> Vec<ExprId> {
|
|||
|
||||
let mut res = Vec::new();
|
||||
let is_unsafe = match def {
|
||||
DefWithBodyId::FunctionId(it) => db.function_data(it).has_unsafe_kw(),
|
||||
DefWithBodyId::FunctionId(it) => db.function_data(it).is_unsafe(),
|
||||
DefWithBodyId::StaticId(_)
|
||||
| DefWithBodyId::ConstId(_)
|
||||
| DefWithBodyId::VariantId(_)
|
||||
|
|
|
@ -1022,16 +1022,16 @@ impl HirDisplay for Ty {
|
|||
// We print all params except implicit impl Trait params. Still a bit weird; should we leave out parent and self?
|
||||
if parameters.len() - impl_ > 0 {
|
||||
// `parameters` are in the order of fn's params (including impl traits), fn's lifetimes
|
||||
let without_impl = self_param as usize + type_ + const_ + lifetime;
|
||||
// parent's params (those from enclosing impl or trait, if any).
|
||||
let (fn_params, other) =
|
||||
parameters.split_at(self_param as usize + type_ + const_ + lifetime);
|
||||
let (_impl, parent_params) = other.split_at(impl_);
|
||||
let (fn_params, parent_params) = parameters.split_at(without_impl + impl_);
|
||||
debug_assert_eq!(parent_params.len(), parent_len);
|
||||
|
||||
let parent_params =
|
||||
generic_args_sans_defaults(f, Some(generic_def_id), parent_params);
|
||||
let fn_params =
|
||||
generic_args_sans_defaults(f, Some(generic_def_id), fn_params);
|
||||
&generic_args_sans_defaults(f, Some(generic_def_id), fn_params)
|
||||
[0..without_impl];
|
||||
|
||||
write!(f, "<")?;
|
||||
hir_fmt_generic_arguments(f, parent_params, None)?;
|
||||
|
@ -1069,6 +1069,7 @@ impl HirDisplay for Ty {
|
|||
module_id,
|
||||
PrefixKind::Plain,
|
||||
false,
|
||||
// FIXME: no_std Cfg?
|
||||
ImportPathConfig {
|
||||
prefer_no_std: false,
|
||||
prefer_prelude: true,
|
||||
|
@ -1151,11 +1152,10 @@ impl HirDisplay for Ty {
|
|||
)?;
|
||||
// FIXME: it would maybe be good to distinguish this from the alias type (when debug printing), and to show the substitution
|
||||
}
|
||||
ImplTraitId::AssociatedTypeImplTrait(alias, idx) => {
|
||||
ImplTraitId::TypeAliasImplTrait(alias, idx) => {
|
||||
let datas =
|
||||
db.type_alias_impl_traits(alias).expect("impl trait id without data");
|
||||
let data =
|
||||
(*datas).as_ref().map(|rpit| rpit.impl_traits[idx].bounds.clone());
|
||||
let data = (*datas).as_ref().map(|it| it.impl_traits[idx].bounds.clone());
|
||||
let bounds = data.substitute(Interner, ¶meters);
|
||||
let krate = alias.krate(db.upcast());
|
||||
write_bounds_like_dyn_trait_with_prefix(
|
||||
|
@ -1338,7 +1338,7 @@ impl HirDisplay for Ty {
|
|||
SizedByDefault::Sized { anchor: krate },
|
||||
)?;
|
||||
}
|
||||
ImplTraitId::AssociatedTypeImplTrait(alias, idx) => {
|
||||
ImplTraitId::TypeAliasImplTrait(alias, idx) => {
|
||||
let datas =
|
||||
db.type_alias_impl_traits(alias).expect("impl trait id without data");
|
||||
let data =
|
||||
|
|
|
@ -36,15 +36,14 @@ use hir_def::{
|
|||
body::Body,
|
||||
builtin_type::{BuiltinInt, BuiltinType, BuiltinUint},
|
||||
data::{ConstData, StaticData},
|
||||
hir::LabelId,
|
||||
hir::{BindingAnnotation, BindingId, ExprId, ExprOrPatId, PatId},
|
||||
hir::{BindingAnnotation, BindingId, ExprId, ExprOrPatId, LabelId, PatId},
|
||||
lang_item::{LangItem, LangItemTarget},
|
||||
layout::Integer,
|
||||
path::{ModPath, Path},
|
||||
resolver::{HasResolver, ResolveValueResult, Resolver, TypeNs, ValueNs},
|
||||
type_ref::{LifetimeRef, TypeRef},
|
||||
AdtId, AssocItemId, DefWithBodyId, FieldId, FunctionId, ItemContainerId, Lookup, TraitId,
|
||||
TupleFieldId, TupleId, TypeAliasId, VariantId,
|
||||
AdtId, AssocItemId, DefWithBodyId, FieldId, FunctionId, ImplId, ItemContainerId, Lookup,
|
||||
TraitId, TupleFieldId, TupleId, TypeAliasId, VariantId,
|
||||
};
|
||||
use hir_expand::name::Name;
|
||||
use indexmap::IndexSet;
|
||||
|
@ -785,14 +784,19 @@ impl<'a> InferenceContext<'a> {
|
|||
fn collect_const(&mut self, data: &ConstData) {
|
||||
let return_ty = self.make_ty(&data.type_ref);
|
||||
|
||||
// Constants might be associated items that define ATPITs.
|
||||
self.insert_atpit_coercion_table(iter::once(&return_ty));
|
||||
// Constants might be defining usage sites of TAITs.
|
||||
self.make_tait_coercion_table(iter::once(&return_ty));
|
||||
|
||||
self.return_ty = return_ty;
|
||||
}
|
||||
|
||||
fn collect_static(&mut self, data: &StaticData) {
|
||||
self.return_ty = self.make_ty(&data.type_ref);
|
||||
let return_ty = self.make_ty(&data.type_ref);
|
||||
|
||||
// Statics might be defining usage sites of TAITs.
|
||||
self.make_tait_coercion_table(iter::once(&return_ty));
|
||||
|
||||
self.return_ty = return_ty;
|
||||
}
|
||||
|
||||
fn collect_fn(&mut self, func: FunctionId) {
|
||||
|
@ -857,11 +861,11 @@ impl<'a> InferenceContext<'a> {
|
|||
self.return_ty = self.normalize_associated_types_in(return_ty);
|
||||
self.return_coercion = Some(CoerceMany::new(self.return_ty.clone()));
|
||||
|
||||
// Functions might be associated items that define ATPITs.
|
||||
// To define an ATPITs, that ATPIT must appear in the function's signatures.
|
||||
// Functions might be defining usage sites of TAITs.
|
||||
// To define an TAITs, that TAIT must appear in the function's signatures.
|
||||
// So, it suffices to check for params and return types.
|
||||
params_and_ret_tys.push(self.return_ty.clone());
|
||||
self.insert_atpit_coercion_table(params_and_ret_tys.iter());
|
||||
self.make_tait_coercion_table(params_and_ret_tys.iter());
|
||||
}
|
||||
|
||||
fn insert_inference_vars_for_impl_trait<T>(&mut self, t: T, placeholders: Substitution) -> T
|
||||
|
@ -880,7 +884,7 @@ impl<'a> InferenceContext<'a> {
|
|||
ImplTraitId::ReturnTypeImplTrait(def, idx) => {
|
||||
(self.db.return_type_impl_traits(def), idx)
|
||||
}
|
||||
ImplTraitId::AssociatedTypeImplTrait(def, idx) => {
|
||||
ImplTraitId::TypeAliasImplTrait(def, idx) => {
|
||||
(self.db.type_alias_impl_traits(def), idx)
|
||||
}
|
||||
_ => unreachable!(),
|
||||
|
@ -909,23 +913,25 @@ impl<'a> InferenceContext<'a> {
|
|||
}
|
||||
|
||||
/// The coercion of a non-inference var into an opaque type should fail,
|
||||
/// but not in the defining sites of the ATPITs.
|
||||
/// In such cases, we insert an proxy inference var for each ATPIT,
|
||||
/// and coerce into it instead of ATPIT itself.
|
||||
/// but not in the defining sites of the TAITs.
|
||||
/// In such cases, we insert an proxy inference var for each TAIT,
|
||||
/// and coerce into it instead of TAIT itself.
|
||||
///
|
||||
/// The inference var stretagy is effective because;
|
||||
///
|
||||
/// - It can still unify types that coerced into ATPIT
|
||||
/// - It can still unify types that coerced into TAITs
|
||||
/// - We are pushing `impl Trait` bounds into it
|
||||
///
|
||||
/// This function inserts a map that maps the opaque type to that proxy inference var.
|
||||
fn insert_atpit_coercion_table<'b>(&mut self, tys: impl Iterator<Item = &'b Ty>) {
|
||||
struct OpaqueTyCollector<'a, 'b> {
|
||||
fn make_tait_coercion_table<'b>(&mut self, tait_candidates: impl Iterator<Item = &'b Ty>) {
|
||||
struct TypeAliasImplTraitCollector<'a, 'b> {
|
||||
db: &'b dyn HirDatabase,
|
||||
table: &'b mut InferenceTable<'a>,
|
||||
opaque_tys: FxHashMap<OpaqueTyId, Ty>,
|
||||
assocs: FxHashMap<OpaqueTyId, (ImplId, Ty)>,
|
||||
non_assocs: FxHashMap<OpaqueTyId, Ty>,
|
||||
}
|
||||
|
||||
impl<'a, 'b> TypeVisitor<Interner> for OpaqueTyCollector<'a, 'b> {
|
||||
impl<'a, 'b> TypeVisitor<Interner> for TypeAliasImplTraitCollector<'a, 'b> {
|
||||
type BreakTy = ();
|
||||
|
||||
fn as_dyn(&mut self) -> &mut dyn TypeVisitor<Interner, BreakTy = Self::BreakTy> {
|
||||
|
@ -944,59 +950,105 @@ impl<'a> InferenceContext<'a> {
|
|||
let ty = self.table.resolve_ty_shallow(ty);
|
||||
|
||||
if let TyKind::OpaqueType(id, _) = ty.kind(Interner) {
|
||||
self.opaque_tys.insert(*id, ty.clone());
|
||||
if let ImplTraitId::TypeAliasImplTrait(alias_id, _) =
|
||||
self.db.lookup_intern_impl_trait_id((*id).into())
|
||||
{
|
||||
let loc = self.db.lookup_intern_type_alias(alias_id);
|
||||
match loc.container {
|
||||
ItemContainerId::ImplId(impl_id) => {
|
||||
self.assocs.insert(*id, (impl_id, ty.clone()));
|
||||
}
|
||||
ItemContainerId::ModuleId(..) | ItemContainerId::ExternBlockId(..) => {
|
||||
self.non_assocs.insert(*id, ty.clone());
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ty.super_visit_with(self, outer_binder)
|
||||
}
|
||||
}
|
||||
|
||||
// Early return if this is not happening inside the impl block
|
||||
let impl_id = if let Some(impl_id) = self.resolver.impl_def() {
|
||||
impl_id
|
||||
} else {
|
||||
return;
|
||||
let mut collector = TypeAliasImplTraitCollector {
|
||||
db: self.db,
|
||||
table: &mut self.table,
|
||||
assocs: FxHashMap::default(),
|
||||
non_assocs: FxHashMap::default(),
|
||||
};
|
||||
|
||||
let assoc_tys: FxHashSet<_> = self
|
||||
.db
|
||||
.impl_data(impl_id)
|
||||
.items
|
||||
.iter()
|
||||
.filter_map(|item| match item {
|
||||
AssocItemId::TypeAliasId(alias) => Some(*alias),
|
||||
_ => None,
|
||||
})
|
||||
.collect();
|
||||
if assoc_tys.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
let mut collector =
|
||||
OpaqueTyCollector { table: &mut self.table, opaque_tys: FxHashMap::default() };
|
||||
for ty in tys {
|
||||
for ty in tait_candidates {
|
||||
ty.visit_with(collector.as_dyn(), DebruijnIndex::INNERMOST);
|
||||
}
|
||||
let atpit_coercion_table: FxHashMap<_, _> = collector
|
||||
.opaque_tys
|
||||
.into_iter()
|
||||
.filter_map(|(opaque_ty_id, ty)| {
|
||||
if let ImplTraitId::AssociatedTypeImplTrait(alias_id, _) =
|
||||
self.db.lookup_intern_impl_trait_id(opaque_ty_id.into())
|
||||
{
|
||||
if assoc_tys.contains(&alias_id) {
|
||||
let alias_placeholders = TyBuilder::placeholder_subst(self.db, alias_id);
|
||||
let ty = self.insert_inference_vars_for_impl_trait(ty, alias_placeholders);
|
||||
return Some((opaque_ty_id, ty));
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
// Non-assoc TAITs can be define-used everywhere as long as they are
|
||||
// in function signatures or const types, etc
|
||||
let mut taits = collector.non_assocs;
|
||||
|
||||
// assoc TAITs(ATPITs) can be only define-used inside their impl block.
|
||||
// They cannot be define-used in inner items like in the following;
|
||||
//
|
||||
// ```
|
||||
// impl Trait for Struct {
|
||||
// type Assoc = impl Default;
|
||||
//
|
||||
// fn assoc_fn() -> Self::Assoc {
|
||||
// let foo: Self::Assoc = true; // Allowed here
|
||||
//
|
||||
// fn inner() -> Self::Assoc {
|
||||
// false // Not allowed here
|
||||
// }
|
||||
//
|
||||
// foo
|
||||
// }
|
||||
// }
|
||||
// ```
|
||||
let impl_id = match self.owner {
|
||||
DefWithBodyId::FunctionId(it) => {
|
||||
let loc = self.db.lookup_intern_function(it);
|
||||
if let ItemContainerId::ImplId(impl_id) = loc.container {
|
||||
Some(impl_id)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
DefWithBodyId::ConstId(it) => {
|
||||
let loc = self.db.lookup_intern_const(it);
|
||||
if let ItemContainerId::ImplId(impl_id) = loc.container {
|
||||
Some(impl_id)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
_ => None,
|
||||
};
|
||||
|
||||
if let Some(impl_id) = impl_id {
|
||||
taits.extend(collector.assocs.into_iter().filter_map(|(id, (impl_, ty))| {
|
||||
if impl_ == impl_id {
|
||||
Some((id, ty))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
let tait_coercion_table: FxHashMap<_, _> = taits
|
||||
.into_iter()
|
||||
.filter_map(|(id, ty)| {
|
||||
if let ImplTraitId::TypeAliasImplTrait(alias_id, _) =
|
||||
self.db.lookup_intern_impl_trait_id(id.into())
|
||||
{
|
||||
let subst = TyBuilder::placeholder_subst(self.db, alias_id);
|
||||
let ty = self.insert_inference_vars_for_impl_trait(ty, subst);
|
||||
Some((id, ty))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
if !atpit_coercion_table.is_empty() {
|
||||
self.table.atpit_coercion_table = Some(atpit_coercion_table);
|
||||
if !tait_coercion_table.is_empty() {
|
||||
self.table.tait_coercion_table = Some(tait_coercion_table);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -276,16 +276,16 @@ impl InferenceTable<'_> {
|
|||
return success(simple(Adjust::NeverToAny)(to_ty.clone()), to_ty.clone(), vec![]);
|
||||
}
|
||||
|
||||
// If we are coercing into an ATPIT, coerce into its proxy inference var, instead.
|
||||
// If we are coercing into a TAIT, coerce into its proxy inference var, instead.
|
||||
let mut to_ty = to_ty;
|
||||
let _to;
|
||||
if let Some(atpit_table) = &self.atpit_coercion_table {
|
||||
if let Some(tait_table) = &self.tait_coercion_table {
|
||||
if let TyKind::OpaqueType(opaque_ty_id, _) = to_ty.kind(Interner) {
|
||||
if !matches!(
|
||||
from_ty.kind(Interner),
|
||||
TyKind::InferenceVar(..) | TyKind::OpaqueType(..)
|
||||
) {
|
||||
if let Some(ty) = atpit_table.get(opaque_ty_id) {
|
||||
if let Some(ty) = tait_table.get(opaque_ty_id) {
|
||||
_to = ty.clone();
|
||||
to_ty = &_to;
|
||||
}
|
||||
|
|
|
@ -1759,13 +1759,14 @@ impl InferenceContext<'_> {
|
|||
skip_indices: &[u32],
|
||||
is_varargs: bool,
|
||||
) {
|
||||
if args.len() != param_tys.len() + skip_indices.len() && !is_varargs {
|
||||
let arg_count_mismatch = args.len() != param_tys.len() + skip_indices.len() && !is_varargs;
|
||||
if arg_count_mismatch {
|
||||
self.push_diagnostic(InferenceDiagnostic::MismatchedArgCount {
|
||||
call_expr: expr,
|
||||
expected: param_tys.len() + skip_indices.len(),
|
||||
found: args.len(),
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// Quoting https://github.com/rust-lang/rust/blob/6ef275e6c3cb1384ec78128eceeb4963ff788dca/src/librustc_typeck/check/mod.rs#L3325 --
|
||||
// We do this in a pretty awful way: first we type-check any arguments
|
||||
|
@ -1819,7 +1820,7 @@ impl InferenceContext<'_> {
|
|||
// The function signature may contain some unknown types, so we need to insert
|
||||
// type vars here to avoid type mismatch false positive.
|
||||
let coercion_target = self.insert_type_vars(coercion_target);
|
||||
if self.coerce(Some(arg), &ty, &coercion_target).is_err() {
|
||||
if self.coerce(Some(arg), &ty, &coercion_target).is_err() && !arg_count_mismatch {
|
||||
self.result.type_mismatches.insert(
|
||||
arg.into(),
|
||||
TypeMismatch { expected: coercion_target, actual: ty.clone() },
|
||||
|
|
|
@ -224,7 +224,7 @@ type ChalkInferenceTable = chalk_solve::infer::InferenceTable<Interner>;
|
|||
pub(crate) struct InferenceTable<'a> {
|
||||
pub(crate) db: &'a dyn HirDatabase,
|
||||
pub(crate) trait_env: Arc<TraitEnvironment>,
|
||||
pub(crate) atpit_coercion_table: Option<FxHashMap<OpaqueTyId, Ty>>,
|
||||
pub(crate) tait_coercion_table: Option<FxHashMap<OpaqueTyId, Ty>>,
|
||||
var_unification_table: ChalkInferenceTable,
|
||||
type_variable_table: SmallVec<[TypeVariableFlags; 16]>,
|
||||
pending_obligations: Vec<Canonicalized<InEnvironment<Goal>>>,
|
||||
|
@ -244,7 +244,7 @@ impl<'a> InferenceTable<'a> {
|
|||
InferenceTable {
|
||||
db,
|
||||
trait_env,
|
||||
atpit_coercion_table: None,
|
||||
tait_coercion_table: None,
|
||||
var_unification_table: ChalkInferenceTable::new(),
|
||||
type_variable_table: SmallVec::new(),
|
||||
pending_obligations: Vec::new(),
|
||||
|
|
|
@ -391,7 +391,7 @@ pub fn layout_of_ty_query(
|
|||
let infer = db.infer(func.into());
|
||||
return db.layout_of_ty(infer.type_of_rpit[idx].clone(), trait_env);
|
||||
}
|
||||
crate::ImplTraitId::AssociatedTypeImplTrait(..) => {
|
||||
crate::ImplTraitId::TypeAliasImplTrait(..) => {
|
||||
return Err(LayoutError::NotImplemented);
|
||||
}
|
||||
crate::ImplTraitId::AsyncBlockTypeImplTrait(_, _) => {
|
||||
|
|
|
@ -595,7 +595,7 @@ impl TypeFoldable<Interner> for CallableSig {
|
|||
#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
|
||||
pub enum ImplTraitId {
|
||||
ReturnTypeImplTrait(hir_def::FunctionId, ImplTraitIdx),
|
||||
AssociatedTypeImplTrait(hir_def::TypeAliasId, ImplTraitIdx),
|
||||
TypeAliasImplTrait(hir_def::TypeAliasId, ImplTraitIdx),
|
||||
AsyncBlockTypeImplTrait(hir_def::DefWithBodyId, ExprId),
|
||||
}
|
||||
impl InternValueTrivial for ImplTraitId {}
|
||||
|
|
|
@ -341,7 +341,7 @@ impl<'a> TyLoweringContext<'a> {
|
|||
|
||||
let impl_trait_id = origin.either(
|
||||
|f| ImplTraitId::ReturnTypeImplTrait(f, idx),
|
||||
|a| ImplTraitId::AssociatedTypeImplTrait(a, idx),
|
||||
|a| ImplTraitId::TypeAliasImplTrait(a, idx),
|
||||
);
|
||||
let opaque_ty_id = self.db.intern_impl_trait_id(impl_trait_id).into();
|
||||
let generics =
|
||||
|
@ -1857,7 +1857,7 @@ fn fn_sig_for_fn(db: &dyn HirDatabase, def: FunctionId) -> PolyFnSig {
|
|||
params,
|
||||
ret,
|
||||
data.is_varargs(),
|
||||
if data.has_unsafe_kw() { Safety::Unsafe } else { Safety::Safe },
|
||||
if data.is_unsafe() { Safety::Unsafe } else { Safety::Safe },
|
||||
data.abi.as_ref().map_or(FnAbi::Rust, FnAbi::from_symbol),
|
||||
);
|
||||
make_binders(db, &generics, sig)
|
||||
|
@ -2131,7 +2131,6 @@ pub(crate) fn type_alias_impl_traits(
|
|||
if let Some(type_ref) = &data.type_ref {
|
||||
let _ty = ctx.lower_ty(type_ref);
|
||||
}
|
||||
let generics = generics(db.upcast(), def.into());
|
||||
let type_alias_impl_traits = ImplTraits {
|
||||
impl_traits: match ctx.impl_trait_mode {
|
||||
ImplTraitLoweringState::Opaque(x) => x.into_inner(),
|
||||
|
@ -2141,6 +2140,7 @@ pub(crate) fn type_alias_impl_traits(
|
|||
if type_alias_impl_traits.impl_traits.is_empty() {
|
||||
None
|
||||
} else {
|
||||
let generics = generics(db.upcast(), def.into());
|
||||
Some(Arc::new(make_binders(db, &generics, type_alias_impl_traits)))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -82,8 +82,8 @@ impl FallibleTypeFolder<Interner> for Filler<'_> {
|
|||
};
|
||||
filler.try_fold_ty(infer.type_of_rpit[idx].clone(), outer_binder)
|
||||
}
|
||||
crate::ImplTraitId::AssociatedTypeImplTrait(..) => {
|
||||
not_supported!("associated type impl trait");
|
||||
crate::ImplTraitId::TypeAliasImplTrait(..) => {
|
||||
not_supported!("type alias impl trait");
|
||||
}
|
||||
crate::ImplTraitId::AsyncBlockTypeImplTrait(_, _) => {
|
||||
not_supported!("async block impl trait");
|
||||
|
|
|
@ -15,7 +15,7 @@ use test_utils::extract_annotations;
|
|||
use triomphe::Arc;
|
||||
|
||||
#[salsa::database(
|
||||
base_db::SourceDatabaseExtStorage,
|
||||
base_db::SourceRootDatabaseStorage,
|
||||
base_db::SourceDatabaseStorage,
|
||||
hir_expand::db::ExpandDatabaseStorage,
|
||||
hir_def::db::InternDatabaseStorage,
|
||||
|
@ -75,9 +75,6 @@ impl salsa::ParallelDatabase for TestDB {
|
|||
impl panic::RefUnwindSafe for TestDB {}
|
||||
|
||||
impl FileLoader for TestDB {
|
||||
fn file_text(&self, file_id: FileId) -> Arc<str> {
|
||||
FileLoaderDelegate(self).file_text(file_id)
|
||||
}
|
||||
fn resolve_path(&self, path: AnchoredPath<'_>) -> Option<FileId> {
|
||||
FileLoaderDelegate(self).resolve_path(path)
|
||||
}
|
||||
|
|
|
@ -9,10 +9,11 @@ mod patterns;
|
|||
mod regression;
|
||||
mod simple;
|
||||
mod traits;
|
||||
mod type_alias_impl_traits;
|
||||
|
||||
use std::env;
|
||||
|
||||
use base_db::SourceDatabaseExt2 as _;
|
||||
use base_db::SourceDatabaseFileInputExt as _;
|
||||
use expect_test::Expect;
|
||||
use hir_def::{
|
||||
body::{Body, BodySourceMap, SyntheticSyntax},
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use base_db::SourceDatabaseExt2 as _;
|
||||
use base_db::SourceDatabaseFileInputExt as _;
|
||||
use test_fixture::WithFixture;
|
||||
|
||||
use crate::{db::HirDatabase, test_db::TestDB};
|
||||
|
|
|
@ -2122,3 +2122,22 @@ fn test() {
|
|||
"#,
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn issue_17191() {
|
||||
check_types(
|
||||
r#"
|
||||
trait A {
|
||||
type Item;
|
||||
}
|
||||
|
||||
trait B<T> {}
|
||||
|
||||
fn foo<T: B<impl A>>() {}
|
||||
|
||||
fn test() {
|
||||
let f = foo;
|
||||
//^ fn foo<{unknown}>()
|
||||
}"#,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -4691,119 +4691,6 @@ fn f<T: Send, U>() {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn associated_type_impl_trait() {
|
||||
check_types(
|
||||
r#"
|
||||
trait Foo {}
|
||||
struct S1;
|
||||
impl Foo for S1 {}
|
||||
|
||||
trait Bar {
|
||||
type Item;
|
||||
fn bar(&self) -> Self::Item;
|
||||
}
|
||||
struct S2;
|
||||
impl Bar for S2 {
|
||||
type Item = impl Foo;
|
||||
fn bar(&self) -> Self::Item {
|
||||
S1
|
||||
}
|
||||
}
|
||||
|
||||
fn test() {
|
||||
let x = S2.bar();
|
||||
//^ impl Foo + ?Sized
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn associated_type_impl_traits_complex() {
|
||||
check_types(
|
||||
r#"
|
||||
struct Unary<T>(T);
|
||||
struct Binary<T, U>(T, U);
|
||||
|
||||
trait Foo {}
|
||||
struct S1;
|
||||
impl Foo for S1 {}
|
||||
|
||||
trait Bar {
|
||||
type Item;
|
||||
fn bar(&self) -> Unary<Self::Item>;
|
||||
}
|
||||
struct S2;
|
||||
impl Bar for S2 {
|
||||
type Item = Unary<impl Foo>;
|
||||
fn bar(&self) -> Unary<<Self as Bar>::Item> {
|
||||
Unary(Unary(S1))
|
||||
}
|
||||
}
|
||||
|
||||
trait Baz {
|
||||
type Target1;
|
||||
type Target2;
|
||||
fn baz(&self) -> Binary<Self::Target1, Self::Target2>;
|
||||
}
|
||||
struct S3;
|
||||
impl Baz for S3 {
|
||||
type Target1 = impl Foo;
|
||||
type Target2 = Unary<impl Bar>;
|
||||
fn baz(&self) -> Binary<Self::Target1, Self::Target2> {
|
||||
Binary(S1, Unary(S2))
|
||||
}
|
||||
}
|
||||
|
||||
fn test() {
|
||||
let x = S3.baz();
|
||||
//^ Binary<impl Foo + ?Sized, Unary<impl Bar + ?Sized>>
|
||||
let y = x.1.0.bar();
|
||||
//^ Unary<Bar::Item<impl Bar + ?Sized>>
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn associated_type_with_impl_trait_in_tuple() {
|
||||
check_no_mismatches(
|
||||
r#"
|
||||
pub trait Iterator {
|
||||
type Item;
|
||||
}
|
||||
|
||||
pub trait Value {}
|
||||
|
||||
fn bar<I: Iterator<Item = (usize, impl Value)>>() {}
|
||||
|
||||
fn foo() {
|
||||
bar();
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn associated_type_with_impl_trait_in_nested_tuple() {
|
||||
check_no_mismatches(
|
||||
r#"
|
||||
pub trait Iterator {
|
||||
type Item;
|
||||
}
|
||||
|
||||
pub trait Value {}
|
||||
|
||||
fn bar<I: Iterator<Item = ((impl Value, usize), u32)>>() {}
|
||||
|
||||
fn foo() {
|
||||
bar();
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn dyn_trait_with_lifetime_in_rpit() {
|
||||
check_types(
|
||||
|
|
161
crates/hir-ty/src/tests/type_alias_impl_traits.rs
Normal file
161
crates/hir-ty/src/tests/type_alias_impl_traits.rs
Normal file
|
@ -0,0 +1,161 @@
|
|||
use expect_test::expect;
|
||||
|
||||
use super::{check_infer_with_mismatches, check_no_mismatches, check_types};
|
||||
|
||||
#[test]
|
||||
fn associated_type_impl_trait() {
|
||||
check_types(
|
||||
r#"
|
||||
trait Foo {}
|
||||
struct S1;
|
||||
impl Foo for S1 {}
|
||||
|
||||
trait Bar {
|
||||
type Item;
|
||||
fn bar(&self) -> Self::Item;
|
||||
}
|
||||
struct S2;
|
||||
impl Bar for S2 {
|
||||
type Item = impl Foo;
|
||||
fn bar(&self) -> Self::Item {
|
||||
S1
|
||||
}
|
||||
}
|
||||
|
||||
fn test() {
|
||||
let x = S2.bar();
|
||||
//^ impl Foo + ?Sized
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn associated_type_impl_traits_complex() {
|
||||
check_types(
|
||||
r#"
|
||||
struct Unary<T>(T);
|
||||
struct Binary<T, U>(T, U);
|
||||
|
||||
trait Foo {}
|
||||
struct S1;
|
||||
impl Foo for S1 {}
|
||||
|
||||
trait Bar {
|
||||
type Item;
|
||||
fn bar(&self) -> Unary<Self::Item>;
|
||||
}
|
||||
struct S2;
|
||||
impl Bar for S2 {
|
||||
type Item = Unary<impl Foo>;
|
||||
fn bar(&self) -> Unary<<Self as Bar>::Item> {
|
||||
Unary(Unary(S1))
|
||||
}
|
||||
}
|
||||
|
||||
trait Baz {
|
||||
type Target1;
|
||||
type Target2;
|
||||
fn baz(&self) -> Binary<Self::Target1, Self::Target2>;
|
||||
}
|
||||
struct S3;
|
||||
impl Baz for S3 {
|
||||
type Target1 = impl Foo;
|
||||
type Target2 = Unary<impl Bar>;
|
||||
fn baz(&self) -> Binary<Self::Target1, Self::Target2> {
|
||||
Binary(S1, Unary(S2))
|
||||
}
|
||||
}
|
||||
|
||||
fn test() {
|
||||
let x = S3.baz();
|
||||
//^ Binary<impl Foo + ?Sized, Unary<impl Bar + ?Sized>>
|
||||
let y = x.1.0.bar();
|
||||
//^ Unary<Bar::Item<impl Bar + ?Sized>>
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn associated_type_with_impl_trait_in_tuple() {
|
||||
check_no_mismatches(
|
||||
r#"
|
||||
pub trait Iterator {
|
||||
type Item;
|
||||
}
|
||||
|
||||
pub trait Value {}
|
||||
|
||||
fn bar<I: Iterator<Item = (usize, impl Value)>>() {}
|
||||
|
||||
fn foo() {
|
||||
bar();
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn associated_type_with_impl_trait_in_nested_tuple() {
|
||||
check_no_mismatches(
|
||||
r#"
|
||||
pub trait Iterator {
|
||||
type Item;
|
||||
}
|
||||
|
||||
pub trait Value {}
|
||||
|
||||
fn bar<I: Iterator<Item = ((impl Value, usize), u32)>>() {}
|
||||
|
||||
fn foo() {
|
||||
bar();
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn type_alias_impl_trait_simple() {
|
||||
check_no_mismatches(
|
||||
r#"
|
||||
trait Trait {}
|
||||
|
||||
struct Struct;
|
||||
|
||||
impl Trait for Struct {}
|
||||
|
||||
type AliasTy = impl Trait;
|
||||
|
||||
static ALIAS: AliasTy = {
|
||||
let res: AliasTy = Struct;
|
||||
res
|
||||
};
|
||||
"#,
|
||||
);
|
||||
|
||||
check_infer_with_mismatches(
|
||||
r#"
|
||||
trait Trait {}
|
||||
|
||||
struct Struct;
|
||||
|
||||
impl Trait for Struct {}
|
||||
|
||||
type AliasTy = impl Trait;
|
||||
|
||||
static ALIAS: i32 = {
|
||||
// TATIs cannot be define-used if not in signature or type annotations
|
||||
let _a: AliasTy = Struct;
|
||||
5
|
||||
};
|
||||
"#,
|
||||
expect![[r#"
|
||||
106..220 '{ ... 5 }': i32
|
||||
191..193 '_a': impl Trait + ?Sized
|
||||
205..211 'Struct': Struct
|
||||
217..218 '5': i32
|
||||
205..211: expected impl Trait + ?Sized, got Struct
|
||||
"#]],
|
||||
)
|
||||
}
|
|
@ -253,12 +253,7 @@ impl<'a> ClosureSubst<'a> {
|
|||
|
||||
pub fn is_fn_unsafe_to_call(db: &dyn HirDatabase, func: FunctionId) -> bool {
|
||||
let data = db.function_data(func);
|
||||
if data.has_unsafe_kw() {
|
||||
// Functions that are `#[rustc_deprecated_safe_2024]` are safe to call before 2024.
|
||||
if db.attrs(func.into()).by_key(&sym::rustc_deprecated_safe_2024).exists() {
|
||||
// FIXME: Properly check the caller span and mark it as unsafe after 2024.
|
||||
return false;
|
||||
}
|
||||
if data.is_unsafe() {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
[package]
|
||||
name = "hir"
|
||||
version = "0.0.0"
|
||||
description = "TBD"
|
||||
repository.workspace = true
|
||||
description = "A high-level object-oriented access to Rust code for rust-analyzer."
|
||||
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
|
|
|
@ -48,6 +48,7 @@ macro_rules! diagnostics {
|
|||
// ]
|
||||
|
||||
diagnostics![
|
||||
AwaitOutsideOfAsync,
|
||||
BreakOutsideOfLoop,
|
||||
ExpectedFunction,
|
||||
InactiveCode,
|
||||
|
@ -135,6 +136,12 @@ pub struct UnreachableLabel {
|
|||
pub name: Name,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct AwaitOutsideOfAsync {
|
||||
pub node: InFile<AstPtr<ast::AwaitExpr>>,
|
||||
pub location: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
pub struct UndeclaredLabel {
|
||||
pub node: InFile<AstPtr<ast::Lifetime>>,
|
||||
|
|
|
@ -69,13 +69,13 @@ impl HirDisplay for Function {
|
|||
|
||||
write_visibility(module_id, self.visibility(db), f)?;
|
||||
|
||||
if data.has_default_kw() {
|
||||
if data.is_default() {
|
||||
f.write_str("default ")?;
|
||||
}
|
||||
if data.has_const_kw() {
|
||||
if data.is_const() {
|
||||
f.write_str("const ")?;
|
||||
}
|
||||
if data.has_async_kw() {
|
||||
if data.is_async() {
|
||||
f.write_str("async ")?;
|
||||
}
|
||||
if self.is_unsafe_to_call(db) {
|
||||
|
@ -125,7 +125,7 @@ impl HirDisplay for Function {
|
|||
// `FunctionData::ret_type` will be `::core::future::Future<Output = ...>` for async fns.
|
||||
// Use ugly pattern match to strip the Future trait.
|
||||
// Better way?
|
||||
let ret_type = if !data.has_async_kw() {
|
||||
let ret_type = if !data.is_async() {
|
||||
&data.ret_type
|
||||
} else {
|
||||
match &*data.ret_type {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
//! HIR (previously known as descriptors) provides a high-level object oriented
|
||||
//! HIR (previously known as descriptors) provides a high-level object-oriented
|
||||
//! access to Rust code.
|
||||
//!
|
||||
//! The principal difference between HIR and syntax trees is that HIR is bound
|
||||
|
@ -1828,6 +1828,9 @@ impl DefWithBody {
|
|||
is_bang: true,
|
||||
}
|
||||
.into(),
|
||||
BodyDiagnostic::AwaitOutsideOfAsync { node, location } => {
|
||||
AwaitOutsideOfAsync { node: *node, location: location.clone() }.into()
|
||||
}
|
||||
BodyDiagnostic::UnreachableLabel { node, name } => {
|
||||
UnreachableLabel { node: *node, name: name.clone() }.into()
|
||||
}
|
||||
|
@ -2186,11 +2189,11 @@ impl Function {
|
|||
}
|
||||
|
||||
pub fn is_const(self, db: &dyn HirDatabase) -> bool {
|
||||
db.function_data(self.id).has_const_kw()
|
||||
db.function_data(self.id).is_const()
|
||||
}
|
||||
|
||||
pub fn is_async(self, db: &dyn HirDatabase) -> bool {
|
||||
db.function_data(self.id).has_async_kw()
|
||||
db.function_data(self.id).is_async()
|
||||
}
|
||||
|
||||
/// Does this function have `#[test]` attribute?
|
||||
|
|
|
@ -28,7 +28,7 @@ use hir_expand::{
|
|||
use itertools::Itertools;
|
||||
use rustc_hash::{FxHashMap, FxHashSet};
|
||||
use smallvec::{smallvec, SmallVec};
|
||||
use span::{EditionedFileId, FileId, Span, SyntaxContextId, ROOT_ERASED_FILE_AST_ID};
|
||||
use span::{EditionedFileId, FileId};
|
||||
use stdx::TupleExt;
|
||||
use syntax::{
|
||||
algo::skip_trivia_token,
|
||||
|
@ -757,81 +757,9 @@ impl<'db> SemanticsImpl<'db> {
|
|||
res
|
||||
}
|
||||
|
||||
// return:
|
||||
// SourceAnalyzer(file_id that original call include!)
|
||||
// macro file id
|
||||
// token in include! macro mapped from token in params
|
||||
// span for the mapped token
|
||||
fn is_from_include_file(
|
||||
&self,
|
||||
token: SyntaxToken,
|
||||
) -> Option<(SourceAnalyzer, HirFileId, SyntaxToken, Span)> {
|
||||
let parent = token.parent()?;
|
||||
let file_id = self.find_file(&parent).file_id.file_id()?;
|
||||
|
||||
// iterate related crates and find all include! invocations that include_file_id matches
|
||||
for (invoc, _) in self
|
||||
.db
|
||||
.relevant_crates(file_id.file_id())
|
||||
.iter()
|
||||
.flat_map(|krate| self.db.include_macro_invoc(*krate))
|
||||
.filter(|&(_, include_file_id)| include_file_id == file_id)
|
||||
{
|
||||
let macro_file = invoc.as_macro_file();
|
||||
let expansion_info = {
|
||||
self.with_ctx(|ctx| {
|
||||
ctx.cache
|
||||
.expansion_info_cache
|
||||
.entry(macro_file)
|
||||
.or_insert_with(|| {
|
||||
let exp_info = macro_file.expansion_info(self.db.upcast());
|
||||
|
||||
let InMacroFile { file_id, value } = exp_info.expanded();
|
||||
if let InFile { file_id, value: Some(value) } = exp_info.arg() {
|
||||
self.cache(value.ancestors().last().unwrap(), file_id);
|
||||
}
|
||||
self.cache(value, file_id.into());
|
||||
|
||||
exp_info
|
||||
})
|
||||
.clone()
|
||||
})
|
||||
};
|
||||
|
||||
// FIXME: uncached parse
|
||||
// Create the source analyzer for the macro call scope
|
||||
let Some(sa) = expansion_info
|
||||
.arg()
|
||||
.value
|
||||
.and_then(|it| self.analyze_no_infer(&it.ancestors().last().unwrap()))
|
||||
else {
|
||||
continue;
|
||||
};
|
||||
|
||||
// get mapped token in the include! macro file
|
||||
let span = span::Span {
|
||||
range: token.text_range(),
|
||||
anchor: span::SpanAnchor { file_id, ast_id: ROOT_ERASED_FILE_AST_ID },
|
||||
ctx: SyntaxContextId::ROOT,
|
||||
};
|
||||
let Some(InMacroFile { file_id, value: mut mapped_tokens }) =
|
||||
expansion_info.map_range_down_exact(span)
|
||||
else {
|
||||
continue;
|
||||
};
|
||||
|
||||
// if we find one, then return
|
||||
if let Some(t) = mapped_tokens.next() {
|
||||
return Some((sa, file_id.into(), t, span));
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
fn descend_into_macros_impl(
|
||||
&self,
|
||||
mut token: SyntaxToken,
|
||||
token: SyntaxToken,
|
||||
f: &mut dyn FnMut(InFile<SyntaxToken>) -> ControlFlow<()>,
|
||||
) {
|
||||
let _p = tracing::info_span!("descend_into_macros_impl").entered();
|
||||
|
@ -848,17 +776,7 @@ impl<'db> SemanticsImpl<'db> {
|
|||
return;
|
||||
}
|
||||
},
|
||||
None => {
|
||||
// if we cannot find a source analyzer for this token, then we try to find out
|
||||
// whether this file is an included file and treat that as the include input
|
||||
let Some((it, macro_file_id, mapped_token, s)) =
|
||||
self.is_from_include_file(token)
|
||||
else {
|
||||
return;
|
||||
};
|
||||
token = mapped_token;
|
||||
(it, s, macro_file_id)
|
||||
}
|
||||
None => return,
|
||||
};
|
||||
|
||||
let mut m_cache = self.macro_call_cache.borrow_mut();
|
||||
|
|
|
@ -94,8 +94,9 @@ use hir_def::{
|
|||
},
|
||||
hir::{BindingId, LabelId},
|
||||
AdtId, BlockId, ConstId, ConstParamId, DefWithBodyId, EnumId, EnumVariantId, ExternCrateId,
|
||||
FieldId, FunctionId, GenericDefId, GenericParamId, ImplId, LifetimeParamId, MacroId, ModuleId,
|
||||
StaticId, StructId, TraitAliasId, TraitId, TypeAliasId, TypeParamId, UnionId, UseId, VariantId,
|
||||
FieldId, FunctionId, GenericDefId, GenericParamId, ImplId, LifetimeParamId, Lookup, MacroId,
|
||||
ModuleId, StaticId, StructId, TraitAliasId, TraitId, TypeAliasId, TypeParamId, UnionId, UseId,
|
||||
VariantId,
|
||||
};
|
||||
use hir_expand::{
|
||||
attrs::AttrId, name::AsName, ExpansionInfo, HirFileId, HirFileIdExt, MacroCallId,
|
||||
|
@ -131,11 +132,30 @@ impl SourceToDefCtx<'_, '_> {
|
|||
for &crate_id in self.db.relevant_crates(file).iter() {
|
||||
// Note: `mod` declarations in block modules cannot be supported here
|
||||
let crate_def_map = self.db.crate_def_map(crate_id);
|
||||
mods.extend(
|
||||
let n_mods = mods.len();
|
||||
let modules = |file| {
|
||||
crate_def_map
|
||||
.modules_for_file(file)
|
||||
.map(|local_id| crate_def_map.module_id(local_id)),
|
||||
)
|
||||
.map(|local_id| crate_def_map.module_id(local_id))
|
||||
};
|
||||
mods.extend(modules(file));
|
||||
if mods.len() == n_mods {
|
||||
mods.extend(
|
||||
self.db
|
||||
.include_macro_invoc(crate_id)
|
||||
.iter()
|
||||
.filter(|&&(_, file_id)| file_id == file)
|
||||
.flat_map(|(call, _)| {
|
||||
modules(
|
||||
call.lookup(self.db.upcast())
|
||||
.kind
|
||||
.file_id()
|
||||
.original_file(self.db.upcast())
|
||||
.file_id(),
|
||||
)
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
if mods.is_empty() {
|
||||
// FIXME: detached file
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
[package]
|
||||
name = "ide-assists"
|
||||
version = "0.0.0"
|
||||
description = "TBD"
|
||||
repository.workspace = true
|
||||
description = "Code assists for rust-analyzer."
|
||||
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
|
|
|
@ -2280,4 +2280,29 @@ impl b::LocalTrait for B {
|
|||
"#,
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn impl_with_type_param_with_former_param_as_default() {
|
||||
check_assist(
|
||||
add_missing_impl_members,
|
||||
r#"
|
||||
pub trait Test<'a, T, U = T> {
|
||||
fn test(item: &'a T) -> U;
|
||||
}
|
||||
impl<'a> Test<'a, i32> for bool {
|
||||
$0
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
pub trait Test<'a, T, U = T> {
|
||||
fn test(item: &'a T) -> U;
|
||||
}
|
||||
impl<'a> Test<'a, i32> for bool {
|
||||
fn test(item: &'a i32) -> i32 {
|
||||
${0:todo!()}
|
||||
}
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,7 +43,7 @@ pub(crate) fn bind_unused_param(acc: &mut Assists, ctx: &AssistContext<'_>) -> O
|
|||
|
||||
acc.add(
|
||||
AssistId("bind_unused_param", AssistKind::QuickFix),
|
||||
&format!("Bind as `let _ = {ident_pat};`"),
|
||||
format!("Bind as `let _ = {ident_pat};`"),
|
||||
param.syntax().text_range(),
|
||||
|builder| {
|
||||
let line_index = ctx.db().line_index(ctx.file_id().into());
|
||||
|
|
|
@ -2,7 +2,7 @@ use either::Either;
|
|||
use ide_db::defs::{Definition, NameRefClass};
|
||||
use syntax::{
|
||||
ast::{self, AstNode, HasGenericParams, HasVisibility},
|
||||
match_ast, SyntaxNode,
|
||||
match_ast, SyntaxKind, SyntaxNode,
|
||||
};
|
||||
|
||||
use crate::{assist_context::SourceChangeBuilder, AssistContext, AssistId, AssistKind, Assists};
|
||||
|
@ -100,7 +100,9 @@ fn edit_struct_def(
|
|||
ast::make::tokens::single_newline().text(),
|
||||
);
|
||||
edit.insert(tuple_fields_text_range.start(), w.syntax().text());
|
||||
edit.insert(tuple_fields_text_range.start(), ",");
|
||||
if !w.syntax().last_token().is_some_and(|t| t.kind() == SyntaxKind::COMMA) {
|
||||
edit.insert(tuple_fields_text_range.start(), ",");
|
||||
}
|
||||
edit.insert(
|
||||
tuple_fields_text_range.start(),
|
||||
ast::make::tokens::single_newline().text(),
|
||||
|
@ -879,6 +881,29 @@ use crate::{A::Variant, Inner};
|
|||
fn f() {
|
||||
let a = Variant { field1: Inner };
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn where_clause_with_trailing_comma() {
|
||||
check_assist(
|
||||
convert_tuple_struct_to_named_struct,
|
||||
r#"
|
||||
trait Foo {}
|
||||
|
||||
struct Bar$0<T>(pub T)
|
||||
where
|
||||
T: Foo,;
|
||||
"#,
|
||||
r#"
|
||||
trait Foo {}
|
||||
|
||||
struct Bar<T>
|
||||
where
|
||||
T: Foo,
|
||||
{ pub field1: T }
|
||||
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ mod generated;
|
|||
use expect_test::expect;
|
||||
use hir::{FileRange, Semantics};
|
||||
use ide_db::{
|
||||
base_db::SourceDatabaseExt,
|
||||
base_db::{SourceDatabase, SourceRootDatabase},
|
||||
imports::insert_use::{ImportGranularity, InsertUseConfig},
|
||||
source_change::FileSystemEdit,
|
||||
EditionedFileId, RootDatabase, SnippetCap,
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
[package]
|
||||
name = "ide-completion"
|
||||
version = "0.0.0"
|
||||
description = "TBD"
|
||||
repository.workspace = true
|
||||
description = "Utilities for generating completions of user input for rust-analyzer."
|
||||
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
|
|
|
@ -24,7 +24,7 @@ pub(crate) mod vis;
|
|||
|
||||
use std::iter;
|
||||
|
||||
use hir::{sym, HasAttrs, ImportPathConfig, Name, ScopeDef, Variant};
|
||||
use hir::{sym, HasAttrs, Name, ScopeDef, Variant};
|
||||
use ide_db::{imports::import_assets::LocatedImport, RootDatabase, SymbolKind};
|
||||
use syntax::{ast, SmolStr, ToSmolStr};
|
||||
|
||||
|
@ -645,11 +645,7 @@ fn enum_variants_with_paths(
|
|||
if let Some(path) = ctx.module.find_path(
|
||||
ctx.db,
|
||||
hir::ModuleDef::from(variant),
|
||||
ImportPathConfig {
|
||||
prefer_no_std: ctx.config.prefer_no_std,
|
||||
prefer_prelude: ctx.config.prefer_prelude,
|
||||
prefer_absolute: ctx.config.prefer_absolute,
|
||||
},
|
||||
ctx.config.import_path_config(),
|
||||
) {
|
||||
// Variants with trivial paths are already added by the existing completion logic,
|
||||
// so we should avoid adding these twice
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
//! Completion of names from the current scope in expression position.
|
||||
|
||||
use hir::{sym, ImportPathConfig, Name, ScopeDef};
|
||||
use hir::{sym, Name, ScopeDef};
|
||||
use syntax::ast;
|
||||
|
||||
use crate::{
|
||||
|
@ -174,11 +174,7 @@ pub(crate) fn complete_expr_path(
|
|||
.find_path(
|
||||
ctx.db,
|
||||
hir::ModuleDef::from(strukt),
|
||||
ImportPathConfig {
|
||||
prefer_no_std: ctx.config.prefer_no_std,
|
||||
prefer_prelude: ctx.config.prefer_prelude,
|
||||
prefer_absolute: ctx.config.prefer_absolute,
|
||||
},
|
||||
ctx.config.import_path_config(),
|
||||
)
|
||||
.filter(|it| it.len() > 1);
|
||||
|
||||
|
@ -200,11 +196,7 @@ pub(crate) fn complete_expr_path(
|
|||
.find_path(
|
||||
ctx.db,
|
||||
hir::ModuleDef::from(un),
|
||||
ImportPathConfig {
|
||||
prefer_no_std: ctx.config.prefer_no_std,
|
||||
prefer_prelude: ctx.config.prefer_prelude,
|
||||
prefer_absolute: ctx.config.prefer_absolute,
|
||||
},
|
||||
ctx.config.import_path_config(),
|
||||
)
|
||||
.filter(|it| it.len() > 1);
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
//! See [`import_on_the_fly`].
|
||||
use hir::{ImportPathConfig, ItemInNs, ModuleDef};
|
||||
use hir::{ItemInNs, ModuleDef};
|
||||
use ide_db::imports::{
|
||||
import_assets::{ImportAssets, LocatedImport},
|
||||
insert_use::ImportScope,
|
||||
|
@ -256,11 +256,7 @@ fn import_on_the_fly(
|
|||
};
|
||||
let user_input_lowercased = potential_import_name.to_lowercase();
|
||||
|
||||
let import_cfg = ImportPathConfig {
|
||||
prefer_no_std: ctx.config.prefer_no_std,
|
||||
prefer_prelude: ctx.config.prefer_prelude,
|
||||
prefer_absolute: ctx.config.prefer_absolute,
|
||||
};
|
||||
let import_cfg = ctx.config.import_path_config();
|
||||
|
||||
import_assets
|
||||
.search_for_imports(&ctx.sema, import_cfg, ctx.config.insert_use.prefix_kind)
|
||||
|
@ -306,12 +302,7 @@ fn import_on_the_fly_pat_(
|
|||
ItemInNs::Values(def) => matches!(def, hir::ModuleDef::Const(_)),
|
||||
};
|
||||
let user_input_lowercased = potential_import_name.to_lowercase();
|
||||
|
||||
let cfg = ImportPathConfig {
|
||||
prefer_no_std: ctx.config.prefer_no_std,
|
||||
prefer_prelude: ctx.config.prefer_prelude,
|
||||
prefer_absolute: ctx.config.prefer_absolute,
|
||||
};
|
||||
let cfg = ctx.config.import_path_config();
|
||||
|
||||
import_assets
|
||||
.search_for_imports(&ctx.sema, cfg, ctx.config.insert_use.prefix_kind)
|
||||
|
@ -353,11 +344,7 @@ fn import_on_the_fly_method(
|
|||
|
||||
let user_input_lowercased = potential_import_name.to_lowercase();
|
||||
|
||||
let cfg = ImportPathConfig {
|
||||
prefer_no_std: ctx.config.prefer_no_std,
|
||||
prefer_prelude: ctx.config.prefer_prelude,
|
||||
prefer_absolute: ctx.config.prefer_absolute,
|
||||
};
|
||||
let cfg = ctx.config.import_path_config();
|
||||
|
||||
import_assets
|
||||
.search_for_imports(&ctx.sema, cfg, ctx.config.insert_use.prefix_kind)
|
||||
|
|
|
@ -4,7 +4,7 @@ use std::iter;
|
|||
|
||||
use hir::{HirFileIdExt, Module};
|
||||
use ide_db::{
|
||||
base_db::{SourceDatabaseExt, VfsPath},
|
||||
base_db::{SourceRootDatabase, VfsPath},
|
||||
FxHashSet, RootDatabase, SymbolKind,
|
||||
};
|
||||
use stdx::IsNoneOr;
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
mod format_like;
|
||||
|
||||
use hir::{ImportPathConfig, ItemInNs};
|
||||
use hir::ItemInNs;
|
||||
use ide_db::{
|
||||
documentation::{Documentation, HasDocs},
|
||||
imports::insert_use::ImportScope,
|
||||
|
@ -60,11 +60,7 @@ pub(crate) fn complete_postfix(
|
|||
None => return,
|
||||
};
|
||||
|
||||
let cfg = ImportPathConfig {
|
||||
prefer_no_std: ctx.config.prefer_no_std,
|
||||
prefer_prelude: ctx.config.prefer_prelude,
|
||||
prefer_absolute: ctx.config.prefer_absolute,
|
||||
};
|
||||
let cfg = ctx.config.import_path_config();
|
||||
|
||||
if let Some(drop_trait) = ctx.famous_defs().core_ops_Drop() {
|
||||
if receiver_ty.impls_trait(ctx.db, drop_trait, &[]) {
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
//! module, and we use to statically check that we only produce snippet
|
||||
//! completions if we are allowed to.
|
||||
|
||||
use hir::ImportPathConfig;
|
||||
use ide_db::{imports::insert_use::InsertUseConfig, SnippetCap};
|
||||
|
||||
use crate::snippet::Snippet;
|
||||
|
@ -45,4 +46,12 @@ impl CompletionConfig {
|
|||
.iter()
|
||||
.flat_map(|snip| snip.prefix_triggers.iter().map(move |trigger| (&**trigger, snip)))
|
||||
}
|
||||
|
||||
pub fn import_path_config(&self) -> ImportPathConfig {
|
||||
ImportPathConfig {
|
||||
prefer_no_std: self.prefer_no_std,
|
||||
prefer_prelude: self.prefer_prelude,
|
||||
prefer_absolute: self.prefer_absolute,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,6 @@ mod snippet;
|
|||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
use hir::ImportPathConfig;
|
||||
use ide_db::{
|
||||
helpers::mod_path_to_ast,
|
||||
imports::{
|
||||
|
@ -249,11 +248,7 @@ pub fn resolve_completion_edits(
|
|||
let new_ast = scope.clone_for_update();
|
||||
let mut import_insert = TextEdit::builder();
|
||||
|
||||
let cfg = ImportPathConfig {
|
||||
prefer_no_std: config.prefer_no_std,
|
||||
prefer_prelude: config.prefer_prelude,
|
||||
prefer_absolute: config.prefer_absolute,
|
||||
};
|
||||
let cfg = config.import_path_config();
|
||||
|
||||
imports.into_iter().for_each(|(full_import_path, imported_name)| {
|
||||
let items_with_name = items_locator::items_with_name(
|
||||
|
|
|
@ -10,7 +10,7 @@ pub(crate) mod type_alias;
|
|||
pub(crate) mod union_literal;
|
||||
pub(crate) mod variant;
|
||||
|
||||
use hir::{sym, AsAssocItem, HasAttrs, HirDisplay, ImportPathConfig, ModuleDef, ScopeDef, Type};
|
||||
use hir::{sym, AsAssocItem, HasAttrs, HirDisplay, ModuleDef, ScopeDef, Type};
|
||||
use ide_db::{
|
||||
documentation::{Documentation, HasDocs},
|
||||
helpers::item_name,
|
||||
|
@ -294,11 +294,7 @@ pub(crate) fn render_expr(
|
|||
.unwrap_or_else(|| String::from("..."))
|
||||
};
|
||||
|
||||
let cfg = ImportPathConfig {
|
||||
prefer_no_std: ctx.config.prefer_no_std,
|
||||
prefer_prelude: ctx.config.prefer_prelude,
|
||||
prefer_absolute: ctx.config.prefer_absolute,
|
||||
};
|
||||
let cfg = ctx.config.import_path_config();
|
||||
|
||||
let label = expr.gen_source_code(&ctx.scope, &mut label_formatter, cfg).ok()?;
|
||||
|
||||
|
|
|
@ -100,7 +100,6 @@
|
|||
// }
|
||||
// ----
|
||||
|
||||
use hir::ImportPathConfig;
|
||||
use ide_db::imports::import_assets::LocatedImport;
|
||||
use itertools::Itertools;
|
||||
use syntax::{ast, AstNode, GreenNode, SyntaxNode};
|
||||
|
@ -169,11 +168,7 @@ impl Snippet {
|
|||
}
|
||||
|
||||
fn import_edits(ctx: &CompletionContext<'_>, requires: &[GreenNode]) -> Option<Vec<LocatedImport>> {
|
||||
let import_cfg = ImportPathConfig {
|
||||
prefer_no_std: ctx.config.prefer_no_std,
|
||||
prefer_prelude: ctx.config.prefer_prelude,
|
||||
prefer_absolute: ctx.config.prefer_absolute,
|
||||
};
|
||||
let import_cfg = ctx.config.import_path_config();
|
||||
|
||||
let resolve = |import: &GreenNode| {
|
||||
let path = ast::Path::cast(SyntaxNode::new_root(import.clone()))?;
|
||||
|
|
|
@ -23,10 +23,10 @@ mod type_pos;
|
|||
mod use_tree;
|
||||
mod visibility;
|
||||
|
||||
use base_db::SourceDatabase;
|
||||
use expect_test::Expect;
|
||||
use hir::PrefixKind;
|
||||
use ide_db::{
|
||||
base_db::FileLoader,
|
||||
imports::insert_use::{ImportGranularity, InsertUseConfig},
|
||||
FilePosition, RootDatabase, SnippetCap,
|
||||
};
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
[package]
|
||||
name = "ide-db"
|
||||
version = "0.0.0"
|
||||
description = "TBD"
|
||||
repository.workspace = true
|
||||
description = "Core data structure representing IDE state for rust-analyzer."
|
||||
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
|
@ -13,7 +14,7 @@ doctest = false
|
|||
|
||||
[dependencies]
|
||||
cov-mark = "2.0.0-pre.1"
|
||||
crossbeam-channel = "0.5.5"
|
||||
crossbeam-channel.workspace = true
|
||||
tracing.workspace = true
|
||||
rayon.workspace = true
|
||||
fst = { version = "0.4.7", default-features = false }
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
use std::collections::VecDeque;
|
||||
|
||||
use base_db::SourceDatabaseExt;
|
||||
use base_db::SourceRootDatabase;
|
||||
use hir::{Crate, DescendPreference, ItemInNs, ModuleDef, Name, Semantics};
|
||||
use span::FileId;
|
||||
use syntax::{
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
//! This crate defines the core datastructure representing IDE state -- `RootDatabase`.
|
||||
//! This crate defines the core data structure representing IDE state -- `RootDatabase`.
|
||||
//!
|
||||
//! It is mainly a `HirDatabase` for semantic analysis, plus a `SymbolsDatabase`, for fuzzy search.
|
||||
|
||||
|
@ -74,7 +74,7 @@ pub type FilePosition = FilePositionWrapper<FileId>;
|
|||
pub type FileRange = FileRangeWrapper<FileId>;
|
||||
|
||||
#[salsa::database(
|
||||
base_db::SourceDatabaseExtStorage,
|
||||
base_db::SourceRootDatabaseStorage,
|
||||
base_db::SourceDatabaseStorage,
|
||||
hir::db::ExpandDatabaseStorage,
|
||||
hir::db::DefDatabaseStorage,
|
||||
|
@ -125,9 +125,6 @@ impl Upcast<dyn HirDatabase> for RootDatabase {
|
|||
}
|
||||
|
||||
impl FileLoader for RootDatabase {
|
||||
fn file_text(&self, file_id: FileId) -> Arc<str> {
|
||||
FileLoaderDelegate(self).file_text(file_id)
|
||||
}
|
||||
fn resolve_path(&self, path: AnchoredPath<'_>) -> Option<FileId> {
|
||||
FileLoaderDelegate(self).resolve_path(path)
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ use itertools::Itertools;
|
|||
use rustc_hash::FxHashMap;
|
||||
use syntax::{
|
||||
ast::{self, make, AstNode, HasGenericArgs},
|
||||
ted, SyntaxNode,
|
||||
ted, NodeOrToken, SyntaxNode,
|
||||
};
|
||||
|
||||
#[derive(Default)]
|
||||
|
@ -328,10 +328,26 @@ impl Ctx<'_> {
|
|||
let qualified = make::path_from_segments(std::iter::once(segment), false);
|
||||
ted::replace(path.syntax(), qualified.clone_for_update().syntax());
|
||||
} else if let Some(path_ty) = ast::PathType::cast(parent) {
|
||||
ted::replace(
|
||||
path_ty.syntax(),
|
||||
subst.clone_subtree().clone_for_update().syntax(),
|
||||
);
|
||||
let old = path_ty.syntax();
|
||||
|
||||
if old.parent().is_some() {
|
||||
ted::replace(old, subst.clone_subtree().clone_for_update().syntax());
|
||||
} else {
|
||||
// Some `path_ty` has no parent, especially ones made for default value
|
||||
// of type parameters.
|
||||
// In this case, `ted` cannot replace `path_ty` with `subst` directly.
|
||||
// So, just replace its children as long as the `subst` is the same type.
|
||||
let new = subst.clone_subtree().clone_for_update();
|
||||
if !matches!(new, ast::Type::PathType(..)) {
|
||||
return None;
|
||||
}
|
||||
let start = path_ty.syntax().first_child().map(NodeOrToken::Node)?;
|
||||
let end = path_ty.syntax().last_child().map(NodeOrToken::Node)?;
|
||||
ted::replace_all(
|
||||
start..=end,
|
||||
new.syntax().children().map(NodeOrToken::Node).collect::<Vec<_>>(),
|
||||
);
|
||||
}
|
||||
} else {
|
||||
ted::replace(
|
||||
path.syntax(),
|
||||
|
|
|
@ -11,7 +11,7 @@ use hir::db::DefDatabase;
|
|||
use crate::{
|
||||
base_db::{
|
||||
salsa::{Database, ParallelDatabase, Snapshot},
|
||||
Cancelled, CrateId, SourceDatabase, SourceDatabaseExt,
|
||||
Cancelled, CrateId, SourceDatabase, SourceRootDatabase,
|
||||
},
|
||||
FxIndexMap, RootDatabase,
|
||||
};
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
use std::mem;
|
||||
|
||||
use base_db::{salsa::Database, SourceDatabase, SourceDatabaseExt};
|
||||
use base_db::{salsa::Database, SourceDatabase, SourceRootDatabase};
|
||||
use hir::{
|
||||
sym, AsAssocItem, DefWithBody, DescendPreference, FileRange, HasAttrs, HasSource, HirFileIdExt,
|
||||
InFile, InRealFile, ModuleSource, PathResolution, Semantics, Visibility,
|
||||
|
@ -663,9 +663,16 @@ impl<'a> FindUsages<'a> {
|
|||
name_ref: &ast::NameRef,
|
||||
sink: &mut dyn FnMut(EditionedFileId, FileReference) -> bool,
|
||||
) -> bool {
|
||||
// See https://github.com/rust-lang/rust-analyzer/pull/15864/files/e0276dc5ddc38c65240edb408522bb869f15afb4#r1389848845
|
||||
let ty_eq = |ty: hir::Type| match (ty.as_adt(), self_ty.as_adt()) {
|
||||
(Some(ty), Some(self_ty)) => ty == self_ty,
|
||||
(None, None) => ty == *self_ty,
|
||||
_ => false,
|
||||
};
|
||||
|
||||
match NameRefClass::classify(self.sema, name_ref) {
|
||||
Some(NameRefClass::Definition(Definition::SelfType(impl_)))
|
||||
if impl_.self_ty(self.sema.db).as_adt() == self_ty.as_adt() =>
|
||||
if ty_eq(impl_.self_ty(self.sema.db)) =>
|
||||
{
|
||||
let FileRange { file_id, range } = self.sema.original_range(name_ref.syntax());
|
||||
let reference = FileReference {
|
||||
|
|
|
@ -29,7 +29,7 @@ use std::{
|
|||
|
||||
use base_db::{
|
||||
salsa::{self, ParallelDatabase},
|
||||
SourceDatabaseExt, SourceRootId, Upcast,
|
||||
SourceRootDatabase, SourceRootId, Upcast,
|
||||
};
|
||||
use fst::{raw::IndexedValue, Automaton, Streamer};
|
||||
use hir::{
|
||||
|
@ -100,7 +100,7 @@ impl Query {
|
|||
}
|
||||
|
||||
#[salsa::query_group(SymbolsDatabaseStorage)]
|
||||
pub trait SymbolsDatabase: HirDatabase + SourceDatabaseExt + Upcast<dyn HirDatabase> {
|
||||
pub trait SymbolsDatabase: HirDatabase + SourceRootDatabase + Upcast<dyn HirDatabase> {
|
||||
/// The symbol index for a given module. These modules should only be in source roots that
|
||||
/// are inside local_roots.
|
||||
fn module_symbols(&self, module: Module) -> Arc<SymbolIndex>;
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
[package]
|
||||
name = "ide-diagnostics"
|
||||
version = "0.0.0"
|
||||
description = "TBD"
|
||||
repository.workspace = true
|
||||
description = "Diagnostics rendering and fixits for rust-analyzer."
|
||||
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
|
|
101
crates/ide-diagnostics/src/handlers/await_outside_of_async.rs
Normal file
101
crates/ide-diagnostics/src/handlers/await_outside_of_async.rs
Normal file
|
@ -0,0 +1,101 @@
|
|||
use crate::{adjusted_display_range, Diagnostic, DiagnosticsContext};
|
||||
|
||||
// Diagnostic: await-outside-of-async
|
||||
//
|
||||
// This diagnostic is triggered if the `await` keyword is used outside of an async function or block
|
||||
pub(crate) fn await_outside_of_async(
|
||||
ctx: &DiagnosticsContext<'_>,
|
||||
d: &hir::AwaitOutsideOfAsync,
|
||||
) -> Diagnostic {
|
||||
let display_range =
|
||||
adjusted_display_range(ctx, d.node, &|node| Some(node.await_token()?.text_range()));
|
||||
Diagnostic::new(
|
||||
crate::DiagnosticCode::RustcHardError("E0728"),
|
||||
format!("`await` is used inside {}, which is not an `async` context", d.location),
|
||||
display_range,
|
||||
)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::tests::check_diagnostics;
|
||||
|
||||
#[test]
|
||||
fn await_inside_non_async_fn() {
|
||||
check_diagnostics(
|
||||
r#"
|
||||
async fn foo() {}
|
||||
|
||||
fn bar() {
|
||||
foo().await;
|
||||
//^^^^^ error: `await` is used inside non-async function, which is not an `async` context
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn await_inside_async_fn() {
|
||||
check_diagnostics(
|
||||
r#"
|
||||
async fn foo() {}
|
||||
|
||||
async fn bar() {
|
||||
foo().await;
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn await_inside_closure() {
|
||||
check_diagnostics(
|
||||
r#"
|
||||
async fn foo() {}
|
||||
|
||||
async fn bar() {
|
||||
let _a = || { foo().await };
|
||||
//^^^^^ error: `await` is used inside non-async closure, which is not an `async` context
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn await_inside_async_block() {
|
||||
check_diagnostics(
|
||||
r#"
|
||||
async fn foo() {}
|
||||
|
||||
fn bar() {
|
||||
let _a = async { foo().await };
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn await_in_complex_context() {
|
||||
check_diagnostics(
|
||||
r#"
|
||||
async fn foo() {}
|
||||
|
||||
fn bar() {
|
||||
async fn baz() {
|
||||
let a = foo().await;
|
||||
}
|
||||
|
||||
let x = || {
|
||||
let y = async {
|
||||
baz().await;
|
||||
let z = || {
|
||||
baz().await;
|
||||
//^^^^^ error: `await` is used inside non-async closure, which is not an `async` context
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
}
|
|
@ -42,7 +42,10 @@ mod tests {
|
|||
use crate::{tests::check_diagnostics_with_config, DiagnosticsConfig};
|
||||
|
||||
pub(crate) fn check(ra_fixture: &str) {
|
||||
let config = DiagnosticsConfig::test_sample();
|
||||
let config = DiagnosticsConfig {
|
||||
disabled: std::iter::once("unlinked-file".to_owned()).collect(),
|
||||
..DiagnosticsConfig::test_sample()
|
||||
};
|
||||
check_diagnostics_with_config(config, ra_fixture)
|
||||
}
|
||||
|
||||
|
@ -168,6 +171,27 @@ union FooBar {
|
|||
#[cfg(a)] baz: u32,
|
||||
//^^^^^^^^^^^^^^^^^^ weak: code is inactive due to #[cfg] directives: a is disabled
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn modules() {
|
||||
check(
|
||||
r#"
|
||||
//- /main.rs
|
||||
#[cfg(outline)] mod outline;
|
||||
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^ weak: code is inactive due to #[cfg] directives: outline is disabled
|
||||
|
||||
mod outline_inner;
|
||||
//^^^^^^^^^^^^^^^^^^ weak: code is inactive due to #[cfg] directives: outline_inner is disabled
|
||||
|
||||
#[cfg(inline)] mod inline {}
|
||||
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^ weak: code is inactive due to #[cfg] directives: inline is disabled
|
||||
|
||||
//- /outline_inner.rs
|
||||
#![cfg(outline_inner)]
|
||||
//- /outline.rs
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -273,11 +273,7 @@ fn f() {
|
|||
|
||||
#[test]
|
||||
fn include_does_not_break_diagnostics() {
|
||||
let mut config = DiagnosticsConfig::test_sample();
|
||||
config.disabled.insert("inactive-code".to_owned());
|
||||
config.disabled.insert("unlinked-file".to_owned());
|
||||
check_diagnostics_with_config(
|
||||
config,
|
||||
check_diagnostics(
|
||||
r#"
|
||||
//- minicore: include
|
||||
//- /lib.rs crate:lib
|
||||
|
|
|
@ -472,4 +472,18 @@ fn f(
|
|||
"#,
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn no_type_mismatches_when_arg_count_mismatch() {
|
||||
check_diagnostics(
|
||||
r#"
|
||||
fn foo((): (), (): ()) {
|
||||
foo(1, 2, 3);
|
||||
// ^^ error: expected 2 arguments, found 3
|
||||
foo(1);
|
||||
// ^ error: expected 2 arguments, found 1
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1032,6 +1032,44 @@ fn f() {
|
|||
check_diagnostics_no_bails(&code);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn min_exhaustive() {
|
||||
check_diagnostics(
|
||||
r#"
|
||||
//- minicore: result
|
||||
fn test(x: Result<i32, !>) {
|
||||
match x {
|
||||
Ok(_y) => {}
|
||||
}
|
||||
}
|
||||
"#,
|
||||
);
|
||||
check_diagnostics(
|
||||
r#"
|
||||
//- minicore: result
|
||||
fn test(ptr: *const Result<i32, !>) {
|
||||
unsafe {
|
||||
match *ptr {
|
||||
//^^^^ error: missing match arm: `Err(!)` not covered
|
||||
Ok(_x) => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
"#,
|
||||
);
|
||||
check_diagnostics(
|
||||
r#"
|
||||
//- minicore: result
|
||||
fn test(x: Result<i32, &'static !>) {
|
||||
match x {
|
||||
//^ error: missing match arm: `Err(_)` not covered
|
||||
Ok(_y) => {}
|
||||
}
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
mod rust_unstable {
|
||||
use super::*;
|
||||
|
||||
|
|
|
@ -483,6 +483,30 @@ unsafe fn foo() -> u8 {
|
|||
|
||||
fn main() {
|
||||
let x = format!("foo: {}", foo$0());
|
||||
}
|
||||
"#,
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rustc_deprecated_safe_2024() {
|
||||
check_diagnostics(
|
||||
r#"
|
||||
//- /ed2021.rs crate:ed2021 edition:2021
|
||||
#[rustc_deprecated_safe_2024]
|
||||
unsafe fn safe() -> u8 {
|
||||
0
|
||||
}
|
||||
//- /ed2024.rs crate:ed2024 edition:2024
|
||||
#[rustc_deprecated_safe_2024]
|
||||
unsafe fn not_safe() -> u8 {
|
||||
0
|
||||
}
|
||||
//- /main.rs crate:main deps:ed2021,ed2024
|
||||
fn main() {
|
||||
ed2021::safe();
|
||||
ed2024::not_safe();
|
||||
//^^^^^^^^^^^^^^^^^^💡 error: this operation is unsafe and requires an unsafe function or block
|
||||
}
|
||||
"#,
|
||||
)
|
||||
|
|
|
@ -41,6 +41,67 @@ fn main() {
|
|||
fn main() {
|
||||
let Some(_) | None = Some(5);
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn option_nonexhaustive_inside_blocks() {
|
||||
check_diagnostics(
|
||||
r#"
|
||||
//- minicore: option
|
||||
fn main() {
|
||||
'_a: {
|
||||
let None = Some(5);
|
||||
//^^^^ error: non-exhaustive pattern: `Some(_)` not covered
|
||||
}
|
||||
}
|
||||
"#,
|
||||
);
|
||||
|
||||
check_diagnostics(
|
||||
r#"
|
||||
//- minicore: future, option
|
||||
fn main() {
|
||||
let _ = async {
|
||||
let None = Some(5);
|
||||
//^^^^ error: non-exhaustive pattern: `Some(_)` not covered
|
||||
};
|
||||
}
|
||||
"#,
|
||||
);
|
||||
|
||||
check_diagnostics(
|
||||
r#"
|
||||
//- minicore: option
|
||||
fn main() {
|
||||
unsafe {
|
||||
let None = Some(5);
|
||||
//^^^^ error: non-exhaustive pattern: `Some(_)` not covered
|
||||
}
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn min_exhaustive() {
|
||||
check_diagnostics(
|
||||
r#"
|
||||
//- minicore: result
|
||||
fn test(x: Result<i32, !>) {
|
||||
let Ok(_y) = x;
|
||||
}
|
||||
"#,
|
||||
);
|
||||
|
||||
check_diagnostics(
|
||||
r#"
|
||||
//- minicore: result
|
||||
fn test(x: Result<i32, &'static !>) {
|
||||
let Ok(_y) = x;
|
||||
//^^^^^^ error: non-exhaustive pattern: `Err(_)` not covered
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -2,8 +2,12 @@ use either::Either;
|
|||
use hir::{db::ExpandDatabase, ClosureStyle, HirDisplay, HirFileIdExt, InFile, Type};
|
||||
use ide_db::{famous_defs::FamousDefs, source_change::SourceChange};
|
||||
use syntax::{
|
||||
ast::{self, BlockExpr, ExprStmt},
|
||||
AstNode, AstPtr,
|
||||
ast::{
|
||||
self,
|
||||
edit::{AstNodeEdit, IndentLevel},
|
||||
BlockExpr, Expr, ExprStmt,
|
||||
},
|
||||
AstNode, AstPtr, TextSize,
|
||||
};
|
||||
use text_edit::TextEdit;
|
||||
|
||||
|
@ -119,6 +123,38 @@ fn add_missing_ok_or_some(
|
|||
return None;
|
||||
}
|
||||
|
||||
if d.actual.is_unit() {
|
||||
if let Expr::BlockExpr(block) = &expr {
|
||||
if block.tail_expr().is_none() {
|
||||
let mut builder = TextEdit::builder();
|
||||
let block_indent = block.indent_level();
|
||||
|
||||
if block.statements().count() == 0 {
|
||||
// Empty block
|
||||
let indent = block_indent + 1;
|
||||
builder.insert(
|
||||
block.syntax().text_range().start() + TextSize::from(1),
|
||||
format!("\n{indent}{variant_name}(())\n{block_indent}"),
|
||||
);
|
||||
} else {
|
||||
let indent = IndentLevel::from(1);
|
||||
builder.insert(
|
||||
block.syntax().text_range().end() - TextSize::from(1),
|
||||
format!("{indent}{variant_name}(())\n{block_indent}"),
|
||||
);
|
||||
}
|
||||
|
||||
let source_change = SourceChange::from_text_edit(
|
||||
expr_ptr.file_id.original_file(ctx.sema.db),
|
||||
builder.finish(),
|
||||
);
|
||||
let name = format!("Insert {variant_name}(()) as the tail of this block");
|
||||
acc.push(fix("insert_wrapped_unit", &name, source_change, expr_range));
|
||||
}
|
||||
return Some(());
|
||||
}
|
||||
}
|
||||
|
||||
let mut builder = TextEdit::builder();
|
||||
builder.insert(expr.syntax().text_range().start(), format!("{variant_name}("));
|
||||
builder.insert(expr.syntax().text_range().end(), ")".to_owned());
|
||||
|
@ -533,6 +569,36 @@ fn div(x: i32, y: i32) -> MyResult<i32> {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_wrapped_unit_as_block_tail_expr() {
|
||||
check_fix(
|
||||
r#"
|
||||
//- minicore: result
|
||||
fn foo() -> Result<(), ()> {
|
||||
foo();
|
||||
}$0
|
||||
"#,
|
||||
r#"
|
||||
fn foo() -> Result<(), ()> {
|
||||
foo();
|
||||
Ok(())
|
||||
}
|
||||
"#,
|
||||
);
|
||||
|
||||
check_fix(
|
||||
r#"
|
||||
//- minicore: result
|
||||
fn foo() -> Result<(), ()> {}$0
|
||||
"#,
|
||||
r#"
|
||||
fn foo() -> Result<(), ()> {
|
||||
Ok(())
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_in_const_and_static() {
|
||||
check_fix(
|
||||
|
|
|
@ -4,7 +4,7 @@ use std::iter;
|
|||
|
||||
use hir::{db::DefDatabase, DefMap, InFile, ModuleSource};
|
||||
use ide_db::{
|
||||
base_db::{FileLoader, SourceDatabaseExt},
|
||||
base_db::{FileLoader, SourceDatabase, SourceRootDatabase},
|
||||
source_change::SourceChange,
|
||||
FileId, FileRange, LineIndexDatabase,
|
||||
};
|
||||
|
@ -47,7 +47,7 @@ pub(crate) fn unlinked_file(
|
|||
//
|
||||
// Only show this diagnostic on the first three characters of
|
||||
// the file, to avoid overwhelming the user during startup.
|
||||
range = FileLoader::file_text(ctx.sema.db, file_id)
|
||||
range = SourceDatabase::file_text(ctx.sema.db, file_id)
|
||||
.char_indices()
|
||||
.take(3)
|
||||
.last()
|
||||
|
@ -499,6 +499,18 @@ $0
|
|||
mod bar {
|
||||
mod foo;
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn include_macro_works() {
|
||||
check_diagnostics(
|
||||
r#"
|
||||
//- minicore: include
|
||||
//- /main.rs
|
||||
include!("bar/foo/mod.rs");
|
||||
//- /bar/foo/mod.rs
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
//! don't yet have a great pattern for how to do them properly.
|
||||
|
||||
mod handlers {
|
||||
pub(crate) mod await_outside_of_async;
|
||||
pub(crate) mod break_outside_of_loop;
|
||||
pub(crate) mod expected_function;
|
||||
pub(crate) mod inactive_code;
|
||||
|
@ -96,6 +97,7 @@ use syntax::{
|
|||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub enum DiagnosticCode {
|
||||
RustcHardError(&'static str),
|
||||
SyntaxError,
|
||||
RustcLint(&'static str),
|
||||
Clippy(&'static str),
|
||||
Ra(&'static str, Severity),
|
||||
|
@ -107,6 +109,9 @@ impl DiagnosticCode {
|
|||
DiagnosticCode::RustcHardError(e) => {
|
||||
format!("https://doc.rust-lang.org/stable/error_codes/{e}.html")
|
||||
}
|
||||
DiagnosticCode::SyntaxError => {
|
||||
String::from("https://doc.rust-lang.org/stable/reference/")
|
||||
}
|
||||
DiagnosticCode::RustcLint(e) => {
|
||||
format!("https://doc.rust-lang.org/rustc/?search={e}")
|
||||
}
|
||||
|
@ -125,6 +130,7 @@ impl DiagnosticCode {
|
|||
| DiagnosticCode::RustcLint(r)
|
||||
| DiagnosticCode::Clippy(r)
|
||||
| DiagnosticCode::Ra(r, _) => r,
|
||||
DiagnosticCode::SyntaxError => "syntax-error",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -154,7 +160,7 @@ impl Diagnostic {
|
|||
message,
|
||||
range: range.into(),
|
||||
severity: match code {
|
||||
DiagnosticCode::RustcHardError(_) => Severity::Error,
|
||||
DiagnosticCode::RustcHardError(_) | DiagnosticCode::SyntaxError => Severity::Error,
|
||||
// FIXME: Rustc lints are not always warning, but the ones that are currently implemented are all warnings.
|
||||
DiagnosticCode::RustcLint(_) => Severity::Warning,
|
||||
// FIXME: We can make this configurable, and if the user uses `cargo clippy` on flycheck, we can
|
||||
|
@ -297,31 +303,54 @@ impl DiagnosticsContext<'_> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Request diagnostics for the given [`FileId`]. The produced diagnostics may point to other files
|
||||
/// Request parser level diagnostics for the given [`FileId`].
|
||||
pub fn syntax_diagnostics(
|
||||
db: &RootDatabase,
|
||||
config: &DiagnosticsConfig,
|
||||
file_id: FileId,
|
||||
) -> Vec<Diagnostic> {
|
||||
let _p = tracing::info_span!("syntax_diagnostics").entered();
|
||||
|
||||
if config.disabled.contains("syntax-error") {
|
||||
return Vec::new();
|
||||
}
|
||||
|
||||
let sema = Semantics::new(db);
|
||||
let file_id = sema
|
||||
.attach_first_edition(file_id)
|
||||
.unwrap_or_else(|| EditionedFileId::current_edition(file_id));
|
||||
|
||||
// [#3434] Only take first 128 errors to prevent slowing down editor/ide, the number 128 is chosen arbitrarily.
|
||||
db.parse_errors(file_id)
|
||||
.as_deref()
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.take(128)
|
||||
.map(|err| {
|
||||
Diagnostic::new(
|
||||
DiagnosticCode::SyntaxError,
|
||||
format!("Syntax Error: {err}"),
|
||||
FileRange { file_id: file_id.into(), range: err.range() },
|
||||
)
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// Request semantic diagnostics for the given [`FileId`]. The produced diagnostics may point to other files
|
||||
/// due to macros.
|
||||
pub fn diagnostics(
|
||||
pub fn semantic_diagnostics(
|
||||
db: &RootDatabase,
|
||||
config: &DiagnosticsConfig,
|
||||
resolve: &AssistResolveStrategy,
|
||||
file_id: FileId,
|
||||
) -> Vec<Diagnostic> {
|
||||
let _p = tracing::info_span!("diagnostics").entered();
|
||||
let _p = tracing::info_span!("semantic_diagnostics").entered();
|
||||
let sema = Semantics::new(db);
|
||||
let file_id = sema
|
||||
.attach_first_edition(file_id)
|
||||
.unwrap_or_else(|| EditionedFileId::current_edition(file_id));
|
||||
let mut res = Vec::new();
|
||||
|
||||
// [#34344] Only take first 128 errors to prevent slowing down editor/ide, the number 128 is chosen arbitrarily.
|
||||
res.extend(db.parse_errors(file_id).as_deref().into_iter().flatten().take(128).map(|err| {
|
||||
Diagnostic::new(
|
||||
DiagnosticCode::RustcHardError("syntax-error"),
|
||||
format!("Syntax Error: {err}"),
|
||||
FileRange { file_id: file_id.into(), range: err.range() },
|
||||
)
|
||||
}));
|
||||
let parse_errors = res.len();
|
||||
|
||||
let parse = sema.parse(file_id);
|
||||
|
||||
// FIXME: This iterates the entire file which is a rather expensive operation.
|
||||
|
@ -341,13 +370,17 @@ pub fn diagnostics(
|
|||
match module {
|
||||
// A bunch of parse errors in a file indicate some bigger structural parse changes in the
|
||||
// file, so we skip semantic diagnostics so we can show these faster.
|
||||
Some(m) if parse_errors < 16 => m.diagnostics(db, &mut diags, config.style_lints),
|
||||
Some(_) => (),
|
||||
Some(m) => {
|
||||
if !db.parse_errors(file_id).as_deref().is_some_and(|es| es.len() >= 16) {
|
||||
m.diagnostics(db, &mut diags, config.style_lints);
|
||||
}
|
||||
}
|
||||
None => handlers::unlinked_file::unlinked_file(&ctx, &mut res, file_id.file_id()),
|
||||
}
|
||||
|
||||
for diag in diags {
|
||||
let d = match diag {
|
||||
AnyDiagnostic::AwaitOutsideOfAsync(d) => handlers::await_outside_of_async::await_outside_of_async(&ctx, &d),
|
||||
AnyDiagnostic::ExpectedFunction(d) => handlers::expected_function::expected_function(&ctx, &d),
|
||||
AnyDiagnostic::InactiveCode(d) => match handlers::inactive_code::inactive_code(&ctx, &d) {
|
||||
Some(it) => it,
|
||||
|
@ -363,7 +396,7 @@ pub fn diagnostics(
|
|||
res.extend(d.errors.iter().take(16).map(|err| {
|
||||
{
|
||||
Diagnostic::new(
|
||||
DiagnosticCode::RustcHardError("syntax-error"),
|
||||
DiagnosticCode::SyntaxError,
|
||||
format!("Syntax Error in Expansion: {err}"),
|
||||
ctx.resolve_precise_location(&d.node.clone(), d.precise_location),
|
||||
)
|
||||
|
@ -464,6 +497,19 @@ pub fn diagnostics(
|
|||
res
|
||||
}
|
||||
|
||||
/// Request both syntax and semantic diagnostics for the given [`FileId`].
|
||||
pub fn full_diagnostics(
|
||||
db: &RootDatabase,
|
||||
config: &DiagnosticsConfig,
|
||||
resolve: &AssistResolveStrategy,
|
||||
file_id: FileId,
|
||||
) -> Vec<Diagnostic> {
|
||||
let mut res = syntax_diagnostics(db, config, file_id);
|
||||
let sema = semantic_diagnostics(db, config, resolve, file_id);
|
||||
res.extend(sema);
|
||||
res
|
||||
}
|
||||
|
||||
// `__RA_EVERY_LINT` is a fake lint group to allow every lint in proc macros
|
||||
|
||||
static RUSTC_LINT_GROUPS_DICT: Lazy<FxHashMap<&str, Vec<&str>>> =
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#![allow(clippy::print_stderr)]
|
||||
|
||||
use ide_db::{
|
||||
assists::AssistResolveStrategy, base_db::SourceDatabaseExt, LineIndexDatabase, RootDatabase,
|
||||
assists::AssistResolveStrategy, base_db::SourceDatabase, LineIndexDatabase, RootDatabase,
|
||||
};
|
||||
use itertools::Itertools;
|
||||
use stdx::trim_indent;
|
||||
|
@ -59,10 +59,14 @@ fn check_nth_fix_with_config(
|
|||
let after = trim_indent(ra_fixture_after);
|
||||
|
||||
let (db, file_position) = RootDatabase::with_position(ra_fixture_before);
|
||||
let diagnostic =
|
||||
super::diagnostics(&db, &config, &AssistResolveStrategy::All, file_position.file_id.into())
|
||||
.pop()
|
||||
.expect("no diagnostics");
|
||||
let diagnostic = super::full_diagnostics(
|
||||
&db,
|
||||
&config,
|
||||
&AssistResolveStrategy::All,
|
||||
file_position.file_id.into(),
|
||||
)
|
||||
.pop()
|
||||
.expect("no diagnostics");
|
||||
let fix = &diagnostic
|
||||
.fixes
|
||||
.unwrap_or_else(|| panic!("{:?} diagnostic misses fixes", diagnostic.code))[nth];
|
||||
|
@ -102,37 +106,39 @@ pub(crate) fn check_has_fix(ra_fixture_before: &str, ra_fixture_after: &str) {
|
|||
let (db, file_position) = RootDatabase::with_position(ra_fixture_before);
|
||||
let mut conf = DiagnosticsConfig::test_sample();
|
||||
conf.expr_fill_default = ExprFillDefaultMode::Default;
|
||||
let fix =
|
||||
super::diagnostics(&db, &conf, &AssistResolveStrategy::All, file_position.file_id.into())
|
||||
.into_iter()
|
||||
.find(|d| {
|
||||
d.fixes
|
||||
.as_ref()
|
||||
.and_then(|fixes| {
|
||||
fixes.iter().find(|fix| {
|
||||
if !fix.target.contains_inclusive(file_position.offset) {
|
||||
return false;
|
||||
}
|
||||
let actual = {
|
||||
let source_change = fix.source_change.as_ref().unwrap();
|
||||
let file_id =
|
||||
*source_change.source_file_edits.keys().next().unwrap();
|
||||
let mut actual = db.file_text(file_id).to_string();
|
||||
let fix = super::full_diagnostics(
|
||||
&db,
|
||||
&conf,
|
||||
&AssistResolveStrategy::All,
|
||||
file_position.file_id.into(),
|
||||
)
|
||||
.into_iter()
|
||||
.find(|d| {
|
||||
d.fixes
|
||||
.as_ref()
|
||||
.and_then(|fixes| {
|
||||
fixes.iter().find(|fix| {
|
||||
if !fix.target.contains_inclusive(file_position.offset) {
|
||||
return false;
|
||||
}
|
||||
let actual = {
|
||||
let source_change = fix.source_change.as_ref().unwrap();
|
||||
let file_id = *source_change.source_file_edits.keys().next().unwrap();
|
||||
let mut actual = db.file_text(file_id).to_string();
|
||||
|
||||
for (edit, snippet_edit) in source_change.source_file_edits.values()
|
||||
{
|
||||
edit.apply(&mut actual);
|
||||
if let Some(snippet_edit) = snippet_edit {
|
||||
snippet_edit.apply(&mut actual);
|
||||
}
|
||||
}
|
||||
actual
|
||||
};
|
||||
after == actual
|
||||
})
|
||||
})
|
||||
.is_some()
|
||||
});
|
||||
for (edit, snippet_edit) in source_change.source_file_edits.values() {
|
||||
edit.apply(&mut actual);
|
||||
if let Some(snippet_edit) = snippet_edit {
|
||||
snippet_edit.apply(&mut actual);
|
||||
}
|
||||
}
|
||||
actual
|
||||
};
|
||||
after == actual
|
||||
})
|
||||
})
|
||||
.is_some()
|
||||
});
|
||||
assert!(fix.is_some(), "no diagnostic with desired fix");
|
||||
}
|
||||
|
||||
|
@ -144,38 +150,40 @@ pub(crate) fn check_has_single_fix(ra_fixture_before: &str, ra_fixture_after: &s
|
|||
let mut conf = DiagnosticsConfig::test_sample();
|
||||
conf.expr_fill_default = ExprFillDefaultMode::Default;
|
||||
let mut n_fixes = 0;
|
||||
let fix =
|
||||
super::diagnostics(&db, &conf, &AssistResolveStrategy::All, file_position.file_id.into())
|
||||
.into_iter()
|
||||
.find(|d| {
|
||||
d.fixes
|
||||
.as_ref()
|
||||
.and_then(|fixes| {
|
||||
n_fixes += fixes.len();
|
||||
fixes.iter().find(|fix| {
|
||||
if !fix.target.contains_inclusive(file_position.offset) {
|
||||
return false;
|
||||
}
|
||||
let actual = {
|
||||
let source_change = fix.source_change.as_ref().unwrap();
|
||||
let file_id =
|
||||
*source_change.source_file_edits.keys().next().unwrap();
|
||||
let mut actual = db.file_text(file_id).to_string();
|
||||
let fix = super::full_diagnostics(
|
||||
&db,
|
||||
&conf,
|
||||
&AssistResolveStrategy::All,
|
||||
file_position.file_id.into(),
|
||||
)
|
||||
.into_iter()
|
||||
.find(|d| {
|
||||
d.fixes
|
||||
.as_ref()
|
||||
.and_then(|fixes| {
|
||||
n_fixes += fixes.len();
|
||||
fixes.iter().find(|fix| {
|
||||
if !fix.target.contains_inclusive(file_position.offset) {
|
||||
return false;
|
||||
}
|
||||
let actual = {
|
||||
let source_change = fix.source_change.as_ref().unwrap();
|
||||
let file_id = *source_change.source_file_edits.keys().next().unwrap();
|
||||
let mut actual = db.file_text(file_id).to_string();
|
||||
|
||||
for (edit, snippet_edit) in source_change.source_file_edits.values()
|
||||
{
|
||||
edit.apply(&mut actual);
|
||||
if let Some(snippet_edit) = snippet_edit {
|
||||
snippet_edit.apply(&mut actual);
|
||||
}
|
||||
}
|
||||
actual
|
||||
};
|
||||
after == actual
|
||||
})
|
||||
})
|
||||
.is_some()
|
||||
});
|
||||
for (edit, snippet_edit) in source_change.source_file_edits.values() {
|
||||
edit.apply(&mut actual);
|
||||
if let Some(snippet_edit) = snippet_edit {
|
||||
snippet_edit.apply(&mut actual);
|
||||
}
|
||||
}
|
||||
actual
|
||||
};
|
||||
after == actual
|
||||
})
|
||||
})
|
||||
.is_some()
|
||||
});
|
||||
assert!(fix.is_some(), "no diagnostic with desired fix");
|
||||
assert!(n_fixes == 1, "Too many fixes suggested");
|
||||
}
|
||||
|
@ -183,7 +191,7 @@ pub(crate) fn check_has_single_fix(ra_fixture_before: &str, ra_fixture_after: &s
|
|||
/// Checks that there's a diagnostic *without* fix at `$0`.
|
||||
pub(crate) fn check_no_fix(ra_fixture: &str) {
|
||||
let (db, file_position) = RootDatabase::with_position(ra_fixture);
|
||||
let diagnostic = super::diagnostics(
|
||||
let diagnostic = super::full_diagnostics(
|
||||
&db,
|
||||
&DiagnosticsConfig::test_sample(),
|
||||
&AssistResolveStrategy::All,
|
||||
|
@ -215,7 +223,7 @@ pub(crate) fn check_diagnostics_with_config(config: DiagnosticsConfig, ra_fixtur
|
|||
.iter()
|
||||
.copied()
|
||||
.flat_map(|file_id| {
|
||||
super::diagnostics(&db, &config, &AssistResolveStrategy::All, file_id.into())
|
||||
super::full_diagnostics(&db, &config, &AssistResolveStrategy::All, file_id.into())
|
||||
.into_iter()
|
||||
.map(|d| {
|
||||
let mut annotation = String::new();
|
||||
|
@ -243,6 +251,12 @@ pub(crate) fn check_diagnostics_with_config(config: DiagnosticsConfig, ra_fixtur
|
|||
let mut actual = annotations.remove(&file_id).unwrap_or_default();
|
||||
let expected = extract_annotations(&db.file_text(file_id));
|
||||
actual.sort_by_key(|(range, _)| range.start());
|
||||
// FIXME: We should panic on duplicates instead, but includes currently cause us to report
|
||||
// diagnostics twice for the calling module when both files are queried.
|
||||
actual.dedup();
|
||||
// actual.iter().duplicates().for_each(|(range, msg)| {
|
||||
// panic!("duplicate diagnostic at {:?}: {msg:?}", line_index.line_col(range.start()))
|
||||
// });
|
||||
if expected.is_empty() {
|
||||
// makes minicore smoke test debuggable
|
||||
for (e, _) in &actual {
|
||||
|
@ -277,10 +291,10 @@ fn test_disabled_diagnostics() {
|
|||
let (db, file_id) = RootDatabase::with_single_file(r#"mod foo;"#);
|
||||
let file_id = file_id.into();
|
||||
|
||||
let diagnostics = super::diagnostics(&db, &config, &AssistResolveStrategy::All, file_id);
|
||||
let diagnostics = super::full_diagnostics(&db, &config, &AssistResolveStrategy::All, file_id);
|
||||
assert!(diagnostics.is_empty());
|
||||
|
||||
let diagnostics = super::diagnostics(
|
||||
let diagnostics = super::full_diagnostics(
|
||||
&db,
|
||||
&DiagnosticsConfig::test_sample(),
|
||||
&AssistResolveStrategy::All,
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
[package]
|
||||
name = "ide-ssr"
|
||||
version = "0.0.0"
|
||||
description = "Structural search and replace of Rust code"
|
||||
repository = "https://github.com/rust-lang/rust-analyzer"
|
||||
repository.workspace = true
|
||||
description = "Structural search and replace of Rust code for rust-analyzer."
|
||||
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue