mirror of
https://github.com/rust-lang/rust.git
synced 2026-05-04 01:42:54 +03:00
Merge commit '574e23ec508064613783cba3d1833a95fd9a5080' into sync-from-ra
This commit is contained in:
@@ -3,6 +3,7 @@ xtask = "run --package xtask --bin xtask --"
|
||||
tq = "test -- -q"
|
||||
qt = "tq"
|
||||
lint = "clippy --all-targets -- --cap-lints warn"
|
||||
codegen = "run --package xtask --bin xtask -- codegen"
|
||||
|
||||
[target.x86_64-pc-windows-msvc]
|
||||
linker = "rust-lld"
|
||||
|
||||
@@ -79,6 +79,9 @@ jobs:
|
||||
if: matrix.os == 'ubuntu-latest'
|
||||
run: sed -i '/\[profile.dev]/a opt-level=1' Cargo.toml
|
||||
|
||||
- name: Codegen checks (rust-analyzer)
|
||||
run: cargo codegen --check
|
||||
|
||||
- name: Compile (tests)
|
||||
run: cargo test --no-run --locked ${{ env.USE_SYSROOT_ABI }}
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@ extend-exclude = [
|
||||
"crates/parser/test_data/lexer/err/",
|
||||
"crates/project-model/test_data/",
|
||||
]
|
||||
ignore-hidden = false
|
||||
|
||||
[default]
|
||||
extend-ignore-re = [
|
||||
|
||||
+288
-360
@@ -4,9 +4,9 @@ version = 3
|
||||
|
||||
[[package]]
|
||||
name = "addr2line"
|
||||
version = "0.19.0"
|
||||
version = "0.21.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97"
|
||||
checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb"
|
||||
dependencies = [
|
||||
"gimli",
|
||||
]
|
||||
@@ -28,9 +28,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.75"
|
||||
version = "1.0.80"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6"
|
||||
checksum = "5ad32ce52e4161730f7098c077cd2ed6229b5804ccf99e5366be1ab72a98b4e1"
|
||||
|
||||
[[package]]
|
||||
name = "arbitrary"
|
||||
@@ -52,16 +52,16 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||
|
||||
[[package]]
|
||||
name = "backtrace"
|
||||
version = "0.3.67"
|
||||
version = "0.3.69"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca"
|
||||
checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837"
|
||||
dependencies = [
|
||||
"addr2line",
|
||||
"cc",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"miniz_oxide 0.6.2",
|
||||
"object 0.30.4",
|
||||
"miniz_oxide",
|
||||
"object 0.32.2",
|
||||
"rustc-demangle",
|
||||
]
|
||||
|
||||
@@ -71,7 +71,6 @@ version = "0.0.0"
|
||||
dependencies = [
|
||||
"cfg",
|
||||
"la-arena 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"profile",
|
||||
"rustc-hash",
|
||||
"salsa",
|
||||
"semver",
|
||||
@@ -91,30 +90,30 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.4.1"
|
||||
version = "2.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07"
|
||||
checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf"
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.4.3"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
|
||||
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
|
||||
|
||||
[[package]]
|
||||
name = "camino"
|
||||
version = "1.1.4"
|
||||
version = "1.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c530edf18f37068ac2d977409ed5cd50d53d73bc653c7647b48eb78976ac9ae2"
|
||||
checksum = "c59e92b5a388f549b863a7bea62612c09f24c8393560709a54558a9abdfb3b9c"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cargo-platform"
|
||||
version = "0.1.2"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cbdb825da8a5df079a43676dbe042702f1707b1109f713a01420fbb4cc71fa27"
|
||||
checksum = "694c8807f2ae16faecc43dc17d74b3eb042482789fd0eb64b39a2e04e087053f"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
@@ -135,9 +134,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.79"
|
||||
version = "1.0.89"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
|
||||
checksum = "a0ba8f7aaa012f30d5b2861462f6708eccd49c3c39863fe083a308035f63d723"
|
||||
|
||||
[[package]]
|
||||
name = "cfg"
|
||||
@@ -177,7 +176,7 @@ version = "0.96.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ff550c2cdd63ff74394214dce03d06386928a641c0f08837535f04af573a966d"
|
||||
dependencies = [
|
||||
"bitflags 2.4.1",
|
||||
"bitflags 2.4.2",
|
||||
"chalk-derive",
|
||||
"lazy_static",
|
||||
]
|
||||
@@ -217,7 +216,7 @@ version = "2.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5080df6b0f0ecb76cab30808f00d937ba725cebe266a3da8cd89dff92f2a9916"
|
||||
dependencies = [
|
||||
"nix 0.26.2",
|
||||
"nix 0.26.4",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
@@ -240,64 +239,55 @@ checksum = "0d48d8f76bd9331f19fe2aaf3821a9f9fb32c3963e1e3d6ce82a8c09cef7444a"
|
||||
|
||||
[[package]]
|
||||
name = "crc32fast"
|
||||
version = "1.3.2"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d"
|
||||
checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-channel"
|
||||
version = "0.5.8"
|
||||
version = "0.5.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200"
|
||||
checksum = "ab3db02a9c5b5121e1e42fbdb1aeb65f5e02624cc58c43f2884c6ccac0b82f95"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-deque"
|
||||
version = "0.8.3"
|
||||
version = "0.8.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef"
|
||||
checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"crossbeam-epoch",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-epoch"
|
||||
version = "0.9.15"
|
||||
version = "0.9.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7"
|
||||
checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"cfg-if",
|
||||
"crossbeam-utils",
|
||||
"memoffset",
|
||||
"scopeguard",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-utils"
|
||||
version = "0.8.16"
|
||||
version = "0.8.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345"
|
||||
|
||||
[[package]]
|
||||
name = "ctrlc"
|
||||
version = "3.4.1"
|
||||
version = "3.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "82e95fbd621905b854affdc67943b043a0fbb6ed7385fd5a25650d19a8a6cfdf"
|
||||
checksum = "b467862cc8610ca6fc9a1532d7777cee0804e678ab45410897b9396495994a0b"
|
||||
dependencies = [
|
||||
"nix 0.27.1",
|
||||
"windows-sys 0.48.0",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -313,6 +303,15 @@ dependencies = [
|
||||
"parking_lot_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "deranged"
|
||||
version = "0.3.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4"
|
||||
dependencies = [
|
||||
"powerfmt",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "derive_arbitrary"
|
||||
version = "1.3.2"
|
||||
@@ -344,9 +343,9 @@ checksum = "9bda8e21c04aca2ae33ffc2fd8c23134f3cac46db123ba97bd9d3f3b8a4a85e1"
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.9.0"
|
||||
version = "1.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
|
||||
checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a"
|
||||
|
||||
[[package]]
|
||||
name = "ena"
|
||||
@@ -357,20 +356,11 @@ dependencies = [
|
||||
"log",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "env_logger"
|
||||
version = "0.10.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4cd405aab171cb85d6735e5c8d9db038c17d3ca007a4d2c25f337935c3d90580"
|
||||
dependencies = [
|
||||
"log",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "equivalent"
|
||||
version = "1.0.0"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "88bffebc5d80432c9b140ee17875ff173a8ab62faad5b257da912bd2f6c1c0a1"
|
||||
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
|
||||
|
||||
[[package]]
|
||||
name = "expect-test"
|
||||
@@ -384,14 +374,14 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "filetime"
|
||||
version = "0.2.22"
|
||||
version = "0.2.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d4029edd3e734da6fe05b6cd7bd2960760a616bd2ddd0d59a0124746d6272af0"
|
||||
checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"redox_syscall 0.3.5",
|
||||
"windows-sys 0.48.0",
|
||||
"redox_syscall",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -402,12 +392,12 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
|
||||
|
||||
[[package]]
|
||||
name = "flate2"
|
||||
version = "1.0.26"
|
||||
version = "1.0.28"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3b9429470923de8e8cbd4d2dc513535400b4b3fef0319fb5c4e1f520a7bef743"
|
||||
checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e"
|
||||
dependencies = [
|
||||
"crc32fast",
|
||||
"miniz_oxide 0.7.1",
|
||||
"miniz_oxide",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -428,9 +418,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "form_urlencoded"
|
||||
version = "1.2.0"
|
||||
version = "1.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652"
|
||||
checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456"
|
||||
dependencies = [
|
||||
"percent-encoding",
|
||||
]
|
||||
@@ -463,9 +453,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "gimli"
|
||||
version = "0.27.3"
|
||||
version = "0.28.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e"
|
||||
checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253"
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
@@ -481,12 +471,9 @@ checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.2.6"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
|
||||
|
||||
[[package]]
|
||||
name = "hir"
|
||||
@@ -501,7 +488,6 @@ dependencies = [
|
||||
"hir-ty",
|
||||
"itertools",
|
||||
"once_cell",
|
||||
"profile",
|
||||
"rustc-hash",
|
||||
"smallvec",
|
||||
"span",
|
||||
@@ -518,7 +504,7 @@ version = "0.0.0"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"base-db",
|
||||
"bitflags 2.4.1",
|
||||
"bitflags 2.4.2",
|
||||
"cfg",
|
||||
"cov-mark",
|
||||
"dashmap",
|
||||
@@ -565,7 +551,6 @@ dependencies = [
|
||||
"la-arena 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"limit",
|
||||
"mbe",
|
||||
"profile",
|
||||
"rustc-hash",
|
||||
"smallvec",
|
||||
"span",
|
||||
@@ -582,7 +567,7 @@ version = "0.0.0"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"base-db",
|
||||
"bitflags 2.4.1",
|
||||
"bitflags 2.4.2",
|
||||
"chalk-derive",
|
||||
"chalk-ir",
|
||||
"chalk-recursive",
|
||||
@@ -601,10 +586,9 @@ dependencies = [
|
||||
"nohash-hasher",
|
||||
"once_cell",
|
||||
"oorandom",
|
||||
"profile",
|
||||
"project-model",
|
||||
"ra-ap-rustc_abi",
|
||||
"ra-ap-rustc_index 0.35.0",
|
||||
"ra-ap-rustc_index",
|
||||
"ra-ap-rustc_pattern_analysis",
|
||||
"rustc-hash",
|
||||
"scoped-tls",
|
||||
@@ -622,11 +606,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "home"
|
||||
version = "0.5.5"
|
||||
version = "0.5.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5444c27eef6923071f7ebcc33e3444508466a76f7a2b93da00ed6e19f30c1ddb"
|
||||
checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5"
|
||||
dependencies = [
|
||||
"windows-sys 0.48.0",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -673,9 +657,7 @@ dependencies = [
|
||||
"hir",
|
||||
"ide-db",
|
||||
"itertools",
|
||||
"profile",
|
||||
"smallvec",
|
||||
"sourcegen",
|
||||
"stdx",
|
||||
"syntax",
|
||||
"test-fixture",
|
||||
@@ -695,7 +677,6 @@ dependencies = [
|
||||
"ide-db",
|
||||
"itertools",
|
||||
"once_cell",
|
||||
"profile",
|
||||
"smallvec",
|
||||
"stdx",
|
||||
"syntax",
|
||||
@@ -724,12 +705,10 @@ dependencies = [
|
||||
"memchr",
|
||||
"nohash-hasher",
|
||||
"once_cell",
|
||||
"oorandom",
|
||||
"parser",
|
||||
"profile",
|
||||
"rayon",
|
||||
"rustc-hash",
|
||||
"sourcegen",
|
||||
"span",
|
||||
"stdx",
|
||||
"syntax",
|
||||
@@ -738,7 +717,6 @@ dependencies = [
|
||||
"text-edit",
|
||||
"tracing",
|
||||
"triomphe",
|
||||
"xshell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -753,9 +731,7 @@ dependencies = [
|
||||
"ide-db",
|
||||
"itertools",
|
||||
"once_cell",
|
||||
"profile",
|
||||
"serde_json",
|
||||
"sourcegen",
|
||||
"stdx",
|
||||
"syntax",
|
||||
"test-fixture",
|
||||
@@ -785,9 +761,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "idna"
|
||||
version = "0.4.0"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c"
|
||||
checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6"
|
||||
dependencies = [
|
||||
"unicode-bidi",
|
||||
"unicode-normalization",
|
||||
@@ -795,9 +771,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "2.1.0"
|
||||
version = "2.2.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f"
|
||||
checksum = "7b0b929d511467233429c45a44ac1dcaa21ba0f5ba11e4879e6ed28ddb4f9df4"
|
||||
dependencies = [
|
||||
"equivalent",
|
||||
"hashbrown",
|
||||
@@ -835,18 +811,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.12.0"
|
||||
version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "25db6b064527c5d482d0423354fcd07a89a2dfe07b67892e62411946db7f07b0"
|
||||
checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569"
|
||||
dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.6"
|
||||
version = "1.0.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6"
|
||||
checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c"
|
||||
|
||||
[[package]]
|
||||
name = "jod-thread"
|
||||
@@ -856,9 +832,9 @@ checksum = "8b23360e99b8717f20aaa4598f5a6541efbe30630039fbc7706cf954a87947ae"
|
||||
|
||||
[[package]]
|
||||
name = "kqueue"
|
||||
version = "1.0.7"
|
||||
version = "1.0.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2c8fc60ba15bf51257aa9807a48a61013db043fcf3a78cb0d916e8e396dcad98"
|
||||
checksum = "7447f1ca1b7b563588a205fe93dea8df60fd981423a768bc1c0ded35ed147d0c"
|
||||
dependencies = [
|
||||
"kqueue-sys",
|
||||
"libc",
|
||||
@@ -866,9 +842,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "kqueue-sys"
|
||||
version = "1.0.3"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8367585489f01bc55dd27404dcf56b95e6da061a256a666ab23be9ba96a2e587"
|
||||
checksum = "ed9625ffda8729b85e45cf04090035ac368927b8cebc34898e7c120f52e4838b"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"libc",
|
||||
@@ -892,25 +868,25 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.150"
|
||||
version = "0.2.153"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c"
|
||||
checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
|
||||
|
||||
[[package]]
|
||||
name = "libloading"
|
||||
version = "0.8.0"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d580318f95776505201b28cf98eb1fa5e4be3b689633ba6a3e6cd880ff22d8cb"
|
||||
checksum = "2caa5afb8bf9f3a2652760ce7d4f62d21c4d5a423e68466fca30df82f2330164"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"windows-sys 0.48.0",
|
||||
"windows-targets 0.52.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libmimalloc-sys"
|
||||
version = "0.1.33"
|
||||
version = "0.1.35"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f4ac0e912c8ef1b735e92369695618dc5b1819f5a7bf3f167301a3ba1cea515e"
|
||||
checksum = "3979b5c37ece694f1f5e51e7ecc871fdb0f517ed04ee45f88d15d6d553cb9664"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
@@ -925,6 +901,7 @@ name = "line-index"
|
||||
version = "0.1.1"
|
||||
dependencies = [
|
||||
"nohash-hasher",
|
||||
"oorandom",
|
||||
"text-size",
|
||||
]
|
||||
|
||||
@@ -964,9 +941,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
version = "0.4.10"
|
||||
version = "0.4.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16"
|
||||
checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"scopeguard",
|
||||
@@ -974,9 +951,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.19"
|
||||
version = "0.4.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4"
|
||||
checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c"
|
||||
|
||||
[[package]]
|
||||
name = "lsp-server"
|
||||
@@ -1057,41 +1034,32 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mimalloc"
|
||||
version = "0.1.37"
|
||||
version = "0.1.39"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4e2894987a3459f3ffb755608bd82188f8ed00d0ae077f1edea29c068d639d98"
|
||||
checksum = "fa01922b5ea280a911e323e4d2fd24b7fe5cc4042e0d2cda3c40775cdc4bdc9c"
|
||||
dependencies = [
|
||||
"libmimalloc-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.6.2"
|
||||
version = "0.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa"
|
||||
dependencies = [
|
||||
"adler",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7"
|
||||
checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7"
|
||||
dependencies = [
|
||||
"adler",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mio"
|
||||
version = "0.8.5"
|
||||
version = "0.8.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5d732bc30207a6423068df043e3d02e0735b155ad7ce1a6f76fe2baa5b158de"
|
||||
checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"log",
|
||||
"wasi",
|
||||
"windows-sys 0.42.0",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1105,14 +1073,13 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nix"
|
||||
version = "0.26.2"
|
||||
version = "0.26.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bfdda3d196821d6af13126e40375cdf7da646a96114af134d5f417a9a1dc8e1a"
|
||||
checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"static_assertions",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1121,7 +1088,7 @@ version = "0.27.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053"
|
||||
dependencies = [
|
||||
"bitflags 2.4.1",
|
||||
"bitflags 2.4.2",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
]
|
||||
@@ -1138,7 +1105,7 @@ version = "6.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6205bd8bb1e454ad2e27422015fb5e4f2bcc7e08fa8f27058670d208324a4d2d"
|
||||
dependencies = [
|
||||
"bitflags 2.4.1",
|
||||
"bitflags 2.4.2",
|
||||
"crossbeam-channel",
|
||||
"filetime",
|
||||
"fsevent-sys",
|
||||
@@ -1161,10 +1128,16 @@ dependencies = [
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num_cpus"
|
||||
version = "1.15.0"
|
||||
name = "num-conv"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b"
|
||||
checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
|
||||
|
||||
[[package]]
|
||||
name = "num_cpus"
|
||||
version = "1.16.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"libc",
|
||||
@@ -1172,27 +1145,27 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "object"
|
||||
version = "0.30.4"
|
||||
version = "0.32.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "03b4680b86d9cfafba8fc491dc9b6df26b68cf40e9e6cd73909194759a63c385"
|
||||
checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "object"
|
||||
version = "0.32.0"
|
||||
version = "0.33.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "77ac5bbd07aea88c60a577a1ce218075ffd59208b2d7ca97adf9bfc5aeb21ebe"
|
||||
checksum = "d8dd6c0cdf9429bce006e1362bfce61fa1bfd8c898a643ed8d2b471934701d3d"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.18.0"
|
||||
version = "1.19.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
|
||||
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
|
||||
|
||||
[[package]]
|
||||
name = "oorandom"
|
||||
@@ -1218,9 +1191,9 @@ checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"redox_syscall 0.4.1",
|
||||
"redox_syscall",
|
||||
"smallvec",
|
||||
"windows-targets",
|
||||
"windows-targets 0.48.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1233,13 +1206,14 @@ dependencies = [
|
||||
"ra-ap-rustc_lexer",
|
||||
"sourcegen",
|
||||
"stdx",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "paste"
|
||||
version = "1.0.12"
|
||||
version = "1.0.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9f746c4065a8fa3fe23974dd82f15431cc8d40779821001404d10d2e79ca7d79"
|
||||
checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c"
|
||||
|
||||
[[package]]
|
||||
name = "paths"
|
||||
@@ -1247,9 +1221,9 @@ version = "0.0.0"
|
||||
|
||||
[[package]]
|
||||
name = "percent-encoding"
|
||||
version = "2.3.0"
|
||||
version = "2.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94"
|
||||
checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
|
||||
|
||||
[[package]]
|
||||
name = "perf-event"
|
||||
@@ -1282,9 +1256,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pin-project-lite"
|
||||
version = "0.2.9"
|
||||
version = "0.2.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116"
|
||||
checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58"
|
||||
|
||||
[[package]]
|
||||
name = "powerfmt"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
@@ -1300,9 +1280,8 @@ dependencies = [
|
||||
"indexmap",
|
||||
"la-arena 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"memmap2",
|
||||
"object 0.32.0",
|
||||
"object 0.33.0",
|
||||
"paths",
|
||||
"profile",
|
||||
"rustc-hash",
|
||||
"serde",
|
||||
"serde_json",
|
||||
@@ -1324,7 +1303,7 @@ dependencies = [
|
||||
"libloading",
|
||||
"mbe",
|
||||
"memmap2",
|
||||
"object 0.32.0",
|
||||
"object 0.33.0",
|
||||
"paths",
|
||||
"proc-macro-api",
|
||||
"proc-macro-test",
|
||||
@@ -1347,14 +1326,13 @@ name = "proc-macro-test"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"cargo_metadata",
|
||||
"toolchain",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.69"
|
||||
version = "1.0.78"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da"
|
||||
checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
@@ -1386,7 +1364,6 @@ dependencies = [
|
||||
"itertools",
|
||||
"la-arena 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"paths",
|
||||
"profile",
|
||||
"rustc-hash",
|
||||
"semver",
|
||||
"serde",
|
||||
@@ -1419,11 +1396,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pulldown-cmark"
|
||||
version = "0.9.3"
|
||||
version = "0.9.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "77a1a2f1f0a7ecff9c31abbe177637be0e97a0aef46cf8738ece09327985d998"
|
||||
checksum = "57206b407293d2bcd3af849ce869d52068623f19e1b5ff8e8778e3309439682b"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"bitflags 2.4.2",
|
||||
"memchr",
|
||||
"unicase",
|
||||
]
|
||||
@@ -1439,63 +1416,40 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.28"
|
||||
version = "1.0.35"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1b9ab9c7eadfd8df19006f1cf1a4aed13540ed5cbc047010ece5826e10825488"
|
||||
checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ra-ap-rustc_abi"
|
||||
version = "0.35.0"
|
||||
version = "0.42.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3c0baa423a2c2bfd6e4bd40e7215f7ddebd12a649ce0b65078a38b91068895aa"
|
||||
checksum = "c2ae52e2d5b08762c9464b541345f519b8719d57b643b73632bade43ecece9dc"
|
||||
dependencies = [
|
||||
"bitflags 2.4.1",
|
||||
"ra-ap-rustc_index 0.35.0",
|
||||
"bitflags 2.4.2",
|
||||
"ra-ap-rustc_index",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ra-ap-rustc_index"
|
||||
version = "0.35.0"
|
||||
version = "0.42.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "322b751895cc4a0a2ee0c6ab36ec80bc8abf5f8d76254c482f96f03c27c92ebe"
|
||||
checksum = "bfd7e10c7853fe79443d46e1d2d8ab09fe99926118e59653fb8b480d5045f126"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"ra-ap-rustc_index_macros 0.35.0",
|
||||
"smallvec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ra-ap-rustc_index"
|
||||
version = "0.37.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "df5a0ba0d08af366cf235dbe8eb7226cced7a4fe502c98aa434ccf416defd746"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"ra-ap-rustc_index_macros 0.37.0",
|
||||
"ra-ap-rustc_index_macros",
|
||||
"smallvec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ra-ap-rustc_index_macros"
|
||||
version = "0.35.0"
|
||||
version = "0.42.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "054e25eac52f0506c1309ca4317c11ad4925d7b99eb897f71aa7c3cbafb46c2b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"synstructure",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ra-ap-rustc_index_macros"
|
||||
version = "0.37.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1971ebf9a701e0e68387c264a32517dcb4861ad3a4862f2e2803c1121ade20d5"
|
||||
checksum = "47f1d1c589be6c9a9e852fadee0e60329c0f862e87442ac2fe5adae30663cc76"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -1505,9 +1459,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ra-ap-rustc_lexer"
|
||||
version = "0.35.0"
|
||||
version = "0.42.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c8da0fa51a1a97ba4296a1c78fa454815a153b472e2546b6338a0902ad59e015"
|
||||
checksum = "fa852373a757b4c723bbdc96ced7f575cad68a1e266e45fee12bc4c69a482d80"
|
||||
dependencies = [
|
||||
"unicode-properties",
|
||||
"unicode-xid",
|
||||
@@ -1515,21 +1469,21 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ra-ap-rustc_parse_format"
|
||||
version = "0.35.0"
|
||||
version = "0.42.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3851f930a54adcb76889983dcd5c00a0c4e206e190e1384dbc00d49b82dfb45e"
|
||||
checksum = "2afe3c49accd95a53ac4d72ae13bafc7d115bdd80c8cd56ab09e6fc68f482210"
|
||||
dependencies = [
|
||||
"ra-ap-rustc_index 0.35.0",
|
||||
"ra-ap-rustc_index",
|
||||
"ra-ap-rustc_lexer",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ra-ap-rustc_pattern_analysis"
|
||||
version = "0.37.0"
|
||||
version = "0.42.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2c3c0e7ca9c5bdc66e3b590688e237a22ac47a48e4eac7f46b05b2abbfaf0abd"
|
||||
checksum = "1253da23515d80c377a3998731e0ec3794997b62b989fd47db73efbde6a0bd7c"
|
||||
dependencies = [
|
||||
"ra-ap-rustc_index 0.37.0",
|
||||
"ra-ap-rustc_index",
|
||||
"rustc-hash",
|
||||
"rustc_apfloat",
|
||||
"smallvec",
|
||||
@@ -1568,9 +1522,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rayon"
|
||||
version = "1.8.0"
|
||||
version = "1.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1"
|
||||
checksum = "e4963ed1bc86e4f3ee217022bd855b297cef07fb9eac5dfa1f788b220b49b3bd"
|
||||
dependencies = [
|
||||
"either",
|
||||
"rayon-core",
|
||||
@@ -1578,23 +1532,14 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rayon-core"
|
||||
version = "1.12.0"
|
||||
version = "1.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed"
|
||||
checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2"
|
||||
dependencies = [
|
||||
"crossbeam-deque",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.3.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.4.1"
|
||||
@@ -1697,9 +1642,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.13"
|
||||
version = "1.0.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041"
|
||||
checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1"
|
||||
|
||||
[[package]]
|
||||
name = "salsa"
|
||||
@@ -1717,7 +1662,6 @@ dependencies = [
|
||||
"rustc-hash",
|
||||
"salsa-macros",
|
||||
"smallvec",
|
||||
"test-log",
|
||||
"tracing",
|
||||
"triomphe",
|
||||
]
|
||||
@@ -1758,33 +1702,33 @@ checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294"
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
version = "1.1.0"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
||||
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "1.0.17"
|
||||
version = "1.0.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed"
|
||||
checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.193"
|
||||
version = "1.0.197"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89"
|
||||
checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.193"
|
||||
version = "1.0.197"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3"
|
||||
checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -1793,9 +1737,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.108"
|
||||
version = "1.0.114"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b"
|
||||
checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"itoa",
|
||||
@@ -1805,9 +1749,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde_repr"
|
||||
version = "0.1.12"
|
||||
version = "0.1.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bcec881020c684085e55a25f7fd888954d56609ef363479dc5a1305eb0d40cab"
|
||||
checksum = "0b2e6b945e9d3df726b65d6ee24060aff8e3533d431f677a9695db04eff9dfdb"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -1816,18 +1760,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "sharded-slab"
|
||||
version = "0.1.4"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31"
|
||||
checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
version = "1.12.0"
|
||||
version = "1.13.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2593d31f82ead8df961d8bd23a64c2ccf2eb5dd34b0a34bfb4dd54011c72009e"
|
||||
checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7"
|
||||
|
||||
[[package]]
|
||||
name = "smol_str"
|
||||
@@ -1840,9 +1784,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "snap"
|
||||
version = "1.1.0"
|
||||
version = "1.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5e9f0ab6ef7eb7353d9119c170a436d1bf248eea575ac42d19d12f4e34130831"
|
||||
checksum = "1b6b67fb9a61334225b5b790716f609cd58395f895b3fe8b328786812a40bc3b"
|
||||
|
||||
[[package]]
|
||||
name = "sourcegen"
|
||||
@@ -1870,12 +1814,6 @@ version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
|
||||
|
||||
[[package]]
|
||||
name = "static_assertions"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
||||
|
||||
[[package]]
|
||||
name = "stdx"
|
||||
version = "0.0.0"
|
||||
@@ -1892,9 +1830,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.39"
|
||||
version = "2.0.52"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a"
|
||||
checksum = "b699d15b36d1f02c3e7c69f8ffef53de37aefae075d8488d4ba1a7788d574a07"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -1903,14 +1841,13 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "synstructure"
|
||||
version = "0.13.0"
|
||||
version = "0.13.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "285ba80e733fac80aa4270fbcdf83772a79b80aa35c97075320abfee4a915b06"
|
||||
checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1925,7 +1862,6 @@ dependencies = [
|
||||
"once_cell",
|
||||
"parser",
|
||||
"proc-macro2",
|
||||
"profile",
|
||||
"quote",
|
||||
"ra-ap-rustc_lexer",
|
||||
"rayon",
|
||||
@@ -1955,27 +1891,6 @@ dependencies = [
|
||||
"tt",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "test-log"
|
||||
version = "0.2.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6159ab4116165c99fc88cce31f99fa2c9dbe08d3691cb38da02fc3b45f357d2b"
|
||||
dependencies = [
|
||||
"env_logger",
|
||||
"test-log-macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "test-log-macros"
|
||||
version = "0.2.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7ba277e77219e9eea169e8508942db1bf5d8a41ff2db9b20aab5a5aadc9fa25d"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "test-utils"
|
||||
version = "0.0.0"
|
||||
@@ -2004,18 +1919,18 @@ checksum = "f18aa187839b2bdb1ad2fa35ead8c4c2976b64e4363c386d45ac0f7ee85c9233"
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.40"
|
||||
version = "1.0.57"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac"
|
||||
checksum = "1e45bcbe8ed29775f228095caf2cd67af7a4ccf756ebff23a306bf3e8b47b24b"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.40"
|
||||
version = "1.0.57"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f"
|
||||
checksum = "a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -2024,9 +1939,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "thread_local"
|
||||
version = "1.1.7"
|
||||
version = "1.1.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152"
|
||||
checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"once_cell",
|
||||
@@ -2034,9 +1949,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tikv-jemalloc-ctl"
|
||||
version = "0.5.0"
|
||||
version = "0.5.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e37706572f4b151dff7a0146e040804e9c26fe3a3118591112f05cf12a4216c1"
|
||||
checksum = "619bfed27d807b54f7f776b9430d4f8060e66ee138a28632ca898584d462c31c"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"paste",
|
||||
@@ -2045,9 +1960,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tikv-jemalloc-sys"
|
||||
version = "0.5.3+5.3.0-patched"
|
||||
version = "0.5.4+5.3.0-patched"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a678df20055b43e57ef8cddde41cdfda9a3c1a060b67f4c5836dfb1d78543ba8"
|
||||
checksum = "9402443cb8fd499b6f327e40565234ff34dbda27460c5b47db0db77443dd85d1"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
@@ -2055,9 +1970,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tikv-jemallocator"
|
||||
version = "0.5.0"
|
||||
version = "0.5.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "20612db8a13a6c06d57ec83953694185a367e16945f66565e8028d2c0bd76979"
|
||||
checksum = "965fe0c26be5c56c94e38ba547249074803efd52adfb66de62107d95aab3eaca"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"tikv-jemalloc-sys",
|
||||
@@ -2065,19 +1980,22 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.3.22"
|
||||
version = "0.3.34"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ea9e1b3cf1243ae005d9e74085d4d542f3125458f3a81af210d901dcd7411efd"
|
||||
checksum = "c8248b6521bb14bc45b4067159b9b6ad792e2d6d754d6c41fb50e29fefe38749"
|
||||
dependencies = [
|
||||
"deranged",
|
||||
"num-conv",
|
||||
"powerfmt",
|
||||
"serde",
|
||||
"time-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time-core"
|
||||
version = "0.1.1"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb"
|
||||
checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3"
|
||||
|
||||
[[package]]
|
||||
name = "tinyvec"
|
||||
@@ -2202,39 +2120,39 @@ checksum = "a3e5df347f0bf3ec1d670aad6ca5c6a1859cd9ea61d2113125794654ccced68f"
|
||||
|
||||
[[package]]
|
||||
name = "unicase"
|
||||
version = "2.6.0"
|
||||
version = "2.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6"
|
||||
checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89"
|
||||
dependencies = [
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-bidi"
|
||||
version = "0.3.13"
|
||||
version = "0.3.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460"
|
||||
checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.9"
|
||||
version = "1.0.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0"
|
||||
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-normalization"
|
||||
version = "0.1.22"
|
||||
version = "0.1.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921"
|
||||
checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5"
|
||||
dependencies = [
|
||||
"tinyvec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-properties"
|
||||
version = "0.1.0"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c7f91c8b21fbbaa18853c3d0801c78f4fc94cdb976699bb03e832e75f7fd22f0"
|
||||
checksum = "e4259d9d4425d9f0661581b804cb85fe66a4c631cadd8f490d1c13a35d5d9291"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
@@ -2244,9 +2162,9 @@ checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
|
||||
|
||||
[[package]]
|
||||
name = "url"
|
||||
version = "2.4.0"
|
||||
version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "50bff7831e19200a85b17131d085c25d7811bc4e186efdaf54bbd132994a88cb"
|
||||
checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633"
|
||||
dependencies = [
|
||||
"form_urlencoded",
|
||||
"idna",
|
||||
@@ -2293,9 +2211,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "walkdir"
|
||||
version = "2.3.3"
|
||||
version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "36df944cda56c7d8d8b7496af378e6b16de9284591917d307c9b4d313c44e698"
|
||||
checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"
|
||||
dependencies = [
|
||||
"same-file",
|
||||
"winapi-util",
|
||||
@@ -2325,9 +2243,9 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-util"
|
||||
version = "0.1.5"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
|
||||
checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
@@ -2338,149 +2256,158 @@ version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.42.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm 0.42.2",
|
||||
"windows_aarch64_msvc 0.42.2",
|
||||
"windows_i686_gnu 0.42.2",
|
||||
"windows_i686_msvc 0.42.2",
|
||||
"windows_x86_64_gnu 0.42.2",
|
||||
"windows_x86_64_gnullvm 0.42.2",
|
||||
"windows_x86_64_msvc 0.42.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
|
||||
dependencies = [
|
||||
"windows-targets",
|
||||
"windows-targets 0.48.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.52.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
|
||||
dependencies = [
|
||||
"windows-targets 0.52.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.48.0"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5"
|
||||
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm 0.48.0",
|
||||
"windows_aarch64_msvc 0.48.0",
|
||||
"windows_i686_gnu 0.48.0",
|
||||
"windows_i686_msvc 0.48.0",
|
||||
"windows_x86_64_gnu 0.48.0",
|
||||
"windows_x86_64_gnullvm 0.48.0",
|
||||
"windows_x86_64_msvc 0.48.0",
|
||||
"windows_aarch64_gnullvm 0.48.5",
|
||||
"windows_aarch64_msvc 0.48.5",
|
||||
"windows_i686_gnu 0.48.5",
|
||||
"windows_i686_msvc 0.48.5",
|
||||
"windows_x86_64_gnu 0.48.5",
|
||||
"windows_x86_64_gnullvm 0.48.5",
|
||||
"windows_x86_64_msvc 0.48.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.52.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm 0.52.4",
|
||||
"windows_aarch64_msvc 0.52.4",
|
||||
"windows_i686_gnu 0.52.4",
|
||||
"windows_i686_msvc 0.52.4",
|
||||
"windows_x86_64_gnu 0.52.4",
|
||||
"windows_x86_64_gnullvm 0.52.4",
|
||||
"windows_x86_64_msvc 0.52.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.42.2"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
|
||||
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.48.0"
|
||||
version = "0.52.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc"
|
||||
checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.42.2"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
|
||||
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.48.0"
|
||||
version = "0.52.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3"
|
||||
checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.42.2"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
|
||||
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.48.0"
|
||||
version = "0.52.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241"
|
||||
checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.42.2"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
|
||||
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.48.0"
|
||||
version = "0.52.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00"
|
||||
checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.42.2"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
|
||||
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.48.0"
|
||||
version = "0.52.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1"
|
||||
checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.42.2"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
|
||||
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.48.0"
|
||||
version = "0.52.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953"
|
||||
checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.42.2"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
|
||||
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.48.0"
|
||||
version = "0.52.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
|
||||
checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8"
|
||||
|
||||
[[package]]
|
||||
name = "write-json"
|
||||
version = "0.1.2"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "06069a848f95fceae3e5e03c0ddc8cb78452b56654ee0c8e68f938cf790fb9e3"
|
||||
checksum = "23f6174b2566cc4a74f95e1367ec343e7fa80c93cc8087f5c4a3d6a1088b2118"
|
||||
|
||||
[[package]]
|
||||
name = "xflags"
|
||||
version = "0.3.1"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c4554b580522d0ca238369c16b8f6ce34524d61dafe7244993754bbd05f2c2ea"
|
||||
checksum = "7d9e15fbb3de55454b0106e314b28e671279009b363e6f1d8e39fdc3bf048944"
|
||||
dependencies = [
|
||||
"xflags-macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "xflags-macros"
|
||||
version = "0.3.1"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f58e7b3ca8977093aae6b87b6a7730216fc4c53a6530bab5c43a783cd810c1a8"
|
||||
checksum = "672423d4fea7ffa2f6c25ba60031ea13dc6258070556f125cc4d790007d4a155"
|
||||
|
||||
[[package]]
|
||||
name = "xshell"
|
||||
@@ -2503,6 +2430,7 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"flate2",
|
||||
"stdx",
|
||||
"time",
|
||||
"write-json",
|
||||
"xflags",
|
||||
|
||||
@@ -84,11 +84,11 @@ 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.35.0", default-features = false }
|
||||
ra-ap-rustc_parse_format = { version = "0.35.0", default-features = false }
|
||||
ra-ap-rustc_index = { version = "0.35.0", default-features = false }
|
||||
ra-ap-rustc_abi = { version = "0.35.0", default-features = false }
|
||||
ra-ap-rustc_pattern_analysis = { version = "0.37.0", default-features = false }
|
||||
ra-ap-rustc_lexer = { version = "0.42.0", default-features = false }
|
||||
ra-ap-rustc_parse_format = { version = "0.42.0", default-features = false }
|
||||
ra-ap-rustc_index = { version = "0.42.0", default-features = false }
|
||||
ra-ap-rustc_abi = { version = "0.42.0", default-features = false }
|
||||
ra-ap-rustc_pattern_analysis = { version = "0.42.0", default-features = false }
|
||||
|
||||
# local crates that aren't published to crates.io. These should not have versions.
|
||||
sourcegen = { path = "./crates/sourcegen" }
|
||||
@@ -108,6 +108,7 @@ cargo_metadata = "0.18.1"
|
||||
command-group = "2.0.1"
|
||||
crossbeam-channel = "0.5.8"
|
||||
dissimilar = "1.0.7"
|
||||
dot = "0.1.4"
|
||||
either = "1.9.0"
|
||||
expect-test = "1.4.0"
|
||||
hashbrown = { version = "0.14", features = [
|
||||
@@ -117,6 +118,16 @@ indexmap = "2.1.0"
|
||||
itertools = "0.12.0"
|
||||
libc = "0.2.150"
|
||||
nohash-hasher = "0.2.0"
|
||||
oorandom = "11.1.3"
|
||||
object = { version = "0.33.0", default-features = false, features = [
|
||||
"std",
|
||||
"read_core",
|
||||
"elf",
|
||||
"macho",
|
||||
"pe",
|
||||
] }
|
||||
pulldown-cmark-to-cmark = "10.0.4"
|
||||
pulldown-cmark = { version = "0.9.0", default-features = false }
|
||||
rayon = "1.8.0"
|
||||
rustc-hash = "1.1.0"
|
||||
semver = "1.0.14"
|
||||
@@ -137,6 +148,7 @@ tracing-subscriber = { version = "0.3.18", default-features = false, features =
|
||||
"tracing-log",
|
||||
] }
|
||||
triomphe = { version = "0.1.10", default-features = false, features = ["std"] }
|
||||
url = "2.3.1"
|
||||
xshell = "0.2.5"
|
||||
|
||||
|
||||
@@ -146,6 +158,7 @@ dashmap = { version = "=5.5.3", features = ["raw-api"] }
|
||||
[workspace.lints.rust]
|
||||
rust_2018_idioms = "warn"
|
||||
unused_lifetimes = "warn"
|
||||
unreachable_pub = "warn"
|
||||
semicolon_in_expressions_from_macros = "warn"
|
||||
|
||||
[workspace.lints.clippy]
|
||||
|
||||
@@ -21,7 +21,6 @@ tracing.workspace = true
|
||||
|
||||
# local deps
|
||||
cfg.workspace = true
|
||||
profile.workspace = true
|
||||
stdx.workspace = true
|
||||
syntax.workspace = true
|
||||
vfs.workspace = true
|
||||
|
||||
@@ -43,7 +43,7 @@ pub trait Upcast<T: ?Sized> {
|
||||
}
|
||||
|
||||
pub const DEFAULT_PARSE_LRU_CAP: usize = 128;
|
||||
pub const DEFAULT_BORROWCK_LRU_CAP: usize = 256;
|
||||
pub const DEFAULT_BORROWCK_LRU_CAP: usize = 1024;
|
||||
|
||||
pub trait FileLoader {
|
||||
/// Text of the file.
|
||||
|
||||
@@ -0,0 +1,156 @@
|
||||
//! Utilities for running a cargo command like `cargo check` or `cargo test` in a separate thread and
|
||||
//! parse its stdout/stderr.
|
||||
|
||||
use std::{
|
||||
ffi::OsString,
|
||||
fmt, io,
|
||||
path::PathBuf,
|
||||
process::{ChildStderr, ChildStdout, Command, Stdio},
|
||||
};
|
||||
|
||||
use command_group::{CommandGroup, GroupChild};
|
||||
use crossbeam_channel::{unbounded, Receiver, Sender};
|
||||
use stdx::process::streaming_output;
|
||||
|
||||
/// Cargo output is structured as a one JSON per line. This trait abstracts parsing one line of
|
||||
/// cargo output into a Rust data type.
|
||||
pub(crate) trait ParseFromLine: Sized + Send + 'static {
|
||||
fn from_line(line: &str, error: &mut String) -> Option<Self>;
|
||||
fn from_eof() -> Option<Self>;
|
||||
}
|
||||
|
||||
struct CargoActor<T> {
|
||||
sender: Sender<T>,
|
||||
stdout: ChildStdout,
|
||||
stderr: ChildStderr,
|
||||
}
|
||||
|
||||
impl<T: ParseFromLine> CargoActor<T> {
|
||||
fn new(sender: Sender<T>, stdout: ChildStdout, stderr: ChildStderr) -> Self {
|
||||
CargoActor { sender, stdout, stderr }
|
||||
}
|
||||
|
||||
fn run(self) -> io::Result<(bool, String)> {
|
||||
// We manually read a line at a time, instead of using serde's
|
||||
// stream deserializers, because the deserializer cannot recover
|
||||
// from an error, resulting in it getting stuck, because we try to
|
||||
// be resilient against failures.
|
||||
//
|
||||
// Because cargo only outputs one JSON object per line, we can
|
||||
// simply skip a line if it doesn't parse, which just ignores any
|
||||
// erroneous output.
|
||||
|
||||
let mut stdout_errors = String::new();
|
||||
let mut stderr_errors = String::new();
|
||||
let mut read_at_least_one_stdout_message = false;
|
||||
let mut read_at_least_one_stderr_message = false;
|
||||
let process_line = |line: &str, error: &mut String| {
|
||||
// Try to deserialize a message from Cargo or Rustc.
|
||||
if let Some(t) = T::from_line(line, error) {
|
||||
self.sender.send(t).unwrap();
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
};
|
||||
let output = streaming_output(
|
||||
self.stdout,
|
||||
self.stderr,
|
||||
&mut |line| {
|
||||
if process_line(line, &mut stdout_errors) {
|
||||
read_at_least_one_stdout_message = true;
|
||||
}
|
||||
},
|
||||
&mut |line| {
|
||||
if process_line(line, &mut stderr_errors) {
|
||||
read_at_least_one_stderr_message = true;
|
||||
}
|
||||
},
|
||||
&mut || {
|
||||
if let Some(t) = T::from_eof() {
|
||||
self.sender.send(t).unwrap();
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
let read_at_least_one_message =
|
||||
read_at_least_one_stdout_message || read_at_least_one_stderr_message;
|
||||
let mut error = stdout_errors;
|
||||
error.push_str(&stderr_errors);
|
||||
match output {
|
||||
Ok(_) => Ok((read_at_least_one_message, error)),
|
||||
Err(e) => Err(io::Error::new(e.kind(), format!("{e:?}: {error}"))),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct JodGroupChild(GroupChild);
|
||||
|
||||
impl Drop for JodGroupChild {
|
||||
fn drop(&mut self) {
|
||||
_ = self.0.kill();
|
||||
_ = self.0.wait();
|
||||
}
|
||||
}
|
||||
|
||||
/// A handle to a cargo process used for fly-checking.
|
||||
pub(crate) struct CommandHandle<T> {
|
||||
/// The handle to the actual cargo process. As we cannot cancel directly from with
|
||||
/// a read syscall dropping and therefore terminating the process is our best option.
|
||||
child: JodGroupChild,
|
||||
thread: stdx::thread::JoinHandle<io::Result<(bool, String)>>,
|
||||
pub(crate) receiver: Receiver<T>,
|
||||
program: OsString,
|
||||
arguments: Vec<OsString>,
|
||||
current_dir: Option<PathBuf>,
|
||||
}
|
||||
|
||||
impl<T> fmt::Debug for CommandHandle<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("CommandHandle")
|
||||
.field("program", &self.program)
|
||||
.field("arguments", &self.arguments)
|
||||
.field("current_dir", &self.current_dir)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ParseFromLine> CommandHandle<T> {
|
||||
pub(crate) fn spawn(mut command: Command) -> std::io::Result<Self> {
|
||||
command.stdout(Stdio::piped()).stderr(Stdio::piped()).stdin(Stdio::null());
|
||||
let mut child = command.group_spawn().map(JodGroupChild)?;
|
||||
|
||||
let program = command.get_program().into();
|
||||
let arguments = command.get_args().map(|arg| arg.into()).collect::<Vec<OsString>>();
|
||||
let current_dir = command.get_current_dir().map(|arg| arg.to_path_buf());
|
||||
|
||||
let stdout = child.0.inner().stdout.take().unwrap();
|
||||
let stderr = child.0.inner().stderr.take().unwrap();
|
||||
|
||||
let (sender, receiver) = unbounded();
|
||||
let actor = CargoActor::<T>::new(sender, stdout, stderr);
|
||||
let thread = stdx::thread::Builder::new(stdx::thread::ThreadIntent::Worker)
|
||||
.name("CommandHandle".to_owned())
|
||||
.spawn(move || actor.run())
|
||||
.expect("failed to spawn thread");
|
||||
Ok(CommandHandle { program, arguments, current_dir, child, thread, receiver })
|
||||
}
|
||||
|
||||
pub(crate) fn cancel(mut self) {
|
||||
let _ = self.child.0.kill();
|
||||
let _ = self.child.0.wait();
|
||||
}
|
||||
|
||||
pub(crate) fn join(mut self) -> io::Result<()> {
|
||||
let _ = self.child.0.kill();
|
||||
let exit_status = self.child.0.wait()?;
|
||||
let (read_at_least_one_message, error) = self.thread.join()?;
|
||||
if read_at_least_one_message || exit_status.success() {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(io::Error::new(io::ErrorKind::Other, format!(
|
||||
"Cargo watcher failed, the command produced no valid metadata (exit code: {exit_status:?}):\n{error}"
|
||||
)))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,22 +2,18 @@
|
||||
//! another compatible command (f.x. clippy) in a background thread and provide
|
||||
//! LSP diagnostics based on the output of the command.
|
||||
|
||||
// FIXME: This crate now handles running `cargo test` needed in the test explorer in
|
||||
// addition to `cargo check`. Either split it into 3 crates (one for test, one for check
|
||||
// and one common utilities) or change its name and docs to reflect the current state.
|
||||
|
||||
#![warn(rust_2018_idioms, unused_lifetimes)]
|
||||
|
||||
use std::{
|
||||
ffi::OsString,
|
||||
fmt, io,
|
||||
path::PathBuf,
|
||||
process::{ChildStderr, ChildStdout, Command, Stdio},
|
||||
time::Duration,
|
||||
};
|
||||
use std::{fmt, io, path::PathBuf, process::Command, time::Duration};
|
||||
|
||||
use command_group::{CommandGroup, GroupChild};
|
||||
use crossbeam_channel::{never, select, unbounded, Receiver, Sender};
|
||||
use paths::{AbsPath, AbsPathBuf};
|
||||
use rustc_hash::FxHashMap;
|
||||
use serde::Deserialize;
|
||||
use stdx::process::streaming_output;
|
||||
|
||||
pub use cargo_metadata::diagnostic::{
|
||||
Applicability, Diagnostic, DiagnosticCode, DiagnosticLevel, DiagnosticSpan,
|
||||
@@ -25,6 +21,12 @@
|
||||
};
|
||||
use toolchain::Tool;
|
||||
|
||||
mod command;
|
||||
mod test_runner;
|
||||
|
||||
use command::{CommandHandle, ParseFromLine};
|
||||
pub use test_runner::{CargoTestHandle, CargoTestMessage, TestState};
|
||||
|
||||
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
|
||||
pub enum InvocationStrategy {
|
||||
Once,
|
||||
@@ -181,12 +183,12 @@ struct FlycheckActor {
|
||||
/// doesn't provide a way to read sub-process output without blocking, so we
|
||||
/// have to wrap sub-processes output handling in a thread and pass messages
|
||||
/// back over a channel.
|
||||
command_handle: Option<CommandHandle>,
|
||||
command_handle: Option<CommandHandle<CargoCheckMessage>>,
|
||||
}
|
||||
|
||||
enum Event {
|
||||
RequestStateChange(StateChange),
|
||||
CheckEvent(Option<CargoMessage>),
|
||||
CheckEvent(Option<CargoCheckMessage>),
|
||||
}
|
||||
|
||||
const SAVED_FILE_PLACEHOLDER: &str = "$saved_file";
|
||||
@@ -282,7 +284,7 @@ fn run(mut self, inbox: Receiver<StateChange>) {
|
||||
self.report_progress(Progress::DidFinish(res));
|
||||
}
|
||||
Event::CheckEvent(Some(message)) => match message {
|
||||
CargoMessage::CompilerArtifact(msg) => {
|
||||
CargoCheckMessage::CompilerArtifact(msg) => {
|
||||
tracing::trace!(
|
||||
flycheck_id = self.id,
|
||||
artifact = msg.target.name,
|
||||
@@ -291,7 +293,7 @@ fn run(mut self, inbox: Receiver<StateChange>) {
|
||||
self.report_progress(Progress::DidCheckCrate(msg.target.name));
|
||||
}
|
||||
|
||||
CargoMessage::Diagnostic(msg) => {
|
||||
CargoCheckMessage::Diagnostic(msg) => {
|
||||
tracing::trace!(
|
||||
flycheck_id = self.id,
|
||||
message = msg.message,
|
||||
@@ -448,161 +450,42 @@ fn send(&self, check_task: Message) {
|
||||
}
|
||||
}
|
||||
|
||||
struct JodGroupChild(GroupChild);
|
||||
|
||||
impl Drop for JodGroupChild {
|
||||
fn drop(&mut self) {
|
||||
_ = self.0.kill();
|
||||
_ = self.0.wait();
|
||||
}
|
||||
}
|
||||
|
||||
/// A handle to a cargo process used for fly-checking.
|
||||
struct CommandHandle {
|
||||
/// The handle to the actual cargo process. As we cannot cancel directly from with
|
||||
/// a read syscall dropping and therefore terminating the process is our best option.
|
||||
child: JodGroupChild,
|
||||
thread: stdx::thread::JoinHandle<io::Result<(bool, String)>>,
|
||||
receiver: Receiver<CargoMessage>,
|
||||
program: OsString,
|
||||
arguments: Vec<OsString>,
|
||||
current_dir: Option<PathBuf>,
|
||||
}
|
||||
|
||||
impl fmt::Debug for CommandHandle {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("CommandHandle")
|
||||
.field("program", &self.program)
|
||||
.field("arguments", &self.arguments)
|
||||
.field("current_dir", &self.current_dir)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl CommandHandle {
|
||||
fn spawn(mut command: Command) -> std::io::Result<CommandHandle> {
|
||||
command.stdout(Stdio::piped()).stderr(Stdio::piped()).stdin(Stdio::null());
|
||||
let mut child = command.group_spawn().map(JodGroupChild)?;
|
||||
|
||||
let program = command.get_program().into();
|
||||
let arguments = command.get_args().map(|arg| arg.into()).collect::<Vec<OsString>>();
|
||||
let current_dir = command.get_current_dir().map(|arg| arg.to_path_buf());
|
||||
|
||||
let stdout = child.0.inner().stdout.take().unwrap();
|
||||
let stderr = child.0.inner().stderr.take().unwrap();
|
||||
|
||||
let (sender, receiver) = unbounded();
|
||||
let actor = CargoActor::new(sender, stdout, stderr);
|
||||
let thread = stdx::thread::Builder::new(stdx::thread::ThreadIntent::Worker)
|
||||
.name("CommandHandle".to_owned())
|
||||
.spawn(move || actor.run())
|
||||
.expect("failed to spawn thread");
|
||||
Ok(CommandHandle { program, arguments, current_dir, child, thread, receiver })
|
||||
}
|
||||
|
||||
fn cancel(mut self) {
|
||||
let _ = self.child.0.kill();
|
||||
let _ = self.child.0.wait();
|
||||
}
|
||||
|
||||
fn join(mut self) -> io::Result<()> {
|
||||
let _ = self.child.0.kill();
|
||||
let exit_status = self.child.0.wait()?;
|
||||
let (read_at_least_one_message, error) = self.thread.join()?;
|
||||
if read_at_least_one_message || exit_status.success() {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(io::Error::new(io::ErrorKind::Other, format!(
|
||||
"Cargo watcher failed, the command produced no valid metadata (exit code: {exit_status:?}):\n{error}"
|
||||
)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct CargoActor {
|
||||
sender: Sender<CargoMessage>,
|
||||
stdout: ChildStdout,
|
||||
stderr: ChildStderr,
|
||||
}
|
||||
|
||||
impl CargoActor {
|
||||
fn new(sender: Sender<CargoMessage>, stdout: ChildStdout, stderr: ChildStderr) -> CargoActor {
|
||||
CargoActor { sender, stdout, stderr }
|
||||
}
|
||||
|
||||
fn run(self) -> io::Result<(bool, String)> {
|
||||
// We manually read a line at a time, instead of using serde's
|
||||
// stream deserializers, because the deserializer cannot recover
|
||||
// from an error, resulting in it getting stuck, because we try to
|
||||
// be resilient against failures.
|
||||
//
|
||||
// Because cargo only outputs one JSON object per line, we can
|
||||
// simply skip a line if it doesn't parse, which just ignores any
|
||||
// erroneous output.
|
||||
|
||||
let mut stdout_errors = String::new();
|
||||
let mut stderr_errors = String::new();
|
||||
let mut read_at_least_one_stdout_message = false;
|
||||
let mut read_at_least_one_stderr_message = false;
|
||||
let process_line = |line: &str, error: &mut String| {
|
||||
// Try to deserialize a message from Cargo or Rustc.
|
||||
let mut deserializer = serde_json::Deserializer::from_str(line);
|
||||
deserializer.disable_recursion_limit();
|
||||
if let Ok(message) = JsonMessage::deserialize(&mut deserializer) {
|
||||
match message {
|
||||
// Skip certain kinds of messages to only spend time on what's useful
|
||||
JsonMessage::Cargo(message) => match message {
|
||||
cargo_metadata::Message::CompilerArtifact(artifact) if !artifact.fresh => {
|
||||
self.sender.send(CargoMessage::CompilerArtifact(artifact)).unwrap();
|
||||
}
|
||||
cargo_metadata::Message::CompilerMessage(msg) => {
|
||||
self.sender.send(CargoMessage::Diagnostic(msg.message)).unwrap();
|
||||
}
|
||||
_ => (),
|
||||
},
|
||||
JsonMessage::Rustc(message) => {
|
||||
self.sender.send(CargoMessage::Diagnostic(message)).unwrap();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
error.push_str(line);
|
||||
error.push('\n');
|
||||
false
|
||||
};
|
||||
let output = streaming_output(
|
||||
self.stdout,
|
||||
self.stderr,
|
||||
&mut |line| {
|
||||
if process_line(line, &mut stdout_errors) {
|
||||
read_at_least_one_stdout_message = true;
|
||||
}
|
||||
},
|
||||
&mut |line| {
|
||||
if process_line(line, &mut stderr_errors) {
|
||||
read_at_least_one_stderr_message = true;
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
let read_at_least_one_message =
|
||||
read_at_least_one_stdout_message || read_at_least_one_stderr_message;
|
||||
let mut error = stdout_errors;
|
||||
error.push_str(&stderr_errors);
|
||||
match output {
|
||||
Ok(_) => Ok((read_at_least_one_message, error)),
|
||||
Err(e) => Err(io::Error::new(e.kind(), format!("{e:?}: {error}"))),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::large_enum_variant)]
|
||||
enum CargoMessage {
|
||||
enum CargoCheckMessage {
|
||||
CompilerArtifact(cargo_metadata::Artifact),
|
||||
Diagnostic(Diagnostic),
|
||||
}
|
||||
|
||||
impl ParseFromLine for CargoCheckMessage {
|
||||
fn from_line(line: &str, error: &mut String) -> Option<Self> {
|
||||
let mut deserializer = serde_json::Deserializer::from_str(line);
|
||||
deserializer.disable_recursion_limit();
|
||||
if let Ok(message) = JsonMessage::deserialize(&mut deserializer) {
|
||||
return match message {
|
||||
// Skip certain kinds of messages to only spend time on what's useful
|
||||
JsonMessage::Cargo(message) => match message {
|
||||
cargo_metadata::Message::CompilerArtifact(artifact) if !artifact.fresh => {
|
||||
Some(CargoCheckMessage::CompilerArtifact(artifact))
|
||||
}
|
||||
cargo_metadata::Message::CompilerMessage(msg) => {
|
||||
Some(CargoCheckMessage::Diagnostic(msg.message))
|
||||
}
|
||||
_ => None,
|
||||
},
|
||||
JsonMessage::Rustc(message) => Some(CargoCheckMessage::Diagnostic(message)),
|
||||
};
|
||||
}
|
||||
|
||||
error.push_str(line);
|
||||
error.push('\n');
|
||||
None
|
||||
}
|
||||
|
||||
fn from_eof() -> Option<Self> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[serde(untagged)]
|
||||
enum JsonMessage {
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
//! This module provides the functionality needed to run `cargo test` in a background
|
||||
//! thread and report the result of each test in a channel.
|
||||
|
||||
use std::process::Command;
|
||||
|
||||
use crossbeam_channel::Receiver;
|
||||
use serde::Deserialize;
|
||||
use toolchain::Tool;
|
||||
|
||||
use crate::command::{CommandHandle, ParseFromLine};
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(tag = "event", rename_all = "camelCase")]
|
||||
pub enum TestState {
|
||||
Started,
|
||||
Ok,
|
||||
Ignored,
|
||||
Failed { stdout: String },
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(tag = "type", rename_all = "camelCase")]
|
||||
pub enum CargoTestMessage {
|
||||
Test {
|
||||
name: String,
|
||||
#[serde(flatten)]
|
||||
state: TestState,
|
||||
},
|
||||
Suite,
|
||||
Finished,
|
||||
}
|
||||
|
||||
impl ParseFromLine for CargoTestMessage {
|
||||
fn from_line(line: &str, error: &mut String) -> Option<Self> {
|
||||
let mut deserializer = serde_json::Deserializer::from_str(line);
|
||||
deserializer.disable_recursion_limit();
|
||||
if let Ok(message) = CargoTestMessage::deserialize(&mut deserializer) {
|
||||
return Some(message);
|
||||
}
|
||||
|
||||
error.push_str(line);
|
||||
error.push('\n');
|
||||
None
|
||||
}
|
||||
|
||||
fn from_eof() -> Option<Self> {
|
||||
Some(CargoTestMessage::Finished)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct CargoTestHandle {
|
||||
handle: CommandHandle<CargoTestMessage>,
|
||||
}
|
||||
|
||||
// Example of a cargo test command:
|
||||
// cargo test -- module::func -Z unstable-options --format=json
|
||||
|
||||
impl CargoTestHandle {
|
||||
pub fn new(path: Option<&str>) -> std::io::Result<Self> {
|
||||
let mut cmd = Command::new(Tool::Cargo.path());
|
||||
cmd.env("RUSTC_BOOTSTRAP", "1");
|
||||
cmd.arg("test");
|
||||
cmd.arg("--");
|
||||
if let Some(path) = path {
|
||||
cmd.arg(path);
|
||||
}
|
||||
cmd.args(["-Z", "unstable-options"]);
|
||||
cmd.arg("--format=json");
|
||||
Ok(Self { handle: CommandHandle::spawn(cmd)? })
|
||||
}
|
||||
|
||||
pub fn receiver(&self) -> &Receiver<CargoTestMessage> {
|
||||
&self.handle.receiver
|
||||
}
|
||||
}
|
||||
@@ -348,7 +348,7 @@ pub(crate) fn attrs_query(db: &dyn DefDatabase, def: AttrDefId) -> Attrs {
|
||||
.raw_attrs(AttrOwner::ModItem(definition_tree_id.value.into()))
|
||||
.clone(),
|
||||
ModuleOrigin::BlockExpr { id, .. } => {
|
||||
let tree = db.block_item_tree_query(id);
|
||||
let tree = db.block_item_tree(id);
|
||||
tree.raw_attrs(AttrOwner::TopLevel).clone()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
use either::Either;
|
||||
use hir_expand::{name::Name, HirFileId, InFile};
|
||||
use la_arena::{Arena, ArenaMap};
|
||||
use profile::Count;
|
||||
use rustc_hash::FxHashMap;
|
||||
use syntax::{ast, AstPtr, SyntaxNodePtr};
|
||||
use triomphe::Arc;
|
||||
@@ -51,7 +50,6 @@ pub struct Body {
|
||||
pub body_expr: ExprId,
|
||||
/// Block expressions in this body that may contain inner items.
|
||||
block_scopes: Vec<BlockId>,
|
||||
_c: Count<Self>,
|
||||
}
|
||||
|
||||
pub type ExprPtr = AstPtr<ast::Expr>;
|
||||
@@ -216,7 +214,6 @@ fn new(
|
||||
|
||||
fn shrink_to_fit(&mut self) {
|
||||
let Self {
|
||||
_c: _,
|
||||
body_expr: _,
|
||||
block_scopes,
|
||||
exprs,
|
||||
@@ -300,7 +297,6 @@ fn default() -> Self {
|
||||
params: Default::default(),
|
||||
block_scopes: Default::default(),
|
||||
binding_owners: Default::default(),
|
||||
_c: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
ExpandError, InFile,
|
||||
};
|
||||
use intern::Interned;
|
||||
use profile::Count;
|
||||
use rustc_hash::FxHashMap;
|
||||
use smallvec::SmallVec;
|
||||
use span::AstIdMap;
|
||||
@@ -76,7 +75,6 @@ pub(super) fn lower(
|
||||
params: Vec::new(),
|
||||
body_expr: dummy_expr_id(),
|
||||
block_scopes: Vec::new(),
|
||||
_c: Count::new(),
|
||||
},
|
||||
expander,
|
||||
current_try_block_label: None,
|
||||
@@ -705,7 +703,8 @@ fn desugar_try_block(&mut self, e: BlockExpr) -> ExprId {
|
||||
let Some(try_from_output) = LangItem::TryTraitFromOutput.path(self.db, self.krate) else {
|
||||
return self.collect_block(e);
|
||||
};
|
||||
let label = self.alloc_label_desugared(Label { name: Name::generate_new_name() });
|
||||
let label = self
|
||||
.alloc_label_desugared(Label { name: Name::generate_new_name(self.body.labels.len()) });
|
||||
let old_label = self.current_try_block_label.replace(label);
|
||||
|
||||
let (btail, expr_id) = self.with_labeled_rib(label, |this| {
|
||||
@@ -842,7 +841,7 @@ fn collect_for_loop(&mut self, syntax_ptr: AstPtr<ast::Expr>, e: ast::ForExpr) -
|
||||
this.collect_expr_opt(e.loop_body().map(|it| it.into()))
|
||||
}),
|
||||
};
|
||||
let iter_name = Name::generate_new_name();
|
||||
let iter_name = Name::generate_new_name(self.body.exprs.len());
|
||||
let iter_expr = self.alloc_expr(Expr::Path(Path::from(iter_name.clone())), syntax_ptr);
|
||||
let iter_expr_mut = self.alloc_expr(
|
||||
Expr::Ref { expr: iter_expr, rawness: Rawness::Ref, mutability: Mutability::Mut },
|
||||
@@ -903,7 +902,7 @@ fn collect_try_operator(&mut self, syntax_ptr: AstPtr<ast::Expr>, e: ast::TryExp
|
||||
Expr::Call { callee: try_branch, args: Box::new([operand]), is_assignee_expr: false },
|
||||
syntax_ptr,
|
||||
);
|
||||
let continue_name = Name::generate_new_name();
|
||||
let continue_name = Name::generate_new_name(self.body.bindings.len());
|
||||
let continue_binding =
|
||||
self.alloc_binding(continue_name.clone(), BindingAnnotation::Unannotated);
|
||||
let continue_bpat =
|
||||
@@ -918,7 +917,7 @@ fn collect_try_operator(&mut self, syntax_ptr: AstPtr<ast::Expr>, e: ast::TryExp
|
||||
guard: None,
|
||||
expr: self.alloc_expr(Expr::Path(Path::from(continue_name)), syntax_ptr),
|
||||
};
|
||||
let break_name = Name::generate_new_name();
|
||||
let break_name = Name::generate_new_name(self.body.bindings.len());
|
||||
let break_binding = self.alloc_binding(break_name.clone(), BindingAnnotation::Unannotated);
|
||||
let break_bpat = self.alloc_pat_desugared(Pat::Bind { id: break_binding, subpat: None });
|
||||
self.add_definition_to_binding(break_binding, break_bpat);
|
||||
@@ -1415,16 +1414,10 @@ fn collect_pat(&mut self, pat: ast::Pat, binding_list: &mut BindingList) -> PatI
|
||||
ast::Pat::LiteralPat(it) => {
|
||||
Some(Box::new(LiteralOrConst::Literal(pat_literal_to_hir(it)?.0)))
|
||||
}
|
||||
ast::Pat::IdentPat(p) => {
|
||||
let name =
|
||||
p.name().map(|nr| nr.as_name()).unwrap_or_else(Name::missing);
|
||||
Some(Box::new(LiteralOrConst::Const(name.into())))
|
||||
pat @ (ast::Pat::IdentPat(_) | ast::Pat::PathPat(_)) => {
|
||||
let subpat = self.collect_pat(pat.clone(), binding_list);
|
||||
Some(Box::new(LiteralOrConst::Const(subpat)))
|
||||
}
|
||||
ast::Pat::PathPat(p) => p
|
||||
.path()
|
||||
.and_then(|path| self.expander.parse_path(self.db, path))
|
||||
.map(LiteralOrConst::Const)
|
||||
.map(Box::new),
|
||||
_ => None,
|
||||
})
|
||||
};
|
||||
|
||||
@@ -635,7 +635,7 @@ fn print_stmt(&mut self, stmt: &Statement) {
|
||||
fn print_literal_or_const(&mut self, literal_or_const: &LiteralOrConst) {
|
||||
match literal_or_const {
|
||||
LiteralOrConst::Literal(l) => self.print_literal(l),
|
||||
LiteralOrConst::Const(c) => self.print_path(c),
|
||||
LiteralOrConst::Const(c) => self.print_pat(*c),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -788,11 +788,12 @@ fn collect_macro_items(
|
||||
};
|
||||
self.diagnostics.push(diag);
|
||||
}
|
||||
if let errors @ [_, ..] = parse.errors() {
|
||||
let errors = parse.errors();
|
||||
if !errors.is_empty() {
|
||||
self.diagnostics.push(DefDiagnostic::macro_expansion_parse_error(
|
||||
self.module_id.local_id,
|
||||
error_call_kind(),
|
||||
errors,
|
||||
errors.into_boxed_slice(),
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
@@ -400,7 +400,7 @@ pub(crate) fn lower_struct(
|
||||
item_tree: &ItemTree,
|
||||
fields: &Fields,
|
||||
) -> StructKind {
|
||||
let ctx = LowerCtx::with_file_id(db, ast.file_id);
|
||||
let ctx = LowerCtx::new(db, ast.file_id);
|
||||
|
||||
match (&ast.value, fields) {
|
||||
(ast::StructKind::Tuple(fl), Fields::Tuple(fields)) => {
|
||||
@@ -415,7 +415,9 @@ pub(crate) fn lower_struct(
|
||||
|| FieldData {
|
||||
name: Name::new_tuple_field(i),
|
||||
type_ref: Interned::new(TypeRef::from_ast_opt(&ctx, fd.ty())),
|
||||
visibility: RawVisibility::from_ast(db, ast.with_value(fd.visibility())),
|
||||
visibility: RawVisibility::from_ast(db, fd.visibility(), &mut |range| {
|
||||
ctx.span_map().span_for_range(range).ctx
|
||||
}),
|
||||
},
|
||||
);
|
||||
}
|
||||
@@ -433,7 +435,9 @@ pub(crate) fn lower_struct(
|
||||
|| FieldData {
|
||||
name: fd.name().map(|n| n.as_name()).unwrap_or_else(Name::missing),
|
||||
type_ref: Interned::new(TypeRef::from_ast_opt(&ctx, fd.ty())),
|
||||
visibility: RawVisibility::from_ast(db, ast.with_value(fd.visibility())),
|
||||
visibility: RawVisibility::from_ast(db, fd.visibility(), &mut |range| {
|
||||
ctx.span_map().span_for_range(range).ctx
|
||||
}),
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@@ -87,14 +87,10 @@ pub trait DefDatabase: InternDatabase + ExpandDatabase + Upcast<dyn ExpandDataba
|
||||
fn file_item_tree(&self, file_id: HirFileId) -> Arc<ItemTree>;
|
||||
|
||||
#[salsa::invoke(ItemTree::block_item_tree_query)]
|
||||
fn block_item_tree_query(&self, block_id: BlockId) -> Arc<ItemTree>;
|
||||
|
||||
#[salsa::invoke(crate_def_map_wait)]
|
||||
#[salsa::transparent]
|
||||
fn crate_def_map(&self, krate: CrateId) -> Arc<DefMap>;
|
||||
fn block_item_tree(&self, block_id: BlockId) -> Arc<ItemTree>;
|
||||
|
||||
#[salsa::invoke(DefMap::crate_def_map_query)]
|
||||
fn crate_def_map_query(&self, krate: CrateId) -> Arc<DefMap>;
|
||||
fn crate_def_map(&self, krate: CrateId) -> Arc<DefMap>;
|
||||
|
||||
/// Computes the block-level `DefMap`.
|
||||
#[salsa::invoke(DefMap::block_def_map_query)]
|
||||
@@ -253,11 +249,6 @@ fn include_macro_invoc(db: &dyn DefDatabase, krate: CrateId) -> Vec<(MacroCallId
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn crate_def_map_wait(db: &dyn DefDatabase, krate: CrateId) -> Arc<DefMap> {
|
||||
let _p = tracing::span!(tracing::Level::INFO, "crate_def_map:wait").entered();
|
||||
db.crate_def_map_query(krate)
|
||||
}
|
||||
|
||||
fn crate_supports_no_std(db: &dyn DefDatabase, crate_id: CrateId) -> bool {
|
||||
let file = db.crate_graph()[crate_id].root_file_id;
|
||||
let item_tree = db.file_item_tree(file.into());
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
//! Macro expansion utilities.
|
||||
|
||||
use std::cell::OnceCell;
|
||||
|
||||
use base_db::CrateId;
|
||||
use cfg::CfgOptions;
|
||||
use drop_bomb::DropBomb;
|
||||
@@ -18,7 +20,7 @@
|
||||
#[derive(Debug)]
|
||||
pub struct Expander {
|
||||
cfg_options: CfgOptions,
|
||||
span_map: SpanMap,
|
||||
span_map: OnceCell<SpanMap>,
|
||||
krate: CrateId,
|
||||
current_file_id: HirFileId,
|
||||
pub(crate) module: ModuleId,
|
||||
@@ -42,7 +44,7 @@ pub fn new(db: &dyn DefDatabase, current_file_id: HirFileId, module: ModuleId) -
|
||||
recursion_depth: 0,
|
||||
recursion_limit,
|
||||
cfg_options: db.crate_graph()[module.krate].cfg_options.clone(),
|
||||
span_map: db.span_map(current_file_id),
|
||||
span_map: OnceCell::new(),
|
||||
krate: module.krate,
|
||||
}
|
||||
}
|
||||
@@ -100,7 +102,7 @@ pub fn exit(&mut self, mut mark: Mark) {
|
||||
}
|
||||
|
||||
pub fn ctx<'a>(&self, db: &'a dyn DefDatabase) -> LowerCtx<'a> {
|
||||
LowerCtx::new(db, self.span_map.clone(), self.current_file_id)
|
||||
LowerCtx::with_span_map_cell(db, self.current_file_id, self.span_map.clone())
|
||||
}
|
||||
|
||||
pub(crate) fn in_file<T>(&self, value: T) -> InFile<T> {
|
||||
@@ -108,7 +110,15 @@ pub(crate) fn in_file<T>(&self, value: T) -> InFile<T> {
|
||||
}
|
||||
|
||||
pub(crate) fn parse_attrs(&self, db: &dyn DefDatabase, owner: &dyn ast::HasAttrs) -> Attrs {
|
||||
Attrs::filter(db, self.krate, RawAttrs::new(db.upcast(), owner, self.span_map.as_ref()))
|
||||
Attrs::filter(
|
||||
db,
|
||||
self.krate,
|
||||
RawAttrs::new(
|
||||
db.upcast(),
|
||||
owner,
|
||||
self.span_map.get_or_init(|| db.span_map(self.current_file_id)).as_ref(),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
pub(crate) fn cfg_options(&self) -> &CfgOptions {
|
||||
@@ -120,7 +130,7 @@ pub fn current_file_id(&self) -> HirFileId {
|
||||
}
|
||||
|
||||
pub(crate) fn parse_path(&mut self, db: &dyn DefDatabase, path: ast::Path) -> Option<Path> {
|
||||
let ctx = LowerCtx::new(db, self.span_map.clone(), self.current_file_id);
|
||||
let ctx = LowerCtx::with_span_map_cell(db, self.current_file_id, self.span_map.clone());
|
||||
Path::from_src(&ctx, path)
|
||||
}
|
||||
|
||||
@@ -165,10 +175,11 @@ fn within_limit<F, T: ast::AstNode>(
|
||||
let parse = res.value.0.cast::<T>()?;
|
||||
|
||||
self.recursion_depth += 1;
|
||||
let old_span_map = std::mem::replace(
|
||||
&mut self.span_map,
|
||||
SpanMap::ExpansionSpanMap(res.value.1),
|
||||
);
|
||||
let old_span_map = OnceCell::new();
|
||||
if let Some(prev) = self.span_map.take() {
|
||||
_ = old_span_map.set(prev);
|
||||
};
|
||||
_ = self.span_map.set(SpanMap::ExpansionSpanMap(res.value.1));
|
||||
let old_file_id =
|
||||
std::mem::replace(&mut self.current_file_id, macro_file.into());
|
||||
let mark = Mark {
|
||||
@@ -187,6 +198,6 @@ fn within_limit<F, T: ast::AstNode>(
|
||||
#[derive(Debug)]
|
||||
pub struct Mark {
|
||||
file_id: HirFileId,
|
||||
span_map: SpanMap,
|
||||
span_map: OnceCell<SpanMap>,
|
||||
bomb: DropBomb,
|
||||
}
|
||||
|
||||
@@ -611,8 +611,10 @@ fn check_found_path_(
|
||||
let parsed_path_file = syntax::SourceFile::parse(&format!("use {path};"));
|
||||
let ast_path =
|
||||
parsed_path_file.syntax_node().descendants().find_map(syntax::ast::Path::cast).unwrap();
|
||||
let mod_path =
|
||||
ModPath::from_src(&db, ast_path, db.span_map(pos.file_id.into()).as_ref()).unwrap();
|
||||
let mod_path = ModPath::from_src(&db, ast_path, &mut |range| {
|
||||
db.span_map(pos.file_id.into()).as_ref().span_for_range(range).ctx
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
let def_map = module.def_map(&db);
|
||||
let resolved = def_map
|
||||
|
||||
@@ -101,7 +101,7 @@ pub enum Literal {
|
||||
/// Used in range patterns.
|
||||
pub enum LiteralOrConst {
|
||||
Literal(Literal),
|
||||
Const(Path),
|
||||
Const(PatId),
|
||||
}
|
||||
|
||||
impl Literal {
|
||||
|
||||
@@ -251,7 +251,7 @@ fn lower_abi(abi: ast::Abi) -> Interned<str> {
|
||||
TypeRef::DynTrait(type_bounds_from_ast(ctx, inner.type_bound_list()))
|
||||
}
|
||||
ast::Type::MacroType(mt) => match mt.macro_call() {
|
||||
Some(mc) => ctx.ast_id(&mc).map(TypeRef::Macro).unwrap_or(TypeRef::Error),
|
||||
Some(mc) => TypeRef::Macro(ctx.ast_id(&mc)),
|
||||
None => TypeRef::Error,
|
||||
},
|
||||
}
|
||||
@@ -398,9 +398,8 @@ pub enum ConstRef {
|
||||
impl ConstRef {
|
||||
pub(crate) fn from_const_arg(lower_ctx: &LowerCtx<'_>, arg: Option<ast::ConstArg>) -> Self {
|
||||
if let Some(arg) = arg {
|
||||
let ast_id = lower_ctx.ast_id(&arg);
|
||||
if let Some(expr) = arg.expr() {
|
||||
return Self::from_expr(expr, ast_id);
|
||||
return Self::from_expr(expr, Some(lower_ctx.ast_id(&arg)));
|
||||
}
|
||||
}
|
||||
Self::Scalar(LiteralConstRef::Unknown)
|
||||
|
||||
@@ -29,9 +29,6 @@
|
||||
//!
|
||||
//! In general, any item in the `ItemTree` stores its `AstId`, which allows mapping it back to its
|
||||
//! surface syntax.
|
||||
//!
|
||||
//! Note that we cannot store [`span::Span`]s inside of this, as typing in an item invalidates its
|
||||
//! encompassing span!
|
||||
|
||||
mod lower;
|
||||
mod pretty;
|
||||
@@ -50,7 +47,6 @@
|
||||
use hir_expand::{attrs::RawAttrs, name::Name, ExpandTo, HirFileId, InFile};
|
||||
use intern::Interned;
|
||||
use la_arena::{Arena, Idx, IdxRange, RawIdx};
|
||||
use profile::Count;
|
||||
use rustc_hash::FxHashMap;
|
||||
use smallvec::SmallVec;
|
||||
use span::{AstIdNode, FileAstId, Span};
|
||||
@@ -94,8 +90,6 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
/// The item tree of a source file.
|
||||
#[derive(Debug, Default, Eq, PartialEq)]
|
||||
pub struct ItemTree {
|
||||
_c: Count<Self>,
|
||||
|
||||
top_level: SmallVec<[ModItem; 1]>,
|
||||
attrs: FxHashMap<AttrOwner, RawAttrs>,
|
||||
|
||||
@@ -263,14 +257,6 @@ fn alloc(&mut self, vis: RawVisibility) -> RawVisibilityId {
|
||||
}
|
||||
}
|
||||
|
||||
static VIS_PUB: RawVisibility = RawVisibility::Public;
|
||||
static VIS_PRIV_IMPLICIT: RawVisibility =
|
||||
RawVisibility::Module(ModPath::from_kind(PathKind::Super(0)), VisibilityExplicitness::Implicit);
|
||||
static VIS_PRIV_EXPLICIT: RawVisibility =
|
||||
RawVisibility::Module(ModPath::from_kind(PathKind::Super(0)), VisibilityExplicitness::Explicit);
|
||||
static VIS_PUB_CRATE: RawVisibility =
|
||||
RawVisibility::Module(ModPath::from_kind(PathKind::Crate), VisibilityExplicitness::Explicit);
|
||||
|
||||
#[derive(Default, Debug, Eq, PartialEq)]
|
||||
struct ItemTreeData {
|
||||
uses: Arena<Use>,
|
||||
@@ -403,7 +389,7 @@ pub(crate) fn new(file: HirFileId, block: Option<BlockId>) -> Self {
|
||||
|
||||
pub(crate) fn item_tree(&self, db: &dyn DefDatabase) -> Arc<ItemTree> {
|
||||
match self.block {
|
||||
Some(block) => db.block_item_tree_query(block),
|
||||
Some(block) => db.block_item_tree(block),
|
||||
None => db.file_item_tree(self.file),
|
||||
}
|
||||
}
|
||||
@@ -562,6 +548,20 @@ fn index(&self, index: Idx<$t>) -> &Self::Output {
|
||||
impl Index<RawVisibilityId> for ItemTree {
|
||||
type Output = RawVisibility;
|
||||
fn index(&self, index: RawVisibilityId) -> &Self::Output {
|
||||
static VIS_PUB: RawVisibility = RawVisibility::Public;
|
||||
static VIS_PRIV_IMPLICIT: RawVisibility = RawVisibility::Module(
|
||||
ModPath::from_kind(PathKind::Super(0)),
|
||||
VisibilityExplicitness::Implicit,
|
||||
);
|
||||
static VIS_PRIV_EXPLICIT: RawVisibility = RawVisibility::Module(
|
||||
ModPath::from_kind(PathKind::Super(0)),
|
||||
VisibilityExplicitness::Explicit,
|
||||
);
|
||||
static VIS_PUB_CRATE: RawVisibility = RawVisibility::Module(
|
||||
ModPath::from_kind(PathKind::Crate),
|
||||
VisibilityExplicitness::Explicit,
|
||||
);
|
||||
|
||||
match index {
|
||||
RawVisibilityId::PRIV_IMPLICIT => &VIS_PRIV_IMPLICIT,
|
||||
RawVisibilityId::PRIV_EXPLICIT => &VIS_PRIV_EXPLICIT,
|
||||
@@ -821,11 +821,13 @@ pub fn use_tree_to_ast(
|
||||
// Note: The AST unwraps are fine, since if they fail we should have never obtained `index`.
|
||||
let ast = InFile::new(file_id, self.ast_id).to_node(db.upcast());
|
||||
let ast_use_tree = ast.use_tree().expect("missing `use_tree`");
|
||||
let span_map = db.span_map(file_id);
|
||||
let (_, source_map) = lower::lower_use_tree(db, span_map.as_ref(), ast_use_tree)
|
||||
.expect("failed to lower use tree");
|
||||
let (_, source_map) = lower::lower_use_tree(db, ast_use_tree, &mut |range| {
|
||||
db.span_map(file_id).span_for_range(range).ctx
|
||||
})
|
||||
.expect("failed to lower use tree");
|
||||
source_map[index].clone()
|
||||
}
|
||||
|
||||
/// Maps a `UseTree` contained in this import back to its AST node.
|
||||
pub fn use_tree_source_map(
|
||||
&self,
|
||||
@@ -836,10 +838,11 @@ pub fn use_tree_source_map(
|
||||
// Note: The AST unwraps are fine, since if they fail we should have never obtained `index`.
|
||||
let ast = InFile::new(file_id, self.ast_id).to_node(db.upcast());
|
||||
let ast_use_tree = ast.use_tree().expect("missing `use_tree`");
|
||||
let span_map = db.span_map(file_id);
|
||||
lower::lower_use_tree(db, span_map.as_ref(), ast_use_tree)
|
||||
.expect("failed to lower use tree")
|
||||
.1
|
||||
lower::lower_use_tree(db, ast_use_tree, &mut |range| {
|
||||
db.span_map(file_id).span_for_range(range).ctx
|
||||
})
|
||||
.expect("failed to lower use tree")
|
||||
.1
|
||||
}
|
||||
}
|
||||
|
||||
@@ -871,25 +874,19 @@ fn concat_mod_paths(
|
||||
prefix: Option<ModPath>,
|
||||
path: &ModPath,
|
||||
) -> Option<(ModPath, ImportKind)> {
|
||||
match (prefix, &path.kind) {
|
||||
match (prefix, path.kind) {
|
||||
(None, _) => Some((path.clone(), ImportKind::Plain)),
|
||||
(Some(mut prefix), PathKind::Plain) => {
|
||||
for segment in path.segments() {
|
||||
prefix.push_segment(segment.clone());
|
||||
}
|
||||
prefix.extend(path.segments().iter().cloned());
|
||||
Some((prefix, ImportKind::Plain))
|
||||
}
|
||||
(Some(mut prefix), PathKind::Super(n))
|
||||
if *n > 0 && prefix.segments().is_empty() =>
|
||||
{
|
||||
(Some(mut prefix), PathKind::Super(n)) if n > 0 && prefix.segments().is_empty() => {
|
||||
// `super::super` + `super::rest`
|
||||
match &mut prefix.kind {
|
||||
PathKind::Super(m) => {
|
||||
cov_mark::hit!(concat_super_mod_paths);
|
||||
*m += *n;
|
||||
for segment in path.segments() {
|
||||
prefix.push_segment(segment.clone());
|
||||
}
|
||||
*m += n;
|
||||
prefix.extend(path.segments().iter().cloned());
|
||||
Some((prefix, ImportKind::Plain))
|
||||
}
|
||||
_ => None,
|
||||
@@ -963,10 +960,10 @@ pub fn as_assoc_item(&self) -> Option<AssocItem> {
|
||||
| ModItem::Mod(_)
|
||||
| ModItem::MacroRules(_)
|
||||
| ModItem::Macro2(_) => None,
|
||||
ModItem::MacroCall(call) => Some(AssocItem::MacroCall(*call)),
|
||||
ModItem::Const(konst) => Some(AssocItem::Const(*konst)),
|
||||
ModItem::TypeAlias(alias) => Some(AssocItem::TypeAlias(*alias)),
|
||||
ModItem::Function(func) => Some(AssocItem::Function(*func)),
|
||||
&ModItem::MacroCall(call) => Some(AssocItem::MacroCall(call)),
|
||||
&ModItem::Const(konst) => Some(AssocItem::Const(konst)),
|
||||
&ModItem::TypeAlias(alias) => Some(AssocItem::TypeAlias(alias)),
|
||||
&ModItem::Function(func) => Some(AssocItem::Function(func)),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
use hir_expand::{mod_path::path, name, name::AsName, span_map::SpanMapRef, HirFileId};
|
||||
use la_arena::Arena;
|
||||
use span::AstIdMap;
|
||||
use span::{AstIdMap, SyntaxContextId};
|
||||
use syntax::{
|
||||
ast::{self, HasModuleItem, HasName, HasTypeBounds, IsString},
|
||||
AstNode,
|
||||
@@ -45,7 +45,7 @@ pub(super) fn new(db: &'a dyn DefDatabase, file: HirFileId) -> Self {
|
||||
db,
|
||||
tree: ItemTree::default(),
|
||||
source_ast_id_map: db.ast_id_map(file),
|
||||
body_ctx: crate::lower::LowerCtx::with_file_id(db, file),
|
||||
body_ctx: crate::lower::LowerCtx::new(db, file),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -535,7 +535,9 @@ fn lower_impl(&mut self, impl_def: &ast::Impl) -> Option<FileItemTreeId<Impl>> {
|
||||
fn lower_use(&mut self, use_item: &ast::Use) -> Option<FileItemTreeId<Use>> {
|
||||
let visibility = self.lower_visibility(use_item);
|
||||
let ast_id = self.source_ast_id_map.ast_id(use_item);
|
||||
let (use_tree, _) = lower_use_tree(self.db, self.span_map(), use_item.use_tree()?)?;
|
||||
let (use_tree, _) = lower_use_tree(self.db, use_item.use_tree()?, &mut |range| {
|
||||
self.span_map().span_for_range(range).ctx
|
||||
})?;
|
||||
|
||||
let res = Use { visibility, ast_id, use_tree };
|
||||
Some(id(self.data().uses.alloc(res)))
|
||||
@@ -558,7 +560,9 @@ fn lower_extern_crate(
|
||||
|
||||
fn lower_macro_call(&mut self, m: &ast::MacroCall) -> Option<FileItemTreeId<MacroCall>> {
|
||||
let span_map = self.span_map();
|
||||
let path = Interned::new(ModPath::from_src(self.db.upcast(), m.path()?, span_map)?);
|
||||
let path = Interned::new(ModPath::from_src(self.db.upcast(), m.path()?, &mut |range| {
|
||||
span_map.span_for_range(range).ctx
|
||||
})?);
|
||||
let ast_id = self.source_ast_id_map.ast_id(m);
|
||||
let expand_to = hir_expand::ExpandTo::from_call_site(m);
|
||||
let res = MacroCall {
|
||||
@@ -672,8 +676,9 @@ fn lower_type_bounds(&mut self, node: &dyn ast::HasTypeBounds) -> Box<[Interned<
|
||||
}
|
||||
|
||||
fn lower_visibility(&mut self, item: &dyn ast::HasVisibility) -> RawVisibilityId {
|
||||
let vis =
|
||||
RawVisibility::from_opt_ast_with_span_map(self.db, item.visibility(), self.span_map());
|
||||
let vis = RawVisibility::from_ast(self.db, item.visibility(), &mut |range| {
|
||||
self.span_map().span_for_range(range).ctx
|
||||
});
|
||||
self.data().vis.alloc(vis)
|
||||
}
|
||||
|
||||
@@ -745,12 +750,15 @@ fn lower_abi(abi: ast::Abi) -> Interned<str> {
|
||||
|
||||
struct UseTreeLowering<'a> {
|
||||
db: &'a dyn DefDatabase,
|
||||
span_map: SpanMapRef<'a>,
|
||||
mapping: Arena<ast::UseTree>,
|
||||
}
|
||||
|
||||
impl UseTreeLowering<'_> {
|
||||
fn lower_use_tree(&mut self, tree: ast::UseTree) -> Option<UseTree> {
|
||||
fn lower_use_tree(
|
||||
&mut self,
|
||||
tree: ast::UseTree,
|
||||
span_for_range: &mut dyn FnMut(::tt::TextRange) -> SyntaxContextId,
|
||||
) -> Option<UseTree> {
|
||||
if let Some(use_tree_list) = tree.use_tree_list() {
|
||||
let prefix = match tree.path() {
|
||||
// E.g. use something::{{{inner}}};
|
||||
@@ -758,15 +766,17 @@ fn lower_use_tree(&mut self, tree: ast::UseTree) -> Option<UseTree> {
|
||||
// E.g. `use something::{inner}` (prefix is `None`, path is `something`)
|
||||
// or `use something::{path::{inner::{innerer}}}` (prefix is `something::path`, path is `inner`)
|
||||
Some(path) => {
|
||||
match ModPath::from_src(self.db.upcast(), path, self.span_map) {
|
||||
match ModPath::from_src(self.db.upcast(), path, span_for_range) {
|
||||
Some(it) => Some(it),
|
||||
None => return None, // FIXME: report errors somewhere
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let list =
|
||||
use_tree_list.use_trees().filter_map(|tree| self.lower_use_tree(tree)).collect();
|
||||
let list = use_tree_list
|
||||
.use_trees()
|
||||
.filter_map(|tree| self.lower_use_tree(tree, span_for_range))
|
||||
.collect();
|
||||
|
||||
Some(
|
||||
self.use_tree(
|
||||
@@ -777,7 +787,7 @@ fn lower_use_tree(&mut self, tree: ast::UseTree) -> Option<UseTree> {
|
||||
} else {
|
||||
let is_glob = tree.star_token().is_some();
|
||||
let path = match tree.path() {
|
||||
Some(path) => Some(ModPath::from_src(self.db.upcast(), path, self.span_map)?),
|
||||
Some(path) => Some(ModPath::from_src(self.db.upcast(), path, span_for_range)?),
|
||||
None => None,
|
||||
};
|
||||
let alias = tree.rename().map(|a| {
|
||||
@@ -813,10 +823,10 @@ fn use_tree(&mut self, kind: UseTreeKind, ast: ast::UseTree) -> UseTree {
|
||||
|
||||
pub(crate) fn lower_use_tree(
|
||||
db: &dyn DefDatabase,
|
||||
span_map: SpanMapRef<'_>,
|
||||
tree: ast::UseTree,
|
||||
span_for_range: &mut dyn FnMut(::tt::TextRange) -> SyntaxContextId,
|
||||
) -> Option<(UseTree, Arena<ast::UseTree>)> {
|
||||
let mut lowering = UseTreeLowering { db, span_map, mapping: Arena::new() };
|
||||
let tree = lowering.lower_use_tree(tree)?;
|
||||
let mut lowering = UseTreeLowering { db, mapping: Arena::new() };
|
||||
let tree = lowering.lower_use_tree(tree, span_for_range)?;
|
||||
Some((tree, lowering.mapping))
|
||||
}
|
||||
|
||||
@@ -1341,8 +1341,11 @@ fn as_call_id_with_errors(
|
||||
let expands_to = hir_expand::ExpandTo::from_call_site(self.value);
|
||||
let ast_id = AstId::new(self.file_id, db.ast_id_map(self.file_id).ast_id(self.value));
|
||||
let span_map = db.span_map(self.file_id);
|
||||
let path =
|
||||
self.value.path().and_then(|path| path::ModPath::from_src(db, path, span_map.as_ref()));
|
||||
let path = self.value.path().and_then(|path| {
|
||||
path::ModPath::from_src(db, path, &mut |range| {
|
||||
span_map.as_ref().span_for_range(range).ctx
|
||||
})
|
||||
});
|
||||
|
||||
let Some(path) = path else {
|
||||
return Ok(ExpandResult::only_err(ExpandError::other("malformed macro invocation")));
|
||||
|
||||
@@ -13,39 +13,36 @@
|
||||
|
||||
pub struct LowerCtx<'a> {
|
||||
pub db: &'a dyn DefDatabase,
|
||||
span_map: SpanMap,
|
||||
// FIXME: This optimization is probably pointless, ast id map should pretty much always exist anyways.
|
||||
ast_id_map: Option<(HirFileId, OnceCell<Arc<AstIdMap>>)>,
|
||||
file_id: HirFileId,
|
||||
span_map: OnceCell<SpanMap>,
|
||||
ast_id_map: OnceCell<Arc<AstIdMap>>,
|
||||
}
|
||||
|
||||
impl<'a> LowerCtx<'a> {
|
||||
pub fn new(db: &'a dyn DefDatabase, span_map: SpanMap, file_id: HirFileId) -> Self {
|
||||
LowerCtx { db, span_map, ast_id_map: Some((file_id, OnceCell::new())) }
|
||||
pub fn new(db: &'a dyn DefDatabase, file_id: HirFileId) -> Self {
|
||||
LowerCtx { db, file_id, span_map: OnceCell::new(), ast_id_map: OnceCell::new() }
|
||||
}
|
||||
|
||||
pub fn with_file_id(db: &'a dyn DefDatabase, file_id: HirFileId) -> Self {
|
||||
LowerCtx {
|
||||
db,
|
||||
span_map: db.span_map(file_id),
|
||||
ast_id_map: Some((file_id, OnceCell::new())),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_span_map(db: &'a dyn DefDatabase, span_map: SpanMap) -> Self {
|
||||
LowerCtx { db, span_map, ast_id_map: None }
|
||||
pub fn with_span_map_cell(
|
||||
db: &'a dyn DefDatabase,
|
||||
file_id: HirFileId,
|
||||
span_map: OnceCell<SpanMap>,
|
||||
) -> Self {
|
||||
LowerCtx { db, file_id, span_map, ast_id_map: OnceCell::new() }
|
||||
}
|
||||
|
||||
pub(crate) fn span_map(&self) -> SpanMapRef<'_> {
|
||||
self.span_map.as_ref()
|
||||
self.span_map.get_or_init(|| self.db.span_map(self.file_id)).as_ref()
|
||||
}
|
||||
|
||||
pub(crate) fn lower_path(&self, ast: ast::Path) -> Option<Path> {
|
||||
Path::from_src(self, ast)
|
||||
}
|
||||
|
||||
pub(crate) fn ast_id<N: AstIdNode>(&self, item: &N) -> Option<AstId<N>> {
|
||||
let &(file_id, ref ast_id_map) = self.ast_id_map.as_ref()?;
|
||||
let ast_id_map = ast_id_map.get_or_init(|| self.db.ast_id_map(file_id));
|
||||
Some(InFile::new(file_id, ast_id_map.ast_id(item)))
|
||||
pub(crate) fn ast_id<N: AstIdNode>(&self, item: &N) -> AstId<N> {
|
||||
InFile::new(
|
||||
self.file_id,
|
||||
self.ast_id_map.get_or_init(|| self.db.ast_id_map(self.file_id)).ast_id(item),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,7 +65,6 @@
|
||||
};
|
||||
use itertools::Itertools;
|
||||
use la_arena::Arena;
|
||||
use profile::Count;
|
||||
use rustc_hash::{FxHashMap, FxHashSet};
|
||||
use span::FileAstId;
|
||||
use stdx::format_to;
|
||||
@@ -95,7 +94,6 @@
|
||||
/// is computed by the `block_def_map` query.
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub struct DefMap {
|
||||
_c: Count<Self>,
|
||||
/// When this is a block def map, this will hold the block id of the block and module that
|
||||
/// contains this block.
|
||||
block: Option<BlockInfo>,
|
||||
@@ -154,6 +152,23 @@ struct DefMapCrateData {
|
||||
}
|
||||
|
||||
impl DefMapCrateData {
|
||||
fn new(edition: Edition) -> Self {
|
||||
Self {
|
||||
extern_prelude: FxHashMap::default(),
|
||||
exported_derives: FxHashMap::default(),
|
||||
fn_proc_macro_mapping: FxHashMap::default(),
|
||||
proc_macro_loading_error: None,
|
||||
registered_attrs: Vec::new(),
|
||||
registered_tools: Vec::new(),
|
||||
unstable_features: FxHashSet::default(),
|
||||
rustc_coherence_is_core: false,
|
||||
no_core: false,
|
||||
no_std: false,
|
||||
edition,
|
||||
recursion_limit: None,
|
||||
}
|
||||
}
|
||||
|
||||
fn shrink_to_fit(&mut self) {
|
||||
let Self {
|
||||
extern_prelude,
|
||||
@@ -305,67 +320,67 @@ impl DefMap {
|
||||
/// The module id of a crate or block root.
|
||||
pub const ROOT: LocalModuleId = LocalModuleId::from_raw(la_arena::RawIdx::from_u32(0));
|
||||
|
||||
pub(crate) fn crate_def_map_query(db: &dyn DefDatabase, krate: CrateId) -> Arc<DefMap> {
|
||||
pub(crate) fn crate_def_map_query(db: &dyn DefDatabase, crate_id: CrateId) -> Arc<DefMap> {
|
||||
let crate_graph = db.crate_graph();
|
||||
let krate_name = crate_graph[krate].display_name.as_deref().unwrap_or_default();
|
||||
let krate = &crate_graph[crate_id];
|
||||
let name = krate.display_name.as_deref().unwrap_or_default();
|
||||
let _p = tracing::span!(tracing::Level::INFO, "crate_def_map_query", ?name).entered();
|
||||
|
||||
let _p = tracing::span!(tracing::Level::INFO, "crate_def_map_query", ?krate_name).entered();
|
||||
|
||||
let crate_graph = db.crate_graph();
|
||||
|
||||
let edition = crate_graph[krate].edition;
|
||||
let origin = ModuleOrigin::CrateRoot { definition: crate_graph[krate].root_file_id };
|
||||
let def_map = DefMap::empty(krate, edition, ModuleData::new(origin, Visibility::Public));
|
||||
let def_map = collector::collect_defs(
|
||||
db,
|
||||
def_map,
|
||||
TreeId::new(crate_graph[krate].root_file_id.into(), None),
|
||||
let module_data = ModuleData::new(
|
||||
ModuleOrigin::CrateRoot { definition: krate.root_file_id },
|
||||
Visibility::Public,
|
||||
);
|
||||
|
||||
let def_map = DefMap::empty(
|
||||
crate_id,
|
||||
Arc::new(DefMapCrateData::new(krate.edition)),
|
||||
module_data,
|
||||
None,
|
||||
);
|
||||
let def_map =
|
||||
collector::collect_defs(db, def_map, TreeId::new(krate.root_file_id.into(), None));
|
||||
|
||||
Arc::new(def_map)
|
||||
}
|
||||
|
||||
pub(crate) fn block_def_map_query(db: &dyn DefDatabase, block_id: BlockId) -> Arc<DefMap> {
|
||||
let block: BlockLoc = block_id.lookup(db);
|
||||
let BlockLoc { ast_id, module } = block_id.lookup(db);
|
||||
|
||||
let parent_map = block.module.def_map(db);
|
||||
let krate = block.module.krate;
|
||||
let local_id = LocalModuleId::from_raw(la_arena::RawIdx::from(0));
|
||||
// NB: we use `None` as block here, which would be wrong for implicit
|
||||
// modules declared by blocks with items. At the moment, we don't use
|
||||
// this visibility for anything outside IDE, so that's probably OK.
|
||||
let visibility = Visibility::Module(
|
||||
ModuleId { krate, local_id, block: None },
|
||||
ModuleId { krate: module.krate, local_id: Self::ROOT, block: module.block },
|
||||
VisibilityExplicitness::Implicit,
|
||||
);
|
||||
let module_data = ModuleData::new(
|
||||
ModuleOrigin::BlockExpr { block: block.ast_id, id: block_id },
|
||||
visibility,
|
||||
let module_data =
|
||||
ModuleData::new(ModuleOrigin::BlockExpr { block: ast_id, id: block_id }, visibility);
|
||||
|
||||
let parent_map = module.def_map(db);
|
||||
let def_map = DefMap::empty(
|
||||
module.krate,
|
||||
parent_map.data.clone(),
|
||||
module_data,
|
||||
Some(BlockInfo {
|
||||
block: block_id,
|
||||
parent: BlockRelativeModuleId { block: module.block, local_id: module.local_id },
|
||||
}),
|
||||
);
|
||||
|
||||
let mut def_map = DefMap::empty(krate, parent_map.data.edition, module_data);
|
||||
def_map.data = parent_map.data.clone();
|
||||
def_map.block = Some(BlockInfo {
|
||||
block: block_id,
|
||||
parent: BlockRelativeModuleId {
|
||||
block: block.module.block,
|
||||
local_id: block.module.local_id,
|
||||
},
|
||||
});
|
||||
|
||||
let def_map =
|
||||
collector::collect_defs(db, def_map, TreeId::new(block.ast_id.file_id, Some(block_id)));
|
||||
collector::collect_defs(db, def_map, TreeId::new(ast_id.file_id, Some(block_id)));
|
||||
Arc::new(def_map)
|
||||
}
|
||||
|
||||
fn empty(krate: CrateId, edition: Edition, module_data: ModuleData) -> DefMap {
|
||||
fn empty(
|
||||
krate: CrateId,
|
||||
crate_data: Arc<DefMapCrateData>,
|
||||
module_data: ModuleData,
|
||||
block: Option<BlockInfo>,
|
||||
) -> DefMap {
|
||||
let mut modules: Arena<ModuleData> = Arena::default();
|
||||
let root = modules.alloc(module_data);
|
||||
assert_eq!(root, Self::ROOT);
|
||||
|
||||
DefMap {
|
||||
_c: Count::new(),
|
||||
block: None,
|
||||
block,
|
||||
modules,
|
||||
krate,
|
||||
prelude: None,
|
||||
@@ -373,23 +388,36 @@ fn empty(krate: CrateId, edition: Edition, module_data: ModuleData) -> DefMap {
|
||||
derive_helpers_in_scope: FxHashMap::default(),
|
||||
diagnostics: Vec::new(),
|
||||
enum_definitions: FxHashMap::default(),
|
||||
data: Arc::new(DefMapCrateData {
|
||||
extern_prelude: FxHashMap::default(),
|
||||
exported_derives: FxHashMap::default(),
|
||||
fn_proc_macro_mapping: FxHashMap::default(),
|
||||
proc_macro_loading_error: None,
|
||||
registered_attrs: Vec::new(),
|
||||
registered_tools: Vec::new(),
|
||||
unstable_features: FxHashSet::default(),
|
||||
rustc_coherence_is_core: false,
|
||||
no_core: false,
|
||||
no_std: false,
|
||||
edition,
|
||||
recursion_limit: None,
|
||||
}),
|
||||
data: crate_data,
|
||||
}
|
||||
}
|
||||
fn shrink_to_fit(&mut self) {
|
||||
// Exhaustive match to require handling new fields.
|
||||
let Self {
|
||||
macro_use_prelude,
|
||||
diagnostics,
|
||||
modules,
|
||||
derive_helpers_in_scope,
|
||||
block: _,
|
||||
krate: _,
|
||||
prelude: _,
|
||||
data: _,
|
||||
enum_definitions,
|
||||
} = self;
|
||||
|
||||
macro_use_prelude.shrink_to_fit();
|
||||
diagnostics.shrink_to_fit();
|
||||
modules.shrink_to_fit();
|
||||
derive_helpers_in_scope.shrink_to_fit();
|
||||
enum_definitions.shrink_to_fit();
|
||||
for (_, module) in modules.iter_mut() {
|
||||
module.children.shrink_to_fit();
|
||||
module.scope.shrink_to_fit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl DefMap {
|
||||
pub fn modules_for_file(&self, file_id: FileId) -> impl Iterator<Item = LocalModuleId> + '_ {
|
||||
self.modules
|
||||
.iter()
|
||||
@@ -440,6 +468,105 @@ pub fn krate(&self) -> CrateId {
|
||||
self.krate
|
||||
}
|
||||
|
||||
pub fn module_id(&self, local_id: LocalModuleId) -> ModuleId {
|
||||
let block = self.block.map(|b| b.block);
|
||||
ModuleId { krate: self.krate, local_id, block }
|
||||
}
|
||||
|
||||
pub fn crate_root(&self) -> CrateRootModuleId {
|
||||
CrateRootModuleId { krate: self.krate }
|
||||
}
|
||||
|
||||
/// This is the same as [`Self::crate_root`] for crate def maps, but for block def maps, it
|
||||
/// returns the root block module.
|
||||
pub fn root_module_id(&self) -> ModuleId {
|
||||
self.module_id(Self::ROOT)
|
||||
}
|
||||
|
||||
/// If this `DefMap` is for a block expression, returns the module containing the block (which
|
||||
/// might again be a block, or a module inside a block).
|
||||
pub fn parent(&self) -> Option<ModuleId> {
|
||||
let BlockRelativeModuleId { block, local_id } = self.block?.parent;
|
||||
Some(ModuleId { krate: self.krate, block, local_id })
|
||||
}
|
||||
|
||||
/// Returns the module containing `local_mod`, either the parent `mod`, or the module (or block) containing
|
||||
/// the block, if `self` corresponds to a block expression.
|
||||
pub fn containing_module(&self, local_mod: LocalModuleId) -> Option<ModuleId> {
|
||||
match self[local_mod].parent {
|
||||
Some(parent) => Some(self.module_id(parent)),
|
||||
None => {
|
||||
self.block.map(
|
||||
|BlockInfo { parent: BlockRelativeModuleId { block, local_id }, .. }| {
|
||||
ModuleId { krate: self.krate, block, local_id }
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Get a reference to the def map's diagnostics.
|
||||
pub fn diagnostics(&self) -> &[DefDiagnostic] {
|
||||
self.diagnostics.as_slice()
|
||||
}
|
||||
|
||||
pub fn recursion_limit(&self) -> u32 {
|
||||
// 128 is the default in rustc
|
||||
self.data.recursion_limit.unwrap_or(128)
|
||||
}
|
||||
|
||||
// FIXME: this can use some more human-readable format (ideally, an IR
|
||||
// even), as this should be a great debugging aid.
|
||||
pub fn dump(&self, db: &dyn DefDatabase) -> String {
|
||||
let mut buf = String::new();
|
||||
let mut arc;
|
||||
let mut current_map = self;
|
||||
while let Some(block) = current_map.block {
|
||||
go(&mut buf, db, current_map, "block scope", Self::ROOT);
|
||||
buf.push('\n');
|
||||
arc = block.parent.def_map(db, self.krate);
|
||||
current_map = &arc;
|
||||
}
|
||||
go(&mut buf, db, current_map, "crate", Self::ROOT);
|
||||
return buf;
|
||||
|
||||
fn go(
|
||||
buf: &mut String,
|
||||
db: &dyn DefDatabase,
|
||||
map: &DefMap,
|
||||
path: &str,
|
||||
module: LocalModuleId,
|
||||
) {
|
||||
format_to!(buf, "{}\n", path);
|
||||
|
||||
map.modules[module].scope.dump(db.upcast(), buf);
|
||||
|
||||
for (name, child) in
|
||||
map.modules[module].children.iter().sorted_by(|a, b| Ord::cmp(&a.0, &b.0))
|
||||
{
|
||||
let path = format!("{path}::{}", name.display(db.upcast()));
|
||||
buf.push('\n');
|
||||
go(buf, db, map, &path, *child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn dump_block_scopes(&self, db: &dyn DefDatabase) -> String {
|
||||
let mut buf = String::new();
|
||||
let mut arc;
|
||||
let mut current_map = self;
|
||||
while let Some(block) = current_map.block {
|
||||
format_to!(buf, "{:?} in {:?}\n", block.block, block.parent);
|
||||
arc = block.parent.def_map(db, self.krate);
|
||||
current_map = &arc;
|
||||
}
|
||||
|
||||
format_to!(buf, "crate scope\n");
|
||||
buf
|
||||
}
|
||||
}
|
||||
|
||||
impl DefMap {
|
||||
pub(crate) fn block_id(&self) -> Option<BlockId> {
|
||||
self.block.map(|block| block.block)
|
||||
}
|
||||
@@ -460,21 +587,6 @@ pub(crate) fn macro_use_prelude(
|
||||
self.macro_use_prelude.iter().map(|(name, &def)| (name, def))
|
||||
}
|
||||
|
||||
pub fn module_id(&self, local_id: LocalModuleId) -> ModuleId {
|
||||
let block = self.block.map(|b| b.block);
|
||||
ModuleId { krate: self.krate, local_id, block }
|
||||
}
|
||||
|
||||
pub fn crate_root(&self) -> CrateRootModuleId {
|
||||
CrateRootModuleId { krate: self.krate }
|
||||
}
|
||||
|
||||
/// This is the same as [`Self::crate_root`] for crate def maps, but for block def maps, it
|
||||
/// returns the root block module.
|
||||
pub fn root_module_id(&self) -> ModuleId {
|
||||
self.module_id(Self::ROOT)
|
||||
}
|
||||
|
||||
pub(crate) fn resolve_path(
|
||||
&self,
|
||||
db: &dyn DefDatabase,
|
||||
@@ -536,114 +648,6 @@ pub(crate) fn with_ancestor_maps<T>(
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
/// If this `DefMap` is for a block expression, returns the module containing the block (which
|
||||
/// might again be a block, or a module inside a block).
|
||||
pub fn parent(&self) -> Option<ModuleId> {
|
||||
let BlockRelativeModuleId { block, local_id } = self.block?.parent;
|
||||
Some(ModuleId { krate: self.krate, block, local_id })
|
||||
}
|
||||
|
||||
/// Returns the module containing `local_mod`, either the parent `mod`, or the module (or block) containing
|
||||
/// the block, if `self` corresponds to a block expression.
|
||||
pub fn containing_module(&self, local_mod: LocalModuleId) -> Option<ModuleId> {
|
||||
match self[local_mod].parent {
|
||||
Some(parent) => Some(self.module_id(parent)),
|
||||
None => {
|
||||
self.block.map(
|
||||
|BlockInfo { parent: BlockRelativeModuleId { block, local_id }, .. }| {
|
||||
ModuleId { krate: self.krate, block, local_id }
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: this can use some more human-readable format (ideally, an IR
|
||||
// even), as this should be a great debugging aid.
|
||||
pub fn dump(&self, db: &dyn DefDatabase) -> String {
|
||||
let mut buf = String::new();
|
||||
let mut arc;
|
||||
let mut current_map = self;
|
||||
while let Some(block) = current_map.block {
|
||||
go(&mut buf, db, current_map, "block scope", Self::ROOT);
|
||||
buf.push('\n');
|
||||
arc = block.parent.def_map(db, self.krate);
|
||||
current_map = &arc;
|
||||
}
|
||||
go(&mut buf, db, current_map, "crate", Self::ROOT);
|
||||
return buf;
|
||||
|
||||
fn go(
|
||||
buf: &mut String,
|
||||
db: &dyn DefDatabase,
|
||||
map: &DefMap,
|
||||
path: &str,
|
||||
module: LocalModuleId,
|
||||
) {
|
||||
format_to!(buf, "{}\n", path);
|
||||
|
||||
map.modules[module].scope.dump(db.upcast(), buf);
|
||||
|
||||
for (name, child) in
|
||||
map.modules[module].children.iter().sorted_by(|a, b| Ord::cmp(&a.0, &b.0))
|
||||
{
|
||||
let path = format!("{path}::{}", name.display(db.upcast()));
|
||||
buf.push('\n');
|
||||
go(buf, db, map, &path, *child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn dump_block_scopes(&self, db: &dyn DefDatabase) -> String {
|
||||
let mut buf = String::new();
|
||||
let mut arc;
|
||||
let mut current_map = self;
|
||||
while let Some(block) = current_map.block {
|
||||
format_to!(buf, "{:?} in {:?}\n", block.block, block.parent);
|
||||
arc = block.parent.def_map(db, self.krate);
|
||||
current_map = &arc;
|
||||
}
|
||||
|
||||
format_to!(buf, "crate scope\n");
|
||||
buf
|
||||
}
|
||||
|
||||
fn shrink_to_fit(&mut self) {
|
||||
// Exhaustive match to require handling new fields.
|
||||
let Self {
|
||||
_c: _,
|
||||
macro_use_prelude,
|
||||
diagnostics,
|
||||
modules,
|
||||
derive_helpers_in_scope,
|
||||
block: _,
|
||||
krate: _,
|
||||
prelude: _,
|
||||
data: _,
|
||||
enum_definitions,
|
||||
} = self;
|
||||
|
||||
macro_use_prelude.shrink_to_fit();
|
||||
diagnostics.shrink_to_fit();
|
||||
modules.shrink_to_fit();
|
||||
derive_helpers_in_scope.shrink_to_fit();
|
||||
enum_definitions.shrink_to_fit();
|
||||
for (_, module) in modules.iter_mut() {
|
||||
module.children.shrink_to_fit();
|
||||
module.scope.shrink_to_fit();
|
||||
}
|
||||
}
|
||||
|
||||
/// Get a reference to the def map's diagnostics.
|
||||
pub fn diagnostics(&self) -> &[DefDiagnostic] {
|
||||
self.diagnostics.as_slice()
|
||||
}
|
||||
|
||||
pub fn recursion_limit(&self) -> u32 {
|
||||
// 128 is the default in rustc
|
||||
self.data.recursion_limit.unwrap_or(128)
|
||||
}
|
||||
}
|
||||
|
||||
impl ModuleData {
|
||||
|
||||
@@ -64,19 +64,18 @@
|
||||
pub(super) fn collect_defs(db: &dyn DefDatabase, def_map: DefMap, tree_id: TreeId) -> DefMap {
|
||||
let crate_graph = db.crate_graph();
|
||||
|
||||
let mut deps = FxHashMap::default();
|
||||
// populate external prelude and dependency list
|
||||
let krate = &crate_graph[def_map.krate];
|
||||
|
||||
// populate external prelude and dependency list
|
||||
let mut deps =
|
||||
FxHashMap::with_capacity_and_hasher(krate.dependencies.len(), Default::default());
|
||||
for dep in &krate.dependencies {
|
||||
tracing::debug!("crate dep {:?} -> {:?}", dep.name, dep.crate_id);
|
||||
|
||||
deps.insert(dep.as_name(), dep.clone());
|
||||
}
|
||||
|
||||
let cfg_options = &krate.cfg_options;
|
||||
|
||||
let is_proc_macro = krate.is_proc_macro;
|
||||
let proc_macros = if is_proc_macro {
|
||||
let proc_macros = if krate.is_proc_macro {
|
||||
match db.proc_macros().get(&def_map.krate) {
|
||||
Some(Ok(proc_macros)) => {
|
||||
Ok(proc_macros
|
||||
@@ -124,11 +123,11 @@ pub(super) fn collect_defs(db: &dyn DefDatabase, def_map: DefMap, tree_id: TreeI
|
||||
indeterminate_imports: Vec::new(),
|
||||
unresolved_macros: Vec::new(),
|
||||
mod_dirs: FxHashMap::default(),
|
||||
cfg_options,
|
||||
cfg_options: &krate.cfg_options,
|
||||
proc_macros,
|
||||
from_glob_import: Default::default(),
|
||||
skip_attrs: Default::default(),
|
||||
is_proc_macro,
|
||||
is_proc_macro: krate.is_proc_macro,
|
||||
};
|
||||
if tree_id.is_block() {
|
||||
collector.seed_with_inner(tree_id);
|
||||
@@ -302,71 +301,50 @@ fn seed_with_top_level(&mut self) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
let attr_name = match attr.path.as_ident() {
|
||||
Some(name) => name,
|
||||
None => continue,
|
||||
};
|
||||
let Some(attr_name) = attr.path.as_ident() else { continue };
|
||||
|
||||
if *attr_name == hir_expand::name![recursion_limit] {
|
||||
if let Some(limit) = attr.string_value() {
|
||||
if let Ok(limit) = limit.parse() {
|
||||
crate_data.recursion_limit = Some(limit);
|
||||
match () {
|
||||
() if *attr_name == hir_expand::name![recursion_limit] => {
|
||||
if let Some(limit) = attr.string_value() {
|
||||
if let Ok(limit) = limit.parse() {
|
||||
crate_data.recursion_limit = Some(limit);
|
||||
}
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if *attr_name == hir_expand::name![crate_type] {
|
||||
if let Some("proc-macro") = attr.string_value().map(SmolStr::as_str) {
|
||||
self.is_proc_macro = true;
|
||||
() if *attr_name == hir_expand::name![crate_type] => {
|
||||
if let Some("proc-macro") = attr.string_value().map(SmolStr::as_str) {
|
||||
self.is_proc_macro = true;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if *attr_name == hir_expand::name![no_core] {
|
||||
crate_data.no_core = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if *attr_name == hir_expand::name![no_std] {
|
||||
crate_data.no_std = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if attr_name.as_text().as_deref() == Some("rustc_coherence_is_core") {
|
||||
crate_data.rustc_coherence_is_core = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if *attr_name == hir_expand::name![feature] {
|
||||
let features = attr
|
||||
.parse_path_comma_token_tree(self.db.upcast())
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.filter_map(|(feat, _)| match feat.segments() {
|
||||
[name] => Some(name.to_smol_str()),
|
||||
_ => None,
|
||||
});
|
||||
crate_data.unstable_features.extend(features);
|
||||
}
|
||||
|
||||
let attr_is_register_like = *attr_name == hir_expand::name![register_attr]
|
||||
|| *attr_name == hir_expand::name![register_tool];
|
||||
if !attr_is_register_like {
|
||||
continue;
|
||||
}
|
||||
|
||||
let registered_name = match attr.single_ident_value() {
|
||||
Some(ident) => ident.as_name(),
|
||||
_ => continue,
|
||||
};
|
||||
|
||||
if *attr_name == hir_expand::name![register_attr] {
|
||||
crate_data.registered_attrs.push(registered_name.to_smol_str());
|
||||
cov_mark::hit!(register_attr);
|
||||
} else {
|
||||
crate_data.registered_tools.push(registered_name.to_smol_str());
|
||||
cov_mark::hit!(register_tool);
|
||||
() if *attr_name == hir_expand::name![no_core] => crate_data.no_core = true,
|
||||
() if *attr_name == hir_expand::name![no_std] => crate_data.no_std = true,
|
||||
() if attr_name.as_text().as_deref() == Some("rustc_coherence_is_core") => {
|
||||
crate_data.rustc_coherence_is_core = true;
|
||||
}
|
||||
() if *attr_name == hir_expand::name![feature] => {
|
||||
let features = attr
|
||||
.parse_path_comma_token_tree(self.db.upcast())
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.filter_map(|(feat, _)| match feat.segments() {
|
||||
[name] => Some(name.to_smol_str()),
|
||||
_ => None,
|
||||
});
|
||||
crate_data.unstable_features.extend(features);
|
||||
}
|
||||
() if *attr_name == hir_expand::name![register_attr] => {
|
||||
if let Some(ident) = attr.single_ident_value() {
|
||||
crate_data.registered_attrs.push(ident.text.clone());
|
||||
cov_mark::hit!(register_attr);
|
||||
}
|
||||
}
|
||||
() if *attr_name == hir_expand::name![register_tool] => {
|
||||
if let Some(ident) = attr.single_ident_value() {
|
||||
crate_data.registered_tools.push(ident.text.clone());
|
||||
cov_mark::hit!(register_tool);
|
||||
}
|
||||
}
|
||||
() => (),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -409,6 +387,7 @@ fn resolution_loop(&mut self) {
|
||||
// main name resolution fixed-point loop.
|
||||
let mut i = 0;
|
||||
'resolve_attr: loop {
|
||||
let _p = tracing::span!(tracing::Level::INFO, "resolve_macros loop").entered();
|
||||
'resolve_macros: loop {
|
||||
self.db.unwind_if_cancelled();
|
||||
|
||||
@@ -466,9 +445,8 @@ fn collect(&mut self) {
|
||||
// Additionally, while the proc macro entry points must be `pub`, they are not publicly
|
||||
// exported in type/value namespace. This function reduces the visibility of all items
|
||||
// in the crate root that aren't proc macros.
|
||||
let root = DefMap::ROOT;
|
||||
let module_id = self.def_map.module_id(root);
|
||||
let root = &mut self.def_map.modules[root];
|
||||
let module_id = self.def_map.module_id(DefMap::ROOT);
|
||||
let root = &mut self.def_map.modules[DefMap::ROOT];
|
||||
root.scope.censor_non_proc_macros(module_id);
|
||||
}
|
||||
}
|
||||
@@ -828,12 +806,10 @@ fn resolve_import(&self, module_id: LocalModuleId, import: &Import) -> PartialRe
|
||||
return PartialResolvedImport::Unresolved;
|
||||
}
|
||||
|
||||
if let Some(krate) = res.krate {
|
||||
if krate != self.def_map.krate {
|
||||
return PartialResolvedImport::Resolved(
|
||||
def.filter_visibility(|v| matches!(v, Visibility::Public)),
|
||||
);
|
||||
}
|
||||
if res.from_differing_crate {
|
||||
return PartialResolvedImport::Resolved(
|
||||
def.filter_visibility(|v| matches!(v, Visibility::Public)),
|
||||
);
|
||||
}
|
||||
|
||||
// Check whether all namespaces are resolved.
|
||||
@@ -1408,7 +1384,9 @@ fn collect_macro_expansion(
|
||||
// First, fetch the raw expansion result for purposes of error reporting. This goes through
|
||||
// `parse_macro_expansion_error` to avoid depending on the full expansion result (to improve
|
||||
// incrementality).
|
||||
let ExpandResult { value, err } = self.db.parse_macro_expansion_error(macro_call_id);
|
||||
// FIXME: This kind of error fetching feels a bit odd?
|
||||
let ExpandResult { value: errors, err } =
|
||||
self.db.parse_macro_expansion_error(macro_call_id);
|
||||
if let Some(err) = err {
|
||||
let loc: MacroCallLoc = self.db.lookup_intern_macro_call(macro_call_id);
|
||||
let diag = match err {
|
||||
@@ -1422,7 +1400,7 @@ fn collect_macro_expansion(
|
||||
|
||||
self.def_map.diagnostics.push(diag);
|
||||
}
|
||||
if let errors @ [_, ..] = &*value {
|
||||
if !errors.is_empty() {
|
||||
let loc: MacroCallLoc = self.db.lookup_intern_macro_call(macro_call_id);
|
||||
let diag = DefDiagnostic::macro_expansion_parse_error(module_id, loc.kind, errors);
|
||||
self.def_map.diagnostics.push(diag);
|
||||
@@ -1920,7 +1898,7 @@ fn process_macro_use_extern_crate<'a>(
|
||||
}
|
||||
|
||||
fn collect_module(&mut self, module_id: FileItemTreeId<Mod>, attrs: &Attrs) {
|
||||
let path_attr = attrs.by_key("path").string_value();
|
||||
let path_attr = attrs.by_key("path").string_value().map(SmolStr::as_str);
|
||||
let is_macro_use = attrs.by_key("macro_use").exists();
|
||||
let module = &self.item_tree[module_id];
|
||||
match &module.kind {
|
||||
@@ -1934,25 +1912,26 @@ fn collect_module(&mut self, module_id: FileItemTreeId<Mod>, attrs: &Attrs) {
|
||||
module_id,
|
||||
);
|
||||
|
||||
if let Some(mod_dir) = self.mod_dir.descend_into_definition(&module.name, path_attr)
|
||||
{
|
||||
ModCollector {
|
||||
def_collector: &mut *self.def_collector,
|
||||
macro_depth: self.macro_depth,
|
||||
module_id,
|
||||
tree_id: self.tree_id,
|
||||
item_tree: self.item_tree,
|
||||
mod_dir,
|
||||
}
|
||||
.collect_in_top_module(items);
|
||||
if is_macro_use {
|
||||
self.import_all_legacy_macros(module_id);
|
||||
}
|
||||
let Some(mod_dir) = self.mod_dir.descend_into_definition(&module.name, path_attr)
|
||||
else {
|
||||
return;
|
||||
};
|
||||
ModCollector {
|
||||
def_collector: &mut *self.def_collector,
|
||||
macro_depth: self.macro_depth,
|
||||
module_id,
|
||||
tree_id: self.tree_id,
|
||||
item_tree: self.item_tree,
|
||||
mod_dir,
|
||||
}
|
||||
.collect_in_top_module(items);
|
||||
if is_macro_use {
|
||||
self.import_all_legacy_macros(module_id);
|
||||
}
|
||||
}
|
||||
// out of line module, resolve, parse and recurse
|
||||
ModKind::Outline => {
|
||||
let ast_id = AstId::new(self.tree_id.file_id(), module.ast_id);
|
||||
let ast_id = AstId::new(self.file_id(), module.ast_id);
|
||||
let db = self.def_collector.db;
|
||||
match self.mod_dir.resolve_declaration(db, self.file_id(), &module.name, path_attr)
|
||||
{
|
||||
@@ -2445,7 +2424,7 @@ mod tests {
|
||||
use base_db::SourceDatabase;
|
||||
use test_fixture::WithFixture;
|
||||
|
||||
use crate::test_db::TestDB;
|
||||
use crate::{nameres::DefMapCrateData, test_db::TestDB};
|
||||
|
||||
use super::*;
|
||||
|
||||
@@ -2476,8 +2455,12 @@ fn do_resolve(not_ra_fixture: &str) -> DefMap {
|
||||
|
||||
let edition = db.crate_graph()[krate].edition;
|
||||
let module_origin = ModuleOrigin::CrateRoot { definition: file_id };
|
||||
let def_map =
|
||||
DefMap::empty(krate, edition, ModuleData::new(module_origin, Visibility::Public));
|
||||
let def_map = DefMap::empty(
|
||||
krate,
|
||||
Arc::new(DefMapCrateData::new(edition)),
|
||||
ModuleData::new(module_origin, Visibility::Public),
|
||||
None,
|
||||
);
|
||||
do_collect_defs(&db, def_map)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
//! Diagnostics emitted during DefMap construction.
|
||||
|
||||
use std::ops::Not;
|
||||
|
||||
use base_db::CrateId;
|
||||
use cfg::{CfgExpr, CfgOptions};
|
||||
use hir_expand::{attrs::AttrId, ErasedAstId, MacroCallKind};
|
||||
@@ -16,27 +18,16 @@
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum DefDiagnosticKind {
|
||||
UnresolvedModule { ast: AstId<ast::Module>, candidates: Box<[String]> },
|
||||
|
||||
UnresolvedExternCrate { ast: AstId<ast::ExternCrate> },
|
||||
|
||||
UnresolvedImport { id: ItemTreeId<item_tree::Use>, index: Idx<ast::UseTree> },
|
||||
|
||||
UnconfiguredCode { ast: ErasedAstId, cfg: CfgExpr, opts: CfgOptions },
|
||||
|
||||
UnresolvedProcMacro { ast: MacroCallKind, krate: CrateId },
|
||||
|
||||
UnresolvedMacroCall { ast: MacroCallKind, path: ModPath },
|
||||
|
||||
MacroError { ast: MacroCallKind, message: String },
|
||||
|
||||
MacroExpansionParseError { ast: MacroCallKind, errors: Box<[SyntaxError]> },
|
||||
|
||||
UnimplementedBuiltinMacro { ast: AstId<ast::Macro> },
|
||||
|
||||
InvalidDeriveTarget { ast: AstId<ast::Item>, id: usize },
|
||||
|
||||
MalformedDerive { ast: AstId<ast::Adt>, id: usize },
|
||||
|
||||
MacroDefError { ast: AstId<ast::Macro>, message: String },
|
||||
}
|
||||
|
||||
@@ -45,11 +36,12 @@ pub enum DefDiagnosticKind {
|
||||
|
||||
impl DefDiagnostics {
|
||||
pub fn new(diagnostics: Vec<DefDiagnostic>) -> Self {
|
||||
Self(if diagnostics.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(triomphe::Arc::new(diagnostics.into_boxed_slice()))
|
||||
})
|
||||
Self(
|
||||
diagnostics
|
||||
.is_empty()
|
||||
.not()
|
||||
.then(|| triomphe::Arc::new(diagnostics.into_boxed_slice())),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn iter(&self) -> impl Iterator<Item = &DefDiagnostic> {
|
||||
@@ -125,14 +117,11 @@ pub(crate) fn macro_error(
|
||||
pub(crate) fn macro_expansion_parse_error(
|
||||
container: LocalModuleId,
|
||||
ast: MacroCallKind,
|
||||
errors: &[SyntaxError],
|
||||
errors: Box<[SyntaxError]>,
|
||||
) -> Self {
|
||||
Self {
|
||||
in_module: container,
|
||||
kind: DefDiagnosticKind::MacroExpansionParseError {
|
||||
ast,
|
||||
errors: errors.to_vec().into_boxed_slice(),
|
||||
},
|
||||
kind: DefDiagnosticKind::MacroExpansionParseError { ast, errors },
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
use base_db::{AnchoredPath, FileId};
|
||||
use hir_expand::{name::Name, HirFileIdExt, MacroFileIdExt};
|
||||
use limit::Limit;
|
||||
use syntax::SmolStr;
|
||||
|
||||
use crate::{db::DefDatabase, HirFileId};
|
||||
|
||||
@@ -29,9 +28,9 @@ pub(super) fn root() -> ModDir {
|
||||
pub(super) fn descend_into_definition(
|
||||
&self,
|
||||
name: &Name,
|
||||
attr_path: Option<&SmolStr>,
|
||||
attr_path: Option<&str>,
|
||||
) -> Option<ModDir> {
|
||||
let path = match attr_path.map(SmolStr::as_str) {
|
||||
let path = match attr_path {
|
||||
None => {
|
||||
let mut path = self.dir_path.clone();
|
||||
path.push(&name.unescaped().to_smol_str());
|
||||
@@ -63,10 +62,9 @@ pub(super) fn resolve_declaration(
|
||||
db: &dyn DefDatabase,
|
||||
file_id: HirFileId,
|
||||
name: &Name,
|
||||
attr_path: Option<&SmolStr>,
|
||||
attr_path: Option<&str>,
|
||||
) -> Result<(FileId, bool, ModDir), Box<[String]>> {
|
||||
let name = name.unescaped();
|
||||
let orig_file_id = file_id.original_file_respecting_includes(db.upcast());
|
||||
|
||||
let mut candidate_files = ArrayVec::<_, 2>::new();
|
||||
match attr_path {
|
||||
@@ -91,17 +89,19 @@ pub(super) fn resolve_declaration(
|
||||
}
|
||||
};
|
||||
|
||||
let orig_file_id = file_id.original_file_respecting_includes(db.upcast());
|
||||
for candidate in candidate_files.iter() {
|
||||
let path = AnchoredPath { anchor: orig_file_id, path: candidate.as_str() };
|
||||
if let Some(file_id) = db.resolve_path(path) {
|
||||
let is_mod_rs = candidate.ends_with("/mod.rs");
|
||||
|
||||
let (dir_path, root_non_dir_owner) = if is_mod_rs || attr_path.is_some() {
|
||||
(DirPath::empty(), false)
|
||||
let root_dir_owner = is_mod_rs || attr_path.is_some();
|
||||
let dir_path = if root_dir_owner {
|
||||
DirPath::empty()
|
||||
} else {
|
||||
(DirPath::new(format!("{}/", name.display(db.upcast()))), true)
|
||||
DirPath::new(format!("{}/", name.display(db.upcast())))
|
||||
};
|
||||
if let Some(mod_dir) = self.child(dir_path, root_non_dir_owner) {
|
||||
if let Some(mod_dir) = self.child(dir_path, !root_dir_owner) {
|
||||
return Ok((file_id, is_mod_rs, mod_dir));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
path::{ModPath, PathKind},
|
||||
per_ns::PerNs,
|
||||
visibility::{RawVisibility, Visibility},
|
||||
AdtId, CrateId, LocalModuleId, ModuleDefId,
|
||||
AdtId, LocalModuleId, ModuleDefId,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
@@ -42,21 +42,21 @@ pub(super) struct ResolvePathResult {
|
||||
pub(super) resolved_def: PerNs,
|
||||
pub(super) segment_index: Option<usize>,
|
||||
pub(super) reached_fixedpoint: ReachedFixedPoint,
|
||||
pub(super) krate: Option<CrateId>,
|
||||
pub(super) from_differing_crate: bool,
|
||||
}
|
||||
|
||||
impl ResolvePathResult {
|
||||
fn empty(reached_fixedpoint: ReachedFixedPoint) -> ResolvePathResult {
|
||||
ResolvePathResult::with(PerNs::none(), reached_fixedpoint, None, None)
|
||||
ResolvePathResult::new(PerNs::none(), reached_fixedpoint, None, false)
|
||||
}
|
||||
|
||||
fn with(
|
||||
fn new(
|
||||
resolved_def: PerNs,
|
||||
reached_fixedpoint: ReachedFixedPoint,
|
||||
segment_index: Option<usize>,
|
||||
krate: Option<CrateId>,
|
||||
from_differing_crate: bool,
|
||||
) -> ResolvePathResult {
|
||||
ResolvePathResult { resolved_def, segment_index, reached_fixedpoint, krate }
|
||||
ResolvePathResult { resolved_def, segment_index, reached_fixedpoint, from_differing_crate }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -134,7 +134,19 @@ pub(super) fn resolve_path_fp_with_macro(
|
||||
// resolving them to. Pass `None` otherwise, e.g. when we're resolving import paths.
|
||||
expected_macro_subns: Option<MacroSubNs>,
|
||||
) -> ResolvePathResult {
|
||||
let mut result = ResolvePathResult::empty(ReachedFixedPoint::No);
|
||||
let mut result = self.resolve_path_fp_with_macro_single(
|
||||
db,
|
||||
mode,
|
||||
original_module,
|
||||
path,
|
||||
shadow,
|
||||
expected_macro_subns,
|
||||
);
|
||||
|
||||
if self.block.is_none() {
|
||||
// If we're in the root `DefMap`, we can resolve the path directly.
|
||||
return result;
|
||||
}
|
||||
|
||||
let mut arc;
|
||||
let mut current_map = self;
|
||||
@@ -153,8 +165,7 @@ pub(super) fn resolve_path_fp_with_macro(
|
||||
if result.reached_fixedpoint == ReachedFixedPoint::No {
|
||||
result.reached_fixedpoint = new.reached_fixedpoint;
|
||||
}
|
||||
// FIXME: this doesn't seem right; what if the different namespace resolutions come from different crates?
|
||||
result.krate = result.krate.or(new.krate);
|
||||
result.from_differing_crate |= new.from_differing_crate;
|
||||
result.segment_index = match (result.segment_index, new.segment_index) {
|
||||
(Some(idx), None) => Some(idx),
|
||||
(Some(old), Some(new)) => Some(old.max(new)),
|
||||
@@ -333,11 +344,11 @@ pub(super) fn resolve_path_fp_with_macro_single(
|
||||
// expectation is discarded.
|
||||
let (def, s) =
|
||||
defp_map.resolve_path(db, module.local_id, &path, shadow, None);
|
||||
return ResolvePathResult::with(
|
||||
return ResolvePathResult::new(
|
||||
def,
|
||||
ReachedFixedPoint::Yes,
|
||||
s.map(|s| s + i),
|
||||
Some(module.krate),
|
||||
true,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -385,11 +396,11 @@ pub(super) fn resolve_path_fp_with_macro_single(
|
||||
match res {
|
||||
Some(res) => res,
|
||||
None => {
|
||||
return ResolvePathResult::with(
|
||||
return ResolvePathResult::new(
|
||||
PerNs::types(e.into(), vis, imp),
|
||||
ReachedFixedPoint::Yes,
|
||||
Some(i),
|
||||
Some(self.krate),
|
||||
false,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -403,11 +414,11 @@ pub(super) fn resolve_path_fp_with_macro_single(
|
||||
curr,
|
||||
);
|
||||
|
||||
return ResolvePathResult::with(
|
||||
return ResolvePathResult::new(
|
||||
PerNs::types(s, vis, imp),
|
||||
ReachedFixedPoint::Yes,
|
||||
Some(i),
|
||||
Some(self.krate),
|
||||
false,
|
||||
);
|
||||
}
|
||||
};
|
||||
@@ -416,7 +427,7 @@ pub(super) fn resolve_path_fp_with_macro_single(
|
||||
.filter_visibility(|vis| vis.is_visible_from_def_map(db, self, original_module));
|
||||
}
|
||||
|
||||
ResolvePathResult::with(curr_per_ns, ReachedFixedPoint::Yes, None, Some(self.krate))
|
||||
ResolvePathResult::new(curr_per_ns, ReachedFixedPoint::Yes, None, false)
|
||||
}
|
||||
|
||||
fn resolve_name_in_module(
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
use std::iter;
|
||||
|
||||
use hir_expand::{span_map::SpanMapRef, InFile};
|
||||
use la_arena::ArenaMap;
|
||||
use span::SyntaxContextId;
|
||||
use syntax::ast;
|
||||
use triomphe::Arc;
|
||||
|
||||
@@ -34,36 +34,25 @@ pub(crate) const fn private() -> RawVisibility {
|
||||
}
|
||||
|
||||
pub(crate) fn from_ast(
|
||||
db: &dyn DefDatabase,
|
||||
node: InFile<Option<ast::Visibility>>,
|
||||
) -> RawVisibility {
|
||||
let node = match node.transpose() {
|
||||
None => return RawVisibility::private(),
|
||||
Some(node) => node,
|
||||
};
|
||||
Self::from_ast_with_span_map(db, node.value, db.span_map(node.file_id).as_ref())
|
||||
}
|
||||
|
||||
pub(crate) fn from_opt_ast_with_span_map(
|
||||
db: &dyn DefDatabase,
|
||||
node: Option<ast::Visibility>,
|
||||
span_map: SpanMapRef<'_>,
|
||||
span_for_range: &mut dyn FnMut(::tt::TextRange) -> SyntaxContextId,
|
||||
) -> RawVisibility {
|
||||
let node = match node {
|
||||
None => return RawVisibility::private(),
|
||||
Some(node) => node,
|
||||
};
|
||||
Self::from_ast_with_span_map(db, node, span_map)
|
||||
Self::from_ast_with_span_map(db, node, span_for_range)
|
||||
}
|
||||
|
||||
fn from_ast_with_span_map(
|
||||
db: &dyn DefDatabase,
|
||||
node: ast::Visibility,
|
||||
span_map: SpanMapRef<'_>,
|
||||
span_for_range: &mut dyn FnMut(::tt::TextRange) -> SyntaxContextId,
|
||||
) -> RawVisibility {
|
||||
let path = match node.kind() {
|
||||
ast::VisibilityKind::In(path) => {
|
||||
let path = ModPath::from_src(db.upcast(), path, span_map);
|
||||
let path = ModPath::from_src(db.upcast(), path, span_for_range);
|
||||
match path {
|
||||
None => return RawVisibility::private(),
|
||||
Some(path) => path,
|
||||
|
||||
@@ -28,7 +28,6 @@ intern.workspace = true
|
||||
base-db.workspace = true
|
||||
cfg.workspace = true
|
||||
syntax.workspace = true
|
||||
profile.workspace = true
|
||||
tt.workspace = true
|
||||
mbe.workspace = true
|
||||
limit.workspace = true
|
||||
@@ -38,4 +37,4 @@ span.workspace = true
|
||||
expect-test = "1.4.0"
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
workspace = true
|
||||
|
||||
@@ -90,7 +90,7 @@ pub fn merge(&self, other: Self) -> Self {
|
||||
}
|
||||
|
||||
/// Processes `cfg_attr`s, returning the resulting semantic `Attrs`.
|
||||
// FIXME: This should return a different type
|
||||
// FIXME: This should return a different type, signaling it was filtered?
|
||||
pub fn filter(self, db: &dyn ExpandDatabase, krate: CrateId) -> RawAttrs {
|
||||
let has_cfg_attrs = self
|
||||
.iter()
|
||||
@@ -201,7 +201,9 @@ fn from_src(
|
||||
span_map: SpanMapRef<'_>,
|
||||
id: AttrId,
|
||||
) -> Option<Attr> {
|
||||
let path = Interned::new(ModPath::from_src(db, ast.path()?, span_map)?);
|
||||
let path = Interned::new(ModPath::from_src(db, ast.path()?, &mut |range| {
|
||||
span_map.span_for_range(range).ctx
|
||||
})?);
|
||||
let span = span_map.span_for_range(ast.syntax().text_range());
|
||||
let input = if let Some(ast::Expr::Literal(lit)) = ast.expr() {
|
||||
let value = match lit.kind() {
|
||||
|
||||
@@ -4,23 +4,17 @@
|
||||
use crate::{db::ExpandDatabase, name, tt, ExpandResult, MacroCallKind};
|
||||
|
||||
macro_rules! register_builtin {
|
||||
($expand_fn:ident: $(($name:ident, $variant:ident) => $expand:ident),* ) => {
|
||||
($(($name:ident, $variant:ident) => $expand:ident),* ) => {
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub enum BuiltinAttrExpander {
|
||||
$($variant),*
|
||||
}
|
||||
|
||||
impl BuiltinAttrExpander {
|
||||
pub fn $expand_fn(
|
||||
&self,
|
||||
db: &dyn ExpandDatabase,
|
||||
id: MacroCallId,
|
||||
tt: &tt::Subtree,
|
||||
) -> ExpandResult<tt::Subtree> {
|
||||
let expander = match *self {
|
||||
pub fn expander(&self) -> fn (&dyn ExpandDatabase, MacroCallId, &tt::Subtree) -> ExpandResult<tt::Subtree> {
|
||||
match *self {
|
||||
$( BuiltinAttrExpander::$variant => $expand, )*
|
||||
};
|
||||
expander(db, id, tt)
|
||||
}
|
||||
}
|
||||
|
||||
fn find_by_name(name: &name::Name) -> Option<Self> {
|
||||
@@ -35,6 +29,15 @@ fn find_by_name(name: &name::Name) -> Option<Self> {
|
||||
}
|
||||
|
||||
impl BuiltinAttrExpander {
|
||||
pub fn expand(
|
||||
&self,
|
||||
db: &dyn ExpandDatabase,
|
||||
id: MacroCallId,
|
||||
tt: &tt::Subtree,
|
||||
) -> ExpandResult<tt::Subtree> {
|
||||
self.expander()(db, id, tt)
|
||||
}
|
||||
|
||||
pub fn is_derive(self) -> bool {
|
||||
matches!(self, BuiltinAttrExpander::Derive | BuiltinAttrExpander::DeriveConst)
|
||||
}
|
||||
@@ -46,7 +49,7 @@ pub fn is_bench(self) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
register_builtin! { expand:
|
||||
register_builtin! {
|
||||
(bench, Bench) => dummy_attr_expand,
|
||||
(cfg, Cfg) => dummy_attr_expand,
|
||||
(cfg_attr, CfgAttr) => dummy_attr_expand,
|
||||
|
||||
@@ -10,10 +10,12 @@
|
||||
hygiene::span_with_def_site_ctxt,
|
||||
name::{AsName, Name},
|
||||
quote::dollar_crate,
|
||||
span_map::SpanMapRef,
|
||||
span_map::ExpansionSpanMap,
|
||||
tt,
|
||||
};
|
||||
use syntax::ast::{self, AstNode, FieldList, HasAttrs, HasGenericParams, HasName, HasTypeBounds};
|
||||
use syntax::ast::{
|
||||
self, AstNode, FieldList, HasAttrs, HasGenericParams, HasModuleItem, HasName, HasTypeBounds,
|
||||
};
|
||||
|
||||
use crate::{db::ExpandDatabase, name, quote, ExpandError, ExpandResult};
|
||||
|
||||
@@ -25,20 +27,10 @@ pub enum BuiltinDeriveExpander {
|
||||
}
|
||||
|
||||
impl BuiltinDeriveExpander {
|
||||
pub fn expand(
|
||||
&self,
|
||||
db: &dyn ExpandDatabase,
|
||||
id: MacroCallId,
|
||||
tt: &ast::Adt,
|
||||
token_map: SpanMapRef<'_>,
|
||||
) -> ExpandResult<tt::Subtree> {
|
||||
let expander = match *self {
|
||||
pub fn expander(&self) -> fn(Span, &tt::Subtree) -> ExpandResult<tt::Subtree> {
|
||||
match *self {
|
||||
$( BuiltinDeriveExpander::$trait => $expand, )*
|
||||
};
|
||||
|
||||
let span = db.lookup_intern_macro_call(id).call_site;
|
||||
let span = span_with_def_site_ctxt(db, span, id);
|
||||
expander(span, tt, token_map)
|
||||
}
|
||||
}
|
||||
|
||||
fn find_by_name(name: &name::Name) -> Option<Self> {
|
||||
@@ -52,6 +44,19 @@ fn find_by_name(name: &name::Name) -> Option<Self> {
|
||||
};
|
||||
}
|
||||
|
||||
impl BuiltinDeriveExpander {
|
||||
pub fn expand(
|
||||
&self,
|
||||
db: &dyn ExpandDatabase,
|
||||
id: MacroCallId,
|
||||
tt: &tt::Subtree,
|
||||
) -> ExpandResult<tt::Subtree> {
|
||||
let span = db.lookup_intern_macro_call(id).call_site;
|
||||
let span = span_with_def_site_ctxt(db, span, id);
|
||||
self.expander()(span, tt)
|
||||
}
|
||||
}
|
||||
|
||||
register_builtin! {
|
||||
Copy => copy_expand,
|
||||
Clone => clone_expand,
|
||||
@@ -122,7 +127,7 @@ fn as_pattern_map(
|
||||
}
|
||||
}
|
||||
|
||||
fn from(tm: SpanMapRef<'_>, value: Option<FieldList>) -> Result<Self, ExpandError> {
|
||||
fn from(tm: &ExpansionSpanMap, value: Option<FieldList>) -> Result<Self, ExpandError> {
|
||||
let r = match value {
|
||||
None => VariantShape::Unit,
|
||||
Some(FieldList::RecordFieldList(it)) => VariantShape::Struct(
|
||||
@@ -198,11 +203,13 @@ struct BasicAdtInfo {
|
||||
associated_types: Vec<tt::Subtree>,
|
||||
}
|
||||
|
||||
fn parse_adt(
|
||||
tm: SpanMapRef<'_>,
|
||||
adt: &ast::Adt,
|
||||
call_site: Span,
|
||||
) -> Result<BasicAdtInfo, ExpandError> {
|
||||
fn parse_adt(tt: &tt::Subtree, call_site: Span) -> Result<BasicAdtInfo, ExpandError> {
|
||||
let (parsed, tm) = &mbe::token_tree_to_syntax_node(tt, mbe::TopEntryPoint::MacroItems);
|
||||
let macro_items = ast::MacroItems::cast(parsed.syntax_node())
|
||||
.ok_or_else(|| ExpandError::other("invalid item definition"))?;
|
||||
let item = macro_items.items().next().ok_or_else(|| ExpandError::other("no item found"))?;
|
||||
let adt = &ast::Adt::cast(item.syntax().clone())
|
||||
.ok_or_else(|| ExpandError::other("expected struct, enum or union"))?;
|
||||
let (name, generic_param_list, where_clause, shape) = match adt {
|
||||
ast::Adt::Struct(it) => (
|
||||
it.name(),
|
||||
@@ -318,14 +325,14 @@ fn parse_adt(
|
||||
}
|
||||
|
||||
fn name_to_token(
|
||||
token_map: SpanMapRef<'_>,
|
||||
token_map: &ExpansionSpanMap,
|
||||
name: Option<ast::Name>,
|
||||
) -> Result<tt::Ident, ExpandError> {
|
||||
let name = name.ok_or_else(|| {
|
||||
debug!("parsed item has no name");
|
||||
ExpandError::other("missing name")
|
||||
})?;
|
||||
let span = token_map.span_for_range(name.syntax().text_range());
|
||||
let span = token_map.span_at(name.syntax().text_range().start());
|
||||
let name_token = tt::Ident { span, text: name.text().into() };
|
||||
Ok(name_token)
|
||||
}
|
||||
@@ -362,14 +369,12 @@ fn name_to_token(
|
||||
/// where B1, ..., BN are the bounds given by `bounds_paths`. Z is a phantom type, and
|
||||
/// therefore does not get bound by the derived trait.
|
||||
fn expand_simple_derive(
|
||||
// FIXME: use
|
||||
invoc_span: Span,
|
||||
tt: &ast::Adt,
|
||||
tm: SpanMapRef<'_>,
|
||||
tt: &tt::Subtree,
|
||||
trait_path: tt::Subtree,
|
||||
make_trait_body: impl FnOnce(&BasicAdtInfo) -> tt::Subtree,
|
||||
) -> ExpandResult<tt::Subtree> {
|
||||
let info = match parse_adt(tm, tt, invoc_span) {
|
||||
let info = match parse_adt(tt, invoc_span) {
|
||||
Ok(info) => info,
|
||||
Err(e) => {
|
||||
return ExpandResult::new(
|
||||
@@ -412,14 +417,14 @@ impl < ##params > #trait_path for #name < ##args > where ##where_block { #trait_
|
||||
ExpandResult::ok(expanded)
|
||||
}
|
||||
|
||||
fn copy_expand(span: Span, tt: &ast::Adt, tm: SpanMapRef<'_>) -> ExpandResult<tt::Subtree> {
|
||||
fn copy_expand(span: Span, tt: &tt::Subtree) -> ExpandResult<tt::Subtree> {
|
||||
let krate = dollar_crate(span);
|
||||
expand_simple_derive(span, tt, tm, quote! {span => #krate::marker::Copy }, |_| quote! {span =>})
|
||||
expand_simple_derive(span, tt, quote! {span => #krate::marker::Copy }, |_| quote! {span =>})
|
||||
}
|
||||
|
||||
fn clone_expand(span: Span, tt: &ast::Adt, tm: SpanMapRef<'_>) -> ExpandResult<tt::Subtree> {
|
||||
fn clone_expand(span: Span, tt: &tt::Subtree) -> ExpandResult<tt::Subtree> {
|
||||
let krate = dollar_crate(span);
|
||||
expand_simple_derive(span, tt, tm, quote! {span => #krate::clone::Clone }, |adt| {
|
||||
expand_simple_derive(span, tt, quote! {span => #krate::clone::Clone }, |adt| {
|
||||
if matches!(adt.shape, AdtShape::Union) {
|
||||
let star = tt::Punct { char: '*', spacing: ::tt::Spacing::Alone, span };
|
||||
return quote! {span =>
|
||||
@@ -468,9 +473,9 @@ fn and_and(span: Span) -> tt::Subtree {
|
||||
quote! {span => #and& }
|
||||
}
|
||||
|
||||
fn default_expand(span: Span, tt: &ast::Adt, tm: SpanMapRef<'_>) -> ExpandResult<tt::Subtree> {
|
||||
fn default_expand(span: Span, tt: &tt::Subtree) -> ExpandResult<tt::Subtree> {
|
||||
let krate = &dollar_crate(span);
|
||||
expand_simple_derive(span, tt, tm, quote! {span => #krate::default::Default }, |adt| {
|
||||
expand_simple_derive(span, tt, quote! {span => #krate::default::Default }, |adt| {
|
||||
let body = match &adt.shape {
|
||||
AdtShape::Struct(fields) => {
|
||||
let name = &adt.name;
|
||||
@@ -507,9 +512,9 @@ fn default() -> Self {
|
||||
})
|
||||
}
|
||||
|
||||
fn debug_expand(span: Span, tt: &ast::Adt, tm: SpanMapRef<'_>) -> ExpandResult<tt::Subtree> {
|
||||
fn debug_expand(span: Span, tt: &tt::Subtree) -> ExpandResult<tt::Subtree> {
|
||||
let krate = &dollar_crate(span);
|
||||
expand_simple_derive(span, tt, tm, quote! {span => #krate::fmt::Debug }, |adt| {
|
||||
expand_simple_derive(span, tt, quote! {span => #krate::fmt::Debug }, |adt| {
|
||||
let for_variant = |name: String, v: &VariantShape| match v {
|
||||
VariantShape::Struct(fields) => {
|
||||
let for_fields = fields.iter().map(|it| {
|
||||
@@ -579,9 +584,9 @@ fn fmt(&self, f: &mut #krate::fmt::Formatter) -> #krate::fmt::Result {
|
||||
})
|
||||
}
|
||||
|
||||
fn hash_expand(span: Span, tt: &ast::Adt, tm: SpanMapRef<'_>) -> ExpandResult<tt::Subtree> {
|
||||
fn hash_expand(span: Span, tt: &tt::Subtree) -> ExpandResult<tt::Subtree> {
|
||||
let krate = &dollar_crate(span);
|
||||
expand_simple_derive(span, tt, tm, quote! {span => #krate::hash::Hash }, |adt| {
|
||||
expand_simple_derive(span, tt, quote! {span => #krate::hash::Hash }, |adt| {
|
||||
if matches!(adt.shape, AdtShape::Union) {
|
||||
// FIXME: Return expand error here
|
||||
return quote! {span =>};
|
||||
@@ -626,14 +631,14 @@ fn hash<H: #krate::hash::Hasher>(&self, ra_expand_state: &mut H) {
|
||||
})
|
||||
}
|
||||
|
||||
fn eq_expand(span: Span, tt: &ast::Adt, tm: SpanMapRef<'_>) -> ExpandResult<tt::Subtree> {
|
||||
fn eq_expand(span: Span, tt: &tt::Subtree) -> ExpandResult<tt::Subtree> {
|
||||
let krate = dollar_crate(span);
|
||||
expand_simple_derive(span, tt, tm, quote! {span => #krate::cmp::Eq }, |_| quote! {span =>})
|
||||
expand_simple_derive(span, tt, quote! {span => #krate::cmp::Eq }, |_| quote! {span =>})
|
||||
}
|
||||
|
||||
fn partial_eq_expand(span: Span, tt: &ast::Adt, tm: SpanMapRef<'_>) -> ExpandResult<tt::Subtree> {
|
||||
fn partial_eq_expand(span: Span, tt: &tt::Subtree) -> ExpandResult<tt::Subtree> {
|
||||
let krate = dollar_crate(span);
|
||||
expand_simple_derive(span, tt, tm, quote! {span => #krate::cmp::PartialEq }, |adt| {
|
||||
expand_simple_derive(span, tt, quote! {span => #krate::cmp::PartialEq }, |adt| {
|
||||
if matches!(adt.shape, AdtShape::Union) {
|
||||
// FIXME: Return expand error here
|
||||
return quote! {span =>};
|
||||
@@ -703,9 +708,9 @@ fn self_and_other_patterns(
|
||||
(self_patterns, other_patterns)
|
||||
}
|
||||
|
||||
fn ord_expand(span: Span, tt: &ast::Adt, tm: SpanMapRef<'_>) -> ExpandResult<tt::Subtree> {
|
||||
fn ord_expand(span: Span, tt: &tt::Subtree) -> ExpandResult<tt::Subtree> {
|
||||
let krate = &dollar_crate(span);
|
||||
expand_simple_derive(span, tt, tm, quote! {span => #krate::cmp::Ord }, |adt| {
|
||||
expand_simple_derive(span, tt, quote! {span => #krate::cmp::Ord }, |adt| {
|
||||
fn compare(
|
||||
krate: &tt::Ident,
|
||||
left: tt::Subtree,
|
||||
@@ -761,9 +766,9 @@ fn cmp(&self, other: &Self) -> #krate::cmp::Ordering {
|
||||
})
|
||||
}
|
||||
|
||||
fn partial_ord_expand(span: Span, tt: &ast::Adt, tm: SpanMapRef<'_>) -> ExpandResult<tt::Subtree> {
|
||||
fn partial_ord_expand(span: Span, tt: &tt::Subtree) -> ExpandResult<tt::Subtree> {
|
||||
let krate = &dollar_crate(span);
|
||||
expand_simple_derive(span, tt, tm, quote! {span => #krate::cmp::PartialOrd }, |adt| {
|
||||
expand_simple_derive(span, tt, quote! {span => #krate::cmp::PartialOrd }, |adt| {
|
||||
fn compare(
|
||||
krate: &tt::Ident,
|
||||
left: tt::Subtree,
|
||||
|
||||
@@ -31,36 +31,18 @@ pub enum EagerExpander {
|
||||
}
|
||||
|
||||
impl BuiltinFnLikeExpander {
|
||||
pub fn expand(
|
||||
&self,
|
||||
db: &dyn ExpandDatabase,
|
||||
id: MacroCallId,
|
||||
tt: &tt::Subtree,
|
||||
) -> ExpandResult<tt::Subtree> {
|
||||
let expander = match *self {
|
||||
pub fn expander(&self) -> fn (&dyn ExpandDatabase, MacroCallId, &tt::Subtree, Span) -> ExpandResult<tt::Subtree> {
|
||||
match *self {
|
||||
$( BuiltinFnLikeExpander::$kind => $expand, )*
|
||||
};
|
||||
|
||||
let span = db.lookup_intern_macro_call(id).call_site;
|
||||
let span = span_with_def_site_ctxt(db, span, id);
|
||||
expander(db, id, tt, span)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl EagerExpander {
|
||||
pub fn expand(
|
||||
&self,
|
||||
db: &dyn ExpandDatabase,
|
||||
id: MacroCallId,
|
||||
tt: &tt::Subtree,
|
||||
) -> ExpandResult<tt::Subtree> {
|
||||
let expander = match *self {
|
||||
pub fn expander(&self) -> fn (&dyn ExpandDatabase, MacroCallId, &tt::Subtree, Span) -> ExpandResult<tt::Subtree> {
|
||||
match *self {
|
||||
$( EagerExpander::$e_kind => $e_expand, )*
|
||||
};
|
||||
|
||||
let span = db.lookup_intern_macro_call(id).call_site;
|
||||
let span = span_with_def_site_ctxt(db, span, id);
|
||||
expander(db, id, tt, span)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,7 +56,31 @@ fn find_by_name(ident: &name::Name) -> Option<Either<BuiltinFnLikeExpander, Eage
|
||||
};
|
||||
}
|
||||
|
||||
impl BuiltinFnLikeExpander {
|
||||
pub fn expand(
|
||||
&self,
|
||||
db: &dyn ExpandDatabase,
|
||||
id: MacroCallId,
|
||||
tt: &tt::Subtree,
|
||||
) -> ExpandResult<tt::Subtree> {
|
||||
let span = db.lookup_intern_macro_call(id).call_site;
|
||||
let span = span_with_def_site_ctxt(db, span, id);
|
||||
self.expander()(db, id, tt, span)
|
||||
}
|
||||
}
|
||||
|
||||
impl EagerExpander {
|
||||
pub fn expand(
|
||||
&self,
|
||||
db: &dyn ExpandDatabase,
|
||||
id: MacroCallId,
|
||||
tt: &tt::Subtree,
|
||||
) -> ExpandResult<tt::Subtree> {
|
||||
let span = db.lookup_intern_macro_call(id).call_site;
|
||||
let span = span_with_def_site_ctxt(db, span, id);
|
||||
self.expander()(db, id, tt, span)
|
||||
}
|
||||
|
||||
pub fn is_include(&self) -> bool {
|
||||
matches!(self, EagerExpander::Include)
|
||||
}
|
||||
|
||||
@@ -11,14 +11,14 @@
|
||||
use crate::{db::ExpandDatabase, proc_macro::ProcMacros};
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct Change {
|
||||
pub struct ChangeWithProcMacros {
|
||||
pub source_change: FileChange,
|
||||
pub proc_macros: Option<ProcMacros>,
|
||||
pub toolchains: Option<Vec<Option<Version>>>,
|
||||
pub target_data_layouts: Option<Vec<TargetLayoutLoadResult>>,
|
||||
}
|
||||
|
||||
impl Change {
|
||||
impl ChangeWithProcMacros {
|
||||
pub fn new() -> Self {
|
||||
Self::default()
|
||||
}
|
||||
|
||||
@@ -215,11 +215,6 @@ pub fn expand_speculative(
|
||||
MacroDefKind::BuiltInAttr(BuiltinAttrExpander::Derive, _) => {
|
||||
pseudo_derive_attr_expansion(&tt, attr_arg.as_ref()?, loc.call_site)
|
||||
}
|
||||
MacroDefKind::BuiltInDerive(expander, ..) => {
|
||||
// this cast is a bit sus, can we avoid losing the typedness here?
|
||||
let adt = ast::Adt::cast(speculative_args.clone()).unwrap();
|
||||
expander.expand(db, actual_macro_call, &adt, span_map)
|
||||
}
|
||||
MacroDefKind::Declarative(it) => db.decl_macro_expander(loc.krate, it).expand_unhygienic(
|
||||
db,
|
||||
tt,
|
||||
@@ -227,6 +222,9 @@ pub fn expand_speculative(
|
||||
loc.call_site,
|
||||
),
|
||||
MacroDefKind::BuiltIn(it, _) => it.expand(db, actual_macro_call, &tt).map_err(Into::into),
|
||||
MacroDefKind::BuiltInDerive(it, ..) => {
|
||||
it.expand(db, actual_macro_call, &tt).map_err(Into::into)
|
||||
}
|
||||
MacroDefKind::BuiltInEager(it, _) => {
|
||||
it.expand(db, actual_macro_call, &tt).map_err(Into::into)
|
||||
}
|
||||
@@ -303,7 +301,7 @@ fn parse_macro_expansion_error(
|
||||
macro_call_id: MacroCallId,
|
||||
) -> ExpandResult<Box<[SyntaxError]>> {
|
||||
db.parse_macro_expansion(MacroFileId { macro_call_id })
|
||||
.map(|it| it.0.errors().to_vec().into_boxed_slice())
|
||||
.map(|it| it.0.errors().into_boxed_slice())
|
||||
}
|
||||
|
||||
pub(crate) fn parse_with_map(
|
||||
@@ -321,6 +319,7 @@ pub(crate) fn parse_with_map(
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: for derive attributes, this will return separate copies of the same structures!
|
||||
fn macro_arg(
|
||||
db: &dyn ExpandDatabase,
|
||||
id: MacroCallId,
|
||||
@@ -445,7 +444,7 @@ fn macro_arg(
|
||||
|
||||
if matches!(loc.def.kind, MacroDefKind::BuiltInEager(..)) {
|
||||
match parse.errors() {
|
||||
[] => ValueResult::ok((Arc::new(tt), undo_info)),
|
||||
errors if errors.is_empty() => ValueResult::ok((Arc::new(tt), undo_info)),
|
||||
errors => ValueResult::new(
|
||||
(Arc::new(tt), undo_info),
|
||||
// Box::<[_]>::from(res.errors()), not stable yet
|
||||
@@ -526,16 +525,6 @@ fn macro_expand(
|
||||
|
||||
let ExpandResult { value: tt, mut err } = match loc.def.kind {
|
||||
MacroDefKind::ProcMacro(..) => return db.expand_proc_macro(macro_call_id).map(CowArc::Arc),
|
||||
MacroDefKind::BuiltInDerive(expander, ..) => {
|
||||
let (root, map) = parse_with_map(db, loc.kind.file_id());
|
||||
let root = root.syntax_node();
|
||||
let MacroCallKind::Derive { ast_id, .. } = loc.kind else { unreachable!() };
|
||||
let node = ast_id.to_ptr(db).to_node(&root);
|
||||
|
||||
// FIXME: Use censoring
|
||||
let _censor = censor_for_macro_input(&loc, node.syntax());
|
||||
expander.expand(db, macro_call_id, &node, map.as_ref())
|
||||
}
|
||||
_ => {
|
||||
let ValueResult { value: (macro_arg, undo_info), err } = db.macro_arg(macro_call_id);
|
||||
let format_parse_err = |err: Arc<Box<[SyntaxError]>>| {
|
||||
@@ -569,6 +558,9 @@ fn macro_expand(
|
||||
err: err.map(format_parse_err),
|
||||
};
|
||||
}
|
||||
MacroDefKind::BuiltInDerive(it, _) => {
|
||||
it.expand(db, macro_call_id, arg).map_err(Into::into)
|
||||
}
|
||||
MacroDefKind::BuiltInEager(it, _) => {
|
||||
it.expand(db, macro_call_id, arg).map_err(Into::into)
|
||||
}
|
||||
|
||||
@@ -27,7 +27,6 @@
|
||||
ast::{self, AstNode},
|
||||
db::ExpandDatabase,
|
||||
mod_path::ModPath,
|
||||
span_map::SpanMapRef,
|
||||
EagerCallInfo, ExpandError, ExpandResult, ExpandTo, ExpansionSpanMap, InFile, Intern,
|
||||
MacroCallId, MacroCallKind, MacroCallLoc, MacroDefId, MacroDefKind,
|
||||
};
|
||||
@@ -155,10 +154,9 @@ fn eager_macro_recur(
|
||||
}
|
||||
};
|
||||
|
||||
let def = match call
|
||||
.path()
|
||||
.and_then(|path| ModPath::from_src(db, path, SpanMapRef::ExpansionSpanMap(span_map)))
|
||||
{
|
||||
let def = match call.path().and_then(|path| {
|
||||
ModPath::from_src(db, path, &mut |range| span_map.span_at(range.start()).ctx)
|
||||
}) {
|
||||
Some(path) => match macro_resolver(path.clone()) {
|
||||
Some(def) => def,
|
||||
None => {
|
||||
|
||||
@@ -252,7 +252,7 @@ pub fn original_syntax_node(
|
||||
map_node_range_up(db, &db.expansion_span_map(file_id), self.value.text_range())?;
|
||||
|
||||
// FIXME: Figure out an API that makes proper use of ctx, this only exists to
|
||||
// keep pre-token map rewrite behaviour.
|
||||
// keep pre-token map rewrite behavior.
|
||||
if !ctx.is_root() {
|
||||
return None;
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
db::ExpandDatabase,
|
||||
hygiene::{marks_rev, SyntaxContextExt, Transparency},
|
||||
name::{known, AsName, Name},
|
||||
span_map::SpanMapRef,
|
||||
tt,
|
||||
};
|
||||
use base_db::CrateId;
|
||||
@@ -49,9 +48,9 @@ impl ModPath {
|
||||
pub fn from_src(
|
||||
db: &dyn ExpandDatabase,
|
||||
path: ast::Path,
|
||||
span_map: SpanMapRef<'_>,
|
||||
span_for_range: &mut dyn FnMut(::tt::TextRange) -> SyntaxContextId,
|
||||
) -> Option<ModPath> {
|
||||
convert_path(db, path, span_map)
|
||||
convert_path(db, path, span_for_range)
|
||||
}
|
||||
|
||||
pub fn from_tt(db: &dyn ExpandDatabase, tt: &[tt::TokenTree]) -> Option<ModPath> {
|
||||
@@ -144,6 +143,12 @@ pub fn display<'a>(&'a self, db: &'a dyn crate::db::ExpandDatabase) -> impl fmt:
|
||||
}
|
||||
}
|
||||
|
||||
impl Extend<Name> for ModPath {
|
||||
fn extend<T: IntoIterator<Item = Name>>(&mut self, iter: T) {
|
||||
self.segments.extend(iter);
|
||||
}
|
||||
}
|
||||
|
||||
struct Display<'a> {
|
||||
db: &'a dyn ExpandDatabase,
|
||||
path: &'a ModPath,
|
||||
@@ -215,7 +220,7 @@ fn display_fmt_path(
|
||||
fn convert_path(
|
||||
db: &dyn ExpandDatabase,
|
||||
path: ast::Path,
|
||||
span_map: SpanMapRef<'_>,
|
||||
span_for_range: &mut dyn FnMut(::tt::TextRange) -> SyntaxContextId,
|
||||
) -> Option<ModPath> {
|
||||
let mut segments = path.segments();
|
||||
|
||||
@@ -224,12 +229,9 @@ fn convert_path(
|
||||
ast::PathSegmentKind::Name(name_ref) => {
|
||||
if name_ref.text() == "$crate" {
|
||||
ModPath::from_kind(
|
||||
resolve_crate_root(
|
||||
db,
|
||||
span_map.span_for_range(name_ref.syntax().text_range()).ctx,
|
||||
)
|
||||
.map(PathKind::DollarCrate)
|
||||
.unwrap_or(PathKind::Crate),
|
||||
resolve_crate_root(db, span_for_range(name_ref.syntax().text_range()))
|
||||
.map(PathKind::DollarCrate)
|
||||
.unwrap_or(PathKind::Crate),
|
||||
)
|
||||
} else {
|
||||
let mut res = ModPath::from_kind(
|
||||
@@ -283,7 +285,7 @@ fn convert_path(
|
||||
// We follow what it did anyway :)
|
||||
if mod_path.segments.len() == 1 && mod_path.kind == PathKind::Plain {
|
||||
if let Some(_macro_call) = path.syntax().parent().and_then(ast::MacroCall::cast) {
|
||||
let syn_ctx = span_map.span_for_range(segment.syntax().text_range()).ctx;
|
||||
let syn_ctx = span_for_range(segment.syntax().text_range());
|
||||
if let Some(macro_call_id) = db.lookup_intern_syntax_context(syn_ctx).outer_expn {
|
||||
if db.lookup_intern_macro_call(macro_call_id).def.local_inner {
|
||||
mod_path.kind = match resolve_crate_root(db, syn_ctx) {
|
||||
|
||||
@@ -111,15 +111,11 @@ pub fn is_missing(&self) -> bool {
|
||||
self == &Name::missing()
|
||||
}
|
||||
|
||||
/// Generates a new name which is only equal to itself, by incrementing a counter. Due
|
||||
/// its implementation, it should not be used in things that salsa considers, like
|
||||
/// type names or field names, and it should be only used in names of local variables
|
||||
/// and labels and similar things.
|
||||
pub fn generate_new_name() -> Name {
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
static CNT: AtomicUsize = AtomicUsize::new(0);
|
||||
let c = CNT.fetch_add(1, Ordering::Relaxed);
|
||||
Name::new_text(format_smolstr!("<ra@gennew>{c}"))
|
||||
/// Generates a new name that attempts to be unique. Should only be used when body lowering and
|
||||
/// creating desugared locals and labels. The caller is responsible for picking an index
|
||||
/// that is stable across re-executions
|
||||
pub fn generate_new_name(idx: usize) -> Name {
|
||||
Name::new_text(format_smolstr!("<ra@gennew>{idx}"))
|
||||
}
|
||||
|
||||
/// Returns the tuple index this name represents if it is a tuple field.
|
||||
|
||||
@@ -31,11 +31,13 @@ fn span_for(&self, range: TextRange) -> Span {
|
||||
self.span_for_range(range)
|
||||
}
|
||||
}
|
||||
|
||||
impl mbe::SpanMapper<Span> for SpanMapRef<'_> {
|
||||
fn span_for(&self, range: TextRange) -> Span {
|
||||
self.span_for_range(range)
|
||||
}
|
||||
}
|
||||
|
||||
impl SpanMap {
|
||||
pub fn span_for_range(&self, range: TextRange) -> Span {
|
||||
match self {
|
||||
|
||||
@@ -45,7 +45,6 @@ intern.workspace = true
|
||||
hir-def.workspace = true
|
||||
hir-expand.workspace = true
|
||||
base-db.workspace = true
|
||||
profile.workspace = true
|
||||
syntax.workspace = true
|
||||
limit.workspace = true
|
||||
|
||||
|
||||
@@ -31,12 +31,8 @@
|
||||
|
||||
#[salsa::query_group(HirDatabaseStorage)]
|
||||
pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
|
||||
#[salsa::invoke(infer_wait)]
|
||||
#[salsa::transparent]
|
||||
fn infer(&self, def: DefWithBodyId) -> Arc<InferenceResult>;
|
||||
|
||||
#[salsa::invoke(crate::infer::infer_query)]
|
||||
fn infer_query(&self, def: DefWithBodyId) -> Arc<InferenceResult>;
|
||||
fn infer(&self, def: DefWithBodyId) -> Arc<InferenceResult>;
|
||||
|
||||
// region:mir
|
||||
|
||||
@@ -258,17 +254,8 @@ fn normalize_projection(
|
||||
env: Arc<TraitEnvironment>,
|
||||
) -> Ty;
|
||||
|
||||
#[salsa::invoke(trait_solve_wait)]
|
||||
#[salsa::transparent]
|
||||
fn trait_solve(
|
||||
&self,
|
||||
krate: CrateId,
|
||||
block: Option<BlockId>,
|
||||
goal: crate::Canonical<crate::InEnvironment<crate::Goal>>,
|
||||
) -> Option<crate::Solution>;
|
||||
|
||||
#[salsa::invoke(crate::traits::trait_solve_query)]
|
||||
fn trait_solve_query(
|
||||
fn trait_solve(
|
||||
&self,
|
||||
krate: CrateId,
|
||||
block: Option<BlockId>,
|
||||
@@ -284,38 +271,6 @@ fn program_clauses_for_chalk_env(
|
||||
) -> chalk_ir::ProgramClauses<Interner>;
|
||||
}
|
||||
|
||||
fn infer_wait(db: &dyn HirDatabase, def: DefWithBodyId) -> Arc<InferenceResult> {
|
||||
let detail = match def {
|
||||
DefWithBodyId::FunctionId(it) => db.function_data(it).name.display(db.upcast()).to_string(),
|
||||
DefWithBodyId::StaticId(it) => {
|
||||
db.static_data(it).name.clone().display(db.upcast()).to_string()
|
||||
}
|
||||
DefWithBodyId::ConstId(it) => db
|
||||
.const_data(it)
|
||||
.name
|
||||
.clone()
|
||||
.unwrap_or_else(Name::missing)
|
||||
.display(db.upcast())
|
||||
.to_string(),
|
||||
DefWithBodyId::VariantId(it) => {
|
||||
db.enum_variant_data(it).name.display(db.upcast()).to_string()
|
||||
}
|
||||
DefWithBodyId::InTypeConstId(it) => format!("in type const {it:?}"),
|
||||
};
|
||||
let _p = tracing::span!(tracing::Level::INFO, "infer:wait", ?detail).entered();
|
||||
db.infer_query(def)
|
||||
}
|
||||
|
||||
fn trait_solve_wait(
|
||||
db: &dyn HirDatabase,
|
||||
krate: CrateId,
|
||||
block: Option<BlockId>,
|
||||
goal: crate::Canonical<crate::InEnvironment<crate::Goal>>,
|
||||
) -> Option<crate::Solution> {
|
||||
let _p = tracing::span!(tracing::Level::INFO, "trait_solve::wait").entered();
|
||||
db.trait_solve_query(krate, block, goal)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hir_database_is_object_safe() {
|
||||
fn _assert_object_safe(_: &dyn HirDatabase) {}
|
||||
|
||||
@@ -60,12 +60,17 @@ pub enum BodyValidationDiagnostic {
|
||||
}
|
||||
|
||||
impl BodyValidationDiagnostic {
|
||||
pub fn collect(db: &dyn HirDatabase, owner: DefWithBodyId) -> Vec<BodyValidationDiagnostic> {
|
||||
pub fn collect(
|
||||
db: &dyn HirDatabase,
|
||||
owner: DefWithBodyId,
|
||||
validate_lints: bool,
|
||||
) -> Vec<BodyValidationDiagnostic> {
|
||||
let _p =
|
||||
tracing::span!(tracing::Level::INFO, "BodyValidationDiagnostic::collect").entered();
|
||||
let infer = db.infer(owner);
|
||||
let body = db.body(owner);
|
||||
let mut validator = ExprValidator { owner, body, infer, diagnostics: Vec::new() };
|
||||
let mut validator =
|
||||
ExprValidator { owner, body, infer, diagnostics: Vec::new(), validate_lints };
|
||||
validator.validate_body(db);
|
||||
validator.diagnostics
|
||||
}
|
||||
@@ -76,6 +81,7 @@ struct ExprValidator {
|
||||
body: Arc<Body>,
|
||||
infer: Arc<InferenceResult>,
|
||||
diagnostics: Vec<BodyValidationDiagnostic>,
|
||||
validate_lints: bool,
|
||||
}
|
||||
|
||||
impl ExprValidator {
|
||||
@@ -139,6 +145,9 @@ fn validate_call(
|
||||
expr: &Expr,
|
||||
filter_map_next_checker: &mut Option<FilterMapNextChecker>,
|
||||
) {
|
||||
if !self.validate_lints {
|
||||
return;
|
||||
}
|
||||
// Check that the number of arguments matches the number of parameters.
|
||||
|
||||
if self.infer.expr_type_mismatches().next().is_some() {
|
||||
@@ -173,7 +182,7 @@ fn validate_match(
|
||||
db: &dyn HirDatabase,
|
||||
) {
|
||||
let scrut_ty = &self.infer[scrutinee_expr];
|
||||
if scrut_ty.is_unknown() {
|
||||
if scrut_ty.contains_unknown() {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -230,6 +239,7 @@ fn validate_match(
|
||||
m_arms.as_slice(),
|
||||
scrut_ty.clone(),
|
||||
ValidityConstraint::ValidOnly,
|
||||
None,
|
||||
) {
|
||||
Ok(report) => report,
|
||||
Err(()) => return,
|
||||
@@ -257,6 +267,9 @@ fn validate_block(&mut self, db: &dyn HirDatabase, expr: &Expr) {
|
||||
};
|
||||
let Some(initializer) = initializer else { continue };
|
||||
let ty = &self.infer[initializer];
|
||||
if ty.contains_unknown() {
|
||||
continue;
|
||||
}
|
||||
|
||||
let mut have_errors = false;
|
||||
let deconstructed_pat = self.lower_pattern(&cx, pat, db, &mut have_errors);
|
||||
@@ -274,6 +287,7 @@ fn validate_block(&mut self, db: &dyn HirDatabase, expr: &Expr) {
|
||||
&[match_arm],
|
||||
ty.clone(),
|
||||
ValidityConstraint::ValidOnly,
|
||||
None,
|
||||
) {
|
||||
Ok(v) => v,
|
||||
Err(e) => {
|
||||
@@ -308,6 +322,9 @@ fn lower_pattern<'p>(
|
||||
}
|
||||
|
||||
fn check_for_trailing_return(&mut self, body_expr: ExprId, body: &Body) {
|
||||
if !self.validate_lints {
|
||||
return;
|
||||
}
|
||||
match &body.exprs[body_expr] {
|
||||
Expr::Block { statements, tail, .. } => {
|
||||
let last_stmt = tail.or_else(|| match statements.last()? {
|
||||
@@ -340,6 +357,9 @@ fn check_for_trailing_return(&mut self, body_expr: ExprId, body: &Body) {
|
||||
}
|
||||
|
||||
fn check_for_unnecessary_else(&mut self, id: ExprId, expr: &Expr, db: &dyn HirDatabase) {
|
||||
if !self.validate_lints {
|
||||
return;
|
||||
}
|
||||
if let Expr::If { condition: _, then_branch, else_branch } = expr {
|
||||
if else_branch.is_none() {
|
||||
return;
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
use rustc_pattern_analysis::{
|
||||
constructor::{Constructor, ConstructorSet, VariantVisibility},
|
||||
index::IdxContainer,
|
||||
Captures, TypeCx,
|
||||
Captures, PrivateUninhabitedField, TypeCx,
|
||||
};
|
||||
use smallvec::{smallvec, SmallVec};
|
||||
use stdx::never;
|
||||
@@ -88,39 +88,21 @@ fn variant_id_for_adt(ctor: &Constructor<Self>, adt: hir_def::AdtId) -> Option<V
|
||||
}
|
||||
}
|
||||
|
||||
// In the cases of either a `#[non_exhaustive]` field list or a non-public field, we hide
|
||||
// uninhabited fields in order not to reveal the uninhabitedness of the whole variant.
|
||||
// This lists the fields we keep along with their types.
|
||||
fn list_variant_nonhidden_fields<'a>(
|
||||
// This lists the fields of a variant along with their types.
|
||||
fn list_variant_fields<'a>(
|
||||
&'a self,
|
||||
ty: &'a Ty,
|
||||
variant: VariantId,
|
||||
) -> impl Iterator<Item = (LocalFieldId, Ty)> + Captures<'a> + Captures<'p> {
|
||||
let cx = self;
|
||||
let (adt, substs) = ty.as_adt().unwrap();
|
||||
let (_, substs) = ty.as_adt().unwrap();
|
||||
|
||||
let adt_is_local = variant.module(cx.db.upcast()).krate() == cx.module.krate();
|
||||
let field_tys = self.db.field_types(variant);
|
||||
let fields_len = variant.variant_data(self.db.upcast()).fields().len() as u32;
|
||||
|
||||
// Whether we must not match the fields of this variant exhaustively.
|
||||
let is_non_exhaustive =
|
||||
cx.db.attrs(variant.into()).by_key("non_exhaustive").exists() && !adt_is_local;
|
||||
|
||||
let visibility = cx.db.field_visibilities(variant);
|
||||
let field_ty = cx.db.field_types(variant);
|
||||
let fields_len = variant.variant_data(cx.db.upcast()).fields().len() as u32;
|
||||
|
||||
(0..fields_len).map(|idx| LocalFieldId::from_raw(idx.into())).filter_map(move |fid| {
|
||||
let ty = field_ty[fid].clone().substitute(Interner, substs);
|
||||
let ty = normalize(cx.db, cx.db.trait_environment_for_body(cx.body), ty);
|
||||
let is_visible = matches!(adt, hir_def::AdtId::EnumId(..))
|
||||
|| visibility[fid].is_visible_from(cx.db.upcast(), cx.module);
|
||||
let is_uninhabited = cx.is_uninhabited(&ty);
|
||||
|
||||
if is_uninhabited && (!is_visible || is_non_exhaustive) {
|
||||
None
|
||||
} else {
|
||||
Some((fid, ty))
|
||||
}
|
||||
(0..fields_len).map(|idx| LocalFieldId::from_raw(idx.into())).map(move |fid| {
|
||||
let ty = field_tys[fid].clone().substitute(Interner, substs);
|
||||
let ty = normalize(self.db, self.db.trait_environment_for_body(self.body), ty);
|
||||
(fid, ty)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -199,23 +181,16 @@ pub(crate) fn lower_pat(&self, pat: &Pat) -> DeconstructedPat<'p> {
|
||||
}
|
||||
};
|
||||
let variant = Self::variant_id_for_adt(&ctor, adt.0).unwrap();
|
||||
let fields_len = variant.variant_data(self.db.upcast()).fields().len();
|
||||
// For each field in the variant, we store the relevant index into `self.fields` if any.
|
||||
let mut field_id_to_id: Vec<Option<usize>> = vec![None; fields_len];
|
||||
let tys = self
|
||||
.list_variant_nonhidden_fields(&pat.ty, variant)
|
||||
.enumerate()
|
||||
.map(|(i, (fid, ty))| {
|
||||
let field_idx: u32 = fid.into_raw().into();
|
||||
field_id_to_id[field_idx as usize] = Some(i);
|
||||
ty
|
||||
});
|
||||
let mut wilds: Vec<_> = tys.map(DeconstructedPat::wildcard).collect();
|
||||
// Fill a vec with wildcards, then place the fields we have at the right
|
||||
// index.
|
||||
let mut wilds: Vec<_> = self
|
||||
.list_variant_fields(&pat.ty, variant)
|
||||
.map(|(_, ty)| ty)
|
||||
.map(DeconstructedPat::wildcard)
|
||||
.collect();
|
||||
for pat in subpatterns {
|
||||
let field_idx: u32 = pat.field.into_raw().into();
|
||||
if let Some(i) = field_id_to_id[field_idx as usize] {
|
||||
wilds[i] = self.lower_pat(&pat.pattern);
|
||||
}
|
||||
let field_id: u32 = pat.field.into_raw().into();
|
||||
wilds[field_id as usize] = self.lower_pat(&pat.pattern);
|
||||
}
|
||||
fields = wilds;
|
||||
}
|
||||
@@ -263,7 +238,7 @@ pub(crate) fn hoist_witness_pat(&self, pat: &WitnessPat<'p>) -> Pat {
|
||||
TyKind::Adt(adt, substs) => {
|
||||
let variant = Self::variant_id_for_adt(pat.ctor(), adt.0).unwrap();
|
||||
let subpatterns = self
|
||||
.list_variant_nonhidden_fields(pat.ty(), variant)
|
||||
.list_variant_fields(pat.ty(), variant)
|
||||
.zip(subpatterns)
|
||||
.map(|((field, _ty), pattern)| FieldPat { field, pattern })
|
||||
.collect();
|
||||
@@ -286,7 +261,7 @@ pub(crate) fn hoist_witness_pat(&self, pat: &WitnessPat<'p>) -> Pat {
|
||||
Ref => PatKind::Deref { subpattern: subpatterns.next().unwrap() },
|
||||
Slice(_) => unimplemented!(),
|
||||
&Str(void) => match void {},
|
||||
Wildcard | NonExhaustive | Hidden => PatKind::Wild,
|
||||
Wildcard | NonExhaustive | Hidden | PrivateUninhabited => PatKind::Wild,
|
||||
Missing | F32Range(..) | F64Range(..) | Opaque(..) | Or => {
|
||||
never!("can't convert to pattern: {:?}", pat.ctor());
|
||||
PatKind::Wild
|
||||
@@ -326,7 +301,7 @@ fn ctor_arity(
|
||||
1
|
||||
} else {
|
||||
let variant = Self::variant_id_for_adt(ctor, adt).unwrap();
|
||||
self.list_variant_nonhidden_fields(ty, variant).count()
|
||||
variant.variant_data(self.db.upcast()).fields().len()
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
@@ -337,7 +312,7 @@ fn ctor_arity(
|
||||
Ref => 1,
|
||||
Slice(..) => unimplemented!(),
|
||||
Bool(..) | IntRange(..) | F32Range(..) | F64Range(..) | Str(..) | Opaque(..)
|
||||
| NonExhaustive | Hidden | Missing | Wildcard => 0,
|
||||
| NonExhaustive | PrivateUninhabited | Hidden | Missing | Wildcard => 0,
|
||||
Or => {
|
||||
never!("The `Or` constructor doesn't have a fixed arity");
|
||||
0
|
||||
@@ -349,13 +324,13 @@ fn ctor_sub_tys<'a>(
|
||||
&'a self,
|
||||
ctor: &'a rustc_pattern_analysis::constructor::Constructor<Self>,
|
||||
ty: &'a Self::Ty,
|
||||
) -> impl ExactSizeIterator<Item = Self::Ty> + Captures<'a> {
|
||||
let single = |ty| smallvec![ty];
|
||||
) -> impl ExactSizeIterator<Item = (Self::Ty, PrivateUninhabitedField)> + Captures<'a> {
|
||||
let single = |ty| smallvec![(ty, PrivateUninhabitedField(false))];
|
||||
let tys: SmallVec<[_; 2]> = match ctor {
|
||||
Struct | Variant(_) | UnionField => match ty.kind(Interner) {
|
||||
TyKind::Tuple(_, substs) => {
|
||||
let tys = substs.iter(Interner).map(|ty| ty.assert_ty_ref(Interner));
|
||||
tys.cloned().collect()
|
||||
tys.cloned().map(|ty| (ty, PrivateUninhabitedField(false))).collect()
|
||||
}
|
||||
TyKind::Ref(.., rty) => single(rty.clone()),
|
||||
&TyKind::Adt(AdtId(adt), ref substs) => {
|
||||
@@ -366,7 +341,27 @@ fn ctor_sub_tys<'a>(
|
||||
single(subst_ty)
|
||||
} else {
|
||||
let variant = Self::variant_id_for_adt(ctor, adt).unwrap();
|
||||
self.list_variant_nonhidden_fields(ty, variant).map(|(_, ty)| ty).collect()
|
||||
let (adt, _) = ty.as_adt().unwrap();
|
||||
|
||||
let adt_is_local =
|
||||
variant.module(self.db.upcast()).krate() == self.module.krate();
|
||||
// Whether we must not match the fields of this variant exhaustively.
|
||||
let is_non_exhaustive =
|
||||
self.db.attrs(variant.into()).by_key("non_exhaustive").exists()
|
||||
&& !adt_is_local;
|
||||
let visibilities = self.db.field_visibilities(variant);
|
||||
|
||||
self.list_variant_fields(ty, variant)
|
||||
.map(move |(fid, ty)| {
|
||||
let is_visible = matches!(adt, hir_def::AdtId::EnumId(..))
|
||||
|| visibilities[fid]
|
||||
.is_visible_from(self.db.upcast(), self.module);
|
||||
let is_uninhabited = self.is_uninhabited(&ty);
|
||||
let private_uninhabited =
|
||||
is_uninhabited && (!is_visible || is_non_exhaustive);
|
||||
(ty, PrivateUninhabitedField(private_uninhabited))
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
ty_kind => {
|
||||
@@ -383,7 +378,7 @@ fn ctor_sub_tys<'a>(
|
||||
},
|
||||
Slice(_) => unreachable!("Found a `Slice` constructor in match checking"),
|
||||
Bool(..) | IntRange(..) | F32Range(..) | F64Range(..) | Str(..) | Opaque(..)
|
||||
| NonExhaustive | Hidden | Missing | Wildcard => smallvec![],
|
||||
| NonExhaustive | PrivateUninhabited | Hidden | Missing | Wildcard => smallvec![],
|
||||
Or => {
|
||||
never!("called `Fields::wildcards` on an `Or` ctor");
|
||||
smallvec![]
|
||||
@@ -478,6 +473,11 @@ fn write_variant_name(
|
||||
fn bug(&self, fmt: fmt::Arguments<'_>) {
|
||||
debug!("{}", fmt)
|
||||
}
|
||||
|
||||
fn complexity_exceeded(&self) -> Result<(), Self::Error> {
|
||||
// FIXME(Nadrieril): make use of the complexity counter.
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'p> fmt::Debug for MatchCheckCtx<'p> {
|
||||
|
||||
@@ -63,6 +63,7 @@ pub struct HirFormatter<'a> {
|
||||
buf: String,
|
||||
curr_size: usize,
|
||||
pub(crate) max_size: Option<usize>,
|
||||
pub entity_limit: Option<usize>,
|
||||
omit_verbose_types: bool,
|
||||
closure_style: ClosureStyle,
|
||||
display_target: DisplayTarget,
|
||||
@@ -86,6 +87,7 @@ fn into_displayable<'a>(
|
||||
&'a self,
|
||||
db: &'a dyn HirDatabase,
|
||||
max_size: Option<usize>,
|
||||
limited_size: Option<usize>,
|
||||
omit_verbose_types: bool,
|
||||
display_target: DisplayTarget,
|
||||
closure_style: ClosureStyle,
|
||||
@@ -101,6 +103,7 @@ fn into_displayable<'a>(
|
||||
db,
|
||||
t: self,
|
||||
max_size,
|
||||
limited_size,
|
||||
omit_verbose_types,
|
||||
display_target,
|
||||
closure_style,
|
||||
@@ -117,6 +120,7 @@ fn display<'a>(&'a self, db: &'a dyn HirDatabase) -> HirDisplayWrapper<'a, Self>
|
||||
db,
|
||||
t: self,
|
||||
max_size: None,
|
||||
limited_size: None,
|
||||
omit_verbose_types: false,
|
||||
closure_style: ClosureStyle::ImplFn,
|
||||
display_target: DisplayTarget::Diagnostics,
|
||||
@@ -137,6 +141,28 @@ fn display_truncated<'a>(
|
||||
db,
|
||||
t: self,
|
||||
max_size,
|
||||
limited_size: None,
|
||||
omit_verbose_types: true,
|
||||
closure_style: ClosureStyle::ImplFn,
|
||||
display_target: DisplayTarget::Diagnostics,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a `Display`able type that is human-readable and tries to limit the number of items inside.
|
||||
/// Use this for showing definitions which may contain too many items, like `trait`, `struct`, `enum`
|
||||
fn display_limited<'a>(
|
||||
&'a self,
|
||||
db: &'a dyn HirDatabase,
|
||||
limited_size: Option<usize>,
|
||||
) -> HirDisplayWrapper<'a, Self>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
HirDisplayWrapper {
|
||||
db,
|
||||
t: self,
|
||||
max_size: None,
|
||||
limited_size,
|
||||
omit_verbose_types: true,
|
||||
closure_style: ClosureStyle::ImplFn,
|
||||
display_target: DisplayTarget::Diagnostics,
|
||||
@@ -158,6 +184,7 @@ fn display_source_code<'a>(
|
||||
buf: String::with_capacity(20),
|
||||
curr_size: 0,
|
||||
max_size: None,
|
||||
entity_limit: None,
|
||||
omit_verbose_types: false,
|
||||
closure_style: ClosureStyle::ImplFn,
|
||||
display_target: DisplayTarget::SourceCode { module_id, allow_opaque },
|
||||
@@ -178,6 +205,7 @@ fn display_test<'a>(&'a self, db: &'a dyn HirDatabase) -> HirDisplayWrapper<'a,
|
||||
db,
|
||||
t: self,
|
||||
max_size: None,
|
||||
limited_size: None,
|
||||
omit_verbose_types: false,
|
||||
closure_style: ClosureStyle::ImplFn,
|
||||
display_target: DisplayTarget::Test,
|
||||
@@ -295,6 +323,7 @@ pub struct HirDisplayWrapper<'a, T> {
|
||||
db: &'a dyn HirDatabase,
|
||||
t: &'a T,
|
||||
max_size: Option<usize>,
|
||||
limited_size: Option<usize>,
|
||||
omit_verbose_types: bool,
|
||||
closure_style: ClosureStyle,
|
||||
display_target: DisplayTarget,
|
||||
@@ -323,6 +352,7 @@ pub fn write_to<F: HirWrite>(&self, f: &mut F) -> Result<(), HirDisplayError> {
|
||||
buf: String::with_capacity(20),
|
||||
curr_size: 0,
|
||||
max_size: self.max_size,
|
||||
entity_limit: self.limited_size,
|
||||
omit_verbose_types: self.omit_verbose_types,
|
||||
display_target: self.display_target,
|
||||
closure_style: self.closure_style,
|
||||
@@ -1751,10 +1781,7 @@ fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
|
||||
f.write_joined(bounds, " + ")?;
|
||||
}
|
||||
TypeRef::Macro(macro_call) => {
|
||||
let ctx = hir_def::lower::LowerCtx::with_span_map(
|
||||
f.db.upcast(),
|
||||
f.db.span_map(macro_call.file_id),
|
||||
);
|
||||
let ctx = hir_def::lower::LowerCtx::new(f.db.upcast(), macro_call.file_id);
|
||||
let macro_call = macro_call.to_node(f.db.upcast());
|
||||
match macro_call.path() {
|
||||
Some(path) => match Path::from_src(&ctx, path) {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
//! Compute the binary representation of a type
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::fmt;
|
||||
use std::{borrow::Cow, fmt};
|
||||
|
||||
use base_db::salsa::Cycle;
|
||||
use chalk_ir::{AdtId, FloatTy, IntTy, TyKind, UintTy};
|
||||
|
||||
@@ -995,12 +995,12 @@ pub(crate) fn lower_where_predicate(
|
||||
|
||||
pub(crate) fn lower_type_bound(
|
||||
&'a self,
|
||||
bound: &'a TypeBound,
|
||||
bound: &'a Interned<TypeBound>,
|
||||
self_ty: Ty,
|
||||
ignore_bindings: bool,
|
||||
) -> impl Iterator<Item = QuantifiedWhereClause> + 'a {
|
||||
let mut bindings = None;
|
||||
let trait_ref = match bound {
|
||||
let trait_ref = match bound.as_ref() {
|
||||
TypeBound::Path(path, TraitBoundModifier::None) => {
|
||||
bindings = self.lower_trait_ref_from_path(path, Some(self_ty));
|
||||
bindings
|
||||
@@ -1055,10 +1055,10 @@ pub(crate) fn lower_type_bound(
|
||||
|
||||
fn assoc_type_bindings_from_type_bound(
|
||||
&'a self,
|
||||
bound: &'a TypeBound,
|
||||
bound: &'a Interned<TypeBound>,
|
||||
trait_ref: TraitRef,
|
||||
) -> impl Iterator<Item = QuantifiedWhereClause> + 'a {
|
||||
let last_segment = match bound {
|
||||
let last_segment = match bound.as_ref() {
|
||||
TypeBound::Path(path, TraitBoundModifier::None) | TypeBound::ForLifetime(_, path) => {
|
||||
path.segments().last()
|
||||
}
|
||||
@@ -1121,7 +1121,63 @@ fn assoc_type_bindings_from_type_bound(
|
||||
);
|
||||
}
|
||||
} else {
|
||||
let ty = self.lower_ty(type_ref);
|
||||
let ty = 'ty: {
|
||||
if matches!(
|
||||
self.impl_trait_mode,
|
||||
ImplTraitLoweringState::Param(_)
|
||||
| ImplTraitLoweringState::Variable(_)
|
||||
) {
|
||||
// Find the generic index for the target of our `bound`
|
||||
let target_param_idx = self
|
||||
.resolver
|
||||
.where_predicates_in_scope()
|
||||
.find_map(|p| match p {
|
||||
WherePredicate::TypeBound {
|
||||
target: WherePredicateTypeTarget::TypeOrConstParam(idx),
|
||||
bound: b,
|
||||
} if b == bound => Some(idx),
|
||||
_ => None,
|
||||
});
|
||||
if let Some(target_param_idx) = target_param_idx {
|
||||
let mut counter = 0;
|
||||
for (idx, data) in self.generics().params.type_or_consts.iter()
|
||||
{
|
||||
// Count the number of `impl Trait` things that appear before
|
||||
// the target of our `bound`.
|
||||
// Our counter within `impl_trait_mode` should be that number
|
||||
// to properly lower each types within `type_ref`
|
||||
if data.type_param().is_some_and(|p| {
|
||||
p.provenance == TypeParamProvenance::ArgumentImplTrait
|
||||
}) {
|
||||
counter += 1;
|
||||
}
|
||||
if idx == *target_param_idx {
|
||||
break;
|
||||
}
|
||||
}
|
||||
let mut ext = TyLoweringContext::new_maybe_unowned(
|
||||
self.db,
|
||||
self.resolver,
|
||||
self.owner,
|
||||
)
|
||||
.with_type_param_mode(self.type_param_mode);
|
||||
match &self.impl_trait_mode {
|
||||
ImplTraitLoweringState::Param(_) => {
|
||||
ext.impl_trait_mode =
|
||||
ImplTraitLoweringState::Param(Cell::new(counter));
|
||||
}
|
||||
ImplTraitLoweringState::Variable(_) => {
|
||||
ext.impl_trait_mode = ImplTraitLoweringState::Variable(
|
||||
Cell::new(counter),
|
||||
);
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
break 'ty ext.lower_ty(type_ref);
|
||||
}
|
||||
}
|
||||
self.lower_ty(type_ref)
|
||||
};
|
||||
let alias_eq =
|
||||
AliasEq { alias: AliasTy::Projection(projection_ty.clone()), ty };
|
||||
predicates.push(crate::wrap_empty_binders(WhereClause::AliasEq(alias_eq)));
|
||||
@@ -1403,8 +1459,14 @@ pub(crate) fn generic_predicates_for_param_query(
|
||||
assoc_name: Option<Name>,
|
||||
) -> Arc<[Binders<QuantifiedWhereClause>]> {
|
||||
let resolver = def.resolver(db.upcast());
|
||||
let ctx = TyLoweringContext::new(db, &resolver, def.into())
|
||||
.with_type_param_mode(ParamLoweringMode::Variable);
|
||||
let ctx = if let GenericDefId::FunctionId(_) = def {
|
||||
TyLoweringContext::new(db, &resolver, def.into())
|
||||
.with_impl_trait_mode(ImplTraitLoweringMode::Variable)
|
||||
.with_type_param_mode(ParamLoweringMode::Variable)
|
||||
} else {
|
||||
TyLoweringContext::new(db, &resolver, def.into())
|
||||
.with_type_param_mode(ParamLoweringMode::Variable)
|
||||
};
|
||||
let generics = generics(db.upcast(), def);
|
||||
|
||||
// we have to filter out all other predicates *first*, before attempting to lower them
|
||||
@@ -1490,8 +1552,14 @@ pub(crate) fn trait_environment_query(
|
||||
def: GenericDefId,
|
||||
) -> Arc<TraitEnvironment> {
|
||||
let resolver = def.resolver(db.upcast());
|
||||
let ctx = TyLoweringContext::new(db, &resolver, def.into())
|
||||
.with_type_param_mode(ParamLoweringMode::Placeholder);
|
||||
let ctx = if let GenericDefId::FunctionId(_) = def {
|
||||
TyLoweringContext::new(db, &resolver, def.into())
|
||||
.with_impl_trait_mode(ImplTraitLoweringMode::Param)
|
||||
.with_type_param_mode(ParamLoweringMode::Placeholder)
|
||||
} else {
|
||||
TyLoweringContext::new(db, &resolver, def.into())
|
||||
.with_type_param_mode(ParamLoweringMode::Placeholder)
|
||||
};
|
||||
let mut traits_in_scope = Vec::new();
|
||||
let mut clauses = Vec::new();
|
||||
for pred in resolver.where_predicates_in_scope() {
|
||||
@@ -1549,8 +1617,14 @@ pub(crate) fn generic_predicates_query(
|
||||
def: GenericDefId,
|
||||
) -> Arc<[Binders<QuantifiedWhereClause>]> {
|
||||
let resolver = def.resolver(db.upcast());
|
||||
let ctx = TyLoweringContext::new(db, &resolver, def.into())
|
||||
.with_type_param_mode(ParamLoweringMode::Variable);
|
||||
let ctx = if let GenericDefId::FunctionId(_) = def {
|
||||
TyLoweringContext::new(db, &resolver, def.into())
|
||||
.with_impl_trait_mode(ImplTraitLoweringMode::Variable)
|
||||
.with_type_param_mode(ParamLoweringMode::Variable)
|
||||
} else {
|
||||
TyLoweringContext::new(db, &resolver, def.into())
|
||||
.with_type_param_mode(ParamLoweringMode::Variable)
|
||||
};
|
||||
let generics = generics(db.upcast(), def);
|
||||
|
||||
let mut predicates = resolver
|
||||
|
||||
@@ -1364,10 +1364,16 @@ fn lower_literal_or_const_to_operand(
|
||||
match loc {
|
||||
LiteralOrConst::Literal(l) => self.lower_literal_to_operand(ty, l),
|
||||
LiteralOrConst::Const(c) => {
|
||||
let unresolved_name = || MirLowerError::unresolved_path(self.db, c);
|
||||
let c = match &self.body.pats[*c] {
|
||||
Pat::Path(p) => p,
|
||||
_ => not_supported!(
|
||||
"only `char` and numeric types are allowed in range patterns"
|
||||
),
|
||||
};
|
||||
let unresolved_name = || MirLowerError::unresolved_path(self.db, c.as_ref());
|
||||
let resolver = self.owner.resolver(self.db.upcast());
|
||||
let pr = resolver
|
||||
.resolve_path_in_value_ns(self.db.upcast(), c)
|
||||
.resolve_path_in_value_ns(self.db.upcast(), c.as_ref())
|
||||
.ok_or_else(unresolved_name)?;
|
||||
match pr {
|
||||
ResolveValueResult::ValueNs(v, _) => {
|
||||
|
||||
@@ -1231,6 +1231,53 @@ fn test(x: impl Trait<u64>, y: &impl Trait<u64>) {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn argument_impl_trait_with_projection() {
|
||||
check_infer(
|
||||
r#"
|
||||
trait X {
|
||||
type Item;
|
||||
}
|
||||
|
||||
impl<T> X for [T; 2] {
|
||||
type Item = T;
|
||||
}
|
||||
|
||||
trait Y {}
|
||||
|
||||
impl<T> Y for T {}
|
||||
|
||||
enum R<T, U> {
|
||||
A(T),
|
||||
B(U),
|
||||
}
|
||||
|
||||
fn foo<T>(x: impl X<Item = R<impl Y, T>>) -> T { loop {} }
|
||||
|
||||
fn bar() {
|
||||
let a = foo([R::A(()), R::B(7)]);
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
153..154 'x': impl X<Item = R<impl Y + ?Sized, T>> + ?Sized
|
||||
190..201 '{ loop {} }': T
|
||||
192..199 'loop {}': !
|
||||
197..199 '{}': ()
|
||||
212..253 '{ ...)]); }': ()
|
||||
222..223 'a': i32
|
||||
226..229 'foo': fn foo<i32>([R<(), i32>; 2]) -> i32
|
||||
226..250 'foo([R...B(7)])': i32
|
||||
230..249 '[R::A(...:B(7)]': [R<(), i32>; 2]
|
||||
231..235 'R::A': extern "rust-call" A<(), i32>(()) -> R<(), i32>
|
||||
231..239 'R::A(())': R<(), i32>
|
||||
236..238 '()': ()
|
||||
241..245 'R::B': extern "rust-call" B<(), i32>(i32) -> R<(), i32>
|
||||
241..248 'R::B(7)': R<(), i32>
|
||||
246..247 '7': i32
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn simple_return_pos_impl_trait() {
|
||||
cov_mark::check!(lower_rpit);
|
||||
|
||||
@@ -27,7 +27,6 @@ cfg.workspace = true
|
||||
hir-def.workspace = true
|
||||
hir-expand.workspace = true
|
||||
hir-ty.workspace = true
|
||||
profile.workspace = true
|
||||
stdx.workspace = true
|
||||
syntax.workspace = true
|
||||
tt.workspace = true
|
||||
|
||||
@@ -4,20 +4,20 @@
|
||||
//!
|
||||
//! But we need this for at least LRU caching at the query level.
|
||||
pub use hir_def::db::{
|
||||
AttrsQuery, BlockDefMapQuery, BlockItemTreeQueryQuery, BodyQuery, BodyWithSourceMapQuery,
|
||||
ConstDataQuery, ConstVisibilityQuery, CrateDefMapQueryQuery, CrateLangItemsQuery,
|
||||
CrateSupportsNoStdQuery, DefDatabase, DefDatabaseStorage, EnumDataQuery,
|
||||
EnumVariantDataWithDiagnosticsQuery, ExprScopesQuery, ExternCrateDeclDataQuery,
|
||||
FieldVisibilitiesQuery, FieldsAttrsQuery, FieldsAttrsSourceMapQuery, FileItemTreeQuery,
|
||||
FunctionDataQuery, FunctionVisibilityQuery, GenericParamsQuery, ImplDataWithDiagnosticsQuery,
|
||||
ImportMapQuery, InternAnonymousConstQuery, InternBlockQuery, InternConstQuery, InternDatabase,
|
||||
InternDatabaseStorage, InternEnumQuery, InternExternBlockQuery, InternExternCrateQuery,
|
||||
InternFunctionQuery, InternImplQuery, InternInTypeConstQuery, InternMacro2Query,
|
||||
InternMacroRulesQuery, InternProcMacroQuery, InternStaticQuery, InternStructQuery,
|
||||
InternTraitAliasQuery, InternTraitQuery, InternTypeAliasQuery, InternUnionQuery,
|
||||
InternUseQuery, LangItemQuery, Macro2DataQuery, MacroRulesDataQuery, ProcMacroDataQuery,
|
||||
StaticDataQuery, StructDataWithDiagnosticsQuery, TraitAliasDataQuery,
|
||||
TraitDataWithDiagnosticsQuery, TypeAliasDataQuery, UnionDataWithDiagnosticsQuery,
|
||||
AttrsQuery, BlockDefMapQuery, BodyQuery, BodyWithSourceMapQuery, ConstDataQuery,
|
||||
ConstVisibilityQuery, CrateLangItemsQuery, CrateSupportsNoStdQuery, DefDatabase,
|
||||
DefDatabaseStorage, EnumDataQuery, EnumVariantDataWithDiagnosticsQuery, ExprScopesQuery,
|
||||
ExternCrateDeclDataQuery, FieldVisibilitiesQuery, FieldsAttrsQuery, FieldsAttrsSourceMapQuery,
|
||||
FileItemTreeQuery, FunctionDataQuery, FunctionVisibilityQuery, GenericParamsQuery,
|
||||
ImplDataWithDiagnosticsQuery, ImportMapQuery, InternAnonymousConstQuery, InternBlockQuery,
|
||||
InternConstQuery, InternDatabase, InternDatabaseStorage, InternEnumQuery,
|
||||
InternExternBlockQuery, InternExternCrateQuery, InternFunctionQuery, InternImplQuery,
|
||||
InternInTypeConstQuery, InternMacro2Query, InternMacroRulesQuery, InternProcMacroQuery,
|
||||
InternStaticQuery, InternStructQuery, InternTraitAliasQuery, InternTraitQuery,
|
||||
InternTypeAliasQuery, InternUnionQuery, InternUseQuery, LangItemQuery, Macro2DataQuery,
|
||||
MacroRulesDataQuery, ProcMacroDataQuery, StaticDataQuery, StructDataWithDiagnosticsQuery,
|
||||
TraitAliasDataQuery, TraitDataWithDiagnosticsQuery, TypeAliasDataQuery,
|
||||
UnionDataWithDiagnosticsQuery,
|
||||
};
|
||||
pub use hir_expand::db::{
|
||||
AstIdMapQuery, DeclMacroExpanderQuery, ExpandDatabase, ExpandDatabaseStorage,
|
||||
|
||||
@@ -17,10 +17,10 @@
|
||||
};
|
||||
|
||||
use crate::{
|
||||
Adt, AsAssocItem, AssocItemContainer, Const, ConstParam, Enum, ExternCrateDecl, Field,
|
||||
Function, GenericParam, HasCrate, HasVisibility, LifetimeParam, Macro, Module, SelfParam,
|
||||
Static, Struct, Trait, TraitAlias, TupleField, TyBuilder, Type, TypeAlias, TypeOrConstParam,
|
||||
TypeParam, Union, Variant,
|
||||
Adt, AsAssocItem, AssocItem, AssocItemContainer, Const, ConstParam, Enum, ExternCrateDecl,
|
||||
Field, Function, GenericParam, HasCrate, HasVisibility, LifetimeParam, Macro, Module,
|
||||
SelfParam, Static, Struct, Trait, TraitAlias, TupleField, TyBuilder, Type, TypeAlias,
|
||||
TypeOrConstParam, TypeParam, Union, Variant,
|
||||
};
|
||||
|
||||
impl HirDisplay for Function {
|
||||
@@ -595,6 +595,35 @@ fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
|
||||
let def_id = GenericDefId::TraitId(self.id);
|
||||
write_generic_params(def_id, f)?;
|
||||
write_where_clause(def_id, f)?;
|
||||
|
||||
if let Some(limit) = f.entity_limit {
|
||||
let assoc_items = self.items(f.db);
|
||||
let count = assoc_items.len().min(limit);
|
||||
if count == 0 {
|
||||
if assoc_items.is_empty() {
|
||||
f.write_str(" {}")?;
|
||||
} else {
|
||||
f.write_str(" { /* … */ }")?;
|
||||
}
|
||||
} else {
|
||||
f.write_str(" {\n")?;
|
||||
for item in &assoc_items[..count] {
|
||||
f.write_str(" ")?;
|
||||
match item {
|
||||
AssocItem::Function(func) => func.hir_fmt(f),
|
||||
AssocItem::Const(cst) => cst.hir_fmt(f),
|
||||
AssocItem::TypeAlias(type_alias) => type_alias.hir_fmt(f),
|
||||
}?;
|
||||
f.write_str(";\n")?;
|
||||
}
|
||||
|
||||
if assoc_items.len() > count {
|
||||
f.write_str(" /* … */\n")?;
|
||||
}
|
||||
f.write_str("}")?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,7 +126,7 @@
|
||||
},
|
||||
hir_expand::{
|
||||
attrs::{Attr, AttrId},
|
||||
change::Change,
|
||||
change::ChangeWithProcMacros,
|
||||
hygiene::{marks_rev, SyntaxContextExt},
|
||||
name::{known, Name},
|
||||
proc_macro::ProcMacros,
|
||||
@@ -365,7 +365,7 @@ pub fn name(self, db: &dyn HirDatabase) -> Option<Name> {
|
||||
Some(name)
|
||||
}
|
||||
|
||||
pub fn diagnostics(self, db: &dyn HirDatabase) -> Vec<AnyDiagnostic> {
|
||||
pub fn diagnostics(self, db: &dyn HirDatabase, style_lints: bool) -> Vec<AnyDiagnostic> {
|
||||
let id = match self {
|
||||
ModuleDef::Adt(it) => match it {
|
||||
Adt::Struct(it) => it.id.into(),
|
||||
@@ -387,7 +387,7 @@ pub fn diagnostics(self, db: &dyn HirDatabase) -> Vec<AnyDiagnostic> {
|
||||
|
||||
match self.as_def_with_body() {
|
||||
Some(def) => {
|
||||
def.diagnostics(db, &mut acc);
|
||||
def.diagnostics(db, &mut acc, style_lints);
|
||||
}
|
||||
None => {
|
||||
for diag in hir_ty::diagnostics::incorrect_case(db, id) {
|
||||
@@ -541,7 +541,12 @@ pub fn scope(
|
||||
}
|
||||
|
||||
/// Fills `acc` with the module's diagnostics.
|
||||
pub fn diagnostics(self, db: &dyn HirDatabase, acc: &mut Vec<AnyDiagnostic>) {
|
||||
pub fn diagnostics(
|
||||
self,
|
||||
db: &dyn HirDatabase,
|
||||
acc: &mut Vec<AnyDiagnostic>,
|
||||
style_lints: bool,
|
||||
) {
|
||||
let name = self.name(db);
|
||||
let _p = tracing::span!(tracing::Level::INFO, "Module::diagnostics", ?name);
|
||||
let def_map = self.id.def_map(db.upcast());
|
||||
@@ -558,9 +563,9 @@ pub fn diagnostics(self, db: &dyn HirDatabase, acc: &mut Vec<AnyDiagnostic>) {
|
||||
ModuleDef::Module(m) => {
|
||||
// Only add diagnostics from inline modules
|
||||
if def_map[m.id.local_id].origin.is_inline() {
|
||||
m.diagnostics(db, acc)
|
||||
m.diagnostics(db, acc, style_lints)
|
||||
}
|
||||
acc.extend(def.diagnostics(db))
|
||||
acc.extend(def.diagnostics(db, style_lints))
|
||||
}
|
||||
ModuleDef::Trait(t) => {
|
||||
for diag in db.trait_data_with_diagnostics(t.id).1.iter() {
|
||||
@@ -568,10 +573,10 @@ pub fn diagnostics(self, db: &dyn HirDatabase, acc: &mut Vec<AnyDiagnostic>) {
|
||||
}
|
||||
|
||||
for item in t.items(db) {
|
||||
item.diagnostics(db, acc);
|
||||
item.diagnostics(db, acc, style_lints);
|
||||
}
|
||||
|
||||
acc.extend(def.diagnostics(db))
|
||||
acc.extend(def.diagnostics(db, style_lints))
|
||||
}
|
||||
ModuleDef::Adt(adt) => {
|
||||
match adt {
|
||||
@@ -587,17 +592,17 @@ pub fn diagnostics(self, db: &dyn HirDatabase, acc: &mut Vec<AnyDiagnostic>) {
|
||||
}
|
||||
Adt::Enum(e) => {
|
||||
for v in e.variants(db) {
|
||||
acc.extend(ModuleDef::Variant(v).diagnostics(db));
|
||||
acc.extend(ModuleDef::Variant(v).diagnostics(db, style_lints));
|
||||
for diag in db.enum_variant_data_with_diagnostics(v.id).1.iter() {
|
||||
emit_def_diagnostic(db, acc, diag);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
acc.extend(def.diagnostics(db))
|
||||
acc.extend(def.diagnostics(db, style_lints))
|
||||
}
|
||||
ModuleDef::Macro(m) => emit_macro_def_diagnostics(db, acc, m),
|
||||
_ => acc.extend(def.diagnostics(db)),
|
||||
_ => acc.extend(def.diagnostics(db, style_lints)),
|
||||
}
|
||||
}
|
||||
self.legacy_macros(db).into_iter().for_each(|m| emit_macro_def_diagnostics(db, acc, m));
|
||||
@@ -738,7 +743,7 @@ pub fn diagnostics(self, db: &dyn HirDatabase, acc: &mut Vec<AnyDiagnostic>) {
|
||||
}
|
||||
|
||||
for &item in &db.impl_data(impl_def.id).items {
|
||||
AssocItem::from(item).diagnostics(db, acc);
|
||||
AssocItem::from(item).diagnostics(db, acc, style_lints);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1616,14 +1621,19 @@ pub fn debug_mir(self, db: &dyn HirDatabase) -> String {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn diagnostics(self, db: &dyn HirDatabase, acc: &mut Vec<AnyDiagnostic>) {
|
||||
pub fn diagnostics(
|
||||
self,
|
||||
db: &dyn HirDatabase,
|
||||
acc: &mut Vec<AnyDiagnostic>,
|
||||
style_lints: bool,
|
||||
) {
|
||||
db.unwind_if_cancelled();
|
||||
let krate = self.module(db).id.krate();
|
||||
|
||||
let (body, source_map) = db.body_with_source_map(self.into());
|
||||
|
||||
for (_, def_map) in body.blocks(db.upcast()) {
|
||||
Module { id: def_map.module_id(DefMap::ROOT) }.diagnostics(db, acc);
|
||||
Module { id: def_map.module_id(DefMap::ROOT) }.diagnostics(db, acc, style_lints);
|
||||
}
|
||||
|
||||
for diag in source_map.diagnostics() {
|
||||
@@ -1784,7 +1794,7 @@ pub fn diagnostics(self, db: &dyn HirDatabase, acc: &mut Vec<AnyDiagnostic>) {
|
||||
}
|
||||
}
|
||||
|
||||
for diagnostic in BodyValidationDiagnostic::collect(db, self.into()) {
|
||||
for diagnostic in BodyValidationDiagnostic::collect(db, self.into(), style_lints) {
|
||||
acc.extend(AnyDiagnostic::body_validation_diagnostic(db, diagnostic, &source_map));
|
||||
}
|
||||
|
||||
@@ -2098,6 +2108,14 @@ pub struct Param {
|
||||
}
|
||||
|
||||
impl Param {
|
||||
pub fn parent_fn(&self) -> Function {
|
||||
self.func
|
||||
}
|
||||
|
||||
pub fn index(&self) -> usize {
|
||||
self.idx
|
||||
}
|
||||
|
||||
pub fn ty(&self) -> &Type {
|
||||
&self.ty
|
||||
}
|
||||
@@ -2162,6 +2180,10 @@ pub fn source(&self, db: &dyn HirDatabase) -> Option<InFile<ast::SelfParam>> {
|
||||
.map(|value| InFile { file_id, value })
|
||||
}
|
||||
|
||||
pub fn parent_fn(&self) -> Function {
|
||||
Function::from(self.func)
|
||||
}
|
||||
|
||||
pub fn ty(&self, db: &dyn HirDatabase) -> Type {
|
||||
let substs = TyBuilder::placeholder_subst(db, self.func);
|
||||
let callable_sig =
|
||||
@@ -2897,13 +2919,18 @@ pub fn as_type_alias(self) -> Option<TypeAlias> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn diagnostics(self, db: &dyn HirDatabase, acc: &mut Vec<AnyDiagnostic>) {
|
||||
pub fn diagnostics(
|
||||
self,
|
||||
db: &dyn HirDatabase,
|
||||
acc: &mut Vec<AnyDiagnostic>,
|
||||
style_lints: bool,
|
||||
) {
|
||||
match self {
|
||||
AssocItem::Function(func) => {
|
||||
DefWithBody::from(func).diagnostics(db, acc);
|
||||
DefWithBody::from(func).diagnostics(db, acc, style_lints);
|
||||
}
|
||||
AssocItem::Const(const_) => {
|
||||
DefWithBody::from(const_).diagnostics(db, acc);
|
||||
DefWithBody::from(const_).diagnostics(db, acc, style_lints);
|
||||
}
|
||||
AssocItem::TypeAlias(type_alias) => {
|
||||
for diag in hir_ty::diagnostics::incorrect_case(db, type_alias.id.into()) {
|
||||
|
||||
@@ -38,10 +38,11 @@
|
||||
db::HirDatabase,
|
||||
semantics::source_to_def::{ChildContainer, SourceToDefCache, SourceToDefCtx},
|
||||
source_analyzer::{resolve_hir_path, SourceAnalyzer},
|
||||
Access, Adjust, Adjustment, AutoBorrow, BindingMode, BuiltinAttr, Callable, ConstParam, Crate,
|
||||
DeriveHelper, Field, Function, HasSource, HirFileId, Impl, InFile, Label, LifetimeParam, Local,
|
||||
Macro, Module, ModuleDef, Name, OverloadedDeref, Path, ScopeDef, Struct, ToolModule, Trait,
|
||||
TupleField, Type, TypeAlias, TypeParam, VariantDef,
|
||||
Access, Adjust, Adjustment, Adt, AutoBorrow, BindingMode, BuiltinAttr, Callable, Const,
|
||||
ConstParam, Crate, DeriveHelper, Enum, Field, Function, HasSource, HirFileId, Impl, InFile,
|
||||
Label, LifetimeParam, Local, Macro, Module, ModuleDef, Name, OverloadedDeref, Path, ScopeDef,
|
||||
Static, Struct, ToolModule, Trait, TraitAlias, TupleField, Type, TypeAlias, TypeParam, Union,
|
||||
Variant, VariantDef,
|
||||
};
|
||||
|
||||
pub enum DescendPreference {
|
||||
@@ -223,20 +224,68 @@ pub fn resolve_variant(&self, record_lit: ast::RecordExpr) -> Option<VariantDef>
|
||||
self.imp.resolve_variant(record_lit).map(VariantDef::from)
|
||||
}
|
||||
|
||||
pub fn to_module_def(&self, file: FileId) -> Option<Module> {
|
||||
self.imp.to_module_def(file).next()
|
||||
pub fn file_to_module_def(&self, file: FileId) -> Option<Module> {
|
||||
self.imp.file_to_module_defs(file).next()
|
||||
}
|
||||
|
||||
pub fn to_module_defs(&self, file: FileId) -> impl Iterator<Item = Module> {
|
||||
self.imp.to_module_def(file)
|
||||
pub fn file_to_module_defs(&self, file: FileId) -> impl Iterator<Item = Module> {
|
||||
self.imp.file_to_module_defs(file)
|
||||
}
|
||||
|
||||
pub fn to_adt_def(&self, a: &ast::Adt) -> Option<Adt> {
|
||||
self.imp.to_def(a).map(Adt::from)
|
||||
}
|
||||
|
||||
pub fn to_const_def(&self, c: &ast::Const) -> Option<Const> {
|
||||
self.imp.to_def(c).map(Const::from)
|
||||
}
|
||||
|
||||
pub fn to_enum_def(&self, e: &ast::Enum) -> Option<Enum> {
|
||||
self.imp.to_def(e).map(Enum::from)
|
||||
}
|
||||
|
||||
pub fn to_enum_variant_def(&self, v: &ast::Variant) -> Option<Variant> {
|
||||
self.imp.to_def(v).map(Variant::from)
|
||||
}
|
||||
|
||||
pub fn to_fn_def(&self, f: &ast::Fn) -> Option<Function> {
|
||||
self.imp.to_def(f).map(Function::from)
|
||||
}
|
||||
|
||||
pub fn to_impl_def(&self, i: &ast::Impl) -> Option<Impl> {
|
||||
self.imp.to_def(i).map(Impl::from)
|
||||
}
|
||||
|
||||
pub fn to_macro_def(&self, m: &ast::Macro) -> Option<Macro> {
|
||||
self.imp.to_def(m).map(Macro::from)
|
||||
}
|
||||
|
||||
pub fn to_module_def(&self, m: &ast::Module) -> Option<Module> {
|
||||
self.imp.to_def(m).map(Module::from)
|
||||
}
|
||||
|
||||
pub fn to_static_def(&self, s: &ast::Static) -> Option<Static> {
|
||||
self.imp.to_def(s).map(Static::from)
|
||||
}
|
||||
|
||||
pub fn to_struct_def(&self, s: &ast::Struct) -> Option<Struct> {
|
||||
self.imp.to_def(s).map(Struct::from)
|
||||
}
|
||||
|
||||
pub fn to_impl_def(&self, i: &ast::Impl) -> Option<Impl> {
|
||||
self.imp.to_def(i).map(Impl::from)
|
||||
pub fn to_trait_alias_def(&self, t: &ast::TraitAlias) -> Option<TraitAlias> {
|
||||
self.imp.to_def(t).map(TraitAlias::from)
|
||||
}
|
||||
|
||||
pub fn to_trait_def(&self, t: &ast::Trait) -> Option<Trait> {
|
||||
self.imp.to_def(t).map(Trait::from)
|
||||
}
|
||||
|
||||
pub fn to_type_alias_def(&self, t: &ast::TypeAlias) -> Option<TypeAlias> {
|
||||
self.imp.to_def(t).map(TypeAlias::from)
|
||||
}
|
||||
|
||||
pub fn to_union_def(&self, u: &ast::Union) -> Option<Union> {
|
||||
self.imp.to_def(u).map(Union::from)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1024,7 +1073,7 @@ pub fn resolve_label(&self, lifetime: &ast::Lifetime) -> Option<Label> {
|
||||
|
||||
pub fn resolve_type(&self, ty: &ast::Type) -> Option<Type> {
|
||||
let analyze = self.analyze(ty.syntax())?;
|
||||
let ctx = LowerCtx::with_file_id(self.db.upcast(), analyze.file_id);
|
||||
let ctx = LowerCtx::new(self.db.upcast(), analyze.file_id);
|
||||
let ty = hir_ty::TyLoweringContext::new_maybe_unowned(
|
||||
self.db,
|
||||
&analyze.resolver,
|
||||
@@ -1036,8 +1085,7 @@ pub fn resolve_type(&self, ty: &ast::Type) -> Option<Type> {
|
||||
|
||||
pub fn resolve_trait(&self, path: &ast::Path) -> Option<Trait> {
|
||||
let analyze = self.analyze(path.syntax())?;
|
||||
let span_map = self.db.span_map(analyze.file_id);
|
||||
let ctx = LowerCtx::with_span_map(self.db.upcast(), span_map);
|
||||
let ctx = LowerCtx::new(self.db.upcast(), analyze.file_id);
|
||||
let hir_path = Path::from_src(&ctx, path.clone())?;
|
||||
match analyze.resolver.resolve_path_in_type_ns_fully(self.db.upcast(), &hir_path)? {
|
||||
TypeNs::TraitId(id) => Some(Trait { id }),
|
||||
@@ -1241,7 +1289,7 @@ pub fn to_def<T: ToDef>(&self, src: &T) -> Option<T::Def> {
|
||||
T::to_def(self, src)
|
||||
}
|
||||
|
||||
fn to_module_def(&self, file: FileId) -> impl Iterator<Item = Module> {
|
||||
fn file_to_module_defs(&self, file: FileId) -> impl Iterator<Item = Module> {
|
||||
self.with_ctx(|ctx| ctx.file_to_def(file)).into_iter().map(Module::from)
|
||||
}
|
||||
|
||||
@@ -1645,7 +1693,7 @@ pub fn process_all_names(&self, f: &mut dyn FnMut(Name, ScopeDef)) {
|
||||
/// Resolve a path as-if it was written at the given scope. This is
|
||||
/// necessary a heuristic, as it doesn't take hygiene into account.
|
||||
pub fn speculative_resolve(&self, path: &ast::Path) -> Option<PathResolution> {
|
||||
let ctx = LowerCtx::with_file_id(self.db.upcast(), self.file_id);
|
||||
let ctx = LowerCtx::new(self.db.upcast(), self.file_id);
|
||||
let path = Path::from_src(&ctx, path.clone())?;
|
||||
resolve_hir_path(self.db, &self.resolver, &path)
|
||||
}
|
||||
|
||||
@@ -118,7 +118,7 @@ pub(super) struct SourceToDefCtx<'a, 'b> {
|
||||
|
||||
impl SourceToDefCtx<'_, '_> {
|
||||
pub(super) fn file_to_def(&self, file: FileId) -> SmallVec<[ModuleId; 1]> {
|
||||
let _p = tracing::span!(tracing::Level::INFO, "SourceBinder::to_module_def");
|
||||
let _p = tracing::span!(tracing::Level::INFO, "SourceBinder::file_to_module_def");
|
||||
let mut mods = SmallVec::new();
|
||||
for &crate_id in self.db.relevant_crates(file).iter() {
|
||||
// FIXME: inner items
|
||||
|
||||
@@ -549,7 +549,7 @@ pub(crate) fn resolve_macro_call(
|
||||
db: &dyn HirDatabase,
|
||||
macro_call: InFile<&ast::MacroCall>,
|
||||
) -> Option<Macro> {
|
||||
let ctx = LowerCtx::with_file_id(db.upcast(), macro_call.file_id);
|
||||
let ctx = LowerCtx::new(db.upcast(), macro_call.file_id);
|
||||
let path = macro_call.value.path().and_then(|ast| Path::from_src(&ctx, ast))?;
|
||||
self.resolver
|
||||
.resolve_path_as_macro(db.upcast(), path.mod_path()?, Some(MacroSubNs::Bang))
|
||||
@@ -662,7 +662,7 @@ pub(crate) fn resolve_path(
|
||||
}
|
||||
|
||||
// This must be a normal source file rather than macro file.
|
||||
let ctx = LowerCtx::with_span_map(db.upcast(), db.span_map(self.file_id));
|
||||
let ctx = LowerCtx::new(db.upcast(), self.file_id);
|
||||
let hir_path = Path::from_src(&ctx, path.clone())?;
|
||||
|
||||
// Case where path is a qualifier of a use tree, e.g. foo::bar::{Baz, Qux} where we are
|
||||
|
||||
@@ -23,7 +23,6 @@ tracing.workspace = true
|
||||
stdx.workspace = true
|
||||
syntax.workspace = true
|
||||
text-edit.workspace = true
|
||||
profile.workspace = true
|
||||
ide-db.workspace = true
|
||||
hir.workspace = true
|
||||
|
||||
@@ -33,10 +32,6 @@ expect-test = "1.4.0"
|
||||
# local deps
|
||||
test-utils.workspace = true
|
||||
test-fixture.workspace = true
|
||||
sourcegen.workspace = true
|
||||
|
||||
[features]
|
||||
in-rust-tree = []
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
+19
-8
@@ -107,6 +107,10 @@ fn collect_data(ident_pat: ast::IdentPat, ctx: &AssistContext<'_>) -> Option<Str
|
||||
let visible_fields =
|
||||
fields.into_iter().filter(|field| field.is_visible_from(ctx.db(), module)).collect_vec();
|
||||
|
||||
if visible_fields.is_empty() {
|
||||
return None;
|
||||
}
|
||||
|
||||
let has_private_members =
|
||||
(is_non_exhaustive && is_foreign_crate) || visible_fields.len() < n_fields;
|
||||
|
||||
@@ -413,7 +417,7 @@ fn main() {
|
||||
|
||||
#[test]
|
||||
fn unit_struct() {
|
||||
check_assist(
|
||||
check_assist_not_applicable(
|
||||
destructure_struct_binding,
|
||||
r#"
|
||||
struct Foo;
|
||||
@@ -422,13 +426,6 @@ fn main() {
|
||||
let $0foo = Foo;
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
struct Foo;
|
||||
|
||||
fn main() {
|
||||
let Foo = Foo;
|
||||
}
|
||||
"#,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -739,4 +736,18 @@ fn main(foo: Foo) {
|
||||
"#,
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn record_struct_no_public_members() {
|
||||
check_assist_not_applicable(
|
||||
destructure_struct_binding,
|
||||
r#"
|
||||
//- /lib.rs crate:dep
|
||||
pub struct Foo { bar: i32, baz: i32 };
|
||||
|
||||
//- /main.rs crate:main deps:dep
|
||||
fn main($0foo: dep::Foo) {}
|
||||
"#,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
+18
@@ -274,4 +274,22 @@ fn main() {
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn escaped_literals() {
|
||||
check_assist(
|
||||
extract_expressions_from_format_string,
|
||||
r#"
|
||||
//- minicore: fmt
|
||||
fn main() {
|
||||
print!("\n$ {x + 1}$0");
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
fn main() {
|
||||
print!("\n$ {}"$0, x + 1);
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,8 @@
|
||||
ast::{
|
||||
self,
|
||||
edit::{self, AstNodeEdit},
|
||||
make, AssocItem, GenericArgList, GenericParamList, HasGenericParams, HasName,
|
||||
edit_in_place::AttrsOwnerEdit,
|
||||
make, AssocItem, GenericArgList, GenericParamList, HasAttrs, HasGenericParams, HasName,
|
||||
HasTypeBounds, HasVisibility as astHasVisibility, Path, WherePred,
|
||||
},
|
||||
ted::{self, Position},
|
||||
@@ -116,7 +117,7 @@ pub(crate) fn new(
|
||||
) -> Option<Field> {
|
||||
let db = ctx.sema.db;
|
||||
|
||||
let module = ctx.sema.to_module_def(ctx.file_id())?;
|
||||
let module = ctx.sema.file_to_module_def(ctx.file_id())?;
|
||||
|
||||
let (name, range, ty) = match f {
|
||||
Either::Left(f) => {
|
||||
@@ -619,7 +620,8 @@ fn process_assoc_item(
|
||||
qual_path_ty: ast::Path,
|
||||
base_name: &str,
|
||||
) -> Option<ast::AssocItem> {
|
||||
match item {
|
||||
let attrs = item.attrs();
|
||||
let assoc = match item {
|
||||
AssocItem::Const(c) => const_assoc_item(c, qual_path_ty),
|
||||
AssocItem::Fn(f) => func_assoc_item(f, qual_path_ty, base_name),
|
||||
AssocItem::MacroCall(_) => {
|
||||
@@ -628,7 +630,18 @@ fn process_assoc_item(
|
||||
None
|
||||
}
|
||||
AssocItem::TypeAlias(ta) => ty_assoc_item(ta, qual_path_ty),
|
||||
};
|
||||
if let Some(assoc) = &assoc {
|
||||
attrs.for_each(|attr| {
|
||||
assoc.add_attr(attr.clone());
|
||||
// fix indentations
|
||||
if let Some(tok) = attr.syntax().next_sibling_or_token() {
|
||||
let pos = Position::after(tok);
|
||||
ted::insert(pos, make::tokens::whitespace(" "));
|
||||
}
|
||||
})
|
||||
}
|
||||
assoc
|
||||
}
|
||||
|
||||
fn const_assoc_item(item: syntax::ast::Const, qual_path_ty: ast::Path) -> Option<AssocItem> {
|
||||
@@ -1703,4 +1716,65 @@ fn method_(&mut self) -> bool {
|
||||
}"#,
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fn_with_attrs() {
|
||||
check_assist(
|
||||
generate_delegate_trait,
|
||||
r#"
|
||||
struct A;
|
||||
|
||||
trait T {
|
||||
#[cfg(test)]
|
||||
fn f(&self, a: u32);
|
||||
#[cfg(not(test))]
|
||||
fn f(&self, a: bool);
|
||||
}
|
||||
|
||||
impl T for A {
|
||||
#[cfg(test)]
|
||||
fn f(&self, a: u32) {}
|
||||
#[cfg(not(test))]
|
||||
fn f(&self, a: bool) {}
|
||||
}
|
||||
|
||||
struct B {
|
||||
a$0: A,
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
struct A;
|
||||
|
||||
trait T {
|
||||
#[cfg(test)]
|
||||
fn f(&self, a: u32);
|
||||
#[cfg(not(test))]
|
||||
fn f(&self, a: bool);
|
||||
}
|
||||
|
||||
impl T for A {
|
||||
#[cfg(test)]
|
||||
fn f(&self, a: u32) {}
|
||||
#[cfg(not(test))]
|
||||
fn f(&self, a: bool) {}
|
||||
}
|
||||
|
||||
struct B {
|
||||
a: A,
|
||||
}
|
||||
|
||||
impl T for B {
|
||||
#[cfg(test)]
|
||||
fn f(&self, a: u32) {
|
||||
<A as T>::f(&self.a, a)
|
||||
}
|
||||
|
||||
#[cfg(not(test))]
|
||||
fn f(&self, a: bool) {
|
||||
<A as T>::f(&self.a, a)
|
||||
}
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -418,24 +418,15 @@ fn inline(
|
||||
let expr: &ast::Expr = expr;
|
||||
|
||||
let mut insert_let_stmt = || {
|
||||
let param_ty = match param_ty {
|
||||
None => None,
|
||||
Some(param_ty) => {
|
||||
if sema.hir_file_for(param_ty.syntax()).is_macro() {
|
||||
if let Some(param_ty) =
|
||||
ast::Type::cast(insert_ws_into(param_ty.syntax().clone()))
|
||||
{
|
||||
Some(param_ty)
|
||||
} else {
|
||||
Some(param_ty.clone_for_update())
|
||||
}
|
||||
} else {
|
||||
Some(param_ty.clone_for_update())
|
||||
}
|
||||
let param_ty = param_ty.clone().map(|param_ty| {
|
||||
if sema.hir_file_for(param_ty.syntax()).is_macro() {
|
||||
ast::Type::cast(insert_ws_into(param_ty.syntax().clone())).unwrap_or(param_ty)
|
||||
} else {
|
||||
param_ty
|
||||
}
|
||||
};
|
||||
let ty: Option<syntax::ast::Type> =
|
||||
sema.type_of_expr(expr).filter(TypeInfo::has_adjustment).and(param_ty);
|
||||
});
|
||||
|
||||
let ty = sema.type_of_expr(expr).filter(TypeInfo::has_adjustment).and(param_ty);
|
||||
|
||||
let is_self = param
|
||||
.name(sema.db)
|
||||
@@ -1359,8 +1350,8 @@ macro_rules! define_foo {
|
||||
define_foo!();
|
||||
fn bar() -> u32 {
|
||||
{
|
||||
let x = 0;
|
||||
x
|
||||
let x = 0;
|
||||
x
|
||||
}
|
||||
}
|
||||
"#,
|
||||
@@ -1673,7 +1664,7 @@ fn main() {
|
||||
let a: A = A{};
|
||||
let b = {
|
||||
let a = a;
|
||||
a as A
|
||||
a as A
|
||||
};
|
||||
}
|
||||
"#,
|
||||
@@ -1792,7 +1783,7 @@ fn _hash2(self_: &u64, state: &mut u64) {
|
||||
{
|
||||
let inner_self_: &u64 = &self_;
|
||||
let state: &mut u64 = state;
|
||||
_write_u64(state, *inner_self_)
|
||||
_write_u64(state, *inner_self_)
|
||||
};
|
||||
}
|
||||
"#,
|
||||
|
||||
@@ -288,11 +288,11 @@ macro_rules! foo {
|
||||
}
|
||||
fn main() {
|
||||
cfg_if!{
|
||||
if #[cfg(test)]{
|
||||
1;
|
||||
}else {
|
||||
1;
|
||||
}
|
||||
if #[cfg(test)]{
|
||||
1;
|
||||
}else {
|
||||
1;
|
||||
}
|
||||
};
|
||||
}
|
||||
"#,
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
// ```
|
||||
pub(crate) fn move_from_mod_rs(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
|
||||
let source_file = ctx.find_node_at_offset::<ast::SourceFile>()?;
|
||||
let module = ctx.sema.to_module_def(ctx.file_id())?;
|
||||
let module = ctx.sema.file_to_module_def(ctx.file_id())?;
|
||||
// Enable this assist if the user select all "meaningful" content in the source file
|
||||
let trimmed_selected_range = trimmed_text_range(&source_file, ctx.selection_trimmed());
|
||||
let trimmed_file_range = trimmed_text_range(&source_file, source_file.syntax().text_range());
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
// ```
|
||||
pub(crate) fn move_to_mod_rs(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
|
||||
let source_file = ctx.find_node_at_offset::<ast::SourceFile>()?;
|
||||
let module = ctx.sema.to_module_def(ctx.file_id())?;
|
||||
let module = ctx.sema.file_to_module_def(ctx.file_id())?;
|
||||
// Enable this assist if the user select all "meaningful" content in the source file
|
||||
let trimmed_selected_range = trimmed_text_range(&source_file, ctx.selection_trimmed());
|
||||
let trimmed_file_range = trimmed_text_range(&source_file, source_file.syntax().text_range());
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
mod generated;
|
||||
#[cfg(not(feature = "in-rust-tree"))]
|
||||
mod sourcegen;
|
||||
|
||||
use expect_test::expect;
|
||||
use hir::Semantics;
|
||||
|
||||
@@ -23,7 +23,6 @@ smallvec.workspace = true
|
||||
# local deps
|
||||
base-db.workspace = true
|
||||
ide-db.workspace = true
|
||||
profile.workspace = true
|
||||
stdx.workspace = true
|
||||
syntax.workspace = true
|
||||
text-edit.workspace = true
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
//! Completes identifiers in format string literals.
|
||||
|
||||
use ide_db::syntax_helpers::format_string::is_format_string;
|
||||
use hir::{ModuleDef, ScopeDef};
|
||||
use ide_db::{syntax_helpers::format_string::is_format_string, SymbolKind};
|
||||
use itertools::Itertools;
|
||||
use syntax::{ast, AstToken, TextRange, TextSize};
|
||||
|
||||
@@ -33,7 +34,23 @@ pub(crate) fn format_string(
|
||||
ctx.locals.iter().for_each(|(name, _)| {
|
||||
CompletionItem::new(CompletionItemKind::Binding, source_range, name.to_smol_str())
|
||||
.add_to(acc, ctx.db);
|
||||
})
|
||||
});
|
||||
ctx.scope.process_all_names(&mut |name, scope| {
|
||||
if let ScopeDef::ModuleDef(module_def) = scope {
|
||||
let symbol_kind = match module_def {
|
||||
ModuleDef::Const(..) => SymbolKind::Const,
|
||||
ModuleDef::Static(..) => SymbolKind::Static,
|
||||
_ => return,
|
||||
};
|
||||
|
||||
CompletionItem::new(
|
||||
CompletionItemKind::SymbolKind(symbol_kind),
|
||||
source_range,
|
||||
name.to_smol_str(),
|
||||
)
|
||||
.add_to(acc, ctx.db);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@@ -110,6 +127,80 @@ fn main() {
|
||||
let foobar = 1;
|
||||
format_args!("{foobar");
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn completes_constants() {
|
||||
check_edit(
|
||||
"FOOBAR",
|
||||
r#"
|
||||
//- minicore: fmt
|
||||
fn main() {
|
||||
const FOOBAR: usize = 42;
|
||||
format_args!("{f$0");
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
fn main() {
|
||||
const FOOBAR: usize = 42;
|
||||
format_args!("{FOOBAR");
|
||||
}
|
||||
"#,
|
||||
);
|
||||
|
||||
check_edit(
|
||||
"FOOBAR",
|
||||
r#"
|
||||
//- minicore: fmt
|
||||
fn main() {
|
||||
const FOOBAR: usize = 42;
|
||||
format_args!("{$0");
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
fn main() {
|
||||
const FOOBAR: usize = 42;
|
||||
format_args!("{FOOBAR");
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn completes_static_constants() {
|
||||
check_edit(
|
||||
"FOOBAR",
|
||||
r#"
|
||||
//- minicore: fmt
|
||||
fn main() {
|
||||
static FOOBAR: usize = 42;
|
||||
format_args!("{f$0");
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
fn main() {
|
||||
static FOOBAR: usize = 42;
|
||||
format_args!("{FOOBAR");
|
||||
}
|
||||
"#,
|
||||
);
|
||||
|
||||
check_edit(
|
||||
"FOOBAR",
|
||||
r#"
|
||||
//- minicore: fmt
|
||||
fn main() {
|
||||
static FOOBAR: usize = 42;
|
||||
format_args!("{$0");
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
fn main() {
|
||||
static FOOBAR: usize = 42;
|
||||
format_args!("{FOOBAR");
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -258,7 +258,7 @@ pub(crate) fn complete_postfix(
|
||||
}
|
||||
|
||||
fn get_receiver_text(receiver: &ast::Expr, receiver_is_ambiguous_float_literal: bool) -> String {
|
||||
let text = if receiver_is_ambiguous_float_literal {
|
||||
let mut text = if receiver_is_ambiguous_float_literal {
|
||||
let text = receiver.syntax().text();
|
||||
let without_dot = ..text.len() - TextSize::of('.');
|
||||
text.slice(without_dot).to_string()
|
||||
@@ -267,12 +267,18 @@ fn get_receiver_text(receiver: &ast::Expr, receiver_is_ambiguous_float_literal:
|
||||
};
|
||||
|
||||
// The receiver texts should be interpreted as-is, as they are expected to be
|
||||
// normal Rust expressions. We escape '\' and '$' so they don't get treated as
|
||||
// snippet-specific constructs.
|
||||
//
|
||||
// Note that we don't need to escape the other characters that can be escaped,
|
||||
// because they wouldn't be treated as snippet-specific constructs without '$'.
|
||||
text.replace('\\', "\\\\").replace('$', "\\$")
|
||||
// normal Rust expressions.
|
||||
escape_snippet_bits(&mut text);
|
||||
text
|
||||
}
|
||||
|
||||
/// Escapes `\` and `$` so that they don't get interpreted as snippet-specific constructs.
|
||||
///
|
||||
/// Note that we don't need to escape the other characters that can be escaped,
|
||||
/// because they wouldn't be treated as snippet-specific constructs without '$'.
|
||||
fn escape_snippet_bits(text: &mut String) {
|
||||
stdx::replace(text, '\\', "\\\\");
|
||||
stdx::replace(text, '$', "\\$");
|
||||
}
|
||||
|
||||
fn include_references(initial_element: &ast::Expr) -> (ast::Expr, ast::Expr) {
|
||||
|
||||
+13
-3
@@ -17,13 +17,15 @@
|
||||
// image::https://user-images.githubusercontent.com/48062697/113020656-b560f500-917a-11eb-87de-02991f61beb8.gif[]
|
||||
|
||||
use ide_db::{
|
||||
syntax_helpers::format_string_exprs::{parse_format_exprs, with_placeholders},
|
||||
syntax_helpers::format_string_exprs::{parse_format_exprs, with_placeholders, Arg},
|
||||
SnippetCap,
|
||||
};
|
||||
use syntax::{ast, AstToken};
|
||||
|
||||
use crate::{
|
||||
completions::postfix::build_postfix_snippet_builder, context::CompletionContext, Completions,
|
||||
completions::postfix::{build_postfix_snippet_builder, escape_snippet_bits},
|
||||
context::CompletionContext,
|
||||
Completions,
|
||||
};
|
||||
|
||||
/// Mapping ("postfix completion item" => "macro to use")
|
||||
@@ -51,7 +53,15 @@ pub(crate) fn add_format_like_completions(
|
||||
None => return,
|
||||
};
|
||||
|
||||
if let Ok((out, exprs)) = parse_format_exprs(receiver_text.text()) {
|
||||
if let Ok((mut out, mut exprs)) = parse_format_exprs(receiver_text.text()) {
|
||||
// Escape any snippet bits in the out text and any of the exprs.
|
||||
escape_snippet_bits(&mut out);
|
||||
for arg in &mut exprs {
|
||||
if let Arg::Ident(text) | Arg::Expr(text) = arg {
|
||||
escape_snippet_bits(text)
|
||||
}
|
||||
}
|
||||
|
||||
let exprs = with_placeholders(exprs);
|
||||
for (label, macro_name) in KINDS {
|
||||
let snippet = if exprs.is_empty() {
|
||||
|
||||
@@ -44,13 +44,10 @@ line-index.workspace = true
|
||||
|
||||
[dev-dependencies]
|
||||
expect-test = "1.4.0"
|
||||
oorandom = "11.1.3"
|
||||
xshell.workspace = true
|
||||
|
||||
# local deps
|
||||
test-utils.workspace = true
|
||||
test-fixture.workspace = true
|
||||
sourcegen.workspace = true
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
use rustc_hash::FxHashSet;
|
||||
use triomphe::Arc;
|
||||
|
||||
use crate::{symbol_index::SymbolsDatabase, Change, RootDatabase};
|
||||
use crate::{symbol_index::SymbolsDatabase, ChangeWithProcMacros, RootDatabase};
|
||||
|
||||
impl RootDatabase {
|
||||
pub fn request_cancellation(&mut self) {
|
||||
@@ -20,7 +20,7 @@ pub fn request_cancellation(&mut self) {
|
||||
self.synthetic_write(Durability::LOW);
|
||||
}
|
||||
|
||||
pub fn apply_change(&mut self, change: Change) {
|
||||
pub fn apply_change(&mut self, change: ChangeWithProcMacros) {
|
||||
let _p = tracing::span!(tracing::Level::INFO, "RootDatabase::apply_change").entered();
|
||||
self.request_cancellation();
|
||||
tracing::trace!("apply_change {:?}", change);
|
||||
@@ -91,7 +91,6 @@ macro_rules! purge_each_query {
|
||||
crate::symbol_index::LocalRootsQuery
|
||||
crate::symbol_index::LibraryRootsQuery
|
||||
// HirDatabase
|
||||
hir::db::InferQueryQuery
|
||||
hir::db::MirBodyQuery
|
||||
hir::db::BorrowckQuery
|
||||
hir::db::TyQuery
|
||||
@@ -130,12 +129,10 @@ macro_rules! purge_each_query {
|
||||
hir::db::FnDefVarianceQuery
|
||||
hir::db::AdtVarianceQuery
|
||||
hir::db::AssociatedTyValueQuery
|
||||
hir::db::TraitSolveQueryQuery
|
||||
hir::db::ProgramClausesForChalkEnvQuery
|
||||
|
||||
// DefDatabase
|
||||
hir::db::FileItemTreeQuery
|
||||
hir::db::CrateDefMapQueryQuery
|
||||
hir::db::BlockDefMapQuery
|
||||
hir::db::StructDataWithDiagnosticsQuery
|
||||
hir::db::UnionDataWithDiagnosticsQuery
|
||||
@@ -165,7 +162,6 @@ macro_rules! purge_each_query {
|
||||
hir::db::FunctionVisibilityQuery
|
||||
hir::db::ConstVisibilityQuery
|
||||
hir::db::CrateSupportsNoStdQuery
|
||||
hir::db::BlockItemTreeQueryQuery
|
||||
hir::db::ExternCrateDeclDataQuery
|
||||
hir::db::InternAnonymousConstQuery
|
||||
hir::db::InternExternCrateQuery
|
||||
|
||||
@@ -22,6 +22,10 @@ pub struct LintGroup {
|
||||
description: r##"detects certain glob imports that require reporting an ambiguity error"##,
|
||||
},
|
||||
Lint { label: "ambiguous_glob_reexports", description: r##"ambiguous glob re-exports"## },
|
||||
Lint {
|
||||
label: "ambiguous_wide_pointer_comparisons",
|
||||
description: r##"detects ambiguous wide pointer comparisons"##,
|
||||
},
|
||||
Lint { label: "anonymous_parameters", description: r##"detects anonymous parameters"## },
|
||||
Lint { label: "arithmetic_overflow", description: r##"arithmetic operation overflows"## },
|
||||
Lint {
|
||||
@@ -66,10 +70,6 @@ pub struct LintGroup {
|
||||
label: "coherence_leak_check",
|
||||
description: r##"distinct impls distinguished only by the leak-check code"##,
|
||||
},
|
||||
Lint {
|
||||
label: "coinductive_overlap_in_coherence",
|
||||
description: r##"impls that are not considered to overlap may be considered to overlap in the future"##,
|
||||
},
|
||||
Lint {
|
||||
label: "conflicting_repr_hints",
|
||||
description: r##"conflicts between `#[repr(..)]` hints that were previously accepted and used in practice"##,
|
||||
@@ -86,10 +86,6 @@ pub struct LintGroup {
|
||||
label: "const_item_mutation",
|
||||
description: r##"detects attempts to mutate a `const` item"##,
|
||||
},
|
||||
Lint {
|
||||
label: "const_patterns_without_partial_eq",
|
||||
description: r##"constant in pattern does not implement `PartialEq`"##,
|
||||
},
|
||||
Lint { label: "dead_code", description: r##"detect unused, unexported items"## },
|
||||
Lint { label: "deprecated", description: r##"detects use of deprecated items"## },
|
||||
Lint {
|
||||
@@ -176,7 +172,7 @@ pub struct LintGroup {
|
||||
},
|
||||
Lint {
|
||||
label: "future_incompatible",
|
||||
description: r##"lint group for: deref-into-dyn-supertrait, ambiguous-associated-items, ambiguous-glob-imports, byte-slice-in-packed-struct-with-derive, cenum-impl-drop-cast, coherence-leak-check, coinductive-overlap-in-coherence, conflicting-repr-hints, const-evaluatable-unchecked, const-patterns-without-partial-eq, deprecated-cfg-attr-crate-type-name, elided-lifetimes-in-associated-constant, forbidden-lint-groups, ill-formed-attribute-input, illegal-floating-point-literal-pattern, implied-bounds-entailment, indirect-structural-match, invalid-doc-attributes, invalid-type-param-default, late-bound-lifetime-arguments, legacy-derive-helpers, macro-expanded-macro-exports-accessed-by-absolute-paths, missing-fragment-specifier, nontrivial-structural-match, order-dependent-trait-objects, patterns-in-fns-without-body, pointer-structural-match, proc-macro-back-compat, proc-macro-derive-resolution-fallback, pub-use-of-private-extern-crate, repr-transparent-external-private-fields, semicolon-in-expressions-from-macros, soft-unstable, suspicious-auto-trait-impls, uninhabited-static, unstable-name-collisions, unstable-syntax-pre-expansion, unsupported-calling-conventions, where-clauses-object-safety"##,
|
||||
description: r##"lint group for: deref-into-dyn-supertrait, ambiguous-associated-items, ambiguous-glob-imports, byte-slice-in-packed-struct-with-derive, cenum-impl-drop-cast, coherence-leak-check, conflicting-repr-hints, const-evaluatable-unchecked, deprecated-cfg-attr-crate-type-name, elided-lifetimes-in-associated-constant, forbidden-lint-groups, ill-formed-attribute-input, indirect-structural-match, invalid-doc-attributes, invalid-type-param-default, late-bound-lifetime-arguments, legacy-derive-helpers, macro-expanded-macro-exports-accessed-by-absolute-paths, missing-fragment-specifier, order-dependent-trait-objects, patterns-in-fns-without-body, pointer-structural-match, proc-macro-back-compat, proc-macro-derive-resolution-fallback, pub-use-of-private-extern-crate, repr-transparent-external-private-fields, semicolon-in-expressions-from-macros, soft-unstable, uninhabited-static, unstable-name-collisions, unstable-syntax-pre-expansion, unsupported-calling-conventions, where-clauses-object-safety, writes-through-immutable-pointer"##,
|
||||
},
|
||||
Lint {
|
||||
label: "fuzzy_provenance_casts",
|
||||
@@ -190,14 +186,6 @@ pub struct LintGroup {
|
||||
label: "ill_formed_attribute_input",
|
||||
description: r##"ill-formed attribute inputs that were previously accepted and used in practice"##,
|
||||
},
|
||||
Lint {
|
||||
label: "illegal_floating_point_literal_pattern",
|
||||
description: r##"floating-point literals cannot be used in patterns"##,
|
||||
},
|
||||
Lint {
|
||||
label: "implied_bounds_entailment",
|
||||
description: r##"impl method assumes more implied bounds than its corresponding trait method"##,
|
||||
},
|
||||
Lint {
|
||||
label: "improper_ctypes",
|
||||
description: r##"proper use of libc types in foreign modules"##,
|
||||
@@ -372,6 +360,7 @@ pub struct LintGroup {
|
||||
label: "non_fmt_panics",
|
||||
description: r##"detect single-argument panic!() invocations in which the argument is not a format string"##,
|
||||
},
|
||||
Lint { label: "non_local_definitions", description: r##"checks for non-local definitions"## },
|
||||
Lint {
|
||||
label: "non_shorthand_field_patterns",
|
||||
description: r##"using `Struct { x: x }` instead of `Struct { x }` in a pattern"##,
|
||||
@@ -388,10 +377,6 @@ pub struct LintGroup {
|
||||
label: "nonstandard_style",
|
||||
description: r##"lint group for: non-camel-case-types, non-snake-case, non-upper-case-globals"##,
|
||||
},
|
||||
Lint {
|
||||
label: "nontrivial_structural_match",
|
||||
description: r##"constant used in pattern of non-structural-match type and the constant's initializer expression contains values of non-structural-match types"##,
|
||||
},
|
||||
Lint {
|
||||
label: "noop_method_call",
|
||||
description: r##"detects the use of well-known noop methods"##,
|
||||
@@ -482,6 +467,10 @@ pub struct LintGroup {
|
||||
label: "rust_2021_prelude_collisions",
|
||||
description: r##"detects the usage of trait methods which are ambiguous with traits added to the prelude in future editions"##,
|
||||
},
|
||||
Lint {
|
||||
label: "rust_2024_compatibility",
|
||||
description: r##"lint group for: static-mut-refs, unsafe-op-in-unsafe-fn"##,
|
||||
},
|
||||
Lint {
|
||||
label: "semicolon_in_expressions_from_macros",
|
||||
description: r##"trailing semicolon in macro body used as expression"##,
|
||||
@@ -502,6 +491,10 @@ pub struct LintGroup {
|
||||
label: "stable_features",
|
||||
description: r##"stable features found in `#[feature]` directive"##,
|
||||
},
|
||||
Lint {
|
||||
label: "static_mut_refs",
|
||||
description: r##"shared references or mutable references of mutable static is discouraged"##,
|
||||
},
|
||||
Lint {
|
||||
label: "suspicious_double_ref_op",
|
||||
description: r##"suspicious call of trait method on `&&T`"##,
|
||||
@@ -575,6 +568,10 @@ pub struct LintGroup {
|
||||
description: r##"enabling track_caller on an async fn is a no-op unless the async_fn_track_caller feature is enabled"##,
|
||||
},
|
||||
Lint { label: "uninhabited_static", description: r##"uninhabited static"## },
|
||||
Lint {
|
||||
label: "unit_bindings",
|
||||
description: r##"binding is useless because it has the unit `()` type"##,
|
||||
},
|
||||
Lint {
|
||||
label: "unknown_crate_types",
|
||||
description: r##"unknown crate type found in `#[crate_type]` directive"##,
|
||||
@@ -606,10 +603,7 @@ pub struct LintGroup {
|
||||
label: "unsafe_op_in_unsafe_fn",
|
||||
description: r##"unsafe operations in unsafe functions without an explicit unsafe block are deprecated"##,
|
||||
},
|
||||
Lint {
|
||||
label: "unstable_features",
|
||||
description: r##"enabling unstable features (deprecated. do not use)"##,
|
||||
},
|
||||
Lint { label: "unstable_features", description: r##"enabling unstable features"## },
|
||||
Lint {
|
||||
label: "unstable_name_collisions",
|
||||
description: r##"detects name collision with an existing but unstable method"##,
|
||||
@@ -695,10 +689,6 @@ pub struct LintGroup {
|
||||
label: "unused_results",
|
||||
description: r##"unused result of an expression in a statement"##,
|
||||
},
|
||||
Lint {
|
||||
label: "unused_tuple_struct_fields",
|
||||
description: r##"detects tuple struct fields that are never read"##,
|
||||
},
|
||||
Lint { label: "unused_unsafe", description: r##"unnecessary use of an `unsafe` block"## },
|
||||
Lint {
|
||||
label: "unused_variables",
|
||||
@@ -732,13 +722,17 @@ pub struct LintGroup {
|
||||
label: "while_true",
|
||||
description: r##"suggest using `loop { }` instead of `while true { }`"##,
|
||||
},
|
||||
Lint {
|
||||
label: "writes_through_immutable_pointer",
|
||||
description: r##"shared references are immutable, and pointers derived from them must not be written to"##,
|
||||
},
|
||||
];
|
||||
|
||||
pub const DEFAULT_LINT_GROUPS: &[LintGroup] = &[
|
||||
LintGroup {
|
||||
lint: Lint {
|
||||
label: "future_incompatible",
|
||||
description: r##"lint group for: deref-into-dyn-supertrait, ambiguous-associated-items, ambiguous-glob-imports, byte-slice-in-packed-struct-with-derive, cenum-impl-drop-cast, coherence-leak-check, coinductive-overlap-in-coherence, conflicting-repr-hints, const-evaluatable-unchecked, const-patterns-without-partial-eq, deprecated-cfg-attr-crate-type-name, elided-lifetimes-in-associated-constant, forbidden-lint-groups, ill-formed-attribute-input, illegal-floating-point-literal-pattern, implied-bounds-entailment, indirect-structural-match, invalid-doc-attributes, invalid-type-param-default, late-bound-lifetime-arguments, legacy-derive-helpers, macro-expanded-macro-exports-accessed-by-absolute-paths, missing-fragment-specifier, nontrivial-structural-match, order-dependent-trait-objects, patterns-in-fns-without-body, pointer-structural-match, proc-macro-back-compat, proc-macro-derive-resolution-fallback, pub-use-of-private-extern-crate, repr-transparent-external-private-fields, semicolon-in-expressions-from-macros, soft-unstable, suspicious-auto-trait-impls, uninhabited-static, unstable-name-collisions, unstable-syntax-pre-expansion, unsupported-calling-conventions, where-clauses-object-safety"##,
|
||||
description: r##"lint group for: deref-into-dyn-supertrait, ambiguous-associated-items, ambiguous-glob-imports, byte-slice-in-packed-struct-with-derive, cenum-impl-drop-cast, coherence-leak-check, conflicting-repr-hints, const-evaluatable-unchecked, deprecated-cfg-attr-crate-type-name, elided-lifetimes-in-associated-constant, forbidden-lint-groups, ill-formed-attribute-input, indirect-structural-match, invalid-doc-attributes, invalid-type-param-default, late-bound-lifetime-arguments, legacy-derive-helpers, macro-expanded-macro-exports-accessed-by-absolute-paths, missing-fragment-specifier, order-dependent-trait-objects, patterns-in-fns-without-body, pointer-structural-match, proc-macro-back-compat, proc-macro-derive-resolution-fallback, pub-use-of-private-extern-crate, repr-transparent-external-private-fields, semicolon-in-expressions-from-macros, soft-unstable, uninhabited-static, unstable-name-collisions, unstable-syntax-pre-expansion, unsupported-calling-conventions, where-clauses-object-safety, writes-through-immutable-pointer"##,
|
||||
},
|
||||
children: &[
|
||||
"deref_into_dyn_supertrait",
|
||||
@@ -747,16 +741,12 @@ pub struct LintGroup {
|
||||
"byte_slice_in_packed_struct_with_derive",
|
||||
"cenum_impl_drop_cast",
|
||||
"coherence_leak_check",
|
||||
"coinductive_overlap_in_coherence",
|
||||
"conflicting_repr_hints",
|
||||
"const_evaluatable_unchecked",
|
||||
"const_patterns_without_partial_eq",
|
||||
"deprecated_cfg_attr_crate_type_name",
|
||||
"elided_lifetimes_in_associated_constant",
|
||||
"forbidden_lint_groups",
|
||||
"ill_formed_attribute_input",
|
||||
"illegal_floating_point_literal_pattern",
|
||||
"implied_bounds_entailment",
|
||||
"indirect_structural_match",
|
||||
"invalid_doc_attributes",
|
||||
"invalid_type_param_default",
|
||||
@@ -764,7 +754,6 @@ pub struct LintGroup {
|
||||
"legacy_derive_helpers",
|
||||
"macro_expanded_macro_exports_accessed_by_absolute_paths",
|
||||
"missing_fragment_specifier",
|
||||
"nontrivial_structural_match",
|
||||
"order_dependent_trait_objects",
|
||||
"patterns_in_fns_without_body",
|
||||
"pointer_structural_match",
|
||||
@@ -779,6 +768,7 @@ pub struct LintGroup {
|
||||
"unstable_syntax_pre_expansion",
|
||||
"unsupported_calling_conventions",
|
||||
"where_clauses_object_safety",
|
||||
"writes_through_immutable_pointer",
|
||||
],
|
||||
},
|
||||
LintGroup {
|
||||
@@ -836,6 +826,13 @@ pub struct LintGroup {
|
||||
"non_fmt_panics",
|
||||
],
|
||||
},
|
||||
LintGroup {
|
||||
lint: Lint {
|
||||
label: "rust_2024_compatibility",
|
||||
description: r##"lint group for: static-mut-refs, unsafe-op-in-unsafe-fn"##,
|
||||
},
|
||||
children: &["static_mut_refs", "unsafe_op_in_unsafe_fn"],
|
||||
},
|
||||
LintGroup {
|
||||
lint: Lint {
|
||||
label: "unused",
|
||||
@@ -1730,9 +1727,17 @@ pub fn device_function() {
|
||||
label: "async_fn_traits",
|
||||
description: r##"# `async_fn_traits`
|
||||
|
||||
This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use.
|
||||
See Also: [`fn_traits`](../library-features/fn-traits.md)
|
||||
|
||||
------------------------
|
||||
----
|
||||
|
||||
The `async_fn_traits` feature allows for implementation of the [`AsyncFn*`] traits
|
||||
for creating custom closure-like types that return futures.
|
||||
|
||||
[`AsyncFn*`]: ../../std/ops/trait.AsyncFn.html
|
||||
|
||||
The main difference to the `Fn*` family of traits is that `AsyncFn` can return a future
|
||||
that borrows from itself (`FnOnce::Output` has no lifetime parameters, while `AsyncFn::CallFuture` does).
|
||||
"##,
|
||||
},
|
||||
Lint {
|
||||
@@ -2372,17 +2377,6 @@ fn b() {
|
||||
|
||||
[#89653]: https://github.com/rust-lang/rust/issues/89653
|
||||
|
||||
------------------------
|
||||
"##,
|
||||
},
|
||||
Lint {
|
||||
label: "cfg_target_abi",
|
||||
description: r##"# `cfg_target_abi`
|
||||
|
||||
The tracking issue for this feature is: [#80970]
|
||||
|
||||
[#80970]: https://github.com/rust-lang/rust/issues/80970
|
||||
|
||||
------------------------
|
||||
"##,
|
||||
},
|
||||
@@ -3128,6 +3122,17 @@ fn foobar() -> u32 { 23 }
|
||||
|
||||
This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use.
|
||||
|
||||
------------------------
|
||||
"##,
|
||||
},
|
||||
Lint {
|
||||
label: "const_intrinsic_copy",
|
||||
description: r##"# `const_intrinsic_copy`
|
||||
|
||||
The tracking issue for this feature is: [#80697]
|
||||
|
||||
[#80697]: https://github.com/rust-lang/rust/issues/80697
|
||||
|
||||
------------------------
|
||||
"##,
|
||||
},
|
||||
@@ -3296,6 +3301,17 @@ fn foobar() -> u32 { 23 }
|
||||
|
||||
[#110840]: https://github.com/rust-lang/rust/issues/110840
|
||||
|
||||
------------------------
|
||||
"##,
|
||||
},
|
||||
Lint {
|
||||
label: "const_ops",
|
||||
description: r##"# `const_ops`
|
||||
|
||||
The tracking issue for this feature is: [#90080]
|
||||
|
||||
[#90080]: https://github.com/rust-lang/rust/issues/90080
|
||||
|
||||
------------------------
|
||||
"##,
|
||||
},
|
||||
@@ -3439,6 +3455,17 @@ fn foobar() -> u32 { 23 }
|
||||
|
||||
[#80384]: https://github.com/rust-lang/rust/issues/80384
|
||||
|
||||
------------------------
|
||||
"##,
|
||||
},
|
||||
Lint {
|
||||
label: "const_refs_to_static",
|
||||
description: r##"# `const_refs_to_static`
|
||||
|
||||
The tracking issue for this feature is: [#119618]
|
||||
|
||||
[#119618]: https://github.com/rust-lang/rust/issues/119618
|
||||
|
||||
------------------------
|
||||
"##,
|
||||
},
|
||||
@@ -4251,6 +4278,15 @@ fn my_runner(tests: &[&i32]) {
|
||||
|
||||
[#27336]: https://github.com/rust-lang/rust/issues/27336
|
||||
|
||||
------------------------
|
||||
"##,
|
||||
},
|
||||
Lint {
|
||||
label: "delayed_debug_assertions",
|
||||
description: r##"# `delayed_debug_assertions`
|
||||
|
||||
This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use.
|
||||
|
||||
------------------------
|
||||
"##,
|
||||
},
|
||||
@@ -4632,6 +4668,19 @@ pub fn my_fn() -> MyStruct { MyStruct }
|
||||
[#57391]: https://github.com/rust-lang/rust/issues/57391
|
||||
|
||||
------------------------
|
||||
"##,
|
||||
},
|
||||
Lint {
|
||||
label: "duration_constructors",
|
||||
description: r##"# `duration_constructors`
|
||||
|
||||
The tracking issue for this feature is: [#120301]
|
||||
|
||||
[#120301]: https://github.com/rust-lang/rust/issues/120301
|
||||
|
||||
------------------------
|
||||
|
||||
Add the methods `from_mins`, `from_hours` and `from_days` to `Duration`.
|
||||
"##,
|
||||
},
|
||||
Lint {
|
||||
@@ -4642,6 +4691,17 @@ pub fn my_fn() -> MyStruct { MyStruct }
|
||||
|
||||
[#72440]: https://github.com/rust-lang/rust/issues/72440
|
||||
|
||||
------------------------
|
||||
"##,
|
||||
},
|
||||
Lint {
|
||||
label: "duration_units",
|
||||
description: r##"# `duration_units`
|
||||
|
||||
The tracking issue for this feature is: [#120301]
|
||||
|
||||
[#120301]: https://github.com/rust-lang/rust/issues/120301
|
||||
|
||||
------------------------
|
||||
"##,
|
||||
},
|
||||
@@ -5654,13 +5714,62 @@ const fn one() -> i32 { 1 }
|
||||
|
||||
The tracking issue for this feature is: None.
|
||||
|
||||
Intrinsics are never intended to be stable directly, but intrinsics are often
|
||||
Intrinsics are rarely intended to be stable directly, but are usually
|
||||
exported in some sort of stable manner. Prefer using the stable interfaces to
|
||||
the intrinsic directly when you can.
|
||||
|
||||
------------------------
|
||||
|
||||
|
||||
## Intrinsics with fallback logic
|
||||
|
||||
Many intrinsics can be written in pure rust, albeit inefficiently or without supporting
|
||||
some features that only exist on some backends. Backends can simply not implement those
|
||||
intrinsics without causing any code miscompilations or failures to compile.
|
||||
All intrinsic fallback bodies are automatically made cross-crate inlineable (like `#[inline]`)
|
||||
by the codegen backend, but not the MIR inliner.
|
||||
|
||||
```rust
|
||||
#![feature(rustc_attrs, effects)]
|
||||
#![allow(internal_features)]
|
||||
|
||||
#[rustc_intrinsic]
|
||||
const unsafe fn const_deallocate(_ptr: *mut u8, _size: usize, _align: usize) {}
|
||||
```
|
||||
|
||||
Since these are just regular functions, it is perfectly ok to create the intrinsic twice:
|
||||
|
||||
```rust
|
||||
#![feature(rustc_attrs, effects)]
|
||||
#![allow(internal_features)]
|
||||
|
||||
#[rustc_intrinsic]
|
||||
const unsafe fn const_deallocate(_ptr: *mut u8, _size: usize, _align: usize) {}
|
||||
|
||||
mod foo {
|
||||
#[rustc_intrinsic]
|
||||
const unsafe fn const_deallocate(_ptr: *mut u8, _size: usize, _align: usize) {
|
||||
panic!("noisy const dealloc")
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
The behaviour on backends that override the intrinsic is exactly the same. On other
|
||||
backends, the intrinsic behaviour depends on which implementation is called, just like
|
||||
with any regular function.
|
||||
|
||||
## Intrinsics lowered to MIR instructions
|
||||
|
||||
Various intrinsics have native MIR operations that they correspond to. Instead of requiring
|
||||
backends to implement both the intrinsic and the MIR operation, the `lower_intrinsics` pass
|
||||
will convert the calls to the MIR operation. Backends do not need to know about these intrinsics
|
||||
at all.
|
||||
|
||||
## Intrinsics without fallback logic
|
||||
|
||||
These must be implemented by all backends.
|
||||
|
||||
These are imported as if they were FFI functions, with the special
|
||||
`rust-intrinsic` ABI. For example, if one was in a freestanding
|
||||
context, but wished to be able to `transmute` between types, and
|
||||
@@ -5679,7 +5788,8 @@ const fn one() -> i32 { 1 }
|
||||
}
|
||||
```
|
||||
|
||||
As with any other FFI functions, these are always `unsafe` to call.
|
||||
As with any other FFI functions, these are by default always `unsafe` to call.
|
||||
You can add `#[rustc_safe_intrinsic]` to the intrinsic to make it safe to call.
|
||||
"##,
|
||||
},
|
||||
Lint {
|
||||
@@ -5754,6 +5864,17 @@ const fn one() -> i32 { 1 }
|
||||
|
||||
[#101288]: https://github.com/rust-lang/rust/issues/101288
|
||||
|
||||
------------------------
|
||||
"##,
|
||||
},
|
||||
Lint {
|
||||
label: "is_riscv_feature_detected",
|
||||
description: r##"# `is_riscv_feature_detected`
|
||||
|
||||
The tracking issue for this feature is: [#111192]
|
||||
|
||||
[#111192]: https://github.com/rust-lang/rust/issues/111192
|
||||
|
||||
------------------------
|
||||
"##,
|
||||
},
|
||||
@@ -5932,6 +6053,17 @@ const fn one() -> i32 { 1 }
|
||||
|
||||
[#87053]: https://github.com/rust-lang/rust/issues/87053
|
||||
|
||||
------------------------
|
||||
"##,
|
||||
},
|
||||
Lint {
|
||||
label: "lahfsahf_target_feature",
|
||||
description: r##"# `lahfsahf_target_feature`
|
||||
|
||||
The tracking issue for this feature is: [#44839]
|
||||
|
||||
[#44839]: https://github.com/rust-lang/rust/issues/44839
|
||||
|
||||
------------------------
|
||||
"##,
|
||||
},
|
||||
@@ -6255,6 +6387,17 @@ fn panic_handler(_info: &PanicInfo) -> ! { intrinsics::abort() }
|
||||
|
||||
[#82971]: https://github.com/rust-lang/rust/issues/82971
|
||||
|
||||
------------------------
|
||||
"##,
|
||||
},
|
||||
Lint {
|
||||
label: "local_waker",
|
||||
description: r##"# `local_waker`
|
||||
|
||||
The tracking issue for this feature is: [#118959]
|
||||
|
||||
[#118959]: https://github.com/rust-lang/rust/issues/118959
|
||||
|
||||
------------------------
|
||||
"##,
|
||||
},
|
||||
@@ -6321,6 +6464,17 @@ fn panic_handler(_info: &PanicInfo) -> ! { intrinsics::abort() }
|
||||
|
||||
[#82766]: https://github.com/rust-lang/rust/issues/82766
|
||||
|
||||
------------------------
|
||||
"##,
|
||||
},
|
||||
Lint {
|
||||
label: "mapped_lock_guards",
|
||||
description: r##"# `mapped_lock_guards`
|
||||
|
||||
The tracking issue for this feature is: [#117108]
|
||||
|
||||
[#117108]: https://github.com/rust-lang/rust/issues/117108
|
||||
|
||||
------------------------
|
||||
"##,
|
||||
},
|
||||
@@ -6534,17 +6688,6 @@ impl A for Foo {
|
||||
|
||||
[#83310]: https://github.com/rust-lang/rust/issues/83310
|
||||
|
||||
------------------------
|
||||
"##,
|
||||
},
|
||||
Lint {
|
||||
label: "mutex_unlock",
|
||||
description: r##"# `mutex_unlock`
|
||||
|
||||
The tracking issue for this feature is: [#81872]
|
||||
|
||||
[#81872]: https://github.com/rust-lang/rust/issues/81872
|
||||
|
||||
------------------------
|
||||
"##,
|
||||
},
|
||||
@@ -6972,6 +7115,17 @@ fn foo() {
|
||||
|
||||
[#70086]: https://github.com/rust-lang/rust/issues/70086
|
||||
|
||||
------------------------
|
||||
"##,
|
||||
},
|
||||
Lint {
|
||||
label: "os_str_display",
|
||||
description: r##"# `os_str_display`
|
||||
|
||||
The tracking issue for this feature is: [#120048]
|
||||
|
||||
[#120048]: https://github.com/rust-lang/rust/issues/120048
|
||||
|
||||
------------------------
|
||||
"##,
|
||||
},
|
||||
@@ -7102,6 +7256,15 @@ fn foo() {
|
||||
|
||||
[#27721]: https://github.com/rust-lang/rust/issues/27721
|
||||
|
||||
------------------------
|
||||
"##,
|
||||
},
|
||||
Lint {
|
||||
label: "pattern_complexity",
|
||||
description: r##"# `pattern_complexity`
|
||||
|
||||
This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use.
|
||||
|
||||
------------------------
|
||||
"##,
|
||||
},
|
||||
@@ -7124,17 +7287,6 @@ fn foo() {
|
||||
|
||||
[#86918]: https://github.com/rust-lang/rust/issues/86918
|
||||
|
||||
------------------------
|
||||
"##,
|
||||
},
|
||||
Lint {
|
||||
label: "platform_intrinsics",
|
||||
description: r##"# `platform_intrinsics`
|
||||
|
||||
The tracking issue for this feature is: [#27731]
|
||||
|
||||
[#27731]: https://github.com/rust-lang/rust/issues/27731
|
||||
|
||||
------------------------
|
||||
"##,
|
||||
},
|
||||
@@ -7184,7 +7336,9 @@ fn foo() {
|
||||
label: "prelude_2024",
|
||||
description: r##"# `prelude_2024`
|
||||
|
||||
This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use.
|
||||
The tracking issue for this feature is: [#121042]
|
||||
|
||||
[#121042]: https://github.com/rust-lang/rust/issues/121042
|
||||
|
||||
------------------------
|
||||
"##,
|
||||
@@ -7195,6 +7349,17 @@ fn foo() {
|
||||
|
||||
This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use.
|
||||
|
||||
------------------------
|
||||
"##,
|
||||
},
|
||||
Lint {
|
||||
label: "prfchw_target_feature",
|
||||
description: r##"# `prfchw_target_feature`
|
||||
|
||||
The tracking issue for this feature is: [#44839]
|
||||
|
||||
[#44839]: https://github.com/rust-lang/rust/issues/44839
|
||||
|
||||
------------------------
|
||||
"##,
|
||||
},
|
||||
@@ -7507,6 +7672,17 @@ fn foo() {
|
||||
|
||||
This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use.
|
||||
|
||||
------------------------
|
||||
"##,
|
||||
},
|
||||
Lint {
|
||||
label: "reentrant_lock",
|
||||
description: r##"# `reentrant_lock`
|
||||
|
||||
The tracking issue for this feature is: [#121440]
|
||||
|
||||
[#121440]: https://github.com/rust-lang/rust/issues/121440
|
||||
|
||||
------------------------
|
||||
"##,
|
||||
},
|
||||
@@ -8177,6 +8353,39 @@ fn start(_argc: isize, _argv: *const *const u8) -> isize {
|
||||
|
||||
This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use.
|
||||
|
||||
------------------------
|
||||
"##,
|
||||
},
|
||||
Lint {
|
||||
label: "stdarch_arm_feature_detection",
|
||||
description: r##"# `stdarch_arm_feature_detection`
|
||||
|
||||
The tracking issue for this feature is: [#111190]
|
||||
|
||||
[#111190]: https://github.com/rust-lang/rust/issues/111190
|
||||
|
||||
------------------------
|
||||
"##,
|
||||
},
|
||||
Lint {
|
||||
label: "stdarch_mips_feature_detection",
|
||||
description: r##"# `stdarch_mips_feature_detection`
|
||||
|
||||
The tracking issue for this feature is: [#111188]
|
||||
|
||||
[#111188]: https://github.com/rust-lang/rust/issues/111188
|
||||
|
||||
------------------------
|
||||
"##,
|
||||
},
|
||||
Lint {
|
||||
label: "stdarch_powerpc_feature_detection",
|
||||
description: r##"# `stdarch_powerpc_feature_detection`
|
||||
|
||||
The tracking issue for this feature is: [#111191]
|
||||
|
||||
[#111191]: https://github.com/rust-lang/rust/issues/111191
|
||||
|
||||
------------------------
|
||||
"##,
|
||||
},
|
||||
@@ -8188,17 +8397,6 @@ fn start(_argc: isize, _argv: *const *const u8) -> isize {
|
||||
|
||||
[#98288]: https://github.com/rust-lang/rust/issues/98288
|
||||
|
||||
------------------------
|
||||
"##,
|
||||
},
|
||||
Lint {
|
||||
label: "stdsimd",
|
||||
description: r##"# `stdsimd`
|
||||
|
||||
The tracking issue for this feature is: [#48556]
|
||||
|
||||
[#48556]: https://github.com/rust-lang/rust/issues/48556
|
||||
|
||||
------------------------
|
||||
"##,
|
||||
},
|
||||
@@ -8459,6 +8657,17 @@ pub fn is_it_the_answer(value: Value) -> bool {
|
||||
|
||||
[#44839]: https://github.com/rust-lang/rust/issues/44839
|
||||
|
||||
------------------------
|
||||
"##,
|
||||
},
|
||||
Lint {
|
||||
label: "tcp_deferaccept",
|
||||
description: r##"# `tcp_deferaccept`
|
||||
|
||||
The tracking issue for this feature is: [#119639]
|
||||
|
||||
[#119639]: https://github.com/rust-lang/rust/issues/119639
|
||||
|
||||
------------------------
|
||||
"##,
|
||||
},
|
||||
@@ -10151,7 +10360,7 @@ fn bar() -> Option<String> {
|
||||
},
|
||||
Lint {
|
||||
label: "clippy::blocks_in_conditions",
|
||||
description: r##"Checks for `if` conditions that use blocks containing an
|
||||
description: r##"Checks for `if` and `match` conditions that use blocks containing an
|
||||
expression, statements or conditions that use closures with blocks."##,
|
||||
},
|
||||
Lint {
|
||||
@@ -10453,6 +10662,12 @@ fn bar() -> Option<String> {
|
||||
label: "clippy::deprecated_cfg_attr",
|
||||
description: r##"Checks for `#[cfg_attr(rustfmt, rustfmt_skip)]` and suggests to replace it
|
||||
with `#[rustfmt::skip]`."##,
|
||||
},
|
||||
Lint {
|
||||
label: "clippy::deprecated_clippy_cfg_attr",
|
||||
description: r##"Checks for `#[cfg_attr(feature = cargo-clippy, ...)]` and for
|
||||
`#[cfg(feature = cargo-clippy)]` and suggests to replace it with
|
||||
`#[cfg_attr(clippy, ...)]` or `#[cfg(clippy)]`."##,
|
||||
},
|
||||
Lint {
|
||||
label: "clippy::deprecated_semver",
|
||||
@@ -10596,6 +10811,7 @@ fn bar() -> Option<String> {
|
||||
description: r##"Checks for usage of if expressions with an `else if` branch,
|
||||
but without a final `else` branch."##,
|
||||
},
|
||||
Lint { label: "clippy::empty_docs", description: r##"Detects documentation that is empty."## },
|
||||
Lint {
|
||||
label: "clippy::empty_drop",
|
||||
description: r##"Checks for empty `Drop` implementations."##,
|
||||
@@ -11352,6 +11568,7 @@ fn bar() -> Option<String> {
|
||||
description: r##"Checks for usage of `std::mem::size_of::<T>() * 8` when
|
||||
`T::BITS` is available."##,
|
||||
},
|
||||
Lint { label: "clippy::manual_c_str_literals", description: r##""## },
|
||||
Lint {
|
||||
label: "clippy::manual_clamp",
|
||||
description: r##"Identifies good opportunities for a clamp function from std or core, and suggests using it."##,
|
||||
@@ -11726,6 +11943,10 @@ fn bar() -> Option<String> {
|
||||
label: "clippy::mistyped_literal_suffixes",
|
||||
description: r##"Warns for mistyped suffix in literals"##,
|
||||
},
|
||||
Lint {
|
||||
label: "clippy::mixed_attributes_style",
|
||||
description: r##"Checks that an item has only one kind of attributes."##,
|
||||
},
|
||||
Lint {
|
||||
label: "clippy::mixed_case_hex_literals",
|
||||
description: r##"Warns on hexadecimal literals with mixed-case letter
|
||||
@@ -11758,6 +11979,10 @@ fn bar() -> Option<String> {
|
||||
one."##,
|
||||
},
|
||||
Lint { label: "clippy::multi_assignments", description: r##"Checks for nested assignments."## },
|
||||
Lint {
|
||||
label: "clippy::multiple_bound_locations",
|
||||
description: r##"Check if a generic is defined both in the bound predicate and in the `where` clause."##,
|
||||
},
|
||||
Lint {
|
||||
label: "clippy::multiple_crate_versions",
|
||||
description: r##"Checks to see if multiple versions of a crate are being
|
||||
@@ -12331,8 +12556,8 @@ fn bar() -> Option<String> {
|
||||
Lint {
|
||||
label: "clippy::read_line_without_trim",
|
||||
description: r##"Looks for calls to [`Stdin::read_line`] to read a line from the standard input
|
||||
into a string, then later attempting to parse this string into a type without first trimming it, which will
|
||||
always fail because the string has a trailing newline in it."##,
|
||||
into a string, then later attempting to use that string for an operation that will never
|
||||
work for strings with a trailing newline character in it (e.g. parsing into a `i32`)."##,
|
||||
},
|
||||
Lint {
|
||||
label: "clippy::read_zero_byte_vec",
|
||||
@@ -12439,6 +12664,11 @@ fn bar() -> Option<String> {
|
||||
label: "clippy::redundant_type_annotations",
|
||||
description: r##"Warns about needless / redundant type annotations."##,
|
||||
},
|
||||
Lint {
|
||||
label: "clippy::ref_as_ptr",
|
||||
description: r##"Checks for casts of references to pointer using `as`
|
||||
and suggests `std::ptr::from_ref` and `std::ptr::from_mut` instead."##,
|
||||
},
|
||||
Lint {
|
||||
label: "clippy::ref_binding_to_reference",
|
||||
description: r##"Checks for `ref` bindings which create a reference to a reference."##,
|
||||
@@ -13090,6 +13320,11 @@ fn bar() -> Option<String> {
|
||||
label: "clippy::unnecessary_cast",
|
||||
description: r##"Checks for casts to the same type, casts of int literals to integer types, casts of float
|
||||
literals to float types and casts between raw pointers without changing type or constness."##,
|
||||
},
|
||||
Lint {
|
||||
label: "clippy::unnecessary_clippy_cfg",
|
||||
description: r##"Checks for `#[cfg_attr(clippy, allow(clippy::lint))]`
|
||||
and suggests to replace it with `#[allow(clippy::lint)]`."##,
|
||||
},
|
||||
Lint {
|
||||
label: "clippy::unnecessary_fallible_conversions",
|
||||
@@ -13114,6 +13349,10 @@ fn bar() -> Option<String> {
|
||||
Specifically, this checks for `fold`s which could be replaced by `any`, `all`,
|
||||
`sum` or `product`."##,
|
||||
},
|
||||
Lint {
|
||||
label: "clippy::unnecessary_get_then_check",
|
||||
description: r##"Checks the usage of `.get().is_some()` or `.get().is_none()` on std map types."##,
|
||||
},
|
||||
Lint {
|
||||
label: "clippy::unnecessary_join",
|
||||
description: r##"Checks for usage of `.collect::<Vec<String>>().join()` on iterators."##,
|
||||
@@ -13825,7 +14064,7 @@ fn bar() -> Option<String> {
|
||||
LintGroup {
|
||||
lint: Lint {
|
||||
label: "clippy::pedantic",
|
||||
description: r##"lint group for: clippy::bool_to_int_with_if, clippy::borrow_as_ptr, clippy::case_sensitive_file_extension_comparisons, clippy::cast_lossless, clippy::cast_possible_truncation, clippy::cast_possible_wrap, clippy::cast_precision_loss, clippy::cast_ptr_alignment, clippy::cast_sign_loss, clippy::checked_conversions, clippy::cloned_instead_of_copied, clippy::copy_iterator, clippy::default_trait_access, clippy::doc_link_with_quotes, clippy::doc_markdown, clippy::empty_enum, clippy::enum_glob_use, clippy::expl_impl_clone_on_copy, clippy::explicit_deref_methods, clippy::explicit_into_iter_loop, clippy::explicit_iter_loop, clippy::filter_map_next, clippy::flat_map_option, clippy::float_cmp, clippy::fn_params_excessive_bools, clippy::from_iter_instead_of_collect, clippy::if_not_else, clippy::ignored_unit_patterns, clippy::implicit_clone, clippy::implicit_hasher, clippy::inconsistent_struct_constructor, clippy::index_refutable_slice, clippy::inefficient_to_string, clippy::inline_always, clippy::into_iter_without_iter, clippy::invalid_upcast_comparisons, clippy::items_after_statements, clippy::iter_filter_is_ok, clippy::iter_filter_is_some, clippy::iter_not_returning_iterator, clippy::iter_without_into_iter, clippy::large_digit_groups, clippy::large_futures, clippy::large_stack_arrays, clippy::large_types_passed_by_value, clippy::linkedlist, clippy::macro_use_imports, clippy::manual_assert, clippy::manual_instant_elapsed, clippy::manual_is_variant_and, clippy::manual_let_else, clippy::manual_ok_or, clippy::manual_string_new, clippy::many_single_char_names, clippy::map_unwrap_or, clippy::match_bool, clippy::match_on_vec_items, clippy::match_same_arms, clippy::match_wild_err_arm, clippy::match_wildcard_for_single_variants, clippy::maybe_infinite_iter, clippy::mismatching_type_param_order, clippy::missing_errors_doc, clippy::missing_fields_in_debug, clippy::missing_panics_doc, clippy::module_name_repetitions, clippy::must_use_candidate, clippy::mut_mut, clippy::naive_bytecount, clippy::needless_bitwise_bool, clippy::needless_continue, clippy::needless_for_each, clippy::needless_pass_by_value, clippy::needless_raw_string_hashes, clippy::no_effect_underscore_binding, clippy::no_mangle_with_rust_abi, clippy::option_as_ref_cloned, clippy::option_option, clippy::ptr_as_ptr, clippy::ptr_cast_constness, clippy::pub_underscore_fields, clippy::range_minus_one, clippy::range_plus_one, clippy::redundant_closure_for_method_calls, clippy::redundant_else, clippy::ref_binding_to_reference, clippy::ref_option_ref, clippy::return_self_not_must_use, clippy::same_functions_in_if_condition, clippy::semicolon_if_nothing_returned, clippy::should_panic_without_expect, clippy::similar_names, clippy::single_match_else, clippy::stable_sort_primitive, clippy::str_split_at_newline, clippy::string_add_assign, clippy::struct_excessive_bools, clippy::struct_field_names, clippy::too_many_lines, clippy::transmute_ptr_to_ptr, clippy::trivially_copy_pass_by_ref, clippy::unchecked_duration_subtraction, clippy::unicode_not_nfc, clippy::uninlined_format_args, clippy::unnecessary_box_returns, clippy::unnecessary_join, clippy::unnecessary_wraps, clippy::unnested_or_patterns, clippy::unreadable_literal, clippy::unsafe_derive_deserialize, clippy::unused_async, clippy::unused_self, clippy::used_underscore_binding, clippy::verbose_bit_mask, clippy::wildcard_imports, clippy::zero_sized_map_values"##,
|
||||
description: r##"lint group for: clippy::bool_to_int_with_if, clippy::borrow_as_ptr, clippy::case_sensitive_file_extension_comparisons, clippy::cast_lossless, clippy::cast_possible_truncation, clippy::cast_possible_wrap, clippy::cast_precision_loss, clippy::cast_ptr_alignment, clippy::cast_sign_loss, clippy::checked_conversions, clippy::cloned_instead_of_copied, clippy::copy_iterator, clippy::default_trait_access, clippy::doc_link_with_quotes, clippy::doc_markdown, clippy::empty_enum, clippy::enum_glob_use, clippy::expl_impl_clone_on_copy, clippy::explicit_deref_methods, clippy::explicit_into_iter_loop, clippy::explicit_iter_loop, clippy::filter_map_next, clippy::flat_map_option, clippy::float_cmp, clippy::fn_params_excessive_bools, clippy::from_iter_instead_of_collect, clippy::if_not_else, clippy::ignored_unit_patterns, clippy::implicit_clone, clippy::implicit_hasher, clippy::inconsistent_struct_constructor, clippy::index_refutable_slice, clippy::inefficient_to_string, clippy::inline_always, clippy::into_iter_without_iter, clippy::invalid_upcast_comparisons, clippy::items_after_statements, clippy::iter_filter_is_ok, clippy::iter_filter_is_some, clippy::iter_not_returning_iterator, clippy::iter_without_into_iter, clippy::large_digit_groups, clippy::large_futures, clippy::large_stack_arrays, clippy::large_types_passed_by_value, clippy::linkedlist, clippy::macro_use_imports, clippy::manual_assert, clippy::manual_c_str_literals, clippy::manual_instant_elapsed, clippy::manual_is_variant_and, clippy::manual_let_else, clippy::manual_ok_or, clippy::manual_string_new, clippy::many_single_char_names, clippy::map_unwrap_or, clippy::match_bool, clippy::match_on_vec_items, clippy::match_same_arms, clippy::match_wild_err_arm, clippy::match_wildcard_for_single_variants, clippy::maybe_infinite_iter, clippy::mismatching_type_param_order, clippy::missing_errors_doc, clippy::missing_fields_in_debug, clippy::missing_panics_doc, clippy::module_name_repetitions, clippy::must_use_candidate, clippy::mut_mut, clippy::naive_bytecount, clippy::needless_bitwise_bool, clippy::needless_continue, clippy::needless_for_each, clippy::needless_pass_by_value, clippy::needless_raw_string_hashes, clippy::no_effect_underscore_binding, clippy::no_mangle_with_rust_abi, clippy::option_as_ref_cloned, clippy::option_option, clippy::ptr_as_ptr, clippy::ptr_cast_constness, clippy::pub_underscore_fields, clippy::range_minus_one, clippy::range_plus_one, clippy::redundant_closure_for_method_calls, clippy::redundant_else, clippy::ref_as_ptr, clippy::ref_binding_to_reference, clippy::ref_option_ref, clippy::return_self_not_must_use, clippy::same_functions_in_if_condition, clippy::semicolon_if_nothing_returned, clippy::should_panic_without_expect, clippy::similar_names, clippy::single_match_else, clippy::stable_sort_primitive, clippy::str_split_at_newline, clippy::string_add_assign, clippy::struct_excessive_bools, clippy::struct_field_names, clippy::too_many_lines, clippy::transmute_ptr_to_ptr, clippy::trivially_copy_pass_by_ref, clippy::unchecked_duration_subtraction, clippy::unicode_not_nfc, clippy::uninlined_format_args, clippy::unnecessary_box_returns, clippy::unnecessary_join, clippy::unnecessary_wraps, clippy::unnested_or_patterns, clippy::unreadable_literal, clippy::unsafe_derive_deserialize, clippy::unused_async, clippy::unused_self, clippy::used_underscore_binding, clippy::verbose_bit_mask, clippy::wildcard_imports, clippy::zero_sized_map_values"##,
|
||||
},
|
||||
children: &[
|
||||
"clippy::bool_to_int_with_if",
|
||||
@@ -13876,6 +14115,7 @@ fn bar() -> Option<String> {
|
||||
"clippy::linkedlist",
|
||||
"clippy::macro_use_imports",
|
||||
"clippy::manual_assert",
|
||||
"clippy::manual_c_str_literals",
|
||||
"clippy::manual_instant_elapsed",
|
||||
"clippy::manual_is_variant_and",
|
||||
"clippy::manual_let_else",
|
||||
@@ -13913,6 +14153,7 @@ fn bar() -> Option<String> {
|
||||
"clippy::range_plus_one",
|
||||
"clippy::redundant_closure_for_method_calls",
|
||||
"clippy::redundant_else",
|
||||
"clippy::ref_as_ptr",
|
||||
"clippy::ref_binding_to_reference",
|
||||
"clippy::ref_option_ref",
|
||||
"clippy::return_self_not_must_use",
|
||||
@@ -14257,7 +14498,7 @@ fn bar() -> Option<String> {
|
||||
LintGroup {
|
||||
lint: Lint {
|
||||
label: "clippy::suspicious",
|
||||
description: r##"lint group for: clippy::almost_complete_range, clippy::arc_with_non_send_sync, clippy::await_holding_invalid_type, clippy::await_holding_lock, clippy::await_holding_refcell_ref, clippy::blanket_clippy_restriction_lints, clippy::cast_abs_to_unsigned, clippy::cast_enum_constructor, clippy::cast_enum_truncation, clippy::cast_nan_to_int, clippy::cast_slice_from_raw_parts, clippy::crate_in_macro_def, clippy::drop_non_drop, clippy::duplicate_mod, clippy::empty_loop, clippy::float_equality_without_abs, clippy::forget_non_drop, clippy::four_forward_slashes, clippy::from_raw_with_void_ptr, clippy::incompatible_msrv, clippy::ineffective_open_options, clippy::iter_out_of_bounds, clippy::join_absolute_paths, clippy::let_underscore_future, clippy::lines_filter_map_ok, clippy::maybe_misused_cfg, clippy::misnamed_getters, clippy::misrefactored_assign_op, clippy::multi_assignments, clippy::mut_range_bound, clippy::mutable_key_type, clippy::no_effect_replace, clippy::non_canonical_clone_impl, clippy::non_canonical_partial_ord_impl, clippy::octal_escapes, clippy::path_ends_with_ext, clippy::permissions_set_readonly_false, clippy::print_in_format_impl, clippy::rc_clone_in_vec_init, clippy::repeat_vec_with_capacity, clippy::single_range_in_vec_init, clippy::size_of_ref, clippy::suspicious_arithmetic_impl, clippy::suspicious_assignment_formatting, clippy::suspicious_command_arg_space, clippy::suspicious_doc_comments, clippy::suspicious_else_formatting, clippy::suspicious_map, clippy::suspicious_op_assign_impl, clippy::suspicious_open_options, clippy::suspicious_to_owned, clippy::suspicious_unary_op_formatting, clippy::swap_ptr_to_ref, clippy::test_attr_in_doctest, clippy::type_id_on_box, clippy::unconditional_recursion, clippy::unnecessary_result_map_or_else"##,
|
||||
description: r##"lint group for: clippy::almost_complete_range, clippy::arc_with_non_send_sync, clippy::await_holding_invalid_type, clippy::await_holding_lock, clippy::await_holding_refcell_ref, clippy::blanket_clippy_restriction_lints, clippy::cast_abs_to_unsigned, clippy::cast_enum_constructor, clippy::cast_enum_truncation, clippy::cast_nan_to_int, clippy::cast_slice_from_raw_parts, clippy::crate_in_macro_def, clippy::deprecated_clippy_cfg_attr, clippy::drop_non_drop, clippy::duplicate_mod, clippy::empty_docs, clippy::empty_loop, clippy::float_equality_without_abs, clippy::forget_non_drop, clippy::four_forward_slashes, clippy::from_raw_with_void_ptr, clippy::incompatible_msrv, clippy::ineffective_open_options, clippy::iter_out_of_bounds, clippy::join_absolute_paths, clippy::let_underscore_future, clippy::lines_filter_map_ok, clippy::maybe_misused_cfg, clippy::misnamed_getters, clippy::misrefactored_assign_op, clippy::mixed_attributes_style, clippy::multi_assignments, clippy::multiple_bound_locations, clippy::mut_range_bound, clippy::mutable_key_type, clippy::no_effect_replace, clippy::non_canonical_clone_impl, clippy::non_canonical_partial_ord_impl, clippy::octal_escapes, clippy::path_ends_with_ext, clippy::permissions_set_readonly_false, clippy::print_in_format_impl, clippy::rc_clone_in_vec_init, clippy::repeat_vec_with_capacity, clippy::single_range_in_vec_init, clippy::size_of_ref, clippy::suspicious_arithmetic_impl, clippy::suspicious_assignment_formatting, clippy::suspicious_command_arg_space, clippy::suspicious_doc_comments, clippy::suspicious_else_formatting, clippy::suspicious_map, clippy::suspicious_op_assign_impl, clippy::suspicious_open_options, clippy::suspicious_to_owned, clippy::suspicious_unary_op_formatting, clippy::swap_ptr_to_ref, clippy::test_attr_in_doctest, clippy::type_id_on_box, clippy::unconditional_recursion, clippy::unnecessary_clippy_cfg, clippy::unnecessary_get_then_check, clippy::unnecessary_result_map_or_else"##,
|
||||
},
|
||||
children: &[
|
||||
"clippy::almost_complete_range",
|
||||
@@ -14272,8 +14513,10 @@ fn bar() -> Option<String> {
|
||||
"clippy::cast_nan_to_int",
|
||||
"clippy::cast_slice_from_raw_parts",
|
||||
"clippy::crate_in_macro_def",
|
||||
"clippy::deprecated_clippy_cfg_attr",
|
||||
"clippy::drop_non_drop",
|
||||
"clippy::duplicate_mod",
|
||||
"clippy::empty_docs",
|
||||
"clippy::empty_loop",
|
||||
"clippy::float_equality_without_abs",
|
||||
"clippy::forget_non_drop",
|
||||
@@ -14288,7 +14531,9 @@ fn bar() -> Option<String> {
|
||||
"clippy::maybe_misused_cfg",
|
||||
"clippy::misnamed_getters",
|
||||
"clippy::misrefactored_assign_op",
|
||||
"clippy::mixed_attributes_style",
|
||||
"clippy::multi_assignments",
|
||||
"clippy::multiple_bound_locations",
|
||||
"clippy::mut_range_bound",
|
||||
"clippy::mutable_key_type",
|
||||
"clippy::no_effect_replace",
|
||||
@@ -14316,6 +14561,8 @@ fn bar() -> Option<String> {
|
||||
"clippy::test_attr_in_doctest",
|
||||
"clippy::type_id_on_box",
|
||||
"clippy::unconditional_recursion",
|
||||
"clippy::unnecessary_clippy_cfg",
|
||||
"clippy::unnecessary_get_then_check",
|
||||
"clippy::unnecessary_result_map_or_else",
|
||||
],
|
||||
},
|
||||
|
||||
@@ -64,7 +64,7 @@ pub fn visit_file_defs(
|
||||
cb: &mut dyn FnMut(Definition),
|
||||
) {
|
||||
let db = sema.db;
|
||||
let module = match sema.to_module_def(file_id) {
|
||||
let module = match sema.file_to_module_def(file_id) {
|
||||
Some(it) => it,
|
||||
None => return,
|
||||
};
|
||||
|
||||
@@ -44,7 +44,7 @@ pub mod syntax_helpers {
|
||||
pub use parser::LexedStr;
|
||||
}
|
||||
|
||||
pub use hir::Change;
|
||||
pub use hir::ChangeWithProcMacros;
|
||||
|
||||
use std::{fmt, mem::ManuallyDrop};
|
||||
|
||||
@@ -216,7 +216,6 @@ macro_rules! update_lru_capacity_per_query {
|
||||
|
||||
// DefDatabase
|
||||
hir_db::FileItemTreeQuery
|
||||
hir_db::CrateDefMapQueryQuery
|
||||
hir_db::BlockDefMapQuery
|
||||
hir_db::StructDataWithDiagnosticsQuery
|
||||
hir_db::UnionDataWithDiagnosticsQuery
|
||||
@@ -248,7 +247,6 @@ macro_rules! update_lru_capacity_per_query {
|
||||
hir_db::CrateSupportsNoStdQuery
|
||||
|
||||
// HirDatabase
|
||||
hir_db::InferQueryQuery
|
||||
hir_db::MirBodyQuery
|
||||
hir_db::BorrowckQuery
|
||||
hir_db::TyQuery
|
||||
@@ -287,7 +285,6 @@ macro_rules! update_lru_capacity_per_query {
|
||||
hir_db::FnDefVarianceQuery
|
||||
hir_db::AdtVarianceQuery
|
||||
hir_db::AssociatedTyValueQuery
|
||||
hir_db::TraitSolveQueryQuery
|
||||
hir_db::ProgramClausesForChalkEnvQuery
|
||||
|
||||
// SymbolsDatabase
|
||||
@@ -412,9 +409,3 @@ pub const fn new(allow_snippets: bool) -> Option<SnippetCap> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
mod line_index;
|
||||
mod sourcegen_lints;
|
||||
}
|
||||
|
||||
@@ -129,7 +129,7 @@ enum ParallelPrimeCacheWorkerProgress {
|
||||
crates_currently_indexing.insert(crate_id, crate_name);
|
||||
}
|
||||
ParallelPrimeCacheWorkerProgress::EndCrate { crate_id } => {
|
||||
crates_currently_indexing.remove(&crate_id);
|
||||
crates_currently_indexing.swap_remove(&crate_id);
|
||||
crates_to_prime.mark_done(crate_id);
|
||||
crates_done += 1;
|
||||
}
|
||||
|
||||
@@ -11,15 +11,12 @@ pub enum Arg {
|
||||
Expr(String),
|
||||
}
|
||||
|
||||
/**
|
||||
Add placeholders like `$1` and `$2` in place of [`Arg::Placeholder`],
|
||||
and unwraps the [`Arg::Ident`] and [`Arg::Expr`] enums.
|
||||
```rust
|
||||
# use ide_db::syntax_helpers::format_string_exprs::*;
|
||||
assert_eq!(with_placeholders(vec![Arg::Ident("ident".to_owned()), Arg::Placeholder, Arg::Expr("expr + 2".to_owned())]), vec!["ident".to_owned(), "$1".to_owned(), "expr + 2".to_owned()])
|
||||
```
|
||||
*/
|
||||
|
||||
/// Add placeholders like `$1` and `$2` in place of [`Arg::Placeholder`],
|
||||
/// and unwraps the [`Arg::Ident`] and [`Arg::Expr`] enums.
|
||||
/// ```rust
|
||||
/// # use ide_db::syntax_helpers::format_string_exprs::*;
|
||||
/// assert_eq!(with_placeholders(vec![Arg::Ident("ident".to_owned()), Arg::Placeholder, Arg::Expr("expr + 2".to_owned())]), vec!["ident".to_owned(), "$1".to_owned(), "expr + 2".to_owned()])
|
||||
/// ```
|
||||
pub fn with_placeholders(args: Vec<Arg>) -> Vec<String> {
|
||||
let mut placeholder_id = 1;
|
||||
args.into_iter()
|
||||
@@ -34,18 +31,15 @@ pub fn with_placeholders(args: Vec<Arg>) -> Vec<String> {
|
||||
.collect()
|
||||
}
|
||||
|
||||
/**
|
||||
Parser for a format-like string. It is more allowing in terms of string contents,
|
||||
as we expect variable placeholders to be filled with expressions.
|
||||
|
||||
Built for completions and assists, and escapes `\` and `$` in output.
|
||||
(See the comments on `get_receiver_text()` for detail.)
|
||||
Splits a format string that may contain expressions
|
||||
like
|
||||
```rust
|
||||
assert_eq!(parse("{ident} {} {expr + 42} ").unwrap(), ("{} {} {}", vec![Arg::Ident("ident"), Arg::Placeholder, Arg::Expr("expr + 42")]));
|
||||
```
|
||||
*/
|
||||
/// Parser for a format-like string. It is more allowing in terms of string contents,
|
||||
/// as we expect variable placeholders to be filled with expressions.
|
||||
///
|
||||
/// Splits a format string that may contain expressions
|
||||
/// like
|
||||
/// ```rust
|
||||
/// # use ide_db::syntax_helpers::format_string_exprs::*;
|
||||
/// assert_eq!(parse_format_exprs("{ident} {} {expr + 42} ").unwrap(), ("{ident} {} {} ".to_owned(), vec![Arg::Placeholder, Arg::Expr("expr + 42".to_owned())]));
|
||||
/// ```
|
||||
pub fn parse_format_exprs(input: &str) -> Result<(String, Vec<Arg>), ()> {
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
enum State {
|
||||
@@ -79,9 +73,6 @@ enum State {
|
||||
state = State::MaybeIncorrect;
|
||||
}
|
||||
(State::NotArg, _) => {
|
||||
if matches!(chr, '\\' | '$') {
|
||||
output.push('\\');
|
||||
}
|
||||
output.push(chr);
|
||||
}
|
||||
(State::MaybeIncorrect, '}') => {
|
||||
@@ -110,9 +101,6 @@ enum State {
|
||||
state = State::FormatOpts;
|
||||
}
|
||||
(State::MaybeArg, _) => {
|
||||
if matches!(chr, '\\' | '$') {
|
||||
current_expr.push('\\');
|
||||
}
|
||||
current_expr.push(chr);
|
||||
|
||||
// While Rust uses the unicode sets of XID_start and XID_continue for Identifiers
|
||||
@@ -172,9 +160,6 @@ enum State {
|
||||
state = State::Expr;
|
||||
}
|
||||
|
||||
if matches!(chr, '\\' | '$') {
|
||||
current_expr.push('\\');
|
||||
}
|
||||
current_expr.push(chr);
|
||||
}
|
||||
(State::FormatOpts, '}') => {
|
||||
@@ -182,9 +167,6 @@ enum State {
|
||||
state = State::NotArg;
|
||||
}
|
||||
(State::FormatOpts, _) => {
|
||||
if matches!(chr, '\\' | '$') {
|
||||
output.push('\\');
|
||||
}
|
||||
output.push(chr);
|
||||
}
|
||||
}
|
||||
@@ -217,15 +199,15 @@ fn check(input: &str, expect: &Expect) {
|
||||
fn format_str_parser() {
|
||||
let test_vector = &[
|
||||
("no expressions", expect![["no expressions"]]),
|
||||
(r"no expressions with \$0$1", expect![r"no expressions with \\\$0\$1"]),
|
||||
(r"no expressions with \$0$1", expect![r"no expressions with \$0$1"]),
|
||||
("{expr} is {2 + 2}", expect![["{expr} is {}; 2 + 2"]]),
|
||||
("{expr:?}", expect![["{expr:?}"]]),
|
||||
("{expr:1$}", expect![[r"{expr:1\$}"]]),
|
||||
("{:1$}", expect![[r"{:1\$}; $1"]]),
|
||||
("{:>padding$}", expect![[r"{:>padding\$}; $1"]]),
|
||||
("{expr:1$}", expect![[r"{expr:1$}"]]),
|
||||
("{:1$}", expect![[r"{:1$}; $1"]]),
|
||||
("{:>padding$}", expect![[r"{:>padding$}; $1"]]),
|
||||
("{}, {}, {0}", expect![[r"{}, {}, {0}; $1, $2"]]),
|
||||
("{}, {}, {0:b}", expect![[r"{}, {}, {0:b}; $1, $2"]]),
|
||||
("{$0}", expect![[r"{}; \$0"]]),
|
||||
("{$0}", expect![[r"{}; $0"]]),
|
||||
("{malformed", expect![["-"]]),
|
||||
("malformed}", expect![["-"]]),
|
||||
("{{correct", expect![["{{correct"]]),
|
||||
|
||||
+3
-6
@@ -20,7 +20,7 @@ pub fn insert_ws_into(syn: SyntaxNode) -> SyntaxNode {
|
||||
let after = Position::after;
|
||||
|
||||
let do_indent = |pos: fn(_) -> Position, token: &SyntaxToken, indent| {
|
||||
(pos(token.clone()), make::tokens::whitespace(&" ".repeat(2 * indent)))
|
||||
(pos(token.clone()), make::tokens::whitespace(&" ".repeat(4 * indent)))
|
||||
};
|
||||
let do_ws = |pos: fn(_) -> Position, token: &SyntaxToken| {
|
||||
(pos(token.clone()), make::tokens::single_space())
|
||||
@@ -41,7 +41,7 @@ pub fn insert_ws_into(syn: SyntaxNode) -> SyntaxNode {
|
||||
if indent > 0 {
|
||||
mods.push((
|
||||
Position::after(node.clone()),
|
||||
make::tokens::whitespace(&" ".repeat(2 * indent)),
|
||||
make::tokens::whitespace(&" ".repeat(4 * indent)),
|
||||
));
|
||||
}
|
||||
if node.parent().is_some() {
|
||||
@@ -91,10 +91,7 @@ pub fn insert_ws_into(syn: SyntaxNode) -> SyntaxNode {
|
||||
LIFETIME_IDENT if is_next(is_text, true) => {
|
||||
mods.push(do_ws(after, tok));
|
||||
}
|
||||
MUT_KW if is_next(|it| it == SELF_KW, false) => {
|
||||
mods.push(do_ws(after, tok));
|
||||
}
|
||||
AS_KW | DYN_KW | IMPL_KW | CONST_KW => {
|
||||
AS_KW | DYN_KW | IMPL_KW | CONST_KW | MUT_KW => {
|
||||
mods.push(do_ws(after, tok));
|
||||
}
|
||||
T![;] if is_next(|it| it != R_CURLY, true) => {
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
use line_index::{LineCol, LineIndex, WideEncoding};
|
||||
use test_utils::skip_slow_tests;
|
||||
|
||||
#[test]
|
||||
fn test_every_chars() {
|
||||
if skip_slow_tests() {
|
||||
return;
|
||||
}
|
||||
|
||||
let text: String = {
|
||||
let mut chars: Vec<char> = ((0 as char)..char::MAX).collect(); // Neat!
|
||||
chars.extend("\n".repeat(chars.len() / 16).chars());
|
||||
let mut rng = oorandom::Rand32::new(stdx::rand::seed());
|
||||
stdx::rand::shuffle(&mut chars, |i| rng.rand_range(0..i as u32) as usize);
|
||||
chars.into_iter().collect()
|
||||
};
|
||||
assert!(text.contains('💩')); // Sanity check.
|
||||
|
||||
let line_index = LineIndex::new(&text);
|
||||
|
||||
let mut lin_col = LineCol { line: 0, col: 0 };
|
||||
let mut col_utf16 = 0;
|
||||
let mut col_utf32 = 0;
|
||||
for (offset, c) in text.char_indices() {
|
||||
let got_offset = line_index.offset(lin_col).unwrap();
|
||||
assert_eq!(usize::from(got_offset), offset);
|
||||
|
||||
let got_lin_col = line_index.line_col(got_offset);
|
||||
assert_eq!(got_lin_col, lin_col);
|
||||
|
||||
for (enc, col) in [(WideEncoding::Utf16, col_utf16), (WideEncoding::Utf32, col_utf32)] {
|
||||
let wide_lin_col = line_index.to_wide(enc, lin_col).unwrap();
|
||||
let got_lin_col = line_index.to_utf8(enc, wide_lin_col).unwrap();
|
||||
assert_eq!(got_lin_col, lin_col);
|
||||
assert_eq!(wide_lin_col.col, col)
|
||||
}
|
||||
|
||||
if c == '\n' {
|
||||
lin_col.line += 1;
|
||||
lin_col.col = 0;
|
||||
col_utf16 = 0;
|
||||
col_utf32 = 0;
|
||||
} else {
|
||||
lin_col.col += c.len_utf8() as u32;
|
||||
col_utf16 += c.len_utf16() as u32;
|
||||
col_utf32 += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,6 @@ tracing.workspace = true
|
||||
once_cell = "1.17.0"
|
||||
|
||||
# local deps
|
||||
profile.workspace = true
|
||||
stdx.workspace = true
|
||||
syntax.workspace = true
|
||||
text-edit.workspace = true
|
||||
@@ -34,10 +33,6 @@ expect-test = "1.4.0"
|
||||
# local deps
|
||||
test-utils.workspace = true
|
||||
test-fixture.workspace = true
|
||||
sourcegen.workspace = true
|
||||
|
||||
[features]
|
||||
in-rust-tree = []
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
@@ -200,7 +200,7 @@ fn get_default_constructor(
|
||||
}
|
||||
}
|
||||
|
||||
let krate = ctx.sema.to_module_def(d.file.original_file(ctx.sema.db))?.krate();
|
||||
let krate = ctx.sema.file_to_module_def(d.file.original_file(ctx.sema.db))?.krate();
|
||||
let module = krate.root_module();
|
||||
|
||||
// Look for a ::new() associated function
|
||||
|
||||
@@ -597,21 +597,19 @@ fn bang(never: !) {
|
||||
|
||||
#[test]
|
||||
fn unknown_type() {
|
||||
cov_mark::check_count!(validate_match_bailed_out, 1);
|
||||
|
||||
check_diagnostics(
|
||||
check_diagnostics_no_bails(
|
||||
r#"
|
||||
enum Option<T> { Some(T), None }
|
||||
|
||||
#[allow(unused)]
|
||||
fn main() {
|
||||
// `Never` is deliberately not defined so that it's an uninferred type.
|
||||
// We ignore these to avoid triggering bugs in the analysis.
|
||||
match Option::<Never>::None {
|
||||
None => (),
|
||||
Some(never) => match never {},
|
||||
}
|
||||
match Option::<Never>::None {
|
||||
//^^^^^^^^^^^^^^^^^^^^^ error: missing match arm: `None` not covered
|
||||
Option::Some(_never) => {},
|
||||
}
|
||||
}
|
||||
@@ -619,6 +617,18 @@ fn main() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn arity_mismatch_issue_16746() {
|
||||
check_diagnostics_with_disabled(
|
||||
r#"
|
||||
fn main() {
|
||||
let (a, ) = (0, 0);
|
||||
}
|
||||
"#,
|
||||
&["E0308"],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tuple_of_bools_with_ellipsis_at_end_missing_arm() {
|
||||
check_diagnostics_no_bails(
|
||||
|
||||
@@ -30,6 +30,7 @@ pub(crate) fn remove_unnecessary_else(
|
||||
"remove unnecessary else block",
|
||||
display_range,
|
||||
)
|
||||
.experimental()
|
||||
.with_fixes(fixes(ctx, d))
|
||||
}
|
||||
|
||||
|
||||
@@ -227,6 +227,7 @@ pub struct DiagnosticsConfig {
|
||||
pub disable_experimental: bool,
|
||||
pub disabled: FxHashSet<String>,
|
||||
pub expr_fill_default: ExprFillDefaultMode,
|
||||
pub style_lints: bool,
|
||||
// FIXME: We may want to include a whole `AssistConfig` here
|
||||
pub insert_use: InsertUseConfig,
|
||||
pub prefer_no_std: bool,
|
||||
@@ -245,6 +246,7 @@ pub fn test_sample() -> Self {
|
||||
disable_experimental: Default::default(),
|
||||
disabled: Default::default(),
|
||||
expr_fill_default: Default::default(),
|
||||
style_lints: true,
|
||||
insert_use: InsertUseConfig {
|
||||
granularity: ImportGranularity::Preserve,
|
||||
enforce_granularity: false,
|
||||
@@ -299,7 +301,7 @@ pub fn diagnostics(
|
||||
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(parse.errors().iter().take(128).map(|err| {
|
||||
res.extend(parse.errors().into_iter().take(128).map(|err| {
|
||||
Diagnostic::new(
|
||||
DiagnosticCode::RustcHardError("syntax-error"),
|
||||
format!("Syntax Error: {err}"),
|
||||
@@ -315,7 +317,7 @@ pub fn diagnostics(
|
||||
handlers::json_is_not_rust::json_in_items(&sema, &mut res, file_id, &node, config);
|
||||
}
|
||||
|
||||
let module = sema.to_module_def(file_id);
|
||||
let module = sema.file_to_module_def(file_id);
|
||||
|
||||
let ctx = DiagnosticsContext { config, sema, resolve };
|
||||
if module.is_none() {
|
||||
@@ -324,7 +326,7 @@ pub fn diagnostics(
|
||||
|
||||
let mut diags = Vec::new();
|
||||
if let Some(m) = module {
|
||||
m.diagnostics(db, &mut diags);
|
||||
m.diagnostics(db, &mut diags, config.style_lints);
|
||||
}
|
||||
|
||||
for diag in diags {
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
#![allow(clippy::print_stderr)]
|
||||
#[cfg(not(feature = "in-rust-tree"))]
|
||||
mod sourcegen;
|
||||
|
||||
use ide_db::{
|
||||
assists::AssistResolveStrategy, base_db::SourceDatabaseExt, LineIndexDatabase, RootDatabase,
|
||||
|
||||
@@ -17,11 +17,11 @@ arrayvec.workspace = true
|
||||
either.workspace = true
|
||||
itertools.workspace = true
|
||||
tracing.workspace = true
|
||||
oorandom = "11.1.3"
|
||||
pulldown-cmark-to-cmark = "10.0.4"
|
||||
pulldown-cmark = { version = "0.9.1", default-features = false }
|
||||
url = "2.3.1"
|
||||
dot = "0.1.4"
|
||||
oorandom.workspace = true
|
||||
pulldown-cmark-to-cmark.workspace = true
|
||||
pulldown-cmark.workspace = true
|
||||
url.workspace = true
|
||||
dot.workspace = true
|
||||
smallvec.workspace = true
|
||||
triomphe.workspace = true
|
||||
nohash-hasher.workspace = true
|
||||
@@ -51,8 +51,5 @@ expect-test = "1.4.0"
|
||||
test-utils.workspace = true
|
||||
test-fixture.workspace = true
|
||||
|
||||
[features]
|
||||
in-rust-tree = ["ide-assists/in-rust-tree", "ide-diagnostics/in-rust-tree"]
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
@@ -189,7 +189,7 @@ fn _format(
|
||||
let &crate_id = db.relevant_crates(file_id).iter().next()?;
|
||||
let edition = db.crate_graph()[crate_id].edition;
|
||||
|
||||
let mut cmd = std::process::Command::new(toolchain::rustfmt());
|
||||
let mut cmd = std::process::Command::new(toolchain::Tool::Rustfmt.path());
|
||||
cmd.arg("--edition");
|
||||
cmd.arg(edition.to_string());
|
||||
|
||||
@@ -308,8 +308,8 @@ fn some_thing() -> u32 {
|
||||
expect![[r#"
|
||||
foo!
|
||||
fn some_thing() -> u32 {
|
||||
let a = 0;
|
||||
a+10
|
||||
let a = 0;
|
||||
a+10
|
||||
}"#]],
|
||||
);
|
||||
}
|
||||
@@ -342,13 +342,13 @@ fn main() {
|
||||
expect![[r#"
|
||||
match_ast!
|
||||
{
|
||||
if let Some(it) = ast::TraitDef::cast(container.clone()){}
|
||||
else if let Some(it) = ast::ImplDef::cast(container.clone()){}
|
||||
else {
|
||||
{
|
||||
continue
|
||||
if let Some(it) = ast::TraitDef::cast(container.clone()){}
|
||||
else if let Some(it) = ast::ImplDef::cast(container.clone()){}
|
||||
else {
|
||||
{
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
}"#]],
|
||||
);
|
||||
}
|
||||
@@ -397,12 +397,12 @@ fn main() {
|
||||
expect![[r#"
|
||||
foo!
|
||||
{
|
||||
macro_rules! bar {
|
||||
() => {
|
||||
42
|
||||
macro_rules! bar {
|
||||
() => {
|
||||
42
|
||||
}
|
||||
}
|
||||
}
|
||||
42
|
||||
42
|
||||
}"#]],
|
||||
);
|
||||
}
|
||||
@@ -482,16 +482,16 @@ struct Foo {}
|
||||
expect![[r#"
|
||||
Clone
|
||||
impl < >$crate::clone::Clone for Foo< >where {
|
||||
fn clone(&self) -> Self {
|
||||
match self {
|
||||
Foo{}
|
||||
=> Foo{}
|
||||
,
|
||||
fn clone(&self) -> Self {
|
||||
match self {
|
||||
Foo{}
|
||||
=> Foo{}
|
||||
,
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}"#]],
|
||||
}"#]],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -534,16 +534,16 @@ struct Foo {}
|
||||
expect![[r#"
|
||||
Clone
|
||||
impl < >$crate::clone::Clone for Foo< >where {
|
||||
fn clone(&self) -> Self {
|
||||
match self {
|
||||
Foo{}
|
||||
=> Foo{}
|
||||
,
|
||||
fn clone(&self) -> Self {
|
||||
match self {
|
||||
Foo{}
|
||||
=> Foo{}
|
||||
,
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}"#]],
|
||||
}"#]],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -536,6 +536,24 @@ fn bar() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn goto_definition_works_for_consts_inside_range_pattern() {
|
||||
check(
|
||||
r#"
|
||||
//- /lib.rs
|
||||
const A: u32 = 0;
|
||||
//^
|
||||
|
||||
fn bar(v: u32) {
|
||||
match v {
|
||||
0..=$0A => {}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn goto_def_for_use_alias() {
|
||||
check(
|
||||
|
||||
@@ -32,6 +32,7 @@ pub struct HoverConfig {
|
||||
pub documentation: bool,
|
||||
pub keywords: bool,
|
||||
pub format: HoverDocFormat,
|
||||
pub max_trait_assoc_items_count: Option<usize>,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
|
||||
@@ -406,7 +406,12 @@ pub(super) fn definition(
|
||||
config: &HoverConfig,
|
||||
) -> Markup {
|
||||
let mod_path = definition_mod_path(db, &def);
|
||||
let label = def.label(db);
|
||||
let label = match def {
|
||||
Definition::Trait(trait_) => {
|
||||
trait_.display_limited(db, config.max_trait_assoc_items_count).to_string()
|
||||
}
|
||||
_ => def.label(db),
|
||||
};
|
||||
let docs = def.docs(db, famous_defs);
|
||||
let value = (|| match def {
|
||||
Definition::Variant(it) => {
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
documentation: true,
|
||||
format: HoverDocFormat::Markdown,
|
||||
keywords: true,
|
||||
max_trait_assoc_items_count: None,
|
||||
};
|
||||
|
||||
fn check_hover_no_result(ra_fixture: &str) {
|
||||
@@ -48,6 +49,28 @@ fn check(ra_fixture: &str, expect: Expect) {
|
||||
expect.assert_eq(&actual)
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
fn check_assoc_count(count: usize, ra_fixture: &str, expect: Expect) {
|
||||
let (analysis, position) = fixture::position(ra_fixture);
|
||||
let hover = analysis
|
||||
.hover(
|
||||
&HoverConfig {
|
||||
links_in_hover: true,
|
||||
max_trait_assoc_items_count: Some(count),
|
||||
..HOVER_BASE_CONFIG
|
||||
},
|
||||
FileRange { file_id: position.file_id, range: TextRange::empty(position.offset) },
|
||||
)
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
|
||||
let content = analysis.db.file_text(position.file_id);
|
||||
let hovered_element = &content[hover.range];
|
||||
|
||||
let actual = format!("*{hovered_element}*\n{}\n", hover.info.markup);
|
||||
expect.assert_eq(&actual)
|
||||
}
|
||||
|
||||
fn check_hover_no_links(ra_fixture: &str, expect: Expect) {
|
||||
let (analysis, position) = fixture::position(ra_fixture);
|
||||
let hover = analysis
|
||||
@@ -2672,26 +2695,26 @@ fn foo() -> impl Foo {}
|
||||
fn main() { let s$0t = foo(); }
|
||||
"#,
|
||||
expect![[r#"
|
||||
[
|
||||
GoToType(
|
||||
[
|
||||
HoverGotoTypeData {
|
||||
mod_path: "test::Foo",
|
||||
nav: NavigationTarget {
|
||||
file_id: FileId(
|
||||
0,
|
||||
),
|
||||
full_range: 0..12,
|
||||
focus_range: 6..9,
|
||||
name: "Foo",
|
||||
kind: Trait,
|
||||
description: "trait Foo",
|
||||
},
|
||||
[
|
||||
GoToType(
|
||||
[
|
||||
HoverGotoTypeData {
|
||||
mod_path: "test::Foo",
|
||||
nav: NavigationTarget {
|
||||
file_id: FileId(
|
||||
0,
|
||||
),
|
||||
full_range: 0..12,
|
||||
focus_range: 6..9,
|
||||
name: "Foo",
|
||||
kind: Trait,
|
||||
description: "trait Foo",
|
||||
},
|
||||
],
|
||||
),
|
||||
]
|
||||
"#]],
|
||||
},
|
||||
],
|
||||
),
|
||||
]
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2706,39 +2729,39 @@ fn foo() -> impl Foo<S> {}
|
||||
fn main() { let s$0t = foo(); }
|
||||
"#,
|
||||
expect![[r#"
|
||||
[
|
||||
GoToType(
|
||||
[
|
||||
HoverGotoTypeData {
|
||||
mod_path: "test::Foo",
|
||||
nav: NavigationTarget {
|
||||
file_id: FileId(
|
||||
0,
|
||||
),
|
||||
full_range: 0..15,
|
||||
focus_range: 6..9,
|
||||
name: "Foo",
|
||||
kind: Trait,
|
||||
description: "trait Foo<T>",
|
||||
},
|
||||
[
|
||||
GoToType(
|
||||
[
|
||||
HoverGotoTypeData {
|
||||
mod_path: "test::Foo",
|
||||
nav: NavigationTarget {
|
||||
file_id: FileId(
|
||||
0,
|
||||
),
|
||||
full_range: 0..15,
|
||||
focus_range: 6..9,
|
||||
name: "Foo",
|
||||
kind: Trait,
|
||||
description: "trait Foo<T>",
|
||||
},
|
||||
HoverGotoTypeData {
|
||||
mod_path: "test::S",
|
||||
nav: NavigationTarget {
|
||||
file_id: FileId(
|
||||
0,
|
||||
),
|
||||
full_range: 16..25,
|
||||
focus_range: 23..24,
|
||||
name: "S",
|
||||
kind: Struct,
|
||||
description: "struct S",
|
||||
},
|
||||
},
|
||||
HoverGotoTypeData {
|
||||
mod_path: "test::S",
|
||||
nav: NavigationTarget {
|
||||
file_id: FileId(
|
||||
0,
|
||||
),
|
||||
full_range: 16..25,
|
||||
focus_range: 23..24,
|
||||
name: "S",
|
||||
kind: Struct,
|
||||
description: "struct S",
|
||||
},
|
||||
],
|
||||
),
|
||||
]
|
||||
"#]],
|
||||
},
|
||||
],
|
||||
),
|
||||
]
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2873,26 +2896,26 @@ trait Foo {}
|
||||
fn foo(ar$0g: &impl Foo) {}
|
||||
"#,
|
||||
expect![[r#"
|
||||
[
|
||||
GoToType(
|
||||
[
|
||||
HoverGotoTypeData {
|
||||
mod_path: "test::Foo",
|
||||
nav: NavigationTarget {
|
||||
file_id: FileId(
|
||||
0,
|
||||
),
|
||||
full_range: 0..12,
|
||||
focus_range: 6..9,
|
||||
name: "Foo",
|
||||
kind: Trait,
|
||||
description: "trait Foo",
|
||||
},
|
||||
[
|
||||
GoToType(
|
||||
[
|
||||
HoverGotoTypeData {
|
||||
mod_path: "test::Foo",
|
||||
nav: NavigationTarget {
|
||||
file_id: FileId(
|
||||
0,
|
||||
),
|
||||
full_range: 0..12,
|
||||
focus_range: 6..9,
|
||||
name: "Foo",
|
||||
kind: Trait,
|
||||
description: "trait Foo",
|
||||
},
|
||||
],
|
||||
),
|
||||
]
|
||||
"#]],
|
||||
},
|
||||
],
|
||||
),
|
||||
]
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -3020,39 +3043,39 @@ struct S {}
|
||||
fn foo(ar$0g: &impl Foo<S>) {}
|
||||
"#,
|
||||
expect![[r#"
|
||||
[
|
||||
GoToType(
|
||||
[
|
||||
HoverGotoTypeData {
|
||||
mod_path: "test::Foo",
|
||||
nav: NavigationTarget {
|
||||
file_id: FileId(
|
||||
0,
|
||||
),
|
||||
full_range: 0..15,
|
||||
focus_range: 6..9,
|
||||
name: "Foo",
|
||||
kind: Trait,
|
||||
description: "trait Foo<T>",
|
||||
},
|
||||
[
|
||||
GoToType(
|
||||
[
|
||||
HoverGotoTypeData {
|
||||
mod_path: "test::Foo",
|
||||
nav: NavigationTarget {
|
||||
file_id: FileId(
|
||||
0,
|
||||
),
|
||||
full_range: 0..15,
|
||||
focus_range: 6..9,
|
||||
name: "Foo",
|
||||
kind: Trait,
|
||||
description: "trait Foo<T>",
|
||||
},
|
||||
HoverGotoTypeData {
|
||||
mod_path: "test::S",
|
||||
nav: NavigationTarget {
|
||||
file_id: FileId(
|
||||
0,
|
||||
),
|
||||
full_range: 16..27,
|
||||
focus_range: 23..24,
|
||||
name: "S",
|
||||
kind: Struct,
|
||||
description: "struct S {}",
|
||||
},
|
||||
},
|
||||
HoverGotoTypeData {
|
||||
mod_path: "test::S",
|
||||
nav: NavigationTarget {
|
||||
file_id: FileId(
|
||||
0,
|
||||
),
|
||||
full_range: 16..27,
|
||||
focus_range: 23..24,
|
||||
name: "S",
|
||||
kind: Struct,
|
||||
description: "struct S {}",
|
||||
},
|
||||
],
|
||||
),
|
||||
]
|
||||
"#]],
|
||||
},
|
||||
],
|
||||
),
|
||||
]
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -3070,39 +3093,39 @@ fn foo() -> B<dyn Foo> {}
|
||||
fn main() { let s$0t = foo(); }
|
||||
"#,
|
||||
expect![[r#"
|
||||
[
|
||||
GoToType(
|
||||
[
|
||||
HoverGotoTypeData {
|
||||
mod_path: "test::B",
|
||||
nav: NavigationTarget {
|
||||
file_id: FileId(
|
||||
0,
|
||||
),
|
||||
full_range: 42..55,
|
||||
focus_range: 49..50,
|
||||
name: "B",
|
||||
kind: Struct,
|
||||
description: "struct B<T> {}",
|
||||
},
|
||||
[
|
||||
GoToType(
|
||||
[
|
||||
HoverGotoTypeData {
|
||||
mod_path: "test::B",
|
||||
nav: NavigationTarget {
|
||||
file_id: FileId(
|
||||
0,
|
||||
),
|
||||
full_range: 42..55,
|
||||
focus_range: 49..50,
|
||||
name: "B",
|
||||
kind: Struct,
|
||||
description: "struct B<T> {}",
|
||||
},
|
||||
HoverGotoTypeData {
|
||||
mod_path: "test::Foo",
|
||||
nav: NavigationTarget {
|
||||
file_id: FileId(
|
||||
0,
|
||||
),
|
||||
full_range: 0..12,
|
||||
focus_range: 6..9,
|
||||
name: "Foo",
|
||||
kind: Trait,
|
||||
description: "trait Foo",
|
||||
},
|
||||
},
|
||||
HoverGotoTypeData {
|
||||
mod_path: "test::Foo",
|
||||
nav: NavigationTarget {
|
||||
file_id: FileId(
|
||||
0,
|
||||
),
|
||||
full_range: 0..12,
|
||||
focus_range: 6..9,
|
||||
name: "Foo",
|
||||
kind: Trait,
|
||||
description: "trait Foo",
|
||||
},
|
||||
],
|
||||
),
|
||||
]
|
||||
"#]],
|
||||
},
|
||||
],
|
||||
),
|
||||
]
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -3114,26 +3137,26 @@ trait Foo {}
|
||||
fn foo(ar$0g: &dyn Foo) {}
|
||||
"#,
|
||||
expect![[r#"
|
||||
[
|
||||
GoToType(
|
||||
[
|
||||
HoverGotoTypeData {
|
||||
mod_path: "test::Foo",
|
||||
nav: NavigationTarget {
|
||||
file_id: FileId(
|
||||
0,
|
||||
),
|
||||
full_range: 0..12,
|
||||
focus_range: 6..9,
|
||||
name: "Foo",
|
||||
kind: Trait,
|
||||
description: "trait Foo",
|
||||
},
|
||||
[
|
||||
GoToType(
|
||||
[
|
||||
HoverGotoTypeData {
|
||||
mod_path: "test::Foo",
|
||||
nav: NavigationTarget {
|
||||
file_id: FileId(
|
||||
0,
|
||||
),
|
||||
full_range: 0..12,
|
||||
focus_range: 6..9,
|
||||
name: "Foo",
|
||||
kind: Trait,
|
||||
description: "trait Foo",
|
||||
},
|
||||
],
|
||||
),
|
||||
]
|
||||
"#]],
|
||||
},
|
||||
],
|
||||
),
|
||||
]
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -3146,39 +3169,39 @@ struct S {}
|
||||
fn foo(ar$0g: &dyn Foo<S>) {}
|
||||
"#,
|
||||
expect![[r#"
|
||||
[
|
||||
GoToType(
|
||||
[
|
||||
HoverGotoTypeData {
|
||||
mod_path: "test::Foo",
|
||||
nav: NavigationTarget {
|
||||
file_id: FileId(
|
||||
0,
|
||||
),
|
||||
full_range: 0..15,
|
||||
focus_range: 6..9,
|
||||
name: "Foo",
|
||||
kind: Trait,
|
||||
description: "trait Foo<T>",
|
||||
},
|
||||
[
|
||||
GoToType(
|
||||
[
|
||||
HoverGotoTypeData {
|
||||
mod_path: "test::Foo",
|
||||
nav: NavigationTarget {
|
||||
file_id: FileId(
|
||||
0,
|
||||
),
|
||||
full_range: 0..15,
|
||||
focus_range: 6..9,
|
||||
name: "Foo",
|
||||
kind: Trait,
|
||||
description: "trait Foo<T>",
|
||||
},
|
||||
HoverGotoTypeData {
|
||||
mod_path: "test::S",
|
||||
nav: NavigationTarget {
|
||||
file_id: FileId(
|
||||
0,
|
||||
),
|
||||
full_range: 16..27,
|
||||
focus_range: 23..24,
|
||||
name: "S",
|
||||
kind: Struct,
|
||||
description: "struct S {}",
|
||||
},
|
||||
},
|
||||
HoverGotoTypeData {
|
||||
mod_path: "test::S",
|
||||
nav: NavigationTarget {
|
||||
file_id: FileId(
|
||||
0,
|
||||
),
|
||||
full_range: 16..27,
|
||||
focus_range: 23..24,
|
||||
name: "S",
|
||||
kind: Struct,
|
||||
description: "struct S {}",
|
||||
},
|
||||
],
|
||||
),
|
||||
]
|
||||
"#]],
|
||||
},
|
||||
],
|
||||
),
|
||||
]
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -3275,26 +3298,26 @@ fn test() -> impl Foo { S {} }
|
||||
fn main() { let s$0t = test().get(); }
|
||||
"#,
|
||||
expect![[r#"
|
||||
[
|
||||
GoToType(
|
||||
[
|
||||
HoverGotoTypeData {
|
||||
mod_path: "test::Foo",
|
||||
nav: NavigationTarget {
|
||||
file_id: FileId(
|
||||
0,
|
||||
),
|
||||
full_range: 0..62,
|
||||
focus_range: 6..9,
|
||||
name: "Foo",
|
||||
kind: Trait,
|
||||
description: "trait Foo",
|
||||
},
|
||||
[
|
||||
GoToType(
|
||||
[
|
||||
HoverGotoTypeData {
|
||||
mod_path: "test::Foo",
|
||||
nav: NavigationTarget {
|
||||
file_id: FileId(
|
||||
0,
|
||||
),
|
||||
full_range: 0..62,
|
||||
focus_range: 6..9,
|
||||
name: "Foo",
|
||||
kind: Trait,
|
||||
description: "trait Foo",
|
||||
},
|
||||
],
|
||||
),
|
||||
]
|
||||
"#]],
|
||||
},
|
||||
],
|
||||
),
|
||||
]
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -3340,26 +3363,26 @@ trait Foo {}
|
||||
fn foo<T: Foo>(t: T$0){}
|
||||
"#,
|
||||
expect![[r#"
|
||||
[
|
||||
GoToType(
|
||||
[
|
||||
HoverGotoTypeData {
|
||||
mod_path: "test::Foo",
|
||||
nav: NavigationTarget {
|
||||
file_id: FileId(
|
||||
0,
|
||||
),
|
||||
full_range: 0..12,
|
||||
focus_range: 6..9,
|
||||
name: "Foo",
|
||||
kind: Trait,
|
||||
description: "trait Foo",
|
||||
},
|
||||
[
|
||||
GoToType(
|
||||
[
|
||||
HoverGotoTypeData {
|
||||
mod_path: "test::Foo",
|
||||
nav: NavigationTarget {
|
||||
file_id: FileId(
|
||||
0,
|
||||
),
|
||||
full_range: 0..12,
|
||||
focus_range: 6..9,
|
||||
name: "Foo",
|
||||
kind: Trait,
|
||||
description: "trait Foo",
|
||||
},
|
||||
],
|
||||
),
|
||||
]
|
||||
"#]],
|
||||
},
|
||||
],
|
||||
),
|
||||
]
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -5434,13 +5457,62 @@ fn hover_feature() {
|
||||
|
||||
The tracking issue for this feature is: None.
|
||||
|
||||
Intrinsics are never intended to be stable directly, but intrinsics are often
|
||||
Intrinsics are rarely intended to be stable directly, but are usually
|
||||
exported in some sort of stable manner. Prefer using the stable interfaces to
|
||||
the intrinsic directly when you can.
|
||||
|
||||
------------------------
|
||||
|
||||
|
||||
## Intrinsics with fallback logic
|
||||
|
||||
Many intrinsics can be written in pure rust, albeit inefficiently or without supporting
|
||||
some features that only exist on some backends. Backends can simply not implement those
|
||||
intrinsics without causing any code miscompilations or failures to compile.
|
||||
All intrinsic fallback bodies are automatically made cross-crate inlineable (like `#[inline]`)
|
||||
by the codegen backend, but not the MIR inliner.
|
||||
|
||||
```rust
|
||||
#![feature(rustc_attrs, effects)]
|
||||
#![allow(internal_features)]
|
||||
|
||||
#[rustc_intrinsic]
|
||||
const unsafe fn const_deallocate(_ptr: *mut u8, _size: usize, _align: usize) {}
|
||||
```
|
||||
|
||||
Since these are just regular functions, it is perfectly ok to create the intrinsic twice:
|
||||
|
||||
```rust
|
||||
#![feature(rustc_attrs, effects)]
|
||||
#![allow(internal_features)]
|
||||
|
||||
#[rustc_intrinsic]
|
||||
const unsafe fn const_deallocate(_ptr: *mut u8, _size: usize, _align: usize) {}
|
||||
|
||||
mod foo {
|
||||
#[rustc_intrinsic]
|
||||
const unsafe fn const_deallocate(_ptr: *mut u8, _size: usize, _align: usize) {
|
||||
panic!("noisy const dealloc")
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
The behaviour on backends that override the intrinsic is exactly the same. On other
|
||||
backends, the intrinsic behaviour depends on which implementation is called, just like
|
||||
with any regular function.
|
||||
|
||||
## Intrinsics lowered to MIR instructions
|
||||
|
||||
Various intrinsics have native MIR operations that they correspond to. Instead of requiring
|
||||
backends to implement both the intrinsic and the MIR operation, the `lower_intrinsics` pass
|
||||
will convert the calls to the MIR operation. Backends do not need to know about these intrinsics
|
||||
at all.
|
||||
|
||||
## Intrinsics without fallback logic
|
||||
|
||||
These must be implemented by all backends.
|
||||
|
||||
These are imported as if they were FFI functions, with the special
|
||||
`rust-intrinsic` ABI. For example, if one was in a freestanding
|
||||
context, but wished to be able to `transmute` between types, and
|
||||
@@ -5459,7 +5531,8 @@ fn hover_feature() {
|
||||
}
|
||||
```
|
||||
|
||||
As with any other FFI functions, these are always `unsafe` to call.
|
||||
As with any other FFI functions, these are by default always `unsafe` to call.
|
||||
You can add `#[rustc_safe_intrinsic]` to the intrinsic to make it safe to call.
|
||||
|
||||
"#]],
|
||||
)
|
||||
@@ -6277,6 +6350,151 @@ fn func()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hover_trait_show_assoc_items() {
|
||||
check_assoc_count(
|
||||
0,
|
||||
r#"
|
||||
trait T {}
|
||||
impl T$0 for () {}
|
||||
"#,
|
||||
expect![[r#"
|
||||
*T*
|
||||
|
||||
```rust
|
||||
test
|
||||
```
|
||||
|
||||
```rust
|
||||
trait T {}
|
||||
```
|
||||
"#]],
|
||||
);
|
||||
|
||||
check_assoc_count(
|
||||
1,
|
||||
r#"
|
||||
trait T {}
|
||||
impl T$0 for () {}
|
||||
"#,
|
||||
expect![[r#"
|
||||
*T*
|
||||
|
||||
```rust
|
||||
test
|
||||
```
|
||||
|
||||
```rust
|
||||
trait T {}
|
||||
```
|
||||
"#]],
|
||||
);
|
||||
|
||||
check_assoc_count(
|
||||
0,
|
||||
r#"
|
||||
trait T {
|
||||
fn func() {}
|
||||
const FLAG: i32 = 34;
|
||||
type Bar;
|
||||
}
|
||||
impl T$0 for () {}
|
||||
"#,
|
||||
expect![[r#"
|
||||
*T*
|
||||
|
||||
```rust
|
||||
test
|
||||
```
|
||||
|
||||
```rust
|
||||
trait T { /* … */ }
|
||||
```
|
||||
"#]],
|
||||
);
|
||||
|
||||
check_assoc_count(
|
||||
2,
|
||||
r#"
|
||||
trait T {
|
||||
fn func() {}
|
||||
const FLAG: i32 = 34;
|
||||
type Bar;
|
||||
}
|
||||
impl T$0 for () {}
|
||||
"#,
|
||||
expect![[r#"
|
||||
*T*
|
||||
|
||||
```rust
|
||||
test
|
||||
```
|
||||
|
||||
```rust
|
||||
trait T {
|
||||
fn func();
|
||||
const FLAG: i32;
|
||||
/* … */
|
||||
}
|
||||
```
|
||||
"#]],
|
||||
);
|
||||
|
||||
check_assoc_count(
|
||||
3,
|
||||
r#"
|
||||
trait T {
|
||||
fn func() {}
|
||||
const FLAG: i32 = 34;
|
||||
type Bar;
|
||||
}
|
||||
impl T$0 for () {}
|
||||
"#,
|
||||
expect![[r#"
|
||||
*T*
|
||||
|
||||
```rust
|
||||
test
|
||||
```
|
||||
|
||||
```rust
|
||||
trait T {
|
||||
fn func();
|
||||
const FLAG: i32;
|
||||
type Bar;
|
||||
}
|
||||
```
|
||||
"#]],
|
||||
);
|
||||
|
||||
check_assoc_count(
|
||||
4,
|
||||
r#"
|
||||
trait T {
|
||||
fn func() {}
|
||||
const FLAG: i32 = 34;
|
||||
type Bar;
|
||||
}
|
||||
impl T$0 for () {}
|
||||
"#,
|
||||
expect![[r#"
|
||||
*T*
|
||||
|
||||
```rust
|
||||
test
|
||||
```
|
||||
|
||||
```rust
|
||||
trait T {
|
||||
fn func();
|
||||
const FLAG: i32;
|
||||
type Bar;
|
||||
}
|
||||
```
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hover_ranged_macro_call() {
|
||||
check_hover_range(
|
||||
@@ -6366,8 +6584,8 @@ macro_rules! m {
|
||||
|
||||
```rust
|
||||
pub const V: i8 = {
|
||||
let e = 123;
|
||||
f(e)
|
||||
let e = 123;
|
||||
f(e)
|
||||
}
|
||||
```
|
||||
"#]],
|
||||
@@ -6393,7 +6611,7 @@ macro_rules! m {
|
||||
|
||||
```rust
|
||||
pub static V: i8 = {
|
||||
let e = 123;
|
||||
let e = 123;
|
||||
}
|
||||
```
|
||||
"#]],
|
||||
|
||||
@@ -50,6 +50,7 @@
|
||||
mod status;
|
||||
mod syntax_highlighting;
|
||||
mod syntax_tree;
|
||||
mod test_explorer;
|
||||
mod typing;
|
||||
mod view_crate_graph;
|
||||
mod view_hir;
|
||||
@@ -61,7 +62,7 @@
|
||||
|
||||
use cfg::CfgOptions;
|
||||
use fetch_crates::CrateInfo;
|
||||
use hir::Change;
|
||||
use hir::ChangeWithProcMacros;
|
||||
use ide_db::{
|
||||
base_db::{
|
||||
salsa::{self, ParallelDatabase},
|
||||
@@ -108,6 +109,7 @@
|
||||
tags::{Highlight, HlMod, HlMods, HlOperator, HlPunct, HlTag},
|
||||
HighlightConfig, HlRange,
|
||||
},
|
||||
test_explorer::{TestItem, TestItemKind},
|
||||
};
|
||||
pub use hir::Semantics;
|
||||
pub use ide_assists::{
|
||||
@@ -184,7 +186,7 @@ pub fn analysis(&self) -> Analysis {
|
||||
|
||||
/// Applies changes to the current state of the world. If there are
|
||||
/// outstanding snapshots, they will be canceled.
|
||||
pub fn apply_change(&mut self, change: Change) {
|
||||
pub fn apply_change(&mut self, change: ChangeWithProcMacros) {
|
||||
self.db.apply_change(change);
|
||||
}
|
||||
|
||||
@@ -239,7 +241,7 @@ pub fn from_single_file(text: String) -> (Analysis, FileId) {
|
||||
file_set.insert(file_id, VfsPath::new_virtual_path("/main.rs".to_owned()));
|
||||
let source_root = SourceRoot::new_local(file_set);
|
||||
|
||||
let mut change = Change::new();
|
||||
let mut change = ChangeWithProcMacros::new();
|
||||
change.set_roots(vec![source_root]);
|
||||
let mut crate_graph = CrateGraph::default();
|
||||
// FIXME: cfg options
|
||||
@@ -340,6 +342,18 @@ pub fn view_item_tree(&self, file_id: FileId) -> Cancellable<String> {
|
||||
self.with_db(|db| view_item_tree::view_item_tree(db, file_id))
|
||||
}
|
||||
|
||||
pub fn discover_test_roots(&self) -> Cancellable<Vec<TestItem>> {
|
||||
self.with_db(test_explorer::discover_test_roots)
|
||||
}
|
||||
|
||||
pub fn discover_tests_in_crate_by_test_id(&self, crate_id: &str) -> Cancellable<Vec<TestItem>> {
|
||||
self.with_db(|db| test_explorer::discover_tests_in_crate_by_test_id(db, crate_id))
|
||||
}
|
||||
|
||||
pub fn discover_tests_in_crate(&self, crate_id: CrateId) -> Cancellable<Vec<TestItem>> {
|
||||
self.with_db(|db| test_explorer::discover_tests_in_crate(db, crate_id))
|
||||
}
|
||||
|
||||
/// Renders the crate graph to GraphViz "dot" syntax.
|
||||
pub fn view_crate_graph(&self, full: bool) -> Cancellable<Result<String, String>> {
|
||||
self.with_db(|db| view_crate_graph::view_crate_graph(db, full))
|
||||
|
||||
@@ -48,7 +48,7 @@ pub(crate) fn parent_module(db: &RootDatabase, position: FilePosition) -> Vec<Na
|
||||
.flat_map(|module| NavigationTarget::from_module_to_decl(db, module))
|
||||
.collect(),
|
||||
None => sema
|
||||
.to_module_defs(position.file_id)
|
||||
.file_to_module_defs(position.file_id)
|
||||
.flat_map(|module| NavigationTarget::from_module_to_decl(db, module))
|
||||
.collect(),
|
||||
}
|
||||
|
||||
@@ -156,7 +156,7 @@ pub(crate) fn will_rename_file(
|
||||
new_name_stem: &str,
|
||||
) -> Option<SourceChange> {
|
||||
let sema = Semantics::new(db);
|
||||
let module = sema.to_module_def(file_id)?;
|
||||
let module = sema.file_to_module_def(file_id)?;
|
||||
let def = Definition::Module(module);
|
||||
let mut change = if is_raw_identifier(new_name_stem) {
|
||||
def.rename(&sema, &SmolStr::from_iter(["r#", new_name_stem])).ok()?
|
||||
|
||||
@@ -178,7 +178,7 @@ pub(crate) fn runnables(db: &RootDatabase, file_id: FileId) -> Vec<Runnable> {
|
||||
}
|
||||
});
|
||||
|
||||
sema.to_module_defs(file_id)
|
||||
sema.file_to_module_defs(file_id)
|
||||
.map(|it| runnable_mod_outline_definition(&sema, it))
|
||||
.for_each(|it| add_opt(it, None));
|
||||
|
||||
|
||||
@@ -166,6 +166,7 @@ fn add_file(&mut self, file_id: FileId) {
|
||||
documentation: true,
|
||||
keywords: true,
|
||||
format: crate::HoverDocFormat::Markdown,
|
||||
max_trait_assoc_items_count: None,
|
||||
};
|
||||
let tokens = tokens.filter(|token| {
|
||||
matches!(
|
||||
|
||||
@@ -223,7 +223,7 @@ fn traverse(
|
||||
krate: hir::Crate,
|
||||
range_to_highlight: TextRange,
|
||||
) {
|
||||
let is_unlinked = sema.to_module_def(file_id).is_none();
|
||||
let is_unlinked = sema.file_to_module_def(file_id).is_none();
|
||||
let mut bindings_shadow_count: FxHashMap<Name, u32> = FxHashMap::default();
|
||||
|
||||
enum AttrOrDerive {
|
||||
|
||||
@@ -0,0 +1,135 @@
|
||||
//! Discovers tests
|
||||
|
||||
use hir::{Crate, Module, ModuleDef, Semantics};
|
||||
use ide_db::{
|
||||
base_db::{CrateGraph, CrateId, FileId, SourceDatabase},
|
||||
RootDatabase,
|
||||
};
|
||||
use syntax::TextRange;
|
||||
|
||||
use crate::{navigation_target::ToNav, runnables::runnable_fn, Runnable, TryToNav};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum TestItemKind {
|
||||
Crate,
|
||||
Module,
|
||||
Function,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct TestItem {
|
||||
pub id: String,
|
||||
pub kind: TestItemKind,
|
||||
pub label: String,
|
||||
pub parent: Option<String>,
|
||||
pub file: Option<FileId>,
|
||||
pub text_range: Option<TextRange>,
|
||||
pub runnable: Option<Runnable>,
|
||||
}
|
||||
|
||||
pub(crate) fn discover_test_roots(db: &RootDatabase) -> Vec<TestItem> {
|
||||
let crate_graph = db.crate_graph();
|
||||
crate_graph
|
||||
.iter()
|
||||
.filter(|&id| crate_graph[id].origin.is_local())
|
||||
.filter_map(|id| Some(crate_graph[id].display_name.as_ref()?.to_string()))
|
||||
.map(|id| TestItem {
|
||||
kind: TestItemKind::Crate,
|
||||
label: id.clone(),
|
||||
id,
|
||||
parent: None,
|
||||
file: None,
|
||||
text_range: None,
|
||||
runnable: None,
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn find_crate_by_id(crate_graph: &CrateGraph, crate_id: &str) -> Option<CrateId> {
|
||||
// here, we use display_name as the crate id. This is not super ideal, but it works since we
|
||||
// only show tests for the local crates.
|
||||
crate_graph.iter().find(|&id| {
|
||||
crate_graph[id].origin.is_local()
|
||||
&& crate_graph[id].display_name.as_ref().is_some_and(|x| x.to_string() == crate_id)
|
||||
})
|
||||
}
|
||||
|
||||
fn discover_tests_in_module(db: &RootDatabase, module: Module, prefix_id: String) -> Vec<TestItem> {
|
||||
let sema = Semantics::new(db);
|
||||
|
||||
let mut r = vec![];
|
||||
for c in module.children(db) {
|
||||
let module_name =
|
||||
c.name(db).as_ref().and_then(|n| n.as_str()).unwrap_or("[mod without name]").to_owned();
|
||||
let module_id = format!("{prefix_id}::{module_name}");
|
||||
let module_children = discover_tests_in_module(db, c, module_id.clone());
|
||||
if !module_children.is_empty() {
|
||||
let nav = c.to_nav(db).call_site;
|
||||
r.push(TestItem {
|
||||
id: module_id,
|
||||
kind: TestItemKind::Module,
|
||||
label: module_name,
|
||||
parent: Some(prefix_id.clone()),
|
||||
file: Some(nav.file_id),
|
||||
text_range: Some(nav.focus_or_full_range()),
|
||||
runnable: None,
|
||||
});
|
||||
r.extend(module_children);
|
||||
}
|
||||
}
|
||||
for def in module.declarations(db) {
|
||||
let ModuleDef::Function(f) = def else {
|
||||
continue;
|
||||
};
|
||||
if !f.is_test(db) {
|
||||
continue;
|
||||
}
|
||||
let nav = f.try_to_nav(db).map(|r| r.call_site);
|
||||
let fn_name = f.name(db).as_str().unwrap_or("[function without name]").to_owned();
|
||||
r.push(TestItem {
|
||||
id: format!("{prefix_id}::{fn_name}"),
|
||||
kind: TestItemKind::Function,
|
||||
label: fn_name,
|
||||
parent: Some(prefix_id.clone()),
|
||||
file: nav.as_ref().map(|n| n.file_id),
|
||||
text_range: nav.as_ref().map(|n| n.focus_or_full_range()),
|
||||
runnable: runnable_fn(&sema, f),
|
||||
});
|
||||
}
|
||||
r
|
||||
}
|
||||
|
||||
pub(crate) fn discover_tests_in_crate_by_test_id(
|
||||
db: &RootDatabase,
|
||||
crate_test_id: &str,
|
||||
) -> Vec<TestItem> {
|
||||
let crate_graph = db.crate_graph();
|
||||
let Some(crate_id) = find_crate_by_id(&crate_graph, crate_test_id) else {
|
||||
return vec![];
|
||||
};
|
||||
discover_tests_in_crate(db, crate_id)
|
||||
}
|
||||
|
||||
pub(crate) fn discover_tests_in_crate(db: &RootDatabase, crate_id: CrateId) -> Vec<TestItem> {
|
||||
let crate_graph = db.crate_graph();
|
||||
if !crate_graph[crate_id].origin.is_local() {
|
||||
return vec![];
|
||||
}
|
||||
let Some(crate_test_id) = &crate_graph[crate_id].display_name else {
|
||||
return vec![];
|
||||
};
|
||||
let crate_test_id = crate_test_id.to_string();
|
||||
let crate_id: Crate = crate_id.into();
|
||||
let module = crate_id.root_module();
|
||||
let mut r = vec![TestItem {
|
||||
id: crate_test_id.clone(),
|
||||
kind: TestItemKind::Crate,
|
||||
label: crate_test_id.clone(),
|
||||
parent: None,
|
||||
file: None,
|
||||
text_range: None,
|
||||
runnable: None,
|
||||
}];
|
||||
r.extend(discover_tests_in_module(db, module, crate_test_id));
|
||||
r
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user