Auto merge of #125272 - lnicola:sync-from-ra, r=lnicola

Subtree update of `rust-analyzer`

r? `@ghost`
This commit is contained in:
bors 2024-05-19 12:56:35 +00:00
commit 48826c85fd
204 changed files with 5515 additions and 2911 deletions

View file

@ -6,3 +6,10 @@
# prettier format # prettier format
f247090558c9ba3c551566eae5882b7ca865225f f247090558c9ba3c551566eae5882b7ca865225f
# subtree syncs
932d85b52946d917deab2c23ead552f7f713b828
3e358a6827d83e8d6473913a5e304734aadfed04
9d2cb42a413e51deb50b36794a2e1605381878fc
f532576ac53ddcc666bc8d59e0b6437065e2f599
c48062fe2ab9a2d913d1985a6b0aec4bf936bfc1

View file

@ -63,15 +63,15 @@ jobs:
- name: Install Rust toolchain - name: Install Rust toolchain
run: | run: |
rustup update --no-self-update ${{ env.RUST_CHANNEL }} rustup update --no-self-update ${{ env.RUST_CHANNEL }}
rustup component add --toolchain ${{ env.RUST_CHANNEL }} rustfmt rust-src
rustup default ${{ env.RUST_CHANNEL }} 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 # https://github.com/actions-rust-lang/setup-rust-toolchain/blob/main/rust.json
- name: Install Rust Problem Matcher - name: Install Rust Problem Matcher
if: matrix.os == 'ubuntu-latest' if: matrix.os == 'ubuntu-latest'
run: echo "::add-matcher::.github/rust.json" run: echo "::add-matcher::.github/rust.json"
- name: Cache Dependencies - name: Cache Dependencies
uses: Swatinem/rust-cache@640a22190e7a783d4c409684cea558f081f92012 uses: Swatinem/rust-cache@9bdad043e88c75890e36ad3bbc8d27f0090dd609
with: with:
key: ${{ env.RUST_CHANNEL }} key: ${{ env.RUST_CHANNEL }}
@ -140,7 +140,7 @@ jobs:
rustup target add ${{ env.targets }} ${{ env.targets_ide }} rustup target add ${{ env.targets }} ${{ env.targets_ide }}
- name: Cache Dependencies - name: Cache Dependencies
uses: Swatinem/rust-cache@640a22190e7a783d4c409684cea558f081f92012 uses: Swatinem/rust-cache@9bdad043e88c75890e36ad3bbc8d27f0090dd609
- name: Check - name: Check
run: | run: |

View file

@ -11,34 +11,21 @@ env:
RUSTUP_MAX_RETRIES: 10 RUSTUP_MAX_RETRIES: 10
jobs: jobs:
setup_cargo: build_metrics:
if: github.repository == 'rust-lang/rust-analyzer' if: github.repository == 'rust-lang/rust-analyzer'
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Install Rust toolchain - name: Install Rust toolchain
run: | run: |
rustup update --no-self-update stable rustup update --no-self-update stable
rustup component add rustfmt rust-src
rustup default stable rustup default stable
- name: Cache cargo rustup component add --toolchain stable rust-src
uses: actions/cache@v4
with:
path: |
~/.cargo/bin/
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
key: ${{ runner.os }}-cargo-${{ github.sha }}
build_metrics:
runs-on: ubuntu-latest
needs: setup_cargo
steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v4 uses: actions/checkout@v4
- name: Restore cargo cache - name: Cache cargo
uses: actions/cache@v4 uses: actions/cache@v4
with: with:
path: | path: |
@ -69,22 +56,18 @@ jobs:
matrix: matrix:
names: [self, ripgrep-13.0.0, webrender-2022, diesel-1.4.8, hyper-0.14.18] names: [self, ripgrep-13.0.0, webrender-2022, diesel-1.4.8, hyper-0.14.18]
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: [setup_cargo, build_metrics] needs: build_metrics
steps: 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 - name: Checkout repository
uses: actions/checkout@v4 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 - name: Restore target cache
uses: actions/cache@v4 uses: actions/cache@v4
with: with:

View file

@ -26,7 +26,7 @@ jobs:
run: cargo doc --all --no-deps run: cargo doc --all --no-deps
- name: Deploy Docs - name: Deploy Docs
uses: peaceiris/actions-gh-pages@364c31d33bb99327c77b3a5438a83a357a6729ad # v3.4.0 uses: peaceiris/actions-gh-pages@4f9cc6602d3f66b9c108549d475ec49e8ef4d45e # v4.0.0
with: with:
github_token: ${{ secrets.GITHUB_TOKEN }} github_token: ${{ secrets.GITHUB_TOKEN }}
publish_branch: gh-pages publish_branch: gh-pages

406
Cargo.lock generated
View file

@ -28,9 +28,9 @@ dependencies = [
[[package]] [[package]]
name = "anyhow" name = "anyhow"
version = "1.0.80" version = "1.0.83"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ad32ce52e4161730f7098c077cd2ed6229b5804ccf99e5366be1ab72a98b4e1" checksum = "25bdb32cbbdce2b519a9cd7df3a678443100e265d5e25ca763b7572a5104f5f3"
[[package]] [[package]]
name = "arbitrary" name = "arbitrary"
@ -46,15 +46,15 @@ checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711"
[[package]] [[package]]
name = "autocfg" name = "autocfg"
version = "1.1.0" version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
[[package]] [[package]]
name = "backtrace" name = "backtrace"
version = "0.3.69" version = "0.3.71"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d"
dependencies = [ dependencies = [
"addr2line", "addr2line",
"cc", "cc",
@ -91,9 +91,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]] [[package]]
name = "bitflags" name = "bitflags"
version = "2.4.2" version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1"
[[package]] [[package]]
name = "byteorder" name = "byteorder"
@ -112,9 +112,9 @@ dependencies = [
[[package]] [[package]]
name = "cargo-platform" name = "cargo-platform"
version = "0.1.7" version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "694c8807f2ae16faecc43dc17d74b3eb042482789fd0eb64b39a2e04e087053f" checksum = "24b1f0365a6c6bb4020cd05806fd0d33c44d38046b8bd7f0e40814b9763cabfc"
dependencies = [ dependencies = [
"serde", "serde",
] ]
@ -135,9 +135,9 @@ dependencies = [
[[package]] [[package]]
name = "cc" name = "cc"
version = "1.0.90" version = "1.0.97"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5" checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4"
[[package]] [[package]]
name = "cfg" name = "cfg"
@ -159,6 +159,12 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "cfg_aliases"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e"
[[package]] [[package]]
name = "chalk-derive" name = "chalk-derive"
version = "0.97.0" version = "0.97.0"
@ -177,7 +183,7 @@ version = "0.97.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db18493569b190f7266a04901e520fc3a5c00564475154287906f8a27302c119" checksum = "db18493569b190f7266a04901e520fc3a5c00564475154287906f8a27302c119"
dependencies = [ dependencies = [
"bitflags 2.4.2", "bitflags 2.5.0",
"chalk-derive", "chalk-derive",
] ]
@ -282,11 +288,11 @@ checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345"
[[package]] [[package]]
name = "ctrlc" name = "ctrlc"
version = "3.4.2" version = "3.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b467862cc8610ca6fc9a1532d7777cee0804e678ab45410897b9396495994a0b" checksum = "672465ae37dc1bc6380a6547a8883d5dd397b0f1faaad4f265726cc7042a5345"
dependencies = [ dependencies = [
"nix 0.27.1", "nix 0.28.0",
"windows-sys 0.52.0", "windows-sys 0.52.0",
] ]
@ -324,10 +330,31 @@ dependencies = [
] ]
[[package]] [[package]]
name = "dissimilar" name = "directories"
version = "1.0.7" version = "5.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index" 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]] [[package]]
name = "dot" name = "dot"
@ -343,15 +370,15 @@ checksum = "9bda8e21c04aca2ae33ffc2fd8c23134f3cac46db123ba97bd9d3f3b8a4a85e1"
[[package]] [[package]]
name = "either" name = "either"
version = "1.10.0" version = "1.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2"
[[package]] [[package]]
name = "ena" name = "ena"
version = "0.14.2" version = "0.14.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c533630cf40e9caa44bd91aadc88a75d75a4c3a12b4cfde353cbed41daa1e1f1" checksum = "3d248bdd43ce613d87415282f69b9bb99d947d290b10962dd6c56233312c2ad5"
dependencies = [ dependencies = [
"log", "log",
] ]
@ -364,9 +391,9 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
[[package]] [[package]]
name = "expect-test" name = "expect-test"
version = "1.4.1" version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "30d9eafeadd538e68fb28016364c9732d78e420b9ff8853fa5e4058861e9f8d3" checksum = "9e0be0a561335815e06dab7c62e50353134c796e7a6155402a64bcff66b6a5e0"
dependencies = [ dependencies = [
"dissimilar", "dissimilar",
"once_cell", "once_cell",
@ -380,7 +407,7 @@ checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"libc", "libc",
"redox_syscall", "redox_syscall 0.4.1",
"windows-sys 0.52.0", "windows-sys 0.52.0",
] ]
@ -392,9 +419,9 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
[[package]] [[package]]
name = "flate2" name = "flate2"
version = "1.0.28" version = "1.0.30"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae"
dependencies = [ dependencies = [
"crc32fast", "crc32fast",
"miniz_oxide", "miniz_oxide",
@ -442,9 +469,9 @@ checksum = "7ab85b9b05e3978cc9a9cf8fea7f01b494e1a09ed3037e16ba39edc7a29eb61a"
[[package]] [[package]]
name = "getrandom" name = "getrandom"
version = "0.2.12" version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"libc", "libc",
@ -459,9 +486,9 @@ checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253"
[[package]] [[package]]
name = "hashbrown" name = "hashbrown"
version = "0.14.3" version = "0.14.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
[[package]] [[package]]
name = "heck" name = "heck"
@ -504,7 +531,7 @@ version = "0.0.0"
dependencies = [ dependencies = [
"arrayvec", "arrayvec",
"base-db", "base-db",
"bitflags 2.4.2", "bitflags 2.5.0",
"cfg", "cfg",
"cov-mark", "cov-mark",
"dashmap", "dashmap",
@ -568,7 +595,7 @@ version = "0.0.0"
dependencies = [ dependencies = [
"arrayvec", "arrayvec",
"base-db", "base-db",
"bitflags 2.4.2", "bitflags 2.5.0",
"chalk-derive", "chalk-derive",
"chalk-ir", "chalk-ir",
"chalk-recursive", "chalk-recursive",
@ -589,7 +616,7 @@ dependencies = [
"oorandom", "oorandom",
"project-model", "project-model",
"ra-ap-rustc_abi", "ra-ap-rustc_abi",
"ra-ap-rustc_index", "ra-ap-rustc_index 0.53.0",
"ra-ap-rustc_pattern_analysis", "ra-ap-rustc_pattern_analysis",
"rustc-hash", "rustc-hash",
"scoped-tls", "scoped-tls",
@ -695,7 +722,7 @@ version = "0.0.0"
dependencies = [ dependencies = [
"arrayvec", "arrayvec",
"base-db", "base-db",
"bitflags 2.4.2", "bitflags 2.5.0",
"cov-mark", "cov-mark",
"crossbeam-channel", "crossbeam-channel",
"either", "either",
@ -776,9 +803,9 @@ dependencies = [
[[package]] [[package]]
name = "indexmap" name = "indexmap"
version = "2.2.5" version = "2.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b0b929d511467233429c45a44ac1dcaa21ba0f5ba11e4879e6ed28ddb4f9df4" checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26"
dependencies = [ dependencies = [
"equivalent", "equivalent",
"hashbrown", "hashbrown",
@ -826,9 +853,9 @@ dependencies = [
[[package]] [[package]]
name = "itoa" name = "itoa"
version = "1.0.10" version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
[[package]] [[package]]
name = "jod-thread" name = "jod-thread"
@ -874,9 +901,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.153" version = "0.2.154"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346"
[[package]] [[package]]
name = "libloading" name = "libloading"
@ -885,19 +912,29 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"windows-targets 0.52.4", "windows-targets 0.52.5",
] ]
[[package]] [[package]]
name = "libmimalloc-sys" name = "libmimalloc-sys"
version = "0.1.35" version = "0.1.37"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3979b5c37ece694f1f5e51e7ecc871fdb0f517ed04ee45f88d15d6d553cb9664" checksum = "81eb4061c0582dedea1cbc7aff2240300dd6982e0239d1c99e65c1dbf4a30ba7"
dependencies = [ dependencies = [
"cc", "cc",
"libc", "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]] [[package]]
name = "limit" name = "limit"
version = "0.0.0" version = "0.0.0"
@ -948,9 +985,9 @@ dependencies = [
[[package]] [[package]]
name = "lock_api" name = "lock_api"
version = "0.4.11" version = "0.4.12"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17"
dependencies = [ dependencies = [
"autocfg", "autocfg",
"scopeguard", "scopeguard",
@ -1001,9 +1038,9 @@ dependencies = [
[[package]] [[package]]
name = "lz4_flex" name = "lz4_flex"
version = "0.11.2" version = "0.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "912b45c753ff5f7f5208307e8ace7d2a2e30d024e26d3509f3dce546c044ce15" checksum = "75761162ae2b0e580d7e7c390558127e5f01b4194debd6221fd8c207fc80e3f5"
[[package]] [[package]]
name = "mbe" name = "mbe"
@ -1023,9 +1060,9 @@ dependencies = [
[[package]] [[package]]
name = "memchr" name = "memchr"
version = "2.7.1" version = "2.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d"
[[package]] [[package]]
name = "memmap2" name = "memmap2"
@ -1038,18 +1075,18 @@ dependencies = [
[[package]] [[package]]
name = "memoffset" name = "memoffset"
version = "0.9.0" version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a"
dependencies = [ dependencies = [
"autocfg", "autocfg",
] ]
[[package]] [[package]]
name = "mimalloc" name = "mimalloc"
version = "0.1.39" version = "0.1.41"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa01922b5ea280a911e323e4d2fd24b7fe5cc4042e0d2cda3c40775cdc4bdc9c" checksum = "9f41a2280ded0da56c8cf898babb86e8f10651a34adcfff190ae9a1159c6908d"
dependencies = [ dependencies = [
"libmimalloc-sys", "libmimalloc-sys",
] ]
@ -1097,12 +1134,13 @@ dependencies = [
[[package]] [[package]]
name = "nix" name = "nix"
version = "0.27.1" version = "0.28.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4"
dependencies = [ dependencies = [
"bitflags 2.4.2", "bitflags 2.5.0",
"cfg-if", "cfg-if",
"cfg_aliases",
"libc", "libc",
] ]
@ -1118,7 +1156,7 @@ version = "6.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6205bd8bb1e454ad2e27422015fb5e4f2bcc7e08fa8f27058670d208324a4d2d" checksum = "6205bd8bb1e454ad2e27422015fb5e4f2bcc7e08fa8f27058670d208324a4d2d"
dependencies = [ dependencies = [
"bitflags 2.4.2", "bitflags 2.5.0",
"crossbeam-channel", "crossbeam-channel",
"filetime", "filetime",
"fsevent-sys", "fsevent-sys",
@ -1187,10 +1225,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575"
[[package]] [[package]]
name = "parking_lot" name = "option-ext"
version = "0.12.1" version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" 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 = [ dependencies = [
"lock_api", "lock_api",
"parking_lot_core", "parking_lot_core",
@ -1198,15 +1242,15 @@ dependencies = [
[[package]] [[package]]
name = "parking_lot_core" name = "parking_lot_core"
version = "0.9.9" version = "0.9.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"libc", "libc",
"redox_syscall", "redox_syscall 0.5.1",
"smallvec", "smallvec",
"windows-targets 0.48.5", "windows-targets 0.52.5",
] ]
[[package]] [[package]]
@ -1224,9 +1268,9 @@ dependencies = [
[[package]] [[package]]
name = "paste" name = "paste"
version = "1.0.14" version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
[[package]] [[package]]
name = "paths" name = "paths"
@ -1262,9 +1306,9 @@ dependencies = [
[[package]] [[package]]
name = "petgraph" name = "petgraph"
version = "0.6.4" version = "0.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9" checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db"
dependencies = [ dependencies = [
"fixedbitset", "fixedbitset",
"indexmap", "indexmap",
@ -1272,9 +1316,9 @@ dependencies = [
[[package]] [[package]]
name = "pin-project-lite" name = "pin-project-lite"
version = "0.2.13" version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02"
[[package]] [[package]]
name = "powerfmt" name = "powerfmt"
@ -1346,9 +1390,9 @@ dependencies = [
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.78" version = "1.0.82"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" checksum = "8ad3d49ab951a01fbaafe34f2ec74122942fe18a3f9814c3268f1bb72042131b"
dependencies = [ dependencies = [
"unicode-ident", "unicode-ident",
] ]
@ -1365,7 +1409,7 @@ dependencies = [
"perf-event", "perf-event",
"tikv-jemalloc-ctl", "tikv-jemalloc-ctl",
"tracing", "tracing",
"winapi", "windows-sys 0.52.0",
] ]
[[package]] [[package]]
@ -1417,7 +1461,7 @@ version = "0.9.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57206b407293d2bcd3af849ce869d52068623f19e1b5ff8e8778e3309439682b" checksum = "57206b407293d2bcd3af849ce869d52068623f19e1b5ff8e8778e3309439682b"
dependencies = [ dependencies = [
"bitflags 2.4.2", "bitflags 2.5.0",
"memchr", "memchr",
"unicase", "unicase",
] ]
@ -1433,21 +1477,21 @@ dependencies = [
[[package]] [[package]]
name = "quote" name = "quote"
version = "1.0.35" version = "1.0.36"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
] ]
[[package]] [[package]]
name = "ra-ap-rustc_abi" name = "ra-ap-rustc_abi"
version = "0.44.0" version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8709df2a746f055316bc0c62bd30948695a25e734863bf6e1f9755403e010ab" checksum = "80b1d613eee933486c0613a7bc26e515e46f43adf479d1edd5e537f983e9ce46"
dependencies = [ dependencies = [
"bitflags 2.4.2", "bitflags 2.5.0",
"ra-ap-rustc_index", "ra-ap-rustc_index 0.53.0",
"tracing", "tracing",
] ]
@ -1458,7 +1502,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ad68bacffb87dcdbb23a3ce11261375078aaa06b85d348c49f39ffd5510dc20" checksum = "9ad68bacffb87dcdbb23a3ce11261375078aaa06b85d348c49f39ffd5510dc20"
dependencies = [ dependencies = [
"arrayvec", "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", "smallvec",
] ]
@ -1475,10 +1530,22 @@ dependencies = [
] ]
[[package]] [[package]]
name = "ra-ap-rustc_lexer" name = "ra-ap-rustc_index_macros"
version = "0.44.0" version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index" 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 = [ dependencies = [
"unicode-properties", "unicode-properties",
"unicode-xid", "unicode-xid",
@ -1486,11 +1553,11 @@ dependencies = [
[[package]] [[package]]
name = "ra-ap-rustc_parse_format" name = "ra-ap-rustc_parse_format"
version = "0.44.0" version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0bcf9ff5edbf784b67b8ad5e03a068f1300fcc24062c0d476b3018965135d933" checksum = "70dad7a491c2554590222e0c9212dcb7c2e7aceb668875075012a35ea780d135"
dependencies = [ dependencies = [
"ra-ap-rustc_index", "ra-ap-rustc_index 0.53.0",
"ra-ap-rustc_lexer", "ra-ap-rustc_lexer",
] ]
@ -1500,7 +1567,7 @@ version = "0.44.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d63d1e1d5b2a13273cee1a10011147418f40e12b70f70578ce1dee0f1cafc334" checksum = "d63d1e1d5b2a13273cee1a10011147418f40e12b70f70578ce1dee0f1cafc334"
dependencies = [ dependencies = [
"ra-ap-rustc_index", "ra-ap-rustc_index 0.44.0",
"rustc-hash", "rustc-hash",
"rustc_apfloat", "rustc_apfloat",
"smallvec", "smallvec",
@ -1539,9 +1606,9 @@ dependencies = [
[[package]] [[package]]
name = "rayon" name = "rayon"
version = "1.9.0" version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e4963ed1bc86e4f3ee217022bd855b297cef07fb9eac5dfa1f788b220b49b3bd" checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa"
dependencies = [ dependencies = [
"either", "either",
"rayon-core", "rayon-core",
@ -1566,6 +1633,26 @@ dependencies = [
"bitflags 1.3.2", "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]] [[package]]
name = "rowan" name = "rowan"
version = "0.15.15" version = "0.15.15"
@ -1634,16 +1721,16 @@ dependencies = [
"vfs", "vfs",
"vfs-notify", "vfs-notify",
"walkdir", "walkdir",
"winapi", "windows-sys 0.52.0",
"xflags", "xflags",
"xshell", "xshell",
] ]
[[package]] [[package]]
name = "rustc-demangle" name = "rustc-demangle"
version = "0.1.23" version = "0.1.24"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
[[package]] [[package]]
name = "rustc-hash" name = "rustc-hash"
@ -1663,9 +1750,9 @@ dependencies = [
[[package]] [[package]]
name = "ryu" name = "ryu"
version = "1.0.17" version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
[[package]] [[package]]
name = "salsa" name = "salsa"
@ -1729,27 +1816,27 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]] [[package]]
name = "semver" name = "semver"
version = "1.0.22" version = "1.0.23"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b"
dependencies = [ dependencies = [
"serde", "serde",
] ]
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.197" version = "1.0.201"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" checksum = "780f1cebed1629e4753a1a38a3c72d30b97ec044f0aef68cb26650a3c5cf363c"
dependencies = [ dependencies = [
"serde_derive", "serde_derive",
] ]
[[package]] [[package]]
name = "serde_derive" name = "serde_derive"
version = "1.0.197" version = "1.0.201"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" checksum = "c5e405930b9796f1c00bee880d03fc7e0bb4b9a11afc776885ffe84320da2865"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -1758,9 +1845,9 @@ dependencies = [
[[package]] [[package]]
name = "serde_json" name = "serde_json"
version = "1.0.114" version = "1.0.117"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0" checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3"
dependencies = [ dependencies = [
"indexmap", "indexmap",
"itoa", "itoa",
@ -1770,9 +1857,9 @@ dependencies = [
[[package]] [[package]]
name = "serde_repr" name = "serde_repr"
version = "0.1.18" version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b2e6b945e9d3df726b65d6ee24060aff8e3533d431f677a9695db04eff9dfdb" checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -1799,9 +1886,9 @@ dependencies = [
[[package]] [[package]]
name = "smallvec" name = "smallvec"
version = "1.13.1" version = "1.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
[[package]] [[package]]
name = "smol_str" name = "smol_str"
@ -1856,14 +1943,14 @@ dependencies = [
"jod-thread", "jod-thread",
"libc", "libc",
"miow", "miow",
"winapi", "windows-sys 0.52.0",
] ]
[[package]] [[package]]
name = "syn" name = "syn"
version = "2.0.52" version = "2.0.63"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b699d15b36d1f02c3e7c69f8ffef53de37aefae075d8488d4ba1a7788d574a07" checksum = "bf5be731623ca1a1fb7d8be6f261a3be6d3e2337b8a1f97be944d020c8fcb704"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -1946,18 +2033,18 @@ checksum = "f18aa187839b2bdb1ad2fa35ead8c4c2976b64e4363c386d45ac0f7ee85c9233"
[[package]] [[package]]
name = "thiserror" name = "thiserror"
version = "1.0.57" version = "1.0.60"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e45bcbe8ed29775f228095caf2cd67af7a4ccf756ebff23a306bf3e8b47b24b" checksum = "579e9083ca58dd9dcf91a9923bb9054071b9ebbd800b342194c9feb0ee89fc18"
dependencies = [ dependencies = [
"thiserror-impl", "thiserror-impl",
] ]
[[package]] [[package]]
name = "thiserror-impl" name = "thiserror-impl"
version = "1.0.57" version = "1.0.60"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81" checksum = "e2470041c06ec3ac1ab38d0356a6119054dedaea53e12fbefc0de730a1c08524"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -2007,9 +2094,9 @@ dependencies = [
[[package]] [[package]]
name = "time" name = "time"
version = "0.3.34" version = "0.3.36"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c8248b6521bb14bc45b4067159b9b6ad792e2d6d754d6c41fb50e29fefe38749" checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885"
dependencies = [ dependencies = [
"deranged", "deranged",
"num-conv", "num-conv",
@ -2041,9 +2128,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
[[package]] [[package]]
name = "toml" name = "toml"
version = "0.8.8" version = "0.8.12"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1a195ec8c9da26928f773888e0742ca3ca1040c6cd859c919c9f59c1954ab35" checksum = "e9dd1545e8208b4a5af1aa9bbd0b4cf7e9ea08fabc5d0a5c67fcaafa17433aa3"
dependencies = [ dependencies = [
"serde", "serde",
"serde_spanned", "serde_spanned",
@ -2062,9 +2149,9 @@ dependencies = [
[[package]] [[package]]
name = "toml_edit" name = "toml_edit"
version = "0.21.0" version = "0.22.12"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d34d383cd00a163b4a5b85053df514d45bc330f6de7737edfe0a93311d1eaa03" checksum = "d3328d4f68a705b2a4498da1d580585d39a6510f98318a2cec3018a7ec61ddef"
dependencies = [ dependencies = [
"indexmap", "indexmap",
"serde", "serde",
@ -2255,6 +2342,7 @@ dependencies = [
"paths", "paths",
"rustc-hash", "rustc-hash",
"stdx", "stdx",
"tracing",
] ]
[[package]] [[package]]
@ -2304,11 +2392,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]] [[package]]
name = "winapi-util" name = "winapi-util"
version = "0.1.6" version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b"
dependencies = [ dependencies = [
"winapi", "windows-sys 0.52.0",
] ]
[[package]] [[package]]
@ -2332,7 +2420,7 @@ version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
dependencies = [ dependencies = [
"windows-targets 0.52.4", "windows-targets 0.52.5",
] ]
[[package]] [[package]]
@ -2352,17 +2440,18 @@ dependencies = [
[[package]] [[package]]
name = "windows-targets" name = "windows-targets"
version = "0.52.4" version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb"
dependencies = [ dependencies = [
"windows_aarch64_gnullvm 0.52.4", "windows_aarch64_gnullvm 0.52.5",
"windows_aarch64_msvc 0.52.4", "windows_aarch64_msvc 0.52.5",
"windows_i686_gnu 0.52.4", "windows_i686_gnu 0.52.5",
"windows_i686_msvc 0.52.4", "windows_i686_gnullvm",
"windows_x86_64_gnu 0.52.4", "windows_i686_msvc 0.52.5",
"windows_x86_64_gnullvm 0.52.4", "windows_x86_64_gnu 0.52.5",
"windows_x86_64_msvc 0.52.4", "windows_x86_64_gnullvm 0.52.5",
"windows_x86_64_msvc 0.52.5",
] ]
[[package]] [[package]]
@ -2373,9 +2462,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
[[package]] [[package]]
name = "windows_aarch64_gnullvm" name = "windows_aarch64_gnullvm"
version = "0.52.4" version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263"
[[package]] [[package]]
name = "windows_aarch64_msvc" name = "windows_aarch64_msvc"
@ -2385,9 +2474,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
[[package]] [[package]]
name = "windows_aarch64_msvc" name = "windows_aarch64_msvc"
version = "0.52.4" version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6"
[[package]] [[package]]
name = "windows_i686_gnu" name = "windows_i686_gnu"
@ -2397,9 +2486,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
[[package]] [[package]]
name = "windows_i686_gnu" name = "windows_i686_gnu"
version = "0.52.4" version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index" 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]] [[package]]
name = "windows_i686_msvc" name = "windows_i686_msvc"
@ -2409,9 +2504,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
[[package]] [[package]]
name = "windows_i686_msvc" name = "windows_i686_msvc"
version = "0.52.4" version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf"
[[package]] [[package]]
name = "windows_x86_64_gnu" name = "windows_x86_64_gnu"
@ -2421,9 +2516,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
[[package]] [[package]]
name = "windows_x86_64_gnu" name = "windows_x86_64_gnu"
version = "0.52.4" version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9"
[[package]] [[package]]
name = "windows_x86_64_gnullvm" name = "windows_x86_64_gnullvm"
@ -2433,9 +2528,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
[[package]] [[package]]
name = "windows_x86_64_gnullvm" name = "windows_x86_64_gnullvm"
version = "0.52.4" version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596"
[[package]] [[package]]
name = "windows_x86_64_msvc" name = "windows_x86_64_msvc"
@ -2445,15 +2540,15 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
[[package]] [[package]]
name = "windows_x86_64_msvc" name = "windows_x86_64_msvc"
version = "0.52.4" version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0"
[[package]] [[package]]
name = "winnow" name = "winnow"
version = "0.5.32" version = "0.6.8"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8434aeec7b290e8da5c3f0d628cb0eac6cabcb31d14bb74f779a08109a5914d6" checksum = "c3c52e9c97a68071b23e836c9380edae937f17b9c4667bd021973efc689f618d"
dependencies = [ dependencies = [
"memchr", "memchr",
] ]
@ -2481,24 +2576,25 @@ checksum = "672423d4fea7ffa2f6c25ba60031ea13dc6258070556f125cc4d790007d4a155"
[[package]] [[package]]
name = "xshell" name = "xshell"
version = "0.2.5" version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce2107fe03e558353b4c71ad7626d58ed82efaf56c54134228608893c77023ad" checksum = "6db0ab86eae739efd1b054a8d3d16041914030ac4e01cd1dca0cf252fd8b6437"
dependencies = [ dependencies = [
"xshell-macros", "xshell-macros",
] ]
[[package]] [[package]]
name = "xshell-macros" name = "xshell-macros"
version = "0.2.5" version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7e2c411759b501fb9501aac2b1b2d287a6e93e5bdcf13c25306b23e1b716dd0e" checksum = "9d422e8e38ec76e2f06ee439ccc765e9c6a9638b9e7c9f2e8255e4d41e8bd852"
[[package]] [[package]]
name = "xtask" name = "xtask"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"directories",
"flate2", "flate2",
"itertools", "itertools",
"proc-macro2", "proc-macro2",

View file

@ -4,7 +4,7 @@ exclude = ["crates/proc-macro-srv/proc-macro-test/imp"]
resolver = "2" resolver = "2"
[workspace.package] [workspace.package]
rust-version = "1.76" rust-version = "1.78"
edition = "2021" edition = "2021"
license = "MIT OR Apache-2.0" license = "MIT OR Apache-2.0"
authors = ["rust-analyzer team"] 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-notify = { path = "./crates/vfs-notify", version = "0.0.0" }
vfs = { path = "./crates/vfs", 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_lexer = { version = "0.53.0", default-features = false }
ra-ap-rustc_parse_format = { version = "0.44.0", default-features = false } ra-ap-rustc_parse_format = { version = "0.53.0", default-features = false }
ra-ap-rustc_index = { version = "0.44.0", default-features = false } ra-ap-rustc_index = { version = "0.53.0", default-features = false }
ra-ap-rustc_abi = { version = "0.44.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 } 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. # local crates that aren't published to crates.io. These should not have versions.

View file

@ -51,7 +51,7 @@ impl FileChange {
} }
pub fn apply(self, db: &mut dyn SourceDatabaseExt) { 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 { if let Some(roots) = self.roots {
for (idx, root) in roots.into_iter().enumerate() { for (idx, root) in roots.into_iter().enumerate() {
let root_id = SourceRootId(idx as u32); let root_id = SourceRootId(idx as u32);

View file

@ -324,21 +324,27 @@ pub struct Dependency {
pub crate_id: CrateId, pub crate_id: CrateId,
pub name: CrateName, pub name: CrateName,
prelude: bool, prelude: bool,
sysroot: bool,
} }
impl Dependency { impl Dependency {
pub fn new(name: CrateName, crate_id: CrateId) -> Self { 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 { pub fn with_prelude(name: CrateName, crate_id: CrateId, prelude: bool, sysroot: bool) -> Self {
Self { name, crate_id, prelude } Self { name, crate_id, prelude, sysroot }
} }
/// Whether this dependency is to be added to the depending crate's extern prelude. /// Whether this dependency is to be added to the depending crate's extern prelude.
pub fn is_prelude(&self) -> bool { pub fn is_prelude(&self) -> bool {
self.prelude self.prelude
} }
/// Whether this dependency is a sysroot injected one.
pub fn is_sysroot(&self) -> bool {
self.sysroot
}
} }
impl CrateGraph { impl CrateGraph {

View file

@ -8,7 +8,7 @@ mod input;
use std::panic; use std::panic;
use salsa::Durability; use salsa::Durability;
use syntax::{ast, Parse, SourceFile}; use syntax::{ast, Parse, SourceFile, SyntaxError};
use triomphe::Arc; use triomphe::Arc;
pub use crate::{ pub use crate::{
@ -51,6 +51,7 @@ pub trait FileLoader {
/// Text of the file. /// Text of the file.
fn file_text(&self, file_id: FileId) -> Arc<str>; fn file_text(&self, file_id: FileId) -> Arc<str>;
fn resolve_path(&self, path: AnchoredPath<'_>) -> Option<FileId>; 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]>; 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. /// Parses the file into the syntax tree.
fn parse(&self, file_id: FileId) -> Parse<ast::SourceFile>; 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. /// The crate graph.
#[salsa::input] #[salsa::input]
fn crate_graph(&self) -> Arc<CrateGraph>; 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> { 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); let text = db.file_text(file_id);
// FIXME: Edition based parsing // FIXME: Edition based parsing
SourceFile::parse(&text, span::Edition::CURRENT) 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 /// We don't want to give HIR knowledge of source roots, hence we extract these
/// methods into a separate DB. /// methods into a separate DB.
#[salsa::query_group(SourceDatabaseExtStorage)] #[salsa::query_group(SourceDatabaseExtStorage)]
@ -104,6 +116,7 @@ pub trait SourceDatabaseExt: SourceDatabase {
#[salsa::input] #[salsa::input]
fn source_root(&self, id: SourceRootId) -> Arc<SourceRoot>; fn source_root(&self, id: SourceRootId) -> Arc<SourceRoot>;
/// Crates whose root fool is in `id`.
fn source_root_crates(&self, id: SourceRootId) -> Arc<[CrateId]>; fn source_root_crates(&self, id: SourceRootId) -> Arc<[CrateId]>;
} }

View file

@ -1,6 +1,6 @@
use arbitrary::{Arbitrary, Unstructured}; use arbitrary::{Arbitrary, Unstructured};
use expect_test::{expect, Expect}; 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 syntax::{ast, AstNode, Edition};
use crate::{CfgAtom, CfgExpr, CfgOptions, DnfExpr}; use crate::{CfgAtom, CfgExpr, CfgOptions, DnfExpr};
@ -8,7 +8,12 @@ use crate::{CfgAtom, CfgExpr, CfgOptions, DnfExpr};
fn assert_parse_result(input: &str, expected: CfgExpr) { fn assert_parse_result(input: &str, expected: CfgExpr) {
let source_file = ast::SourceFile::parse(input, Edition::CURRENT).ok().unwrap(); 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 = 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 cfg = CfgExpr::parse(&tt);
assert_eq!(cfg, expected); assert_eq!(cfg, expected);
} }
@ -16,7 +21,12 @@ fn assert_parse_result(input: &str, expected: CfgExpr) {
fn check_dnf(input: &str, expect: Expect) { fn check_dnf(input: &str, expect: Expect) {
let source_file = ast::SourceFile::parse(input, Edition::CURRENT).ok().unwrap(); 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 = 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 cfg = CfgExpr::parse(&tt);
let actual = format!("#![cfg({})]", DnfExpr::new(cfg)); let actual = format!("#![cfg({})]", DnfExpr::new(cfg));
expect.assert_eq(&actual); 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) { fn check_why_inactive(input: &str, opts: &CfgOptions, expect: Expect) {
let source_file = ast::SourceFile::parse(input, Edition::CURRENT).ok().unwrap(); 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 = 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 cfg = CfgExpr::parse(&tt);
let dnf = DnfExpr::new(cfg); let dnf = DnfExpr::new(cfg);
let why_inactive = dnf.why_inactive(opts).unwrap().to_string(); 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]) { fn check_enable_hints(input: &str, opts: &CfgOptions, expected_hints: &[&str]) {
let source_file = ast::SourceFile::parse(input, Edition::CURRENT).ok().unwrap(); 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 = 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 cfg = CfgExpr::parse(&tt);
let dnf = DnfExpr::new(cfg); let dnf = DnfExpr::new(cfg);
let hints = dnf.compute_enable_hints(opts).map(|diff| diff.to_string()).collect::<Vec<_>>(); let hints = dnf.compute_enable_hints(opts).map(|diff| diff.to_string()).collect::<Vec<_>>();

View file

@ -125,8 +125,10 @@ impl FlycheckHandle {
config: FlycheckConfig, config: FlycheckConfig,
sysroot_root: Option<AbsPathBuf>, sysroot_root: Option<AbsPathBuf>,
workspace_root: AbsPathBuf, workspace_root: AbsPathBuf,
manifest_path: Option<AbsPathBuf>,
) -> FlycheckHandle { ) -> 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 (sender, receiver) = unbounded::<StateChange>();
let thread = stdx::thread::Builder::new(stdx::thread::ThreadIntent::Worker) let thread = stdx::thread::Builder::new(stdx::thread::ThreadIntent::Worker)
.name("Flycheck".to_owned()) .name("Flycheck".to_owned())
@ -205,6 +207,7 @@ struct FlycheckActor {
id: usize, id: usize,
sender: Box<dyn Fn(Message) + Send>, sender: Box<dyn Fn(Message) + Send>,
config: FlycheckConfig, config: FlycheckConfig,
manifest_path: Option<AbsPathBuf>,
/// Either the workspace root of the workspace we are flychecking, /// Either the workspace root of the workspace we are flychecking,
/// or the project root of the project. /// or the project root of the project.
root: AbsPathBuf, root: AbsPathBuf,
@ -233,6 +236,7 @@ impl FlycheckActor {
config: FlycheckConfig, config: FlycheckConfig,
sysroot_root: Option<AbsPathBuf>, sysroot_root: Option<AbsPathBuf>,
workspace_root: AbsPathBuf, workspace_root: AbsPathBuf,
manifest_path: Option<AbsPathBuf>,
) -> FlycheckActor { ) -> FlycheckActor {
tracing::info!(%id, ?workspace_root, "Spawning flycheck"); tracing::info!(%id, ?workspace_root, "Spawning flycheck");
FlycheckActor { FlycheckActor {
@ -241,6 +245,7 @@ impl FlycheckActor {
config, config,
sysroot_root, sysroot_root,
root: workspace_root, root: workspace_root,
manifest_path,
command_handle: None, command_handle: None,
command_receiver: None, command_receiver: None,
} }
@ -388,8 +393,13 @@ impl FlycheckActor {
"--message-format=json" "--message-format=json"
}); });
cmd.arg("--manifest-path"); if let Some(manifest_path) = &self.manifest_path {
cmd.arg(self.root.join("Cargo.toml")); 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); options.apply_on_command(&mut cmd);
(cmd, options.extra_args.clone()) (cmd, options.extra_args.clone())

View file

@ -5,7 +5,7 @@ use triomphe::Arc;
use base_db::FileId; use base_db::FileId;
use hir_expand::span_map::{RealSpanMap, SpanMap}; 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 syntax::{ast, AstNode, TextRange};
use crate::attr::{DocAtom, DocExpr}; use crate::attr::{DocAtom, DocExpr};
@ -18,6 +18,7 @@ fn assert_parse_result(input: &str, expected: DocExpr) {
tt.syntax(), tt.syntax(),
map.as_ref(), map.as_ref(),
map.span_for_range(TextRange::empty(0.into())), map.span_for_range(TextRange::empty(0.into())),
DocCommentDesugarMode::ProcMacro,
); );
let cfg = DocExpr::parse(&tt); let cfg = DocExpr::parse(&tt);
assert_eq!(cfg, expected); assert_eq!(cfg, expected);

View file

@ -10,9 +10,10 @@ use std::ops::Index;
use base_db::CrateId; use base_db::CrateId;
use cfg::{CfgExpr, CfgOptions}; use cfg::{CfgExpr, CfgOptions};
use hir_expand::{name::Name, HirFileId, InFile}; use hir_expand::{name::Name, InFile};
use la_arena::{Arena, ArenaMap}; use la_arena::{Arena, ArenaMap};
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
use span::MacroFileId;
use syntax::{ast, AstPtr, SyntaxNodePtr}; use syntax::{ast, AstPtr, SyntaxNodePtr};
use triomphe::Arc; use triomphe::Arc;
@ -98,7 +99,7 @@ pub struct BodySourceMap {
format_args_template_map: FxHashMap<ExprId, Vec<(syntax::TextRange, Name)>>, 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 /// Diagnostics accumulated during body lowering. These contain `AstPtr`s and so are stored in
/// the source map (since they're just as volatile). /// the source map (since they're just as volatile).
@ -349,11 +350,17 @@ impl BodySourceMap {
self.expr_map.get(&src).cloned() 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); let src = node.map(AstPtr::new);
self.expansions.get(&src).cloned() 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> { pub fn pat_syntax(&self, pat: PatId) -> Result<PatSource, SyntheticSyntax> {
self.pat_map_back.get(pat).cloned().ok_or(SyntheticSyntax) self.pat_map_back.get(pat).cloned().ok_or(SyntheticSyntax)
} }

View file

@ -1006,7 +1006,9 @@ impl ExprCollector<'_> {
Some((mark, expansion)) => { Some((mark, expansion)) => {
// Keep collecting even with expansion errors so we can provide completions and // Keep collecting even with expansion errors so we can provide completions and
// other services in incomplete macro expressions. // 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( let prev_ast_id_map = mem::replace(
&mut self.ast_id_map, &mut self.ast_id_map,
self.db.ast_id_map(self.expander.current_file_id()), self.db.ast_id_map(self.expander.current_file_id()),
@ -1869,42 +1871,45 @@ impl ExprCollector<'_> {
) -> ExprId { ) -> ExprId {
match count { match count {
Some(FormatCount::Literal(n)) => { Some(FormatCount::Literal(n)) => {
match LangItem::FormatCount.ty_rel_path(self.db, self.krate, name![Is]) { let args = self.alloc_expr_desugared(Expr::Literal(Literal::Uint(
Some(count_is) => { *n as u128,
let count_is = self.alloc_expr_desugared(Expr::Path(count_is)); Some(BuiltinUint::Usize),
let args = self.alloc_expr_desugared(Expr::Literal(Literal::Uint( )));
*n as u128, let count_is =
Some(BuiltinUint::Usize), match LangItem::FormatCount.ty_rel_path(self.db, self.krate, name![Is]) {
))); Some(count_is) => self.alloc_expr_desugared(Expr::Path(count_is)),
self.alloc_expr_desugared(Expr::Call { None => self.missing_expr(),
callee: count_is, };
args: Box::new([args]), self.alloc_expr_desugared(Expr::Call {
is_assignee_expr: false, callee: count_is,
}) args: Box::new([args]),
} is_assignee_expr: false,
None => self.missing_expr(), })
}
} }
Some(FormatCount::Argument(arg)) => { Some(FormatCount::Argument(arg)) => {
if let Ok(arg_index) = arg.index { if let Ok(arg_index) = arg.index {
let (i, _) = argmap.insert_full((arg_index, ArgumentType::Usize)); let (i, _) = argmap.insert_full((arg_index, ArgumentType::Usize));
match LangItem::FormatCount.ty_rel_path(self.db, self.krate, name![Param]) { let args = self.alloc_expr_desugared(Expr::Literal(Literal::Uint(
Some(count_param) => { i as u128,
let count_param = self.alloc_expr_desugared(Expr::Path(count_param)); Some(BuiltinUint::Usize),
let args = self.alloc_expr_desugared(Expr::Literal(Literal::Uint( )));
i as u128, let count_param = match LangItem::FormatCount.ty_rel_path(
Some(BuiltinUint::Usize), self.db,
))); self.krate,
self.alloc_expr_desugared(Expr::Call { name![Param],
callee: count_param, ) {
args: Box::new([args]), Some(count_param) => self.alloc_expr_desugared(Expr::Path(count_param)),
is_assignee_expr: false,
})
}
None => self.missing_expr(), None => self.missing_expr(),
} };
self.alloc_expr_desugared(Expr::Call {
callee: count_param,
args: Box::new([args]),
is_assignee_expr: false,
})
} else { } else {
// FIXME: This drops arg causing it to potentially not be resolved/type checked
// when typing?
self.missing_expr() self.missing_expr()
} }
} }
@ -1925,7 +1930,8 @@ impl ExprCollector<'_> {
fn make_argument(&mut self, arg: ExprId, ty: ArgumentType) -> ExprId { fn make_argument(&mut self, arg: ExprId, ty: ArgumentType) -> ExprId {
use ArgumentType::*; use ArgumentType::*;
use FormatTrait::*; use FormatTrait::*;
match LangItem::FormatArgument.ty_rel_path(
let new_fn = match LangItem::FormatArgument.ty_rel_path(
self.db, self.db,
self.krate, self.krate,
match ty { match ty {
@ -1941,16 +1947,14 @@ impl ExprCollector<'_> {
Usize => name![from_usize], Usize => name![from_usize],
}, },
) { ) {
Some(new_fn) => { Some(new_fn) => self.alloc_expr_desugared(Expr::Path(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,
})
}
None => self.missing_expr(), None => self.missing_expr(),
} };
self.alloc_expr_desugared(Expr::Call {
callee: new_fn,
args: Box::new([arg]),
is_assignee_expr: false,
})
} }
// endregion: format // endregion: format
} }

View file

@ -7,7 +7,7 @@ use crate::{
body::Body, body::Body,
db::DefDatabase, db::DefDatabase,
hir::{Binding, BindingId, Expr, ExprId, LabelId, Pat, PatId, Statement}, hir::{Binding, BindingId, Expr, ExprId, LabelId, Pat, PatId, Statement},
BlockId, DefWithBodyId, BlockId, ConstBlockId, DefWithBodyId,
}; };
pub type ScopeId = Idx<ScopeData>; pub type ScopeId = Idx<ScopeData>;
@ -46,7 +46,9 @@ pub struct ScopeData {
impl ExprScopes { impl ExprScopes {
pub(crate) fn expr_scopes_query(db: &dyn DefDatabase, def: DefWithBodyId) -> Arc<ExprScopes> { pub(crate) fn expr_scopes_query(db: &dyn DefDatabase, def: DefWithBodyId) -> Arc<ExprScopes> {
let body = db.body(def); 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(); scopes.shrink_to_fit();
Arc::new(scopes) Arc::new(scopes)
} }
@ -89,7 +91,10 @@ fn empty_entries(idx: usize) -> IdxRange<ScopeEntry> {
} }
impl ExprScopes { impl ExprScopes {
fn new(body: &Body) -> ExprScopes { fn new(
body: &Body,
resolve_const_block: impl (Fn(ConstBlockId) -> ExprId) + Copy,
) -> ExprScopes {
let mut scopes = ExprScopes { let mut scopes = ExprScopes {
scopes: Arena::default(), scopes: Arena::default(),
scope_entries: Arena::default(), scope_entries: Arena::default(),
@ -100,7 +105,7 @@ impl ExprScopes {
scopes.add_bindings(body, root, self_param); scopes.add_bindings(body, root, self_param);
} }
scopes.add_params_bindings(body, root, &body.params); 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 scopes
} }
@ -183,35 +188,46 @@ fn compute_block_scopes(
body: &Body, body: &Body,
scopes: &mut ExprScopes, scopes: &mut ExprScopes,
scope: &mut ScopeId, scope: &mut ScopeId,
resolve_const_block: impl (Fn(ConstBlockId) -> ExprId) + Copy,
) { ) {
for stmt in statements { for stmt in statements {
match stmt { match stmt {
Statement::Let { pat, initializer, else_branch, .. } => { Statement::Let { pat, initializer, else_branch, .. } => {
if let Some(expr) = initializer { 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 { 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); *scope = scopes.new_scope(*scope);
scopes.add_pat_bindings(body, *scope, *pat); scopes.add_pat_bindings(body, *scope, *pat);
} }
Statement::Expr { expr, .. } => { Statement::Expr { expr, .. } => {
compute_expr_scopes(*expr, body, scopes, scope); compute_expr_scopes(*expr, body, scopes, scope, resolve_const_block);
} }
Statement::Item => (), Statement::Item => (),
} }
} }
if let Some(expr) = tail { 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 = let make_label =
|label: &Option<LabelId>| label.map(|label| (label, body.labels[label].name.clone())); |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); scopes.set_scope(expr, *scope);
match &body[expr] { match &body[expr] {
Expr::Block { statements, tail, id, label } => { 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 // 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). // via the block itself (important for blocks that only contain items, no expressions).
scopes.set_scope(expr, scope); 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(_) => { Expr::Const(id) => {
// FIXME: This is broken. 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 } => { Expr::Unsafe { id, statements, tail } | Expr::Async { id, statements, tail } => {
let mut scope = scopes.new_block_scope(*scope, *id, None); 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 // 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). // via the block itself (important for blocks that only contain items, no expressions).
scopes.set_scope(expr, scope); 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 } => { Expr::Loop { body: body_expr, label } => {
let mut scope = scopes.new_labeled_scope(*scope, make_label(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, .. } => { Expr::Closure { args, body: body_expr, .. } => {
let mut scope = scopes.new_scope(*scope); let mut scope = scopes.new_scope(*scope);
scopes.add_params_bindings(body, scope, args); 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 } => { Expr::Match { expr, arms } => {
compute_expr_scopes(*expr, body, scopes, scope); compute_expr_scopes(scopes, *expr, scope);
for arm in arms.iter() { for arm in arms.iter() {
let mut scope = scopes.new_scope(*scope); let mut scope = scopes.new_scope(*scope);
scopes.add_pat_bindings(body, scope, arm.pat); scopes.add_pat_bindings(body, scope, arm.pat);
if let Some(guard) = arm.guard { if let Some(guard) = arm.guard {
scope = scopes.new_scope(scope); 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 } => { &Expr::If { condition, then_branch, else_branch } => {
let mut then_branch_scope = scopes.new_scope(*scope); let mut then_branch_scope = scopes.new_scope(*scope);
compute_expr_scopes(condition, body, scopes, &mut then_branch_scope); compute_expr_scopes(scopes, condition, &mut then_branch_scope);
compute_expr_scopes(then_branch, body, scopes, &mut then_branch_scope); compute_expr_scopes(scopes, then_branch, &mut then_branch_scope);
if let Some(else_branch) = else_branch { 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 } => { &Expr::Let { pat, expr } => {
compute_expr_scopes(expr, body, scopes, scope); compute_expr_scopes(scopes, expr, scope);
*scope = scopes.new_scope(*scope); *scope = scopes.new_scope(*scope);
scopes.add_pat_bindings(body, *scope, pat); 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)),
}; };
} }

View file

@ -318,18 +318,20 @@ fn f() {
expect![[r#" expect![[r#"
fn f() { fn f() {
$crate::panicking::panic_fmt( {
builtin#lang(Arguments::new_v1_formatted)( $crate::panicking::panic_fmt(
&[ builtin#lang(Arguments::new_v1_formatted)(
"cc", &[
], "cc",
&[], ],
&[], &[],
unsafe { &[],
builtin#lang(UnsafeArg::new)() unsafe {
}, builtin#lang(UnsafeArg::new)()
), },
); ),
);
};
}"#]] }"#]]
.assert_eq(&body.pretty_print(&db, def)) .assert_eq(&body.pretty_print(&db, def))
} }

View file

@ -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 /// method calls to this trait's methods when the receiver is an array and the crate edition is
/// 2015 or 2018. /// 2015 or 2018.
// box it as the vec is usually empty anyways // 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 { impl TraitData {
@ -258,12 +258,12 @@ impl TraitData {
let mut collector = let mut collector =
AssocItemCollector::new(db, module_id, tree_id.file_id(), ItemContainerId::TraitId(tr)); AssocItemCollector::new(db, module_id, tree_id.file_id(), ItemContainerId::TraitId(tr));
collector.collect(&item_tree, tree_id.tree_id(), &tr_def.items); 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 { Arc::new(TraitData {
name, name,
attribute_calls, macro_calls,
items, items,
is_auto, is_auto,
is_unsafe, is_unsafe,
@ -298,7 +298,7 @@ impl TraitData {
} }
pub fn attribute_calls(&self) -> impl Iterator<Item = (AstId<ast::Item>, MacroCallId)> + '_ { 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 struct ImplData {
pub target_trait: Option<Interned<TraitRef>>, pub target_trait: Option<Interned<TraitRef>>,
pub self_ty: Interned<TypeRef>, pub self_ty: Interned<TypeRef>,
@ -327,7 +327,7 @@ pub struct ImplData {
pub is_negative: bool, pub is_negative: bool,
pub is_unsafe: bool, pub is_unsafe: bool,
// box it as the vec is usually empty anyways // 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 { impl ImplData {
@ -354,7 +354,7 @@ impl ImplData {
AssocItemCollector::new(db, module_id, tree_id.file_id(), ItemContainerId::ImplId(id)); AssocItemCollector::new(db, module_id, tree_id.file_id(), ItemContainerId::ImplId(id));
collector.collect(&item_tree, tree_id.tree_id(), &impl_def.items); 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(); let items = items.into_iter().map(|(_, item)| item).collect();
( (
@ -364,14 +364,14 @@ impl ImplData {
items, items,
is_negative, is_negative,
is_unsafe, is_unsafe,
attribute_calls, macro_calls,
}), }),
DefDiagnostics::new(diagnostics), DefDiagnostics::new(diagnostics),
) )
} }
pub fn attribute_calls(&self) -> impl Iterator<Item = (AstId<ast::Item>, MacroCallId)> + '_ { 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, expander: Expander,
items: Vec<(Name, AssocItemId)>, items: Vec<(Name, AssocItemId)>,
attr_calls: Vec<(AstId<ast::Item>, MacroCallId)>, macro_calls: Vec<(AstId<ast::Item>, MacroCallId)>,
} }
impl<'a> AssocItemCollector<'a> { impl<'a> AssocItemCollector<'a> {
@ -590,7 +590,7 @@ impl<'a> AssocItemCollector<'a> {
container, container,
expander: Expander::new(db, file_id, module_id), expander: Expander::new(db, file_id, module_id),
items: Vec::new(), items: Vec::new(),
attr_calls: Vec::new(), macro_calls: Vec::new(),
diagnostics: Vec::new(), diagnostics: Vec::new(),
} }
} }
@ -604,7 +604,7 @@ impl<'a> AssocItemCollector<'a> {
) { ) {
( (
self.items, 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, 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 = let res =
self.expander.enter_expand_id::<ast::MacroItems>(self.db, call_id); 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; continue 'items;
} }
Ok(_) => (), Ok(_) => (),
@ -698,24 +698,22 @@ impl<'a> AssocItemCollector<'a> {
match item { match item {
AssocItem::Function(id) => { AssocItem::Function(id) => {
let item = &item_tree[id]; let item = &item_tree[id];
let def = let def =
FunctionLoc { container, id: ItemTreeId::new(tree_id, id) }.intern(self.db); FunctionLoc { container, id: ItemTreeId::new(tree_id, id) }.intern(self.db);
self.items.push((item.name.clone(), def.into())); 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) => { AssocItem::Const(id) => {
let item = &item_tree[id]; let item = &item_tree[id];
let Some(name) = item.name.clone() else { return }; let Some(name) = item.name.clone() else { return };
let def = ConstLoc { container, id: ItemTreeId::new(tree_id, id) }.intern(self.db); let def = ConstLoc { container, id: ItemTreeId::new(tree_id, id) }.intern(self.db);
self.items.push((name, def.into())); 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) => { AssocItem::MacroCall(call) => {
let file_id = self.expander.current_file_id(); let file_id = self.expander.current_file_id();
let MacroCall { ast_id, expand_to, ctxt, ref path } = item_tree[call]; let MacroCall { ast_id, expand_to, ctxt, ref path } = item_tree[call];
@ -745,11 +743,8 @@ impl<'a> AssocItemCollector<'a> {
Ok(Some(call_id)) => { Ok(Some(call_id)) => {
let res = let res =
self.expander.enter_expand_id::<ast::MacroItems>(self.db, call_id); self.expander.enter_expand_id::<ast::MacroItems>(self.db, call_id);
self.collect_macro_items(res, &|| hir_expand::MacroCallKind::FnLike { self.macro_calls.push((InFile::new(file_id, ast_id.upcast()), call_id));
ast_id: InFile::new(file_id, ast_id), self.collect_macro_items(res);
expand_to: hir_expand::ExpandTo::Items,
eager: None,
});
} }
Ok(None) => (), Ok(None) => (),
Err(_) => { Err(_) => {
@ -768,39 +763,8 @@ impl<'a> AssocItemCollector<'a> {
} }
} }
fn collect_macro_items( fn collect_macro_items(&mut self, res: ExpandResult<Option<(Mark, Parse<ast::MacroItems>)>>) {
&mut self, let Some((mark, _parse)) = res.value else { return };
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(),
));
}
let tree_id = item_tree::TreeId::new(self.expander.current_file_id(), None); let tree_id = item_tree::TreeId::new(self.expander.current_file_id(), None);
let item_tree = tree_id.item_tree(self.db); let item_tree = tree_id.item_tree(self.db);

View file

@ -1177,6 +1177,8 @@ pub mod fmt {
//- /main.rs crate:main deps:alloc,std //- /main.rs crate:main deps:alloc,std
#![no_std] #![no_std]
extern crate alloc;
$0 $0
//- /std.rs crate:std deps:alloc //- /std.rs crate:std deps:alloc

View file

@ -20,7 +20,7 @@ use triomphe::Arc;
use crate::{ use crate::{
db::DefDatabase, db::DefDatabase,
expander::Expander, expander::Expander,
item_tree::{GenericsItemTreeNode, ItemTree}, item_tree::{AttrOwner, FileItemTreeId, GenericModItem, GenericsItemTreeNode, ItemTree},
lower::LowerCtx, lower::LowerCtx,
nameres::{DefMap, MacroSubNs}, nameres::{DefMap, MacroSubNs},
type_ref::{ConstRef, LifetimeRef, TypeBound, TypeRef}, type_ref::{ConstRef, LifetimeRef, TypeBound, TypeRef},
@ -339,6 +339,7 @@ impl GenericParamsCollector {
target: Either<TypeRef, LifetimeRef>, target: Either<TypeRef, LifetimeRef>,
) { ) {
let bound = TypeBound::from_ast(lower_ctx, bound); let bound = TypeBound::from_ast(lower_ctx, bound);
self.fill_impl_trait_bounds(lower_ctx.take_impl_traits_bounds());
let predicate = match (target, bound) { let predicate = match (target, bound) {
(Either::Left(type_ref), bound) => match hrtb_lifetimes { (Either::Left(type_ref), bound) => match hrtb_lifetimes {
Some(hrtb_lifetimes) => WherePredicate::ForLifetime { Some(hrtb_lifetimes) => WherePredicate::ForLifetime {
@ -359,7 +360,24 @@ impl GenericParamsCollector {
self.where_predicates.push(predicate); 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, &mut self,
db: &dyn DefDatabase, db: &dyn DefDatabase,
exp: &mut Lazy<(Arc<DefMap>, Expander), impl FnOnce() -> (Arc<DefMap>, Expander)>, 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; let cfg_options = &cfg_options[krate].cfg_options;
// Returns the generic parameters that are enabled under the current `#[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_params =
let enabled = |param| item_tree.attrs(db, krate, param).is_cfg_enabled(cfg_options); |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. // 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, // 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. // clone the `Interned<GenericParams>` instead of recreating an identical copy.
let all_type_or_consts_enabled = let all_type_or_consts_enabled =
params.type_or_consts.iter().all(|(idx, _)| enabled(idx.into())); params.type_or_consts.iter().all(|(idx, _)| enabled(attr_owner_ct(idx)));
let all_lifetimes_enabled = params.lifetimes.iter().all(|(idx, _)| enabled(idx.into())); let all_lifetimes_enabled =
params.lifetimes.iter().all(|(idx, _)| enabled(attr_owner_lt(idx)));
if all_type_or_consts_enabled && all_lifetimes_enabled { if all_type_or_consts_enabled && all_lifetimes_enabled {
params.clone() params.clone()
} else { } else {
Interned::new(GenericParams { Interned::new(GenericParams {
type_or_consts: all_type_or_consts_enabled type_or_consts: all_type_or_consts_enabled
.then(|| params.type_or_consts.clone()) .then(|| params.type_or_consts.clone())
.unwrap_or_else(|| { .unwrap_or_else(|| {
params params
.type_or_consts .type_or_consts
.iter() .iter()
.filter(|(idx, _)| enabled((*idx).into())) .filter(|&(idx, _)| enabled(attr_owner_ct(idx)))
.map(|(_, param)| param.clone()) .map(|(_, param)| param.clone())
.collect() .collect()
}), }),
lifetimes: all_lifetimes_enabled lifetimes: all_lifetimes_enabled
.then(|| params.lifetimes.clone()) .then(|| params.lifetimes.clone())
.unwrap_or_else(|| { .unwrap_or_else(|| {
params params
.lifetimes .lifetimes
.iter() .iter()
.filter(|(idx, _)| enabled((*idx).into())) .filter(|&(idx, _)| enabled(attr_owner_lt(idx)))
.map(|(_, param)| param.clone()) .map(|(_, param)| param.clone())
.collect() .collect()
}), }),
where_predicates: params.where_predicates.clone(), where_predicates: params.where_predicates.clone(),
}) })
} }
}; };
fn id_to_generics<Id: GenericsItemTreeNode>( fn id_to_generics<Id: GenericsItemTreeNode>(
db: &dyn DefDatabase, db: &dyn DefDatabase,
id: impl for<'db> Lookup< id: impl for<'db> Lookup<
Database<'db> = dyn DefDatabase + 'db, Database<'db> = dyn DefDatabase + 'db,
Data = impl ItemTreeLoc<Id = Id>, Data = impl ItemTreeLoc<Id = Id>,
>, >,
enabled_params: impl Fn(&Interned<GenericParams>, &ItemTree) -> Interned<GenericParams>, enabled_params: impl Fn(
) -> Interned<GenericParams> { &Interned<GenericParams>,
&ItemTree,
GenericModItem,
) -> Interned<GenericParams>,
) -> Interned<GenericParams>
where
FileItemTreeId<Id>: Into<GenericModItem>,
{
let id = id.lookup(db).item_tree_id(); let id = id.lookup(db).item_tree_id();
let tree = id.item_tree(db); let tree = id.item_tree(db);
let item = &tree[id.value]; let item = &tree[id.value];
enabled_params(item.generic_params(), &tree) enabled_params(item.generic_params(), &tree, id.value.into())
} }
match def { match def {
@ -514,7 +543,8 @@ impl GenericParams {
let tree = loc.id.item_tree(db); let tree = loc.id.item_tree(db);
let item = &tree[loc.id.value]; 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 module = loc.container.module(db);
let func_data = db.function_data(id); let func_data = db.function_data(id);

View file

@ -136,15 +136,15 @@ impl From<ast::LiteralKind> for Literal {
Literal::Float(FloatTypeWrapper::new(lit.value().unwrap_or(Default::default())), ty) Literal::Float(FloatTypeWrapper::new(lit.value().unwrap_or(Default::default())), ty)
} }
LiteralKind::ByteString(bs) => { 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) Literal::ByteString(text)
} }
LiteralKind::String(s) => { 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) Literal::String(text)
} }
LiteralKind::CString(s) => { 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) Literal::CString(text)
} }
LiteralKind::Byte(b) => { LiteralKind::Byte(b) => {

View file

@ -234,6 +234,14 @@ impl ItemScope {
self.impls.iter().copied() 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)> + '_ { pub(crate) fn modules_in_scope(&self) -> impl Iterator<Item = (ModuleId, Visibility)> + '_ {
self.types.values().copied().filter_map(|(def, vis, _)| match def { self.types.values().copied().filter_map(|(def, vis, _)| match def {
ModuleDefId::ModuleId(module) => Some((module, vis)), ModuleDefId::ModuleId(module) => Some((module, vis)),

View file

@ -29,6 +29,7 @@
//! //!
//! In general, any item in the `ItemTree` stores its `AstId`, which allows mapping it back to its //! In general, any item in the `ItemTree` stores its `AstId`, which allows mapping it back to its
//! surface syntax. //! surface syntax.
#![allow(unexpected_cfgs)]
mod lower; mod lower;
mod pretty; mod pretty;
@ -57,21 +58,21 @@ use triomphe::Arc;
use crate::{ use crate::{
attr::Attrs, attr::Attrs,
db::DefDatabase, db::DefDatabase,
generics::{GenericParams, LifetimeParamData, TypeOrConstParamData}, generics::GenericParams,
path::{GenericArgs, ImportAlias, ModPath, Path, PathKind}, path::{GenericArgs, ImportAlias, ModPath, Path, PathKind},
type_ref::{Mutability, TraitRef, TypeBound, TypeRef}, type_ref::{Mutability, TraitRef, TypeBound, TypeRef},
visibility::{RawVisibility, VisibilityExplicitness}, visibility::{RawVisibility, VisibilityExplicitness},
BlockId, Lookup, BlockId, LocalLifetimeParamId, LocalTypeOrConstParamId, Lookup,
}; };
#[derive(Copy, Clone, Eq, PartialEq)] #[derive(Copy, Clone, Eq, PartialEq)]
pub struct RawVisibilityId(u32); pub struct RawVisibilityId(u32);
impl RawVisibilityId { impl RawVisibilityId {
pub const PUB: Self = RawVisibilityId(u32::max_value()); pub const PUB: Self = RawVisibilityId(u32::MAX);
pub const PRIV_IMPLICIT: Self = RawVisibilityId(u32::max_value() - 1); pub const PRIV_IMPLICIT: Self = RawVisibilityId(u32::MAX - 1);
pub const PRIV_EXPLICIT: Self = RawVisibilityId(u32::max_value() - 2); pub const PRIV_EXPLICIT: Self = RawVisibilityId(u32::MAX - 2);
pub const PUB_CRATE: Self = RawVisibilityId(u32::max_value() - 3); pub const PUB_CRATE: Self = RawVisibilityId(u32::MAX - 3);
} }
impl fmt::Debug for RawVisibilityId { impl fmt::Debug for RawVisibilityId {
@ -293,8 +294,8 @@ pub enum AttrOwner {
Variant(FileItemTreeId<Variant>), Variant(FileItemTreeId<Variant>),
Field(Idx<Field>), Field(Idx<Field>),
Param(Idx<Param>), Param(Idx<Param>),
TypeOrConstParamData(Idx<TypeOrConstParamData>), TypeOrConstParamData(GenericModItem, LocalTypeOrConstParamId),
LifetimeParamData(Idx<LifetimeParamData>), LifetimeParamData(GenericModItem, LocalLifetimeParamId),
} }
macro_rules! from_attrs { macro_rules! from_attrs {
@ -314,8 +315,6 @@ from_attrs!(
Variant(FileItemTreeId<Variant>), Variant(FileItemTreeId<Variant>),
Field(Idx<Field>), Field(Idx<Field>),
Param(Idx<Param>), Param(Idx<Param>),
TypeOrConstParamData(Idx<TypeOrConstParamData>),
LifetimeParamData(Idx<LifetimeParamData>),
); );
/// Trait implemented by all nodes in the item tree. /// 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 { impl From<FileItemTreeId<$typ>> for ModItem {
fn from(id: FileItemTreeId<$typ>) -> ModItem { fn from(id: FileItemTreeId<$typ>) -> ModItem {
ModItem::$typ(id) ModItem::$typ(id)
} }
} }
$(
#[cfg_attr(ignore_fragment, $generic_params)]
impl From<FileItemTreeId<$typ>> for GenericModItem {
fn from(id: FileItemTreeId<$typ>) -> GenericModItem {
GenericModItem::$typ(id)
}
}
)?
)+ )+
$( $(

View file

@ -4,6 +4,7 @@ use std::collections::hash_map::Entry;
use hir_expand::{mod_path::path, name, name::AsName, span_map::SpanMapRef, HirFileId}; use hir_expand::{mod_path::path, name, name::AsName, span_map::SpanMapRef, HirFileId};
use la_arena::Arena; use la_arena::Arena;
use rustc_hash::FxHashMap;
use span::{AstIdMap, SyntaxContextId}; use span::{AstIdMap, SyntaxContextId};
use syntax::{ use syntax::{
ast::{self, HasModuleItem, HasName, HasTypeBounds, IsString}, ast::{self, HasModuleItem, HasName, HasTypeBounds, IsString},
@ -16,11 +17,11 @@ use crate::{
generics::{GenericParams, GenericParamsCollector, TypeParamData, TypeParamProvenance}, generics::{GenericParams, GenericParamsCollector, TypeParamData, TypeParamProvenance},
item_tree::{ item_tree::{
AssocItem, AttrOwner, Const, Either, Enum, ExternBlock, ExternCrate, Field, FieldAstId, AssocItem, AttrOwner, Const, Either, Enum, ExternBlock, ExternCrate, Field, FieldAstId,
Fields, FileItemTreeId, FnFlags, Function, GenericArgs, Idx, IdxRange, Impl, ImportAlias, Fields, FileItemTreeId, FnFlags, Function, GenericArgs, GenericModItem, Idx, IdxRange,
Interned, ItemTree, ItemTreeData, ItemTreeNode, Macro2, MacroCall, MacroRules, Mod, Impl, ImportAlias, Interned, ItemTree, ItemTreeData, ItemTreeNode, Macro2, MacroCall,
ModItem, ModKind, ModPath, Mutability, Name, Param, ParamAstId, Path, Range, RawAttrs, MacroRules, Mod, ModItem, ModKind, ModPath, Mutability, Name, Param, ParamAstId, Path,
RawIdx, RawVisibilityId, Static, Struct, StructKind, Trait, TraitAlias, TypeAlias, Union, Range, RawAttrs, RawIdx, RawVisibilityId, Static, Struct, StructKind, Trait, TraitAlias,
Use, UseTree, UseTreeKind, Variant, TypeAlias, Union, Use, UseTree, UseTreeKind, Variant,
}, },
path::AssociatedTypeBinding, path::AssociatedTypeBinding,
type_ref::{LifetimeRef, TraitBoundModifier, TraitRef, TypeBound, TypeRef}, type_ref::{LifetimeRef, TraitBoundModifier, TraitRef, TypeBound, TypeRef},
@ -36,6 +37,8 @@ pub(super) struct Ctx<'a> {
db: &'a dyn DefDatabase, db: &'a dyn DefDatabase,
tree: ItemTree, tree: ItemTree,
source_ast_id_map: Arc<AstIdMap>, source_ast_id_map: Arc<AstIdMap>,
generic_param_attr_buffer:
FxHashMap<Either<LocalTypeOrConstParamId, LocalLifetimeParamId>, RawAttrs>,
body_ctx: crate::lower::LowerCtx<'a>, body_ctx: crate::lower::LowerCtx<'a>,
} }
@ -44,6 +47,7 @@ impl<'a> Ctx<'a> {
Self { Self {
db, db,
tree: ItemTree::default(), tree: ItemTree::default(),
generic_param_attr_buffer: FxHashMap::default(),
source_ast_id_map: db.ast_id_map(file), source_ast_id_map: db.ast_id_map(file),
body_ctx: crate::lower::LowerCtx::new(db, 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 { pub(super) fn lower_module_items(mut self, item_owner: &dyn HasModuleItem) -> ItemTree {
self.tree.top_level = self.tree.top_level =
item_owner.items().flat_map(|item| self.lower_mod_item(&item)).collect(); item_owner.items().flat_map(|item| self.lower_mod_item(&item)).collect();
assert!(self.generic_param_attr_buffer.is_empty());
self.tree self.tree
} }
@ -89,6 +94,7 @@ impl<'a> Ctx<'a> {
} }
} }
assert!(self.generic_param_attr_buffer.is_empty());
self.tree self.tree
} }
@ -117,6 +123,7 @@ impl<'a> Ctx<'a> {
} }
} }
assert!(self.generic_param_attr_buffer.is_empty());
self.tree self.tree
} }
@ -185,10 +192,12 @@ impl<'a> Ctx<'a> {
let visibility = self.lower_visibility(strukt); let visibility = self.lower_visibility(strukt);
let name = strukt.name()?.as_name(); let name = strukt.name()?.as_name();
let ast_id = self.source_ast_id_map.ast_id(strukt); 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 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 }; 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 { 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 visibility = self.lower_visibility(union);
let name = union.name()?.as_name(); let name = union.name()?.as_name();
let ast_id = self.source_ast_id_map.ast_id(union); 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() { let fields = match union.record_field_list() {
Some(record_field_list) => self.lower_fields(&StructKind::Record(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())), 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 }; 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>> { fn lower_enum(&mut self, enum_: &ast::Enum) -> Option<FileItemTreeId<Enum>> {
let visibility = self.lower_visibility(enum_); let visibility = self.lower_visibility(enum_);
let name = enum_.name()?.as_name(); let name = enum_.name()?.as_name();
let ast_id = self.source_ast_id_map.ast_id(enum_); 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() { let variants = match &enum_.variant_list() {
Some(variant_list) => self.lower_variants(variant_list), Some(variant_list) => self.lower_variants(variant_list),
None => { None => {
FileItemTreeId(self.next_variant_idx())..FileItemTreeId(self.next_variant_idx()) 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 }; 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>> { fn lower_variants(&mut self, variants: &ast::VariantList) -> Range<FileItemTreeId<Variant>> {
@ -414,7 +427,9 @@ impl<'a> Ctx<'a> {
flags, 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( 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 ast_id = self.source_ast_id_map.ast_id(type_alias);
let generic_params = self.lower_generic_params(HasImplicitSelf::No, 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 }; 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>> { 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 name = trait_def.name()?.as_name();
let visibility = self.lower_visibility(trait_def); let visibility = self.lower_visibility(trait_def);
let ast_id = self.source_ast_id_map.ast_id(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_auto = trait_def.auto_token().is_some();
let is_unsafe = trait_def.unsafe_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)) .filter_map(|item_node| self.lower_assoc_item(&item_node))
.collect(); .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 }; 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( fn lower_trait_alias(
@ -504,19 +523,18 @@ impl<'a> Ctx<'a> {
); );
let alias = TraitAlias { name, visibility, generic_params, ast_id }; 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>> { fn lower_impl(&mut self, impl_def: &ast::Impl) -> Option<FileItemTreeId<Impl>> {
let ast_id = self.source_ast_id_map.ast_id(impl_def); 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 // 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 // as if it was an non-trait impl. Ideally we want to create a unique missing ref that only
// equals itself. // 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 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_negative = impl_def.excl_token().is_some();
let is_unsafe = impl_def.unsafe_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()) .flat_map(|it| it.assoc_items())
.filter_map(|item| self.lower_assoc_item(&item)) .filter_map(|item| self.lower_assoc_item(&item))
.collect(); .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 = let res =
Impl { generic_params, target_trait, self_ty, is_negative, is_unsafe, items, ast_id }; 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>> { 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)) 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( fn lower_generic_params(
&mut self, &mut self,
has_implicit_self: HasImplicitSelf, has_implicit_self: HasImplicitSelf,
node: &dyn ast::HasGenericParams, node: &dyn ast::HasGenericParams,
) -> Interned<GenericParams> { ) -> 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(), &param, 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(); let mut generics = GenericParamsCollector::default();
if let HasImplicitSelf::Yes(bounds) = has_implicit_self { if let HasImplicitSelf::Yes(bounds) = has_implicit_self {
@ -635,28 +677,13 @@ impl<'a> Ctx<'a> {
); );
// add super traits as bounds on Self // add super traits as bounds on Self
// i.e., `trait Foo: Bar` is equivalent to `trait Foo where Self: Bar` // i.e., `trait Foo: Bar` is equivalent to `trait Foo where Self: Bar`
let self_param = TypeRef::Path(name![Self].into()); generics.fill_bounds(
generics.fill_bounds(&self.body_ctx, bounds, Either::Left(self_param)); &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(), &param, 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); generics.fill(&self.body_ctx, node, add_param_attrs);
Interned::new(generics.finish()) Interned::new(generics.finish())

View file

@ -8,8 +8,8 @@ use crate::{
generics::{TypeOrConstParamData, WherePredicate, WherePredicateTypeTarget}, generics::{TypeOrConstParamData, WherePredicate, WherePredicateTypeTarget},
item_tree::{ item_tree::{
AttrOwner, Const, DefDatabase, Enum, ExternBlock, ExternCrate, Field, FieldAstId, Fields, AttrOwner, Const, DefDatabase, Enum, ExternBlock, ExternCrate, Field, FieldAstId, Fields,
FileItemTreeId, FnFlags, Function, GenericParams, Impl, Interned, ItemTree, Macro2, FileItemTreeId, FnFlags, Function, GenericModItem, GenericParams, Impl, Interned, ItemTree,
MacroCall, MacroRules, Mod, ModItem, ModKind, Param, ParamAstId, Path, RawAttrs, Macro2, MacroCall, MacroRules, Mod, ModItem, ModKind, Param, ParamAstId, Path, RawAttrs,
RawVisibilityId, Static, Struct, Trait, TraitAlias, TypeAlias, TypeBound, TypeRef, Union, RawVisibilityId, Static, Struct, Trait, TraitAlias, TypeAlias, TypeBound, TypeRef, Union,
Use, UseTree, UseTreeKind, Variant, Use, UseTree, UseTreeKind, Variant,
}, },
@ -276,7 +276,7 @@ impl Printer<'_> {
w!(self, "extern \"{}\" ", abi); w!(self, "extern \"{}\" ", abi);
} }
w!(self, "fn {}", name.display(self.db.upcast())); 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, "("); w!(self, "(");
if !params.is_empty() { if !params.is_empty() {
self.indented(|this| { self.indented(|this| {
@ -316,7 +316,7 @@ impl Printer<'_> {
self.print_ast_id(ast_id.erase()); self.print_ast_id(ast_id.erase());
self.print_visibility(*visibility); self.print_visibility(*visibility);
w!(self, "struct {}", name.display(self.db.upcast())); 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); self.print_fields_and_where_clause(fields, generic_params);
if matches!(fields, Fields::Record(_)) { if matches!(fields, Fields::Record(_)) {
wln!(self); wln!(self);
@ -329,7 +329,7 @@ impl Printer<'_> {
self.print_ast_id(ast_id.erase()); self.print_ast_id(ast_id.erase());
self.print_visibility(*visibility); self.print_visibility(*visibility);
w!(self, "union {}", name.display(self.db.upcast())); 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); self.print_fields_and_where_clause(fields, generic_params);
if matches!(fields, Fields::Record(_)) { if matches!(fields, Fields::Record(_)) {
wln!(self); wln!(self);
@ -342,7 +342,7 @@ impl Printer<'_> {
self.print_ast_id(ast_id.erase()); self.print_ast_id(ast_id.erase());
self.print_visibility(*visibility); self.print_visibility(*visibility);
w!(self, "enum {}", name.display(self.db.upcast())); 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.print_where_clause_and_opening_brace(generic_params);
self.indented(|this| { self.indented(|this| {
for variant in FileItemTreeId::range_iter(variants.clone()) { for variant in FileItemTreeId::range_iter(variants.clone()) {
@ -394,7 +394,7 @@ impl Printer<'_> {
w!(self, "auto "); w!(self, "auto ");
} }
w!(self, "trait {}", name.display(self.db.upcast())); 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.print_where_clause_and_opening_brace(generic_params);
self.indented(|this| { self.indented(|this| {
for item in &**items { for item in &**items {
@ -408,7 +408,7 @@ impl Printer<'_> {
self.print_ast_id(ast_id.erase()); self.print_ast_id(ast_id.erase());
self.print_visibility(*visibility); self.print_visibility(*visibility);
w!(self, "trait {}", name.display(self.db.upcast())); w!(self, "trait {}", name.display(self.db.upcast()));
self.print_generic_params(generic_params); self.print_generic_params(generic_params, it.into());
w!(self, " = "); w!(self, " = ");
self.print_where_clause(generic_params); self.print_where_clause(generic_params);
w!(self, ";"); w!(self, ";");
@ -429,7 +429,7 @@ impl Printer<'_> {
w!(self, "unsafe"); w!(self, "unsafe");
} }
w!(self, "impl"); w!(self, "impl");
self.print_generic_params(generic_params); self.print_generic_params(generic_params, it.into());
w!(self, " "); w!(self, " ");
if *is_negative { if *is_negative {
w!(self, "!"); w!(self, "!");
@ -453,7 +453,7 @@ impl Printer<'_> {
self.print_ast_id(ast_id.erase()); self.print_ast_id(ast_id.erase());
self.print_visibility(*visibility); self.print_visibility(*visibility);
w!(self, "type {}", name.display(self.db.upcast())); 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() { if !bounds.is_empty() {
w!(self, ": "); w!(self, ": ");
self.print_type_bounds(bounds); self.print_type_bounds(bounds);
@ -525,7 +525,7 @@ impl Printer<'_> {
print_path(self.db, path, self).unwrap(); 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() { if params.is_empty() {
return; return;
} }
@ -537,7 +537,7 @@ impl Printer<'_> {
w!(self, ", "); w!(self, ", ");
} }
first = false; first = false;
self.print_attrs_of(idx, " "); self.print_attrs_of(AttrOwner::LifetimeParamData(parent, idx), " ");
w!(self, "{}", lt.name.display(self.db.upcast())); w!(self, "{}", lt.name.display(self.db.upcast()));
} }
for (idx, x) in params.type_or_consts.iter() { for (idx, x) in params.type_or_consts.iter() {
@ -545,7 +545,7 @@ impl Printer<'_> {
w!(self, ", "); w!(self, ", ");
} }
first = false; first = false;
self.print_attrs_of(idx, " "); self.print_attrs_of(AttrOwner::TypeOrConstParamData(parent, idx), " ");
match x { match x {
TypeOrConstParamData::TypeParamData(ty) => match &ty.name { TypeOrConstParamData::TypeParamData(ty) => match &ty.name {
Some(name) => w!(self, "{}", name.display(self.db.upcast())), Some(name) => w!(self, "{}", name.display(self.db.upcast())),

View file

@ -427,10 +427,18 @@ fn generics_with_attributes() {
check( check(
r#" r#"
struct S<#[cfg(never)] T>; struct S<#[cfg(never)] T>;
struct S<A, B, #[cfg(never)] C>;
struct S<A, #[cfg(never)] B, C>;
"#, "#,
expect![[r#" expect![[r#"
// AstId: 1 // AstId: 1
pub(self) struct S<#[cfg(never)] T>; 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>;
"#]], "#]],
) )
} }

View file

@ -1,26 +1,34 @@
//! Context for lowering paths. //! Context for lowering paths.
use std::cell::OnceCell; use std::cell::{OnceCell, RefCell};
use hir_expand::{ use hir_expand::{
span_map::{SpanMap, SpanMapRef}, span_map::{SpanMap, SpanMapRef},
AstId, HirFileId, InFile, AstId, HirFileId, InFile,
}; };
use intern::Interned;
use span::{AstIdMap, AstIdNode}; use span::{AstIdMap, AstIdNode};
use syntax::ast; use syntax::ast;
use triomphe::Arc; use triomphe::Arc;
use crate::{db::DefDatabase, path::Path}; use crate::{db::DefDatabase, path::Path, type_ref::TypeBound};
pub struct LowerCtx<'a> { pub struct LowerCtx<'a> {
pub db: &'a dyn DefDatabase, pub db: &'a dyn DefDatabase,
file_id: HirFileId, file_id: HirFileId,
span_map: OnceCell<SpanMap>, span_map: OnceCell<SpanMap>,
ast_id_map: OnceCell<Arc<AstIdMap>>, ast_id_map: OnceCell<Arc<AstIdMap>>,
impl_trait_bounds: RefCell<Vec<Vec<Interned<TypeBound>>>>,
} }
impl<'a> LowerCtx<'a> { impl<'a> LowerCtx<'a> {
pub fn new(db: &'a dyn DefDatabase, file_id: HirFileId) -> Self { 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( pub fn with_span_map_cell(
@ -28,7 +36,13 @@ impl<'a> LowerCtx<'a> {
file_id: HirFileId, file_id: HirFileId,
span_map: OnceCell<SpanMap>, span_map: OnceCell<SpanMap>,
) -> Self { ) -> 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<'_> { 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), 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()
}
} }

View file

@ -186,3 +186,33 @@ fn#0:1@45..47#0# foo#0:1@48..51#0#(#0:1@51..52#0#&#0:1@52..53#0#self#0:1@53..57#
}#0:1@76..77#0#"#]], }#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;"##]],
);
}

View file

@ -5,7 +5,7 @@
use std::{cmp::Ordering, iter, mem, ops::Not}; 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 cfg::{CfgExpr, CfgOptions};
use either::Either; use either::Either;
use hir_expand::{ use hir_expand::{
@ -15,15 +15,13 @@ use hir_expand::{
builtin_fn_macro::find_builtin_macro, builtin_fn_macro::find_builtin_macro,
name::{name, AsName, Name}, name::{name, AsName, Name},
proc_macro::CustomProcMacroExpander, proc_macro::CustomProcMacroExpander,
ExpandResult, ExpandTo, HirFileId, InFile, MacroCallId, MacroCallKind, MacroCallLoc, ExpandTo, HirFileId, InFile, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind,
MacroDefId, MacroDefKind,
}; };
use itertools::{izip, Itertools}; use itertools::{izip, Itertools};
use la_arena::Idx; use la_arena::Idx;
use limit::Limit; use limit::Limit;
use rustc_hash::{FxHashMap, FxHashSet}; use rustc_hash::{FxHashMap, FxHashSet};
use span::{Edition, ErasedFileAstId, FileAstId, Span, SyntaxContextId}; use span::{Edition, ErasedFileAstId, FileAstId, Span, SyntaxContextId};
use stdx::always;
use syntax::ast; use syntax::ast;
use triomphe::Arc; use triomphe::Arc;
@ -279,7 +277,8 @@ impl DefCollector<'_> {
fn seed_with_top_level(&mut self) { fn seed_with_top_level(&mut self) {
let _p = tracing::span!(tracing::Level::INFO, "seed_with_top_level").entered(); 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 item_tree = self.db.file_item_tree(file_id.into());
let attrs = item_tree.top_level_attrs(self.db, self.def_map.krate); 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(); 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()); crate_data.proc_macro_loading_error = Some(e.clone());
} }
for (name, dep) in &self.deps { let mut process = true;
if dep.is_prelude() {
crate_data
.extern_prelude
.insert(name.clone(), (CrateRootModuleId { krate: dep.crate_id }, None));
}
}
// Process other crate-level attributes. // Process other crate-level attributes.
for attr in &*attrs { for attr in &*attrs {
if let Some(cfg) = attr.cfg() { if let Some(cfg) = attr.cfg() {
if self.cfg_options.check(&cfg) == Some(false) { if self.cfg_options.check(&cfg) == Some(false) {
return; process = false;
break;
} }
} }
let Some(attr_name) = attr.path.as_ident() else { continue }; 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(); self.inject_prelude();
if !process {
return;
}
ModCollector { ModCollector {
def_collector: self, def_collector: self,
macro_depth: 0, macro_depth: 0,
@ -362,6 +385,7 @@ impl DefCollector<'_> {
mod_dir: ModDir::root(), mod_dir: ModDir::root(),
} }
.collect_in_top_module(item_tree.top_level_items()); .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) { fn seed_with_inner(&mut self, tree_id: TreeId) {
@ -519,15 +543,12 @@ impl DefCollector<'_> {
let krate = if self.def_map.data.no_std { let krate = if self.def_map.data.no_std {
name![core] name![core]
} else if self.def_map.extern_prelude().any(|(name, _)| *name == name![std]) {
name![std]
} else { } else {
let std = name![std]; // If `std` does not exist for some reason, fall back to core. This mostly helps
if self.def_map.extern_prelude().any(|(name, _)| *name == std) { // keep r-a's own tests minimal.
std name![core]
} 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]
}
}; };
let edition = match self.def_map.data.edition { let edition = match self.def_map.data.edition {
@ -1389,31 +1410,6 @@ impl DefCollector<'_> {
} }
let file_id = macro_call_id.as_file(); 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. // 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); let item_tree = self.db.file_item_tree(file_id);

View file

@ -6,7 +6,7 @@ use base_db::CrateId;
use cfg::{CfgExpr, CfgOptions}; use cfg::{CfgExpr, CfgOptions};
use hir_expand::{attrs::AttrId, ErasedAstId, MacroCallKind}; use hir_expand::{attrs::AttrId, ErasedAstId, MacroCallKind};
use la_arena::Idx; use la_arena::Idx;
use syntax::{ast, SyntaxError}; use syntax::ast;
use crate::{ use crate::{
item_tree::{self, ItemTreeId}, item_tree::{self, ItemTreeId},
@ -23,8 +23,6 @@ pub enum DefDiagnosticKind {
UnconfiguredCode { ast: ErasedAstId, cfg: CfgExpr, opts: CfgOptions }, UnconfiguredCode { ast: ErasedAstId, cfg: CfgExpr, opts: CfgOptions },
UnresolvedProcMacro { ast: MacroCallKind, krate: CrateId }, UnresolvedProcMacro { ast: MacroCallKind, krate: CrateId },
UnresolvedMacroCall { ast: MacroCallKind, path: ModPath }, UnresolvedMacroCall { ast: MacroCallKind, path: ModPath },
MacroError { ast: MacroCallKind, message: String },
MacroExpansionParseError { ast: MacroCallKind, errors: Box<[SyntaxError]> },
UnimplementedBuiltinMacro { ast: AstId<ast::Macro> }, UnimplementedBuiltinMacro { ast: AstId<ast::Macro> },
InvalidDeriveTarget { ast: AstId<ast::Item>, id: usize }, InvalidDeriveTarget { ast: AstId<ast::Item>, id: usize },
MalformedDerive { ast: AstId<ast::Adt>, 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 // 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 // yet the diagnostic handler in ide-diagnostics has to figure out what happened because this
// struct loses all that information! // struct loses all that information!
pub(crate) fn unresolved_proc_macro( pub fn unresolved_proc_macro(
container: LocalModuleId, container: LocalModuleId,
ast: MacroCallKind, ast: MacroCallKind,
krate: CrateId, krate: CrateId,
@ -106,25 +104,6 @@ impl DefDiagnostic {
Self { in_module: container, kind: DefDiagnosticKind::UnresolvedProcMacro { ast, krate } } 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 // FIXME: Whats the difference between this and unresolved_proc_macro
pub(crate) fn unresolved_macro_call( pub(crate) fn unresolved_macro_call(
container: LocalModuleId, container: LocalModuleId,

View file

@ -208,6 +208,13 @@ pub(super) fn lower_generic_args(
.and_then(|args| lower_generic_args(lower_ctx, args)) .and_then(|args| lower_generic_args(lower_ctx, args))
.map(Interned::new); .map(Interned::new);
let type_ref = assoc_type_arg.ty().map(|it| TypeRef::from_ast(lower_ctx, it)); 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() { let bounds = if let Some(l) = assoc_type_arg.type_bound_list() {
l.bounds() l.bounds()
.map(|it| Interned::new(TypeBound::from_ast(lower_ctx, it))) .map(|it| Interned::new(TypeBound::from_ast(lower_ctx, it)))

View file

@ -1,5 +1,5 @@
//! Name resolution façade. //! Name resolution façade.
use std::{fmt, hash::BuildHasherDefault, mem}; use std::{fmt, hash::BuildHasherDefault, iter, mem};
use base_db::CrateId; use base_db::CrateId;
use hir_expand::{ use hir_expand::{
@ -591,13 +591,13 @@ impl Resolver {
pub fn where_predicates_in_scope( pub fn where_predicates_in_scope(
&self, &self,
) -> impl Iterator<Item = &crate::generics::WherePredicate> { ) -> impl Iterator<Item = (&crate::generics::WherePredicate, &GenericDefId)> {
self.scopes() self.scopes()
.filter_map(|scope| match scope { .filter_map(|scope| match scope {
Scope::GenericParams { params, .. } => Some(params), Scope::GenericParams { params, def } => Some((params, def)),
_ => None, _ => 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> { pub fn generic_def(&self) -> Option<GenericDefId> {

View file

@ -5,7 +5,7 @@ use base_db::CrateId;
use cfg::CfgExpr; use cfg::CfgExpr;
use either::Either; use either::Either;
use intern::Interned; 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 smallvec::{smallvec, SmallVec};
use span::{Span, SyntaxContextId}; use span::{Span, SyntaxContextId};
use syntax::unescape; use syntax::unescape;
@ -239,7 +239,12 @@ impl Attr {
span, span,
}))) })))
} else if let Some(tt) = ast.token_tree() { } 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)))) Some(Interned::new(AttrInput::TokenTree(Box::new(tree))))
} else { } else {
None None
@ -247,8 +252,18 @@ impl Attr {
Some(Attr { id, path, input, ctxt: span.ctx }) Some(Attr { id, path, input, ctxt: span.ctx })
} }
fn from_tt(db: &dyn ExpandDatabase, tt: &[tt::TokenTree], id: AttrId) -> Option<Attr> { fn from_tt(db: &dyn ExpandDatabase, mut tt: &[tt::TokenTree], id: AttrId) -> Option<Attr> {
let ctxt = tt.first()?.first_span().ctx; 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 let path_end = tt
.iter() .iter()
.position(|tt| { .position(|tt| {
@ -430,7 +445,7 @@ fn inner_attributes(
// Input subtree is: `(cfg, $(attr),+)` // Input subtree is: `(cfg, $(attr),+)`
// Split it up into a `cfg` subtree and the `attr` subtrees. // Split it up into a `cfg` subtree and the `attr` subtrees.
pub fn parse_cfg_attr_input( fn parse_cfg_attr_input(
subtree: &Subtree, subtree: &Subtree,
) -> Option<(&[tt::TokenTree], impl Iterator<Item = &[tt::TokenTree]>)> { ) -> Option<(&[tt::TokenTree], impl Iterator<Item = &[tt::TokenTree]>)> {
let mut parts = subtree let mut parts = subtree

View file

@ -1,6 +1,7 @@
//! Builtin derives. //! Builtin derives.
use itertools::izip; use itertools::izip;
use mbe::DocCommentDesugarMode;
use rustc_hash::FxHashSet; use rustc_hash::FxHashSet;
use span::{MacroCallId, Span}; use span::{MacroCallId, Span};
use stdx::never; use stdx::never;
@ -262,7 +263,12 @@ fn parse_adt(tt: &tt::Subtree, call_site: Span) -> Result<BasicAdtInfo, ExpandEr
match this { match this {
Some(it) => { Some(it) => {
param_type_set.insert(it.as_name()); 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 => { None => {
tt::Subtree::empty(::tt::DelimSpan { open: call_site, close: call_site }) 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 &param { let bounds = match &param {
ast::TypeOrConstParam::Type(it) => it ast::TypeOrConstParam::Type(it) => it.type_bound_list().map(|it| {
.type_bound_list() mbe::syntax_node_to_token_tree(
.map(|it| mbe::syntax_node_to_token_tree(it.syntax(), tm, call_site)), it.syntax(),
tm,
call_site,
DocCommentDesugarMode::ProcMacro,
)
}),
ast::TypeOrConstParam::Const(_) => None, ast::TypeOrConstParam::Const(_) => None,
}; };
let ty = if let ast::TypeOrConstParam::Const(param) = param { let ty = if let ast::TypeOrConstParam::Const(param) = param {
let ty = param let ty = param
.ty() .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(|| { .unwrap_or_else(|| {
tt::Subtree::empty(::tt::DelimSpan { open: call_site, close: call_site }) 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 { let where_clause = if let Some(w) = where_clause {
w.predicates() 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() .collect()
} else { } else {
vec![] 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(); let name = p.path()?.qualifier()?.as_single_name_ref()?.as_name();
param_type_set.contains(&name).then_some(p) 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(); .collect();
let name_token = name_to_token(tm, name)?; let name_token = name_to_token(tm, name)?;
Ok(BasicAdtInfo { name: name_token, shape, param_types, where_clause, associated_types }) Ok(BasicAdtInfo { name: name_token, shape, param_types, where_clause, associated_types })

View file

@ -441,21 +441,21 @@ fn unquote_str(lit: &tt::Literal) -> Option<(String, Span)> {
let span = lit.span; let span = lit.span;
let lit = ast::make::tokens::literal(&lit.to_string()); let lit = ast::make::tokens::literal(&lit.to_string());
let token = ast::String::cast(lit)?; 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)> { fn unquote_char(lit: &tt::Literal) -> Option<(char, Span)> {
let span = lit.span; let span = lit.span;
let lit = ast::make::tokens::literal(&lit.to_string()); let lit = ast::make::tokens::literal(&lit.to_string());
let token = ast::Char::cast(lit)?; 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)> { fn unquote_byte_string(lit: &tt::Literal) -> Option<(Vec<u8>, Span)> {
let span = lit.span; let span = lit.span;
let lit = ast::make::tokens::literal(&lit.to_string()); let lit = ast::make::tokens::literal(&lit.to_string());
let token = ast::ByteString::cast(lit)?; 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( fn compile_error_expand(

View file

@ -3,7 +3,7 @@
use base_db::{salsa, CrateId, FileId, SourceDatabase}; use base_db::{salsa, CrateId, FileId, SourceDatabase};
use either::Either; use either::Either;
use limit::Limit; 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 rustc_hash::FxHashSet;
use span::{AstIdMap, Span, SyntaxContextData, SyntaxContextId}; use span::{AstIdMap, Span, SyntaxContextData, SyntaxContextId};
use syntax::{ast, AstNode, Parse, SyntaxElement, SyntaxError, SyntaxNode, SyntaxToken, T}; use syntax::{ast, AstNode, Parse, SyntaxElement, SyntaxError, SyntaxNode, SyntaxToken, T};
@ -132,7 +132,7 @@ pub trait ExpandDatabase: SourceDatabase {
fn parse_macro_expansion_error( fn parse_macro_expansion_error(
&self, &self,
macro_call: MacroCallId, macro_call: MacroCallId,
) -> ExpandResult<Box<[SyntaxError]>>; ) -> Option<Arc<ExpandResult<Arc<[SyntaxError]>>>>;
} }
/// This expands the given macro call, but with different arguments. This is /// 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 // Build the subtree and token mapping for the speculative args
let (mut tt, undo_info) = match loc.kind { let (mut tt, undo_info) = match loc.kind {
MacroCallKind::FnLike { .. } => ( 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, SyntaxFixupUndoInfo::NONE,
), ),
MacroCallKind::Attr { .. } if loc.def.is_attribute_derive() => ( 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, SyntaxFixupUndoInfo::NONE,
), ),
MacroCallKind::Derive { derive_attr_index: index, .. } MacroCallKind::Derive { derive_attr_index: index, .. }
@ -176,7 +190,12 @@ pub fn expand_speculative(
let censor_cfg = let censor_cfg =
cfg_process::process_cfg_attrs(db, speculative_args, &loc).unwrap_or_default(); 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 { fixups.append.retain(|it, _| match it {
syntax::NodeOrToken::Token(_) => true, syntax::NodeOrToken::Token(_) => true,
it => !censor.contains(it) && !censor_cfg.contains(it), it => !censor.contains(it) && !censor_cfg.contains(it),
@ -191,6 +210,7 @@ pub fn expand_speculative(
fixups.append, fixups.append,
fixups.remove, fixups.remove,
span, span,
DocCommentDesugarMode::ProcMacro,
), ),
fixups.undo_info, fixups.undo_info,
) )
@ -212,7 +232,12 @@ pub fn expand_speculative(
}?; }?;
match attr.token_tree() { match attr.token_tree() {
Some(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); tree.delimiter = tt::Delimiter::invisible_spanned(span);
Some(tree) Some(tree)
@ -332,9 +357,14 @@ fn parse_macro_expansion(
fn parse_macro_expansion_error( fn parse_macro_expansion_error(
db: &dyn ExpandDatabase, db: &dyn ExpandDatabase,
macro_call_id: MacroCallId, macro_call_id: MacroCallId,
) -> ExpandResult<Box<[SyntaxError]>> { ) -> Option<Arc<ExpandResult<Arc<[SyntaxError]>>>> {
db.parse_macro_expansion(MacroFileId { macro_call_id }) let e: ExpandResult<Arc<[SyntaxError]>> =
.map(|it| it.0.errors().into_boxed_slice()) 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( pub(crate) fn parse_with_map(
@ -432,7 +462,16 @@ fn macro_arg(db: &dyn ExpandDatabase, id: MacroCallId) -> MacroArgResult {
return dummy_tt(kind); 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() { if loc.def.is_proc_macro() {
// proc macros expect their inputs without parentheses, MBEs expect it with them included // proc macros expect their inputs without parentheses, MBEs expect it with them included
tt.delimiter.kind = tt::DelimiterKind::Invisible; 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 (mut tt, undo_info) = {
let syntax = item_node.syntax(); let syntax = item_node.syntax();
let censor_cfg = cfg_process::process_cfg_attrs(db, syntax, &loc).unwrap_or_default(); 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 { fixups.append.retain(|it, _| match it {
syntax::NodeOrToken::Token(_) => true, syntax::NodeOrToken::Token(_) => true,
it => !censor.contains(it) && !censor_cfg.contains(it), it => !censor.contains(it) && !censor_cfg.contains(it),
@ -484,6 +524,7 @@ fn macro_arg(db: &dyn ExpandDatabase, id: MacroCallId) -> MacroArgResult {
fixups.append, fixups.append,
fixups.remove, fixups.remove,
span, span,
DocCommentDesugarMode::ProcMacro,
), ),
fixups.undo_info, fixups.undo_info,
) )

View file

@ -2,6 +2,7 @@
use std::sync::OnceLock; use std::sync::OnceLock;
use base_db::{CrateId, VersionReq}; use base_db::{CrateId, VersionReq};
use mbe::DocCommentDesugarMode;
use span::{Edition, MacroCallId, Span, SyntaxContextId}; use span::{Edition, MacroCallId, Span, SyntaxContextId};
use stdx::TupleExt; use stdx::TupleExt;
use syntax::{ast, AstNode}; use syntax::{ast, AstNode};
@ -158,6 +159,7 @@ impl DeclarativeMacroExpander {
map.span_for_range( map.span_for_range(
macro_rules.macro_rules_token().unwrap().text_range(), macro_rules.macro_rules_token().unwrap().text_range(),
), ),
DocCommentDesugarMode::Mbe,
); );
mbe::DeclarativeMacro::parse_macro_rules(&tt, edition, new_meta_vars) mbe::DeclarativeMacro::parse_macro_rules(&tt, edition, new_meta_vars)
@ -175,6 +177,7 @@ impl DeclarativeMacroExpander {
arg.syntax(), arg.syntax(),
map.as_ref(), map.as_ref(),
map.span_for_range(macro_def.macro_token().unwrap().text_range()), map.span_for_range(macro_def.macro_token().unwrap().text_range()),
DocCommentDesugarMode::Mbe,
); );
mbe::DeclarativeMacro::parse_macro2(&tt, edition, new_meta_vars) mbe::DeclarativeMacro::parse_macro2(&tt, edition, new_meta_vars)

View file

@ -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> //! 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 base_db::CrateId;
use mbe::DocCommentDesugarMode;
use span::SyntaxContextId; use span::SyntaxContextId;
use syntax::{ted, Parse, SyntaxElement, SyntaxNode, TextSize, WalkEvent}; use syntax::{ted, Parse, SyntaxElement, SyntaxNode, TextSize, WalkEvent};
use triomphe::Arc; use triomphe::Arc;
@ -80,7 +81,12 @@ pub fn expand_eager_macro_input(
return ExpandResult { value: None, err }; 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; subtree.delimiter.kind = crate::tt::DelimiterKind::Invisible;

View file

@ -1,6 +1,7 @@
//! To make attribute macros work reliably when typing, we need to take care to //! 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. //! fix up syntax errors in the code we're passing to them.
use mbe::DocCommentDesugarMode;
use rustc_hash::{FxHashMap, FxHashSet}; use rustc_hash::{FxHashMap, FxHashSet};
use smallvec::SmallVec; use smallvec::SmallVec;
use span::{ErasedFileAstId, Span, SpanAnchor, FIXUP_ERASED_FILE_AST_ID_MARKER}; use span::{ErasedFileAstId, Span, SpanAnchor, FIXUP_ERASED_FILE_AST_ID_MARKER};
@ -49,6 +50,7 @@ pub(crate) fn fixup_syntax(
span_map: SpanMapRef<'_>, span_map: SpanMapRef<'_>,
node: &SyntaxNode, node: &SyntaxNode,
call_site: Span, call_site: Span,
mode: DocCommentDesugarMode,
) -> SyntaxFixups { ) -> SyntaxFixups {
let mut append = FxHashMap::<SyntaxElement, _>::default(); let mut append = FxHashMap::<SyntaxElement, _>::default();
let mut remove = FxHashSet::<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) { if can_handle_error(&node) && has_error_to_handle(&node) {
remove.insert(node.clone().into()); remove.insert(node.clone().into());
// the node contains an error node, we have to completely replace it by something valid // 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; let idx = original.len() as u32;
original.push(original_tree); original.push(original_tree);
let span = span_map.span_for_range(node_range); let span = span_map.span_for_range(node_range);
@ -360,6 +362,7 @@ fn reverse_fixups_(tt: &mut Subtree, undo_info: &[Subtree]) {
mod tests { mod tests {
use base_db::FileId; use base_db::FileId;
use expect_test::{expect, Expect}; use expect_test::{expect, Expect};
use mbe::DocCommentDesugarMode;
use syntax::TextRange; use syntax::TextRange;
use triomphe::Arc; use triomphe::Arc;
@ -402,6 +405,7 @@ mod tests {
span_map.as_ref(), span_map.as_ref(),
&parsed.syntax_node(), &parsed.syntax_node(),
span_map.span_for_range(TextRange::empty(0.into())), span_map.span_for_range(TextRange::empty(0.into())),
DocCommentDesugarMode::Mbe,
); );
let mut tt = mbe::syntax_node_to_token_tree_modified( let mut tt = mbe::syntax_node_to_token_tree_modified(
&parsed.syntax_node(), &parsed.syntax_node(),
@ -409,6 +413,7 @@ mod tests {
fixups.append, fixups.append,
fixups.remove, fixups.remove,
span_map.span_for_range(TextRange::empty(0.into())), span_map.span_for_range(TextRange::empty(0.into())),
DocCommentDesugarMode::Mbe,
); );
let actual = format!("{tt}\n"); let actual = format!("{tt}\n");
@ -436,6 +441,7 @@ mod tests {
&parsed.syntax_node(), &parsed.syntax_node(),
span_map.as_ref(), span_map.as_ref(),
span_map.span_for_range(TextRange::empty(0.into())), span_map.span_for_range(TextRange::empty(0.into())),
DocCommentDesugarMode::Mbe,
); );
assert!( assert!(
check_subtree_eq(&tt, &original_as_tt), check_subtree_eq(&tt, &original_as_tt),

View file

@ -132,13 +132,13 @@ pub enum ExpandError {
MacroDefinition, MacroDefinition,
Mbe(mbe::ExpandError), Mbe(mbe::ExpandError),
RecursionOverflow, RecursionOverflow,
Other(Box<Box<str>>), Other(Arc<Box<str>>),
ProcMacroPanic(Box<Box<str>>), ProcMacroPanic(Arc<Box<str>>),
} }
impl ExpandError { impl ExpandError {
pub fn other(msg: impl Into<Box<str>>) -> Self { pub fn other(msg: impl Into<Box<str>>) -> Self {
ExpandError::Other(Box::new(msg.into())) ExpandError::Other(Arc::new(msg.into()))
} }
} }

View file

@ -8,6 +8,7 @@ use rustc_hash::FxHashMap;
use span::Span; use span::Span;
use stdx::never; use stdx::never;
use syntax::SmolStr; use syntax::SmolStr;
use triomphe::Arc;
use crate::{db::ExpandDatabase, tt, ExpandError, ExpandResult}; use crate::{db::ExpandDatabase, tt, ExpandError, ExpandResult};
@ -157,7 +158,7 @@ impl CustomProcMacroExpander {
ProcMacroExpansionError::System(text) ProcMacroExpansionError::System(text)
| ProcMacroExpansionError::Panic(text) => ExpandResult::new( | ProcMacroExpansionError::Panic(text) => ExpandResult::new(
tt::Subtree::empty(tt::DelimSpan { open: call_site, close: call_site }), 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())),
), ),
}, },
} }

View file

@ -806,7 +806,7 @@ pub(crate) fn impl_datum_query(
krate: CrateId, krate: CrateId,
impl_id: ImplId, impl_id: ImplId,
) -> Arc<ImplDatum> { ) -> 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); debug!("impl_datum {:?}", impl_id);
let impl_: hir_def::ImplId = from_chalk(db, impl_id); let impl_: hir_def::ImplId = from_chalk(db, impl_id);
impl_def_datum(db, krate, impl_id, impl_) impl_def_datum(db, krate, impl_id, impl_)

View file

@ -27,6 +27,7 @@ pub trait TyExt {
fn is_scalar(&self) -> bool; fn is_scalar(&self) -> bool;
fn is_floating_point(&self) -> bool; fn is_floating_point(&self) -> bool;
fn is_never(&self) -> bool; fn is_never(&self) -> bool;
fn is_str(&self) -> bool;
fn is_unknown(&self) -> bool; fn is_unknown(&self) -> bool;
fn contains_unknown(&self) -> bool; fn contains_unknown(&self) -> bool;
fn is_ty_var(&self) -> bool; fn is_ty_var(&self) -> bool;
@ -87,6 +88,10 @@ impl TyExt for Ty {
matches!(self.kind(Interner), TyKind::Never) matches!(self.kind(Interner), TyKind::Never)
} }
fn is_str(&self) -> bool {
matches!(self.kind(Interner), TyKind::Str)
}
fn is_unknown(&self) -> bool { fn is_unknown(&self) -> bool {
matches!(self.kind(Interner), TyKind::Error) matches!(self.kind(Interner), TyKind::Error)
} }

View file

@ -797,8 +797,20 @@ impl HirDisplay for Ty {
c.hir_fmt(f)?; c.hir_fmt(f)?;
write!(f, "]")?; write!(f, "]")?;
} }
TyKind::Raw(m, t) | TyKind::Ref(m, _, t) => { kind @ (TyKind::Raw(m, t) | TyKind::Ref(m, _, t)) => {
if matches!(self.kind(Interner), TyKind::Raw(..)) { 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!( write!(
f, f,
"*{}", "*{}",
@ -807,15 +819,6 @@ impl HirDisplay for Ty {
Mutability::Mut => "mut ", Mutability::Mut => "mut ",
} }
)?; )?;
} else {
write!(
f,
"&{}",
match m {
Mutability::Not => "",
Mutability::Mut => "mut ",
}
)?;
} }
// FIXME: all this just to decide whether to use parentheses... // 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); 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, "<")?; write!(f, "<")?;
hir_fmt_generic_arguments(f, parameters_to_write)?; hir_fmt_generic_arguments(f, parameters_to_write)?;
write!(f, ">")?; write!(f, ">")?;
@ -1403,6 +1417,18 @@ fn hir_fmt_generic_arguments(
None => (parameters, &[][..]), None => (parameters, &[][..]),
}; };
for generic_arg in lifetimes.iter().chain(ty_or_const) { 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 { if !first {
write!(f, ", ")?; write!(f, ", ")?;
} }
@ -1728,9 +1754,9 @@ impl HirDisplay for LifetimeData {
LifetimeData::BoundVar(idx) => idx.hir_fmt(f), LifetimeData::BoundVar(idx) => idx.hir_fmt(f),
LifetimeData::InferenceVar(_) => write!(f, "_"), LifetimeData::InferenceVar(_) => write!(f, "_"),
LifetimeData::Static => write!(f, "'static"), LifetimeData::Static => write!(f, "'static"),
LifetimeData::Error => write!(f, "'{{error}}"), LifetimeData::Error => write!(f, "'?"),
LifetimeData::Erased => Ok(()), LifetimeData::Erased => write!(f, "'<erased>"),
LifetimeData::Phantom(_, _) => Ok(()), LifetimeData::Phantom(void, _) => match *void {},
} }
} }
} }

View file

@ -198,6 +198,7 @@ pub enum InferenceDiagnostic {
NoSuchField { NoSuchField {
field: ExprOrPatId, field: ExprOrPatId,
private: bool, private: bool,
variant: VariantId,
}, },
PrivateField { PrivateField {
expr: ExprId, expr: ExprId,

View file

@ -563,6 +563,7 @@ impl InferenceContext<'_> {
InferenceDiagnostic::NoSuchField { InferenceDiagnostic::NoSuchField {
field: field.expr.into(), field: field.expr.into(),
private: true, private: true,
variant: def,
}, },
); );
} }
@ -572,6 +573,7 @@ impl InferenceContext<'_> {
self.push_diagnostic(InferenceDiagnostic::NoSuchField { self.push_diagnostic(InferenceDiagnostic::NoSuchField {
field: field.expr.into(), field: field.expr.into(),
private: false, private: false,
variant: def,
}); });
None None
} }

View file

@ -177,6 +177,7 @@ impl InferenceContext<'_> {
self.push_diagnostic(InferenceDiagnostic::NoSuchField { self.push_diagnostic(InferenceDiagnostic::NoSuchField {
field: inner.into(), field: inner.into(),
private: true, private: true,
variant: def,
}); });
} }
let f = field_types[local_id].clone(); let f = field_types[local_id].clone();
@ -190,6 +191,7 @@ impl InferenceContext<'_> {
self.push_diagnostic(InferenceDiagnostic::NoSuchField { self.push_diagnostic(InferenceDiagnostic::NoSuchField {
field: inner.into(), field: inner.into(),
private: false, private: false,
variant: def,
}); });
self.err_ty() self.err_ty()
} }

View file

@ -345,51 +345,47 @@ impl<'a> TyLoweringContext<'a> {
} }
ImplTraitLoweringState::Param(counter) => { ImplTraitLoweringState::Param(counter) => {
let idx = counter.get(); 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); counter.set(idx + count_impl_traits(type_ref) as u16);
if let Some(generics) = self.generics() { let kind = self
let param = generics .generics()
.iter() .expect("param impl trait lowering must be in a generic def")
.filter(|(_, data)| { .iter()
matches!( .filter_map(|(id, data)| match (id, data) {
data, (
GenericParamDataRef::TypeParamData(data) GenericParamId::TypeParamId(id),
if data.provenance == TypeParamProvenance::ArgumentImplTrait GenericParamDataRef::TypeParamData(data),
) ) if data.provenance == TypeParamProvenance::ArgumentImplTrait => {
}) Some(id)
.nth(idx as usize) }
.map_or(TyKind::Error, |(id, _)| { _ => None,
if let GenericParamId::TypeParamId(id) = id { })
TyKind::Placeholder(to_placeholder_idx(self.db, id.into())) .nth(idx as usize)
} else { .map_or(TyKind::Error, |id| {
// we just filtered them out TyKind::Placeholder(to_placeholder_idx(self.db, id.into()))
unreachable!("Unexpected lifetime or const argument"); });
} kind.intern(Interner)
});
param.intern(Interner)
} else {
TyKind::Error.intern(Interner)
}
} }
ImplTraitLoweringState::Variable(counter) => { ImplTraitLoweringState::Variable(counter) => {
let idx = counter.get(); 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); counter.set(idx + count_impl_traits(type_ref) as u16);
let ( let (
_parent_params, _parent_params,
self_params, self_params,
list_params, type_params,
const_params, const_params,
_impl_trait_params, _impl_trait_params,
_lifetime_params, _lifetime_params,
) = if let Some(generics) = self.generics() { ) = self
generics.provenance_split() .generics()
} else { .expect("variable impl trait lowering must be in a generic def")
(0, 0, 0, 0, 0, 0) .provenance_split();
};
TyKind::BoundVar(BoundVar::new( TyKind::BoundVar(BoundVar::new(
self.in_binders, self.in_binders,
idx as usize + self_params + list_params + const_params, idx as usize + self_params + type_params + const_params,
)) ))
.intern(Interner) .intern(Interner)
} }
@ -1010,6 +1006,7 @@ impl<'a> TyLoweringContext<'a> {
pub(crate) fn lower_where_predicate<'b>( pub(crate) fn lower_where_predicate<'b>(
&'b self, &'b self,
where_predicate: &'b WherePredicate, where_predicate: &'b WherePredicate,
&def: &GenericDefId,
ignore_bindings: bool, ignore_bindings: bool,
) -> impl Iterator<Item = QuantifiedWhereClause> + 'b { ) -> impl Iterator<Item = QuantifiedWhereClause> + 'b {
match where_predicate { match where_predicate {
@ -1018,7 +1015,6 @@ impl<'a> TyLoweringContext<'a> {
let self_ty = match target { let self_ty = match target {
WherePredicateTypeTarget::TypeRef(type_ref) => self.lower_ty(type_ref), WherePredicateTypeTarget::TypeRef(type_ref) => self.lower_ty(type_ref),
&WherePredicateTypeTarget::TypeOrConstParam(local_id) => { &WherePredicateTypeTarget::TypeOrConstParam(local_id) => {
let def = self.resolver.generic_def().expect("generics in scope");
let param_id = hir_def::TypeOrConstParamId { parent: def, local_id }; let param_id = hir_def::TypeOrConstParamId { parent: def, local_id };
match self.type_param_mode { match self.type_param_mode {
ParamLoweringMode::Placeholder => { ParamLoweringMode::Placeholder => {
@ -1056,23 +1052,7 @@ impl<'a> TyLoweringContext<'a> {
let clause = match bound.as_ref() { let clause = match bound.as_ref() {
TypeBound::Path(path, TraitBoundModifier::None) => { TypeBound::Path(path, TraitBoundModifier::None) => {
trait_ref = self.lower_trait_ref_from_path(path, Some(self_ty)); trait_ref = self.lower_trait_ref_from_path(path, Some(self_ty));
trait_ref trait_ref.clone().map(WhereClause::Implemented).map(crate::wrap_empty_binders)
.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)
} }
TypeBound::Path(path, TraitBoundModifier::Maybe) => { TypeBound::Path(path, TraitBoundModifier::Maybe) => {
let sized_trait = self let sized_trait = self
@ -1166,84 +1146,77 @@ impl<'a> TyLoweringContext<'a> {
binding.type_ref.as_ref().map_or(0, |_| 1) + binding.bounds.len(), binding.type_ref.as_ref().map_or(0, |_| 1) + binding.bounds.len(),
); );
if let Some(type_ref) = &binding.type_ref { if let Some(type_ref) = &binding.type_ref {
if let ( match (type_ref, &self.impl_trait_mode) {
TypeRef::ImplTrait(bounds), (TypeRef::ImplTrait(_), ImplTraitLoweringState::Disallowed) => (),
ImplTraitLoweringState::Param(_) (
| ImplTraitLoweringState::Variable(_) _,
| ImplTraitLoweringState::Disallowed, ImplTraitLoweringState::Disallowed | ImplTraitLoweringState::Opaque(_),
) = (type_ref, &self.impl_trait_mode) ) => {
{ let ty = self.lower_ty(type_ref);
for bound in bounds { let alias_eq =
predicates.extend( AliasEq { alias: AliasTy::Projection(projection_ty.clone()), ty };
self.lower_type_bound( predicates
bound, .push(crate::wrap_empty_binders(WhereClause::AliasEq(alias_eq)));
TyKind::Alias(AliasTy::Projection(projection_ty.clone()))
.intern(Interner),
false,
),
);
} }
} else { (
let ty = 'ty: { _,
if matches!( ImplTraitLoweringState::Param(_) | ImplTraitLoweringState::Variable(_),
self.impl_trait_mode, ) => {
ImplTraitLoweringState::Param(_) // Find the generic index for the target of our `bound`
| ImplTraitLoweringState::Variable(_) let target_param_idx = self
) { .resolver
// Find the generic index for the target of our `bound` .where_predicates_in_scope()
let target_param_idx = self .find_map(|(p, _)| match p {
.resolver WherePredicate::TypeBound {
.where_predicates_in_scope() target: WherePredicateTypeTarget::TypeOrConstParam(idx),
.find_map(|p| match p { bound: b,
WherePredicate::TypeBound { } if b == bound => Some(idx),
target: WherePredicateTypeTarget::TypeOrConstParam(idx), _ => None,
bound: b, });
} if b == bound => Some(idx), let ty = if let Some(target_param_idx) = target_param_idx {
_ => None, let mut counter = 0;
}); let generics = self.generics().expect("generics in scope");
if let Some(target_param_idx) = target_param_idx { for (idx, data) in generics.params.type_or_consts.iter() {
let mut counter = 0; // Count the number of `impl Trait` things that appear before
let generics = self.generics().expect("generics in scope"); // the target of our `bound`.
for (idx, data) in generics.params.type_or_consts.iter() { // Our counter within `impl_trait_mode` should be that number
// Count the number of `impl Trait` things that appear before // to properly lower each types within `type_ref`
// the target of our `bound`. if data.type_param().is_some_and(|p| {
// Our counter within `impl_trait_mode` should be that number p.provenance == TypeParamProvenance::ArgumentImplTrait
// to properly lower each types within `type_ref` }) {
if data.type_param().is_some_and(|p| { counter += 1;
p.provenance == TypeParamProvenance::ArgumentImplTrait
}) {
counter += 1;
}
if idx == *target_param_idx {
break;
}
} }
let mut ext = TyLoweringContext::new_maybe_unowned( if idx == *target_param_idx {
self.db, break;
self.resolver,
self.owner,
)
.with_type_param_mode(self.type_param_mode);
match &self.impl_trait_mode {
ImplTraitLoweringState::Param(_) => {
ext.impl_trait_mode =
ImplTraitLoweringState::Param(Cell::new(counter));
}
ImplTraitLoweringState::Variable(_) => {
ext.impl_trait_mode = ImplTraitLoweringState::Variable(
Cell::new(counter),
);
}
_ => unreachable!(),
} }
break 'ty ext.lower_ty(type_ref);
} }
} let mut ext = TyLoweringContext::new_maybe_unowned(
self.lower_ty(type_ref) self.db,
}; self.resolver,
let alias_eq = self.owner,
AliasEq { alias: AliasTy::Projection(projection_ty.clone()), ty }; )
predicates.push(crate::wrap_empty_binders(WhereClause::AliasEq(alias_eq))); .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() { for bound in binding.bounds.iter() {
@ -1338,11 +1311,10 @@ impl<'a> TyLoweringContext<'a> {
bounds, bounds,
lifetime: match lifetime { lifetime: match lifetime {
Some(it) => match it.bound_var(Interner) { Some(it) => match it.bound_var(Interner) {
Some(bound_var) => LifetimeData::BoundVar(BoundVar::new( Some(bound_var) => bound_var
DebruijnIndex::INNERMOST, .shifted_out_to(DebruijnIndex::new(2))
bound_var.index, .map(|bound_var| LifetimeData::BoundVar(bound_var).intern(Interner))
)) .unwrap_or(it),
.intern(Interner),
None => it, None => it,
}, },
None => static_lifetime(), 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). /// Build the signature of a callable item (function, struct or enum variant).
pub(crate) fn callable_item_sig(db: &dyn HirDatabase, def: CallableDefId) -> PolyFnSig { pub(crate) fn callable_item_sig(db: &dyn HirDatabase, def: CallableDefId) -> PolyFnSig {
match def { 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)) 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>( fn named_associated_type_shorthand_candidates<R>(
db: &dyn HirDatabase, db: &dyn HirDatabase,
// If the type parameter is defined in an impl and we're in a method, there // 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); let generics = generics(db.upcast(), def);
// we have to filter out all other predicates *first*, before attempting to lower them // 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::ForLifetime { target, bound, .. }
| WherePredicate::TypeBound { target, bound, .. } => { | WherePredicate::TypeBound { target, bound, .. } => {
let invalid_target = match target { let invalid_target = match target {
@ -1617,8 +1590,8 @@ pub(crate) fn generic_predicates_for_param_query(
let mut predicates: Vec<_> = resolver let mut predicates: Vec<_> = resolver
.where_predicates_in_scope() .where_predicates_in_scope()
.filter(predicate) .filter(predicate)
.flat_map(|pred| { .flat_map(|(pred, def)| {
ctx.lower_where_predicate(pred, true).map(|p| make_binders(db, &generics, p)) ctx.lower_where_predicate(pred, def, true).map(|p| make_binders(db, &generics, p))
}) })
.collect(); .collect();
@ -1671,8 +1644,8 @@ pub(crate) fn trait_environment_query(
}; };
let mut traits_in_scope = Vec::new(); let mut traits_in_scope = Vec::new();
let mut clauses = Vec::new(); let mut clauses = Vec::new();
for pred in resolver.where_predicates_in_scope() { for (pred, def) in resolver.where_predicates_in_scope() {
for pred in ctx.lower_where_predicate(pred, false) { for pred in ctx.lower_where_predicate(pred, def, false) {
if let WhereClause::Implemented(tr) = &pred.skip_binders() { if let WhereClause::Implemented(tr) = &pred.skip_binders() {
traits_in_scope.push((tr.self_type_parameter(Interner).clone(), tr.hir_trait_id())); 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 let mut predicates = resolver
.where_predicates_in_scope() .where_predicates_in_scope()
.flat_map(|pred| { .flat_map(|(pred, def)| {
ctx.lower_where_predicate(pred, false).map(|p| make_binders(db, &generics, p)) ctx.lower_where_predicate(pred, def, false).map(|p| make_binders(db, &generics, p))
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();

View file

@ -368,7 +368,7 @@ pub(crate) fn incoherent_inherent_impl_crates(
krate: CrateId, krate: CrateId,
fp: TyFingerprint, fp: TyFingerprint,
) -> SmallVec<[CrateId; 2]> { ) -> 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 mut res = SmallVec::new();
let crate_graph = db.crate_graph(); let crate_graph = db.crate_graph();

View file

@ -428,6 +428,17 @@ impl MirEvalError {
} }
Ok(()) 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 { impl std::fmt::Debug for MirEvalError {
@ -1138,7 +1149,7 @@ impl Evaluator<'_> {
let mut ty = self.operand_ty(lhs, locals)?; let mut ty = self.operand_ty(lhs, locals)?;
while let TyKind::Ref(_, _, z) = ty.kind(Interner) { while let TyKind::Ref(_, _, z) = ty.kind(Interner) {
ty = z.clone(); ty = z.clone();
let size = if ty.kind(Interner) == &TyKind::Str { let size = if ty.is_str() {
if *op != BinOp::Eq { if *op != BinOp::Eq {
never!("Only eq is builtin for `str`"); never!("Only eq is builtin for `str`");
} }

View file

@ -49,6 +49,7 @@ impl Evaluator<'_> {
if self.not_special_fn_cache.borrow().contains(&def) { if self.not_special_fn_cache.borrow().contains(&def) {
return Ok(false); return Ok(false);
} }
let function_data = self.db.function_data(def); let function_data = self.db.function_data(def);
let is_intrinsic = match &function_data.abi { let is_intrinsic = match &function_data.abi {
Some(abi) => *abi == Interned::new_str("rust-intrinsic"), Some(abi) => *abi == Interned::new_str("rust-intrinsic"),
@ -131,9 +132,7 @@ impl Evaluator<'_> {
return Ok(true); return Ok(true);
} }
if let Some(it) = self.detect_lang_function(def) { if let Some(it) = self.detect_lang_function(def) {
let arg_bytes = let result = self.exec_lang_item(it, generic_args, args, locals, span)?;
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)?;
destination.write_from_bytes(self, &result)?; destination.write_from_bytes(self, &result)?;
return Ok(true); return Ok(true);
} }
@ -311,16 +310,20 @@ impl Evaluator<'_> {
fn detect_lang_function(&self, def: FunctionId) -> Option<LangItem> { fn detect_lang_function(&self, def: FunctionId) -> Option<LangItem> {
use 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 // We want to execute these functions with special logic
// `PanicFmt` is not detected here as it's redirected later. // `PanicFmt` is not detected here as it's redirected later.
if [BeginPanic, SliceLen, DropInPlace].contains(&candidate) { if [BeginPanic, SliceLen, DropInPlace].contains(&candidate) {
return Some(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 None
} }
@ -328,18 +331,52 @@ impl Evaluator<'_> {
&mut self, &mut self,
it: LangItem, it: LangItem,
generic_args: &Substitution, generic_args: &Substitution,
args: &[Vec<u8>], args: &[IntervalAndTy],
locals: &Locals, locals: &Locals,
span: MirSpan, span: MirSpan,
) -> Result<Vec<u8>> { ) -> Result<Vec<u8>> {
use LangItem::*; use LangItem::*;
let mut args = args.iter(); let mut args = args.iter();
match it { 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 => { SliceLen => {
let arg = args.next().ok_or(MirEvalError::InternalError( let arg = args.next().ok_or(MirEvalError::InternalError(
"argument of <[T]>::len() is not provided".into(), "argument of <[T]>::len() is not provided".into(),
))?; ))?;
let arg = arg.get(self)?;
let ptr_size = arg.len() / 2; let ptr_size = arg.len() / 2;
Ok(arg[ptr_size..].into()) Ok(arg[ptr_size..].into())
} }
@ -353,6 +390,7 @@ impl Evaluator<'_> {
let arg = args.next().ok_or(MirEvalError::InternalError( let arg = args.next().ok_or(MirEvalError::InternalError(
"argument of drop_in_place is not provided".into(), "argument of drop_in_place is not provided".into(),
))?; ))?;
let arg = arg.interval.get(self)?.to_owned();
self.run_drop_glue_deep( self.run_drop_glue_deep(
ty.clone(), ty.clone(),
locals, locals,

View file

@ -31,6 +31,7 @@ fn eval_main(db: &TestDB, file_id: FileId) -> Result<(String, String), MirEvalEr
db.trait_environment(func_id.into()), db.trait_environment(func_id.into()),
) )
.map_err(|e| MirEvalError::MirLowerError(func_id, e))?; .map_err(|e| MirEvalError::MirLowerError(func_id, e))?;
let (result, output) = interpret_mir(db, body, false, None); let (result, output) = interpret_mir(db, body, false, None);
result?; result?;
Ok((output.stdout().into_owned(), output.stderr().into_owned())) 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] #[test]
fn function_with_extern_c_abi() { fn function_with_extern_c_abi() {
check_pass( 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] #[test]
fn drop_basic() { fn drop_basic() {
check_pass( check_pass(

View file

@ -186,7 +186,7 @@ fn test() {
let x = match 1 { let x = match 1 {
1 => t as *mut i32, 1 => t as *mut i32,
2 => t as &i32, 2 => t as &i32,
//^^^^^^^^^ expected *mut i32, got &i32 //^^^^^^^^^ expected *mut i32, got &'? i32
_ => t as *const i32, _ => t as *const i32,
// ^^^^^^^^^^^^^^^ adjustments: Pointer(MutToConstPointer) // ^^^^^^^^^^^^^^^ adjustments: Pointer(MutToConstPointer)
@ -307,7 +307,7 @@ fn test() {
let foo = Foo; let foo = Foo;
//^^^ type: Foo<{unknown}> //^^^ type: Foo<{unknown}>
let _: &u32 = &Foo; let _: &u32 = &Foo;
//^^^^ expected &u32, got &Foo<{unknown}> //^^^^ expected &'? u32, got &'? Foo<{unknown}>
}", }",
); );
} }
@ -544,9 +544,9 @@ struct Bar<T>(Foo<T>);
fn test() { fn test() {
let _: &Foo<[usize]> = &Foo { t: [1, 2, 3] }; 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] }); 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)) { fn test(f: impl Foo, g: &(impl Foo + ?Sized)) {
let _: &dyn Foo = &f; let _: &dyn Foo = &f;
let _: &dyn Foo = g; 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() { fn main() {
let a: V<&dyn Tr>; let a: V<&dyn Tr>;
(a,) = V { t: &S }; (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 }; let mut a: V<&dyn Tr> = V { t: &S };
(a,) = V { t: &S }; (a,) = V { t: &S };
//^^^^expected V<&S>, got (V<&dyn Tr>,) //^^^^expected V<&'? S>, got (V<&'? dyn Tr>,)
} }
"#, "#,
); );

View file

@ -8,7 +8,7 @@ fn function_return_type_mismatch_1() {
r#" r#"
fn test() -> &'static str { fn test() -> &'static str {
5 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 { fn test(x: bool) -> &'static str {
if x { if x {
return 1; return 1;
//^ expected &str, got i32 //^ expected &'static str, got i32
} }
"ok" "ok"
} }
@ -38,7 +38,7 @@ fn test(x: bool) -> &'static str {
return "ok"; return "ok";
} }
1 1
//^ expected &str, got i32 //^ expected &'static str, got i32
} }
"#, "#,
); );
@ -53,7 +53,7 @@ fn test(x: bool) -> &'static str {
"ok" "ok"
} else { } else {
1 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 { fn test(x: bool) -> &'static str {
if x { if x {
1 1
//^ expected &str, got i32 //^ expected &'static str, got i32
} else { } else {
"ok" "ok"
} }
@ -83,10 +83,10 @@ fn non_unit_block_expr_stmt_no_semi() {
fn test(x: bool) { fn test(x: bool) {
if x { if x {
"notok" "notok"
//^^^^^^^ expected (), got &str //^^^^^^^ expected (), got &'static str
} else { } else {
"ok" "ok"
//^^^^ expected (), got &str //^^^^ expected (), got &'static str
} }
match x { true => true, false => 0 } match x { true => true, false => 0 }
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected (), got bool //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected (), got bool

View file

@ -67,11 +67,11 @@ trait B: A {}
fn test( fn test(
_: &(dyn A<Assoc = ()> + Send), _: &(dyn A<Assoc = ()> + Send),
//^ &(dyn A<Assoc = ()> + Send) //^ &'_ (dyn A<Assoc = ()> + Send)
_: &(dyn Send + A<Assoc = ()>), _: &(dyn Send + A<Assoc = ()>),
//^ &(dyn A<Assoc = ()> + Send) //^ &'_ (dyn A<Assoc = ()> + Send)
_: &dyn B<Assoc = ()>, _: &dyn B<Assoc = ()>,
//^ &(dyn B<Assoc = ()>) //^ &'_ (dyn B<Assoc = ()>)
) {} ) {}
"#, "#,
); );
@ -85,7 +85,7 @@ fn render_dyn_for_ty() {
trait Foo<'a> {} trait Foo<'a> {}
fn foo(foo: &dyn for<'a> Foo<'a>) {} fn foo(foo: &dyn for<'a> Foo<'a>) {}
// ^^^ &dyn Foo<'_> // ^^^ &'_ dyn Foo<'_>
"#, "#,
); );
} }
@ -111,11 +111,11 @@ fn test(
b; b;
//^ impl Foo //^ impl Foo
c; c;
//^ &impl Foo + ?Sized //^ &'_ impl Foo + ?Sized
d; d;
//^ S<impl Foo> //^ S<impl Foo>
ref_any; ref_any;
//^^^^^^^ &impl ?Sized //^^^^^^^ &'_ impl ?Sized
empty; empty;
} //^^^^^ impl Sized } //^^^^^ impl Sized
"#, "#,
@ -192,7 +192,7 @@ fn test(
b; b;
//^ fn(impl Foo) -> impl Foo //^ fn(impl Foo) -> impl Foo
c; c;
} //^ fn(&impl Foo + ?Sized) -> &impl Foo + ?Sized } //^ fn(&'_ impl Foo + ?Sized) -> &'_ impl Foo + ?Sized
"#, "#,
); );
} }

View file

@ -200,8 +200,8 @@ fn expr_macro_def_expanded_in_various_places() {
100..119 'for _ ...!() {}': IntoIterator::IntoIter<isize> 100..119 'for _ ...!() {}': IntoIterator::IntoIter<isize>
100..119 'for _ ...!() {}': ! 100..119 'for _ ...!() {}': !
100..119 'for _ ...!() {}': IntoIterator::IntoIter<isize> 100..119 'for _ ...!() {}': IntoIterator::IntoIter<isize>
100..119 'for _ ...!() {}': &mut 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 _ ...!() {}': 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 _ ...!() {}': Option<IntoIterator::Item<isize>>
100..119 'for _ ...!() {}': () 100..119 'for _ ...!() {}': ()
100..119 'for _ ...!() {}': () 100..119 'for _ ...!() {}': ()
@ -221,7 +221,7 @@ fn expr_macro_def_expanded_in_various_places() {
281..303 'Spam {...m!() }': {unknown} 281..303 'Spam {...m!() }': {unknown}
309..325 'spam!(...am!()]': {unknown} 309..325 'spam!(...am!()]': {unknown}
350..366 'spam!(... usize': usize 350..366 'spam!(... usize': usize
372..380 '&spam!()': &isize 372..380 '&spam!()': &'? isize
386..394 '-spam!()': isize 386..394 '-spam!()': isize
400..416 'spam!(...pam!()': {unknown} 400..416 'spam!(...pam!()': {unknown}
422..439 'spam!(...pam!()': isize 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 _ ...!() {}': IntoIterator::IntoIter<isize>
114..133 'for _ ...!() {}': ! 114..133 'for _ ...!() {}': !
114..133 'for _ ...!() {}': IntoIterator::IntoIter<isize> 114..133 'for _ ...!() {}': IntoIterator::IntoIter<isize>
114..133 'for _ ...!() {}': &mut 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 _ ...!() {}': 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 _ ...!() {}': Option<IntoIterator::Item<isize>>
114..133 'for _ ...!() {}': () 114..133 'for _ ...!() {}': ()
114..133 'for _ ...!() {}': () 114..133 'for _ ...!() {}': ()
@ -314,7 +314,7 @@ fn expr_macro_rules_expanded_in_various_places() {
295..317 'Spam {...m!() }': {unknown} 295..317 'Spam {...m!() }': {unknown}
323..339 'spam!(...am!()]': {unknown} 323..339 'spam!(...am!()]': {unknown}
364..380 'spam!(... usize': usize 364..380 'spam!(... usize': usize
386..394 '&spam!()': &isize 386..394 '&spam!()': &'? isize
400..408 '-spam!()': isize 400..408 '-spam!()': isize
414..430 'spam!(...pam!()': {unknown} 414..430 'spam!(...pam!()': {unknown}
436..453 'spam!(...pam!()': isize 436..453 'spam!(...pam!()': isize
@ -539,7 +539,7 @@ fn test() {
let msg = foo::Message(foo::MessageRef); let msg = foo::Message(foo::MessageRef);
let r = msg.deref(); let r = msg.deref();
r; r;
//^ &MessageRef //^ &'? MessageRef
} }
//- /lib.rs crate:foo //- /lib.rs crate:foo
@ -703,9 +703,9 @@ fn infer_builtin_macros_file() {
} }
"#, "#,
expect![[r#" expect![[r#"
!0..2 '""': &str !0..2 '""': &'static str
63..87 '{ ...!(); }': () 63..87 '{ ...!(); }': ()
73..74 'x': &str 73..74 'x': &'static str
"#]], "#]],
); );
} }
@ -741,9 +741,9 @@ fn infer_builtin_macros_concat() {
} }
"#, "#,
expect![[r#" expect![[r#"
!0..13 '"helloworld!"': &str !0..13 '"helloworld!"': &'static str
65..121 '{ ...")); }': () 65..121 '{ ...")); }': ()
75..76 'x': &str 75..76 'x': &'static str
"#]], "#]],
); );
} }
@ -820,7 +820,7 @@ macro_rules! include_str {() => {}}
fn main() { fn main() {
let a = include_str!("foo.rs"); let a = include_str!("foo.rs");
a; a;
} //^ &str } //^ &'static str
//- /foo.rs //- /foo.rs
hello hello
@ -847,7 +847,7 @@ macro_rules! m {
fn main() { fn main() {
let a = include_str!(m!(".rs")); let a = include_str!(m!(".rs"));
a; a;
} //^ &str } //^ &'static str
//- /foo.rs //- /foo.rs
hello hello
@ -960,9 +960,9 @@ fn infer_builtin_macros_concat_with_lazy() {
} }
"#, "#,
expect![[r#" expect![[r#"
!0..13 '"helloworld!"': &str !0..13 '"helloworld!"': &'static str
103..160 '{ ...")); }': () 103..160 '{ ...")); }': ()
113..114 'x': &str 113..114 'x': &'static str
"#]], "#]],
); );
} }
@ -977,7 +977,7 @@ fn infer_builtin_macros_env() {
fn main() { fn main() {
let x = env!("foo"); let x = env!("foo");
//^ &str //^ &'static str
} }
"#, "#,
); );
@ -991,7 +991,7 @@ fn infer_builtin_macros_option_env() {
//- /main.rs env:foo=bar //- /main.rs env:foo=bar
fn main() { fn main() {
let x = option_env!("foo"); let x = option_env!("foo");
//^ Option<&str> //^ Option<&'static str>
} }
"#, "#,
); );

View file

@ -658,7 +658,7 @@ fn infer_call_trait_method_on_generic_param_1() {
} }
"#, "#,
expect![[r#" expect![[r#"
29..33 'self': &Self 29..33 'self': &'? Self
63..64 't': T 63..64 't': T
69..88 '{ ...d(); }': () 69..88 '{ ...d(); }': ()
75..76 't': T 75..76 't': T
@ -679,7 +679,7 @@ fn infer_call_trait_method_on_generic_param_2() {
} }
"#, "#,
expect![[r#" expect![[r#"
32..36 'self': &Self 32..36 'self': &'? Self
70..71 't': T 70..71 't': T
76..95 '{ ...d(); }': () 76..95 '{ ...d(); }': ()
82..83 't': T 82..83 't': T
@ -757,7 +757,7 @@ struct S;
impl Clone for S {} impl Clone for S {}
impl Clone for &S {} impl Clone for &S {}
fn test() { (S.clone(), (&S).clone(), (&&S).clone()); } 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#" expect![[r#"
51..55 'self': &Self 51..55 'self': &'? Self
64..69 '{ 0 }': u32 64..69 '{ 0 }': u32
66..67 '0': u32 66..67 '0': u32
176..177 'd': &dyn Trait 176..177 'd': &'? dyn Trait
191..207 '{ ...o(); }': () 191..207 '{ ...o(); }': ()
197..198 'd': &dyn Trait 197..198 'd': &'? dyn Trait
197..204 'd.foo()': u32 197..204 'd.foo()': u32
"#]], "#]],
); );
@ -1182,15 +1182,15 @@ fn test() {
} }
"#, "#,
expect![[r#" expect![[r#"
75..79 'self': &S 75..79 'self': &'? S
89..109 '{ ... }': bool 89..109 '{ ... }': bool
99..103 'true': bool 99..103 'true': bool
123..167 '{ ...o(); }': () 123..167 '{ ...o(); }': ()
133..134 's': &S 133..134 's': &'? S
137..151 'unsafe { f() }': &S 137..151 'unsafe { f() }': &'static S
146..147 'f': fn f() -> &S 146..147 'f': fn f() -> &'static S
146..149 'f()': &S 146..149 'f()': &'static S
157..158 's': &S 157..158 's': &'? S
157..164 's.foo()': bool 157..164 's.foo()': bool
"#]], "#]],
); );
@ -1601,11 +1601,11 @@ use core::IntoIterator;
fn f() { fn f() {
let v = [4].into_iter(); let v = [4].into_iter();
v; v;
//^ &i32 //^ &'? i32
let a = [0, 1].into_iter(); let a = [0, 1].into_iter();
a; a;
//^ &i32 //^ &'? i32
} }
//- /main2021.rs crate:main2021 deps:core edition:2021 //- /main2021.rs crate:main2021 deps:core edition:2021
@ -1618,7 +1618,7 @@ fn f() {
let a = [0, 1].into_iter(); let a = [0, 1].into_iter();
a; a;
//^ &i32 //^ &'? i32
} }
//- /core.rs crate:core //- /core.rs crate:core
@ -1767,7 +1767,7 @@ fn test() {
let a2 = A(make(), 1i32); let a2 = A(make(), 1i32);
let _: &str = a2.thing(); let _: &str = a2.thing();
a2; a2;
//^^ A<C<&str>, i32> //^^ A<C<&'? str>, i32>
} }
"#, "#,
); );

View file

@ -104,7 +104,7 @@ enum Option<T> { None, Some(T) }
fn test() { fn test() {
let a = if true { Option::None } else { Option::Some(return) }; let a = if true { Option::None } else { Option::Some(return) };
a; a;
//^ Option<&str> //^ Option<&'static str>
match 42 { match 42 {
42 => a, 42 => a,
_ => Option::Some("str"), _ => Option::Some("str"),
@ -317,8 +317,8 @@ fn diverging_expression_2() {
63..81 '{ loop...foo" }': u32 63..81 '{ loop...foo" }': u32
65..72 'loop {}': ! 65..72 'loop {}': !
70..72 '{}': () 70..72 '{}': ()
74..79 '"foo"': &str 74..79 '"foo"': &'static str
74..79: expected u32, got &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; }': {unknown}
151..172 'for a ...eak; }': ! 151..172 'for a ...eak; }': !
151..172 'for a ...eak; }': {unknown} 151..172 'for a ...eak; }': {unknown}
151..172 'for a ...eak; }': &mut {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; }': fn next<{unknown}>(&'? mut {unknown}) -> Option<<{unknown} as Iterator>::Item>
151..172 'for a ...eak; }': Option<{unknown}> 151..172 'for a ...eak; }': Option<{unknown}>
151..172 'for a ...eak; }': () 151..172 'for a ...eak; }': ()
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 {}': {unknown}
237..250 'for a in b {}': ! 237..250 'for a in b {}': !
237..250 'for a in b {}': {unknown} 237..250 'for a in b {}': {unknown}
237..250 'for a in b {}': &mut {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 {}': fn next<{unknown}>(&'? mut {unknown}) -> Option<<{unknown} as Iterator>::Item>
237..250 'for a in b {}': Option<{unknown}> 237..250 'for a in b {}': Option<{unknown}>
237..250 'for a in b {}': () 237..250 'for a in b {}': ()
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; }': {unknown}
315..337 'for a ...urn; }': ! 315..337 'for a ...urn; }': !
315..337 'for a ...urn; }': {unknown} 315..337 'for a ...urn; }': {unknown}
315..337 'for a ...urn; }': &mut {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; }': fn next<{unknown}>(&'? mut {unknown}) -> Option<<{unknown} as Iterator>::Item>
315..337 'for a ...urn; }': Option<{unknown}> 315..337 'for a ...urn; }': Option<{unknown}>
315..337 'for a ...urn; }': () 315..337 'for a ...urn; }': ()
315..337 'for a ...urn; }': () 315..337 'for a ...urn; }': ()

View file

@ -32,27 +32,27 @@ fn infer_pattern() {
} }
"#, "#,
expect![[r#" expect![[r#"
8..9 'x': &i32 8..9 'x': &'? i32
17..400 '{ ...o_x; }': () 17..400 '{ ...o_x; }': ()
27..28 'y': &i32 27..28 'y': &'? i32
31..32 'x': &i32 31..32 'x': &'? i32
42..44 '&z': &i32 42..44 '&z': &'? i32
43..44 'z': i32 43..44 'z': i32
47..48 'x': &i32 47..48 'x': &'? i32
58..59 'a': i32 58..59 'a': i32
62..63 'z': i32 62..63 'z': i32
73..79 '(c, d)': (i32, &str) 73..79 '(c, d)': (i32, &'static str)
74..75 'c': i32 74..75 'c': i32
77..78 'd': &str 77..78 'd': &'static str
82..94 '(1, "hello")': (i32, &str) 82..94 '(1, "hello")': (i32, &'static str)
83..84 '1': i32 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... }': fn into_iter<{unknown}>({unknown}) -> <{unknown} as IntoIterator>::IntoIter
101..151 'for (e... }': {unknown} 101..151 'for (e... }': {unknown}
101..151 'for (e... }': ! 101..151 'for (e... }': !
101..151 'for (e... }': {unknown} 101..151 'for (e... }': {unknown}
101..151 'for (e... }': &mut {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... }': fn next<{unknown}>(&'? mut {unknown}) -> Option<<{unknown} as Iterator>::Item>
101..151 'for (e... }': Option<({unknown}, {unknown})> 101..151 'for (e... }': Option<({unknown}, {unknown})>
101..151 'for (e... }': () 101..151 'for (e... }': ()
101..151 'for (e... }': () 101..151 'for (e... }': ()
@ -74,10 +74,10 @@ fn infer_pattern() {
194..197 'val': {unknown} 194..197 'val': {unknown}
210..236 'if let...rue {}': () 210..236 'if let...rue {}': ()
213..233 'let x ... &true': bool 213..233 'let x ... &true': bool
217..225 'x @ true': &bool 217..225 'x @ true': &'? bool
221..225 'true': bool 221..225 'true': bool
221..225 'true': bool 221..225 'true': bool
228..233 '&true': &bool 228..233 '&true': &'? bool
229..233 'true': bool 229..233 'true': bool
234..236 '{}': () 234..236 '{}': ()
246..252 'lambda': impl Fn(u64, u64, i32) -> i32 246..252 'lambda': impl Fn(u64, u64, i32) -> i32
@ -90,14 +90,14 @@ fn infer_pattern() {
277..282 'a + b': u64 277..282 'a + b': u64
281..282 'b': u64 281..282 'b': u64
284..285 'c': i32 284..285 'c': i32
298..310 'ref ref_to_x': &&i32 298..310 'ref ref_to_x': &'? &'? i32
313..314 'x': &i32 313..314 'x': &'? i32
324..333 'mut mut_x': &i32 324..333 'mut mut_x': &'? i32
336..337 'x': &i32 336..337 'x': &'? i32
347..367 'ref mu...f_to_x': &mut &i32 347..367 'ref mu...f_to_x': &'? mut &'? i32
370..371 'x': &i32 370..371 'x': &'? i32
381..382 'k': &mut &i32 381..382 'k': &'? mut &'? i32
385..397 'mut_ref_to_x': &mut &i32 385..397 'mut_ref_to_x': &'? mut &'? i32
"#]], "#]],
); );
} }
@ -120,14 +120,14 @@ fn infer_literal_pattern() {
17..28 '{ loop {} }': T 17..28 '{ loop {} }': T
19..26 'loop {}': ! 19..26 'loop {}': !
24..26 '{}': () 24..26 '{}': ()
37..38 'x': &i32 37..38 'x': &'? i32
46..208 '{ ...) {} }': () 46..208 '{ ...) {} }': ()
52..75 'if let...y() {}': () 52..75 'if let...y() {}': ()
55..72 'let "f... any()': bool 55..72 'let "f... any()': bool
59..64 '"foo"': &str 59..64 '"foo"': &'static str
59..64 '"foo"': &str 59..64 '"foo"': &'static str
67..70 'any': fn any<&str>() -> &str 67..70 'any': fn any<&'static str>() -> &'static str
67..72 'any()': &str 67..72 'any()': &'static str
73..75 '{}': () 73..75 '{}': ()
80..99 'if let...y() {}': () 80..99 'if let...y() {}': ()
83..96 'let 1 = any()': bool 83..96 'let 1 = any()': bool
@ -178,7 +178,7 @@ fn infer_range_pattern() {
} }
"#, "#,
expect![[r#" expect![[r#"
8..9 'x': &i32 8..9 'x': &'? i32
17..75 '{ ...2 {} }': () 17..75 '{ ...2 {} }': ()
23..45 'if let...u32 {}': () 23..45 'if let...u32 {}': ()
26..42 'let 1....= 2u32': bool 26..42 'let 1....= 2u32': bool
@ -208,14 +208,14 @@ fn infer_pattern_match_ergonomics() {
expect![[r#" expect![[r#"
27..78 '{ ...(1); }': () 27..78 '{ ...(1); }': ()
37..41 'A(n)': A<i32> 37..41 'A(n)': A<i32>
39..40 'n': &i32 39..40 'n': &'? i32
44..49 '&A(1)': &A<i32> 44..49 '&A(1)': &'? A<i32>
45..46 'A': extern "rust-call" A<i32>(i32) -> A<i32> 45..46 'A': extern "rust-call" A<i32>(i32) -> A<i32>
45..49 'A(1)': A<i32> 45..49 'A(1)': A<i32>
47..48 '1': i32 47..48 '1': i32
59..63 'A(n)': A<i32> 59..63 'A(n)': A<i32>
61..62 'n': &mut i32 61..62 'n': &'? mut i32
66..75 '&mut A(1)': &mut A<i32> 66..75 '&mut A(1)': &'? mut A<i32>
71..72 'A': extern "rust-call" A<i32>(i32) -> A<i32> 71..72 'A': extern "rust-call" A<i32>(i32) -> A<i32>
71..75 'A(1)': A<i32> 71..75 'A(1)': A<i32>
73..74 '1': i32 73..74 '1': i32
@ -235,17 +235,17 @@ fn infer_pattern_match_ergonomics_ref() {
"#, "#,
expect![[r#" expect![[r#"
10..56 '{ ...= v; }': () 10..56 '{ ...= v; }': ()
20..21 'v': &(i32, &i32) 20..21 'v': &'? (i32, &'? i32)
24..32 '&(1, &2)': &(i32, &i32) 24..32 '&(1, &2)': &'? (i32, &'? i32)
25..32 '(1, &2)': (i32, &i32) 25..32 '(1, &2)': (i32, &'? i32)
26..27 '1': i32 26..27 '1': i32
29..31 '&2': &i32 29..31 '&2': &'? i32
30..31 '2': i32 30..31 '2': i32
42..49 '(_, &w)': (i32, &i32) 42..49 '(_, &w)': (i32, &'? i32)
43..44 '_': i32 43..44 '_': i32
46..48 '&w': &i32 46..48 '&w': &'? i32
47..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#" expect![[r#"
10..209 '{ ... } }': () 10..209 '{ ... } }': ()
20..25 'slice': &[f64] 20..25 'slice': &'? [f64]
36..42 '&[0.0]': &[f64; 1] 36..42 '&[0.0]': &'? [f64; 1]
37..42 '[0.0]': [f64; 1] 37..42 '[0.0]': [f64; 1]
38..41 '0.0': f64 38..41 '0.0': f64
48..207 'match ... }': () 48..207 'match ... }': ()
54..59 'slice': &[f64] 54..59 'slice': &'? [f64]
70..73 '&[]': &[f64] 70..73 '&[]': &'? [f64]
71..73 '[]': [f64] 71..73 '[]': [f64]
77..79 '{}': () 77..79 '{}': ()
89..93 '&[a]': &[f64] 89..93 '&[a]': &'? [f64]
90..93 '[a]': [f64] 90..93 '[a]': [f64]
91..92 'a': f64 91..92 'a': f64
97..123 '{ ... }': () 97..123 '{ ... }': ()
111..112 'a': f64 111..112 'a': f64
133..140 '&[b, c]': &[f64] 133..140 '&[b, c]': &'? [f64]
134..140 '[b, c]': [f64] 134..140 '[b, c]': [f64]
135..136 'b': f64 135..136 'b': f64
138..139 'c': f64 138..139 'c': f64
144..185 '{ ... }': () 144..185 '{ ... }': ()
158..159 'b': f64 158..159 'b': f64
173..174 'c': f64 173..174 'c': f64
194..195 '_': &[f64] 194..195 '_': &'? [f64]
199..201 '{}': () 199..201 '{}': ()
"#]], "#]],
); );
@ -327,14 +327,14 @@ fn infer_pattern_match_string_literal() {
"#, "#,
expect![[r#" expect![[r#"
10..98 '{ ... } }': () 10..98 '{ ... } }': ()
20..21 's': &str 20..21 's': &'? str
30..37 '"hello"': &str 30..37 '"hello"': &'static str
43..96 'match ... }': () 43..96 'match ... }': ()
49..50 's': &str 49..50 's': &'? str
61..68 '"hello"': &str 61..68 '"hello"': &'static str
61..68 '"hello"': &str 61..68 '"hello"': &'static str
72..74 '{}': () 72..74 '{}': ()
83..84 '_': &str 83..84 '_': &'? str
88..90 '{}': () 88..90 '{}': ()
"#]], "#]],
); );
@ -358,27 +358,27 @@ fn infer_pattern_match_byte_string_literal() {
} }
"#, "#,
expect![[r#" expect![[r#"
105..109 'self': &[T; N] 105..109 'self': &'? [T; N]
111..116 'index': {unknown} 111..116 'index': {unknown}
157..180 '{ ... }': &[u8] 157..180 '{ ... }': &'? [u8]
167..174 'loop {}': ! 167..174 'loop {}': !
172..174 '{}': () 172..174 '{}': ()
191..192 'v': [u8; 3] 191..192 'v': [u8; 3]
203..261 '{ ...v {} }': () 203..261 '{ ...v {} }': ()
209..233 'if let...[S] {}': () 209..233 'if let...[S] {}': ()
212..230 'let b"... &v[S]': bool 212..230 'let b"... &v[S]': bool
216..222 'b"foo"': &[u8] 216..222 'b"foo"': &'static [u8]
216..222 'b"foo"': &[u8] 216..222 'b"foo"': &'static [u8]
225..230 '&v[S]': &[u8] 225..230 '&v[S]': &'? [u8]
226..227 'v': [u8; 3] 226..227 'v': [u8; 3]
226..230 'v[S]': [u8] 226..230 'v[S]': [u8]
228..229 'S': S 228..229 'S': S
231..233 '{}': () 231..233 '{}': ()
238..259 'if let... &v {}': () 238..259 'if let... &v {}': ()
241..256 'let b"foo" = &v': bool 241..256 'let b"foo" = &v': bool
245..251 'b"foo"': &[u8; 3] 245..251 'b"foo"': &'static [u8; 3]
245..251 'b"foo"': &[u8; 3] 245..251 'b"foo"': &'static [u8; 3]
254..256 '&v': &[u8; 3] 254..256 '&v': &'? [u8; 3]
255..256 'v': [u8; 3] 255..256 'v': [u8; 3]
257..259 '{}': () 257..259 '{}': ()
"#]], "#]],
@ -399,17 +399,17 @@ fn infer_pattern_match_or() {
"#, "#,
expect![[r#" expect![[r#"
10..108 '{ ... } }': () 10..108 '{ ... } }': ()
20..21 's': &str 20..21 's': &'? str
30..37 '"hello"': &str 30..37 '"hello"': &'static str
43..106 'match ... }': () 43..106 'match ... }': ()
49..50 's': &str 49..50 's': &'? str
61..68 '"hello"': &str 61..68 '"hello"': &'static str
61..68 '"hello"': &str 61..68 '"hello"': &'static str
61..78 '"hello...world"': &str 61..78 '"hello...world"': &'? str
71..78 '"world"': &str 71..78 '"world"': &'static str
71..78 '"world"': &str 71..78 '"world"': &'static str
82..84 '{}': () 82..84 '{}': ()
93..94 '_': &str 93..94 '_': &'? str
98..100 '{}': () 98..100 '{}': ()
"#]], "#]],
); );
@ -505,10 +505,10 @@ fn infer_adt_pattern() {
216..217 '1': usize 216..217 '1': usize
227..231 'E::B': E 227..231 'E::B': E
235..237 '10': usize 235..237 '10': usize
255..274 'ref d ...{ .. }': &E 255..274 'ref d ...{ .. }': &'? E
263..274 'E::A { .. }': E 263..274 'E::A { .. }': E
277..278 'e': E 277..278 'e': E
284..285 'd': &E 284..285 'd': &'? E
"#]], "#]],
); );
} }
@ -529,14 +529,14 @@ impl Foo {
expect![[r#" expect![[r#"
42..151 '{ ... }': () 42..151 '{ ... }': ()
56..64 'Self(s,)': Foo 56..64 'Self(s,)': Foo
61..62 's': &usize 61..62 's': &'? usize
67..75 '&Foo(0,)': &Foo 67..75 '&Foo(0,)': &'? Foo
68..71 'Foo': extern "rust-call" Foo(usize) -> Foo 68..71 'Foo': extern "rust-call" Foo(usize) -> Foo
68..75 'Foo(0,)': Foo 68..75 'Foo(0,)': Foo
72..73 '0': usize 72..73 '0': usize
89..97 'Self(s,)': Foo 89..97 'Self(s,)': Foo
94..95 's': &mut usize 94..95 's': &'? mut usize
100..112 '&mut Foo(0,)': &mut Foo 100..112 '&mut Foo(0,)': &'? mut Foo
105..108 'Foo': extern "rust-call" Foo(usize) -> Foo 105..108 'Foo': extern "rust-call" Foo(usize) -> Foo
105..112 'Foo(0,)': Foo 105..112 'Foo(0,)': Foo
109..110 '0': usize 109..110 '0': usize
@ -669,7 +669,7 @@ fn main() {
} }
"#, "#,
expect![[r#" expect![[r#"
27..31 'self': &S 27..31 'self': &'? S
41..50 '{ false }': bool 41..50 '{ false }': bool
43..48 'false': bool 43..48 'false': bool
64..115 '{ ... } }': () 64..115 '{ ... } }': ()
@ -679,7 +679,7 @@ fn main() {
93..94 's': S 93..94 's': S
93..100 's.foo()': bool 93..100 's.foo()': bool
104..106 '()': () 104..106 '()': ()
"#]], "#]],
) )
} }
@ -702,29 +702,29 @@ fn test() {
51..58 'loop {}': ! 51..58 'loop {}': !
56..58 '{}': () 56..58 '{}': ()
72..171 '{ ... x); }': () 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 78..105 'foo(&(...y)| x)': i32
82..91 '&(1, "a")': &(i32, &str) 82..91 '&(1, "a")': &'? (i32, &'static str)
83..91 '(1, "a")': (i32, &str) 83..91 '(1, "a")': (i32, &'static str)
84..85 '1': i32 84..85 '1': i32
87..90 '"a"': &str 87..90 '"a"': &'static str
93..104 '|&(x, y)| x': impl FnOnce(&(i32, &str)) -> i32 93..104 '|&(x, y)| x': impl FnOnce(&'? (i32, &'? str)) -> i32
94..101 '&(x, y)': &(i32, &str) 94..101 '&(x, y)': &'? (i32, &'? str)
95..101 '(x, y)': (i32, &str) 95..101 '(x, y)': (i32, &'? str)
96..97 'x': i32 96..97 'x': i32
99..100 'y': &str 99..100 'y': &'? str
103..104 'x': i32 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..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 142..168 'foo(&(...y)| x)': &'? i32
146..155 '&(1, "a")': &(i32, &str) 146..155 '&(1, "a")': &'? (i32, &'static str)
147..155 '(1, "a")': (i32, &str) 147..155 '(1, "a")': (i32, &'static str)
148..149 '1': i32 148..149 '1': i32
151..154 '"a"': &str 151..154 '"a"': &'static str
157..167 '|(x, y)| x': impl FnOnce(&(i32, &str)) -> &i32 157..167 '|(x, y)| x': impl FnOnce(&'? (i32, &'? str)) -> &'? i32
158..164 '(x, y)': (i32, &str) 158..164 '(x, y)': (i32, &'? str)
159..160 'x': &i32 159..160 'x': &'? i32
162..163 'y': &&str 162..163 'y': &'? &'? str
166..167 'x': &i32 166..167 'x': &'? i32
"#]], "#]],
); );
} }
@ -741,13 +741,13 @@ fn slice_tail_pattern() {
} }
"#, "#,
expect![[r#" expect![[r#"
7..13 'params': &[i32] 7..13 'params': &'? [i32]
23..92 '{ ... } }': () 23..92 '{ ... } }': ()
29..90 'match ... }': () 29..90 'match ... }': ()
35..41 'params': &[i32] 35..41 'params': &'? [i32]
52..69 '[head,... @ ..]': [i32] 52..69 '[head,... @ ..]': [i32]
53..57 'head': &i32 53..57 'head': &'? i32
59..68 'tail @ ..': &[i32] 59..68 'tail @ ..': &'? [i32]
66..68 '..': [i32] 66..68 '..': [i32]
73..84 '{ }': () 73..84 '{ }': ()
"#]], "#]],
@ -1109,7 +1109,7 @@ fn var_args() {
#[lang = "va_list"] #[lang = "va_list"]
pub struct VaListImpl<'f>; pub struct VaListImpl<'f>;
fn my_fn(foo: ...) {} fn my_fn(foo: ...) {}
//^^^ VaListImpl<'{error}> //^^^ VaListImpl<'?>
"#, "#,
); );
} }
@ -1122,9 +1122,9 @@ fn foo() {
let &() = &(); let &() = &();
let &mut () = &mut (); let &mut () = &mut ();
let &mut () = &(); let &mut () = &();
//^^^^^^^ expected &(), got &mut () //^^^^^^^ expected &'? (), got &'? mut ()
let &() = &mut (); let &() = &mut ();
//^^^ expected &mut (), got &() //^^^ expected &'? mut (), got &'? ()
} }
"#, "#,
); );
@ -1148,7 +1148,7 @@ fn main() {
}; };
if let Wrap::<X>::A { cool, ..} = &wrapped {} 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 {} if let Wrap::<<S as Schematic>::Props>::A { cool, ..} = &wrapped {}
//^^^^ &u32 //^^^^ &'? u32
} }
"#, "#,
); );
@ -1217,7 +1217,7 @@ fn main() {
match &6 { match &6 {
Foo::<i32>::TEST_I32_REF => (), Foo::<i32>::TEST_I32_REF => (),
Foo::<i32>::TEST_I32 => (), Foo::<i32>::TEST_I32 => (),
//^^^^^^^^^^^^^^^^^^^^ expected &i32, got i32 //^^^^^^^^^^^^^^^^^^^^ expected &'? i32, got i32
_ => (), _ => (),
} }
} }

View file

@ -99,7 +99,7 @@ fn recursive_vars() {
24..31 'unknown': {unknown} 24..31 'unknown': {unknown}
37..44 '[y, &y]': [{unknown}; 2] 37..44 '[y, &y]': [{unknown}; 2]
38..39 'y': {unknown} 38..39 'y': {unknown}
41..43 '&y': &{unknown} 41..43 '&y': &'? {unknown}
42..43 'y': {unknown} 42..43 'y': {unknown}
"#]], "#]],
); );
@ -117,19 +117,19 @@ fn recursive_vars_2() {
"#, "#,
expect![[r#" expect![[r#"
10..79 '{ ...x)]; }': () 10..79 '{ ...x)]; }': ()
20..21 'x': &{unknown} 20..21 'x': &'? {unknown}
24..31 'unknown': &{unknown} 24..31 'unknown': &'? {unknown}
41..42 'y': {unknown} 41..42 'y': {unknown}
45..52 'unknown': {unknown} 45..52 'unknown': {unknown}
58..76 '[(x, y..., &x)]': [(&{unknown}, {unknown}); 2] 58..76 '[(x, y..., &x)]': [(&'? {unknown}, {unknown}); 2]
59..65 '(x, y)': (&{unknown}, {unknown}) 59..65 '(x, y)': (&'? {unknown}, {unknown})
60..61 'x': &{unknown} 60..61 'x': &'? {unknown}
63..64 'y': {unknown} 63..64 'y': {unknown}
67..75 '(&y, &x)': (&{unknown}, {unknown}) 67..75 '(&y, &x)': (&'? {unknown}, {unknown})
68..70 '&y': &{unknown} 68..70 '&y': &'? {unknown}
69..70 'y': {unknown} 69..70 'y': {unknown}
72..74 '&x': &&{unknown} 72..74 '&x': &'? &'? {unknown}
73..74 'x': &{unknown} 73..74 'x': &'? {unknown}
"#]], "#]],
); );
} }
@ -166,7 +166,7 @@ fn infer_std_crash_1() {
59..136 'match ... }': () 59..136 'match ... }': ()
65..82 'someth...nknown': Maybe<{unknown}> 65..82 'someth...nknown': Maybe<{unknown}>
93..123 'Maybe:...thing)': Maybe<{unknown}> 93..123 'Maybe:...thing)': Maybe<{unknown}>
105..122 'ref mu...ething': &mut {unknown} 105..122 'ref mu...ething': &'? mut {unknown}
127..129 '()': () 127..129 '()': ()
"#]], "#]],
); );
@ -183,7 +183,7 @@ fn infer_std_crash_2() {
"#, "#,
expect![[r#" expect![[r#"
22..52 '{ ...n']; }': () 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] 29..49 '[0, b'...b'\n']': [u8; 4]
30..31 '0': u8 30..31 '0': u8
33..38 'b'\n'': u8 33..38 'b'\n'': u8
@ -269,8 +269,8 @@ fn infer_std_crash_5() {
32..320 'for co... }': {unknown} 32..320 'for co... }': {unknown}
32..320 'for co... }': ! 32..320 'for co... }': !
32..320 'for co... }': {unknown} 32..320 'for co... }': {unknown}
32..320 'for co... }': &mut {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... }': fn next<{unknown}>(&'? mut {unknown}) -> Option<<{unknown} as Iterator>::Item>
32..320 'for co... }': Option<{unknown}> 32..320 'for co... }': Option<{unknown}>
32..320 'for co... }': () 32..320 'for co... }': ()
32..320 'for co... }': () 32..320 'for co... }': ()
@ -278,22 +278,22 @@ fn infer_std_crash_5() {
36..43 'content': {unknown} 36..43 'content': {unknown}
47..60 'doesnt_matter': {unknown} 47..60 'doesnt_matter': {unknown}
61..320 '{ ... }': () 61..320 '{ ... }': ()
75..79 'name': &{unknown} 75..79 'name': &'? {unknown}
82..166 'if doe... }': &{unknown} 82..166 'if doe... }': &'? {unknown}
85..98 'doesnt_matter': bool 85..98 'doesnt_matter': bool
99..128 '{ ... }': &{unknown} 99..128 '{ ... }': &'? {unknown}
113..118 'first': &{unknown} 113..118 'first': &'? {unknown}
134..166 '{ ... }': &{unknown} 134..166 '{ ... }': &'? {unknown}
148..156 '&content': &{unknown} 148..156 '&content': &'? {unknown}
149..156 'content': {unknown} 149..156 'content': {unknown}
181..188 'content': &{unknown} 181..188 'content': &'? {unknown}
191..313 'if ICE... }': &{unknown} 191..313 'if ICE... }': &'? {unknown}
194..231 'ICE_RE..._VALUE': {unknown} 194..231 'ICE_RE..._VALUE': {unknown}
194..247 'ICE_RE...&name)': bool 194..247 'ICE_RE...&name)': bool
241..246 '&name': &&{unknown} 241..246 '&name': &'? &'? {unknown}
242..246 'name': &{unknown} 242..246 'name': &'? {unknown}
248..276 '{ ... }': &{unknown} 248..276 '{ ... }': &'? {unknown}
262..266 'name': &{unknown} 262..266 'name': &'? {unknown}
282..313 '{ ... }': {unknown} 282..313 '{ ... }': {unknown}
296..303 'content': {unknown} 296..303 'content': {unknown}
"#]], "#]],
@ -318,7 +318,7 @@ fn infer_nested_generics_crash() {
expect![[r#" expect![[r#"
91..105 'query_response': Canonical<QueryResponse<R>> 91..105 'query_response': Canonical<QueryResponse<R>>
136..166 '{ ...lue; }': () 136..166 '{ ...lue; }': ()
142..163 '&query....value': &QueryResponse<R> 142..163 '&query....value': &'? QueryResponse<R>
143..157 'query_response': Canonical<QueryResponse<R>> 143..157 'query_response': Canonical<QueryResponse<R>>
143..163 'query_....value': QueryResponse<R> 143..163 'query_....value': QueryResponse<R>
"#]], "#]],
@ -465,12 +465,12 @@ fn issue_3999_slice() {
} }
"#, "#,
expect![[r#" expect![[r#"
7..13 'params': &[usize] 7..13 'params': &'? [usize]
25..80 '{ ... } }': () 25..80 '{ ... } }': ()
31..78 'match ... }': () 31..78 'match ... }': ()
37..43 'params': &[usize] 37..43 'params': &'? [usize]
54..66 '[ps @ .., _]': [usize] 54..66 '[ps @ .., _]': [usize]
55..62 'ps @ ..': &[usize] 55..62 'ps @ ..': &'? [usize]
60..62 '..': [usize] 60..62 '..': [usize]
64..65 '_': usize 64..65 '_': usize
70..72 '{}': () 70..72 '{}': ()
@ -523,13 +523,13 @@ fn issue_4235_name_conflicts() {
"#, "#,
expect![[r#" expect![[r#"
31..37 'FOO {}': FOO 31..37 'FOO {}': FOO
63..67 'self': &FOO 63..67 'self': &'? FOO
69..71 '{}': () 69..71 '{}': ()
85..119 '{ ...o(); }': () 85..119 '{ ...o(); }': ()
95..96 'a': &FOO 95..96 'a': &'? FOO
99..103 '&FOO': &FOO 99..103 '&FOO': &'? FOO
100..103 'FOO': FOO 100..103 'FOO': FOO
109..110 'a': &FOO 109..110 'a': &'? FOO
109..116 'a.foo()': () 109..116 'a.foo()': ()
"#]], "#]],
); );
@ -715,12 +715,12 @@ fn issue_4885() {
} }
"#, "#,
expect![[r#" expect![[r#"
70..73 'key': &K 70..73 'key': &'? K
132..148 '{ ...key) }': impl Future<Output = <K as Foo<R>>::Bar> 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> 138..146 'bar(key)': impl Future<Output = <K as Foo<R>>::Bar>
142..145 'key': &K 142..145 'key': &'? K
162..165 'key': &K 162..165 'key': &'? K
224..227 '{ }': () 224..227 '{ }': ()
"#]], "#]],
); );
@ -771,11 +771,11 @@ fn issue_4800() {
} }
"#, "#,
expect![[r#" expect![[r#"
379..383 'self': &mut PeerSet<D> 379..383 'self': &'? mut PeerSet<D>
401..424 '{ ... }': dyn Future<Output = ()> 401..424 '{ ... }': dyn Future<Output = ()>
411..418 'loop {}': ! 411..418 'loop {}': !
416..418 '{}': () 416..418 '{}': ()
575..579 'self': &mut Self 575..579 'self': &'? mut Self
"#]], "#]],
); );
} }
@ -815,19 +815,19 @@ fn issue_4966() {
225..229 'iter': T 225..229 'iter': T
244..246 '{}': Vec<A> 244..246 '{}': Vec<A>
258..402 '{ ...r(); }': () 258..402 '{ ...r(); }': ()
268..273 'inner': Map<impl Fn(&f64) -> f64> 268..273 'inner': Map<impl Fn(&'? f64) -> f64>
276..300 'Map { ... 0.0 }': Map<impl Fn(&f64) -> f64> 276..300 'Map { ... 0.0 }': Map<impl Fn(&'? f64) -> f64>
285..298 '|_: &f64| 0.0': impl Fn(&f64) -> f64 285..298 '|_: &f64| 0.0': impl Fn(&'? f64) -> f64
286..287 '_': &f64 286..287 '_': &'? f64
295..298 '0.0': f64 295..298 '0.0': f64
311..317 'repeat': 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>> 320..345 'Repeat...nner }': Repeat<Map<impl Fn(&'? f64) -> f64>>
338..343 'inner': 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>>>> 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..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>>>> 362..379 'from_i...epeat)': Vec<IntoIterator::Item<Repeat<Map<impl Fn(&'? f64) -> f64>>>>
372..378 'repeat': 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..389 'vec': Vec<IntoIterator::Item<Repeat<Map<impl Fn(&'? f64) -> f64>>>>
386..399 'vec.foo_bar()': {unknown} 386..399 'vec.foo_bar()': {unknown}
"#]], "#]],
); );
@ -850,10 +850,10 @@ fn main() {
} }
"#, "#,
expect![[r#" expect![[r#"
40..44 'self': &S<T> 40..44 'self': &'? S<T>
46..48 '_t': T 46..48 '_t': T
53..55 '{}': () 53..55 '{}': ()
81..85 'self': &S<T> 81..85 'self': &'? S<T>
87..89 '_f': F 87..89 '_f': F
94..96 '{}': () 94..96 '{}': ()
109..160 '{ ...10); }': () 109..160 '{ ...10); }': ()
@ -862,8 +862,8 @@ fn main() {
123..126 'S()': S<i32> 123..126 'S()': S<i32>
132..133 's': S<i32> 132..133 's': S<i32>
132..144 's.g(|_x| {})': () 132..144 's.g(|_x| {})': ()
136..143 '|_x| {}': impl FnOnce(&i32) 136..143 '|_x| {}': impl FnOnce(&'? i32)
137..139 '_x': &i32 137..139 '_x': &'? i32
141..143 '{}': () 141..143 '{}': ()
150..151 's': S<i32> 150..151 's': S<i32>
150..157 's.f(10)': () 150..157 's.f(10)': ()
@ -895,14 +895,14 @@ fn flush(&self) {
} }
"#, "#,
expect![[r#" expect![[r#"
123..127 'self': &Mutex<T> 123..127 'self': &'? Mutex<T>
150..152 '{}': MutexGuard<'{error}, T> 150..152 '{}': MutexGuard<'?, T>
234..238 'self': &{unknown} 234..238 'self': &'? {unknown}
240..290 '{ ...()); }': () 240..290 '{ ...()); }': ()
250..251 'w': &Mutex<BufWriter> 250..251 'w': &'? Mutex<BufWriter>
276..287 '*(w.lock())': BufWriter 276..287 '*(w.lock())': BufWriter
278..279 'w': &Mutex<BufWriter> 278..279 'w': &'? Mutex<BufWriter>
278..286 'w.lock()': MutexGuard<'{error}, BufWriter> 278..286 'w.lock()': MutexGuard<'?, BufWriter>
"#]], "#]],
); );
} }
@ -1023,20 +1023,20 @@ fn cfg_tail() {
expect![[r#" expect![[r#"
14..53 '{ ...)] 9 }': () 14..53 '{ ...)] 9 }': ()
20..31 '{ "first" }': () 20..31 '{ "first" }': ()
22..29 '"first"': &str 22..29 '"first"': &'static str
72..190 '{ ...] 13 }': () 72..190 '{ ...] 13 }': ()
78..88 '{ "fake" }': () 78..88 '{ "fake" }': ()
80..86 '"fake"': &str 80..86 '"fake"': &'static str
93..103 '{ "fake" }': () 93..103 '{ "fake" }': ()
95..101 '"fake"': &str 95..101 '"fake"': &'static str
108..120 '{ "second" }': () 108..120 '{ "second" }': ()
110..118 '"second"': &str 110..118 '"second"': &'static str
210..273 '{ ... 15; }': () 210..273 '{ ... 15; }': ()
216..227 '{ "third" }': () 216..227 '{ "third" }': ()
218..225 '"third"': &str 218..225 '"third"': &'static str
293..357 '{ ...] 15 }': () 293..357 '{ ...] 15 }': ()
299..311 '{ "fourth" }': &str 299..311 '{ "fourth" }': &'static str
301..309 '"fourth"': &str 301..309 '"fourth"': &'static str
"#]], "#]],
) )
} }
@ -1238,8 +1238,8 @@ fn test() {
16..66 'for _ ... }': IntoIterator::IntoIter<()> 16..66 'for _ ... }': IntoIterator::IntoIter<()>
16..66 'for _ ... }': ! 16..66 'for _ ... }': !
16..66 'for _ ... }': IntoIterator::IntoIter<()> 16..66 'for _ ... }': IntoIterator::IntoIter<()>
16..66 'for _ ... }': &mut 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 _ ... }': fn next<IntoIterator::IntoIter<()>>(&'? mut IntoIterator::IntoIter<()>) -> Option<<IntoIterator::IntoIter<()> as Iterator>::Item>
16..66 'for _ ... }': Option<IntoIterator::Item<()>> 16..66 'for _ ... }': Option<IntoIterator::Item<()>>
16..66 'for _ ... }': () 16..66 'for _ ... }': ()
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] #[test]
fn tuple_struct_pattern_with_unmatched_args_crash() { fn tuple_struct_pattern_with_unmatched_args_crash() {
check_infer( check_infer(
@ -1727,7 +1648,7 @@ fn dyn_with_unresolved_trait() {
r#" r#"
fn foo(a: &dyn DoesNotExist) { fn foo(a: &dyn DoesNotExist) {
a.bar(); a.bar();
//^&{unknown} //^&'? {unknown}
} }
"#, "#,
); );
@ -1851,9 +1772,9 @@ fn foo() {
match &E::A { match &E::A {
b @ (x @ E::A | x) => { b @ (x @ E::A | x) => {
b; b;
//^ &E //^ &'? E
x; 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,
{}
"#,
);
}

View file

@ -115,15 +115,15 @@ fn test(a: u32, b: isize, c: !, d: &str) {
8..9 'a': u32 8..9 'a': u32
16..17 'b': isize 16..17 'b': isize
26..27 'c': ! 26..27 'c': !
32..33 'd': &str 32..33 'd': &'? str
41..120 '{ ...f32; }': () 41..120 '{ ...f32; }': ()
47..48 'a': u32 47..48 'a': u32
54..55 'b': isize 54..55 'b': isize
61..62 'c': ! 61..62 'c': !
68..69 'd': &str 68..69 'd': &'? str
75..81 '1usize': usize 75..81 '1usize': usize
87..93 '1isize': isize 87..93 '1isize': isize
99..105 '"test"': &str 99..105 '"test"': &'static str
111..117 '1.0f32': f32 111..117 '1.0f32': f32
"#]], "#]],
); );
@ -344,23 +344,23 @@ fn test(a: &u32, b: &mut u32, c: *const u32, d: *mut u32) {
} }
"#, "#,
expect![[r#" expect![[r#"
8..9 'a': &u32 8..9 'a': &'? u32
17..18 'b': &mut u32 17..18 'b': &'? mut u32
30..31 'c': *const u32 30..31 'c': *const u32
45..46 'd': *mut u32 45..46 'd': *mut u32
58..149 '{ ... *d; }': () 58..149 '{ ... *d; }': ()
64..65 'a': &u32 64..65 'a': &'? u32
71..73 '*a': u32 71..73 '*a': u32
72..73 'a': &u32 72..73 'a': &'? u32
79..81 '&a': &&u32 79..81 '&a': &'? &'? u32
80..81 'a': &u32 80..81 'a': &'? u32
87..93 '&mut a': &mut &u32 87..93 '&mut a': &'? mut &'? u32
92..93 'a': &u32 92..93 'a': &'? u32
99..100 'b': &mut u32 99..100 'b': &'? mut u32
106..108 '*b': u32 106..108 '*b': u32
107..108 'b': &mut u32 107..108 'b': &'? mut u32
114..116 '&b': &&mut u32 114..116 '&b': &'? &'? mut u32
115..116 'b': &mut u32 115..116 'b': &'? mut u32
122..123 'c': *const u32 122..123 'c': *const u32
129..131 '*c': u32 129..131 '*c': u32
130..131 'c': *const u32 130..131 'c': *const u32
@ -425,22 +425,22 @@ h";
32..36 '5i32': i32 32..36 '5i32': i32
50..54 '5f32': f32 50..54 '5f32': f32
68..72 '5f64': f64 68..72 '5f64': f64
86..93 '"hello"': &str 86..93 '"hello"': &'static str
107..115 'b"bytes"': &[u8; 5] 107..115 'b"bytes"': &'static [u8; 5]
129..132 ''c'': char 129..132 ''c'': char
146..150 'b'b'': u8 146..150 'b'b'': u8
164..168 '3.14': f64 164..168 '3.14': f64
182..186 '5000': i32 182..186 '5000': i32
200..205 'false': bool 200..205 'false': bool
219..223 'true': bool 219..223 'true': bool
237..333 'r#" ... "#': &str 237..333 'r#" ... "#': &'static str
347..357 'br#"yolo"#': &[u8; 4] 347..357 'br#"yolo"#': &'static [u8; 4]
375..376 'a': &[u8; 4] 375..376 'a': &'static [u8; 4]
379..403 'b"a\x2... c"': &[u8; 4] 379..403 'b"a\x2... c"': &'static [u8; 4]
421..422 'b': &[u8; 4] 421..422 'b': &'static [u8; 4]
425..433 'br"g\ h"': &[u8; 4] 425..433 'br"g\ h"': &'static [u8; 4]
451..452 'c': &[u8; 6] 451..452 'c': &'static [u8; 6]
455..467 'br#"x"\"yb"#': &[u8; 6] 455..467 'br#"x"\"yb"#': &'static [u8; 6]
"##]], "##]],
); );
} }
@ -508,9 +508,9 @@ fn test(x: SomeType) {
238..240 '!x': {unknown} 238..240 '!x': {unknown}
239..240 'x': SomeType 239..240 'x': SomeType
246..254 '-"hello"': {unknown} 246..254 '-"hello"': {unknown}
247..254 '"hello"': &str 247..254 '"hello"': &'static str
260..268 '!"hello"': {unknown} 260..268 '!"hello"': {unknown}
261..268 '"hello"': &str 261..268 '"hello"': &'static str
"#]], "#]],
); );
} }
@ -535,7 +535,7 @@ fn test() -> &mut &f64 {
expect![[r#" expect![[r#"
13..14 'x': u32 13..14 'x': u32
21..23 '{}': () 21..23 '{}': ()
77..230 '{ ...t &c }': &mut &f64 77..230 '{ ...t &c }': &'? mut &'? f64
87..88 'a': u32 87..88 'a': u32
91..107 'unknow...nction': {unknown} 91..107 'unknow...nction': {unknown}
91..109 'unknow...tion()': u32 91..109 'unknow...tion()': u32
@ -550,8 +550,8 @@ fn test() -> &mut &f64 {
193..194 'c': f64 193..194 'c': f64
197..213 'unknow...nction': {unknown} 197..213 'unknow...nction': {unknown}
197..215 'unknow...tion()': f64 197..215 'unknow...tion()': f64
221..228 '&mut &c': &mut &f64 221..228 '&mut &c': &'? mut &'? f64
226..228 '&c': &f64 226..228 '&c': &'? f64
227..228 'c': f64 227..228 'c': f64
"#]], "#]],
); );
@ -579,12 +579,12 @@ impl S {
} }
"#, "#,
expect![[r#" expect![[r#"
33..37 'self': &S 33..37 'self': &'? S
39..60 '{ ... }': () 39..60 '{ ... }': ()
49..53 'self': &S 49..53 'self': &'? S
74..78 'self': &S 74..78 'self': &'? S
87..108 '{ ... }': () 87..108 '{ ... }': ()
97..101 'self': &S 97..101 'self': &'? S
132..152 '{ ... }': S 132..152 '{ ... }': S
142..146 'S {}': S 142..146 'S {}': S
176..199 '{ ... }': S 176..199 '{ ... }': S
@ -771,35 +771,35 @@ fn test2(a1: *const A, a2: *mut A) {
64..65 'a': A 64..65 'a': A
71..73 'a1': A 71..73 'a1': A
71..75 'a1.b': B 71..75 'a1.b': B
85..87 'a2': &A 85..87 'a2': &'? A
90..92 '&a': &A 90..92 '&a': &'? A
91..92 'a': A 91..92 'a': A
98..100 'a2': &A 98..100 'a2': &'? A
98..102 'a2.b': B 98..102 'a2.b': B
112..114 'a3': &mut A 112..114 'a3': &'? mut A
117..123 '&mut a': &mut A 117..123 '&mut a': &'? mut A
122..123 'a': A 122..123 'a': A
129..131 'a3': &mut A 129..131 'a3': &'? mut A
129..133 'a3.b': B 129..133 'a3.b': B
143..145 'a4': &&&&&&&A 143..145 'a4': &'? &'? &'? &'? &'? &'? &'? A
148..156 '&&&&&&&a': &&&&&&&A 148..156 '&&&&&&&a': &'? &'? &'? &'? &'? &'? &'? A
149..156 '&&&&&&a': &&&&&&A 149..156 '&&&&&&a': &'? &'? &'? &'? &'? &'? A
150..156 '&&&&&a': &&&&&A 150..156 '&&&&&a': &'? &'? &'? &'? &'? A
151..156 '&&&&a': &&&&A 151..156 '&&&&a': &'? &'? &'? &'? A
152..156 '&&&a': &&&A 152..156 '&&&a': &'? &'? &'? A
153..156 '&&a': &&A 153..156 '&&a': &'? &'? A
154..156 '&a': &A 154..156 '&a': &'? A
155..156 'a': A 155..156 'a': A
162..164 'a4': &&&&&&&A 162..164 'a4': &'? &'? &'? &'? &'? &'? &'? A
162..166 'a4.b': B 162..166 'a4.b': B
176..178 'a5': &mut &&mut &&mut A 176..178 'a5': &'? mut &'? &'? mut &'? &'? mut A
181..199 '&mut &...&mut a': &mut &&mut &&mut A 181..199 '&mut &...&mut a': &'? mut &'? &'? mut &'? &'? mut A
186..199 '&&mut &&mut a': &&mut &&mut A 186..199 '&&mut &&mut a': &'? &'? mut &'? &'? mut A
187..199 '&mut &&mut a': &mut &&mut A 187..199 '&mut &&mut a': &'? mut &'? &'? mut A
192..199 '&&mut a': &&mut A 192..199 '&&mut a': &'? &'? mut A
193..199 '&mut a': &mut A 193..199 '&mut a': &'? mut A
198..199 'a': A 198..199 'a': A
205..207 'a5': &mut &&mut &&mut A 205..207 'a5': &'? mut &'? &'? mut &'? &'? mut A
205..209 'a5.b': B 205..209 'a5.b': B
223..225 'a1': *const A 223..225 'a1': *const A
237..239 'a2': *mut A 237..239 'a2': *mut A
@ -840,22 +840,22 @@ fn test() {
} }
"#, "#,
expect![[r#" expect![[r#"
66..70 'self': &A<T> 66..70 'self': &'? A<T>
78..101 '{ ... }': &T 78..101 '{ ... }': &'? T
88..95 '&self.0': &T 88..95 '&self.0': &'? T
89..93 'self': &A<T> 89..93 'self': &'? A<T>
89..95 'self.0': T 89..95 'self.0': T
182..186 'self': &B<T> 182..186 'self': &'? B<T>
205..228 '{ ... }': &T 205..228 '{ ... }': &'? T
215..222 '&self.0': &T 215..222 '&self.0': &'? T
216..220 'self': &B<T> 216..220 'self': &'? B<T>
216..222 'self.0': T 216..222 'self.0': T
242..280 '{ ...))); }': () 242..280 '{ ...))); }': ()
252..253 't': &i32 252..253 't': &'? i32
256..262 'A::foo': fn foo<i32>(&A<i32>) -> &i32 256..262 'A::foo': fn foo<i32>(&'? A<i32>) -> &'? i32
256..277 'A::foo...42))))': &i32 256..277 'A::foo...42))))': &'? i32
263..276 '&&B(B(A(42)))': &&B<B<A<i32>>> 263..276 '&&B(B(A(42)))': &'? &'? B<B<A<i32>>>
264..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..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>>> 265..276 'B(B(A(42)))': B<B<A<i32>>>
267..268 'B': extern "rust-call" B<A<i32>>(A<i32>) -> 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#" expect![[r#"
71..75 'self': &A<T> 71..75 'self': &'? A<T>
77..78 'x': &A<T> 77..78 'x': &'? A<T>
93..114 '{ ... }': &T 93..114 '{ ... }': &'? T
103..108 '&*x.0': &T 103..108 '&*x.0': &'? T
104..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 105..108 'x.0': *mut T
195..199 'self': &B<T> 195..199 'self': &'? B<T>
218..241 '{ ... }': &T 218..241 '{ ... }': &'? T
228..235 '&self.0': &T 228..235 '&self.0': &'? T
229..233 'self': &B<T> 229..233 'self': &'? B<T>
229..235 'self.0': T 229..235 'self.0': T
253..254 'a': A<i32> 253..254 'a': A<i32>
264..310 '{ ...))); }': () 264..310 '{ ...))); }': ()
274..275 't': &i32 274..275 't': &'? i32
278..279 'A': extern "rust-call" A<i32>(*mut i32) -> A<i32> 278..279 'A': extern "rust-call" A<i32>(*mut i32) -> A<i32>
278..292 'A(0 as *mut _)': 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..281 '0': i32
280..291 '0 as *mut _': *mut i32 280..291 '0 as *mut _': *mut i32
297..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>>> 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..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>>> 299..306 'B(B(a))': B<B<A<i32>>>
301..302 'B': extern "rust-call" B<A<i32>>(A<i32>) -> 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 31..35 'self': A
37..38 'x': u32 37..38 'x': u32
52..54 '{}': i32 52..54 '{}': i32
106..110 'self': &A 106..110 'self': &'? A
112..113 'x': u64 112..113 'x': u64
127..129 '{}': i64 127..129 '{}': i64
147..148 'a': A 147..148 'a': A
@ -1053,7 +1053,7 @@ fn infer_inherent_method() {
159..167 'a.foo(1)': i32 159..167 'a.foo(1)': i32
165..166 '1': u32 165..166 '1': u32
173..184 '(&a).bar(1)': i64 173..184 '(&a).bar(1)': i64
174..176 '&a': &A 174..176 '&a': &'? A
175..176 'a': A 175..176 'a': A
182..183 '1': u64 182..183 '1': u64
190..191 'a': A 190..191 'a': A
@ -1078,10 +1078,10 @@ fn test() {
} }
"#, "#,
expect![[r#" expect![[r#"
67..71 'self': &str 67..71 'self': &'? str
80..82 '{}': i32 80..82 '{}': i32
96..116 '{ ...o(); }': () 96..116 '{ ...o(); }': ()
102..107 '"foo"': &str 102..107 '"foo"': &'static str
102..113 '"foo".foo()': i32 102..113 '"foo".foo()': i32
"#]], "#]],
); );
@ -1101,33 +1101,33 @@ fn infer_tuple() {
} }
"#, "#,
expect![[r#" expect![[r#"
8..9 'x': &str 8..9 'x': &'? str
17..18 'y': isize 17..18 'y': isize
27..169 '{ ...d"); }': () 27..169 '{ ...d"); }': ()
37..38 'a': (u32, &str) 37..38 'a': (u32, &'? str)
54..62 '(1, "a")': (u32, &str) 54..62 '(1, "a")': (u32, &'? str)
55..56 '1': u32 55..56 '1': u32
58..61 '"a"': &str 58..61 '"a"': &'static str
72..73 'b': ((u32, &str), &str) 72..73 'b': ((u32, &'? str), &'? str)
76..82 '(a, x)': ((u32, &str), &str) 76..82 '(a, x)': ((u32, &'? str), &'? str)
77..78 'a': (u32, &str) 77..78 'a': (u32, &'? str)
80..81 'x': &str 80..81 'x': &'? str
92..93 'c': (isize, &str) 92..93 'c': (isize, &'? str)
96..102 '(y, x)': (isize, &str) 96..102 '(y, x)': (isize, &'? str)
97..98 'y': isize 97..98 'y': isize
100..101 'x': &str 100..101 'x': &'? str
112..113 'd': ((isize, &str), &str) 112..113 'd': ((isize, &'? str), &'? str)
116..122 '(c, x)': ((isize, &str), &str) 116..122 '(c, x)': ((isize, &'? str), &'? str)
117..118 'c': (isize, &str) 117..118 'c': (isize, &'? str)
120..121 'x': &str 120..121 'x': &'? str
132..133 'e': (i32, &str) 132..133 'e': (i32, &'static str)
136..144 '(1, "e")': (i32, &str) 136..144 '(1, "e")': (i32, &'static str)
137..138 '1': i32 137..138 '1': i32
140..143 '"e"': &str 140..143 '"e"': &'static str
154..155 'f': ((i32, &str), &str) 154..155 'f': ((i32, &'static str), &'static str)
158..166 '(e, "d")': ((i32, &str), &str) 158..166 '(e, "d")': ((i32, &'static str), &'static str)
159..160 'e': (i32, &str) 159..160 'e': (i32, &'static str)
162..165 '"d"': &str 162..165 '"d"': &'static str
"#]], "#]],
); );
} }
@ -1156,20 +1156,20 @@ fn infer_array() {
} }
"#, "#,
expect![[r#" expect![[r#"
8..9 'x': &str 8..9 'x': &'? str
17..18 'y': isize 17..18 'y': isize
27..326 '{ ...,4]; }': () 27..326 '{ ...,4]; }': ()
37..38 'a': [&str; 1] 37..38 'a': [&'? str; 1]
41..44 '[x]': [&str; 1] 41..44 '[x]': [&'? str; 1]
42..43 'x': &str 42..43 'x': &'? str
54..55 'b': [[&str; 1]; 2] 54..55 'b': [[&'? str; 1]; 2]
58..64 '[a, a]': [[&str; 1]; 2] 58..64 '[a, a]': [[&'? str; 1]; 2]
59..60 'a': [&str; 1] 59..60 'a': [&'? str; 1]
62..63 'a': [&str; 1] 62..63 'a': [&'? str; 1]
74..75 'c': [[[&str; 1]; 2]; 2] 74..75 'c': [[[&'? str; 1]; 2]; 2]
78..84 '[b, b]': [[[&str; 1]; 2]; 2] 78..84 '[b, b]': [[[&'? str; 1]; 2]; 2]
79..80 'b': [[&str; 1]; 2] 79..80 'b': [[&'? str; 1]; 2]
82..83 'b': [[&str; 1]; 2] 82..83 'b': [[&'? str; 1]; 2]
95..96 'd': [isize; 4] 95..96 'd': [isize; 4]
99..111 '[y, 1, 2, 3]': [isize; 4] 99..111 '[y, 1, 2, 3]': [isize; 4]
100..101 'y': isize 100..101 'y': isize
@ -1197,15 +1197,15 @@ fn infer_array() {
209..215 '[1, 2]': [i32; 2] 209..215 '[1, 2]': [i32; 2]
210..211 '1': i32 210..211 '1': i32
213..214 '2': i32 213..214 '2': i32
225..226 'i': [&str; 2] 225..226 'i': [&'? str; 2]
229..239 '["a", "b"]': [&str; 2] 229..239 '["a", "b"]': [&'? str; 2]
230..233 '"a"': &str 230..233 '"a"': &'static str
235..238 '"b"': &str 235..238 '"b"': &'static str
250..251 'b': [[&str; 1]; 2] 250..251 'b': [[&'? str; 1]; 2]
254..264 '[a, ["b"]]': [[&str; 1]; 2] 254..264 '[a, ["b"]]': [[&'? str; 1]; 2]
255..256 'a': [&str; 1] 255..256 'a': [&'? str; 1]
258..263 '["b"]': [&str; 1] 258..263 '["b"]': [&'? str; 1]
259..262 '"b"': &str 259..262 '"b"': &'static str
274..275 'x': [u8; 0] 274..275 'x': [u8; 0]
287..289 '[]': [u8; 0] 287..289 '[]': [u8; 0]
299..300 'y': [u8; 4] 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..93 'A': extern "rust-call" A<u128>(u128) -> A<u128>
92..101 'A(42u128)': A<u128> 92..101 'A(42u128)': A<u128>
94..100 '42u128': u128 94..100 '42u128': u128
107..111 'Some': extern "rust-call" Some<&str>(&str) -> Option<&str> 107..111 'Some': extern "rust-call" Some<&'static str>(&'static str) -> Option<&'static str>
107..116 'Some("x")': Option<&str> 107..116 'Some("x")': Option<&'static str>
112..115 '"x"': &str 112..115 '"x"': &'static str
122..134 'Option::Some': extern "rust-call" Some<&str>(&str) -> Option<&str> 122..134 'Option::Some': extern "rust-call" Some<&'static str>(&'static str) -> Option<&'static str>
122..139 'Option...e("x")': Option<&str> 122..139 'Option...e("x")': Option<&'static str>
135..138 '"x"': &str 135..138 '"x"': &'static str
145..149 'None': Option<{unknown}> 145..149 'None': Option<{unknown}>
159..160 'x': Option<i64> 159..160 'x': Option<i64>
176..180 'None': Option<i64> 176..180 'None': Option<i64>
@ -1405,15 +1405,15 @@ fn infer_impl_generics_with_autoderef() {
} }
"#, "#,
expect![[r#" expect![[r#"
77..81 'self': &Option<T> 77..81 'self': &'? Option<T>
97..99 '{}': Option<&T> 97..99 '{}': Option<&'? T>
110..111 'o': Option<u32> 110..111 'o': Option<u32>
126..164 '{ ...f(); }': () 126..164 '{ ...f(); }': ()
132..145 '(&o).as_ref()': Option<&u32> 132..145 '(&o).as_ref()': Option<&'? u32>
133..135 '&o': &Option<u32> 133..135 '&o': &'? Option<u32>
134..135 'o': Option<u32> 134..135 'o': Option<u32>
151..152 '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#" expect![[r#"
115..116 'x': A<u32, i128> 115..116 'x': A<u32, i128>
123..124 'y': A<&str, u128> 123..124 'y': A<&'? str, u128>
137..138 'z': A<u8, i8> 137..138 'z': A<u8, i8>
153..210 '{ ...z.y; }': () 153..210 '{ ...z.y; }': ()
159..160 'x': A<u32, i128> 159..160 'x': A<u32, i128>
159..162 'x.x': u32 159..162 'x.x': u32
168..169 'x': A<u32, i128> 168..169 'x': A<u32, i128>
168..171 'x.y': i128 168..171 'x.y': i128
177..178 'y': A<&str, u128> 177..178 'y': A<&'? str, u128>
177..180 'y.x': &str 177..180 'y.x': &'? str
186..187 'y': A<&str, u128> 186..187 'y': A<&'? str, u128>
186..189 'y.y': u128 186..189 'y.y': u128
195..196 'z': A<u8, i8> 195..196 'z': A<u8, i8>
195..198 'z.x': u8 195..198 'z.x': u8
@ -1572,8 +1572,8 @@ fn infer_type_alias() {
312..328 'm::Ali...Foo(0)': Enum 312..328 'm::Ali...Foo(0)': Enum
326..327 '0': u8 326..327 '0': u8
338..354 'm::Ali...Foo(x)': Enum 338..354 'm::Ali...Foo(x)': Enum
352..353 'x': &u8 352..353 'x': &'? u8
357..359 '&e': &Enum 357..359 '&e': &'? Enum
358..359 'e': Enum 358..359 'e': Enum
"#]], "#]],
) )
@ -1618,10 +1618,10 @@ fn infer_type_param() {
9..10 'x': T 9..10 'x': T
20..29 '{ x }': T 20..29 '{ x }': T
26..27 'x': T 26..27 'x': T
43..44 'x': &T 43..44 'x': &'? T
55..65 '{ *x }': T 55..65 '{ *x }': T
61..63 '*x': T 61..63 '*x': T
62..63 'x': &T 62..63 'x': &'? T
77..157 '{ ...(1); }': () 77..157 '{ ...(1); }': ()
87..88 'y': u32 87..88 'y': u32
91..96 '10u32': u32 91..96 '10u32': u32
@ -1629,9 +1629,9 @@ fn infer_type_param() {
102..107 'id(y)': u32 102..107 'id(y)': u32
105..106 'y': u32 105..106 'y': u32
117..118 'x': bool 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 127..135 'clone(z)': bool
133..134 'z': &bool 133..134 'z': &'? bool
141..151 'id::<i128>': fn id<i128>(i128) -> i128 141..151 'id::<i128>': fn id<i128>(i128) -> i128
141..154 'id::<i128>(1)': i128 141..154 'id::<i128>(1)': i128
152..153 '1': i128 152..153 '1': i128
@ -1842,7 +1842,7 @@ fn foo() -> &'static str { "" }
fn main() { fn main() {
foo(); foo();
//^^^^^ &str //^^^^^ &'static str
}"#, }"#,
); );
} }
@ -1940,10 +1940,10 @@ fn closure_return_inferred() {
"#, "#,
expect![[r#" expect![[r#"
16..46 '{ ..." }; }': u32 16..46 '{ ..." }; }': u32
26..27 'x': impl Fn() -> &str 26..27 'x': impl Fn() -> &'static str
30..43 '|| { "test" }': impl Fn() -> &str 30..43 '|| { "test" }': impl Fn() -> &'static str
33..43 '{ "test" }': &str 33..43 '{ "test" }': &'static str
35..41 '"test"': &str 35..41 '"test"': &'static str
"#]], "#]],
); );
} }
@ -1975,10 +1975,10 @@ fn test() {
70..71 'v': i64 70..71 'v': i64
78..80 '{}': () 78..80 '{}': ()
91..362 '{ ... } }': () 91..362 '{ ... } }': ()
101..106 'mut g': |usize| yields i64 -> &str 101..106 'mut g': |usize| yields i64 -> &'static str
109..218 '|r| { ... }': |usize| yields i64 -> &str 109..218 '|r| { ... }': |usize| yields i64 -> &'static str
110..111 'r': usize 110..111 'r': usize
113..218 '{ ... }': &str 113..218 '{ ... }': &'static str
127..128 'a': usize 127..128 'a': usize
131..138 'yield 0': usize 131..138 'yield 0': usize
137..138 '0': i64 137..138 '0': i64
@ -1988,22 +1988,22 @@ fn test() {
177..178 'a': usize 177..178 'a': usize
181..188 'yield 2': usize 181..188 'yield 2': usize
187..188 '2': i64 187..188 '2': i64
198..212 '"return value"': &str 198..212 '"return value"': &'static str
225..360 'match ... }': () 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..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 -> &str> 231..247 'Pin::n...mut g)': Pin<&'? mut |usize| yields i64 -> &'static str>
231..262 'Pin::n...usize)': CoroutineState<i64, &str> 231..262 'Pin::n...usize)': CoroutineState<i64, &'static str>
240..246 '&mut g': &mut |usize| yields i64 -> &str 240..246 '&mut g': &'? mut |usize| yields i64 -> &'static str
245..246 'g': |usize| yields i64 -> &str 245..246 'g': |usize| yields i64 -> &'static str
255..261 '0usize': usize 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 297..298 'y': i64
303..312 '{ f(y); }': () 303..312 '{ f(y); }': ()
305..306 'f': fn f(i64) 305..306 'f': fn f(i64)
305..309 'f(y)': () 305..309 'f(y)': ()
307..308 'y': i64 307..308 'y': i64
321..348 'Corout...ete(r)': CoroutineState<i64, &str> 321..348 'Corout...ete(r)': CoroutineState<i64, &'static str>
346..347 'r': &str 346..347 'r': &'static str
352..354 '{}': () 352..354 '{}': ()
"#]], "#]],
); );
@ -2050,7 +2050,7 @@ fn f(x: (&&&&i32, &&&i32)) {
_ => loop {}, _ => loop {},
}; };
f; f;
//^ (&&&&i32, &&&i32) //^ (&'? &'? &'? &'? i32, &'? &'? &'? i32)
} }
"#, "#,
); );
@ -2059,10 +2059,10 @@ fn f(x: (&&&&i32, &&&i32)) {
fn f() { fn f() {
let x = &&&(&&&2, &&&&&3); let x = &&&(&&&2, &&&&&3);
let (y, z) = x; let (y, z) = x;
//^ &&&&i32 //^ &'? &'? &'? &'? i32
let t @ (y, z) = x; let t @ (y, z) = x;
t; t;
//^ &&&(&&&i32, &&&&&i32) //^ &'? &'? &'? (&'? &'? &'? i32, &'? &'? &'? &'? &'? i32)
} }
"#, "#,
); );
@ -2071,10 +2071,10 @@ fn f() {
fn f() { fn f() {
let x = &&&(&&&2, &&&&&3); let x = &&&(&&&2, &&&&&3);
let (y, z) = x; let (y, z) = x;
//^ &&&&i32 //^ &'? &'? &'? &'? i32
let t @ (y, z) = x; let t @ (y, z) = x;
t; t;
//^ &&&(&&&i32, &&&&&i32) //^ &'? &'? &'? (&'? &'? &'? i32, &'? &'? &'? &'? &'? i32)
} }
"#, "#,
); );
@ -2761,23 +2761,23 @@ impl S {
fn f() { fn f() {
let x = S; let x = S;
let c1 = || x.read(); let c1 = || x.read();
//^^ impl Fn() -> &S //^^ impl Fn() -> &'? S
let c2 = || x.write(); let c2 = || x.write();
//^^ impl FnMut() -> &mut S //^^ impl FnMut() -> &'? mut S
let c3 = || x.consume(); let c3 = || x.consume();
//^^ impl FnOnce() -> S //^^ impl FnOnce() -> S
let c3 = || x.consume().consume().consume(); let c3 = || x.consume().consume().consume();
//^^ impl FnOnce() -> S //^^ impl FnOnce() -> S
let c3 = || x.consume().write().read(); let c3 = || x.consume().write().read();
//^^ impl FnOnce() -> &S //^^ impl FnOnce() -> &'? S
let x = &mut x; let x = &mut x;
let c1 = || x.write(); let c1 = || x.write();
//^^ impl FnMut() -> &mut S //^^ impl FnMut() -> &'? mut S
let x = S; let x = S;
let c1 = || { let ref t = x; t }; let c1 = || { let ref t = x; t };
//^^ impl Fn() -> &S //^^ impl Fn() -> &'? S
let c2 = || { let ref mut t = x; t }; let c2 = || { let ref mut t = x; t };
//^^ impl FnMut() -> &mut S //^^ impl FnMut() -> &'? mut S
let c3 = || { let t = x; t }; let c3 = || { let t = x; t };
//^^ impl FnOnce() -> S //^^ impl FnOnce() -> S
} }
@ -3074,11 +3074,11 @@ fn main() {
} }
"#, "#,
expect![[r#" expect![[r#"
104..108 'self': &Box<T> 104..108 'self': &'? Box<T>
188..192 'self': &Box<Foo<T>> 188..192 'self': &'a Box<Foo<T>>
218..220 '{}': &T 218..220 '{}': &'a T
242..246 'self': &Box<Foo<T>> 242..246 'self': &'a Box<Foo<T>>
275..277 '{}': &Foo<T> 275..277 '{}': &'a Foo<T>
297..301 'self': Box<Foo<T>> 297..301 'self': Box<Foo<T>>
322..324 '{}': Foo<T> 322..324 '{}': Foo<T>
338..559 '{ ...r(); }': () 338..559 '{ ...r(); }': ()
@ -3088,21 +3088,21 @@ fn main() {
360..363 'Foo': extern "rust-call" Foo<i32>(i32) -> Foo<i32> 360..363 'Foo': extern "rust-call" Foo<i32>(i32) -> Foo<i32>
360..370 'Foo(0_i32)': Foo<i32> 360..370 'Foo(0_i32)': Foo<i32>
364..369 '0_i32': i32 364..369 '0_i32': i32
382..386 'bad1': &i32 382..386 'bad1': &'? i32
389..394 'boxed': Box<Foo<i32>> 389..394 'boxed': Box<Foo<i32>>
389..406 'boxed....nner()': &i32 389..406 'boxed....nner()': &'? i32
416..421 'good1': &i32 416..421 'good1': &'? i32
424..438 'Foo::get_inner': fn get_inner<i32, '{error}>(&Box<Foo<i32>>) -> &i32 424..438 'Foo::get_inner': fn get_inner<i32, '?>(&'? Box<Foo<i32>>) -> &'? i32
424..446 'Foo::g...boxed)': &i32 424..446 'Foo::g...boxed)': &'? i32
439..445 '&boxed': &Box<Foo<i32>> 439..445 '&boxed': &'? Box<Foo<i32>>
440..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..469 'boxed': Box<Foo<i32>>
464..480 'boxed....self()': &Foo<i32> 464..480 'boxed....self()': &'? Foo<i32>
490..495 'good2': &Foo<i32> 490..495 'good2': &'? Foo<i32>
498..511 'Foo::get_self': fn get_self<i32, '{error}>(&Box<Foo<i32>>) -> &Foo<i32> 498..511 'Foo::get_self': fn get_self<i32, '?>(&'? Box<Foo<i32>>) -> &'? Foo<i32>
498..519 'Foo::g...boxed)': &Foo<i32> 498..519 'Foo::g...boxed)': &'? Foo<i32>
512..518 '&boxed': &Box<Foo<i32>> 512..518 '&boxed': &'? Box<Foo<i32>>
513..518 'boxed': Box<Foo<i32>> 513..518 'boxed': Box<Foo<i32>>
530..535 'inner': Foo<i32> 530..535 'inner': Foo<i32>
538..543 'boxed': Box<Foo<i32>> 538..543 'boxed': Box<Foo<i32>>
@ -3414,31 +3414,31 @@ struct TS(usize);
fn main() { fn main() {
let x; let x;
[x,] = &[1,]; [x,] = &[1,];
//^^^^expected &[i32; 1], got [{unknown}; _] //^^^^expected &'? [i32; 1], got [{unknown}; _]
let x; let x;
[(x,),] = &[(1,),]; [(x,),] = &[(1,),];
//^^^^^^^expected &[(i32,); 1], got [{unknown}; _] //^^^^^^^expected &'? [(i32,); 1], got [{unknown}; _]
let x; let x;
((x,),) = &((1,),); ((x,),) = &((1,),);
//^^^^^^^expected &((i32,),), got (({unknown},),) //^^^^^^^expected &'? ((i32,),), got (({unknown},),)
let x; let x;
(x,) = &(1,); (x,) = &(1,);
//^^^^expected &(i32,), got ({unknown},) //^^^^expected &'? (i32,), got ({unknown},)
let x; let x;
(S { a: x },) = &(S { a: 42 },); (S { a: x },) = &(S { a: 42 },);
//^^^^^^^^^^^^^expected &(S,), got (S,) //^^^^^^^^^^^^^expected &'? (S,), got (S,)
let x; let x;
S { a: x } = &S { a: 42 }; S { a: x } = &S { a: 42 };
//^^^^^^^^^^expected &S, got S //^^^^^^^^^^expected &'? S, got S
let x; let x;
TS(x) = &TS(42); TS(x) = &TS(42);
//^^^^^expected &TS, got TS //^^^^^expected &'? TS, got TS
} }
"#, "#,
); );
@ -3548,17 +3548,17 @@ fn f<T>(t: Ark<T>) {
} }
"#, "#,
expect![[r#" expect![[r#"
47..51 'self': &Ark<T> 47..51 'self': &'? Ark<T>
65..88 '{ ... }': *const T 65..88 '{ ... }': *const T
75..82 '&self.0': &T 75..82 '&self.0': &'? T
76..80 'self': &Ark<T> 76..80 'self': &'? Ark<T>
76..82 'self.0': T 76..82 'self.0': T
99..100 't': Ark<T> 99..100 't': Ark<T>
110..144 '{ ... (); }': () 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..128 'Ark::foo(&t)': *const T
116..141 'Ark::f...nst ()': *const () 116..141 'Ark::f...nst ()': *const ()
125..127 '&t': &Ark<T> 125..127 '&t': &'? Ark<T>
126..127 't': Ark<T> 126..127 't': Ark<T>
"#]], "#]],
); );
@ -3632,7 +3632,7 @@ pub struct CStr;
fn main() { fn main() {
c"ello"; c"ello";
//^^^^^^^ &CStr //^^^^^^^ &'static CStr
} }
"#, "#,
); );
@ -3659,7 +3659,25 @@ fn main() {
let are = "are"; let are = "are";
let count = 10; let count = 10;
builtin#format_args("hello {count:02} {} friends, we {are:?} {0}{last}", "fancy", last = "!"); 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
}
} }
"#, "#,
); );

View file

@ -238,6 +238,7 @@ fn infer_for_loop() {
//- minicore: iterator //- minicore: iterator
//- /main.rs crate:main deps:alloc //- /main.rs crate:main deps:alloc
#![no_std] #![no_std]
extern crate alloc;
use alloc::collections::Vec; use alloc::collections::Vec;
fn test() { fn test() {
@ -245,7 +246,7 @@ fn test() {
v.push("foo"); v.push("foo");
for x in v { for x in v {
x; x;
} //^ &str } //^ &'static str
} }
//- /alloc.rs crate:alloc //- /alloc.rs crate:alloc
@ -575,7 +576,7 @@ fn indexing_arrays() {
"fn main() { &mut [9][2]; }", "fn main() { &mut [9][2]; }",
expect![[r#" expect![[r#"
10..26 '{ &mut...[2]; }': () 10..26 '{ &mut...[2]; }': ()
12..23 '&mut [9][2]': &mut {unknown} 12..23 '&mut [9][2]': &'? mut {unknown}
17..20 '[9]': [i32; 1] 17..20 '[9]': [i32; 1]
17..23 '[9][2]': {unknown} 17..23 '[9][2]': {unknown}
18..19 '9': i32 18..19 '9': i32
@ -873,7 +874,7 @@ impl<U, T: Trait<U>> O<T> {
fn test(o: O<S>) { fn test(o: O<S>) {
o.foo(); o.foo();
} //^^^^^^^ &str } //^^^^^^^ &'? str
"#, "#,
); );
} }
@ -1016,15 +1017,15 @@ fn test(x: impl Trait<u64>, y: &impl Trait<u32>) {
z.foo2(); z.foo2();
}"#, }"#,
expect![[r#" expect![[r#"
29..33 'self': &Self 29..33 'self': &'? Self
54..58 'self': &Self 54..58 'self': &'? Self
77..78 'x': impl Trait<u16> 77..78 'x': impl Trait<u16>
97..99 '{}': () 97..99 '{}': ()
154..155 'x': impl Trait<u64> 154..155 'x': impl Trait<u64>
174..175 'y': &impl Trait<u32> 174..175 'y': &'? impl Trait<u32>
195..323 '{ ...2(); }': () 195..323 '{ ...2(); }': ()
201..202 'x': impl Trait<u64> 201..202 'x': impl Trait<u64>
208..209 'y': &impl Trait<u32> 208..209 'y': &'? impl Trait<u32>
219..220 'z': S<u16> 219..220 'z': S<u16>
223..224 'S': extern "rust-call" S<u16>(u16) -> S<u16> 223..224 'S': extern "rust-call" S<u16>(u16) -> S<u16>
223..227 'S(1)': 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> 237..238 'z': S<u16>
245..246 'x': impl Trait<u64> 245..246 'x': impl Trait<u64>
245..252 'x.foo()': u64 245..252 'x.foo()': u64
258..259 'y': &impl Trait<u32> 258..259 'y': &'? impl Trait<u32>
258..265 'y.foo()': u32 258..265 'y.foo()': u32
271..272 'z': S<u16> 271..272 'z': S<u16>
271..278 'z.foo()': u16 271..278 'z.foo()': u16
284..285 'x': impl Trait<u64> 284..285 'x': impl Trait<u64>
284..292 'x.foo2()': i64 284..292 'x.foo2()': i64
298..299 'y': &impl Trait<u32> 298..299 'y': &'? impl Trait<u32>
298..306 'y.foo2()': i64 298..306 'y.foo2()': i64
312..313 'z': S<u16> 312..313 'z': S<u16>
312..320 'z.foo2()': i64 312..320 'z.foo2()': i64
@ -1204,26 +1205,26 @@ fn test(x: impl Trait<u64>, y: &impl Trait<u64>) {
z.foo2(); z.foo2();
}"#, }"#,
expect![[r#" expect![[r#"
29..33 'self': &Self 29..33 'self': &'? Self
54..58 'self': &Self 54..58 'self': &'? Self
98..100 '{}': () 98..100 '{}': ()
110..111 'x': impl Trait<u64> 110..111 'x': impl Trait<u64>
130..131 'y': &impl Trait<u64> 130..131 'y': &'? impl Trait<u64>
151..268 '{ ...2(); }': () 151..268 '{ ...2(); }': ()
157..158 'x': impl Trait<u64> 157..158 'x': impl Trait<u64>
164..165 'y': &impl Trait<u64> 164..165 'y': &'? impl Trait<u64>
175..176 'z': impl Trait<u64> 175..176 'z': impl Trait<u64>
179..182 'bar': fn bar() -> impl Trait<u64> 179..182 'bar': fn bar() -> impl Trait<u64>
179..184 'bar()': impl Trait<u64> 179..184 'bar()': impl Trait<u64>
190..191 'x': impl Trait<u64> 190..191 'x': impl Trait<u64>
190..197 'x.foo()': u64 190..197 'x.foo()': u64
203..204 'y': &impl Trait<u64> 203..204 'y': &'? impl Trait<u64>
203..210 'y.foo()': u64 203..210 'y.foo()': u64
216..217 'z': impl Trait<u64> 216..217 'z': impl Trait<u64>
216..223 'z.foo()': u64 216..223 'z.foo()': u64
229..230 'x': impl Trait<u64> 229..230 'x': impl Trait<u64>
229..237 'x.foo2()': i64 229..237 'x.foo2()': i64
243..244 'y': &impl Trait<u64> 243..244 'y': &'? impl Trait<u64>
243..251 'y.foo2()': i64 243..251 'y.foo2()': i64
257..258 'z': impl Trait<u64> 257..258 'z': impl Trait<u64>
257..265 'z.foo2()': i64 257..265 'z.foo2()': i64
@ -1328,7 +1329,7 @@ fn test() {
a.foo(); a.foo();
}"#, }"#,
expect![[r#" expect![[r#"
29..33 'self': &Self 29..33 'self': &'? Self
71..82 '{ loop {} }': ! 71..82 '{ loop {} }': !
73..80 'loop {}': ! 73..80 'loop {}': !
78..80 '{}': () 78..80 '{}': ()
@ -1366,8 +1367,8 @@ fn test() {
d.foo(); d.foo();
}"#, }"#,
expect![[r#" expect![[r#"
49..53 'self': &mut Self 49..53 'self': &'? mut Self
101..105 'self': &Self 101..105 'self': &'? Self
184..195 '{ loop {} }': ({unknown}, {unknown}) 184..195 '{ loop {} }': ({unknown}, {unknown})
186..193 'loop {}': ! 186..193 'loop {}': !
191..193 '{}': () 191..193 '{}': ()
@ -1414,10 +1415,10 @@ fn foo<const C: u8, T>() -> (impl FnOnce(&str, T), impl Trait<u8>) {
} }
"#, "#,
expect![[r#" expect![[r#"
134..165 '{ ...(C)) }': (impl FnOnce(&str, T), Bar<u8>) 134..165 '{ ...(C)) }': (impl FnOnce(&'? str, T), Bar<u8>)
140..163 '(|inpu...ar(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) 141..154 '|input, t| {}': impl FnOnce(&'? str, T)
142..147 'input': &str 142..147 'input': &'? str
149..150 't': T 149..150 't': T
152..154 '{}': () 152..154 '{}': ()
156..159 'Bar': extern "rust-call" Bar<u8>(u8) -> Bar<u8> 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(); z.foo2();
}"#, }"#,
expect![[r#" expect![[r#"
29..33 'self': &Self 29..33 'self': &'? Self
54..58 'self': &Self 54..58 'self': &'? Self
97..99 '{}': dyn Trait<u64> 97..99 '{}': dyn Trait<u64>
109..110 'x': dyn Trait<u64> 109..110 'x': dyn Trait<u64>
128..129 'y': &dyn Trait<u64> 128..129 'y': &'? dyn Trait<u64>
148..265 '{ ...2(); }': () 148..265 '{ ...2(); }': ()
154..155 'x': dyn Trait<u64> 154..155 'x': dyn Trait<u64>
161..162 'y': &dyn Trait<u64> 161..162 'y': &'? dyn Trait<u64>
172..173 'z': dyn Trait<u64> 172..173 'z': dyn Trait<u64>
176..179 'bar': fn bar() -> dyn Trait<u64> 176..179 'bar': fn bar() -> dyn Trait<u64>
176..181 'bar()': dyn Trait<u64> 176..181 'bar()': dyn Trait<u64>
187..188 'x': dyn Trait<u64> 187..188 'x': dyn Trait<u64>
187..194 'x.foo()': u64 187..194 'x.foo()': u64
200..201 'y': &dyn Trait<u64> 200..201 'y': &'? dyn Trait<u64>
200..207 'y.foo()': u64 200..207 'y.foo()': u64
213..214 'z': dyn Trait<u64> 213..214 'z': dyn Trait<u64>
213..220 'z.foo()': u64 213..220 'z.foo()': u64
226..227 'x': dyn Trait<u64> 226..227 'x': dyn Trait<u64>
226..234 'x.foo2()': i64 226..234 'x.foo2()': i64
240..241 'y': &dyn Trait<u64> 240..241 'y': &'? dyn Trait<u64>
240..248 'y.foo2()': i64 240..248 'y.foo2()': i64
254..255 'z': dyn Trait<u64> 254..255 'z': dyn Trait<u64>
254..262 'z.foo2()': i64 254..262 'z.foo2()': i64
@ -1514,16 +1515,16 @@ fn test(s: S<u32, i32>) {
s.bar().baz(); s.bar().baz();
}"#, }"#,
expect![[r#" expect![[r#"
32..36 'self': &Self 32..36 'self': &'? Self
102..106 'self': &S<T, U> 102..106 'self': &'? S<T, U>
128..139 '{ loop {} }': &dyn Trait<T, U> 128..139 '{ loop {} }': &'? dyn Trait<T, U>
130..137 'loop {}': ! 130..137 'loop {}': !
135..137 '{}': () 135..137 '{}': ()
175..179 'self': &Self 175..179 'self': &'? Self
251..252 's': S<u32, i32> 251..252 's': S<u32, i32>
267..289 '{ ...z(); }': () 267..289 '{ ...z(); }': ()
273..274 's': S<u32, i32> 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) 273..286 's.bar().baz()': (u32, i32)
"#]], "#]],
); );
@ -1548,19 +1549,19 @@ fn test(x: Trait, y: &Trait) -> u64 {
z.foo(); z.foo();
}"#, }"#,
expect![[r#" expect![[r#"
26..30 'self': &Self 26..30 'self': &'? Self
60..62 '{}': dyn Trait 60..62 '{}': dyn Trait
72..73 'x': dyn Trait 72..73 'x': dyn Trait
82..83 'y': &dyn Trait 82..83 'y': &'? dyn Trait
100..175 '{ ...o(); }': u64 100..175 '{ ...o(); }': u64
106..107 'x': dyn Trait 106..107 'x': dyn Trait
113..114 'y': &dyn Trait 113..114 'y': &'? dyn Trait
124..125 'z': dyn Trait 124..125 'z': dyn Trait
128..131 'bar': fn bar() -> dyn Trait 128..131 'bar': fn bar() -> dyn Trait
128..133 'bar()': dyn Trait 128..133 'bar()': dyn Trait
139..140 'x': dyn Trait 139..140 'x': dyn Trait
139..146 'x.foo()': u64 139..146 'x.foo()': u64
152..153 'y': &dyn Trait 152..153 'y': &'? dyn Trait
152..159 'y.foo()': u64 152..159 'y.foo()': u64
165..166 'z': dyn Trait 165..166 'z': dyn Trait
165..172 'z.foo()': u64 165..172 'z.foo()': u64
@ -1580,14 +1581,14 @@ fn main() {
} }
"#, "#,
expect![[r#" expect![[r#"
31..35 'self': &S 31..35 'self': &'? S
37..39 '{}': () 37..39 '{}': ()
47..48 '_': &dyn Fn(S) 47..48 '_': &'? dyn Fn(S)
58..60 '{}': () 58..60 '{}': ()
71..105 '{ ...()); }': () 71..105 '{ ...()); }': ()
77..78 'f': fn f(&dyn Fn(S)) 77..78 'f': fn f(&'? dyn Fn(S))
77..102 'f(&|nu...foo())': () 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) 80..101 '|numbe....foo()': impl Fn(S)
81..87 'number': S 81..87 'number': S
89..95 'number': S 89..95 'number': S
@ -1790,7 +1791,7 @@ fn test<T: Trait1, U: Trait2>(x: T, y: U) {
y.foo(); y.foo();
}"#, }"#,
expect![[r#" expect![[r#"
53..57 'self': &Self 53..57 'self': &'? Self
66..68 '{}': u32 66..68 '{}': u32
185..186 'x': T 185..186 'x': T
191..192 'y': U 191..192 'y': U
@ -1819,11 +1820,11 @@ fn test(x: &impl Trait1) {
x.foo(); x.foo();
}"#, }"#,
expect![[r#" expect![[r#"
53..57 'self': &Self 53..57 'self': &'? Self
66..68 '{}': u32 66..68 '{}': u32
119..120 'x': &impl Trait1 119..120 'x': &'? impl Trait1
136..152 '{ ...o(); }': () 136..152 '{ ...o(); }': ()
142..143 'x': &impl Trait1 142..143 'x': &'? impl Trait1
142..149 'x.foo()': u32 142..149 'x.foo()': u32
"#]], "#]],
); );
@ -1934,8 +1935,8 @@ fn test() {
opt.map(f); opt.map(f);
}"#, }"#,
expect![[r#" expect![[r#"
28..32 'self': &Self 28..32 'self': &'? Self
132..136 'self': &Bar<F> 132..136 'self': &'? Bar<F>
149..160 '{ loop {} }': (A1, R) 149..160 '{ loop {} }': (A1, R)
151..158 'loop {}': ! 151..158 'loop {}': !
156..158 '{}': () 156..158 '{}': ()
@ -1988,7 +1989,7 @@ fn test() {
let r2 = lazy2.foo(); let r2 = lazy2.foo();
}"#, }"#,
expect![[r#" expect![[r#"
36..40 'self': &Foo 36..40 'self': &'? Foo
51..53 '{}': usize 51..53 '{}': usize
131..132 'f': F 131..132 'f': F
151..153 '{}': Lazy<T, F> 151..153 '{}': Lazy<T, F>
@ -2262,14 +2263,14 @@ impl Trait for S2 {
fn f(&self, x: <Self>::Item) { let y = x; } fn f(&self, x: <Self>::Item) { let y = x; }
}"#, }"#,
expect![[r#" expect![[r#"
40..44 'self': &Self 40..44 'self': &'? Self
46..47 'x': Trait::Item<Self> 46..47 'x': Trait::Item<Self>
126..130 'self': &S 126..130 'self': &'? S
132..133 'x': u32 132..133 'x': u32
147..161 '{ let y = x; }': () 147..161 '{ let y = x; }': ()
153..154 'y': u32 153..154 'y': u32
157..158 'x': u32 157..158 'x': u32
228..232 'self': &S2 228..232 'self': &'? S2
234..235 'x': i32 234..235 'x': i32
251..265 '{ let y = x; }': () 251..265 '{ let y = x; }': ()
257..258 'y': i32 257..258 'y': i32
@ -2643,12 +2644,12 @@ fn main() {
72..74 '_v': F 72..74 '_v': F
117..120 '{ }': () 117..120 '{ }': ()
132..163 '{ ... }); }': () 132..163 '{ ... }); }': ()
138..148 'f::<(), _>': fn f<(), impl FnOnce(&())>(impl FnOnce(&())) 138..148 'f::<(), _>': fn f<(), impl FnOnce(&'? ())>(impl FnOnce(&'? ()))
138..160 'f::<()... z; })': () 138..160 'f::<()... z; })': ()
149..159 '|z| { z; }': impl FnOnce(&()) 149..159 '|z| { z; }': impl FnOnce(&'? ())
150..151 'z': &() 150..151 'z': &'? ()
153..159 '{ z; }': () 153..159 '{ z; }': ()
155..156 'z': &() 155..156 'z': &'? ()
"#]], "#]],
); );
} }
@ -2897,13 +2898,13 @@ fn test(x: &dyn Foo) {
foo(x); foo(x);
}"#, }"#,
expect![[r#" expect![[r#"
21..22 'x': &dyn Foo 21..22 'x': &'? dyn Foo
34..36 '{}': () 34..36 '{}': ()
46..47 'x': &dyn Foo 46..47 'x': &'? dyn Foo
59..74 '{ foo(x); }': () 59..74 '{ foo(x); }': ()
65..68 'foo': fn foo(&dyn Foo) 65..68 'foo': fn foo(&'? dyn Foo)
65..71 'foo(x)': () 65..71 'foo(x)': ()
69..70 'x': &dyn Foo 69..70 'x': &'? dyn Foo
"#]], "#]],
); );
} }
@ -2927,7 +2928,7 @@ fn test() {
(IsCopy, NotCopy).test(); (IsCopy, NotCopy).test();
}"#, }"#,
expect![[r#" expect![[r#"
78..82 'self': &Self 78..82 'self': &'? Self
134..235 '{ ...t(); }': () 134..235 '{ ...t(); }': ()
140..146 'IsCopy': IsCopy 140..146 'IsCopy': IsCopy
140..153 'IsCopy.test()': bool 140..153 'IsCopy.test()': bool
@ -2969,7 +2970,7 @@ fn test() {
28..29 'T': {unknown} 28..29 'T': {unknown}
36..38 '{}': T 36..38 '{}': T
36..38: expected T, got () 36..38: expected T, got ()
113..117 'self': &Self 113..117 'self': &'? Self
169..249 '{ ...t(); }': () 169..249 '{ ...t(); }': ()
175..178 'foo': fn foo() 175..178 'foo': fn foo()
175..185 'foo.test()': bool 175..185 'foo.test()': bool
@ -2997,16 +2998,16 @@ fn test(f1: fn(), f2: fn(usize) -> u8, f3: fn(u8, u8) -> &u8) {
f3.test(); f3.test();
}"#, }"#,
expect![[r#" expect![[r#"
22..26 'self': &Self 22..26 'self': &'? Self
76..78 'f1': fn() 76..78 'f1': fn()
86..88 'f2': fn(usize) -> u8 86..88 'f2': fn(usize) -> u8
107..109 'f3': fn(u8, u8) -> &u8 107..109 'f3': fn(u8, u8) -> &'? u8
130..178 '{ ...t(); }': () 130..178 '{ ...t(); }': ()
136..138 'f1': fn() 136..138 'f1': fn()
136..145 'f1.test()': bool 136..145 'f1.test()': bool
151..153 'f2': fn(usize) -> u8 151..153 'f2': fn(usize) -> u8
151..160 'f2.test()': bool 151..160 'f2.test()': bool
166..168 'f3': fn(u8, u8) -> &u8 166..168 'f3': fn(u8, u8) -> &'? u8
166..175 'f3.test()': bool 166..175 'f3.test()': bool
"#]], "#]],
); );
@ -3027,13 +3028,13 @@ fn test() {
(1u8, *"foo").test(); // not Sized (1u8, *"foo").test(); // not Sized
}"#, }"#,
expect![[r#" expect![[r#"
22..26 'self': &Self 22..26 'self': &'? Self
79..194 '{ ...ized }': () 79..194 '{ ...ized }': ()
85..88 '1u8': u8 85..88 '1u8': u8
85..95 '1u8.test()': bool 85..95 '1u8.test()': bool
101..116 '(*"foo").test()': {unknown} 101..116 '(*"foo").test()': {unknown}
102..108 '*"foo"': str 102..108 '*"foo"': str
103..108 '"foo"': &str 103..108 '"foo"': &'static str
135..145 '(1u8, 1u8)': (u8, u8) 135..145 '(1u8, 1u8)': (u8, u8)
135..152 '(1u8, ...test()': bool 135..152 '(1u8, ...test()': bool
136..139 '1u8': u8 136..139 '1u8': u8
@ -3042,7 +3043,7 @@ fn test() {
158..178 '(1u8, ...test()': {unknown} 158..178 '(1u8, ...test()': {unknown}
159..162 '1u8': u8 159..162 '1u8': u8
164..170 '*"foo"': str 164..170 '*"foo"': str
165..170 '"foo"': &str 165..170 '"foo"': &'static str
"#]], "#]],
); );
} }
@ -3093,7 +3094,7 @@ fn foo() {
93..94 'x': Option<i32> 93..94 'x': Option<i32>
109..111 '{}': () 109..111 '{}': ()
117..124 '(&f)(s)': () 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>) 119..120 'f': impl Fn(Option<i32>)
122..123 's': Option<i32> 122..123 's': Option<i32>
"#]], "#]],
@ -3170,25 +3171,25 @@ fn foo() {
f(&s); f(&s);
}"#, }"#,
expect![[r#" expect![[r#"
154..158 'self': &Box<T> 154..158 'self': &'? Box<T>
166..205 '{ ... }': &T 166..205 '{ ... }': &'? T
176..199 'unsafe...nner }': &T 176..199 'unsafe...nner }': &'? T
185..197 '&*self.inner': &T 185..197 '&*self.inner': &'? T
186..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 187..197 'self.inner': *mut T
218..324 '{ ...&s); }': () 218..324 '{ ...&s); }': ()
228..229 's': Option<i32> 228..229 's': Option<i32>
232..236 'None': Option<i32> 232..236 'None': Option<i32>
246..247 'f': Box<dyn FnOnce(&Option<i32>)> 246..247 'f': Box<dyn FnOnce(&'? Option<i32>)>
281..310 'Box { ... {}) }': Box<dyn FnOnce(&Option<i32>)> 281..310 'Box { ... {}) }': Box<dyn FnOnce(&'? Option<i32>)>
294..308 '&mut (|ps| {})': &mut impl FnOnce(&Option<i32>) 294..308 '&mut (|ps| {})': &'? mut impl FnOnce(&'? Option<i32>)
300..307 '|ps| {}': impl FnOnce(&Option<i32>) 300..307 '|ps| {}': impl FnOnce(&'? Option<i32>)
301..303 'ps': &Option<i32> 301..303 'ps': &'? Option<i32>
305..307 '{}': () 305..307 '{}': ()
316..317 'f': Box<dyn FnOnce(&Option<i32>)> 316..317 'f': Box<dyn FnOnce(&'? Option<i32>)>
316..321 'f(&s)': () 316..321 'f(&s)': ()
318..320 '&s': &Option<i32> 318..320 '&s': &'? Option<i32>
319..320 's': Option<i32> 319..320 's': Option<i32>
"#]], "#]],
); );
@ -3320,7 +3321,7 @@ fn f() {
} }
}"#, }"#,
expect![[r#" expect![[r#"
46..50 'self': &Self 46..50 'self': &'? Self
58..63 '{ 0 }': u8 58..63 '{ 0 }': u8
60..61 '0': u8 60..61 '0': u8
115..185 '{ ... } }': () 115..185 '{ ... } }': ()
@ -3595,7 +3596,7 @@ fn take_u32(_: u32) {}
fn minimized() { fn minimized() {
let v = V::default(); let v = V::default();
let p = v.get(&0); let p = v.get(&0);
//^ &u32 //^ &'? u32
take_u32(42 + p); take_u32(42 + p);
} }
"#, "#,
@ -3625,7 +3626,7 @@ fn take_u32(_: u32) {}
fn minimized() { fn minimized() {
let v = V::default(); let v = V::default();
let p = v.get(); let p = v.get();
//^ &{unknown} //^ &'? {unknown}
take_u32(42 + p); take_u32(42 + p);
} }
"#, "#,
@ -3684,11 +3685,11 @@ fn main() {
} }
"#, "#,
expect![[r#" expect![[r#"
44..48 'self': &Self 44..48 'self': &'? Self
133..137 'self': &[u8; 4] 133..137 'self': &'? [u8; 4]
155..172 '{ ... }': usize 155..172 '{ ... }': usize
165..166 '2': usize 165..166 '2': usize
236..240 'self': &[u8; 2] 236..240 'self': &'? [u8; 2]
258..275 '{ ... }': u8 258..275 '{ ... }': u8
268..269 '2': u8 268..269 '2': u8
289..392 '{ ...g(); }': () 289..392 '{ ...g(); }': ()
@ -3732,11 +3733,11 @@ fn main() {
} }
"#, "#,
expect![[r#" expect![[r#"
44..48 'self': &Self 44..48 'self': &'? Self
151..155 'self': &[u8; L] 151..155 'self': &'? [u8; L]
173..194 '{ ... }': [u8; L] 173..194 '{ ... }': [u8; L]
183..188 '*self': [u8; L] 183..188 '*self': [u8; L]
184..188 'self': &[u8; L] 184..188 'self': &'? [u8; L]
208..260 '{ ...g(); }': () 208..260 '{ ...g(); }': ()
218..219 'v': [u8; 2] 218..219 'v': [u8; 2]
222..230 '[0u8; 2]': [u8; 2] 222..230 '[0u8; 2]': [u8; 2]
@ -4056,13 +4057,13 @@ fn g(t: &(dyn Sync + T2 + T1 + Send)) {
} }
"#, "#,
expect![[r#" expect![[r#"
68..69 't': &{unknown} 68..69 't': &'? {unknown}
101..103 '{}': () 101..103 '{}': ()
109..110 't': &{unknown} 109..110 't': &'? {unknown}
142..155 '{ f(t); }': () 142..155 '{ f(t); }': ()
148..149 'f': fn f(&{unknown}) 148..149 'f': fn f(&'? {unknown})
148..152 'f(t)': () 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 = ()>) {} fn f(t: &dyn Trait<T = (), T = ()>) {}
//^&{unknown} //^&'? {unknown}
"#, "#,
); );
} }
@ -4175,27 +4176,27 @@ trait Trait {
fn f<T>(v: impl Trait) { fn f<T>(v: impl Trait) {
let a = v.get::<i32>().deref(); let a = v.get::<i32>().deref();
//^ &i32 //^ &'? i32
let a = v.get::<T>().deref(); let a = v.get::<T>().deref();
//^ &T //^ &'? T
} }
fn g<'a, T: 'a>(v: impl Trait<Assoc<T> = &'a T>) { fn g<'a, T: 'a>(v: impl Trait<Assoc<T> = &'a T>) {
let a = v.get::<T>(); let a = v.get::<T>();
//^ &T //^ &'a T
let a = v.get::<()>(); 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>) { fn h<'a>(v: impl Trait<Assoc<i32> = &'a i32> + Trait<Assoc<i64> = &'a i64>) {
let a = v.get::<i32>(); let a = v.get::<i32>();
//^ &i32 //^ &'a i32
let a = v.get::<i64>(); let a = v.get::<i64>();
//^ &i64 //^ &'a i64
} }
fn i<'a>(v: impl Trait<Assoc<i32> = &'a i32, Assoc<i64> = &'a i64>) { fn i<'a>(v: impl Trait<Assoc<i32> = &'a i32, Assoc<i64> = &'a i64>) {
let a = v.get::<i32>(); let a = v.get::<i32>();
//^ &i32 //^ &'a i32
let a = v.get::<i64>(); let a = v.get::<i64>();
//^ &i64 //^ &'a i64
} }
"#, "#,
); );
@ -4221,12 +4222,12 @@ fn f<'a>(v: &dyn Trait<Assoc<i32> = &'a i32>) {
} }
"#, "#,
expect![[r#" expect![[r#"
90..94 'self': &Self 90..94 'self': &'? Self
127..128 'v': &(dyn Trait<Assoc<i32> = &i32>) 127..128 'v': &'? (dyn Trait<Assoc<i32> = &'a i32>)
164..195 '{ ...f(); }': () 164..195 '{ ...f(); }': ()
170..171 'v': &(dyn Trait<Assoc<i32> = &i32>) 170..171 'v': &'? (dyn Trait<Assoc<i32> = &'a i32>)
170..184 'v.get::<i32>()': &i32 170..184 'v.get::<i32>()': &'? i32
170..192 'v.get:...eref()': &i32 170..192 'v.get:...eref()': &'? i32
"#]], "#]],
); );
} }
@ -4487,19 +4488,19 @@ fn derive_macro_bounds() {
let x = (&Copy).clone(); let x = (&Copy).clone();
//^ Copy //^ Copy
let x = (&NotCopy).clone(); let x = (&NotCopy).clone();
//^ &NotCopy //^ &'? NotCopy
let x = (&Generic(Copy)).clone(); let x = (&Generic(Copy)).clone();
//^ Generic<Copy> //^ Generic<Copy>
let x = (&Generic(NotCopy)).clone(); let x = (&Generic(NotCopy)).clone();
//^ &Generic<NotCopy> //^ &'? Generic<NotCopy>
let x: &AssocGeneric<Copy> = &AssocGeneric(NotCopy); let x: &AssocGeneric<Copy> = &AssocGeneric(NotCopy);
let x = x.clone(); let x = x.clone();
//^ &AssocGeneric<Copy> //^ &'? AssocGeneric<Copy>
// let x: &AssocGeneric2<Copy> = &AssocGeneric2(NotCopy); // let x: &AssocGeneric2<Copy> = &AssocGeneric2(NotCopy);
// let x = x.clone(); // let x = x.clone();
let x: &AssocGeneric3<Copy> = &AssocGeneric3(Generic(NotCopy)); let x: &AssocGeneric3<Copy> = &AssocGeneric3(Generic(NotCopy));
let x = x.clone(); let x = x.clone();
//^ &AssocGeneric3<Copy> //^ &'? AssocGeneric3<Copy>
let x = (&R1(Vec())).clone(); let x = (&R1(Vec())).clone();
//^ R1 //^ R1
let x = (&R2(R1(Vec()))).clone(); let x = (&R2(R1(Vec()))).clone();
@ -4582,7 +4583,7 @@ impl B for u16 {
fn ttt() { fn ttt() {
let inp = Y; let inp = Y;
x::<u16>(&inp); x::<u16>(&inp);
//^^^^ expected &X, got &Y //^^^^ expected &'? X, got &'? Y
} }
"#, "#,
); );
@ -4629,7 +4630,7 @@ fn foo() {
let mut map = SomeMap; let mut map = SomeMap;
map["a"] = (); map["a"] = ();
map; 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
}
"#,
)
}

View file

@ -9,9 +9,11 @@ use hir_ty::{db::HirDatabase, diagnostics::BodyValidationDiagnostic, InferenceDi
use base_db::CrateId; use base_db::CrateId;
use cfg::{CfgExpr, CfgOptions}; use cfg::{CfgExpr, CfgOptions};
use either::Either; use either::Either;
pub use hir_def::VariantId;
use hir_def::{body::SyntheticSyntax, hir::ExprOrPatId, path::ModPath, AssocItemId, DefWithBodyId}; use hir_def::{body::SyntheticSyntax, hir::ExprOrPatId, path::ModPath, AssocItemId, DefWithBodyId};
use hir_expand::{name::Name, HirFileId, InFile}; use hir_expand::{name::Name, HirFileId, InFile};
use syntax::{ast, AstPtr, SyntaxError, SyntaxNodePtr, TextRange}; use syntax::{ast, AstPtr, SyntaxError, SyntaxNodePtr, TextRange};
use triomphe::Arc;
use crate::{AssocItem, Field, Local, MacroKind, Trait, Type}; use crate::{AssocItem, Field, Local, MacroKind, Trait, Type};
@ -171,7 +173,7 @@ pub struct MacroError {
pub struct MacroExpansionParseError { pub struct MacroExpansionParseError {
pub node: InFile<SyntaxNodePtr>, pub node: InFile<SyntaxNodePtr>,
pub precise_location: Option<TextRange>, pub precise_location: Option<TextRange>,
pub errors: Box<[SyntaxError]>, pub errors: Arc<[SyntaxError]>,
} }
#[derive(Debug, Clone, Eq, PartialEq)] #[derive(Debug, Clone, Eq, PartialEq)]
@ -200,6 +202,7 @@ pub struct MalformedDerive {
pub struct NoSuchField { pub struct NoSuchField {
pub field: InFile<AstPtr<Either<ast::RecordExprField, ast::RecordPatField>>>, pub field: InFile<AstPtr<Either<ast::RecordExprField, ast::RecordPatField>>>,
pub private: bool, pub private: bool,
pub variant: VariantId,
} }
#[derive(Debug)] #[derive(Debug)]
@ -525,7 +528,7 @@ impl AnyDiagnostic {
source_map.pat_syntax(pat).inspect_err(|_| tracing::error!("synthetic syntax")).ok() source_map.pat_syntax(pat).inspect_err(|_| tracing::error!("synthetic syntax")).ok()
}; };
Some(match d { Some(match d {
&InferenceDiagnostic::NoSuchField { field: expr, private } => { &InferenceDiagnostic::NoSuchField { field: expr, private, variant } => {
let expr_or_pat = match expr { let expr_or_pat = match expr {
ExprOrPatId::ExprId(expr) => { ExprOrPatId::ExprId(expr) => {
source_map.field_syntax(expr).map(AstPtr::wrap_left) 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) 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 } => { &InferenceDiagnostic::MismatchedArgCount { call_expr, expected, found } => {
MismatchedArgCount { call_expr: expr_syntax(call_expr)?, expected, found }.into() MismatchedArgCount { call_expr: expr_syntax(call_expr)?, expected, found }.into()

View file

@ -188,28 +188,7 @@ impl HirDisplay for Struct {
StructKind::Record => { StructKind::Record => {
let has_where_clause = write_where_clause(def_id, f)?; let has_where_clause = write_where_clause(def_id, f)?;
if let Some(limit) = f.entity_limit { if let Some(limit) = f.entity_limit {
let fields = self.fields(f.db); display_fields(&self.fields(f.db), has_where_clause, limit, false, f)?;
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("}")?;
}
} }
} }
StructKind::Unit => _ = write_where_clause(def_id, 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()))?; write!(f, "{}", self.name(f.db).display(f.db.upcast()))?;
let def_id = GenericDefId::AdtId(AdtId::EnumId(self.id)); let def_id = GenericDefId::AdtId(AdtId::EnumId(self.id));
write_generic_params(def_id, f)?; write_generic_params(def_id, f)?;
let has_where_clause = write_where_clause(def_id, f)?;
let variants = self.variants(f.db); let has_where_clause = write_where_clause(def_id, f)?;
if !variants.is_empty() { if let Some(limit) = f.entity_limit {
f.write_char(if !has_where_clause { ' ' } else { '\n' })?; display_variants(&self.variants(f.db), has_where_clause, limit, f)?;
f.write_str("{\n")?;
for variant in variants {
f.write_str(" ")?;
variant.hir_fmt(f)?;
f.write_str(",\n")?;
}
f.write_str("}")?;
} }
Ok(()) Ok(())
@ -251,24 +222,104 @@ impl HirDisplay for Union {
write!(f, "{}", self.name(f.db).display(f.db.upcast()))?; write!(f, "{}", self.name(f.db).display(f.db.upcast()))?;
let def_id = GenericDefId::AdtId(AdtId::UnionId(self.id)); let def_id = GenericDefId::AdtId(AdtId::UnionId(self.id));
write_generic_params(def_id, f)?; write_generic_params(def_id, f)?;
let has_where_clause = write_where_clause(def_id, f)?; let has_where_clause = write_where_clause(def_id, f)?;
if let Some(limit) = f.entity_limit {
let fields = self.fields(f.db); display_fields(&self.fields(f.db), has_where_clause, limit, false, f)?;
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("}")?;
} }
Ok(()) 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 { impl HirDisplay for Field {
fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> { fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
write_visibility(self.parent.module(f.db).id, self.visibility(f.db), f)?; write_visibility(self.parent.module(f.db).id, self.visibility(f.db), f)?;
@ -304,21 +355,10 @@ impl HirDisplay for Variant {
} }
f.write_char(')')?; f.write_char(')')?;
} }
VariantData::Record(fields) => { VariantData::Record(_) => {
f.write_str(" {")?; if let Some(limit) = f.entity_limit {
let mut first = true; display_fields(&self.fields(f.db), false, limit, true, f)?;
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)?;
} }
f.write_str(" }")?;
} }
} }
Ok(()) Ok(())

View file

@ -59,7 +59,9 @@ use hir_def::{
ModuleId, StaticId, StructId, TraitAliasId, TraitId, TupleId, TypeAliasId, TypeOrConstParamId, ModuleId, StaticId, StructId, TraitAliasId, TraitId, TupleId, TypeAliasId, TypeOrConstParamId,
TypeParamId, UnionId, 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::{ use hir_ty::{
all_super_traits, autoderef, check_orphan_rules, all_super_traits, autoderef, check_orphan_rules,
consteval::{try_const_usize, unknown_const_as_generic, ConstExt}, consteval::{try_const_usize, unknown_const_as_generic, ConstExt},
@ -79,7 +81,7 @@ use hir_ty::{
use itertools::Itertools; use itertools::Itertools;
use nameres::diagnostics::DefDiagnosticKind; use nameres::diagnostics::DefDiagnosticKind;
use rustc_hash::FxHashSet; use rustc_hash::FxHashSet;
use span::Edition; use span::{Edition, MacroCallId};
use stdx::{impl_from, never}; use stdx::{impl_from, never};
use syntax::{ use syntax::{
ast::{self, HasAttrs as _, HasName}, ast::{self, HasAttrs as _, HasName},
@ -559,6 +561,12 @@ impl Module {
emit_def_diagnostic(db, acc, diag); 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) { for def in self.declarations(db) {
match def { match def {
ModuleDef::Module(m) => { ModuleDef::Module(m) => {
@ -577,6 +585,10 @@ impl Module {
item.diagnostics(db, acc, style_lints); 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)) acc.extend(def.diagnostics(db, style_lints))
} }
ModuleDef::Adt(adt) => { 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 // FIXME: Once we diagnose the inputs to builtin derives, we should at least extract those diagnostics somehow
continue; 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); let ast_id_map = db.ast_id_map(file_id);
for diag in db.impl_data_with_diagnostics(impl_def.id).1.iter() { 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) { fn emit_macro_def_diagnostics(db: &dyn HirDatabase, acc: &mut Vec<AnyDiagnostic>, m: Macro) {
let id = db.macro_def(m.id); let id = db.macro_def(m.id);
if let hir_expand::db::TokenExpander::DeclarativeMacro(expander) = db.macro_expander(id) { if let hir_expand::db::TokenExpander::DeclarativeMacro(expander) = db.macro_expander(id) {
@ -888,16 +936,6 @@ fn emit_def_diagnostic_(
.into(), .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 } => { DefDiagnosticKind::UnimplementedBuiltinMacro { ast } => {
let node = ast.to_node(db.upcast()); let node = ast.to_node(db.upcast());
// Must have a name, otherwise we wouldn't emit it. // Must have a name, otherwise we wouldn't emit it.
@ -1489,6 +1527,14 @@ impl Adt {
.map(|arena| arena.1.clone()) .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> { pub fn as_enum(&self) -> Option<Enum> {
if let Self::Enum(v) = self { if let Self::Enum(v) = self {
Some(*v) Some(*v)
@ -1636,6 +1682,10 @@ impl DefWithBody {
Module { id: def_map.module_id(DefMap::ROOT) }.diagnostics(db, acc, style_lints); 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() { for diag in source_map.diagnostics() {
acc.push(match diag { acc.push(match diag {
BodyDiagnostic::InactiveCode { node, cfg, opts } => { BodyDiagnostic::InactiveCode { node, cfg, opts } => {
@ -2437,6 +2487,14 @@ impl Trait {
.filter(|(_, ty)| !count_required_only || !ty.has_default()) .filter(|(_, ty)| !count_required_only || !ty.has_default())
.count() .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 { 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)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct BuiltinType { pub struct BuiltinType {
pub(crate) inner: hir_def::builtin_type::BuiltinType, pub(crate) inner: hir_def::builtin_type::BuiltinType,
@ -2535,6 +2602,20 @@ impl BuiltinType {
matches!(self.inner, hir_def::builtin_type::BuiltinType::Float(_)) 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 { pub fn is_char(&self) -> bool {
matches!(self.inner, hir_def::builtin_type::BuiltinType::Char) 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 { pub fn check_orphan_rules(self, db: &dyn HirDatabase) -> bool {
check_orphan_rules(db, self.id) 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)] #[derive(Clone, PartialEq, Eq, Debug, Hash)]
@ -4495,7 +4584,8 @@ impl Type {
name: Option<&Name>, name: Option<&Name>,
mut callback: impl FnMut(Function) -> Option<T>, mut callback: impl FnMut(Function) -> Option<T>,
) -> 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; let mut slot = None;
self.iterate_method_candidates_dyn( self.iterate_method_candidates_dyn(

View file

@ -131,7 +131,7 @@ pub struct SemanticsImpl<'db> {
pub db: &'db dyn HirDatabase, pub db: &'db dyn HirDatabase,
s2d_cache: RefCell<SourceToDefCache>, s2d_cache: RefCell<SourceToDefCache>,
/// Rootnode to HirFileId cache /// 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 // 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 // So we might wanna move them out into something specific for semantic highlighting
expansion_info_cache: RefCell<FxHashMap<MacroFileId, ExpansionInfo>>, expansion_info_cache: RefCell<FxHashMap<MacroFileId, ExpansionInfo>>,
@ -294,7 +294,7 @@ impl<'db> SemanticsImpl<'db> {
SemanticsImpl { SemanticsImpl {
db, db,
s2d_cache: Default::default(), s2d_cache: Default::default(),
cache: Default::default(), root_to_file_cache: Default::default(),
expansion_info_cache: Default::default(), expansion_info_cache: Default::default(),
macro_call_cache: Default::default(), macro_call_cache: Default::default(),
} }
@ -690,6 +690,7 @@ impl<'db> SemanticsImpl<'db> {
exp_info exp_info
}); });
// FIXME: uncached parse
// Create the source analyzer for the macro call scope // Create the source analyzer for the macro call scope
let Some(sa) = self.analyze_no_infer(&self.parse_or_expand(expansion_info.call_file())) let Some(sa) = self.analyze_no_infer(&self.parse_or_expand(expansion_info.call_file()))
else { else {
@ -722,7 +723,7 @@ impl<'db> SemanticsImpl<'db> {
mut token: SyntaxToken, mut token: SyntaxToken,
f: &mut dyn FnMut(InFile<SyntaxToken>) -> ControlFlow<()>, 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) = let (sa, span, file_id) =
match token.parent().and_then(|parent| self.analyze_no_infer(&parent)) { match token.parent().and_then(|parent| self.analyze_no_infer(&parent)) {
Some(sa) => match sa.file_id.file_id() { Some(sa) => match sa.file_id.file_id() {
@ -1025,6 +1026,7 @@ impl<'db> SemanticsImpl<'db> {
None => { None => {
let call_node = file_id.macro_file()?.call_node(db); let call_node = file_id.macro_file()?.call_node(db);
// cache the node // cache the node
// FIXME: uncached parse
self.parse_or_expand(call_node.file_id); self.parse_or_expand(call_node.file_id);
Some(call_node) Some(call_node)
} }
@ -1370,7 +1372,7 @@ impl<'db> SemanticsImpl<'db> {
offset: Option<TextSize>, offset: Option<TextSize>,
infer_body: bool, infer_body: bool,
) -> Option<SourceAnalyzer> { ) -> 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 node = self.find_file(node);
let container = self.with_ctx(|ctx| ctx.find_container(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) { fn cache(&self, root_node: SyntaxNode, file_id: HirFileId) {
assert!(root_node.parent().is_none()); 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); let prev = cache.insert(root_node, file_id);
assert!(prev.is_none() || prev == Some(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> { 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() cache.get(root_node).copied()
} }
@ -1427,7 +1429,7 @@ impl<'db> SemanticsImpl<'db> {
known nodes: {}\n\n", known nodes: {}\n\n",
node, node,
root_node, root_node,
self.cache self.root_to_file_cache
.borrow() .borrow()
.keys() .keys()
.map(|it| format!("{it:?}")) .map(|it| format!("{it:?}"))

View file

@ -118,10 +118,10 @@ pub(super) struct SourceToDefCtx<'a, 'b> {
impl SourceToDefCtx<'_, '_> { impl SourceToDefCtx<'_, '_> {
pub(super) fn file_to_def(&self, file: FileId) -> SmallVec<[ModuleId; 1]> { 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(); let mut mods = SmallVec::new();
for &crate_id in self.db.relevant_crates(file).iter() { 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); let crate_def_map = self.db.crate_def_map(crate_id);
mods.extend( mods.extend(
crate_def_map crate_def_map
@ -129,6 +129,9 @@ impl SourceToDefCtx<'_, '_> {
.map(|local_id| crate_def_map.module_id(local_id)), .map(|local_id| crate_def_map.module_id(local_id)),
) )
} }
if mods.is_empty() {
// FIXME: detached file
}
mods mods
} }

View file

@ -28,7 +28,7 @@ use hir_expand::{
mod_path::path, mod_path::path,
name, name,
name::{AsName, Name}, name::{AsName, Name},
HirFileId, InFile, MacroFileId, MacroFileIdExt, HirFileId, InFile, InMacroFile, MacroFileId, MacroFileIdExt,
}; };
use hir_ty::{ use hir_ty::{
diagnostics::{ diagnostics::{
@ -118,7 +118,7 @@ impl SourceAnalyzer {
fn expr_id(&self, db: &dyn HirDatabase, expr: &ast::Expr) -> Option<ExprId> { fn expr_id(&self, db: &dyn HirDatabase, expr: &ast::Expr) -> Option<ExprId> {
let src = match expr { let src = match expr {
ast::Expr::MacroExpr(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()), _ => InFile::new(self.file_id, expr.clone()),
}; };
@ -145,20 +145,20 @@ impl SourceAnalyzer {
&self, &self,
db: &dyn HirDatabase, db: &dyn HirDatabase,
expr: InFile<ast::MacroCall>, 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 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()) { let res = if let Some(stmts) = ast::MacroStmts::cast(expanded.clone()) {
match stmts.expr()? { match stmts.expr()? {
ast::Expr::MacroExpr(mac) => { 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()) { } 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 { } else {
InFile::new(macro_file, ast::Expr::cast(expanded)?) InMacroFile::new(macro_file, ast::Expr::cast(expanded)?)
}; };
Some(res) Some(res)

View file

@ -127,6 +127,13 @@ impl LookupTable {
self.types_wishlist.insert(ty.clone()); 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 res
} }
@ -158,6 +165,13 @@ impl LookupTable {
self.types_wishlist.insert(ty.clone()); 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 res
} }
@ -255,13 +269,13 @@ pub struct TermSearchConfig {
pub enable_borrowcheck: bool, pub enable_borrowcheck: bool,
/// Indicate when to squash multiple trees to `Many` as there are too many to keep track /// Indicate when to squash multiple trees to `Many` as there are too many to keep track
pub many_alternatives_threshold: usize, pub many_alternatives_threshold: usize,
/// Depth of the search eg. number of cycles to run /// Fuel for term search in "units of work"
pub depth: usize, pub fuel: u64,
} }
impl Default for TermSearchConfig { impl Default for TermSearchConfig {
fn default() -> Self { 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 /// 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 /// type (return type). Other transformations include methods on type, type constructors and
/// projections to struct fields (field access). /// 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 /// 3. If we run out of fuel (term search takes too long) we stop iterating.
/// if we can find more paths that take us to the `goal` type.
/// 4. Return all the paths (type trees) that take us to the `goal` type. /// 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 /// 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 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 // Try trivial tactic first, also populates lookup table
let mut solutions: Vec<Expr> = tactics::trivial(ctx, &defs, &mut lookup).collect(); 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 // Use well known types tactic before iterations as it does not depend on other tactics
solutions.extend(tactics::famous_types(ctx, &defs, &mut lookup)); solutions.extend(tactics::famous_types(ctx, &defs, &mut lookup));
for _ in 0..ctx.config.depth { while should_continue() {
lookup.new_round(); lookup.new_round();
solutions.extend(tactics::type_constructor(ctx, &defs, &mut lookup)); solutions.extend(tactics::type_constructor(ctx, &defs, &mut lookup, should_continue));
solutions.extend(tactics::free_function(ctx, &defs, &mut lookup)); solutions.extend(tactics::free_function(ctx, &defs, &mut lookup, should_continue));
solutions.extend(tactics::impl_method(ctx, &defs, &mut lookup)); solutions.extend(tactics::impl_method(ctx, &defs, &mut lookup, should_continue));
solutions.extend(tactics::struct_projection(ctx, &defs, &mut lookup)); solutions.extend(tactics::struct_projection(ctx, &defs, &mut lookup, should_continue));
solutions.extend(tactics::impl_static_method(ctx, &defs, &mut lookup)); solutions.extend(tactics::impl_static_method(ctx, &defs, &mut lookup, should_continue));
solutions.extend(tactics::make_tuple(ctx, &defs, &mut lookup)); solutions.extend(tactics::make_tuple(ctx, &defs, &mut lookup, should_continue));
// Discard not interesting `ScopeDef`s for speedup // Discard not interesting `ScopeDef`s for speedup
for def in lookup.exhausted_scopedefs() { for def in lookup.exhausted_scopedefs() {

View file

@ -211,13 +211,13 @@ impl Expr {
} }
} }
Expr::Method { func, target, params, .. } => { 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))); return Ok(many_formatter(&target.ty(db)));
} }
let func_name = func.name(db).display(db.upcast()).to_string(); let func_name = func.name(db).display(db.upcast()).to_string();
let self_param = func.self_param(db).unwrap(); let self_param = func.self_param(db).unwrap();
let target = target.gen_source_code( let target_str = target.gen_source_code(
sema_scope, sema_scope,
many_formatter, many_formatter,
prefer_no_std, prefer_no_std,
@ -236,9 +236,12 @@ impl Expr {
Some(trait_) => { Some(trait_) => {
let trait_name = mod_item_path_str(sema_scope, &ModuleDef::Trait(trait_))?; let trait_name = mod_item_path_str(sema_scope, &ModuleDef::Trait(trait_))?;
let target = match self_param.access(db) { let target = match self_param.access(db) {
crate::Access::Shared => format!("&{target}"), crate::Access::Shared if !target.is_many() => format!("&{target_str}"),
crate::Access::Exclusive => format!("&mut {target}"), crate::Access::Exclusive if !target.is_many() => {
crate::Access::Owned => target, format!("&mut {target_str}")
}
crate::Access::Owned => target_str,
_ => many_formatter(&target.ty(db)),
}; };
let res = match args.is_empty() { let res = match args.is_empty() {
true => format!("{trait_name}::{func_name}({target})",), true => format!("{trait_name}::{func_name}({target})",),
@ -246,7 +249,7 @@ impl Expr {
}; };
Ok(res) Ok(res)
} }
None => Ok(format!("{target}.{func_name}({args})")), None => Ok(format!("{target_str}.{func_name}({args})")),
} }
} }
Expr::Variant { variant, generics, params } => { Expr::Variant { variant, generics, params } => {
@ -381,7 +384,7 @@ impl Expr {
Ok(res) Ok(res)
} }
Expr::Field { expr, field } => { 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))); return Ok(many_formatter(&expr.ty(db)));
} }
@ -395,7 +398,7 @@ impl Expr {
Ok(format!("{strukt}.{field}")) Ok(format!("{strukt}.{field}"))
} }
Expr::Reference(expr) => { 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))); return Ok(many_formatter(&expr.ty(db)));
} }
@ -466,10 +469,15 @@ impl Expr {
/// macro!().bar() /// macro!().bar()
/// &macro!() /// &macro!()
/// ``` /// ```
fn contains_many_in_illegal_pos(&self) -> bool { fn contains_many_in_illegal_pos(&self, db: &dyn HirDatabase) -> bool {
match self { match self {
Expr::Method { target, .. } => target.contains_many_in_illegal_pos(), Expr::Method { target, func, .. } => {
Expr::Field { expr, .. } => expr.contains_many_in_illegal_pos(), 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::Reference(target) => target.is_many(),
Expr::Many(_) => true, Expr::Many(_) => true,
_ => false, _ => false,

View file

@ -4,6 +4,7 @@
//! * `ctx` - Context for the term search //! * `ctx` - Context for the term search
//! * `defs` - Set of items in scope at term search target location //! * `defs` - Set of items in scope at term search target location
//! * `lookup` - Lookup table for types //! * `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. //! And they return iterator that yields type trees that unify with the `goal` type.
use std::iter; use std::iter;
@ -97,16 +98,19 @@ pub(super) fn trivial<'a, DB: HirDatabase>(
/// * `ctx` - Context for the term search /// * `ctx` - Context for the term search
/// * `defs` - Set of items in scope at term search target location /// * `defs` - Set of items in scope at term search target location
/// * `lookup` - Lookup table for types /// * `lookup` - Lookup table for types
/// * `should_continue` - Function that indicates when to stop iterating
pub(super) fn type_constructor<'a, DB: HirDatabase>( pub(super) fn type_constructor<'a, DB: HirDatabase>(
ctx: &'a TermSearchCtx<'a, DB>, ctx: &'a TermSearchCtx<'a, DB>,
defs: &'a FxHashSet<ScopeDef>, defs: &'a FxHashSet<ScopeDef>,
lookup: &'a mut LookupTable, lookup: &'a mut LookupTable,
should_continue: &'a dyn std::ops::Fn() -> bool,
) -> impl Iterator<Item = Expr> + 'a { ) -> impl Iterator<Item = Expr> + 'a {
let db = ctx.sema.db; let db = ctx.sema.db;
let module = ctx.scope.module(); let module = ctx.scope.module();
fn variant_helper( fn variant_helper(
db: &dyn HirDatabase, db: &dyn HirDatabase,
lookup: &mut LookupTable, lookup: &mut LookupTable,
should_continue: &dyn std::ops::Fn() -> bool,
parent_enum: Enum, parent_enum: Enum,
variant: Variant, variant: Variant,
config: &TermSearchConfig, 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())); .chain((non_default_type_params_len == 0).then_some(Vec::new()));
generic_params generic_params
.filter(|_| should_continue())
.filter_map(move |generics| { .filter_map(move |generics| {
// Insert default type params // Insert default type params
let mut g = generics.into_iter(); let mut g = generics.into_iter();
@ -194,8 +199,14 @@ pub(super) fn type_constructor<'a, DB: HirDatabase>(
defs.iter() defs.iter()
.filter_map(move |def| match def { .filter_map(move |def| match def {
ScopeDef::ModuleDef(ModuleDef::Variant(it)) => { ScopeDef::ModuleDef(ModuleDef::Variant(it)) => {
let variant_exprs = let variant_exprs = variant_helper(
variant_helper(db, lookup, it.parent_enum(db), *it, &ctx.config); db,
lookup,
should_continue,
it.parent_enum(db),
*it,
&ctx.config,
);
if variant_exprs.is_empty() { if variant_exprs.is_empty() {
return None; return None;
} }
@ -213,7 +224,9 @@ pub(super) fn type_constructor<'a, DB: HirDatabase>(
let exprs: Vec<(Type, Vec<Expr>)> = enum_ let exprs: Vec<(Type, Vec<Expr>)> = enum_
.variants(db) .variants(db)
.into_iter() .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(); .collect();
if exprs.is_empty() { 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())); .chain((non_default_type_params_len == 0).then_some(Vec::new()));
let exprs = generic_params let exprs = generic_params
.filter(|_| should_continue())
.filter_map(|generics| { .filter_map(|generics| {
// Insert default type params // Insert default type params
let mut g = generics.into_iter(); let mut g = generics.into_iter();
@ -345,10 +359,12 @@ pub(super) fn type_constructor<'a, DB: HirDatabase>(
/// * `ctx` - Context for the term search /// * `ctx` - Context for the term search
/// * `defs` - Set of items in scope at term search target location /// * `defs` - Set of items in scope at term search target location
/// * `lookup` - Lookup table for types /// * `lookup` - Lookup table for types
/// * `should_continue` - Function that indicates when to stop iterating
pub(super) fn free_function<'a, DB: HirDatabase>( pub(super) fn free_function<'a, DB: HirDatabase>(
ctx: &'a TermSearchCtx<'a, DB>, ctx: &'a TermSearchCtx<'a, DB>,
defs: &'a FxHashSet<ScopeDef>, defs: &'a FxHashSet<ScopeDef>,
lookup: &'a mut LookupTable, lookup: &'a mut LookupTable,
should_continue: &'a dyn std::ops::Fn() -> bool,
) -> impl Iterator<Item = Expr> + 'a { ) -> impl Iterator<Item = Expr> + 'a {
let db = ctx.sema.db; let db = ctx.sema.db;
let module = ctx.scope.module(); let module = ctx.scope.module();
@ -390,6 +406,7 @@ pub(super) fn free_function<'a, DB: HirDatabase>(
.permutations(non_default_type_params_len); .permutations(non_default_type_params_len);
let exprs: Vec<_> = generic_params let exprs: Vec<_> = generic_params
.filter(|_| should_continue())
.filter_map(|generics| { .filter_map(|generics| {
// Insert default type params // Insert default type params
let mut g = generics.into_iter(); let mut g = generics.into_iter();
@ -474,10 +491,12 @@ pub(super) fn free_function<'a, DB: HirDatabase>(
/// * `ctx` - Context for the term search /// * `ctx` - Context for the term search
/// * `defs` - Set of items in scope at term search target location /// * `defs` - Set of items in scope at term search target location
/// * `lookup` - Lookup table for types /// * `lookup` - Lookup table for types
/// * `should_continue` - Function that indicates when to stop iterating
pub(super) fn impl_method<'a, DB: HirDatabase>( pub(super) fn impl_method<'a, DB: HirDatabase>(
ctx: &'a TermSearchCtx<'a, DB>, ctx: &'a TermSearchCtx<'a, DB>,
_defs: &'a FxHashSet<ScopeDef>, _defs: &'a FxHashSet<ScopeDef>,
lookup: &'a mut LookupTable, lookup: &'a mut LookupTable,
should_continue: &'a dyn std::ops::Fn() -> bool,
) -> impl Iterator<Item = Expr> + 'a { ) -> impl Iterator<Item = Expr> + 'a {
let db = ctx.sema.db; let db = ctx.sema.db;
let module = ctx.scope.module(); let module = ctx.scope.module();
@ -554,6 +573,7 @@ pub(super) fn impl_method<'a, DB: HirDatabase>(
.permutations(non_default_fn_type_params_len); .permutations(non_default_fn_type_params_len);
let exprs: Vec<_> = generic_params let exprs: Vec<_> = generic_params
.filter(|_| should_continue())
.filter_map(|generics| { .filter_map(|generics| {
// Insert default type params // Insert default type params
let mut g = generics.into_iter(); let mut g = generics.into_iter();
@ -645,10 +665,12 @@ pub(super) fn impl_method<'a, DB: HirDatabase>(
/// * `ctx` - Context for the term search /// * `ctx` - Context for the term search
/// * `defs` - Set of items in scope at term search target location /// * `defs` - Set of items in scope at term search target location
/// * `lookup` - Lookup table for types /// * `lookup` - Lookup table for types
/// * `should_continue` - Function that indicates when to stop iterating
pub(super) fn struct_projection<'a, DB: HirDatabase>( pub(super) fn struct_projection<'a, DB: HirDatabase>(
ctx: &'a TermSearchCtx<'a, DB>, ctx: &'a TermSearchCtx<'a, DB>,
_defs: &'a FxHashSet<ScopeDef>, _defs: &'a FxHashSet<ScopeDef>,
lookup: &'a mut LookupTable, lookup: &'a mut LookupTable,
should_continue: &'a dyn std::ops::Fn() -> bool,
) -> impl Iterator<Item = Expr> + 'a { ) -> impl Iterator<Item = Expr> + 'a {
let db = ctx.sema.db; let db = ctx.sema.db;
let module = ctx.scope.module(); let module = ctx.scope.module();
@ -656,6 +678,7 @@ pub(super) fn struct_projection<'a, DB: HirDatabase>(
.new_types(NewTypesKey::StructProjection) .new_types(NewTypesKey::StructProjection)
.into_iter() .into_iter()
.map(|ty| (ty.clone(), lookup.find(db, &ty).expect("Expr not in lookup"))) .map(|ty| (ty.clone(), lookup.find(db, &ty).expect("Expr not in lookup")))
.filter(|_| should_continue())
.flat_map(move |(ty, targets)| { .flat_map(move |(ty, targets)| {
ty.fields(db).into_iter().filter_map(move |(field, filed_ty)| { ty.fields(db).into_iter().filter_map(move |(field, filed_ty)| {
if !field.is_visible_from(db, module) { 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 /// * `ctx` - Context for the term search
/// * `defs` - Set of items in scope at term search target location /// * `defs` - Set of items in scope at term search target location
/// * `lookup` - Lookup table for types /// * `lookup` - Lookup table for types
/// * `should_continue` - Function that indicates when to stop iterating
pub(super) fn impl_static_method<'a, DB: HirDatabase>( pub(super) fn impl_static_method<'a, DB: HirDatabase>(
ctx: &'a TermSearchCtx<'a, DB>, ctx: &'a TermSearchCtx<'a, DB>,
_defs: &'a FxHashSet<ScopeDef>, _defs: &'a FxHashSet<ScopeDef>,
lookup: &'a mut LookupTable, lookup: &'a mut LookupTable,
should_continue: &'a dyn std::ops::Fn() -> bool,
) -> impl Iterator<Item = Expr> + 'a { ) -> impl Iterator<Item = Expr> + 'a {
let db = ctx.sema.db; let db = ctx.sema.db;
let module = ctx.scope.module(); let module = ctx.scope.module();
@ -728,6 +753,7 @@ pub(super) fn impl_static_method<'a, DB: HirDatabase>(
.clone() .clone()
.into_iter() .into_iter()
.chain(iter::once(ctx.goal.clone())) .chain(iter::once(ctx.goal.clone()))
.filter(|_| should_continue())
.flat_map(|ty| { .flat_map(|ty| {
Impl::all_for_type(db, ty.clone()).into_iter().map(move |imp| (ty.clone(), imp)) 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); .permutations(non_default_fn_type_params_len);
let exprs: Vec<_> = generic_params let exprs: Vec<_> = generic_params
.filter(|_| should_continue())
.filter_map(|generics| { .filter_map(|generics| {
// Insert default type params // Insert default type params
let mut g = generics.into_iter(); 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 /// * `ctx` - Context for the term search
/// * `defs` - Set of items in scope at term search target location /// * `defs` - Set of items in scope at term search target location
/// * `lookup` - Lookup table for types /// * `lookup` - Lookup table for types
/// * `should_continue` - Function that indicates when to stop iterating
pub(super) fn make_tuple<'a, DB: HirDatabase>( pub(super) fn make_tuple<'a, DB: HirDatabase>(
ctx: &'a TermSearchCtx<'a, DB>, ctx: &'a TermSearchCtx<'a, DB>,
_defs: &'a FxHashSet<ScopeDef>, _defs: &'a FxHashSet<ScopeDef>,
lookup: &'a mut LookupTable, lookup: &'a mut LookupTable,
should_continue: &'a dyn std::ops::Fn() -> bool,
) -> impl Iterator<Item = Expr> + 'a { ) -> impl Iterator<Item = Expr> + 'a {
let db = ctx.sema.db; let db = ctx.sema.db;
let module = ctx.scope.module(); let module = ctx.scope.module();
@ -896,6 +925,7 @@ pub(super) fn make_tuple<'a, DB: HirDatabase>(
.types_wishlist() .types_wishlist()
.clone() .clone()
.into_iter() .into_iter()
.filter(|_| should_continue())
.filter(|ty| ty.is_tuple()) .filter(|ty| ty.is_tuple())
.filter_map(move |ty| { .filter_map(move |ty| {
// Double check to not contain unknown // Double check to not contain unknown
@ -915,6 +945,7 @@ pub(super) fn make_tuple<'a, DB: HirDatabase>(
let exprs: Vec<Expr> = param_exprs let exprs: Vec<Expr> = param_exprs
.into_iter() .into_iter()
.multi_cartesian_product() .multi_cartesian_product()
.filter(|_| should_continue())
.map(|params| { .map(|params| {
let tys: Vec<Type> = params.iter().map(|it| it.ty(db)).collect(); let tys: Vec<Type> = params.iter().map(|it| it.ty(db)).collect();
let tuple_ty = Type::new_tuple(module.krate().into(), &tys); let tuple_ty = Type::new_tuple(module.krate().into(), &tys);

View file

@ -16,4 +16,5 @@ pub struct AssistConfig {
pub prefer_no_std: bool, pub prefer_no_std: bool,
pub prefer_prelude: bool, pub prefer_prelude: bool,
pub assist_emit_must_use: bool, pub assist_emit_must_use: bool,
pub term_search_fuel: u64,
} }

View file

@ -8,8 +8,7 @@ use ide_db::{
}; };
use syntax::{ use syntax::{
ast::{self, make, AstNode, Expr::BinExpr, HasArgList}, ast::{self, make, AstNode, Expr::BinExpr, HasArgList},
ted::{self, Position}, ted, SyntaxKind, T,
SyntaxKind,
}; };
use crate::{utils::invert_boolean_expression, AssistContext, AssistId, AssistKind, Assists}; 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(); let demorganed = bin_expr.clone_subtree().clone_for_update();
ted::replace(demorganed.op_token()?, ast::make::token(inv_token)); 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.lhs()?, demorganed.lhs()?),
(bin_expr.rhs()?, demorganed.rhs()?), (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( acc.add_group(
&GroupLabel("Apply De Morgan's law".to_owned()), &GroupLabel("Apply De Morgan's law".to_owned()),
AssistId("apply_demorgan", AssistKind::RefactorRewrite), AssistId("apply_demorgan", AssistKind::RefactorRewrite),
"Apply De Morgan's law", "Apply De Morgan's law",
op_range, op_range,
|edit| { |edit| {
let demorganed = ast::Expr::BinExpr(demorganed);
let paren_expr = bin_expr.syntax().parent().and_then(ast::ParenExpr::cast); let paren_expr = bin_expr.syntax().parent().and_then(ast::ParenExpr::cast);
let neg_expr = paren_expr let neg_expr = paren_expr
.clone() .clone()
.and_then(|paren_expr| paren_expr.syntax().parent()) .and_then(|paren_expr| paren_expr.syntax().parent())
.and_then(ast::PrefixExpr::cast) .and_then(ast::PrefixExpr::cast)
.and_then(|prefix_expr| { .filter(|prefix_expr| matches!(prefix_expr.op_kind(), Some(ast::UnaryOp::Not)))
if prefix_expr.op_kind()? == ast::UnaryOp::Not { .map(ast::Expr::PrefixExpr);
Some(prefix_expr)
} else {
None
}
});
if let Some(paren_expr) = paren_expr { if let Some(paren_expr) = paren_expr {
if let Some(neg_expr) = neg_expr { if let Some(neg_expr) = neg_expr {
cov_mark::hit!(demorgan_double_negation); 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 { } else {
cov_mark::hit!(demorgan_double_parens); cov_mark::hit!(demorgan_double_parens);
ted::insert_all_raw( edit.replace_ast(paren_expr.into(), add_bang_paren(demorganed));
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());
} }
} else { } else {
ted::insert_all_raw( edit.replace_ast(bin_expr.into(), add_bang_paren(demorganed));
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);
} }
}, },
) )
@ -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)] #[cfg(test)]
mod tests { mod tests {
use super::*; 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) }") check_assist(apply_demorgan, "fn f() { (x ||$0 x) }", "fn f() { !(!x && !x) }")
} }
// FIXME : This needs to go. #[test]
// // https://github.com/rust-lang/rust-analyzer/issues/10963 fn demorgan_doesnt_hang() {
// #[test] check_assist(
// fn demorgan_doesnt_hang() { apply_demorgan,
// check_assist( "fn f() { 1 || 3 &&$0 4 || 5 }",
// apply_demorgan, "fn f() { 1 || !(!3 || !4) || 5 }",
// "fn f() { 1 || 3 &&$0 4 || 5 }", )
// "fn f() { !(!1 || !3 || !4) || 5 }", }
// )
// }
#[test] #[test]
fn demorgan_keep_pars_for_op_precedence() { 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] #[test]
fn demorgan_removes_pars_in_eq_precedence() { fn demorgan_removes_pars_in_eq_precedence() {
check_assist( 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] #[test]
fn demorgan_iterator_any_all_reverse() { fn demorgan_iterator_any_all_reverse() {
check_assist( check_assist(

View file

@ -85,7 +85,7 @@ fn edit_struct_def(
strukt: &Either<ast::Struct, ast::Variant>, strukt: &Either<ast::Struct, ast::Variant>,
record_fields: ast::RecordFieldList, 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. // currently not triggered for struct definitions inside macro calls.
let tuple_fields = record_fields let tuple_fields = record_fields
.fields() .fields()

View file

@ -5623,7 +5623,7 @@ fn func<T: Debug>(i: Struct<'_, T>) {
fun_name(i); fun_name(i);
} }
fn $0fun_name(i: Struct<'_, T>) { fn $0fun_name(i: Struct<T>) {
foo(i); foo(i);
} }
"#, "#,

View file

@ -1,6 +1,6 @@
use hir::{ use hir::{
Adt, AsAssocItem, HasSource, HirDisplay, HirFileIdExt, Module, PathResolution, Semantics, Type, Adt, AsAssocItem, HasSource, HirDisplay, HirFileIdExt, Module, PathResolution, Semantics,
TypeInfo, StructKind, Type, TypeInfo,
}; };
use ide_db::{ use ide_db::{
base_db::FileId, base_db::FileId,
@ -15,8 +15,8 @@ use itertools::Itertools;
use stdx::to_lower_snake_case; use stdx::to_lower_snake_case;
use syntax::{ use syntax::{
ast::{ ast::{
self, edit::IndentLevel, edit_in_place::Indent, make, AstNode, CallExpr, HasArgList, self, edit::IndentLevel, edit_in_place::Indent, make, AstNode, BlockExpr, CallExpr,
HasGenericParams, HasModuleItem, HasTypeBounds, HasArgList, HasGenericParams, HasModuleItem, HasTypeBounds,
}, },
ted, SyntaxKind, SyntaxNode, TextRange, T, 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 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)?; fn_target_info(ctx, path, &call, fn_name)?;
if let Some(m) = target_module { 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 text_range = call.syntax().text_range();
let label = format!("Generate {} function", function_builder.fn_name); 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 { struct TargetInfo {
target_module: Option<Module>, target_module: Option<Module>,
adt_name: Option<hir::Name>, adt_info: Option<AdtInfo>,
target: GeneratedFunctionTarget, target: GeneratedFunctionTarget,
file: FileId, file: FileId,
} }
@ -91,11 +92,11 @@ struct TargetInfo {
impl TargetInfo { impl TargetInfo {
fn new( fn new(
target_module: Option<Module>, target_module: Option<Module>,
adt_name: Option<hir::Name>, adt_info: Option<AdtInfo>,
target: GeneratedFunctionTarget, target: GeneratedFunctionTarget,
file: FileId, file: FileId,
) -> Self { ) -> 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, target,
)?; )?;
let text_range = call.syntax().text_range(); 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); 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( fn add_func_to_accumulator(
@ -168,7 +169,7 @@ fn add_func_to_accumulator(
text_range: TextRange, text_range: TextRange,
function_builder: FunctionBuilder, function_builder: FunctionBuilder,
file: FileId, file: FileId,
adt_name: Option<hir::Name>, adt_info: Option<AdtInfo>,
label: String, label: String,
) -> Option<()> { ) -> Option<()> {
acc.add(AssistId("generate_function", AssistKind::Generate), label, text_range, |edit| { 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 target = function_builder.target.clone();
let func = function_builder.render(ctx.config.snippet_cap, edit); let func = function_builder.render(ctx.config.snippet_cap, edit);
if let Some(name) = adt_name { if let Some(adt) =
let name = make::ty_path(make::ext::ident_path(&format!("{}", name.display(ctx.db())))); 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. // FIXME: adt may have generic params.
let impl_ = make::impl_(None, None, name, None, None).clone_for_update(); let impl_ = make::impl_(None, None, name, None, None).clone_for_update();
@ -210,6 +217,7 @@ struct FunctionBuilder {
generic_param_list: Option<ast::GenericParamList>, generic_param_list: Option<ast::GenericParamList>,
where_clause: Option<ast::WhereClause>, where_clause: Option<ast::WhereClause>,
params: ast::ParamList, params: ast::ParamList,
fn_body: BlockExpr,
ret_type: Option<ast::RetType>, ret_type: Option<ast::RetType>,
should_focus_return_type: bool, should_focus_return_type: bool,
visibility: Visibility, visibility: Visibility,
@ -225,6 +233,7 @@ impl FunctionBuilder {
fn_name: &str, fn_name: &str,
target_module: Option<Module>, target_module: Option<Module>,
target: GeneratedFunctionTarget, target: GeneratedFunctionTarget,
adt_info: &Option<AdtInfo>,
) -> Option<Self> { ) -> Option<Self> {
let target_module = let target_module =
target_module.or_else(|| ctx.sema.scope(target.syntax()).map(|it| it.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 await_expr = call.syntax().parent().and_then(ast::AwaitExpr::cast);
let is_async = await_expr.is_some(); 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;
let (ret_type, should_focus_return_type) = let should_focus_return_type;
make_return_type(ctx, &expr_for_ret_ty, target_module, &mut necessary_generic_params); 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) = let (generic_param_list, where_clause) =
fn_generic_params(ctx, necessary_generic_params, &target)?; fn_generic_params(ctx, necessary_generic_params, &target)?;
@ -256,6 +283,7 @@ impl FunctionBuilder {
generic_param_list, generic_param_list,
where_clause, where_clause,
params, params,
fn_body,
ret_type, ret_type,
should_focus_return_type, should_focus_return_type,
visibility, visibility,
@ -294,12 +322,16 @@ impl FunctionBuilder {
let (generic_param_list, where_clause) = let (generic_param_list, where_clause) =
fn_generic_params(ctx, necessary_generic_params, &target)?; 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 { Some(Self {
target, target,
fn_name, fn_name,
generic_param_list, generic_param_list,
where_clause, where_clause,
params, params,
fn_body,
ret_type, ret_type,
should_focus_return_type, should_focus_return_type,
visibility, visibility,
@ -308,8 +340,6 @@ impl FunctionBuilder {
} }
fn render(self, cap: Option<SnippetCap>, edit: &mut SourceChangeBuilder) -> ast::Fn { 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 { let visibility = match self.visibility {
Visibility::None => None, Visibility::None => None,
Visibility::Crate => Some(make::visibility_pub_crate()), Visibility::Crate => Some(make::visibility_pub_crate()),
@ -321,7 +351,7 @@ impl FunctionBuilder {
self.generic_param_list, self.generic_param_list,
self.where_clause, self.where_clause,
self.params, self.params,
fn_body, self.fn_body,
self.ret_type, self.ret_type,
self.is_async, self.is_async,
false, // FIXME : const and unsafe are not handled yet. false, // FIXME : const and unsafe are not handled yet.
@ -391,6 +421,53 @@ fn make_return_type(
(ret_type, should_focus_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( fn get_fn_target_info(
ctx: &AssistContext<'_>, ctx: &AssistContext<'_>,
target_module: Option<Module>, target_module: Option<Module>,
@ -443,8 +520,8 @@ fn assoc_fn_target_info(
} }
let (impl_, file) = get_adt_source(ctx, &adt, fn_name)?; let (impl_, file) = get_adt_source(ctx, &adt, fn_name)?;
let target = get_method_target(ctx, &impl_, &adt)?; let target = get_method_target(ctx, &impl_, &adt)?;
let adt_name = if impl_.is_none() { Some(adt.name(ctx.sema.db)) } else { None }; let adt_info = AdtInfo::new(adt, impl_.is_some());
Some(TargetInfo::new(target_module, adt_name, target, file)) Some(TargetInfo::new(target_module, Some(adt_info), target, file))
} }
#[derive(Clone)] #[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. /// Computes parameter list for the generated function.
fn fn_args( fn fn_args(
ctx: &AssistContext<'_>, ctx: &AssistContext<'_>,
@ -2758,18 +2846,18 @@ fn main() {
r" r"
enum Foo {} enum Foo {}
fn main() { fn main() {
Foo::new$0(); Foo::bar$0();
} }
", ",
r" r"
enum Foo {} enum Foo {}
impl Foo { impl Foo {
fn new() ${0:-> _} { fn bar() ${0:-> _} {
todo!() todo!()
} }
} }
fn main() { 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");
}
"#,
)
}
} }

View file

@ -1,6 +1,7 @@
use std::iter; use std::iter;
use ast::edit::IndentLevel; use ast::edit::IndentLevel;
use hir::HasAttrs;
use ide_db::base_db::AnchoredPathBuf; use ide_db::base_db::AnchoredPathBuf;
use itertools::Itertools; use itertools::Itertools;
use stdx::format_to; use stdx::format_to;
@ -50,9 +51,17 @@ pub(crate) fn move_module_to_file(acc: &mut Assists, ctx: &AssistContext<'_>) ->
|builder| { |builder| {
let path = { let path = {
let mut buf = String::from("./"); let mut buf = String::from("./");
match parent_module.name(ctx.db()) { let db = ctx.db();
Some(name) if !parent_module.is_mod_rs(ctx.db()) => { match parent_module.name(db) {
format_to!(buf, "{}/", name.display(ctx.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::*; 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] #[test]
fn extract_from_root() { fn extract_from_root() {
check_assist( check_assist(

View file

@ -25,7 +25,7 @@ pub(crate) fn make_raw_string(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opt
if token.is_raw() { if token.is_raw() {
return None; return None;
} }
let value = token.value()?; let value = token.value().ok()?;
let target = token.syntax().text_range(); let target = token.syntax().text_range();
acc.add( acc.add(
AssistId("make_raw_string", AssistKind::RefactorRewrite), 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() { if !token.is_raw() {
return None; return None;
} }
let value = token.value()?; let value = token.value().ok()?;
let target = token.syntax().text_range(); let target = token.syntax().text_range();
acc.add( acc.add(
AssistId("make_usual_string", AssistKind::RefactorRewrite), AssistId("make_usual_string", AssistKind::RefactorRewrite),
@ -398,12 +398,12 @@ string"###;
} }
#[test] #[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"; }"#); check_assist_not_applicable(remove_hash, r#"fn f() { let s = $0"random string"; }"#);
} }
#[test] #[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"; }"#); check_assist_not_applicable(remove_hash, r#"fn f() { let s = $0r"random string"; }"#);
} }

View file

@ -77,7 +77,7 @@ pub(crate) fn reorder_impl_items(acc: &mut Assists, ctx: &AssistContext<'_>) ->
ast::AssocItem::MacroCall(_) => None, 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(); .collect();

View file

@ -25,7 +25,7 @@ use crate::{AssistContext, AssistId, AssistKind, Assists};
// ``` // ```
pub(crate) fn replace_string_with_char(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { 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 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(); let target = token.syntax().text_range();
if value.chars().take(2).count() != 1 { if value.chars().take(2).count() != 1 {

View file

@ -1,5 +1,5 @@
//! Term search assist //! Term search assist
use hir::term_search::TermSearchCtx; use hir::term_search::{TermSearchConfig, TermSearchCtx};
use ide_db::{ use ide_db::{
assists::{AssistId, AssistKind, GroupLabel}, assists::{AssistId, AssistKind, GroupLabel},
famous_defs::FamousDefs, famous_defs::FamousDefs,
@ -34,7 +34,7 @@ pub(crate) fn term_search(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<
sema: &ctx.sema, sema: &ctx.sema,
scope: &scope, scope: &scope,
goal: target_ty, 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); let paths = hir::term_search::term_search(&term_search_ctx);

View file

@ -31,6 +31,7 @@ pub(crate) const TEST_CONFIG: AssistConfig = AssistConfig {
prefer_no_std: false, prefer_no_std: false,
prefer_prelude: true, prefer_prelude: true,
assist_emit_must_use: false, assist_emit_must_use: false,
term_search_fuel: 400,
}; };
pub(crate) const TEST_CONFIG_NO_SNIPPET_CAP: AssistConfig = AssistConfig { 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_no_std: false,
prefer_prelude: true, prefer_prelude: true,
assist_emit_must_use: false, assist_emit_must_use: false,
term_search_fuel: 400,
}; };
pub(crate) const TEST_CONFIG_IMPORT_ONE: AssistConfig = AssistConfig { 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_no_std: false,
prefer_prelude: true, prefer_prelude: true,
assist_emit_must_use: false, assist_emit_must_use: false,
term_search_fuel: 400,
}; };
pub(crate) fn with_single_file(text: &str) -> (RootDatabase, FileId) { pub(crate) fn with_single_file(text: &str) -> (RootDatabase, FileId) {

View file

@ -353,7 +353,7 @@ pub(crate) fn complete_expr(acc: &mut Completions, ctx: &CompletionContext<'_>)
config: hir::term_search::TermSearchConfig { config: hir::term_search::TermSearchConfig {
enable_borrowcheck: false, enable_borrowcheck: false,
many_alternatives_threshold: 1, many_alternatives_threshold: 1,
depth: 6, fuel: 200,
}, },
}; };
let exprs = hir::term_search::term_search(&term_search_ctx); let exprs = hir::term_search::term_search(&term_search_ctx);

View file

@ -296,7 +296,7 @@ fn import_on_the_fly_pat_(
position: SyntaxNode, position: SyntaxNode,
potential_import_name: String, potential_import_name: String,
) -> Option<()> { ) -> 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(); .entered();
ImportScope::find_insert_use_container(&position, &ctx.sema)?; ImportScope::find_insert_use_container(&position, &ctx.sema)?;

View file

@ -15,6 +15,7 @@ pub struct CompletionConfig {
pub enable_self_on_the_fly: bool, pub enable_self_on_the_fly: bool,
pub enable_private_editable: bool, pub enable_private_editable: bool,
pub enable_term_search: bool, pub enable_term_search: bool,
pub term_search_fuel: u64,
pub full_function_signatures: bool, pub full_function_signatures: bool,
pub callable: Option<CallableSnippets>, pub callable: Option<CallableSnippets>,
pub snippet_cap: Option<SnippetCap>, pub snippet_cap: Option<SnippetCap>,

View file

@ -466,7 +466,7 @@ impl CompletionContext<'_> {
cov_mark::hit!(completes_if_lifetime_without_idents); cov_mark::hit!(completes_if_lifetime_without_idents);
TextRange::at(self.original_token.text_range().start(), TextSize::from(1)) 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(), _ if kind.is_keyword() => self.original_token.text_range(),
_ => TextRange::empty(self.position.offset), _ => TextRange::empty(self.position.offset),
} }

View file

@ -368,7 +368,7 @@ fn render_resolution_pat(
import_to_add: Option<LocatedImport>, import_to_add: Option<LocatedImport>,
resolution: ScopeDef, resolution: ScopeDef,
) -> Builder { ) -> 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::*; use hir::ModuleDef::*;
if let ScopeDef::ModuleDef(Macro(mac)) = resolution { if let ScopeDef::ModuleDef(Macro(mac)) = resolution {
@ -386,7 +386,7 @@ fn render_resolution_path(
import_to_add: Option<LocatedImport>, import_to_add: Option<LocatedImport>,
resolution: ScopeDef, resolution: ScopeDef,
) -> Builder { ) -> 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::*; use hir::ModuleDef::*;
match resolution { match resolution {
@ -494,7 +494,7 @@ fn render_resolution_simple_(
import_to_add: Option<LocatedImport>, import_to_add: Option<LocatedImport>,
resolution: ScopeDef, resolution: ScopeDef,
) -> Builder { ) -> 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 db = ctx.db();
let ctx = ctx.import_to_add(import_to_add); 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] #[test]
fn record_field_and_call_relevances() { fn record_field_and_call_relevances() {
check_relevance( check_relevance(
@ -1808,8 +1853,7 @@ fn f() { A { bar: b$0 }; }
fn baz() [type] fn baz() [type]
ex baz() [type] ex baz() [type]
ex bar() [type] ex bar() [type]
ex A { bar: baz() }.bar [type] ex A { bar: ... }.bar [type]
ex A { bar: bar() }.bar [type]
st A [] st A []
fn f() [] fn f() []
"#]], "#]],
@ -1947,8 +1991,8 @@ fn main() {
} }
"#, "#,
expect![[r#" 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) (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 m [local]
lc t [local] lc t [local]
lc &t [type+local] lc &t [type+local]
@ -1997,8 +2041,8 @@ fn main() {
} }
"#, "#,
expect![[r#" 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) (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 m [local]
lc t [local] lc t [local]
lc &mut t [type+local] lc &mut t [type+local]

View file

@ -27,7 +27,7 @@ pub(crate) fn render_variant_lit(
variant: hir::Variant, variant: hir::Variant,
path: Option<hir::ModPath>, path: Option<hir::ModPath>,
) -> Option<Builder> { ) -> 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 db = ctx.db();
let name = local_name.unwrap_or_else(|| variant.name(db)); let name = local_name.unwrap_or_else(|| variant.name(db));

View file

@ -27,7 +27,7 @@ pub(crate) fn render_macro_pat(
name: hir::Name, name: hir::Name,
macro_: hir::Macro, macro_: hir::Macro,
) -> Builder { ) -> 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_) render(ctx, false, false, false, name, macro_)
} }

View file

@ -80,6 +80,7 @@ pub(crate) const TEST_CONFIG: CompletionConfig = CompletionConfig {
}, },
snippets: Vec::new(), snippets: Vec::new(),
limit: None, limit: None,
term_search_fuel: 200,
}; };
pub(crate) fn completion_list(ra_fixture: &str) -> String { pub(crate) fn completion_list(ra_fixture: &str) -> String {

View file

@ -19,7 +19,7 @@ struct Foo<'lt, T, const C: usize> where $0 {}
en Enum Enum en Enum Enum
ma makro!() macro_rules! makro ma makro!() macro_rules! makro
md module md module
st Foo<> Foo<'{error}, {unknown}, _> st Foo<> Foo<{unknown}, _>
st Record Record st Record Record
st Tuple Tuple st Tuple Tuple
st Unit Unit st Unit Unit
@ -92,7 +92,7 @@ struct Foo<'lt, T, const C: usize> where for<'a> $0 {}
en Enum Enum en Enum Enum
ma makro!() macro_rules! makro ma makro!() macro_rules! makro
md module md module
st Foo<> Foo<'{error}, {unknown}, _> st Foo<> Foo<{unknown}, _>
st Record Record st Record Record
st Tuple Tuple st Tuple Tuple
st Unit Unit st Unit Unit

View file

@ -20,8 +20,8 @@ struct Foo<'lt, T, const C: usize> {
en Enum Enum en Enum Enum
ma makro!() macro_rules! makro ma makro!() macro_rules! makro
md module md module
sp Self Foo<'{error}, {unknown}, _> sp Self Foo<{unknown}, _>
st Foo<> Foo<'{error}, {unknown}, _> st Foo<> Foo<{unknown}, _>
st Record Record st Record Record
st Tuple Tuple st Tuple Tuple
st Unit Unit st Unit Unit
@ -45,8 +45,8 @@ struct Foo<'lt, T, const C: usize>(f$0);
en Enum Enum en Enum Enum
ma makro!() macro_rules! makro ma makro!() macro_rules! makro
md module md module
sp Self Foo<'{error}, {unknown}, _> sp Self Foo<{unknown}, _>
st Foo<> Foo<'{error}, {unknown}, _> st Foo<> Foo<{unknown}, _>
st Record Record st Record Record
st Tuple Tuple st Tuple Tuple
st Unit Unit st Unit Unit

View file

@ -11,8 +11,8 @@ use hir::{
Adt, AsAssocItem, AsExternAssocItem, AssocItem, AttributeTemplate, BuiltinAttr, BuiltinType, Adt, AsAssocItem, AsExternAssocItem, AssocItem, AttributeTemplate, BuiltinAttr, BuiltinType,
Const, Crate, DefWithBody, DeriveHelper, DocLinkDef, ExternAssocItem, ExternCrateDecl, Field, Const, Crate, DefWithBody, DeriveHelper, DocLinkDef, ExternAssocItem, ExternCrateDecl, Field,
Function, GenericParam, HasVisibility, HirDisplay, Impl, Label, Local, Macro, Module, Function, GenericParam, HasVisibility, HirDisplay, Impl, Label, Local, Macro, Module,
ModuleDef, Name, PathResolution, Semantics, Static, ToolModule, Trait, TraitAlias, TupleField, ModuleDef, Name, PathResolution, Semantics, Static, StaticLifetime, ToolModule, Trait,
TypeAlias, Variant, VariantDef, Visibility, TraitAlias, TupleField, TypeAlias, Variant, VariantDef, Visibility,
}; };
use stdx::{format_to, impl_from}; use stdx::{format_to, impl_from};
use syntax::{ use syntax::{
@ -39,12 +39,13 @@ pub enum Definition {
Trait(Trait), Trait(Trait),
TraitAlias(TraitAlias), TraitAlias(TraitAlias),
TypeAlias(TypeAlias), TypeAlias(TypeAlias),
BuiltinType(BuiltinType),
SelfType(Impl), SelfType(Impl),
GenericParam(GenericParam), GenericParam(GenericParam),
Local(Local), Local(Local),
Label(Label), Label(Label),
DeriveHelper(DeriveHelper), DeriveHelper(DeriveHelper),
BuiltinType(BuiltinType),
BuiltinLifetime(StaticLifetime),
BuiltinAttr(BuiltinAttr), BuiltinAttr(BuiltinAttr),
ToolModule(ToolModule), ToolModule(ToolModule),
ExternCrateDecl(ExternCrateDecl), ExternCrateDecl(ExternCrateDecl),
@ -83,6 +84,7 @@ impl Definition {
Definition::DeriveHelper(it) => it.derive().module(db), Definition::DeriveHelper(it) => it.derive().module(db),
Definition::BuiltinAttr(_) Definition::BuiltinAttr(_)
| Definition::BuiltinType(_) | Definition::BuiltinType(_)
| Definition::BuiltinLifetime(_)
| Definition::TupleField(_) | Definition::TupleField(_)
| Definition::ToolModule(_) => return None, | Definition::ToolModule(_) => return None,
}; };
@ -112,6 +114,7 @@ impl Definition {
Definition::BuiltinType(_) | Definition::TupleField(_) => Visibility::Public, Definition::BuiltinType(_) | Definition::TupleField(_) => Visibility::Public,
Definition::Macro(_) => return None, Definition::Macro(_) => return None,
Definition::BuiltinAttr(_) Definition::BuiltinAttr(_)
| Definition::BuiltinLifetime(_)
| Definition::ToolModule(_) | Definition::ToolModule(_)
| Definition::SelfType(_) | Definition::SelfType(_)
| Definition::Local(_) | Definition::Local(_)
@ -141,6 +144,7 @@ impl Definition {
Definition::Local(it) => it.name(db), Definition::Local(it) => it.name(db),
Definition::GenericParam(it) => it.name(db), Definition::GenericParam(it) => it.name(db),
Definition::Label(it) => it.name(db), Definition::Label(it) => it.name(db),
Definition::BuiltinLifetime(StaticLifetime) => hir::known::STATIC_LIFETIME,
Definition::BuiltinAttr(_) => return None, // FIXME Definition::BuiltinAttr(_) => return None, // FIXME
Definition::ToolModule(_) => return None, // FIXME Definition::ToolModule(_) => return None, // FIXME
Definition::DeriveHelper(it) => it.name(db), Definition::DeriveHelper(it) => it.name(db),
@ -174,6 +178,7 @@ impl Definition {
doc_owner.docs(fd.0.db) doc_owner.docs(fd.0.db)
}) })
} }
Definition::BuiltinLifetime(StaticLifetime) => None,
Definition::Local(_) => None, Definition::Local(_) => None,
Definition::SelfType(impl_def) => { Definition::SelfType(impl_def) => {
impl_def.self_ty(db).as_adt().map(|adt| adt.docs(db))? 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::TraitAlias(it) => it.display(db).to_string(),
Definition::TypeAlias(it) => it.display(db).to_string(), Definition::TypeAlias(it) => it.display(db).to_string(),
Definition::BuiltinType(it) => it.name().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) => { Definition::Local(it) => {
let ty = it.ty(db); let ty = it.ty(db);
let ty_display = ty.display_truncated(db, None); let ty_display = ty.display_truncated(db, None);
@ -693,6 +699,9 @@ impl NameRefClass {
) -> Option<NameRefClass> { ) -> Option<NameRefClass> {
let _p = tracing::span!(tracing::Level::INFO, "NameRefClass::classify_lifetime", ?lifetime) let _p = tracing::span!(tracing::Level::INFO, "NameRefClass::classify_lifetime", ?lifetime)
.entered(); .entered();
if lifetime.text() == "'static" {
return Some(NameRefClass::Definition(Definition::BuiltinLifetime(StaticLifetime)));
}
let parent = lifetime.syntax().parent()?; let parent = lifetime.syntax().parent()?;
match parent.kind() { match parent.kind() {
SyntaxKind::BREAK_EXPR | SyntaxKind::CONTINUE_EXPR => { SyntaxKind::BREAK_EXPR | SyntaxKind::CONTINUE_EXPR => {

View file

@ -209,8 +209,7 @@ impl ImportAssets {
prefer_no_std: bool, prefer_no_std: bool,
prefer_prelude: bool, prefer_prelude: bool,
) -> impl Iterator<Item = LocatedImport> { ) -> impl Iterator<Item = LocatedImport> {
let _p = let _p = tracing::span!(tracing::Level::INFO, "ImportAssets::search_for_imports").entered();
tracing::span!(tracing::Level::INFO, "import_assets::search_for_imports").entered();
self.search_for(sema, Some(prefix_kind), prefer_no_std, prefer_prelude) self.search_for(sema, Some(prefix_kind), prefer_no_std, prefer_prelude)
} }
@ -221,7 +220,7 @@ impl ImportAssets {
prefer_no_std: bool, prefer_no_std: bool,
prefer_prelude: bool, prefer_prelude: bool,
) -> impl Iterator<Item = LocatedImport> { ) -> 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(); .entered();
self.search_for(sema, None, prefer_no_std, prefer_prelude) self.search_for(sema, None, prefer_no_std, prefer_prelude)
} }
@ -263,7 +262,7 @@ impl ImportAssets {
prefer_no_std: bool, prefer_no_std: bool,
prefer_prelude: bool, prefer_prelude: bool,
) -> impl Iterator<Item = LocatedImport> { ) -> 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) { let scope = match sema.scope(&self.candidate_node) {
Some(it) => it, Some(it) => it,
@ -308,7 +307,7 @@ impl ImportAssets {
} }
fn scope_definitions(&self, sema: &Semantics<'_, RootDatabase>) -> FxHashSet<ScopeDef> { 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(); let mut scope_definitions = FxHashSet::default();
if let Some(scope) = sema.scope(&self.candidate_node) { if let Some(scope) = sema.scope(&self.candidate_node) {
scope.process_all_names(&mut |_, scope_def| { scope.process_all_names(&mut |_, scope_def| {
@ -327,7 +326,7 @@ fn path_applicable_imports(
scope_filter: impl Fn(ItemInNs) -> bool + Copy, scope_filter: impl Fn(ItemInNs) -> bool + Copy,
) -> FxHashSet<LocatedImport> { ) -> FxHashSet<LocatedImport> {
let _p = 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 { match &path_candidate.qualifier {
None => { None => {
@ -374,7 +373,7 @@ fn import_for_item(
original_item: ItemInNs, original_item: ItemInNs,
scope_filter: impl Fn(ItemInNs) -> bool, scope_filter: impl Fn(ItemInNs) -> bool,
) -> Option<LocatedImport> { ) -> 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 [first_segment, ..] = unresolved_qualifier else { return None };
let item_as_assoc = item_as_assoc(db, original_item); 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>, mod_path: impl Fn(ItemInNs) -> Option<ModPath>,
scope_filter: impl Fn(hir::Trait) -> bool, scope_filter: impl Fn(hir::Trait) -> bool,
) -> FxHashSet<LocatedImport> { ) -> FxHashSet<LocatedImport> {
let _p = let _p = tracing::span!(tracing::Level::INFO, "ImportAssets::trait_applicable_items").entered();
tracing::span!(tracing::Level::INFO, "import_assets::trait_applicable_items").entered();
let db = sema.db; let db = sema.db;

View file

@ -194,7 +194,7 @@ fn insert_use_with_alias_option(
cfg: &InsertUseConfig, cfg: &InsertUseConfig,
alias: Option<ast::Rename>, 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 { let mut mb = match cfg.granularity {
ImportGranularity::Crate => Some(MergeBehavior::Crate), ImportGranularity::Crate => Some(MergeBehavior::Crate),
ImportGranularity::Module => Some(MergeBehavior::Module), ImportGranularity::Module => Some(MergeBehavior::Module),

View file

@ -1,6 +1,6 @@
//! rust-analyzer is lazy and doesn't compute anything unless asked. This //! rust-analyzer is lazy and doesn't compute anything unless asked. This
//! sometimes is counter productive when, for example, the first goto definition //! 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. //! various caches, it's not really advanced at the moment.
mod topologic_sort; mod topologic_sort;
@ -32,7 +32,7 @@ pub fn parallel_prime_caches(
num_worker_threads: u8, num_worker_threads: u8,
cb: &(dyn Fn(ParallelPrimeCachesProgress) + Sync), 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 graph = db.crate_graph();
let mut crates_to_prime = { let mut crates_to_prime = {

View file

@ -196,11 +196,12 @@ impl Definition {
.and_then(syn_ctx_is_root) .and_then(syn_ctx_is_root)
} }
} }
Definition::BuiltinType(_) => return None, Definition::BuiltinType(_)
Definition::SelfType(_) => return None, | Definition::BuiltinLifetime(_)
Definition::BuiltinAttr(_) => return None, | Definition::BuiltinAttr(_)
Definition::ToolModule(_) => return None, | Definition::SelfType(_)
Definition::TupleField(_) => return None, | Definition::ToolModule(_)
| Definition::TupleField(_) => return None,
// FIXME: This should be doable in theory // FIXME: This should be doable in theory
Definition::DeriveHelper(_) => return None, Definition::DeriveHelper(_) => return None,
}; };

View file

@ -1,7 +1,7 @@
//! Implementation of find-usages functionality. //! Implementation of find-usages functionality.
//! //!
//! It is based on the standard ide trick: first, we run a fast text search to //! 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. //! name resolution.
use std::mem; use std::mem;

View file

@ -301,8 +301,8 @@ impl SymbolIndex {
} }
fn range_to_map_value(start: usize, end: usize) -> u64 { fn range_to_map_value(start: usize, end: usize) -> u64 {
debug_assert![start <= (std::u32::MAX as usize)]; debug_assert![start <= (u32::MAX as usize)];
debug_assert![end <= (std::u32::MAX as usize)]; debug_assert![end <= (u32::MAX as usize)];
((start as u64) << 32) | end as u64 ((start as u64) << 32) | end as u64
} }

View file

@ -7,7 +7,7 @@ use ide_db::{
helpers::mod_path_to_ast, helpers::mod_path_to_ast,
imports::insert_use::{insert_use, ImportScope}, imports::insert_use::{insert_use, ImportScope},
source_change::SourceChangeBuilder, source_change::SourceChangeBuilder,
RootDatabase, FxHashMap, RootDatabase,
}; };
use itertools::Itertools; use itertools::Itertools;
use stdx::{format_to, never}; use stdx::{format_to, never};
@ -22,15 +22,22 @@ use crate::{fix, Diagnostic, DiagnosticCode, DiagnosticsConfig, Severity};
#[derive(Default)] #[derive(Default)]
struct State { struct State {
result: String, result: String,
struct_counts: usize,
has_serialize: bool, has_serialize: bool,
has_deserialize: bool, has_deserialize: bool,
names: FxHashMap<String, usize>,
} }
impl State { impl State {
fn generate_new_name(&mut self) -> ast::Name { fn generate_new_name(&mut self, name: &str) -> ast::Name {
self.struct_counts += 1; let name = stdx::to_camel_case(name);
make::name(&format!("Struct{}", self.struct_counts)) 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 { 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 { fn build_struct(
let name = self.generate_new_name(); &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 ty = make::ty(&name.to_string());
let strukt = make::struct_( let strukt = make::struct_(
None, None,
name, name,
None, None,
make::record_field_list(value.iter().sorted_unstable_by_key(|x| x.0).map( 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(), .into(),
); );
@ -68,7 +81,7 @@ impl State {
ty 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 { match value {
serde_json::Value::Null => make::ty_unit(), serde_json::Value::Null => make::ty_unit(),
serde_json::Value::Bool(_) => make::ty("bool"), serde_json::Value::Bool(_) => make::ty("bool"),
@ -76,12 +89,12 @@ impl State {
serde_json::Value::String(_) => make::ty("String"), serde_json::Value::String(_) => make::ty("String"),
serde_json::Value::Array(it) => { serde_json::Value::Array(it) => {
let ty = match it.iter().next() { let ty = match it.iter().next() {
Some(x) => self.type_of(x), Some(x) => self.type_of(name, x),
None => make::ty_placeholder(), None => make::ty_placeholder(),
}; };
make::ty(&format!("Vec<{ty}>")) 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"); let serialize_resolved = scope_resolve("::serde::Serialize");
state.has_deserialize = deserialize_resolved.is_some(); state.has_deserialize = deserialize_resolved.is_some();
state.has_serialize = serialize_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); edit.insert(range.start(), state.result);
acc.push( acc.push(
Diagnostic::new( Diagnostic::new(
@ -218,7 +231,7 @@ mod tests {
} }
#[derive(Serialize)] #[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#" r#"
struct Struct3{ } struct Value1{ }
struct Struct2{ kind: String, value: Struct3 } struct Bar1{ kind: String, value: Value1 }
struct Struct1{ bar: Struct2, foo: String } 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; use serde::Deserialize;
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
struct Struct2{ x: i64, y: i64 } struct OfObject1{ x: i64, y: i64 }
#[derive(Serialize, Deserialize)] #[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> }
"#, "#,
); );

View file

@ -1,5 +1,5 @@
use either::Either; 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 ide_db::{base_db::FileId, source_change::SourceChange, RootDatabase};
use syntax::{ use syntax::{
ast::{self, edit::IndentLevel, make}, ast::{self, edit::IndentLevel, make},
@ -25,7 +25,10 @@ pub(crate) fn no_such_field(ctx: &DiagnosticsContext<'_>, d: &hir::NoSuchField)
} else { } else {
Diagnostic::new_with_syntax_node_ptr( Diagnostic::new_with_syntax_node_ptr(
ctx, ctx,
DiagnosticCode::RustcHardError("E0559"), match d.variant {
VariantId::EnumVariantId(_) => DiagnosticCode::RustcHardError("E0559"),
_ => DiagnosticCode::RustcHardError("E0560"),
},
"no such field", "no such field",
node, node,
) )

Some files were not shown because too many files have changed in this diff Show more