mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-11-17 18:57:04 +00:00
Merge pull request #1853 from Kobzol/pull-fixed
Perform the first rustc pull.. for the second time
This commit is contained in:
commit
6e66342f5b
212 changed files with 3548 additions and 1530 deletions
39
.github/workflows/ci.yaml
vendored
39
.github/workflows/ci.yaml
vendored
|
|
@ -17,6 +17,10 @@ env:
|
||||||
RUST_BACKTRACE: short
|
RUST_BACKTRACE: short
|
||||||
RUSTUP_MAX_RETRIES: 10
|
RUSTUP_MAX_RETRIES: 10
|
||||||
|
|
||||||
|
defaults:
|
||||||
|
run:
|
||||||
|
shell: bash
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
changes:
|
changes:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
@ -80,6 +84,7 @@ jobs:
|
||||||
CC: deny_c
|
CC: deny_c
|
||||||
|
|
||||||
strategy:
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
os: [ubuntu-latest, windows-latest, macos-latest]
|
os: [ubuntu-latest, windows-latest, macos-latest]
|
||||||
|
|
||||||
|
|
@ -99,7 +104,7 @@ jobs:
|
||||||
rustup toolchain install nightly --profile minimal --component rustfmt
|
rustup toolchain install nightly --profile minimal --component rustfmt
|
||||||
# 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 == 'macos-latest'
|
||||||
run: echo "::add-matcher::.github/rust.json"
|
run: echo "::add-matcher::.github/rust.json"
|
||||||
|
|
||||||
# - name: Cache Dependencies
|
# - name: Cache Dependencies
|
||||||
|
|
@ -116,23 +121,9 @@ jobs:
|
||||||
if: matrix.os == 'ubuntu-latest'
|
if: matrix.os == 'ubuntu-latest'
|
||||||
run: cargo codegen --check
|
run: cargo codegen --check
|
||||||
|
|
||||||
- name: Compile tests
|
|
||||||
run: cargo test --no-run
|
|
||||||
|
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
run: cargo nextest run --no-fail-fast --hide-progress-bar --status-level fail
|
run: cargo nextest run --no-fail-fast --hide-progress-bar --status-level fail
|
||||||
|
|
||||||
- name: Cancel parallel jobs
|
|
||||||
if: failure()
|
|
||||||
run: |
|
|
||||||
# https://docs.github.com/en/rest/actions/workflow-runs?apiVersion=2022-11-28#cancel-a-workflow-run
|
|
||||||
curl -L \
|
|
||||||
-X POST \
|
|
||||||
-H "Accept: application/vnd.github.v3+json" \
|
|
||||||
-H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \
|
|
||||||
-H "X-GitHub-Api-Version: 2022-11-28" \
|
|
||||||
https://api.github.com/repos/${{ github.repository }}/actions/runs/${{ github.run_id }}/cancel
|
|
||||||
|
|
||||||
- name: Run Clippy
|
- name: Run Clippy
|
||||||
if: matrix.os == 'macos-latest'
|
if: matrix.os == 'macos-latest'
|
||||||
run: cargo clippy --all-targets -- -D clippy::disallowed_macros -D clippy::dbg_macro -D clippy::todo -D clippy::print_stdout -D clippy::print_stderr
|
run: cargo clippy --all-targets -- -D clippy::disallowed_macros -D clippy::dbg_macro -D clippy::todo -D clippy::print_stdout -D clippy::print_stderr
|
||||||
|
|
@ -333,3 +324,21 @@ jobs:
|
||||||
jq -C <<< '${{ toJson(needs) }}'
|
jq -C <<< '${{ toJson(needs) }}'
|
||||||
# Check if all jobs that we depend on (in the needs array) were successful (or have been skipped).
|
# Check if all jobs that we depend on (in the needs array) were successful (or have been skipped).
|
||||||
jq --exit-status 'all(.result == "success" or .result == "skipped")' <<< '${{ toJson(needs) }}'
|
jq --exit-status 'all(.result == "success" or .result == "skipped")' <<< '${{ toJson(needs) }}'
|
||||||
|
|
||||||
|
cancel-if-matrix-failed:
|
||||||
|
needs: rust
|
||||||
|
if: ${{ always() }}
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Cancel parallel jobs
|
||||||
|
run: |
|
||||||
|
if jq --exit-status 'all(.result == "success" or .result == "skipped")' <<< '${{ toJson(needs) }}'; then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
# https://docs.github.com/en/rest/actions/workflow-runs?apiVersion=2022-11-28#cancel-a-workflow-run
|
||||||
|
curl -L \
|
||||||
|
-X POST \
|
||||||
|
-H "Accept: application/vnd.github.v3+json" \
|
||||||
|
-H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \
|
||||||
|
-H "X-GitHub-Api-Version: 2022-11-28" \
|
||||||
|
https://api.github.com/repos/${{ github.repository }}/actions/runs/${{ github.run_id }}/cancel
|
||||||
|
|
|
||||||
4
.github/workflows/release.yaml
vendored
4
.github/workflows/release.yaml
vendored
|
|
@ -134,13 +134,13 @@ jobs:
|
||||||
|
|
||||||
- name: Run analysis-stats on rust-analyzer
|
- name: Run analysis-stats on rust-analyzer
|
||||||
if: matrix.target == 'x86_64-unknown-linux-gnu'
|
if: matrix.target == 'x86_64-unknown-linux-gnu'
|
||||||
run: target/${{ matrix.target }}/release/rust-analyzer analysis-stats .
|
run: target/${{ matrix.target }}/release/rust-analyzer analysis-stats . -q
|
||||||
|
|
||||||
- name: Run analysis-stats on rust std library
|
- name: Run analysis-stats on rust std library
|
||||||
if: matrix.target == 'x86_64-unknown-linux-gnu'
|
if: matrix.target == 'x86_64-unknown-linux-gnu'
|
||||||
env:
|
env:
|
||||||
RUSTC_BOOTSTRAP: 1
|
RUSTC_BOOTSTRAP: 1
|
||||||
run: target/${{ matrix.target }}/release/rust-analyzer analysis-stats --with-deps $(rustc --print sysroot)/lib/rustlib/src/rust/library/std
|
run: target/${{ matrix.target }}/release/rust-analyzer analysis-stats --with-deps $(rustc --print sysroot)/lib/rustlib/src/rust/library/std -q
|
||||||
|
|
||||||
- name: Upload artifacts
|
- name: Upload artifacts
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
|
|
|
||||||
60
Cargo.lock
generated
60
Cargo.lock
generated
|
|
@ -569,12 +569,6 @@ dependencies = [
|
||||||
"hashbrown 0.15.4",
|
"hashbrown 0.15.4",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "heck"
|
|
||||||
version = "0.5.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hermit-abi"
|
name = "hermit-abi"
|
||||||
version = "0.5.2"
|
version = "0.5.2"
|
||||||
|
|
@ -1020,6 +1014,15 @@ dependencies = [
|
||||||
"triomphe",
|
"triomphe",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "intrusive-collections"
|
||||||
|
version = "0.9.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "189d0897e4cbe8c75efedf3502c18c887b05046e59d28404d4d8e46cbc4d1e86"
|
||||||
|
dependencies = [
|
||||||
|
"memoffset",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "itertools"
|
name = "itertools"
|
||||||
version = "0.12.1"
|
version = "0.12.1"
|
||||||
|
|
@ -1427,6 +1430,16 @@ dependencies = [
|
||||||
"num-traits",
|
"num-traits",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "papaya"
|
||||||
|
version = "0.2.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f92dd0b07c53a0a0c764db2ace8c541dc47320dad97c2200c2a637ab9dd2328f"
|
||||||
|
dependencies = [
|
||||||
|
"equivalent",
|
||||||
|
"seize",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "parking_lot"
|
name = "parking_lot"
|
||||||
version = "0.12.4"
|
version = "0.12.4"
|
||||||
|
|
@ -1458,7 +1471,7 @@ dependencies = [
|
||||||
"edition",
|
"edition",
|
||||||
"expect-test",
|
"expect-test",
|
||||||
"ra-ap-rustc_lexer",
|
"ra-ap-rustc_lexer",
|
||||||
"rustc-literal-escaper 0.0.3",
|
"rustc-literal-escaper 0.0.4",
|
||||||
"stdx",
|
"stdx",
|
||||||
"tracing",
|
"tracing",
|
||||||
]
|
]
|
||||||
|
|
@ -1927,9 +1940,9 @@ checksum = "0041b6238913c41fe704213a4a9329e2f685a156d1781998128b4149c230ad04"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustc-literal-escaper"
|
name = "rustc-literal-escaper"
|
||||||
version = "0.0.3"
|
version = "0.0.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "78744cd17f5d01c75b709e49807d1363e02a940ccee2e9e72435843fdb0d076e"
|
checksum = "ab03008eb631b703dd16978282ae36c73282e7922fe101a4bd072a40ecea7b8b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustc-stable-hash"
|
name = "rustc-stable-hash"
|
||||||
|
|
@ -1955,16 +1968,18 @@ checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "salsa"
|
name = "salsa"
|
||||||
version = "0.22.0"
|
version = "0.23.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c8fff508e3d6ef42a32607f7538e17171a877a12015e32036f46e99d00c95781"
|
checksum = "2e235afdb8e510f38a07138fbe5a0b64691894358a9c0cbd813b1aade110efc9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"boxcar",
|
"boxcar",
|
||||||
"crossbeam-queue",
|
"crossbeam-queue",
|
||||||
"dashmap",
|
"crossbeam-utils",
|
||||||
"hashbrown 0.15.4",
|
"hashbrown 0.15.4",
|
||||||
"hashlink",
|
"hashlink",
|
||||||
"indexmap",
|
"indexmap",
|
||||||
|
"intrusive-collections",
|
||||||
|
"papaya",
|
||||||
"parking_lot",
|
"parking_lot",
|
||||||
"portable-atomic",
|
"portable-atomic",
|
||||||
"rayon",
|
"rayon",
|
||||||
|
|
@ -1978,17 +1993,16 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "salsa-macro-rules"
|
name = "salsa-macro-rules"
|
||||||
version = "0.22.0"
|
version = "0.23.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8ea72b3c06f2ce6350fe3a0eeb7aaaf842d1d8352b706973c19c4f02e298a87c"
|
checksum = "2edb86a7e9c91f6d30c9ce054312721dbe773a162db27bbfae834d16177b30ce"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "salsa-macros"
|
name = "salsa-macros"
|
||||||
version = "0.22.0"
|
version = "0.23.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0ce92025bc160b27814a207cb78d680973af17f863c7f4fc56cf3a535e22f378"
|
checksum = "d0778d6e209051bc4e75acfe83bcd7848601ec3dbe9c3dbb982829020e9128af"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"heck",
|
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn",
|
||||||
|
|
@ -2025,6 +2039,16 @@ version = "1.2.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "seize"
|
||||||
|
version = "0.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e4b8d813387d566f627f3ea1b914c068aac94c40ae27ec43f5f33bde65abefe7"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"windows-sys 0.52.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "semver"
|
name = "semver"
|
||||||
version = "1.0.26"
|
version = "1.0.26"
|
||||||
|
|
@ -2207,7 +2231,7 @@ dependencies = [
|
||||||
"rayon",
|
"rayon",
|
||||||
"rowan",
|
"rowan",
|
||||||
"rustc-hash 2.1.1",
|
"rustc-hash 2.1.1",
|
||||||
"rustc-literal-escaper 0.0.3",
|
"rustc-literal-escaper 0.0.4",
|
||||||
"rustc_apfloat",
|
"rustc_apfloat",
|
||||||
"smol_str",
|
"smol_str",
|
||||||
"stdx",
|
"stdx",
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,8 @@ debug = 2
|
||||||
# ungrammar = { path = "../ungrammar" }
|
# ungrammar = { path = "../ungrammar" }
|
||||||
|
|
||||||
# salsa = { path = "../salsa" }
|
# salsa = { path = "../salsa" }
|
||||||
|
# salsa-macros = { path = "../salsa/components/salsa-macros" }
|
||||||
|
# salsa-macro-rules = { path = "../salsa/components/salsa-macro-rules" }
|
||||||
|
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
# local crates
|
# local crates
|
||||||
|
|
@ -136,14 +138,14 @@ rayon = "1.10.0"
|
||||||
rowan = "=0.15.15"
|
rowan = "=0.15.15"
|
||||||
# Ideally we'd not enable the macros feature but unfortunately the `tracked` attribute does not work
|
# Ideally we'd not enable the macros feature but unfortunately the `tracked` attribute does not work
|
||||||
# on impls without it
|
# on impls without it
|
||||||
salsa = { version = "0.22.0", default-features = true, features = ["rayon","salsa_unstable", "macros"] }
|
salsa = { version = "0.23.0", default-features = true, features = ["rayon","salsa_unstable", "macros"] }
|
||||||
salsa-macros = "0.22.0"
|
salsa-macros = "0.23.0"
|
||||||
semver = "1.0.26"
|
semver = "1.0.26"
|
||||||
serde = { version = "1.0.219" }
|
serde = { version = "1.0.219" }
|
||||||
serde_derive = { version = "1.0.219" }
|
serde_derive = { version = "1.0.219" }
|
||||||
serde_json = "1.0.140"
|
serde_json = "1.0.140"
|
||||||
rustc-hash = "2.1.1"
|
rustc-hash = "2.1.1"
|
||||||
rustc-literal-escaper = "0.0.3"
|
rustc-literal-escaper = "0.0.4"
|
||||||
smallvec = { version = "1.15.1", features = [
|
smallvec = { version = "1.15.1", features = [
|
||||||
"const_new",
|
"const_new",
|
||||||
"union",
|
"union",
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ license.workspace = true
|
||||||
rust-version.workspace = true
|
rust-version.workspace = true
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
|
doctest = false
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
la-arena.workspace = true
|
la-arena.workspace = true
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@
|
||||||
//! actual IO. See `vfs` and `project_model` in the `rust-analyzer` crate for how
|
//! actual IO. See `vfs` and `project_model` in the `rust-analyzer` crate for how
|
||||||
//! actual IO is done and lowered to input.
|
//! actual IO is done and lowered to input.
|
||||||
|
|
||||||
|
use std::error::Error;
|
||||||
use std::hash::BuildHasherDefault;
|
use std::hash::BuildHasherDefault;
|
||||||
use std::{fmt, mem, ops};
|
use std::{fmt, mem, ops};
|
||||||
|
|
||||||
|
|
@ -22,7 +23,49 @@ use vfs::{AbsPathBuf, AnchoredPath, FileId, VfsPath, file_set::FileSet};
|
||||||
|
|
||||||
use crate::{CrateWorkspaceData, EditionedFileId, FxIndexSet, RootQueryDb};
|
use crate::{CrateWorkspaceData, EditionedFileId, FxIndexSet, RootQueryDb};
|
||||||
|
|
||||||
pub type ProcMacroPaths = FxHashMap<CrateBuilderId, Result<(String, AbsPathBuf), String>>;
|
pub type ProcMacroPaths =
|
||||||
|
FxHashMap<CrateBuilderId, Result<(String, AbsPathBuf), ProcMacroLoadingError>>;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
|
pub enum ProcMacroLoadingError {
|
||||||
|
Disabled,
|
||||||
|
FailedToBuild,
|
||||||
|
MissingDylibPath,
|
||||||
|
NotYetBuilt,
|
||||||
|
NoProcMacros,
|
||||||
|
ProcMacroSrvError(Box<str>),
|
||||||
|
}
|
||||||
|
impl ProcMacroLoadingError {
|
||||||
|
pub fn is_hard_error(&self) -> bool {
|
||||||
|
match self {
|
||||||
|
ProcMacroLoadingError::Disabled | ProcMacroLoadingError::NotYetBuilt => false,
|
||||||
|
ProcMacroLoadingError::FailedToBuild
|
||||||
|
| ProcMacroLoadingError::MissingDylibPath
|
||||||
|
| ProcMacroLoadingError::NoProcMacros
|
||||||
|
| ProcMacroLoadingError::ProcMacroSrvError(_) => true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Error for ProcMacroLoadingError {}
|
||||||
|
impl fmt::Display for ProcMacroLoadingError {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
ProcMacroLoadingError::Disabled => write!(f, "proc-macro expansion is disabled"),
|
||||||
|
ProcMacroLoadingError::FailedToBuild => write!(f, "proc-macro failed to build"),
|
||||||
|
ProcMacroLoadingError::MissingDylibPath => {
|
||||||
|
write!(f, "proc-macro crate build data is missing a dylib path")
|
||||||
|
}
|
||||||
|
ProcMacroLoadingError::NotYetBuilt => write!(f, "proc-macro not yet built"),
|
||||||
|
ProcMacroLoadingError::NoProcMacros => {
|
||||||
|
write!(f, "proc macro library has no proc macros")
|
||||||
|
}
|
||||||
|
ProcMacroLoadingError::ProcMacroSrvError(msg) => {
|
||||||
|
write!(f, "proc macro server error: {msg}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||||
pub struct SourceRootId(pub u32);
|
pub struct SourceRootId(pub u32);
|
||||||
|
|
|
||||||
|
|
@ -14,8 +14,9 @@ pub use crate::{
|
||||||
input::{
|
input::{
|
||||||
BuiltCrateData, BuiltDependency, Crate, CrateBuilder, CrateBuilderId, CrateDataBuilder,
|
BuiltCrateData, BuiltDependency, Crate, CrateBuilder, CrateBuilderId, CrateDataBuilder,
|
||||||
CrateDisplayName, CrateGraphBuilder, CrateName, CrateOrigin, CratesIdMap, CratesMap,
|
CrateDisplayName, CrateGraphBuilder, CrateName, CrateOrigin, CratesIdMap, CratesMap,
|
||||||
DependencyBuilder, Env, ExtraCrateData, LangCrateOrigin, ProcMacroPaths, ReleaseChannel,
|
DependencyBuilder, Env, ExtraCrateData, LangCrateOrigin, ProcMacroLoadingError,
|
||||||
SourceRoot, SourceRootId, TargetLayoutLoadResult, UniqueCrateData,
|
ProcMacroPaths, ReleaseChannel, SourceRoot, SourceRootId, TargetLayoutLoadResult,
|
||||||
|
UniqueCrateData,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use dashmap::{DashMap, mapref::entry::Entry};
|
use dashmap::{DashMap, mapref::entry::Entry};
|
||||||
|
|
@ -33,7 +34,7 @@ pub type FxIndexSet<T> = indexmap::IndexSet<T, rustc_hash::FxBuildHasher>;
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! impl_intern_key {
|
macro_rules! impl_intern_key {
|
||||||
($id:ident, $loc:ident) => {
|
($id:ident, $loc:ident) => {
|
||||||
#[salsa_macros::interned(no_lifetime)]
|
#[salsa_macros::interned(no_lifetime, revisions = usize::MAX)]
|
||||||
#[derive(PartialOrd, Ord)]
|
#[derive(PartialOrd, Ord)]
|
||||||
pub struct $id {
|
pub struct $id {
|
||||||
pub loc: $loc,
|
pub loc: $loc,
|
||||||
|
|
@ -43,7 +44,7 @@ macro_rules! impl_intern_key {
|
||||||
impl ::std::fmt::Debug for $id {
|
impl ::std::fmt::Debug for $id {
|
||||||
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
|
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
|
||||||
f.debug_tuple(stringify!($id))
|
f.debug_tuple(stringify!($id))
|
||||||
.field(&format_args!("{:04x}", self.0.as_u32()))
|
.field(&format_args!("{:04x}", self.0.index()))
|
||||||
.finish()
|
.finish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -167,7 +168,7 @@ impl Files {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[salsa_macros::interned(no_lifetime, debug, constructor=from_span)]
|
#[salsa_macros::interned(no_lifetime, debug, constructor=from_span, revisions = usize::MAX)]
|
||||||
#[derive(PartialOrd, Ord)]
|
#[derive(PartialOrd, Ord)]
|
||||||
pub struct EditionedFileId {
|
pub struct EditionedFileId {
|
||||||
pub editioned_file_id: span::EditionedFileId,
|
pub editioned_file_id: span::EditionedFileId,
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ license.workspace = true
|
||||||
rust-version.workspace = true
|
rust-version.workspace = true
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
|
doctest = false
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
rustc-hash.workspace = true
|
rustc-hash.workspace = true
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ license.workspace = true
|
||||||
rust-version.workspace = true
|
rust-version.workspace = true
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
|
doctest = false
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
arrayvec.workspace = true
|
arrayvec.workspace = true
|
||||||
|
|
|
||||||
|
|
@ -25,11 +25,10 @@ use crate::{
|
||||||
import_map::ImportMap,
|
import_map::ImportMap,
|
||||||
item_tree::{ItemTree, file_item_tree_query},
|
item_tree::{ItemTree, file_item_tree_query},
|
||||||
lang_item::{self, LangItem},
|
lang_item::{self, LangItem},
|
||||||
nameres::{assoc::TraitItems, crate_def_map, diagnostics::DefDiagnostics},
|
nameres::crate_def_map,
|
||||||
signatures::{
|
signatures::{
|
||||||
ConstSignature, EnumSignature, FunctionSignature, ImplSignature, StaticSignature,
|
ConstSignature, EnumSignature, FunctionSignature, ImplSignature, StaticSignature,
|
||||||
StructSignature, TraitAliasSignature, TraitSignature, TypeAliasSignature, UnionSignature,
|
StructSignature, TraitAliasSignature, TraitSignature, TypeAliasSignature, UnionSignature,
|
||||||
VariantFields,
|
|
||||||
},
|
},
|
||||||
tt,
|
tt,
|
||||||
visibility::{self, Visibility},
|
visibility::{self, Visibility},
|
||||||
|
|
@ -113,24 +112,6 @@ pub trait DefDatabase: InternDatabase + ExpandDatabase + SourceDatabase {
|
||||||
|
|
||||||
// region:data
|
// region:data
|
||||||
|
|
||||||
#[salsa::invoke(VariantFields::query)]
|
|
||||||
fn variant_fields_with_source_map(
|
|
||||||
&self,
|
|
||||||
id: VariantId,
|
|
||||||
) -> (Arc<VariantFields>, Arc<ExpressionStoreSourceMap>);
|
|
||||||
|
|
||||||
#[salsa::transparent]
|
|
||||||
#[salsa::invoke(TraitItems::trait_items_query)]
|
|
||||||
fn trait_items(&self, e: TraitId) -> Arc<TraitItems>;
|
|
||||||
|
|
||||||
#[salsa::invoke(TraitItems::trait_items_with_diagnostics_query)]
|
|
||||||
fn trait_items_with_diagnostics(&self, tr: TraitId) -> (Arc<TraitItems>, DefDiagnostics);
|
|
||||||
|
|
||||||
#[salsa::tracked]
|
|
||||||
fn variant_fields(&self, id: VariantId) -> Arc<VariantFields> {
|
|
||||||
self.variant_fields_with_source_map(id).0
|
|
||||||
}
|
|
||||||
|
|
||||||
#[salsa::tracked]
|
#[salsa::tracked]
|
||||||
fn trait_signature(&self, trait_: TraitId) -> Arc<TraitSignature> {
|
fn trait_signature(&self, trait_: TraitId) -> Arc<TraitSignature> {
|
||||||
self.trait_signature_with_source_map(trait_).0
|
self.trait_signature_with_source_map(trait_).0
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,10 @@ pub mod scope;
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests;
|
mod tests;
|
||||||
|
|
||||||
use std::ops::{Deref, Index};
|
use std::{
|
||||||
|
ops::{Deref, Index},
|
||||||
|
sync::LazyLock,
|
||||||
|
};
|
||||||
|
|
||||||
use cfg::{CfgExpr, CfgOptions};
|
use cfg::{CfgExpr, CfgOptions};
|
||||||
use either::Either;
|
use either::Either;
|
||||||
|
|
@ -19,6 +22,7 @@ use rustc_hash::FxHashMap;
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
use span::{Edition, SyntaxContext};
|
use span::{Edition, SyntaxContext};
|
||||||
use syntax::{AstPtr, SyntaxNodePtr, ast};
|
use syntax::{AstPtr, SyntaxNodePtr, ast};
|
||||||
|
use triomphe::Arc;
|
||||||
use tt::TextRange;
|
use tt::TextRange;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
|
@ -89,7 +93,7 @@ pub type TypeSource = InFile<TypePtr>;
|
||||||
pub type LifetimePtr = AstPtr<ast::Lifetime>;
|
pub type LifetimePtr = AstPtr<ast::Lifetime>;
|
||||||
pub type LifetimeSource = InFile<LifetimePtr>;
|
pub type LifetimeSource = InFile<LifetimePtr>;
|
||||||
|
|
||||||
#[derive(Debug, Eq, PartialEq)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
pub struct ExpressionStore {
|
pub struct ExpressionStore {
|
||||||
pub exprs: Arena<Expr>,
|
pub exprs: Arena<Expr>,
|
||||||
pub pats: Arena<Pat>,
|
pub pats: Arena<Pat>,
|
||||||
|
|
@ -110,7 +114,7 @@ pub struct ExpressionStore {
|
||||||
ident_hygiene: FxHashMap<ExprOrPatId, HygieneId>,
|
ident_hygiene: FxHashMap<ExprOrPatId, HygieneId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Eq, PartialEq, Default)]
|
#[derive(Debug, Eq, Default)]
|
||||||
pub struct ExpressionStoreSourceMap {
|
pub struct ExpressionStoreSourceMap {
|
||||||
// AST expressions can create patterns in destructuring assignments. Therefore, `ExprSource` can also map
|
// AST expressions can create patterns in destructuring assignments. Therefore, `ExprSource` can also map
|
||||||
// to `PatId`, and `PatId` can also map to `ExprSource` (the other way around is unaffected).
|
// to `PatId`, and `PatId` can also map to `ExprSource` (the other way around is unaffected).
|
||||||
|
|
@ -123,19 +127,20 @@ pub struct ExpressionStoreSourceMap {
|
||||||
label_map: FxHashMap<LabelSource, LabelId>,
|
label_map: FxHashMap<LabelSource, LabelId>,
|
||||||
label_map_back: ArenaMap<LabelId, LabelSource>,
|
label_map_back: ArenaMap<LabelId, LabelSource>,
|
||||||
|
|
||||||
binding_definitions: FxHashMap<BindingId, SmallVec<[PatId; 4]>>,
|
|
||||||
|
|
||||||
/// We don't create explicit nodes for record fields (`S { record_field: 92 }`).
|
|
||||||
/// Instead, we use id of expression (`92`) to identify the field.
|
|
||||||
field_map_back: FxHashMap<ExprId, FieldSource>,
|
|
||||||
pat_field_map_back: FxHashMap<PatId, PatFieldSource>,
|
|
||||||
|
|
||||||
types_map_back: ArenaMap<TypeRefId, TypeSource>,
|
types_map_back: ArenaMap<TypeRefId, TypeSource>,
|
||||||
types_map: FxHashMap<TypeSource, TypeRefId>,
|
types_map: FxHashMap<TypeSource, TypeRefId>,
|
||||||
|
|
||||||
lifetime_map_back: ArenaMap<LifetimeRefId, LifetimeSource>,
|
lifetime_map_back: ArenaMap<LifetimeRefId, LifetimeSource>,
|
||||||
lifetime_map: FxHashMap<LifetimeSource, LifetimeRefId>,
|
lifetime_map: FxHashMap<LifetimeSource, LifetimeRefId>,
|
||||||
|
|
||||||
|
binding_definitions:
|
||||||
|
ArenaMap<BindingId, SmallVec<[PatId; 2 * size_of::<usize>() / size_of::<PatId>()]>>,
|
||||||
|
|
||||||
|
/// We don't create explicit nodes for record fields (`S { record_field: 92 }`).
|
||||||
|
/// Instead, we use id of expression (`92`) to identify the field.
|
||||||
|
field_map_back: FxHashMap<ExprId, FieldSource>,
|
||||||
|
pat_field_map_back: FxHashMap<PatId, PatFieldSource>,
|
||||||
|
|
||||||
template_map: Option<Box<FormatTemplate>>,
|
template_map: Option<Box<FormatTemplate>>,
|
||||||
|
|
||||||
pub expansions: FxHashMap<InFile<MacroCallPtr>, MacroCallId>,
|
pub expansions: FxHashMap<InFile<MacroCallPtr>, MacroCallId>,
|
||||||
|
|
@ -145,6 +150,43 @@ pub struct ExpressionStoreSourceMap {
|
||||||
pub diagnostics: Vec<ExpressionStoreDiagnostics>,
|
pub diagnostics: Vec<ExpressionStoreDiagnostics>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl PartialEq for ExpressionStoreSourceMap {
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
// we only need to compare one of the two mappings
|
||||||
|
// as the other is a reverse mapping and thus will compare
|
||||||
|
// the same as normal mapping
|
||||||
|
let Self {
|
||||||
|
expr_map: _,
|
||||||
|
expr_map_back,
|
||||||
|
pat_map: _,
|
||||||
|
pat_map_back,
|
||||||
|
label_map: _,
|
||||||
|
label_map_back,
|
||||||
|
types_map_back,
|
||||||
|
types_map: _,
|
||||||
|
lifetime_map_back,
|
||||||
|
lifetime_map: _,
|
||||||
|
// If this changed, our pattern data must have changed
|
||||||
|
binding_definitions: _,
|
||||||
|
// If this changed, our expression data must have changed
|
||||||
|
field_map_back: _,
|
||||||
|
// If this changed, our pattern data must have changed
|
||||||
|
pat_field_map_back: _,
|
||||||
|
template_map,
|
||||||
|
expansions,
|
||||||
|
diagnostics,
|
||||||
|
} = self;
|
||||||
|
*expr_map_back == other.expr_map_back
|
||||||
|
&& *pat_map_back == other.pat_map_back
|
||||||
|
&& *label_map_back == other.label_map_back
|
||||||
|
&& *types_map_back == other.types_map_back
|
||||||
|
&& *lifetime_map_back == other.lifetime_map_back
|
||||||
|
&& *template_map == other.template_map
|
||||||
|
&& *expansions == other.expansions
|
||||||
|
&& *diagnostics == other.diagnostics
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// The body of an item (function, const etc.).
|
/// The body of an item (function, const etc.).
|
||||||
#[derive(Debug, Eq, PartialEq, Default)]
|
#[derive(Debug, Eq, PartialEq, Default)]
|
||||||
pub struct ExpressionStoreBuilder {
|
pub struct ExpressionStoreBuilder {
|
||||||
|
|
@ -220,6 +262,12 @@ impl ExpressionStoreBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ExpressionStore {
|
impl ExpressionStore {
|
||||||
|
pub fn empty_singleton() -> Arc<Self> {
|
||||||
|
static EMPTY: LazyLock<Arc<ExpressionStore>> =
|
||||||
|
LazyLock::new(|| Arc::new(ExpressionStoreBuilder::default().finish()));
|
||||||
|
EMPTY.clone()
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns an iterator over all block expressions in this store that define inner items.
|
/// Returns an iterator over all block expressions in this store that define inner items.
|
||||||
pub fn blocks<'a>(
|
pub fn blocks<'a>(
|
||||||
&'a self,
|
&'a self,
|
||||||
|
|
@ -636,6 +684,12 @@ impl Index<PathId> for ExpressionStore {
|
||||||
// FIXME: Change `node_` prefix to something more reasonable.
|
// FIXME: Change `node_` prefix to something more reasonable.
|
||||||
// Perhaps `expr_syntax` and `expr_id`?
|
// Perhaps `expr_syntax` and `expr_id`?
|
||||||
impl ExpressionStoreSourceMap {
|
impl ExpressionStoreSourceMap {
|
||||||
|
pub fn empty_singleton() -> Arc<Self> {
|
||||||
|
static EMPTY: LazyLock<Arc<ExpressionStoreSourceMap>> =
|
||||||
|
LazyLock::new(|| Arc::new(ExpressionStoreSourceMap::default()));
|
||||||
|
EMPTY.clone()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn expr_or_pat_syntax(&self, id: ExprOrPatId) -> Result<ExprOrPatSource, SyntheticSyntax> {
|
pub fn expr_or_pat_syntax(&self, id: ExprOrPatId) -> Result<ExprOrPatSource, SyntheticSyntax> {
|
||||||
match id {
|
match id {
|
||||||
ExprOrPatId::ExprId(id) => self.expr_syntax(id),
|
ExprOrPatId::ExprId(id) => self.expr_syntax(id),
|
||||||
|
|
@ -682,7 +736,7 @@ impl ExpressionStoreSourceMap {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn patterns_for_binding(&self, binding: BindingId) -> &[PatId] {
|
pub fn patterns_for_binding(&self, binding: BindingId) -> &[PatId] {
|
||||||
self.binding_definitions.get(&binding).map_or(&[], Deref::deref)
|
self.binding_definitions.get(binding).map_or(&[], Deref::deref)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn node_label(&self, node: InFile<&ast::Label>) -> Option<LabelId> {
|
pub fn node_label(&self, node: InFile<&ast::Label>) -> Option<LabelId> {
|
||||||
|
|
|
||||||
|
|
@ -2250,7 +2250,7 @@ impl ExprCollector<'_> {
|
||||||
Some(ModuleDefId::ConstId(_)) => (None, Pat::Path(name.into())),
|
Some(ModuleDefId::ConstId(_)) => (None, Pat::Path(name.into())),
|
||||||
Some(ModuleDefId::EnumVariantId(variant))
|
Some(ModuleDefId::EnumVariantId(variant))
|
||||||
// FIXME: This can cause a cycle if the user is writing invalid code
|
// FIXME: This can cause a cycle if the user is writing invalid code
|
||||||
if self.db.variant_fields(variant.into()).shape != FieldsShape::Record =>
|
if variant.fields(self.db).shape != FieldsShape::Record =>
|
||||||
{
|
{
|
||||||
(None, Pat::Path(name.into()))
|
(None, Pat::Path(name.into()))
|
||||||
}
|
}
|
||||||
|
|
@ -2825,14 +2825,7 @@ impl ExprCollector<'_> {
|
||||||
let use_format_args_since_1_89_0 = fmt_args().is_some() && fmt_unsafe_arg().is_none();
|
let use_format_args_since_1_89_0 = fmt_args().is_some() && fmt_unsafe_arg().is_none();
|
||||||
|
|
||||||
let idx = if use_format_args_since_1_89_0 {
|
let idx = if use_format_args_since_1_89_0 {
|
||||||
self.collect_format_args_impl(
|
self.collect_format_args_impl(syntax_ptr, fmt, argmap, lit_pieces, format_options)
|
||||||
syntax_ptr,
|
|
||||||
fmt,
|
|
||||||
hygiene,
|
|
||||||
argmap,
|
|
||||||
lit_pieces,
|
|
||||||
format_options,
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
self.collect_format_args_before_1_89_0_impl(
|
self.collect_format_args_before_1_89_0_impl(
|
||||||
syntax_ptr,
|
syntax_ptr,
|
||||||
|
|
@ -2962,7 +2955,6 @@ impl ExprCollector<'_> {
|
||||||
&mut self,
|
&mut self,
|
||||||
syntax_ptr: AstPtr<ast::Expr>,
|
syntax_ptr: AstPtr<ast::Expr>,
|
||||||
fmt: FormatArgs,
|
fmt: FormatArgs,
|
||||||
hygiene: HygieneId,
|
|
||||||
argmap: FxIndexSet<(usize, ArgumentType)>,
|
argmap: FxIndexSet<(usize, ArgumentType)>,
|
||||||
lit_pieces: ExprId,
|
lit_pieces: ExprId,
|
||||||
format_options: ExprId,
|
format_options: ExprId,
|
||||||
|
|
@ -2997,8 +2989,11 @@ impl ExprCollector<'_> {
|
||||||
let args =
|
let args =
|
||||||
self.alloc_expr_desugared(Expr::Array(Array::ElementList { elements: args }));
|
self.alloc_expr_desugared(Expr::Array(Array::ElementList { elements: args }));
|
||||||
let args_name = Name::new_symbol_root(sym::args);
|
let args_name = Name::new_symbol_root(sym::args);
|
||||||
let args_binding =
|
let args_binding = self.alloc_binding(
|
||||||
self.alloc_binding(args_name.clone(), BindingAnnotation::Unannotated, hygiene);
|
args_name.clone(),
|
||||||
|
BindingAnnotation::Unannotated,
|
||||||
|
HygieneId::ROOT,
|
||||||
|
);
|
||||||
let args_pat = self.alloc_pat_desugared(Pat::Bind { id: args_binding, subpat: None });
|
let args_pat = self.alloc_pat_desugared(Pat::Bind { id: args_binding, subpat: None });
|
||||||
self.add_definition_to_binding(args_binding, args_pat);
|
self.add_definition_to_binding(args_binding, args_pat);
|
||||||
// TODO: We don't have `super let` yet.
|
// TODO: We don't have `super let` yet.
|
||||||
|
|
@ -3008,13 +3003,16 @@ impl ExprCollector<'_> {
|
||||||
initializer: Some(args),
|
initializer: Some(args),
|
||||||
else_branch: None,
|
else_branch: None,
|
||||||
};
|
};
|
||||||
(vec![let_stmt], self.alloc_expr_desugared(Expr::Path(Path::from(args_name))))
|
(vec![let_stmt], self.alloc_expr_desugared(Expr::Path(args_name.into())))
|
||||||
} else {
|
} else {
|
||||||
// Generate:
|
// Generate:
|
||||||
// super let args = (&arg0, &arg1, &...);
|
// super let args = (&arg0, &arg1, &...);
|
||||||
let args_name = Name::new_symbol_root(sym::args);
|
let args_name = Name::new_symbol_root(sym::args);
|
||||||
let args_binding =
|
let args_binding = self.alloc_binding(
|
||||||
self.alloc_binding(args_name.clone(), BindingAnnotation::Unannotated, hygiene);
|
args_name.clone(),
|
||||||
|
BindingAnnotation::Unannotated,
|
||||||
|
HygieneId::ROOT,
|
||||||
|
);
|
||||||
let args_pat = self.alloc_pat_desugared(Pat::Bind { id: args_binding, subpat: None });
|
let args_pat = self.alloc_pat_desugared(Pat::Bind { id: args_binding, subpat: None });
|
||||||
self.add_definition_to_binding(args_binding, args_pat);
|
self.add_definition_to_binding(args_binding, args_pat);
|
||||||
let elements = arguments
|
let elements = arguments
|
||||||
|
|
@ -3057,8 +3055,11 @@ impl ExprCollector<'_> {
|
||||||
.collect();
|
.collect();
|
||||||
let array =
|
let array =
|
||||||
self.alloc_expr_desugared(Expr::Array(Array::ElementList { elements: args }));
|
self.alloc_expr_desugared(Expr::Array(Array::ElementList { elements: args }));
|
||||||
let args_binding =
|
let args_binding = self.alloc_binding(
|
||||||
self.alloc_binding(args_name.clone(), BindingAnnotation::Unannotated, hygiene);
|
args_name.clone(),
|
||||||
|
BindingAnnotation::Unannotated,
|
||||||
|
HygieneId::ROOT,
|
||||||
|
);
|
||||||
let args_pat = self.alloc_pat_desugared(Pat::Bind { id: args_binding, subpat: None });
|
let args_pat = self.alloc_pat_desugared(Pat::Bind { id: args_binding, subpat: None });
|
||||||
self.add_definition_to_binding(args_binding, args_pat);
|
self.add_definition_to_binding(args_binding, args_pat);
|
||||||
let let_stmt2 = Statement::Let {
|
let let_stmt2 = Statement::Let {
|
||||||
|
|
|
||||||
|
|
@ -29,8 +29,8 @@ pub enum Path {
|
||||||
// This type is being used a lot, make sure it doesn't grow unintentionally.
|
// This type is being used a lot, make sure it doesn't grow unintentionally.
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
const _: () = {
|
const _: () = {
|
||||||
assert!(size_of::<Path>() == 16);
|
assert!(size_of::<Path>() == 24);
|
||||||
assert!(size_of::<Option<Path>>() == 16);
|
assert!(size_of::<Option<Path>>() == 24);
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
|
|
|
||||||
|
|
@ -121,7 +121,7 @@ pub fn print_variant_body_hir(db: &dyn DefDatabase, owner: VariantId, edition: E
|
||||||
VariantId::UnionId(it) => format!("union {}", item_name(db, it, "<missing>")),
|
VariantId::UnionId(it) => format!("union {}", item_name(db, it, "<missing>")),
|
||||||
};
|
};
|
||||||
|
|
||||||
let fields = db.variant_fields(owner);
|
let fields = owner.fields(db);
|
||||||
|
|
||||||
let mut p = Printer {
|
let mut p = Printer {
|
||||||
db,
|
db,
|
||||||
|
|
|
||||||
|
|
@ -535,7 +535,7 @@ fn foo() {
|
||||||
|
|
||||||
let resolved = scopes.resolve_name_in_scope(expr_scope, &name_ref.as_name()).unwrap();
|
let resolved = scopes.resolve_name_in_scope(expr_scope, &name_ref.as_name()).unwrap();
|
||||||
let pat_src = source_map
|
let pat_src = source_map
|
||||||
.pat_syntax(*source_map.binding_definitions[&resolved.binding()].first().unwrap())
|
.pat_syntax(*source_map.binding_definitions[resolved.binding()].first().unwrap())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let local_name = pat_src.value.syntax_node_ptr().to_node(file.syntax());
|
let local_name = pat_src.value.syntax_node_ptr().to_node(file.syntax());
|
||||||
|
|
|
||||||
|
|
@ -331,13 +331,13 @@ impl GenericParams {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn no_predicates(&self) -> bool {
|
pub fn has_no_predicates(&self) -> bool {
|
||||||
self.where_predicates.is_empty()
|
self.where_predicates.is_empty()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn where_predicates(&self) -> std::slice::Iter<'_, WherePredicate> {
|
pub fn where_predicates(&self) -> &[WherePredicate] {
|
||||||
self.where_predicates.iter()
|
&self.where_predicates
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Iterator of type_or_consts field
|
/// Iterator of type_or_consts field
|
||||||
|
|
|
||||||
|
|
@ -149,7 +149,7 @@ pub enum TypeRef {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
const _: () = assert!(size_of::<TypeRef>() == 16);
|
const _: () = assert!(size_of::<TypeRef>() == 24);
|
||||||
|
|
||||||
pub type TypeRefId = Idx<TypeRef>;
|
pub type TypeRefId = Idx<TypeRef>;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ use crate::{
|
||||||
AssocItemId, AttrDefId, Complete, FxIndexMap, ModuleDefId, ModuleId, TraitId,
|
AssocItemId, AttrDefId, Complete, FxIndexMap, ModuleDefId, ModuleId, TraitId,
|
||||||
db::DefDatabase,
|
db::DefDatabase,
|
||||||
item_scope::{ImportOrExternCrate, ItemInNs},
|
item_scope::{ImportOrExternCrate, ItemInNs},
|
||||||
nameres::{DefMap, crate_def_map},
|
nameres::{DefMap, assoc::TraitItems, crate_def_map},
|
||||||
visibility::Visibility,
|
visibility::Visibility,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -221,7 +221,7 @@ impl ImportMap {
|
||||||
trait_import_info: &ImportInfo,
|
trait_import_info: &ImportInfo,
|
||||||
) {
|
) {
|
||||||
let _p = tracing::info_span!("collect_trait_assoc_items").entered();
|
let _p = tracing::info_span!("collect_trait_assoc_items").entered();
|
||||||
for &(ref assoc_item_name, item) in &db.trait_items(tr).items {
|
for &(ref assoc_item_name, item) in &TraitItems::query(db, tr).items {
|
||||||
let module_def_id = match item {
|
let module_def_id = match item {
|
||||||
AssocItemId::FunctionId(f) => ModuleDefId::from(f),
|
AssocItemId::FunctionId(f) => ModuleDefId::from(f),
|
||||||
AssocItemId::ConstId(c) => ModuleDefId::from(c),
|
AssocItemId::ConstId(c) => ModuleDefId::from(c),
|
||||||
|
|
@ -482,7 +482,7 @@ mod tests {
|
||||||
use expect_test::{Expect, expect};
|
use expect_test::{Expect, expect};
|
||||||
use test_fixture::WithFixture;
|
use test_fixture::WithFixture;
|
||||||
|
|
||||||
use crate::{ItemContainerId, Lookup, test_db::TestDB};
|
use crate::{ItemContainerId, Lookup, nameres::assoc::TraitItems, test_db::TestDB};
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
|
@ -580,7 +580,7 @@ mod tests {
|
||||||
|
|
||||||
let trait_info = dependency_imports.import_info_for(ItemInNs::Types(trait_id.into()))?;
|
let trait_info = dependency_imports.import_info_for(ItemInNs::Types(trait_id.into()))?;
|
||||||
|
|
||||||
let trait_items = db.trait_items(trait_id);
|
let trait_items = TraitItems::query(db, trait_id);
|
||||||
let (assoc_item_name, _) = trait_items
|
let (assoc_item_name, _) = trait_items
|
||||||
.items
|
.items
|
||||||
.iter()
|
.iter()
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,10 @@ use triomphe::Arc;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
AdtId, AssocItemId, AttrDefId, Crate, EnumId, EnumVariantId, FunctionId, ImplId, ModuleDefId,
|
AdtId, AssocItemId, AttrDefId, Crate, EnumId, EnumVariantId, FunctionId, ImplId, ModuleDefId,
|
||||||
StaticId, StructId, TraitId, TypeAliasId, UnionId, db::DefDatabase, expr_store::path::Path,
|
StaticId, StructId, TraitId, TypeAliasId, UnionId,
|
||||||
nameres::crate_def_map,
|
db::DefDatabase,
|
||||||
|
expr_store::path::Path,
|
||||||
|
nameres::{assoc::TraitItems, crate_def_map},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
|
|
@ -113,14 +115,16 @@ pub fn crate_lang_items(db: &dyn DefDatabase, krate: Crate) -> Option<Box<LangIt
|
||||||
match def {
|
match def {
|
||||||
ModuleDefId::TraitId(trait_) => {
|
ModuleDefId::TraitId(trait_) => {
|
||||||
lang_items.collect_lang_item(db, trait_, LangItemTarget::Trait);
|
lang_items.collect_lang_item(db, trait_, LangItemTarget::Trait);
|
||||||
db.trait_items(trait_).items.iter().for_each(|&(_, assoc_id)| match assoc_id {
|
TraitItems::query(db, trait_).items.iter().for_each(|&(_, assoc_id)| {
|
||||||
AssocItemId::FunctionId(f) => {
|
match assoc_id {
|
||||||
lang_items.collect_lang_item(db, f, LangItemTarget::Function);
|
AssocItemId::FunctionId(f) => {
|
||||||
|
lang_items.collect_lang_item(db, f, LangItemTarget::Function);
|
||||||
|
}
|
||||||
|
AssocItemId::TypeAliasId(alias) => {
|
||||||
|
lang_items.collect_lang_item(db, alias, LangItemTarget::TypeAlias)
|
||||||
|
}
|
||||||
|
AssocItemId::ConstId(_) => {}
|
||||||
}
|
}
|
||||||
AssocItemId::TypeAliasId(alias) => {
|
|
||||||
lang_items.collect_lang_item(db, alias, LangItemTarget::TypeAlias)
|
|
||||||
}
|
|
||||||
AssocItemId::ConstId(_) => {}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
ModuleDefId::AdtId(AdtId::EnumId(e)) => {
|
ModuleDefId::AdtId(AdtId::EnumId(e)) => {
|
||||||
|
|
@ -304,6 +308,8 @@ impl LangItem {
|
||||||
language_item_table! {
|
language_item_table! {
|
||||||
// Variant name, Name, Getter method name, Target Generic requirements;
|
// Variant name, Name, Getter method name, Target Generic requirements;
|
||||||
Sized, sym::sized, sized_trait, Target::Trait, GenericRequirement::Exact(0);
|
Sized, sym::sized, sized_trait, Target::Trait, GenericRequirement::Exact(0);
|
||||||
|
MetaSized, sym::meta_sized, sized_trait, Target::Trait, GenericRequirement::Exact(0);
|
||||||
|
PointeeSized, sym::pointee_sized, sized_trait, Target::Trait, GenericRequirement::Exact(0);
|
||||||
Unsize, sym::unsize, unsize_trait, Target::Trait, GenericRequirement::Minimum(1);
|
Unsize, sym::unsize, unsize_trait, Target::Trait, GenericRequirement::Minimum(1);
|
||||||
/// Trait injected by `#[derive(PartialEq)]`, (i.e. "Partial EQ").
|
/// Trait injected by `#[derive(PartialEq)]`, (i.e. "Partial EQ").
|
||||||
StructuralPeq, sym::structural_peq, structural_peq_trait, Target::Trait, GenericRequirement::None;
|
StructuralPeq, sym::structural_peq, structural_peq_trait, Target::Trait, GenericRequirement::None;
|
||||||
|
|
|
||||||
|
|
@ -87,9 +87,12 @@ use crate::{
|
||||||
attr::Attrs,
|
attr::Attrs,
|
||||||
builtin_type::BuiltinType,
|
builtin_type::BuiltinType,
|
||||||
db::DefDatabase,
|
db::DefDatabase,
|
||||||
|
expr_store::ExpressionStoreSourceMap,
|
||||||
hir::generics::{LocalLifetimeParamId, LocalTypeOrConstParamId},
|
hir::generics::{LocalLifetimeParamId, LocalTypeOrConstParamId},
|
||||||
nameres::{
|
nameres::{
|
||||||
LocalDefMap, assoc::ImplItems, block_def_map, crate_def_map, crate_local_def_map,
|
LocalDefMap,
|
||||||
|
assoc::{ImplItems, TraitItems},
|
||||||
|
block_def_map, crate_def_map, crate_local_def_map,
|
||||||
diagnostics::DefDiagnostics,
|
diagnostics::DefDiagnostics,
|
||||||
},
|
},
|
||||||
signatures::{EnumVariants, InactiveEnumVariantCode, VariantFields},
|
signatures::{EnumVariants, InactiveEnumVariantCode, VariantFields},
|
||||||
|
|
@ -252,9 +255,35 @@ impl_intern!(FunctionId, FunctionLoc, intern_function, lookup_intern_function);
|
||||||
type StructLoc = ItemLoc<ast::Struct>;
|
type StructLoc = ItemLoc<ast::Struct>;
|
||||||
impl_intern!(StructId, StructLoc, intern_struct, lookup_intern_struct);
|
impl_intern!(StructId, StructLoc, intern_struct, lookup_intern_struct);
|
||||||
|
|
||||||
|
impl StructId {
|
||||||
|
pub fn fields(self, db: &dyn DefDatabase) -> &VariantFields {
|
||||||
|
VariantFields::firewall(db, self.into())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn fields_with_source_map(
|
||||||
|
self,
|
||||||
|
db: &dyn DefDatabase,
|
||||||
|
) -> (Arc<VariantFields>, Arc<ExpressionStoreSourceMap>) {
|
||||||
|
VariantFields::query(db, self.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub type UnionLoc = ItemLoc<ast::Union>;
|
pub type UnionLoc = ItemLoc<ast::Union>;
|
||||||
impl_intern!(UnionId, UnionLoc, intern_union, lookup_intern_union);
|
impl_intern!(UnionId, UnionLoc, intern_union, lookup_intern_union);
|
||||||
|
|
||||||
|
impl UnionId {
|
||||||
|
pub fn fields(self, db: &dyn DefDatabase) -> &VariantFields {
|
||||||
|
VariantFields::firewall(db, self.into())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn fields_with_source_map(
|
||||||
|
self,
|
||||||
|
db: &dyn DefDatabase,
|
||||||
|
) -> (Arc<VariantFields>, Arc<ExpressionStoreSourceMap>) {
|
||||||
|
VariantFields::query(db, self.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub type EnumLoc = ItemLoc<ast::Enum>;
|
pub type EnumLoc = ItemLoc<ast::Enum>;
|
||||||
impl_intern!(EnumId, EnumLoc, intern_enum, lookup_intern_enum);
|
impl_intern!(EnumId, EnumLoc, intern_enum, lookup_intern_enum);
|
||||||
|
|
||||||
|
|
@ -282,6 +311,13 @@ impl_intern!(StaticId, StaticLoc, intern_static, lookup_intern_static);
|
||||||
pub type TraitLoc = ItemLoc<ast::Trait>;
|
pub type TraitLoc = ItemLoc<ast::Trait>;
|
||||||
impl_intern!(TraitId, TraitLoc, intern_trait, lookup_intern_trait);
|
impl_intern!(TraitId, TraitLoc, intern_trait, lookup_intern_trait);
|
||||||
|
|
||||||
|
impl TraitId {
|
||||||
|
#[inline]
|
||||||
|
pub fn trait_items(self, db: &dyn DefDatabase) -> &TraitItems {
|
||||||
|
TraitItems::query(db, self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub type TraitAliasLoc = ItemLoc<ast::TraitAlias>;
|
pub type TraitAliasLoc = ItemLoc<ast::TraitAlias>;
|
||||||
impl_intern!(TraitAliasId, TraitAliasLoc, intern_trait_alias, lookup_intern_trait_alias);
|
impl_intern!(TraitAliasId, TraitAliasLoc, intern_trait_alias, lookup_intern_trait_alias);
|
||||||
|
|
||||||
|
|
@ -328,6 +364,20 @@ pub struct EnumVariantLoc {
|
||||||
}
|
}
|
||||||
impl_intern!(EnumVariantId, EnumVariantLoc, intern_enum_variant, lookup_intern_enum_variant);
|
impl_intern!(EnumVariantId, EnumVariantLoc, intern_enum_variant, lookup_intern_enum_variant);
|
||||||
impl_loc!(EnumVariantLoc, id: Variant, parent: EnumId);
|
impl_loc!(EnumVariantLoc, id: Variant, parent: EnumId);
|
||||||
|
|
||||||
|
impl EnumVariantId {
|
||||||
|
pub fn fields(self, db: &dyn DefDatabase) -> &VariantFields {
|
||||||
|
VariantFields::firewall(db, self.into())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn fields_with_source_map(
|
||||||
|
self,
|
||||||
|
db: &dyn DefDatabase,
|
||||||
|
) -> (Arc<VariantFields>, Arc<ExpressionStoreSourceMap>) {
|
||||||
|
VariantFields::query(db, self.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
pub struct Macro2Loc {
|
pub struct Macro2Loc {
|
||||||
pub container: ModuleId,
|
pub container: ModuleId,
|
||||||
|
|
@ -1015,8 +1065,15 @@ pub enum VariantId {
|
||||||
impl_from!(EnumVariantId, StructId, UnionId for VariantId);
|
impl_from!(EnumVariantId, StructId, UnionId for VariantId);
|
||||||
|
|
||||||
impl VariantId {
|
impl VariantId {
|
||||||
pub fn variant_data(self, db: &dyn DefDatabase) -> Arc<VariantFields> {
|
pub fn fields(self, db: &dyn DefDatabase) -> &VariantFields {
|
||||||
db.variant_fields(self)
|
VariantFields::firewall(db, self)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn fields_with_source_map(
|
||||||
|
self,
|
||||||
|
db: &dyn DefDatabase,
|
||||||
|
) -> (Arc<VariantFields>, Arc<ExpressionStoreSourceMap>) {
|
||||||
|
VariantFields::query(db, self)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn file_id(self, db: &dyn DefDatabase) -> HirFileId {
|
pub fn file_id(self, db: &dyn DefDatabase) -> HirFileId {
|
||||||
|
|
|
||||||
|
|
@ -746,3 +746,83 @@ struct Struct9<#[pointee] T, U>(T) where T: ?Sized;
|
||||||
623..690: `derive(CoercePointee)` requires `T` to be marked `?Sized`"#]],
|
623..690: `derive(CoercePointee)` requires `T` to be marked `?Sized`"#]],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn union_derive() {
|
||||||
|
check_errors(
|
||||||
|
r#"
|
||||||
|
//- minicore: clone, copy, default, fmt, hash, ord, eq, derive
|
||||||
|
|
||||||
|
#[derive(Copy)]
|
||||||
|
union Foo1 { _v: () }
|
||||||
|
#[derive(Clone)]
|
||||||
|
union Foo2 { _v: () }
|
||||||
|
#[derive(Default)]
|
||||||
|
union Foo3 { _v: () }
|
||||||
|
#[derive(Debug)]
|
||||||
|
union Foo4 { _v: () }
|
||||||
|
#[derive(Hash)]
|
||||||
|
union Foo5 { _v: () }
|
||||||
|
#[derive(Ord)]
|
||||||
|
union Foo6 { _v: () }
|
||||||
|
#[derive(PartialOrd)]
|
||||||
|
union Foo7 { _v: () }
|
||||||
|
#[derive(Eq)]
|
||||||
|
union Foo8 { _v: () }
|
||||||
|
#[derive(PartialEq)]
|
||||||
|
union Foo9 { _v: () }
|
||||||
|
"#,
|
||||||
|
expect![[r#"
|
||||||
|
78..118: this trait cannot be derived for unions
|
||||||
|
119..157: this trait cannot be derived for unions
|
||||||
|
158..195: this trait cannot be derived for unions
|
||||||
|
196..232: this trait cannot be derived for unions
|
||||||
|
233..276: this trait cannot be derived for unions
|
||||||
|
313..355: this trait cannot be derived for unions"#]],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn default_enum_without_default_attr() {
|
||||||
|
check_errors(
|
||||||
|
r#"
|
||||||
|
//- minicore: default, derive
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
enum Foo {
|
||||||
|
Bar,
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
expect!["1..41: `#[derive(Default)]` on enum with no `#[default]`"],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn generic_enum_default() {
|
||||||
|
check(
|
||||||
|
r#"
|
||||||
|
//- minicore: default, derive
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
enum Foo<T> {
|
||||||
|
Bar(T),
|
||||||
|
#[default]
|
||||||
|
Baz,
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
expect![[r#"
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
enum Foo<T> {
|
||||||
|
Bar(T),
|
||||||
|
#[default]
|
||||||
|
Baz,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl <T, > $crate::default::Default for Foo<T, > where {
|
||||||
|
fn default() -> Self {
|
||||||
|
Foo::Baz
|
||||||
|
}
|
||||||
|
}"#]],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -38,16 +38,18 @@ pub struct TraitItems {
|
||||||
pub macro_calls: ThinVec<(AstId<ast::Item>, MacroCallId)>,
|
pub macro_calls: ThinVec<(AstId<ast::Item>, MacroCallId)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[salsa::tracked]
|
||||||
impl TraitItems {
|
impl TraitItems {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub(crate) fn trait_items_query(db: &dyn DefDatabase, tr: TraitId) -> Arc<TraitItems> {
|
pub(crate) fn query(db: &dyn DefDatabase, tr: TraitId) -> &TraitItems {
|
||||||
db.trait_items_with_diagnostics(tr).0
|
&Self::query_with_diagnostics(db, tr).0
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn trait_items_with_diagnostics_query(
|
#[salsa::tracked(returns(ref))]
|
||||||
|
pub fn query_with_diagnostics(
|
||||||
db: &dyn DefDatabase,
|
db: &dyn DefDatabase,
|
||||||
tr: TraitId,
|
tr: TraitId,
|
||||||
) -> (Arc<TraitItems>, DefDiagnostics) {
|
) -> (TraitItems, DefDiagnostics) {
|
||||||
let ItemLoc { container: module_id, id: ast_id } = tr.lookup(db);
|
let ItemLoc { container: module_id, id: ast_id } = tr.lookup(db);
|
||||||
|
|
||||||
let collector =
|
let collector =
|
||||||
|
|
@ -55,7 +57,7 @@ impl TraitItems {
|
||||||
let source = ast_id.with_value(collector.ast_id_map.get(ast_id.value)).to_node(db);
|
let source = ast_id.with_value(collector.ast_id_map.get(ast_id.value)).to_node(db);
|
||||||
let (items, macro_calls, diagnostics) = collector.collect(source.assoc_item_list());
|
let (items, macro_calls, diagnostics) = collector.collect(source.assoc_item_list());
|
||||||
|
|
||||||
(Arc::new(TraitItems { macro_calls, items }), DefDiagnostics::new(diagnostics))
|
(TraitItems { macro_calls, items }, DefDiagnostics::new(diagnostics))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn associated_types(&self) -> impl Iterator<Item = TypeAliasId> + '_ {
|
pub fn associated_types(&self) -> impl Iterator<Item = TypeAliasId> + '_ {
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,7 @@ use crate::{
|
||||||
macro_call_as_call_id,
|
macro_call_as_call_id,
|
||||||
nameres::{
|
nameres::{
|
||||||
BuiltinShadowMode, DefMap, LocalDefMap, MacroSubNs, ModuleData, ModuleOrigin, ResolveMode,
|
BuiltinShadowMode, DefMap, LocalDefMap, MacroSubNs, ModuleData, ModuleOrigin, ResolveMode,
|
||||||
|
assoc::TraitItems,
|
||||||
attr_resolution::{attr_macro_as_call_id, derive_macro_as_call_id},
|
attr_resolution::{attr_macro_as_call_id, derive_macro_as_call_id},
|
||||||
crate_def_map,
|
crate_def_map,
|
||||||
diagnostics::DefDiagnostic,
|
diagnostics::DefDiagnostic,
|
||||||
|
|
@ -1020,8 +1021,7 @@ impl<'db> DefCollector<'db> {
|
||||||
let resolutions = if true {
|
let resolutions = if true {
|
||||||
vec![]
|
vec![]
|
||||||
} else {
|
} else {
|
||||||
self.db
|
TraitItems::query(self.db, it)
|
||||||
.trait_items(it)
|
|
||||||
.items
|
.items
|
||||||
.iter()
|
.iter()
|
||||||
.map(|&(ref name, variant)| {
|
.map(|&(ref name, variant)| {
|
||||||
|
|
|
||||||
|
|
@ -24,8 +24,8 @@ use crate::{
|
||||||
item_scope::{BUILTIN_SCOPE, ImportOrExternCrate},
|
item_scope::{BUILTIN_SCOPE, ImportOrExternCrate},
|
||||||
item_tree::FieldsShape,
|
item_tree::FieldsShape,
|
||||||
nameres::{
|
nameres::{
|
||||||
BlockInfo, BuiltinShadowMode, DefMap, LocalDefMap, MacroSubNs, crate_def_map,
|
BlockInfo, BuiltinShadowMode, DefMap, LocalDefMap, MacroSubNs, assoc::TraitItems,
|
||||||
sub_namespace_match,
|
crate_def_map, sub_namespace_match,
|
||||||
},
|
},
|
||||||
per_ns::PerNs,
|
per_ns::PerNs,
|
||||||
visibility::{RawVisibility, Visibility},
|
visibility::{RawVisibility, Visibility},
|
||||||
|
|
@ -584,8 +584,11 @@ impl DefMap {
|
||||||
// now resulting in a cycle.
|
// now resulting in a cycle.
|
||||||
// To properly implement this, trait item collection needs to be done in def map
|
// To properly implement this, trait item collection needs to be done in def map
|
||||||
// collection...
|
// collection...
|
||||||
let item =
|
let item = if true {
|
||||||
if true { None } else { db.trait_items(t).assoc_item_by_name(segment) };
|
None
|
||||||
|
} else {
|
||||||
|
TraitItems::query(db, t).assoc_item_by_name(segment)
|
||||||
|
};
|
||||||
return match item {
|
return match item {
|
||||||
Some(item) => ResolvePathResult::new(
|
Some(item) => ResolvePathResult::new(
|
||||||
match item {
|
match item {
|
||||||
|
|
|
||||||
|
|
@ -172,7 +172,7 @@ fn no() {}
|
||||||
"ast_id_map_shim",
|
"ast_id_map_shim",
|
||||||
"parse_shim",
|
"parse_shim",
|
||||||
"real_span_map_shim",
|
"real_span_map_shim",
|
||||||
"of_",
|
"EnumVariants::of_",
|
||||||
]
|
]
|
||||||
"#]],
|
"#]],
|
||||||
expect![[r#"
|
expect![[r#"
|
||||||
|
|
@ -181,7 +181,7 @@ fn no() {}
|
||||||
"ast_id_map_shim",
|
"ast_id_map_shim",
|
||||||
"file_item_tree_query",
|
"file_item_tree_query",
|
||||||
"real_span_map_shim",
|
"real_span_map_shim",
|
||||||
"of_",
|
"EnumVariants::of_",
|
||||||
]
|
]
|
||||||
"#]],
|
"#]],
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
//! Item signature IR definitions
|
//! Item signature IR definitions
|
||||||
|
|
||||||
use std::ops::Not as _;
|
use std::{cell::LazyCell, ops::Not as _};
|
||||||
|
|
||||||
use bitflags::bitflags;
|
use bitflags::bitflags;
|
||||||
use cfg::{CfgExpr, CfgOptions};
|
use cfg::{CfgExpr, CfgOptions};
|
||||||
|
|
@ -731,29 +731,26 @@ pub struct VariantFields {
|
||||||
pub store: Arc<ExpressionStore>,
|
pub store: Arc<ExpressionStore>,
|
||||||
pub shape: FieldsShape,
|
pub shape: FieldsShape,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[salsa::tracked]
|
||||||
impl VariantFields {
|
impl VariantFields {
|
||||||
#[inline]
|
#[salsa::tracked(returns(clone))]
|
||||||
pub(crate) fn query(
|
pub(crate) fn query(
|
||||||
db: &dyn DefDatabase,
|
db: &dyn DefDatabase,
|
||||||
id: VariantId,
|
id: VariantId,
|
||||||
) -> (Arc<Self>, Arc<ExpressionStoreSourceMap>) {
|
) -> (Arc<Self>, Arc<ExpressionStoreSourceMap>) {
|
||||||
let (shape, (fields, store, source_map)) = match id {
|
let (shape, result) = match id {
|
||||||
VariantId::EnumVariantId(id) => {
|
VariantId::EnumVariantId(id) => {
|
||||||
let loc = id.lookup(db);
|
let loc = id.lookup(db);
|
||||||
let parent = loc.parent.lookup(db);
|
let parent = loc.parent.lookup(db);
|
||||||
let source = loc.source(db);
|
let source = loc.source(db);
|
||||||
let shape = adt_shape(source.value.kind());
|
let shape = adt_shape(source.value.kind());
|
||||||
let span_map = db.span_map(source.file_id);
|
let enum_vis = Some(source.value.parent_enum().visibility());
|
||||||
let override_visibility = visibility_from_ast(
|
|
||||||
db,
|
|
||||||
source.value.parent_enum().visibility(),
|
|
||||||
&mut |range| span_map.span_for_range(range).ctx,
|
|
||||||
);
|
|
||||||
let fields = lower_field_list(
|
let fields = lower_field_list(
|
||||||
db,
|
db,
|
||||||
parent.container,
|
parent.container,
|
||||||
source.map(|src| src.field_list()),
|
source.map(|src| src.field_list()),
|
||||||
Some(override_visibility),
|
enum_vis,
|
||||||
);
|
);
|
||||||
(shape, fields)
|
(shape, fields)
|
||||||
}
|
}
|
||||||
|
|
@ -777,10 +774,29 @@ impl VariantFields {
|
||||||
(FieldsShape::Record, fields)
|
(FieldsShape::Record, fields)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
match result {
|
||||||
(Arc::new(VariantFields { fields, store: Arc::new(store), shape }), Arc::new(source_map))
|
Some((fields, store, source_map)) => (
|
||||||
|
Arc::new(VariantFields { fields, store: Arc::new(store), shape }),
|
||||||
|
Arc::new(source_map),
|
||||||
|
),
|
||||||
|
None => (
|
||||||
|
Arc::new(VariantFields {
|
||||||
|
fields: Arena::default(),
|
||||||
|
store: ExpressionStore::empty_singleton(),
|
||||||
|
shape,
|
||||||
|
}),
|
||||||
|
ExpressionStoreSourceMap::empty_singleton(),
|
||||||
|
),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[salsa::tracked(returns(deref))]
|
||||||
|
pub(crate) fn firewall(db: &dyn DefDatabase, id: VariantId) -> Arc<Self> {
|
||||||
|
Self::query(db, id).0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl VariantFields {
|
||||||
pub fn len(&self) -> usize {
|
pub fn len(&self) -> usize {
|
||||||
self.fields.len()
|
self.fields.len()
|
||||||
}
|
}
|
||||||
|
|
@ -798,31 +814,24 @@ fn lower_field_list(
|
||||||
db: &dyn DefDatabase,
|
db: &dyn DefDatabase,
|
||||||
module: ModuleId,
|
module: ModuleId,
|
||||||
fields: InFile<Option<ast::FieldList>>,
|
fields: InFile<Option<ast::FieldList>>,
|
||||||
override_visibility: Option<RawVisibility>,
|
override_visibility: Option<Option<ast::Visibility>>,
|
||||||
) -> (Arena<FieldData>, ExpressionStore, ExpressionStoreSourceMap) {
|
) -> Option<(Arena<FieldData>, ExpressionStore, ExpressionStoreSourceMap)> {
|
||||||
let file_id = fields.file_id;
|
let file_id = fields.file_id;
|
||||||
match fields.value {
|
match fields.value? {
|
||||||
Some(ast::FieldList::RecordFieldList(fields)) => lower_fields(
|
ast::FieldList::RecordFieldList(fields) => lower_fields(
|
||||||
db,
|
db,
|
||||||
module,
|
module,
|
||||||
InFile::new(file_id, fields.fields().map(|field| (field.ty(), field))),
|
InFile::new(file_id, fields.fields().map(|field| (field.ty(), field))),
|
||||||
|_, field| as_name_opt(field.name()),
|
|_, field| as_name_opt(field.name()),
|
||||||
override_visibility,
|
override_visibility,
|
||||||
),
|
),
|
||||||
Some(ast::FieldList::TupleFieldList(fields)) => lower_fields(
|
ast::FieldList::TupleFieldList(fields) => lower_fields(
|
||||||
db,
|
db,
|
||||||
module,
|
module,
|
||||||
InFile::new(file_id, fields.fields().map(|field| (field.ty(), field))),
|
InFile::new(file_id, fields.fields().map(|field| (field.ty(), field))),
|
||||||
|idx, _| Name::new_tuple_field(idx),
|
|idx, _| Name::new_tuple_field(idx),
|
||||||
override_visibility,
|
override_visibility,
|
||||||
),
|
),
|
||||||
None => lower_fields(
|
|
||||||
db,
|
|
||||||
module,
|
|
||||||
InFile::new(file_id, std::iter::empty::<(Option<ast::Type>, ast::RecordField)>()),
|
|
||||||
|_, _| Name::missing(),
|
|
||||||
None,
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -831,22 +840,34 @@ fn lower_fields<Field: ast::HasAttrs + ast::HasVisibility>(
|
||||||
module: ModuleId,
|
module: ModuleId,
|
||||||
fields: InFile<impl Iterator<Item = (Option<ast::Type>, Field)>>,
|
fields: InFile<impl Iterator<Item = (Option<ast::Type>, Field)>>,
|
||||||
mut field_name: impl FnMut(usize, &Field) -> Name,
|
mut field_name: impl FnMut(usize, &Field) -> Name,
|
||||||
override_visibility: Option<RawVisibility>,
|
override_visibility: Option<Option<ast::Visibility>>,
|
||||||
) -> (Arena<FieldData>, ExpressionStore, ExpressionStoreSourceMap) {
|
) -> Option<(Arena<FieldData>, ExpressionStore, ExpressionStoreSourceMap)> {
|
||||||
let mut arena = Arena::new();
|
|
||||||
let cfg_options = module.krate.cfg_options(db);
|
let cfg_options = module.krate.cfg_options(db);
|
||||||
let mut col = ExprCollector::new(db, module, fields.file_id);
|
let mut col = ExprCollector::new(db, module, fields.file_id);
|
||||||
|
let override_visibility = override_visibility.map(|vis| {
|
||||||
|
LazyCell::new(|| {
|
||||||
|
let span_map = db.span_map(fields.file_id);
|
||||||
|
visibility_from_ast(db, vis, &mut |range| span_map.span_for_range(range).ctx)
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
let mut arena = Arena::new();
|
||||||
let mut idx = 0;
|
let mut idx = 0;
|
||||||
|
let mut has_fields = false;
|
||||||
for (ty, field) in fields.value {
|
for (ty, field) in fields.value {
|
||||||
|
has_fields = true;
|
||||||
match Attrs::is_cfg_enabled_for(db, &field, col.span_map(), cfg_options) {
|
match Attrs::is_cfg_enabled_for(db, &field, col.span_map(), cfg_options) {
|
||||||
Ok(()) => {
|
Ok(()) => {
|
||||||
let type_ref =
|
let type_ref =
|
||||||
col.lower_type_ref_opt(ty, &mut ExprCollector::impl_trait_error_allocator);
|
col.lower_type_ref_opt(ty, &mut ExprCollector::impl_trait_error_allocator);
|
||||||
let visibility = override_visibility.clone().unwrap_or_else(|| {
|
let visibility = override_visibility.as_ref().map_or_else(
|
||||||
visibility_from_ast(db, field.visibility(), &mut |range| {
|
|| {
|
||||||
col.span_map().span_for_range(range).ctx
|
visibility_from_ast(db, field.visibility(), &mut |range| {
|
||||||
})
|
col.span_map().span_for_range(range).ctx
|
||||||
});
|
})
|
||||||
|
},
|
||||||
|
|it| RawVisibility::clone(it),
|
||||||
|
);
|
||||||
let is_unsafe = field
|
let is_unsafe = field
|
||||||
.syntax()
|
.syntax()
|
||||||
.children_with_tokens()
|
.children_with_tokens()
|
||||||
|
|
@ -867,9 +888,12 @@ fn lower_fields<Field: ast::HasAttrs + ast::HasVisibility>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if !has_fields {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
let store = col.store.finish();
|
let store = col.store.finish();
|
||||||
arena.shrink_to_fit();
|
arena.shrink_to_fit();
|
||||||
(arena, store, col.source_map)
|
Some((arena, store, col.source_map))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
|
|
@ -948,7 +972,7 @@ impl EnumVariants {
|
||||||
self.variants.iter().all(|&(v, _, _)| {
|
self.variants.iter().all(|&(v, _, _)| {
|
||||||
// The condition check order is slightly modified from rustc
|
// The condition check order is slightly modified from rustc
|
||||||
// to improve performance by early returning with relatively fast checks
|
// to improve performance by early returning with relatively fast checks
|
||||||
let variant = &db.variant_fields(v.into());
|
let variant = v.fields(db);
|
||||||
if !variant.fields().is_empty() {
|
if !variant.fields().is_empty() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -273,7 +273,7 @@ pub(crate) fn field_visibilities_query(
|
||||||
db: &dyn DefDatabase,
|
db: &dyn DefDatabase,
|
||||||
variant_id: VariantId,
|
variant_id: VariantId,
|
||||||
) -> Arc<ArenaMap<LocalFieldId, Visibility>> {
|
) -> Arc<ArenaMap<LocalFieldId, Visibility>> {
|
||||||
let variant_fields = db.variant_fields(variant_id);
|
let variant_fields = variant_id.fields(db);
|
||||||
let fields = variant_fields.fields();
|
let fields = variant_fields.fields();
|
||||||
if fields.is_empty() {
|
if fields.is_empty() {
|
||||||
return Arc::default();
|
return Arc::default();
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ license.workspace = true
|
||||||
rust-version.workspace = true
|
rust-version.workspace = true
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
|
doctest = false
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
cov-mark = "2.0.0"
|
cov-mark = "2.0.0"
|
||||||
|
|
|
||||||
|
|
@ -433,20 +433,19 @@ fn unescape(s: &str) -> Option<Cow<'_, str>> {
|
||||||
let mut buf = String::new();
|
let mut buf = String::new();
|
||||||
let mut prev_end = 0;
|
let mut prev_end = 0;
|
||||||
let mut has_error = false;
|
let mut has_error = false;
|
||||||
unescape::unescape_unicode(s, unescape::Mode::Str, &mut |char_range, unescaped_char| match (
|
unescape::unescape_str(s, |char_range, unescaped_char| {
|
||||||
unescaped_char,
|
match (unescaped_char, buf.capacity() == 0) {
|
||||||
buf.capacity() == 0,
|
(Ok(c), false) => buf.push(c),
|
||||||
) {
|
(Ok(_), true) if char_range.len() == 1 && char_range.start == prev_end => {
|
||||||
(Ok(c), false) => buf.push(c),
|
prev_end = char_range.end
|
||||||
(Ok(_), true) if char_range.len() == 1 && char_range.start == prev_end => {
|
}
|
||||||
prev_end = char_range.end
|
(Ok(c), true) => {
|
||||||
|
buf.reserve_exact(s.len());
|
||||||
|
buf.push_str(&s[..prev_end]);
|
||||||
|
buf.push(c);
|
||||||
|
}
|
||||||
|
(Err(_), _) => has_error = true,
|
||||||
}
|
}
|
||||||
(Ok(c), true) => {
|
|
||||||
buf.reserve_exact(s.len());
|
|
||||||
buf.push_str(&s[..prev_end]);
|
|
||||||
buf.push(c);
|
|
||||||
}
|
|
||||||
(Err(_), _) => has_error = true,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
match (has_error, buf.capacity() == 0) {
|
match (has_error, buf.capacity() == 0) {
|
||||||
|
|
|
||||||
|
|
@ -458,6 +458,7 @@ fn expand_simple_derive(
|
||||||
invoc_span: Span,
|
invoc_span: Span,
|
||||||
tt: &tt::TopSubtree,
|
tt: &tt::TopSubtree,
|
||||||
trait_path: tt::TopSubtree,
|
trait_path: tt::TopSubtree,
|
||||||
|
allow_unions: bool,
|
||||||
make_trait_body: impl FnOnce(&BasicAdtInfo) -> tt::TopSubtree,
|
make_trait_body: impl FnOnce(&BasicAdtInfo) -> tt::TopSubtree,
|
||||||
) -> ExpandResult<tt::TopSubtree> {
|
) -> ExpandResult<tt::TopSubtree> {
|
||||||
let info = match parse_adt(db, tt, invoc_span) {
|
let info = match parse_adt(db, tt, invoc_span) {
|
||||||
|
|
@ -469,6 +470,12 @@ fn expand_simple_derive(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
if !allow_unions && matches!(info.shape, AdtShape::Union) {
|
||||||
|
return ExpandResult::new(
|
||||||
|
tt::TopSubtree::empty(tt::DelimSpan::from_single(invoc_span)),
|
||||||
|
ExpandError::other(invoc_span, "this trait cannot be derived for unions"),
|
||||||
|
);
|
||||||
|
}
|
||||||
ExpandResult::ok(expand_simple_derive_with_parsed(
|
ExpandResult::ok(expand_simple_derive_with_parsed(
|
||||||
invoc_span,
|
invoc_span,
|
||||||
info,
|
info,
|
||||||
|
|
@ -535,7 +542,14 @@ fn copy_expand(
|
||||||
tt: &tt::TopSubtree,
|
tt: &tt::TopSubtree,
|
||||||
) -> ExpandResult<tt::TopSubtree> {
|
) -> ExpandResult<tt::TopSubtree> {
|
||||||
let krate = dollar_crate(span);
|
let krate = dollar_crate(span);
|
||||||
expand_simple_derive(db, span, tt, quote! {span => #krate::marker::Copy }, |_| quote! {span =>})
|
expand_simple_derive(
|
||||||
|
db,
|
||||||
|
span,
|
||||||
|
tt,
|
||||||
|
quote! {span => #krate::marker::Copy },
|
||||||
|
true,
|
||||||
|
|_| quote! {span =>},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn clone_expand(
|
fn clone_expand(
|
||||||
|
|
@ -544,7 +558,7 @@ fn clone_expand(
|
||||||
tt: &tt::TopSubtree,
|
tt: &tt::TopSubtree,
|
||||||
) -> ExpandResult<tt::TopSubtree> {
|
) -> ExpandResult<tt::TopSubtree> {
|
||||||
let krate = dollar_crate(span);
|
let krate = dollar_crate(span);
|
||||||
expand_simple_derive(db, span, tt, quote! {span => #krate::clone::Clone }, |adt| {
|
expand_simple_derive(db, span, tt, quote! {span => #krate::clone::Clone }, true, |adt| {
|
||||||
if matches!(adt.shape, AdtShape::Union) {
|
if matches!(adt.shape, AdtShape::Union) {
|
||||||
let star = tt::Punct { char: '*', spacing: ::tt::Spacing::Alone, span };
|
let star = tt::Punct { char: '*', spacing: ::tt::Spacing::Alone, span };
|
||||||
return quote! {span =>
|
return quote! {span =>
|
||||||
|
|
@ -599,41 +613,63 @@ fn default_expand(
|
||||||
tt: &tt::TopSubtree,
|
tt: &tt::TopSubtree,
|
||||||
) -> ExpandResult<tt::TopSubtree> {
|
) -> ExpandResult<tt::TopSubtree> {
|
||||||
let krate = &dollar_crate(span);
|
let krate = &dollar_crate(span);
|
||||||
expand_simple_derive(db, span, tt, quote! {span => #krate::default::Default }, |adt| {
|
let adt = match parse_adt(db, tt, span) {
|
||||||
let body = match &adt.shape {
|
Ok(info) => info,
|
||||||
AdtShape::Struct(fields) => {
|
Err(e) => {
|
||||||
let name = &adt.name;
|
return ExpandResult::new(
|
||||||
fields.as_pattern_map(
|
tt::TopSubtree::empty(tt::DelimSpan { open: span, close: span }),
|
||||||
quote!(span =>#name),
|
e,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let (body, constrain_to_trait) = match &adt.shape {
|
||||||
|
AdtShape::Struct(fields) => {
|
||||||
|
let name = &adt.name;
|
||||||
|
let body = fields.as_pattern_map(
|
||||||
|
quote!(span =>#name),
|
||||||
|
span,
|
||||||
|
|_| quote!(span =>#krate::default::Default::default()),
|
||||||
|
);
|
||||||
|
(body, true)
|
||||||
|
}
|
||||||
|
AdtShape::Enum { default_variant, variants } => {
|
||||||
|
if let Some(d) = default_variant {
|
||||||
|
let (name, fields) = &variants[*d];
|
||||||
|
let adt_name = &adt.name;
|
||||||
|
let body = fields.as_pattern_map(
|
||||||
|
quote!(span =>#adt_name :: #name),
|
||||||
span,
|
span,
|
||||||
|_| quote!(span =>#krate::default::Default::default()),
|
|_| quote!(span =>#krate::default::Default::default()),
|
||||||
)
|
);
|
||||||
}
|
(body, false)
|
||||||
AdtShape::Enum { default_variant, variants } => {
|
} else {
|
||||||
if let Some(d) = default_variant {
|
return ExpandResult::new(
|
||||||
let (name, fields) = &variants[*d];
|
tt::TopSubtree::empty(tt::DelimSpan::from_single(span)),
|
||||||
let adt_name = &adt.name;
|
ExpandError::other(span, "`#[derive(Default)]` on enum with no `#[default]`"),
|
||||||
fields.as_pattern_map(
|
);
|
||||||
quote!(span =>#adt_name :: #name),
|
|
||||||
span,
|
|
||||||
|_| quote!(span =>#krate::default::Default::default()),
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
// FIXME: Return expand error here
|
|
||||||
quote!(span =>)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
AdtShape::Union => {
|
|
||||||
// FIXME: Return expand error here
|
|
||||||
quote!(span =>)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
quote! {span =>
|
|
||||||
fn default() -> Self {
|
|
||||||
#body
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
AdtShape::Union => {
|
||||||
|
return ExpandResult::new(
|
||||||
|
tt::TopSubtree::empty(tt::DelimSpan::from_single(span)),
|
||||||
|
ExpandError::other(span, "this trait cannot be derived for unions"),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
ExpandResult::ok(expand_simple_derive_with_parsed(
|
||||||
|
span,
|
||||||
|
adt,
|
||||||
|
quote! {span => #krate::default::Default },
|
||||||
|
|_adt| {
|
||||||
|
quote! {span =>
|
||||||
|
fn default() -> Self {
|
||||||
|
#body
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
constrain_to_trait,
|
||||||
|
tt::TopSubtree::empty(tt::DelimSpan::from_single(span)),
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn debug_expand(
|
fn debug_expand(
|
||||||
|
|
@ -642,7 +678,7 @@ fn debug_expand(
|
||||||
tt: &tt::TopSubtree,
|
tt: &tt::TopSubtree,
|
||||||
) -> ExpandResult<tt::TopSubtree> {
|
) -> ExpandResult<tt::TopSubtree> {
|
||||||
let krate = &dollar_crate(span);
|
let krate = &dollar_crate(span);
|
||||||
expand_simple_derive(db, span, tt, quote! {span => #krate::fmt::Debug }, |adt| {
|
expand_simple_derive(db, span, tt, quote! {span => #krate::fmt::Debug }, false, |adt| {
|
||||||
let for_variant = |name: String, v: &VariantShape| match v {
|
let for_variant = |name: String, v: &VariantShape| match v {
|
||||||
VariantShape::Struct(fields) => {
|
VariantShape::Struct(fields) => {
|
||||||
let for_fields = fields.iter().map(|it| {
|
let for_fields = fields.iter().map(|it| {
|
||||||
|
|
@ -697,10 +733,7 @@ fn debug_expand(
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect(),
|
.collect(),
|
||||||
AdtShape::Union => {
|
AdtShape::Union => unreachable!(),
|
||||||
// FIXME: Return expand error here
|
|
||||||
vec![]
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
quote! {span =>
|
quote! {span =>
|
||||||
fn fmt(&self, f: &mut #krate::fmt::Formatter) -> #krate::fmt::Result {
|
fn fmt(&self, f: &mut #krate::fmt::Formatter) -> #krate::fmt::Result {
|
||||||
|
|
@ -718,11 +751,7 @@ fn hash_expand(
|
||||||
tt: &tt::TopSubtree,
|
tt: &tt::TopSubtree,
|
||||||
) -> ExpandResult<tt::TopSubtree> {
|
) -> ExpandResult<tt::TopSubtree> {
|
||||||
let krate = &dollar_crate(span);
|
let krate = &dollar_crate(span);
|
||||||
expand_simple_derive(db, span, tt, quote! {span => #krate::hash::Hash }, |adt| {
|
expand_simple_derive(db, span, tt, quote! {span => #krate::hash::Hash }, false, |adt| {
|
||||||
if matches!(adt.shape, AdtShape::Union) {
|
|
||||||
// FIXME: Return expand error here
|
|
||||||
return quote! {span =>};
|
|
||||||
}
|
|
||||||
if matches!(&adt.shape, AdtShape::Enum { variants, .. } if variants.is_empty()) {
|
if matches!(&adt.shape, AdtShape::Enum { variants, .. } if variants.is_empty()) {
|
||||||
let star = tt::Punct { char: '*', spacing: ::tt::Spacing::Alone, span };
|
let star = tt::Punct { char: '*', spacing: ::tt::Spacing::Alone, span };
|
||||||
return quote! {span =>
|
return quote! {span =>
|
||||||
|
|
@ -769,7 +798,14 @@ fn eq_expand(
|
||||||
tt: &tt::TopSubtree,
|
tt: &tt::TopSubtree,
|
||||||
) -> ExpandResult<tt::TopSubtree> {
|
) -> ExpandResult<tt::TopSubtree> {
|
||||||
let krate = dollar_crate(span);
|
let krate = dollar_crate(span);
|
||||||
expand_simple_derive(db, span, tt, quote! {span => #krate::cmp::Eq }, |_| quote! {span =>})
|
expand_simple_derive(
|
||||||
|
db,
|
||||||
|
span,
|
||||||
|
tt,
|
||||||
|
quote! {span => #krate::cmp::Eq },
|
||||||
|
true,
|
||||||
|
|_| quote! {span =>},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn partial_eq_expand(
|
fn partial_eq_expand(
|
||||||
|
|
@ -778,11 +814,7 @@ fn partial_eq_expand(
|
||||||
tt: &tt::TopSubtree,
|
tt: &tt::TopSubtree,
|
||||||
) -> ExpandResult<tt::TopSubtree> {
|
) -> ExpandResult<tt::TopSubtree> {
|
||||||
let krate = dollar_crate(span);
|
let krate = dollar_crate(span);
|
||||||
expand_simple_derive(db, span, tt, quote! {span => #krate::cmp::PartialEq }, |adt| {
|
expand_simple_derive(db, span, tt, quote! {span => #krate::cmp::PartialEq }, false, |adt| {
|
||||||
if matches!(adt.shape, AdtShape::Union) {
|
|
||||||
// FIXME: Return expand error here
|
|
||||||
return quote! {span =>};
|
|
||||||
}
|
|
||||||
let name = &adt.name;
|
let name = &adt.name;
|
||||||
|
|
||||||
let (self_patterns, other_patterns) = self_and_other_patterns(adt, name, span);
|
let (self_patterns, other_patterns) = self_and_other_patterns(adt, name, span);
|
||||||
|
|
@ -854,7 +886,7 @@ fn ord_expand(
|
||||||
tt: &tt::TopSubtree,
|
tt: &tt::TopSubtree,
|
||||||
) -> ExpandResult<tt::TopSubtree> {
|
) -> ExpandResult<tt::TopSubtree> {
|
||||||
let krate = &dollar_crate(span);
|
let krate = &dollar_crate(span);
|
||||||
expand_simple_derive(db, span, tt, quote! {span => #krate::cmp::Ord }, |adt| {
|
expand_simple_derive(db, span, tt, quote! {span => #krate::cmp::Ord }, false, |adt| {
|
||||||
fn compare(
|
fn compare(
|
||||||
krate: &tt::Ident,
|
krate: &tt::Ident,
|
||||||
left: tt::TopSubtree,
|
left: tt::TopSubtree,
|
||||||
|
|
@ -873,10 +905,6 @@ fn ord_expand(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if matches!(adt.shape, AdtShape::Union) {
|
|
||||||
// FIXME: Return expand error here
|
|
||||||
return quote!(span =>);
|
|
||||||
}
|
|
||||||
let (self_patterns, other_patterns) = self_and_other_patterns(adt, &adt.name, span);
|
let (self_patterns, other_patterns) = self_and_other_patterns(adt, &adt.name, span);
|
||||||
let arms = izip!(self_patterns, other_patterns, adt.shape.field_names(span)).map(
|
let arms = izip!(self_patterns, other_patterns, adt.shape.field_names(span)).map(
|
||||||
|(pat1, pat2, fields)| {
|
|(pat1, pat2, fields)| {
|
||||||
|
|
@ -916,7 +944,7 @@ fn partial_ord_expand(
|
||||||
tt: &tt::TopSubtree,
|
tt: &tt::TopSubtree,
|
||||||
) -> ExpandResult<tt::TopSubtree> {
|
) -> ExpandResult<tt::TopSubtree> {
|
||||||
let krate = &dollar_crate(span);
|
let krate = &dollar_crate(span);
|
||||||
expand_simple_derive(db, span, tt, quote! {span => #krate::cmp::PartialOrd }, |adt| {
|
expand_simple_derive(db, span, tt, quote! {span => #krate::cmp::PartialOrd }, false, |adt| {
|
||||||
fn compare(
|
fn compare(
|
||||||
krate: &tt::Ident,
|
krate: &tt::Ident,
|
||||||
left: tt::TopSubtree,
|
left: tt::TopSubtree,
|
||||||
|
|
@ -935,10 +963,6 @@ fn partial_ord_expand(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if matches!(adt.shape, AdtShape::Union) {
|
|
||||||
// FIXME: Return expand error here
|
|
||||||
return quote!(span =>);
|
|
||||||
}
|
|
||||||
let left = quote!(span =>#krate::intrinsics::discriminant_value(self));
|
let left = quote!(span =>#krate::intrinsics::discriminant_value(self));
|
||||||
let right = quote!(span =>#krate::intrinsics::discriminant_value(other));
|
let right = quote!(span =>#krate::intrinsics::discriminant_value(other));
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,12 +7,13 @@ use intern::{
|
||||||
Symbol,
|
Symbol,
|
||||||
sym::{self},
|
sym::{self},
|
||||||
};
|
};
|
||||||
|
use itertools::Itertools;
|
||||||
use mbe::{DelimiterKind, expect_fragment};
|
use mbe::{DelimiterKind, expect_fragment};
|
||||||
use span::{Edition, FileId, Span};
|
use span::{Edition, FileId, Span};
|
||||||
use stdx::format_to;
|
use stdx::format_to;
|
||||||
use syntax::{
|
use syntax::{
|
||||||
format_smolstr,
|
format_smolstr,
|
||||||
unescape::{Mode, unescape_byte, unescape_char, unescape_unicode},
|
unescape::{unescape_byte, unescape_char, unescape_str},
|
||||||
};
|
};
|
||||||
use syntax_bridge::syntax_node_to_token_tree;
|
use syntax_bridge::syntax_node_to_token_tree;
|
||||||
|
|
||||||
|
|
@ -430,7 +431,7 @@ fn compile_error_expand(
|
||||||
kind: tt::LitKind::Str | tt::LitKind::StrRaw(_),
|
kind: tt::LitKind::Str | tt::LitKind::StrRaw(_),
|
||||||
suffix: _,
|
suffix: _,
|
||||||
})),
|
})),
|
||||||
] => ExpandError::other(span, Box::from(unescape_str(text).as_str())),
|
] => ExpandError::other(span, Box::from(unescape_symbol(text).as_str())),
|
||||||
_ => ExpandError::other(span, "`compile_error!` argument must be a string"),
|
_ => ExpandError::other(span, "`compile_error!` argument must be a string"),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -481,7 +482,7 @@ fn concat_expand(
|
||||||
format_to!(text, "{}", it.symbol.as_str())
|
format_to!(text, "{}", it.symbol.as_str())
|
||||||
}
|
}
|
||||||
tt::LitKind::Str => {
|
tt::LitKind::Str => {
|
||||||
text.push_str(unescape_str(&it.symbol).as_str());
|
text.push_str(unescape_symbol(&it.symbol).as_str());
|
||||||
record_span(it.span);
|
record_span(it.span);
|
||||||
}
|
}
|
||||||
tt::LitKind::StrRaw(_) => {
|
tt::LitKind::StrRaw(_) => {
|
||||||
|
|
@ -681,52 +682,36 @@ fn relative_file(
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_string(tt: &tt::TopSubtree) -> Result<(Symbol, Span), ExpandError> {
|
fn parse_string(tt: &tt::TopSubtree) -> Result<(Symbol, Span), ExpandError> {
|
||||||
let delimiter = tt.top_subtree().delimiter;
|
let mut tt = TtElement::Subtree(tt.top_subtree(), tt.iter());
|
||||||
tt.iter()
|
(|| {
|
||||||
.next()
|
// FIXME: We wrap expression fragments in parentheses which can break this expectation
|
||||||
.ok_or(delimiter.open.cover(delimiter.close))
|
// here
|
||||||
.and_then(|tt| match tt {
|
// Remove this once we handle none delims correctly
|
||||||
|
while let TtElement::Subtree(sub, tt_iter) = &mut tt
|
||||||
|
&& let DelimiterKind::Parenthesis | DelimiterKind::Invisible = sub.delimiter.kind
|
||||||
|
{
|
||||||
|
tt =
|
||||||
|
tt_iter.exactly_one().map_err(|_| sub.delimiter.open.cover(sub.delimiter.close))?;
|
||||||
|
}
|
||||||
|
|
||||||
|
match tt {
|
||||||
TtElement::Leaf(tt::Leaf::Literal(tt::Literal {
|
TtElement::Leaf(tt::Leaf::Literal(tt::Literal {
|
||||||
symbol: text,
|
symbol: text,
|
||||||
span,
|
span,
|
||||||
kind: tt::LitKind::Str,
|
kind: tt::LitKind::Str,
|
||||||
suffix: _,
|
suffix: _,
|
||||||
})) => Ok((unescape_str(text), *span)),
|
})) => Ok((unescape_symbol(text), *span)),
|
||||||
TtElement::Leaf(tt::Leaf::Literal(tt::Literal {
|
TtElement::Leaf(tt::Leaf::Literal(tt::Literal {
|
||||||
symbol: text,
|
symbol: text,
|
||||||
span,
|
span,
|
||||||
kind: tt::LitKind::StrRaw(_),
|
kind: tt::LitKind::StrRaw(_),
|
||||||
suffix: _,
|
suffix: _,
|
||||||
})) => Ok((text.clone(), *span)),
|
})) => Ok((text.clone(), *span)),
|
||||||
// FIXME: We wrap expression fragments in parentheses which can break this expectation
|
|
||||||
// here
|
|
||||||
// Remove this once we handle none delims correctly
|
|
||||||
TtElement::Subtree(tt, mut tt_iter)
|
|
||||||
if tt.delimiter.kind == DelimiterKind::Parenthesis =>
|
|
||||||
{
|
|
||||||
tt_iter
|
|
||||||
.next()
|
|
||||||
.and_then(|tt| match tt {
|
|
||||||
TtElement::Leaf(tt::Leaf::Literal(tt::Literal {
|
|
||||||
symbol: text,
|
|
||||||
span,
|
|
||||||
kind: tt::LitKind::Str,
|
|
||||||
suffix: _,
|
|
||||||
})) => Some((unescape_str(text), *span)),
|
|
||||||
TtElement::Leaf(tt::Leaf::Literal(tt::Literal {
|
|
||||||
symbol: text,
|
|
||||||
span,
|
|
||||||
kind: tt::LitKind::StrRaw(_),
|
|
||||||
suffix: _,
|
|
||||||
})) => Some((text.clone(), *span)),
|
|
||||||
_ => None,
|
|
||||||
})
|
|
||||||
.ok_or(delimiter.open.cover(delimiter.close))
|
|
||||||
}
|
|
||||||
TtElement::Leaf(l) => Err(*l.span()),
|
TtElement::Leaf(l) => Err(*l.span()),
|
||||||
TtElement::Subtree(tt, _) => Err(tt.delimiter.open.cover(tt.delimiter.close)),
|
TtElement::Subtree(tt, _) => Err(tt.delimiter.open.cover(tt.delimiter.close)),
|
||||||
})
|
}
|
||||||
.map_err(|span| ExpandError::other(span, "expected string literal"))
|
})()
|
||||||
|
.map_err(|span| ExpandError::other(span, "expected string literal"))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn include_expand(
|
fn include_expand(
|
||||||
|
|
@ -897,11 +882,11 @@ fn quote_expand(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn unescape_str(s: &Symbol) -> Symbol {
|
fn unescape_symbol(s: &Symbol) -> Symbol {
|
||||||
if s.as_str().contains('\\') {
|
if s.as_str().contains('\\') {
|
||||||
let s = s.as_str();
|
let s = s.as_str();
|
||||||
let mut buf = String::with_capacity(s.len());
|
let mut buf = String::with_capacity(s.len());
|
||||||
unescape_unicode(s, Mode::Str, &mut |_, c| {
|
unescape_str(s, |_, c| {
|
||||||
if let Ok(c) = c {
|
if let Ok(c) = c {
|
||||||
buf.push(c)
|
buf.push(c)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -145,7 +145,7 @@ pub trait ExpandDatabase: RootQueryDb {
|
||||||
fn syntax_context(&self, file: HirFileId, edition: Edition) -> SyntaxContext;
|
fn syntax_context(&self, file: HirFileId, edition: Edition) -> SyntaxContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[salsa_macros::interned(no_lifetime, id = span::SyntaxContext)]
|
#[salsa_macros::interned(no_lifetime, id = span::SyntaxContext, revisions = usize::MAX)]
|
||||||
pub struct SyntaxContextWrapper {
|
pub struct SyntaxContextWrapper {
|
||||||
pub data: SyntaxContext,
|
pub data: SyntaxContext,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -315,11 +315,11 @@ impl<SN: Borrow<SyntaxNode>> InFile<SN> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Falls back to the macro call range if the node cannot be mapped up fully.
|
/// Falls back to the macro call range if the node cannot be mapped up fully.
|
||||||
pub fn original_file_range_with_macro_call_body(
|
pub fn original_file_range_with_macro_call_input(
|
||||||
self,
|
self,
|
||||||
db: &dyn db::ExpandDatabase,
|
db: &dyn db::ExpandDatabase,
|
||||||
) -> FileRange {
|
) -> FileRange {
|
||||||
self.borrow().map(SyntaxNode::text_range).original_node_file_range_with_macro_call_body(db)
|
self.borrow().map(SyntaxNode::text_range).original_node_file_range_with_macro_call_input(db)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn original_syntax_node_rooted(
|
pub fn original_syntax_node_rooted(
|
||||||
|
|
@ -465,7 +465,7 @@ impl InFile<TextRange> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn original_node_file_range_with_macro_call_body(
|
pub fn original_node_file_range_with_macro_call_input(
|
||||||
self,
|
self,
|
||||||
db: &dyn db::ExpandDatabase,
|
db: &dyn db::ExpandDatabase,
|
||||||
) -> FileRange {
|
) -> FileRange {
|
||||||
|
|
@ -476,7 +476,7 @@ impl InFile<TextRange> {
|
||||||
Some(it) => it,
|
Some(it) => it,
|
||||||
_ => {
|
_ => {
|
||||||
let loc = db.lookup_intern_macro_call(mac_file);
|
let loc = db.lookup_intern_macro_call(mac_file);
|
||||||
loc.kind.original_call_range_with_body(db)
|
loc.kind.original_call_range_with_input(db)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -497,6 +497,18 @@ impl InFile<TextRange> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn original_node_file_range_rooted_opt(
|
||||||
|
self,
|
||||||
|
db: &dyn db::ExpandDatabase,
|
||||||
|
) -> Option<FileRange> {
|
||||||
|
match self.file_id {
|
||||||
|
HirFileId::FileId(file_id) => Some(FileRange { file_id, range: self.value }),
|
||||||
|
HirFileId::MacroFile(mac_file) => {
|
||||||
|
map_node_range_up_rooted(db, &db.expansion_span_map(mac_file), self.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<N: AstNode> InFile<N> {
|
impl<N: AstNode> InFile<N> {
|
||||||
|
|
|
||||||
|
|
@ -199,9 +199,9 @@ impl ExpandErrorKind {
|
||||||
},
|
},
|
||||||
&ExpandErrorKind::MissingProcMacroExpander(def_crate) => {
|
&ExpandErrorKind::MissingProcMacroExpander(def_crate) => {
|
||||||
match db.proc_macros_for_crate(def_crate).as_ref().and_then(|it| it.get_error()) {
|
match db.proc_macros_for_crate(def_crate).as_ref().and_then(|it| it.get_error()) {
|
||||||
Some((e, hard_err)) => RenderedExpandError {
|
Some(e) => RenderedExpandError {
|
||||||
message: e.to_owned(),
|
message: e.to_string(),
|
||||||
error: hard_err,
|
error: e.is_hard_error(),
|
||||||
kind: RenderedExpandError::GENERAL_KIND,
|
kind: RenderedExpandError::GENERAL_KIND,
|
||||||
},
|
},
|
||||||
None => RenderedExpandError {
|
None => RenderedExpandError {
|
||||||
|
|
@ -688,8 +688,11 @@ impl MacroCallKind {
|
||||||
|
|
||||||
/// Returns the original file range that best describes the location of this macro call.
|
/// Returns the original file range that best describes the location of this macro call.
|
||||||
///
|
///
|
||||||
/// Unlike `MacroCallKind::original_call_range`, this also spans the item of attributes and derives.
|
/// This spans the entire macro call, including its input. That is for
|
||||||
pub fn original_call_range_with_body(self, db: &dyn ExpandDatabase) -> FileRange {
|
/// - fn_like! {}, it spans the path and token tree
|
||||||
|
/// - #\[derive], it spans the `#[derive(...)]` attribute and the annotated item
|
||||||
|
/// - #\[attr], it spans the `#[attr(...)]` attribute and the annotated item
|
||||||
|
pub fn original_call_range_with_input(self, db: &dyn ExpandDatabase) -> FileRange {
|
||||||
let mut kind = self;
|
let mut kind = self;
|
||||||
let file_id = loop {
|
let file_id = loop {
|
||||||
match kind.file_id() {
|
match kind.file_id() {
|
||||||
|
|
@ -712,8 +715,8 @@ impl MacroCallKind {
|
||||||
/// Returns the original file range that best describes the location of this macro call.
|
/// Returns the original file range that best describes the location of this macro call.
|
||||||
///
|
///
|
||||||
/// Here we try to roughly match what rustc does to improve diagnostics: fn-like macros
|
/// Here we try to roughly match what rustc does to improve diagnostics: fn-like macros
|
||||||
/// get the whole `ast::MacroCall`, attribute macros get the attribute's range, and derives
|
/// get the macro path (rustc shows the whole `ast::MacroCall`), attribute macros get the
|
||||||
/// get only the specific derive that is being referred to.
|
/// attribute's range, and derives get only the specific derive that is being referred to.
|
||||||
pub fn original_call_range(self, db: &dyn ExpandDatabase) -> FileRange {
|
pub fn original_call_range(self, db: &dyn ExpandDatabase) -> FileRange {
|
||||||
let mut kind = self;
|
let mut kind = self;
|
||||||
let file_id = loop {
|
let file_id = loop {
|
||||||
|
|
@ -726,7 +729,14 @@ impl MacroCallKind {
|
||||||
};
|
};
|
||||||
|
|
||||||
let range = match kind {
|
let range = match kind {
|
||||||
MacroCallKind::FnLike { ast_id, .. } => ast_id.to_ptr(db).text_range(),
|
MacroCallKind::FnLike { ast_id, .. } => {
|
||||||
|
let node = ast_id.to_node(db);
|
||||||
|
node.path()
|
||||||
|
.unwrap()
|
||||||
|
.syntax()
|
||||||
|
.text_range()
|
||||||
|
.cover(node.excl_token().unwrap().text_range())
|
||||||
|
}
|
||||||
MacroCallKind::Derive { ast_id, derive_attr_index, .. } => {
|
MacroCallKind::Derive { ast_id, derive_attr_index, .. } => {
|
||||||
// FIXME: should be the range of the macro name, not the whole derive
|
// FIXME: should be the range of the macro name, not the whole derive
|
||||||
// FIXME: handle `cfg_attr`
|
// FIXME: handle `cfg_attr`
|
||||||
|
|
@ -1056,7 +1066,7 @@ impl ExpandTo {
|
||||||
|
|
||||||
intern::impl_internable!(ModPath, attrs::AttrInput);
|
intern::impl_internable!(ModPath, attrs::AttrInput);
|
||||||
|
|
||||||
#[salsa_macros::interned(no_lifetime, debug)]
|
#[salsa_macros::interned(no_lifetime, debug, revisions = usize::MAX)]
|
||||||
#[doc(alias = "MacroFileId")]
|
#[doc(alias = "MacroFileId")]
|
||||||
pub struct MacroCallId {
|
pub struct MacroCallId {
|
||||||
pub loc: MacroCallLoc,
|
pub loc: MacroCallLoc,
|
||||||
|
|
|
||||||
|
|
@ -179,9 +179,10 @@ impl Name {
|
||||||
self.symbol.as_str()
|
self.symbol.as_str()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn display<'a>(
|
pub fn display<'a>(
|
||||||
&'a self,
|
&'a self,
|
||||||
db: &dyn crate::db::ExpandDatabase,
|
db: &dyn salsa::Database,
|
||||||
edition: Edition,
|
edition: Edition,
|
||||||
) -> impl fmt::Display + 'a {
|
) -> impl fmt::Display + 'a {
|
||||||
_ = db;
|
_ = db;
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,7 @@ pub fn prettify_macro_expansion(
|
||||||
} else if let Some(crate_name) = ¯o_def_crate.extra_data(db).display_name {
|
} else if let Some(crate_name) = ¯o_def_crate.extra_data(db).display_name {
|
||||||
make::tokens::ident(crate_name.crate_name().as_str())
|
make::tokens::ident(crate_name.crate_name().as_str())
|
||||||
} else {
|
} else {
|
||||||
return dollar_crate.clone();
|
dollar_crate.clone()
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if replacement.text() == "$crate" {
|
if replacement.text() == "$crate" {
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ use core::fmt;
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use std::{panic::RefUnwindSafe, sync};
|
use std::{panic::RefUnwindSafe, sync};
|
||||||
|
|
||||||
use base_db::{Crate, CrateBuilderId, CratesIdMap, Env};
|
use base_db::{Crate, CrateBuilderId, CratesIdMap, Env, ProcMacroLoadingError};
|
||||||
use intern::Symbol;
|
use intern::Symbol;
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
use span::Span;
|
use span::Span;
|
||||||
|
|
@ -53,8 +53,8 @@ pub enum ProcMacroExpansionError {
|
||||||
System(String),
|
System(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type ProcMacroLoadResult = Result<Vec<ProcMacro>, (String, bool)>;
|
pub type ProcMacroLoadResult = Result<Vec<ProcMacro>, ProcMacroLoadingError>;
|
||||||
type StoredProcMacroLoadResult = Result<Box<[ProcMacro]>, (Box<str>, bool)>;
|
type StoredProcMacroLoadResult = Result<Box<[ProcMacro]>, ProcMacroLoadingError>;
|
||||||
|
|
||||||
#[derive(Default, Debug)]
|
#[derive(Default, Debug)]
|
||||||
pub struct ProcMacrosBuilder(FxHashMap<CrateBuilderId, Arc<CrateProcMacros>>);
|
pub struct ProcMacrosBuilder(FxHashMap<CrateBuilderId, Arc<CrateProcMacros>>);
|
||||||
|
|
@ -77,9 +77,7 @@ impl ProcMacrosBuilder {
|
||||||
proc_macros_crate,
|
proc_macros_crate,
|
||||||
match proc_macro {
|
match proc_macro {
|
||||||
Ok(it) => Arc::new(CrateProcMacros(Ok(it.into_boxed_slice()))),
|
Ok(it) => Arc::new(CrateProcMacros(Ok(it.into_boxed_slice()))),
|
||||||
Err((e, hard_err)) => {
|
Err(e) => Arc::new(CrateProcMacros(Err(e))),
|
||||||
Arc::new(CrateProcMacros(Err((e.into_boxed_str(), hard_err))))
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -139,8 +137,8 @@ impl CrateProcMacros {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_error(&self) -> Option<(&str, bool)> {
|
pub fn get_error(&self) -> Option<&ProcMacroLoadingError> {
|
||||||
self.0.as_ref().err().map(|(e, hard_err)| (&**e, *hard_err))
|
self.0.as_ref().err()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Fetch the [`CustomProcMacroExpander`]s and their corresponding names for the given crate.
|
/// Fetch the [`CustomProcMacroExpander`]s and their corresponding names for the given crate.
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ license.workspace = true
|
||||||
rust-version.workspace = true
|
rust-version.workspace = true
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
|
doctest = false
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
cov-mark = "2.0.0"
|
cov-mark = "2.0.0"
|
||||||
|
|
|
||||||
|
|
@ -208,7 +208,7 @@ pub(crate) fn deref_by_trait(
|
||||||
};
|
};
|
||||||
let trait_id = trait_id()?;
|
let trait_id = trait_id()?;
|
||||||
let target =
|
let target =
|
||||||
db.trait_items(trait_id).associated_type_by_name(&Name::new_symbol_root(sym::Target))?;
|
trait_id.trait_items(db).associated_type_by_name(&Name::new_symbol_root(sym::Target))?;
|
||||||
|
|
||||||
let projection = {
|
let projection = {
|
||||||
let b = TyBuilder::subst_for_def(db, trait_id, None);
|
let b = TyBuilder::subst_for_def(db, trait_id, None);
|
||||||
|
|
|
||||||
|
|
@ -315,9 +315,8 @@ impl chalk_solve::RustIrDatabase<Interner> for ChalkContext<'_> {
|
||||||
crate::ImplTraitId::AsyncBlockTypeImplTrait(..) => {
|
crate::ImplTraitId::AsyncBlockTypeImplTrait(..) => {
|
||||||
if let Some((future_trait, future_output)) =
|
if let Some((future_trait, future_output)) =
|
||||||
LangItem::Future.resolve_trait(self.db, self.krate).and_then(|trait_| {
|
LangItem::Future.resolve_trait(self.db, self.krate).and_then(|trait_| {
|
||||||
let alias = self
|
let alias = trait_
|
||||||
.db
|
.trait_items(self.db)
|
||||||
.trait_items(trait_)
|
|
||||||
.associated_type_by_name(&Name::new_symbol_root(sym::Output))?;
|
.associated_type_by_name(&Name::new_symbol_root(sym::Output))?;
|
||||||
Some((trait_, alias))
|
Some((trait_, alias))
|
||||||
})
|
})
|
||||||
|
|
@ -711,7 +710,7 @@ pub(crate) fn trait_datum_query(
|
||||||
};
|
};
|
||||||
let where_clauses = convert_where_clauses(db, trait_.into(), &bound_vars);
|
let where_clauses = convert_where_clauses(db, trait_.into(), &bound_vars);
|
||||||
let associated_ty_ids =
|
let associated_ty_ids =
|
||||||
db.trait_items(trait_).associated_types().map(to_assoc_type_id).collect();
|
trait_.trait_items(db).associated_types().map(to_assoc_type_id).collect();
|
||||||
let trait_datum_bound = rust_ir::TraitDatumBound { where_clauses };
|
let trait_datum_bound = rust_ir::TraitDatumBound { where_clauses };
|
||||||
let well_known = db.lang_attr(trait_.into()).and_then(well_known_trait_from_lang_item);
|
let well_known = db.lang_attr(trait_.into()).and_then(well_known_trait_from_lang_item);
|
||||||
let trait_datum = TraitDatum {
|
let trait_datum = TraitDatum {
|
||||||
|
|
@ -802,7 +801,7 @@ pub(crate) fn adt_datum_query(
|
||||||
|
|
||||||
// this slows down rust-analyzer by quite a bit unfortunately, so enabling this is currently not worth it
|
// this slows down rust-analyzer by quite a bit unfortunately, so enabling this is currently not worth it
|
||||||
let _variant_id_to_fields = |id: VariantId| {
|
let _variant_id_to_fields = |id: VariantId| {
|
||||||
let variant_data = &id.variant_data(db);
|
let variant_data = &id.fields(db);
|
||||||
let fields = if variant_data.fields().is_empty() {
|
let fields = if variant_data.fields().is_empty() {
|
||||||
vec![]
|
vec![]
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -879,7 +878,7 @@ fn impl_def_datum(db: &dyn HirDatabase, krate: Crate, impl_id: hir_def::ImplId)
|
||||||
let polarity = if negative { rust_ir::Polarity::Negative } else { rust_ir::Polarity::Positive };
|
let polarity = if negative { rust_ir::Polarity::Negative } else { rust_ir::Polarity::Positive };
|
||||||
|
|
||||||
let impl_datum_bound = rust_ir::ImplDatumBound { trait_ref, where_clauses };
|
let impl_datum_bound = rust_ir::ImplDatumBound { trait_ref, where_clauses };
|
||||||
let trait_data = db.trait_items(trait_);
|
let trait_data = trait_.trait_items(db);
|
||||||
let associated_ty_value_ids = impl_id
|
let associated_ty_value_ids = impl_id
|
||||||
.impl_items(db)
|
.impl_items(db)
|
||||||
.items
|
.items
|
||||||
|
|
@ -931,8 +930,9 @@ fn type_alias_associated_ty_value(
|
||||||
.into_value_and_skipped_binders()
|
.into_value_and_skipped_binders()
|
||||||
.0; // we don't return any assoc ty values if the impl'd trait can't be resolved
|
.0; // we don't return any assoc ty values if the impl'd trait can't be resolved
|
||||||
|
|
||||||
let assoc_ty = db
|
let assoc_ty = trait_ref
|
||||||
.trait_items(trait_ref.hir_trait_id())
|
.hir_trait_id()
|
||||||
|
.trait_items(db)
|
||||||
.associated_type_by_name(&type_alias_data.name)
|
.associated_type_by_name(&type_alias_data.name)
|
||||||
.expect("assoc ty value should not exist"); // validated when building the impl data as well
|
.expect("assoc ty value should not exist"); // validated when building the impl data as well
|
||||||
let (ty, binders) = db.ty(type_alias.into()).into_value_and_skipped_binders();
|
let (ty, binders) = db.ty(type_alias.into()).into_value_and_skipped_binders();
|
||||||
|
|
|
||||||
|
|
@ -236,15 +236,6 @@ pub trait HirDatabase: DefDatabase + std::fmt::Debug {
|
||||||
fn trait_impls_in_deps(&self, krate: Crate) -> Arc<[Arc<TraitImpls>]>;
|
fn trait_impls_in_deps(&self, krate: Crate) -> Arc<[Arc<TraitImpls>]>;
|
||||||
|
|
||||||
// Interned IDs for Chalk integration
|
// Interned IDs for Chalk integration
|
||||||
#[salsa::interned]
|
|
||||||
fn intern_type_or_const_param_id(
|
|
||||||
&self,
|
|
||||||
param_id: TypeOrConstParamId,
|
|
||||||
) -> InternedTypeOrConstParamId;
|
|
||||||
|
|
||||||
#[salsa::interned]
|
|
||||||
fn intern_lifetime_param_id(&self, param_id: LifetimeParamId) -> InternedLifetimeParamId;
|
|
||||||
|
|
||||||
#[salsa::interned]
|
#[salsa::interned]
|
||||||
fn intern_impl_trait_id(&self, id: ImplTraitId) -> InternedOpaqueTyId;
|
fn intern_impl_trait_id(&self, id: ImplTraitId) -> InternedOpaqueTyId;
|
||||||
|
|
||||||
|
|
@ -282,9 +273,8 @@ pub trait HirDatabase: DefDatabase + std::fmt::Debug {
|
||||||
|
|
||||||
#[salsa::invoke(crate::variance::variances_of)]
|
#[salsa::invoke(crate::variance::variances_of)]
|
||||||
#[salsa::cycle(
|
#[salsa::cycle(
|
||||||
// cycle_fn = crate::variance::variances_of_cycle_fn,
|
cycle_fn = crate::variance::variances_of_cycle_fn,
|
||||||
// cycle_initial = crate::variance::variances_of_cycle_initial,
|
cycle_initial = crate::variance::variances_of_cycle_initial,
|
||||||
cycle_result = crate::variance::variances_of_cycle_initial,
|
|
||||||
)]
|
)]
|
||||||
fn variances_of(&self, def: GenericDefId) -> Option<Arc<[crate::variance::Variance]>>;
|
fn variances_of(&self, def: GenericDefId) -> Option<Arc<[crate::variance::Variance]>>;
|
||||||
|
|
||||||
|
|
@ -329,9 +319,31 @@ fn hir_database_is_dyn_compatible() {
|
||||||
fn _assert_dyn_compatible(_: &dyn HirDatabase) {}
|
fn _assert_dyn_compatible(_: &dyn HirDatabase) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_intern_key!(InternedTypeOrConstParamId, TypeOrConstParamId);
|
#[salsa_macros::interned(no_lifetime, revisions = usize::MAX)]
|
||||||
|
#[derive(PartialOrd, Ord)]
|
||||||
|
pub struct InternedTypeOrConstParamId {
|
||||||
|
pub loc: TypeOrConstParamId,
|
||||||
|
}
|
||||||
|
impl ::std::fmt::Debug for InternedTypeOrConstParamId {
|
||||||
|
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
|
||||||
|
f.debug_tuple(stringify!(InternedTypeOrConstParamId))
|
||||||
|
.field(&format_args!("{:04x}", self.0.index()))
|
||||||
|
.finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl_intern_key!(InternedLifetimeParamId, LifetimeParamId);
|
#[salsa_macros::interned(no_lifetime, revisions = usize::MAX)]
|
||||||
|
#[derive(PartialOrd, Ord)]
|
||||||
|
pub struct InternedLifetimeParamId {
|
||||||
|
pub loc: LifetimeParamId,
|
||||||
|
}
|
||||||
|
impl ::std::fmt::Debug for InternedLifetimeParamId {
|
||||||
|
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
|
||||||
|
f.debug_tuple(stringify!(InternedLifetimeParamId))
|
||||||
|
.field(&format_args!("{:04x}", self.0.index()))
|
||||||
|
.finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl_intern_key!(InternedConstParamId, ConstParamId);
|
impl_intern_key!(InternedConstParamId, ConstParamId);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -307,7 +307,7 @@ impl<'a> DeclValidator<'a> {
|
||||||
|
|
||||||
/// Check incorrect names for struct fields.
|
/// Check incorrect names for struct fields.
|
||||||
fn validate_struct_fields(&mut self, struct_id: StructId) {
|
fn validate_struct_fields(&mut self, struct_id: StructId) {
|
||||||
let data = self.db.variant_fields(struct_id.into());
|
let data = struct_id.fields(self.db);
|
||||||
if data.shape != FieldsShape::Record {
|
if data.shape != FieldsShape::Record {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
@ -468,7 +468,7 @@ impl<'a> DeclValidator<'a> {
|
||||||
|
|
||||||
/// Check incorrect names for fields of enum variant.
|
/// Check incorrect names for fields of enum variant.
|
||||||
fn validate_enum_variant_fields(&mut self, variant_id: EnumVariantId) {
|
fn validate_enum_variant_fields(&mut self, variant_id: EnumVariantId) {
|
||||||
let variant_data = self.db.variant_fields(variant_id.into());
|
let variant_data = variant_id.fields(self.db);
|
||||||
if variant_data.shape != FieldsShape::Record {
|
if variant_data.shape != FieldsShape::Record {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -494,7 +494,7 @@ impl FilterMapNextChecker {
|
||||||
Some(next_function_id),
|
Some(next_function_id),
|
||||||
match next_function_id.lookup(db).container {
|
match next_function_id.lookup(db).container {
|
||||||
ItemContainerId::TraitId(iterator_trait_id) => {
|
ItemContainerId::TraitId(iterator_trait_id) => {
|
||||||
let iterator_trait_items = &db.trait_items(iterator_trait_id).items;
|
let iterator_trait_items = &iterator_trait_id.trait_items(db).items;
|
||||||
iterator_trait_items.iter().find_map(|(name, it)| match it {
|
iterator_trait_items.iter().find_map(|(name, it)| match it {
|
||||||
&AssocItemId::FunctionId(id) if *name == sym::filter_map => Some(id),
|
&AssocItemId::FunctionId(id) if *name == sym::filter_map => Some(id),
|
||||||
_ => None,
|
_ => None,
|
||||||
|
|
@ -558,7 +558,7 @@ pub fn record_literal_missing_fields(
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let variant_data = variant_def.variant_data(db);
|
let variant_data = variant_def.fields(db);
|
||||||
|
|
||||||
let specified_fields: FxHashSet<_> = fields.iter().map(|f| &f.name).collect();
|
let specified_fields: FxHashSet<_> = fields.iter().map(|f| &f.name).collect();
|
||||||
let missed_fields: Vec<LocalFieldId> = variant_data
|
let missed_fields: Vec<LocalFieldId> = variant_data
|
||||||
|
|
@ -588,7 +588,7 @@ pub fn record_pattern_missing_fields(
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let variant_data = variant_def.variant_data(db);
|
let variant_data = variant_def.fields(db);
|
||||||
|
|
||||||
let specified_fields: FxHashSet<_> = fields.iter().map(|f| &f.name).collect();
|
let specified_fields: FxHashSet<_> = fields.iter().map(|f| &f.name).collect();
|
||||||
let missed_fields: Vec<LocalFieldId> = variant_data
|
let missed_fields: Vec<LocalFieldId> = variant_data
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,6 @@ use crate::{
|
||||||
db::HirDatabase,
|
db::HirDatabase,
|
||||||
display::{HirDisplay, HirDisplayError, HirFormatter},
|
display::{HirDisplay, HirDisplayError, HirFormatter},
|
||||||
infer::BindingMode,
|
infer::BindingMode,
|
||||||
lang_items::is_box,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use self::pat_util::EnumerateAndAdjustIterator;
|
use self::pat_util::EnumerateAndAdjustIterator;
|
||||||
|
|
@ -77,7 +76,7 @@ pub(crate) enum PatKind {
|
||||||
subpatterns: Vec<FieldPat>,
|
subpatterns: Vec<FieldPat>,
|
||||||
},
|
},
|
||||||
|
|
||||||
/// `box P`, `&P`, `&mut P`, etc.
|
/// `&P`, `&mut P`, etc.
|
||||||
Deref {
|
Deref {
|
||||||
subpattern: Pat,
|
subpattern: Pat,
|
||||||
},
|
},
|
||||||
|
|
@ -169,13 +168,13 @@ impl<'a> PatCtxt<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
hir_def::hir::Pat::TupleStruct { ref args, ellipsis, .. } if variant.is_some() => {
|
hir_def::hir::Pat::TupleStruct { ref args, ellipsis, .. } if variant.is_some() => {
|
||||||
let expected_len = variant.unwrap().variant_data(self.db).fields().len();
|
let expected_len = variant.unwrap().fields(self.db).fields().len();
|
||||||
let subpatterns = self.lower_tuple_subpats(args, expected_len, ellipsis);
|
let subpatterns = self.lower_tuple_subpats(args, expected_len, ellipsis);
|
||||||
self.lower_variant_or_leaf(pat, ty, subpatterns)
|
self.lower_variant_or_leaf(pat, ty, subpatterns)
|
||||||
}
|
}
|
||||||
|
|
||||||
hir_def::hir::Pat::Record { ref args, .. } if variant.is_some() => {
|
hir_def::hir::Pat::Record { ref args, .. } if variant.is_some() => {
|
||||||
let variant_data = variant.unwrap().variant_data(self.db);
|
let variant_data = variant.unwrap().fields(self.db);
|
||||||
let subpatterns = args
|
let subpatterns = args
|
||||||
.iter()
|
.iter()
|
||||||
.map(|field| {
|
.map(|field| {
|
||||||
|
|
@ -345,7 +344,7 @@ impl HirDisplay for Pat {
|
||||||
)?,
|
)?,
|
||||||
};
|
};
|
||||||
|
|
||||||
let variant_data = variant.variant_data(f.db);
|
let variant_data = variant.fields(f.db);
|
||||||
if variant_data.shape == FieldsShape::Record {
|
if variant_data.shape == FieldsShape::Record {
|
||||||
write!(f, " {{ ")?;
|
write!(f, " {{ ")?;
|
||||||
|
|
||||||
|
|
@ -377,7 +376,7 @@ impl HirDisplay for Pat {
|
||||||
}
|
}
|
||||||
|
|
||||||
let num_fields =
|
let num_fields =
|
||||||
variant.map_or(subpatterns.len(), |v| v.variant_data(f.db).fields().len());
|
variant.map_or(subpatterns.len(), |v| v.fields(f.db).fields().len());
|
||||||
if num_fields != 0 || variant.is_none() {
|
if num_fields != 0 || variant.is_none() {
|
||||||
write!(f, "(")?;
|
write!(f, "(")?;
|
||||||
let subpats = (0..num_fields).map(|i| {
|
let subpats = (0..num_fields).map(|i| {
|
||||||
|
|
@ -406,7 +405,6 @@ impl HirDisplay for Pat {
|
||||||
}
|
}
|
||||||
PatKind::Deref { subpattern } => {
|
PatKind::Deref { subpattern } => {
|
||||||
match self.ty.kind(Interner) {
|
match self.ty.kind(Interner) {
|
||||||
TyKind::Adt(adt, _) if is_box(f.db, adt.0) => write!(f, "box ")?,
|
|
||||||
&TyKind::Ref(mutbl, ..) => {
|
&TyKind::Ref(mutbl, ..) => {
|
||||||
write!(f, "&{}", if mutbl == Mutability::Mut { "mut " } else { "" })?
|
write!(f, "&{}", if mutbl == Mutability::Mut { "mut " } else { "" })?
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ use std::fmt;
|
||||||
use hir_def::{DefWithBodyId, EnumId, EnumVariantId, HasModule, LocalFieldId, ModuleId, VariantId};
|
use hir_def::{DefWithBodyId, EnumId, EnumVariantId, HasModule, LocalFieldId, ModuleId, VariantId};
|
||||||
use intern::sym;
|
use intern::sym;
|
||||||
use rustc_pattern_analysis::{
|
use rustc_pattern_analysis::{
|
||||||
Captures, IndexVec, PatCx, PrivateUninhabitedField,
|
IndexVec, PatCx, PrivateUninhabitedField,
|
||||||
constructor::{Constructor, ConstructorSet, VariantVisibility},
|
constructor::{Constructor, ConstructorSet, VariantVisibility},
|
||||||
usefulness::{PlaceValidity, UsefulnessReport, compute_match_usefulness},
|
usefulness::{PlaceValidity, UsefulnessReport, compute_match_usefulness},
|
||||||
};
|
};
|
||||||
|
|
@ -21,7 +21,7 @@ use crate::{
|
||||||
inhabitedness::{is_enum_variant_uninhabited_from, is_ty_uninhabited_from},
|
inhabitedness::{is_enum_variant_uninhabited_from, is_ty_uninhabited_from},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{FieldPat, Pat, PatKind, is_box};
|
use super::{FieldPat, Pat, PatKind};
|
||||||
|
|
||||||
use Constructor::*;
|
use Constructor::*;
|
||||||
|
|
||||||
|
|
@ -138,15 +138,15 @@ impl<'db> MatchCheckCtx<'db> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// This lists the fields of a variant along with their types.
|
// This lists the fields of a variant along with their types.
|
||||||
fn list_variant_fields<'a>(
|
fn list_variant_fields(
|
||||||
&'a self,
|
&self,
|
||||||
ty: &'a Ty,
|
ty: &Ty,
|
||||||
variant: VariantId,
|
variant: VariantId,
|
||||||
) -> impl Iterator<Item = (LocalFieldId, Ty)> + Captures<'a> + Captures<'db> {
|
) -> impl Iterator<Item = (LocalFieldId, Ty)> {
|
||||||
let (_, substs) = ty.as_adt().unwrap();
|
let (_, substs) = ty.as_adt().unwrap();
|
||||||
|
|
||||||
let field_tys = self.db.field_types(variant);
|
let field_tys = self.db.field_types(variant);
|
||||||
let fields_len = variant.variant_data(self.db).fields().len() as u32;
|
let fields_len = variant.fields(self.db).fields().len() as u32;
|
||||||
|
|
||||||
(0..fields_len).map(|idx| LocalFieldId::from_raw(idx.into())).map(move |fid| {
|
(0..fields_len).map(|idx| LocalFieldId::from_raw(idx.into())).map(move |fid| {
|
||||||
let ty = field_tys[fid].clone().substitute(Interner, substs);
|
let ty = field_tys[fid].clone().substitute(Interner, substs);
|
||||||
|
|
@ -170,8 +170,6 @@ impl<'db> MatchCheckCtx<'db> {
|
||||||
}
|
}
|
||||||
PatKind::Deref { subpattern } => {
|
PatKind::Deref { subpattern } => {
|
||||||
ctor = match pat.ty.kind(Interner) {
|
ctor = match pat.ty.kind(Interner) {
|
||||||
// This is a box pattern.
|
|
||||||
TyKind::Adt(adt, _) if is_box(self.db, adt.0) => Struct,
|
|
||||||
TyKind::Ref(..) => Ref,
|
TyKind::Ref(..) => Ref,
|
||||||
_ => {
|
_ => {
|
||||||
never!("pattern has unexpected type: pat: {:?}, ty: {:?}", pat, &pat.ty);
|
never!("pattern has unexpected type: pat: {:?}, ty: {:?}", pat, &pat.ty);
|
||||||
|
|
@ -194,23 +192,6 @@ impl<'db> MatchCheckCtx<'db> {
|
||||||
ctor = Struct;
|
ctor = Struct;
|
||||||
arity = substs.len(Interner);
|
arity = substs.len(Interner);
|
||||||
}
|
}
|
||||||
TyKind::Adt(adt, _) if is_box(self.db, adt.0) => {
|
|
||||||
// The only legal patterns of type `Box` (outside `std`) are `_` and box
|
|
||||||
// patterns. If we're here we can assume this is a box pattern.
|
|
||||||
// FIXME(Nadrieril): A `Box` can in theory be matched either with `Box(_,
|
|
||||||
// _)` or a box pattern. As a hack to avoid an ICE with the former, we
|
|
||||||
// ignore other fields than the first one. This will trigger an error later
|
|
||||||
// anyway.
|
|
||||||
// See https://github.com/rust-lang/rust/issues/82772 ,
|
|
||||||
// explanation: https://github.com/rust-lang/rust/pull/82789#issuecomment-796921977
|
|
||||||
// The problem is that we can't know from the type whether we'll match
|
|
||||||
// normally or through box-patterns. We'll have to figure out a proper
|
|
||||||
// solution when we introduce generalized deref patterns. Also need to
|
|
||||||
// prevent mixing of those two options.
|
|
||||||
fields.retain(|ipat| ipat.idx == 0);
|
|
||||||
ctor = Struct;
|
|
||||||
arity = 1;
|
|
||||||
}
|
|
||||||
&TyKind::Adt(AdtId(adt), _) => {
|
&TyKind::Adt(AdtId(adt), _) => {
|
||||||
ctor = match pat.kind.as_ref() {
|
ctor = match pat.kind.as_ref() {
|
||||||
PatKind::Leaf { .. } if matches!(adt, hir_def::AdtId::UnionId(_)) => {
|
PatKind::Leaf { .. } if matches!(adt, hir_def::AdtId::UnionId(_)) => {
|
||||||
|
|
@ -229,7 +210,7 @@ impl<'db> MatchCheckCtx<'db> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let variant = Self::variant_id_for_adt(self.db, &ctor, adt).unwrap();
|
let variant = Self::variant_id_for_adt(self.db, &ctor, adt).unwrap();
|
||||||
arity = variant.variant_data(self.db).fields().len();
|
arity = variant.fields(self.db).fields().len();
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
never!("pattern has unexpected type: pat: {:?}, ty: {:?}", pat, &pat.ty);
|
never!("pattern has unexpected type: pat: {:?}, ty: {:?}", pat, &pat.ty);
|
||||||
|
|
@ -277,12 +258,6 @@ impl<'db> MatchCheckCtx<'db> {
|
||||||
})
|
})
|
||||||
.collect(),
|
.collect(),
|
||||||
},
|
},
|
||||||
TyKind::Adt(adt, _) if is_box(self.db, adt.0) => {
|
|
||||||
// Without `box_patterns`, the only legal pattern of type `Box` is `_` (outside
|
|
||||||
// of `std`). So this branch is only reachable when the feature is enabled and
|
|
||||||
// the pattern is a box pattern.
|
|
||||||
PatKind::Deref { subpattern: subpatterns.next().unwrap() }
|
|
||||||
}
|
|
||||||
TyKind::Adt(adt, substs) => {
|
TyKind::Adt(adt, substs) => {
|
||||||
let variant = Self::variant_id_for_adt(self.db, pat.ctor(), adt.0).unwrap();
|
let variant = Self::variant_id_for_adt(self.db, pat.ctor(), adt.0).unwrap();
|
||||||
let subpatterns = self
|
let subpatterns = self
|
||||||
|
|
@ -343,14 +318,8 @@ impl PatCx for MatchCheckCtx<'_> {
|
||||||
Struct | Variant(_) | UnionField => match *ty.kind(Interner) {
|
Struct | Variant(_) | UnionField => match *ty.kind(Interner) {
|
||||||
TyKind::Tuple(arity, ..) => arity,
|
TyKind::Tuple(arity, ..) => arity,
|
||||||
TyKind::Adt(AdtId(adt), ..) => {
|
TyKind::Adt(AdtId(adt), ..) => {
|
||||||
if is_box(self.db, adt) {
|
let variant = Self::variant_id_for_adt(self.db, ctor, adt).unwrap();
|
||||||
// The only legal patterns of type `Box` (outside `std`) are `_` and box
|
variant.fields(self.db).fields().len()
|
||||||
// patterns. If we're here we can assume this is a box pattern.
|
|
||||||
1
|
|
||||||
} else {
|
|
||||||
let variant = Self::variant_id_for_adt(self.db, ctor, adt).unwrap();
|
|
||||||
variant.variant_data(self.db).fields().len()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
never!("Unexpected type for `Single` constructor: {:?}", ty);
|
never!("Unexpected type for `Single` constructor: {:?}", ty);
|
||||||
|
|
@ -383,29 +352,22 @@ impl PatCx for MatchCheckCtx<'_> {
|
||||||
tys.cloned().map(|ty| (ty, PrivateUninhabitedField(false))).collect()
|
tys.cloned().map(|ty| (ty, PrivateUninhabitedField(false))).collect()
|
||||||
}
|
}
|
||||||
TyKind::Ref(.., rty) => single(rty.clone()),
|
TyKind::Ref(.., rty) => single(rty.clone()),
|
||||||
&TyKind::Adt(AdtId(adt), ref substs) => {
|
&TyKind::Adt(AdtId(adt), ..) => {
|
||||||
if is_box(self.db, adt) {
|
let variant = Self::variant_id_for_adt(self.db, ctor, adt).unwrap();
|
||||||
// The only legal patterns of type `Box` (outside `std`) are `_` and box
|
|
||||||
// patterns. If we're here we can assume this is a box pattern.
|
|
||||||
let subst_ty = substs.at(Interner, 0).assert_ty_ref(Interner).clone();
|
|
||||||
single(subst_ty)
|
|
||||||
} else {
|
|
||||||
let variant = Self::variant_id_for_adt(self.db, ctor, adt).unwrap();
|
|
||||||
|
|
||||||
let visibilities = LazyCell::new(|| self.db.field_visibilities(variant));
|
let visibilities = LazyCell::new(|| self.db.field_visibilities(variant));
|
||||||
|
|
||||||
self.list_variant_fields(ty, variant)
|
self.list_variant_fields(ty, variant)
|
||||||
.map(move |(fid, ty)| {
|
.map(move |(fid, ty)| {
|
||||||
let is_visible = || {
|
let is_visible = || {
|
||||||
matches!(adt, hir_def::AdtId::EnumId(..))
|
matches!(adt, hir_def::AdtId::EnumId(..))
|
||||||
|| visibilities[fid].is_visible_from(self.db, self.module)
|
|| visibilities[fid].is_visible_from(self.db, self.module)
|
||||||
};
|
};
|
||||||
let is_uninhabited = self.is_uninhabited(&ty);
|
let is_uninhabited = self.is_uninhabited(&ty);
|
||||||
let private_uninhabited = is_uninhabited && !is_visible();
|
let private_uninhabited = is_uninhabited && !is_visible();
|
||||||
(ty, PrivateUninhabitedField(private_uninhabited))
|
(ty, PrivateUninhabitedField(private_uninhabited))
|
||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
}
|
|
||||||
}
|
}
|
||||||
ty_kind => {
|
ty_kind => {
|
||||||
never!("Unexpected type for `{:?}` constructor: {:?}", ctor, ty_kind);
|
never!("Unexpected type for `{:?}` constructor: {:?}", ctor, ty_kind);
|
||||||
|
|
|
||||||
|
|
@ -888,7 +888,7 @@ fn render_const_scalar(
|
||||||
write!(f, "{}", data.name.display(f.db, f.edition()))?;
|
write!(f, "{}", data.name.display(f.db, f.edition()))?;
|
||||||
let field_types = f.db.field_types(s.into());
|
let field_types = f.db.field_types(s.into());
|
||||||
render_variant_after_name(
|
render_variant_after_name(
|
||||||
&f.db.variant_fields(s.into()),
|
s.fields(f.db),
|
||||||
f,
|
f,
|
||||||
&field_types,
|
&field_types,
|
||||||
f.db.trait_environment(adt.0.into()),
|
f.db.trait_environment(adt.0.into()),
|
||||||
|
|
@ -920,7 +920,7 @@ fn render_const_scalar(
|
||||||
)?;
|
)?;
|
||||||
let field_types = f.db.field_types(var_id.into());
|
let field_types = f.db.field_types(var_id.into());
|
||||||
render_variant_after_name(
|
render_variant_after_name(
|
||||||
&f.db.variant_fields(var_id.into()),
|
var_id.fields(f.db),
|
||||||
f,
|
f,
|
||||||
&field_types,
|
&field_types,
|
||||||
f.db.trait_environment(adt.0.into()),
|
f.db.trait_environment(adt.0.into()),
|
||||||
|
|
@ -1394,7 +1394,7 @@ impl HirDisplay for Ty {
|
||||||
let future_trait =
|
let future_trait =
|
||||||
LangItem::Future.resolve_trait(db, body.module(db).krate());
|
LangItem::Future.resolve_trait(db, body.module(db).krate());
|
||||||
let output = future_trait.and_then(|t| {
|
let output = future_trait.and_then(|t| {
|
||||||
db.trait_items(t)
|
t.trait_items(db)
|
||||||
.associated_type_by_name(&Name::new_symbol_root(sym::Output))
|
.associated_type_by_name(&Name::new_symbol_root(sym::Output))
|
||||||
});
|
});
|
||||||
write!(f, "impl ")?;
|
write!(f, "impl ")?;
|
||||||
|
|
@ -1432,10 +1432,10 @@ impl HirDisplay for Ty {
|
||||||
match f.closure_style {
|
match f.closure_style {
|
||||||
ClosureStyle::Hide => return write!(f, "{TYPE_HINT_TRUNCATION}"),
|
ClosureStyle::Hide => return write!(f, "{TYPE_HINT_TRUNCATION}"),
|
||||||
ClosureStyle::ClosureWithId => {
|
ClosureStyle::ClosureWithId => {
|
||||||
return write!(f, "{{closure#{:?}}}", id.0.as_u32());
|
return write!(f, "{{closure#{:?}}}", id.0.index());
|
||||||
}
|
}
|
||||||
ClosureStyle::ClosureWithSubst => {
|
ClosureStyle::ClosureWithSubst => {
|
||||||
write!(f, "{{closure#{:?}}}", id.0.as_u32())?;
|
write!(f, "{{closure#{:?}}}", id.0.index())?;
|
||||||
return hir_fmt_generics(f, substs.as_slice(Interner), None, None);
|
return hir_fmt_generics(f, substs.as_slice(Interner), None, None);
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
|
|
@ -2178,6 +2178,7 @@ impl HirDisplayWithExpressionStore for TypeRefId {
|
||||||
f.write_joined(
|
f.write_joined(
|
||||||
generic_params
|
generic_params
|
||||||
.where_predicates()
|
.where_predicates()
|
||||||
|
.iter()
|
||||||
.filter_map(|it| match it {
|
.filter_map(|it| match it {
|
||||||
WherePredicate::TypeBound { target, bound }
|
WherePredicate::TypeBound { target, bound }
|
||||||
| WherePredicate::ForLifetime { lifetimes: _, target, bound }
|
| WherePredicate::ForLifetime { lifetimes: _, target, bound }
|
||||||
|
|
|
||||||
|
|
@ -101,7 +101,7 @@ where
|
||||||
|
|
||||||
// rustc checks for non-lifetime binders here, but we don't support HRTB yet
|
// rustc checks for non-lifetime binders here, but we don't support HRTB yet
|
||||||
|
|
||||||
let trait_data = db.trait_items(trait_);
|
let trait_data = trait_.trait_items(db);
|
||||||
for (_, assoc_item) in &trait_data.items {
|
for (_, assoc_item) in &trait_data.items {
|
||||||
dyn_compatibility_violation_for_assoc_item(db, trait_, *assoc_item, cb)?;
|
dyn_compatibility_violation_for_assoc_item(db, trait_, *assoc_item, cb)?;
|
||||||
}
|
}
|
||||||
|
|
@ -164,7 +164,7 @@ fn predicates_reference_self(db: &dyn HirDatabase, trait_: TraitId) -> bool {
|
||||||
|
|
||||||
// Same as the above, `predicates_reference_self`
|
// Same as the above, `predicates_reference_self`
|
||||||
fn bounds_reference_self(db: &dyn HirDatabase, trait_: TraitId) -> bool {
|
fn bounds_reference_self(db: &dyn HirDatabase, trait_: TraitId) -> bool {
|
||||||
let trait_data = db.trait_items(trait_);
|
let trait_data = trait_.trait_items(db);
|
||||||
trait_data
|
trait_data
|
||||||
.items
|
.items
|
||||||
.iter()
|
.iter()
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,16 @@ impl Generics {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn where_predicates(&self) -> impl Iterator<Item = &WherePredicate> {
|
pub(crate) fn where_predicates(&self) -> impl Iterator<Item = &WherePredicate> {
|
||||||
self.params.where_predicates()
|
self.params.where_predicates().iter()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn has_no_predicates(&self) -> bool {
|
||||||
|
self.params.has_no_predicates()
|
||||||
|
&& self.parent_generics.as_ref().is_none_or(|g| g.params.has_no_predicates())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn is_empty(&self) -> bool {
|
||||||
|
self.params.is_empty() && self.parent_generics.as_ref().is_none_or(|g| g.params.is_empty())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn iter_id(&self) -> impl Iterator<Item = GenericParamId> + '_ {
|
pub(crate) fn iter_id(&self) -> impl Iterator<Item = GenericParamId> + '_ {
|
||||||
|
|
|
||||||
|
|
@ -460,19 +460,17 @@ pub struct InferenceResult {
|
||||||
/// Whenever a tuple field expression access a tuple field, we allocate a tuple id in
|
/// Whenever a tuple field expression access a tuple field, we allocate a tuple id in
|
||||||
/// [`InferenceContext`] and store the tuples substitution there. This map is the reverse of
|
/// [`InferenceContext`] and store the tuples substitution there. This map is the reverse of
|
||||||
/// that which allows us to resolve a [`TupleFieldId`]s type.
|
/// that which allows us to resolve a [`TupleFieldId`]s type.
|
||||||
pub tuple_field_access_types: FxHashMap<TupleId, Substitution>,
|
tuple_field_access_types: FxHashMap<TupleId, Substitution>,
|
||||||
/// During inference this field is empty and [`InferenceContext::diagnostics`] is filled instead.
|
/// During inference this field is empty and [`InferenceContext::diagnostics`] is filled instead.
|
||||||
pub diagnostics: Vec<InferenceDiagnostic>,
|
diagnostics: Vec<InferenceDiagnostic>,
|
||||||
pub type_of_expr: ArenaMap<ExprId, Ty>,
|
pub(crate) type_of_expr: ArenaMap<ExprId, Ty>,
|
||||||
/// For each pattern record the type it resolves to.
|
/// For each pattern record the type it resolves to.
|
||||||
///
|
///
|
||||||
/// **Note**: When a pattern type is resolved it may still contain
|
/// **Note**: When a pattern type is resolved it may still contain
|
||||||
/// unresolved or missing subpatterns or subpatterns of mismatched types.
|
/// unresolved or missing subpatterns or subpatterns of mismatched types.
|
||||||
pub type_of_pat: ArenaMap<PatId, Ty>,
|
pub(crate) type_of_pat: ArenaMap<PatId, Ty>,
|
||||||
pub type_of_binding: ArenaMap<BindingId, Ty>,
|
pub(crate) type_of_binding: ArenaMap<BindingId, Ty>,
|
||||||
pub type_of_rpit: ArenaMap<ImplTraitIdx, Ty>,
|
pub(crate) type_of_rpit: ArenaMap<ImplTraitIdx, Ty>,
|
||||||
/// Type of the result of `.into_iter()` on the for. `ExprId` is the one of the whole for loop.
|
|
||||||
pub type_of_for_iterator: FxHashMap<ExprId, Ty>,
|
|
||||||
type_mismatches: FxHashMap<ExprOrPatId, TypeMismatch>,
|
type_mismatches: FxHashMap<ExprOrPatId, TypeMismatch>,
|
||||||
/// Whether there are any type-mismatching errors in the result.
|
/// Whether there are any type-mismatching errors in the result.
|
||||||
// FIXME: This isn't as useful as initially thought due to us falling back placeholders to
|
// FIXME: This isn't as useful as initially thought due to us falling back placeholders to
|
||||||
|
|
@ -483,7 +481,7 @@ pub struct InferenceResult {
|
||||||
// FIXME: Move this into `InferenceContext`
|
// FIXME: Move this into `InferenceContext`
|
||||||
standard_types: InternedStandardTypes,
|
standard_types: InternedStandardTypes,
|
||||||
/// Stores the types which were implicitly dereferenced in pattern binding modes.
|
/// Stores the types which were implicitly dereferenced in pattern binding modes.
|
||||||
pub pat_adjustments: FxHashMap<PatId, Vec<Ty>>,
|
pub(crate) pat_adjustments: FxHashMap<PatId, Vec<Ty>>,
|
||||||
/// Stores the binding mode (`ref` in `let ref x = 2`) of bindings.
|
/// Stores the binding mode (`ref` in `let ref x = 2`) of bindings.
|
||||||
///
|
///
|
||||||
/// This one is tied to the `PatId` instead of `BindingId`, because in some rare cases, a binding in an
|
/// This one is tied to the `PatId` instead of `BindingId`, because in some rare cases, a binding in an
|
||||||
|
|
@ -497,12 +495,12 @@ pub struct InferenceResult {
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
/// the first `rest` has implicit `ref` binding mode, but the second `rest` binding mode is `move`.
|
/// the first `rest` has implicit `ref` binding mode, but the second `rest` binding mode is `move`.
|
||||||
pub binding_modes: ArenaMap<PatId, BindingMode>,
|
pub(crate) binding_modes: ArenaMap<PatId, BindingMode>,
|
||||||
pub expr_adjustments: FxHashMap<ExprId, Box<[Adjustment]>>,
|
pub(crate) expr_adjustments: FxHashMap<ExprId, Box<[Adjustment]>>,
|
||||||
pub(crate) closure_info: FxHashMap<ClosureId, (Vec<CapturedItem>, FnTrait)>,
|
pub(crate) closure_info: FxHashMap<ClosureId, (Vec<CapturedItem>, FnTrait)>,
|
||||||
// FIXME: remove this field
|
// FIXME: remove this field
|
||||||
pub mutated_bindings_in_closure: FxHashSet<BindingId>,
|
pub mutated_bindings_in_closure: FxHashSet<BindingId>,
|
||||||
pub coercion_casts: FxHashSet<ExprId>,
|
pub(crate) coercion_casts: FxHashSet<ExprId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InferenceResult {
|
impl InferenceResult {
|
||||||
|
|
@ -566,6 +564,26 @@ impl InferenceResult {
|
||||||
pub fn is_erroneous(&self) -> bool {
|
pub fn is_erroneous(&self) -> bool {
|
||||||
self.has_errors && self.type_of_expr.iter().count() == 0
|
self.has_errors && self.type_of_expr.iter().count() == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn diagnostics(&self) -> &[InferenceDiagnostic] {
|
||||||
|
&self.diagnostics
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn tuple_field_access_type(&self, id: TupleId) -> &Substitution {
|
||||||
|
&self.tuple_field_access_types[&id]
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pat_adjustment(&self, id: PatId) -> Option<&[Ty]> {
|
||||||
|
self.pat_adjustments.get(&id).map(|it| &**it)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn expr_adjustment(&self, id: ExprId) -> Option<&[Adjustment]> {
|
||||||
|
self.expr_adjustments.get(&id).map(|it| &**it)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn binding_mode(&self, id: PatId) -> Option<BindingMode> {
|
||||||
|
self.binding_modes.get(id).copied()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Index<ExprId> for InferenceResult {
|
impl Index<ExprId> for InferenceResult {
|
||||||
|
|
@ -772,7 +790,6 @@ impl<'db> InferenceContext<'db> {
|
||||||
type_of_pat,
|
type_of_pat,
|
||||||
type_of_binding,
|
type_of_binding,
|
||||||
type_of_rpit,
|
type_of_rpit,
|
||||||
type_of_for_iterator,
|
|
||||||
type_mismatches,
|
type_mismatches,
|
||||||
has_errors,
|
has_errors,
|
||||||
standard_types: _,
|
standard_types: _,
|
||||||
|
|
@ -832,11 +849,6 @@ impl<'db> InferenceContext<'db> {
|
||||||
*has_errors = *has_errors || ty.contains_unknown();
|
*has_errors = *has_errors || ty.contains_unknown();
|
||||||
}
|
}
|
||||||
type_of_rpit.shrink_to_fit();
|
type_of_rpit.shrink_to_fit();
|
||||||
for ty in type_of_for_iterator.values_mut() {
|
|
||||||
*ty = table.resolve_completely(ty.clone());
|
|
||||||
*has_errors = *has_errors || ty.contains_unknown();
|
|
||||||
}
|
|
||||||
type_of_for_iterator.shrink_to_fit();
|
|
||||||
|
|
||||||
*has_errors |= !type_mismatches.is_empty();
|
*has_errors |= !type_mismatches.is_empty();
|
||||||
|
|
||||||
|
|
@ -1813,7 +1825,7 @@ impl<'db> InferenceContext<'db> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve_output_on(&self, trait_: TraitId) -> Option<TypeAliasId> {
|
fn resolve_output_on(&self, trait_: TraitId) -> Option<TypeAliasId> {
|
||||||
self.db.trait_items(trait_).associated_type_by_name(&Name::new_symbol_root(sym::Output))
|
trait_.trait_items(self.db).associated_type_by_name(&Name::new_symbol_root(sym::Output))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve_lang_trait(&self, lang: LangItem) -> Option<TraitId> {
|
fn resolve_lang_trait(&self, lang: LangItem) -> Option<TraitId> {
|
||||||
|
|
|
||||||
|
|
@ -382,7 +382,7 @@ fn pointer_kind(ty: &Ty, table: &mut InferenceTable<'_>) -> Result<Option<Pointe
|
||||||
return Err(());
|
return Err(());
|
||||||
};
|
};
|
||||||
|
|
||||||
let struct_data = table.db.variant_fields(id.into());
|
let struct_data = id.fields(table.db);
|
||||||
if let Some((last_field, _)) = struct_data.fields().iter().last() {
|
if let Some((last_field, _)) = struct_data.fields().iter().last() {
|
||||||
let last_field_ty =
|
let last_field_ty =
|
||||||
table.db.field_types(id.into())[last_field].clone().substitute(Interner, subst);
|
table.db.field_types(id.into())[last_field].clone().substitute(Interner, subst);
|
||||||
|
|
|
||||||
|
|
@ -677,7 +677,7 @@ impl CapturedItem {
|
||||||
match proj {
|
match proj {
|
||||||
ProjectionElem::Deref => {}
|
ProjectionElem::Deref => {}
|
||||||
ProjectionElem::Field(Either::Left(f)) => {
|
ProjectionElem::Field(Either::Left(f)) => {
|
||||||
let variant_data = f.parent.variant_data(db);
|
let variant_data = f.parent.fields(db);
|
||||||
match variant_data.shape {
|
match variant_data.shape {
|
||||||
FieldsShape::Record => {
|
FieldsShape::Record => {
|
||||||
result.push('_');
|
result.push('_');
|
||||||
|
|
@ -720,7 +720,7 @@ impl CapturedItem {
|
||||||
// In source code autoderef kicks in.
|
// In source code autoderef kicks in.
|
||||||
ProjectionElem::Deref => {}
|
ProjectionElem::Deref => {}
|
||||||
ProjectionElem::Field(Either::Left(f)) => {
|
ProjectionElem::Field(Either::Left(f)) => {
|
||||||
let variant_data = f.parent.variant_data(db);
|
let variant_data = f.parent.fields(db);
|
||||||
match variant_data.shape {
|
match variant_data.shape {
|
||||||
FieldsShape::Record => format_to!(
|
FieldsShape::Record => format_to!(
|
||||||
result,
|
result,
|
||||||
|
|
@ -782,7 +782,7 @@ impl CapturedItem {
|
||||||
if field_need_paren {
|
if field_need_paren {
|
||||||
result = format!("({result})");
|
result = format!("({result})");
|
||||||
}
|
}
|
||||||
let variant_data = f.parent.variant_data(db);
|
let variant_data = f.parent.fields(db);
|
||||||
let field = match variant_data.shape {
|
let field = match variant_data.shape {
|
||||||
FieldsShape::Record => {
|
FieldsShape::Record => {
|
||||||
variant_data.fields()[f.local_id].name.as_str().to_owned()
|
variant_data.fields()[f.local_id].name.as_str().to_owned()
|
||||||
|
|
@ -1210,9 +1210,8 @@ impl InferenceContext<'_> {
|
||||||
if let Some(deref_trait) =
|
if let Some(deref_trait) =
|
||||||
self.resolve_lang_item(LangItem::DerefMut).and_then(|it| it.as_trait())
|
self.resolve_lang_item(LangItem::DerefMut).and_then(|it| it.as_trait())
|
||||||
{
|
{
|
||||||
if let Some(deref_fn) = self
|
if let Some(deref_fn) = deref_trait
|
||||||
.db
|
.trait_items(self.db)
|
||||||
.trait_items(deref_trait)
|
|
||||||
.method_by_name(&Name::new_symbol_root(sym::deref_mut))
|
.method_by_name(&Name::new_symbol_root(sym::deref_mut))
|
||||||
{
|
{
|
||||||
break 'b deref_fn == f;
|
break 'b deref_fn == f;
|
||||||
|
|
@ -1230,10 +1229,11 @@ impl InferenceContext<'_> {
|
||||||
self.select_from_expr(*expr);
|
self.select_from_expr(*expr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Expr::Let { pat: _, expr } => {
|
Expr::Let { pat, expr } => {
|
||||||
self.walk_expr(*expr);
|
self.walk_expr(*expr);
|
||||||
let place = self.place_of_expr(*expr);
|
if let Some(place) = self.place_of_expr(*expr) {
|
||||||
self.ref_expr(*expr, place);
|
self.consume_with_pat(place, *pat);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Expr::UnaryOp { expr, op: _ }
|
Expr::UnaryOp { expr, op: _ }
|
||||||
| Expr::Array(Array::Repeat { initializer: expr, repeat: _ })
|
| Expr::Array(Array::Repeat { initializer: expr, repeat: _ })
|
||||||
|
|
@ -1560,7 +1560,7 @@ impl InferenceContext<'_> {
|
||||||
self.consume_place(place)
|
self.consume_place(place)
|
||||||
}
|
}
|
||||||
VariantId::StructId(s) => {
|
VariantId::StructId(s) => {
|
||||||
let vd = &*self.db.variant_fields(s.into());
|
let vd = s.fields(self.db);
|
||||||
for field_pat in args.iter() {
|
for field_pat in args.iter() {
|
||||||
let arg = field_pat.pat;
|
let arg = field_pat.pat;
|
||||||
let Some(local_id) = vd.field(&field_pat.name) else {
|
let Some(local_id) = vd.field(&field_pat.name) else {
|
||||||
|
|
@ -1612,7 +1612,7 @@ impl InferenceContext<'_> {
|
||||||
self.consume_place(place)
|
self.consume_place(place)
|
||||||
}
|
}
|
||||||
VariantId::StructId(s) => {
|
VariantId::StructId(s) => {
|
||||||
let vd = &*self.db.variant_fields(s.into());
|
let vd = s.fields(self.db);
|
||||||
let (al, ar) =
|
let (al, ar) =
|
||||||
args.split_at(ellipsis.map_or(args.len(), |it| it as usize));
|
args.split_at(ellipsis.map_or(args.len(), |it| it as usize));
|
||||||
let fields = vd.fields().iter();
|
let fields = vd.fields().iter();
|
||||||
|
|
|
||||||
|
|
@ -542,7 +542,7 @@ impl InferenceContext<'_> {
|
||||||
_ if fields.is_empty() => {}
|
_ if fields.is_empty() => {}
|
||||||
Some(def) => {
|
Some(def) => {
|
||||||
let field_types = self.db.field_types(def);
|
let field_types = self.db.field_types(def);
|
||||||
let variant_data = def.variant_data(self.db);
|
let variant_data = def.fields(self.db);
|
||||||
let visibilities = self.db.field_visibilities(def);
|
let visibilities = self.db.field_visibilities(def);
|
||||||
for field in fields.iter() {
|
for field in fields.iter() {
|
||||||
let field_def = {
|
let field_def = {
|
||||||
|
|
@ -654,9 +654,8 @@ impl InferenceContext<'_> {
|
||||||
match op {
|
match op {
|
||||||
UnaryOp::Deref => {
|
UnaryOp::Deref => {
|
||||||
if let Some(deref_trait) = self.resolve_lang_trait(LangItem::Deref) {
|
if let Some(deref_trait) = self.resolve_lang_trait(LangItem::Deref) {
|
||||||
if let Some(deref_fn) = self
|
if let Some(deref_fn) = deref_trait
|
||||||
.db
|
.trait_items(self.db)
|
||||||
.trait_items(deref_trait)
|
|
||||||
.method_by_name(&Name::new_symbol_root(sym::deref))
|
.method_by_name(&Name::new_symbol_root(sym::deref))
|
||||||
{
|
{
|
||||||
// FIXME: this is wrong in multiple ways, subst is empty, and we emit it even for builtin deref (note that
|
// FIXME: this is wrong in multiple ways, subst is empty, and we emit it even for builtin deref (note that
|
||||||
|
|
@ -732,9 +731,32 @@ impl InferenceContext<'_> {
|
||||||
&Pat::Expr(expr) => {
|
&Pat::Expr(expr) => {
|
||||||
Some(self.infer_expr(expr, &Expectation::none(), ExprIsRead::No))
|
Some(self.infer_expr(expr, &Expectation::none(), ExprIsRead::No))
|
||||||
}
|
}
|
||||||
Pat::Path(path) => Some(self.infer_expr_path(path, target.into(), tgt_expr)),
|
Pat::Path(path) => {
|
||||||
|
let resolver_guard =
|
||||||
|
self.resolver.update_to_inner_scope(self.db, self.owner, tgt_expr);
|
||||||
|
let resolution = self.resolver.resolve_path_in_value_ns_fully(
|
||||||
|
self.db,
|
||||||
|
path,
|
||||||
|
self.body.pat_path_hygiene(target),
|
||||||
|
);
|
||||||
|
self.resolver.reset_to_guard(resolver_guard);
|
||||||
|
|
||||||
|
if matches!(
|
||||||
|
resolution,
|
||||||
|
Some(
|
||||||
|
ValueNs::ConstId(_)
|
||||||
|
| ValueNs::StructId(_)
|
||||||
|
| ValueNs::EnumVariantId(_)
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(self.infer_expr_path(path, target.into(), tgt_expr))
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
|
let is_destructuring_assignment = lhs_ty.is_none();
|
||||||
|
|
||||||
if let Some(lhs_ty) = lhs_ty {
|
if let Some(lhs_ty) = lhs_ty {
|
||||||
self.write_pat_ty(target, lhs_ty.clone());
|
self.write_pat_ty(target, lhs_ty.clone());
|
||||||
|
|
@ -748,7 +770,15 @@ impl InferenceContext<'_> {
|
||||||
self.inside_assignment = false;
|
self.inside_assignment = false;
|
||||||
self.resolver.reset_to_guard(resolver_guard);
|
self.resolver.reset_to_guard(resolver_guard);
|
||||||
}
|
}
|
||||||
self.result.standard_types.unit.clone()
|
if is_destructuring_assignment && self.diverges.is_always() {
|
||||||
|
// Ordinary assignments always return `()`, even when they diverge.
|
||||||
|
// However, rustc lowers destructuring assignments into blocks, and blocks return `!` if they have no tail
|
||||||
|
// expression and they diverge. Therefore, we have to do the same here, even though we don't lower destructuring
|
||||||
|
// assignments into blocks.
|
||||||
|
self.table.new_maybe_never_var()
|
||||||
|
} else {
|
||||||
|
self.result.standard_types.unit.clone()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Expr::Range { lhs, rhs, range_type } => {
|
Expr::Range { lhs, rhs, range_type } => {
|
||||||
let lhs_ty =
|
let lhs_ty =
|
||||||
|
|
@ -813,9 +843,8 @@ impl InferenceContext<'_> {
|
||||||
self.table.new_lifetime_var(),
|
self.table.new_lifetime_var(),
|
||||||
));
|
));
|
||||||
self.write_expr_adj(*base, adj.into_boxed_slice());
|
self.write_expr_adj(*base, adj.into_boxed_slice());
|
||||||
if let Some(func) = self
|
if let Some(func) = index_trait
|
||||||
.db
|
.trait_items(self.db)
|
||||||
.trait_items(index_trait)
|
|
||||||
.method_by_name(&Name::new_symbol_root(sym::index))
|
.method_by_name(&Name::new_symbol_root(sym::index))
|
||||||
{
|
{
|
||||||
let subst = TyBuilder::subst_for_def(self.db, index_trait, None);
|
let subst = TyBuilder::subst_for_def(self.db, index_trait, None);
|
||||||
|
|
@ -1148,7 +1177,7 @@ impl InferenceContext<'_> {
|
||||||
let Some(trait_) = fn_x.get_id(self.db, self.table.trait_env.krate) else {
|
let Some(trait_) = fn_x.get_id(self.db, self.table.trait_env.krate) else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
let trait_data = self.db.trait_items(trait_);
|
let trait_data = trait_.trait_items(self.db);
|
||||||
if let Some(func) = trait_data.method_by_name(&fn_x.method_name()) {
|
if let Some(func) = trait_data.method_by_name(&fn_x.method_name()) {
|
||||||
let subst = TyBuilder::subst_for_def(self.db, trait_, None)
|
let subst = TyBuilder::subst_for_def(self.db, trait_, None)
|
||||||
.push(callee_ty.clone())
|
.push(callee_ty.clone())
|
||||||
|
|
@ -1316,7 +1345,7 @@ impl InferenceContext<'_> {
|
||||||
|
|
||||||
let trait_func = lang_items_for_bin_op(op).and_then(|(name, lang_item)| {
|
let trait_func = lang_items_for_bin_op(op).and_then(|(name, lang_item)| {
|
||||||
let trait_id = self.resolve_lang_item(lang_item)?.as_trait()?;
|
let trait_id = self.resolve_lang_item(lang_item)?.as_trait()?;
|
||||||
let func = self.db.trait_items(trait_id).method_by_name(&name)?;
|
let func = trait_id.trait_items(self.db).method_by_name(&name)?;
|
||||||
Some((trait_id, func))
|
Some((trait_id, func))
|
||||||
});
|
});
|
||||||
let (trait_, func) = match trait_func {
|
let (trait_, func) = match trait_func {
|
||||||
|
|
@ -1568,12 +1597,12 @@ impl InferenceContext<'_> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
&TyKind::Adt(AdtId(hir_def::AdtId::StructId(s)), ref parameters) => {
|
&TyKind::Adt(AdtId(hir_def::AdtId::StructId(s)), ref parameters) => {
|
||||||
let local_id = self.db.variant_fields(s.into()).field(name)?;
|
let local_id = s.fields(self.db).field(name)?;
|
||||||
let field = FieldId { parent: s.into(), local_id };
|
let field = FieldId { parent: s.into(), local_id };
|
||||||
(field, parameters.clone())
|
(field, parameters.clone())
|
||||||
}
|
}
|
||||||
&TyKind::Adt(AdtId(hir_def::AdtId::UnionId(u)), ref parameters) => {
|
&TyKind::Adt(AdtId(hir_def::AdtId::UnionId(u)), ref parameters) => {
|
||||||
let local_id = self.db.variant_fields(u.into()).field(name)?;
|
let local_id = u.fields(self.db).field(name)?;
|
||||||
let field = FieldId { parent: u.into(), local_id };
|
let field = FieldId { parent: u.into(), local_id };
|
||||||
(field, parameters.clone())
|
(field, parameters.clone())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -129,9 +129,8 @@ impl InferenceContext<'_> {
|
||||||
if let Some(index_trait) =
|
if let Some(index_trait) =
|
||||||
LangItem::IndexMut.resolve_trait(self.db, self.table.trait_env.krate)
|
LangItem::IndexMut.resolve_trait(self.db, self.table.trait_env.krate)
|
||||||
{
|
{
|
||||||
if let Some(index_fn) = self
|
if let Some(index_fn) = index_trait
|
||||||
.db
|
.trait_items(self.db)
|
||||||
.trait_items(index_trait)
|
|
||||||
.method_by_name(&Name::new_symbol_root(sym::index_mut))
|
.method_by_name(&Name::new_symbol_root(sym::index_mut))
|
||||||
{
|
{
|
||||||
*f = index_fn;
|
*f = index_fn;
|
||||||
|
|
@ -194,9 +193,8 @@ impl InferenceContext<'_> {
|
||||||
});
|
});
|
||||||
if is_mut_ptr {
|
if is_mut_ptr {
|
||||||
mutability = Mutability::Not;
|
mutability = Mutability::Not;
|
||||||
} else if let Some(deref_fn) = self
|
} else if let Some(deref_fn) = deref_trait
|
||||||
.db
|
.trait_items(self.db)
|
||||||
.trait_items(deref_trait)
|
|
||||||
.method_by_name(&Name::new_symbol_root(sym::deref_mut))
|
.method_by_name(&Name::new_symbol_root(sym::deref_mut))
|
||||||
{
|
{
|
||||||
*f = deref_fn;
|
*f = deref_fn;
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ impl InferenceContext<'_> {
|
||||||
decl: Option<DeclContext>,
|
decl: Option<DeclContext>,
|
||||||
) -> Ty {
|
) -> Ty {
|
||||||
let (ty, def) = self.resolve_variant(id.into(), path, true);
|
let (ty, def) = self.resolve_variant(id.into(), path, true);
|
||||||
let var_data = def.map(|it| it.variant_data(self.db));
|
let var_data = def.map(|it| it.fields(self.db));
|
||||||
if let Some(variant) = def {
|
if let Some(variant) = def {
|
||||||
self.write_variant_resolution(id.into(), variant);
|
self.write_variant_resolution(id.into(), variant);
|
||||||
}
|
}
|
||||||
|
|
@ -60,7 +60,7 @@ impl InferenceContext<'_> {
|
||||||
_ if subs.is_empty() => {}
|
_ if subs.is_empty() => {}
|
||||||
Some(def) => {
|
Some(def) => {
|
||||||
let field_types = self.db.field_types(def);
|
let field_types = self.db.field_types(def);
|
||||||
let variant_data = def.variant_data(self.db);
|
let variant_data = def.fields(self.db);
|
||||||
let visibilities = self.db.field_visibilities(def);
|
let visibilities = self.db.field_visibilities(def);
|
||||||
|
|
||||||
let (pre, post) = match ellipsis {
|
let (pre, post) = match ellipsis {
|
||||||
|
|
@ -129,7 +129,7 @@ impl InferenceContext<'_> {
|
||||||
_ if subs.len() == 0 => {}
|
_ if subs.len() == 0 => {}
|
||||||
Some(def) => {
|
Some(def) => {
|
||||||
let field_types = self.db.field_types(def);
|
let field_types = self.db.field_types(def);
|
||||||
let variant_data = def.variant_data(self.db);
|
let variant_data = def.fields(self.db);
|
||||||
let visibilities = self.db.field_visibilities(def);
|
let visibilities = self.db.field_visibilities(def);
|
||||||
|
|
||||||
let substs = ty.as_adt().map(TupleExt::tail);
|
let substs = ty.as_adt().map(TupleExt::tail);
|
||||||
|
|
|
||||||
|
|
@ -278,7 +278,7 @@ impl InferenceContext<'_> {
|
||||||
) -> Option<(ValueNs, Substitution)> {
|
) -> Option<(ValueNs, Substitution)> {
|
||||||
let trait_ = trait_ref.hir_trait_id();
|
let trait_ = trait_ref.hir_trait_id();
|
||||||
let item =
|
let item =
|
||||||
self.db.trait_items(trait_).items.iter().map(|(_name, id)| *id).find_map(|item| {
|
trait_.trait_items(self.db).items.iter().map(|(_name, id)| *id).find_map(|item| {
|
||||||
match item {
|
match item {
|
||||||
AssocItemId::FunctionId(func) => {
|
AssocItemId::FunctionId(func) => {
|
||||||
if segment.name == &self.db.function_signature(func).name {
|
if segment.name == &self.db.function_signature(func).name {
|
||||||
|
|
|
||||||
|
|
@ -859,7 +859,7 @@ impl<'a> InferenceTable<'a> {
|
||||||
] {
|
] {
|
||||||
let krate = self.trait_env.krate;
|
let krate = self.trait_env.krate;
|
||||||
let fn_trait = fn_trait_name.get_id(self.db, krate)?;
|
let fn_trait = fn_trait_name.get_id(self.db, krate)?;
|
||||||
let trait_data = self.db.trait_items(fn_trait);
|
let trait_data = fn_trait.trait_items(self.db);
|
||||||
let output_assoc_type =
|
let output_assoc_type =
|
||||||
trait_data.associated_type_by_name(&Name::new_symbol_root(output_assoc_name))?;
|
trait_data.associated_type_by_name(&Name::new_symbol_root(output_assoc_name))?;
|
||||||
|
|
||||||
|
|
@ -1001,7 +1001,7 @@ impl<'a> InferenceTable<'a> {
|
||||||
// Must use a loop here and not recursion because otherwise users will conduct completely
|
// Must use a loop here and not recursion because otherwise users will conduct completely
|
||||||
// artificial examples of structs that have themselves as the tail field and complain r-a crashes.
|
// artificial examples of structs that have themselves as the tail field and complain r-a crashes.
|
||||||
while let Some((AdtId::StructId(id), subst)) = ty.as_adt() {
|
while let Some((AdtId::StructId(id), subst)) = ty.as_adt() {
|
||||||
let struct_data = self.db.variant_fields(id.into());
|
let struct_data = id.fields(self.db);
|
||||||
if let Some((last_field, _)) = struct_data.fields().iter().next_back() {
|
if let Some((last_field, _)) = struct_data.fields().iter().next_back() {
|
||||||
let last_field_ty = self.db.field_types(id.into())[last_field]
|
let last_field_ty = self.db.field_types(id.into())[last_field]
|
||||||
.clone()
|
.clone()
|
||||||
|
|
|
||||||
|
|
@ -132,7 +132,7 @@ impl UninhabitedFrom<'_> {
|
||||||
variant: VariantId,
|
variant: VariantId,
|
||||||
subst: &Substitution,
|
subst: &Substitution,
|
||||||
) -> ControlFlow<VisiblyUninhabited> {
|
) -> ControlFlow<VisiblyUninhabited> {
|
||||||
let variant_data = self.db.variant_fields(variant);
|
let variant_data = variant.fields(self.db);
|
||||||
let fields = variant_data.fields();
|
let fields = variant_data.fields();
|
||||||
if fields.is_empty() {
|
if fields.is_empty() {
|
||||||
return CONTINUE_OPAQUELY_INHABITED;
|
return CONTINUE_OPAQUELY_INHABITED;
|
||||||
|
|
|
||||||
|
|
@ -261,7 +261,7 @@ pub fn layout_of_ty_query(
|
||||||
}
|
}
|
||||||
// Potentially-wide pointers.
|
// Potentially-wide pointers.
|
||||||
TyKind::Ref(_, _, pointee) | TyKind::Raw(_, pointee) => {
|
TyKind::Ref(_, _, pointee) | TyKind::Raw(_, pointee) => {
|
||||||
let mut data_ptr = scalar_unit(dl, Primitive::Pointer(AddressSpace::DATA));
|
let mut data_ptr = scalar_unit(dl, Primitive::Pointer(AddressSpace::ZERO));
|
||||||
if matches!(ty.kind(Interner), TyKind::Ref(..)) {
|
if matches!(ty.kind(Interner), TyKind::Ref(..)) {
|
||||||
data_ptr.valid_range_mut().start = 1;
|
data_ptr.valid_range_mut().start = 1;
|
||||||
}
|
}
|
||||||
|
|
@ -285,7 +285,7 @@ pub fn layout_of_ty_query(
|
||||||
scalar_unit(dl, Primitive::Int(dl.ptr_sized_integer(), false))
|
scalar_unit(dl, Primitive::Int(dl.ptr_sized_integer(), false))
|
||||||
}
|
}
|
||||||
TyKind::Dyn(..) => {
|
TyKind::Dyn(..) => {
|
||||||
let mut vtable = scalar_unit(dl, Primitive::Pointer(AddressSpace::DATA));
|
let mut vtable = scalar_unit(dl, Primitive::Pointer(AddressSpace::ZERO));
|
||||||
vtable.valid_range_mut().start = 1;
|
vtable.valid_range_mut().start = 1;
|
||||||
vtable
|
vtable
|
||||||
}
|
}
|
||||||
|
|
@ -375,7 +375,7 @@ pub(crate) fn layout_of_ty_cycle_result(
|
||||||
fn struct_tail_erasing_lifetimes(db: &dyn HirDatabase, pointee: Ty) -> Ty {
|
fn struct_tail_erasing_lifetimes(db: &dyn HirDatabase, pointee: Ty) -> Ty {
|
||||||
match pointee.kind(Interner) {
|
match pointee.kind(Interner) {
|
||||||
&TyKind::Adt(AdtId(hir_def::AdtId::StructId(i)), ref subst) => {
|
&TyKind::Adt(AdtId(hir_def::AdtId::StructId(i)), ref subst) => {
|
||||||
let data = db.variant_fields(i.into());
|
let data = i.fields(db);
|
||||||
let mut it = data.fields().iter().rev();
|
let mut it = data.fields().iter().rev();
|
||||||
match it.next() {
|
match it.next() {
|
||||||
Some((f, _)) => {
|
Some((f, _)) => {
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ pub fn layout_of_adt_query(
|
||||||
AdtId::StructId(s) => {
|
AdtId::StructId(s) => {
|
||||||
let sig = db.struct_signature(s);
|
let sig = db.struct_signature(s);
|
||||||
let mut r = SmallVec::<[_; 1]>::new();
|
let mut r = SmallVec::<[_; 1]>::new();
|
||||||
r.push(handle_variant(s.into(), &db.variant_fields(s.into()))?);
|
r.push(handle_variant(s.into(), s.fields(db))?);
|
||||||
(
|
(
|
||||||
r,
|
r,
|
||||||
sig.repr.unwrap_or_default(),
|
sig.repr.unwrap_or_default(),
|
||||||
|
|
@ -52,7 +52,7 @@ pub fn layout_of_adt_query(
|
||||||
AdtId::UnionId(id) => {
|
AdtId::UnionId(id) => {
|
||||||
let data = db.union_signature(id);
|
let data = db.union_signature(id);
|
||||||
let mut r = SmallVec::new();
|
let mut r = SmallVec::new();
|
||||||
r.push(handle_variant(id.into(), &db.variant_fields(id.into()))?);
|
r.push(handle_variant(id.into(), id.fields(db))?);
|
||||||
(r, data.repr.unwrap_or_default(), false)
|
(r, data.repr.unwrap_or_default(), false)
|
||||||
}
|
}
|
||||||
AdtId::EnumId(e) => {
|
AdtId::EnumId(e) => {
|
||||||
|
|
@ -60,7 +60,7 @@ pub fn layout_of_adt_query(
|
||||||
let r = variants
|
let r = variants
|
||||||
.variants
|
.variants
|
||||||
.iter()
|
.iter()
|
||||||
.map(|&(v, _, _)| handle_variant(v.into(), &db.variant_fields(v.into())))
|
.map(|&(v, _, _)| handle_variant(v.into(), v.fields(db)))
|
||||||
.collect::<Result<SmallVec<_>, _>>()?;
|
.collect::<Result<SmallVec<_>, _>>()?;
|
||||||
(r, db.enum_signature(e).repr.unwrap_or_default(), false)
|
(r, db.enum_signature(e).repr.unwrap_or_default(), false)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
use base_db::Crate;
|
use base_db::Crate;
|
||||||
use hir_def::layout::TargetDataLayout;
|
use hir_def::layout::TargetDataLayout;
|
||||||
use rustc_abi::{AlignFromBytesError, TargetDataLayoutErrors};
|
use rustc_abi::{AlignFromBytesError, TargetDataLayoutErrors, AddressSpace};
|
||||||
use triomphe::Arc;
|
use triomphe::Arc;
|
||||||
|
|
||||||
use crate::db::HirDatabase;
|
use crate::db::HirDatabase;
|
||||||
|
|
@ -12,7 +12,7 @@ pub fn target_data_layout_query(
|
||||||
krate: Crate,
|
krate: Crate,
|
||||||
) -> Result<Arc<TargetDataLayout>, Arc<str>> {
|
) -> Result<Arc<TargetDataLayout>, Arc<str>> {
|
||||||
match &krate.workspace_data(db).data_layout {
|
match &krate.workspace_data(db).data_layout {
|
||||||
Ok(it) => match TargetDataLayout::parse_from_llvm_datalayout_string(it) {
|
Ok(it) => match TargetDataLayout::parse_from_llvm_datalayout_string(it, AddressSpace::ZERO) {
|
||||||
Ok(it) => Ok(Arc::new(it)),
|
Ok(it) => Ok(Arc::new(it)),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
Err(match e {
|
Err(match e {
|
||||||
|
|
@ -39,6 +39,7 @@ pub fn target_data_layout_query(
|
||||||
target,
|
target,
|
||||||
} => format!(r#"inconsistent target specification: "data-layout" claims pointers are {pointer_size}-bit, while "target-pointer-width" is `{target}`"#),
|
} => format!(r#"inconsistent target specification: "data-layout" claims pointers are {pointer_size}-bit, while "target-pointer-width" is `{target}`"#),
|
||||||
TargetDataLayoutErrors::InvalidBitsSize { err } => err,
|
TargetDataLayoutErrors::InvalidBitsSize { err } => err,
|
||||||
|
TargetDataLayoutErrors::UnknownPointerSpecification { err } => format!(r#"use of unknown pointer specifer in "data-layout": {err}"#),
|
||||||
}.into())
|
}.into())
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -891,8 +891,8 @@ pub fn callable_sig_from_fn_trait(
|
||||||
) -> Option<(FnTrait, CallableSig)> {
|
) -> Option<(FnTrait, CallableSig)> {
|
||||||
let krate = trait_env.krate;
|
let krate = trait_env.krate;
|
||||||
let fn_once_trait = FnTrait::FnOnce.get_id(db, krate)?;
|
let fn_once_trait = FnTrait::FnOnce.get_id(db, krate)?;
|
||||||
let output_assoc_type = db
|
let output_assoc_type = fn_once_trait
|
||||||
.trait_items(fn_once_trait)
|
.trait_items(db)
|
||||||
.associated_type_by_name(&Name::new_symbol_root(sym::Output))?;
|
.associated_type_by_name(&Name::new_symbol_root(sym::Output))?;
|
||||||
|
|
||||||
let mut table = InferenceTable::new(db, trait_env.clone());
|
let mut table = InferenceTable::new(db, trait_env.clone());
|
||||||
|
|
|
||||||
|
|
@ -581,11 +581,28 @@ impl<'a> TyLoweringContext<'a> {
|
||||||
match bound {
|
match bound {
|
||||||
&TypeBound::Path(path, TraitBoundModifier::None) | &TypeBound::ForLifetime(_, path) => {
|
&TypeBound::Path(path, TraitBoundModifier::None) | &TypeBound::ForLifetime(_, path) => {
|
||||||
// FIXME Don't silently drop the hrtb lifetimes here
|
// FIXME Don't silently drop the hrtb lifetimes here
|
||||||
if let Some((trait_ref, ctx)) = self.lower_trait_ref_from_path(path, self_ty) {
|
if let Some((trait_ref, mut ctx)) =
|
||||||
if !ignore_bindings {
|
self.lower_trait_ref_from_path(path, self_ty.clone())
|
||||||
assoc_bounds = ctx.assoc_type_bindings_from_type_bound(trait_ref.clone());
|
{
|
||||||
|
// FIXME(sized-hierarchy): Remove this bound modifications once we have implemented
|
||||||
|
// sized-hierarchy correctly.
|
||||||
|
let meta_sized = LangItem::MetaSized
|
||||||
|
.resolve_trait(ctx.ty_ctx().db, ctx.ty_ctx().resolver.krate());
|
||||||
|
let pointee_sized = LangItem::PointeeSized
|
||||||
|
.resolve_trait(ctx.ty_ctx().db, ctx.ty_ctx().resolver.krate());
|
||||||
|
if meta_sized.is_some_and(|it| it == trait_ref.hir_trait_id()) {
|
||||||
|
// Ignore this bound
|
||||||
|
} else if pointee_sized.is_some_and(|it| it == trait_ref.hir_trait_id()) {
|
||||||
|
// Regard this as `?Sized` bound
|
||||||
|
ctx.ty_ctx().unsized_types.insert(self_ty);
|
||||||
|
} else {
|
||||||
|
if !ignore_bindings {
|
||||||
|
assoc_bounds =
|
||||||
|
ctx.assoc_type_bindings_from_type_bound(trait_ref.clone());
|
||||||
|
}
|
||||||
|
clause =
|
||||||
|
Some(crate::wrap_empty_binders(WhereClause::Implemented(trait_ref)));
|
||||||
}
|
}
|
||||||
clause = Some(crate::wrap_empty_binders(WhereClause::Implemented(trait_ref)));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&TypeBound::Path(path, TraitBoundModifier::Maybe) => {
|
&TypeBound::Path(path, TraitBoundModifier::Maybe) => {
|
||||||
|
|
@ -711,7 +728,7 @@ impl<'a> TyLoweringContext<'a> {
|
||||||
.unwrap_or(it),
|
.unwrap_or(it),
|
||||||
None => it,
|
None => it,
|
||||||
},
|
},
|
||||||
None => static_lifetime(),
|
None => error_lifetime(),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
.intern(Interner)
|
.intern(Interner)
|
||||||
|
|
@ -805,7 +822,7 @@ fn named_associated_type_shorthand_candidates<R>(
|
||||||
) -> Option<R> {
|
) -> Option<R> {
|
||||||
let mut search = |t| {
|
let mut search = |t| {
|
||||||
all_super_trait_refs(db, t, |t| {
|
all_super_trait_refs(db, t, |t| {
|
||||||
let data = db.trait_items(t.hir_trait_id());
|
let data = t.hir_trait_id().trait_items(db);
|
||||||
|
|
||||||
for (name, assoc_id) in &data.items {
|
for (name, assoc_id) in &data.items {
|
||||||
if let AssocItemId::TypeAliasId(alias) = assoc_id {
|
if let AssocItemId::TypeAliasId(alias) = assoc_id {
|
||||||
|
|
@ -883,7 +900,12 @@ pub(crate) fn field_types_with_diagnostics_query(
|
||||||
db: &dyn HirDatabase,
|
db: &dyn HirDatabase,
|
||||||
variant_id: VariantId,
|
variant_id: VariantId,
|
||||||
) -> (Arc<ArenaMap<LocalFieldId, Binders<Ty>>>, Diagnostics) {
|
) -> (Arc<ArenaMap<LocalFieldId, Binders<Ty>>>, Diagnostics) {
|
||||||
let var_data = db.variant_fields(variant_id);
|
let var_data = variant_id.fields(db);
|
||||||
|
let fields = var_data.fields();
|
||||||
|
if fields.is_empty() {
|
||||||
|
return (Arc::new(ArenaMap::default()), None);
|
||||||
|
}
|
||||||
|
|
||||||
let (resolver, def): (_, GenericDefId) = match variant_id {
|
let (resolver, def): (_, GenericDefId) = match variant_id {
|
||||||
VariantId::StructId(it) => (it.resolver(db), it.into()),
|
VariantId::StructId(it) => (it.resolver(db), it.into()),
|
||||||
VariantId::UnionId(it) => (it.resolver(db), it.into()),
|
VariantId::UnionId(it) => (it.resolver(db), it.into()),
|
||||||
|
|
@ -899,7 +921,7 @@ pub(crate) fn field_types_with_diagnostics_query(
|
||||||
LifetimeElisionKind::AnonymousReportError,
|
LifetimeElisionKind::AnonymousReportError,
|
||||||
)
|
)
|
||||||
.with_type_param_mode(ParamLoweringMode::Variable);
|
.with_type_param_mode(ParamLoweringMode::Variable);
|
||||||
for (field_id, field_data) in var_data.fields().iter() {
|
for (field_id, field_data) in fields.iter() {
|
||||||
res.insert(field_id, make_binders(db, &generics, ctx.lower_ty(field_data.type_ref)));
|
res.insert(field_id, make_binders(db, &generics, ctx.lower_ty(field_data.type_ref)));
|
||||||
}
|
}
|
||||||
(Arc::new(res), create_diagnostics(ctx.diagnostics))
|
(Arc::new(res), create_diagnostics(ctx.diagnostics))
|
||||||
|
|
@ -920,6 +942,10 @@ pub(crate) fn generic_predicates_for_param_query(
|
||||||
assoc_name: Option<Name>,
|
assoc_name: Option<Name>,
|
||||||
) -> GenericPredicates {
|
) -> GenericPredicates {
|
||||||
let generics = generics(db, def);
|
let generics = generics(db, def);
|
||||||
|
if generics.has_no_predicates() && generics.is_empty() {
|
||||||
|
return GenericPredicates(None);
|
||||||
|
}
|
||||||
|
|
||||||
let resolver = def.resolver(db);
|
let resolver = def.resolver(db);
|
||||||
let mut ctx = TyLoweringContext::new(
|
let mut ctx = TyLoweringContext::new(
|
||||||
db,
|
db,
|
||||||
|
|
@ -936,8 +962,32 @@ pub(crate) fn generic_predicates_for_param_query(
|
||||||
| WherePredicate::TypeBound { target, bound, .. } => {
|
| WherePredicate::TypeBound { target, bound, .. } => {
|
||||||
let invalid_target = { ctx.lower_ty_only_param(*target) != Some(param_id) };
|
let invalid_target = { ctx.lower_ty_only_param(*target) != Some(param_id) };
|
||||||
if invalid_target {
|
if invalid_target {
|
||||||
// If this is filtered out without lowering, `?Sized` is not gathered into `ctx.unsized_types`
|
// FIXME(sized-hierarchy): Revisit and adjust this properly once we have implemented
|
||||||
if let TypeBound::Path(_, TraitBoundModifier::Maybe) = bound {
|
// sized-hierarchy correctly.
|
||||||
|
// If this is filtered out without lowering, `?Sized` or `PointeeSized` is not gathered into
|
||||||
|
// `ctx.unsized_types`
|
||||||
|
let lower = || -> bool {
|
||||||
|
match bound {
|
||||||
|
TypeBound::Path(_, TraitBoundModifier::Maybe) => true,
|
||||||
|
TypeBound::Path(path, _) | TypeBound::ForLifetime(_, path) => {
|
||||||
|
let TypeRef::Path(path) = &ctx.store[path.type_ref()] else {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
let Some(pointee_sized) =
|
||||||
|
LangItem::PointeeSized.resolve_trait(ctx.db, ctx.resolver.krate())
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
// Lower the path directly with `Resolver` instead of PathLoweringContext`
|
||||||
|
// to prevent diagnostics duplications.
|
||||||
|
ctx.resolver.resolve_path_in_type_ns_fully(ctx.db, path).is_some_and(
|
||||||
|
|it| matches!(it, TypeNs::TraitId(tr) if tr == pointee_sized),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}();
|
||||||
|
if lower {
|
||||||
ctx.lower_where_predicate(pred, true).for_each(drop);
|
ctx.lower_where_predicate(pred, true).for_each(drop);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -957,7 +1007,7 @@ pub(crate) fn generic_predicates_for_param_query(
|
||||||
};
|
};
|
||||||
|
|
||||||
all_super_traits(db, tr).iter().any(|tr| {
|
all_super_traits(db, tr).iter().any(|tr| {
|
||||||
db.trait_items(*tr).items.iter().any(|(name, item)| {
|
tr.trait_items(db).items.iter().any(|(name, item)| {
|
||||||
matches!(item, AssocItemId::TypeAliasId(_)) && name == assoc_name
|
matches!(item, AssocItemId::TypeAliasId(_)) && name == assoc_name
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
@ -1025,6 +1075,10 @@ pub(crate) fn trait_environment_query(
|
||||||
def: GenericDefId,
|
def: GenericDefId,
|
||||||
) -> Arc<TraitEnvironment> {
|
) -> Arc<TraitEnvironment> {
|
||||||
let generics = generics(db, def);
|
let generics = generics(db, def);
|
||||||
|
if generics.has_no_predicates() && generics.is_empty() {
|
||||||
|
return TraitEnvironment::empty(def.krate(db));
|
||||||
|
}
|
||||||
|
|
||||||
let resolver = def.resolver(db);
|
let resolver = def.resolver(db);
|
||||||
let mut ctx = TyLoweringContext::new(
|
let mut ctx = TyLoweringContext::new(
|
||||||
db,
|
db,
|
||||||
|
|
@ -1128,6 +1182,10 @@ where
|
||||||
F: Fn(&WherePredicate, GenericDefId) -> bool,
|
F: Fn(&WherePredicate, GenericDefId) -> bool,
|
||||||
{
|
{
|
||||||
let generics = generics(db, def);
|
let generics = generics(db, def);
|
||||||
|
if generics.has_no_predicates() && generics.is_empty() {
|
||||||
|
return (GenericPredicates(None), None);
|
||||||
|
}
|
||||||
|
|
||||||
let resolver = def.resolver(db);
|
let resolver = def.resolver(db);
|
||||||
let mut ctx = TyLoweringContext::new(
|
let mut ctx = TyLoweringContext::new(
|
||||||
db,
|
db,
|
||||||
|
|
@ -1154,7 +1212,7 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if generics.len() > 0 {
|
if !generics.is_empty() {
|
||||||
let subst = generics.bound_vars_subst(db, DebruijnIndex::INNERMOST);
|
let subst = generics.bound_vars_subst(db, DebruijnIndex::INNERMOST);
|
||||||
let explicitly_unsized_tys = ctx.unsized_types;
|
let explicitly_unsized_tys = ctx.unsized_types;
|
||||||
if let Some(implicitly_sized_predicates) =
|
if let Some(implicitly_sized_predicates) =
|
||||||
|
|
@ -1229,7 +1287,7 @@ pub(crate) fn generic_defaults_with_diagnostics_query(
|
||||||
def: GenericDefId,
|
def: GenericDefId,
|
||||||
) -> (GenericDefaults, Diagnostics) {
|
) -> (GenericDefaults, Diagnostics) {
|
||||||
let generic_params = generics(db, def);
|
let generic_params = generics(db, def);
|
||||||
if generic_params.len() == 0 {
|
if generic_params.is_empty() {
|
||||||
return (GenericDefaults(None), None);
|
return (GenericDefaults(None), None);
|
||||||
}
|
}
|
||||||
let resolver = def.resolver(db);
|
let resolver = def.resolver(db);
|
||||||
|
|
@ -1418,7 +1476,7 @@ fn fn_sig_for_struct_constructor(db: &dyn HirDatabase, def: StructId) -> PolyFnS
|
||||||
|
|
||||||
/// Build the type of a tuple struct constructor.
|
/// Build the type of a tuple struct constructor.
|
||||||
fn type_for_struct_constructor(db: &dyn HirDatabase, def: StructId) -> Option<Binders<Ty>> {
|
fn type_for_struct_constructor(db: &dyn HirDatabase, def: StructId) -> Option<Binders<Ty>> {
|
||||||
let struct_data = db.variant_fields(def.into());
|
let struct_data = def.fields(db);
|
||||||
match struct_data.shape {
|
match struct_data.shape {
|
||||||
FieldsShape::Record => None,
|
FieldsShape::Record => None,
|
||||||
FieldsShape::Unit => Some(type_for_adt(db, def.into())),
|
FieldsShape::Unit => Some(type_for_adt(db, def.into())),
|
||||||
|
|
@ -1451,7 +1509,7 @@ fn type_for_enum_variant_constructor(
|
||||||
def: EnumVariantId,
|
def: EnumVariantId,
|
||||||
) -> Option<Binders<Ty>> {
|
) -> Option<Binders<Ty>> {
|
||||||
let e = def.lookup(db).parent;
|
let e = def.lookup(db).parent;
|
||||||
match db.variant_fields(def.into()).shape {
|
match def.fields(db).shape {
|
||||||
FieldsShape::Record => None,
|
FieldsShape::Record => None,
|
||||||
FieldsShape::Unit => Some(type_for_adt(db, e.into())),
|
FieldsShape::Unit => Some(type_for_adt(db, e.into())),
|
||||||
FieldsShape::Tuple => {
|
FieldsShape::Tuple => {
|
||||||
|
|
|
||||||
|
|
@ -173,7 +173,7 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
|
||||||
self.skip_resolved_segment();
|
self.skip_resolved_segment();
|
||||||
let segment = self.current_or_prev_segment;
|
let segment = self.current_or_prev_segment;
|
||||||
let found =
|
let found =
|
||||||
self.ctx.db.trait_items(trait_).associated_type_by_name(segment.name);
|
trait_.trait_items(self.ctx.db).associated_type_by_name(segment.name);
|
||||||
|
|
||||||
match found {
|
match found {
|
||||||
Some(associated_ty) => {
|
Some(associated_ty) => {
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,8 @@ use salsa::{
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
AssocTypeId, CallableDefId, ChalkTraitId, FnDefId, ForeignDefId, Interner, OpaqueTyId,
|
AssocTypeId, CallableDefId, ChalkTraitId, FnDefId, ForeignDefId, Interner, OpaqueTyId,
|
||||||
PlaceholderIndex, chalk_db, db::HirDatabase,
|
PlaceholderIndex, chalk_db,
|
||||||
|
db::{HirDatabase, InternedLifetimeParamId, InternedTypeOrConstParamId},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub trait ToChalk {
|
pub trait ToChalk {
|
||||||
|
|
@ -125,30 +126,32 @@ pub fn from_assoc_type_id(id: AssocTypeId) -> TypeAliasId {
|
||||||
pub fn from_placeholder_idx(db: &dyn HirDatabase, idx: PlaceholderIndex) -> TypeOrConstParamId {
|
pub fn from_placeholder_idx(db: &dyn HirDatabase, idx: PlaceholderIndex) -> TypeOrConstParamId {
|
||||||
assert_eq!(idx.ui, chalk_ir::UniverseIndex::ROOT);
|
assert_eq!(idx.ui, chalk_ir::UniverseIndex::ROOT);
|
||||||
// SAFETY: We cannot really encapsulate this unfortunately, so just hope this is sound.
|
// SAFETY: We cannot really encapsulate this unfortunately, so just hope this is sound.
|
||||||
let interned_id = FromId::from_id(unsafe { Id::from_u32(idx.idx.try_into().unwrap()) });
|
let interned_id =
|
||||||
db.lookup_intern_type_or_const_param_id(interned_id)
|
InternedTypeOrConstParamId::from_id(unsafe { Id::from_index(idx.idx.try_into().unwrap()) });
|
||||||
|
interned_id.loc(db)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_placeholder_idx(db: &dyn HirDatabase, id: TypeOrConstParamId) -> PlaceholderIndex {
|
pub fn to_placeholder_idx(db: &dyn HirDatabase, id: TypeOrConstParamId) -> PlaceholderIndex {
|
||||||
let interned_id = db.intern_type_or_const_param_id(id);
|
let interned_id = InternedTypeOrConstParamId::new(db, id);
|
||||||
PlaceholderIndex {
|
PlaceholderIndex {
|
||||||
ui: chalk_ir::UniverseIndex::ROOT,
|
ui: chalk_ir::UniverseIndex::ROOT,
|
||||||
idx: interned_id.as_id().as_u32() as usize,
|
idx: interned_id.as_id().index() as usize,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn lt_from_placeholder_idx(db: &dyn HirDatabase, idx: PlaceholderIndex) -> LifetimeParamId {
|
pub fn lt_from_placeholder_idx(db: &dyn HirDatabase, idx: PlaceholderIndex) -> LifetimeParamId {
|
||||||
assert_eq!(idx.ui, chalk_ir::UniverseIndex::ROOT);
|
assert_eq!(idx.ui, chalk_ir::UniverseIndex::ROOT);
|
||||||
// SAFETY: We cannot really encapsulate this unfortunately, so just hope this is sound.
|
// SAFETY: We cannot really encapsulate this unfortunately, so just hope this is sound.
|
||||||
let interned_id = FromId::from_id(unsafe { Id::from_u32(idx.idx.try_into().unwrap()) });
|
let interned_id =
|
||||||
db.lookup_intern_lifetime_param_id(interned_id)
|
InternedLifetimeParamId::from_id(unsafe { Id::from_index(idx.idx.try_into().unwrap()) });
|
||||||
|
interned_id.loc(db)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn lt_to_placeholder_idx(db: &dyn HirDatabase, id: LifetimeParamId) -> PlaceholderIndex {
|
pub fn lt_to_placeholder_idx(db: &dyn HirDatabase, id: LifetimeParamId) -> PlaceholderIndex {
|
||||||
let interned_id = db.intern_lifetime_param_id(id);
|
let interned_id = InternedLifetimeParamId::new(db, id);
|
||||||
PlaceholderIndex {
|
PlaceholderIndex {
|
||||||
ui: chalk_ir::UniverseIndex::ROOT,
|
ui: chalk_ir::UniverseIndex::ROOT,
|
||||||
idx: interned_id.as_id().as_u32() as usize,
|
idx: interned_id.as_id().index() as usize,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1302,7 +1302,7 @@ fn iterate_trait_method_candidates(
|
||||||
// trait, but if we find out it doesn't, we'll skip the rest of the
|
// trait, but if we find out it doesn't, we'll skip the rest of the
|
||||||
// iteration
|
// iteration
|
||||||
let mut known_implemented = false;
|
let mut known_implemented = false;
|
||||||
for &(_, item) in db.trait_items(t).items.iter() {
|
for &(_, item) in t.trait_items(db).items.iter() {
|
||||||
// Don't pass a `visible_from_module` down to `is_valid_candidate`,
|
// Don't pass a `visible_from_module` down to `is_valid_candidate`,
|
||||||
// since only inherent methods should be included into visibility checking.
|
// since only inherent methods should be included into visibility checking.
|
||||||
let visible =
|
let visible =
|
||||||
|
|
@ -1429,7 +1429,7 @@ fn iterate_inherent_methods(
|
||||||
) -> ControlFlow<()> {
|
) -> ControlFlow<()> {
|
||||||
let db = table.db;
|
let db = table.db;
|
||||||
for t in traits {
|
for t in traits {
|
||||||
let data = db.trait_items(t);
|
let data = t.trait_items(db);
|
||||||
for &(_, item) in data.items.iter() {
|
for &(_, item) in data.items.iter() {
|
||||||
// We don't pass `visible_from_module` as all trait items should be visible.
|
// We don't pass `visible_from_module` as all trait items should be visible.
|
||||||
let visible = match is_valid_trait_method_candidate(
|
let visible = match is_valid_trait_method_candidate(
|
||||||
|
|
|
||||||
|
|
@ -630,7 +630,7 @@ impl Evaluator<'_> {
|
||||||
Ok(target_data_layout) => target_data_layout,
|
Ok(target_data_layout) => target_data_layout,
|
||||||
Err(e) => return Err(MirEvalError::TargetDataLayoutNotAvailable(e)),
|
Err(e) => return Err(MirEvalError::TargetDataLayoutNotAvailable(e)),
|
||||||
};
|
};
|
||||||
let cached_ptr_size = target_data_layout.pointer_size.bytes_usize();
|
let cached_ptr_size = target_data_layout.pointer_size().bytes_usize();
|
||||||
Ok(Evaluator {
|
Ok(Evaluator {
|
||||||
target_data_layout,
|
target_data_layout,
|
||||||
stack: vec![0],
|
stack: vec![0],
|
||||||
|
|
@ -657,12 +657,12 @@ impl Evaluator<'_> {
|
||||||
cached_ptr_size,
|
cached_ptr_size,
|
||||||
cached_fn_trait_func: LangItem::Fn
|
cached_fn_trait_func: LangItem::Fn
|
||||||
.resolve_trait(db, crate_id)
|
.resolve_trait(db, crate_id)
|
||||||
.and_then(|x| db.trait_items(x).method_by_name(&Name::new_symbol_root(sym::call))),
|
.and_then(|x| x.trait_items(db).method_by_name(&Name::new_symbol_root(sym::call))),
|
||||||
cached_fn_mut_trait_func: LangItem::FnMut.resolve_trait(db, crate_id).and_then(|x| {
|
cached_fn_mut_trait_func: LangItem::FnMut.resolve_trait(db, crate_id).and_then(|x| {
|
||||||
db.trait_items(x).method_by_name(&Name::new_symbol_root(sym::call_mut))
|
x.trait_items(db).method_by_name(&Name::new_symbol_root(sym::call_mut))
|
||||||
}),
|
}),
|
||||||
cached_fn_once_trait_func: LangItem::FnOnce.resolve_trait(db, crate_id).and_then(|x| {
|
cached_fn_once_trait_func: LangItem::FnOnce.resolve_trait(db, crate_id).and_then(|x| {
|
||||||
db.trait_items(x).method_by_name(&Name::new_symbol_root(sym::call_once))
|
x.trait_items(db).method_by_name(&Name::new_symbol_root(sym::call_once))
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
@ -1749,8 +1749,7 @@ impl Evaluator<'_> {
|
||||||
AdtId::UnionId(_) => not_supported!("unsizing unions"),
|
AdtId::UnionId(_) => not_supported!("unsizing unions"),
|
||||||
AdtId::EnumId(_) => not_supported!("unsizing enums"),
|
AdtId::EnumId(_) => not_supported!("unsizing enums"),
|
||||||
};
|
};
|
||||||
let Some((last_field, _)) =
|
let Some((last_field, _)) = id.fields(self.db).fields().iter().next_back()
|
||||||
self.db.variant_fields(id.into()).fields().iter().next_back()
|
|
||||||
else {
|
else {
|
||||||
not_supported!("unsizing struct without field");
|
not_supported!("unsizing struct without field");
|
||||||
};
|
};
|
||||||
|
|
@ -2232,7 +2231,7 @@ impl Evaluator<'_> {
|
||||||
}
|
}
|
||||||
chalk_ir::TyKind::Adt(adt, subst) => match adt.0 {
|
chalk_ir::TyKind::Adt(adt, subst) => match adt.0 {
|
||||||
AdtId::StructId(s) => {
|
AdtId::StructId(s) => {
|
||||||
let data = this.db.variant_fields(s.into());
|
let data = s.fields(this.db);
|
||||||
let layout = this.layout(ty)?;
|
let layout = this.layout(ty)?;
|
||||||
let field_types = this.db.field_types(s.into());
|
let field_types = this.db.field_types(s.into());
|
||||||
for (f, _) in data.fields().iter() {
|
for (f, _) in data.fields().iter() {
|
||||||
|
|
@ -2261,7 +2260,7 @@ impl Evaluator<'_> {
|
||||||
bytes,
|
bytes,
|
||||||
e,
|
e,
|
||||||
) {
|
) {
|
||||||
let data = &this.db.variant_fields(v.into());
|
let data = v.fields(this.db);
|
||||||
let field_types = this.db.field_types(v.into());
|
let field_types = this.db.field_types(v.into());
|
||||||
for (f, _) in data.fields().iter() {
|
for (f, _) in data.fields().iter() {
|
||||||
let offset =
|
let offset =
|
||||||
|
|
@ -2808,7 +2807,7 @@ impl Evaluator<'_> {
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let Some(drop_fn) = (|| {
|
let Some(drop_fn) = (|| {
|
||||||
let drop_trait = LangItem::Drop.resolve_trait(self.db, self.crate_id)?;
|
let drop_trait = LangItem::Drop.resolve_trait(self.db, self.crate_id)?;
|
||||||
self.db.trait_items(drop_trait).method_by_name(&Name::new_symbol_root(sym::drop))
|
drop_trait.trait_items(self.db).method_by_name(&Name::new_symbol_root(sym::drop))
|
||||||
})() else {
|
})() else {
|
||||||
// in some tests we don't have drop trait in minicore, and
|
// in some tests we don't have drop trait in minicore, and
|
||||||
// we can ignore drop in them.
|
// we can ignore drop in them.
|
||||||
|
|
@ -2838,7 +2837,7 @@ impl Evaluator<'_> {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
let layout = self.layout_adt(id.0, subst.clone())?;
|
let layout = self.layout_adt(id.0, subst.clone())?;
|
||||||
let variant_fields = self.db.variant_fields(s.into());
|
let variant_fields = s.fields(self.db);
|
||||||
match variant_fields.shape {
|
match variant_fields.shape {
|
||||||
FieldsShape::Record | FieldsShape::Tuple => {
|
FieldsShape::Record | FieldsShape::Tuple => {
|
||||||
let field_types = self.db.field_types(s.into());
|
let field_types = self.db.field_types(s.into());
|
||||||
|
|
@ -2918,7 +2917,7 @@ pub fn render_const_using_debug_impl(
|
||||||
not_supported!("core::fmt::Debug not found");
|
not_supported!("core::fmt::Debug not found");
|
||||||
};
|
};
|
||||||
let Some(debug_fmt_fn) =
|
let Some(debug_fmt_fn) =
|
||||||
db.trait_items(debug_trait).method_by_name(&Name::new_symbol_root(sym::fmt))
|
debug_trait.trait_items(db).method_by_name(&Name::new_symbol_root(sym::fmt))
|
||||||
else {
|
else {
|
||||||
not_supported!("core::fmt::Debug::fmt not found");
|
not_supported!("core::fmt::Debug::fmt not found");
|
||||||
};
|
};
|
||||||
|
|
@ -3045,7 +3044,10 @@ impl IntValue {
|
||||||
(8, true) => Self::I64(i64::from_le_bytes(bytes.try_into().unwrap())),
|
(8, true) => Self::I64(i64::from_le_bytes(bytes.try_into().unwrap())),
|
||||||
(16, false) => Self::U128(u128::from_le_bytes(bytes.try_into().unwrap())),
|
(16, false) => Self::U128(u128::from_le_bytes(bytes.try_into().unwrap())),
|
||||||
(16, true) => Self::I128(i128::from_le_bytes(bytes.try_into().unwrap())),
|
(16, true) => Self::I128(i128::from_le_bytes(bytes.try_into().unwrap())),
|
||||||
_ => panic!("invalid integer size"),
|
(len, is_signed) => {
|
||||||
|
never!("invalid integer size: {len}, signed: {is_signed}");
|
||||||
|
Self::I32(0)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1257,9 +1257,8 @@ impl Evaluator<'_> {
|
||||||
args.push(IntervalAndTy::new(addr, field, self, locals)?);
|
args.push(IntervalAndTy::new(addr, field, self, locals)?);
|
||||||
}
|
}
|
||||||
if let Some(target) = LangItem::FnOnce.resolve_trait(self.db, self.crate_id) {
|
if let Some(target) = LangItem::FnOnce.resolve_trait(self.db, self.crate_id) {
|
||||||
if let Some(def) = self
|
if let Some(def) = target
|
||||||
.db
|
.trait_items(self.db)
|
||||||
.trait_items(target)
|
|
||||||
.method_by_name(&Name::new_symbol_root(sym::call_once))
|
.method_by_name(&Name::new_symbol_root(sym::call_once))
|
||||||
{
|
{
|
||||||
self.exec_fn_trait(
|
self.exec_fn_trait(
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ impl Evaluator<'_> {
|
||||||
Some(len) => len,
|
Some(len) => len,
|
||||||
_ => {
|
_ => {
|
||||||
if let AdtId::StructId(id) = id.0 {
|
if let AdtId::StructId(id) = id.0 {
|
||||||
let struct_data = self.db.variant_fields(id.into());
|
let struct_data = id.fields(self.db);
|
||||||
let fields = struct_data.fields();
|
let fields = struct_data.fields();
|
||||||
let Some((first_field, _)) = fields.iter().next() else {
|
let Some((first_field, _)) = fields.iter().next() else {
|
||||||
not_supported!("simd type with no field");
|
not_supported!("simd type with no field");
|
||||||
|
|
|
||||||
|
|
@ -984,3 +984,17 @@ fn main<'a, T: Foo + Bar + Baz>(
|
||||||
|e| matches!(e, MirEvalError::MirLowerError(_, MirLowerError::GenericArgNotProvided(..))),
|
|e| matches!(e, MirEvalError::MirLowerError(_, MirLowerError::GenericArgNotProvided(..))),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn format_args_pass() {
|
||||||
|
check_pass(
|
||||||
|
r#"
|
||||||
|
//- minicore: fmt
|
||||||
|
fn main() {
|
||||||
|
let x1 = format_args!("");
|
||||||
|
let x2 = format_args!("{}", x1);
|
||||||
|
let x3 = format_args!("{} {}", x1, x2);
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -503,7 +503,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
|
||||||
Ok(Some(current))
|
Ok(Some(current))
|
||||||
}
|
}
|
||||||
ValueNs::EnumVariantId(variant_id) => {
|
ValueNs::EnumVariantId(variant_id) => {
|
||||||
let variant_fields = &self.db.variant_fields(variant_id.into());
|
let variant_fields = variant_id.fields(self.db);
|
||||||
if variant_fields.shape == FieldsShape::Unit {
|
if variant_fields.shape == FieldsShape::Unit {
|
||||||
let ty = self.infer.type_of_expr[expr_id].clone();
|
let ty = self.infer.type_of_expr[expr_id].clone();
|
||||||
current = self.lower_enum_variant(
|
current = self.lower_enum_variant(
|
||||||
|
|
@ -856,7 +856,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
|
||||||
TyKind::Adt(_, s) => s.clone(),
|
TyKind::Adt(_, s) => s.clone(),
|
||||||
_ => not_supported!("Non ADT record literal"),
|
_ => not_supported!("Non ADT record literal"),
|
||||||
};
|
};
|
||||||
let variant_fields = self.db.variant_fields(variant_id);
|
let variant_fields = variant_id.fields(self.db);
|
||||||
match variant_id {
|
match variant_id {
|
||||||
VariantId::EnumVariantId(_) | VariantId::StructId(_) => {
|
VariantId::EnumVariantId(_) | VariantId::StructId(_) => {
|
||||||
let mut operands = vec![None; variant_fields.fields().len()];
|
let mut operands = vec![None; variant_fields.fields().len()];
|
||||||
|
|
@ -1176,8 +1176,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
|
||||||
place,
|
place,
|
||||||
Rvalue::Aggregate(
|
Rvalue::Aggregate(
|
||||||
AggregateKind::Adt(st.into(), subst.clone()),
|
AggregateKind::Adt(st.into(), subst.clone()),
|
||||||
self.db
|
st.fields(self.db)
|
||||||
.variant_fields(st.into())
|
|
||||||
.fields()
|
.fields()
|
||||||
.iter()
|
.iter()
|
||||||
.map(|it| {
|
.map(|it| {
|
||||||
|
|
|
||||||
|
|
@ -193,9 +193,8 @@ impl MirLowerCtx<'_> {
|
||||||
if let Some(deref_trait) =
|
if let Some(deref_trait) =
|
||||||
self.resolve_lang_item(LangItem::DerefMut)?.as_trait()
|
self.resolve_lang_item(LangItem::DerefMut)?.as_trait()
|
||||||
{
|
{
|
||||||
if let Some(deref_fn) = self
|
if let Some(deref_fn) = deref_trait
|
||||||
.db
|
.trait_items(self.db)
|
||||||
.trait_items(deref_trait)
|
|
||||||
.method_by_name(&Name::new_symbol_root(sym::deref_mut))
|
.method_by_name(&Name::new_symbol_root(sym::deref_mut))
|
||||||
{
|
{
|
||||||
break 'b deref_fn == f;
|
break 'b deref_fn == f;
|
||||||
|
|
@ -347,9 +346,8 @@ impl MirLowerCtx<'_> {
|
||||||
.resolve_lang_item(trait_lang_item)?
|
.resolve_lang_item(trait_lang_item)?
|
||||||
.as_trait()
|
.as_trait()
|
||||||
.ok_or(MirLowerError::LangItemNotFound(trait_lang_item))?;
|
.ok_or(MirLowerError::LangItemNotFound(trait_lang_item))?;
|
||||||
let deref_fn = self
|
let deref_fn = deref_trait
|
||||||
.db
|
.trait_items(self.db)
|
||||||
.trait_items(deref_trait)
|
|
||||||
.method_by_name(&trait_method_name)
|
.method_by_name(&trait_method_name)
|
||||||
.ok_or(MirLowerError::LangItemNotFound(trait_lang_item))?;
|
.ok_or(MirLowerError::LangItemNotFound(trait_lang_item))?;
|
||||||
let deref_fn_op = Operand::const_zst(
|
let deref_fn_op = Operand::const_zst(
|
||||||
|
|
|
||||||
|
|
@ -609,7 +609,7 @@ impl MirLowerCtx<'_> {
|
||||||
}
|
}
|
||||||
self.pattern_matching_variant_fields(
|
self.pattern_matching_variant_fields(
|
||||||
shape,
|
shape,
|
||||||
&self.db.variant_fields(v.into()),
|
v.fields(self.db),
|
||||||
variant,
|
variant,
|
||||||
current,
|
current,
|
||||||
current_else,
|
current_else,
|
||||||
|
|
@ -619,7 +619,7 @@ impl MirLowerCtx<'_> {
|
||||||
}
|
}
|
||||||
VariantId::StructId(s) => self.pattern_matching_variant_fields(
|
VariantId::StructId(s) => self.pattern_matching_variant_fields(
|
||||||
shape,
|
shape,
|
||||||
&self.db.variant_fields(s.into()),
|
s.fields(self.db),
|
||||||
variant,
|
variant,
|
||||||
current,
|
current,
|
||||||
current_else,
|
current_else,
|
||||||
|
|
|
||||||
|
|
@ -326,7 +326,7 @@ impl<'a> MirPrettyCtx<'a> {
|
||||||
w!(this, ")");
|
w!(this, ")");
|
||||||
}
|
}
|
||||||
ProjectionElem::Field(Either::Left(field)) => {
|
ProjectionElem::Field(Either::Left(field)) => {
|
||||||
let variant_fields = this.db.variant_fields(field.parent);
|
let variant_fields = field.parent.fields(this.db);
|
||||||
let name = &variant_fields.fields()[field.local_id].name;
|
let name = &variant_fields.fields()[field.local_id].name;
|
||||||
match field.parent {
|
match field.parent {
|
||||||
hir_def::VariantId::EnumVariantId(e) => {
|
hir_def::VariantId::EnumVariantId(e) => {
|
||||||
|
|
|
||||||
|
|
@ -166,10 +166,10 @@ impl TestDB {
|
||||||
self.events.lock().unwrap().take().unwrap()
|
self.events.lock().unwrap().take().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn log_executed(&self, f: impl FnOnce()) -> Vec<String> {
|
pub(crate) fn log_executed(&self, f: impl FnOnce()) -> (Vec<String>, Vec<salsa::Event>) {
|
||||||
let events = self.log(f);
|
let events = self.log(f);
|
||||||
events
|
let executed = events
|
||||||
.into_iter()
|
.iter()
|
||||||
.filter_map(|e| match e.kind {
|
.filter_map(|e| match e.kind {
|
||||||
// This is pretty horrible, but `Debug` is the only way to inspect
|
// This is pretty horrible, but `Debug` is the only way to inspect
|
||||||
// QueryDescriptor at the moment.
|
// QueryDescriptor at the moment.
|
||||||
|
|
@ -181,6 +181,7 @@ impl TestDB {
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
})
|
})
|
||||||
.collect()
|
.collect();
|
||||||
|
(executed, events)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -486,7 +486,7 @@ pub(crate) fn visit_module(
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
ModuleDefId::TraitId(it) => {
|
ModuleDefId::TraitId(it) => {
|
||||||
let trait_data = db.trait_items(it);
|
let trait_data = it.trait_items(db);
|
||||||
for &(_, item) in trait_data.items.iter() {
|
for &(_, item) in trait_data.items.iter() {
|
||||||
match item {
|
match item {
|
||||||
AssocItemId::FunctionId(it) => cb(it.into()),
|
AssocItemId::FunctionId(it) => cb(it.into()),
|
||||||
|
|
|
||||||
|
|
@ -446,7 +446,7 @@ fn main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn let_binding_is_a_ref_capture() {
|
fn let_binding_is_a_ref_capture_in_ref_binding() {
|
||||||
check_closure_captures(
|
check_closure_captures(
|
||||||
r#"
|
r#"
|
||||||
//- minicore:copy
|
//- minicore:copy
|
||||||
|
|
@ -454,12 +454,36 @@ struct S;
|
||||||
fn main() {
|
fn main() {
|
||||||
let mut s = S;
|
let mut s = S;
|
||||||
let s_ref = &mut s;
|
let s_ref = &mut s;
|
||||||
|
let mut s2 = S;
|
||||||
|
let s_ref2 = &mut s2;
|
||||||
let closure = || {
|
let closure = || {
|
||||||
if let ref cb = s_ref {
|
if let ref cb = s_ref {
|
||||||
|
} else if let ref mut cb = s_ref2 {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
"#,
|
"#,
|
||||||
expect!["83..135;49..54;112..117 ByRef(Shared) s_ref &'? &'? mut S"],
|
expect![[r#"
|
||||||
|
129..225;49..54;149..155 ByRef(Shared) s_ref &'? &'? mut S
|
||||||
|
129..225;93..99;188..198 ByRef(Mut { kind: Default }) s_ref2 &'? mut &'? mut S"#]],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn let_binding_is_a_value_capture_in_binding() {
|
||||||
|
check_closure_captures(
|
||||||
|
r#"
|
||||||
|
//- minicore:copy, option
|
||||||
|
struct Box(i32);
|
||||||
|
fn main() {
|
||||||
|
let b = Some(Box(0));
|
||||||
|
let closure = || {
|
||||||
|
if let Some(b) = b {
|
||||||
|
let _move = b;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
expect!["73..149;37..38;103..104 ByValue b Option<Box>"],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -561,7 +561,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 + 'static), got &'? impl Foo + ?Sized
|
//^ expected &'? (dyn Foo + '?), got &'? impl Foo + ?Sized
|
||||||
}
|
}
|
||||||
"#,
|
"#,
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -67,11 +67,11 @@ trait B: A {}
|
||||||
|
|
||||||
fn test<'a>(
|
fn test<'a>(
|
||||||
_: &(dyn A<Assoc = ()> + Send),
|
_: &(dyn A<Assoc = ()> + Send),
|
||||||
//^ &(dyn A<Assoc = ()> + Send + 'static)
|
//^ &(dyn A<Assoc = ()> + Send)
|
||||||
_: &'a (dyn Send + A<Assoc = ()>),
|
_: &'a (dyn Send + A<Assoc = ()>),
|
||||||
//^ &'a (dyn A<Assoc = ()> + Send + 'static)
|
//^ &'a (dyn A<Assoc = ()> + Send)
|
||||||
_: &dyn B<Assoc = ()>,
|
_: &dyn B<Assoc = ()>,
|
||||||
//^ &(dyn B<Assoc = ()> + 'static)
|
//^ &(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<'?> + 'static)
|
// ^^^ &dyn Foo<'?>
|
||||||
"#,
|
"#,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
use base_db::SourceDatabase;
|
use base_db::SourceDatabase;
|
||||||
use expect_test::Expect;
|
use expect_test::Expect;
|
||||||
use hir_def::{DefWithBodyId, ModuleDefId};
|
use hir_def::{DefWithBodyId, ModuleDefId};
|
||||||
|
use salsa::EventKind;
|
||||||
use test_fixture::WithFixture;
|
use test_fixture::WithFixture;
|
||||||
|
|
||||||
use crate::{db::HirDatabase, test_db::TestDB};
|
use crate::{db::HirDatabase, test_db::TestDB};
|
||||||
|
|
@ -567,11 +568,11 @@ fn main() {
|
||||||
"ast_id_map_shim",
|
"ast_id_map_shim",
|
||||||
"parse_shim",
|
"parse_shim",
|
||||||
"real_span_map_shim",
|
"real_span_map_shim",
|
||||||
"trait_items_with_diagnostics_shim",
|
"TraitItems::query_with_diagnostics_",
|
||||||
"body_shim",
|
"body_shim",
|
||||||
"body_with_source_map_shim",
|
"body_with_source_map_shim",
|
||||||
"attrs_shim",
|
"attrs_shim",
|
||||||
"of_",
|
"ImplItems::of_",
|
||||||
"infer_shim",
|
"infer_shim",
|
||||||
"trait_signature_shim",
|
"trait_signature_shim",
|
||||||
"trait_signature_with_source_map_shim",
|
"trait_signature_with_source_map_shim",
|
||||||
|
|
@ -596,8 +597,8 @@ fn main() {
|
||||||
"struct_signature_with_source_map_shim",
|
"struct_signature_with_source_map_shim",
|
||||||
"generic_predicates_shim",
|
"generic_predicates_shim",
|
||||||
"value_ty_shim",
|
"value_ty_shim",
|
||||||
"variant_fields_shim",
|
"VariantFields::firewall_",
|
||||||
"variant_fields_with_source_map_shim",
|
"VariantFields::query_",
|
||||||
"lang_item",
|
"lang_item",
|
||||||
"inherent_impls_in_crate_shim",
|
"inherent_impls_in_crate_shim",
|
||||||
"impl_signature_shim",
|
"impl_signature_shim",
|
||||||
|
|
@ -674,11 +675,11 @@ fn main() {
|
||||||
"file_item_tree_query",
|
"file_item_tree_query",
|
||||||
"real_span_map_shim",
|
"real_span_map_shim",
|
||||||
"crate_local_def_map",
|
"crate_local_def_map",
|
||||||
"trait_items_with_diagnostics_shim",
|
"TraitItems::query_with_diagnostics_",
|
||||||
"body_with_source_map_shim",
|
"body_with_source_map_shim",
|
||||||
"attrs_shim",
|
"attrs_shim",
|
||||||
"body_shim",
|
"body_shim",
|
||||||
"of_",
|
"ImplItems::of_",
|
||||||
"infer_shim",
|
"infer_shim",
|
||||||
"attrs_shim",
|
"attrs_shim",
|
||||||
"trait_signature_with_source_map_shim",
|
"trait_signature_with_source_map_shim",
|
||||||
|
|
@ -695,11 +696,9 @@ fn main() {
|
||||||
"return_type_impl_traits_shim",
|
"return_type_impl_traits_shim",
|
||||||
"infer_shim",
|
"infer_shim",
|
||||||
"function_signature_with_source_map_shim",
|
"function_signature_with_source_map_shim",
|
||||||
"trait_environment_shim",
|
|
||||||
"expr_scopes_shim",
|
"expr_scopes_shim",
|
||||||
"struct_signature_with_source_map_shim",
|
"struct_signature_with_source_map_shim",
|
||||||
"generic_predicates_shim",
|
"VariantFields::query_",
|
||||||
"variant_fields_with_source_map_shim",
|
|
||||||
"inherent_impls_in_crate_shim",
|
"inherent_impls_in_crate_shim",
|
||||||
"impl_signature_with_source_map_shim",
|
"impl_signature_with_source_map_shim",
|
||||||
"impl_signature_shim",
|
"impl_signature_shim",
|
||||||
|
|
@ -709,7 +708,6 @@ fn main() {
|
||||||
"impl_trait_with_diagnostics_shim",
|
"impl_trait_with_diagnostics_shim",
|
||||||
"impl_self_ty_with_diagnostics_shim",
|
"impl_self_ty_with_diagnostics_shim",
|
||||||
"generic_predicates_shim",
|
"generic_predicates_shim",
|
||||||
"generic_predicates_shim",
|
|
||||||
]
|
]
|
||||||
"#]],
|
"#]],
|
||||||
);
|
);
|
||||||
|
|
@ -721,10 +719,23 @@ fn execute_assert_events(
|
||||||
required: &[(&str, usize)],
|
required: &[(&str, usize)],
|
||||||
expect: Expect,
|
expect: Expect,
|
||||||
) {
|
) {
|
||||||
let events = db.log_executed(f);
|
let (executed, events) = db.log_executed(f);
|
||||||
for (event, count) in required {
|
salsa::attach(db, || {
|
||||||
let n = events.iter().filter(|it| it.contains(event)).count();
|
for (event, count) in required {
|
||||||
assert_eq!(n, *count, "Expected {event} to be executed {count} times, but only got {n}");
|
let n = executed.iter().filter(|it| it.contains(event)).count();
|
||||||
}
|
assert_eq!(
|
||||||
expect.assert_debug_eq(&events);
|
n,
|
||||||
|
*count,
|
||||||
|
"Expected {event} to be executed {count} times, but only got {n}:\n \
|
||||||
|
Executed: {executed:#?}\n \
|
||||||
|
Event log: {events:#?}",
|
||||||
|
events = events
|
||||||
|
.iter()
|
||||||
|
.filter(|event| !matches!(event.kind, EventKind::WillCheckCancellation))
|
||||||
|
.map(|event| { format!("{:?}", event.kind) })
|
||||||
|
.collect::<Vec<_>>(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect.assert_debug_eq(&executed);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1153,9 +1153,9 @@ fn dyn_trait_super_trait_not_in_scope() {
|
||||||
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 + 'static)
|
176..177 'd': &'? (dyn Trait + '?)
|
||||||
191..207 '{ ...o(); }': ()
|
191..207 '{ ...o(); }': ()
|
||||||
197..198 'd': &'? (dyn Trait + 'static)
|
197..198 'd': &'? (dyn Trait + '?)
|
||||||
197..204 'd.foo()': u32
|
197..204 'd.foo()': u32
|
||||||
"#]],
|
"#]],
|
||||||
);
|
);
|
||||||
|
|
@ -2019,10 +2019,10 @@ impl dyn Error + Send {
|
||||||
/// Attempts to downcast the box to a concrete type.
|
/// Attempts to downcast the box to a concrete type.
|
||||||
pub fn downcast<T: Error + 'static>(self: Box<Self>) -> Result<Box<T>, Box<dyn Error + Send>> {
|
pub fn downcast<T: Error + 'static>(self: Box<Self>) -> Result<Box<T>, Box<dyn Error + Send>> {
|
||||||
let err: Box<dyn Error> = self;
|
let err: Box<dyn Error> = self;
|
||||||
// ^^^^ expected Box<dyn Error + 'static>, got Box<dyn Error + Send + 'static>
|
// ^^^^ expected Box<dyn Error + '?>, got Box<dyn Error + Send + '?>
|
||||||
// FIXME, type mismatch should not occur
|
// FIXME, type mismatch should not occur
|
||||||
<dyn Error>::downcast(err).map_err(|_| loop {})
|
<dyn Error>::downcast(err).map_err(|_| loop {})
|
||||||
//^^^^^^^^^^^^^^^^^^^^^ type: fn downcast<{unknown}>(Box<dyn Error + 'static>) -> Result<Box<{unknown}>, Box<dyn Error + 'static>>
|
//^^^^^^^^^^^^^^^^^^^^^ type: fn downcast<{unknown}>(Box<dyn Error + '?>) -> Result<Box<{unknown}>, Box<dyn Error + '?>>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"#,
|
"#,
|
||||||
|
|
|
||||||
|
|
@ -785,3 +785,31 @@ fn make_up_a_pointer<T>() -> *const T {
|
||||||
"#]],
|
"#]],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn diverging_destructuring_assignment() {
|
||||||
|
check_infer_with_mismatches(
|
||||||
|
r#"
|
||||||
|
fn foo() {
|
||||||
|
let n = match 42 {
|
||||||
|
0 => _ = loop {},
|
||||||
|
_ => 0,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
expect![[r#"
|
||||||
|
9..84 '{ ... }; }': ()
|
||||||
|
19..20 'n': i32
|
||||||
|
23..81 'match ... }': i32
|
||||||
|
29..31 '42': i32
|
||||||
|
42..43 '0': i32
|
||||||
|
42..43 '0': i32
|
||||||
|
47..48 '_': !
|
||||||
|
47..58 '_ = loop {}': i32
|
||||||
|
51..58 'loop {}': !
|
||||||
|
56..58 '{}': ()
|
||||||
|
68..69 '_': i32
|
||||||
|
73..74 '0': i32
|
||||||
|
"#]],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -629,7 +629,7 @@ fn issue_4053_diesel_where_clauses() {
|
||||||
488..522 '{ ... }': ()
|
488..522 '{ ... }': ()
|
||||||
498..502 'self': SelectStatement<F, S, D, W, O, LOf, {unknown}, {unknown}>
|
498..502 'self': SelectStatement<F, S, D, W, O, LOf, {unknown}, {unknown}>
|
||||||
498..508 'self.order': O
|
498..508 'self.order': O
|
||||||
498..515 'self.o...into()': dyn QueryFragment<DB> + 'static
|
498..515 'self.o...into()': dyn QueryFragment<DB> + '?
|
||||||
"#]],
|
"#]],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -773,7 +773,7 @@ fn issue_4800() {
|
||||||
"#,
|
"#,
|
||||||
expect![[r#"
|
expect![[r#"
|
||||||
379..383 'self': &'? mut PeerSet<D>
|
379..383 'self': &'? mut PeerSet<D>
|
||||||
401..424 '{ ... }': dyn Future<Output = ()> + 'static
|
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
|
||||||
|
|
|
||||||
|
|
@ -2741,11 +2741,11 @@ impl B for Astruct {}
|
||||||
715..744 '#[rust...1i32])': Box<[i32; 1], Global>
|
715..744 '#[rust...1i32])': Box<[i32; 1], Global>
|
||||||
737..743 '[1i32]': [i32; 1]
|
737..743 '[1i32]': [i32; 1]
|
||||||
738..742 '1i32': i32
|
738..742 '1i32': i32
|
||||||
755..756 'v': Vec<Box<dyn B + 'static, Global>, Global>
|
755..756 'v': Vec<Box<dyn B + '?, Global>, Global>
|
||||||
776..793 '<[_]> ...to_vec': fn into_vec<Box<dyn B + 'static, Global>, Global>(Box<[Box<dyn B + 'static, Global>], Global>) -> Vec<Box<dyn B + 'static, Global>, Global>
|
776..793 '<[_]> ...to_vec': fn into_vec<Box<dyn B + '?, Global>, Global>(Box<[Box<dyn B + '?, Global>], Global>) -> Vec<Box<dyn B + '?, Global>, Global>
|
||||||
776..850 '<[_]> ...ct)]))': Vec<Box<dyn B + 'static, Global>, Global>
|
776..850 '<[_]> ...ct)]))': Vec<Box<dyn B + '?, Global>, Global>
|
||||||
794..849 '#[rust...uct)])': Box<[Box<dyn B + 'static, Global>; 1], Global>
|
794..849 '#[rust...uct)])': Box<[Box<dyn B + '?, Global>; 1], Global>
|
||||||
816..848 '[#[rus...ruct)]': [Box<dyn B + 'static, Global>; 1]
|
816..848 '[#[rus...ruct)]': [Box<dyn B + '?, Global>; 1]
|
||||||
817..847 '#[rust...truct)': Box<Astruct, Global>
|
817..847 '#[rust...truct)': Box<Astruct, Global>
|
||||||
839..846 'Astruct': Astruct
|
839..846 'Astruct': Astruct
|
||||||
"#]],
|
"#]],
|
||||||
|
|
@ -3751,7 +3751,7 @@ fn foo() {
|
||||||
}
|
}
|
||||||
let v: bool = true;
|
let v: bool = true;
|
||||||
m!();
|
m!();
|
||||||
// ^^^^ i32
|
// ^^ i32
|
||||||
}
|
}
|
||||||
"#,
|
"#,
|
||||||
);
|
);
|
||||||
|
|
@ -3765,39 +3765,39 @@ fn foo() {
|
||||||
let v: bool;
|
let v: bool;
|
||||||
macro_rules! m { () => { v } }
|
macro_rules! m { () => { v } }
|
||||||
m!();
|
m!();
|
||||||
// ^^^^ bool
|
// ^^ bool
|
||||||
|
|
||||||
let v: char;
|
let v: char;
|
||||||
macro_rules! m { () => { v } }
|
macro_rules! m { () => { v } }
|
||||||
m!();
|
m!();
|
||||||
// ^^^^ char
|
// ^^ char
|
||||||
|
|
||||||
{
|
{
|
||||||
let v: u8;
|
let v: u8;
|
||||||
macro_rules! m { () => { v } }
|
macro_rules! m { () => { v } }
|
||||||
m!();
|
m!();
|
||||||
// ^^^^ u8
|
// ^^ u8
|
||||||
|
|
||||||
let v: i8;
|
let v: i8;
|
||||||
macro_rules! m { () => { v } }
|
macro_rules! m { () => { v } }
|
||||||
m!();
|
m!();
|
||||||
// ^^^^ i8
|
// ^^ i8
|
||||||
|
|
||||||
let v: i16;
|
let v: i16;
|
||||||
macro_rules! m { () => { v } }
|
macro_rules! m { () => { v } }
|
||||||
m!();
|
m!();
|
||||||
// ^^^^ i16
|
// ^^ i16
|
||||||
|
|
||||||
{
|
{
|
||||||
let v: u32;
|
let v: u32;
|
||||||
macro_rules! m { () => { v } }
|
macro_rules! m { () => { v } }
|
||||||
m!();
|
m!();
|
||||||
// ^^^^ u32
|
// ^^ u32
|
||||||
|
|
||||||
let v: u64;
|
let v: u64;
|
||||||
macro_rules! m { () => { v } }
|
macro_rules! m { () => { v } }
|
||||||
m!();
|
m!();
|
||||||
// ^^^^ u64
|
// ^^ u64
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1475,26 +1475,26 @@ fn test(x: Box<dyn Trait<u64>>, y: &dyn Trait<u64>) {
|
||||||
expect![[r#"
|
expect![[r#"
|
||||||
29..33 'self': &'? Self
|
29..33 'self': &'? Self
|
||||||
54..58 'self': &'? Self
|
54..58 'self': &'? Self
|
||||||
198..200 '{}': Box<dyn Trait<u64> + 'static>
|
198..200 '{}': Box<dyn Trait<u64> + '?>
|
||||||
210..211 'x': Box<dyn Trait<u64> + 'static>
|
210..211 'x': Box<dyn Trait<u64> + '?>
|
||||||
234..235 'y': &'? (dyn Trait<u64> + 'static)
|
234..235 'y': &'? (dyn Trait<u64> + '?)
|
||||||
254..371 '{ ...2(); }': ()
|
254..371 '{ ...2(); }': ()
|
||||||
260..261 'x': Box<dyn Trait<u64> + 'static>
|
260..261 'x': Box<dyn Trait<u64> + '?>
|
||||||
267..268 'y': &'? (dyn Trait<u64> + 'static)
|
267..268 'y': &'? (dyn Trait<u64> + '?)
|
||||||
278..279 'z': Box<dyn Trait<u64> + 'static>
|
278..279 'z': Box<dyn Trait<u64> + '?>
|
||||||
282..285 'bar': fn bar() -> Box<dyn Trait<u64> + 'static>
|
282..285 'bar': fn bar() -> Box<dyn Trait<u64> + '?>
|
||||||
282..287 'bar()': Box<dyn Trait<u64> + 'static>
|
282..287 'bar()': Box<dyn Trait<u64> + '?>
|
||||||
293..294 'x': Box<dyn Trait<u64> + 'static>
|
293..294 'x': Box<dyn Trait<u64> + '?>
|
||||||
293..300 'x.foo()': u64
|
293..300 'x.foo()': u64
|
||||||
306..307 'y': &'? (dyn Trait<u64> + 'static)
|
306..307 'y': &'? (dyn Trait<u64> + '?)
|
||||||
306..313 'y.foo()': u64
|
306..313 'y.foo()': u64
|
||||||
319..320 'z': Box<dyn Trait<u64> + 'static>
|
319..320 'z': Box<dyn Trait<u64> + '?>
|
||||||
319..326 'z.foo()': u64
|
319..326 'z.foo()': u64
|
||||||
332..333 'x': Box<dyn Trait<u64> + 'static>
|
332..333 'x': Box<dyn Trait<u64> + '?>
|
||||||
332..340 'x.foo2()': i64
|
332..340 'x.foo2()': i64
|
||||||
346..347 'y': &'? (dyn Trait<u64> + 'static)
|
346..347 'y': &'? (dyn Trait<u64> + '?)
|
||||||
346..354 'y.foo2()': i64
|
346..354 'y.foo2()': i64
|
||||||
360..361 'z': Box<dyn Trait<u64> + 'static>
|
360..361 'z': Box<dyn Trait<u64> + '?>
|
||||||
360..368 'z.foo2()': i64
|
360..368 'z.foo2()': i64
|
||||||
"#]],
|
"#]],
|
||||||
);
|
);
|
||||||
|
|
@ -1523,14 +1523,14 @@ fn test(s: S<u32, i32>) {
|
||||||
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> + 'static)
|
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> + 'static)
|
273..280 's.bar()': &'? (dyn Trait<u32, i32> + '?)
|
||||||
273..286 's.bar().baz()': (u32, i32)
|
273..286 's.bar().baz()': (u32, i32)
|
||||||
"#]],
|
"#]],
|
||||||
);
|
);
|
||||||
|
|
@ -1556,20 +1556,20 @@ fn test(x: Trait, y: &Trait) -> u64 {
|
||||||
}"#,
|
}"#,
|
||||||
expect![[r#"
|
expect![[r#"
|
||||||
26..30 'self': &'? Self
|
26..30 'self': &'? Self
|
||||||
60..62 '{}': dyn Trait + 'static
|
60..62 '{}': dyn Trait + '?
|
||||||
72..73 'x': dyn Trait + 'static
|
72..73 'x': dyn Trait + '?
|
||||||
82..83 'y': &'? (dyn Trait + 'static)
|
82..83 'y': &'? (dyn Trait + '?)
|
||||||
100..175 '{ ...o(); }': u64
|
100..175 '{ ...o(); }': u64
|
||||||
106..107 'x': dyn Trait + 'static
|
106..107 'x': dyn Trait + '?
|
||||||
113..114 'y': &'? (dyn Trait + 'static)
|
113..114 'y': &'? (dyn Trait + '?)
|
||||||
124..125 'z': dyn Trait + 'static
|
124..125 'z': dyn Trait + '?
|
||||||
128..131 'bar': fn bar() -> dyn Trait + 'static
|
128..131 'bar': fn bar() -> dyn Trait + '?
|
||||||
128..133 'bar()': dyn Trait + 'static
|
128..133 'bar()': dyn Trait + '?
|
||||||
139..140 'x': dyn Trait + 'static
|
139..140 'x': dyn Trait + '?
|
||||||
139..146 'x.foo()': u64
|
139..146 'x.foo()': u64
|
||||||
152..153 'y': &'? (dyn Trait + 'static)
|
152..153 'y': &'? (dyn Trait + '?)
|
||||||
152..159 'y.foo()': u64
|
152..159 'y.foo()': u64
|
||||||
165..166 'z': dyn Trait + 'static
|
165..166 'z': dyn Trait + '?
|
||||||
165..172 'z.foo()': u64
|
165..172 'z.foo()': u64
|
||||||
"#]],
|
"#]],
|
||||||
);
|
);
|
||||||
|
|
@ -1589,10 +1589,10 @@ fn main() {
|
||||||
expect![[r#"
|
expect![[r#"
|
||||||
31..35 'self': &'? S
|
31..35 'self': &'? S
|
||||||
37..39 '{}': ()
|
37..39 '{}': ()
|
||||||
47..48 '_': &'? (dyn Fn(S) + 'static)
|
47..48 '_': &'? (dyn Fn(S) + '?)
|
||||||
58..60 '{}': ()
|
58..60 '{}': ()
|
||||||
71..105 '{ ...()); }': ()
|
71..105 '{ ...()); }': ()
|
||||||
77..78 'f': fn f(&'? (dyn Fn(S) + 'static))
|
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)
|
||||||
|
|
@ -2927,13 +2927,13 @@ fn test(x: &dyn Foo) {
|
||||||
foo(x);
|
foo(x);
|
||||||
}"#,
|
}"#,
|
||||||
expect![[r#"
|
expect![[r#"
|
||||||
21..22 'x': &'? (dyn Foo + 'static)
|
21..22 'x': &'? (dyn Foo + '?)
|
||||||
34..36 '{}': ()
|
34..36 '{}': ()
|
||||||
46..47 'x': &'? (dyn Foo + 'static)
|
46..47 'x': &'? (dyn Foo + '?)
|
||||||
59..74 '{ foo(x); }': ()
|
59..74 '{ foo(x); }': ()
|
||||||
65..68 'foo': fn foo(&'? (dyn Foo + 'static))
|
65..68 'foo': fn foo(&'? (dyn Foo + '?))
|
||||||
65..71 'foo(x)': ()
|
65..71 'foo(x)': ()
|
||||||
69..70 'x': &'? (dyn Foo + 'static)
|
69..70 'x': &'? (dyn Foo + '?)
|
||||||
"#]],
|
"#]],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -3210,13 +3210,13 @@ fn foo() {
|
||||||
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>) + 'static>
|
246..247 'f': Box<dyn FnOnce(&'? Option<i32>) + '?>
|
||||||
281..310 'Box { ... {}) }': Box<dyn FnOnce(&'? Option<i32>) + 'static>
|
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>) + 'static>
|
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>
|
||||||
|
|
@ -4252,9 +4252,9 @@ 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> = &'a i32> + 'static)
|
127..128 'v': &'? (dyn Trait<Assoc<i32> = &'a i32> + '?)
|
||||||
164..195 '{ ...f(); }': ()
|
164..195 '{ ...f(); }': ()
|
||||||
170..171 'v': &'? (dyn Trait<Assoc<i32> = &'a i32> + 'static)
|
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
|
||||||
"#]],
|
"#]],
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
//! Helper functions for working with def, which don't need to be a separate
|
//! Helper functions for working with def, which don't need to be a separate
|
||||||
//! query, but can't be computed directly from `*Data` (ie, which need a `db`).
|
//! query, but can't be computed directly from `*Data` (ie, which need a `db`).
|
||||||
|
|
||||||
use std::iter;
|
use std::{cell::LazyCell, iter};
|
||||||
|
|
||||||
use base_db::Crate;
|
use base_db::Crate;
|
||||||
use chalk_ir::{
|
use chalk_ir::{
|
||||||
|
|
@ -161,11 +161,12 @@ impl Iterator for ClauseElaborator<'_> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn direct_super_traits_cb(db: &dyn DefDatabase, trait_: TraitId, cb: impl FnMut(TraitId)) {
|
fn direct_super_traits_cb(db: &dyn DefDatabase, trait_: TraitId, cb: impl FnMut(TraitId)) {
|
||||||
let resolver = trait_.resolver(db);
|
let resolver = LazyCell::new(|| trait_.resolver(db));
|
||||||
let (generic_params, store) = db.generic_params_and_store(trait_.into());
|
let (generic_params, store) = db.generic_params_and_store(trait_.into());
|
||||||
let trait_self = generic_params.trait_self_param();
|
let trait_self = generic_params.trait_self_param();
|
||||||
generic_params
|
generic_params
|
||||||
.where_predicates()
|
.where_predicates()
|
||||||
|
.iter()
|
||||||
.filter_map(|pred| match pred {
|
.filter_map(|pred| match pred {
|
||||||
WherePredicate::ForLifetime { target, bound, .. }
|
WherePredicate::ForLifetime { target, bound, .. }
|
||||||
| WherePredicate::TypeBound { target, bound } => {
|
| WherePredicate::TypeBound { target, bound } => {
|
||||||
|
|
@ -218,7 +219,7 @@ pub(super) fn associated_type_by_name_including_super_traits(
|
||||||
name: &Name,
|
name: &Name,
|
||||||
) -> Option<(TraitRef, TypeAliasId)> {
|
) -> Option<(TraitRef, TypeAliasId)> {
|
||||||
all_super_trait_refs(db, trait_ref, |t| {
|
all_super_trait_refs(db, trait_ref, |t| {
|
||||||
let assoc_type = db.trait_items(t.hir_trait_id()).associated_type_by_name(name)?;
|
let assoc_type = t.hir_trait_id().trait_items(db).associated_type_by_name(name)?;
|
||||||
Some((t, assoc_type))
|
Some((t, assoc_type))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -54,14 +54,14 @@ pub(crate) fn variances_of(db: &dyn HirDatabase, def: GenericDefId) -> Option<Ar
|
||||||
variances.is_empty().not().then(|| Arc::from_iter(variances))
|
variances.is_empty().not().then(|| Arc::from_iter(variances))
|
||||||
}
|
}
|
||||||
|
|
||||||
// pub(crate) fn variances_of_cycle_fn(
|
pub(crate) fn variances_of_cycle_fn(
|
||||||
// _db: &dyn HirDatabase,
|
_db: &dyn HirDatabase,
|
||||||
// _result: &Option<Arc<[Variance]>>,
|
_result: &Option<Arc<[Variance]>>,
|
||||||
// _count: u32,
|
_count: u32,
|
||||||
// _def: GenericDefId,
|
_def: GenericDefId,
|
||||||
// ) -> salsa::CycleRecoveryAction<Option<Arc<[Variance]>>> {
|
) -> salsa::CycleRecoveryAction<Option<Arc<[Variance]>>> {
|
||||||
// salsa::CycleRecoveryAction::Iterate
|
salsa::CycleRecoveryAction::Iterate
|
||||||
// }
|
}
|
||||||
|
|
||||||
pub(crate) fn variances_of_cycle_initial(
|
pub(crate) fn variances_of_cycle_initial(
|
||||||
db: &dyn HirDatabase,
|
db: &dyn HirDatabase,
|
||||||
|
|
@ -965,7 +965,7 @@ struct S3<T>(S<T, T>);
|
||||||
struct FixedPoint<T, U, V>(&'static FixedPoint<(), T, U>, V);
|
struct FixedPoint<T, U, V>(&'static FixedPoint<(), T, U>, V);
|
||||||
"#,
|
"#,
|
||||||
expect![[r#"
|
expect![[r#"
|
||||||
FixedPoint[T: bivariant, U: bivariant, V: bivariant]
|
FixedPoint[T: covariant, U: covariant, V: covariant]
|
||||||
"#]],
|
"#]],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ license.workspace = true
|
||||||
rust-version.workspace = true
|
rust-version.workspace = true
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
|
doctest = false
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
rustc-hash.workspace = true
|
rustc-hash.workspace = true
|
||||||
|
|
|
||||||
|
|
@ -207,7 +207,7 @@ fn resolve_assoc_or_field(
|
||||||
// Doc paths in this context may only resolve to an item of this trait
|
// Doc paths in this context may only resolve to an item of this trait
|
||||||
// (i.e. no items of its supertraits), so we need to handle them here
|
// (i.e. no items of its supertraits), so we need to handle them here
|
||||||
// independently of others.
|
// independently of others.
|
||||||
return db.trait_items(id).items.iter().find(|it| it.0 == name).map(|(_, assoc_id)| {
|
return id.trait_items(db).items.iter().find(|it| it.0 == name).map(|(_, assoc_id)| {
|
||||||
let def = match *assoc_id {
|
let def = match *assoc_id {
|
||||||
AssocItemId::FunctionId(it) => ModuleDef::Function(it.into()),
|
AssocItemId::FunctionId(it) => ModuleDef::Function(it.into()),
|
||||||
AssocItemId::ConstId(it) => ModuleDef::Const(it.into()),
|
AssocItemId::ConstId(it) => ModuleDef::Const(it.into()),
|
||||||
|
|
|
||||||
|
|
@ -36,16 +36,16 @@ pub use hir_ty::{
|
||||||
};
|
};
|
||||||
|
|
||||||
macro_rules! diagnostics {
|
macro_rules! diagnostics {
|
||||||
($($diag:ident $(<$lt:lifetime>)?,)*) => {
|
($AnyDiagnostic:ident <$db:lifetime> -> $($diag:ident $(<$lt:lifetime>)?,)*) => {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum AnyDiagnostic<'db> {$(
|
pub enum $AnyDiagnostic<$db> {$(
|
||||||
$diag(Box<$diag $(<$lt>)?>),
|
$diag(Box<$diag $(<$lt>)?>),
|
||||||
)*}
|
)*}
|
||||||
|
|
||||||
$(
|
$(
|
||||||
impl<'db> From<$diag $(<$lt>)?> for AnyDiagnostic<'db> {
|
impl<$db> From<$diag $(<$lt>)?> for $AnyDiagnostic<$db> {
|
||||||
fn from(d: $diag $(<$lt>)?) -> AnyDiagnostic<'db> {
|
fn from(d: $diag $(<$lt>)?) -> $AnyDiagnostic<$db> {
|
||||||
AnyDiagnostic::$diag(Box::new(d))
|
$AnyDiagnostic::$diag(Box::new(d))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)*
|
)*
|
||||||
|
|
@ -66,7 +66,7 @@ macro_rules! diagnostics {
|
||||||
// }, ...
|
// }, ...
|
||||||
// ]
|
// ]
|
||||||
|
|
||||||
diagnostics![
|
diagnostics![AnyDiagnostic<'db> ->
|
||||||
AwaitOutsideOfAsync,
|
AwaitOutsideOfAsync,
|
||||||
BreakOutsideOfLoop,
|
BreakOutsideOfLoop,
|
||||||
CastToUnsized<'db>,
|
CastToUnsized<'db>,
|
||||||
|
|
@ -490,7 +490,7 @@ impl<'db> AnyDiagnostic<'db> {
|
||||||
) -> Option<AnyDiagnostic<'db>> {
|
) -> Option<AnyDiagnostic<'db>> {
|
||||||
match diagnostic {
|
match diagnostic {
|
||||||
BodyValidationDiagnostic::RecordMissingFields { record, variant, missed_fields } => {
|
BodyValidationDiagnostic::RecordMissingFields { record, variant, missed_fields } => {
|
||||||
let variant_data = variant.variant_data(db);
|
let variant_data = variant.fields(db);
|
||||||
let missed_fields = missed_fields
|
let missed_fields = missed_fields
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|idx| variant_data.fields()[idx].name.clone())
|
.map(|idx| variant_data.fields()[idx].name.clone())
|
||||||
|
|
|
||||||
|
|
@ -404,7 +404,7 @@ impl HirDisplay for TupleField {
|
||||||
impl HirDisplay for Variant {
|
impl HirDisplay for Variant {
|
||||||
fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
|
fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
|
||||||
write!(f, "{}", self.name(f.db).display(f.db, f.edition()))?;
|
write!(f, "{}", self.name(f.db).display(f.db, f.edition()))?;
|
||||||
let data = f.db.variant_fields(self.id.into());
|
let data = self.id.fields(f.db);
|
||||||
match data.shape {
|
match data.shape {
|
||||||
FieldsShape::Unit => {}
|
FieldsShape::Unit => {}
|
||||||
FieldsShape::Tuple => {
|
FieldsShape::Tuple => {
|
||||||
|
|
@ -633,7 +633,7 @@ fn has_disaplayable_predicates(
|
||||||
params: &GenericParams,
|
params: &GenericParams,
|
||||||
store: &ExpressionStore,
|
store: &ExpressionStore,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
params.where_predicates().any(|pred| {
|
params.where_predicates().iter().any(|pred| {
|
||||||
!matches!(
|
!matches!(
|
||||||
pred,
|
pred,
|
||||||
WherePredicate::TypeBound { target, .. }
|
WherePredicate::TypeBound { target, .. }
|
||||||
|
|
@ -668,7 +668,7 @@ fn write_where_predicates(
|
||||||
_ => false,
|
_ => false,
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut iter = params.where_predicates().peekable();
|
let mut iter = params.where_predicates().iter().peekable();
|
||||||
while let Some(pred) = iter.next() {
|
while let Some(pred) = iter.next() {
|
||||||
if matches!(pred, TypeBound { target, .. } if is_unnamed_type_target(*target)) {
|
if matches!(pred, TypeBound { target, .. } if is_unnamed_type_target(*target)) {
|
||||||
continue;
|
continue;
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,7 @@ use hir_def::{
|
||||||
},
|
},
|
||||||
item_tree::ImportAlias,
|
item_tree::ImportAlias,
|
||||||
layout::{self, ReprOptions, TargetDataLayout},
|
layout::{self, ReprOptions, TargetDataLayout},
|
||||||
nameres::{self, diagnostics::DefDiagnostic},
|
nameres::{self, assoc::TraitItems, diagnostics::DefDiagnostic},
|
||||||
per_ns::PerNs,
|
per_ns::PerNs,
|
||||||
resolver::{HasResolver, Resolver},
|
resolver::{HasResolver, Resolver},
|
||||||
signatures::{ImplFlags, StaticFlags, TraitFlags, VariantFields},
|
signatures::{ImplFlags, StaticFlags, TraitFlags, VariantFields},
|
||||||
|
|
@ -649,7 +649,7 @@ impl Module {
|
||||||
acc.extend(def.diagnostics(db, style_lints))
|
acc.extend(def.diagnostics(db, style_lints))
|
||||||
}
|
}
|
||||||
ModuleDef::Trait(t) => {
|
ModuleDef::Trait(t) => {
|
||||||
for diag in db.trait_items_with_diagnostics(t.id).1.iter() {
|
for diag in TraitItems::query_with_diagnostics(db, t.id).1.iter() {
|
||||||
emit_def_diagnostic(db, acc, diag, edition);
|
emit_def_diagnostic(db, acc, diag, edition);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -668,25 +668,25 @@ impl Module {
|
||||||
Adt::Struct(s) => {
|
Adt::Struct(s) => {
|
||||||
let source_map = db.struct_signature_with_source_map(s.id).1;
|
let source_map = db.struct_signature_with_source_map(s.id).1;
|
||||||
expr_store_diagnostics(db, acc, &source_map);
|
expr_store_diagnostics(db, acc, &source_map);
|
||||||
let source_map = db.variant_fields_with_source_map(s.id.into()).1;
|
let source_map = &s.id.fields_with_source_map(db).1;
|
||||||
expr_store_diagnostics(db, acc, &source_map);
|
expr_store_diagnostics(db, acc, source_map);
|
||||||
push_ty_diagnostics(
|
push_ty_diagnostics(
|
||||||
db,
|
db,
|
||||||
acc,
|
acc,
|
||||||
db.field_types_with_diagnostics(s.id.into()).1,
|
db.field_types_with_diagnostics(s.id.into()).1,
|
||||||
&source_map,
|
source_map,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Adt::Union(u) => {
|
Adt::Union(u) => {
|
||||||
let source_map = db.union_signature_with_source_map(u.id).1;
|
let source_map = db.union_signature_with_source_map(u.id).1;
|
||||||
expr_store_diagnostics(db, acc, &source_map);
|
expr_store_diagnostics(db, acc, &source_map);
|
||||||
let source_map = db.variant_fields_with_source_map(u.id.into()).1;
|
let source_map = &u.id.fields_with_source_map(db).1;
|
||||||
expr_store_diagnostics(db, acc, &source_map);
|
expr_store_diagnostics(db, acc, source_map);
|
||||||
push_ty_diagnostics(
|
push_ty_diagnostics(
|
||||||
db,
|
db,
|
||||||
acc,
|
acc,
|
||||||
db.field_types_with_diagnostics(u.id.into()).1,
|
db.field_types_with_diagnostics(u.id.into()).1,
|
||||||
&source_map,
|
source_map,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Adt::Enum(e) => {
|
Adt::Enum(e) => {
|
||||||
|
|
@ -711,14 +711,14 @@ impl Module {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for &(v, _, _) in &variants.variants {
|
for &(v, _, _) in &variants.variants {
|
||||||
let source_map = db.variant_fields_with_source_map(v.into()).1;
|
let source_map = &v.fields_with_source_map(db).1;
|
||||||
push_ty_diagnostics(
|
push_ty_diagnostics(
|
||||||
db,
|
db,
|
||||||
acc,
|
acc,
|
||||||
db.field_types_with_diagnostics(v.into()).1,
|
db.field_types_with_diagnostics(v.into()).1,
|
||||||
&source_map,
|
source_map,
|
||||||
);
|
);
|
||||||
expr_store_diagnostics(db, acc, &source_map);
|
expr_store_diagnostics(db, acc, source_map);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -822,7 +822,7 @@ impl Module {
|
||||||
|
|
||||||
// Negative impls can't have items, don't emit missing items diagnostic for them
|
// Negative impls can't have items, don't emit missing items diagnostic for them
|
||||||
if let (false, Some(trait_)) = (impl_is_negative, trait_) {
|
if let (false, Some(trait_)) = (impl_is_negative, trait_) {
|
||||||
let items = &db.trait_items(trait_.into()).items;
|
let items = &trait_.id.trait_items(db).items;
|
||||||
let required_items = items.iter().filter(|&(_, assoc)| match *assoc {
|
let required_items = items.iter().filter(|&(_, assoc)| match *assoc {
|
||||||
AssocItemId::FunctionId(it) => !db.function_signature(it).has_body(),
|
AssocItemId::FunctionId(it) => !db.function_signature(it).has_body(),
|
||||||
AssocItemId::ConstId(id) => !db.const_signature(id).has_body(),
|
AssocItemId::ConstId(id) => !db.const_signature(id).has_body(),
|
||||||
|
|
@ -1260,7 +1260,9 @@ impl TupleField {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ty<'db>(&self, db: &'db dyn HirDatabase) -> Type<'db> {
|
pub fn ty<'db>(&self, db: &'db dyn HirDatabase) -> Type<'db> {
|
||||||
let ty = db.infer(self.owner).tuple_field_access_types[&self.tuple]
|
let ty = db
|
||||||
|
.infer(self.owner)
|
||||||
|
.tuple_field_access_type(self.tuple)
|
||||||
.as_slice(Interner)
|
.as_slice(Interner)
|
||||||
.get(self.index as usize)
|
.get(self.index as usize)
|
||||||
.and_then(|arg| arg.ty(Interner))
|
.and_then(|arg| arg.ty(Interner))
|
||||||
|
|
@ -1311,7 +1313,7 @@ impl AstNode for FieldSource {
|
||||||
|
|
||||||
impl Field {
|
impl Field {
|
||||||
pub fn name(&self, db: &dyn HirDatabase) -> Name {
|
pub fn name(&self, db: &dyn HirDatabase) -> Name {
|
||||||
db.variant_fields(self.parent.into()).fields()[self.id].name.clone()
|
VariantId::from(self.parent).fields(db).fields()[self.id].name.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn index(&self) -> usize {
|
pub fn index(&self) -> usize {
|
||||||
|
|
@ -1380,7 +1382,7 @@ impl Field {
|
||||||
|
|
||||||
impl HasVisibility for Field {
|
impl HasVisibility for Field {
|
||||||
fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
|
fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
|
||||||
let variant_data = db.variant_fields(self.parent.into());
|
let variant_data = VariantId::from(self.parent).fields(db);
|
||||||
let visibility = &variant_data.fields()[self.id].visibility;
|
let visibility = &variant_data.fields()[self.id].visibility;
|
||||||
let parent_id: hir_def::VariantId = self.parent.into();
|
let parent_id: hir_def::VariantId = self.parent.into();
|
||||||
// FIXME: RawVisibility::Public doesn't need to construct a resolver
|
// FIXME: RawVisibility::Public doesn't need to construct a resolver
|
||||||
|
|
@ -1403,7 +1405,8 @@ impl Struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fields(self, db: &dyn HirDatabase) -> Vec<Field> {
|
pub fn fields(self, db: &dyn HirDatabase) -> Vec<Field> {
|
||||||
db.variant_fields(self.id.into())
|
self.id
|
||||||
|
.fields(db)
|
||||||
.fields()
|
.fields()
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(id, _)| Field { parent: self.into(), id })
|
.map(|(id, _)| Field { parent: self.into(), id })
|
||||||
|
|
@ -1434,8 +1437,8 @@ impl Struct {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn variant_fields(self, db: &dyn HirDatabase) -> Arc<VariantFields> {
|
fn variant_fields(self, db: &dyn HirDatabase) -> &VariantFields {
|
||||||
db.variant_fields(self.id.into())
|
self.id.fields(db)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_unstable(self, db: &dyn HirDatabase) -> bool {
|
pub fn is_unstable(self, db: &dyn HirDatabase) -> bool {
|
||||||
|
|
@ -1478,7 +1481,7 @@ impl Union {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn kind(self, db: &dyn HirDatabase) -> StructKind {
|
pub fn kind(self, db: &dyn HirDatabase) -> StructKind {
|
||||||
match db.variant_fields(self.id.into()).shape {
|
match self.id.fields(db).shape {
|
||||||
hir_def::item_tree::FieldsShape::Record => StructKind::Record,
|
hir_def::item_tree::FieldsShape::Record => StructKind::Record,
|
||||||
hir_def::item_tree::FieldsShape::Tuple => StructKind::Tuple,
|
hir_def::item_tree::FieldsShape::Tuple => StructKind::Tuple,
|
||||||
hir_def::item_tree::FieldsShape::Unit => StructKind::Unit,
|
hir_def::item_tree::FieldsShape::Unit => StructKind::Unit,
|
||||||
|
|
@ -1486,7 +1489,8 @@ impl Union {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fields(self, db: &dyn HirDatabase) -> Vec<Field> {
|
pub fn fields(self, db: &dyn HirDatabase) -> Vec<Field> {
|
||||||
db.variant_fields(self.id.into())
|
self.id
|
||||||
|
.fields(db)
|
||||||
.fields()
|
.fields()
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(id, _)| Field { parent: self.into(), id })
|
.map(|(id, _)| Field { parent: self.into(), id })
|
||||||
|
|
@ -1626,7 +1630,8 @@ impl Variant {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fields(self, db: &dyn HirDatabase) -> Vec<Field> {
|
pub fn fields(self, db: &dyn HirDatabase) -> Vec<Field> {
|
||||||
db.variant_fields(self.id.into())
|
self.id
|
||||||
|
.fields(db)
|
||||||
.fields()
|
.fields()
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(id, _)| Field { parent: self.into(), id })
|
.map(|(id, _)| Field { parent: self.into(), id })
|
||||||
|
|
@ -1634,7 +1639,7 @@ impl Variant {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn kind(self, db: &dyn HirDatabase) -> StructKind {
|
pub fn kind(self, db: &dyn HirDatabase) -> StructKind {
|
||||||
match db.variant_fields(self.id.into()).shape {
|
match self.id.fields(db).shape {
|
||||||
hir_def::item_tree::FieldsShape::Record => StructKind::Record,
|
hir_def::item_tree::FieldsShape::Record => StructKind::Record,
|
||||||
hir_def::item_tree::FieldsShape::Tuple => StructKind::Tuple,
|
hir_def::item_tree::FieldsShape::Tuple => StructKind::Tuple,
|
||||||
hir_def::item_tree::FieldsShape::Unit => StructKind::Unit,
|
hir_def::item_tree::FieldsShape::Unit => StructKind::Unit,
|
||||||
|
|
@ -1727,10 +1732,10 @@ impl Adt {
|
||||||
pub fn ty_with_args<'db>(
|
pub fn ty_with_args<'db>(
|
||||||
self,
|
self,
|
||||||
db: &'db dyn HirDatabase,
|
db: &'db dyn HirDatabase,
|
||||||
args: impl Iterator<Item = Type<'db>>,
|
args: impl IntoIterator<Item = Type<'db>>,
|
||||||
) -> Type<'db> {
|
) -> Type<'db> {
|
||||||
let id = AdtId::from(self);
|
let id = AdtId::from(self);
|
||||||
let mut it = args.map(|t| t.ty);
|
let mut it = args.into_iter().map(|t| t.ty);
|
||||||
let ty = TyBuilder::def_ty(db, id.into(), None)
|
let ty = TyBuilder::def_ty(db, id.into(), None)
|
||||||
.fill(|x| {
|
.fill(|x| {
|
||||||
let r = it.next().unwrap_or_else(|| TyKind::Error.intern(Interner));
|
let r = it.next().unwrap_or_else(|| TyKind::Error.intern(Interner));
|
||||||
|
|
@ -1924,7 +1929,7 @@ impl DefWithBody {
|
||||||
expr_store_diagnostics(db, acc, &source_map);
|
expr_store_diagnostics(db, acc, &source_map);
|
||||||
|
|
||||||
let infer = db.infer(self.into());
|
let infer = db.infer(self.into());
|
||||||
for d in &infer.diagnostics {
|
for d in infer.diagnostics() {
|
||||||
acc.extend(AnyDiagnostic::inference_diagnostic(
|
acc.extend(AnyDiagnostic::inference_diagnostic(
|
||||||
db,
|
db,
|
||||||
self.into(),
|
self.into(),
|
||||||
|
|
@ -2883,7 +2888,7 @@ impl Trait {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn function(self, db: &dyn HirDatabase, name: impl PartialEq<Name>) -> Option<Function> {
|
pub fn function(self, db: &dyn HirDatabase, name: impl PartialEq<Name>) -> Option<Function> {
|
||||||
db.trait_items(self.id).items.iter().find(|(n, _)| name == *n).and_then(|&(_, it)| match it
|
self.id.trait_items(db).items.iter().find(|(n, _)| name == *n).and_then(|&(_, it)| match it
|
||||||
{
|
{
|
||||||
AssocItemId::FunctionId(id) => Some(Function { id }),
|
AssocItemId::FunctionId(id) => Some(Function { id }),
|
||||||
_ => None,
|
_ => None,
|
||||||
|
|
@ -2891,7 +2896,7 @@ impl Trait {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn items(self, db: &dyn HirDatabase) -> Vec<AssocItem> {
|
pub fn items(self, db: &dyn HirDatabase) -> Vec<AssocItem> {
|
||||||
db.trait_items(self.id).items.iter().map(|(_name, it)| (*it).into()).collect()
|
self.id.trait_items(db).items.iter().map(|(_name, it)| (*it).into()).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn items_with_supertraits(self, db: &dyn HirDatabase) -> Vec<AssocItem> {
|
pub fn items_with_supertraits(self, db: &dyn HirDatabase) -> Vec<AssocItem> {
|
||||||
|
|
@ -2939,7 +2944,7 @@ impl Trait {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn all_macro_calls(&self, db: &dyn HirDatabase) -> Box<[(AstId<ast::Item>, MacroCallId)]> {
|
fn all_macro_calls(&self, db: &dyn HirDatabase) -> Box<[(AstId<ast::Item>, MacroCallId)]> {
|
||||||
db.trait_items(self.id).macro_calls.to_vec().into_boxed_slice()
|
self.id.trait_items(db).macro_calls.to_vec().into_boxed_slice()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `#[rust_analyzer::completions(...)]` mode.
|
/// `#[rust_analyzer::completions(...)]` mode.
|
||||||
|
|
@ -3043,10 +3048,17 @@ pub struct BuiltinType {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BuiltinType {
|
impl BuiltinType {
|
||||||
|
// Constructors are added on demand, feel free to add more.
|
||||||
pub fn str() -> BuiltinType {
|
pub fn str() -> BuiltinType {
|
||||||
BuiltinType { inner: hir_def::builtin_type::BuiltinType::Str }
|
BuiltinType { inner: hir_def::builtin_type::BuiltinType::Str }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn i32() -> BuiltinType {
|
||||||
|
BuiltinType {
|
||||||
|
inner: hir_def::builtin_type::BuiltinType::Int(hir_ty::primitive::BuiltinInt::I32),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn ty<'db>(self, db: &'db dyn HirDatabase) -> Type<'db> {
|
pub fn ty<'db>(self, db: &'db dyn HirDatabase) -> Type<'db> {
|
||||||
let core = Crate::core(db).map(|core| core.id).unwrap_or_else(|| db.all_crates()[0]);
|
let core = Crate::core(db).map(|core| core.id).unwrap_or_else(|| db.all_crates()[0]);
|
||||||
Type::new_for_crate(core, TyBuilder::builtin(self.inner))
|
Type::new_for_crate(core, TyBuilder::builtin(self.inner))
|
||||||
|
|
@ -3667,7 +3679,7 @@ impl GenericDef {
|
||||||
|
|
||||||
let generics = db.generic_params(def);
|
let generics = db.generic_params(def);
|
||||||
|
|
||||||
if generics.is_empty() && generics.no_predicates() {
|
if generics.is_empty() && generics.has_no_predicates() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -5000,7 +5012,7 @@ impl<'db> Type<'db> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let output_assoc_type =
|
let output_assoc_type =
|
||||||
db.trait_items(trait_).associated_type_by_name(&Name::new_symbol_root(sym::Output))?;
|
trait_.trait_items(db).associated_type_by_name(&Name::new_symbol_root(sym::Output))?;
|
||||||
self.normalize_trait_assoc_type(db, &[], output_assoc_type.into())
|
self.normalize_trait_assoc_type(db, &[], output_assoc_type.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -5013,8 +5025,8 @@ impl<'db> Type<'db> {
|
||||||
/// This does **not** resolve `IntoIterator`, only `Iterator`.
|
/// This does **not** resolve `IntoIterator`, only `Iterator`.
|
||||||
pub fn iterator_item(self, db: &'db dyn HirDatabase) -> Option<Type<'db>> {
|
pub fn iterator_item(self, db: &'db dyn HirDatabase) -> Option<Type<'db>> {
|
||||||
let iterator_trait = LangItem::Iterator.resolve_trait(db, self.env.krate)?;
|
let iterator_trait = LangItem::Iterator.resolve_trait(db, self.env.krate)?;
|
||||||
let iterator_item = db
|
let iterator_item = iterator_trait
|
||||||
.trait_items(iterator_trait)
|
.trait_items(db)
|
||||||
.associated_type_by_name(&Name::new_symbol_root(sym::Item))?;
|
.associated_type_by_name(&Name::new_symbol_root(sym::Item))?;
|
||||||
self.normalize_trait_assoc_type(db, &[], iterator_item.into())
|
self.normalize_trait_assoc_type(db, &[], iterator_item.into())
|
||||||
}
|
}
|
||||||
|
|
@ -5044,8 +5056,8 @@ impl<'db> Type<'db> {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let into_iter_assoc_type = db
|
let into_iter_assoc_type = trait_
|
||||||
.trait_items(trait_)
|
.trait_items(db)
|
||||||
.associated_type_by_name(&Name::new_symbol_root(sym::IntoIter))?;
|
.associated_type_by_name(&Name::new_symbol_root(sym::IntoIter))?;
|
||||||
self.normalize_trait_assoc_type(db, &[], into_iter_assoc_type.into())
|
self.normalize_trait_assoc_type(db, &[], into_iter_assoc_type.into())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2199,6 +2199,10 @@ pub struct SemanticsScope<'db> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'db> SemanticsScope<'db> {
|
impl<'db> SemanticsScope<'db> {
|
||||||
|
pub fn file_id(&self) -> HirFileId {
|
||||||
|
self.file_id
|
||||||
|
}
|
||||||
|
|
||||||
pub fn module(&self) -> Module {
|
pub fn module(&self) -> Module {
|
||||||
Module { id: self.resolver.module() }
|
Module { id: self.resolver.module() }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ pub(crate) trait ChildBySource {
|
||||||
|
|
||||||
impl ChildBySource for TraitId {
|
impl ChildBySource for TraitId {
|
||||||
fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap, file_id: HirFileId) {
|
fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap, file_id: HirFileId) {
|
||||||
let data = db.trait_items(*self);
|
let data = self.trait_items(db);
|
||||||
|
|
||||||
data.macro_calls().filter(|(ast_id, _)| ast_id.file_id == file_id).for_each(
|
data.macro_calls().filter(|(ast_id, _)| ast_id.file_id == file_id).for_each(
|
||||||
|(ast_id, call_id)| {
|
|(ast_id, call_id)| {
|
||||||
|
|
@ -191,7 +191,7 @@ impl ChildBySource for VariantId {
|
||||||
Either::Right(source) => res[keys::RECORD_FIELD].insert(AstPtr::new(&source), id),
|
Either::Right(source) => res[keys::RECORD_FIELD].insert(AstPtr::new(&source), id),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let (_, sm) = db.variant_fields_with_source_map(*self);
|
let (_, sm) = self.fields_with_source_map(db);
|
||||||
sm.expansions().for_each(|(ast, &exp_id)| res[keys::MACRO_CALL].insert(ast.value, exp_id));
|
sm.expansions().for_each(|(ast, &exp_id)| res[keys::MACRO_CALL].insert(ast.value, exp_id));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -156,14 +156,14 @@ impl<'db> SourceAnalyzer<'db> {
|
||||||
InFile { file_id, .. }: InFile<&SyntaxNode>,
|
InFile { file_id, .. }: InFile<&SyntaxNode>,
|
||||||
_offset: Option<TextSize>,
|
_offset: Option<TextSize>,
|
||||||
) -> SourceAnalyzer<'db> {
|
) -> SourceAnalyzer<'db> {
|
||||||
let (fields, source_map) = db.variant_fields_with_source_map(def);
|
let (fields, source_map) = def.fields_with_source_map(db);
|
||||||
let resolver = def.resolver(db);
|
let resolver = def.resolver(db);
|
||||||
SourceAnalyzer {
|
SourceAnalyzer {
|
||||||
resolver,
|
resolver,
|
||||||
body_or_sig: Some(BodyOrSig::VariantFields {
|
body_or_sig: Some(BodyOrSig::VariantFields {
|
||||||
def,
|
def,
|
||||||
store: fields.store.clone(),
|
store: fields.store.clone(),
|
||||||
source_map,
|
source_map: source_map.clone(),
|
||||||
}),
|
}),
|
||||||
file_id,
|
file_id,
|
||||||
}
|
}
|
||||||
|
|
@ -254,7 +254,7 @@ impl<'db> SourceAnalyzer<'db> {
|
||||||
// expressions nor patterns).
|
// expressions nor patterns).
|
||||||
let expr_id = self.expr_id(expr.clone())?.as_expr()?;
|
let expr_id = self.expr_id(expr.clone())?.as_expr()?;
|
||||||
let infer = self.infer()?;
|
let infer = self.infer()?;
|
||||||
infer.expr_adjustments.get(&expr_id).map(|v| &**v)
|
infer.expr_adjustment(expr_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn type_of_type(
|
pub(crate) fn type_of_type(
|
||||||
|
|
@ -286,7 +286,7 @@ impl<'db> SourceAnalyzer<'db> {
|
||||||
let infer = self.infer()?;
|
let infer = self.infer()?;
|
||||||
let coerced = expr_id
|
let coerced = expr_id
|
||||||
.as_expr()
|
.as_expr()
|
||||||
.and_then(|expr_id| infer.expr_adjustments.get(&expr_id))
|
.and_then(|expr_id| infer.expr_adjustment(expr_id))
|
||||||
.and_then(|adjusts| adjusts.last().map(|adjust| adjust.target.clone()));
|
.and_then(|adjusts| adjusts.last().map(|adjust| adjust.target.clone()));
|
||||||
let ty = infer[expr_id].clone();
|
let ty = infer[expr_id].clone();
|
||||||
let mk_ty = |ty| Type::new_with_resolver(db, &self.resolver, ty);
|
let mk_ty = |ty| Type::new_with_resolver(db, &self.resolver, ty);
|
||||||
|
|
@ -302,12 +302,11 @@ impl<'db> SourceAnalyzer<'db> {
|
||||||
let infer = self.infer()?;
|
let infer = self.infer()?;
|
||||||
let coerced = match expr_or_pat_id {
|
let coerced = match expr_or_pat_id {
|
||||||
ExprOrPatId::ExprId(idx) => infer
|
ExprOrPatId::ExprId(idx) => infer
|
||||||
.expr_adjustments
|
.expr_adjustment(idx)
|
||||||
.get(&idx)
|
|
||||||
.and_then(|adjusts| adjusts.last().cloned())
|
.and_then(|adjusts| adjusts.last().cloned())
|
||||||
.map(|adjust| adjust.target),
|
.map(|adjust| adjust.target),
|
||||||
ExprOrPatId::PatId(idx) => {
|
ExprOrPatId::PatId(idx) => {
|
||||||
infer.pat_adjustments.get(&idx).and_then(|adjusts| adjusts.last().cloned())
|
infer.pat_adjustment(idx).and_then(|adjusts| adjusts.last().cloned())
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -345,7 +344,7 @@ impl<'db> SourceAnalyzer<'db> {
|
||||||
) -> Option<BindingMode> {
|
) -> Option<BindingMode> {
|
||||||
let id = self.pat_id(&pat.clone().into())?;
|
let id = self.pat_id(&pat.clone().into())?;
|
||||||
let infer = self.infer()?;
|
let infer = self.infer()?;
|
||||||
infer.binding_modes.get(id.as_pat()?).map(|bm| match bm {
|
infer.binding_mode(id.as_pat()?).map(|bm| match bm {
|
||||||
hir_ty::BindingMode::Move => BindingMode::Move,
|
hir_ty::BindingMode::Move => BindingMode::Move,
|
||||||
hir_ty::BindingMode::Ref(hir_ty::Mutability::Mut) => BindingMode::Ref(Mutability::Mut),
|
hir_ty::BindingMode::Ref(hir_ty::Mutability::Mut) => BindingMode::Ref(Mutability::Mut),
|
||||||
hir_ty::BindingMode::Ref(hir_ty::Mutability::Not) => {
|
hir_ty::BindingMode::Ref(hir_ty::Mutability::Not) => {
|
||||||
|
|
@ -362,8 +361,7 @@ impl<'db> SourceAnalyzer<'db> {
|
||||||
let infer = self.infer()?;
|
let infer = self.infer()?;
|
||||||
Some(
|
Some(
|
||||||
infer
|
infer
|
||||||
.pat_adjustments
|
.pat_adjustment(pat_id.as_pat()?)?
|
||||||
.get(&pat_id.as_pat()?)?
|
|
||||||
.iter()
|
.iter()
|
||||||
.map(|ty| Type::new_with_resolver(db, &self.resolver, ty.clone()))
|
.map(|ty| Type::new_with_resolver(db, &self.resolver, ty.clone()))
|
||||||
.collect(),
|
.collect(),
|
||||||
|
|
@ -713,7 +711,7 @@ impl<'db> SourceAnalyzer<'db> {
|
||||||
};
|
};
|
||||||
let (adt, subst) = self.infer()?.type_of_expr_or_pat(expr_id)?.as_adt()?;
|
let (adt, subst) = self.infer()?.type_of_expr_or_pat(expr_id)?.as_adt()?;
|
||||||
let variant = self.infer()?.variant_resolution_for_expr_or_pat(expr_id)?;
|
let variant = self.infer()?.variant_resolution_for_expr_or_pat(expr_id)?;
|
||||||
let variant_data = variant.variant_data(db);
|
let variant_data = variant.fields(db);
|
||||||
let field = FieldId { parent: variant, local_id: variant_data.field(&local_name)? };
|
let field = FieldId { parent: variant, local_id: variant_data.field(&local_name)? };
|
||||||
let field_ty =
|
let field_ty =
|
||||||
db.field_types(variant).get(field.local_id)?.clone().substitute(Interner, subst);
|
db.field_types(variant).get(field.local_id)?.clone().substitute(Interner, subst);
|
||||||
|
|
@ -734,9 +732,9 @@ impl<'db> SourceAnalyzer<'db> {
|
||||||
let record_pat = ast::RecordPat::cast(field.syntax().parent().and_then(|p| p.parent())?)?;
|
let record_pat = ast::RecordPat::cast(field.syntax().parent().and_then(|p| p.parent())?)?;
|
||||||
let pat_id = self.pat_id(&record_pat.into())?;
|
let pat_id = self.pat_id(&record_pat.into())?;
|
||||||
let variant = self.infer()?.variant_resolution_for_pat(pat_id.as_pat()?)?;
|
let variant = self.infer()?.variant_resolution_for_pat(pat_id.as_pat()?)?;
|
||||||
let variant_data = variant.variant_data(db);
|
let variant_data = variant.fields(db);
|
||||||
let field = FieldId { parent: variant, local_id: variant_data.field(&field_name)? };
|
let field = FieldId { parent: variant, local_id: variant_data.field(&field_name)? };
|
||||||
let (adt, subst) = self.infer()?.type_of_pat.get(pat_id.as_pat()?)?.as_adt()?;
|
let (adt, subst) = self.infer()?[pat_id.as_pat()?].as_adt()?;
|
||||||
let field_ty =
|
let field_ty =
|
||||||
db.field_types(variant).get(field.local_id)?.clone().substitute(Interner, subst);
|
db.field_types(variant).get(field.local_id)?.clone().substitute(Interner, subst);
|
||||||
Some((
|
Some((
|
||||||
|
|
@ -765,7 +763,8 @@ impl<'db> SourceAnalyzer<'db> {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
let res = resolve_hir_path(db, &self.resolver, path, HygieneId::ROOT, Some(store))?;
|
let body_owner = self.resolver.body_owner();
|
||||||
|
let res = resolve_hir_value_path(db, &self.resolver, body_owner, path, HygieneId::ROOT)?;
|
||||||
match res {
|
match res {
|
||||||
PathResolution::Def(def) => Some(def),
|
PathResolution::Def(def) => Some(def),
|
||||||
_ => None,
|
_ => None,
|
||||||
|
|
@ -803,8 +802,8 @@ impl<'db> SourceAnalyzer<'db> {
|
||||||
};
|
};
|
||||||
container = Either::Right(db.normalize_projection(projection, trait_env.clone()));
|
container = Either::Right(db.normalize_projection(projection, trait_env.clone()));
|
||||||
}
|
}
|
||||||
let handle_variants = |variant, subst: &Substitution, container: &mut _| {
|
let handle_variants = |variant: VariantId, subst: &Substitution, container: &mut _| {
|
||||||
let fields = db.variant_fields(variant);
|
let fields = variant.fields(db);
|
||||||
let field = fields.field(&field_name.as_name())?;
|
let field = fields.field(&field_name.as_name())?;
|
||||||
let field_types = db.field_types(variant);
|
let field_types = db.field_types(variant);
|
||||||
*container = Either::Right(field_types[field].clone().substitute(Interner, subst));
|
*container = Either::Right(field_types[field].clone().substitute(Interner, subst));
|
||||||
|
|
@ -1249,7 +1248,7 @@ impl<'db> SourceAnalyzer<'db> {
|
||||||
let infer = self.infer()?;
|
let infer = self.infer()?;
|
||||||
|
|
||||||
let pat_id = self.pat_id(&pattern.clone().into())?.as_pat()?;
|
let pat_id = self.pat_id(&pattern.clone().into())?.as_pat()?;
|
||||||
let substs = infer.type_of_pat[pat_id].as_adt()?.1;
|
let substs = infer[pat_id].as_adt()?.1;
|
||||||
|
|
||||||
let (variant, missing_fields, _exhaustive) =
|
let (variant, missing_fields, _exhaustive) =
|
||||||
record_pattern_missing_fields(db, infer, pat_id, &body[pat_id])?;
|
record_pattern_missing_fields(db, infer, pat_id, &body[pat_id])?;
|
||||||
|
|
@ -1423,7 +1422,7 @@ impl<'db> SourceAnalyzer<'db> {
|
||||||
method_name: &Name,
|
method_name: &Name,
|
||||||
) -> Option<(TraitId, FunctionId)> {
|
) -> Option<(TraitId, FunctionId)> {
|
||||||
let trait_id = lang_trait.resolve_trait(db, self.resolver.krate())?;
|
let trait_id = lang_trait.resolve_trait(db, self.resolver.krate())?;
|
||||||
let fn_id = db.trait_items(trait_id).method_by_name(method_name)?;
|
let fn_id = trait_id.trait_items(db).method_by_name(method_name)?;
|
||||||
Some((trait_id, fn_id))
|
Some((trait_id, fn_id))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1580,7 +1579,7 @@ fn resolve_hir_path_(
|
||||||
// within the trait's associated types.
|
// within the trait's associated types.
|
||||||
if let (Some(unresolved), &TypeNs::TraitId(trait_id)) = (&unresolved, &ty) {
|
if let (Some(unresolved), &TypeNs::TraitId(trait_id)) = (&unresolved, &ty) {
|
||||||
if let Some(type_alias_id) =
|
if let Some(type_alias_id) =
|
||||||
db.trait_items(trait_id).associated_type_by_name(unresolved.name)
|
trait_id.trait_items(db).associated_type_by_name(unresolved.name)
|
||||||
{
|
{
|
||||||
return Some(PathResolution::Def(ModuleDefId::from(type_alias_id).into()));
|
return Some(PathResolution::Def(ModuleDefId::from(type_alias_id).into()));
|
||||||
}
|
}
|
||||||
|
|
@ -1731,7 +1730,7 @@ fn resolve_hir_path_qualifier(
|
||||||
// within the trait's associated types.
|
// within the trait's associated types.
|
||||||
if let (Some(unresolved), &TypeNs::TraitId(trait_id)) = (&unresolved, &ty) {
|
if let (Some(unresolved), &TypeNs::TraitId(trait_id)) = (&unresolved, &ty) {
|
||||||
if let Some(type_alias_id) =
|
if let Some(type_alias_id) =
|
||||||
db.trait_items(trait_id).associated_type_by_name(unresolved.name)
|
trait_id.trait_items(db).associated_type_by_name(unresolved.name)
|
||||||
{
|
{
|
||||||
return Some(PathResolution::Def(ModuleDefId::from(type_alias_id).into()));
|
return Some(PathResolution::Def(ModuleDefId::from(type_alias_id).into()));
|
||||||
}
|
}
|
||||||
|
|
@ -1785,8 +1784,8 @@ pub(crate) fn name_hygiene(db: &dyn HirDatabase, name: InFile<&SyntaxNode>) -> H
|
||||||
}
|
}
|
||||||
|
|
||||||
fn type_of_expr_including_adjust(infer: &InferenceResult, id: ExprId) -> Option<&Ty> {
|
fn type_of_expr_including_adjust(infer: &InferenceResult, id: ExprId) -> Option<&Ty> {
|
||||||
match infer.expr_adjustments.get(&id).and_then(|adjustments| adjustments.last()) {
|
match infer.expr_adjustment(id).and_then(|adjustments| adjustments.last()) {
|
||||||
Some(adjustment) => Some(&adjustment.target),
|
Some(adjustment) => Some(&adjustment.target),
|
||||||
None => infer.type_of_expr.get(id),
|
None => Some(&infer[id]),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -334,7 +334,7 @@ impl<'a> SymbolCollector<'a> {
|
||||||
fn collect_from_trait(&mut self, trait_id: TraitId, trait_do_not_complete: Complete) {
|
fn collect_from_trait(&mut self, trait_id: TraitId, trait_do_not_complete: Complete) {
|
||||||
let trait_data = self.db.trait_signature(trait_id);
|
let trait_data = self.db.trait_signature(trait_id);
|
||||||
self.with_container_name(Some(trait_data.name.as_str().into()), |s| {
|
self.with_container_name(Some(trait_data.name.as_str().into()), |s| {
|
||||||
for &(ref name, assoc_item_id) in &self.db.trait_items(trait_id).items {
|
for &(ref name, assoc_item_id) in &trait_id.trait_items(self.db).items {
|
||||||
s.push_assoc_item(assoc_item_id, name, Some(trait_do_not_complete));
|
s.push_assoc_item(assoc_item_id, name, Some(trait_do_not_complete));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ license.workspace = true
|
||||||
rust-version.workspace = true
|
rust-version.workspace = true
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
|
doctest = false
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
cov-mark = "2.0.0"
|
cov-mark = "2.0.0"
|
||||||
|
|
|
||||||
|
|
@ -175,7 +175,7 @@ pub(crate) fn expand_rest_pattern(acc: &mut Assists, ctx: &AssistContext<'_>) ->
|
||||||
// ast::TuplePat(it) => (),
|
// ast::TuplePat(it) => (),
|
||||||
// FIXME
|
// FIXME
|
||||||
// ast::SlicePat(it) => (),
|
// ast::SlicePat(it) => (),
|
||||||
_ => return None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
use std::slice;
|
||||||
|
|
||||||
use ide_db::assists::GroupLabel;
|
use ide_db::assists::GroupLabel;
|
||||||
use stdx::to_lower_snake_case;
|
use stdx::to_lower_snake_case;
|
||||||
use syntax::ast::HasVisibility;
|
use syntax::ast::HasVisibility;
|
||||||
|
|
@ -52,7 +54,7 @@ pub(crate) fn generate_enum_is_method(acc: &mut Assists, ctx: &AssistContext<'_>
|
||||||
let fn_name = format!("is_{}", &to_lower_snake_case(&variant_name.text()));
|
let fn_name = format!("is_{}", &to_lower_snake_case(&variant_name.text()));
|
||||||
|
|
||||||
// Return early if we've found an existing new fn
|
// Return early if we've found an existing new fn
|
||||||
let impl_def = find_struct_impl(ctx, &parent_enum, &[fn_name.clone()])?;
|
let impl_def = find_struct_impl(ctx, &parent_enum, slice::from_ref(&fn_name))?;
|
||||||
|
|
||||||
let target = variant.syntax().text_range();
|
let target = variant.syntax().text_range();
|
||||||
acc.add_group(
|
acc.add_group(
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
use std::slice;
|
||||||
|
|
||||||
use ide_db::assists::GroupLabel;
|
use ide_db::assists::GroupLabel;
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use stdx::to_lower_snake_case;
|
use stdx::to_lower_snake_case;
|
||||||
|
|
@ -148,7 +150,7 @@ fn generate_enum_projection_method(
|
||||||
let fn_name = format!("{fn_name_prefix}_{}", &to_lower_snake_case(&variant_name.text()));
|
let fn_name = format!("{fn_name_prefix}_{}", &to_lower_snake_case(&variant_name.text()));
|
||||||
|
|
||||||
// Return early if we've found an existing new fn
|
// Return early if we've found an existing new fn
|
||||||
let impl_def = find_struct_impl(ctx, &parent_enum, &[fn_name.clone()])?;
|
let impl_def = find_struct_impl(ctx, &parent_enum, slice::from_ref(&fn_name))?;
|
||||||
|
|
||||||
let target = variant.syntax().text_range();
|
let target = variant.syntax().text_range();
|
||||||
acc.add_group(
|
acc.add_group(
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,7 @@ use ide_db::{assists::AssistId, defs::Definition};
|
||||||
use stdx::to_upper_snake_case;
|
use stdx::to_upper_snake_case;
|
||||||
use syntax::{
|
use syntax::{
|
||||||
AstNode,
|
AstNode,
|
||||||
ast::{self, HasName, make},
|
ast::{self, HasName, syntax_factory::SyntaxFactory},
|
||||||
ted,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
|
@ -69,15 +68,18 @@ pub(crate) fn promote_local_to_const(acc: &mut Assists, ctx: &AssistContext<'_>)
|
||||||
"Promote local to constant",
|
"Promote local to constant",
|
||||||
let_stmt.syntax().text_range(),
|
let_stmt.syntax().text_range(),
|
||||||
|edit| {
|
|edit| {
|
||||||
|
let make = SyntaxFactory::with_mappings();
|
||||||
|
let mut editor = edit.make_editor(let_stmt.syntax());
|
||||||
let name = to_upper_snake_case(&name.to_string());
|
let name = to_upper_snake_case(&name.to_string());
|
||||||
let usages = Definition::Local(local).usages(&ctx.sema).all();
|
let usages = Definition::Local(local).usages(&ctx.sema).all();
|
||||||
if let Some(usages) = usages.references.get(&ctx.file_id()) {
|
if let Some(usages) = usages.references.get(&ctx.file_id()) {
|
||||||
let name_ref = make::name_ref(&name);
|
let name_ref = make.name_ref(&name);
|
||||||
|
|
||||||
for usage in usages {
|
for usage in usages {
|
||||||
let Some(usage_name) = usage.name.as_name_ref().cloned() else { continue };
|
let Some(usage_name) = usage.name.as_name_ref().cloned() else { continue };
|
||||||
if let Some(record_field) = ast::RecordExprField::for_name_ref(&usage_name) {
|
if let Some(record_field) = ast::RecordExprField::for_name_ref(&usage_name) {
|
||||||
let name_expr = make::expr_path(make::path_from_text(&name));
|
let path = make.ident_path(&name);
|
||||||
|
let name_expr = make.expr_path(path);
|
||||||
utils::replace_record_field_expr(ctx, edit, record_field, name_expr);
|
utils::replace_record_field_expr(ctx, edit, record_field, name_expr);
|
||||||
} else {
|
} else {
|
||||||
let usage_range = usage.range;
|
let usage_range = usage.range;
|
||||||
|
|
@ -86,15 +88,17 @@ pub(crate) fn promote_local_to_const(acc: &mut Assists, ctx: &AssistContext<'_>)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let item = make::item_const(None, make::name(&name), make::ty(&ty), initializer)
|
let item = make.item_const(None, make.name(&name), make.ty(&ty), initializer);
|
||||||
.clone_for_update();
|
|
||||||
let let_stmt = edit.make_mut(let_stmt);
|
|
||||||
|
|
||||||
if let Some((cap, name)) = ctx.config.snippet_cap.zip(item.name()) {
|
if let Some((cap, name)) = ctx.config.snippet_cap.zip(item.name()) {
|
||||||
edit.add_tabstop_before(cap, name);
|
let tabstop = edit.make_tabstop_before(cap);
|
||||||
|
editor.add_annotation(name.syntax().clone(), tabstop);
|
||||||
}
|
}
|
||||||
|
|
||||||
ted::replace(let_stmt.syntax(), item.syntax());
|
editor.replace(let_stmt.syntax(), item.syntax());
|
||||||
|
|
||||||
|
editor.add_mappings(make.finish_with_mappings());
|
||||||
|
edit.add_file_edits(ctx.vfs_file_id(), editor);
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue