mirror of
https://github.com/rust-lang/rust-analyzer
synced 2025-01-01 07:48:45 +00:00
Auto merge of #125272 - lnicola:sync-from-ra, r=lnicola
Subtree update of `rust-analyzer` r? `@ghost`
This commit is contained in:
commit
48826c85fd
204 changed files with 5515 additions and 2911 deletions
|
@ -6,3 +6,10 @@
|
||||||
|
|
||||||
# prettier format
|
# prettier format
|
||||||
f247090558c9ba3c551566eae5882b7ca865225f
|
f247090558c9ba3c551566eae5882b7ca865225f
|
||||||
|
|
||||||
|
# subtree syncs
|
||||||
|
932d85b52946d917deab2c23ead552f7f713b828
|
||||||
|
3e358a6827d83e8d6473913a5e304734aadfed04
|
||||||
|
9d2cb42a413e51deb50b36794a2e1605381878fc
|
||||||
|
f532576ac53ddcc666bc8d59e0b6437065e2f599
|
||||||
|
c48062fe2ab9a2d913d1985a6b0aec4bf936bfc1
|
||||||
|
|
6
.github/workflows/ci.yaml
vendored
6
.github/workflows/ci.yaml
vendored
|
@ -63,15 +63,15 @@ jobs:
|
||||||
- name: Install Rust toolchain
|
- 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: |
|
||||||
|
|
39
.github/workflows/metrics.yaml
vendored
39
.github/workflows/metrics.yaml
vendored
|
@ -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:
|
||||||
|
|
2
.github/workflows/rustdoc.yaml
vendored
2
.github/workflows/rustdoc.yaml
vendored
|
@ -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
406
Cargo.lock
generated
|
@ -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",
|
||||||
|
|
10
Cargo.toml
10
Cargo.toml
|
@ -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.
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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]>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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<_>>();
|
||||||
|
|
|
@ -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())
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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))
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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) => {
|
||||||
|
|
|
@ -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)),
|
||||||
|
|
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)?
|
||||||
)+
|
)+
|
||||||
|
|
||||||
$(
|
$(
|
||||||
|
|
|
@ -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(), ¶m, self.body_ctx.span_map());
|
||||||
|
debug_assert!(self.generic_param_attr_buffer.insert(item, attrs).is_none());
|
||||||
|
};
|
||||||
|
self.body_ctx.take_impl_traits_bounds();
|
||||||
let mut generics = GenericParamsCollector::default();
|
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(), ¶m, self.body_ctx.span_map());
|
|
||||||
// This is identical to the body of `Ctx::add_attrs()` but we can't call that here
|
|
||||||
// because it requires `&mut self` and the call to `generics.fill()` below also
|
|
||||||
// references `self`.
|
|
||||||
match self.tree.attrs.entry(match item {
|
|
||||||
Either::Right(id) => id.into(),
|
|
||||||
Either::Left(id) => id.into(),
|
|
||||||
}) {
|
|
||||||
Entry::Occupied(mut entry) => {
|
|
||||||
*entry.get_mut() = entry.get().merge(attrs);
|
|
||||||
}
|
|
||||||
Entry::Vacant(entry) => {
|
|
||||||
entry.insert(attrs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
generics.fill(&self.body_ctx, node, add_param_attrs);
|
generics.fill(&self.body_ctx, node, add_param_attrs);
|
||||||
|
|
||||||
Interned::new(generics.finish())
|
Interned::new(generics.finish())
|
||||||
|
|
|
@ -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())),
|
||||||
|
|
|
@ -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>;
|
||||||
"#]],
|
"#]],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -186,3 +186,33 @@ fn#0:1@45..47#0# foo#0:1@48..51#0#(#0:1@51..52#0#�:1@52..53#0#self#0:1@53..57#
|
||||||
}#0:1@76..77#0#"#]],
|
}#0:1@76..77#0#"#]],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn attribute_macro_doc_desugaring() {
|
||||||
|
check(
|
||||||
|
r#"
|
||||||
|
//- proc_macros: identity
|
||||||
|
#[proc_macros::identity]
|
||||||
|
/// doc string \n with newline
|
||||||
|
/**
|
||||||
|
MultiLines Doc
|
||||||
|
MultiLines Doc
|
||||||
|
*/
|
||||||
|
#[doc = "doc attr"]
|
||||||
|
struct S;
|
||||||
|
"#,
|
||||||
|
expect![[r##"
|
||||||
|
#[proc_macros::identity]
|
||||||
|
/// doc string \n with newline
|
||||||
|
/**
|
||||||
|
MultiLines Doc
|
||||||
|
MultiLines Doc
|
||||||
|
*/
|
||||||
|
#[doc = "doc attr"]
|
||||||
|
struct S;
|
||||||
|
|
||||||
|
#[doc = " doc string \\n with newline"]
|
||||||
|
#[doc = "\n MultiLines Doc\n MultiLines Doc\n"]
|
||||||
|
#[doc = "doc attr"] struct S;"##]],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
use std::{cmp::Ordering, iter, mem, ops::Not};
|
use 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);
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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)))
|
||||||
|
|
|
@ -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> {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 ¶m {
|
let bounds = match ¶m {
|
||||||
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 })
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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,
|
||||||
)
|
)
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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),
|
||||||
|
|
|
@ -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()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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())),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -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_)
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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()
|
||||||
}
|
}
|
||||||
|
|
|
@ -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<_>>();
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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`");
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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>,)
|
||||||
}
|
}
|
||||||
"#,
|
"#,
|
||||||
);
|
);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
"#,
|
"#,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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>
|
||||||
}
|
}
|
||||||
"#,
|
"#,
|
||||||
);
|
);
|
||||||
|
|
|
@ -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>
|
||||||
}
|
}
|
||||||
"#,
|
"#,
|
||||||
);
|
);
|
||||||
|
|
|
@ -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; }': ()
|
||||||
|
|
|
@ -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
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
{}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
"#,
|
"#,
|
||||||
);
|
);
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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(())
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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:?}"))
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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()
|
||||||
/// ¯o!()
|
/// ¯o!()
|
||||||
/// ```
|
/// ```
|
||||||
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,
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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,
|
||||||
}
|
}
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
"#,
|
"#,
|
||||||
|
|
|
@ -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");
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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"; }"#);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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)?;
|
||||||
|
|
|
@ -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>,
|
||||||
|
|
|
@ -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),
|
||||||
}
|
}
|
||||||
|
|
|
@ -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]
|
||||||
|
|
|
@ -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));
|
||||||
|
|
|
@ -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_)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 => {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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),
|
||||||
|
|
|
@ -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 = {
|
||||||
|
|
|
@ -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,
|
||||||
};
|
};
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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> }
|
||||||
|
|
||||||
"#,
|
"#,
|
||||||
);
|
);
|
||||||
|
|
|
@ -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
Loading…
Reference in a new issue