mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-29 14:33:29 +00:00
Auto merge of #125272 - lnicola:sync-from-ra, r=lnicola
Subtree update of `rust-analyzer` r? `@ghost`
This commit is contained in:
commit
48826c85fd
204 changed files with 5515 additions and 2911 deletions
|
@ -6,3 +6,10 @@
|
|||
|
||||
# prettier format
|
||||
f247090558c9ba3c551566eae5882b7ca865225f
|
||||
|
||||
# subtree syncs
|
||||
932d85b52946d917deab2c23ead552f7f713b828
|
||||
3e358a6827d83e8d6473913a5e304734aadfed04
|
||||
9d2cb42a413e51deb50b36794a2e1605381878fc
|
||||
f532576ac53ddcc666bc8d59e0b6437065e2f599
|
||||
c48062fe2ab9a2d913d1985a6b0aec4bf936bfc1
|
||||
|
|
6
.github/workflows/ci.yaml
vendored
6
.github/workflows/ci.yaml
vendored
|
@ -63,15 +63,15 @@ jobs:
|
|||
- name: Install Rust toolchain
|
||||
run: |
|
||||
rustup update --no-self-update ${{ env.RUST_CHANNEL }}
|
||||
rustup component add --toolchain ${{ env.RUST_CHANNEL }} rustfmt rust-src
|
||||
rustup default ${{ env.RUST_CHANNEL }}
|
||||
rustup component add --toolchain ${{ env.RUST_CHANNEL }} rustfmt rust-src
|
||||
# https://github.com/actions-rust-lang/setup-rust-toolchain/blob/main/rust.json
|
||||
- name: Install Rust Problem Matcher
|
||||
if: matrix.os == 'ubuntu-latest'
|
||||
run: echo "::add-matcher::.github/rust.json"
|
||||
|
||||
- name: Cache Dependencies
|
||||
uses: Swatinem/rust-cache@640a22190e7a783d4c409684cea558f081f92012
|
||||
uses: Swatinem/rust-cache@9bdad043e88c75890e36ad3bbc8d27f0090dd609
|
||||
with:
|
||||
key: ${{ env.RUST_CHANNEL }}
|
||||
|
||||
|
@ -140,7 +140,7 @@ jobs:
|
|||
rustup target add ${{ env.targets }} ${{ env.targets_ide }}
|
||||
|
||||
- name: Cache Dependencies
|
||||
uses: Swatinem/rust-cache@640a22190e7a783d4c409684cea558f081f92012
|
||||
uses: Swatinem/rust-cache@9bdad043e88c75890e36ad3bbc8d27f0090dd609
|
||||
|
||||
- name: Check
|
||||
run: |
|
||||
|
|
39
.github/workflows/metrics.yaml
vendored
39
.github/workflows/metrics.yaml
vendored
|
@ -11,34 +11,21 @@ env:
|
|||
RUSTUP_MAX_RETRIES: 10
|
||||
|
||||
jobs:
|
||||
setup_cargo:
|
||||
build_metrics:
|
||||
if: github.repository == 'rust-lang/rust-analyzer'
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Install Rust toolchain
|
||||
run: |
|
||||
rustup update --no-self-update stable
|
||||
rustup component add rustfmt rust-src
|
||||
rustup default stable
|
||||
- name: Cache cargo
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~/.cargo/bin/
|
||||
~/.cargo/registry/index/
|
||||
~/.cargo/registry/cache/
|
||||
~/.cargo/git/db/
|
||||
key: ${{ runner.os }}-cargo-${{ github.sha }}
|
||||
rustup component add --toolchain stable rust-src
|
||||
|
||||
build_metrics:
|
||||
runs-on: ubuntu-latest
|
||||
needs: setup_cargo
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Restore cargo cache
|
||||
- name: Cache cargo
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
|
@ -69,22 +56,18 @@ jobs:
|
|||
matrix:
|
||||
names: [self, ripgrep-13.0.0, webrender-2022, diesel-1.4.8, hyper-0.14.18]
|
||||
runs-on: ubuntu-latest
|
||||
needs: [setup_cargo, build_metrics]
|
||||
needs: build_metrics
|
||||
|
||||
steps:
|
||||
- name: Install Rust toolchain
|
||||
run: |
|
||||
rustup update --no-self-update stable
|
||||
rustup default stable
|
||||
rustup component add --toolchain stable rust-src
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Restore cargo cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~/.cargo/bin/
|
||||
~/.cargo/registry/index/
|
||||
~/.cargo/registry/cache/
|
||||
~/.cargo/git/db/
|
||||
key: ${{ runner.os }}-cargo-${{ github.sha }}
|
||||
|
||||
- name: Restore target cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
|
|
2
.github/workflows/rustdoc.yaml
vendored
2
.github/workflows/rustdoc.yaml
vendored
|
@ -26,7 +26,7 @@ jobs:
|
|||
run: cargo doc --all --no-deps
|
||||
|
||||
- name: Deploy Docs
|
||||
uses: peaceiris/actions-gh-pages@364c31d33bb99327c77b3a5438a83a357a6729ad # v3.4.0
|
||||
uses: peaceiris/actions-gh-pages@4f9cc6602d3f66b9c108549d475ec49e8ef4d45e # v4.0.0
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
publish_branch: gh-pages
|
||||
|
|
406
Cargo.lock
generated
406
Cargo.lock
generated
|
@ -28,9 +28,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.80"
|
||||
version = "1.0.83"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5ad32ce52e4161730f7098c077cd2ed6229b5804ccf99e5366be1ab72a98b4e1"
|
||||
checksum = "25bdb32cbbdce2b519a9cd7df3a678443100e265d5e25ca763b7572a5104f5f3"
|
||||
|
||||
[[package]]
|
||||
name = "arbitrary"
|
||||
|
@ -46,15 +46,15 @@ checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711"
|
|||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.1.0"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||
checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
|
||||
|
||||
[[package]]
|
||||
name = "backtrace"
|
||||
version = "0.3.69"
|
||||
version = "0.3.71"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837"
|
||||
checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d"
|
||||
dependencies = [
|
||||
"addr2line",
|
||||
"cc",
|
||||
|
@ -91,9 +91,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
|||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.4.2"
|
||||
version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf"
|
||||
checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1"
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
|
@ -112,9 +112,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "cargo-platform"
|
||||
version = "0.1.7"
|
||||
version = "0.1.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "694c8807f2ae16faecc43dc17d74b3eb042482789fd0eb64b39a2e04e087053f"
|
||||
checksum = "24b1f0365a6c6bb4020cd05806fd0d33c44d38046b8bd7f0e40814b9763cabfc"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
@ -135,9 +135,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.90"
|
||||
version = "1.0.97"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5"
|
||||
checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4"
|
||||
|
||||
[[package]]
|
||||
name = "cfg"
|
||||
|
@ -159,6 +159,12 @@ version = "1.0.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "cfg_aliases"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e"
|
||||
|
||||
[[package]]
|
||||
name = "chalk-derive"
|
||||
version = "0.97.0"
|
||||
|
@ -177,7 +183,7 @@ version = "0.97.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "db18493569b190f7266a04901e520fc3a5c00564475154287906f8a27302c119"
|
||||
dependencies = [
|
||||
"bitflags 2.4.2",
|
||||
"bitflags 2.5.0",
|
||||
"chalk-derive",
|
||||
]
|
||||
|
||||
|
@ -282,11 +288,11 @@ checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345"
|
|||
|
||||
[[package]]
|
||||
name = "ctrlc"
|
||||
version = "3.4.2"
|
||||
version = "3.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b467862cc8610ca6fc9a1532d7777cee0804e678ab45410897b9396495994a0b"
|
||||
checksum = "672465ae37dc1bc6380a6547a8883d5dd397b0f1faaad4f265726cc7042a5345"
|
||||
dependencies = [
|
||||
"nix 0.27.1",
|
||||
"nix 0.28.0",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
|
@ -324,10 +330,31 @@ dependencies = [
|
|||
]
|
||||
|
||||
[[package]]
|
||||
name = "dissimilar"
|
||||
version = "1.0.7"
|
||||
name = "directories"
|
||||
version = "5.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "86e3bdc80eee6e16b2b6b0f87fbc98c04bee3455e35174c0de1a125d0688c632"
|
||||
checksum = "9a49173b84e034382284f27f1af4dcbbd231ffa358c0fe316541a7337f376a35"
|
||||
dependencies = [
|
||||
"dirs-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dirs-sys"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"option-ext",
|
||||
"redox_users",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dissimilar"
|
||||
version = "1.0.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "59f8e79d1fbf76bdfbde321e902714bf6c49df88a7dda6fc682fc2979226962d"
|
||||
|
||||
[[package]]
|
||||
name = "dot"
|
||||
|
@ -343,15 +370,15 @@ checksum = "9bda8e21c04aca2ae33ffc2fd8c23134f3cac46db123ba97bd9d3f3b8a4a85e1"
|
|||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.10.0"
|
||||
version = "1.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a"
|
||||
checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2"
|
||||
|
||||
[[package]]
|
||||
name = "ena"
|
||||
version = "0.14.2"
|
||||
version = "0.14.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c533630cf40e9caa44bd91aadc88a75d75a4c3a12b4cfde353cbed41daa1e1f1"
|
||||
checksum = "3d248bdd43ce613d87415282f69b9bb99d947d290b10962dd6c56233312c2ad5"
|
||||
dependencies = [
|
||||
"log",
|
||||
]
|
||||
|
@ -364,9 +391,9 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
|
|||
|
||||
[[package]]
|
||||
name = "expect-test"
|
||||
version = "1.4.1"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "30d9eafeadd538e68fb28016364c9732d78e420b9ff8853fa5e4058861e9f8d3"
|
||||
checksum = "9e0be0a561335815e06dab7c62e50353134c796e7a6155402a64bcff66b6a5e0"
|
||||
dependencies = [
|
||||
"dissimilar",
|
||||
"once_cell",
|
||||
|
@ -380,7 +407,7 @@ checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd"
|
|||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"redox_syscall",
|
||||
"redox_syscall 0.4.1",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
|
@ -392,9 +419,9 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
|
|||
|
||||
[[package]]
|
||||
name = "flate2"
|
||||
version = "1.0.28"
|
||||
version = "1.0.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e"
|
||||
checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae"
|
||||
dependencies = [
|
||||
"crc32fast",
|
||||
"miniz_oxide",
|
||||
|
@ -442,9 +469,9 @@ checksum = "7ab85b9b05e3978cc9a9cf8fea7f01b494e1a09ed3037e16ba39edc7a29eb61a"
|
|||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.12"
|
||||
version = "0.2.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5"
|
||||
checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
|
@ -459,9 +486,9 @@ checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253"
|
|||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.14.3"
|
||||
version = "0.14.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604"
|
||||
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
|
@ -504,7 +531,7 @@ version = "0.0.0"
|
|||
dependencies = [
|
||||
"arrayvec",
|
||||
"base-db",
|
||||
"bitflags 2.4.2",
|
||||
"bitflags 2.5.0",
|
||||
"cfg",
|
||||
"cov-mark",
|
||||
"dashmap",
|
||||
|
@ -568,7 +595,7 @@ version = "0.0.0"
|
|||
dependencies = [
|
||||
"arrayvec",
|
||||
"base-db",
|
||||
"bitflags 2.4.2",
|
||||
"bitflags 2.5.0",
|
||||
"chalk-derive",
|
||||
"chalk-ir",
|
||||
"chalk-recursive",
|
||||
|
@ -589,7 +616,7 @@ dependencies = [
|
|||
"oorandom",
|
||||
"project-model",
|
||||
"ra-ap-rustc_abi",
|
||||
"ra-ap-rustc_index",
|
||||
"ra-ap-rustc_index 0.53.0",
|
||||
"ra-ap-rustc_pattern_analysis",
|
||||
"rustc-hash",
|
||||
"scoped-tls",
|
||||
|
@ -695,7 +722,7 @@ version = "0.0.0"
|
|||
dependencies = [
|
||||
"arrayvec",
|
||||
"base-db",
|
||||
"bitflags 2.4.2",
|
||||
"bitflags 2.5.0",
|
||||
"cov-mark",
|
||||
"crossbeam-channel",
|
||||
"either",
|
||||
|
@ -776,9 +803,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "2.2.5"
|
||||
version = "2.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7b0b929d511467233429c45a44ac1dcaa21ba0f5ba11e4879e6ed28ddb4f9df4"
|
||||
checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26"
|
||||
dependencies = [
|
||||
"equivalent",
|
||||
"hashbrown",
|
||||
|
@ -826,9 +853,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.10"
|
||||
version = "1.0.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c"
|
||||
checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
|
||||
|
||||
[[package]]
|
||||
name = "jod-thread"
|
||||
|
@ -874,9 +901,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
|||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.153"
|
||||
version = "0.2.154"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
|
||||
checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346"
|
||||
|
||||
[[package]]
|
||||
name = "libloading"
|
||||
|
@ -885,19 +912,29 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"windows-targets 0.52.4",
|
||||
"windows-targets 0.52.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libmimalloc-sys"
|
||||
version = "0.1.35"
|
||||
version = "0.1.37"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3979b5c37ece694f1f5e51e7ecc871fdb0f517ed04ee45f88d15d6d553cb9664"
|
||||
checksum = "81eb4061c0582dedea1cbc7aff2240300dd6982e0239d1c99e65c1dbf4a30ba7"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libredox"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d"
|
||||
dependencies = [
|
||||
"bitflags 2.5.0",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "limit"
|
||||
version = "0.0.0"
|
||||
|
@ -948,9 +985,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
version = "0.4.11"
|
||||
version = "0.4.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45"
|
||||
checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"scopeguard",
|
||||
|
@ -1001,9 +1038,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "lz4_flex"
|
||||
version = "0.11.2"
|
||||
version = "0.11.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "912b45c753ff5f7f5208307e8ace7d2a2e30d024e26d3509f3dce546c044ce15"
|
||||
checksum = "75761162ae2b0e580d7e7c390558127e5f01b4194debd6221fd8c207fc80e3f5"
|
||||
|
||||
[[package]]
|
||||
name = "mbe"
|
||||
|
@ -1023,9 +1060,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.7.1"
|
||||
version = "2.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149"
|
||||
checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d"
|
||||
|
||||
[[package]]
|
||||
name = "memmap2"
|
||||
|
@ -1038,18 +1075,18 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "memoffset"
|
||||
version = "0.9.0"
|
||||
version = "0.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c"
|
||||
checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mimalloc"
|
||||
version = "0.1.39"
|
||||
version = "0.1.41"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fa01922b5ea280a911e323e4d2fd24b7fe5cc4042e0d2cda3c40775cdc4bdc9c"
|
||||
checksum = "9f41a2280ded0da56c8cf898babb86e8f10651a34adcfff190ae9a1159c6908d"
|
||||
dependencies = [
|
||||
"libmimalloc-sys",
|
||||
]
|
||||
|
@ -1097,12 +1134,13 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "nix"
|
||||
version = "0.27.1"
|
||||
version = "0.28.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053"
|
||||
checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4"
|
||||
dependencies = [
|
||||
"bitflags 2.4.2",
|
||||
"bitflags 2.5.0",
|
||||
"cfg-if",
|
||||
"cfg_aliases",
|
||||
"libc",
|
||||
]
|
||||
|
||||
|
@ -1118,7 +1156,7 @@ version = "6.1.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6205bd8bb1e454ad2e27422015fb5e4f2bcc7e08fa8f27058670d208324a4d2d"
|
||||
dependencies = [
|
||||
"bitflags 2.4.2",
|
||||
"bitflags 2.5.0",
|
||||
"crossbeam-channel",
|
||||
"filetime",
|
||||
"fsevent-sys",
|
||||
|
@ -1187,10 +1225,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575"
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot"
|
||||
version = "0.12.1"
|
||||
name = "option-ext"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
|
||||
checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot"
|
||||
version = "0.12.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7e4af0ca4f6caed20e900d564c242b8e5d4903fdacf31d3daf527b66fe6f42fb"
|
||||
dependencies = [
|
||||
"lock_api",
|
||||
"parking_lot_core",
|
||||
|
@ -1198,15 +1242,15 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "parking_lot_core"
|
||||
version = "0.9.9"
|
||||
version = "0.9.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e"
|
||||
checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"redox_syscall",
|
||||
"redox_syscall 0.5.1",
|
||||
"smallvec",
|
||||
"windows-targets 0.48.5",
|
||||
"windows-targets 0.52.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1224,9 +1268,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "paste"
|
||||
version = "1.0.14"
|
||||
version = "1.0.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c"
|
||||
checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
|
||||
|
||||
[[package]]
|
||||
name = "paths"
|
||||
|
@ -1262,9 +1306,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "petgraph"
|
||||
version = "0.6.4"
|
||||
version = "0.6.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9"
|
||||
checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db"
|
||||
dependencies = [
|
||||
"fixedbitset",
|
||||
"indexmap",
|
||||
|
@ -1272,9 +1316,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "pin-project-lite"
|
||||
version = "0.2.13"
|
||||
version = "0.2.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58"
|
||||
checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02"
|
||||
|
||||
[[package]]
|
||||
name = "powerfmt"
|
||||
|
@ -1346,9 +1390,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.78"
|
||||
version = "1.0.82"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae"
|
||||
checksum = "8ad3d49ab951a01fbaafe34f2ec74122942fe18a3f9814c3268f1bb72042131b"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
@ -1365,7 +1409,7 @@ dependencies = [
|
|||
"perf-event",
|
||||
"tikv-jemalloc-ctl",
|
||||
"tracing",
|
||||
"winapi",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1417,7 +1461,7 @@ version = "0.9.6"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "57206b407293d2bcd3af849ce869d52068623f19e1b5ff8e8778e3309439682b"
|
||||
dependencies = [
|
||||
"bitflags 2.4.2",
|
||||
"bitflags 2.5.0",
|
||||
"memchr",
|
||||
"unicase",
|
||||
]
|
||||
|
@ -1433,21 +1477,21 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.35"
|
||||
version = "1.0.36"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
|
||||
checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ra-ap-rustc_abi"
|
||||
version = "0.44.0"
|
||||
version = "0.53.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b8709df2a746f055316bc0c62bd30948695a25e734863bf6e1f9755403e010ab"
|
||||
checksum = "80b1d613eee933486c0613a7bc26e515e46f43adf479d1edd5e537f983e9ce46"
|
||||
dependencies = [
|
||||
"bitflags 2.4.2",
|
||||
"ra-ap-rustc_index",
|
||||
"bitflags 2.5.0",
|
||||
"ra-ap-rustc_index 0.53.0",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
|
@ -1458,7 +1502,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "9ad68bacffb87dcdbb23a3ce11261375078aaa06b85d348c49f39ffd5510dc20"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"ra-ap-rustc_index_macros",
|
||||
"ra-ap-rustc_index_macros 0.44.0",
|
||||
"smallvec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ra-ap-rustc_index"
|
||||
version = "0.53.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f072060ac77e9e1a02cc20028095993af7e72cc0804779c68bcbf47b16de49c9"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"ra-ap-rustc_index_macros 0.53.0",
|
||||
"smallvec",
|
||||
]
|
||||
|
||||
|
@ -1475,10 +1530,22 @@ dependencies = [
|
|||
]
|
||||
|
||||
[[package]]
|
||||
name = "ra-ap-rustc_lexer"
|
||||
version = "0.44.0"
|
||||
name = "ra-ap-rustc_index_macros"
|
||||
version = "0.53.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aab683fc8579d09eb72033bd5dc9ba6d701aa9645b5fed087ef19af71184dff3"
|
||||
checksum = "82f3d6dcb30a66905388e14756b8f2216131d9f8004922c07f13335840e058d1"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"synstructure",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ra-ap-rustc_lexer"
|
||||
version = "0.53.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dbd8a2b0bdcba9892cbce0b25f6c953d31b0febc1f3420fc692884fce5a23ad8"
|
||||
dependencies = [
|
||||
"unicode-properties",
|
||||
"unicode-xid",
|
||||
|
@ -1486,11 +1553,11 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "ra-ap-rustc_parse_format"
|
||||
version = "0.44.0"
|
||||
version = "0.53.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0bcf9ff5edbf784b67b8ad5e03a068f1300fcc24062c0d476b3018965135d933"
|
||||
checksum = "70dad7a491c2554590222e0c9212dcb7c2e7aceb668875075012a35ea780d135"
|
||||
dependencies = [
|
||||
"ra-ap-rustc_index",
|
||||
"ra-ap-rustc_index 0.53.0",
|
||||
"ra-ap-rustc_lexer",
|
||||
]
|
||||
|
||||
|
@ -1500,7 +1567,7 @@ version = "0.44.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d63d1e1d5b2a13273cee1a10011147418f40e12b70f70578ce1dee0f1cafc334"
|
||||
dependencies = [
|
||||
"ra-ap-rustc_index",
|
||||
"ra-ap-rustc_index 0.44.0",
|
||||
"rustc-hash",
|
||||
"rustc_apfloat",
|
||||
"smallvec",
|
||||
|
@ -1539,9 +1606,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "rayon"
|
||||
version = "1.9.0"
|
||||
version = "1.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e4963ed1bc86e4f3ee217022bd855b297cef07fb9eac5dfa1f788b220b49b3bd"
|
||||
checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa"
|
||||
dependencies = [
|
||||
"either",
|
||||
"rayon-core",
|
||||
|
@ -1566,6 +1633,26 @@ dependencies = [
|
|||
"bitflags 1.3.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "469052894dcb553421e483e4209ee581a45100d31b4018de03e5a7ad86374a7e"
|
||||
dependencies = [
|
||||
"bitflags 2.5.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_users"
|
||||
version = "0.4.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bd283d9651eeda4b2a83a43c1c91b266c40fd76ecd39a50a8c630ae69dc72891"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
"libredox",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rowan"
|
||||
version = "0.15.15"
|
||||
|
@ -1634,16 +1721,16 @@ dependencies = [
|
|||
"vfs",
|
||||
"vfs-notify",
|
||||
"walkdir",
|
||||
"winapi",
|
||||
"windows-sys 0.52.0",
|
||||
"xflags",
|
||||
"xshell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-demangle"
|
||||
version = "0.1.23"
|
||||
version = "0.1.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
|
||||
checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
|
||||
|
||||
[[package]]
|
||||
name = "rustc-hash"
|
||||
|
@ -1663,9 +1750,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.17"
|
||||
version = "1.0.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1"
|
||||
checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
|
||||
|
||||
[[package]]
|
||||
name = "salsa"
|
||||
|
@ -1729,27 +1816,27 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
|||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "1.0.22"
|
||||
version = "1.0.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca"
|
||||
checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.197"
|
||||
version = "1.0.201"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2"
|
||||
checksum = "780f1cebed1629e4753a1a38a3c72d30b97ec044f0aef68cb26650a3c5cf363c"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.197"
|
||||
version = "1.0.201"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b"
|
||||
checksum = "c5e405930b9796f1c00bee880d03fc7e0bb4b9a11afc776885ffe84320da2865"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -1758,9 +1845,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.114"
|
||||
version = "1.0.117"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0"
|
||||
checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"itoa",
|
||||
|
@ -1770,9 +1857,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "serde_repr"
|
||||
version = "0.1.18"
|
||||
version = "0.1.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b2e6b945e9d3df726b65d6ee24060aff8e3533d431f677a9695db04eff9dfdb"
|
||||
checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -1799,9 +1886,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
version = "1.13.1"
|
||||
version = "1.13.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7"
|
||||
checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
|
||||
|
||||
[[package]]
|
||||
name = "smol_str"
|
||||
|
@ -1856,14 +1943,14 @@ dependencies = [
|
|||
"jod-thread",
|
||||
"libc",
|
||||
"miow",
|
||||
"winapi",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.52"
|
||||
version = "2.0.63"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b699d15b36d1f02c3e7c69f8ffef53de37aefae075d8488d4ba1a7788d574a07"
|
||||
checksum = "bf5be731623ca1a1fb7d8be6f261a3be6d3e2337b8a1f97be944d020c8fcb704"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -1946,18 +2033,18 @@ checksum = "f18aa187839b2bdb1ad2fa35ead8c4c2976b64e4363c386d45ac0f7ee85c9233"
|
|||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.57"
|
||||
version = "1.0.60"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e45bcbe8ed29775f228095caf2cd67af7a4ccf756ebff23a306bf3e8b47b24b"
|
||||
checksum = "579e9083ca58dd9dcf91a9923bb9054071b9ebbd800b342194c9feb0ee89fc18"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.57"
|
||||
version = "1.0.60"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81"
|
||||
checksum = "e2470041c06ec3ac1ab38d0356a6119054dedaea53e12fbefc0de730a1c08524"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -2007,9 +2094,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.3.34"
|
||||
version = "0.3.36"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c8248b6521bb14bc45b4067159b9b6ad792e2d6d754d6c41fb50e29fefe38749"
|
||||
checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885"
|
||||
dependencies = [
|
||||
"deranged",
|
||||
"num-conv",
|
||||
|
@ -2041,9 +2128,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
|
|||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.8.8"
|
||||
version = "0.8.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1a195ec8c9da26928f773888e0742ca3ca1040c6cd859c919c9f59c1954ab35"
|
||||
checksum = "e9dd1545e8208b4a5af1aa9bbd0b4cf7e9ea08fabc5d0a5c67fcaafa17433aa3"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_spanned",
|
||||
|
@ -2062,9 +2149,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "toml_edit"
|
||||
version = "0.21.0"
|
||||
version = "0.22.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d34d383cd00a163b4a5b85053df514d45bc330f6de7737edfe0a93311d1eaa03"
|
||||
checksum = "d3328d4f68a705b2a4498da1d580585d39a6510f98318a2cec3018a7ec61ddef"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"serde",
|
||||
|
@ -2255,6 +2342,7 @@ dependencies = [
|
|||
"paths",
|
||||
"rustc-hash",
|
||||
"stdx",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2304,11 +2392,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
|||
|
||||
[[package]]
|
||||
name = "winapi-util"
|
||||
version = "0.1.6"
|
||||
version = "0.1.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596"
|
||||
checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2332,7 +2420,7 @@ version = "0.52.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
|
||||
dependencies = [
|
||||
"windows-targets 0.52.4",
|
||||
"windows-targets 0.52.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2352,17 +2440,18 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.52.4"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b"
|
||||
checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb"
|
||||
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",
|
||||
"windows_aarch64_gnullvm 0.52.5",
|
||||
"windows_aarch64_msvc 0.52.5",
|
||||
"windows_i686_gnu 0.52.5",
|
||||
"windows_i686_gnullvm",
|
||||
"windows_i686_msvc 0.52.5",
|
||||
"windows_x86_64_gnu 0.52.5",
|
||||
"windows_x86_64_gnullvm 0.52.5",
|
||||
"windows_x86_64_msvc 0.52.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2373,9 +2462,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
|
|||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.52.4"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9"
|
||||
checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
|
@ -2385,9 +2474,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
|
|||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.52.4"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675"
|
||||
checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
|
@ -2397,9 +2486,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
|
|||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.52.4"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3"
|
||||
checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnullvm"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
|
@ -2409,9 +2504,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
|
|||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.52.4"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02"
|
||||
checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
|
@ -2421,9 +2516,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
|
|||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.52.4"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03"
|
||||
checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
|
@ -2433,9 +2528,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
|
|||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.52.4"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177"
|
||||
checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
|
@ -2445,15 +2540,15 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
|
|||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.52.4"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8"
|
||||
checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0"
|
||||
|
||||
[[package]]
|
||||
name = "winnow"
|
||||
version = "0.5.32"
|
||||
version = "0.6.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8434aeec7b290e8da5c3f0d628cb0eac6cabcb31d14bb74f779a08109a5914d6"
|
||||
checksum = "c3c52e9c97a68071b23e836c9380edae937f17b9c4667bd021973efc689f618d"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
@ -2481,24 +2576,25 @@ checksum = "672423d4fea7ffa2f6c25ba60031ea13dc6258070556f125cc4d790007d4a155"
|
|||
|
||||
[[package]]
|
||||
name = "xshell"
|
||||
version = "0.2.5"
|
||||
version = "0.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ce2107fe03e558353b4c71ad7626d58ed82efaf56c54134228608893c77023ad"
|
||||
checksum = "6db0ab86eae739efd1b054a8d3d16041914030ac4e01cd1dca0cf252fd8b6437"
|
||||
dependencies = [
|
||||
"xshell-macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "xshell-macros"
|
||||
version = "0.2.5"
|
||||
version = "0.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7e2c411759b501fb9501aac2b1b2d287a6e93e5bdcf13c25306b23e1b716dd0e"
|
||||
checksum = "9d422e8e38ec76e2f06ee439ccc765e9c6a9638b9e7c9f2e8255e4d41e8bd852"
|
||||
|
||||
[[package]]
|
||||
name = "xtask"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"directories",
|
||||
"flate2",
|
||||
"itertools",
|
||||
"proc-macro2",
|
||||
|
|
10
Cargo.toml
10
Cargo.toml
|
@ -4,7 +4,7 @@ exclude = ["crates/proc-macro-srv/proc-macro-test/imp"]
|
|||
resolver = "2"
|
||||
|
||||
[workspace.package]
|
||||
rust-version = "1.76"
|
||||
rust-version = "1.78"
|
||||
edition = "2021"
|
||||
license = "MIT OR Apache-2.0"
|
||||
authors = ["rust-analyzer team"]
|
||||
|
@ -85,10 +85,10 @@ 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.44.0", default-features = false }
|
||||
ra-ap-rustc_parse_format = { version = "0.44.0", default-features = false }
|
||||
ra-ap-rustc_index = { version = "0.44.0", default-features = false }
|
||||
ra-ap-rustc_abi = { version = "0.44.0", default-features = false }
|
||||
ra-ap-rustc_lexer = { version = "0.53.0", default-features = false }
|
||||
ra-ap-rustc_parse_format = { version = "0.53.0", default-features = false }
|
||||
ra-ap-rustc_index = { version = "0.53.0", default-features = false }
|
||||
ra-ap-rustc_abi = { version = "0.53.0", default-features = false }
|
||||
ra-ap-rustc_pattern_analysis = { version = "0.44.0", default-features = false }
|
||||
|
||||
# local crates that aren't published to crates.io. These should not have versions.
|
||||
|
|
|
@ -51,7 +51,7 @@ impl FileChange {
|
|||
}
|
||||
|
||||
pub fn apply(self, db: &mut dyn SourceDatabaseExt) {
|
||||
let _p = tracing::span!(tracing::Level::INFO, "RootDatabase::apply_change").entered();
|
||||
let _p = tracing::span!(tracing::Level::INFO, "FileChange::apply").entered();
|
||||
if let Some(roots) = self.roots {
|
||||
for (idx, root) in roots.into_iter().enumerate() {
|
||||
let root_id = SourceRootId(idx as u32);
|
||||
|
|
|
@ -324,21 +324,27 @@ pub struct Dependency {
|
|||
pub crate_id: CrateId,
|
||||
pub name: CrateName,
|
||||
prelude: bool,
|
||||
sysroot: bool,
|
||||
}
|
||||
|
||||
impl Dependency {
|
||||
pub fn new(name: CrateName, crate_id: CrateId) -> Self {
|
||||
Self { name, crate_id, prelude: true }
|
||||
Self { name, crate_id, prelude: true, sysroot: false }
|
||||
}
|
||||
|
||||
pub fn with_prelude(name: CrateName, crate_id: CrateId, prelude: bool) -> Self {
|
||||
Self { name, crate_id, prelude }
|
||||
pub fn with_prelude(name: CrateName, crate_id: CrateId, prelude: bool, sysroot: bool) -> Self {
|
||||
Self { name, crate_id, prelude, sysroot }
|
||||
}
|
||||
|
||||
/// Whether this dependency is to be added to the depending crate's extern prelude.
|
||||
pub fn is_prelude(&self) -> bool {
|
||||
self.prelude
|
||||
}
|
||||
|
||||
/// Whether this dependency is a sysroot injected one.
|
||||
pub fn is_sysroot(&self) -> bool {
|
||||
self.sysroot
|
||||
}
|
||||
}
|
||||
|
||||
impl CrateGraph {
|
||||
|
|
|
@ -8,7 +8,7 @@ mod input;
|
|||
use std::panic;
|
||||
|
||||
use salsa::Durability;
|
||||
use syntax::{ast, Parse, SourceFile};
|
||||
use syntax::{ast, Parse, SourceFile, SyntaxError};
|
||||
use triomphe::Arc;
|
||||
|
||||
pub use crate::{
|
||||
|
@ -51,6 +51,7 @@ pub trait FileLoader {
|
|||
/// Text of the file.
|
||||
fn file_text(&self, file_id: FileId) -> Arc<str>;
|
||||
fn resolve_path(&self, path: AnchoredPath<'_>) -> Option<FileId>;
|
||||
/// Crates whose root's source root is the same as the source root of `file_id`
|
||||
fn relevant_crates(&self, file_id: FileId) -> Arc<[CrateId]>;
|
||||
}
|
||||
|
||||
|
@ -61,6 +62,9 @@ pub trait SourceDatabase: FileLoader + std::fmt::Debug {
|
|||
/// Parses the file into the syntax tree.
|
||||
fn parse(&self, file_id: FileId) -> Parse<ast::SourceFile>;
|
||||
|
||||
/// Returns the set of errors obtained from parsing the file including validation errors.
|
||||
fn parse_errors(&self, file_id: FileId) -> Option<Arc<[SyntaxError]>>;
|
||||
|
||||
/// The crate graph.
|
||||
#[salsa::input]
|
||||
fn crate_graph(&self) -> Arc<CrateGraph>;
|
||||
|
@ -81,12 +85,20 @@ fn toolchain_channel(db: &dyn SourceDatabase, krate: CrateId) -> Option<ReleaseC
|
|||
}
|
||||
|
||||
fn parse(db: &dyn SourceDatabase, file_id: FileId) -> Parse<ast::SourceFile> {
|
||||
let _p = tracing::span!(tracing::Level::INFO, "parse_query", ?file_id).entered();
|
||||
let _p = tracing::span!(tracing::Level::INFO, "parse", ?file_id).entered();
|
||||
let text = db.file_text(file_id);
|
||||
// FIXME: Edition based parsing
|
||||
SourceFile::parse(&text, span::Edition::CURRENT)
|
||||
}
|
||||
|
||||
fn parse_errors(db: &dyn SourceDatabase, file_id: FileId) -> Option<Arc<[SyntaxError]>> {
|
||||
let errors = db.parse(file_id).errors();
|
||||
match &*errors {
|
||||
[] => None,
|
||||
[..] => Some(errors.into()),
|
||||
}
|
||||
}
|
||||
|
||||
/// We don't want to give HIR knowledge of source roots, hence we extract these
|
||||
/// methods into a separate DB.
|
||||
#[salsa::query_group(SourceDatabaseExtStorage)]
|
||||
|
@ -104,6 +116,7 @@ pub trait SourceDatabaseExt: SourceDatabase {
|
|||
#[salsa::input]
|
||||
fn source_root(&self, id: SourceRootId) -> Arc<SourceRoot>;
|
||||
|
||||
/// Crates whose root fool is in `id`.
|
||||
fn source_root_crates(&self, id: SourceRootId) -> Arc<[CrateId]>;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use arbitrary::{Arbitrary, Unstructured};
|
||||
use expect_test::{expect, Expect};
|
||||
use mbe::{syntax_node_to_token_tree, DummyTestSpanMap, DUMMY};
|
||||
use mbe::{syntax_node_to_token_tree, DocCommentDesugarMode, DummyTestSpanMap, DUMMY};
|
||||
use syntax::{ast, AstNode, Edition};
|
||||
|
||||
use crate::{CfgAtom, CfgExpr, CfgOptions, DnfExpr};
|
||||
|
@ -8,7 +8,12 @@ use crate::{CfgAtom, CfgExpr, CfgOptions, DnfExpr};
|
|||
fn assert_parse_result(input: &str, expected: CfgExpr) {
|
||||
let source_file = ast::SourceFile::parse(input, Edition::CURRENT).ok().unwrap();
|
||||
let tt = source_file.syntax().descendants().find_map(ast::TokenTree::cast).unwrap();
|
||||
let tt = syntax_node_to_token_tree(tt.syntax(), DummyTestSpanMap, DUMMY);
|
||||
let tt = syntax_node_to_token_tree(
|
||||
tt.syntax(),
|
||||
DummyTestSpanMap,
|
||||
DUMMY,
|
||||
DocCommentDesugarMode::ProcMacro,
|
||||
);
|
||||
let cfg = CfgExpr::parse(&tt);
|
||||
assert_eq!(cfg, expected);
|
||||
}
|
||||
|
@ -16,7 +21,12 @@ fn assert_parse_result(input: &str, expected: CfgExpr) {
|
|||
fn check_dnf(input: &str, expect: Expect) {
|
||||
let source_file = ast::SourceFile::parse(input, Edition::CURRENT).ok().unwrap();
|
||||
let tt = source_file.syntax().descendants().find_map(ast::TokenTree::cast).unwrap();
|
||||
let tt = syntax_node_to_token_tree(tt.syntax(), DummyTestSpanMap, DUMMY);
|
||||
let tt = syntax_node_to_token_tree(
|
||||
tt.syntax(),
|
||||
DummyTestSpanMap,
|
||||
DUMMY,
|
||||
DocCommentDesugarMode::ProcMacro,
|
||||
);
|
||||
let cfg = CfgExpr::parse(&tt);
|
||||
let actual = format!("#![cfg({})]", DnfExpr::new(cfg));
|
||||
expect.assert_eq(&actual);
|
||||
|
@ -25,7 +35,12 @@ fn check_dnf(input: &str, expect: Expect) {
|
|||
fn check_why_inactive(input: &str, opts: &CfgOptions, expect: Expect) {
|
||||
let source_file = ast::SourceFile::parse(input, Edition::CURRENT).ok().unwrap();
|
||||
let tt = source_file.syntax().descendants().find_map(ast::TokenTree::cast).unwrap();
|
||||
let tt = syntax_node_to_token_tree(tt.syntax(), DummyTestSpanMap, DUMMY);
|
||||
let tt = syntax_node_to_token_tree(
|
||||
tt.syntax(),
|
||||
DummyTestSpanMap,
|
||||
DUMMY,
|
||||
DocCommentDesugarMode::ProcMacro,
|
||||
);
|
||||
let cfg = CfgExpr::parse(&tt);
|
||||
let dnf = DnfExpr::new(cfg);
|
||||
let why_inactive = dnf.why_inactive(opts).unwrap().to_string();
|
||||
|
@ -36,7 +51,12 @@ fn check_why_inactive(input: &str, opts: &CfgOptions, expect: Expect) {
|
|||
fn check_enable_hints(input: &str, opts: &CfgOptions, expected_hints: &[&str]) {
|
||||
let source_file = ast::SourceFile::parse(input, Edition::CURRENT).ok().unwrap();
|
||||
let tt = source_file.syntax().descendants().find_map(ast::TokenTree::cast).unwrap();
|
||||
let tt = syntax_node_to_token_tree(tt.syntax(), DummyTestSpanMap, DUMMY);
|
||||
let tt = syntax_node_to_token_tree(
|
||||
tt.syntax(),
|
||||
DummyTestSpanMap,
|
||||
DUMMY,
|
||||
DocCommentDesugarMode::ProcMacro,
|
||||
);
|
||||
let cfg = CfgExpr::parse(&tt);
|
||||
let dnf = DnfExpr::new(cfg);
|
||||
let hints = dnf.compute_enable_hints(opts).map(|diff| diff.to_string()).collect::<Vec<_>>();
|
||||
|
|
|
@ -125,8 +125,10 @@ impl FlycheckHandle {
|
|||
config: FlycheckConfig,
|
||||
sysroot_root: Option<AbsPathBuf>,
|
||||
workspace_root: AbsPathBuf,
|
||||
manifest_path: Option<AbsPathBuf>,
|
||||
) -> FlycheckHandle {
|
||||
let actor = FlycheckActor::new(id, sender, config, sysroot_root, workspace_root);
|
||||
let actor =
|
||||
FlycheckActor::new(id, sender, config, sysroot_root, workspace_root, manifest_path);
|
||||
let (sender, receiver) = unbounded::<StateChange>();
|
||||
let thread = stdx::thread::Builder::new(stdx::thread::ThreadIntent::Worker)
|
||||
.name("Flycheck".to_owned())
|
||||
|
@ -205,6 +207,7 @@ struct FlycheckActor {
|
|||
id: usize,
|
||||
sender: Box<dyn Fn(Message) + Send>,
|
||||
config: FlycheckConfig,
|
||||
manifest_path: Option<AbsPathBuf>,
|
||||
/// Either the workspace root of the workspace we are flychecking,
|
||||
/// or the project root of the project.
|
||||
root: AbsPathBuf,
|
||||
|
@ -233,6 +236,7 @@ impl FlycheckActor {
|
|||
config: FlycheckConfig,
|
||||
sysroot_root: Option<AbsPathBuf>,
|
||||
workspace_root: AbsPathBuf,
|
||||
manifest_path: Option<AbsPathBuf>,
|
||||
) -> FlycheckActor {
|
||||
tracing::info!(%id, ?workspace_root, "Spawning flycheck");
|
||||
FlycheckActor {
|
||||
|
@ -241,6 +245,7 @@ impl FlycheckActor {
|
|||
config,
|
||||
sysroot_root,
|
||||
root: workspace_root,
|
||||
manifest_path,
|
||||
command_handle: None,
|
||||
command_receiver: None,
|
||||
}
|
||||
|
@ -388,8 +393,13 @@ impl FlycheckActor {
|
|||
"--message-format=json"
|
||||
});
|
||||
|
||||
cmd.arg("--manifest-path");
|
||||
cmd.arg(self.root.join("Cargo.toml"));
|
||||
if let Some(manifest_path) = &self.manifest_path {
|
||||
cmd.arg("--manifest-path");
|
||||
cmd.arg(manifest_path);
|
||||
if manifest_path.extension().map_or(false, |ext| ext == "rs") {
|
||||
cmd.arg("-Zscript");
|
||||
}
|
||||
}
|
||||
|
||||
options.apply_on_command(&mut cmd);
|
||||
(cmd, options.extra_args.clone())
|
||||
|
|
|
@ -5,7 +5,7 @@ use triomphe::Arc;
|
|||
|
||||
use base_db::FileId;
|
||||
use hir_expand::span_map::{RealSpanMap, SpanMap};
|
||||
use mbe::syntax_node_to_token_tree;
|
||||
use mbe::{syntax_node_to_token_tree, DocCommentDesugarMode};
|
||||
use syntax::{ast, AstNode, TextRange};
|
||||
|
||||
use crate::attr::{DocAtom, DocExpr};
|
||||
|
@ -18,6 +18,7 @@ fn assert_parse_result(input: &str, expected: DocExpr) {
|
|||
tt.syntax(),
|
||||
map.as_ref(),
|
||||
map.span_for_range(TextRange::empty(0.into())),
|
||||
DocCommentDesugarMode::ProcMacro,
|
||||
);
|
||||
let cfg = DocExpr::parse(&tt);
|
||||
assert_eq!(cfg, expected);
|
||||
|
|
|
@ -10,9 +10,10 @@ use std::ops::Index;
|
|||
|
||||
use base_db::CrateId;
|
||||
use cfg::{CfgExpr, CfgOptions};
|
||||
use hir_expand::{name::Name, HirFileId, InFile};
|
||||
use hir_expand::{name::Name, InFile};
|
||||
use la_arena::{Arena, ArenaMap};
|
||||
use rustc_hash::FxHashMap;
|
||||
use span::MacroFileId;
|
||||
use syntax::{ast, AstPtr, SyntaxNodePtr};
|
||||
use triomphe::Arc;
|
||||
|
||||
|
@ -98,7 +99,7 @@ pub struct BodySourceMap {
|
|||
|
||||
format_args_template_map: FxHashMap<ExprId, Vec<(syntax::TextRange, Name)>>,
|
||||
|
||||
expansions: FxHashMap<InFile<AstPtr<ast::MacroCall>>, HirFileId>,
|
||||
expansions: FxHashMap<InFile<AstPtr<ast::MacroCall>>, MacroFileId>,
|
||||
|
||||
/// Diagnostics accumulated during body lowering. These contain `AstPtr`s and so are stored in
|
||||
/// the source map (since they're just as volatile).
|
||||
|
@ -349,11 +350,17 @@ impl BodySourceMap {
|
|||
self.expr_map.get(&src).cloned()
|
||||
}
|
||||
|
||||
pub fn node_macro_file(&self, node: InFile<&ast::MacroCall>) -> Option<HirFileId> {
|
||||
pub fn node_macro_file(&self, node: InFile<&ast::MacroCall>) -> Option<MacroFileId> {
|
||||
let src = node.map(AstPtr::new);
|
||||
self.expansions.get(&src).cloned()
|
||||
}
|
||||
|
||||
pub fn macro_calls(
|
||||
&self,
|
||||
) -> impl Iterator<Item = (InFile<AstPtr<ast::MacroCall>>, MacroFileId)> + '_ {
|
||||
self.expansions.iter().map(|(&a, &b)| (a, b))
|
||||
}
|
||||
|
||||
pub fn pat_syntax(&self, pat: PatId) -> Result<PatSource, SyntheticSyntax> {
|
||||
self.pat_map_back.get(pat).cloned().ok_or(SyntheticSyntax)
|
||||
}
|
||||
|
|
|
@ -1006,7 +1006,9 @@ impl ExprCollector<'_> {
|
|||
Some((mark, expansion)) => {
|
||||
// Keep collecting even with expansion errors so we can provide completions and
|
||||
// other services in incomplete macro expressions.
|
||||
self.source_map.expansions.insert(macro_call_ptr, self.expander.current_file_id());
|
||||
self.source_map
|
||||
.expansions
|
||||
.insert(macro_call_ptr, self.expander.current_file_id().macro_file().unwrap());
|
||||
let prev_ast_id_map = mem::replace(
|
||||
&mut self.ast_id_map,
|
||||
self.db.ast_id_map(self.expander.current_file_id()),
|
||||
|
@ -1869,42 +1871,45 @@ impl ExprCollector<'_> {
|
|||
) -> ExprId {
|
||||
match count {
|
||||
Some(FormatCount::Literal(n)) => {
|
||||
match LangItem::FormatCount.ty_rel_path(self.db, self.krate, name![Is]) {
|
||||
Some(count_is) => {
|
||||
let count_is = self.alloc_expr_desugared(Expr::Path(count_is));
|
||||
let args = self.alloc_expr_desugared(Expr::Literal(Literal::Uint(
|
||||
*n as u128,
|
||||
Some(BuiltinUint::Usize),
|
||||
)));
|
||||
self.alloc_expr_desugared(Expr::Call {
|
||||
callee: count_is,
|
||||
args: Box::new([args]),
|
||||
is_assignee_expr: false,
|
||||
})
|
||||
}
|
||||
None => self.missing_expr(),
|
||||
}
|
||||
let args = self.alloc_expr_desugared(Expr::Literal(Literal::Uint(
|
||||
*n as u128,
|
||||
Some(BuiltinUint::Usize),
|
||||
)));
|
||||
let count_is =
|
||||
match LangItem::FormatCount.ty_rel_path(self.db, self.krate, name![Is]) {
|
||||
Some(count_is) => self.alloc_expr_desugared(Expr::Path(count_is)),
|
||||
None => self.missing_expr(),
|
||||
};
|
||||
self.alloc_expr_desugared(Expr::Call {
|
||||
callee: count_is,
|
||||
args: Box::new([args]),
|
||||
is_assignee_expr: false,
|
||||
})
|
||||
}
|
||||
Some(FormatCount::Argument(arg)) => {
|
||||
if let Ok(arg_index) = arg.index {
|
||||
let (i, _) = argmap.insert_full((arg_index, ArgumentType::Usize));
|
||||
|
||||
match LangItem::FormatCount.ty_rel_path(self.db, self.krate, name![Param]) {
|
||||
Some(count_param) => {
|
||||
let count_param = self.alloc_expr_desugared(Expr::Path(count_param));
|
||||
let args = self.alloc_expr_desugared(Expr::Literal(Literal::Uint(
|
||||
i as u128,
|
||||
Some(BuiltinUint::Usize),
|
||||
)));
|
||||
self.alloc_expr_desugared(Expr::Call {
|
||||
callee: count_param,
|
||||
args: Box::new([args]),
|
||||
is_assignee_expr: false,
|
||||
})
|
||||
}
|
||||
let args = self.alloc_expr_desugared(Expr::Literal(Literal::Uint(
|
||||
i as u128,
|
||||
Some(BuiltinUint::Usize),
|
||||
)));
|
||||
let count_param = match LangItem::FormatCount.ty_rel_path(
|
||||
self.db,
|
||||
self.krate,
|
||||
name![Param],
|
||||
) {
|
||||
Some(count_param) => self.alloc_expr_desugared(Expr::Path(count_param)),
|
||||
None => self.missing_expr(),
|
||||
}
|
||||
};
|
||||
self.alloc_expr_desugared(Expr::Call {
|
||||
callee: count_param,
|
||||
args: Box::new([args]),
|
||||
is_assignee_expr: false,
|
||||
})
|
||||
} else {
|
||||
// FIXME: This drops arg causing it to potentially not be resolved/type checked
|
||||
// when typing?
|
||||
self.missing_expr()
|
||||
}
|
||||
}
|
||||
|
@ -1925,7 +1930,8 @@ impl ExprCollector<'_> {
|
|||
fn make_argument(&mut self, arg: ExprId, ty: ArgumentType) -> ExprId {
|
||||
use ArgumentType::*;
|
||||
use FormatTrait::*;
|
||||
match LangItem::FormatArgument.ty_rel_path(
|
||||
|
||||
let new_fn = match LangItem::FormatArgument.ty_rel_path(
|
||||
self.db,
|
||||
self.krate,
|
||||
match ty {
|
||||
|
@ -1941,16 +1947,14 @@ impl ExprCollector<'_> {
|
|||
Usize => name![from_usize],
|
||||
},
|
||||
) {
|
||||
Some(new_fn) => {
|
||||
let new_fn = self.alloc_expr_desugared(Expr::Path(new_fn));
|
||||
self.alloc_expr_desugared(Expr::Call {
|
||||
callee: new_fn,
|
||||
args: Box::new([arg]),
|
||||
is_assignee_expr: false,
|
||||
})
|
||||
}
|
||||
Some(new_fn) => self.alloc_expr_desugared(Expr::Path(new_fn)),
|
||||
None => self.missing_expr(),
|
||||
}
|
||||
};
|
||||
self.alloc_expr_desugared(Expr::Call {
|
||||
callee: new_fn,
|
||||
args: Box::new([arg]),
|
||||
is_assignee_expr: false,
|
||||
})
|
||||
}
|
||||
// endregion: format
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ use crate::{
|
|||
body::Body,
|
||||
db::DefDatabase,
|
||||
hir::{Binding, BindingId, Expr, ExprId, LabelId, Pat, PatId, Statement},
|
||||
BlockId, DefWithBodyId,
|
||||
BlockId, ConstBlockId, DefWithBodyId,
|
||||
};
|
||||
|
||||
pub type ScopeId = Idx<ScopeData>;
|
||||
|
@ -46,7 +46,9 @@ pub struct ScopeData {
|
|||
impl ExprScopes {
|
||||
pub(crate) fn expr_scopes_query(db: &dyn DefDatabase, def: DefWithBodyId) -> Arc<ExprScopes> {
|
||||
let body = db.body(def);
|
||||
let mut scopes = ExprScopes::new(&body);
|
||||
let mut scopes = ExprScopes::new(&body, |const_block| {
|
||||
db.lookup_intern_anonymous_const(const_block).root
|
||||
});
|
||||
scopes.shrink_to_fit();
|
||||
Arc::new(scopes)
|
||||
}
|
||||
|
@ -89,7 +91,10 @@ fn empty_entries(idx: usize) -> IdxRange<ScopeEntry> {
|
|||
}
|
||||
|
||||
impl ExprScopes {
|
||||
fn new(body: &Body) -> ExprScopes {
|
||||
fn new(
|
||||
body: &Body,
|
||||
resolve_const_block: impl (Fn(ConstBlockId) -> ExprId) + Copy,
|
||||
) -> ExprScopes {
|
||||
let mut scopes = ExprScopes {
|
||||
scopes: Arena::default(),
|
||||
scope_entries: Arena::default(),
|
||||
|
@ -100,7 +105,7 @@ impl ExprScopes {
|
|||
scopes.add_bindings(body, root, self_param);
|
||||
}
|
||||
scopes.add_params_bindings(body, root, &body.params);
|
||||
compute_expr_scopes(body.body_expr, body, &mut scopes, &mut root);
|
||||
compute_expr_scopes(body.body_expr, body, &mut scopes, &mut root, resolve_const_block);
|
||||
scopes
|
||||
}
|
||||
|
||||
|
@ -183,35 +188,46 @@ fn compute_block_scopes(
|
|||
body: &Body,
|
||||
scopes: &mut ExprScopes,
|
||||
scope: &mut ScopeId,
|
||||
resolve_const_block: impl (Fn(ConstBlockId) -> ExprId) + Copy,
|
||||
) {
|
||||
for stmt in statements {
|
||||
match stmt {
|
||||
Statement::Let { pat, initializer, else_branch, .. } => {
|
||||
if let Some(expr) = initializer {
|
||||
compute_expr_scopes(*expr, body, scopes, scope);
|
||||
compute_expr_scopes(*expr, body, scopes, scope, resolve_const_block);
|
||||
}
|
||||
if let Some(expr) = else_branch {
|
||||
compute_expr_scopes(*expr, body, scopes, scope);
|
||||
compute_expr_scopes(*expr, body, scopes, scope, resolve_const_block);
|
||||
}
|
||||
|
||||
*scope = scopes.new_scope(*scope);
|
||||
scopes.add_pat_bindings(body, *scope, *pat);
|
||||
}
|
||||
Statement::Expr { expr, .. } => {
|
||||
compute_expr_scopes(*expr, body, scopes, scope);
|
||||
compute_expr_scopes(*expr, body, scopes, scope, resolve_const_block);
|
||||
}
|
||||
Statement::Item => (),
|
||||
}
|
||||
}
|
||||
if let Some(expr) = tail {
|
||||
compute_expr_scopes(expr, body, scopes, scope);
|
||||
compute_expr_scopes(expr, body, scopes, scope, resolve_const_block);
|
||||
}
|
||||
}
|
||||
|
||||
fn compute_expr_scopes(expr: ExprId, body: &Body, scopes: &mut ExprScopes, scope: &mut ScopeId) {
|
||||
fn compute_expr_scopes(
|
||||
expr: ExprId,
|
||||
body: &Body,
|
||||
scopes: &mut ExprScopes,
|
||||
scope: &mut ScopeId,
|
||||
resolve_const_block: impl (Fn(ConstBlockId) -> ExprId) + Copy,
|
||||
) {
|
||||
let make_label =
|
||||
|label: &Option<LabelId>| label.map(|label| (label, body.labels[label].name.clone()));
|
||||
|
||||
let compute_expr_scopes = |scopes: &mut ExprScopes, expr: ExprId, scope: &mut ScopeId| {
|
||||
compute_expr_scopes(expr, body, scopes, scope, resolve_const_block)
|
||||
};
|
||||
|
||||
scopes.set_scope(expr, *scope);
|
||||
match &body[expr] {
|
||||
Expr::Block { statements, tail, id, label } => {
|
||||
|
@ -219,53 +235,54 @@ fn compute_expr_scopes(expr: ExprId, body: &Body, scopes: &mut ExprScopes, scope
|
|||
// Overwrite the old scope for the block expr, so that every block scope can be found
|
||||
// via the block itself (important for blocks that only contain items, no expressions).
|
||||
scopes.set_scope(expr, scope);
|
||||
compute_block_scopes(statements, *tail, body, scopes, &mut scope);
|
||||
compute_block_scopes(statements, *tail, body, scopes, &mut scope, resolve_const_block);
|
||||
}
|
||||
Expr::Const(_) => {
|
||||
// FIXME: This is broken.
|
||||
Expr::Const(id) => {
|
||||
let mut scope = scopes.root_scope();
|
||||
compute_expr_scopes(scopes, resolve_const_block(*id), &mut scope);
|
||||
}
|
||||
Expr::Unsafe { id, statements, tail } | Expr::Async { id, statements, tail } => {
|
||||
let mut scope = scopes.new_block_scope(*scope, *id, None);
|
||||
// Overwrite the old scope for the block expr, so that every block scope can be found
|
||||
// via the block itself (important for blocks that only contain items, no expressions).
|
||||
scopes.set_scope(expr, scope);
|
||||
compute_block_scopes(statements, *tail, body, scopes, &mut scope);
|
||||
compute_block_scopes(statements, *tail, body, scopes, &mut scope, resolve_const_block);
|
||||
}
|
||||
Expr::Loop { body: body_expr, label } => {
|
||||
let mut scope = scopes.new_labeled_scope(*scope, make_label(label));
|
||||
compute_expr_scopes(*body_expr, body, scopes, &mut scope);
|
||||
compute_expr_scopes(scopes, *body_expr, &mut scope);
|
||||
}
|
||||
Expr::Closure { args, body: body_expr, .. } => {
|
||||
let mut scope = scopes.new_scope(*scope);
|
||||
scopes.add_params_bindings(body, scope, args);
|
||||
compute_expr_scopes(*body_expr, body, scopes, &mut scope);
|
||||
compute_expr_scopes(scopes, *body_expr, &mut scope);
|
||||
}
|
||||
Expr::Match { expr, arms } => {
|
||||
compute_expr_scopes(*expr, body, scopes, scope);
|
||||
compute_expr_scopes(scopes, *expr, scope);
|
||||
for arm in arms.iter() {
|
||||
let mut scope = scopes.new_scope(*scope);
|
||||
scopes.add_pat_bindings(body, scope, arm.pat);
|
||||
if let Some(guard) = arm.guard {
|
||||
scope = scopes.new_scope(scope);
|
||||
compute_expr_scopes(guard, body, scopes, &mut scope);
|
||||
compute_expr_scopes(scopes, guard, &mut scope);
|
||||
}
|
||||
compute_expr_scopes(arm.expr, body, scopes, &mut scope);
|
||||
compute_expr_scopes(scopes, arm.expr, &mut scope);
|
||||
}
|
||||
}
|
||||
&Expr::If { condition, then_branch, else_branch } => {
|
||||
let mut then_branch_scope = scopes.new_scope(*scope);
|
||||
compute_expr_scopes(condition, body, scopes, &mut then_branch_scope);
|
||||
compute_expr_scopes(then_branch, body, scopes, &mut then_branch_scope);
|
||||
compute_expr_scopes(scopes, condition, &mut then_branch_scope);
|
||||
compute_expr_scopes(scopes, then_branch, &mut then_branch_scope);
|
||||
if let Some(else_branch) = else_branch {
|
||||
compute_expr_scopes(else_branch, body, scopes, scope);
|
||||
compute_expr_scopes(scopes, else_branch, scope);
|
||||
}
|
||||
}
|
||||
&Expr::Let { pat, expr } => {
|
||||
compute_expr_scopes(expr, body, scopes, scope);
|
||||
compute_expr_scopes(scopes, expr, scope);
|
||||
*scope = scopes.new_scope(*scope);
|
||||
scopes.add_pat_bindings(body, *scope, pat);
|
||||
}
|
||||
e => e.walk_child_exprs(|e| compute_expr_scopes(e, body, scopes, scope)),
|
||||
e => e.walk_child_exprs(|e| compute_expr_scopes(scopes, e, scope)),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -318,18 +318,20 @@ fn f() {
|
|||
|
||||
expect![[r#"
|
||||
fn f() {
|
||||
$crate::panicking::panic_fmt(
|
||||
builtin#lang(Arguments::new_v1_formatted)(
|
||||
&[
|
||||
"cc",
|
||||
],
|
||||
&[],
|
||||
&[],
|
||||
unsafe {
|
||||
builtin#lang(UnsafeArg::new)()
|
||||
},
|
||||
),
|
||||
);
|
||||
{
|
||||
$crate::panicking::panic_fmt(
|
||||
builtin#lang(Arguments::new_v1_formatted)(
|
||||
&[
|
||||
"cc",
|
||||
],
|
||||
&[],
|
||||
&[],
|
||||
unsafe {
|
||||
builtin#lang(UnsafeArg::new)()
|
||||
},
|
||||
),
|
||||
);
|
||||
};
|
||||
}"#]]
|
||||
.assert_eq(&body.pretty_print(&db, def))
|
||||
}
|
||||
|
|
|
@ -229,7 +229,7 @@ pub struct TraitData {
|
|||
/// method calls to this trait's methods when the receiver is an array and the crate edition is
|
||||
/// 2015 or 2018.
|
||||
// box it as the vec is usually empty anyways
|
||||
pub attribute_calls: Option<Box<Vec<(AstId<ast::Item>, MacroCallId)>>>,
|
||||
pub macro_calls: Option<Box<Vec<(AstId<ast::Item>, MacroCallId)>>>,
|
||||
}
|
||||
|
||||
impl TraitData {
|
||||
|
@ -258,12 +258,12 @@ impl TraitData {
|
|||
let mut collector =
|
||||
AssocItemCollector::new(db, module_id, tree_id.file_id(), ItemContainerId::TraitId(tr));
|
||||
collector.collect(&item_tree, tree_id.tree_id(), &tr_def.items);
|
||||
let (items, attribute_calls, diagnostics) = collector.finish();
|
||||
let (items, macro_calls, diagnostics) = collector.finish();
|
||||
|
||||
(
|
||||
Arc::new(TraitData {
|
||||
name,
|
||||
attribute_calls,
|
||||
macro_calls,
|
||||
items,
|
||||
is_auto,
|
||||
is_unsafe,
|
||||
|
@ -298,7 +298,7 @@ impl TraitData {
|
|||
}
|
||||
|
||||
pub fn attribute_calls(&self) -> impl Iterator<Item = (AstId<ast::Item>, MacroCallId)> + '_ {
|
||||
self.attribute_calls.iter().flat_map(|it| it.iter()).copied()
|
||||
self.macro_calls.iter().flat_map(|it| it.iter()).copied()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -319,7 +319,7 @@ impl TraitAliasData {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub struct ImplData {
|
||||
pub target_trait: Option<Interned<TraitRef>>,
|
||||
pub self_ty: Interned<TypeRef>,
|
||||
|
@ -327,7 +327,7 @@ pub struct ImplData {
|
|||
pub is_negative: bool,
|
||||
pub is_unsafe: bool,
|
||||
// box it as the vec is usually empty anyways
|
||||
pub attribute_calls: Option<Box<Vec<(AstId<ast::Item>, MacroCallId)>>>,
|
||||
pub macro_calls: Option<Box<Vec<(AstId<ast::Item>, MacroCallId)>>>,
|
||||
}
|
||||
|
||||
impl ImplData {
|
||||
|
@ -354,7 +354,7 @@ impl ImplData {
|
|||
AssocItemCollector::new(db, module_id, tree_id.file_id(), ItemContainerId::ImplId(id));
|
||||
collector.collect(&item_tree, tree_id.tree_id(), &impl_def.items);
|
||||
|
||||
let (items, attribute_calls, diagnostics) = collector.finish();
|
||||
let (items, macro_calls, diagnostics) = collector.finish();
|
||||
let items = items.into_iter().map(|(_, item)| item).collect();
|
||||
|
||||
(
|
||||
|
@ -364,14 +364,14 @@ impl ImplData {
|
|||
items,
|
||||
is_negative,
|
||||
is_unsafe,
|
||||
attribute_calls,
|
||||
macro_calls,
|
||||
}),
|
||||
DefDiagnostics::new(diagnostics),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn attribute_calls(&self) -> impl Iterator<Item = (AstId<ast::Item>, MacroCallId)> + '_ {
|
||||
self.attribute_calls.iter().flat_map(|it| it.iter()).copied()
|
||||
self.macro_calls.iter().flat_map(|it| it.iter()).copied()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -573,7 +573,7 @@ struct AssocItemCollector<'a> {
|
|||
expander: Expander,
|
||||
|
||||
items: Vec<(Name, AssocItemId)>,
|
||||
attr_calls: Vec<(AstId<ast::Item>, MacroCallId)>,
|
||||
macro_calls: Vec<(AstId<ast::Item>, MacroCallId)>,
|
||||
}
|
||||
|
||||
impl<'a> AssocItemCollector<'a> {
|
||||
|
@ -590,7 +590,7 @@ impl<'a> AssocItemCollector<'a> {
|
|||
container,
|
||||
expander: Expander::new(db, file_id, module_id),
|
||||
items: Vec::new(),
|
||||
attr_calls: Vec::new(),
|
||||
macro_calls: Vec::new(),
|
||||
diagnostics: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
@ -604,7 +604,7 @@ impl<'a> AssocItemCollector<'a> {
|
|||
) {
|
||||
(
|
||||
self.items,
|
||||
if self.attr_calls.is_empty() { None } else { Some(Box::new(self.attr_calls)) },
|
||||
if self.macro_calls.is_empty() { None } else { Some(Box::new(self.macro_calls)) },
|
||||
self.diagnostics,
|
||||
)
|
||||
}
|
||||
|
@ -662,11 +662,11 @@ impl<'a> AssocItemCollector<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
self.attr_calls.push((ast_id, call_id));
|
||||
self.macro_calls.push((ast_id, call_id));
|
||||
|
||||
let res =
|
||||
self.expander.enter_expand_id::<ast::MacroItems>(self.db, call_id);
|
||||
self.collect_macro_items(res, &|| loc.kind.clone());
|
||||
self.collect_macro_items(res);
|
||||
continue 'items;
|
||||
}
|
||||
Ok(_) => (),
|
||||
|
@ -698,24 +698,22 @@ impl<'a> AssocItemCollector<'a> {
|
|||
match item {
|
||||
AssocItem::Function(id) => {
|
||||
let item = &item_tree[id];
|
||||
|
||||
let def =
|
||||
FunctionLoc { container, id: ItemTreeId::new(tree_id, id) }.intern(self.db);
|
||||
self.items.push((item.name.clone(), def.into()));
|
||||
}
|
||||
AssocItem::TypeAlias(id) => {
|
||||
let item = &item_tree[id];
|
||||
let def =
|
||||
TypeAliasLoc { container, id: ItemTreeId::new(tree_id, id) }.intern(self.db);
|
||||
self.items.push((item.name.clone(), def.into()));
|
||||
}
|
||||
AssocItem::Const(id) => {
|
||||
let item = &item_tree[id];
|
||||
let Some(name) = item.name.clone() else { return };
|
||||
let def = ConstLoc { container, id: ItemTreeId::new(tree_id, id) }.intern(self.db);
|
||||
self.items.push((name, def.into()));
|
||||
}
|
||||
AssocItem::TypeAlias(id) => {
|
||||
let item = &item_tree[id];
|
||||
|
||||
let def =
|
||||
TypeAliasLoc { container, id: ItemTreeId::new(tree_id, id) }.intern(self.db);
|
||||
self.items.push((item.name.clone(), def.into()));
|
||||
}
|
||||
AssocItem::MacroCall(call) => {
|
||||
let file_id = self.expander.current_file_id();
|
||||
let MacroCall { ast_id, expand_to, ctxt, ref path } = item_tree[call];
|
||||
|
@ -745,11 +743,8 @@ impl<'a> AssocItemCollector<'a> {
|
|||
Ok(Some(call_id)) => {
|
||||
let res =
|
||||
self.expander.enter_expand_id::<ast::MacroItems>(self.db, call_id);
|
||||
self.collect_macro_items(res, &|| hir_expand::MacroCallKind::FnLike {
|
||||
ast_id: InFile::new(file_id, ast_id),
|
||||
expand_to: hir_expand::ExpandTo::Items,
|
||||
eager: None,
|
||||
});
|
||||
self.macro_calls.push((InFile::new(file_id, ast_id.upcast()), call_id));
|
||||
self.collect_macro_items(res);
|
||||
}
|
||||
Ok(None) => (),
|
||||
Err(_) => {
|
||||
|
@ -768,39 +763,8 @@ impl<'a> AssocItemCollector<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn collect_macro_items(
|
||||
&mut self,
|
||||
ExpandResult { value, err }: ExpandResult<Option<(Mark, Parse<ast::MacroItems>)>>,
|
||||
error_call_kind: &dyn Fn() -> hir_expand::MacroCallKind,
|
||||
) {
|
||||
let Some((mark, parse)) = value else { return };
|
||||
|
||||
if let Some(err) = err {
|
||||
let diag = match err {
|
||||
// why is this reported here?
|
||||
hir_expand::ExpandError::UnresolvedProcMacro(krate) => {
|
||||
DefDiagnostic::unresolved_proc_macro(
|
||||
self.module_id.local_id,
|
||||
error_call_kind(),
|
||||
krate,
|
||||
)
|
||||
}
|
||||
_ => DefDiagnostic::macro_error(
|
||||
self.module_id.local_id,
|
||||
error_call_kind(),
|
||||
err.to_string(),
|
||||
),
|
||||
};
|
||||
self.diagnostics.push(diag);
|
||||
}
|
||||
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.into_boxed_slice(),
|
||||
));
|
||||
}
|
||||
fn collect_macro_items(&mut self, res: ExpandResult<Option<(Mark, Parse<ast::MacroItems>)>>) {
|
||||
let Some((mark, _parse)) = res.value else { return };
|
||||
|
||||
let tree_id = item_tree::TreeId::new(self.expander.current_file_id(), None);
|
||||
let item_tree = tree_id.item_tree(self.db);
|
||||
|
|
|
@ -1177,6 +1177,8 @@ pub mod fmt {
|
|||
//- /main.rs crate:main deps:alloc,std
|
||||
#![no_std]
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
$0
|
||||
|
||||
//- /std.rs crate:std deps:alloc
|
||||
|
|
|
@ -20,7 +20,7 @@ use triomphe::Arc;
|
|||
use crate::{
|
||||
db::DefDatabase,
|
||||
expander::Expander,
|
||||
item_tree::{GenericsItemTreeNode, ItemTree},
|
||||
item_tree::{AttrOwner, FileItemTreeId, GenericModItem, GenericsItemTreeNode, ItemTree},
|
||||
lower::LowerCtx,
|
||||
nameres::{DefMap, MacroSubNs},
|
||||
type_ref::{ConstRef, LifetimeRef, TypeBound, TypeRef},
|
||||
|
@ -339,6 +339,7 @@ impl GenericParamsCollector {
|
|||
target: Either<TypeRef, LifetimeRef>,
|
||||
) {
|
||||
let bound = TypeBound::from_ast(lower_ctx, bound);
|
||||
self.fill_impl_trait_bounds(lower_ctx.take_impl_traits_bounds());
|
||||
let predicate = match (target, bound) {
|
||||
(Either::Left(type_ref), bound) => match hrtb_lifetimes {
|
||||
Some(hrtb_lifetimes) => WherePredicate::ForLifetime {
|
||||
|
@ -359,7 +360,24 @@ impl GenericParamsCollector {
|
|||
self.where_predicates.push(predicate);
|
||||
}
|
||||
|
||||
pub(crate) fn fill_implicit_impl_trait_args(
|
||||
fn fill_impl_trait_bounds(&mut self, impl_bounds: Vec<Vec<Interned<TypeBound>>>) {
|
||||
for bounds in impl_bounds {
|
||||
let param = TypeParamData {
|
||||
name: None,
|
||||
default: None,
|
||||
provenance: TypeParamProvenance::ArgumentImplTrait,
|
||||
};
|
||||
let param_id = self.type_or_consts.alloc(param.into());
|
||||
for bound in bounds {
|
||||
self.where_predicates.push(WherePredicate::TypeBound {
|
||||
target: WherePredicateTypeTarget::TypeOrConstParam(param_id),
|
||||
bound,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn fill_implicit_impl_trait_args(
|
||||
&mut self,
|
||||
db: &dyn DefDatabase,
|
||||
exp: &mut Lazy<(Arc<DefMap>, Expander), impl FnOnce() -> (Arc<DefMap>, Expander)>,
|
||||
|
@ -456,56 +474,67 @@ impl GenericParams {
|
|||
let cfg_options = &cfg_options[krate].cfg_options;
|
||||
|
||||
// Returns the generic parameters that are enabled under the current `#[cfg]` options
|
||||
let enabled_params = |params: &Interned<GenericParams>, item_tree: &ItemTree| {
|
||||
let enabled = |param| item_tree.attrs(db, krate, param).is_cfg_enabled(cfg_options);
|
||||
let enabled_params =
|
||||
|params: &Interned<GenericParams>, item_tree: &ItemTree, parent: GenericModItem| {
|
||||
let enabled = |param| item_tree.attrs(db, krate, param).is_cfg_enabled(cfg_options);
|
||||
let attr_owner_ct = |param| AttrOwner::TypeOrConstParamData(parent, param);
|
||||
let attr_owner_lt = |param| AttrOwner::LifetimeParamData(parent, param);
|
||||
|
||||
// In the common case, no parameters will by disabled by `#[cfg]` attributes.
|
||||
// Therefore, make a first pass to check if all parameters are enabled and, if so,
|
||||
// clone the `Interned<GenericParams>` instead of recreating an identical copy.
|
||||
let all_type_or_consts_enabled =
|
||||
params.type_or_consts.iter().all(|(idx, _)| enabled(idx.into()));
|
||||
let all_lifetimes_enabled = params.lifetimes.iter().all(|(idx, _)| enabled(idx.into()));
|
||||
// In the common case, no parameters will by disabled by `#[cfg]` attributes.
|
||||
// Therefore, make a first pass to check if all parameters are enabled and, if so,
|
||||
// clone the `Interned<GenericParams>` instead of recreating an identical copy.
|
||||
let all_type_or_consts_enabled =
|
||||
params.type_or_consts.iter().all(|(idx, _)| enabled(attr_owner_ct(idx)));
|
||||
let all_lifetimes_enabled =
|
||||
params.lifetimes.iter().all(|(idx, _)| enabled(attr_owner_lt(idx)));
|
||||
|
||||
if all_type_or_consts_enabled && all_lifetimes_enabled {
|
||||
params.clone()
|
||||
} else {
|
||||
Interned::new(GenericParams {
|
||||
type_or_consts: all_type_or_consts_enabled
|
||||
.then(|| params.type_or_consts.clone())
|
||||
.unwrap_or_else(|| {
|
||||
params
|
||||
.type_or_consts
|
||||
.iter()
|
||||
.filter(|(idx, _)| enabled((*idx).into()))
|
||||
.map(|(_, param)| param.clone())
|
||||
.collect()
|
||||
}),
|
||||
lifetimes: all_lifetimes_enabled
|
||||
.then(|| params.lifetimes.clone())
|
||||
.unwrap_or_else(|| {
|
||||
params
|
||||
.lifetimes
|
||||
.iter()
|
||||
.filter(|(idx, _)| enabled((*idx).into()))
|
||||
.map(|(_, param)| param.clone())
|
||||
.collect()
|
||||
}),
|
||||
where_predicates: params.where_predicates.clone(),
|
||||
})
|
||||
}
|
||||
};
|
||||
if all_type_or_consts_enabled && all_lifetimes_enabled {
|
||||
params.clone()
|
||||
} else {
|
||||
Interned::new(GenericParams {
|
||||
type_or_consts: all_type_or_consts_enabled
|
||||
.then(|| params.type_or_consts.clone())
|
||||
.unwrap_or_else(|| {
|
||||
params
|
||||
.type_or_consts
|
||||
.iter()
|
||||
.filter(|&(idx, _)| enabled(attr_owner_ct(idx)))
|
||||
.map(|(_, param)| param.clone())
|
||||
.collect()
|
||||
}),
|
||||
lifetimes: all_lifetimes_enabled
|
||||
.then(|| params.lifetimes.clone())
|
||||
.unwrap_or_else(|| {
|
||||
params
|
||||
.lifetimes
|
||||
.iter()
|
||||
.filter(|&(idx, _)| enabled(attr_owner_lt(idx)))
|
||||
.map(|(_, param)| param.clone())
|
||||
.collect()
|
||||
}),
|
||||
where_predicates: params.where_predicates.clone(),
|
||||
})
|
||||
}
|
||||
};
|
||||
fn id_to_generics<Id: GenericsItemTreeNode>(
|
||||
db: &dyn DefDatabase,
|
||||
id: impl for<'db> Lookup<
|
||||
Database<'db> = dyn DefDatabase + 'db,
|
||||
Data = impl ItemTreeLoc<Id = Id>,
|
||||
>,
|
||||
enabled_params: impl Fn(&Interned<GenericParams>, &ItemTree) -> Interned<GenericParams>,
|
||||
) -> Interned<GenericParams> {
|
||||
enabled_params: impl Fn(
|
||||
&Interned<GenericParams>,
|
||||
&ItemTree,
|
||||
GenericModItem,
|
||||
) -> Interned<GenericParams>,
|
||||
) -> Interned<GenericParams>
|
||||
where
|
||||
FileItemTreeId<Id>: Into<GenericModItem>,
|
||||
{
|
||||
let id = id.lookup(db).item_tree_id();
|
||||
let tree = id.item_tree(db);
|
||||
let item = &tree[id.value];
|
||||
enabled_params(item.generic_params(), &tree)
|
||||
enabled_params(item.generic_params(), &tree, id.value.into())
|
||||
}
|
||||
|
||||
match def {
|
||||
|
@ -514,7 +543,8 @@ impl GenericParams {
|
|||
let tree = loc.id.item_tree(db);
|
||||
let item = &tree[loc.id.value];
|
||||
|
||||
let enabled_params = enabled_params(&item.explicit_generic_params, &tree);
|
||||
let enabled_params =
|
||||
enabled_params(&item.explicit_generic_params, &tree, loc.id.value.into());
|
||||
|
||||
let module = loc.container.module(db);
|
||||
let func_data = db.function_data(id);
|
||||
|
|
|
@ -136,15 +136,15 @@ impl From<ast::LiteralKind> for Literal {
|
|||
Literal::Float(FloatTypeWrapper::new(lit.value().unwrap_or(Default::default())), ty)
|
||||
}
|
||||
LiteralKind::ByteString(bs) => {
|
||||
let text = bs.value().map(Box::from).unwrap_or_else(Default::default);
|
||||
let text = bs.value().map_or_else(|_| Default::default(), Box::from);
|
||||
Literal::ByteString(text)
|
||||
}
|
||||
LiteralKind::String(s) => {
|
||||
let text = s.value().map(Box::from).unwrap_or_else(Default::default);
|
||||
let text = s.value().map_or_else(|_| Default::default(), Box::from);
|
||||
Literal::String(text)
|
||||
}
|
||||
LiteralKind::CString(s) => {
|
||||
let text = s.value().map(Box::from).unwrap_or_else(Default::default);
|
||||
let text = s.value().map_or_else(|_| Default::default(), Box::from);
|
||||
Literal::CString(text)
|
||||
}
|
||||
LiteralKind::Byte(b) => {
|
||||
|
|
|
@ -234,6 +234,14 @@ impl ItemScope {
|
|||
self.impls.iter().copied()
|
||||
}
|
||||
|
||||
pub fn all_macro_calls(&self) -> impl Iterator<Item = MacroCallId> + '_ {
|
||||
self.macro_invocations.values().copied().chain(self.attr_macros.values().copied()).chain(
|
||||
self.derive_macros.values().flat_map(|it| {
|
||||
it.iter().flat_map(|it| it.derive_call_ids.iter().copied().flatten())
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
pub(crate) fn modules_in_scope(&self) -> impl Iterator<Item = (ModuleId, Visibility)> + '_ {
|
||||
self.types.values().copied().filter_map(|(def, vis, _)| match def {
|
||||
ModuleDefId::ModuleId(module) => Some((module, vis)),
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
//!
|
||||
//! In general, any item in the `ItemTree` stores its `AstId`, which allows mapping it back to its
|
||||
//! surface syntax.
|
||||
#![allow(unexpected_cfgs)]
|
||||
|
||||
mod lower;
|
||||
mod pretty;
|
||||
|
@ -57,21 +58,21 @@ use triomphe::Arc;
|
|||
use crate::{
|
||||
attr::Attrs,
|
||||
db::DefDatabase,
|
||||
generics::{GenericParams, LifetimeParamData, TypeOrConstParamData},
|
||||
generics::GenericParams,
|
||||
path::{GenericArgs, ImportAlias, ModPath, Path, PathKind},
|
||||
type_ref::{Mutability, TraitRef, TypeBound, TypeRef},
|
||||
visibility::{RawVisibility, VisibilityExplicitness},
|
||||
BlockId, Lookup,
|
||||
BlockId, LocalLifetimeParamId, LocalTypeOrConstParamId, Lookup,
|
||||
};
|
||||
|
||||
#[derive(Copy, Clone, Eq, PartialEq)]
|
||||
pub struct RawVisibilityId(u32);
|
||||
|
||||
impl RawVisibilityId {
|
||||
pub const PUB: Self = RawVisibilityId(u32::max_value());
|
||||
pub const PRIV_IMPLICIT: Self = RawVisibilityId(u32::max_value() - 1);
|
||||
pub const PRIV_EXPLICIT: Self = RawVisibilityId(u32::max_value() - 2);
|
||||
pub const PUB_CRATE: Self = RawVisibilityId(u32::max_value() - 3);
|
||||
pub const PUB: Self = RawVisibilityId(u32::MAX);
|
||||
pub const PRIV_IMPLICIT: Self = RawVisibilityId(u32::MAX - 1);
|
||||
pub const PRIV_EXPLICIT: Self = RawVisibilityId(u32::MAX - 2);
|
||||
pub const PUB_CRATE: Self = RawVisibilityId(u32::MAX - 3);
|
||||
}
|
||||
|
||||
impl fmt::Debug for RawVisibilityId {
|
||||
|
@ -293,8 +294,8 @@ pub enum AttrOwner {
|
|||
Variant(FileItemTreeId<Variant>),
|
||||
Field(Idx<Field>),
|
||||
Param(Idx<Param>),
|
||||
TypeOrConstParamData(Idx<TypeOrConstParamData>),
|
||||
LifetimeParamData(Idx<LifetimeParamData>),
|
||||
TypeOrConstParamData(GenericModItem, LocalTypeOrConstParamId),
|
||||
LifetimeParamData(GenericModItem, LocalLifetimeParamId),
|
||||
}
|
||||
|
||||
macro_rules! from_attrs {
|
||||
|
@ -314,8 +315,6 @@ from_attrs!(
|
|||
Variant(FileItemTreeId<Variant>),
|
||||
Field(Idx<Field>),
|
||||
Param(Idx<Param>),
|
||||
TypeOrConstParamData(Idx<TypeOrConstParamData>),
|
||||
LifetimeParamData(Idx<LifetimeParamData>),
|
||||
);
|
||||
|
||||
/// Trait implemented by all nodes in the item tree.
|
||||
|
@ -465,12 +464,49 @@ macro_rules! mod_items {
|
|||
)+
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
|
||||
pub enum GenericModItem {
|
||||
$(
|
||||
$(
|
||||
#[cfg_attr(ignore_fragment, $generic_params)]
|
||||
$typ(FileItemTreeId<$typ>),
|
||||
)?
|
||||
)+
|
||||
}
|
||||
|
||||
impl From<GenericModItem> for ModItem {
|
||||
fn from(id: GenericModItem) -> ModItem {
|
||||
match id {
|
||||
$(
|
||||
$(
|
||||
#[cfg_attr(ignore_fragment, $generic_params)]
|
||||
GenericModItem::$typ(id) => ModItem::$typ(id),
|
||||
)?
|
||||
)+
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<GenericModItem> for AttrOwner {
|
||||
fn from(t: GenericModItem) -> AttrOwner {
|
||||
AttrOwner::ModItem(t.into())
|
||||
}
|
||||
}
|
||||
|
||||
$(
|
||||
impl From<FileItemTreeId<$typ>> for ModItem {
|
||||
fn from(id: FileItemTreeId<$typ>) -> ModItem {
|
||||
ModItem::$typ(id)
|
||||
}
|
||||
}
|
||||
$(
|
||||
#[cfg_attr(ignore_fragment, $generic_params)]
|
||||
impl From<FileItemTreeId<$typ>> for GenericModItem {
|
||||
fn from(id: FileItemTreeId<$typ>) -> GenericModItem {
|
||||
GenericModItem::$typ(id)
|
||||
}
|
||||
}
|
||||
)?
|
||||
)+
|
||||
|
||||
$(
|
||||
|
|
|
@ -4,6 +4,7 @@ use std::collections::hash_map::Entry;
|
|||
|
||||
use hir_expand::{mod_path::path, name, name::AsName, span_map::SpanMapRef, HirFileId};
|
||||
use la_arena::Arena;
|
||||
use rustc_hash::FxHashMap;
|
||||
use span::{AstIdMap, SyntaxContextId};
|
||||
use syntax::{
|
||||
ast::{self, HasModuleItem, HasName, HasTypeBounds, IsString},
|
||||
|
@ -16,11 +17,11 @@ use crate::{
|
|||
generics::{GenericParams, GenericParamsCollector, TypeParamData, TypeParamProvenance},
|
||||
item_tree::{
|
||||
AssocItem, AttrOwner, Const, Either, Enum, ExternBlock, ExternCrate, Field, FieldAstId,
|
||||
Fields, FileItemTreeId, FnFlags, Function, GenericArgs, Idx, IdxRange, Impl, ImportAlias,
|
||||
Interned, ItemTree, ItemTreeData, ItemTreeNode, Macro2, MacroCall, MacroRules, Mod,
|
||||
ModItem, ModKind, ModPath, Mutability, Name, Param, ParamAstId, Path, Range, RawAttrs,
|
||||
RawIdx, RawVisibilityId, Static, Struct, StructKind, Trait, TraitAlias, TypeAlias, Union,
|
||||
Use, UseTree, UseTreeKind, Variant,
|
||||
Fields, FileItemTreeId, FnFlags, Function, GenericArgs, GenericModItem, Idx, IdxRange,
|
||||
Impl, ImportAlias, Interned, ItemTree, ItemTreeData, ItemTreeNode, Macro2, MacroCall,
|
||||
MacroRules, Mod, ModItem, ModKind, ModPath, Mutability, Name, Param, ParamAstId, Path,
|
||||
Range, RawAttrs, RawIdx, RawVisibilityId, Static, Struct, StructKind, Trait, TraitAlias,
|
||||
TypeAlias, Union, Use, UseTree, UseTreeKind, Variant,
|
||||
},
|
||||
path::AssociatedTypeBinding,
|
||||
type_ref::{LifetimeRef, TraitBoundModifier, TraitRef, TypeBound, TypeRef},
|
||||
|
@ -36,6 +37,8 @@ pub(super) struct Ctx<'a> {
|
|||
db: &'a dyn DefDatabase,
|
||||
tree: ItemTree,
|
||||
source_ast_id_map: Arc<AstIdMap>,
|
||||
generic_param_attr_buffer:
|
||||
FxHashMap<Either<LocalTypeOrConstParamId, LocalLifetimeParamId>, RawAttrs>,
|
||||
body_ctx: crate::lower::LowerCtx<'a>,
|
||||
}
|
||||
|
||||
|
@ -44,6 +47,7 @@ impl<'a> Ctx<'a> {
|
|||
Self {
|
||||
db,
|
||||
tree: ItemTree::default(),
|
||||
generic_param_attr_buffer: FxHashMap::default(),
|
||||
source_ast_id_map: db.ast_id_map(file),
|
||||
body_ctx: crate::lower::LowerCtx::new(db, file),
|
||||
}
|
||||
|
@ -56,6 +60,7 @@ impl<'a> Ctx<'a> {
|
|||
pub(super) fn lower_module_items(mut self, item_owner: &dyn HasModuleItem) -> ItemTree {
|
||||
self.tree.top_level =
|
||||
item_owner.items().flat_map(|item| self.lower_mod_item(&item)).collect();
|
||||
assert!(self.generic_param_attr_buffer.is_empty());
|
||||
self.tree
|
||||
}
|
||||
|
||||
|
@ -89,6 +94,7 @@ impl<'a> Ctx<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
assert!(self.generic_param_attr_buffer.is_empty());
|
||||
self.tree
|
||||
}
|
||||
|
||||
|
@ -117,6 +123,7 @@ impl<'a> Ctx<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
assert!(self.generic_param_attr_buffer.is_empty());
|
||||
self.tree
|
||||
}
|
||||
|
||||
|
@ -185,10 +192,12 @@ impl<'a> Ctx<'a> {
|
|||
let visibility = self.lower_visibility(strukt);
|
||||
let name = strukt.name()?.as_name();
|
||||
let ast_id = self.source_ast_id_map.ast_id(strukt);
|
||||
let generic_params = self.lower_generic_params(HasImplicitSelf::No, strukt);
|
||||
let fields = self.lower_fields(&strukt.kind());
|
||||
let generic_params = self.lower_generic_params(HasImplicitSelf::No, strukt);
|
||||
let res = Struct { name, visibility, generic_params, fields, ast_id };
|
||||
Some(id(self.data().structs.alloc(res)))
|
||||
let id = id(self.data().structs.alloc(res));
|
||||
self.write_generic_params_attributes(id.into());
|
||||
Some(id)
|
||||
}
|
||||
|
||||
fn lower_fields(&mut self, strukt_kind: &ast::StructKind) -> Fields {
|
||||
|
@ -252,28 +261,32 @@ impl<'a> Ctx<'a> {
|
|||
let visibility = self.lower_visibility(union);
|
||||
let name = union.name()?.as_name();
|
||||
let ast_id = self.source_ast_id_map.ast_id(union);
|
||||
let generic_params = self.lower_generic_params(HasImplicitSelf::No, union);
|
||||
let fields = match union.record_field_list() {
|
||||
Some(record_field_list) => self.lower_fields(&StructKind::Record(record_field_list)),
|
||||
None => Fields::Record(IdxRange::new(self.next_field_idx()..self.next_field_idx())),
|
||||
};
|
||||
let generic_params = self.lower_generic_params(HasImplicitSelf::No, union);
|
||||
let res = Union { name, visibility, generic_params, fields, ast_id };
|
||||
Some(id(self.data().unions.alloc(res)))
|
||||
let id = id(self.data().unions.alloc(res));
|
||||
self.write_generic_params_attributes(id.into());
|
||||
Some(id)
|
||||
}
|
||||
|
||||
fn lower_enum(&mut self, enum_: &ast::Enum) -> Option<FileItemTreeId<Enum>> {
|
||||
let visibility = self.lower_visibility(enum_);
|
||||
let name = enum_.name()?.as_name();
|
||||
let ast_id = self.source_ast_id_map.ast_id(enum_);
|
||||
let generic_params = self.lower_generic_params(HasImplicitSelf::No, enum_);
|
||||
let variants = match &enum_.variant_list() {
|
||||
Some(variant_list) => self.lower_variants(variant_list),
|
||||
None => {
|
||||
FileItemTreeId(self.next_variant_idx())..FileItemTreeId(self.next_variant_idx())
|
||||
}
|
||||
};
|
||||
let generic_params = self.lower_generic_params(HasImplicitSelf::No, enum_);
|
||||
let res = Enum { name, visibility, generic_params, variants, ast_id };
|
||||
Some(id(self.data().enums.alloc(res)))
|
||||
let id = id(self.data().enums.alloc(res));
|
||||
self.write_generic_params_attributes(id.into());
|
||||
Some(id)
|
||||
}
|
||||
|
||||
fn lower_variants(&mut self, variants: &ast::VariantList) -> Range<FileItemTreeId<Variant>> {
|
||||
|
@ -414,7 +427,9 @@ impl<'a> Ctx<'a> {
|
|||
flags,
|
||||
};
|
||||
|
||||
Some(id(self.data().functions.alloc(res)))
|
||||
let id = id(self.data().functions.alloc(res));
|
||||
self.write_generic_params_attributes(id.into());
|
||||
Some(id)
|
||||
}
|
||||
|
||||
fn lower_type_alias(
|
||||
|
@ -428,7 +443,9 @@ impl<'a> Ctx<'a> {
|
|||
let ast_id = self.source_ast_id_map.ast_id(type_alias);
|
||||
let generic_params = self.lower_generic_params(HasImplicitSelf::No, type_alias);
|
||||
let res = TypeAlias { name, visibility, bounds, generic_params, type_ref, ast_id };
|
||||
Some(id(self.data().type_aliases.alloc(res)))
|
||||
let id = id(self.data().type_aliases.alloc(res));
|
||||
self.write_generic_params_attributes(id.into());
|
||||
Some(id)
|
||||
}
|
||||
|
||||
fn lower_static(&mut self, static_: &ast::Static) -> Option<FileItemTreeId<Static>> {
|
||||
|
@ -475,8 +492,6 @@ impl<'a> Ctx<'a> {
|
|||
let name = trait_def.name()?.as_name();
|
||||
let visibility = self.lower_visibility(trait_def);
|
||||
let ast_id = self.source_ast_id_map.ast_id(trait_def);
|
||||
let generic_params =
|
||||
self.lower_generic_params(HasImplicitSelf::Yes(trait_def.type_bound_list()), trait_def);
|
||||
let is_auto = trait_def.auto_token().is_some();
|
||||
let is_unsafe = trait_def.unsafe_token().is_some();
|
||||
|
||||
|
@ -487,8 +502,12 @@ impl<'a> Ctx<'a> {
|
|||
.filter_map(|item_node| self.lower_assoc_item(&item_node))
|
||||
.collect();
|
||||
|
||||
let generic_params =
|
||||
self.lower_generic_params(HasImplicitSelf::Yes(trait_def.type_bound_list()), trait_def);
|
||||
let def = Trait { name, visibility, generic_params, is_auto, is_unsafe, items, ast_id };
|
||||
Some(id(self.data().traits.alloc(def)))
|
||||
let id = id(self.data().traits.alloc(def));
|
||||
self.write_generic_params_attributes(id.into());
|
||||
Some(id)
|
||||
}
|
||||
|
||||
fn lower_trait_alias(
|
||||
|
@ -504,19 +523,18 @@ impl<'a> Ctx<'a> {
|
|||
);
|
||||
|
||||
let alias = TraitAlias { name, visibility, generic_params, ast_id };
|
||||
Some(id(self.data().trait_aliases.alloc(alias)))
|
||||
let id = id(self.data().trait_aliases.alloc(alias));
|
||||
self.write_generic_params_attributes(id.into());
|
||||
Some(id)
|
||||
}
|
||||
|
||||
fn lower_impl(&mut self, impl_def: &ast::Impl) -> Option<FileItemTreeId<Impl>> {
|
||||
let ast_id = self.source_ast_id_map.ast_id(impl_def);
|
||||
// Note that trait impls don't get implicit `Self` unlike traits, because here they are a
|
||||
// type alias rather than a type parameter, so this is handled by the resolver.
|
||||
let generic_params = self.lower_generic_params(HasImplicitSelf::No, impl_def);
|
||||
// FIXME: If trait lowering fails, due to a non PathType for example, we treat this impl
|
||||
// as if it was an non-trait impl. Ideally we want to create a unique missing ref that only
|
||||
// equals itself.
|
||||
let target_trait = impl_def.trait_().and_then(|tr| self.lower_trait_ref(&tr));
|
||||
let self_ty = self.lower_type_ref(&impl_def.self_ty()?);
|
||||
let target_trait = impl_def.trait_().and_then(|tr| self.lower_trait_ref(&tr));
|
||||
let is_negative = impl_def.excl_token().is_some();
|
||||
let is_unsafe = impl_def.unsafe_token().is_some();
|
||||
|
||||
|
@ -527,9 +545,14 @@ impl<'a> Ctx<'a> {
|
|||
.flat_map(|it| it.assoc_items())
|
||||
.filter_map(|item| self.lower_assoc_item(&item))
|
||||
.collect();
|
||||
// Note that trait impls don't get implicit `Self` unlike traits, because here they are a
|
||||
// type alias rather than a type parameter, so this is handled by the resolver.
|
||||
let generic_params = self.lower_generic_params(HasImplicitSelf::No, impl_def);
|
||||
let res =
|
||||
Impl { generic_params, target_trait, self_ty, is_negative, is_unsafe, items, ast_id };
|
||||
Some(id(self.data().impls.alloc(res)))
|
||||
let id = id(self.data().impls.alloc(res));
|
||||
self.write_generic_params_attributes(id.into());
|
||||
Some(id)
|
||||
}
|
||||
|
||||
fn lower_use(&mut self, use_item: &ast::Use) -> Option<FileItemTreeId<Use>> {
|
||||
|
@ -616,11 +639,30 @@ impl<'a> Ctx<'a> {
|
|||
id(self.data().extern_blocks.alloc(res))
|
||||
}
|
||||
|
||||
fn write_generic_params_attributes(&mut self, parent: GenericModItem) {
|
||||
self.generic_param_attr_buffer.drain().for_each(|(idx, attrs)| {
|
||||
self.tree.attrs.insert(
|
||||
match idx {
|
||||
Either::Left(id) => AttrOwner::TypeOrConstParamData(parent, id),
|
||||
Either::Right(id) => AttrOwner::LifetimeParamData(parent, id),
|
||||
},
|
||||
attrs,
|
||||
);
|
||||
})
|
||||
}
|
||||
|
||||
fn lower_generic_params(
|
||||
&mut self,
|
||||
has_implicit_self: HasImplicitSelf,
|
||||
node: &dyn ast::HasGenericParams,
|
||||
) -> Interned<GenericParams> {
|
||||
debug_assert!(self.generic_param_attr_buffer.is_empty(),);
|
||||
let add_param_attrs = |item: Either<LocalTypeOrConstParamId, LocalLifetimeParamId>,
|
||||
param| {
|
||||
let attrs = RawAttrs::new(self.db.upcast(), ¶m, self.body_ctx.span_map());
|
||||
debug_assert!(self.generic_param_attr_buffer.insert(item, attrs).is_none());
|
||||
};
|
||||
self.body_ctx.take_impl_traits_bounds();
|
||||
let mut generics = GenericParamsCollector::default();
|
||||
|
||||
if let HasImplicitSelf::Yes(bounds) = has_implicit_self {
|
||||
|
@ -635,28 +677,13 @@ impl<'a> Ctx<'a> {
|
|||
);
|
||||
// add super traits as bounds on Self
|
||||
// i.e., `trait Foo: Bar` is equivalent to `trait Foo where Self: Bar`
|
||||
let self_param = TypeRef::Path(name![Self].into());
|
||||
generics.fill_bounds(&self.body_ctx, bounds, Either::Left(self_param));
|
||||
generics.fill_bounds(
|
||||
&self.body_ctx,
|
||||
bounds,
|
||||
Either::Left(TypeRef::Path(name![Self].into())),
|
||||
);
|
||||
}
|
||||
|
||||
let add_param_attrs = |item: Either<LocalTypeOrConstParamId, LocalLifetimeParamId>,
|
||||
param| {
|
||||
let attrs = RawAttrs::new(self.db.upcast(), ¶m, self.body_ctx.span_map());
|
||||
// This is identical to the body of `Ctx::add_attrs()` but we can't call that here
|
||||
// because it requires `&mut self` and the call to `generics.fill()` below also
|
||||
// references `self`.
|
||||
match self.tree.attrs.entry(match item {
|
||||
Either::Right(id) => id.into(),
|
||||
Either::Left(id) => id.into(),
|
||||
}) {
|
||||
Entry::Occupied(mut entry) => {
|
||||
*entry.get_mut() = entry.get().merge(attrs);
|
||||
}
|
||||
Entry::Vacant(entry) => {
|
||||
entry.insert(attrs);
|
||||
}
|
||||
}
|
||||
};
|
||||
generics.fill(&self.body_ctx, node, add_param_attrs);
|
||||
|
||||
Interned::new(generics.finish())
|
||||
|
|
|
@ -8,8 +8,8 @@ use crate::{
|
|||
generics::{TypeOrConstParamData, WherePredicate, WherePredicateTypeTarget},
|
||||
item_tree::{
|
||||
AttrOwner, Const, DefDatabase, Enum, ExternBlock, ExternCrate, Field, FieldAstId, Fields,
|
||||
FileItemTreeId, FnFlags, Function, GenericParams, Impl, Interned, ItemTree, Macro2,
|
||||
MacroCall, MacroRules, Mod, ModItem, ModKind, Param, ParamAstId, Path, RawAttrs,
|
||||
FileItemTreeId, FnFlags, Function, GenericModItem, GenericParams, Impl, Interned, ItemTree,
|
||||
Macro2, MacroCall, MacroRules, Mod, ModItem, ModKind, Param, ParamAstId, Path, RawAttrs,
|
||||
RawVisibilityId, Static, Struct, Trait, TraitAlias, TypeAlias, TypeBound, TypeRef, Union,
|
||||
Use, UseTree, UseTreeKind, Variant,
|
||||
},
|
||||
|
@ -276,7 +276,7 @@ impl Printer<'_> {
|
|||
w!(self, "extern \"{}\" ", abi);
|
||||
}
|
||||
w!(self, "fn {}", name.display(self.db.upcast()));
|
||||
self.print_generic_params(explicit_generic_params);
|
||||
self.print_generic_params(explicit_generic_params, it.into());
|
||||
w!(self, "(");
|
||||
if !params.is_empty() {
|
||||
self.indented(|this| {
|
||||
|
@ -316,7 +316,7 @@ impl Printer<'_> {
|
|||
self.print_ast_id(ast_id.erase());
|
||||
self.print_visibility(*visibility);
|
||||
w!(self, "struct {}", name.display(self.db.upcast()));
|
||||
self.print_generic_params(generic_params);
|
||||
self.print_generic_params(generic_params, it.into());
|
||||
self.print_fields_and_where_clause(fields, generic_params);
|
||||
if matches!(fields, Fields::Record(_)) {
|
||||
wln!(self);
|
||||
|
@ -329,7 +329,7 @@ impl Printer<'_> {
|
|||
self.print_ast_id(ast_id.erase());
|
||||
self.print_visibility(*visibility);
|
||||
w!(self, "union {}", name.display(self.db.upcast()));
|
||||
self.print_generic_params(generic_params);
|
||||
self.print_generic_params(generic_params, it.into());
|
||||
self.print_fields_and_where_clause(fields, generic_params);
|
||||
if matches!(fields, Fields::Record(_)) {
|
||||
wln!(self);
|
||||
|
@ -342,7 +342,7 @@ impl Printer<'_> {
|
|||
self.print_ast_id(ast_id.erase());
|
||||
self.print_visibility(*visibility);
|
||||
w!(self, "enum {}", name.display(self.db.upcast()));
|
||||
self.print_generic_params(generic_params);
|
||||
self.print_generic_params(generic_params, it.into());
|
||||
self.print_where_clause_and_opening_brace(generic_params);
|
||||
self.indented(|this| {
|
||||
for variant in FileItemTreeId::range_iter(variants.clone()) {
|
||||
|
@ -394,7 +394,7 @@ impl Printer<'_> {
|
|||
w!(self, "auto ");
|
||||
}
|
||||
w!(self, "trait {}", name.display(self.db.upcast()));
|
||||
self.print_generic_params(generic_params);
|
||||
self.print_generic_params(generic_params, it.into());
|
||||
self.print_where_clause_and_opening_brace(generic_params);
|
||||
self.indented(|this| {
|
||||
for item in &**items {
|
||||
|
@ -408,7 +408,7 @@ impl Printer<'_> {
|
|||
self.print_ast_id(ast_id.erase());
|
||||
self.print_visibility(*visibility);
|
||||
w!(self, "trait {}", name.display(self.db.upcast()));
|
||||
self.print_generic_params(generic_params);
|
||||
self.print_generic_params(generic_params, it.into());
|
||||
w!(self, " = ");
|
||||
self.print_where_clause(generic_params);
|
||||
w!(self, ";");
|
||||
|
@ -429,7 +429,7 @@ impl Printer<'_> {
|
|||
w!(self, "unsafe");
|
||||
}
|
||||
w!(self, "impl");
|
||||
self.print_generic_params(generic_params);
|
||||
self.print_generic_params(generic_params, it.into());
|
||||
w!(self, " ");
|
||||
if *is_negative {
|
||||
w!(self, "!");
|
||||
|
@ -453,7 +453,7 @@ impl Printer<'_> {
|
|||
self.print_ast_id(ast_id.erase());
|
||||
self.print_visibility(*visibility);
|
||||
w!(self, "type {}", name.display(self.db.upcast()));
|
||||
self.print_generic_params(generic_params);
|
||||
self.print_generic_params(generic_params, it.into());
|
||||
if !bounds.is_empty() {
|
||||
w!(self, ": ");
|
||||
self.print_type_bounds(bounds);
|
||||
|
@ -525,7 +525,7 @@ impl Printer<'_> {
|
|||
print_path(self.db, path, self).unwrap();
|
||||
}
|
||||
|
||||
fn print_generic_params(&mut self, params: &GenericParams) {
|
||||
fn print_generic_params(&mut self, params: &GenericParams, parent: GenericModItem) {
|
||||
if params.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
@ -537,7 +537,7 @@ impl Printer<'_> {
|
|||
w!(self, ", ");
|
||||
}
|
||||
first = false;
|
||||
self.print_attrs_of(idx, " ");
|
||||
self.print_attrs_of(AttrOwner::LifetimeParamData(parent, idx), " ");
|
||||
w!(self, "{}", lt.name.display(self.db.upcast()));
|
||||
}
|
||||
for (idx, x) in params.type_or_consts.iter() {
|
||||
|
@ -545,7 +545,7 @@ impl Printer<'_> {
|
|||
w!(self, ", ");
|
||||
}
|
||||
first = false;
|
||||
self.print_attrs_of(idx, " ");
|
||||
self.print_attrs_of(AttrOwner::TypeOrConstParamData(parent, idx), " ");
|
||||
match x {
|
||||
TypeOrConstParamData::TypeParamData(ty) => match &ty.name {
|
||||
Some(name) => w!(self, "{}", name.display(self.db.upcast())),
|
||||
|
|
|
@ -427,10 +427,18 @@ fn generics_with_attributes() {
|
|||
check(
|
||||
r#"
|
||||
struct S<#[cfg(never)] T>;
|
||||
struct S<A, B, #[cfg(never)] C>;
|
||||
struct S<A, #[cfg(never)] B, C>;
|
||||
"#,
|
||||
expect![[r#"
|
||||
// AstId: 1
|
||||
pub(self) struct S<#[cfg(never)] T>;
|
||||
|
||||
// AstId: 2
|
||||
pub(self) struct S<A, B, #[cfg(never)] C>;
|
||||
|
||||
// AstId: 3
|
||||
pub(self) struct S<A, #[cfg(never)] B, C>;
|
||||
"#]],
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,26 +1,34 @@
|
|||
//! Context for lowering paths.
|
||||
use std::cell::OnceCell;
|
||||
use std::cell::{OnceCell, RefCell};
|
||||
|
||||
use hir_expand::{
|
||||
span_map::{SpanMap, SpanMapRef},
|
||||
AstId, HirFileId, InFile,
|
||||
};
|
||||
use intern::Interned;
|
||||
use span::{AstIdMap, AstIdNode};
|
||||
use syntax::ast;
|
||||
use triomphe::Arc;
|
||||
|
||||
use crate::{db::DefDatabase, path::Path};
|
||||
use crate::{db::DefDatabase, path::Path, type_ref::TypeBound};
|
||||
|
||||
pub struct LowerCtx<'a> {
|
||||
pub db: &'a dyn DefDatabase,
|
||||
file_id: HirFileId,
|
||||
span_map: OnceCell<SpanMap>,
|
||||
ast_id_map: OnceCell<Arc<AstIdMap>>,
|
||||
impl_trait_bounds: RefCell<Vec<Vec<Interned<TypeBound>>>>,
|
||||
}
|
||||
|
||||
impl<'a> LowerCtx<'a> {
|
||||
pub fn new(db: &'a dyn DefDatabase, file_id: HirFileId) -> Self {
|
||||
LowerCtx { db, file_id, span_map: OnceCell::new(), ast_id_map: OnceCell::new() }
|
||||
LowerCtx {
|
||||
db,
|
||||
file_id,
|
||||
span_map: OnceCell::new(),
|
||||
ast_id_map: OnceCell::new(),
|
||||
impl_trait_bounds: RefCell::new(Vec::new()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_span_map_cell(
|
||||
|
@ -28,7 +36,13 @@ impl<'a> LowerCtx<'a> {
|
|||
file_id: HirFileId,
|
||||
span_map: OnceCell<SpanMap>,
|
||||
) -> Self {
|
||||
LowerCtx { db, file_id, span_map, ast_id_map: OnceCell::new() }
|
||||
LowerCtx {
|
||||
db,
|
||||
file_id,
|
||||
span_map,
|
||||
ast_id_map: OnceCell::new(),
|
||||
impl_trait_bounds: RefCell::new(Vec::new()),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn span_map(&self) -> SpanMapRef<'_> {
|
||||
|
@ -45,4 +59,12 @@ impl<'a> LowerCtx<'a> {
|
|||
self.ast_id_map.get_or_init(|| self.db.ast_id_map(self.file_id)).ast_id(item),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn update_impl_traits_bounds(&self, bounds: Vec<Interned<TypeBound>>) {
|
||||
self.impl_trait_bounds.borrow_mut().push(bounds);
|
||||
}
|
||||
|
||||
pub fn take_impl_traits_bounds(&self) -> Vec<Vec<Interned<TypeBound>>> {
|
||||
self.impl_trait_bounds.take()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -186,3 +186,33 @@ fn#0:1@45..47#0# foo#0:1@48..51#0#(#0:1@51..52#0#�:1@52..53#0#self#0:1@53..57#
|
|||
}#0:1@76..77#0#"#]],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn attribute_macro_doc_desugaring() {
|
||||
check(
|
||||
r#"
|
||||
//- proc_macros: identity
|
||||
#[proc_macros::identity]
|
||||
/// doc string \n with newline
|
||||
/**
|
||||
MultiLines Doc
|
||||
MultiLines Doc
|
||||
*/
|
||||
#[doc = "doc attr"]
|
||||
struct S;
|
||||
"#,
|
||||
expect![[r##"
|
||||
#[proc_macros::identity]
|
||||
/// doc string \n with newline
|
||||
/**
|
||||
MultiLines Doc
|
||||
MultiLines Doc
|
||||
*/
|
||||
#[doc = "doc attr"]
|
||||
struct S;
|
||||
|
||||
#[doc = " doc string \\n with newline"]
|
||||
#[doc = "\n MultiLines Doc\n MultiLines Doc\n"]
|
||||
#[doc = "doc attr"] struct S;"##]],
|
||||
);
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
use std::{cmp::Ordering, iter, mem, ops::Not};
|
||||
|
||||
use base_db::{CrateId, Dependency, FileId};
|
||||
use base_db::{CrateId, CrateOrigin, Dependency, FileId, LangCrateOrigin};
|
||||
use cfg::{CfgExpr, CfgOptions};
|
||||
use either::Either;
|
||||
use hir_expand::{
|
||||
|
@ -15,15 +15,13 @@ use hir_expand::{
|
|||
builtin_fn_macro::find_builtin_macro,
|
||||
name::{name, AsName, Name},
|
||||
proc_macro::CustomProcMacroExpander,
|
||||
ExpandResult, ExpandTo, HirFileId, InFile, MacroCallId, MacroCallKind, MacroCallLoc,
|
||||
MacroDefId, MacroDefKind,
|
||||
ExpandTo, HirFileId, InFile, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind,
|
||||
};
|
||||
use itertools::{izip, Itertools};
|
||||
use la_arena::Idx;
|
||||
use limit::Limit;
|
||||
use rustc_hash::{FxHashMap, FxHashSet};
|
||||
use span::{Edition, ErasedFileAstId, FileAstId, Span, SyntaxContextId};
|
||||
use stdx::always;
|
||||
use syntax::ast;
|
||||
use triomphe::Arc;
|
||||
|
||||
|
@ -279,7 +277,8 @@ impl DefCollector<'_> {
|
|||
fn seed_with_top_level(&mut self) {
|
||||
let _p = tracing::span!(tracing::Level::INFO, "seed_with_top_level").entered();
|
||||
|
||||
let file_id = self.db.crate_graph()[self.def_map.krate].root_file_id;
|
||||
let crate_graph = self.db.crate_graph();
|
||||
let file_id = crate_graph[self.def_map.krate].root_file_id;
|
||||
let item_tree = self.db.file_item_tree(file_id.into());
|
||||
let attrs = item_tree.top_level_attrs(self.db, self.def_map.krate);
|
||||
let crate_data = Arc::get_mut(&mut self.def_map.data).unwrap();
|
||||
|
@ -288,19 +287,14 @@ impl DefCollector<'_> {
|
|||
crate_data.proc_macro_loading_error = Some(e.clone());
|
||||
}
|
||||
|
||||
for (name, dep) in &self.deps {
|
||||
if dep.is_prelude() {
|
||||
crate_data
|
||||
.extern_prelude
|
||||
.insert(name.clone(), (CrateRootModuleId { krate: dep.crate_id }, None));
|
||||
}
|
||||
}
|
||||
let mut process = true;
|
||||
|
||||
// Process other crate-level attributes.
|
||||
for attr in &*attrs {
|
||||
if let Some(cfg) = attr.cfg() {
|
||||
if self.cfg_options.check(&cfg) == Some(false) {
|
||||
return;
|
||||
process = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
let Some(attr_name) = attr.path.as_ident() else { continue };
|
||||
|
@ -350,9 +344,38 @@ impl DefCollector<'_> {
|
|||
}
|
||||
}
|
||||
|
||||
crate_data.shrink_to_fit();
|
||||
for (name, dep) in &self.deps {
|
||||
if dep.is_prelude() {
|
||||
// This is a bit confusing but the gist is that `no_core` and `no_std` remove the
|
||||
// sysroot dependence on `core` and `std` respectively. Our `CrateGraph` is eagerly
|
||||
// constructed with them in place no matter what though, since at that point we
|
||||
// don't do pre-configured attribute resolution yet.
|
||||
// So here check if we are no_core / no_std and we are trying to add the
|
||||
// corresponding dep from the sysroot
|
||||
let skip = match crate_graph[dep.crate_id].origin {
|
||||
CrateOrigin::Lang(LangCrateOrigin::Core) => {
|
||||
crate_data.no_core && dep.is_sysroot()
|
||||
}
|
||||
CrateOrigin::Lang(LangCrateOrigin::Std) => {
|
||||
crate_data.no_std && dep.is_sysroot()
|
||||
}
|
||||
_ => false,
|
||||
};
|
||||
if skip {
|
||||
continue;
|
||||
}
|
||||
crate_data
|
||||
.extern_prelude
|
||||
.insert(name.clone(), (CrateRootModuleId { krate: dep.crate_id }, None));
|
||||
}
|
||||
}
|
||||
|
||||
self.inject_prelude();
|
||||
|
||||
if !process {
|
||||
return;
|
||||
}
|
||||
|
||||
ModCollector {
|
||||
def_collector: self,
|
||||
macro_depth: 0,
|
||||
|
@ -362,6 +385,7 @@ impl DefCollector<'_> {
|
|||
mod_dir: ModDir::root(),
|
||||
}
|
||||
.collect_in_top_module(item_tree.top_level_items());
|
||||
Arc::get_mut(&mut self.def_map.data).unwrap().shrink_to_fit();
|
||||
}
|
||||
|
||||
fn seed_with_inner(&mut self, tree_id: TreeId) {
|
||||
|
@ -519,15 +543,12 @@ impl DefCollector<'_> {
|
|||
|
||||
let krate = if self.def_map.data.no_std {
|
||||
name![core]
|
||||
} else if self.def_map.extern_prelude().any(|(name, _)| *name == name![std]) {
|
||||
name![std]
|
||||
} else {
|
||||
let std = name![std];
|
||||
if self.def_map.extern_prelude().any(|(name, _)| *name == std) {
|
||||
std
|
||||
} else {
|
||||
// If `std` does not exist for some reason, fall back to core. This mostly helps
|
||||
// keep r-a's own tests minimal.
|
||||
name![core]
|
||||
}
|
||||
// If `std` does not exist for some reason, fall back to core. This mostly helps
|
||||
// keep r-a's own tests minimal.
|
||||
name![core]
|
||||
};
|
||||
|
||||
let edition = match self.def_map.data.edition {
|
||||
|
@ -1389,31 +1410,6 @@ impl DefCollector<'_> {
|
|||
}
|
||||
let file_id = macro_call_id.as_file();
|
||||
|
||||
// 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).
|
||||
// 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 {
|
||||
// why is this reported here?
|
||||
hir_expand::ExpandError::UnresolvedProcMacro(krate) => {
|
||||
always!(krate == loc.def.krate);
|
||||
DefDiagnostic::unresolved_proc_macro(module_id, loc.kind.clone(), loc.def.krate)
|
||||
}
|
||||
_ => DefDiagnostic::macro_error(module_id, loc.kind, err.to_string()),
|
||||
};
|
||||
|
||||
self.def_map.diagnostics.push(diag);
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
// Then, fetch and process the item tree. This will reuse the expansion result from above.
|
||||
let item_tree = self.db.file_item_tree(file_id);
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ use base_db::CrateId;
|
|||
use cfg::{CfgExpr, CfgOptions};
|
||||
use hir_expand::{attrs::AttrId, ErasedAstId, MacroCallKind};
|
||||
use la_arena::Idx;
|
||||
use syntax::{ast, SyntaxError};
|
||||
use syntax::ast;
|
||||
|
||||
use crate::{
|
||||
item_tree::{self, ItemTreeId},
|
||||
|
@ -23,8 +23,6 @@ pub enum DefDiagnosticKind {
|
|||
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 },
|
||||
|
@ -98,7 +96,7 @@ impl DefDiagnostic {
|
|||
// FIXME: This is used for a lot of things, unresolved proc macros, disabled proc macros, etc
|
||||
// yet the diagnostic handler in ide-diagnostics has to figure out what happened because this
|
||||
// struct loses all that information!
|
||||
pub(crate) fn unresolved_proc_macro(
|
||||
pub fn unresolved_proc_macro(
|
||||
container: LocalModuleId,
|
||||
ast: MacroCallKind,
|
||||
krate: CrateId,
|
||||
|
@ -106,25 +104,6 @@ impl DefDiagnostic {
|
|||
Self { in_module: container, kind: DefDiagnosticKind::UnresolvedProcMacro { ast, krate } }
|
||||
}
|
||||
|
||||
pub(crate) fn macro_error(
|
||||
container: LocalModuleId,
|
||||
ast: MacroCallKind,
|
||||
message: String,
|
||||
) -> Self {
|
||||
Self { in_module: container, kind: DefDiagnosticKind::MacroError { ast, message } }
|
||||
}
|
||||
|
||||
pub(crate) fn macro_expansion_parse_error(
|
||||
container: LocalModuleId,
|
||||
ast: MacroCallKind,
|
||||
errors: Box<[SyntaxError]>,
|
||||
) -> Self {
|
||||
Self {
|
||||
in_module: container,
|
||||
kind: DefDiagnosticKind::MacroExpansionParseError { ast, errors },
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: Whats the difference between this and unresolved_proc_macro
|
||||
pub(crate) fn unresolved_macro_call(
|
||||
container: LocalModuleId,
|
||||
|
|
|
@ -208,6 +208,13 @@ pub(super) fn lower_generic_args(
|
|||
.and_then(|args| lower_generic_args(lower_ctx, args))
|
||||
.map(Interned::new);
|
||||
let type_ref = assoc_type_arg.ty().map(|it| TypeRef::from_ast(lower_ctx, it));
|
||||
let type_ref = type_ref.inspect(|tr| {
|
||||
tr.walk(&mut |tr| {
|
||||
if let TypeRef::ImplTrait(bounds) = tr {
|
||||
lower_ctx.update_impl_traits_bounds(bounds.clone());
|
||||
}
|
||||
});
|
||||
});
|
||||
let bounds = if let Some(l) = assoc_type_arg.type_bound_list() {
|
||||
l.bounds()
|
||||
.map(|it| Interned::new(TypeBound::from_ast(lower_ctx, it)))
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
//! Name resolution façade.
|
||||
use std::{fmt, hash::BuildHasherDefault, mem};
|
||||
use std::{fmt, hash::BuildHasherDefault, iter, mem};
|
||||
|
||||
use base_db::CrateId;
|
||||
use hir_expand::{
|
||||
|
@ -591,13 +591,13 @@ impl Resolver {
|
|||
|
||||
pub fn where_predicates_in_scope(
|
||||
&self,
|
||||
) -> impl Iterator<Item = &crate::generics::WherePredicate> {
|
||||
) -> impl Iterator<Item = (&crate::generics::WherePredicate, &GenericDefId)> {
|
||||
self.scopes()
|
||||
.filter_map(|scope| match scope {
|
||||
Scope::GenericParams { params, .. } => Some(params),
|
||||
Scope::GenericParams { params, def } => Some((params, def)),
|
||||
_ => None,
|
||||
})
|
||||
.flat_map(|params| params.where_predicates.iter())
|
||||
.flat_map(|(params, def)| params.where_predicates.iter().zip(iter::repeat(def)))
|
||||
}
|
||||
|
||||
pub fn generic_def(&self) -> Option<GenericDefId> {
|
||||
|
|
|
@ -5,7 +5,7 @@ use base_db::CrateId;
|
|||
use cfg::CfgExpr;
|
||||
use either::Either;
|
||||
use intern::Interned;
|
||||
use mbe::{syntax_node_to_token_tree, DelimiterKind, Punct};
|
||||
use mbe::{syntax_node_to_token_tree, DelimiterKind, DocCommentDesugarMode, Punct};
|
||||
use smallvec::{smallvec, SmallVec};
|
||||
use span::{Span, SyntaxContextId};
|
||||
use syntax::unescape;
|
||||
|
@ -239,7 +239,12 @@ impl Attr {
|
|||
span,
|
||||
})))
|
||||
} else if let Some(tt) = ast.token_tree() {
|
||||
let tree = syntax_node_to_token_tree(tt.syntax(), span_map, span);
|
||||
let tree = syntax_node_to_token_tree(
|
||||
tt.syntax(),
|
||||
span_map,
|
||||
span,
|
||||
DocCommentDesugarMode::ProcMacro,
|
||||
);
|
||||
Some(Interned::new(AttrInput::TokenTree(Box::new(tree))))
|
||||
} else {
|
||||
None
|
||||
|
@ -247,8 +252,18 @@ impl Attr {
|
|||
Some(Attr { id, path, input, ctxt: span.ctx })
|
||||
}
|
||||
|
||||
fn from_tt(db: &dyn ExpandDatabase, tt: &[tt::TokenTree], id: AttrId) -> Option<Attr> {
|
||||
let ctxt = tt.first()?.first_span().ctx;
|
||||
fn from_tt(db: &dyn ExpandDatabase, mut tt: &[tt::TokenTree], id: AttrId) -> Option<Attr> {
|
||||
if matches!(tt,
|
||||
[tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident { text, .. })), ..]
|
||||
if text == "unsafe"
|
||||
) {
|
||||
match tt.get(1) {
|
||||
Some(tt::TokenTree::Subtree(subtree)) => tt = &subtree.token_trees,
|
||||
_ => return None,
|
||||
}
|
||||
}
|
||||
let first = &tt.first()?;
|
||||
let ctxt = first.first_span().ctx;
|
||||
let path_end = tt
|
||||
.iter()
|
||||
.position(|tt| {
|
||||
|
@ -430,7 +445,7 @@ fn inner_attributes(
|
|||
|
||||
// Input subtree is: `(cfg, $(attr),+)`
|
||||
// Split it up into a `cfg` subtree and the `attr` subtrees.
|
||||
pub fn parse_cfg_attr_input(
|
||||
fn parse_cfg_attr_input(
|
||||
subtree: &Subtree,
|
||||
) -> Option<(&[tt::TokenTree], impl Iterator<Item = &[tt::TokenTree]>)> {
|
||||
let mut parts = subtree
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
//! Builtin derives.
|
||||
|
||||
use itertools::izip;
|
||||
use mbe::DocCommentDesugarMode;
|
||||
use rustc_hash::FxHashSet;
|
||||
use span::{MacroCallId, Span};
|
||||
use stdx::never;
|
||||
|
@ -262,7 +263,12 @@ fn parse_adt(tt: &tt::Subtree, call_site: Span) -> Result<BasicAdtInfo, ExpandEr
|
|||
match this {
|
||||
Some(it) => {
|
||||
param_type_set.insert(it.as_name());
|
||||
mbe::syntax_node_to_token_tree(it.syntax(), tm, call_site)
|
||||
mbe::syntax_node_to_token_tree(
|
||||
it.syntax(),
|
||||
tm,
|
||||
call_site,
|
||||
DocCommentDesugarMode::ProcMacro,
|
||||
)
|
||||
}
|
||||
None => {
|
||||
tt::Subtree::empty(::tt::DelimSpan { open: call_site, close: call_site })
|
||||
|
@ -270,15 +276,27 @@ fn parse_adt(tt: &tt::Subtree, call_site: Span) -> Result<BasicAdtInfo, ExpandEr
|
|||
}
|
||||
};
|
||||
let bounds = match ¶m {
|
||||
ast::TypeOrConstParam::Type(it) => it
|
||||
.type_bound_list()
|
||||
.map(|it| mbe::syntax_node_to_token_tree(it.syntax(), tm, call_site)),
|
||||
ast::TypeOrConstParam::Type(it) => it.type_bound_list().map(|it| {
|
||||
mbe::syntax_node_to_token_tree(
|
||||
it.syntax(),
|
||||
tm,
|
||||
call_site,
|
||||
DocCommentDesugarMode::ProcMacro,
|
||||
)
|
||||
}),
|
||||
ast::TypeOrConstParam::Const(_) => None,
|
||||
};
|
||||
let ty = if let ast::TypeOrConstParam::Const(param) = param {
|
||||
let ty = param
|
||||
.ty()
|
||||
.map(|ty| mbe::syntax_node_to_token_tree(ty.syntax(), tm, call_site))
|
||||
.map(|ty| {
|
||||
mbe::syntax_node_to_token_tree(
|
||||
ty.syntax(),
|
||||
tm,
|
||||
call_site,
|
||||
DocCommentDesugarMode::ProcMacro,
|
||||
)
|
||||
})
|
||||
.unwrap_or_else(|| {
|
||||
tt::Subtree::empty(::tt::DelimSpan { open: call_site, close: call_site })
|
||||
});
|
||||
|
@ -292,7 +310,14 @@ fn parse_adt(tt: &tt::Subtree, call_site: Span) -> Result<BasicAdtInfo, ExpandEr
|
|||
|
||||
let where_clause = if let Some(w) = where_clause {
|
||||
w.predicates()
|
||||
.map(|it| mbe::syntax_node_to_token_tree(it.syntax(), tm, call_site))
|
||||
.map(|it| {
|
||||
mbe::syntax_node_to_token_tree(
|
||||
it.syntax(),
|
||||
tm,
|
||||
call_site,
|
||||
DocCommentDesugarMode::ProcMacro,
|
||||
)
|
||||
})
|
||||
.collect()
|
||||
} else {
|
||||
vec![]
|
||||
|
@ -322,7 +347,14 @@ fn parse_adt(tt: &tt::Subtree, call_site: Span) -> Result<BasicAdtInfo, ExpandEr
|
|||
let name = p.path()?.qualifier()?.as_single_name_ref()?.as_name();
|
||||
param_type_set.contains(&name).then_some(p)
|
||||
})
|
||||
.map(|it| mbe::syntax_node_to_token_tree(it.syntax(), tm, call_site))
|
||||
.map(|it| {
|
||||
mbe::syntax_node_to_token_tree(
|
||||
it.syntax(),
|
||||
tm,
|
||||
call_site,
|
||||
DocCommentDesugarMode::ProcMacro,
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
let name_token = name_to_token(tm, name)?;
|
||||
Ok(BasicAdtInfo { name: name_token, shape, param_types, where_clause, associated_types })
|
||||
|
|
|
@ -441,21 +441,21 @@ fn unquote_str(lit: &tt::Literal) -> Option<(String, Span)> {
|
|||
let span = lit.span;
|
||||
let lit = ast::make::tokens::literal(&lit.to_string());
|
||||
let token = ast::String::cast(lit)?;
|
||||
token.value().map(|it| (it.into_owned(), span))
|
||||
token.value().ok().map(|it| (it.into_owned(), span))
|
||||
}
|
||||
|
||||
fn unquote_char(lit: &tt::Literal) -> Option<(char, Span)> {
|
||||
let span = lit.span;
|
||||
let lit = ast::make::tokens::literal(&lit.to_string());
|
||||
let token = ast::Char::cast(lit)?;
|
||||
token.value().zip(Some(span))
|
||||
token.value().ok().zip(Some(span))
|
||||
}
|
||||
|
||||
fn unquote_byte_string(lit: &tt::Literal) -> Option<(Vec<u8>, Span)> {
|
||||
let span = lit.span;
|
||||
let lit = ast::make::tokens::literal(&lit.to_string());
|
||||
let token = ast::ByteString::cast(lit)?;
|
||||
token.value().map(|it| (it.into_owned(), span))
|
||||
token.value().ok().map(|it| (it.into_owned(), span))
|
||||
}
|
||||
|
||||
fn compile_error_expand(
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
use base_db::{salsa, CrateId, FileId, SourceDatabase};
|
||||
use either::Either;
|
||||
use limit::Limit;
|
||||
use mbe::{syntax_node_to_token_tree, MatchedArmIndex};
|
||||
use mbe::{syntax_node_to_token_tree, DocCommentDesugarMode, MatchedArmIndex};
|
||||
use rustc_hash::FxHashSet;
|
||||
use span::{AstIdMap, Span, SyntaxContextData, SyntaxContextId};
|
||||
use syntax::{ast, AstNode, Parse, SyntaxElement, SyntaxError, SyntaxNode, SyntaxToken, T};
|
||||
|
@ -132,7 +132,7 @@ pub trait ExpandDatabase: SourceDatabase {
|
|||
fn parse_macro_expansion_error(
|
||||
&self,
|
||||
macro_call: MacroCallId,
|
||||
) -> ExpandResult<Box<[SyntaxError]>>;
|
||||
) -> Option<Arc<ExpandResult<Arc<[SyntaxError]>>>>;
|
||||
}
|
||||
|
||||
/// This expands the given macro call, but with different arguments. This is
|
||||
|
@ -156,11 +156,25 @@ pub fn expand_speculative(
|
|||
// Build the subtree and token mapping for the speculative args
|
||||
let (mut tt, undo_info) = match loc.kind {
|
||||
MacroCallKind::FnLike { .. } => (
|
||||
mbe::syntax_node_to_token_tree(speculative_args, span_map, span),
|
||||
mbe::syntax_node_to_token_tree(
|
||||
speculative_args,
|
||||
span_map,
|
||||
span,
|
||||
if loc.def.is_proc_macro() {
|
||||
DocCommentDesugarMode::ProcMacro
|
||||
} else {
|
||||
DocCommentDesugarMode::Mbe
|
||||
},
|
||||
),
|
||||
SyntaxFixupUndoInfo::NONE,
|
||||
),
|
||||
MacroCallKind::Attr { .. } if loc.def.is_attribute_derive() => (
|
||||
mbe::syntax_node_to_token_tree(speculative_args, span_map, span),
|
||||
mbe::syntax_node_to_token_tree(
|
||||
speculative_args,
|
||||
span_map,
|
||||
span,
|
||||
DocCommentDesugarMode::ProcMacro,
|
||||
),
|
||||
SyntaxFixupUndoInfo::NONE,
|
||||
),
|
||||
MacroCallKind::Derive { derive_attr_index: index, .. }
|
||||
|
@ -176,7 +190,12 @@ pub fn expand_speculative(
|
|||
|
||||
let censor_cfg =
|
||||
cfg_process::process_cfg_attrs(db, speculative_args, &loc).unwrap_or_default();
|
||||
let mut fixups = fixup::fixup_syntax(span_map, speculative_args, span);
|
||||
let mut fixups = fixup::fixup_syntax(
|
||||
span_map,
|
||||
speculative_args,
|
||||
span,
|
||||
DocCommentDesugarMode::ProcMacro,
|
||||
);
|
||||
fixups.append.retain(|it, _| match it {
|
||||
syntax::NodeOrToken::Token(_) => true,
|
||||
it => !censor.contains(it) && !censor_cfg.contains(it),
|
||||
|
@ -191,6 +210,7 @@ pub fn expand_speculative(
|
|||
fixups.append,
|
||||
fixups.remove,
|
||||
span,
|
||||
DocCommentDesugarMode::ProcMacro,
|
||||
),
|
||||
fixups.undo_info,
|
||||
)
|
||||
|
@ -212,7 +232,12 @@ pub fn expand_speculative(
|
|||
}?;
|
||||
match attr.token_tree() {
|
||||
Some(token_tree) => {
|
||||
let mut tree = syntax_node_to_token_tree(token_tree.syntax(), span_map, span);
|
||||
let mut tree = syntax_node_to_token_tree(
|
||||
token_tree.syntax(),
|
||||
span_map,
|
||||
span,
|
||||
DocCommentDesugarMode::ProcMacro,
|
||||
);
|
||||
tree.delimiter = tt::Delimiter::invisible_spanned(span);
|
||||
|
||||
Some(tree)
|
||||
|
@ -332,9 +357,14 @@ fn parse_macro_expansion(
|
|||
fn parse_macro_expansion_error(
|
||||
db: &dyn ExpandDatabase,
|
||||
macro_call_id: MacroCallId,
|
||||
) -> ExpandResult<Box<[SyntaxError]>> {
|
||||
db.parse_macro_expansion(MacroFileId { macro_call_id })
|
||||
.map(|it| it.0.errors().into_boxed_slice())
|
||||
) -> Option<Arc<ExpandResult<Arc<[SyntaxError]>>>> {
|
||||
let e: ExpandResult<Arc<[SyntaxError]>> =
|
||||
db.parse_macro_expansion(MacroFileId { macro_call_id }).map(|it| Arc::from(it.0.errors()));
|
||||
if e.value.is_empty() && e.err.is_none() {
|
||||
None
|
||||
} else {
|
||||
Some(Arc::new(e))
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn parse_with_map(
|
||||
|
@ -432,7 +462,16 @@ fn macro_arg(db: &dyn ExpandDatabase, id: MacroCallId) -> MacroArgResult {
|
|||
return dummy_tt(kind);
|
||||
}
|
||||
|
||||
let mut tt = mbe::syntax_node_to_token_tree(tt.syntax(), map.as_ref(), span);
|
||||
let mut tt = mbe::syntax_node_to_token_tree(
|
||||
tt.syntax(),
|
||||
map.as_ref(),
|
||||
span,
|
||||
if loc.def.is_proc_macro() {
|
||||
DocCommentDesugarMode::ProcMacro
|
||||
} else {
|
||||
DocCommentDesugarMode::Mbe
|
||||
},
|
||||
);
|
||||
if loc.def.is_proc_macro() {
|
||||
// proc macros expect their inputs without parentheses, MBEs expect it with them included
|
||||
tt.delimiter.kind = tt::DelimiterKind::Invisible;
|
||||
|
@ -469,7 +508,8 @@ fn macro_arg(db: &dyn ExpandDatabase, id: MacroCallId) -> MacroArgResult {
|
|||
let (mut tt, undo_info) = {
|
||||
let syntax = item_node.syntax();
|
||||
let censor_cfg = cfg_process::process_cfg_attrs(db, syntax, &loc).unwrap_or_default();
|
||||
let mut fixups = fixup::fixup_syntax(map.as_ref(), syntax, span);
|
||||
let mut fixups =
|
||||
fixup::fixup_syntax(map.as_ref(), syntax, span, DocCommentDesugarMode::ProcMacro);
|
||||
fixups.append.retain(|it, _| match it {
|
||||
syntax::NodeOrToken::Token(_) => true,
|
||||
it => !censor.contains(it) && !censor_cfg.contains(it),
|
||||
|
@ -484,6 +524,7 @@ fn macro_arg(db: &dyn ExpandDatabase, id: MacroCallId) -> MacroArgResult {
|
|||
fixups.append,
|
||||
fixups.remove,
|
||||
span,
|
||||
DocCommentDesugarMode::ProcMacro,
|
||||
),
|
||||
fixups.undo_info,
|
||||
)
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
use std::sync::OnceLock;
|
||||
|
||||
use base_db::{CrateId, VersionReq};
|
||||
use mbe::DocCommentDesugarMode;
|
||||
use span::{Edition, MacroCallId, Span, SyntaxContextId};
|
||||
use stdx::TupleExt;
|
||||
use syntax::{ast, AstNode};
|
||||
|
@ -158,6 +159,7 @@ impl DeclarativeMacroExpander {
|
|||
map.span_for_range(
|
||||
macro_rules.macro_rules_token().unwrap().text_range(),
|
||||
),
|
||||
DocCommentDesugarMode::Mbe,
|
||||
);
|
||||
|
||||
mbe::DeclarativeMacro::parse_macro_rules(&tt, edition, new_meta_vars)
|
||||
|
@ -175,6 +177,7 @@ impl DeclarativeMacroExpander {
|
|||
arg.syntax(),
|
||||
map.as_ref(),
|
||||
map.span_for_range(macro_def.macro_token().unwrap().text_range()),
|
||||
DocCommentDesugarMode::Mbe,
|
||||
);
|
||||
|
||||
mbe::DeclarativeMacro::parse_macro2(&tt, edition, new_meta_vars)
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
//!
|
||||
//! See the full discussion : <https://rust-lang.zulipchat.com/#narrow/stream/131828-t-compiler/topic/Eager.20expansion.20of.20built-in.20macros>
|
||||
use base_db::CrateId;
|
||||
use mbe::DocCommentDesugarMode;
|
||||
use span::SyntaxContextId;
|
||||
use syntax::{ted, Parse, SyntaxElement, SyntaxNode, TextSize, WalkEvent};
|
||||
use triomphe::Arc;
|
||||
|
@ -80,7 +81,12 @@ pub fn expand_eager_macro_input(
|
|||
return ExpandResult { value: None, err };
|
||||
};
|
||||
|
||||
let mut subtree = mbe::syntax_node_to_token_tree(&expanded_eager_input, arg_map, span);
|
||||
let mut subtree = mbe::syntax_node_to_token_tree(
|
||||
&expanded_eager_input,
|
||||
arg_map,
|
||||
span,
|
||||
DocCommentDesugarMode::Mbe,
|
||||
);
|
||||
|
||||
subtree.delimiter.kind = crate::tt::DelimiterKind::Invisible;
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
//! To make attribute macros work reliably when typing, we need to take care to
|
||||
//! fix up syntax errors in the code we're passing to them.
|
||||
|
||||
use mbe::DocCommentDesugarMode;
|
||||
use rustc_hash::{FxHashMap, FxHashSet};
|
||||
use smallvec::SmallVec;
|
||||
use span::{ErasedFileAstId, Span, SpanAnchor, FIXUP_ERASED_FILE_AST_ID_MARKER};
|
||||
|
@ -49,6 +50,7 @@ pub(crate) fn fixup_syntax(
|
|||
span_map: SpanMapRef<'_>,
|
||||
node: &SyntaxNode,
|
||||
call_site: Span,
|
||||
mode: DocCommentDesugarMode,
|
||||
) -> SyntaxFixups {
|
||||
let mut append = FxHashMap::<SyntaxElement, _>::default();
|
||||
let mut remove = FxHashSet::<SyntaxElement>::default();
|
||||
|
@ -70,7 +72,7 @@ pub(crate) fn fixup_syntax(
|
|||
if can_handle_error(&node) && has_error_to_handle(&node) {
|
||||
remove.insert(node.clone().into());
|
||||
// the node contains an error node, we have to completely replace it by something valid
|
||||
let original_tree = mbe::syntax_node_to_token_tree(&node, span_map, call_site);
|
||||
let original_tree = mbe::syntax_node_to_token_tree(&node, span_map, call_site, mode);
|
||||
let idx = original.len() as u32;
|
||||
original.push(original_tree);
|
||||
let span = span_map.span_for_range(node_range);
|
||||
|
@ -360,6 +362,7 @@ fn reverse_fixups_(tt: &mut Subtree, undo_info: &[Subtree]) {
|
|||
mod tests {
|
||||
use base_db::FileId;
|
||||
use expect_test::{expect, Expect};
|
||||
use mbe::DocCommentDesugarMode;
|
||||
use syntax::TextRange;
|
||||
use triomphe::Arc;
|
||||
|
||||
|
@ -402,6 +405,7 @@ mod tests {
|
|||
span_map.as_ref(),
|
||||
&parsed.syntax_node(),
|
||||
span_map.span_for_range(TextRange::empty(0.into())),
|
||||
DocCommentDesugarMode::Mbe,
|
||||
);
|
||||
let mut tt = mbe::syntax_node_to_token_tree_modified(
|
||||
&parsed.syntax_node(),
|
||||
|
@ -409,6 +413,7 @@ mod tests {
|
|||
fixups.append,
|
||||
fixups.remove,
|
||||
span_map.span_for_range(TextRange::empty(0.into())),
|
||||
DocCommentDesugarMode::Mbe,
|
||||
);
|
||||
|
||||
let actual = format!("{tt}\n");
|
||||
|
@ -436,6 +441,7 @@ mod tests {
|
|||
&parsed.syntax_node(),
|
||||
span_map.as_ref(),
|
||||
span_map.span_for_range(TextRange::empty(0.into())),
|
||||
DocCommentDesugarMode::Mbe,
|
||||
);
|
||||
assert!(
|
||||
check_subtree_eq(&tt, &original_as_tt),
|
||||
|
|
|
@ -132,13 +132,13 @@ pub enum ExpandError {
|
|||
MacroDefinition,
|
||||
Mbe(mbe::ExpandError),
|
||||
RecursionOverflow,
|
||||
Other(Box<Box<str>>),
|
||||
ProcMacroPanic(Box<Box<str>>),
|
||||
Other(Arc<Box<str>>),
|
||||
ProcMacroPanic(Arc<Box<str>>),
|
||||
}
|
||||
|
||||
impl ExpandError {
|
||||
pub fn other(msg: impl Into<Box<str>>) -> Self {
|
||||
ExpandError::Other(Box::new(msg.into()))
|
||||
ExpandError::Other(Arc::new(msg.into()))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ use rustc_hash::FxHashMap;
|
|||
use span::Span;
|
||||
use stdx::never;
|
||||
use syntax::SmolStr;
|
||||
use triomphe::Arc;
|
||||
|
||||
use crate::{db::ExpandDatabase, tt, ExpandError, ExpandResult};
|
||||
|
||||
|
@ -157,7 +158,7 @@ impl CustomProcMacroExpander {
|
|||
ProcMacroExpansionError::System(text)
|
||||
| ProcMacroExpansionError::Panic(text) => ExpandResult::new(
|
||||
tt::Subtree::empty(tt::DelimSpan { open: call_site, close: call_site }),
|
||||
ExpandError::ProcMacroPanic(Box::new(text.into_boxed_str())),
|
||||
ExpandError::ProcMacroPanic(Arc::new(text.into_boxed_str())),
|
||||
),
|
||||
},
|
||||
}
|
||||
|
|
|
@ -806,7 +806,7 @@ pub(crate) fn impl_datum_query(
|
|||
krate: CrateId,
|
||||
impl_id: ImplId,
|
||||
) -> Arc<ImplDatum> {
|
||||
let _p = tracing::span!(tracing::Level::INFO, "impl_datum").entered();
|
||||
let _p = tracing::span!(tracing::Level::INFO, "impl_datum_query").entered();
|
||||
debug!("impl_datum {:?}", impl_id);
|
||||
let impl_: hir_def::ImplId = from_chalk(db, impl_id);
|
||||
impl_def_datum(db, krate, impl_id, impl_)
|
||||
|
|
|
@ -27,6 +27,7 @@ pub trait TyExt {
|
|||
fn is_scalar(&self) -> bool;
|
||||
fn is_floating_point(&self) -> bool;
|
||||
fn is_never(&self) -> bool;
|
||||
fn is_str(&self) -> bool;
|
||||
fn is_unknown(&self) -> bool;
|
||||
fn contains_unknown(&self) -> bool;
|
||||
fn is_ty_var(&self) -> bool;
|
||||
|
@ -87,6 +88,10 @@ impl TyExt for Ty {
|
|||
matches!(self.kind(Interner), TyKind::Never)
|
||||
}
|
||||
|
||||
fn is_str(&self) -> bool {
|
||||
matches!(self.kind(Interner), TyKind::Str)
|
||||
}
|
||||
|
||||
fn is_unknown(&self) -> bool {
|
||||
matches!(self.kind(Interner), TyKind::Error)
|
||||
}
|
||||
|
|
|
@ -797,8 +797,20 @@ impl HirDisplay for Ty {
|
|||
c.hir_fmt(f)?;
|
||||
write!(f, "]")?;
|
||||
}
|
||||
TyKind::Raw(m, t) | TyKind::Ref(m, _, t) => {
|
||||
if matches!(self.kind(Interner), TyKind::Raw(..)) {
|
||||
kind @ (TyKind::Raw(m, t) | TyKind::Ref(m, _, t)) => {
|
||||
if let TyKind::Ref(_, l, _) = kind {
|
||||
f.write_char('&')?;
|
||||
if cfg!(test) {
|
||||
// rendering these unconditionally is probably too much (at least for inlay
|
||||
// hints) so we gate it to testing only for the time being
|
||||
l.hir_fmt(f)?;
|
||||
f.write_char(' ')?;
|
||||
}
|
||||
match m {
|
||||
Mutability::Not => (),
|
||||
Mutability::Mut => f.write_str("mut ")?,
|
||||
}
|
||||
} else {
|
||||
write!(
|
||||
f,
|
||||
"*{}",
|
||||
|
@ -807,15 +819,6 @@ impl HirDisplay for Ty {
|
|||
Mutability::Mut => "mut ",
|
||||
}
|
||||
)?;
|
||||
} else {
|
||||
write!(
|
||||
f,
|
||||
"&{}",
|
||||
match m {
|
||||
Mutability::Not => "",
|
||||
Mutability::Mut => "mut ",
|
||||
}
|
||||
)?;
|
||||
}
|
||||
|
||||
// FIXME: all this just to decide whether to use parentheses...
|
||||
|
@ -1330,7 +1333,18 @@ fn hir_fmt_generics(
|
|||
}
|
||||
|
||||
let parameters_to_write = generic_args_sans_defaults(f, generic_def, parameters);
|
||||
if !parameters_to_write.is_empty() {
|
||||
|
||||
// FIXME: Remote this
|
||||
// most of our lifetimes will be errors as we lack elision and inference
|
||||
// so don't render them for now
|
||||
let only_err_lifetimes = !cfg!(test)
|
||||
&& parameters_to_write.iter().all(|arg| {
|
||||
matches!(
|
||||
arg.data(Interner),
|
||||
chalk_ir::GenericArgData::Lifetime(it) if *it.data(Interner) == LifetimeData::Error
|
||||
)
|
||||
});
|
||||
if !parameters_to_write.is_empty() && !only_err_lifetimes {
|
||||
write!(f, "<")?;
|
||||
hir_fmt_generic_arguments(f, parameters_to_write)?;
|
||||
write!(f, ">")?;
|
||||
|
@ -1403,6 +1417,18 @@ fn hir_fmt_generic_arguments(
|
|||
None => (parameters, &[][..]),
|
||||
};
|
||||
for generic_arg in lifetimes.iter().chain(ty_or_const) {
|
||||
// FIXME: Remove this
|
||||
// most of our lifetimes will be errors as we lack elision and inference
|
||||
// so don't render them for now
|
||||
if !cfg!(test)
|
||||
&& matches!(
|
||||
generic_arg.lifetime(Interner),
|
||||
Some(l) if ***l.interned() == LifetimeData::Error
|
||||
)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if !first {
|
||||
write!(f, ", ")?;
|
||||
}
|
||||
|
@ -1728,9 +1754,9 @@ impl HirDisplay for LifetimeData {
|
|||
LifetimeData::BoundVar(idx) => idx.hir_fmt(f),
|
||||
LifetimeData::InferenceVar(_) => write!(f, "_"),
|
||||
LifetimeData::Static => write!(f, "'static"),
|
||||
LifetimeData::Error => write!(f, "'{{error}}"),
|
||||
LifetimeData::Erased => Ok(()),
|
||||
LifetimeData::Phantom(_, _) => Ok(()),
|
||||
LifetimeData::Error => write!(f, "'?"),
|
||||
LifetimeData::Erased => write!(f, "'<erased>"),
|
||||
LifetimeData::Phantom(void, _) => match *void {},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -198,6 +198,7 @@ pub enum InferenceDiagnostic {
|
|||
NoSuchField {
|
||||
field: ExprOrPatId,
|
||||
private: bool,
|
||||
variant: VariantId,
|
||||
},
|
||||
PrivateField {
|
||||
expr: ExprId,
|
||||
|
|
|
@ -563,6 +563,7 @@ impl InferenceContext<'_> {
|
|||
InferenceDiagnostic::NoSuchField {
|
||||
field: field.expr.into(),
|
||||
private: true,
|
||||
variant: def,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
@ -572,6 +573,7 @@ impl InferenceContext<'_> {
|
|||
self.push_diagnostic(InferenceDiagnostic::NoSuchField {
|
||||
field: field.expr.into(),
|
||||
private: false,
|
||||
variant: def,
|
||||
});
|
||||
None
|
||||
}
|
||||
|
|
|
@ -177,6 +177,7 @@ impl InferenceContext<'_> {
|
|||
self.push_diagnostic(InferenceDiagnostic::NoSuchField {
|
||||
field: inner.into(),
|
||||
private: true,
|
||||
variant: def,
|
||||
});
|
||||
}
|
||||
let f = field_types[local_id].clone();
|
||||
|
@ -190,6 +191,7 @@ impl InferenceContext<'_> {
|
|||
self.push_diagnostic(InferenceDiagnostic::NoSuchField {
|
||||
field: inner.into(),
|
||||
private: false,
|
||||
variant: def,
|
||||
});
|
||||
self.err_ty()
|
||||
}
|
||||
|
|
|
@ -345,51 +345,47 @@ impl<'a> TyLoweringContext<'a> {
|
|||
}
|
||||
ImplTraitLoweringState::Param(counter) => {
|
||||
let idx = counter.get();
|
||||
// FIXME we're probably doing something wrong here
|
||||
// Count the number of `impl Trait` things that appear within our bounds.
|
||||
// Since t hose have been emitted as implicit type args already.
|
||||
counter.set(idx + count_impl_traits(type_ref) as u16);
|
||||
if let Some(generics) = self.generics() {
|
||||
let param = generics
|
||||
.iter()
|
||||
.filter(|(_, data)| {
|
||||
matches!(
|
||||
data,
|
||||
GenericParamDataRef::TypeParamData(data)
|
||||
if data.provenance == TypeParamProvenance::ArgumentImplTrait
|
||||
)
|
||||
})
|
||||
.nth(idx as usize)
|
||||
.map_or(TyKind::Error, |(id, _)| {
|
||||
if let GenericParamId::TypeParamId(id) = id {
|
||||
TyKind::Placeholder(to_placeholder_idx(self.db, id.into()))
|
||||
} else {
|
||||
// we just filtered them out
|
||||
unreachable!("Unexpected lifetime or const argument");
|
||||
}
|
||||
});
|
||||
param.intern(Interner)
|
||||
} else {
|
||||
TyKind::Error.intern(Interner)
|
||||
}
|
||||
let kind = self
|
||||
.generics()
|
||||
.expect("param impl trait lowering must be in a generic def")
|
||||
.iter()
|
||||
.filter_map(|(id, data)| match (id, data) {
|
||||
(
|
||||
GenericParamId::TypeParamId(id),
|
||||
GenericParamDataRef::TypeParamData(data),
|
||||
) if data.provenance == TypeParamProvenance::ArgumentImplTrait => {
|
||||
Some(id)
|
||||
}
|
||||
_ => None,
|
||||
})
|
||||
.nth(idx as usize)
|
||||
.map_or(TyKind::Error, |id| {
|
||||
TyKind::Placeholder(to_placeholder_idx(self.db, id.into()))
|
||||
});
|
||||
kind.intern(Interner)
|
||||
}
|
||||
ImplTraitLoweringState::Variable(counter) => {
|
||||
let idx = counter.get();
|
||||
// FIXME we're probably doing something wrong here
|
||||
// Count the number of `impl Trait` things that appear within our bounds.
|
||||
// Since t hose have been emitted as implicit type args already.
|
||||
counter.set(idx + count_impl_traits(type_ref) as u16);
|
||||
let (
|
||||
_parent_params,
|
||||
self_params,
|
||||
list_params,
|
||||
type_params,
|
||||
const_params,
|
||||
_impl_trait_params,
|
||||
_lifetime_params,
|
||||
) = if let Some(generics) = self.generics() {
|
||||
generics.provenance_split()
|
||||
} else {
|
||||
(0, 0, 0, 0, 0, 0)
|
||||
};
|
||||
) = self
|
||||
.generics()
|
||||
.expect("variable impl trait lowering must be in a generic def")
|
||||
.provenance_split();
|
||||
TyKind::BoundVar(BoundVar::new(
|
||||
self.in_binders,
|
||||
idx as usize + self_params + list_params + const_params,
|
||||
idx as usize + self_params + type_params + const_params,
|
||||
))
|
||||
.intern(Interner)
|
||||
}
|
||||
|
@ -1010,6 +1006,7 @@ impl<'a> TyLoweringContext<'a> {
|
|||
pub(crate) fn lower_where_predicate<'b>(
|
||||
&'b self,
|
||||
where_predicate: &'b WherePredicate,
|
||||
&def: &GenericDefId,
|
||||
ignore_bindings: bool,
|
||||
) -> impl Iterator<Item = QuantifiedWhereClause> + 'b {
|
||||
match where_predicate {
|
||||
|
@ -1018,7 +1015,6 @@ impl<'a> TyLoweringContext<'a> {
|
|||
let self_ty = match target {
|
||||
WherePredicateTypeTarget::TypeRef(type_ref) => self.lower_ty(type_ref),
|
||||
&WherePredicateTypeTarget::TypeOrConstParam(local_id) => {
|
||||
let def = self.resolver.generic_def().expect("generics in scope");
|
||||
let param_id = hir_def::TypeOrConstParamId { parent: def, local_id };
|
||||
match self.type_param_mode {
|
||||
ParamLoweringMode::Placeholder => {
|
||||
|
@ -1056,23 +1052,7 @@ impl<'a> TyLoweringContext<'a> {
|
|||
let clause = match bound.as_ref() {
|
||||
TypeBound::Path(path, TraitBoundModifier::None) => {
|
||||
trait_ref = self.lower_trait_ref_from_path(path, Some(self_ty));
|
||||
trait_ref
|
||||
.clone()
|
||||
.filter(|tr| {
|
||||
// ignore `T: Drop` or `T: Destruct` bounds.
|
||||
// - `T: ~const Drop` has a special meaning in Rust 1.61 that we don't implement.
|
||||
// (So ideally, we'd only ignore `~const Drop` here)
|
||||
// - `Destruct` impls are built-in in 1.62 (current nightly as of 08-04-2022), so until
|
||||
// the builtin impls are supported by Chalk, we ignore them here.
|
||||
if let Some(lang) = self.db.lang_attr(tr.hir_trait_id().into()) {
|
||||
if matches!(lang, LangItem::Drop | LangItem::Destruct) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
true
|
||||
})
|
||||
.map(WhereClause::Implemented)
|
||||
.map(crate::wrap_empty_binders)
|
||||
trait_ref.clone().map(WhereClause::Implemented).map(crate::wrap_empty_binders)
|
||||
}
|
||||
TypeBound::Path(path, TraitBoundModifier::Maybe) => {
|
||||
let sized_trait = self
|
||||
|
@ -1166,84 +1146,77 @@ impl<'a> TyLoweringContext<'a> {
|
|||
binding.type_ref.as_ref().map_or(0, |_| 1) + binding.bounds.len(),
|
||||
);
|
||||
if let Some(type_ref) = &binding.type_ref {
|
||||
if let (
|
||||
TypeRef::ImplTrait(bounds),
|
||||
ImplTraitLoweringState::Param(_)
|
||||
| ImplTraitLoweringState::Variable(_)
|
||||
| ImplTraitLoweringState::Disallowed,
|
||||
) = (type_ref, &self.impl_trait_mode)
|
||||
{
|
||||
for bound in bounds {
|
||||
predicates.extend(
|
||||
self.lower_type_bound(
|
||||
bound,
|
||||
TyKind::Alias(AliasTy::Projection(projection_ty.clone()))
|
||||
.intern(Interner),
|
||||
false,
|
||||
),
|
||||
);
|
||||
match (type_ref, &self.impl_trait_mode) {
|
||||
(TypeRef::ImplTrait(_), ImplTraitLoweringState::Disallowed) => (),
|
||||
(
|
||||
_,
|
||||
ImplTraitLoweringState::Disallowed | ImplTraitLoweringState::Opaque(_),
|
||||
) => {
|
||||
let ty = 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)));
|
||||
}
|
||||
} else {
|
||||
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;
|
||||
let generics = self.generics().expect("generics in scope");
|
||||
for (idx, data) in 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;
|
||||
}
|
||||
(
|
||||
_,
|
||||
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,
|
||||
});
|
||||
let ty = if let Some(target_param_idx) = target_param_idx {
|
||||
let mut counter = 0;
|
||||
let generics = self.generics().expect("generics in scope");
|
||||
for (idx, data) in 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;
|
||||
}
|
||||
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!(),
|
||||
if idx == *target_param_idx {
|
||||
break;
|
||||
}
|
||||
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)));
|
||||
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!(),
|
||||
}
|
||||
ext.lower_ty(type_ref)
|
||||
} else {
|
||||
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)));
|
||||
}
|
||||
}
|
||||
}
|
||||
for bound in binding.bounds.iter() {
|
||||
|
@ -1338,11 +1311,10 @@ impl<'a> TyLoweringContext<'a> {
|
|||
bounds,
|
||||
lifetime: match lifetime {
|
||||
Some(it) => match it.bound_var(Interner) {
|
||||
Some(bound_var) => LifetimeData::BoundVar(BoundVar::new(
|
||||
DebruijnIndex::INNERMOST,
|
||||
bound_var.index,
|
||||
))
|
||||
.intern(Interner),
|
||||
Some(bound_var) => bound_var
|
||||
.shifted_out_to(DebruijnIndex::new(2))
|
||||
.map(|bound_var| LifetimeData::BoundVar(bound_var).intern(Interner))
|
||||
.unwrap_or(it),
|
||||
None => it,
|
||||
},
|
||||
None => static_lifetime(),
|
||||
|
@ -1410,16 +1382,6 @@ impl<'a> TyLoweringContext<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn count_impl_traits(type_ref: &TypeRef) -> usize {
|
||||
let mut count = 0;
|
||||
type_ref.walk(&mut |type_ref| {
|
||||
if matches!(type_ref, TypeRef::ImplTrait(_)) {
|
||||
count += 1;
|
||||
}
|
||||
});
|
||||
count
|
||||
}
|
||||
|
||||
/// Build the signature of a callable item (function, struct or enum variant).
|
||||
pub(crate) fn callable_item_sig(db: &dyn HirDatabase, def: CallableDefId) -> PolyFnSig {
|
||||
match def {
|
||||
|
@ -1438,6 +1400,17 @@ pub fn associated_type_shorthand_candidates<R>(
|
|||
named_associated_type_shorthand_candidates(db, def, res, None, |name, _, id| cb(name, id))
|
||||
}
|
||||
|
||||
// FIXME: This does not handle macros!
|
||||
fn count_impl_traits(type_ref: &TypeRef) -> usize {
|
||||
let mut count = 0;
|
||||
type_ref.walk(&mut |type_ref| {
|
||||
if matches!(type_ref, TypeRef::ImplTrait(_)) {
|
||||
count += 1;
|
||||
}
|
||||
});
|
||||
count
|
||||
}
|
||||
|
||||
fn named_associated_type_shorthand_candidates<R>(
|
||||
db: &dyn HirDatabase,
|
||||
// If the type parameter is defined in an impl and we're in a method, there
|
||||
|
@ -1575,7 +1548,7 @@ pub(crate) fn generic_predicates_for_param_query(
|
|||
let generics = generics(db.upcast(), def);
|
||||
|
||||
// we have to filter out all other predicates *first*, before attempting to lower them
|
||||
let predicate = |pred: &&_| match pred {
|
||||
let predicate = |(pred, &def): &(&_, _)| match pred {
|
||||
WherePredicate::ForLifetime { target, bound, .. }
|
||||
| WherePredicate::TypeBound { target, bound, .. } => {
|
||||
let invalid_target = match target {
|
||||
|
@ -1617,8 +1590,8 @@ pub(crate) fn generic_predicates_for_param_query(
|
|||
let mut predicates: Vec<_> = resolver
|
||||
.where_predicates_in_scope()
|
||||
.filter(predicate)
|
||||
.flat_map(|pred| {
|
||||
ctx.lower_where_predicate(pred, true).map(|p| make_binders(db, &generics, p))
|
||||
.flat_map(|(pred, def)| {
|
||||
ctx.lower_where_predicate(pred, def, true).map(|p| make_binders(db, &generics, p))
|
||||
})
|
||||
.collect();
|
||||
|
||||
|
@ -1671,8 +1644,8 @@ pub(crate) fn trait_environment_query(
|
|||
};
|
||||
let mut traits_in_scope = Vec::new();
|
||||
let mut clauses = Vec::new();
|
||||
for pred in resolver.where_predicates_in_scope() {
|
||||
for pred in ctx.lower_where_predicate(pred, false) {
|
||||
for (pred, def) in resolver.where_predicates_in_scope() {
|
||||
for pred in ctx.lower_where_predicate(pred, def, false) {
|
||||
if let WhereClause::Implemented(tr) = &pred.skip_binders() {
|
||||
traits_in_scope.push((tr.self_type_parameter(Interner).clone(), tr.hir_trait_id()));
|
||||
}
|
||||
|
@ -1726,8 +1699,8 @@ pub(crate) fn generic_predicates_query(
|
|||
|
||||
let mut predicates = resolver
|
||||
.where_predicates_in_scope()
|
||||
.flat_map(|pred| {
|
||||
ctx.lower_where_predicate(pred, false).map(|p| make_binders(db, &generics, p))
|
||||
.flat_map(|(pred, def)| {
|
||||
ctx.lower_where_predicate(pred, def, false).map(|p| make_binders(db, &generics, p))
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
|
|
|
@ -368,7 +368,7 @@ pub(crate) fn incoherent_inherent_impl_crates(
|
|||
krate: CrateId,
|
||||
fp: TyFingerprint,
|
||||
) -> SmallVec<[CrateId; 2]> {
|
||||
let _p = tracing::span!(tracing::Level::INFO, "inherent_impl_crates_query").entered();
|
||||
let _p = tracing::span!(tracing::Level::INFO, "incoherent_inherent_impl_crates").entered();
|
||||
let mut res = SmallVec::new();
|
||||
let crate_graph = db.crate_graph();
|
||||
|
||||
|
|
|
@ -428,6 +428,17 @@ impl MirEvalError {
|
|||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn is_panic(&self) -> Option<&str> {
|
||||
let mut err = self;
|
||||
while let MirEvalError::InFunction(e, _) = err {
|
||||
err = e;
|
||||
}
|
||||
match err {
|
||||
MirEvalError::Panic(msg) => Some(msg),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for MirEvalError {
|
||||
|
@ -1138,7 +1149,7 @@ impl Evaluator<'_> {
|
|||
let mut ty = self.operand_ty(lhs, locals)?;
|
||||
while let TyKind::Ref(_, _, z) = ty.kind(Interner) {
|
||||
ty = z.clone();
|
||||
let size = if ty.kind(Interner) == &TyKind::Str {
|
||||
let size = if ty.is_str() {
|
||||
if *op != BinOp::Eq {
|
||||
never!("Only eq is builtin for `str`");
|
||||
}
|
||||
|
|
|
@ -49,6 +49,7 @@ impl Evaluator<'_> {
|
|||
if self.not_special_fn_cache.borrow().contains(&def) {
|
||||
return Ok(false);
|
||||
}
|
||||
|
||||
let function_data = self.db.function_data(def);
|
||||
let is_intrinsic = match &function_data.abi {
|
||||
Some(abi) => *abi == Interned::new_str("rust-intrinsic"),
|
||||
|
@ -131,9 +132,7 @@ impl Evaluator<'_> {
|
|||
return Ok(true);
|
||||
}
|
||||
if let Some(it) = self.detect_lang_function(def) {
|
||||
let arg_bytes =
|
||||
args.iter().map(|it| Ok(it.get(self)?.to_owned())).collect::<Result<Vec<_>>>()?;
|
||||
let result = self.exec_lang_item(it, generic_args, &arg_bytes, locals, span)?;
|
||||
let result = self.exec_lang_item(it, generic_args, args, locals, span)?;
|
||||
destination.write_from_bytes(self, &result)?;
|
||||
return Ok(true);
|
||||
}
|
||||
|
@ -311,16 +310,20 @@ impl Evaluator<'_> {
|
|||
|
||||
fn detect_lang_function(&self, def: FunctionId) -> Option<LangItem> {
|
||||
use LangItem::*;
|
||||
let candidate = self.db.lang_attr(def.into())?;
|
||||
let attrs = self.db.attrs(def.into());
|
||||
|
||||
if attrs.by_key("rustc_const_panic_str").exists() {
|
||||
// `#[rustc_const_panic_str]` is treated like `lang = "begin_panic"` by rustc CTFE.
|
||||
return Some(LangItem::BeginPanic);
|
||||
}
|
||||
|
||||
let candidate = attrs.by_key("lang").string_value().and_then(LangItem::from_str)?;
|
||||
// We want to execute these functions with special logic
|
||||
// `PanicFmt` is not detected here as it's redirected later.
|
||||
if [BeginPanic, SliceLen, DropInPlace].contains(&candidate) {
|
||||
return Some(candidate);
|
||||
}
|
||||
if self.db.attrs(def.into()).by_key("rustc_const_panic_str").exists() {
|
||||
// `#[rustc_const_panic_str]` is treated like `lang = "begin_panic"` by rustc CTFE.
|
||||
return Some(LangItem::BeginPanic);
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
|
@ -328,18 +331,52 @@ impl Evaluator<'_> {
|
|||
&mut self,
|
||||
it: LangItem,
|
||||
generic_args: &Substitution,
|
||||
args: &[Vec<u8>],
|
||||
args: &[IntervalAndTy],
|
||||
locals: &Locals,
|
||||
span: MirSpan,
|
||||
) -> Result<Vec<u8>> {
|
||||
use LangItem::*;
|
||||
let mut args = args.iter();
|
||||
match it {
|
||||
BeginPanic => Err(MirEvalError::Panic("<unknown-panic-payload>".to_owned())),
|
||||
BeginPanic => {
|
||||
let mut arg = args
|
||||
.next()
|
||||
.ok_or(MirEvalError::InternalError(
|
||||
"argument of BeginPanic is not provided".into(),
|
||||
))?
|
||||
.clone();
|
||||
while let TyKind::Ref(_, _, ty) = arg.ty.kind(Interner) {
|
||||
if ty.is_str() {
|
||||
let (pointee, metadata) = arg.interval.get(self)?.split_at(self.ptr_size());
|
||||
let len = from_bytes!(usize, metadata);
|
||||
|
||||
return {
|
||||
Err(MirEvalError::Panic(
|
||||
std::str::from_utf8(
|
||||
self.read_memory(Address::from_bytes(pointee)?, len)?,
|
||||
)
|
||||
.unwrap()
|
||||
.to_owned(),
|
||||
))
|
||||
};
|
||||
}
|
||||
let size = self.size_of_sized(ty, locals, "begin panic arg")?;
|
||||
let pointee = arg.interval.get(self)?;
|
||||
arg = IntervalAndTy {
|
||||
interval: Interval::new(Address::from_bytes(pointee)?, size),
|
||||
ty: ty.clone(),
|
||||
};
|
||||
}
|
||||
Err(MirEvalError::Panic(format!(
|
||||
"unknown-panic-payload: {:?}",
|
||||
arg.ty.kind(Interner)
|
||||
)))
|
||||
}
|
||||
SliceLen => {
|
||||
let arg = args.next().ok_or(MirEvalError::InternalError(
|
||||
"argument of <[T]>::len() is not provided".into(),
|
||||
))?;
|
||||
let arg = arg.get(self)?;
|
||||
let ptr_size = arg.len() / 2;
|
||||
Ok(arg[ptr_size..].into())
|
||||
}
|
||||
|
@ -353,6 +390,7 @@ impl Evaluator<'_> {
|
|||
let arg = args.next().ok_or(MirEvalError::InternalError(
|
||||
"argument of drop_in_place is not provided".into(),
|
||||
))?;
|
||||
let arg = arg.interval.get(self)?.to_owned();
|
||||
self.run_drop_glue_deep(
|
||||
ty.clone(),
|
||||
locals,
|
||||
|
|
|
@ -31,6 +31,7 @@ fn eval_main(db: &TestDB, file_id: FileId) -> Result<(String, String), MirEvalEr
|
|||
db.trait_environment(func_id.into()),
|
||||
)
|
||||
.map_err(|e| MirEvalError::MirLowerError(func_id, e))?;
|
||||
|
||||
let (result, output) = interpret_mir(db, body, false, None);
|
||||
result?;
|
||||
Ok((output.stdout().into_owned(), output.stderr().into_owned()))
|
||||
|
@ -72,6 +73,13 @@ fn check_pass_and_stdio(ra_fixture: &str, expected_stdout: &str, expected_stderr
|
|||
}
|
||||
}
|
||||
|
||||
fn check_panic(ra_fixture: &str, expected_panic: &str) {
|
||||
let (db, file_ids) = TestDB::with_many_files(ra_fixture);
|
||||
let file_id = *file_ids.last().unwrap();
|
||||
let e = eval_main(&db, file_id).unwrap_err();
|
||||
assert_eq!(e.is_panic().unwrap_or_else(|| panic!("unexpected error: {:?}", e)), expected_panic);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn function_with_extern_c_abi() {
|
||||
check_pass(
|
||||
|
@ -87,6 +95,43 @@ fn main() {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn panic_fmt() {
|
||||
// panic!
|
||||
// -> panic_2021 (builtin macro redirection)
|
||||
// -> #[lang = "panic_fmt"] core::panicking::panic_fmt (hooked by CTFE for redirection)
|
||||
// -> core::panicking::const_panic_fmt
|
||||
// -> #[rustc_const_panic_str] core::panicking::panic_display (hooked by CTFE for builtin panic)
|
||||
// -> Err(ConstEvalError::Panic)
|
||||
check_panic(
|
||||
r#"
|
||||
//- minicore: fmt, panic
|
||||
fn main() {
|
||||
panic!("hello, world!");
|
||||
}
|
||||
"#,
|
||||
"hello, world!",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn panic_display() {
|
||||
// panic!
|
||||
// -> panic_2021 (builtin macro redirection)
|
||||
// -> #[rustc_const_panic_str] core::panicking::panic_display (hooked by CTFE for builtin panic)
|
||||
// -> Err(ConstEvalError::Panic)
|
||||
check_panic(
|
||||
r#"
|
||||
//- minicore: fmt, panic
|
||||
|
||||
fn main() {
|
||||
panic!("{}", "hello, world!");
|
||||
}
|
||||
"#,
|
||||
"hello, world!",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn drop_basic() {
|
||||
check_pass(
|
||||
|
|
|
@ -186,7 +186,7 @@ fn test() {
|
|||
let x = match 1 {
|
||||
1 => t as *mut i32,
|
||||
2 => t as &i32,
|
||||
//^^^^^^^^^ expected *mut i32, got &i32
|
||||
//^^^^^^^^^ expected *mut i32, got &'? i32
|
||||
_ => t as *const i32,
|
||||
// ^^^^^^^^^^^^^^^ adjustments: Pointer(MutToConstPointer)
|
||||
|
||||
|
@ -307,7 +307,7 @@ fn test() {
|
|||
let foo = Foo;
|
||||
//^^^ type: Foo<{unknown}>
|
||||
let _: &u32 = &Foo;
|
||||
//^^^^ expected &u32, got &Foo<{unknown}>
|
||||
//^^^^ expected &'? u32, got &'? Foo<{unknown}>
|
||||
}",
|
||||
);
|
||||
}
|
||||
|
@ -544,9 +544,9 @@ struct Bar<T>(Foo<T>);
|
|||
|
||||
fn test() {
|
||||
let _: &Foo<[usize]> = &Foo { t: [1, 2, 3] };
|
||||
//^^^^^^^^^^^^^^^^^^^^^ expected &Foo<[usize]>, got &Foo<[i32; 3]>
|
||||
//^^^^^^^^^^^^^^^^^^^^^ expected &'? Foo<[usize]>, got &'? Foo<[i32; 3]>
|
||||
let _: &Bar<[usize]> = &Bar(Foo { t: [1, 2, 3] });
|
||||
//^^^^^^^^^^^^^^^^^^^^^^^^^^ expected &Bar<[usize]>, got &Bar<[i32; 3]>
|
||||
//^^^^^^^^^^^^^^^^^^^^^^^^^^ expected &'? Bar<[usize]>, got &'? Bar<[i32; 3]>
|
||||
}
|
||||
"#,
|
||||
);
|
||||
|
@ -562,7 +562,7 @@ trait Foo {}
|
|||
fn test(f: impl Foo, g: &(impl Foo + ?Sized)) {
|
||||
let _: &dyn Foo = &f;
|
||||
let _: &dyn Foo = g;
|
||||
//^ expected &dyn Foo, got &impl Foo + ?Sized
|
||||
//^ expected &'? dyn Foo, got &'? impl Foo + ?Sized
|
||||
}
|
||||
"#,
|
||||
);
|
||||
|
@ -828,11 +828,11 @@ struct V<T> { t: T }
|
|||
fn main() {
|
||||
let a: V<&dyn Tr>;
|
||||
(a,) = V { t: &S };
|
||||
//^^^^expected V<&S>, got (V<&dyn Tr>,)
|
||||
//^^^^expected V<&'? S>, got (V<&'? dyn Tr>,)
|
||||
|
||||
let mut a: V<&dyn Tr> = V { t: &S };
|
||||
(a,) = V { t: &S };
|
||||
//^^^^expected V<&S>, got (V<&dyn Tr>,)
|
||||
//^^^^expected V<&'? S>, got (V<&'? dyn Tr>,)
|
||||
}
|
||||
"#,
|
||||
);
|
||||
|
|
|
@ -8,7 +8,7 @@ fn function_return_type_mismatch_1() {
|
|||
r#"
|
||||
fn test() -> &'static str {
|
||||
5
|
||||
//^ expected &str, got i32
|
||||
//^ expected &'static str, got i32
|
||||
}
|
||||
"#,
|
||||
);
|
||||
|
@ -21,7 +21,7 @@ fn function_return_type_mismatch_2() {
|
|||
fn test(x: bool) -> &'static str {
|
||||
if x {
|
||||
return 1;
|
||||
//^ expected &str, got i32
|
||||
//^ expected &'static str, got i32
|
||||
}
|
||||
"ok"
|
||||
}
|
||||
|
@ -38,7 +38,7 @@ fn test(x: bool) -> &'static str {
|
|||
return "ok";
|
||||
}
|
||||
1
|
||||
//^ expected &str, got i32
|
||||
//^ expected &'static str, got i32
|
||||
}
|
||||
"#,
|
||||
);
|
||||
|
@ -53,7 +53,7 @@ fn test(x: bool) -> &'static str {
|
|||
"ok"
|
||||
} else {
|
||||
1
|
||||
//^ expected &str, got i32
|
||||
//^ expected &'static str, got i32
|
||||
}
|
||||
}
|
||||
"#,
|
||||
|
@ -67,7 +67,7 @@ fn function_return_type_mismatch_5() {
|
|||
fn test(x: bool) -> &'static str {
|
||||
if x {
|
||||
1
|
||||
//^ expected &str, got i32
|
||||
//^ expected &'static str, got i32
|
||||
} else {
|
||||
"ok"
|
||||
}
|
||||
|
@ -83,10 +83,10 @@ fn non_unit_block_expr_stmt_no_semi() {
|
|||
fn test(x: bool) {
|
||||
if x {
|
||||
"notok"
|
||||
//^^^^^^^ expected (), got &str
|
||||
//^^^^^^^ expected (), got &'static str
|
||||
} else {
|
||||
"ok"
|
||||
//^^^^ expected (), got &str
|
||||
//^^^^ expected (), got &'static str
|
||||
}
|
||||
match x { true => true, false => 0 }
|
||||
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected (), got bool
|
||||
|
|
|
@ -67,11 +67,11 @@ trait B: A {}
|
|||
|
||||
fn test(
|
||||
_: &(dyn A<Assoc = ()> + Send),
|
||||
//^ &(dyn A<Assoc = ()> + Send)
|
||||
//^ &'_ (dyn A<Assoc = ()> + Send)
|
||||
_: &(dyn Send + A<Assoc = ()>),
|
||||
//^ &(dyn A<Assoc = ()> + Send)
|
||||
//^ &'_ (dyn A<Assoc = ()> + Send)
|
||||
_: &dyn B<Assoc = ()>,
|
||||
//^ &(dyn B<Assoc = ()>)
|
||||
//^ &'_ (dyn B<Assoc = ()>)
|
||||
) {}
|
||||
"#,
|
||||
);
|
||||
|
@ -85,7 +85,7 @@ fn render_dyn_for_ty() {
|
|||
trait Foo<'a> {}
|
||||
|
||||
fn foo(foo: &dyn for<'a> Foo<'a>) {}
|
||||
// ^^^ &dyn Foo<'_>
|
||||
// ^^^ &'_ dyn Foo<'_>
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
@ -111,11 +111,11 @@ fn test(
|
|||
b;
|
||||
//^ impl Foo
|
||||
c;
|
||||
//^ &impl Foo + ?Sized
|
||||
//^ &'_ impl Foo + ?Sized
|
||||
d;
|
||||
//^ S<impl Foo>
|
||||
ref_any;
|
||||
//^^^^^^^ &impl ?Sized
|
||||
//^^^^^^^ &'_ impl ?Sized
|
||||
empty;
|
||||
} //^^^^^ impl Sized
|
||||
"#,
|
||||
|
@ -192,7 +192,7 @@ fn test(
|
|||
b;
|
||||
//^ fn(impl Foo) -> impl Foo
|
||||
c;
|
||||
} //^ fn(&impl Foo + ?Sized) -> &impl Foo + ?Sized
|
||||
} //^ fn(&'_ impl Foo + ?Sized) -> &'_ impl Foo + ?Sized
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -200,8 +200,8 @@ fn expr_macro_def_expanded_in_various_places() {
|
|||
100..119 'for _ ...!() {}': IntoIterator::IntoIter<isize>
|
||||
100..119 'for _ ...!() {}': !
|
||||
100..119 'for _ ...!() {}': IntoIterator::IntoIter<isize>
|
||||
100..119 'for _ ...!() {}': &mut IntoIterator::IntoIter<isize>
|
||||
100..119 'for _ ...!() {}': fn next<IntoIterator::IntoIter<isize>>(&mut IntoIterator::IntoIter<isize>) -> Option<<IntoIterator::IntoIter<isize> as Iterator>::Item>
|
||||
100..119 'for _ ...!() {}': &'? mut IntoIterator::IntoIter<isize>
|
||||
100..119 'for _ ...!() {}': fn next<IntoIterator::IntoIter<isize>>(&'? mut IntoIterator::IntoIter<isize>) -> Option<<IntoIterator::IntoIter<isize> as Iterator>::Item>
|
||||
100..119 'for _ ...!() {}': Option<IntoIterator::Item<isize>>
|
||||
100..119 'for _ ...!() {}': ()
|
||||
100..119 'for _ ...!() {}': ()
|
||||
|
@ -221,7 +221,7 @@ fn expr_macro_def_expanded_in_various_places() {
|
|||
281..303 'Spam {...m!() }': {unknown}
|
||||
309..325 'spam!(...am!()]': {unknown}
|
||||
350..366 'spam!(... usize': usize
|
||||
372..380 '&spam!()': &isize
|
||||
372..380 '&spam!()': &'? isize
|
||||
386..394 '-spam!()': isize
|
||||
400..416 'spam!(...pam!()': {unknown}
|
||||
422..439 'spam!(...pam!()': isize
|
||||
|
@ -293,8 +293,8 @@ fn expr_macro_rules_expanded_in_various_places() {
|
|||
114..133 'for _ ...!() {}': IntoIterator::IntoIter<isize>
|
||||
114..133 'for _ ...!() {}': !
|
||||
114..133 'for _ ...!() {}': IntoIterator::IntoIter<isize>
|
||||
114..133 'for _ ...!() {}': &mut IntoIterator::IntoIter<isize>
|
||||
114..133 'for _ ...!() {}': fn next<IntoIterator::IntoIter<isize>>(&mut IntoIterator::IntoIter<isize>) -> Option<<IntoIterator::IntoIter<isize> as Iterator>::Item>
|
||||
114..133 'for _ ...!() {}': &'? mut IntoIterator::IntoIter<isize>
|
||||
114..133 'for _ ...!() {}': fn next<IntoIterator::IntoIter<isize>>(&'? mut IntoIterator::IntoIter<isize>) -> Option<<IntoIterator::IntoIter<isize> as Iterator>::Item>
|
||||
114..133 'for _ ...!() {}': Option<IntoIterator::Item<isize>>
|
||||
114..133 'for _ ...!() {}': ()
|
||||
114..133 'for _ ...!() {}': ()
|
||||
|
@ -314,7 +314,7 @@ fn expr_macro_rules_expanded_in_various_places() {
|
|||
295..317 'Spam {...m!() }': {unknown}
|
||||
323..339 'spam!(...am!()]': {unknown}
|
||||
364..380 'spam!(... usize': usize
|
||||
386..394 '&spam!()': &isize
|
||||
386..394 '&spam!()': &'? isize
|
||||
400..408 '-spam!()': isize
|
||||
414..430 'spam!(...pam!()': {unknown}
|
||||
436..453 'spam!(...pam!()': isize
|
||||
|
@ -539,7 +539,7 @@ fn test() {
|
|||
let msg = foo::Message(foo::MessageRef);
|
||||
let r = msg.deref();
|
||||
r;
|
||||
//^ &MessageRef
|
||||
//^ &'? MessageRef
|
||||
}
|
||||
|
||||
//- /lib.rs crate:foo
|
||||
|
@ -703,9 +703,9 @@ fn infer_builtin_macros_file() {
|
|||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
!0..2 '""': &str
|
||||
!0..2 '""': &'static str
|
||||
63..87 '{ ...!(); }': ()
|
||||
73..74 'x': &str
|
||||
73..74 'x': &'static str
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
@ -741,9 +741,9 @@ fn infer_builtin_macros_concat() {
|
|||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
!0..13 '"helloworld!"': &str
|
||||
!0..13 '"helloworld!"': &'static str
|
||||
65..121 '{ ...")); }': ()
|
||||
75..76 'x': &str
|
||||
75..76 'x': &'static str
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
@ -820,7 +820,7 @@ macro_rules! include_str {() => {}}
|
|||
fn main() {
|
||||
let a = include_str!("foo.rs");
|
||||
a;
|
||||
} //^ &str
|
||||
} //^ &'static str
|
||||
|
||||
//- /foo.rs
|
||||
hello
|
||||
|
@ -847,7 +847,7 @@ macro_rules! m {
|
|||
fn main() {
|
||||
let a = include_str!(m!(".rs"));
|
||||
a;
|
||||
} //^ &str
|
||||
} //^ &'static str
|
||||
|
||||
//- /foo.rs
|
||||
hello
|
||||
|
@ -960,9 +960,9 @@ fn infer_builtin_macros_concat_with_lazy() {
|
|||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
!0..13 '"helloworld!"': &str
|
||||
!0..13 '"helloworld!"': &'static str
|
||||
103..160 '{ ...")); }': ()
|
||||
113..114 'x': &str
|
||||
113..114 'x': &'static str
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
@ -977,7 +977,7 @@ fn infer_builtin_macros_env() {
|
|||
|
||||
fn main() {
|
||||
let x = env!("foo");
|
||||
//^ &str
|
||||
//^ &'static str
|
||||
}
|
||||
"#,
|
||||
);
|
||||
|
@ -991,7 +991,7 @@ fn infer_builtin_macros_option_env() {
|
|||
//- /main.rs env:foo=bar
|
||||
fn main() {
|
||||
let x = option_env!("foo");
|
||||
//^ Option<&str>
|
||||
//^ Option<&'static str>
|
||||
}
|
||||
"#,
|
||||
);
|
||||
|
|
|
@ -658,7 +658,7 @@ fn infer_call_trait_method_on_generic_param_1() {
|
|||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
29..33 'self': &Self
|
||||
29..33 'self': &'? Self
|
||||
63..64 't': T
|
||||
69..88 '{ ...d(); }': ()
|
||||
75..76 't': T
|
||||
|
@ -679,7 +679,7 @@ fn infer_call_trait_method_on_generic_param_2() {
|
|||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
32..36 'self': &Self
|
||||
32..36 'self': &'? Self
|
||||
70..71 't': T
|
||||
76..95 '{ ...d(); }': ()
|
||||
82..83 't': T
|
||||
|
@ -757,7 +757,7 @@ struct S;
|
|||
impl Clone for S {}
|
||||
impl Clone for &S {}
|
||||
fn test() { (S.clone(), (&S).clone(), (&&S).clone()); }
|
||||
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ (S, S, &S)
|
||||
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ (S, S, &'? S)
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
@ -1150,12 +1150,12 @@ fn dyn_trait_super_trait_not_in_scope() {
|
|||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
51..55 'self': &Self
|
||||
51..55 'self': &'? Self
|
||||
64..69 '{ 0 }': u32
|
||||
66..67 '0': u32
|
||||
176..177 'd': &dyn Trait
|
||||
176..177 'd': &'? dyn Trait
|
||||
191..207 '{ ...o(); }': ()
|
||||
197..198 'd': &dyn Trait
|
||||
197..198 'd': &'? dyn Trait
|
||||
197..204 'd.foo()': u32
|
||||
"#]],
|
||||
);
|
||||
|
@ -1182,15 +1182,15 @@ fn test() {
|
|||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
75..79 'self': &S
|
||||
75..79 'self': &'? S
|
||||
89..109 '{ ... }': bool
|
||||
99..103 'true': bool
|
||||
123..167 '{ ...o(); }': ()
|
||||
133..134 's': &S
|
||||
137..151 'unsafe { f() }': &S
|
||||
146..147 'f': fn f() -> &S
|
||||
146..149 'f()': &S
|
||||
157..158 's': &S
|
||||
133..134 's': &'? S
|
||||
137..151 'unsafe { f() }': &'static S
|
||||
146..147 'f': fn f() -> &'static S
|
||||
146..149 'f()': &'static S
|
||||
157..158 's': &'? S
|
||||
157..164 's.foo()': bool
|
||||
"#]],
|
||||
);
|
||||
|
@ -1601,11 +1601,11 @@ use core::IntoIterator;
|
|||
fn f() {
|
||||
let v = [4].into_iter();
|
||||
v;
|
||||
//^ &i32
|
||||
//^ &'? i32
|
||||
|
||||
let a = [0, 1].into_iter();
|
||||
a;
|
||||
//^ &i32
|
||||
//^ &'? i32
|
||||
}
|
||||
|
||||
//- /main2021.rs crate:main2021 deps:core edition:2021
|
||||
|
@ -1618,7 +1618,7 @@ fn f() {
|
|||
|
||||
let a = [0, 1].into_iter();
|
||||
a;
|
||||
//^ &i32
|
||||
//^ &'? i32
|
||||
}
|
||||
|
||||
//- /core.rs crate:core
|
||||
|
@ -1767,7 +1767,7 @@ fn test() {
|
|||
let a2 = A(make(), 1i32);
|
||||
let _: &str = a2.thing();
|
||||
a2;
|
||||
//^^ A<C<&str>, i32>
|
||||
//^^ A<C<&'? str>, i32>
|
||||
}
|
||||
"#,
|
||||
);
|
||||
|
|
|
@ -104,7 +104,7 @@ enum Option<T> { None, Some(T) }
|
|||
fn test() {
|
||||
let a = if true { Option::None } else { Option::Some(return) };
|
||||
a;
|
||||
//^ Option<&str>
|
||||
//^ Option<&'static str>
|
||||
match 42 {
|
||||
42 => a,
|
||||
_ => Option::Some("str"),
|
||||
|
@ -317,8 +317,8 @@ fn diverging_expression_2() {
|
|||
63..81 '{ loop...foo" }': u32
|
||||
65..72 'loop {}': !
|
||||
70..72 '{}': ()
|
||||
74..79 '"foo"': &str
|
||||
74..79: expected u32, got &str
|
||||
74..79 '"foo"': &'static str
|
||||
74..79: expected u32, got &'static str
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
@ -365,8 +365,8 @@ fn diverging_expression_3_break() {
|
|||
151..172 'for a ...eak; }': {unknown}
|
||||
151..172 'for a ...eak; }': !
|
||||
151..172 'for a ...eak; }': {unknown}
|
||||
151..172 'for a ...eak; }': &mut {unknown}
|
||||
151..172 'for a ...eak; }': fn next<{unknown}>(&mut {unknown}) -> Option<<{unknown} as Iterator>::Item>
|
||||
151..172 'for a ...eak; }': &'? mut {unknown}
|
||||
151..172 'for a ...eak; }': fn next<{unknown}>(&'? mut {unknown}) -> Option<<{unknown} as Iterator>::Item>
|
||||
151..172 'for a ...eak; }': Option<{unknown}>
|
||||
151..172 'for a ...eak; }': ()
|
||||
151..172 'for a ...eak; }': ()
|
||||
|
@ -381,8 +381,8 @@ fn diverging_expression_3_break() {
|
|||
237..250 'for a in b {}': {unknown}
|
||||
237..250 'for a in b {}': !
|
||||
237..250 'for a in b {}': {unknown}
|
||||
237..250 'for a in b {}': &mut {unknown}
|
||||
237..250 'for a in b {}': fn next<{unknown}>(&mut {unknown}) -> Option<<{unknown} as Iterator>::Item>
|
||||
237..250 'for a in b {}': &'? mut {unknown}
|
||||
237..250 'for a in b {}': fn next<{unknown}>(&'? mut {unknown}) -> Option<<{unknown} as Iterator>::Item>
|
||||
237..250 'for a in b {}': Option<{unknown}>
|
||||
237..250 'for a in b {}': ()
|
||||
237..250 'for a in b {}': ()
|
||||
|
@ -396,8 +396,8 @@ fn diverging_expression_3_break() {
|
|||
315..337 'for a ...urn; }': {unknown}
|
||||
315..337 'for a ...urn; }': !
|
||||
315..337 'for a ...urn; }': {unknown}
|
||||
315..337 'for a ...urn; }': &mut {unknown}
|
||||
315..337 'for a ...urn; }': fn next<{unknown}>(&mut {unknown}) -> Option<<{unknown} as Iterator>::Item>
|
||||
315..337 'for a ...urn; }': &'? mut {unknown}
|
||||
315..337 'for a ...urn; }': fn next<{unknown}>(&'? mut {unknown}) -> Option<<{unknown} as Iterator>::Item>
|
||||
315..337 'for a ...urn; }': Option<{unknown}>
|
||||
315..337 'for a ...urn; }': ()
|
||||
315..337 'for a ...urn; }': ()
|
||||
|
|
|
@ -32,27 +32,27 @@ fn infer_pattern() {
|
|||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
8..9 'x': &i32
|
||||
8..9 'x': &'? i32
|
||||
17..400 '{ ...o_x; }': ()
|
||||
27..28 'y': &i32
|
||||
31..32 'x': &i32
|
||||
42..44 '&z': &i32
|
||||
27..28 'y': &'? i32
|
||||
31..32 'x': &'? i32
|
||||
42..44 '&z': &'? i32
|
||||
43..44 'z': i32
|
||||
47..48 'x': &i32
|
||||
47..48 'x': &'? i32
|
||||
58..59 'a': i32
|
||||
62..63 'z': i32
|
||||
73..79 '(c, d)': (i32, &str)
|
||||
73..79 '(c, d)': (i32, &'static str)
|
||||
74..75 'c': i32
|
||||
77..78 'd': &str
|
||||
82..94 '(1, "hello")': (i32, &str)
|
||||
77..78 'd': &'static str
|
||||
82..94 '(1, "hello")': (i32, &'static str)
|
||||
83..84 '1': i32
|
||||
86..93 '"hello"': &str
|
||||
86..93 '"hello"': &'static str
|
||||
101..151 'for (e... }': fn into_iter<{unknown}>({unknown}) -> <{unknown} as IntoIterator>::IntoIter
|
||||
101..151 'for (e... }': {unknown}
|
||||
101..151 'for (e... }': !
|
||||
101..151 'for (e... }': {unknown}
|
||||
101..151 'for (e... }': &mut {unknown}
|
||||
101..151 'for (e... }': fn next<{unknown}>(&mut {unknown}) -> Option<<{unknown} as Iterator>::Item>
|
||||
101..151 'for (e... }': &'? mut {unknown}
|
||||
101..151 'for (e... }': fn next<{unknown}>(&'? mut {unknown}) -> Option<<{unknown} as Iterator>::Item>
|
||||
101..151 'for (e... }': Option<({unknown}, {unknown})>
|
||||
101..151 'for (e... }': ()
|
||||
101..151 'for (e... }': ()
|
||||
|
@ -74,10 +74,10 @@ fn infer_pattern() {
|
|||
194..197 'val': {unknown}
|
||||
210..236 'if let...rue {}': ()
|
||||
213..233 'let x ... &true': bool
|
||||
217..225 'x @ true': &bool
|
||||
217..225 'x @ true': &'? bool
|
||||
221..225 'true': bool
|
||||
221..225 'true': bool
|
||||
228..233 '&true': &bool
|
||||
228..233 '&true': &'? bool
|
||||
229..233 'true': bool
|
||||
234..236 '{}': ()
|
||||
246..252 'lambda': impl Fn(u64, u64, i32) -> i32
|
||||
|
@ -90,14 +90,14 @@ fn infer_pattern() {
|
|||
277..282 'a + b': u64
|
||||
281..282 'b': u64
|
||||
284..285 'c': i32
|
||||
298..310 'ref ref_to_x': &&i32
|
||||
313..314 'x': &i32
|
||||
324..333 'mut mut_x': &i32
|
||||
336..337 'x': &i32
|
||||
347..367 'ref mu...f_to_x': &mut &i32
|
||||
370..371 'x': &i32
|
||||
381..382 'k': &mut &i32
|
||||
385..397 'mut_ref_to_x': &mut &i32
|
||||
298..310 'ref ref_to_x': &'? &'? i32
|
||||
313..314 'x': &'? i32
|
||||
324..333 'mut mut_x': &'? i32
|
||||
336..337 'x': &'? i32
|
||||
347..367 'ref mu...f_to_x': &'? mut &'? i32
|
||||
370..371 'x': &'? i32
|
||||
381..382 'k': &'? mut &'? i32
|
||||
385..397 'mut_ref_to_x': &'? mut &'? i32
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
@ -120,14 +120,14 @@ fn infer_literal_pattern() {
|
|||
17..28 '{ loop {} }': T
|
||||
19..26 'loop {}': !
|
||||
24..26 '{}': ()
|
||||
37..38 'x': &i32
|
||||
37..38 'x': &'? i32
|
||||
46..208 '{ ...) {} }': ()
|
||||
52..75 'if let...y() {}': ()
|
||||
55..72 'let "f... any()': bool
|
||||
59..64 '"foo"': &str
|
||||
59..64 '"foo"': &str
|
||||
67..70 'any': fn any<&str>() -> &str
|
||||
67..72 'any()': &str
|
||||
59..64 '"foo"': &'static str
|
||||
59..64 '"foo"': &'static str
|
||||
67..70 'any': fn any<&'static str>() -> &'static str
|
||||
67..72 'any()': &'static str
|
||||
73..75 '{}': ()
|
||||
80..99 'if let...y() {}': ()
|
||||
83..96 'let 1 = any()': bool
|
||||
|
@ -178,7 +178,7 @@ fn infer_range_pattern() {
|
|||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
8..9 'x': &i32
|
||||
8..9 'x': &'? i32
|
||||
17..75 '{ ...2 {} }': ()
|
||||
23..45 'if let...u32 {}': ()
|
||||
26..42 'let 1....= 2u32': bool
|
||||
|
@ -208,14 +208,14 @@ fn infer_pattern_match_ergonomics() {
|
|||
expect![[r#"
|
||||
27..78 '{ ...(1); }': ()
|
||||
37..41 'A(n)': A<i32>
|
||||
39..40 'n': &i32
|
||||
44..49 '&A(1)': &A<i32>
|
||||
39..40 'n': &'? i32
|
||||
44..49 '&A(1)': &'? A<i32>
|
||||
45..46 'A': extern "rust-call" A<i32>(i32) -> A<i32>
|
||||
45..49 'A(1)': A<i32>
|
||||
47..48 '1': i32
|
||||
59..63 'A(n)': A<i32>
|
||||
61..62 'n': &mut i32
|
||||
66..75 '&mut A(1)': &mut A<i32>
|
||||
61..62 'n': &'? mut i32
|
||||
66..75 '&mut A(1)': &'? mut A<i32>
|
||||
71..72 'A': extern "rust-call" A<i32>(i32) -> A<i32>
|
||||
71..75 'A(1)': A<i32>
|
||||
73..74 '1': i32
|
||||
|
@ -235,17 +235,17 @@ fn infer_pattern_match_ergonomics_ref() {
|
|||
"#,
|
||||
expect![[r#"
|
||||
10..56 '{ ...= v; }': ()
|
||||
20..21 'v': &(i32, &i32)
|
||||
24..32 '&(1, &2)': &(i32, &i32)
|
||||
25..32 '(1, &2)': (i32, &i32)
|
||||
20..21 'v': &'? (i32, &'? i32)
|
||||
24..32 '&(1, &2)': &'? (i32, &'? i32)
|
||||
25..32 '(1, &2)': (i32, &'? i32)
|
||||
26..27 '1': i32
|
||||
29..31 '&2': &i32
|
||||
29..31 '&2': &'? i32
|
||||
30..31 '2': i32
|
||||
42..49 '(_, &w)': (i32, &i32)
|
||||
42..49 '(_, &w)': (i32, &'? i32)
|
||||
43..44 '_': i32
|
||||
46..48 '&w': &i32
|
||||
46..48 '&w': &'? i32
|
||||
47..48 'w': i32
|
||||
52..53 'v': &(i32, &i32)
|
||||
52..53 'v': &'? (i32, &'? i32)
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
@ -286,28 +286,28 @@ fn infer_pattern_match_slice() {
|
|||
"#,
|
||||
expect![[r#"
|
||||
10..209 '{ ... } }': ()
|
||||
20..25 'slice': &[f64]
|
||||
36..42 '&[0.0]': &[f64; 1]
|
||||
20..25 'slice': &'? [f64]
|
||||
36..42 '&[0.0]': &'? [f64; 1]
|
||||
37..42 '[0.0]': [f64; 1]
|
||||
38..41 '0.0': f64
|
||||
48..207 'match ... }': ()
|
||||
54..59 'slice': &[f64]
|
||||
70..73 '&[]': &[f64]
|
||||
54..59 'slice': &'? [f64]
|
||||
70..73 '&[]': &'? [f64]
|
||||
71..73 '[]': [f64]
|
||||
77..79 '{}': ()
|
||||
89..93 '&[a]': &[f64]
|
||||
89..93 '&[a]': &'? [f64]
|
||||
90..93 '[a]': [f64]
|
||||
91..92 'a': f64
|
||||
97..123 '{ ... }': ()
|
||||
111..112 'a': f64
|
||||
133..140 '&[b, c]': &[f64]
|
||||
133..140 '&[b, c]': &'? [f64]
|
||||
134..140 '[b, c]': [f64]
|
||||
135..136 'b': f64
|
||||
138..139 'c': f64
|
||||
144..185 '{ ... }': ()
|
||||
158..159 'b': f64
|
||||
173..174 'c': f64
|
||||
194..195 '_': &[f64]
|
||||
194..195 '_': &'? [f64]
|
||||
199..201 '{}': ()
|
||||
"#]],
|
||||
);
|
||||
|
@ -327,14 +327,14 @@ fn infer_pattern_match_string_literal() {
|
|||
"#,
|
||||
expect![[r#"
|
||||
10..98 '{ ... } }': ()
|
||||
20..21 's': &str
|
||||
30..37 '"hello"': &str
|
||||
20..21 's': &'? str
|
||||
30..37 '"hello"': &'static str
|
||||
43..96 'match ... }': ()
|
||||
49..50 's': &str
|
||||
61..68 '"hello"': &str
|
||||
61..68 '"hello"': &str
|
||||
49..50 's': &'? str
|
||||
61..68 '"hello"': &'static str
|
||||
61..68 '"hello"': &'static str
|
||||
72..74 '{}': ()
|
||||
83..84 '_': &str
|
||||
83..84 '_': &'? str
|
||||
88..90 '{}': ()
|
||||
"#]],
|
||||
);
|
||||
|
@ -358,27 +358,27 @@ fn infer_pattern_match_byte_string_literal() {
|
|||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
105..109 'self': &[T; N]
|
||||
105..109 'self': &'? [T; N]
|
||||
111..116 'index': {unknown}
|
||||
157..180 '{ ... }': &[u8]
|
||||
157..180 '{ ... }': &'? [u8]
|
||||
167..174 'loop {}': !
|
||||
172..174 '{}': ()
|
||||
191..192 'v': [u8; 3]
|
||||
203..261 '{ ...v {} }': ()
|
||||
209..233 'if let...[S] {}': ()
|
||||
212..230 'let b"... &v[S]': bool
|
||||
216..222 'b"foo"': &[u8]
|
||||
216..222 'b"foo"': &[u8]
|
||||
225..230 '&v[S]': &[u8]
|
||||
216..222 'b"foo"': &'static [u8]
|
||||
216..222 'b"foo"': &'static [u8]
|
||||
225..230 '&v[S]': &'? [u8]
|
||||
226..227 'v': [u8; 3]
|
||||
226..230 'v[S]': [u8]
|
||||
228..229 'S': S
|
||||
231..233 '{}': ()
|
||||
238..259 'if let... &v {}': ()
|
||||
241..256 'let b"foo" = &v': bool
|
||||
245..251 'b"foo"': &[u8; 3]
|
||||
245..251 'b"foo"': &[u8; 3]
|
||||
254..256 '&v': &[u8; 3]
|
||||
245..251 'b"foo"': &'static [u8; 3]
|
||||
245..251 'b"foo"': &'static [u8; 3]
|
||||
254..256 '&v': &'? [u8; 3]
|
||||
255..256 'v': [u8; 3]
|
||||
257..259 '{}': ()
|
||||
"#]],
|
||||
|
@ -399,17 +399,17 @@ fn infer_pattern_match_or() {
|
|||
"#,
|
||||
expect![[r#"
|
||||
10..108 '{ ... } }': ()
|
||||
20..21 's': &str
|
||||
30..37 '"hello"': &str
|
||||
20..21 's': &'? str
|
||||
30..37 '"hello"': &'static str
|
||||
43..106 'match ... }': ()
|
||||
49..50 's': &str
|
||||
61..68 '"hello"': &str
|
||||
61..68 '"hello"': &str
|
||||
61..78 '"hello...world"': &str
|
||||
71..78 '"world"': &str
|
||||
71..78 '"world"': &str
|
||||
49..50 's': &'? str
|
||||
61..68 '"hello"': &'static str
|
||||
61..68 '"hello"': &'static str
|
||||
61..78 '"hello...world"': &'? str
|
||||
71..78 '"world"': &'static str
|
||||
71..78 '"world"': &'static str
|
||||
82..84 '{}': ()
|
||||
93..94 '_': &str
|
||||
93..94 '_': &'? str
|
||||
98..100 '{}': ()
|
||||
"#]],
|
||||
);
|
||||
|
@ -505,10 +505,10 @@ fn infer_adt_pattern() {
|
|||
216..217 '1': usize
|
||||
227..231 'E::B': E
|
||||
235..237 '10': usize
|
||||
255..274 'ref d ...{ .. }': &E
|
||||
255..274 'ref d ...{ .. }': &'? E
|
||||
263..274 'E::A { .. }': E
|
||||
277..278 'e': E
|
||||
284..285 'd': &E
|
||||
284..285 'd': &'? E
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
@ -529,14 +529,14 @@ impl Foo {
|
|||
expect![[r#"
|
||||
42..151 '{ ... }': ()
|
||||
56..64 'Self(s,)': Foo
|
||||
61..62 's': &usize
|
||||
67..75 '&Foo(0,)': &Foo
|
||||
61..62 's': &'? usize
|
||||
67..75 '&Foo(0,)': &'? Foo
|
||||
68..71 'Foo': extern "rust-call" Foo(usize) -> Foo
|
||||
68..75 'Foo(0,)': Foo
|
||||
72..73 '0': usize
|
||||
89..97 'Self(s,)': Foo
|
||||
94..95 's': &mut usize
|
||||
100..112 '&mut Foo(0,)': &mut Foo
|
||||
94..95 's': &'? mut usize
|
||||
100..112 '&mut Foo(0,)': &'? mut Foo
|
||||
105..108 'Foo': extern "rust-call" Foo(usize) -> Foo
|
||||
105..112 'Foo(0,)': Foo
|
||||
109..110 '0': usize
|
||||
|
@ -669,7 +669,7 @@ fn main() {
|
|||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
27..31 'self': &S
|
||||
27..31 'self': &'? S
|
||||
41..50 '{ false }': bool
|
||||
43..48 'false': bool
|
||||
64..115 '{ ... } }': ()
|
||||
|
@ -679,7 +679,7 @@ fn main() {
|
|||
93..94 's': S
|
||||
93..100 's.foo()': bool
|
||||
104..106 '()': ()
|
||||
"#]],
|
||||
"#]],
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -702,29 +702,29 @@ fn test() {
|
|||
51..58 'loop {}': !
|
||||
56..58 '{}': ()
|
||||
72..171 '{ ... x); }': ()
|
||||
78..81 'foo': fn foo<&(i32, &str), i32, impl FnOnce(&(i32, &str)) -> i32>(&(i32, &str), impl FnOnce(&(i32, &str)) -> i32) -> i32
|
||||
78..81 'foo': fn foo<&'? (i32, &'? str), i32, impl FnOnce(&'? (i32, &'? str)) -> i32>(&'? (i32, &'? str), impl FnOnce(&'? (i32, &'? str)) -> i32) -> i32
|
||||
78..105 'foo(&(...y)| x)': i32
|
||||
82..91 '&(1, "a")': &(i32, &str)
|
||||
83..91 '(1, "a")': (i32, &str)
|
||||
82..91 '&(1, "a")': &'? (i32, &'static str)
|
||||
83..91 '(1, "a")': (i32, &'static str)
|
||||
84..85 '1': i32
|
||||
87..90 '"a"': &str
|
||||
93..104 '|&(x, y)| x': impl FnOnce(&(i32, &str)) -> i32
|
||||
94..101 '&(x, y)': &(i32, &str)
|
||||
95..101 '(x, y)': (i32, &str)
|
||||
87..90 '"a"': &'static str
|
||||
93..104 '|&(x, y)| x': impl FnOnce(&'? (i32, &'? str)) -> i32
|
||||
94..101 '&(x, y)': &'? (i32, &'? str)
|
||||
95..101 '(x, y)': (i32, &'? str)
|
||||
96..97 'x': i32
|
||||
99..100 'y': &str
|
||||
99..100 'y': &'? str
|
||||
103..104 'x': i32
|
||||
142..145 'foo': fn foo<&(i32, &str), &i32, impl FnOnce(&(i32, &str)) -> &i32>(&(i32, &str), impl FnOnce(&(i32, &str)) -> &i32) -> &i32
|
||||
142..168 'foo(&(...y)| x)': &i32
|
||||
146..155 '&(1, "a")': &(i32, &str)
|
||||
147..155 '(1, "a")': (i32, &str)
|
||||
142..145 'foo': fn foo<&'? (i32, &'? str), &'? i32, impl FnOnce(&'? (i32, &'? str)) -> &'? i32>(&'? (i32, &'? str), impl FnOnce(&'? (i32, &'? str)) -> &'? i32) -> &'? i32
|
||||
142..168 'foo(&(...y)| x)': &'? i32
|
||||
146..155 '&(1, "a")': &'? (i32, &'static str)
|
||||
147..155 '(1, "a")': (i32, &'static str)
|
||||
148..149 '1': i32
|
||||
151..154 '"a"': &str
|
||||
157..167 '|(x, y)| x': impl FnOnce(&(i32, &str)) -> &i32
|
||||
158..164 '(x, y)': (i32, &str)
|
||||
159..160 'x': &i32
|
||||
162..163 'y': &&str
|
||||
166..167 'x': &i32
|
||||
151..154 '"a"': &'static str
|
||||
157..167 '|(x, y)| x': impl FnOnce(&'? (i32, &'? str)) -> &'? i32
|
||||
158..164 '(x, y)': (i32, &'? str)
|
||||
159..160 'x': &'? i32
|
||||
162..163 'y': &'? &'? str
|
||||
166..167 'x': &'? i32
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
@ -741,13 +741,13 @@ fn slice_tail_pattern() {
|
|||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
7..13 'params': &[i32]
|
||||
7..13 'params': &'? [i32]
|
||||
23..92 '{ ... } }': ()
|
||||
29..90 'match ... }': ()
|
||||
35..41 'params': &[i32]
|
||||
35..41 'params': &'? [i32]
|
||||
52..69 '[head,... @ ..]': [i32]
|
||||
53..57 'head': &i32
|
||||
59..68 'tail @ ..': &[i32]
|
||||
53..57 'head': &'? i32
|
||||
59..68 'tail @ ..': &'? [i32]
|
||||
66..68 '..': [i32]
|
||||
73..84 '{ }': ()
|
||||
"#]],
|
||||
|
@ -1109,7 +1109,7 @@ fn var_args() {
|
|||
#[lang = "va_list"]
|
||||
pub struct VaListImpl<'f>;
|
||||
fn my_fn(foo: ...) {}
|
||||
//^^^ VaListImpl<'{error}>
|
||||
//^^^ VaListImpl<'?>
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
@ -1122,9 +1122,9 @@ fn foo() {
|
|||
let &() = &();
|
||||
let &mut () = &mut ();
|
||||
let &mut () = &();
|
||||
//^^^^^^^ expected &(), got &mut ()
|
||||
//^^^^^^^ expected &'? (), got &'? mut ()
|
||||
let &() = &mut ();
|
||||
//^^^ expected &mut (), got &()
|
||||
//^^^ expected &'? mut (), got &'? ()
|
||||
}
|
||||
"#,
|
||||
);
|
||||
|
@ -1148,7 +1148,7 @@ fn main() {
|
|||
};
|
||||
|
||||
if let Wrap::<X>::A { cool, ..} = &wrapped {}
|
||||
//^^^^ &u32
|
||||
//^^^^ &'? u32
|
||||
}
|
||||
"#,
|
||||
);
|
||||
|
@ -1182,7 +1182,7 @@ fn main() {
|
|||
};
|
||||
|
||||
if let Wrap::<<S as Schematic>::Props>::A { cool, ..} = &wrapped {}
|
||||
//^^^^ &u32
|
||||
//^^^^ &'? u32
|
||||
}
|
||||
"#,
|
||||
);
|
||||
|
@ -1217,7 +1217,7 @@ fn main() {
|
|||
match &6 {
|
||||
Foo::<i32>::TEST_I32_REF => (),
|
||||
Foo::<i32>::TEST_I32 => (),
|
||||
//^^^^^^^^^^^^^^^^^^^^ expected &i32, got i32
|
||||
//^^^^^^^^^^^^^^^^^^^^ expected &'? i32, got i32
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -99,7 +99,7 @@ fn recursive_vars() {
|
|||
24..31 'unknown': {unknown}
|
||||
37..44 '[y, &y]': [{unknown}; 2]
|
||||
38..39 'y': {unknown}
|
||||
41..43 '&y': &{unknown}
|
||||
41..43 '&y': &'? {unknown}
|
||||
42..43 'y': {unknown}
|
||||
"#]],
|
||||
);
|
||||
|
@ -117,19 +117,19 @@ fn recursive_vars_2() {
|
|||
"#,
|
||||
expect![[r#"
|
||||
10..79 '{ ...x)]; }': ()
|
||||
20..21 'x': &{unknown}
|
||||
24..31 'unknown': &{unknown}
|
||||
20..21 'x': &'? {unknown}
|
||||
24..31 'unknown': &'? {unknown}
|
||||
41..42 'y': {unknown}
|
||||
45..52 'unknown': {unknown}
|
||||
58..76 '[(x, y..., &x)]': [(&{unknown}, {unknown}); 2]
|
||||
59..65 '(x, y)': (&{unknown}, {unknown})
|
||||
60..61 'x': &{unknown}
|
||||
58..76 '[(x, y..., &x)]': [(&'? {unknown}, {unknown}); 2]
|
||||
59..65 '(x, y)': (&'? {unknown}, {unknown})
|
||||
60..61 'x': &'? {unknown}
|
||||
63..64 'y': {unknown}
|
||||
67..75 '(&y, &x)': (&{unknown}, {unknown})
|
||||
68..70 '&y': &{unknown}
|
||||
67..75 '(&y, &x)': (&'? {unknown}, {unknown})
|
||||
68..70 '&y': &'? {unknown}
|
||||
69..70 'y': {unknown}
|
||||
72..74 '&x': &&{unknown}
|
||||
73..74 'x': &{unknown}
|
||||
72..74 '&x': &'? &'? {unknown}
|
||||
73..74 'x': &'? {unknown}
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
@ -166,7 +166,7 @@ fn infer_std_crash_1() {
|
|||
59..136 'match ... }': ()
|
||||
65..82 'someth...nknown': Maybe<{unknown}>
|
||||
93..123 'Maybe:...thing)': Maybe<{unknown}>
|
||||
105..122 'ref mu...ething': &mut {unknown}
|
||||
105..122 'ref mu...ething': &'? mut {unknown}
|
||||
127..129 '()': ()
|
||||
"#]],
|
||||
);
|
||||
|
@ -183,7 +183,7 @@ fn infer_std_crash_2() {
|
|||
"#,
|
||||
expect![[r#"
|
||||
22..52 '{ ...n']; }': ()
|
||||
28..49 '&[0, b...b'\n']': &[u8; 4]
|
||||
28..49 '&[0, b...b'\n']': &'? [u8; 4]
|
||||
29..49 '[0, b'...b'\n']': [u8; 4]
|
||||
30..31 '0': u8
|
||||
33..38 'b'\n'': u8
|
||||
|
@ -269,8 +269,8 @@ fn infer_std_crash_5() {
|
|||
32..320 'for co... }': {unknown}
|
||||
32..320 'for co... }': !
|
||||
32..320 'for co... }': {unknown}
|
||||
32..320 'for co... }': &mut {unknown}
|
||||
32..320 'for co... }': fn next<{unknown}>(&mut {unknown}) -> Option<<{unknown} as Iterator>::Item>
|
||||
32..320 'for co... }': &'? mut {unknown}
|
||||
32..320 'for co... }': fn next<{unknown}>(&'? mut {unknown}) -> Option<<{unknown} as Iterator>::Item>
|
||||
32..320 'for co... }': Option<{unknown}>
|
||||
32..320 'for co... }': ()
|
||||
32..320 'for co... }': ()
|
||||
|
@ -278,22 +278,22 @@ fn infer_std_crash_5() {
|
|||
36..43 'content': {unknown}
|
||||
47..60 'doesnt_matter': {unknown}
|
||||
61..320 '{ ... }': ()
|
||||
75..79 'name': &{unknown}
|
||||
82..166 'if doe... }': &{unknown}
|
||||
75..79 'name': &'? {unknown}
|
||||
82..166 'if doe... }': &'? {unknown}
|
||||
85..98 'doesnt_matter': bool
|
||||
99..128 '{ ... }': &{unknown}
|
||||
113..118 'first': &{unknown}
|
||||
134..166 '{ ... }': &{unknown}
|
||||
148..156 '&content': &{unknown}
|
||||
99..128 '{ ... }': &'? {unknown}
|
||||
113..118 'first': &'? {unknown}
|
||||
134..166 '{ ... }': &'? {unknown}
|
||||
148..156 '&content': &'? {unknown}
|
||||
149..156 'content': {unknown}
|
||||
181..188 'content': &{unknown}
|
||||
191..313 'if ICE... }': &{unknown}
|
||||
181..188 'content': &'? {unknown}
|
||||
191..313 'if ICE... }': &'? {unknown}
|
||||
194..231 'ICE_RE..._VALUE': {unknown}
|
||||
194..247 'ICE_RE...&name)': bool
|
||||
241..246 '&name': &&{unknown}
|
||||
242..246 'name': &{unknown}
|
||||
248..276 '{ ... }': &{unknown}
|
||||
262..266 'name': &{unknown}
|
||||
241..246 '&name': &'? &'? {unknown}
|
||||
242..246 'name': &'? {unknown}
|
||||
248..276 '{ ... }': &'? {unknown}
|
||||
262..266 'name': &'? {unknown}
|
||||
282..313 '{ ... }': {unknown}
|
||||
296..303 'content': {unknown}
|
||||
"#]],
|
||||
|
@ -318,7 +318,7 @@ fn infer_nested_generics_crash() {
|
|||
expect![[r#"
|
||||
91..105 'query_response': Canonical<QueryResponse<R>>
|
||||
136..166 '{ ...lue; }': ()
|
||||
142..163 '&query....value': &QueryResponse<R>
|
||||
142..163 '&query....value': &'? QueryResponse<R>
|
||||
143..157 'query_response': Canonical<QueryResponse<R>>
|
||||
143..163 'query_....value': QueryResponse<R>
|
||||
"#]],
|
||||
|
@ -465,12 +465,12 @@ fn issue_3999_slice() {
|
|||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
7..13 'params': &[usize]
|
||||
7..13 'params': &'? [usize]
|
||||
25..80 '{ ... } }': ()
|
||||
31..78 'match ... }': ()
|
||||
37..43 'params': &[usize]
|
||||
37..43 'params': &'? [usize]
|
||||
54..66 '[ps @ .., _]': [usize]
|
||||
55..62 'ps @ ..': &[usize]
|
||||
55..62 'ps @ ..': &'? [usize]
|
||||
60..62 '..': [usize]
|
||||
64..65 '_': usize
|
||||
70..72 '{}': ()
|
||||
|
@ -523,13 +523,13 @@ fn issue_4235_name_conflicts() {
|
|||
"#,
|
||||
expect![[r#"
|
||||
31..37 'FOO {}': FOO
|
||||
63..67 'self': &FOO
|
||||
63..67 'self': &'? FOO
|
||||
69..71 '{}': ()
|
||||
85..119 '{ ...o(); }': ()
|
||||
95..96 'a': &FOO
|
||||
99..103 '&FOO': &FOO
|
||||
95..96 'a': &'? FOO
|
||||
99..103 '&FOO': &'? FOO
|
||||
100..103 'FOO': FOO
|
||||
109..110 'a': &FOO
|
||||
109..110 'a': &'? FOO
|
||||
109..116 'a.foo()': ()
|
||||
"#]],
|
||||
);
|
||||
|
@ -715,12 +715,12 @@ fn issue_4885() {
|
|||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
70..73 'key': &K
|
||||
70..73 'key': &'? K
|
||||
132..148 '{ ...key) }': impl Future<Output = <K as Foo<R>>::Bar>
|
||||
138..141 'bar': fn bar<R, K>(&K) -> impl Future<Output = <K as Foo<R>>::Bar>
|
||||
138..141 'bar': fn bar<R, K>(&'? K) -> impl Future<Output = <K as Foo<R>>::Bar>
|
||||
138..146 'bar(key)': impl Future<Output = <K as Foo<R>>::Bar>
|
||||
142..145 'key': &K
|
||||
162..165 'key': &K
|
||||
142..145 'key': &'? K
|
||||
162..165 'key': &'? K
|
||||
224..227 '{ }': ()
|
||||
"#]],
|
||||
);
|
||||
|
@ -771,11 +771,11 @@ fn issue_4800() {
|
|||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
379..383 'self': &mut PeerSet<D>
|
||||
379..383 'self': &'? mut PeerSet<D>
|
||||
401..424 '{ ... }': dyn Future<Output = ()>
|
||||
411..418 'loop {}': !
|
||||
416..418 '{}': ()
|
||||
575..579 'self': &mut Self
|
||||
575..579 'self': &'? mut Self
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
@ -815,19 +815,19 @@ fn issue_4966() {
|
|||
225..229 'iter': T
|
||||
244..246 '{}': Vec<A>
|
||||
258..402 '{ ...r(); }': ()
|
||||
268..273 'inner': Map<impl Fn(&f64) -> f64>
|
||||
276..300 'Map { ... 0.0 }': Map<impl Fn(&f64) -> f64>
|
||||
285..298 '|_: &f64| 0.0': impl Fn(&f64) -> f64
|
||||
286..287 '_': &f64
|
||||
268..273 'inner': Map<impl Fn(&'? f64) -> f64>
|
||||
276..300 'Map { ... 0.0 }': Map<impl Fn(&'? f64) -> f64>
|
||||
285..298 '|_: &f64| 0.0': impl Fn(&'? f64) -> f64
|
||||
286..287 '_': &'? f64
|
||||
295..298 '0.0': f64
|
||||
311..317 'repeat': Repeat<Map<impl Fn(&f64) -> f64>>
|
||||
320..345 'Repeat...nner }': Repeat<Map<impl Fn(&f64) -> f64>>
|
||||
338..343 'inner': Map<impl Fn(&f64) -> f64>
|
||||
356..359 'vec': Vec<IntoIterator::Item<Repeat<Map<impl Fn(&f64) -> f64>>>>
|
||||
362..371 'from_iter': fn from_iter<IntoIterator::Item<Repeat<Map<impl Fn(&f64) -> f64>>>, Repeat<Map<impl Fn(&f64) -> f64>>>(Repeat<Map<impl Fn(&f64) -> f64>>) -> Vec<IntoIterator::Item<Repeat<Map<impl Fn(&f64) -> f64>>>>
|
||||
362..379 'from_i...epeat)': Vec<IntoIterator::Item<Repeat<Map<impl Fn(&f64) -> f64>>>>
|
||||
372..378 'repeat': Repeat<Map<impl Fn(&f64) -> f64>>
|
||||
386..389 'vec': Vec<IntoIterator::Item<Repeat<Map<impl Fn(&f64) -> f64>>>>
|
||||
311..317 'repeat': Repeat<Map<impl Fn(&'? f64) -> f64>>
|
||||
320..345 'Repeat...nner }': Repeat<Map<impl Fn(&'? f64) -> f64>>
|
||||
338..343 'inner': Map<impl Fn(&'? f64) -> f64>
|
||||
356..359 'vec': Vec<IntoIterator::Item<Repeat<Map<impl Fn(&'? f64) -> f64>>>>
|
||||
362..371 'from_iter': fn from_iter<IntoIterator::Item<Repeat<Map<impl Fn(&'? f64) -> f64>>>, Repeat<Map<impl Fn(&'? f64) -> f64>>>(Repeat<Map<impl Fn(&'? f64) -> f64>>) -> Vec<IntoIterator::Item<Repeat<Map<impl Fn(&'? f64) -> f64>>>>
|
||||
362..379 'from_i...epeat)': Vec<IntoIterator::Item<Repeat<Map<impl Fn(&'? f64) -> f64>>>>
|
||||
372..378 'repeat': Repeat<Map<impl Fn(&'? f64) -> f64>>
|
||||
386..389 'vec': Vec<IntoIterator::Item<Repeat<Map<impl Fn(&'? f64) -> f64>>>>
|
||||
386..399 'vec.foo_bar()': {unknown}
|
||||
"#]],
|
||||
);
|
||||
|
@ -850,10 +850,10 @@ fn main() {
|
|||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
40..44 'self': &S<T>
|
||||
40..44 'self': &'? S<T>
|
||||
46..48 '_t': T
|
||||
53..55 '{}': ()
|
||||
81..85 'self': &S<T>
|
||||
81..85 'self': &'? S<T>
|
||||
87..89 '_f': F
|
||||
94..96 '{}': ()
|
||||
109..160 '{ ...10); }': ()
|
||||
|
@ -862,8 +862,8 @@ fn main() {
|
|||
123..126 'S()': S<i32>
|
||||
132..133 's': S<i32>
|
||||
132..144 's.g(|_x| {})': ()
|
||||
136..143 '|_x| {}': impl FnOnce(&i32)
|
||||
137..139 '_x': &i32
|
||||
136..143 '|_x| {}': impl FnOnce(&'? i32)
|
||||
137..139 '_x': &'? i32
|
||||
141..143 '{}': ()
|
||||
150..151 's': S<i32>
|
||||
150..157 's.f(10)': ()
|
||||
|
@ -895,14 +895,14 @@ fn flush(&self) {
|
|||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
123..127 'self': &Mutex<T>
|
||||
150..152 '{}': MutexGuard<'{error}, T>
|
||||
234..238 'self': &{unknown}
|
||||
123..127 'self': &'? Mutex<T>
|
||||
150..152 '{}': MutexGuard<'?, T>
|
||||
234..238 'self': &'? {unknown}
|
||||
240..290 '{ ...()); }': ()
|
||||
250..251 'w': &Mutex<BufWriter>
|
||||
250..251 'w': &'? Mutex<BufWriter>
|
||||
276..287 '*(w.lock())': BufWriter
|
||||
278..279 'w': &Mutex<BufWriter>
|
||||
278..286 'w.lock()': MutexGuard<'{error}, BufWriter>
|
||||
278..279 'w': &'? Mutex<BufWriter>
|
||||
278..286 'w.lock()': MutexGuard<'?, BufWriter>
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
@ -1023,20 +1023,20 @@ fn cfg_tail() {
|
|||
expect![[r#"
|
||||
14..53 '{ ...)] 9 }': ()
|
||||
20..31 '{ "first" }': ()
|
||||
22..29 '"first"': &str
|
||||
22..29 '"first"': &'static str
|
||||
72..190 '{ ...] 13 }': ()
|
||||
78..88 '{ "fake" }': ()
|
||||
80..86 '"fake"': &str
|
||||
80..86 '"fake"': &'static str
|
||||
93..103 '{ "fake" }': ()
|
||||
95..101 '"fake"': &str
|
||||
95..101 '"fake"': &'static str
|
||||
108..120 '{ "second" }': ()
|
||||
110..118 '"second"': &str
|
||||
110..118 '"second"': &'static str
|
||||
210..273 '{ ... 15; }': ()
|
||||
216..227 '{ "third" }': ()
|
||||
218..225 '"third"': &str
|
||||
218..225 '"third"': &'static str
|
||||
293..357 '{ ...] 15 }': ()
|
||||
299..311 '{ "fourth" }': &str
|
||||
301..309 '"fourth"': &str
|
||||
299..311 '{ "fourth" }': &'static str
|
||||
301..309 '"fourth"': &'static str
|
||||
"#]],
|
||||
)
|
||||
}
|
||||
|
@ -1238,8 +1238,8 @@ fn test() {
|
|||
16..66 'for _ ... }': IntoIterator::IntoIter<()>
|
||||
16..66 'for _ ... }': !
|
||||
16..66 'for _ ... }': IntoIterator::IntoIter<()>
|
||||
16..66 'for _ ... }': &mut IntoIterator::IntoIter<()>
|
||||
16..66 'for _ ... }': fn next<IntoIterator::IntoIter<()>>(&mut IntoIterator::IntoIter<()>) -> Option<<IntoIterator::IntoIter<()> as Iterator>::Item>
|
||||
16..66 'for _ ... }': &'? mut IntoIterator::IntoIter<()>
|
||||
16..66 'for _ ... }': fn next<IntoIterator::IntoIter<()>>(&'? mut IntoIterator::IntoIter<()>) -> Option<<IntoIterator::IntoIter<()> as Iterator>::Item>
|
||||
16..66 'for _ ... }': Option<IntoIterator::Item<()>>
|
||||
16..66 'for _ ... }': ()
|
||||
16..66 'for _ ... }': ()
|
||||
|
@ -1599,85 +1599,6 @@ fn f(s: S) {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rust_161_option_clone() {
|
||||
check_types(
|
||||
r#"
|
||||
//- minicore: option, drop
|
||||
|
||||
fn test(o: &Option<i32>) {
|
||||
o.my_clone();
|
||||
//^^^^^^^^^^^^ Option<i32>
|
||||
}
|
||||
|
||||
pub trait MyClone: Sized {
|
||||
fn my_clone(&self) -> Self;
|
||||
}
|
||||
|
||||
impl<T> const MyClone for Option<T>
|
||||
where
|
||||
T: ~const MyClone + ~const Drop + ~const Destruct,
|
||||
{
|
||||
fn my_clone(&self) -> Self {
|
||||
match self {
|
||||
Some(x) => Some(x.my_clone()),
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl const MyClone for i32 {
|
||||
fn my_clone(&self) -> Self {
|
||||
*self
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Destruct {}
|
||||
|
||||
impl<T: ?Sized> const Destruct for T {}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rust_162_option_clone() {
|
||||
check_types(
|
||||
r#"
|
||||
//- minicore: option, drop
|
||||
|
||||
fn test(o: &Option<i32>) {
|
||||
o.my_clone();
|
||||
//^^^^^^^^^^^^ Option<i32>
|
||||
}
|
||||
|
||||
pub trait MyClone: Sized {
|
||||
fn my_clone(&self) -> Self;
|
||||
}
|
||||
|
||||
impl<T> const MyClone for Option<T>
|
||||
where
|
||||
T: ~const MyClone + ~const Destruct,
|
||||
{
|
||||
fn my_clone(&self) -> Self {
|
||||
match self {
|
||||
Some(x) => Some(x.my_clone()),
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl const MyClone for i32 {
|
||||
fn my_clone(&self) -> Self {
|
||||
*self
|
||||
}
|
||||
}
|
||||
|
||||
#[lang = "destruct"]
|
||||
pub trait Destruct {}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tuple_struct_pattern_with_unmatched_args_crash() {
|
||||
check_infer(
|
||||
|
@ -1727,7 +1648,7 @@ fn dyn_with_unresolved_trait() {
|
|||
r#"
|
||||
fn foo(a: &dyn DoesNotExist) {
|
||||
a.bar();
|
||||
//^&{unknown}
|
||||
//^&'? {unknown}
|
||||
}
|
||||
"#,
|
||||
);
|
||||
|
@ -1851,9 +1772,9 @@ fn foo() {
|
|||
match &E::A {
|
||||
b @ (x @ E::A | x) => {
|
||||
b;
|
||||
//^ &E
|
||||
//^ &'? E
|
||||
x;
|
||||
//^ &E
|
||||
//^ &'? E
|
||||
}
|
||||
}
|
||||
}",
|
||||
|
@ -2040,3 +1961,41 @@ fn main() {
|
|||
"#,
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cfg_first_trait_param_16141() {
|
||||
check_no_mismatches(
|
||||
r#"
|
||||
//- minicore: sized, coerce_unsized
|
||||
trait Bar {
|
||||
fn bar(&self) {}
|
||||
}
|
||||
|
||||
impl<#[cfg(feature = "a-feature")] A> Bar for (){}
|
||||
"#,
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn nested_anon_generics_and_where_bounds_17173() {
|
||||
check_types(
|
||||
r#"
|
||||
//- minicore: sized, fn
|
||||
pub trait Lookup {
|
||||
type Data;
|
||||
fn lookup(&self) -> Self::Data;
|
||||
}
|
||||
pub trait ItemTreeLoc {
|
||||
type Id;
|
||||
}
|
||||
fn id_to_generics(id: impl Lookup<Data = impl ItemTreeLoc<Id = ()>>,
|
||||
//^^ impl Lookup<Data = impl ItemTreeLoc<Id = ()>>
|
||||
enabled_params: impl Fn(),
|
||||
//^^^^^^^^^^^^^^ impl Fn()
|
||||
)
|
||||
where
|
||||
(): Sized,
|
||||
{}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -115,15 +115,15 @@ fn test(a: u32, b: isize, c: !, d: &str) {
|
|||
8..9 'a': u32
|
||||
16..17 'b': isize
|
||||
26..27 'c': !
|
||||
32..33 'd': &str
|
||||
32..33 'd': &'? str
|
||||
41..120 '{ ...f32; }': ()
|
||||
47..48 'a': u32
|
||||
54..55 'b': isize
|
||||
61..62 'c': !
|
||||
68..69 'd': &str
|
||||
68..69 'd': &'? str
|
||||
75..81 '1usize': usize
|
||||
87..93 '1isize': isize
|
||||
99..105 '"test"': &str
|
||||
99..105 '"test"': &'static str
|
||||
111..117 '1.0f32': f32
|
||||
"#]],
|
||||
);
|
||||
|
@ -344,23 +344,23 @@ fn test(a: &u32, b: &mut u32, c: *const u32, d: *mut u32) {
|
|||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
8..9 'a': &u32
|
||||
17..18 'b': &mut u32
|
||||
8..9 'a': &'? u32
|
||||
17..18 'b': &'? mut u32
|
||||
30..31 'c': *const u32
|
||||
45..46 'd': *mut u32
|
||||
58..149 '{ ... *d; }': ()
|
||||
64..65 'a': &u32
|
||||
64..65 'a': &'? u32
|
||||
71..73 '*a': u32
|
||||
72..73 'a': &u32
|
||||
79..81 '&a': &&u32
|
||||
80..81 'a': &u32
|
||||
87..93 '&mut a': &mut &u32
|
||||
92..93 'a': &u32
|
||||
99..100 'b': &mut u32
|
||||
72..73 'a': &'? u32
|
||||
79..81 '&a': &'? &'? u32
|
||||
80..81 'a': &'? u32
|
||||
87..93 '&mut a': &'? mut &'? u32
|
||||
92..93 'a': &'? u32
|
||||
99..100 'b': &'? mut u32
|
||||
106..108 '*b': u32
|
||||
107..108 'b': &mut u32
|
||||
114..116 '&b': &&mut u32
|
||||
115..116 'b': &mut u32
|
||||
107..108 'b': &'? mut u32
|
||||
114..116 '&b': &'? &'? mut u32
|
||||
115..116 'b': &'? mut u32
|
||||
122..123 'c': *const u32
|
||||
129..131 '*c': u32
|
||||
130..131 'c': *const u32
|
||||
|
@ -425,22 +425,22 @@ h";
|
|||
32..36 '5i32': i32
|
||||
50..54 '5f32': f32
|
||||
68..72 '5f64': f64
|
||||
86..93 '"hello"': &str
|
||||
107..115 'b"bytes"': &[u8; 5]
|
||||
86..93 '"hello"': &'static str
|
||||
107..115 'b"bytes"': &'static [u8; 5]
|
||||
129..132 ''c'': char
|
||||
146..150 'b'b'': u8
|
||||
164..168 '3.14': f64
|
||||
182..186 '5000': i32
|
||||
200..205 'false': bool
|
||||
219..223 'true': bool
|
||||
237..333 'r#" ... "#': &str
|
||||
347..357 'br#"yolo"#': &[u8; 4]
|
||||
375..376 'a': &[u8; 4]
|
||||
379..403 'b"a\x2... c"': &[u8; 4]
|
||||
421..422 'b': &[u8; 4]
|
||||
425..433 'br"g\ h"': &[u8; 4]
|
||||
451..452 'c': &[u8; 6]
|
||||
455..467 'br#"x"\"yb"#': &[u8; 6]
|
||||
237..333 'r#" ... "#': &'static str
|
||||
347..357 'br#"yolo"#': &'static [u8; 4]
|
||||
375..376 'a': &'static [u8; 4]
|
||||
379..403 'b"a\x2... c"': &'static [u8; 4]
|
||||
421..422 'b': &'static [u8; 4]
|
||||
425..433 'br"g\ h"': &'static [u8; 4]
|
||||
451..452 'c': &'static [u8; 6]
|
||||
455..467 'br#"x"\"yb"#': &'static [u8; 6]
|
||||
"##]],
|
||||
);
|
||||
}
|
||||
|
@ -508,9 +508,9 @@ fn test(x: SomeType) {
|
|||
238..240 '!x': {unknown}
|
||||
239..240 'x': SomeType
|
||||
246..254 '-"hello"': {unknown}
|
||||
247..254 '"hello"': &str
|
||||
247..254 '"hello"': &'static str
|
||||
260..268 '!"hello"': {unknown}
|
||||
261..268 '"hello"': &str
|
||||
261..268 '"hello"': &'static str
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
@ -535,7 +535,7 @@ fn test() -> &mut &f64 {
|
|||
expect![[r#"
|
||||
13..14 'x': u32
|
||||
21..23 '{}': ()
|
||||
77..230 '{ ...t &c }': &mut &f64
|
||||
77..230 '{ ...t &c }': &'? mut &'? f64
|
||||
87..88 'a': u32
|
||||
91..107 'unknow...nction': {unknown}
|
||||
91..109 'unknow...tion()': u32
|
||||
|
@ -550,8 +550,8 @@ fn test() -> &mut &f64 {
|
|||
193..194 'c': f64
|
||||
197..213 'unknow...nction': {unknown}
|
||||
197..215 'unknow...tion()': f64
|
||||
221..228 '&mut &c': &mut &f64
|
||||
226..228 '&c': &f64
|
||||
221..228 '&mut &c': &'? mut &'? f64
|
||||
226..228 '&c': &'? f64
|
||||
227..228 'c': f64
|
||||
"#]],
|
||||
);
|
||||
|
@ -579,12 +579,12 @@ impl S {
|
|||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
33..37 'self': &S
|
||||
33..37 'self': &'? S
|
||||
39..60 '{ ... }': ()
|
||||
49..53 'self': &S
|
||||
74..78 'self': &S
|
||||
49..53 'self': &'? S
|
||||
74..78 'self': &'? S
|
||||
87..108 '{ ... }': ()
|
||||
97..101 'self': &S
|
||||
97..101 'self': &'? S
|
||||
132..152 '{ ... }': S
|
||||
142..146 'S {}': S
|
||||
176..199 '{ ... }': S
|
||||
|
@ -771,35 +771,35 @@ fn test2(a1: *const A, a2: *mut A) {
|
|||
64..65 'a': A
|
||||
71..73 'a1': A
|
||||
71..75 'a1.b': B
|
||||
85..87 'a2': &A
|
||||
90..92 '&a': &A
|
||||
85..87 'a2': &'? A
|
||||
90..92 '&a': &'? A
|
||||
91..92 'a': A
|
||||
98..100 'a2': &A
|
||||
98..100 'a2': &'? A
|
||||
98..102 'a2.b': B
|
||||
112..114 'a3': &mut A
|
||||
117..123 '&mut a': &mut A
|
||||
112..114 'a3': &'? mut A
|
||||
117..123 '&mut a': &'? mut A
|
||||
122..123 'a': A
|
||||
129..131 'a3': &mut A
|
||||
129..131 'a3': &'? mut A
|
||||
129..133 'a3.b': B
|
||||
143..145 'a4': &&&&&&&A
|
||||
148..156 '&&&&&&&a': &&&&&&&A
|
||||
149..156 '&&&&&&a': &&&&&&A
|
||||
150..156 '&&&&&a': &&&&&A
|
||||
151..156 '&&&&a': &&&&A
|
||||
152..156 '&&&a': &&&A
|
||||
153..156 '&&a': &&A
|
||||
154..156 '&a': &A
|
||||
143..145 'a4': &'? &'? &'? &'? &'? &'? &'? A
|
||||
148..156 '&&&&&&&a': &'? &'? &'? &'? &'? &'? &'? A
|
||||
149..156 '&&&&&&a': &'? &'? &'? &'? &'? &'? A
|
||||
150..156 '&&&&&a': &'? &'? &'? &'? &'? A
|
||||
151..156 '&&&&a': &'? &'? &'? &'? A
|
||||
152..156 '&&&a': &'? &'? &'? A
|
||||
153..156 '&&a': &'? &'? A
|
||||
154..156 '&a': &'? A
|
||||
155..156 'a': A
|
||||
162..164 'a4': &&&&&&&A
|
||||
162..164 'a4': &'? &'? &'? &'? &'? &'? &'? A
|
||||
162..166 'a4.b': B
|
||||
176..178 'a5': &mut &&mut &&mut A
|
||||
181..199 '&mut &...&mut a': &mut &&mut &&mut A
|
||||
186..199 '&&mut &&mut a': &&mut &&mut A
|
||||
187..199 '&mut &&mut a': &mut &&mut A
|
||||
192..199 '&&mut a': &&mut A
|
||||
193..199 '&mut a': &mut A
|
||||
176..178 'a5': &'? mut &'? &'? mut &'? &'? mut A
|
||||
181..199 '&mut &...&mut a': &'? mut &'? &'? mut &'? &'? mut A
|
||||
186..199 '&&mut &&mut a': &'? &'? mut &'? &'? mut A
|
||||
187..199 '&mut &&mut a': &'? mut &'? &'? mut A
|
||||
192..199 '&&mut a': &'? &'? mut A
|
||||
193..199 '&mut a': &'? mut A
|
||||
198..199 'a': A
|
||||
205..207 'a5': &mut &&mut &&mut A
|
||||
205..207 'a5': &'? mut &'? &'? mut &'? &'? mut A
|
||||
205..209 'a5.b': B
|
||||
223..225 'a1': *const A
|
||||
237..239 'a2': *mut A
|
||||
|
@ -840,22 +840,22 @@ fn test() {
|
|||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
66..70 'self': &A<T>
|
||||
78..101 '{ ... }': &T
|
||||
88..95 '&self.0': &T
|
||||
89..93 'self': &A<T>
|
||||
66..70 'self': &'? A<T>
|
||||
78..101 '{ ... }': &'? T
|
||||
88..95 '&self.0': &'? T
|
||||
89..93 'self': &'? A<T>
|
||||
89..95 'self.0': T
|
||||
182..186 'self': &B<T>
|
||||
205..228 '{ ... }': &T
|
||||
215..222 '&self.0': &T
|
||||
216..220 'self': &B<T>
|
||||
182..186 'self': &'? B<T>
|
||||
205..228 '{ ... }': &'? T
|
||||
215..222 '&self.0': &'? T
|
||||
216..220 'self': &'? B<T>
|
||||
216..222 'self.0': T
|
||||
242..280 '{ ...))); }': ()
|
||||
252..253 't': &i32
|
||||
256..262 'A::foo': fn foo<i32>(&A<i32>) -> &i32
|
||||
256..277 'A::foo...42))))': &i32
|
||||
263..276 '&&B(B(A(42)))': &&B<B<A<i32>>>
|
||||
264..276 '&B(B(A(42)))': &B<B<A<i32>>>
|
||||
252..253 't': &'? i32
|
||||
256..262 'A::foo': fn foo<i32>(&'? A<i32>) -> &'? i32
|
||||
256..277 'A::foo...42))))': &'? i32
|
||||
263..276 '&&B(B(A(42)))': &'? &'? B<B<A<i32>>>
|
||||
264..276 '&B(B(A(42)))': &'? B<B<A<i32>>>
|
||||
265..266 'B': extern "rust-call" B<B<A<i32>>>(B<A<i32>>) -> B<B<A<i32>>>
|
||||
265..276 'B(B(A(42)))': B<B<A<i32>>>
|
||||
267..268 'B': extern "rust-call" B<A<i32>>(A<i32>) -> B<A<i32>>
|
||||
|
@ -895,28 +895,28 @@ fn test(a: A<i32>) {
|
|||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
71..75 'self': &A<T>
|
||||
77..78 'x': &A<T>
|
||||
93..114 '{ ... }': &T
|
||||
103..108 '&*x.0': &T
|
||||
71..75 'self': &'? A<T>
|
||||
77..78 'x': &'? A<T>
|
||||
93..114 '{ ... }': &'? T
|
||||
103..108 '&*x.0': &'? T
|
||||
104..108 '*x.0': T
|
||||
105..106 'x': &A<T>
|
||||
105..106 'x': &'? A<T>
|
||||
105..108 'x.0': *mut T
|
||||
195..199 'self': &B<T>
|
||||
218..241 '{ ... }': &T
|
||||
228..235 '&self.0': &T
|
||||
229..233 'self': &B<T>
|
||||
195..199 'self': &'? B<T>
|
||||
218..241 '{ ... }': &'? T
|
||||
228..235 '&self.0': &'? T
|
||||
229..233 'self': &'? B<T>
|
||||
229..235 'self.0': T
|
||||
253..254 'a': A<i32>
|
||||
264..310 '{ ...))); }': ()
|
||||
274..275 't': &i32
|
||||
274..275 't': &'? i32
|
||||
278..279 'A': extern "rust-call" A<i32>(*mut i32) -> A<i32>
|
||||
278..292 'A(0 as *mut _)': A<i32>
|
||||
278..307 'A(0 as...B(a)))': &i32
|
||||
278..307 'A(0 as...B(a)))': &'? i32
|
||||
280..281 '0': i32
|
||||
280..291 '0 as *mut _': *mut i32
|
||||
297..306 '&&B(B(a))': &&B<B<A<i32>>>
|
||||
298..306 '&B(B(a))': &B<B<A<i32>>>
|
||||
297..306 '&&B(B(a))': &'? &'? B<B<A<i32>>>
|
||||
298..306 '&B(B(a))': &'? B<B<A<i32>>>
|
||||
299..300 'B': extern "rust-call" B<B<A<i32>>>(B<A<i32>>) -> B<B<A<i32>>>
|
||||
299..306 'B(B(a))': B<B<A<i32>>>
|
||||
301..302 'B': extern "rust-call" B<A<i32>>(A<i32>) -> B<A<i32>>
|
||||
|
@ -1044,7 +1044,7 @@ fn infer_inherent_method() {
|
|||
31..35 'self': A
|
||||
37..38 'x': u32
|
||||
52..54 '{}': i32
|
||||
106..110 'self': &A
|
||||
106..110 'self': &'? A
|
||||
112..113 'x': u64
|
||||
127..129 '{}': i64
|
||||
147..148 'a': A
|
||||
|
@ -1053,7 +1053,7 @@ fn infer_inherent_method() {
|
|||
159..167 'a.foo(1)': i32
|
||||
165..166 '1': u32
|
||||
173..184 '(&a).bar(1)': i64
|
||||
174..176 '&a': &A
|
||||
174..176 '&a': &'? A
|
||||
175..176 'a': A
|
||||
182..183 '1': u64
|
||||
190..191 'a': A
|
||||
|
@ -1078,10 +1078,10 @@ fn test() {
|
|||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
67..71 'self': &str
|
||||
67..71 'self': &'? str
|
||||
80..82 '{}': i32
|
||||
96..116 '{ ...o(); }': ()
|
||||
102..107 '"foo"': &str
|
||||
102..107 '"foo"': &'static str
|
||||
102..113 '"foo".foo()': i32
|
||||
"#]],
|
||||
);
|
||||
|
@ -1101,33 +1101,33 @@ fn infer_tuple() {
|
|||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
8..9 'x': &str
|
||||
8..9 'x': &'? str
|
||||
17..18 'y': isize
|
||||
27..169 '{ ...d"); }': ()
|
||||
37..38 'a': (u32, &str)
|
||||
54..62 '(1, "a")': (u32, &str)
|
||||
37..38 'a': (u32, &'? str)
|
||||
54..62 '(1, "a")': (u32, &'? str)
|
||||
55..56 '1': u32
|
||||
58..61 '"a"': &str
|
||||
72..73 'b': ((u32, &str), &str)
|
||||
76..82 '(a, x)': ((u32, &str), &str)
|
||||
77..78 'a': (u32, &str)
|
||||
80..81 'x': &str
|
||||
92..93 'c': (isize, &str)
|
||||
96..102 '(y, x)': (isize, &str)
|
||||
58..61 '"a"': &'static str
|
||||
72..73 'b': ((u32, &'? str), &'? str)
|
||||
76..82 '(a, x)': ((u32, &'? str), &'? str)
|
||||
77..78 'a': (u32, &'? str)
|
||||
80..81 'x': &'? str
|
||||
92..93 'c': (isize, &'? str)
|
||||
96..102 '(y, x)': (isize, &'? str)
|
||||
97..98 'y': isize
|
||||
100..101 'x': &str
|
||||
112..113 'd': ((isize, &str), &str)
|
||||
116..122 '(c, x)': ((isize, &str), &str)
|
||||
117..118 'c': (isize, &str)
|
||||
120..121 'x': &str
|
||||
132..133 'e': (i32, &str)
|
||||
136..144 '(1, "e")': (i32, &str)
|
||||
100..101 'x': &'? str
|
||||
112..113 'd': ((isize, &'? str), &'? str)
|
||||
116..122 '(c, x)': ((isize, &'? str), &'? str)
|
||||
117..118 'c': (isize, &'? str)
|
||||
120..121 'x': &'? str
|
||||
132..133 'e': (i32, &'static str)
|
||||
136..144 '(1, "e")': (i32, &'static str)
|
||||
137..138 '1': i32
|
||||
140..143 '"e"': &str
|
||||
154..155 'f': ((i32, &str), &str)
|
||||
158..166 '(e, "d")': ((i32, &str), &str)
|
||||
159..160 'e': (i32, &str)
|
||||
162..165 '"d"': &str
|
||||
140..143 '"e"': &'static str
|
||||
154..155 'f': ((i32, &'static str), &'static str)
|
||||
158..166 '(e, "d")': ((i32, &'static str), &'static str)
|
||||
159..160 'e': (i32, &'static str)
|
||||
162..165 '"d"': &'static str
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
@ -1156,20 +1156,20 @@ fn infer_array() {
|
|||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
8..9 'x': &str
|
||||
8..9 'x': &'? str
|
||||
17..18 'y': isize
|
||||
27..326 '{ ...,4]; }': ()
|
||||
37..38 'a': [&str; 1]
|
||||
41..44 '[x]': [&str; 1]
|
||||
42..43 'x': &str
|
||||
54..55 'b': [[&str; 1]; 2]
|
||||
58..64 '[a, a]': [[&str; 1]; 2]
|
||||
59..60 'a': [&str; 1]
|
||||
62..63 'a': [&str; 1]
|
||||
74..75 'c': [[[&str; 1]; 2]; 2]
|
||||
78..84 '[b, b]': [[[&str; 1]; 2]; 2]
|
||||
79..80 'b': [[&str; 1]; 2]
|
||||
82..83 'b': [[&str; 1]; 2]
|
||||
37..38 'a': [&'? str; 1]
|
||||
41..44 '[x]': [&'? str; 1]
|
||||
42..43 'x': &'? str
|
||||
54..55 'b': [[&'? str; 1]; 2]
|
||||
58..64 '[a, a]': [[&'? str; 1]; 2]
|
||||
59..60 'a': [&'? str; 1]
|
||||
62..63 'a': [&'? str; 1]
|
||||
74..75 'c': [[[&'? str; 1]; 2]; 2]
|
||||
78..84 '[b, b]': [[[&'? str; 1]; 2]; 2]
|
||||
79..80 'b': [[&'? str; 1]; 2]
|
||||
82..83 'b': [[&'? str; 1]; 2]
|
||||
95..96 'd': [isize; 4]
|
||||
99..111 '[y, 1, 2, 3]': [isize; 4]
|
||||
100..101 'y': isize
|
||||
|
@ -1197,15 +1197,15 @@ fn infer_array() {
|
|||
209..215 '[1, 2]': [i32; 2]
|
||||
210..211 '1': i32
|
||||
213..214 '2': i32
|
||||
225..226 'i': [&str; 2]
|
||||
229..239 '["a", "b"]': [&str; 2]
|
||||
230..233 '"a"': &str
|
||||
235..238 '"b"': &str
|
||||
250..251 'b': [[&str; 1]; 2]
|
||||
254..264 '[a, ["b"]]': [[&str; 1]; 2]
|
||||
255..256 'a': [&str; 1]
|
||||
258..263 '["b"]': [&str; 1]
|
||||
259..262 '"b"': &str
|
||||
225..226 'i': [&'? str; 2]
|
||||
229..239 '["a", "b"]': [&'? str; 2]
|
||||
230..233 '"a"': &'static str
|
||||
235..238 '"b"': &'static str
|
||||
250..251 'b': [[&'? str; 1]; 2]
|
||||
254..264 '[a, ["b"]]': [[&'? str; 1]; 2]
|
||||
255..256 'a': [&'? str; 1]
|
||||
258..263 '["b"]': [&'? str; 1]
|
||||
259..262 '"b"': &'static str
|
||||
274..275 'x': [u8; 0]
|
||||
287..289 '[]': [u8; 0]
|
||||
299..300 'y': [u8; 4]
|
||||
|
@ -1279,12 +1279,12 @@ fn infer_tuple_struct_generics() {
|
|||
92..93 'A': extern "rust-call" A<u128>(u128) -> A<u128>
|
||||
92..101 'A(42u128)': A<u128>
|
||||
94..100 '42u128': u128
|
||||
107..111 'Some': extern "rust-call" Some<&str>(&str) -> Option<&str>
|
||||
107..116 'Some("x")': Option<&str>
|
||||
112..115 '"x"': &str
|
||||
122..134 'Option::Some': extern "rust-call" Some<&str>(&str) -> Option<&str>
|
||||
122..139 'Option...e("x")': Option<&str>
|
||||
135..138 '"x"': &str
|
||||
107..111 'Some': extern "rust-call" Some<&'static str>(&'static str) -> Option<&'static str>
|
||||
107..116 'Some("x")': Option<&'static str>
|
||||
112..115 '"x"': &'static str
|
||||
122..134 'Option::Some': extern "rust-call" Some<&'static str>(&'static str) -> Option<&'static str>
|
||||
122..139 'Option...e("x")': Option<&'static str>
|
||||
135..138 '"x"': &'static str
|
||||
145..149 'None': Option<{unknown}>
|
||||
159..160 'x': Option<i64>
|
||||
176..180 'None': Option<i64>
|
||||
|
@ -1405,15 +1405,15 @@ fn infer_impl_generics_with_autoderef() {
|
|||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
77..81 'self': &Option<T>
|
||||
97..99 '{}': Option<&T>
|
||||
77..81 'self': &'? Option<T>
|
||||
97..99 '{}': Option<&'? T>
|
||||
110..111 'o': Option<u32>
|
||||
126..164 '{ ...f(); }': ()
|
||||
132..145 '(&o).as_ref()': Option<&u32>
|
||||
133..135 '&o': &Option<u32>
|
||||
132..145 '(&o).as_ref()': Option<&'? u32>
|
||||
133..135 '&o': &'? Option<u32>
|
||||
134..135 'o': Option<u32>
|
||||
151..152 'o': Option<u32>
|
||||
151..161 'o.as_ref()': Option<&u32>
|
||||
151..161 'o.as_ref()': Option<&'? u32>
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
@ -1551,16 +1551,16 @@ fn infer_type_alias() {
|
|||
"#,
|
||||
expect![[r#"
|
||||
115..116 'x': A<u32, i128>
|
||||
123..124 'y': A<&str, u128>
|
||||
123..124 'y': A<&'? str, u128>
|
||||
137..138 'z': A<u8, i8>
|
||||
153..210 '{ ...z.y; }': ()
|
||||
159..160 'x': A<u32, i128>
|
||||
159..162 'x.x': u32
|
||||
168..169 'x': A<u32, i128>
|
||||
168..171 'x.y': i128
|
||||
177..178 'y': A<&str, u128>
|
||||
177..180 'y.x': &str
|
||||
186..187 'y': A<&str, u128>
|
||||
177..178 'y': A<&'? str, u128>
|
||||
177..180 'y.x': &'? str
|
||||
186..187 'y': A<&'? str, u128>
|
||||
186..189 'y.y': u128
|
||||
195..196 'z': A<u8, i8>
|
||||
195..198 'z.x': u8
|
||||
|
@ -1572,8 +1572,8 @@ fn infer_type_alias() {
|
|||
312..328 'm::Ali...Foo(0)': Enum
|
||||
326..327 '0': u8
|
||||
338..354 'm::Ali...Foo(x)': Enum
|
||||
352..353 'x': &u8
|
||||
357..359 '&e': &Enum
|
||||
352..353 'x': &'? u8
|
||||
357..359 '&e': &'? Enum
|
||||
358..359 'e': Enum
|
||||
"#]],
|
||||
)
|
||||
|
@ -1618,10 +1618,10 @@ fn infer_type_param() {
|
|||
9..10 'x': T
|
||||
20..29 '{ x }': T
|
||||
26..27 'x': T
|
||||
43..44 'x': &T
|
||||
43..44 'x': &'? T
|
||||
55..65 '{ *x }': T
|
||||
61..63 '*x': T
|
||||
62..63 'x': &T
|
||||
62..63 'x': &'? T
|
||||
77..157 '{ ...(1); }': ()
|
||||
87..88 'y': u32
|
||||
91..96 '10u32': u32
|
||||
|
@ -1629,9 +1629,9 @@ fn infer_type_param() {
|
|||
102..107 'id(y)': u32
|
||||
105..106 'y': u32
|
||||
117..118 'x': bool
|
||||
127..132 'clone': fn clone<bool>(&bool) -> bool
|
||||
127..132 'clone': fn clone<bool>(&'? bool) -> bool
|
||||
127..135 'clone(z)': bool
|
||||
133..134 'z': &bool
|
||||
133..134 'z': &'? bool
|
||||
141..151 'id::<i128>': fn id<i128>(i128) -> i128
|
||||
141..154 'id::<i128>(1)': i128
|
||||
152..153 '1': i128
|
||||
|
@ -1842,7 +1842,7 @@ fn foo() -> &'static str { "" }
|
|||
|
||||
fn main() {
|
||||
foo();
|
||||
//^^^^^ &str
|
||||
//^^^^^ &'static str
|
||||
}"#,
|
||||
);
|
||||
}
|
||||
|
@ -1940,10 +1940,10 @@ fn closure_return_inferred() {
|
|||
"#,
|
||||
expect![[r#"
|
||||
16..46 '{ ..." }; }': u32
|
||||
26..27 'x': impl Fn() -> &str
|
||||
30..43 '|| { "test" }': impl Fn() -> &str
|
||||
33..43 '{ "test" }': &str
|
||||
35..41 '"test"': &str
|
||||
26..27 'x': impl Fn() -> &'static str
|
||||
30..43 '|| { "test" }': impl Fn() -> &'static str
|
||||
33..43 '{ "test" }': &'static str
|
||||
35..41 '"test"': &'static str
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
@ -1975,10 +1975,10 @@ fn test() {
|
|||
70..71 'v': i64
|
||||
78..80 '{}': ()
|
||||
91..362 '{ ... } }': ()
|
||||
101..106 'mut g': |usize| yields i64 -> &str
|
||||
109..218 '|r| { ... }': |usize| yields i64 -> &str
|
||||
101..106 'mut g': |usize| yields i64 -> &'static str
|
||||
109..218 '|r| { ... }': |usize| yields i64 -> &'static str
|
||||
110..111 'r': usize
|
||||
113..218 '{ ... }': &str
|
||||
113..218 '{ ... }': &'static str
|
||||
127..128 'a': usize
|
||||
131..138 'yield 0': usize
|
||||
137..138 '0': i64
|
||||
|
@ -1988,22 +1988,22 @@ fn test() {
|
|||
177..178 'a': usize
|
||||
181..188 'yield 2': usize
|
||||
187..188 '2': i64
|
||||
198..212 '"return value"': &str
|
||||
198..212 '"return value"': &'static str
|
||||
225..360 'match ... }': ()
|
||||
231..239 'Pin::new': fn new<&mut |usize| yields i64 -> &str>(&mut |usize| yields i64 -> &str) -> Pin<&mut |usize| yields i64 -> &str>
|
||||
231..247 'Pin::n...mut g)': Pin<&mut |usize| yields i64 -> &str>
|
||||
231..262 'Pin::n...usize)': CoroutineState<i64, &str>
|
||||
240..246 '&mut g': &mut |usize| yields i64 -> &str
|
||||
245..246 'g': |usize| yields i64 -> &str
|
||||
231..239 'Pin::new': fn new<&'? mut |usize| yields i64 -> &'static str>(&'? mut |usize| yields i64 -> &'static str) -> Pin<&'? mut |usize| yields i64 -> &'static str>
|
||||
231..247 'Pin::n...mut g)': Pin<&'? mut |usize| yields i64 -> &'static str>
|
||||
231..262 'Pin::n...usize)': CoroutineState<i64, &'static str>
|
||||
240..246 '&mut g': &'? mut |usize| yields i64 -> &'static str
|
||||
245..246 'g': |usize| yields i64 -> &'static str
|
||||
255..261 '0usize': usize
|
||||
273..299 'Corout...ded(y)': CoroutineState<i64, &str>
|
||||
273..299 'Corout...ded(y)': CoroutineState<i64, &'static str>
|
||||
297..298 'y': i64
|
||||
303..312 '{ f(y); }': ()
|
||||
305..306 'f': fn f(i64)
|
||||
305..309 'f(y)': ()
|
||||
307..308 'y': i64
|
||||
321..348 'Corout...ete(r)': CoroutineState<i64, &str>
|
||||
346..347 'r': &str
|
||||
321..348 'Corout...ete(r)': CoroutineState<i64, &'static str>
|
||||
346..347 'r': &'static str
|
||||
352..354 '{}': ()
|
||||
"#]],
|
||||
);
|
||||
|
@ -2050,7 +2050,7 @@ fn f(x: (&&&&i32, &&&i32)) {
|
|||
_ => loop {},
|
||||
};
|
||||
f;
|
||||
//^ (&&&&i32, &&&i32)
|
||||
//^ (&'? &'? &'? &'? i32, &'? &'? &'? i32)
|
||||
}
|
||||
"#,
|
||||
);
|
||||
|
@ -2059,10 +2059,10 @@ fn f(x: (&&&&i32, &&&i32)) {
|
|||
fn f() {
|
||||
let x = &&&(&&&2, &&&&&3);
|
||||
let (y, z) = x;
|
||||
//^ &&&&i32
|
||||
//^ &'? &'? &'? &'? i32
|
||||
let t @ (y, z) = x;
|
||||
t;
|
||||
//^ &&&(&&&i32, &&&&&i32)
|
||||
//^ &'? &'? &'? (&'? &'? &'? i32, &'? &'? &'? &'? &'? i32)
|
||||
}
|
||||
"#,
|
||||
);
|
||||
|
@ -2071,10 +2071,10 @@ fn f() {
|
|||
fn f() {
|
||||
let x = &&&(&&&2, &&&&&3);
|
||||
let (y, z) = x;
|
||||
//^ &&&&i32
|
||||
//^ &'? &'? &'? &'? i32
|
||||
let t @ (y, z) = x;
|
||||
t;
|
||||
//^ &&&(&&&i32, &&&&&i32)
|
||||
//^ &'? &'? &'? (&'? &'? &'? i32, &'? &'? &'? &'? &'? i32)
|
||||
}
|
||||
"#,
|
||||
);
|
||||
|
@ -2761,23 +2761,23 @@ impl S {
|
|||
fn f() {
|
||||
let x = S;
|
||||
let c1 = || x.read();
|
||||
//^^ impl Fn() -> &S
|
||||
//^^ impl Fn() -> &'? S
|
||||
let c2 = || x.write();
|
||||
//^^ impl FnMut() -> &mut S
|
||||
//^^ impl FnMut() -> &'? mut S
|
||||
let c3 = || x.consume();
|
||||
//^^ impl FnOnce() -> S
|
||||
let c3 = || x.consume().consume().consume();
|
||||
//^^ impl FnOnce() -> S
|
||||
let c3 = || x.consume().write().read();
|
||||
//^^ impl FnOnce() -> &S
|
||||
//^^ impl FnOnce() -> &'? S
|
||||
let x = &mut x;
|
||||
let c1 = || x.write();
|
||||
//^^ impl FnMut() -> &mut S
|
||||
//^^ impl FnMut() -> &'? mut S
|
||||
let x = S;
|
||||
let c1 = || { let ref t = x; t };
|
||||
//^^ impl Fn() -> &S
|
||||
//^^ impl Fn() -> &'? S
|
||||
let c2 = || { let ref mut t = x; t };
|
||||
//^^ impl FnMut() -> &mut S
|
||||
//^^ impl FnMut() -> &'? mut S
|
||||
let c3 = || { let t = x; t };
|
||||
//^^ impl FnOnce() -> S
|
||||
}
|
||||
|
@ -3074,11 +3074,11 @@ fn main() {
|
|||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
104..108 'self': &Box<T>
|
||||
188..192 'self': &Box<Foo<T>>
|
||||
218..220 '{}': &T
|
||||
242..246 'self': &Box<Foo<T>>
|
||||
275..277 '{}': &Foo<T>
|
||||
104..108 'self': &'? Box<T>
|
||||
188..192 'self': &'a Box<Foo<T>>
|
||||
218..220 '{}': &'a T
|
||||
242..246 'self': &'a Box<Foo<T>>
|
||||
275..277 '{}': &'a Foo<T>
|
||||
297..301 'self': Box<Foo<T>>
|
||||
322..324 '{}': Foo<T>
|
||||
338..559 '{ ...r(); }': ()
|
||||
|
@ -3088,21 +3088,21 @@ fn main() {
|
|||
360..363 'Foo': extern "rust-call" Foo<i32>(i32) -> Foo<i32>
|
||||
360..370 'Foo(0_i32)': Foo<i32>
|
||||
364..369 '0_i32': i32
|
||||
382..386 'bad1': &i32
|
||||
382..386 'bad1': &'? i32
|
||||
389..394 'boxed': Box<Foo<i32>>
|
||||
389..406 'boxed....nner()': &i32
|
||||
416..421 'good1': &i32
|
||||
424..438 'Foo::get_inner': fn get_inner<i32, '{error}>(&Box<Foo<i32>>) -> &i32
|
||||
424..446 'Foo::g...boxed)': &i32
|
||||
439..445 '&boxed': &Box<Foo<i32>>
|
||||
389..406 'boxed....nner()': &'? i32
|
||||
416..421 'good1': &'? i32
|
||||
424..438 'Foo::get_inner': fn get_inner<i32, '?>(&'? Box<Foo<i32>>) -> &'? i32
|
||||
424..446 'Foo::g...boxed)': &'? i32
|
||||
439..445 '&boxed': &'? Box<Foo<i32>>
|
||||
440..445 'boxed': Box<Foo<i32>>
|
||||
457..461 'bad2': &Foo<i32>
|
||||
457..461 'bad2': &'? Foo<i32>
|
||||
464..469 'boxed': Box<Foo<i32>>
|
||||
464..480 'boxed....self()': &Foo<i32>
|
||||
490..495 'good2': &Foo<i32>
|
||||
498..511 'Foo::get_self': fn get_self<i32, '{error}>(&Box<Foo<i32>>) -> &Foo<i32>
|
||||
498..519 'Foo::g...boxed)': &Foo<i32>
|
||||
512..518 '&boxed': &Box<Foo<i32>>
|
||||
464..480 'boxed....self()': &'? Foo<i32>
|
||||
490..495 'good2': &'? Foo<i32>
|
||||
498..511 'Foo::get_self': fn get_self<i32, '?>(&'? Box<Foo<i32>>) -> &'? Foo<i32>
|
||||
498..519 'Foo::g...boxed)': &'? Foo<i32>
|
||||
512..518 '&boxed': &'? Box<Foo<i32>>
|
||||
513..518 'boxed': Box<Foo<i32>>
|
||||
530..535 'inner': Foo<i32>
|
||||
538..543 'boxed': Box<Foo<i32>>
|
||||
|
@ -3414,31 +3414,31 @@ struct TS(usize);
|
|||
fn main() {
|
||||
let x;
|
||||
[x,] = &[1,];
|
||||
//^^^^expected &[i32; 1], got [{unknown}; _]
|
||||
//^^^^expected &'? [i32; 1], got [{unknown}; _]
|
||||
|
||||
let x;
|
||||
[(x,),] = &[(1,),];
|
||||
//^^^^^^^expected &[(i32,); 1], got [{unknown}; _]
|
||||
//^^^^^^^expected &'? [(i32,); 1], got [{unknown}; _]
|
||||
|
||||
let x;
|
||||
((x,),) = &((1,),);
|
||||
//^^^^^^^expected &((i32,),), got (({unknown},),)
|
||||
//^^^^^^^expected &'? ((i32,),), got (({unknown},),)
|
||||
|
||||
let x;
|
||||
(x,) = &(1,);
|
||||
//^^^^expected &(i32,), got ({unknown},)
|
||||
//^^^^expected &'? (i32,), got ({unknown},)
|
||||
|
||||
let x;
|
||||
(S { a: x },) = &(S { a: 42 },);
|
||||
//^^^^^^^^^^^^^expected &(S,), got (S,)
|
||||
//^^^^^^^^^^^^^expected &'? (S,), got (S,)
|
||||
|
||||
let x;
|
||||
S { a: x } = &S { a: 42 };
|
||||
//^^^^^^^^^^expected &S, got S
|
||||
//^^^^^^^^^^expected &'? S, got S
|
||||
|
||||
let x;
|
||||
TS(x) = &TS(42);
|
||||
//^^^^^expected &TS, got TS
|
||||
//^^^^^expected &'? TS, got TS
|
||||
}
|
||||
"#,
|
||||
);
|
||||
|
@ -3548,17 +3548,17 @@ fn f<T>(t: Ark<T>) {
|
|||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
47..51 'self': &Ark<T>
|
||||
47..51 'self': &'? Ark<T>
|
||||
65..88 '{ ... }': *const T
|
||||
75..82 '&self.0': &T
|
||||
76..80 'self': &Ark<T>
|
||||
75..82 '&self.0': &'? T
|
||||
76..80 'self': &'? Ark<T>
|
||||
76..82 'self.0': T
|
||||
99..100 't': Ark<T>
|
||||
110..144 '{ ... (); }': ()
|
||||
116..124 'Ark::foo': fn foo<T>(&Ark<T>) -> *const T
|
||||
116..124 'Ark::foo': fn foo<T>(&'? Ark<T>) -> *const T
|
||||
116..128 'Ark::foo(&t)': *const T
|
||||
116..141 'Ark::f...nst ()': *const ()
|
||||
125..127 '&t': &Ark<T>
|
||||
125..127 '&t': &'? Ark<T>
|
||||
126..127 't': Ark<T>
|
||||
"#]],
|
||||
);
|
||||
|
@ -3632,7 +3632,7 @@ pub struct CStr;
|
|||
|
||||
fn main() {
|
||||
c"ello";
|
||||
//^^^^^^^ &CStr
|
||||
//^^^^^^^ &'static CStr
|
||||
}
|
||||
"#,
|
||||
);
|
||||
|
@ -3659,7 +3659,25 @@ fn main() {
|
|||
let are = "are";
|
||||
let count = 10;
|
||||
builtin#format_args("hello {count:02} {} friends, we {are:?} {0}{last}", "fancy", last = "!");
|
||||
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type: Arguments<'{error}>
|
||||
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type: Arguments<'?>
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn inline_const_expression() {
|
||||
check(
|
||||
r#"
|
||||
fn main() {
|
||||
let foo = 0;
|
||||
const {
|
||||
let bar = 1;
|
||||
let unresolved = foo;
|
||||
// ^^^^^^^^^^ type: {unknown}
|
||||
let resolved = bar;
|
||||
// ^^^^^^^^ type: i32
|
||||
}
|
||||
}
|
||||
"#,
|
||||
);
|
||||
|
|
|
@ -238,6 +238,7 @@ fn infer_for_loop() {
|
|||
//- minicore: iterator
|
||||
//- /main.rs crate:main deps:alloc
|
||||
#![no_std]
|
||||
extern crate alloc;
|
||||
use alloc::collections::Vec;
|
||||
|
||||
fn test() {
|
||||
|
@ -245,7 +246,7 @@ fn test() {
|
|||
v.push("foo");
|
||||
for x in v {
|
||||
x;
|
||||
} //^ &str
|
||||
} //^ &'static str
|
||||
}
|
||||
|
||||
//- /alloc.rs crate:alloc
|
||||
|
@ -575,7 +576,7 @@ fn indexing_arrays() {
|
|||
"fn main() { &mut [9][2]; }",
|
||||
expect![[r#"
|
||||
10..26 '{ &mut...[2]; }': ()
|
||||
12..23 '&mut [9][2]': &mut {unknown}
|
||||
12..23 '&mut [9][2]': &'? mut {unknown}
|
||||
17..20 '[9]': [i32; 1]
|
||||
17..23 '[9][2]': {unknown}
|
||||
18..19 '9': i32
|
||||
|
@ -873,7 +874,7 @@ impl<U, T: Trait<U>> O<T> {
|
|||
|
||||
fn test(o: O<S>) {
|
||||
o.foo();
|
||||
} //^^^^^^^ &str
|
||||
} //^^^^^^^ &'? str
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
@ -1016,15 +1017,15 @@ fn test(x: impl Trait<u64>, y: &impl Trait<u32>) {
|
|||
z.foo2();
|
||||
}"#,
|
||||
expect![[r#"
|
||||
29..33 'self': &Self
|
||||
54..58 'self': &Self
|
||||
29..33 'self': &'? Self
|
||||
54..58 'self': &'? Self
|
||||
77..78 'x': impl Trait<u16>
|
||||
97..99 '{}': ()
|
||||
154..155 'x': impl Trait<u64>
|
||||
174..175 'y': &impl Trait<u32>
|
||||
174..175 'y': &'? impl Trait<u32>
|
||||
195..323 '{ ...2(); }': ()
|
||||
201..202 'x': impl Trait<u64>
|
||||
208..209 'y': &impl Trait<u32>
|
||||
208..209 'y': &'? impl Trait<u32>
|
||||
219..220 'z': S<u16>
|
||||
223..224 'S': extern "rust-call" S<u16>(u16) -> S<u16>
|
||||
223..227 'S(1)': S<u16>
|
||||
|
@ -1034,13 +1035,13 @@ fn test(x: impl Trait<u64>, y: &impl Trait<u32>) {
|
|||
237..238 'z': S<u16>
|
||||
245..246 'x': impl Trait<u64>
|
||||
245..252 'x.foo()': u64
|
||||
258..259 'y': &impl Trait<u32>
|
||||
258..259 'y': &'? impl Trait<u32>
|
||||
258..265 'y.foo()': u32
|
||||
271..272 'z': S<u16>
|
||||
271..278 'z.foo()': u16
|
||||
284..285 'x': impl Trait<u64>
|
||||
284..292 'x.foo2()': i64
|
||||
298..299 'y': &impl Trait<u32>
|
||||
298..299 'y': &'? impl Trait<u32>
|
||||
298..306 'y.foo2()': i64
|
||||
312..313 'z': S<u16>
|
||||
312..320 'z.foo2()': i64
|
||||
|
@ -1204,26 +1205,26 @@ fn test(x: impl Trait<u64>, y: &impl Trait<u64>) {
|
|||
z.foo2();
|
||||
}"#,
|
||||
expect![[r#"
|
||||
29..33 'self': &Self
|
||||
54..58 'self': &Self
|
||||
29..33 'self': &'? Self
|
||||
54..58 'self': &'? Self
|
||||
98..100 '{}': ()
|
||||
110..111 'x': impl Trait<u64>
|
||||
130..131 'y': &impl Trait<u64>
|
||||
130..131 'y': &'? impl Trait<u64>
|
||||
151..268 '{ ...2(); }': ()
|
||||
157..158 'x': impl Trait<u64>
|
||||
164..165 'y': &impl Trait<u64>
|
||||
164..165 'y': &'? impl Trait<u64>
|
||||
175..176 'z': impl Trait<u64>
|
||||
179..182 'bar': fn bar() -> impl Trait<u64>
|
||||
179..184 'bar()': impl Trait<u64>
|
||||
190..191 'x': impl Trait<u64>
|
||||
190..197 'x.foo()': u64
|
||||
203..204 'y': &impl Trait<u64>
|
||||
203..204 'y': &'? impl Trait<u64>
|
||||
203..210 'y.foo()': u64
|
||||
216..217 'z': impl Trait<u64>
|
||||
216..223 'z.foo()': u64
|
||||
229..230 'x': impl Trait<u64>
|
||||
229..237 'x.foo2()': i64
|
||||
243..244 'y': &impl Trait<u64>
|
||||
243..244 'y': &'? impl Trait<u64>
|
||||
243..251 'y.foo2()': i64
|
||||
257..258 'z': impl Trait<u64>
|
||||
257..265 'z.foo2()': i64
|
||||
|
@ -1328,7 +1329,7 @@ fn test() {
|
|||
a.foo();
|
||||
}"#,
|
||||
expect![[r#"
|
||||
29..33 'self': &Self
|
||||
29..33 'self': &'? Self
|
||||
71..82 '{ loop {} }': !
|
||||
73..80 'loop {}': !
|
||||
78..80 '{}': ()
|
||||
|
@ -1366,8 +1367,8 @@ fn test() {
|
|||
d.foo();
|
||||
}"#,
|
||||
expect![[r#"
|
||||
49..53 'self': &mut Self
|
||||
101..105 'self': &Self
|
||||
49..53 'self': &'? mut Self
|
||||
101..105 'self': &'? Self
|
||||
184..195 '{ loop {} }': ({unknown}, {unknown})
|
||||
186..193 'loop {}': !
|
||||
191..193 '{}': ()
|
||||
|
@ -1414,10 +1415,10 @@ fn foo<const C: u8, T>() -> (impl FnOnce(&str, T), impl Trait<u8>) {
|
|||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
134..165 '{ ...(C)) }': (impl FnOnce(&str, T), Bar<u8>)
|
||||
140..163 '(|inpu...ar(C))': (impl FnOnce(&str, T), Bar<u8>)
|
||||
141..154 '|input, t| {}': impl FnOnce(&str, T)
|
||||
142..147 'input': &str
|
||||
134..165 '{ ...(C)) }': (impl FnOnce(&'? str, T), Bar<u8>)
|
||||
140..163 '(|inpu...ar(C))': (impl FnOnce(&'? str, T), Bar<u8>)
|
||||
141..154 '|input, t| {}': impl FnOnce(&'? str, T)
|
||||
142..147 'input': &'? str
|
||||
149..150 't': T
|
||||
152..154 '{}': ()
|
||||
156..159 'Bar': extern "rust-call" Bar<u8>(u8) -> Bar<u8>
|
||||
|
@ -1466,26 +1467,26 @@ fn test(x: dyn Trait<u64>, y: &dyn Trait<u64>) {
|
|||
z.foo2();
|
||||
}"#,
|
||||
expect![[r#"
|
||||
29..33 'self': &Self
|
||||
54..58 'self': &Self
|
||||
29..33 'self': &'? Self
|
||||
54..58 'self': &'? Self
|
||||
97..99 '{}': dyn Trait<u64>
|
||||
109..110 'x': dyn Trait<u64>
|
||||
128..129 'y': &dyn Trait<u64>
|
||||
128..129 'y': &'? dyn Trait<u64>
|
||||
148..265 '{ ...2(); }': ()
|
||||
154..155 'x': dyn Trait<u64>
|
||||
161..162 'y': &dyn Trait<u64>
|
||||
161..162 'y': &'? dyn Trait<u64>
|
||||
172..173 'z': dyn Trait<u64>
|
||||
176..179 'bar': fn bar() -> dyn Trait<u64>
|
||||
176..181 'bar()': dyn Trait<u64>
|
||||
187..188 'x': dyn Trait<u64>
|
||||
187..194 'x.foo()': u64
|
||||
200..201 'y': &dyn Trait<u64>
|
||||
200..201 'y': &'? dyn Trait<u64>
|
||||
200..207 'y.foo()': u64
|
||||
213..214 'z': dyn Trait<u64>
|
||||
213..220 'z.foo()': u64
|
||||
226..227 'x': dyn Trait<u64>
|
||||
226..234 'x.foo2()': i64
|
||||
240..241 'y': &dyn Trait<u64>
|
||||
240..241 'y': &'? dyn Trait<u64>
|
||||
240..248 'y.foo2()': i64
|
||||
254..255 'z': dyn Trait<u64>
|
||||
254..262 'z.foo2()': i64
|
||||
|
@ -1514,16 +1515,16 @@ fn test(s: S<u32, i32>) {
|
|||
s.bar().baz();
|
||||
}"#,
|
||||
expect![[r#"
|
||||
32..36 'self': &Self
|
||||
102..106 'self': &S<T, U>
|
||||
128..139 '{ loop {} }': &dyn Trait<T, U>
|
||||
32..36 'self': &'? Self
|
||||
102..106 'self': &'? S<T, U>
|
||||
128..139 '{ loop {} }': &'? dyn Trait<T, U>
|
||||
130..137 'loop {}': !
|
||||
135..137 '{}': ()
|
||||
175..179 'self': &Self
|
||||
175..179 'self': &'? Self
|
||||
251..252 's': S<u32, i32>
|
||||
267..289 '{ ...z(); }': ()
|
||||
273..274 's': S<u32, i32>
|
||||
273..280 's.bar()': &dyn Trait<u32, i32>
|
||||
273..280 's.bar()': &'? dyn Trait<u32, i32>
|
||||
273..286 's.bar().baz()': (u32, i32)
|
||||
"#]],
|
||||
);
|
||||
|
@ -1548,19 +1549,19 @@ fn test(x: Trait, y: &Trait) -> u64 {
|
|||
z.foo();
|
||||
}"#,
|
||||
expect![[r#"
|
||||
26..30 'self': &Self
|
||||
26..30 'self': &'? Self
|
||||
60..62 '{}': dyn Trait
|
||||
72..73 'x': dyn Trait
|
||||
82..83 'y': &dyn Trait
|
||||
82..83 'y': &'? dyn Trait
|
||||
100..175 '{ ...o(); }': u64
|
||||
106..107 'x': dyn Trait
|
||||
113..114 'y': &dyn Trait
|
||||
113..114 'y': &'? dyn Trait
|
||||
124..125 'z': dyn Trait
|
||||
128..131 'bar': fn bar() -> dyn Trait
|
||||
128..133 'bar()': dyn Trait
|
||||
139..140 'x': dyn Trait
|
||||
139..146 'x.foo()': u64
|
||||
152..153 'y': &dyn Trait
|
||||
152..153 'y': &'? dyn Trait
|
||||
152..159 'y.foo()': u64
|
||||
165..166 'z': dyn Trait
|
||||
165..172 'z.foo()': u64
|
||||
|
@ -1580,14 +1581,14 @@ fn main() {
|
|||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
31..35 'self': &S
|
||||
31..35 'self': &'? S
|
||||
37..39 '{}': ()
|
||||
47..48 '_': &dyn Fn(S)
|
||||
47..48 '_': &'? dyn Fn(S)
|
||||
58..60 '{}': ()
|
||||
71..105 '{ ...()); }': ()
|
||||
77..78 'f': fn f(&dyn Fn(S))
|
||||
77..78 'f': fn f(&'? dyn Fn(S))
|
||||
77..102 'f(&|nu...foo())': ()
|
||||
79..101 '&|numb....foo()': &impl Fn(S)
|
||||
79..101 '&|numb....foo()': &'? impl Fn(S)
|
||||
80..101 '|numbe....foo()': impl Fn(S)
|
||||
81..87 'number': S
|
||||
89..95 'number': S
|
||||
|
@ -1790,7 +1791,7 @@ fn test<T: Trait1, U: Trait2>(x: T, y: U) {
|
|||
y.foo();
|
||||
}"#,
|
||||
expect![[r#"
|
||||
53..57 'self': &Self
|
||||
53..57 'self': &'? Self
|
||||
66..68 '{}': u32
|
||||
185..186 'x': T
|
||||
191..192 'y': U
|
||||
|
@ -1819,11 +1820,11 @@ fn test(x: &impl Trait1) {
|
|||
x.foo();
|
||||
}"#,
|
||||
expect![[r#"
|
||||
53..57 'self': &Self
|
||||
53..57 'self': &'? Self
|
||||
66..68 '{}': u32
|
||||
119..120 'x': &impl Trait1
|
||||
119..120 'x': &'? impl Trait1
|
||||
136..152 '{ ...o(); }': ()
|
||||
142..143 'x': &impl Trait1
|
||||
142..143 'x': &'? impl Trait1
|
||||
142..149 'x.foo()': u32
|
||||
"#]],
|
||||
);
|
||||
|
@ -1934,8 +1935,8 @@ fn test() {
|
|||
opt.map(f);
|
||||
}"#,
|
||||
expect![[r#"
|
||||
28..32 'self': &Self
|
||||
132..136 'self': &Bar<F>
|
||||
28..32 'self': &'? Self
|
||||
132..136 'self': &'? Bar<F>
|
||||
149..160 '{ loop {} }': (A1, R)
|
||||
151..158 'loop {}': !
|
||||
156..158 '{}': ()
|
||||
|
@ -1988,7 +1989,7 @@ fn test() {
|
|||
let r2 = lazy2.foo();
|
||||
}"#,
|
||||
expect![[r#"
|
||||
36..40 'self': &Foo
|
||||
36..40 'self': &'? Foo
|
||||
51..53 '{}': usize
|
||||
131..132 'f': F
|
||||
151..153 '{}': Lazy<T, F>
|
||||
|
@ -2262,14 +2263,14 @@ impl Trait for S2 {
|
|||
fn f(&self, x: <Self>::Item) { let y = x; }
|
||||
}"#,
|
||||
expect![[r#"
|
||||
40..44 'self': &Self
|
||||
40..44 'self': &'? Self
|
||||
46..47 'x': Trait::Item<Self>
|
||||
126..130 'self': &S
|
||||
126..130 'self': &'? S
|
||||
132..133 'x': u32
|
||||
147..161 '{ let y = x; }': ()
|
||||
153..154 'y': u32
|
||||
157..158 'x': u32
|
||||
228..232 'self': &S2
|
||||
228..232 'self': &'? S2
|
||||
234..235 'x': i32
|
||||
251..265 '{ let y = x; }': ()
|
||||
257..258 'y': i32
|
||||
|
@ -2643,12 +2644,12 @@ fn main() {
|
|||
72..74 '_v': F
|
||||
117..120 '{ }': ()
|
||||
132..163 '{ ... }); }': ()
|
||||
138..148 'f::<(), _>': fn f<(), impl FnOnce(&())>(impl FnOnce(&()))
|
||||
138..148 'f::<(), _>': fn f<(), impl FnOnce(&'? ())>(impl FnOnce(&'? ()))
|
||||
138..160 'f::<()... z; })': ()
|
||||
149..159 '|z| { z; }': impl FnOnce(&())
|
||||
150..151 'z': &()
|
||||
149..159 '|z| { z; }': impl FnOnce(&'? ())
|
||||
150..151 'z': &'? ()
|
||||
153..159 '{ z; }': ()
|
||||
155..156 'z': &()
|
||||
155..156 'z': &'? ()
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
@ -2897,13 +2898,13 @@ fn test(x: &dyn Foo) {
|
|||
foo(x);
|
||||
}"#,
|
||||
expect![[r#"
|
||||
21..22 'x': &dyn Foo
|
||||
21..22 'x': &'? dyn Foo
|
||||
34..36 '{}': ()
|
||||
46..47 'x': &dyn Foo
|
||||
46..47 'x': &'? dyn Foo
|
||||
59..74 '{ foo(x); }': ()
|
||||
65..68 'foo': fn foo(&dyn Foo)
|
||||
65..68 'foo': fn foo(&'? dyn Foo)
|
||||
65..71 'foo(x)': ()
|
||||
69..70 'x': &dyn Foo
|
||||
69..70 'x': &'? dyn Foo
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
@ -2927,7 +2928,7 @@ fn test() {
|
|||
(IsCopy, NotCopy).test();
|
||||
}"#,
|
||||
expect![[r#"
|
||||
78..82 'self': &Self
|
||||
78..82 'self': &'? Self
|
||||
134..235 '{ ...t(); }': ()
|
||||
140..146 'IsCopy': IsCopy
|
||||
140..153 'IsCopy.test()': bool
|
||||
|
@ -2969,7 +2970,7 @@ fn test() {
|
|||
28..29 'T': {unknown}
|
||||
36..38 '{}': T
|
||||
36..38: expected T, got ()
|
||||
113..117 'self': &Self
|
||||
113..117 'self': &'? Self
|
||||
169..249 '{ ...t(); }': ()
|
||||
175..178 'foo': fn foo()
|
||||
175..185 'foo.test()': bool
|
||||
|
@ -2997,16 +2998,16 @@ fn test(f1: fn(), f2: fn(usize) -> u8, f3: fn(u8, u8) -> &u8) {
|
|||
f3.test();
|
||||
}"#,
|
||||
expect![[r#"
|
||||
22..26 'self': &Self
|
||||
22..26 'self': &'? Self
|
||||
76..78 'f1': fn()
|
||||
86..88 'f2': fn(usize) -> u8
|
||||
107..109 'f3': fn(u8, u8) -> &u8
|
||||
107..109 'f3': fn(u8, u8) -> &'? u8
|
||||
130..178 '{ ...t(); }': ()
|
||||
136..138 'f1': fn()
|
||||
136..145 'f1.test()': bool
|
||||
151..153 'f2': fn(usize) -> u8
|
||||
151..160 'f2.test()': bool
|
||||
166..168 'f3': fn(u8, u8) -> &u8
|
||||
166..168 'f3': fn(u8, u8) -> &'? u8
|
||||
166..175 'f3.test()': bool
|
||||
"#]],
|
||||
);
|
||||
|
@ -3027,13 +3028,13 @@ fn test() {
|
|||
(1u8, *"foo").test(); // not Sized
|
||||
}"#,
|
||||
expect![[r#"
|
||||
22..26 'self': &Self
|
||||
22..26 'self': &'? Self
|
||||
79..194 '{ ...ized }': ()
|
||||
85..88 '1u8': u8
|
||||
85..95 '1u8.test()': bool
|
||||
101..116 '(*"foo").test()': {unknown}
|
||||
102..108 '*"foo"': str
|
||||
103..108 '"foo"': &str
|
||||
103..108 '"foo"': &'static str
|
||||
135..145 '(1u8, 1u8)': (u8, u8)
|
||||
135..152 '(1u8, ...test()': bool
|
||||
136..139 '1u8': u8
|
||||
|
@ -3042,7 +3043,7 @@ fn test() {
|
|||
158..178 '(1u8, ...test()': {unknown}
|
||||
159..162 '1u8': u8
|
||||
164..170 '*"foo"': str
|
||||
165..170 '"foo"': &str
|
||||
165..170 '"foo"': &'static str
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
@ -3093,7 +3094,7 @@ fn foo() {
|
|||
93..94 'x': Option<i32>
|
||||
109..111 '{}': ()
|
||||
117..124 '(&f)(s)': ()
|
||||
118..120 '&f': &impl Fn(Option<i32>)
|
||||
118..120 '&f': &'? impl Fn(Option<i32>)
|
||||
119..120 'f': impl Fn(Option<i32>)
|
||||
122..123 's': Option<i32>
|
||||
"#]],
|
||||
|
@ -3170,25 +3171,25 @@ fn foo() {
|
|||
f(&s);
|
||||
}"#,
|
||||
expect![[r#"
|
||||
154..158 'self': &Box<T>
|
||||
166..205 '{ ... }': &T
|
||||
176..199 'unsafe...nner }': &T
|
||||
185..197 '&*self.inner': &T
|
||||
154..158 'self': &'? Box<T>
|
||||
166..205 '{ ... }': &'? T
|
||||
176..199 'unsafe...nner }': &'? T
|
||||
185..197 '&*self.inner': &'? T
|
||||
186..197 '*self.inner': T
|
||||
187..191 'self': &Box<T>
|
||||
187..191 'self': &'? Box<T>
|
||||
187..197 'self.inner': *mut T
|
||||
218..324 '{ ...&s); }': ()
|
||||
228..229 's': Option<i32>
|
||||
232..236 'None': Option<i32>
|
||||
246..247 'f': Box<dyn FnOnce(&Option<i32>)>
|
||||
281..310 'Box { ... {}) }': Box<dyn FnOnce(&Option<i32>)>
|
||||
294..308 '&mut (|ps| {})': &mut impl FnOnce(&Option<i32>)
|
||||
300..307 '|ps| {}': impl FnOnce(&Option<i32>)
|
||||
301..303 'ps': &Option<i32>
|
||||
246..247 'f': Box<dyn FnOnce(&'? Option<i32>)>
|
||||
281..310 'Box { ... {}) }': Box<dyn FnOnce(&'? Option<i32>)>
|
||||
294..308 '&mut (|ps| {})': &'? mut impl FnOnce(&'? Option<i32>)
|
||||
300..307 '|ps| {}': impl FnOnce(&'? Option<i32>)
|
||||
301..303 'ps': &'? Option<i32>
|
||||
305..307 '{}': ()
|
||||
316..317 'f': Box<dyn FnOnce(&Option<i32>)>
|
||||
316..317 'f': Box<dyn FnOnce(&'? Option<i32>)>
|
||||
316..321 'f(&s)': ()
|
||||
318..320 '&s': &Option<i32>
|
||||
318..320 '&s': &'? Option<i32>
|
||||
319..320 's': Option<i32>
|
||||
"#]],
|
||||
);
|
||||
|
@ -3320,7 +3321,7 @@ fn f() {
|
|||
}
|
||||
}"#,
|
||||
expect![[r#"
|
||||
46..50 'self': &Self
|
||||
46..50 'self': &'? Self
|
||||
58..63 '{ 0 }': u8
|
||||
60..61 '0': u8
|
||||
115..185 '{ ... } }': ()
|
||||
|
@ -3595,7 +3596,7 @@ fn take_u32(_: u32) {}
|
|||
fn minimized() {
|
||||
let v = V::default();
|
||||
let p = v.get(&0);
|
||||
//^ &u32
|
||||
//^ &'? u32
|
||||
take_u32(42 + p);
|
||||
}
|
||||
"#,
|
||||
|
@ -3625,7 +3626,7 @@ fn take_u32(_: u32) {}
|
|||
fn minimized() {
|
||||
let v = V::default();
|
||||
let p = v.get();
|
||||
//^ &{unknown}
|
||||
//^ &'? {unknown}
|
||||
take_u32(42 + p);
|
||||
}
|
||||
"#,
|
||||
|
@ -3684,11 +3685,11 @@ fn main() {
|
|||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
44..48 'self': &Self
|
||||
133..137 'self': &[u8; 4]
|
||||
44..48 'self': &'? Self
|
||||
133..137 'self': &'? [u8; 4]
|
||||
155..172 '{ ... }': usize
|
||||
165..166 '2': usize
|
||||
236..240 'self': &[u8; 2]
|
||||
236..240 'self': &'? [u8; 2]
|
||||
258..275 '{ ... }': u8
|
||||
268..269 '2': u8
|
||||
289..392 '{ ...g(); }': ()
|
||||
|
@ -3732,11 +3733,11 @@ fn main() {
|
|||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
44..48 'self': &Self
|
||||
151..155 'self': &[u8; L]
|
||||
44..48 'self': &'? Self
|
||||
151..155 'self': &'? [u8; L]
|
||||
173..194 '{ ... }': [u8; L]
|
||||
183..188 '*self': [u8; L]
|
||||
184..188 'self': &[u8; L]
|
||||
184..188 'self': &'? [u8; L]
|
||||
208..260 '{ ...g(); }': ()
|
||||
218..219 'v': [u8; 2]
|
||||
222..230 '[0u8; 2]': [u8; 2]
|
||||
|
@ -4056,13 +4057,13 @@ fn g(t: &(dyn Sync + T2 + T1 + Send)) {
|
|||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
68..69 't': &{unknown}
|
||||
68..69 't': &'? {unknown}
|
||||
101..103 '{}': ()
|
||||
109..110 't': &{unknown}
|
||||
109..110 't': &'? {unknown}
|
||||
142..155 '{ f(t); }': ()
|
||||
148..149 'f': fn f(&{unknown})
|
||||
148..149 'f': fn f(&'? {unknown})
|
||||
148..152 'f(t)': ()
|
||||
150..151 't': &{unknown}
|
||||
150..151 't': &'? {unknown}
|
||||
"#]],
|
||||
);
|
||||
|
||||
|
@ -4105,7 +4106,7 @@ trait Trait {
|
|||
}
|
||||
|
||||
fn f(t: &dyn Trait<T = (), T = ()>) {}
|
||||
//^&{unknown}
|
||||
//^&'? {unknown}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
@ -4175,27 +4176,27 @@ trait Trait {
|
|||
|
||||
fn f<T>(v: impl Trait) {
|
||||
let a = v.get::<i32>().deref();
|
||||
//^ &i32
|
||||
//^ &'? i32
|
||||
let a = v.get::<T>().deref();
|
||||
//^ &T
|
||||
//^ &'? T
|
||||
}
|
||||
fn g<'a, T: 'a>(v: impl Trait<Assoc<T> = &'a T>) {
|
||||
let a = v.get::<T>();
|
||||
//^ &T
|
||||
//^ &'a T
|
||||
let a = v.get::<()>();
|
||||
//^ Trait::Assoc<(), impl Trait<Assoc<T> = &T>>
|
||||
//^ Trait::Assoc<(), impl Trait<Assoc<T> = &'a T>>
|
||||
}
|
||||
fn h<'a>(v: impl Trait<Assoc<i32> = &'a i32> + Trait<Assoc<i64> = &'a i64>) {
|
||||
let a = v.get::<i32>();
|
||||
//^ &i32
|
||||
//^ &'a i32
|
||||
let a = v.get::<i64>();
|
||||
//^ &i64
|
||||
//^ &'a i64
|
||||
}
|
||||
fn i<'a>(v: impl Trait<Assoc<i32> = &'a i32, Assoc<i64> = &'a i64>) {
|
||||
let a = v.get::<i32>();
|
||||
//^ &i32
|
||||
//^ &'a i32
|
||||
let a = v.get::<i64>();
|
||||
//^ &i64
|
||||
//^ &'a i64
|
||||
}
|
||||
"#,
|
||||
);
|
||||
|
@ -4221,12 +4222,12 @@ fn f<'a>(v: &dyn Trait<Assoc<i32> = &'a i32>) {
|
|||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
90..94 'self': &Self
|
||||
127..128 'v': &(dyn Trait<Assoc<i32> = &i32>)
|
||||
90..94 'self': &'? Self
|
||||
127..128 'v': &'? (dyn Trait<Assoc<i32> = &'a i32>)
|
||||
164..195 '{ ...f(); }': ()
|
||||
170..171 'v': &(dyn Trait<Assoc<i32> = &i32>)
|
||||
170..184 'v.get::<i32>()': &i32
|
||||
170..192 'v.get:...eref()': &i32
|
||||
170..171 'v': &'? (dyn Trait<Assoc<i32> = &'a i32>)
|
||||
170..184 'v.get::<i32>()': &'? i32
|
||||
170..192 'v.get:...eref()': &'? i32
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
@ -4487,19 +4488,19 @@ fn derive_macro_bounds() {
|
|||
let x = (&Copy).clone();
|
||||
//^ Copy
|
||||
let x = (&NotCopy).clone();
|
||||
//^ &NotCopy
|
||||
//^ &'? NotCopy
|
||||
let x = (&Generic(Copy)).clone();
|
||||
//^ Generic<Copy>
|
||||
let x = (&Generic(NotCopy)).clone();
|
||||
//^ &Generic<NotCopy>
|
||||
//^ &'? Generic<NotCopy>
|
||||
let x: &AssocGeneric<Copy> = &AssocGeneric(NotCopy);
|
||||
let x = x.clone();
|
||||
//^ &AssocGeneric<Copy>
|
||||
//^ &'? AssocGeneric<Copy>
|
||||
// let x: &AssocGeneric2<Copy> = &AssocGeneric2(NotCopy);
|
||||
// let x = x.clone();
|
||||
let x: &AssocGeneric3<Copy> = &AssocGeneric3(Generic(NotCopy));
|
||||
let x = x.clone();
|
||||
//^ &AssocGeneric3<Copy>
|
||||
//^ &'? AssocGeneric3<Copy>
|
||||
let x = (&R1(Vec())).clone();
|
||||
//^ R1
|
||||
let x = (&R2(R1(Vec()))).clone();
|
||||
|
@ -4582,7 +4583,7 @@ impl B for u16 {
|
|||
fn ttt() {
|
||||
let inp = Y;
|
||||
x::<u16>(&inp);
|
||||
//^^^^ expected &X, got &Y
|
||||
//^^^^ expected &'? X, got &'? Y
|
||||
}
|
||||
"#,
|
||||
);
|
||||
|
@ -4629,7 +4630,7 @@ fn foo() {
|
|||
let mut map = SomeMap;
|
||||
map["a"] = ();
|
||||
map;
|
||||
//^^^ SomeMap<&str>
|
||||
//^^^ SomeMap<&'static str>
|
||||
}
|
||||
"#,
|
||||
);
|
||||
|
@ -4764,3 +4765,62 @@ fn test() {
|
|||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn associated_type_with_impl_trait_in_tuple() {
|
||||
check_no_mismatches(
|
||||
r#"
|
||||
pub trait Iterator {
|
||||
type Item;
|
||||
}
|
||||
|
||||
pub trait Value {}
|
||||
|
||||
fn bar<I: Iterator<Item = (usize, impl Value)>>() {}
|
||||
|
||||
fn foo() {
|
||||
bar();
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn associated_type_with_impl_trait_in_nested_tuple() {
|
||||
check_no_mismatches(
|
||||
r#"
|
||||
pub trait Iterator {
|
||||
type Item;
|
||||
}
|
||||
|
||||
pub trait Value {}
|
||||
|
||||
fn bar<I: Iterator<Item = ((impl Value, usize), u32)>>() {}
|
||||
|
||||
fn foo() {
|
||||
bar();
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn dyn_trait_with_lifetime_in_rpit() {
|
||||
check_types(
|
||||
r#"
|
||||
//- minicore: future
|
||||
pub struct Box<T> {}
|
||||
|
||||
trait Trait {}
|
||||
|
||||
pub async fn foo_async<'a>() -> Box<dyn Trait + 'a> {
|
||||
Box {}
|
||||
}
|
||||
|
||||
fn foo() {
|
||||
foo_async();
|
||||
//^^^^^^^^^^^impl Future<Output = Box<dyn Trait>> + ?Sized
|
||||
}
|
||||
"#,
|
||||
)
|
||||
}
|
||||
|
|
|
@ -9,9 +9,11 @@ use hir_ty::{db::HirDatabase, diagnostics::BodyValidationDiagnostic, InferenceDi
|
|||
use base_db::CrateId;
|
||||
use cfg::{CfgExpr, CfgOptions};
|
||||
use either::Either;
|
||||
pub use hir_def::VariantId;
|
||||
use hir_def::{body::SyntheticSyntax, hir::ExprOrPatId, path::ModPath, AssocItemId, DefWithBodyId};
|
||||
use hir_expand::{name::Name, HirFileId, InFile};
|
||||
use syntax::{ast, AstPtr, SyntaxError, SyntaxNodePtr, TextRange};
|
||||
use triomphe::Arc;
|
||||
|
||||
use crate::{AssocItem, Field, Local, MacroKind, Trait, Type};
|
||||
|
||||
|
@ -171,7 +173,7 @@ pub struct MacroError {
|
|||
pub struct MacroExpansionParseError {
|
||||
pub node: InFile<SyntaxNodePtr>,
|
||||
pub precise_location: Option<TextRange>,
|
||||
pub errors: Box<[SyntaxError]>,
|
||||
pub errors: Arc<[SyntaxError]>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
|
@ -200,6 +202,7 @@ pub struct MalformedDerive {
|
|||
pub struct NoSuchField {
|
||||
pub field: InFile<AstPtr<Either<ast::RecordExprField, ast::RecordPatField>>>,
|
||||
pub private: bool,
|
||||
pub variant: VariantId,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -525,7 +528,7 @@ impl AnyDiagnostic {
|
|||
source_map.pat_syntax(pat).inspect_err(|_| tracing::error!("synthetic syntax")).ok()
|
||||
};
|
||||
Some(match d {
|
||||
&InferenceDiagnostic::NoSuchField { field: expr, private } => {
|
||||
&InferenceDiagnostic::NoSuchField { field: expr, private, variant } => {
|
||||
let expr_or_pat = match expr {
|
||||
ExprOrPatId::ExprId(expr) => {
|
||||
source_map.field_syntax(expr).map(AstPtr::wrap_left)
|
||||
|
@ -534,7 +537,7 @@ impl AnyDiagnostic {
|
|||
source_map.pat_field_syntax(pat).map(AstPtr::wrap_right)
|
||||
}
|
||||
};
|
||||
NoSuchField { field: expr_or_pat, private }.into()
|
||||
NoSuchField { field: expr_or_pat, private, variant }.into()
|
||||
}
|
||||
&InferenceDiagnostic::MismatchedArgCount { call_expr, expected, found } => {
|
||||
MismatchedArgCount { call_expr: expr_syntax(call_expr)?, expected, found }.into()
|
||||
|
|
|
@ -188,28 +188,7 @@ impl HirDisplay for Struct {
|
|||
StructKind::Record => {
|
||||
let has_where_clause = write_where_clause(def_id, f)?;
|
||||
if let Some(limit) = f.entity_limit {
|
||||
let fields = self.fields(f.db);
|
||||
let count = fields.len().min(limit);
|
||||
f.write_char(if !has_where_clause { ' ' } else { '\n' })?;
|
||||
if count == 0 {
|
||||
if fields.is_empty() {
|
||||
f.write_str("{}")?;
|
||||
} else {
|
||||
f.write_str("{ /* … */ }")?;
|
||||
}
|
||||
} else {
|
||||
f.write_str(" {\n")?;
|
||||
for field in &fields[..count] {
|
||||
f.write_str(" ")?;
|
||||
field.hir_fmt(f)?;
|
||||
f.write_str(",\n")?;
|
||||
}
|
||||
|
||||
if fields.len() > count {
|
||||
f.write_str(" /* … */\n")?;
|
||||
}
|
||||
f.write_str("}")?;
|
||||
}
|
||||
display_fields(&self.fields(f.db), has_where_clause, limit, false, f)?;
|
||||
}
|
||||
}
|
||||
StructKind::Unit => _ = write_where_clause(def_id, f)?,
|
||||
|
@ -226,18 +205,10 @@ impl HirDisplay for Enum {
|
|||
write!(f, "{}", self.name(f.db).display(f.db.upcast()))?;
|
||||
let def_id = GenericDefId::AdtId(AdtId::EnumId(self.id));
|
||||
write_generic_params(def_id, f)?;
|
||||
let has_where_clause = write_where_clause(def_id, f)?;
|
||||
|
||||
let variants = self.variants(f.db);
|
||||
if !variants.is_empty() {
|
||||
f.write_char(if !has_where_clause { ' ' } else { '\n' })?;
|
||||
f.write_str("{\n")?;
|
||||
for variant in variants {
|
||||
f.write_str(" ")?;
|
||||
variant.hir_fmt(f)?;
|
||||
f.write_str(",\n")?;
|
||||
}
|
||||
f.write_str("}")?;
|
||||
let has_where_clause = write_where_clause(def_id, f)?;
|
||||
if let Some(limit) = f.entity_limit {
|
||||
display_variants(&self.variants(f.db), has_where_clause, limit, f)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
@ -251,24 +222,104 @@ impl HirDisplay for Union {
|
|||
write!(f, "{}", self.name(f.db).display(f.db.upcast()))?;
|
||||
let def_id = GenericDefId::AdtId(AdtId::UnionId(self.id));
|
||||
write_generic_params(def_id, f)?;
|
||||
|
||||
let has_where_clause = write_where_clause(def_id, f)?;
|
||||
|
||||
let fields = self.fields(f.db);
|
||||
if !fields.is_empty() {
|
||||
f.write_char(if !has_where_clause { ' ' } else { '\n' })?;
|
||||
f.write_str("{\n")?;
|
||||
for field in self.fields(f.db) {
|
||||
f.write_str(" ")?;
|
||||
field.hir_fmt(f)?;
|
||||
f.write_str(",\n")?;
|
||||
}
|
||||
f.write_str("}")?;
|
||||
if let Some(limit) = f.entity_limit {
|
||||
display_fields(&self.fields(f.db), has_where_clause, limit, false, f)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn display_fields(
|
||||
fields: &[Field],
|
||||
has_where_clause: bool,
|
||||
limit: usize,
|
||||
in_line: bool,
|
||||
f: &mut HirFormatter<'_>,
|
||||
) -> Result<(), HirDisplayError> {
|
||||
let count = fields.len().min(limit);
|
||||
let (indent, separator) = if in_line { ("", ' ') } else { (" ", '\n') };
|
||||
f.write_char(if !has_where_clause { ' ' } else { separator })?;
|
||||
if count == 0 {
|
||||
if fields.is_empty() {
|
||||
f.write_str("{}")?;
|
||||
} else {
|
||||
f.write_str("{ /* … */ }")?;
|
||||
}
|
||||
} else {
|
||||
f.write_char('{')?;
|
||||
|
||||
if !fields.is_empty() {
|
||||
f.write_char(separator)?;
|
||||
for field in &fields[..count] {
|
||||
f.write_str(indent)?;
|
||||
field.hir_fmt(f)?;
|
||||
f.write_char(',')?;
|
||||
f.write_char(separator)?;
|
||||
}
|
||||
|
||||
if fields.len() > count {
|
||||
f.write_str(indent)?;
|
||||
f.write_str("/* … */")?;
|
||||
f.write_char(separator)?;
|
||||
}
|
||||
}
|
||||
|
||||
f.write_str("}")?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn display_variants(
|
||||
variants: &[Variant],
|
||||
has_where_clause: bool,
|
||||
limit: usize,
|
||||
f: &mut HirFormatter<'_>,
|
||||
) -> Result<(), HirDisplayError> {
|
||||
let count = variants.len().min(limit);
|
||||
f.write_char(if !has_where_clause { ' ' } else { '\n' })?;
|
||||
if count == 0 {
|
||||
if variants.is_empty() {
|
||||
f.write_str("{}")?;
|
||||
} else {
|
||||
f.write_str("{ /* … */ }")?;
|
||||
}
|
||||
} else {
|
||||
f.write_str("{\n")?;
|
||||
for variant in &variants[..count] {
|
||||
f.write_str(" ")?;
|
||||
write!(f, "{}", variant.name(f.db).display(f.db.upcast()))?;
|
||||
match variant.kind(f.db) {
|
||||
StructKind::Tuple => {
|
||||
if variant.fields(f.db).is_empty() {
|
||||
f.write_str("()")?;
|
||||
} else {
|
||||
f.write_str("( /* … */ )")?;
|
||||
}
|
||||
}
|
||||
StructKind::Record => {
|
||||
if variant.fields(f.db).is_empty() {
|
||||
f.write_str(" {}")?;
|
||||
} else {
|
||||
f.write_str(" { /* … */ }")?;
|
||||
}
|
||||
}
|
||||
StructKind::Unit => {}
|
||||
}
|
||||
f.write_str(",\n")?;
|
||||
}
|
||||
|
||||
if variants.len() > count {
|
||||
f.write_str(" /* … */\n")?;
|
||||
}
|
||||
f.write_str("}")?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
impl HirDisplay for Field {
|
||||
fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
|
||||
write_visibility(self.parent.module(f.db).id, self.visibility(f.db), f)?;
|
||||
|
@ -304,21 +355,10 @@ impl HirDisplay for Variant {
|
|||
}
|
||||
f.write_char(')')?;
|
||||
}
|
||||
VariantData::Record(fields) => {
|
||||
f.write_str(" {")?;
|
||||
let mut first = true;
|
||||
for (_, field) in fields.iter() {
|
||||
if first {
|
||||
first = false;
|
||||
f.write_char(' ')?;
|
||||
} else {
|
||||
f.write_str(", ")?;
|
||||
}
|
||||
// Enum variant fields must be pub.
|
||||
write!(f, "{}: ", field.name.display(f.db.upcast()))?;
|
||||
field.type_ref.hir_fmt(f)?;
|
||||
VariantData::Record(_) => {
|
||||
if let Some(limit) = f.entity_limit {
|
||||
display_fields(&self.fields(f.db), false, limit, true, f)?;
|
||||
}
|
||||
f.write_str(" }")?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
|
|
|
@ -59,7 +59,9 @@ use hir_def::{
|
|||
ModuleId, StaticId, StructId, TraitAliasId, TraitId, TupleId, TypeAliasId, TypeOrConstParamId,
|
||||
TypeParamId, UnionId,
|
||||
};
|
||||
use hir_expand::{attrs::collect_attrs, name::name, proc_macro::ProcMacroKind, MacroCallKind};
|
||||
use hir_expand::{
|
||||
attrs::collect_attrs, name::name, proc_macro::ProcMacroKind, AstId, MacroCallKind, ValueResult,
|
||||
};
|
||||
use hir_ty::{
|
||||
all_super_traits, autoderef, check_orphan_rules,
|
||||
consteval::{try_const_usize, unknown_const_as_generic, ConstExt},
|
||||
|
@ -79,7 +81,7 @@ use hir_ty::{
|
|||
use itertools::Itertools;
|
||||
use nameres::diagnostics::DefDiagnosticKind;
|
||||
use rustc_hash::FxHashSet;
|
||||
use span::Edition;
|
||||
use span::{Edition, MacroCallId};
|
||||
use stdx::{impl_from, never};
|
||||
use syntax::{
|
||||
ast::{self, HasAttrs as _, HasName},
|
||||
|
@ -559,6 +561,12 @@ impl Module {
|
|||
emit_def_diagnostic(db, acc, diag);
|
||||
}
|
||||
|
||||
if !self.id.is_block_module() {
|
||||
// These are reported by the body of block modules
|
||||
let scope = &def_map[self.id.local_id].scope;
|
||||
scope.all_macro_calls().for_each(|it| macro_call_diagnostics(db, it, acc));
|
||||
}
|
||||
|
||||
for def in self.declarations(db) {
|
||||
match def {
|
||||
ModuleDef::Module(m) => {
|
||||
|
@ -577,6 +585,10 @@ impl Module {
|
|||
item.diagnostics(db, acc, style_lints);
|
||||
}
|
||||
|
||||
t.all_macro_calls(db)
|
||||
.iter()
|
||||
.for_each(|&(_ast, call_id)| macro_call_diagnostics(db, call_id, acc));
|
||||
|
||||
acc.extend(def.diagnostics(db, style_lints))
|
||||
}
|
||||
ModuleDef::Adt(adt) => {
|
||||
|
@ -621,6 +633,11 @@ impl Module {
|
|||
// FIXME: Once we diagnose the inputs to builtin derives, we should at least extract those diagnostics somehow
|
||||
continue;
|
||||
}
|
||||
impl_def
|
||||
.all_macro_calls(db)
|
||||
.iter()
|
||||
.for_each(|&(_ast, call_id)| macro_call_diagnostics(db, call_id, acc));
|
||||
|
||||
let ast_id_map = db.ast_id_map(file_id);
|
||||
|
||||
for diag in db.impl_data_with_diagnostics(impl_def.id).1.iter() {
|
||||
|
@ -809,6 +826,37 @@ impl Module {
|
|||
}
|
||||
}
|
||||
|
||||
fn macro_call_diagnostics(
|
||||
db: &dyn HirDatabase,
|
||||
macro_call_id: MacroCallId,
|
||||
acc: &mut Vec<AnyDiagnostic>,
|
||||
) {
|
||||
let Some(e) = db.parse_macro_expansion_error(macro_call_id) else {
|
||||
return;
|
||||
};
|
||||
let ValueResult { value: parse_errors, err } = &*e;
|
||||
if let Some(err) = err {
|
||||
let loc = db.lookup_intern_macro_call(macro_call_id);
|
||||
let (node, precise_location, macro_name, kind) = precise_macro_call_location(&loc.kind, db);
|
||||
let diag = match err {
|
||||
&hir_expand::ExpandError::UnresolvedProcMacro(krate) => {
|
||||
UnresolvedProcMacro { node, precise_location, macro_name, kind, krate }.into()
|
||||
}
|
||||
err => MacroError { node, precise_location, message: err.to_string() }.into(),
|
||||
};
|
||||
acc.push(diag);
|
||||
}
|
||||
|
||||
if !parse_errors.is_empty() {
|
||||
let loc = db.lookup_intern_macro_call(macro_call_id);
|
||||
let (node, precise_location, _, _) = precise_macro_call_location(&loc.kind, db);
|
||||
acc.push(
|
||||
MacroExpansionParseError { node, precise_location, errors: parse_errors.clone() }
|
||||
.into(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fn emit_macro_def_diagnostics(db: &dyn HirDatabase, acc: &mut Vec<AnyDiagnostic>, m: Macro) {
|
||||
let id = db.macro_def(m.id);
|
||||
if let hir_expand::db::TokenExpander::DeclarativeMacro(expander) = db.macro_expander(id) {
|
||||
|
@ -888,16 +936,6 @@ fn emit_def_diagnostic_(
|
|||
.into(),
|
||||
);
|
||||
}
|
||||
DefDiagnosticKind::MacroError { ast, message } => {
|
||||
let (node, precise_location, _, _) = precise_macro_call_location(ast, db);
|
||||
acc.push(MacroError { node, precise_location, message: message.clone() }.into());
|
||||
}
|
||||
DefDiagnosticKind::MacroExpansionParseError { ast, errors } => {
|
||||
let (node, precise_location, _, _) = precise_macro_call_location(ast, db);
|
||||
acc.push(
|
||||
MacroExpansionParseError { node, precise_location, errors: errors.clone() }.into(),
|
||||
);
|
||||
}
|
||||
DefDiagnosticKind::UnimplementedBuiltinMacro { ast } => {
|
||||
let node = ast.to_node(db.upcast());
|
||||
// Must have a name, otherwise we wouldn't emit it.
|
||||
|
@ -1489,6 +1527,14 @@ impl Adt {
|
|||
.map(|arena| arena.1.clone())
|
||||
}
|
||||
|
||||
pub fn as_struct(&self) -> Option<Struct> {
|
||||
if let Self::Struct(v) = self {
|
||||
Some(*v)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_enum(&self) -> Option<Enum> {
|
||||
if let Self::Enum(v) = self {
|
||||
Some(*v)
|
||||
|
@ -1636,6 +1682,10 @@ impl DefWithBody {
|
|||
Module { id: def_map.module_id(DefMap::ROOT) }.diagnostics(db, acc, style_lints);
|
||||
}
|
||||
|
||||
source_map
|
||||
.macro_calls()
|
||||
.for_each(|(_ast_id, call_id)| macro_call_diagnostics(db, call_id.macro_call_id, acc));
|
||||
|
||||
for diag in source_map.diagnostics() {
|
||||
acc.push(match diag {
|
||||
BodyDiagnostic::InactiveCode { node, cfg, opts } => {
|
||||
|
@ -2437,6 +2487,14 @@ impl Trait {
|
|||
.filter(|(_, ty)| !count_required_only || !ty.has_default())
|
||||
.count()
|
||||
}
|
||||
|
||||
fn all_macro_calls(&self, db: &dyn HirDatabase) -> Box<[(AstId<ast::Item>, MacroCallId)]> {
|
||||
db.trait_data(self.id)
|
||||
.macro_calls
|
||||
.as_ref()
|
||||
.map(|it| it.as_ref().clone().into_boxed_slice())
|
||||
.unwrap_or_default()
|
||||
}
|
||||
}
|
||||
|
||||
impl HasVisibility for Trait {
|
||||
|
@ -2505,6 +2563,15 @@ impl HasVisibility for TypeAlias {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub struct StaticLifetime;
|
||||
|
||||
impl StaticLifetime {
|
||||
pub fn name(self) -> Name {
|
||||
known::STATIC_LIFETIME
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub struct BuiltinType {
|
||||
pub(crate) inner: hir_def::builtin_type::BuiltinType,
|
||||
|
@ -2535,6 +2602,20 @@ impl BuiltinType {
|
|||
matches!(self.inner, hir_def::builtin_type::BuiltinType::Float(_))
|
||||
}
|
||||
|
||||
pub fn is_f32(&self) -> bool {
|
||||
matches!(
|
||||
self.inner,
|
||||
hir_def::builtin_type::BuiltinType::Float(hir_def::builtin_type::BuiltinFloat::F32)
|
||||
)
|
||||
}
|
||||
|
||||
pub fn is_f64(&self) -> bool {
|
||||
matches!(
|
||||
self.inner,
|
||||
hir_def::builtin_type::BuiltinType::Float(hir_def::builtin_type::BuiltinFloat::F64)
|
||||
)
|
||||
}
|
||||
|
||||
pub fn is_char(&self) -> bool {
|
||||
matches!(self.inner, hir_def::builtin_type::BuiltinType::Char)
|
||||
}
|
||||
|
@ -3743,6 +3824,14 @@ impl Impl {
|
|||
pub fn check_orphan_rules(self, db: &dyn HirDatabase) -> bool {
|
||||
check_orphan_rules(db, self.id)
|
||||
}
|
||||
|
||||
fn all_macro_calls(&self, db: &dyn HirDatabase) -> Box<[(AstId<ast::Item>, MacroCallId)]> {
|
||||
db.impl_data(self.id)
|
||||
.macro_calls
|
||||
.as_ref()
|
||||
.map(|it| it.as_ref().clone().into_boxed_slice())
|
||||
.unwrap_or_default()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
|
||||
|
@ -4495,7 +4584,8 @@ impl Type {
|
|||
name: Option<&Name>,
|
||||
mut callback: impl FnMut(Function) -> Option<T>,
|
||||
) -> Option<T> {
|
||||
let _p = tracing::span!(tracing::Level::INFO, "iterate_method_candidates").entered();
|
||||
let _p =
|
||||
tracing::span!(tracing::Level::INFO, "iterate_method_candidates_with_traits").entered();
|
||||
let mut slot = None;
|
||||
|
||||
self.iterate_method_candidates_dyn(
|
||||
|
|
|
@ -131,7 +131,7 @@ pub struct SemanticsImpl<'db> {
|
|||
pub db: &'db dyn HirDatabase,
|
||||
s2d_cache: RefCell<SourceToDefCache>,
|
||||
/// Rootnode to HirFileId cache
|
||||
cache: RefCell<FxHashMap<SyntaxNode, HirFileId>>,
|
||||
root_to_file_cache: RefCell<FxHashMap<SyntaxNode, HirFileId>>,
|
||||
// These 2 caches are mainly useful for semantic highlighting as nothing else descends a lot of tokens
|
||||
// So we might wanna move them out into something specific for semantic highlighting
|
||||
expansion_info_cache: RefCell<FxHashMap<MacroFileId, ExpansionInfo>>,
|
||||
|
@ -294,7 +294,7 @@ impl<'db> SemanticsImpl<'db> {
|
|||
SemanticsImpl {
|
||||
db,
|
||||
s2d_cache: Default::default(),
|
||||
cache: Default::default(),
|
||||
root_to_file_cache: Default::default(),
|
||||
expansion_info_cache: Default::default(),
|
||||
macro_call_cache: Default::default(),
|
||||
}
|
||||
|
@ -690,6 +690,7 @@ impl<'db> SemanticsImpl<'db> {
|
|||
exp_info
|
||||
});
|
||||
|
||||
// FIXME: uncached parse
|
||||
// Create the source analyzer for the macro call scope
|
||||
let Some(sa) = self.analyze_no_infer(&self.parse_or_expand(expansion_info.call_file()))
|
||||
else {
|
||||
|
@ -722,7 +723,7 @@ impl<'db> SemanticsImpl<'db> {
|
|||
mut token: SyntaxToken,
|
||||
f: &mut dyn FnMut(InFile<SyntaxToken>) -> ControlFlow<()>,
|
||||
) {
|
||||
let _p = tracing::span!(tracing::Level::INFO, "descend_into_macros").entered();
|
||||
let _p = tracing::span!(tracing::Level::INFO, "descend_into_macros_impl").entered();
|
||||
let (sa, span, file_id) =
|
||||
match token.parent().and_then(|parent| self.analyze_no_infer(&parent)) {
|
||||
Some(sa) => match sa.file_id.file_id() {
|
||||
|
@ -1025,6 +1026,7 @@ impl<'db> SemanticsImpl<'db> {
|
|||
None => {
|
||||
let call_node = file_id.macro_file()?.call_node(db);
|
||||
// cache the node
|
||||
// FIXME: uncached parse
|
||||
self.parse_or_expand(call_node.file_id);
|
||||
Some(call_node)
|
||||
}
|
||||
|
@ -1370,7 +1372,7 @@ impl<'db> SemanticsImpl<'db> {
|
|||
offset: Option<TextSize>,
|
||||
infer_body: bool,
|
||||
) -> Option<SourceAnalyzer> {
|
||||
let _p = tracing::span!(tracing::Level::INFO, "Semantics::analyze_impl").entered();
|
||||
let _p = tracing::span!(tracing::Level::INFO, "SemanticsImpl::analyze_impl").entered();
|
||||
let node = self.find_file(node);
|
||||
|
||||
let container = self.with_ctx(|ctx| ctx.find_container(node))?;
|
||||
|
@ -1397,7 +1399,7 @@ impl<'db> SemanticsImpl<'db> {
|
|||
|
||||
fn cache(&self, root_node: SyntaxNode, file_id: HirFileId) {
|
||||
assert!(root_node.parent().is_none());
|
||||
let mut cache = self.cache.borrow_mut();
|
||||
let mut cache = self.root_to_file_cache.borrow_mut();
|
||||
let prev = cache.insert(root_node, file_id);
|
||||
assert!(prev.is_none() || prev == Some(file_id))
|
||||
}
|
||||
|
@ -1407,7 +1409,7 @@ impl<'db> SemanticsImpl<'db> {
|
|||
}
|
||||
|
||||
fn lookup(&self, root_node: &SyntaxNode) -> Option<HirFileId> {
|
||||
let cache = self.cache.borrow();
|
||||
let cache = self.root_to_file_cache.borrow();
|
||||
cache.get(root_node).copied()
|
||||
}
|
||||
|
||||
|
@ -1427,7 +1429,7 @@ impl<'db> SemanticsImpl<'db> {
|
|||
known nodes: {}\n\n",
|
||||
node,
|
||||
root_node,
|
||||
self.cache
|
||||
self.root_to_file_cache
|
||||
.borrow()
|
||||
.keys()
|
||||
.map(|it| format!("{it:?}"))
|
||||
|
|
|
@ -118,10 +118,10 @@ 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::file_to_module_def").entered();
|
||||
let _p = tracing::span!(tracing::Level::INFO, "SourceToDefCtx::file_to_def").entered();
|
||||
let mut mods = SmallVec::new();
|
||||
for &crate_id in self.db.relevant_crates(file).iter() {
|
||||
// FIXME: inner items
|
||||
// Note: `mod` declarations in block modules cannot be supported here
|
||||
let crate_def_map = self.db.crate_def_map(crate_id);
|
||||
mods.extend(
|
||||
crate_def_map
|
||||
|
@ -129,6 +129,9 @@ impl SourceToDefCtx<'_, '_> {
|
|||
.map(|local_id| crate_def_map.module_id(local_id)),
|
||||
)
|
||||
}
|
||||
if mods.is_empty() {
|
||||
// FIXME: detached file
|
||||
}
|
||||
mods
|
||||
}
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@ use hir_expand::{
|
|||
mod_path::path,
|
||||
name,
|
||||
name::{AsName, Name},
|
||||
HirFileId, InFile, MacroFileId, MacroFileIdExt,
|
||||
HirFileId, InFile, InMacroFile, MacroFileId, MacroFileIdExt,
|
||||
};
|
||||
use hir_ty::{
|
||||
diagnostics::{
|
||||
|
@ -118,7 +118,7 @@ impl SourceAnalyzer {
|
|||
fn expr_id(&self, db: &dyn HirDatabase, expr: &ast::Expr) -> Option<ExprId> {
|
||||
let src = match expr {
|
||||
ast::Expr::MacroExpr(expr) => {
|
||||
self.expand_expr(db, InFile::new(self.file_id, expr.macro_call()?))?
|
||||
self.expand_expr(db, InFile::new(self.file_id, expr.macro_call()?))?.into()
|
||||
}
|
||||
_ => InFile::new(self.file_id, expr.clone()),
|
||||
};
|
||||
|
@ -145,20 +145,20 @@ impl SourceAnalyzer {
|
|||
&self,
|
||||
db: &dyn HirDatabase,
|
||||
expr: InFile<ast::MacroCall>,
|
||||
) -> Option<InFile<ast::Expr>> {
|
||||
) -> Option<InMacroFile<ast::Expr>> {
|
||||
let macro_file = self.body_source_map()?.node_macro_file(expr.as_ref())?;
|
||||
let expanded = db.parse_or_expand(macro_file);
|
||||
let expanded = db.parse_macro_expansion(macro_file).value.0.syntax_node();
|
||||
let res = if let Some(stmts) = ast::MacroStmts::cast(expanded.clone()) {
|
||||
match stmts.expr()? {
|
||||
ast::Expr::MacroExpr(mac) => {
|
||||
self.expand_expr(db, InFile::new(macro_file, mac.macro_call()?))?
|
||||
self.expand_expr(db, InFile::new(macro_file.into(), mac.macro_call()?))?
|
||||
}
|
||||
expr => InFile::new(macro_file, expr),
|
||||
expr => InMacroFile::new(macro_file, expr),
|
||||
}
|
||||
} else if let Some(call) = ast::MacroCall::cast(expanded.clone()) {
|
||||
self.expand_expr(db, InFile::new(macro_file, call))?
|
||||
self.expand_expr(db, InFile::new(macro_file.into(), call))?
|
||||
} else {
|
||||
InFile::new(macro_file, ast::Expr::cast(expanded)?)
|
||||
InMacroFile::new(macro_file, ast::Expr::cast(expanded)?)
|
||||
};
|
||||
|
||||
Some(res)
|
||||
|
|
|
@ -127,6 +127,13 @@ impl LookupTable {
|
|||
self.types_wishlist.insert(ty.clone());
|
||||
}
|
||||
|
||||
// Collapse suggestions if there are many
|
||||
if let Some(res) = &res {
|
||||
if res.len() > self.many_threshold {
|
||||
return Some(vec![Expr::Many(ty.clone())]);
|
||||
}
|
||||
}
|
||||
|
||||
res
|
||||
}
|
||||
|
||||
|
@ -158,6 +165,13 @@ impl LookupTable {
|
|||
self.types_wishlist.insert(ty.clone());
|
||||
}
|
||||
|
||||
// Collapse suggestions if there are many
|
||||
if let Some(res) = &res {
|
||||
if res.len() > self.many_threshold {
|
||||
return Some(vec![Expr::Many(ty.clone())]);
|
||||
}
|
||||
}
|
||||
|
||||
res
|
||||
}
|
||||
|
||||
|
@ -255,13 +269,13 @@ pub struct TermSearchConfig {
|
|||
pub enable_borrowcheck: bool,
|
||||
/// Indicate when to squash multiple trees to `Many` as there are too many to keep track
|
||||
pub many_alternatives_threshold: usize,
|
||||
/// Depth of the search eg. number of cycles to run
|
||||
pub depth: usize,
|
||||
/// Fuel for term search in "units of work"
|
||||
pub fuel: u64,
|
||||
}
|
||||
|
||||
impl Default for TermSearchConfig {
|
||||
fn default() -> Self {
|
||||
Self { enable_borrowcheck: true, many_alternatives_threshold: 1, depth: 6 }
|
||||
Self { enable_borrowcheck: true, many_alternatives_threshold: 1, fuel: 400 }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -280,8 +294,7 @@ impl Default for TermSearchConfig {
|
|||
/// transformation tactics. For example functions take as from set of types (arguments) to some
|
||||
/// type (return type). Other transformations include methods on type, type constructors and
|
||||
/// projections to struct fields (field access).
|
||||
/// 3. Once we manage to find path to type we are interested in we continue for single round to see
|
||||
/// if we can find more paths that take us to the `goal` type.
|
||||
/// 3. If we run out of fuel (term search takes too long) we stop iterating.
|
||||
/// 4. Return all the paths (type trees) that take us to the `goal` type.
|
||||
///
|
||||
/// Note that there are usually more ways we can get to the `goal` type but some are discarded to
|
||||
|
@ -297,21 +310,31 @@ pub fn term_search<DB: HirDatabase>(ctx: &TermSearchCtx<'_, DB>) -> Vec<Expr> {
|
|||
});
|
||||
|
||||
let mut lookup = LookupTable::new(ctx.config.many_alternatives_threshold, ctx.goal.clone());
|
||||
let fuel = std::cell::Cell::new(ctx.config.fuel);
|
||||
|
||||
let should_continue = &|| {
|
||||
let remaining = fuel.get();
|
||||
fuel.set(remaining.saturating_sub(1));
|
||||
if remaining == 0 {
|
||||
tracing::debug!("fuel exhausted");
|
||||
}
|
||||
remaining > 0
|
||||
};
|
||||
|
||||
// Try trivial tactic first, also populates lookup table
|
||||
let mut solutions: Vec<Expr> = tactics::trivial(ctx, &defs, &mut lookup).collect();
|
||||
// Use well known types tactic before iterations as it does not depend on other tactics
|
||||
solutions.extend(tactics::famous_types(ctx, &defs, &mut lookup));
|
||||
|
||||
for _ in 0..ctx.config.depth {
|
||||
while should_continue() {
|
||||
lookup.new_round();
|
||||
|
||||
solutions.extend(tactics::type_constructor(ctx, &defs, &mut lookup));
|
||||
solutions.extend(tactics::free_function(ctx, &defs, &mut lookup));
|
||||
solutions.extend(tactics::impl_method(ctx, &defs, &mut lookup));
|
||||
solutions.extend(tactics::struct_projection(ctx, &defs, &mut lookup));
|
||||
solutions.extend(tactics::impl_static_method(ctx, &defs, &mut lookup));
|
||||
solutions.extend(tactics::make_tuple(ctx, &defs, &mut lookup));
|
||||
solutions.extend(tactics::type_constructor(ctx, &defs, &mut lookup, should_continue));
|
||||
solutions.extend(tactics::free_function(ctx, &defs, &mut lookup, should_continue));
|
||||
solutions.extend(tactics::impl_method(ctx, &defs, &mut lookup, should_continue));
|
||||
solutions.extend(tactics::struct_projection(ctx, &defs, &mut lookup, should_continue));
|
||||
solutions.extend(tactics::impl_static_method(ctx, &defs, &mut lookup, should_continue));
|
||||
solutions.extend(tactics::make_tuple(ctx, &defs, &mut lookup, should_continue));
|
||||
|
||||
// Discard not interesting `ScopeDef`s for speedup
|
||||
for def in lookup.exhausted_scopedefs() {
|
||||
|
|
|
@ -211,13 +211,13 @@ impl Expr {
|
|||
}
|
||||
}
|
||||
Expr::Method { func, target, params, .. } => {
|
||||
if target.contains_many_in_illegal_pos() {
|
||||
if self.contains_many_in_illegal_pos(db) {
|
||||
return Ok(many_formatter(&target.ty(db)));
|
||||
}
|
||||
|
||||
let func_name = func.name(db).display(db.upcast()).to_string();
|
||||
let self_param = func.self_param(db).unwrap();
|
||||
let target = target.gen_source_code(
|
||||
let target_str = target.gen_source_code(
|
||||
sema_scope,
|
||||
many_formatter,
|
||||
prefer_no_std,
|
||||
|
@ -236,9 +236,12 @@ impl Expr {
|
|||
Some(trait_) => {
|
||||
let trait_name = mod_item_path_str(sema_scope, &ModuleDef::Trait(trait_))?;
|
||||
let target = match self_param.access(db) {
|
||||
crate::Access::Shared => format!("&{target}"),
|
||||
crate::Access::Exclusive => format!("&mut {target}"),
|
||||
crate::Access::Owned => target,
|
||||
crate::Access::Shared if !target.is_many() => format!("&{target_str}"),
|
||||
crate::Access::Exclusive if !target.is_many() => {
|
||||
format!("&mut {target_str}")
|
||||
}
|
||||
crate::Access::Owned => target_str,
|
||||
_ => many_formatter(&target.ty(db)),
|
||||
};
|
||||
let res = match args.is_empty() {
|
||||
true => format!("{trait_name}::{func_name}({target})",),
|
||||
|
@ -246,7 +249,7 @@ impl Expr {
|
|||
};
|
||||
Ok(res)
|
||||
}
|
||||
None => Ok(format!("{target}.{func_name}({args})")),
|
||||
None => Ok(format!("{target_str}.{func_name}({args})")),
|
||||
}
|
||||
}
|
||||
Expr::Variant { variant, generics, params } => {
|
||||
|
@ -381,7 +384,7 @@ impl Expr {
|
|||
Ok(res)
|
||||
}
|
||||
Expr::Field { expr, field } => {
|
||||
if expr.contains_many_in_illegal_pos() {
|
||||
if expr.contains_many_in_illegal_pos(db) {
|
||||
return Ok(many_formatter(&expr.ty(db)));
|
||||
}
|
||||
|
||||
|
@ -395,7 +398,7 @@ impl Expr {
|
|||
Ok(format!("{strukt}.{field}"))
|
||||
}
|
||||
Expr::Reference(expr) => {
|
||||
if expr.contains_many_in_illegal_pos() {
|
||||
if expr.contains_many_in_illegal_pos(db) {
|
||||
return Ok(many_formatter(&expr.ty(db)));
|
||||
}
|
||||
|
||||
|
@ -466,10 +469,15 @@ impl Expr {
|
|||
/// macro!().bar()
|
||||
/// ¯o!()
|
||||
/// ```
|
||||
fn contains_many_in_illegal_pos(&self) -> bool {
|
||||
fn contains_many_in_illegal_pos(&self, db: &dyn HirDatabase) -> bool {
|
||||
match self {
|
||||
Expr::Method { target, .. } => target.contains_many_in_illegal_pos(),
|
||||
Expr::Field { expr, .. } => expr.contains_many_in_illegal_pos(),
|
||||
Expr::Method { target, func, .. } => {
|
||||
match func.as_assoc_item(db).and_then(|it| it.container_or_implemented_trait(db)) {
|
||||
Some(_) => false,
|
||||
None => target.is_many(),
|
||||
}
|
||||
}
|
||||
Expr::Field { expr, .. } => expr.contains_many_in_illegal_pos(db),
|
||||
Expr::Reference(target) => target.is_many(),
|
||||
Expr::Many(_) => true,
|
||||
_ => false,
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
//! * `ctx` - Context for the term search
|
||||
//! * `defs` - Set of items in scope at term search target location
|
||||
//! * `lookup` - Lookup table for types
|
||||
//! * `should_continue` - Function that indicates when to stop iterating
|
||||
//! And they return iterator that yields type trees that unify with the `goal` type.
|
||||
|
||||
use std::iter;
|
||||
|
@ -97,16 +98,19 @@ pub(super) fn trivial<'a, DB: HirDatabase>(
|
|||
/// * `ctx` - Context for the term search
|
||||
/// * `defs` - Set of items in scope at term search target location
|
||||
/// * `lookup` - Lookup table for types
|
||||
/// * `should_continue` - Function that indicates when to stop iterating
|
||||
pub(super) fn type_constructor<'a, DB: HirDatabase>(
|
||||
ctx: &'a TermSearchCtx<'a, DB>,
|
||||
defs: &'a FxHashSet<ScopeDef>,
|
||||
lookup: &'a mut LookupTable,
|
||||
should_continue: &'a dyn std::ops::Fn() -> bool,
|
||||
) -> impl Iterator<Item = Expr> + 'a {
|
||||
let db = ctx.sema.db;
|
||||
let module = ctx.scope.module();
|
||||
fn variant_helper(
|
||||
db: &dyn HirDatabase,
|
||||
lookup: &mut LookupTable,
|
||||
should_continue: &dyn std::ops::Fn() -> bool,
|
||||
parent_enum: Enum,
|
||||
variant: Variant,
|
||||
config: &TermSearchConfig,
|
||||
|
@ -152,6 +156,7 @@ pub(super) fn type_constructor<'a, DB: HirDatabase>(
|
|||
.chain((non_default_type_params_len == 0).then_some(Vec::new()));
|
||||
|
||||
generic_params
|
||||
.filter(|_| should_continue())
|
||||
.filter_map(move |generics| {
|
||||
// Insert default type params
|
||||
let mut g = generics.into_iter();
|
||||
|
@ -194,8 +199,14 @@ pub(super) fn type_constructor<'a, DB: HirDatabase>(
|
|||
defs.iter()
|
||||
.filter_map(move |def| match def {
|
||||
ScopeDef::ModuleDef(ModuleDef::Variant(it)) => {
|
||||
let variant_exprs =
|
||||
variant_helper(db, lookup, it.parent_enum(db), *it, &ctx.config);
|
||||
let variant_exprs = variant_helper(
|
||||
db,
|
||||
lookup,
|
||||
should_continue,
|
||||
it.parent_enum(db),
|
||||
*it,
|
||||
&ctx.config,
|
||||
);
|
||||
if variant_exprs.is_empty() {
|
||||
return None;
|
||||
}
|
||||
|
@ -213,7 +224,9 @@ pub(super) fn type_constructor<'a, DB: HirDatabase>(
|
|||
let exprs: Vec<(Type, Vec<Expr>)> = enum_
|
||||
.variants(db)
|
||||
.into_iter()
|
||||
.flat_map(|it| variant_helper(db, lookup, *enum_, it, &ctx.config))
|
||||
.flat_map(|it| {
|
||||
variant_helper(db, lookup, should_continue, *enum_, it, &ctx.config)
|
||||
})
|
||||
.collect();
|
||||
|
||||
if exprs.is_empty() {
|
||||
|
@ -271,6 +284,7 @@ pub(super) fn type_constructor<'a, DB: HirDatabase>(
|
|||
.chain((non_default_type_params_len == 0).then_some(Vec::new()));
|
||||
|
||||
let exprs = generic_params
|
||||
.filter(|_| should_continue())
|
||||
.filter_map(|generics| {
|
||||
// Insert default type params
|
||||
let mut g = generics.into_iter();
|
||||
|
@ -345,10 +359,12 @@ pub(super) fn type_constructor<'a, DB: HirDatabase>(
|
|||
/// * `ctx` - Context for the term search
|
||||
/// * `defs` - Set of items in scope at term search target location
|
||||
/// * `lookup` - Lookup table for types
|
||||
/// * `should_continue` - Function that indicates when to stop iterating
|
||||
pub(super) fn free_function<'a, DB: HirDatabase>(
|
||||
ctx: &'a TermSearchCtx<'a, DB>,
|
||||
defs: &'a FxHashSet<ScopeDef>,
|
||||
lookup: &'a mut LookupTable,
|
||||
should_continue: &'a dyn std::ops::Fn() -> bool,
|
||||
) -> impl Iterator<Item = Expr> + 'a {
|
||||
let db = ctx.sema.db;
|
||||
let module = ctx.scope.module();
|
||||
|
@ -390,6 +406,7 @@ pub(super) fn free_function<'a, DB: HirDatabase>(
|
|||
.permutations(non_default_type_params_len);
|
||||
|
||||
let exprs: Vec<_> = generic_params
|
||||
.filter(|_| should_continue())
|
||||
.filter_map(|generics| {
|
||||
// Insert default type params
|
||||
let mut g = generics.into_iter();
|
||||
|
@ -474,10 +491,12 @@ pub(super) fn free_function<'a, DB: HirDatabase>(
|
|||
/// * `ctx` - Context for the term search
|
||||
/// * `defs` - Set of items in scope at term search target location
|
||||
/// * `lookup` - Lookup table for types
|
||||
/// * `should_continue` - Function that indicates when to stop iterating
|
||||
pub(super) fn impl_method<'a, DB: HirDatabase>(
|
||||
ctx: &'a TermSearchCtx<'a, DB>,
|
||||
_defs: &'a FxHashSet<ScopeDef>,
|
||||
lookup: &'a mut LookupTable,
|
||||
should_continue: &'a dyn std::ops::Fn() -> bool,
|
||||
) -> impl Iterator<Item = Expr> + 'a {
|
||||
let db = ctx.sema.db;
|
||||
let module = ctx.scope.module();
|
||||
|
@ -554,6 +573,7 @@ pub(super) fn impl_method<'a, DB: HirDatabase>(
|
|||
.permutations(non_default_fn_type_params_len);
|
||||
|
||||
let exprs: Vec<_> = generic_params
|
||||
.filter(|_| should_continue())
|
||||
.filter_map(|generics| {
|
||||
// Insert default type params
|
||||
let mut g = generics.into_iter();
|
||||
|
@ -645,10 +665,12 @@ pub(super) fn impl_method<'a, DB: HirDatabase>(
|
|||
/// * `ctx` - Context for the term search
|
||||
/// * `defs` - Set of items in scope at term search target location
|
||||
/// * `lookup` - Lookup table for types
|
||||
/// * `should_continue` - Function that indicates when to stop iterating
|
||||
pub(super) fn struct_projection<'a, DB: HirDatabase>(
|
||||
ctx: &'a TermSearchCtx<'a, DB>,
|
||||
_defs: &'a FxHashSet<ScopeDef>,
|
||||
lookup: &'a mut LookupTable,
|
||||
should_continue: &'a dyn std::ops::Fn() -> bool,
|
||||
) -> impl Iterator<Item = Expr> + 'a {
|
||||
let db = ctx.sema.db;
|
||||
let module = ctx.scope.module();
|
||||
|
@ -656,6 +678,7 @@ pub(super) fn struct_projection<'a, DB: HirDatabase>(
|
|||
.new_types(NewTypesKey::StructProjection)
|
||||
.into_iter()
|
||||
.map(|ty| (ty.clone(), lookup.find(db, &ty).expect("Expr not in lookup")))
|
||||
.filter(|_| should_continue())
|
||||
.flat_map(move |(ty, targets)| {
|
||||
ty.fields(db).into_iter().filter_map(move |(field, filed_ty)| {
|
||||
if !field.is_visible_from(db, module) {
|
||||
|
@ -716,10 +739,12 @@ pub(super) fn famous_types<'a, DB: HirDatabase>(
|
|||
/// * `ctx` - Context for the term search
|
||||
/// * `defs` - Set of items in scope at term search target location
|
||||
/// * `lookup` - Lookup table for types
|
||||
/// * `should_continue` - Function that indicates when to stop iterating
|
||||
pub(super) fn impl_static_method<'a, DB: HirDatabase>(
|
||||
ctx: &'a TermSearchCtx<'a, DB>,
|
||||
_defs: &'a FxHashSet<ScopeDef>,
|
||||
lookup: &'a mut LookupTable,
|
||||
should_continue: &'a dyn std::ops::Fn() -> bool,
|
||||
) -> impl Iterator<Item = Expr> + 'a {
|
||||
let db = ctx.sema.db;
|
||||
let module = ctx.scope.module();
|
||||
|
@ -728,6 +753,7 @@ pub(super) fn impl_static_method<'a, DB: HirDatabase>(
|
|||
.clone()
|
||||
.into_iter()
|
||||
.chain(iter::once(ctx.goal.clone()))
|
||||
.filter(|_| should_continue())
|
||||
.flat_map(|ty| {
|
||||
Impl::all_for_type(db, ty.clone()).into_iter().map(move |imp| (ty.clone(), imp))
|
||||
})
|
||||
|
@ -801,6 +827,7 @@ pub(super) fn impl_static_method<'a, DB: HirDatabase>(
|
|||
.permutations(non_default_fn_type_params_len);
|
||||
|
||||
let exprs: Vec<_> = generic_params
|
||||
.filter(|_| should_continue())
|
||||
.filter_map(|generics| {
|
||||
// Insert default type params
|
||||
let mut g = generics.into_iter();
|
||||
|
@ -884,10 +911,12 @@ pub(super) fn impl_static_method<'a, DB: HirDatabase>(
|
|||
/// * `ctx` - Context for the term search
|
||||
/// * `defs` - Set of items in scope at term search target location
|
||||
/// * `lookup` - Lookup table for types
|
||||
/// * `should_continue` - Function that indicates when to stop iterating
|
||||
pub(super) fn make_tuple<'a, DB: HirDatabase>(
|
||||
ctx: &'a TermSearchCtx<'a, DB>,
|
||||
_defs: &'a FxHashSet<ScopeDef>,
|
||||
lookup: &'a mut LookupTable,
|
||||
should_continue: &'a dyn std::ops::Fn() -> bool,
|
||||
) -> impl Iterator<Item = Expr> + 'a {
|
||||
let db = ctx.sema.db;
|
||||
let module = ctx.scope.module();
|
||||
|
@ -896,6 +925,7 @@ pub(super) fn make_tuple<'a, DB: HirDatabase>(
|
|||
.types_wishlist()
|
||||
.clone()
|
||||
.into_iter()
|
||||
.filter(|_| should_continue())
|
||||
.filter(|ty| ty.is_tuple())
|
||||
.filter_map(move |ty| {
|
||||
// Double check to not contain unknown
|
||||
|
@ -915,6 +945,7 @@ pub(super) fn make_tuple<'a, DB: HirDatabase>(
|
|||
let exprs: Vec<Expr> = param_exprs
|
||||
.into_iter()
|
||||
.multi_cartesian_product()
|
||||
.filter(|_| should_continue())
|
||||
.map(|params| {
|
||||
let tys: Vec<Type> = params.iter().map(|it| it.ty(db)).collect();
|
||||
let tuple_ty = Type::new_tuple(module.krate().into(), &tys);
|
||||
|
|
|
@ -16,4 +16,5 @@ pub struct AssistConfig {
|
|||
pub prefer_no_std: bool,
|
||||
pub prefer_prelude: bool,
|
||||
pub assist_emit_must_use: bool,
|
||||
pub term_search_fuel: u64,
|
||||
}
|
||||
|
|
|
@ -8,8 +8,7 @@ use ide_db::{
|
|||
};
|
||||
use syntax::{
|
||||
ast::{self, make, AstNode, Expr::BinExpr, HasArgList},
|
||||
ted::{self, Position},
|
||||
SyntaxKind,
|
||||
ted, SyntaxKind, T,
|
||||
};
|
||||
|
||||
use crate::{utils::invert_boolean_expression, AssistContext, AssistId, AssistKind, Assists};
|
||||
|
@ -62,7 +61,7 @@ pub(crate) fn apply_demorgan(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opti
|
|||
let demorganed = bin_expr.clone_subtree().clone_for_update();
|
||||
|
||||
ted::replace(demorganed.op_token()?, ast::make::token(inv_token));
|
||||
let mut exprs = VecDeque::from(vec![
|
||||
let mut exprs = VecDeque::from([
|
||||
(bin_expr.lhs()?, demorganed.lhs()?),
|
||||
(bin_expr.rhs()?, demorganed.rhs()?),
|
||||
]);
|
||||
|
@ -93,58 +92,38 @@ pub(crate) fn apply_demorgan(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opti
|
|||
}
|
||||
}
|
||||
|
||||
let dm_lhs = demorganed.lhs()?;
|
||||
|
||||
acc.add_group(
|
||||
&GroupLabel("Apply De Morgan's law".to_owned()),
|
||||
AssistId("apply_demorgan", AssistKind::RefactorRewrite),
|
||||
"Apply De Morgan's law",
|
||||
op_range,
|
||||
|edit| {
|
||||
let demorganed = ast::Expr::BinExpr(demorganed);
|
||||
let paren_expr = bin_expr.syntax().parent().and_then(ast::ParenExpr::cast);
|
||||
let neg_expr = paren_expr
|
||||
.clone()
|
||||
.and_then(|paren_expr| paren_expr.syntax().parent())
|
||||
.and_then(ast::PrefixExpr::cast)
|
||||
.and_then(|prefix_expr| {
|
||||
if prefix_expr.op_kind()? == ast::UnaryOp::Not {
|
||||
Some(prefix_expr)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
});
|
||||
.filter(|prefix_expr| matches!(prefix_expr.op_kind(), Some(ast::UnaryOp::Not)))
|
||||
.map(ast::Expr::PrefixExpr);
|
||||
|
||||
if let Some(paren_expr) = paren_expr {
|
||||
if let Some(neg_expr) = neg_expr {
|
||||
cov_mark::hit!(demorgan_double_negation);
|
||||
edit.replace_ast(ast::Expr::PrefixExpr(neg_expr), demorganed.into());
|
||||
let parent = neg_expr.syntax().parent();
|
||||
|
||||
if parent.is_some_and(|parent| demorganed.needs_parens_in(parent)) {
|
||||
cov_mark::hit!(demorgan_keep_parens_for_op_precedence2);
|
||||
edit.replace_ast(neg_expr, make::expr_paren(demorganed));
|
||||
} else {
|
||||
edit.replace_ast(neg_expr, demorganed);
|
||||
};
|
||||
} else {
|
||||
cov_mark::hit!(demorgan_double_parens);
|
||||
ted::insert_all_raw(
|
||||
Position::before(dm_lhs.syntax()),
|
||||
vec![
|
||||
syntax::NodeOrToken::Token(ast::make::token(SyntaxKind::BANG)),
|
||||
syntax::NodeOrToken::Token(ast::make::token(SyntaxKind::L_PAREN)),
|
||||
],
|
||||
);
|
||||
|
||||
ted::append_child_raw(
|
||||
demorganed.syntax(),
|
||||
syntax::NodeOrToken::Token(ast::make::token(SyntaxKind::R_PAREN)),
|
||||
);
|
||||
|
||||
edit.replace_ast(ast::Expr::ParenExpr(paren_expr), demorganed.into());
|
||||
edit.replace_ast(paren_expr.into(), add_bang_paren(demorganed));
|
||||
}
|
||||
} else {
|
||||
ted::insert_all_raw(
|
||||
Position::before(dm_lhs.syntax()),
|
||||
vec![
|
||||
syntax::NodeOrToken::Token(ast::make::token(SyntaxKind::BANG)),
|
||||
syntax::NodeOrToken::Token(ast::make::token(SyntaxKind::L_PAREN)),
|
||||
],
|
||||
);
|
||||
ted::append_child_raw(demorganed.syntax(), ast::make::token(SyntaxKind::R_PAREN));
|
||||
edit.replace_ast(bin_expr, demorganed);
|
||||
edit.replace_ast(bin_expr.into(), add_bang_paren(demorganed));
|
||||
}
|
||||
},
|
||||
)
|
||||
|
@ -271,6 +250,11 @@ fn tail_cb_impl(edit: &mut SourceChangeBuilder, e: &ast::Expr) {
|
|||
}
|
||||
}
|
||||
|
||||
/// Add bang and parentheses to the expression.
|
||||
fn add_bang_paren(expr: ast::Expr) -> ast::Expr {
|
||||
make::expr_prefix(T![!], make::expr_paren(expr))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
@ -349,16 +333,14 @@ fn f() { !(S <= S || S < S) }
|
|||
check_assist(apply_demorgan, "fn f() { (x ||$0 x) }", "fn f() { !(!x && !x) }")
|
||||
}
|
||||
|
||||
// FIXME : This needs to go.
|
||||
// // https://github.com/rust-lang/rust-analyzer/issues/10963
|
||||
// #[test]
|
||||
// fn demorgan_doesnt_hang() {
|
||||
// check_assist(
|
||||
// apply_demorgan,
|
||||
// "fn f() { 1 || 3 &&$0 4 || 5 }",
|
||||
// "fn f() { !(!1 || !3 || !4) || 5 }",
|
||||
// )
|
||||
// }
|
||||
#[test]
|
||||
fn demorgan_doesnt_hang() {
|
||||
check_assist(
|
||||
apply_demorgan,
|
||||
"fn f() { 1 || 3 &&$0 4 || 5 }",
|
||||
"fn f() { 1 || !(!3 || !4) || 5 }",
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn demorgan_keep_pars_for_op_precedence() {
|
||||
|
@ -375,6 +357,21 @@ fn f() { !(S <= S || S < S) }
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn demorgan_keep_pars_for_op_precedence2() {
|
||||
cov_mark::check!(demorgan_keep_parens_for_op_precedence2);
|
||||
check_assist(
|
||||
apply_demorgan,
|
||||
"fn f() { (a && !(b &&$0 c); }",
|
||||
"fn f() { (a && (!b || !c); }",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn demorgan_keep_pars_for_op_precedence3() {
|
||||
check_assist(apply_demorgan, "fn f() { (a || !(b &&$0 c); }", "fn f() { (a || !b || !c; }");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn demorgan_removes_pars_in_eq_precedence() {
|
||||
check_assist(
|
||||
|
@ -384,6 +381,11 @@ fn f() { !(S <= S || S < S) }
|
|||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn demorgan_removes_pars_for_op_precedence2() {
|
||||
check_assist(apply_demorgan, "fn f() { (a || !(b ||$0 c); }", "fn f() { (a || !b && !c; }");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn demorgan_iterator_any_all_reverse() {
|
||||
check_assist(
|
||||
|
|
|
@ -85,7 +85,7 @@ fn edit_struct_def(
|
|||
strukt: &Either<ast::Struct, ast::Variant>,
|
||||
record_fields: ast::RecordFieldList,
|
||||
) {
|
||||
// Note that we don't need to consider macro files in this function because this this is
|
||||
// Note that we don't need to consider macro files in this function because this is
|
||||
// currently not triggered for struct definitions inside macro calls.
|
||||
let tuple_fields = record_fields
|
||||
.fields()
|
||||
|
|
|
@ -5623,7 +5623,7 @@ fn func<T: Debug>(i: Struct<'_, T>) {
|
|||
fun_name(i);
|
||||
}
|
||||
|
||||
fn $0fun_name(i: Struct<'_, T>) {
|
||||
fn $0fun_name(i: Struct<T>) {
|
||||
foo(i);
|
||||
}
|
||||
"#,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use hir::{
|
||||
Adt, AsAssocItem, HasSource, HirDisplay, HirFileIdExt, Module, PathResolution, Semantics, Type,
|
||||
TypeInfo,
|
||||
Adt, AsAssocItem, HasSource, HirDisplay, HirFileIdExt, Module, PathResolution, Semantics,
|
||||
StructKind, Type, TypeInfo,
|
||||
};
|
||||
use ide_db::{
|
||||
base_db::FileId,
|
||||
|
@ -15,8 +15,8 @@ use itertools::Itertools;
|
|||
use stdx::to_lower_snake_case;
|
||||
use syntax::{
|
||||
ast::{
|
||||
self, edit::IndentLevel, edit_in_place::Indent, make, AstNode, CallExpr, HasArgList,
|
||||
HasGenericParams, HasModuleItem, HasTypeBounds,
|
||||
self, edit::IndentLevel, edit_in_place::Indent, make, AstNode, BlockExpr, CallExpr,
|
||||
HasArgList, HasGenericParams, HasModuleItem, HasTypeBounds,
|
||||
},
|
||||
ted, SyntaxKind, SyntaxNode, TextRange, T,
|
||||
};
|
||||
|
@ -66,7 +66,7 @@ fn gen_fn(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
|
|||
}
|
||||
|
||||
let fn_name = &*name_ref.text();
|
||||
let TargetInfo { target_module, adt_name, target, file } =
|
||||
let TargetInfo { target_module, adt_info, target, file } =
|
||||
fn_target_info(ctx, path, &call, fn_name)?;
|
||||
|
||||
if let Some(m) = target_module {
|
||||
|
@ -75,15 +75,16 @@ fn gen_fn(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
|
|||
}
|
||||
}
|
||||
|
||||
let function_builder = FunctionBuilder::from_call(ctx, &call, fn_name, target_module, target)?;
|
||||
let function_builder =
|
||||
FunctionBuilder::from_call(ctx, &call, fn_name, target_module, target, &adt_info)?;
|
||||
let text_range = call.syntax().text_range();
|
||||
let label = format!("Generate {} function", function_builder.fn_name);
|
||||
add_func_to_accumulator(acc, ctx, text_range, function_builder, file, adt_name, label)
|
||||
add_func_to_accumulator(acc, ctx, text_range, function_builder, file, adt_info, label)
|
||||
}
|
||||
|
||||
struct TargetInfo {
|
||||
target_module: Option<Module>,
|
||||
adt_name: Option<hir::Name>,
|
||||
adt_info: Option<AdtInfo>,
|
||||
target: GeneratedFunctionTarget,
|
||||
file: FileId,
|
||||
}
|
||||
|
@ -91,11 +92,11 @@ struct TargetInfo {
|
|||
impl TargetInfo {
|
||||
fn new(
|
||||
target_module: Option<Module>,
|
||||
adt_name: Option<hir::Name>,
|
||||
adt_info: Option<AdtInfo>,
|
||||
target: GeneratedFunctionTarget,
|
||||
file: FileId,
|
||||
) -> Self {
|
||||
Self { target_module, adt_name, target, file }
|
||||
Self { target_module, adt_info, target, file }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -157,9 +158,9 @@ fn gen_method(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
|
|||
target,
|
||||
)?;
|
||||
let text_range = call.syntax().text_range();
|
||||
let adt_name = if impl_.is_none() { Some(adt.name(ctx.sema.db)) } else { None };
|
||||
let adt_info = AdtInfo::new(adt, impl_.is_some());
|
||||
let label = format!("Generate {} method", function_builder.fn_name);
|
||||
add_func_to_accumulator(acc, ctx, text_range, function_builder, file, adt_name, label)
|
||||
add_func_to_accumulator(acc, ctx, text_range, function_builder, file, Some(adt_info), label)
|
||||
}
|
||||
|
||||
fn add_func_to_accumulator(
|
||||
|
@ -168,7 +169,7 @@ fn add_func_to_accumulator(
|
|||
text_range: TextRange,
|
||||
function_builder: FunctionBuilder,
|
||||
file: FileId,
|
||||
adt_name: Option<hir::Name>,
|
||||
adt_info: Option<AdtInfo>,
|
||||
label: String,
|
||||
) -> Option<()> {
|
||||
acc.add(AssistId("generate_function", AssistKind::Generate), label, text_range, |edit| {
|
||||
|
@ -177,8 +178,14 @@ fn add_func_to_accumulator(
|
|||
let target = function_builder.target.clone();
|
||||
let func = function_builder.render(ctx.config.snippet_cap, edit);
|
||||
|
||||
if let Some(name) = adt_name {
|
||||
let name = make::ty_path(make::ext::ident_path(&format!("{}", name.display(ctx.db()))));
|
||||
if let Some(adt) =
|
||||
adt_info
|
||||
.and_then(|adt_info| if adt_info.impl_exists { None } else { Some(adt_info.adt) })
|
||||
{
|
||||
let name = make::ty_path(make::ext::ident_path(&format!(
|
||||
"{}",
|
||||
adt.name(ctx.db()).display(ctx.db())
|
||||
)));
|
||||
|
||||
// FIXME: adt may have generic params.
|
||||
let impl_ = make::impl_(None, None, name, None, None).clone_for_update();
|
||||
|
@ -210,6 +217,7 @@ struct FunctionBuilder {
|
|||
generic_param_list: Option<ast::GenericParamList>,
|
||||
where_clause: Option<ast::WhereClause>,
|
||||
params: ast::ParamList,
|
||||
fn_body: BlockExpr,
|
||||
ret_type: Option<ast::RetType>,
|
||||
should_focus_return_type: bool,
|
||||
visibility: Visibility,
|
||||
|
@ -225,6 +233,7 @@ impl FunctionBuilder {
|
|||
fn_name: &str,
|
||||
target_module: Option<Module>,
|
||||
target: GeneratedFunctionTarget,
|
||||
adt_info: &Option<AdtInfo>,
|
||||
) -> Option<Self> {
|
||||
let target_module =
|
||||
target_module.or_else(|| ctx.sema.scope(target.syntax()).map(|it| it.module()))?;
|
||||
|
@ -243,9 +252,27 @@ impl FunctionBuilder {
|
|||
let await_expr = call.syntax().parent().and_then(ast::AwaitExpr::cast);
|
||||
let is_async = await_expr.is_some();
|
||||
|
||||
let expr_for_ret_ty = await_expr.map_or_else(|| call.clone().into(), |it| it.into());
|
||||
let (ret_type, should_focus_return_type) =
|
||||
make_return_type(ctx, &expr_for_ret_ty, target_module, &mut necessary_generic_params);
|
||||
let ret_type;
|
||||
let should_focus_return_type;
|
||||
let fn_body;
|
||||
|
||||
// If generated function has the name "new" and is an associated function, we generate fn body
|
||||
// as a constructor and assume a "Self" return type.
|
||||
if let Some(body) = make_fn_body_as_new_function(ctx, &fn_name.text(), adt_info) {
|
||||
ret_type = Some(make::ret_type(make::ty_path(make::ext::ident_path("Self"))));
|
||||
should_focus_return_type = false;
|
||||
fn_body = body;
|
||||
} else {
|
||||
let expr_for_ret_ty = await_expr.map_or_else(|| call.clone().into(), |it| it.into());
|
||||
(ret_type, should_focus_return_type) = make_return_type(
|
||||
ctx,
|
||||
&expr_for_ret_ty,
|
||||
target_module,
|
||||
&mut necessary_generic_params,
|
||||
);
|
||||
let placeholder_expr = make::ext::expr_todo();
|
||||
fn_body = make::block_expr(vec![], Some(placeholder_expr));
|
||||
};
|
||||
|
||||
let (generic_param_list, where_clause) =
|
||||
fn_generic_params(ctx, necessary_generic_params, &target)?;
|
||||
|
@ -256,6 +283,7 @@ impl FunctionBuilder {
|
|||
generic_param_list,
|
||||
where_clause,
|
||||
params,
|
||||
fn_body,
|
||||
ret_type,
|
||||
should_focus_return_type,
|
||||
visibility,
|
||||
|
@ -294,12 +322,16 @@ impl FunctionBuilder {
|
|||
let (generic_param_list, where_clause) =
|
||||
fn_generic_params(ctx, necessary_generic_params, &target)?;
|
||||
|
||||
let placeholder_expr = make::ext::expr_todo();
|
||||
let fn_body = make::block_expr(vec![], Some(placeholder_expr));
|
||||
|
||||
Some(Self {
|
||||
target,
|
||||
fn_name,
|
||||
generic_param_list,
|
||||
where_clause,
|
||||
params,
|
||||
fn_body,
|
||||
ret_type,
|
||||
should_focus_return_type,
|
||||
visibility,
|
||||
|
@ -308,8 +340,6 @@ impl FunctionBuilder {
|
|||
}
|
||||
|
||||
fn render(self, cap: Option<SnippetCap>, edit: &mut SourceChangeBuilder) -> ast::Fn {
|
||||
let placeholder_expr = make::ext::expr_todo();
|
||||
let fn_body = make::block_expr(vec![], Some(placeholder_expr));
|
||||
let visibility = match self.visibility {
|
||||
Visibility::None => None,
|
||||
Visibility::Crate => Some(make::visibility_pub_crate()),
|
||||
|
@ -321,7 +351,7 @@ impl FunctionBuilder {
|
|||
self.generic_param_list,
|
||||
self.where_clause,
|
||||
self.params,
|
||||
fn_body,
|
||||
self.fn_body,
|
||||
self.ret_type,
|
||||
self.is_async,
|
||||
false, // FIXME : const and unsafe are not handled yet.
|
||||
|
@ -391,6 +421,53 @@ fn make_return_type(
|
|||
(ret_type, should_focus_return_type)
|
||||
}
|
||||
|
||||
fn make_fn_body_as_new_function(
|
||||
ctx: &AssistContext<'_>,
|
||||
fn_name: &str,
|
||||
adt_info: &Option<AdtInfo>,
|
||||
) -> Option<ast::BlockExpr> {
|
||||
if fn_name != "new" {
|
||||
return None;
|
||||
};
|
||||
let adt_info = adt_info.as_ref()?;
|
||||
|
||||
let path_self = make::ext::ident_path("Self");
|
||||
let placeholder_expr = make::ext::expr_todo();
|
||||
let tail_expr = if let Some(strukt) = adt_info.adt.as_struct() {
|
||||
match strukt.kind(ctx.db()) {
|
||||
StructKind::Record => {
|
||||
let fields = strukt
|
||||
.fields(ctx.db())
|
||||
.iter()
|
||||
.map(|field| {
|
||||
make::record_expr_field(
|
||||
make::name_ref(&format!("{}", field.name(ctx.db()).display(ctx.db()))),
|
||||
Some(placeholder_expr.clone()),
|
||||
)
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
make::record_expr(path_self, make::record_expr_field_list(fields)).into()
|
||||
}
|
||||
StructKind::Tuple => {
|
||||
let args = strukt
|
||||
.fields(ctx.db())
|
||||
.iter()
|
||||
.map(|_| placeholder_expr.clone())
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
make::expr_call(make::expr_path(path_self), make::arg_list(args))
|
||||
}
|
||||
StructKind::Unit => make::expr_path(path_self),
|
||||
}
|
||||
} else {
|
||||
placeholder_expr
|
||||
};
|
||||
|
||||
let fn_body = make::block_expr(vec![], Some(tail_expr));
|
||||
Some(fn_body)
|
||||
}
|
||||
|
||||
fn get_fn_target_info(
|
||||
ctx: &AssistContext<'_>,
|
||||
target_module: Option<Module>,
|
||||
|
@ -443,8 +520,8 @@ fn assoc_fn_target_info(
|
|||
}
|
||||
let (impl_, file) = get_adt_source(ctx, &adt, fn_name)?;
|
||||
let target = get_method_target(ctx, &impl_, &adt)?;
|
||||
let adt_name = if impl_.is_none() { Some(adt.name(ctx.sema.db)) } else { None };
|
||||
Some(TargetInfo::new(target_module, adt_name, target, file))
|
||||
let adt_info = AdtInfo::new(adt, impl_.is_some());
|
||||
Some(TargetInfo::new(target_module, Some(adt_info), target, file))
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
|
@ -560,6 +637,17 @@ impl GeneratedFunctionTarget {
|
|||
}
|
||||
}
|
||||
|
||||
struct AdtInfo {
|
||||
adt: hir::Adt,
|
||||
impl_exists: bool,
|
||||
}
|
||||
|
||||
impl AdtInfo {
|
||||
fn new(adt: Adt, impl_exists: bool) -> Self {
|
||||
Self { adt, impl_exists }
|
||||
}
|
||||
}
|
||||
|
||||
/// Computes parameter list for the generated function.
|
||||
fn fn_args(
|
||||
ctx: &AssistContext<'_>,
|
||||
|
@ -2758,18 +2846,18 @@ fn main() {
|
|||
r"
|
||||
enum Foo {}
|
||||
fn main() {
|
||||
Foo::new$0();
|
||||
Foo::bar$0();
|
||||
}
|
||||
",
|
||||
r"
|
||||
enum Foo {}
|
||||
impl Foo {
|
||||
fn new() ${0:-> _} {
|
||||
fn bar() ${0:-> _} {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
fn main() {
|
||||
Foo::new();
|
||||
Foo::bar();
|
||||
}
|
||||
",
|
||||
)
|
||||
|
@ -2849,4 +2937,152 @@ fn main() {
|
|||
",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn new_function_assume_self_type() {
|
||||
check_assist(
|
||||
generate_function,
|
||||
r"
|
||||
pub struct Foo {
|
||||
field_1: usize,
|
||||
field_2: String,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let foo = Foo::new$0();
|
||||
}
|
||||
",
|
||||
r"
|
||||
pub struct Foo {
|
||||
field_1: usize,
|
||||
field_2: String,
|
||||
}
|
||||
impl Foo {
|
||||
fn new() -> Self {
|
||||
${0:Self { field_1: todo!(), field_2: todo!() }}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let foo = Foo::new();
|
||||
}
|
||||
",
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn new_function_assume_self_type_for_tuple_struct() {
|
||||
check_assist(
|
||||
generate_function,
|
||||
r"
|
||||
pub struct Foo (usize, String);
|
||||
|
||||
fn main() {
|
||||
let foo = Foo::new$0();
|
||||
}
|
||||
",
|
||||
r"
|
||||
pub struct Foo (usize, String);
|
||||
impl Foo {
|
||||
fn new() -> Self {
|
||||
${0:Self(todo!(), todo!())}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let foo = Foo::new();
|
||||
}
|
||||
",
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn new_function_assume_self_type_for_unit_struct() {
|
||||
check_assist(
|
||||
generate_function,
|
||||
r"
|
||||
pub struct Foo;
|
||||
|
||||
fn main() {
|
||||
let foo = Foo::new$0();
|
||||
}
|
||||
",
|
||||
r"
|
||||
pub struct Foo;
|
||||
impl Foo {
|
||||
fn new() -> Self {
|
||||
${0:Self}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let foo = Foo::new();
|
||||
}
|
||||
",
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn new_function_assume_self_type_for_enum() {
|
||||
check_assist(
|
||||
generate_function,
|
||||
r"
|
||||
pub enum Foo {}
|
||||
|
||||
fn main() {
|
||||
let foo = Foo::new$0();
|
||||
}
|
||||
",
|
||||
r"
|
||||
pub enum Foo {}
|
||||
impl Foo {
|
||||
fn new() -> Self {
|
||||
${0:todo!()}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let foo = Foo::new();
|
||||
}
|
||||
",
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn new_function_assume_self_type_with_args() {
|
||||
check_assist(
|
||||
generate_function,
|
||||
r#"
|
||||
pub struct Foo {
|
||||
field_1: usize,
|
||||
field_2: String,
|
||||
}
|
||||
|
||||
struct Baz;
|
||||
fn baz() -> Baz { Baz }
|
||||
|
||||
fn main() {
|
||||
let foo = Foo::new$0(baz(), baz(), "foo", "bar");
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
pub struct Foo {
|
||||
field_1: usize,
|
||||
field_2: String,
|
||||
}
|
||||
impl Foo {
|
||||
fn new(baz_1: Baz, baz_2: Baz, arg_1: &str, arg_2: &str) -> Self {
|
||||
${0:Self { field_1: todo!(), field_2: todo!() }}
|
||||
}
|
||||
}
|
||||
|
||||
struct Baz;
|
||||
fn baz() -> Baz { Baz }
|
||||
|
||||
fn main() {
|
||||
let foo = Foo::new(baz(), baz(), "foo", "bar");
|
||||
}
|
||||
"#,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use std::iter;
|
||||
|
||||
use ast::edit::IndentLevel;
|
||||
use hir::HasAttrs;
|
||||
use ide_db::base_db::AnchoredPathBuf;
|
||||
use itertools::Itertools;
|
||||
use stdx::format_to;
|
||||
|
@ -50,9 +51,17 @@ pub(crate) fn move_module_to_file(acc: &mut Assists, ctx: &AssistContext<'_>) ->
|
|||
|builder| {
|
||||
let path = {
|
||||
let mut buf = String::from("./");
|
||||
match parent_module.name(ctx.db()) {
|
||||
Some(name) if !parent_module.is_mod_rs(ctx.db()) => {
|
||||
format_to!(buf, "{}/", name.display(ctx.db()))
|
||||
let db = ctx.db();
|
||||
match parent_module.name(db) {
|
||||
Some(name)
|
||||
if !parent_module.is_mod_rs(db)
|
||||
&& parent_module
|
||||
.attrs(db)
|
||||
.by_key("path")
|
||||
.string_value_unescape()
|
||||
.is_none() =>
|
||||
{
|
||||
format_to!(buf, "{}/", name.display(db))
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
|
@ -107,6 +116,72 @@ mod tests {
|
|||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn extract_with_specified_path_attr() {
|
||||
check_assist(
|
||||
move_module_to_file,
|
||||
r#"
|
||||
//- /main.rs
|
||||
#[path="parser/__mod.rs"]
|
||||
mod parser;
|
||||
//- /parser/__mod.rs
|
||||
fn test() {}
|
||||
mod $0expr {
|
||||
struct A {}
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
//- /parser/__mod.rs
|
||||
fn test() {}
|
||||
mod expr;
|
||||
//- /parser/expr.rs
|
||||
struct A {}
|
||||
"#,
|
||||
);
|
||||
|
||||
check_assist(
|
||||
move_module_to_file,
|
||||
r#"
|
||||
//- /main.rs
|
||||
#[path="parser/a/__mod.rs"]
|
||||
mod parser;
|
||||
//- /parser/a/__mod.rs
|
||||
fn test() {}
|
||||
mod $0expr {
|
||||
struct A {}
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
//- /parser/a/__mod.rs
|
||||
fn test() {}
|
||||
mod expr;
|
||||
//- /parser/a/expr.rs
|
||||
struct A {}
|
||||
"#,
|
||||
);
|
||||
|
||||
check_assist(
|
||||
move_module_to_file,
|
||||
r#"
|
||||
//- /main.rs
|
||||
#[path="a.rs"]
|
||||
mod parser;
|
||||
//- /a.rs
|
||||
fn test() {}
|
||||
mod $0expr {
|
||||
struct A {}
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
//- /a.rs
|
||||
fn test() {}
|
||||
mod expr;
|
||||
//- /expr.rs
|
||||
struct A {}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn extract_from_root() {
|
||||
check_assist(
|
||||
|
|
|
@ -25,7 +25,7 @@ pub(crate) fn make_raw_string(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opt
|
|||
if token.is_raw() {
|
||||
return None;
|
||||
}
|
||||
let value = token.value()?;
|
||||
let value = token.value().ok()?;
|
||||
let target = token.syntax().text_range();
|
||||
acc.add(
|
||||
AssistId("make_raw_string", AssistKind::RefactorRewrite),
|
||||
|
@ -64,7 +64,7 @@ pub(crate) fn make_usual_string(acc: &mut Assists, ctx: &AssistContext<'_>) -> O
|
|||
if !token.is_raw() {
|
||||
return None;
|
||||
}
|
||||
let value = token.value()?;
|
||||
let value = token.value().ok()?;
|
||||
let target = token.syntax().text_range();
|
||||
acc.add(
|
||||
AssistId("make_usual_string", AssistKind::RefactorRewrite),
|
||||
|
@ -398,12 +398,12 @@ string"###;
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn remove_hash_doesnt_work() {
|
||||
fn remove_hash_does_not_work() {
|
||||
check_assist_not_applicable(remove_hash, r#"fn f() { let s = $0"random string"; }"#);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn remove_hash_no_hash_doesnt_work() {
|
||||
fn remove_hash_no_hash_does_not_work() {
|
||||
check_assist_not_applicable(remove_hash, r#"fn f() { let s = $0r"random string"; }"#);
|
||||
}
|
||||
|
||||
|
|
|
@ -77,7 +77,7 @@ pub(crate) fn reorder_impl_items(acc: &mut Assists, ctx: &AssistContext<'_>) ->
|
|||
ast::AssocItem::MacroCall(_) => None,
|
||||
};
|
||||
|
||||
name.and_then(|n| ranks.get(&n.to_string()).copied()).unwrap_or(usize::max_value())
|
||||
name.and_then(|n| ranks.get(&n.to_string()).copied()).unwrap_or(usize::MAX)
|
||||
})
|
||||
.collect();
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ use crate::{AssistContext, AssistId, AssistKind, Assists};
|
|||
// ```
|
||||
pub(crate) fn replace_string_with_char(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
|
||||
let token = ctx.find_token_syntax_at_offset(STRING).and_then(ast::String::cast)?;
|
||||
let value = token.value()?;
|
||||
let value = token.value().ok()?;
|
||||
let target = token.syntax().text_range();
|
||||
|
||||
if value.chars().take(2).count() != 1 {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
//! Term search assist
|
||||
use hir::term_search::TermSearchCtx;
|
||||
use hir::term_search::{TermSearchConfig, TermSearchCtx};
|
||||
use ide_db::{
|
||||
assists::{AssistId, AssistKind, GroupLabel},
|
||||
famous_defs::FamousDefs,
|
||||
|
@ -34,7 +34,7 @@ pub(crate) fn term_search(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<
|
|||
sema: &ctx.sema,
|
||||
scope: &scope,
|
||||
goal: target_ty,
|
||||
config: Default::default(),
|
||||
config: TermSearchConfig { fuel: ctx.config.term_search_fuel, ..Default::default() },
|
||||
};
|
||||
let paths = hir::term_search::term_search(&term_search_ctx);
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@ pub(crate) const TEST_CONFIG: AssistConfig = AssistConfig {
|
|||
prefer_no_std: false,
|
||||
prefer_prelude: true,
|
||||
assist_emit_must_use: false,
|
||||
term_search_fuel: 400,
|
||||
};
|
||||
|
||||
pub(crate) const TEST_CONFIG_NO_SNIPPET_CAP: AssistConfig = AssistConfig {
|
||||
|
@ -46,6 +47,7 @@ pub(crate) const TEST_CONFIG_NO_SNIPPET_CAP: AssistConfig = AssistConfig {
|
|||
prefer_no_std: false,
|
||||
prefer_prelude: true,
|
||||
assist_emit_must_use: false,
|
||||
term_search_fuel: 400,
|
||||
};
|
||||
|
||||
pub(crate) const TEST_CONFIG_IMPORT_ONE: AssistConfig = AssistConfig {
|
||||
|
@ -61,6 +63,7 @@ pub(crate) const TEST_CONFIG_IMPORT_ONE: AssistConfig = AssistConfig {
|
|||
prefer_no_std: false,
|
||||
prefer_prelude: true,
|
||||
assist_emit_must_use: false,
|
||||
term_search_fuel: 400,
|
||||
};
|
||||
|
||||
pub(crate) fn with_single_file(text: &str) -> (RootDatabase, FileId) {
|
||||
|
|
|
@ -353,7 +353,7 @@ pub(crate) fn complete_expr(acc: &mut Completions, ctx: &CompletionContext<'_>)
|
|||
config: hir::term_search::TermSearchConfig {
|
||||
enable_borrowcheck: false,
|
||||
many_alternatives_threshold: 1,
|
||||
depth: 6,
|
||||
fuel: 200,
|
||||
},
|
||||
};
|
||||
let exprs = hir::term_search::term_search(&term_search_ctx);
|
||||
|
|
|
@ -296,7 +296,7 @@ fn import_on_the_fly_pat_(
|
|||
position: SyntaxNode,
|
||||
potential_import_name: String,
|
||||
) -> Option<()> {
|
||||
let _p = tracing::span!(tracing::Level::INFO, "import_on_the_fly_pat", ?potential_import_name)
|
||||
let _p = tracing::span!(tracing::Level::INFO, "import_on_the_fly_pat_", ?potential_import_name)
|
||||
.entered();
|
||||
|
||||
ImportScope::find_insert_use_container(&position, &ctx.sema)?;
|
||||
|
|
|
@ -15,6 +15,7 @@ pub struct CompletionConfig {
|
|||
pub enable_self_on_the_fly: bool,
|
||||
pub enable_private_editable: bool,
|
||||
pub enable_term_search: bool,
|
||||
pub term_search_fuel: u64,
|
||||
pub full_function_signatures: bool,
|
||||
pub callable: Option<CallableSnippets>,
|
||||
pub snippet_cap: Option<SnippetCap>,
|
||||
|
|
|
@ -466,7 +466,7 @@ impl CompletionContext<'_> {
|
|||
cov_mark::hit!(completes_if_lifetime_without_idents);
|
||||
TextRange::at(self.original_token.text_range().start(), TextSize::from(1))
|
||||
}
|
||||
IDENT | LIFETIME_IDENT | UNDERSCORE => self.original_token.text_range(),
|
||||
IDENT | LIFETIME_IDENT | UNDERSCORE | INT_NUMBER => self.original_token.text_range(),
|
||||
_ if kind.is_keyword() => self.original_token.text_range(),
|
||||
_ => TextRange::empty(self.position.offset),
|
||||
}
|
||||
|
|
|
@ -368,7 +368,7 @@ fn render_resolution_pat(
|
|||
import_to_add: Option<LocatedImport>,
|
||||
resolution: ScopeDef,
|
||||
) -> Builder {
|
||||
let _p = tracing::span!(tracing::Level::INFO, "render_resolution").entered();
|
||||
let _p = tracing::span!(tracing::Level::INFO, "render_resolution_pat").entered();
|
||||
use hir::ModuleDef::*;
|
||||
|
||||
if let ScopeDef::ModuleDef(Macro(mac)) = resolution {
|
||||
|
@ -386,7 +386,7 @@ fn render_resolution_path(
|
|||
import_to_add: Option<LocatedImport>,
|
||||
resolution: ScopeDef,
|
||||
) -> Builder {
|
||||
let _p = tracing::span!(tracing::Level::INFO, "render_resolution").entered();
|
||||
let _p = tracing::span!(tracing::Level::INFO, "render_resolution_path").entered();
|
||||
use hir::ModuleDef::*;
|
||||
|
||||
match resolution {
|
||||
|
@ -494,7 +494,7 @@ fn render_resolution_simple_(
|
|||
import_to_add: Option<LocatedImport>,
|
||||
resolution: ScopeDef,
|
||||
) -> Builder {
|
||||
let _p = tracing::span!(tracing::Level::INFO, "render_resolution").entered();
|
||||
let _p = tracing::span!(tracing::Level::INFO, "render_resolution_simple_").entered();
|
||||
|
||||
let db = ctx.db();
|
||||
let ctx = ctx.import_to_add(import_to_add);
|
||||
|
@ -1730,6 +1730,51 @@ fn foo(a: A) { B { bar: a.$0 }; }
|
|||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tuple_field_detail() {
|
||||
check(
|
||||
r#"
|
||||
struct S(i32);
|
||||
|
||||
fn f() -> i32 {
|
||||
let s = S(0);
|
||||
s.0$0
|
||||
}
|
||||
"#,
|
||||
SymbolKind::Field,
|
||||
expect![[r#"
|
||||
[
|
||||
CompletionItem {
|
||||
label: "0",
|
||||
source_range: 56..57,
|
||||
delete: 56..57,
|
||||
insert: "0",
|
||||
kind: SymbolKind(
|
||||
Field,
|
||||
),
|
||||
detail: "i32",
|
||||
relevance: CompletionRelevance {
|
||||
exact_name_match: false,
|
||||
type_match: Some(
|
||||
Exact,
|
||||
),
|
||||
is_local: false,
|
||||
is_item_from_trait: false,
|
||||
is_item_from_notable_trait: false,
|
||||
is_name_already_imported: false,
|
||||
requires_import: false,
|
||||
is_op_method: false,
|
||||
is_private_editable: false,
|
||||
postfix_match: None,
|
||||
is_definite: false,
|
||||
function: None,
|
||||
},
|
||||
},
|
||||
]
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn record_field_and_call_relevances() {
|
||||
check_relevance(
|
||||
|
@ -1808,8 +1853,7 @@ fn f() { A { bar: b$0 }; }
|
|||
fn baz() [type]
|
||||
ex baz() [type]
|
||||
ex bar() [type]
|
||||
ex A { bar: baz() }.bar [type]
|
||||
ex A { bar: bar() }.bar [type]
|
||||
ex A { bar: ... }.bar [type]
|
||||
st A []
|
||||
fn f() []
|
||||
"#]],
|
||||
|
@ -1947,8 +1991,8 @@ fn main() {
|
|||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
ex core::ops::Deref::deref(&T(S)) (use core::ops::Deref) [type_could_unify]
|
||||
ex core::ops::Deref::deref(&t) (use core::ops::Deref) [type_could_unify]
|
||||
ex core::ops::Deref::deref(&T(S)) (use core::ops::Deref) [type_could_unify]
|
||||
lc m [local]
|
||||
lc t [local]
|
||||
lc &t [type+local]
|
||||
|
@ -1997,8 +2041,8 @@ fn main() {
|
|||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
ex core::ops::DerefMut::deref_mut(&mut T(S)) (use core::ops::DerefMut) [type_could_unify]
|
||||
ex core::ops::DerefMut::deref_mut(&mut t) (use core::ops::DerefMut) [type_could_unify]
|
||||
ex core::ops::DerefMut::deref_mut(&mut T(S)) (use core::ops::DerefMut) [type_could_unify]
|
||||
lc m [local]
|
||||
lc t [local]
|
||||
lc &mut t [type+local]
|
||||
|
|
|
@ -27,7 +27,7 @@ pub(crate) fn render_variant_lit(
|
|||
variant: hir::Variant,
|
||||
path: Option<hir::ModPath>,
|
||||
) -> Option<Builder> {
|
||||
let _p = tracing::span!(tracing::Level::INFO, "render_enum_variant").entered();
|
||||
let _p = tracing::span!(tracing::Level::INFO, "render_variant_lit").entered();
|
||||
let db = ctx.db();
|
||||
|
||||
let name = local_name.unwrap_or_else(|| variant.name(db));
|
||||
|
|
|
@ -27,7 +27,7 @@ pub(crate) fn render_macro_pat(
|
|||
name: hir::Name,
|
||||
macro_: hir::Macro,
|
||||
) -> Builder {
|
||||
let _p = tracing::span!(tracing::Level::INFO, "render_macro").entered();
|
||||
let _p = tracing::span!(tracing::Level::INFO, "render_macro_pat").entered();
|
||||
render(ctx, false, false, false, name, macro_)
|
||||
}
|
||||
|
||||
|
|
|
@ -80,6 +80,7 @@ pub(crate) const TEST_CONFIG: CompletionConfig = CompletionConfig {
|
|||
},
|
||||
snippets: Vec::new(),
|
||||
limit: None,
|
||||
term_search_fuel: 200,
|
||||
};
|
||||
|
||||
pub(crate) fn completion_list(ra_fixture: &str) -> String {
|
||||
|
|
|
@ -19,7 +19,7 @@ struct Foo<'lt, T, const C: usize> where $0 {}
|
|||
en Enum Enum
|
||||
ma makro!(…) macro_rules! makro
|
||||
md module
|
||||
st Foo<…> Foo<'{error}, {unknown}, _>
|
||||
st Foo<…> Foo<{unknown}, _>
|
||||
st Record Record
|
||||
st Tuple Tuple
|
||||
st Unit Unit
|
||||
|
@ -92,7 +92,7 @@ struct Foo<'lt, T, const C: usize> where for<'a> $0 {}
|
|||
en Enum Enum
|
||||
ma makro!(…) macro_rules! makro
|
||||
md module
|
||||
st Foo<…> Foo<'{error}, {unknown}, _>
|
||||
st Foo<…> Foo<{unknown}, _>
|
||||
st Record Record
|
||||
st Tuple Tuple
|
||||
st Unit Unit
|
||||
|
|
|
@ -20,8 +20,8 @@ struct Foo<'lt, T, const C: usize> {
|
|||
en Enum Enum
|
||||
ma makro!(…) macro_rules! makro
|
||||
md module
|
||||
sp Self Foo<'{error}, {unknown}, _>
|
||||
st Foo<…> Foo<'{error}, {unknown}, _>
|
||||
sp Self Foo<{unknown}, _>
|
||||
st Foo<…> Foo<{unknown}, _>
|
||||
st Record Record
|
||||
st Tuple Tuple
|
||||
st Unit Unit
|
||||
|
@ -45,8 +45,8 @@ struct Foo<'lt, T, const C: usize>(f$0);
|
|||
en Enum Enum
|
||||
ma makro!(…) macro_rules! makro
|
||||
md module
|
||||
sp Self Foo<'{error}, {unknown}, _>
|
||||
st Foo<…> Foo<'{error}, {unknown}, _>
|
||||
sp Self Foo<{unknown}, _>
|
||||
st Foo<…> Foo<{unknown}, _>
|
||||
st Record Record
|
||||
st Tuple Tuple
|
||||
st Unit Unit
|
||||
|
|
|
@ -11,8 +11,8 @@ use hir::{
|
|||
Adt, AsAssocItem, AsExternAssocItem, AssocItem, AttributeTemplate, BuiltinAttr, BuiltinType,
|
||||
Const, Crate, DefWithBody, DeriveHelper, DocLinkDef, ExternAssocItem, ExternCrateDecl, Field,
|
||||
Function, GenericParam, HasVisibility, HirDisplay, Impl, Label, Local, Macro, Module,
|
||||
ModuleDef, Name, PathResolution, Semantics, Static, ToolModule, Trait, TraitAlias, TupleField,
|
||||
TypeAlias, Variant, VariantDef, Visibility,
|
||||
ModuleDef, Name, PathResolution, Semantics, Static, StaticLifetime, ToolModule, Trait,
|
||||
TraitAlias, TupleField, TypeAlias, Variant, VariantDef, Visibility,
|
||||
};
|
||||
use stdx::{format_to, impl_from};
|
||||
use syntax::{
|
||||
|
@ -39,12 +39,13 @@ pub enum Definition {
|
|||
Trait(Trait),
|
||||
TraitAlias(TraitAlias),
|
||||
TypeAlias(TypeAlias),
|
||||
BuiltinType(BuiltinType),
|
||||
SelfType(Impl),
|
||||
GenericParam(GenericParam),
|
||||
Local(Local),
|
||||
Label(Label),
|
||||
DeriveHelper(DeriveHelper),
|
||||
BuiltinType(BuiltinType),
|
||||
BuiltinLifetime(StaticLifetime),
|
||||
BuiltinAttr(BuiltinAttr),
|
||||
ToolModule(ToolModule),
|
||||
ExternCrateDecl(ExternCrateDecl),
|
||||
|
@ -83,6 +84,7 @@ impl Definition {
|
|||
Definition::DeriveHelper(it) => it.derive().module(db),
|
||||
Definition::BuiltinAttr(_)
|
||||
| Definition::BuiltinType(_)
|
||||
| Definition::BuiltinLifetime(_)
|
||||
| Definition::TupleField(_)
|
||||
| Definition::ToolModule(_) => return None,
|
||||
};
|
||||
|
@ -112,6 +114,7 @@ impl Definition {
|
|||
Definition::BuiltinType(_) | Definition::TupleField(_) => Visibility::Public,
|
||||
Definition::Macro(_) => return None,
|
||||
Definition::BuiltinAttr(_)
|
||||
| Definition::BuiltinLifetime(_)
|
||||
| Definition::ToolModule(_)
|
||||
| Definition::SelfType(_)
|
||||
| Definition::Local(_)
|
||||
|
@ -141,6 +144,7 @@ impl Definition {
|
|||
Definition::Local(it) => it.name(db),
|
||||
Definition::GenericParam(it) => it.name(db),
|
||||
Definition::Label(it) => it.name(db),
|
||||
Definition::BuiltinLifetime(StaticLifetime) => hir::known::STATIC_LIFETIME,
|
||||
Definition::BuiltinAttr(_) => return None, // FIXME
|
||||
Definition::ToolModule(_) => return None, // FIXME
|
||||
Definition::DeriveHelper(it) => it.name(db),
|
||||
|
@ -174,6 +178,7 @@ impl Definition {
|
|||
doc_owner.docs(fd.0.db)
|
||||
})
|
||||
}
|
||||
Definition::BuiltinLifetime(StaticLifetime) => None,
|
||||
Definition::Local(_) => None,
|
||||
Definition::SelfType(impl_def) => {
|
||||
impl_def.self_ty(db).as_adt().map(|adt| adt.docs(db))?
|
||||
|
@ -228,6 +233,7 @@ impl Definition {
|
|||
Definition::TraitAlias(it) => it.display(db).to_string(),
|
||||
Definition::TypeAlias(it) => it.display(db).to_string(),
|
||||
Definition::BuiltinType(it) => it.name().display(db).to_string(),
|
||||
Definition::BuiltinLifetime(it) => it.name().display(db).to_string(),
|
||||
Definition::Local(it) => {
|
||||
let ty = it.ty(db);
|
||||
let ty_display = ty.display_truncated(db, None);
|
||||
|
@ -693,6 +699,9 @@ impl NameRefClass {
|
|||
) -> Option<NameRefClass> {
|
||||
let _p = tracing::span!(tracing::Level::INFO, "NameRefClass::classify_lifetime", ?lifetime)
|
||||
.entered();
|
||||
if lifetime.text() == "'static" {
|
||||
return Some(NameRefClass::Definition(Definition::BuiltinLifetime(StaticLifetime)));
|
||||
}
|
||||
let parent = lifetime.syntax().parent()?;
|
||||
match parent.kind() {
|
||||
SyntaxKind::BREAK_EXPR | SyntaxKind::CONTINUE_EXPR => {
|
||||
|
|
|
@ -209,8 +209,7 @@ impl ImportAssets {
|
|||
prefer_no_std: bool,
|
||||
prefer_prelude: bool,
|
||||
) -> impl Iterator<Item = LocatedImport> {
|
||||
let _p =
|
||||
tracing::span!(tracing::Level::INFO, "import_assets::search_for_imports").entered();
|
||||
let _p = tracing::span!(tracing::Level::INFO, "ImportAssets::search_for_imports").entered();
|
||||
self.search_for(sema, Some(prefix_kind), prefer_no_std, prefer_prelude)
|
||||
}
|
||||
|
||||
|
@ -221,7 +220,7 @@ impl ImportAssets {
|
|||
prefer_no_std: bool,
|
||||
prefer_prelude: bool,
|
||||
) -> impl Iterator<Item = LocatedImport> {
|
||||
let _p = tracing::span!(tracing::Level::INFO, "import_assets::search_for_relative_paths")
|
||||
let _p = tracing::span!(tracing::Level::INFO, "ImportAssets::search_for_relative_paths")
|
||||
.entered();
|
||||
self.search_for(sema, None, prefer_no_std, prefer_prelude)
|
||||
}
|
||||
|
@ -263,7 +262,7 @@ impl ImportAssets {
|
|||
prefer_no_std: bool,
|
||||
prefer_prelude: bool,
|
||||
) -> impl Iterator<Item = LocatedImport> {
|
||||
let _p = tracing::span!(tracing::Level::INFO, "import_assets::search_for").entered();
|
||||
let _p = tracing::span!(tracing::Level::INFO, "ImportAssets::search_for").entered();
|
||||
|
||||
let scope = match sema.scope(&self.candidate_node) {
|
||||
Some(it) => it,
|
||||
|
@ -308,7 +307,7 @@ impl ImportAssets {
|
|||
}
|
||||
|
||||
fn scope_definitions(&self, sema: &Semantics<'_, RootDatabase>) -> FxHashSet<ScopeDef> {
|
||||
let _p = tracing::span!(tracing::Level::INFO, "import_assets::scope_definitions").entered();
|
||||
let _p = tracing::span!(tracing::Level::INFO, "ImportAssets::scope_definitions").entered();
|
||||
let mut scope_definitions = FxHashSet::default();
|
||||
if let Some(scope) = sema.scope(&self.candidate_node) {
|
||||
scope.process_all_names(&mut |_, scope_def| {
|
||||
|
@ -327,7 +326,7 @@ fn path_applicable_imports(
|
|||
scope_filter: impl Fn(ItemInNs) -> bool + Copy,
|
||||
) -> FxHashSet<LocatedImport> {
|
||||
let _p =
|
||||
tracing::span!(tracing::Level::INFO, "import_assets::path_applicable_imports").entered();
|
||||
tracing::span!(tracing::Level::INFO, "ImportAssets::path_applicable_imports").entered();
|
||||
|
||||
match &path_candidate.qualifier {
|
||||
None => {
|
||||
|
@ -374,7 +373,7 @@ fn import_for_item(
|
|||
original_item: ItemInNs,
|
||||
scope_filter: impl Fn(ItemInNs) -> bool,
|
||||
) -> Option<LocatedImport> {
|
||||
let _p = tracing::span!(tracing::Level::INFO, "import_assets::import_for_item").entered();
|
||||
let _p = tracing::span!(tracing::Level::INFO, "ImportAssets::import_for_item").entered();
|
||||
let [first_segment, ..] = unresolved_qualifier else { return None };
|
||||
|
||||
let item_as_assoc = item_as_assoc(db, original_item);
|
||||
|
@ -508,8 +507,7 @@ fn trait_applicable_items(
|
|||
mod_path: impl Fn(ItemInNs) -> Option<ModPath>,
|
||||
scope_filter: impl Fn(hir::Trait) -> bool,
|
||||
) -> FxHashSet<LocatedImport> {
|
||||
let _p =
|
||||
tracing::span!(tracing::Level::INFO, "import_assets::trait_applicable_items").entered();
|
||||
let _p = tracing::span!(tracing::Level::INFO, "ImportAssets::trait_applicable_items").entered();
|
||||
|
||||
let db = sema.db;
|
||||
|
||||
|
|
|
@ -194,7 +194,7 @@ fn insert_use_with_alias_option(
|
|||
cfg: &InsertUseConfig,
|
||||
alias: Option<ast::Rename>,
|
||||
) {
|
||||
let _p = tracing::span!(tracing::Level::INFO, "insert_use").entered();
|
||||
let _p = tracing::span!(tracing::Level::INFO, "insert_use_with_alias_option").entered();
|
||||
let mut mb = match cfg.granularity {
|
||||
ImportGranularity::Crate => Some(MergeBehavior::Crate),
|
||||
ImportGranularity::Module => Some(MergeBehavior::Module),
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
//! rust-analyzer is lazy and doesn't compute anything unless asked. This
|
||||
//! sometimes is counter productive when, for example, the first goto definition
|
||||
//! request takes longer to compute. This modules implemented prepopulation of
|
||||
//! request takes longer to compute. This module implements prepopulation of
|
||||
//! various caches, it's not really advanced at the moment.
|
||||
mod topologic_sort;
|
||||
|
||||
|
@ -32,7 +32,7 @@ pub fn parallel_prime_caches(
|
|||
num_worker_threads: u8,
|
||||
cb: &(dyn Fn(ParallelPrimeCachesProgress) + Sync),
|
||||
) {
|
||||
let _p = tracing::span!(tracing::Level::INFO, "prime_caches").entered();
|
||||
let _p = tracing::span!(tracing::Level::INFO, "parallel_prime_caches").entered();
|
||||
|
||||
let graph = db.crate_graph();
|
||||
let mut crates_to_prime = {
|
||||
|
|
|
@ -196,11 +196,12 @@ impl Definition {
|
|||
.and_then(syn_ctx_is_root)
|
||||
}
|
||||
}
|
||||
Definition::BuiltinType(_) => return None,
|
||||
Definition::SelfType(_) => return None,
|
||||
Definition::BuiltinAttr(_) => return None,
|
||||
Definition::ToolModule(_) => return None,
|
||||
Definition::TupleField(_) => return None,
|
||||
Definition::BuiltinType(_)
|
||||
| Definition::BuiltinLifetime(_)
|
||||
| Definition::BuiltinAttr(_)
|
||||
| Definition::SelfType(_)
|
||||
| Definition::ToolModule(_)
|
||||
| Definition::TupleField(_) => return None,
|
||||
// FIXME: This should be doable in theory
|
||||
Definition::DeriveHelper(_) => return None,
|
||||
};
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
//! Implementation of find-usages functionality.
|
||||
//!
|
||||
//! It is based on the standard ide trick: first, we run a fast text search to
|
||||
//! get a super-set of matches. Then, we we confirm each match using precise
|
||||
//! get a super-set of matches. Then, we confirm each match using precise
|
||||
//! name resolution.
|
||||
|
||||
use std::mem;
|
||||
|
|
|
@ -301,8 +301,8 @@ impl SymbolIndex {
|
|||
}
|
||||
|
||||
fn range_to_map_value(start: usize, end: usize) -> u64 {
|
||||
debug_assert![start <= (std::u32::MAX as usize)];
|
||||
debug_assert![end <= (std::u32::MAX as usize)];
|
||||
debug_assert![start <= (u32::MAX as usize)];
|
||||
debug_assert![end <= (u32::MAX as usize)];
|
||||
|
||||
((start as u64) << 32) | end as u64
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ use ide_db::{
|
|||
helpers::mod_path_to_ast,
|
||||
imports::insert_use::{insert_use, ImportScope},
|
||||
source_change::SourceChangeBuilder,
|
||||
RootDatabase,
|
||||
FxHashMap, RootDatabase,
|
||||
};
|
||||
use itertools::Itertools;
|
||||
use stdx::{format_to, never};
|
||||
|
@ -22,15 +22,22 @@ use crate::{fix, Diagnostic, DiagnosticCode, DiagnosticsConfig, Severity};
|
|||
#[derive(Default)]
|
||||
struct State {
|
||||
result: String,
|
||||
struct_counts: usize,
|
||||
has_serialize: bool,
|
||||
has_deserialize: bool,
|
||||
names: FxHashMap<String, usize>,
|
||||
}
|
||||
|
||||
impl State {
|
||||
fn generate_new_name(&mut self) -> ast::Name {
|
||||
self.struct_counts += 1;
|
||||
make::name(&format!("Struct{}", self.struct_counts))
|
||||
fn generate_new_name(&mut self, name: &str) -> ast::Name {
|
||||
let name = stdx::to_camel_case(name);
|
||||
let count = if let Some(count) = self.names.get_mut(&name) {
|
||||
*count += 1;
|
||||
*count
|
||||
} else {
|
||||
self.names.insert(name.clone(), 1);
|
||||
1
|
||||
};
|
||||
make::name(&format!("{}{}", name, count))
|
||||
}
|
||||
|
||||
fn serde_derive(&self) -> String {
|
||||
|
@ -52,15 +59,21 @@ impl State {
|
|||
}
|
||||
}
|
||||
|
||||
fn build_struct(&mut self, value: &serde_json::Map<String, serde_json::Value>) -> ast::Type {
|
||||
let name = self.generate_new_name();
|
||||
fn build_struct(
|
||||
&mut self,
|
||||
name: &str,
|
||||
value: &serde_json::Map<String, serde_json::Value>,
|
||||
) -> ast::Type {
|
||||
let name = self.generate_new_name(name);
|
||||
let ty = make::ty(&name.to_string());
|
||||
let strukt = make::struct_(
|
||||
None,
|
||||
name,
|
||||
None,
|
||||
make::record_field_list(value.iter().sorted_unstable_by_key(|x| x.0).map(
|
||||
|(name, value)| make::record_field(None, make::name(name), self.type_of(value)),
|
||||
|(name, value)| {
|
||||
make::record_field(None, make::name(name), self.type_of(name, value))
|
||||
},
|
||||
))
|
||||
.into(),
|
||||
);
|
||||
|
@ -68,7 +81,7 @@ impl State {
|
|||
ty
|
||||
}
|
||||
|
||||
fn type_of(&mut self, value: &serde_json::Value) -> ast::Type {
|
||||
fn type_of(&mut self, name: &str, value: &serde_json::Value) -> ast::Type {
|
||||
match value {
|
||||
serde_json::Value::Null => make::ty_unit(),
|
||||
serde_json::Value::Bool(_) => make::ty("bool"),
|
||||
|
@ -76,12 +89,12 @@ impl State {
|
|||
serde_json::Value::String(_) => make::ty("String"),
|
||||
serde_json::Value::Array(it) => {
|
||||
let ty = match it.iter().next() {
|
||||
Some(x) => self.type_of(x),
|
||||
Some(x) => self.type_of(name, x),
|
||||
None => make::ty_placeholder(),
|
||||
};
|
||||
make::ty(&format!("Vec<{ty}>"))
|
||||
}
|
||||
serde_json::Value::Object(x) => self.build_struct(x),
|
||||
serde_json::Value::Object(x) => self.build_struct(name, x),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -113,7 +126,7 @@ pub(crate) fn json_in_items(
|
|||
let serialize_resolved = scope_resolve("::serde::Serialize");
|
||||
state.has_deserialize = deserialize_resolved.is_some();
|
||||
state.has_serialize = serialize_resolved.is_some();
|
||||
state.build_struct(&it);
|
||||
state.build_struct("Root", &it);
|
||||
edit.insert(range.start(), state.result);
|
||||
acc.push(
|
||||
Diagnostic::new(
|
||||
|
@ -218,7 +231,7 @@ mod tests {
|
|||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct Struct1{ bar: f64, bay: i64, baz: (), r#box: bool, foo: String }
|
||||
struct Root1{ bar: f64, bay: i64, baz: (), r#box: bool, foo: String }
|
||||
|
||||
"#,
|
||||
);
|
||||
|
@ -237,9 +250,44 @@ mod tests {
|
|||
}
|
||||
"#,
|
||||
r#"
|
||||
struct Struct3{ }
|
||||
struct Struct2{ kind: String, value: Struct3 }
|
||||
struct Struct1{ bar: Struct2, foo: String }
|
||||
struct Value1{ }
|
||||
struct Bar1{ kind: String, value: Value1 }
|
||||
struct Root1{ bar: Bar1, foo: String }
|
||||
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn naming() {
|
||||
check_fix(
|
||||
r#"
|
||||
{$0
|
||||
"user": {
|
||||
"address": {
|
||||
"street": "Main St",
|
||||
"house": 3
|
||||
},
|
||||
"email": "example@example.com"
|
||||
},
|
||||
"another_user": {
|
||||
"user": {
|
||||
"address": {
|
||||
"street": "Main St",
|
||||
"house": 3
|
||||
},
|
||||
"email": "example@example.com"
|
||||
}
|
||||
}
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
struct Address1{ house: i64, street: String }
|
||||
struct User1{ address: Address1, email: String }
|
||||
struct AnotherUser1{ user: User1 }
|
||||
struct Address2{ house: i64, street: String }
|
||||
struct User2{ address: Address2, email: String }
|
||||
struct Root1{ another_user: AnotherUser1, user: User2 }
|
||||
|
||||
"#,
|
||||
);
|
||||
|
@ -276,9 +324,9 @@ mod tests {
|
|||
use serde::Deserialize;
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct Struct2{ x: i64, y: i64 }
|
||||
struct OfObject1{ x: i64, y: i64 }
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct Struct1{ empty: Vec<_>, nested: Vec<Vec<Vec<i64>>>, of_object: Vec<Struct2>, of_string: Vec<String> }
|
||||
struct Root1{ empty: Vec<_>, nested: Vec<Vec<Vec<i64>>>, of_object: Vec<OfObject1>, of_string: Vec<String> }
|
||||
|
||||
"#,
|
||||
);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use either::Either;
|
||||
use hir::{db::ExpandDatabase, HasSource, HirDisplay, HirFileIdExt, Semantics};
|
||||
use hir::{db::ExpandDatabase, HasSource, HirDisplay, HirFileIdExt, Semantics, VariantId};
|
||||
use ide_db::{base_db::FileId, source_change::SourceChange, RootDatabase};
|
||||
use syntax::{
|
||||
ast::{self, edit::IndentLevel, make},
|
||||
|
@ -25,7 +25,10 @@ pub(crate) fn no_such_field(ctx: &DiagnosticsContext<'_>, d: &hir::NoSuchField)
|
|||
} else {
|
||||
Diagnostic::new_with_syntax_node_ptr(
|
||||
ctx,
|
||||
DiagnosticCode::RustcHardError("E0559"),
|
||||
match d.variant {
|
||||
VariantId::EnumVariantId(_) => DiagnosticCode::RustcHardError("E0559"),
|
||||
_ => DiagnosticCode::RustcHardError("E0560"),
|
||||
},
|
||||
"no such field",
|
||||
node,
|
||||
)
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue