Unnamed repository; edit this file 'description' to name the repository.
Auto merge of #154572 - lnicola:sync-from-ra, r=lnicola
`rust-analyzer` subtree update Subtree update of `rust-analyzer` to https://github.com/rust-lang/rust-analyzer/commit/f1297b21119565c626320c1ffc248965fffb2527. Created using https://github.com/rust-lang/josh-sync. r? @ghost
bors 7 weeks ago
parent 7f4e321 · parent f1297b2 · commit f8b7092
-rw-r--r--.github/workflows/autopublish.yaml2
-rw-r--r--.github/workflows/ci.yaml31
-rw-r--r--.github/workflows/coverage.yaml6
-rw-r--r--.github/workflows/fuzz.yml6
-rw-r--r--.github/workflows/metrics.yaml22
-rw-r--r--.github/workflows/publish-libs.yaml2
-rw-r--r--.github/workflows/release.yaml32
-rw-r--r--.github/workflows/rustdoc.yaml31
-rw-r--r--Cargo.lock1
-rw-r--r--crates/hir-def/src/attrs.rs2
-rw-r--r--crates/hir-def/src/db.rs162
-rw-r--r--crates/hir-def/src/expr_store.rs148
-rw-r--r--crates/hir-def/src/expr_store/body.rs24
-rw-r--r--crates/hir-def/src/expr_store/expander.rs33
-rw-r--r--crates/hir-def/src/expr_store/lower.rs109
-rw-r--r--crates/hir-def/src/expr_store/lower/generics.rs40
-rw-r--r--crates/hir-def/src/expr_store/lower/path/tests.rs2
-rw-r--r--crates/hir-def/src/expr_store/pretty.rs14
-rw-r--r--crates/hir-def/src/expr_store/scope.rs81
-rw-r--r--crates/hir-def/src/expr_store/tests/body.rs153
-rw-r--r--crates/hir-def/src/expr_store/tests/signatures.rs5
-rw-r--r--crates/hir-def/src/find_path.rs3
-rw-r--r--crates/hir-def/src/hir/generics.rs119
-rw-r--r--crates/hir-def/src/import_map.rs25
-rw-r--r--crates/hir-def/src/item_tree.rs33
-rw-r--r--crates/hir-def/src/item_tree/lower.rs15
-rw-r--r--crates/hir-def/src/lib.rs144
-rw-r--r--crates/hir-def/src/macro_expansion_tests/mod.rs3
-rw-r--r--crates/hir-def/src/nameres/assoc.rs17
-rw-r--r--crates/hir-def/src/nameres/tests/incremental.rs68
-rw-r--r--crates/hir-def/src/resolver.rs99
-rw-r--r--crates/hir-def/src/signatures.rs251
-rw-r--r--crates/hir-def/src/src.rs6
-rw-r--r--crates/hir-def/src/test_db.rs5
-rw-r--r--crates/hir-def/src/visibility.rs39
-rw-r--r--crates/hir-expand/src/db.rs9
-rw-r--r--crates/hir-ty/src/builtin_derive.rs14
-rw-r--r--crates/hir-ty/src/consteval.rs40
-rw-r--r--crates/hir-ty/src/consteval/tests.rs8
-rw-r--r--crates/hir-ty/src/db.rs16
-rw-r--r--crates/hir-ty/src/diagnostics/decl_check.rs33
-rw-r--r--crates/hir-ty/src/diagnostics/expr.rs22
-rw-r--r--crates/hir-ty/src/diagnostics/match_check.rs5
-rw-r--r--crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs4
-rw-r--r--crates/hir-ty/src/diagnostics/unsafe_check.rs40
-rw-r--r--crates/hir-ty/src/display.rs65
-rw-r--r--crates/hir-ty/src/drop.rs12
-rw-r--r--crates/hir-ty/src/dyn_compatibility.rs14
-rw-r--r--crates/hir-ty/src/dyn_compatibility/tests.rs5
-rw-r--r--crates/hir-ty/src/generics.rs29
-rw-r--r--crates/hir-ty/src/infer.rs227
-rw-r--r--crates/hir-ty/src/infer/cast.rs9
-rw-r--r--crates/hir-ty/src/infer/closure/analysis.rs104
-rw-r--r--crates/hir-ty/src/infer/coerce.rs5
-rw-r--r--crates/hir-ty/src/infer/expr.rs32
-rw-r--r--crates/hir-ty/src/infer/mutability.rs12
-rw-r--r--crates/hir-ty/src/infer/pat.rs33
-rw-r--r--crates/hir-ty/src/infer/path.rs9
-rw-r--r--crates/hir-ty/src/infer/unify.rs4
-rw-r--r--crates/hir-ty/src/inhabitedness.rs10
-rw-r--r--crates/hir-ty/src/lang_items.rs8
-rw-r--r--crates/hir-ty/src/layout.rs2
-rw-r--r--crates/hir-ty/src/layout/adt.rs4
-rw-r--r--crates/hir-ty/src/layout/tests.rs50
-rw-r--r--crates/hir-ty/src/lib.rs6
-rw-r--r--crates/hir-ty/src/lower.rs148
-rw-r--r--crates/hir-ty/src/lower/path.rs9
-rw-r--r--crates/hir-ty/src/method_resolution.rs17
-rw-r--r--crates/hir-ty/src/method_resolution/confirm.rs2
-rw-r--r--crates/hir-ty/src/method_resolution/probe.rs13
-rw-r--r--crates/hir-ty/src/mir.rs8
-rw-r--r--crates/hir-ty/src/mir/borrowck.rs10
-rw-r--r--crates/hir-ty/src/mir/eval.rs45
-rw-r--r--crates/hir-ty/src/mir/eval/shim.rs8
-rw-r--r--crates/hir-ty/src/mir/eval/tests.rs6
-rw-r--r--crates/hir-ty/src/mir/lower.rs50
-rw-r--r--crates/hir-ty/src/mir/pretty.rs18
-rw-r--r--crates/hir-ty/src/next_solver/def_id.rs75
-rw-r--r--crates/hir-ty/src/next_solver/fulfill/errors.rs3
-rw-r--r--crates/hir-ty/src/next_solver/generics.rs2
-rw-r--r--crates/hir-ty/src/next_solver/interner.rs85
-rw-r--r--crates/hir-ty/src/next_solver/ir_print.rs15
-rw-r--r--crates/hir-ty/src/next_solver/solver.rs103
-rw-r--r--crates/hir-ty/src/next_solver/ty.rs6
-rw-r--r--crates/hir-ty/src/opaques.rs14
-rw-r--r--crates/hir-ty/src/representability.rs4
-rw-r--r--crates/hir-ty/src/specialization.rs13
-rw-r--r--crates/hir-ty/src/tests.rs176
-rw-r--r--crates/hir-ty/src/tests/closure_captures.rs17
-rw-r--r--crates/hir-ty/src/tests/incremental.rs170
-rw-r--r--crates/hir-ty/src/tests/patterns.rs2
-rw-r--r--crates/hir-ty/src/tests/regression.rs1
-rw-r--r--crates/hir-ty/src/tests/regression/new_solver.rs8
-rw-r--r--crates/hir-ty/src/tests/simple.rs39
-rw-r--r--crates/hir-ty/src/tests/traits.rs6
-rw-r--r--crates/hir-ty/src/traits.rs34
-rw-r--r--crates/hir-ty/src/upvars.rs8
-rw-r--r--crates/hir-ty/src/utils.rs3
-rw-r--r--crates/hir-ty/src/variance.rs9
-rw-r--r--crates/hir/src/attrs.rs17
-rw-r--r--crates/hir/src/display.rs65
-rw-r--r--crates/hir/src/from_id.rs104
-rw-r--r--crates/hir/src/has_source.rs24
-rw-r--r--crates/hir/src/lib.rs595
-rw-r--r--crates/hir/src/semantics.rs147
-rw-r--r--crates/hir/src/semantics/child_by_source.rs13
-rw-r--r--crates/hir/src/semantics/source_to_def.rs83
-rw-r--r--crates/hir/src/source_analyzer.rs249
-rw-r--r--crates/hir/src/symbols.rs10
-rw-r--r--crates/hir/src/term_search/expr.rs8
-rw-r--r--crates/hir/src/term_search/tactics.rs2
-rw-r--r--crates/ide-assists/src/handlers/add_explicit_enum_discriminant.rs6
-rw-r--r--crates/ide-assists/src/handlers/add_missing_match_arms.rs210
-rw-r--r--crates/ide-assists/src/handlers/auto_import.rs2
-rw-r--r--crates/ide-assists/src/handlers/convert_bool_then.rs10
-rw-r--r--crates/ide-assists/src/handlers/convert_for_to_while_let.rs46
-rw-r--r--crates/ide-assists/src/handlers/convert_named_struct_to_tuple_struct.rs10
-rw-r--r--crates/ide-assists/src/handlers/convert_tuple_struct_to_named_struct.rs12
-rw-r--r--crates/ide-assists/src/handlers/destructure_struct_binding.rs36
-rw-r--r--crates/ide-assists/src/handlers/destructure_tuple_binding.rs88
-rw-r--r--crates/ide-assists/src/handlers/desugar_try_expr.rs111
-rw-r--r--crates/ide-assists/src/handlers/expand_glob_import.rs4
-rw-r--r--crates/ide-assists/src/handlers/expand_rest_pattern.rs2
-rw-r--r--crates/ide-assists/src/handlers/extract_module.rs2
-rw-r--r--crates/ide-assists/src/handlers/extract_struct_from_enum_variant.rs13
-rw-r--r--crates/ide-assists/src/handlers/extract_variable.rs2
-rw-r--r--crates/ide-assists/src/handlers/fix_visibility.rs2
-rw-r--r--crates/ide-assists/src/handlers/generate_blanket_trait_impl.rs17
-rw-r--r--crates/ide-assists/src/handlers/generate_default_from_new.rs107
-rw-r--r--crates/ide-assists/src/handlers/generate_deref.rs113
-rw-r--r--crates/ide-assists/src/handlers/generate_from_impl_for_enum.rs82
-rw-r--r--crates/ide-assists/src/handlers/generate_function.rs21
-rw-r--r--crates/ide-assists/src/handlers/generate_getter_or_setter.rs68
-rw-r--r--crates/ide-assists/src/handlers/generate_impl.rs41
-rw-r--r--crates/ide-assists/src/handlers/generate_new.rs88
-rw-r--r--crates/ide-assists/src/handlers/merge_match_arms.rs39
-rw-r--r--crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs45
-rw-r--r--crates/ide-assists/src/handlers/replace_qualified_name_with_use.rs2
-rw-r--r--crates/ide-assists/src/handlers/unmerge_match_arm.rs26
-rw-r--r--crates/ide-assists/src/tests/generated.rs4
-rw-r--r--crates/ide-assists/src/utils.rs305
-rw-r--r--crates/ide-completion/src/completions.rs14
-rw-r--r--crates/ide-completion/src/completions/pattern.rs4
-rw-r--r--crates/ide-completion/src/completions/type.rs4
-rw-r--r--crates/ide-completion/src/context.rs4
-rw-r--r--crates/ide-completion/src/context/analysis.rs8
-rw-r--r--crates/ide-completion/src/render.rs8
-rw-r--r--crates/ide-completion/src/render/literal.rs4
-rw-r--r--crates/ide-completion/src/render/pattern.rs2
-rw-r--r--crates/ide-db/src/active_parameter.rs4
-rw-r--r--crates/ide-db/src/defs.rs50
-rw-r--r--crates/ide-db/src/documentation.rs18
-rw-r--r--crates/ide-db/src/lib.rs2
-rw-r--r--crates/ide-db/src/path_transform.rs2
-rw-r--r--crates/ide-db/src/prime_caches.rs4
-rw-r--r--crates/ide-db/src/rename.rs2
-rw-r--r--crates/ide-db/src/search.rs54
-rw-r--r--crates/ide-db/src/test_data/test_symbol_index_collection.txt8
-rw-r--r--crates/ide-diagnostics/src/handlers/missing_fields.rs8
-rw-r--r--crates/ide-diagnostics/src/handlers/missing_lifetime.rs16
-rw-r--r--crates/ide-diagnostics/src/handlers/no_such_field.rs8
-rw-r--r--crates/ide-diagnostics/src/handlers/trait_impl_redundant_assoc_item.rs97
-rw-r--r--crates/ide-diagnostics/src/handlers/typed_hole.rs26
-rw-r--r--crates/ide/src/doc_links.rs10
-rw-r--r--crates/ide/src/doc_links/tests.rs2
-rw-r--r--crates/ide/src/hover/render.rs16
-rw-r--r--crates/ide/src/inlay_hints/discriminant.rs2
-rw-r--r--crates/ide/src/inlay_hints/implicit_drop.rs4
-rw-r--r--crates/ide/src/inlay_hints/param_name.rs2
-rw-r--r--crates/ide/src/moniker.rs2
-rw-r--r--crates/ide/src/navigation_target.rs8
-rw-r--r--crates/ide/src/references.rs4
-rw-r--r--crates/ide/src/rename.rs4
-rw-r--r--crates/ide/src/runnables.rs2
-rw-r--r--crates/ide/src/signature_help.rs4
-rw-r--r--crates/ide/src/syntax_highlighting.rs37
-rw-r--r--crates/ide/src/syntax_highlighting/highlight.rs2
-rw-r--r--crates/ide/src/syntax_highlighting/inject.rs2
-rw-r--r--crates/ide/src/syntax_highlighting/test_data/highlight_general.html2
-rw-r--r--crates/ide/src/syntax_highlighting/tests.rs2
-rw-r--r--crates/intern/Cargo.toml3
-rw-r--r--crates/intern/src/gc.rs4
-rw-r--r--crates/parser/src/grammar/expressions/atom.rs12
-rw-r--r--crates/parser/src/grammar/items/adt.rs4
-rw-r--r--crates/parser/test_data/generated/runner.rs2
-rw-r--r--crates/parser/test_data/parser/inline/ok/asm_sym_paren.rast49
-rw-r--r--crates/parser/test_data/parser/inline/ok/asm_sym_paren.rs3
-rw-r--r--crates/parser/test_data/parser/inline/ok/record_field_default_values.rast5
-rw-r--r--crates/parser/test_data/parser/inline/ok/variant_discriminant.rast5
-rw-r--r--crates/parser/test_data/parser/ok/0019_enums.rast5
-rw-r--r--crates/rust-analyzer/Cargo.toml2
-rw-r--r--crates/rust-analyzer/src/cli/analysis_stats.rs282
-rw-r--r--crates/rust-analyzer/src/flycheck.rs2
-rw-r--r--crates/rust-analyzer/src/handlers/notification.rs3
-rw-r--r--crates/rust-analyzer/src/main_loop.rs15
-rw-r--r--crates/span/src/ast_id.rs73
-rw-r--r--crates/stdx/src/lib.rs19
-rw-r--r--crates/syntax/rust.ungram4
-rw-r--r--crates/syntax/src/ast/edit.rs2
-rw-r--r--crates/syntax/src/ast/edit_in_place.rs2
-rw-r--r--crates/syntax/src/ast/generated/nodes.rs4
-rw-r--r--crates/syntax/src/ast/make.rs12
-rw-r--r--crates/syntax/src/ast/node_ext.rs4
-rw-r--r--crates/syntax/src/ast/syntax_factory/constructors.rs65
-rw-r--r--crates/syntax/src/syntax_editor/edits.rs4
-rw-r--r--crates/test-utils/src/minicore.rs13
-rw-r--r--editors/code/package-lock.json48
-rw-r--r--rust-version2
208 files changed, 4830 insertions, 2792 deletions
diff --git a/.github/workflows/autopublish.yaml b/.github/workflows/autopublish.yaml
index 6e2be7fd3d..abb9b521f1 100644
--- a/.github/workflows/autopublish.yaml
+++ b/.github/workflows/autopublish.yaml
@@ -16,7 +16,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
- uses: actions/checkout@v4
+ uses: actions/checkout@v6
with:
fetch-depth: 0
diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml
index 04de6d11e3..c27d84fb0b 100644
--- a/.github/workflows/ci.yaml
+++ b/.github/workflows/ci.yaml
@@ -30,8 +30,8 @@ jobs:
outputs:
typescript: ${{ steps.filter.outputs.typescript }}
steps:
- - uses: actions/checkout@v4
- - uses: dorny/paths-filter@1441771bbfdd59dcd748680ee64ebd8faab1a242
+ - uses: actions/checkout@v6
+ - uses: dorny/paths-filter@fbd0ab8f3e69293af611ebaee6363fc25e6d187d # v4.0.1
id: filter
with:
filters: |
@@ -45,7 +45,7 @@ jobs:
steps:
- name: Checkout repository
- uses: actions/checkout@v4
+ uses: actions/checkout@v6
with:
ref: ${{ github.event.pull_request.head.sha }}
@@ -88,7 +88,7 @@ jobs:
steps:
- name: Checkout repository
- uses: actions/checkout@v4
+ uses: actions/checkout@v6
with:
ref: ${{ github.event.pull_request.head.sha }}
@@ -136,7 +136,7 @@ jobs:
steps:
- name: Checkout repository
- uses: actions/checkout@v4
+ uses: actions/checkout@v6
- name: Install Rust toolchain
run: |
@@ -164,7 +164,7 @@ jobs:
steps:
- name: Checkout repository
- uses: actions/checkout@v4
+ uses: actions/checkout@v6
- name: Install Rust toolchain
run: |
@@ -180,7 +180,7 @@ jobs:
steps:
- name: Checkout repository
- uses: actions/checkout@v4
+ uses: actions/checkout@v6
# Note that clippy output is currently dependent on whether rust-src is installed,
# https://github.com/rust-lang/rust-clippy/issues/14625
@@ -202,7 +202,7 @@ jobs:
steps:
- name: Checkout repository
- uses: actions/checkout@v4
+ uses: actions/checkout@v6
- name: Install Rust toolchain
run: |
@@ -226,12 +226,7 @@ jobs:
strategy:
matrix:
- target:
- [
- powerpc-unknown-linux-gnu,
- x86_64-unknown-linux-musl,
- wasm32-unknown-unknown,
- ]
+ target: [powerpc-unknown-linux-gnu, x86_64-unknown-linux-musl, wasm32-unknown-unknown]
include:
# The rust-analyzer binary is not expected to compile on WASM, but the IDE
# crate should
@@ -240,7 +235,7 @@ jobs:
steps:
- name: Checkout repository
- uses: actions/checkout@v4
+ uses: actions/checkout@v6
- name: Install Rust toolchain
run: |
@@ -268,10 +263,10 @@ jobs:
steps:
- name: Checkout repository
- uses: actions/checkout@v4
+ uses: actions/checkout@v6
- name: Install Nodejs
- uses: actions/setup-node@v4
+ uses: actions/setup-node@v6
with:
node-version: 22
@@ -327,7 +322,7 @@ jobs:
run: curl -LsSf https://github.com/crate-ci/typos/releases/download/$TYPOS_VERSION/typos-$TYPOS_VERSION-x86_64-unknown-linux-musl.tar.gz | tar zxf - -C ${CARGO_HOME:-~/.cargo}/bin
- name: Checkout repository
- uses: actions/checkout@v4
+ uses: actions/checkout@v6
with:
ref: ${{ github.event.pull_request.head.sha }}
diff --git a/.github/workflows/coverage.yaml b/.github/workflows/coverage.yaml
index bd4edba747..9460c6a3c7 100644
--- a/.github/workflows/coverage.yaml
+++ b/.github/workflows/coverage.yaml
@@ -13,7 +13,7 @@ jobs:
coverage:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v6
- name: Install Rust toolchain
run: |
@@ -34,9 +34,9 @@ jobs:
- name: Generate code coverage
run: cargo llvm-cov --workspace --lcov --output-path lcov.info
-
+
- name: Upload coverage to Codecov
- uses: codecov/codecov-action@v5
+ uses: codecov/codecov-action@57e3a136b779b570ffcdbf80b3bdc90e7fab3de2 # v6.0.0
with:
files: lcov.info
fail_ci_if_error: false
diff --git a/.github/workflows/fuzz.yml b/.github/workflows/fuzz.yml
index 7acfcbe351..af0e03598e 100644
--- a/.github/workflows/fuzz.yml
+++ b/.github/workflows/fuzz.yml
@@ -2,10 +2,10 @@ name: Fuzz
on:
schedule:
# Once a week
- - cron: '0 0 * * 0'
+ - cron: "0 0 * * 0"
push:
paths:
- - '.github/workflows/fuzz.yml'
+ - ".github/workflows/fuzz.yml"
# Allow manual trigger
workflow_dispatch:
@@ -27,7 +27,7 @@ jobs:
steps:
- name: Checkout repository
- uses: actions/checkout@v4
+ uses: actions/checkout@v6
with:
ref: ${{ github.event.pull_request.head.sha }}
fetch-depth: 1
diff --git a/.github/workflows/metrics.yaml b/.github/workflows/metrics.yaml
index 860837dd7f..a482235105 100644
--- a/.github/workflows/metrics.yaml
+++ b/.github/workflows/metrics.yaml
@@ -23,7 +23,7 @@ jobs:
rustup component add --toolchain beta rust-src
- name: Checkout repository
- uses: actions/checkout@v4
+ uses: actions/checkout@v6
- name: Cache cargo
uses: actions/cache@v4
@@ -45,7 +45,7 @@ jobs:
key: ${{ runner.os }}-target-${{ github.sha }}
- name: Upload build metrics
- uses: actions/upload-artifact@v4
+ uses: actions/upload-artifact@v7
with:
name: build-${{ github.sha }}
path: target/build.json
@@ -66,7 +66,7 @@ jobs:
rustup component add --toolchain beta rust-src
- name: Checkout repository
- uses: actions/checkout@v4
+ uses: actions/checkout@v6
- name: Restore target cache
uses: actions/cache@v4
@@ -78,7 +78,7 @@ jobs:
run: cargo xtask metrics "${{ matrix.names }}"
- name: Upload metrics
- uses: actions/upload-artifact@v4
+ uses: actions/upload-artifact@v7
with:
name: ${{ matrix.names }}-${{ github.sha }}
path: target/${{ matrix.names }}.json
@@ -89,35 +89,35 @@ jobs:
needs: [build_metrics, other_metrics]
steps:
- name: Checkout repository
- uses: actions/checkout@v4
+ uses: actions/checkout@v6
- name: Download build metrics
- uses: actions/download-artifact@v4
+ uses: actions/download-artifact@v8
with:
name: build-${{ github.sha }}
- name: Download self metrics
- uses: actions/download-artifact@v4
+ uses: actions/download-artifact@v8
with:
name: self-${{ github.sha }}
- name: Download ripgrep-13.0.0 metrics
- uses: actions/download-artifact@v4
+ uses: actions/download-artifact@v8
with:
name: ripgrep-13.0.0-${{ github.sha }}
- name: Download webrender-2022 metrics
- uses: actions/download-artifact@v4
+ uses: actions/download-artifact@v8
with:
name: webrender-2022-${{ github.sha }}
- name: Download diesel-1.4.8 metrics
- uses: actions/download-artifact@v4
+ uses: actions/download-artifact@v8
with:
name: diesel-1.4.8-${{ github.sha }}
- name: Download hyper-0.14.18 metrics
- uses: actions/download-artifact@v4
+ uses: actions/download-artifact@v8
with:
name: hyper-0.14.18-${{ github.sha }}
diff --git a/.github/workflows/publish-libs.yaml b/.github/workflows/publish-libs.yaml
index f2c8b6365b..762b7bda87 100644
--- a/.github/workflows/publish-libs.yaml
+++ b/.github/workflows/publish-libs.yaml
@@ -14,7 +14,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
- uses: actions/checkout@v4
+ uses: actions/checkout@v6
with:
fetch-depth: 0
diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml
index 28914118de..b35614f91b 100644
--- a/.github/workflows/release.yaml
+++ b/.github/workflows/release.yaml
@@ -70,12 +70,12 @@ jobs:
steps:
- name: Checkout repository
- uses: actions/checkout@v4
+ uses: actions/checkout@v6
with:
fetch-depth: ${{ env.FETCH_DEPTH }}
- name: Install Node.js toolchain
- uses: actions/setup-node@v4
+ uses: actions/setup-node@v6
with:
node-version: 22
@@ -143,7 +143,7 @@ jobs:
run: target/${{ matrix.target }}/release/rust-analyzer analysis-stats --with-deps --no-sysroot --no-test $(rustc --print sysroot)/lib/rustlib/src/rust/library/std -q
- name: Upload artifacts
- uses: actions/upload-artifact@v4
+ uses: actions/upload-artifact@v7
with:
name: dist-${{ matrix.target }}
path: ./dist
@@ -166,7 +166,7 @@ jobs:
run: apk add --no-cache git clang lld musl-dev nodejs npm
- name: Checkout repository
- uses: actions/checkout@v4
+ uses: actions/checkout@v6
with:
fetch-depth: ${{ env.FETCH_DEPTH }}
@@ -189,7 +189,7 @@ jobs:
- run: rm -rf editors/code/server
- name: Upload artifacts
- uses: actions/upload-artifact@v4
+ uses: actions/upload-artifact@v7
with:
name: dist-x86_64-unknown-linux-musl
path: ./dist
@@ -201,7 +201,7 @@ jobs:
needs: ["dist", "dist-x86_64-unknown-linux-musl"]
steps:
- name: Install Nodejs
- uses: actions/setup-node@v4
+ uses: actions/setup-node@v6
with:
node-version: 22
@@ -212,46 +212,46 @@ jobs:
- run: 'echo "TAG: $TAG"'
- name: Checkout repository
- uses: actions/checkout@v4
+ uses: actions/checkout@v6
with:
fetch-depth: ${{ env.FETCH_DEPTH }}
- run: echo "HEAD_SHA=$(git rev-parse HEAD)" >> $GITHUB_ENV
- run: 'echo "HEAD_SHA: $HEAD_SHA"'
- - uses: actions/download-artifact@v4
+ - uses: actions/download-artifact@v8
with:
name: dist-aarch64-apple-darwin
path: dist
- - uses: actions/download-artifact@v4
+ - uses: actions/download-artifact@v8
with:
name: dist-x86_64-apple-darwin
path: dist
- - uses: actions/download-artifact@v4
+ - uses: actions/download-artifact@v8
with:
name: dist-x86_64-unknown-linux-gnu
path: dist
- - uses: actions/download-artifact@v4
+ - uses: actions/download-artifact@v8
with:
name: dist-x86_64-unknown-linux-musl
path: dist
- - uses: actions/download-artifact@v4
+ - uses: actions/download-artifact@v8
with:
name: dist-aarch64-unknown-linux-gnu
path: dist
- - uses: actions/download-artifact@v4
+ - uses: actions/download-artifact@v8
with:
name: dist-arm-unknown-linux-gnueabihf
path: dist
- - uses: actions/download-artifact@v4
+ - uses: actions/download-artifact@v8
with:
name: dist-x86_64-pc-windows-msvc
path: dist
- - uses: actions/download-artifact@v4
+ - uses: actions/download-artifact@v8
with:
name: dist-i686-pc-windows-msvc
path: dist
- - uses: actions/download-artifact@v4
+ - uses: actions/download-artifact@v8
with:
name: dist-aarch64-pc-windows-msvc
path: dist
diff --git a/.github/workflows/rustdoc.yaml b/.github/workflows/rustdoc.yaml
index 0cc7ce77dd..03fd083175 100644
--- a/.github/workflows/rustdoc.yaml
+++ b/.github/workflows/rustdoc.yaml
@@ -1,8 +1,8 @@
name: rustdoc
on:
push:
- branches:
- - master
+ branches:
+ - master
env:
CARGO_INCREMENTAL: 0
@@ -10,6 +10,7 @@ env:
RUSTFLAGS: "-D warnings -W unreachable-pub"
RUSTDOCFLAGS: "-D warnings"
RUSTUP_MAX_RETRIES: 10
+ ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true
jobs:
rustdoc:
@@ -17,19 +18,19 @@ jobs:
runs-on: ubuntu-latest
steps:
- - name: Checkout repository
- uses: actions/checkout@v4
+ - name: Checkout repository
+ uses: actions/checkout@v6
- - name: Install Rust toolchain
- run: rustup update --no-self-update stable
+ - name: Install Rust toolchain
+ run: rustup update --no-self-update stable
- - name: Build Documentation
- run: cargo doc --all --no-deps --document-private-items
+ - name: Build Documentation
+ run: cargo doc --all --no-deps --document-private-items
- - name: Deploy Docs
- uses: peaceiris/actions-gh-pages@4f9cc6602d3f66b9c108549d475ec49e8ef4d45e # v4.0.0
- with:
- github_token: ${{ secrets.GITHUB_TOKEN }}
- publish_branch: gh-pages
- publish_dir: ./target/doc
- force_orphan: true
+ - name: Deploy Docs
+ uses: peaceiris/actions-gh-pages@4f9cc6602d3f66b9c108549d475ec49e8ef4d45e # v4.0.0
+ with:
+ github_token: ${{ secrets.GITHUB_TOKEN }}
+ publish_branch: gh-pages
+ publish_dir: ./target/doc
+ force_orphan: true
diff --git a/Cargo.lock b/Cargo.lock
index f31dda4a10..5370127ddc 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2315,6 +2315,7 @@ dependencies = [
"ide-db",
"ide-ssr",
"indexmap",
+ "intern",
"itertools 0.14.0",
"load-cargo",
"lsp-server 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)",
diff --git a/crates/hir-def/src/attrs.rs b/crates/hir-def/src/attrs.rs
index 0b8f656872..e3e1aac709 100644
--- a/crates/hir-def/src/attrs.rs
+++ b/crates/hir-def/src/attrs.rs
@@ -894,7 +894,7 @@ impl AttrFlags {
def: GenericDefId,
) -> &(ArenaMap<LocalLifetimeParamId, AttrFlags>, ArenaMap<LocalTypeOrConstParamId, AttrFlags>)
{
- let generic_params = GenericParams::new(db, def);
+ let generic_params = GenericParams::of(db, def);
let params_count_excluding_self =
generic_params.len() - usize::from(generic_params.trait_self_param().is_some());
if params_count_excluding_self == 0 {
diff --git a/crates/hir-def/src/db.rs b/crates/hir-def/src/db.rs
index b0b652a150..5d5d435398 100644
--- a/crates/hir-def/src/db.rs
+++ b/crates/hir-def/src/db.rs
@@ -4,28 +4,18 @@ use hir_expand::{
EditionedFileId, HirFileId, InFile, Lookup, MacroCallId, MacroDefId, MacroDefKind,
db::ExpandDatabase,
};
-use la_arena::ArenaMap;
use triomphe::Arc;
use crate::{
- AssocItemId, AttrDefId, BlockId, BlockLoc, ConstId, ConstLoc, DefWithBodyId, EnumId, EnumLoc,
- EnumVariantId, EnumVariantLoc, ExternBlockId, ExternBlockLoc, ExternCrateId, ExternCrateLoc,
- FunctionId, FunctionLoc, GenericDefId, ImplId, ImplLoc, LocalFieldId, Macro2Id, Macro2Loc,
- MacroExpander, MacroId, MacroRulesId, MacroRulesLoc, MacroRulesLocFlags, ProcMacroId,
- ProcMacroLoc, StaticId, StaticLoc, StructId, StructLoc, TraitId, TraitLoc, TypeAliasId,
- TypeAliasLoc, UnionId, UnionLoc, UseId, UseLoc, VariantId,
+ AnonConstId, AnonConstLoc, AssocItemId, AttrDefId, BlockId, BlockLoc, ConstId, ConstLoc,
+ EnumId, EnumLoc, EnumVariantId, EnumVariantLoc, ExternBlockId, ExternBlockLoc, ExternCrateId,
+ ExternCrateLoc, FunctionId, FunctionLoc, ImplId, ImplLoc, Macro2Id, Macro2Loc, MacroExpander,
+ MacroId, MacroRulesId, MacroRulesLoc, MacroRulesLocFlags, ProcMacroId, ProcMacroLoc, StaticId,
+ StaticLoc, StructId, StructLoc, TraitId, TraitLoc, TypeAliasId, TypeAliasLoc, UnionId,
+ UnionLoc, UseId, UseLoc,
attrs::AttrFlags,
- expr_store::{
- Body, BodySourceMap, ExpressionStore, ExpressionStoreSourceMap, scope::ExprScopes,
- },
- hir::generics::GenericParams,
- import_map::ImportMap,
item_tree::{ItemTree, file_item_tree_query},
nameres::crate_def_map,
- signatures::{
- ConstSignature, EnumSignature, FunctionSignature, ImplSignature, StaticSignature,
- StructSignature, TraitSignature, TypeAliasSignature, UnionSignature,
- },
visibility::{self, Visibility},
};
@@ -62,6 +52,9 @@ pub trait InternDatabase: RootQueryDb {
fn intern_static(&self, loc: StaticLoc) -> StaticId;
#[salsa::interned]
+ fn intern_anon_const(&self, loc: AnonConstLoc) -> AnonConstId;
+
+ #[salsa::interned]
fn intern_trait(&self, loc: TraitLoc) -> TraitId;
#[salsa::interned]
@@ -102,145 +95,8 @@ pub trait DefDatabase: InternDatabase + ExpandDatabase + SourceDatabase {
#[salsa::invoke(macro_def)]
fn macro_def(&self, m: MacroId) -> MacroDefId;
- // region:data
-
- #[salsa::tracked]
- fn trait_signature(&self, trait_: TraitId) -> Arc<TraitSignature> {
- self.trait_signature_with_source_map(trait_).0
- }
-
- #[salsa::tracked]
- fn impl_signature(&self, impl_: ImplId) -> Arc<ImplSignature> {
- self.impl_signature_with_source_map(impl_).0
- }
-
- #[salsa::tracked]
- fn struct_signature(&self, struct_: StructId) -> Arc<StructSignature> {
- self.struct_signature_with_source_map(struct_).0
- }
-
- #[salsa::tracked]
- fn union_signature(&self, union_: UnionId) -> Arc<UnionSignature> {
- self.union_signature_with_source_map(union_).0
- }
-
- #[salsa::tracked]
- fn enum_signature(&self, e: EnumId) -> Arc<EnumSignature> {
- self.enum_signature_with_source_map(e).0
- }
-
- #[salsa::tracked]
- fn const_signature(&self, e: ConstId) -> Arc<ConstSignature> {
- self.const_signature_with_source_map(e).0
- }
-
- #[salsa::tracked]
- fn static_signature(&self, e: StaticId) -> Arc<StaticSignature> {
- self.static_signature_with_source_map(e).0
- }
-
- #[salsa::tracked]
- fn function_signature(&self, e: FunctionId) -> Arc<FunctionSignature> {
- self.function_signature_with_source_map(e).0
- }
-
- #[salsa::tracked]
- fn type_alias_signature(&self, e: TypeAliasId) -> Arc<TypeAliasSignature> {
- self.type_alias_signature_with_source_map(e).0
- }
-
- #[salsa::invoke(TraitSignature::query)]
- fn trait_signature_with_source_map(
- &self,
- trait_: TraitId,
- ) -> (Arc<TraitSignature>, Arc<ExpressionStoreSourceMap>);
-
- #[salsa::invoke(ImplSignature::query)]
- fn impl_signature_with_source_map(
- &self,
- impl_: ImplId,
- ) -> (Arc<ImplSignature>, Arc<ExpressionStoreSourceMap>);
-
- #[salsa::invoke(StructSignature::query)]
- fn struct_signature_with_source_map(
- &self,
- struct_: StructId,
- ) -> (Arc<StructSignature>, Arc<ExpressionStoreSourceMap>);
-
- #[salsa::invoke(UnionSignature::query)]
- fn union_signature_with_source_map(
- &self,
- union_: UnionId,
- ) -> (Arc<UnionSignature>, Arc<ExpressionStoreSourceMap>);
-
- #[salsa::invoke(EnumSignature::query)]
- fn enum_signature_with_source_map(
- &self,
- e: EnumId,
- ) -> (Arc<EnumSignature>, Arc<ExpressionStoreSourceMap>);
-
- #[salsa::invoke(ConstSignature::query)]
- fn const_signature_with_source_map(
- &self,
- e: ConstId,
- ) -> (Arc<ConstSignature>, Arc<ExpressionStoreSourceMap>);
-
- #[salsa::invoke(StaticSignature::query)]
- fn static_signature_with_source_map(
- &self,
- e: StaticId,
- ) -> (Arc<StaticSignature>, Arc<ExpressionStoreSourceMap>);
-
- #[salsa::invoke(FunctionSignature::query)]
- fn function_signature_with_source_map(
- &self,
- e: FunctionId,
- ) -> (Arc<FunctionSignature>, Arc<ExpressionStoreSourceMap>);
-
- #[salsa::invoke(TypeAliasSignature::query)]
- fn type_alias_signature_with_source_map(
- &self,
- e: TypeAliasId,
- ) -> (Arc<TypeAliasSignature>, Arc<ExpressionStoreSourceMap>);
-
- // endregion:data
-
- #[salsa::invoke(Body::body_with_source_map_query)]
- #[salsa::lru(512)]
- fn body_with_source_map(&self, def: DefWithBodyId) -> (Arc<Body>, Arc<BodySourceMap>);
-
- #[salsa::invoke(Body::body_query)]
- fn body(&self, def: DefWithBodyId) -> Arc<Body>;
-
- #[salsa::invoke(ExprScopes::expr_scopes_query)]
- fn expr_scopes(&self, def: DefWithBodyId) -> Arc<ExprScopes>;
-
- #[salsa::transparent]
- #[salsa::invoke(GenericParams::new)]
- fn generic_params(&self, def: GenericDefId) -> Arc<GenericParams>;
-
- #[salsa::transparent]
- #[salsa::invoke(GenericParams::generic_params_and_store)]
- fn generic_params_and_store(
- &self,
- def: GenericDefId,
- ) -> (Arc<GenericParams>, Arc<ExpressionStore>);
-
- #[salsa::transparent]
- #[salsa::invoke(GenericParams::generic_params_and_store_and_source_map)]
- fn generic_params_and_store_and_source_map(
- &self,
- def: GenericDefId,
- ) -> (Arc<GenericParams>, Arc<ExpressionStore>, Arc<ExpressionStoreSourceMap>);
-
- #[salsa::invoke(ImportMap::import_map_query)]
- fn import_map(&self, krate: Crate) -> Arc<ImportMap>;
-
// region:visibilities
- #[salsa::invoke(visibility::field_visibilities_query)]
- fn field_visibilities(&self, var: VariantId) -> Arc<ArenaMap<LocalFieldId, Visibility>>;
-
#[salsa::invoke(visibility::assoc_visibility_query)]
fn assoc_visibility(&self, def: AssocItemId) -> Visibility;
diff --git a/crates/hir-def/src/expr_store.rs b/crates/hir-def/src/expr_store.rs
index 1ce4c881e7..ca523622ec 100644
--- a/crates/hir-def/src/expr_store.rs
+++ b/crates/hir-def/src/expr_store.rs
@@ -9,10 +9,7 @@ pub mod scope;
#[cfg(test)]
mod tests;
-use std::{
- ops::{Deref, Index},
- sync::LazyLock,
-};
+use std::ops::{Deref, Index};
use cfg::{CfgExpr, CfgOptions};
use either::Either;
@@ -23,11 +20,10 @@ use smallvec::SmallVec;
use span::{Edition, SyntaxContext};
use syntax::{AstPtr, SyntaxNodePtr, ast};
use thin_vec::ThinVec;
-use triomphe::Arc;
use tt::TextRange;
use crate::{
- BlockId, SyntheticSyntax,
+ AdtId, BlockId, ExpressionStoreOwnerId, GenericDefId, SyntheticSyntax,
db::DefDatabase,
expr_store::path::Path,
hir::{
@@ -35,6 +31,7 @@ use crate::{
PatId, RecordFieldPat, RecordSpread, Statement,
},
nameres::{DefMap, block_def_map},
+ signatures::VariantFields,
type_ref::{LifetimeRef, LifetimeRefId, PathId, TypeRef, TypeRefId},
};
@@ -94,9 +91,26 @@ pub type TypeSource = InFile<TypePtr>;
pub type LifetimePtr = AstPtr<ast::Lifetime>;
pub type LifetimeSource = InFile<LifetimePtr>;
+/// Describes where a const expression originated from.
+///
+/// Used by signature/body inference to determine the expected type for each
+/// const expression root.
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub enum RootExprOrigin {
+ /// Array length expression: `[T; <expr>]` — expected type is `usize`.
+ ArrayLength,
+ /// Const parameter default value: `const N: usize = <expr>`.
+ ConstParam(crate::hir::generics::LocalTypeOrConstParamId),
+ /// Const generic argument in a path: `SomeType::<{ <expr> }>` or `some_fn::<{ <expr> }>()`.
+ /// Determining the expected type requires path resolution, so it is deferred.
+ GenericArgsPath,
+ /// The root expression of a body.
+ BodyRoot,
+}
+
// We split the store into types-only and expressions, because most stores (e.g. generics)
// don't store any expressions and this saves memory. Same thing for the source map.
-#[derive(Debug, PartialEq, Eq)]
+#[derive(Debug, Clone, PartialEq, Eq)]
struct ExpressionOnlyStore {
exprs: Arena<Expr>,
pats: Arena<Pat>,
@@ -113,9 +127,12 @@ struct ExpressionOnlyStore {
/// Expressions (and destructuing patterns) that can be recorded here are single segment path, although not all single segments path refer
/// to variables and have hygiene (some refer to items, we don't know at this stage).
ident_hygiene: FxHashMap<ExprOrPatId, HygieneId>,
+
+ /// Maps expression roots to their origin.
+ expr_roots: SmallVec<[(ExprId, RootExprOrigin); 1]>,
}
-#[derive(Debug, PartialEq, Eq)]
+#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ExpressionStore {
expr_only: Option<Box<ExpressionOnlyStore>>,
pub types: Arena<TypeRef>,
@@ -226,6 +243,7 @@ pub struct ExpressionStoreBuilder {
pub types: Arena<TypeRef>,
block_scopes: Vec<BlockId>,
ident_hygiene: FxHashMap<ExprOrPatId, HygieneId>,
+ pub inference_roots: Option<SmallVec<[(ExprId, RootExprOrigin); 1]>>,
// 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).
@@ -297,6 +315,7 @@ impl ExpressionStoreBuilder {
mut bindings,
mut binding_owners,
mut ident_hygiene,
+ inference_roots: mut expr_roots,
mut types,
mut lifetimes,
@@ -356,6 +375,9 @@ impl ExpressionStoreBuilder {
let store = {
let expr_only = if has_exprs {
+ if let Some(const_expr_origins) = &mut expr_roots {
+ const_expr_origins.shrink_to_fit();
+ }
Some(Box::new(ExpressionOnlyStore {
exprs,
pats,
@@ -364,6 +386,7 @@ impl ExpressionStoreBuilder {
binding_owners,
block_scopes: block_scopes.into_boxed_slice(),
ident_hygiene,
+ expr_roots: expr_roots.unwrap_or_default(),
}))
} else {
None
@@ -404,13 +427,108 @@ impl ExpressionStoreBuilder {
}
impl ExpressionStore {
- pub fn empty_singleton() -> (Arc<ExpressionStore>, Arc<ExpressionStoreSourceMap>) {
- static EMPTY: LazyLock<(Arc<ExpressionStore>, Arc<ExpressionStoreSourceMap>)> =
- LazyLock::new(|| {
- let (store, source_map) = ExpressionStoreBuilder::default().finish();
- (Arc::new(store), Arc::new(source_map))
- });
- EMPTY.clone()
+ pub fn of(db: &dyn DefDatabase, def: ExpressionStoreOwnerId) -> &ExpressionStore {
+ match def {
+ ExpressionStoreOwnerId::Signature(def) => {
+ use crate::signatures::{
+ ConstSignature, EnumSignature, FunctionSignature, ImplSignature,
+ StaticSignature, StructSignature, TraitSignature, TypeAliasSignature,
+ UnionSignature,
+ };
+ match def {
+ GenericDefId::AdtId(AdtId::EnumId(id)) => &EnumSignature::of(db, id).store,
+ GenericDefId::AdtId(AdtId::StructId(id)) => &StructSignature::of(db, id).store,
+ GenericDefId::AdtId(AdtId::UnionId(id)) => &UnionSignature::of(db, id).store,
+ GenericDefId::ConstId(id) => &ConstSignature::of(db, id).store,
+ GenericDefId::FunctionId(id) => &FunctionSignature::of(db, id).store,
+ GenericDefId::ImplId(id) => &ImplSignature::of(db, id).store,
+ GenericDefId::StaticId(id) => &StaticSignature::of(db, id).store,
+ GenericDefId::TraitId(id) => &TraitSignature::of(db, id).store,
+ GenericDefId::TypeAliasId(id) => &TypeAliasSignature::of(db, id).store,
+ }
+ }
+ ExpressionStoreOwnerId::Body(body) => &Body::of(db, body).store,
+ ExpressionStoreOwnerId::VariantFields(variant_id) => {
+ &VariantFields::of(db, variant_id).store
+ }
+ }
+ }
+
+ pub fn with_source_map(
+ db: &dyn DefDatabase,
+ def: ExpressionStoreOwnerId,
+ ) -> (&ExpressionStore, &ExpressionStoreSourceMap) {
+ match def {
+ ExpressionStoreOwnerId::Signature(def) => {
+ use crate::signatures::{
+ ConstSignature, EnumSignature, FunctionSignature, ImplSignature,
+ StaticSignature, StructSignature, TraitSignature, TypeAliasSignature,
+ UnionSignature,
+ };
+ match def {
+ GenericDefId::AdtId(AdtId::EnumId(id)) => {
+ let sig = EnumSignature::with_source_map(db, id);
+ (&sig.0.store, &sig.1)
+ }
+ GenericDefId::AdtId(AdtId::StructId(id)) => {
+ let sig = StructSignature::with_source_map(db, id);
+ (&sig.0.store, &sig.1)
+ }
+ GenericDefId::AdtId(AdtId::UnionId(id)) => {
+ let sig = UnionSignature::with_source_map(db, id);
+ (&sig.0.store, &sig.1)
+ }
+ GenericDefId::ConstId(id) => {
+ let sig = ConstSignature::with_source_map(db, id);
+ (&sig.0.store, &sig.1)
+ }
+ GenericDefId::FunctionId(id) => {
+ let sig = FunctionSignature::with_source_map(db, id);
+ (&sig.0.store, &sig.1)
+ }
+ GenericDefId::ImplId(id) => {
+ let sig = ImplSignature::with_source_map(db, id);
+ (&sig.0.store, &sig.1)
+ }
+ GenericDefId::StaticId(id) => {
+ let sig = StaticSignature::with_source_map(db, id);
+ (&sig.0.store, &sig.1)
+ }
+ GenericDefId::TraitId(id) => {
+ let sig = TraitSignature::with_source_map(db, id);
+ (&sig.0.store, &sig.1)
+ }
+ GenericDefId::TypeAliasId(id) => {
+ let sig = TypeAliasSignature::with_source_map(db, id);
+ (&sig.0.store, &sig.1)
+ }
+ }
+ }
+ ExpressionStoreOwnerId::Body(body) => {
+ let (store, sm) = Body::with_source_map(db, body);
+ (&store.store, &sm.store)
+ }
+ ExpressionStoreOwnerId::VariantFields(variant_id) => {
+ let (store, sm) = VariantFields::with_source_map(db, variant_id);
+ (&store.store, sm)
+ }
+ }
+ }
+
+ /// Returns all expression root `ExprId`s found in this store.
+ pub fn expr_roots(&self) -> impl Iterator<Item = ExprId> {
+ self.const_expr_origins().iter().map(|&(id, _)| id)
+ }
+
+ /// Like [`Self::signature_const_expr_roots`], but also returns the origin
+ /// of each expression.
+ pub fn expr_roots_with_origins(&self) -> impl Iterator<Item = (ExprId, RootExprOrigin)> {
+ self.const_expr_origins().iter().map(|&(id, origin)| (id, origin))
+ }
+
+ /// Returns the map of const expression roots to their origins.
+ pub fn const_expr_origins(&self) -> &[(ExprId, RootExprOrigin)] {
+ self.expr_only.as_ref().map_or(&[], |it| &it.expr_roots)
}
/// Returns an iterator over all block expressions in this store that define inner items.
diff --git a/crates/hir-def/src/expr_store/body.rs b/crates/hir-def/src/expr_store/body.rs
index c955393b9c..0c8320369f 100644
--- a/crates/hir-def/src/expr_store/body.rs
+++ b/crates/hir-def/src/expr_store/body.rs
@@ -29,8 +29,6 @@ pub struct Body {
/// empty.
pub params: Box<[PatId]>,
pub self_param: Option<BindingId>,
- /// The `ExprId` of the actual body expression.
- pub body_expr: ExprId,
}
impl ops::Deref for Body {
@@ -68,11 +66,10 @@ impl ops::Deref for BodySourceMap {
}
}
+#[salsa::tracked]
impl Body {
- pub(crate) fn body_with_source_map_query(
- db: &dyn DefDatabase,
- def: DefWithBodyId,
- ) -> (Arc<Body>, Arc<BodySourceMap>) {
+ #[salsa::tracked(lru = 512, returns(ref))]
+ pub fn with_source_map(db: &dyn DefDatabase, def: DefWithBodyId) -> (Arc<Body>, BodySourceMap) {
let _p = tracing::info_span!("body_with_source_map_query").entered();
let mut params = None;
@@ -99,18 +96,25 @@ impl Body {
DefWithBodyId::VariantId(v) => {
let s = v.lookup(db);
let src = s.source(db);
- src.map(|it| it.expr())
+ src.map(|it| it.const_arg()?.expr())
}
}
};
let module = def.module(db);
let (body, source_map) = lower_body(db, def, file_id, module, params, body, is_async_fn);
- (Arc::new(body), Arc::new(source_map))
+ (Arc::new(body), source_map)
}
- pub(crate) fn body_query(db: &dyn DefDatabase, def: DefWithBodyId) -> Arc<Body> {
- db.body_with_source_map(def).0
+ #[salsa::tracked(returns(deref))]
+ pub fn of(db: &dyn DefDatabase, def: DefWithBodyId) -> Arc<Body> {
+ Self::with_source_map(db, def).0.clone()
+ }
+}
+
+impl Body {
+ pub fn root_expr(&self) -> ExprId {
+ self.store.expr_roots().next().unwrap()
}
pub fn pretty_print(
diff --git a/crates/hir-def/src/expr_store/expander.rs b/crates/hir-def/src/expr_store/expander.rs
index d34ec9bbc1..2fffa02c13 100644
--- a/crates/hir-def/src/expr_store/expander.rs
+++ b/crates/hir-def/src/expr_store/expander.rs
@@ -14,7 +14,6 @@ use hir_expand::{
use span::{AstIdMap, SyntaxContext};
use syntax::ast::HasAttrs;
use syntax::{AstNode, Parse, ast};
-use triomphe::Arc;
use tt::TextRange;
use crate::{
@@ -23,21 +22,21 @@ use crate::{
};
#[derive(Debug)]
-pub(super) struct Expander {
+pub(super) struct Expander<'db> {
span_map: SpanMap,
current_file_id: HirFileId,
- ast_id_map: Arc<AstIdMap>,
+ ast_id_map: &'db AstIdMap,
/// `recursion_depth == usize::MAX` indicates that the recursion limit has been reached.
recursion_depth: u32,
recursion_limit: usize,
}
-impl Expander {
+impl<'db> Expander<'db> {
pub(super) fn new(
- db: &dyn DefDatabase,
+ db: &'db dyn DefDatabase,
current_file_id: HirFileId,
- def_map: &DefMap,
- ) -> Expander {
+ def_map: &'db DefMap,
+ ) -> Expander<'db> {
let recursion_limit = def_map.recursion_limit() as usize;
let recursion_limit = if cfg!(test) {
// Without this, `body::tests::your_stack_belongs_to_me` stack-overflows in debug
@@ -77,12 +76,12 @@ impl Expander {
pub(super) fn enter_expand<T: ast::AstNode>(
&mut self,
- db: &dyn DefDatabase,
+ db: &'db dyn DefDatabase,
macro_call: ast::MacroCall,
krate: Crate,
resolver: impl Fn(&ModPath) -> Option<MacroId>,
eager_callback: EagerCallBackFn<'_>,
- ) -> Result<ExpandResult<Option<(Mark, Option<Parse<T>>)>>, UnresolvedMacro> {
+ ) -> Result<ExpandResult<Option<(Mark<'db>, Option<Parse<T>>)>>, UnresolvedMacro> {
// FIXME: within_limit should support this, instead of us having to extract the error
let mut unresolved_macro_err = None;
@@ -130,13 +129,13 @@ impl Expander {
pub(super) fn enter_expand_id<T: ast::AstNode>(
&mut self,
- db: &dyn DefDatabase,
+ db: &'db dyn DefDatabase,
call_id: MacroCallId,
- ) -> ExpandResult<Option<(Mark, Option<Parse<T>>)>> {
+ ) -> ExpandResult<Option<(Mark<'db>, Option<Parse<T>>)>> {
self.within_limit(db, |_this| ExpandResult::ok(Some(call_id)))
}
- pub(super) fn exit(&mut self, Mark { file_id, span_map, ast_id_map, mut bomb }: Mark) {
+ pub(super) fn exit(&mut self, Mark { file_id, span_map, ast_id_map, mut bomb }: Mark<'db>) {
self.span_map = span_map;
self.current_file_id = file_id;
self.ast_id_map = ast_id_map;
@@ -162,9 +161,9 @@ impl Expander {
fn within_limit<F, T: ast::AstNode>(
&mut self,
- db: &dyn DefDatabase,
+ db: &'db dyn DefDatabase,
op: F,
- ) -> ExpandResult<Option<(Mark, Option<Parse<T>>)>>
+ ) -> ExpandResult<Option<(Mark<'db>, Option<Parse<T>>)>>
where
F: FnOnce(&mut Self) -> ExpandResult<Option<MacroCallId>>,
{
@@ -219,7 +218,7 @@ impl Expander {
#[inline]
pub(super) fn ast_id_map(&self) -> &AstIdMap {
- &self.ast_id_map
+ self.ast_id_map
}
#[inline]
@@ -229,9 +228,9 @@ impl Expander {
}
#[derive(Debug)]
-pub(super) struct Mark {
+pub(super) struct Mark<'db> {
file_id: HirFileId,
span_map: SpanMap,
- ast_id_map: Arc<AstIdMap>,
+ ast_id_map: &'db AstIdMap,
bomb: DropBomb,
}
diff --git a/crates/hir-def/src/expr_store/lower.rs b/crates/hir-def/src/expr_store/lower.rs
index 1cecd1976b..74006c6037 100644
--- a/crates/hir-def/src/expr_store/lower.rs
+++ b/crates/hir-def/src/expr_store/lower.rs
@@ -18,6 +18,7 @@ use hir_expand::{
};
use intern::{Symbol, sym};
use rustc_hash::FxHashMap;
+use smallvec::smallvec;
use stdx::never;
use syntax::{
AstNode, AstPtr, SyntaxNodePtr,
@@ -28,7 +29,6 @@ use syntax::{
},
};
use thin_vec::ThinVec;
-use triomphe::Arc;
use tt::TextRange;
use crate::{
@@ -39,7 +39,7 @@ use crate::{
expr_store::{
Body, BodySourceMap, ExprPtr, ExpressionStore, ExpressionStoreBuilder,
ExpressionStoreDiagnostics, ExpressionStoreSourceMap, HygieneId, LabelPtr, LifetimePtr,
- PatPtr, TypePtr,
+ PatPtr, RootExprOrigin, TypePtr,
expander::Expander,
lower::generics::ImplTraitLowerFn,
path::{AssociatedTypeBinding, GenericArg, GenericArgs, GenericArgsParentheses, Path},
@@ -53,6 +53,7 @@ use crate::{
item_tree::FieldsShape,
lang_item::{LangItemTarget, LangItems},
nameres::{DefMap, LocalDefMap, MacroSubNs, block_def_map},
+ signatures::StructSignature,
type_ref::{
ArrayType, ConstRef, FnType, LifetimeRef, LifetimeRefId, Mutability, PathId, Rawness,
RefType, TraitBoundModifier, TraitRef, TypeBound, TypeRef, TypeRefId, UseArgRef,
@@ -79,7 +80,7 @@ pub(super) fn lower_body(
let mut self_param = None;
let mut source_map_self_param = None;
let mut params = vec![];
- let mut collector = ExprCollector::new(db, module, current_file_id);
+ let mut collector = ExprCollector::body(db, module, current_file_id);
let skip_body = AttrFlags::query(
db,
@@ -117,9 +118,10 @@ pub(super) fn lower_body(
params = (0..count).map(|_| collector.missing_pat()).collect();
};
let body_expr = collector.missing_expr();
+ collector.store.inference_roots = Some(smallvec![(body_expr, RootExprOrigin::BodyRoot)]);
let (store, source_map) = collector.store.finish();
return (
- Body { store, params: params.into_boxed_slice(), self_param, body_expr },
+ Body { store, params: params.into_boxed_slice(), self_param },
BodySourceMap { self_param: source_map_self_param, store: source_map },
);
}
@@ -173,10 +175,11 @@ pub(super) fn lower_body(
}
},
);
+ collector.store.inference_roots = Some(smallvec![(body_expr, RootExprOrigin::BodyRoot)]);
let (store, source_map) = collector.store.finish();
(
- Body { store, params: params.into_boxed_slice(), self_param, body_expr },
+ Body { store, params: params.into_boxed_slice(), self_param },
BodySourceMap { self_param: source_map_self_param, store: source_map },
)
}
@@ -186,7 +189,7 @@ pub(crate) fn lower_type_ref(
module: ModuleId,
type_ref: InFile<Option<ast::Type>>,
) -> (ExpressionStore, ExpressionStoreSourceMap, TypeRefId) {
- let mut expr_collector = ExprCollector::new(db, module, type_ref.file_id);
+ let mut expr_collector = ExprCollector::signature(db, module, type_ref.file_id);
let type_ref =
expr_collector.lower_type_ref_opt(type_ref.value, &mut ExprCollector::impl_trait_allocator);
let (store, source_map) = expr_collector.store.finish();
@@ -200,13 +203,13 @@ pub(crate) fn lower_generic_params(
file_id: HirFileId,
param_list: Option<ast::GenericParamList>,
where_clause: Option<ast::WhereClause>,
-) -> (Arc<ExpressionStore>, Arc<GenericParams>, ExpressionStoreSourceMap) {
- let mut expr_collector = ExprCollector::new(db, module, file_id);
+) -> (ExpressionStore, GenericParams, ExpressionStoreSourceMap) {
+ let mut expr_collector = ExprCollector::signature(db, module, file_id);
let mut collector = generics::GenericParamsCollector::new(def);
collector.lower(&mut expr_collector, param_list, where_clause);
let params = collector.finish();
let (store, source_map) = expr_collector.store.finish();
- (Arc::new(store), params, source_map)
+ (store, params, source_map)
}
pub(crate) fn lower_impl(
@@ -214,8 +217,8 @@ pub(crate) fn lower_impl(
module: ModuleId,
impl_syntax: InFile<ast::Impl>,
impl_id: ImplId,
-) -> (ExpressionStore, ExpressionStoreSourceMap, TypeRefId, Option<TraitRef>, Arc<GenericParams>) {
- let mut expr_collector = ExprCollector::new(db, module, impl_syntax.file_id);
+) -> (ExpressionStore, ExpressionStoreSourceMap, TypeRefId, Option<TraitRef>, GenericParams) {
+ let mut expr_collector = ExprCollector::signature(db, module, impl_syntax.file_id);
let self_ty =
expr_collector.lower_type_ref_opt_disallow_impl_trait(impl_syntax.value.self_ty());
let trait_ = impl_syntax.value.trait_().and_then(|it| match &it {
@@ -242,8 +245,8 @@ pub(crate) fn lower_trait(
module: ModuleId,
trait_syntax: InFile<ast::Trait>,
trait_id: TraitId,
-) -> (ExpressionStore, ExpressionStoreSourceMap, Arc<GenericParams>) {
- let mut expr_collector = ExprCollector::new(db, module, trait_syntax.file_id);
+) -> (ExpressionStore, ExpressionStoreSourceMap, GenericParams) {
+ let mut expr_collector = ExprCollector::signature(db, module, trait_syntax.file_id);
let mut collector = generics::GenericParamsCollector::with_self_param(
&mut expr_collector,
trait_id.into(),
@@ -264,14 +267,9 @@ pub(crate) fn lower_type_alias(
module: ModuleId,
alias: InFile<ast::TypeAlias>,
type_alias_id: TypeAliasId,
-) -> (
- ExpressionStore,
- ExpressionStoreSourceMap,
- Arc<GenericParams>,
- Box<[TypeBound]>,
- Option<TypeRefId>,
-) {
- let mut expr_collector = ExprCollector::new(db, module, alias.file_id);
+) -> (ExpressionStore, ExpressionStoreSourceMap, GenericParams, Box<[TypeBound]>, Option<TypeRefId>)
+{
+ let mut expr_collector = ExprCollector::signature(db, module, alias.file_id);
let bounds = alias
.value
.type_bound_list()
@@ -307,13 +305,13 @@ pub(crate) fn lower_function(
) -> (
ExpressionStore,
ExpressionStoreSourceMap,
- Arc<GenericParams>,
+ GenericParams,
Box<[TypeRefId]>,
Option<TypeRefId>,
bool,
bool,
) {
- let mut expr_collector = ExprCollector::new(db, module, fn_.file_id);
+ let mut expr_collector = ExprCollector::signature(db, module, fn_.file_id);
let mut collector = generics::GenericParamsCollector::new(function_id.into());
collector.lower(&mut expr_collector, fn_.value.generic_param_list(), fn_.value.where_clause());
let mut params = vec![];
@@ -419,7 +417,7 @@ pub(crate) fn lower_function(
pub struct ExprCollector<'db> {
db: &'db dyn DefDatabase,
cfg_options: &'db CfgOptions,
- expander: Expander,
+ expander: Expander<'db>,
def_map: &'db DefMap,
local_def_map: &'db LocalDefMap,
module: ModuleId,
@@ -532,7 +530,20 @@ impl BindingList {
}
impl<'db> ExprCollector<'db> {
- pub fn new(
+ /// Creates a collector for a signature store, this will populate `const_expr_origins` to any
+ /// top level const arg roots.
+ pub fn signature(
+ db: &dyn DefDatabase,
+ module: ModuleId,
+ current_file_id: HirFileId,
+ ) -> ExprCollector<'_> {
+ let mut this = Self::body(db, module, current_file_id);
+ this.store.inference_roots = Some(Default::default());
+ this
+ }
+
+ /// Creates a collector for a bidy store.
+ pub fn body(
db: &dyn DefDatabase,
module: ModuleId,
current_file_id: HirFileId,
@@ -577,7 +588,10 @@ impl<'db> ExprCollector<'db> {
self.expander.span_map()
}
- pub fn lower_lifetime_ref(&mut self, lifetime: ast::Lifetime) -> LifetimeRefId {
+ pub(in crate::expr_store) fn lower_lifetime_ref(
+ &mut self,
+ lifetime: ast::Lifetime,
+ ) -> LifetimeRefId {
// FIXME: Keyword check?
let lifetime_ref = match &*lifetime.text() {
"" | "'" => LifetimeRef::Error,
@@ -588,7 +602,10 @@ impl<'db> ExprCollector<'db> {
self.alloc_lifetime_ref(lifetime_ref, AstPtr::new(&lifetime))
}
- pub fn lower_lifetime_ref_opt(&mut self, lifetime: Option<ast::Lifetime>) -> LifetimeRefId {
+ pub(in crate::expr_store) fn lower_lifetime_ref_opt(
+ &mut self,
+ lifetime: Option<ast::Lifetime>,
+ ) -> LifetimeRefId {
match lifetime {
Some(lifetime) => self.lower_lifetime_ref(lifetime),
None => self.alloc_lifetime_ref_desugared(LifetimeRef::Placeholder),
@@ -596,7 +613,7 @@ impl<'db> ExprCollector<'db> {
}
/// Converts an `ast::TypeRef` to a `hir::TypeRef`.
- pub fn lower_type_ref(
+ pub(in crate::expr_store) fn lower_type_ref(
&mut self,
node: ast::Type,
impl_trait_lower_fn: ImplTraitLowerFn<'_>,
@@ -621,6 +638,9 @@ impl<'db> ExprCollector<'db> {
}
ast::Type::ArrayType(inner) => {
let len = self.lower_const_arg_opt(inner.const_arg());
+ if let Some(const_expr_origins) = &mut self.store.inference_roots {
+ const_expr_origins.push((len.expr, RootExprOrigin::ArrayLength));
+ }
TypeRef::Array(ArrayType {
ty: self.lower_type_ref_opt(inner.ty(), impl_trait_lower_fn),
len,
@@ -810,7 +830,7 @@ impl<'db> ExprCollector<'db> {
/// Collect `GenericArgs` from the parts of a fn-like path, i.e. `Fn(X, Y)
/// -> Z` (which desugars to `Fn<(X, Y), Output=Z>`).
- pub fn lower_generic_args_from_fn_path(
+ pub(in crate::expr_store) fn lower_generic_args_from_fn_path(
&mut self,
args: Option<ast::ParenthesizedArgList>,
ret_type: Option<ast::RetType>,
@@ -905,6 +925,9 @@ impl<'db> ExprCollector<'db> {
}
ast::GenericArg::ConstArg(arg) => {
let arg = self.lower_const_arg(arg);
+ if let Some(const_expr_origins) = &mut self.store.inference_roots {
+ const_expr_origins.push((arg.expr, RootExprOrigin::GenericArgsPath));
+ }
args.push(GenericArg::Const(arg))
}
}
@@ -1045,17 +1068,30 @@ impl<'db> ExprCollector<'db> {
}
fn lower_const_arg_opt(&mut self, arg: Option<ast::ConstArg>) -> ConstRef {
- ConstRef { expr: self.collect_expr_opt(arg.and_then(|it| it.expr())) }
+ let const_expr_origins = self.store.inference_roots.take();
+ let r = ConstRef { expr: self.collect_expr_opt(arg.and_then(|it| it.expr())) };
+ self.store.inference_roots = const_expr_origins;
+ r
}
- fn lower_const_arg(&mut self, arg: ast::ConstArg) -> ConstRef {
- ConstRef { expr: self.collect_expr_opt(arg.expr()) }
+ pub fn lower_const_arg(&mut self, arg: ast::ConstArg) -> ConstRef {
+ let const_expr_origins = self.store.inference_roots.take();
+ let r = ConstRef { expr: self.collect_expr_opt(arg.expr()) };
+ self.store.inference_roots = const_expr_origins;
+ r
}
fn collect_expr(&mut self, expr: ast::Expr) -> ExprId {
self.maybe_collect_expr(expr).unwrap_or_else(|| self.missing_expr())
}
+ pub(in crate::expr_store) fn collect_expr_opt(&mut self, expr: Option<ast::Expr>) -> ExprId {
+ match expr {
+ Some(expr) => self.collect_expr(expr),
+ None => self.missing_expr(),
+ }
+ }
+
/// Returns `None` if and only if the expression is `#[cfg]`d out.
fn maybe_collect_expr(&mut self, expr: ast::Expr) -> Option<ExprId> {
let syntax_ptr = AstPtr::new(&expr);
@@ -2065,13 +2101,6 @@ impl<'db> ExprCollector<'db> {
}
}
- pub fn collect_expr_opt(&mut self, expr: Option<ast::Expr>) -> ExprId {
- match expr {
- Some(expr) => self.collect_expr(expr),
- None => self.missing_expr(),
- }
- }
-
fn collect_macro_as_stmt(
&mut self,
statements: &mut Vec<Statement>,
@@ -2332,7 +2361,7 @@ impl<'db> ExprCollector<'db> {
}
Some(ModuleDefId::AdtId(AdtId::StructId(s)))
// FIXME: This can cause a cycle if the user is writing invalid code
- if self.db.struct_signature(s).shape != FieldsShape::Record =>
+ if StructSignature::of(self.db, s).shape != FieldsShape::Record =>
{
(None, Pat::Path(name.into()))
}
diff --git a/crates/hir-def/src/expr_store/lower/generics.rs b/crates/hir-def/src/expr_store/lower/generics.rs
index c570df42b2..5ffc4f5851 100644
--- a/crates/hir-def/src/expr_store/lower/generics.rs
+++ b/crates/hir-def/src/expr_store/lower/generics.rs
@@ -3,15 +3,12 @@
//! generic parameters. See also the `Generics` type and the `generics_of` query
//! in rustc.
-use std::sync::LazyLock;
-
use either::Either;
use hir_expand::name::{AsName, Name};
use intern::sym;
use la_arena::Arena;
use syntax::ast::{self, HasName, HasTypeBounds};
use thin_vec::ThinVec;
-use triomphe::Arc;
use crate::{
GenericDefId, TypeOrConstParamId, TypeParamId,
@@ -84,28 +81,16 @@ impl GenericParamsCollector {
)
}
- pub(crate) fn finish(self) -> Arc<GenericParams> {
- let Self { mut lifetimes, mut type_or_consts, mut where_predicates, parent: _ } = self;
-
- if lifetimes.is_empty() && type_or_consts.is_empty() && where_predicates.is_empty() {
- static EMPTY: LazyLock<Arc<GenericParams>> = LazyLock::new(|| {
- Arc::new(GenericParams {
- lifetimes: Arena::new(),
- type_or_consts: Arena::new(),
- where_predicates: Box::default(),
- })
- });
- return Arc::clone(&EMPTY);
- }
+ pub(crate) fn finish(self) -> GenericParams {
+ let Self { mut lifetimes, mut type_or_consts, where_predicates, parent: _ } = self;
lifetimes.shrink_to_fit();
type_or_consts.shrink_to_fit();
- where_predicates.shrink_to_fit();
- Arc::new(GenericParams {
+ GenericParams {
type_or_consts,
lifetimes,
where_predicates: where_predicates.into_boxed_slice(),
- })
+ }
}
fn lower_param_list(&mut self, ec: &mut ExprCollector<'_>, params: ast::GenericParamList) {
@@ -141,12 +126,17 @@ impl GenericParamsCollector {
const_param.ty(),
&mut ExprCollector::impl_trait_error_allocator,
);
- let param = ConstParamData {
- name,
- ty,
- default: const_param.default_val().map(|it| ec.lower_const_arg(it)),
- };
- let _idx = self.type_or_consts.alloc(param.into());
+ let default = const_param.default_val().map(|it| ec.lower_const_arg(it));
+ let param = ConstParamData { name, ty, default };
+ let idx = self.type_or_consts.alloc(param.into());
+ if let Some(default) = default
+ && let Some(const_expr_origins) = &mut ec.store.inference_roots
+ {
+ const_expr_origins.push((
+ default.expr,
+ crate::expr_store::RootExprOrigin::ConstParam(idx),
+ ));
+ }
}
ast::GenericParam::LifetimeParam(lifetime_param) => {
let lifetime = ec.lower_lifetime_ref_opt(lifetime_param.lifetime());
diff --git a/crates/hir-def/src/expr_store/lower/path/tests.rs b/crates/hir-def/src/expr_store/lower/path/tests.rs
index f507841a91..6819eb3deb 100644
--- a/crates/hir-def/src/expr_store/lower/path/tests.rs
+++ b/crates/hir-def/src/expr_store/lower/path/tests.rs
@@ -21,7 +21,7 @@ fn lower_path(path: ast::Path) -> (TestDB, ExpressionStore, Option<Path>) {
let (db, file_id) = TestDB::with_single_file("");
let krate = db.fetch_test_crate();
let mut ctx =
- ExprCollector::new(&db, crate_def_map(&db, krate).root_module_id(), file_id.into());
+ ExprCollector::signature(&db, crate_def_map(&db, krate).root_module_id(), file_id.into());
let lowered_path = ctx.lower_path(path, &mut ExprCollector::impl_trait_allocator);
let (store, _) = ctx.store.finish();
(db, store, lowered_path)
diff --git a/crates/hir-def/src/expr_store/pretty.rs b/crates/hir-def/src/expr_store/pretty.rs
index 35f3cd114e..9c9c4db3b2 100644
--- a/crates/hir-def/src/expr_store/pretty.rs
+++ b/crates/hir-def/src/expr_store/pretty.rs
@@ -105,7 +105,7 @@ pub fn print_body_hir(
p.buf.push(')');
p.buf.push(' ');
}
- p.print_expr(body.body_expr);
+ p.print_expr(body.root_expr());
if matches!(owner, DefWithBodyId::StaticId(_) | DefWithBodyId::ConstId(_)) {
p.buf.push(';');
}
@@ -168,8 +168,8 @@ pub fn print_signature(db: &dyn DefDatabase, owner: GenericDefId, edition: Editi
match owner {
GenericDefId::AdtId(id) => match id {
AdtId::StructId(id) => {
- let signature = db.struct_signature(id);
- print_struct(db, id, &signature, edition)
+ let signature = StructSignature::of(db, id);
+ print_struct(db, id, signature, edition)
}
AdtId::UnionId(id) => {
format!("unimplemented {id:?}")
@@ -180,8 +180,8 @@ pub fn print_signature(db: &dyn DefDatabase, owner: GenericDefId, edition: Editi
},
GenericDefId::ConstId(id) => format!("unimplemented {id:?}"),
GenericDefId::FunctionId(id) => {
- let signature = db.function_signature(id);
- print_function(db, id, &signature, edition)
+ let signature = FunctionSignature::of(db, id);
+ print_function(db, id, signature, edition)
}
GenericDefId::ImplId(id) => format!("unimplemented {id:?}"),
GenericDefId::StaticId(id) => format!("unimplemented {id:?}"),
@@ -1212,7 +1212,7 @@ impl Printer<'_> {
}
pub(crate) fn print_type_param(&mut self, param: TypeParamId) {
- let generic_params = self.db.generic_params(param.parent());
+ let generic_params = GenericParams::of(self.db, param.parent());
match generic_params[param.local_id()].name() {
Some(name) => w!(self, "{}", name.display(self.db, self.edition)),
@@ -1221,7 +1221,7 @@ impl Printer<'_> {
}
pub(crate) fn print_lifetime_param(&mut self, param: LifetimeParamId) {
- let generic_params = self.db.generic_params(param.parent);
+ let generic_params = GenericParams::of(self.db, param.parent);
w!(self, "{}", generic_params[param.local_id].name.display(self.db, self.edition))
}
diff --git a/crates/hir-def/src/expr_store/scope.rs b/crates/hir-def/src/expr_store/scope.rs
index 1952dae9d7..40ae0b7de4 100644
--- a/crates/hir-def/src/expr_store/scope.rs
+++ b/crates/hir-def/src/expr_store/scope.rs
@@ -1,13 +1,16 @@
//! Name resolution for expressions.
use hir_expand::{MacroDefId, name::Name};
use la_arena::{Arena, ArenaMap, Idx, IdxRange, RawIdx};
-use triomphe::Arc;
use crate::{
- BlockId, DefWithBodyId,
+ BlockId, DefWithBodyId, ExpressionStoreOwnerId, GenericDefId, VariantId,
db::DefDatabase,
expr_store::{Body, ExpressionStore, HygieneId},
- hir::{Binding, BindingId, Expr, ExprId, Item, LabelId, Pat, PatId, Statement},
+ hir::{
+ Binding, BindingId, Expr, ExprId, Item, LabelId, Pat, PatId, Statement,
+ generics::GenericParams,
+ },
+ signatures::VariantFields,
};
pub type ScopeId = Idx<ScopeData>;
@@ -50,12 +53,45 @@ pub struct ScopeData {
entries: IdxRange<ScopeEntry>,
}
+#[salsa::tracked]
impl ExprScopes {
- pub(crate) fn expr_scopes_query(db: &dyn DefDatabase, def: DefWithBodyId) -> Arc<ExprScopes> {
- let body = db.body(def);
- let mut scopes = ExprScopes::new_body(&body);
+ #[salsa::tracked(returns(ref))]
+ pub fn body_expr_scopes(db: &dyn DefDatabase, def: DefWithBodyId) -> ExprScopes {
+ let body = Body::of(db, def);
+ let mut scopes = ExprScopes::new_body(body);
scopes.shrink_to_fit();
- Arc::new(scopes)
+ scopes
+ }
+
+ #[salsa::tracked(returns(ref))]
+ pub fn sig_expr_scopes(db: &dyn DefDatabase, def: GenericDefId) -> ExprScopes {
+ let (_, store) = GenericParams::with_store(db, def);
+ let roots = store.expr_roots();
+ let mut scopes = ExprScopes::new_store(store, roots);
+ scopes.shrink_to_fit();
+ scopes
+ }
+
+ #[salsa::tracked(returns(ref))]
+ pub fn variant_scopes(db: &dyn DefDatabase, def: VariantId) -> ExprScopes {
+ let fields = VariantFields::of(db, def);
+ let roots = fields.store.expr_roots();
+ let mut scopes = ExprScopes::new_store(&fields.store, roots);
+ scopes.shrink_to_fit();
+ scopes
+ }
+}
+
+impl ExprScopes {
+ #[inline]
+ pub fn of(db: &dyn DefDatabase, def: impl Into<ExpressionStoreOwnerId>) -> &ExprScopes {
+ match def.into() {
+ ExpressionStoreOwnerId::Body(def) => Self::body_expr_scopes(db, def),
+ ExpressionStoreOwnerId::Signature(def) => Self::sig_expr_scopes(db, def),
+ ExpressionStoreOwnerId::VariantFields(variant_id) => {
+ Self::variant_scopes(db, variant_id)
+ }
+ }
}
pub fn entries(&self, scope: ScopeId) -> &[ScopeEntry] {
@@ -115,7 +151,23 @@ impl ExprScopes {
scopes.add_bindings(body, root, self_param, body.binding_hygiene(self_param));
}
scopes.add_params_bindings(body, root, &body.params);
- compute_expr_scopes(body.body_expr, body, &mut scopes, &mut root);
+ compute_expr_scopes(body.root_expr(), body, &mut scopes, &mut root);
+ scopes
+ }
+
+ fn new_store(store: &ExpressionStore, roots: impl IntoIterator<Item = ExprId>) -> ExprScopes {
+ let mut scopes = ExprScopes {
+ scopes: Arena::default(),
+ scope_entries: Arena::default(),
+ scope_by_expr: ArenaMap::with_capacity(
+ store.expr_only.as_ref().map_or(0, |it| it.exprs.len()),
+ ),
+ };
+ let root = scopes.root_scope();
+ for root_expr in roots {
+ let mut scope = scopes.new_scope(root);
+ compute_expr_scopes(root_expr, store, &mut scopes, &mut scope);
+ }
scopes
}
@@ -327,7 +379,10 @@ mod tests {
use test_utils::{assert_eq_text, extract_offset};
use crate::{
- FunctionId, ModuleDefId, db::DefDatabase, nameres::crate_def_map, test_db::TestDB,
+ DefWithBodyId, FunctionId, ModuleDefId,
+ expr_store::{Body, scope::ExprScopes},
+ nameres::crate_def_map,
+ test_db::TestDB,
};
fn find_function(db: &TestDB, file_id: FileId) -> FunctionId {
@@ -363,8 +418,8 @@ mod tests {
let marker: ast::PathExpr = find_node_at_offset(&file_syntax, offset).unwrap();
let function = find_function(&db, file_id);
- let scopes = db.expr_scopes(function.into());
- let (_body, source_map) = db.body_with_source_map(function.into());
+ let scopes = ExprScopes::of(&db, DefWithBodyId::from(function));
+ let (_body, source_map) = Body::with_source_map(&db, function.into());
let expr_id = source_map
.node_expr(InFile { file_id: editioned_file_id.into(), value: &marker.into() })
@@ -522,8 +577,8 @@ fn foo() {
let function = find_function(&db, file_id);
- let scopes = db.expr_scopes(function.into());
- let (_, source_map) = db.body_with_source_map(function.into());
+ let scopes = ExprScopes::body_expr_scopes(&db, DefWithBodyId::from(function));
+ let (_, source_map) = Body::with_source_map(&db, function.into());
let expr_scope = {
let expr_ast = name_ref.syntax().ancestors().find_map(ast::Expr::cast).unwrap();
diff --git a/crates/hir-def/src/expr_store/tests/body.rs b/crates/hir-def/src/expr_store/tests/body.rs
index 8f857aeeff..985cd96662 100644
--- a/crates/hir-def/src/expr_store/tests/body.rs
+++ b/crates/hir-def/src/expr_store/tests/body.rs
@@ -4,11 +4,10 @@ use crate::{DefWithBodyId, ModuleDefId, hir::MatchArm, nameres::crate_def_map, t
use expect_test::{Expect, expect};
use la_arena::RawIdx;
use test_fixture::WithFixture;
-use triomphe::Arc;
use super::super::*;
-fn lower(#[rust_analyzer::rust_fixture] ra_fixture: &str) -> (TestDB, Arc<Body>, DefWithBodyId) {
+fn lower(#[rust_analyzer::rust_fixture] ra_fixture: &str) -> (TestDB, DefWithBodyId) {
let db = TestDB::with_files(ra_fixture);
let krate = db.fetch_test_crate();
@@ -24,8 +23,27 @@ fn lower(#[rust_analyzer::rust_fixture] ra_fixture: &str) -> (TestDB, Arc<Body>,
}
let fn_def = fn_def.unwrap().into();
- let body = db.body(fn_def);
- (db, body, fn_def)
+ Body::of(&db, fn_def);
+ (db, fn_def)
+}
+
+fn pretty_print(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) {
+ let db = TestDB::with_files(ra_fixture);
+
+ let krate = db.fetch_test_crate();
+ let def_map = crate_def_map(&db, krate);
+ let mut fn_def = None;
+ 'outer: for (_, module) in def_map.modules() {
+ for decl in module.scope.declarations() {
+ if let ModuleDefId::FunctionId(it) = decl {
+ fn_def = Some(it);
+ break 'outer;
+ }
+ }
+ }
+ let fn_def = fn_def.unwrap().into();
+
+ expect.assert_eq(&Body::of(&db, fn_def).pretty_print(&db, fn_def, Edition::CURRENT));
}
fn def_map_at(#[rust_analyzer::rust_fixture] ra_fixture: &str) -> String {
@@ -144,7 +162,7 @@ mod m {
#[test]
fn desugar_for_loop() {
- let (db, body, def) = lower(
+ pretty_print(
r#"
//- minicore: iterator
fn main() {
@@ -154,9 +172,7 @@ fn main() {
}
}
"#,
- );
-
- expect![[r#"
+ expect![[r#"
fn main() {
match builtin#lang(into_iter)(
0..10,
@@ -173,13 +189,13 @@ fn main() {
}
},
}
- }"#]]
- .assert_eq(&body.pretty_print(&db, def, Edition::CURRENT))
+ }"#]],
+ );
}
#[test]
fn desugar_builtin_format_args_before_1_89_0() {
- let (db, body, def) = lower(
+ pretty_print(
r#"
//- minicore: fmt_before_1_89_0
fn main() {
@@ -188,9 +204,7 @@ fn main() {
builtin#format_args("\u{1b}hello {count:02} {} friends, we {are:?} {0}{last}", "fancy", orphan = (), last = "!");
}
"#,
- );
-
- expect![[r#"
+ expect![[r#"
fn main() {
let are = "are";
let count = 10;
@@ -256,13 +270,13 @@ fn main() {
}
},
);
- }"#]]
- .assert_eq(&body.pretty_print(&db, def, Edition::CURRENT))
+ }"#]],
+ )
}
#[test]
fn desugar_builtin_format_args_before_1_93_0() {
- let (db, body, def) = lower(
+ pretty_print(
r#"
//- minicore: fmt_before_1_93_0
fn main() {
@@ -271,9 +285,7 @@ fn main() {
builtin#format_args("\u{1b}hello {count:02} {} friends, we {are:?} {0}{last}", "fancy", orphan = (), last = "!");
}
"#,
- );
-
- expect![[r#"
+ expect![[r#"
fn main() {
let are = "are";
let count = 10;
@@ -339,13 +351,13 @@ fn main() {
)
}
};
- }"#]]
- .assert_eq(&body.pretty_print(&db, def, Edition::CURRENT))
+ }"#]],
+ )
}
#[test]
fn desugar_builtin_format_args() {
- let (db, body, def) = lower(
+ pretty_print(
r#"
//- minicore: fmt
fn main() {
@@ -356,9 +368,7 @@ fn main() {
builtin#format_args("hello world", orphan = ());
}
"#,
- );
-
- expect![[r#"
+ expect![[r#"
fn main() {
let are = "are";
let count = 10;
@@ -392,13 +402,13 @@ fn main() {
"hello world",
)
};
- }"#]]
- .assert_eq(&body.pretty_print(&db, def, Edition::CURRENT))
+ }"#]],
+ )
}
#[test]
fn test_macro_hygiene() {
- let (db, body, def) = lower(
+ pretty_print(
r##"
//- minicore: fmt, from
//- /main.rs
@@ -428,10 +438,7 @@ impl SsrError {
}
}
"##,
- );
-
- assert_eq!(db.body_with_source_map(def).1.diagnostics(), &[]);
- expect![[r#"
+ expect![[r#"
fn main() {
_ = ra_test_fixture::error::SsrError::new(
{
@@ -449,13 +456,13 @@ impl SsrError {
}
},
);
- }"#]]
- .assert_eq(&body.pretty_print(&db, def, Edition::CURRENT))
+ }"#]],
+ )
}
#[test]
fn regression_10300() {
- let (db, body, def) = lower(
+ pretty_print(
r#"
//- minicore: concat, panic, fmt_before_1_89_0
mod private {
@@ -472,16 +479,7 @@ fn f(a: i32, b: u32) -> String {
m!();
}
"#,
- );
-
- let (_, source_map) = db.body_with_source_map(def);
- assert_eq!(source_map.diagnostics(), &[]);
-
- for (_, def_map) in body.blocks(&db) {
- assert_eq!(def_map.diagnostics(), &[]);
- }
-
- expect![[r#"
+ expect![[r#"
fn f(a, b) {
{
core::panicking::panic_fmt(
@@ -497,8 +495,8 @@ fn f(a: i32, b: u32) -> String {
),
);
};
- }"#]]
- .assert_eq(&body.pretty_print(&db, def, Edition::CURRENT))
+ }"#]],
+ )
}
#[test]
@@ -507,7 +505,7 @@ fn destructuring_assignment_tuple_macro() {
// but in destructuring assignment it is valid, because `m!()()` is a valid expression, and destructuring
// assignments start their lives as expressions. So we have to do the same.
- let (db, body, def) = lower(
+ pretty_print(
r#"
struct Bar();
@@ -519,25 +517,16 @@ fn foo() {
m!()() = Bar();
}
"#,
- );
-
- let (_, source_map) = db.body_with_source_map(def);
- assert_eq!(source_map.diagnostics(), &[]);
-
- for (_, def_map) in body.blocks(&db) {
- assert_eq!(def_map.diagnostics(), &[]);
- }
-
- expect![[r#"
+ expect![[r#"
fn foo() {
Bar() = Bar();
- }"#]]
- .assert_eq(&body.pretty_print(&db, def, Edition::CURRENT))
+ }"#]],
+ )
}
#[test]
fn shadowing_record_variant() {
- let (_, body, _) = lower(
+ let (db, def) = lower(
r#"
enum A {
B { field: i32 },
@@ -550,6 +539,7 @@ fn f() {
}
"#,
);
+ let body = Body::of(&db, def);
assert_eq!(body.assert_expr_only().bindings.len(), 1, "should have a binding for `B`");
assert_eq!(
body[BindingId::from_raw(RawIdx::from_u32(0))].name.as_str(),
@@ -560,39 +550,35 @@ fn f() {
#[test]
fn regression_pretty_print_bind_pat() {
- let (db, body, owner) = lower(
+ pretty_print(
r#"
fn foo() {
let v @ u = 123;
}
"#,
- );
- let printed = body.pretty_print(&db, owner, Edition::CURRENT);
-
- expect![[r#"
+ expect![[r#"
fn foo() {
let v @ u = 123;
- }"#]]
- .assert_eq(&printed);
+ }"#]],
+ );
}
#[test]
fn skip_skips_body() {
- let (db, body, owner) = lower(
+ pretty_print(
r#"
#[rust_analyzer::skip]
async fn foo(a: (), b: i32) -> u32 {
0 + 1 + b()
}
"#,
+ expect!["fn foo(�, �) �"],
);
- let printed = body.pretty_print(&db, owner, Edition::CURRENT);
- expect!["fn foo(�, �) �"].assert_eq(&printed);
}
#[test]
fn range_bounds_are_hir_exprs() {
- let (_, body, _) = lower(
+ let (db, body) = lower(
r#"
pub const L: i32 = 6;
mod x {
@@ -607,6 +593,7 @@ const fn f(x: i32) -> i32 {
}"#,
);
+ let body = Body::of(&db, body);
let mtch_arms = body
.assert_expr_only()
.exprs
@@ -635,7 +622,7 @@ const fn f(x: i32) -> i32 {
#[test]
fn print_hir_precedences() {
- let (db, body, def) = lower(
+ pretty_print(
r#"
fn main() {
_ = &(1 - (2 - 3) + 4 * 5 * (6 + 7));
@@ -646,9 +633,7 @@ fn main() {
let _ = &mut (*r as i32)
}
"#,
- );
-
- expect![[r#"
+ expect![[r#"
fn main() {
_ = &((1 - (2 - 3)) + (4 * 5) * (6 + 7));
_ = 1 + 2 < 3 && true && 4 < 5 && (a || b || c) || d && e;
@@ -656,24 +641,22 @@ fn main() {
break a && b || (return) || (return 2);
let r = &2;
let _ = &mut (*r as i32);
- }"#]]
- .assert_eq(&body.pretty_print(&db, def, Edition::CURRENT))
+ }"#]],
+ )
}
#[test]
fn async_fn_weird_param_patterns() {
- let (db, body, def) = lower(
+ pretty_print(
r#"
async fn main(&self, param1: i32, ref mut param2: i32, _: i32, param4 @ _: i32, 123: i32) {}
"#,
- );
-
- expect![[r#"
+ expect![[r#"
fn main(self, param1, mut param2, mut <ra@gennew>0, param4 @ _, mut <ra@gennew>1) async {
let ref mut param2 = param2;
let _ = <ra@gennew>0;
let 123 = <ra@gennew>1;
{}
- }"#]]
- .assert_eq(&body.pretty_print(&db, def, Edition::CURRENT))
+ }"#]],
+ )
}
diff --git a/crates/hir-def/src/expr_store/tests/signatures.rs b/crates/hir-def/src/expr_store/tests/signatures.rs
index f1db00cf6a..5e0184dfad 100644
--- a/crates/hir-def/src/expr_store/tests/signatures.rs
+++ b/crates/hir-def/src/expr_store/tests/signatures.rs
@@ -2,6 +2,7 @@ use crate::{
GenericDefId, ModuleDefId,
expr_store::pretty::{print_function, print_struct},
nameres::crate_def_map,
+ signatures::{FunctionSignature, StructSignature},
test_db::TestDB,
};
use expect_test::{Expect, expect};
@@ -41,7 +42,7 @@ fn lower_and_print(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expe
out += &print_struct(
&db,
struct_id,
- &db.struct_signature(struct_id),
+ StructSignature::of(&db, struct_id),
Edition::CURRENT,
);
}
@@ -53,7 +54,7 @@ fn lower_and_print(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expe
out += &print_function(
&db,
function_id,
- &db.function_signature(function_id),
+ FunctionSignature::of(&db, function_id),
Edition::CURRENT,
)
}
diff --git a/crates/hir-def/src/find_path.rs b/crates/hir-def/src/find_path.rs
index 5d1cac8e93..8308203693 100644
--- a/crates/hir-def/src/find_path.rs
+++ b/crates/hir-def/src/find_path.rs
@@ -14,6 +14,7 @@ use rustc_hash::FxHashSet;
use crate::{
FindPathConfig, ModuleDefId, ModuleId,
db::DefDatabase,
+ import_map::ImportMap,
item_scope::ItemInNs,
nameres::DefMap,
visibility::{Visibility, VisibilityExplicitness},
@@ -426,7 +427,7 @@ fn find_in_dep(
best_choice: &mut Option<Choice>,
dep: Crate,
) {
- let import_map = ctx.db.import_map(dep);
+ let import_map = ImportMap::of(ctx.db, dep);
let Some(import_info_for) = import_map.import_info_for(item) else {
return;
};
diff --git a/crates/hir-def/src/hir/generics.rs b/crates/hir-def/src/hir/generics.rs
index 022f8adfdb..43dd7d1c54 100644
--- a/crates/hir-def/src/hir/generics.rs
+++ b/crates/hir-def/src/hir/generics.rs
@@ -5,12 +5,15 @@ use hir_expand::name::Name;
use la_arena::{Arena, Idx, RawIdx};
use stdx::impl_from;
use thin_vec::ThinVec;
-use triomphe::Arc;
use crate::{
AdtId, ConstParamId, GenericDefId, LifetimeParamId, TypeOrConstParamId, TypeParamId,
db::DefDatabase,
expr_store::{ExpressionStore, ExpressionStoreSourceMap},
+ signatures::{
+ ConstSignature, EnumSignature, FunctionSignature, ImplSignature, StaticSignature,
+ StructSignature, TraitSignature, TypeAliasSignature, UnionSignature,
+ },
type_ref::{ConstRef, LifetimeRefId, TypeBound, TypeRefId},
};
@@ -142,7 +145,7 @@ pub enum GenericParamDataRef<'a> {
}
/// Data about the generic parameters of a function, struct, impl, etc.
-#[derive(Clone, PartialEq, Eq, Debug, Hash)]
+#[derive(PartialEq, Eq, Debug, Hash, Default)]
pub struct GenericParams {
pub(crate) type_or_consts: Arena<TypeOrConstParamData>,
pub(crate) lifetimes: Arena<LifetimeParamData>,
@@ -174,12 +177,10 @@ pub enum WherePredicate {
ForLifetime { lifetimes: ThinVec<Name>, target: TypeRefId, bound: TypeBound },
}
-static EMPTY: LazyLock<Arc<GenericParams>> = LazyLock::new(|| {
- Arc::new(GenericParams {
- type_or_consts: Arena::default(),
- lifetimes: Arena::default(),
- where_predicates: Box::default(),
- })
+static EMPTY: LazyLock<GenericParams> = LazyLock::new(|| GenericParams {
+ type_or_consts: Arena::default(),
+ lifetimes: Arena::default(),
+ where_predicates: Box::default(),
});
impl GenericParams {
@@ -187,112 +188,94 @@ impl GenericParams {
pub const SELF_PARAM_ID_IN_SELF: la_arena::Idx<TypeOrConstParamData> =
LocalTypeOrConstParamId::from_raw(RawIdx::from_u32(0));
- pub fn new(db: &dyn DefDatabase, def: GenericDefId) -> Arc<GenericParams> {
- match def {
- GenericDefId::AdtId(AdtId::EnumId(it)) => db.enum_signature(it).generic_params.clone(),
- GenericDefId::AdtId(AdtId::StructId(it)) => {
- db.struct_signature(it).generic_params.clone()
- }
- GenericDefId::AdtId(AdtId::UnionId(it)) => {
- db.union_signature(it).generic_params.clone()
- }
- GenericDefId::ConstId(_) => EMPTY.clone(),
- GenericDefId::FunctionId(function_id) => {
- db.function_signature(function_id).generic_params.clone()
- }
- GenericDefId::ImplId(impl_id) => db.impl_signature(impl_id).generic_params.clone(),
- GenericDefId::StaticId(_) => EMPTY.clone(),
- GenericDefId::TraitId(trait_id) => db.trait_signature(trait_id).generic_params.clone(),
- GenericDefId::TypeAliasId(type_alias_id) => {
- db.type_alias_signature(type_alias_id).generic_params.clone()
- }
- }
+ pub fn of(db: &dyn DefDatabase, def: GenericDefId) -> &GenericParams {
+ Self::with_store(db, def).0
}
- pub fn generic_params_and_store(
+ pub fn with_store(
db: &dyn DefDatabase,
def: GenericDefId,
- ) -> (Arc<GenericParams>, Arc<ExpressionStore>) {
+ ) -> (&GenericParams, &ExpressionStore) {
match def {
GenericDefId::AdtId(AdtId::EnumId(id)) => {
- let sig = db.enum_signature(id);
- (sig.generic_params.clone(), sig.store.clone())
+ let sig = EnumSignature::of(db, id);
+ (&sig.generic_params, &sig.store)
}
GenericDefId::AdtId(AdtId::StructId(id)) => {
- let sig = db.struct_signature(id);
- (sig.generic_params.clone(), sig.store.clone())
+ let sig = StructSignature::of(db, id);
+ (&sig.generic_params, &sig.store)
}
GenericDefId::AdtId(AdtId::UnionId(id)) => {
- let sig = db.union_signature(id);
- (sig.generic_params.clone(), sig.store.clone())
+ let sig = UnionSignature::of(db, id);
+ (&sig.generic_params, &sig.store)
}
GenericDefId::ConstId(id) => {
- let sig = db.const_signature(id);
- (EMPTY.clone(), sig.store.clone())
+ let sig = ConstSignature::of(db, id);
+ (&EMPTY, &sig.store)
}
GenericDefId::FunctionId(id) => {
- let sig = db.function_signature(id);
- (sig.generic_params.clone(), sig.store.clone())
+ let sig = FunctionSignature::of(db, id);
+ (&sig.generic_params, &sig.store)
}
GenericDefId::ImplId(id) => {
- let sig = db.impl_signature(id);
- (sig.generic_params.clone(), sig.store.clone())
+ let sig = ImplSignature::of(db, id);
+ (&sig.generic_params, &sig.store)
}
GenericDefId::StaticId(id) => {
- let sig = db.static_signature(id);
- (EMPTY.clone(), sig.store.clone())
+ let sig = StaticSignature::of(db, id);
+ (&EMPTY, &sig.store)
}
GenericDefId::TraitId(id) => {
- let sig = db.trait_signature(id);
- (sig.generic_params.clone(), sig.store.clone())
+ let sig = TraitSignature::of(db, id);
+ (&sig.generic_params, &sig.store)
}
GenericDefId::TypeAliasId(id) => {
- let sig = db.type_alias_signature(id);
- (sig.generic_params.clone(), sig.store.clone())
+ let sig = TypeAliasSignature::of(db, id);
+ (&sig.generic_params, &sig.store)
}
}
}
- pub fn generic_params_and_store_and_source_map(
+ pub fn with_source_map(
db: &dyn DefDatabase,
def: GenericDefId,
- ) -> (Arc<GenericParams>, Arc<ExpressionStore>, Arc<ExpressionStoreSourceMap>) {
+ ) -> (&GenericParams, &ExpressionStore, &ExpressionStoreSourceMap) {
match def {
GenericDefId::AdtId(AdtId::EnumId(id)) => {
- let (sig, sm) = db.enum_signature_with_source_map(id);
- (sig.generic_params.clone(), sig.store.clone(), sm)
+ let (sig, sm) = EnumSignature::with_source_map(db, id);
+ (&sig.generic_params, &sig.store, sm)
}
GenericDefId::AdtId(AdtId::StructId(id)) => {
- let (sig, sm) = db.struct_signature_with_source_map(id);
- (sig.generic_params.clone(), sig.store.clone(), sm)
+ let (sig, sm) = StructSignature::with_source_map(db, id);
+ (&sig.generic_params, &sig.store, sm)
}
GenericDefId::AdtId(AdtId::UnionId(id)) => {
- let (sig, sm) = db.union_signature_with_source_map(id);
- (sig.generic_params.clone(), sig.store.clone(), sm)
+ let (sig, sm) = UnionSignature::with_source_map(db, id);
+ (&sig.generic_params, &sig.store, sm)
}
GenericDefId::ConstId(id) => {
- let (sig, sm) = db.const_signature_with_source_map(id);
- (EMPTY.clone(), sig.store.clone(), sm)
+ let (sig, sm) = ConstSignature::with_source_map(db, id);
+ (&EMPTY, &sig.store, sm)
}
GenericDefId::FunctionId(id) => {
- let (sig, sm) = db.function_signature_with_source_map(id);
- (sig.generic_params.clone(), sig.store.clone(), sm)
+ let (sig, sm) = FunctionSignature::with_source_map(db, id);
+ (&sig.generic_params, &sig.store, sm)
}
GenericDefId::ImplId(id) => {
- let (sig, sm) = db.impl_signature_with_source_map(id);
- (sig.generic_params.clone(), sig.store.clone(), sm)
+ let (sig, sm) = ImplSignature::with_source_map(db, id);
+ (&sig.generic_params, &sig.store, sm)
}
GenericDefId::StaticId(id) => {
- let (sig, sm) = db.static_signature_with_source_map(id);
- (EMPTY.clone(), sig.store.clone(), sm)
+ let (sig, sm) = StaticSignature::with_source_map(db, id);
+ (&EMPTY, &sig.store, sm)
}
GenericDefId::TraitId(id) => {
- let (sig, sm) = db.trait_signature_with_source_map(id);
- (sig.generic_params.clone(), sig.store.clone(), sm)
+ let (sig, sm) = TraitSignature::with_source_map(db, id);
+ (&sig.generic_params, &sig.store, sm)
}
GenericDefId::TypeAliasId(id) => {
- let (sig, sm) = db.type_alias_signature_with_source_map(id);
- (sig.generic_params.clone(), sig.store.clone(), sm)
+ let (sig, sm) = TypeAliasSignature::with_source_map(db, id);
+ (&sig.generic_params, &sig.store, sm)
}
}
}
diff --git a/crates/hir-def/src/import_map.rs b/crates/hir-def/src/import_map.rs
index 6c5d226cac..0014e1af5c 100644
--- a/crates/hir-def/src/import_map.rs
+++ b/crates/hir-def/src/import_map.rs
@@ -10,7 +10,6 @@ use rustc_hash::FxHashSet;
use smallvec::SmallVec;
use span::Edition;
use stdx::format_to;
-use triomphe::Arc;
use crate::{
AssocItemId, AttrDefId, Complete, FxIndexMap, ModuleDefId, ModuleId, TraitId,
@@ -63,6 +62,14 @@ enum IsTraitAssocItem {
type ImportMapIndex = FxIndexMap<ItemInNs, (SmallVec<[ImportInfo; 1]>, IsTraitAssocItem)>;
+#[salsa::tracked]
+impl ImportMap {
+ #[salsa::tracked(returns(ref))]
+ pub fn of(db: &dyn DefDatabase, krate: Crate) -> Self {
+ Self::import_map_query_impl(db, krate)
+ }
+}
+
impl ImportMap {
pub fn dump(&self, db: &dyn DefDatabase) -> String {
let mut out = String::new();
@@ -76,7 +83,7 @@ impl ImportMap {
out
}
- pub(crate) fn import_map_query(db: &dyn DefDatabase, krate: Crate) -> Arc<Self> {
+ fn import_map_query_impl(db: &dyn DefDatabase, krate: Crate) -> Self {
let _p = tracing::info_span!("import_map_query").entered();
let map = Self::collect_import_map(db, krate);
@@ -120,7 +127,7 @@ impl ImportMap {
}
let importables = importables.into_iter().map(|(item, _, idx)| (item, idx)).collect();
- Arc::new(ImportMap { item_to_info_map: map, fst: builder.into_map(), importables })
+ ImportMap { item_to_info_map: map, fst: builder.into_map(), importables }
}
pub fn import_info_for(&self, item: ItemInNs) -> Option<&[ImportInfo]> {
@@ -424,7 +431,7 @@ pub fn search_dependencies(
let _p = tracing::info_span!("search_dependencies", ?query).entered();
let import_maps: Vec<_> =
- krate.data(db).dependencies.iter().map(|dep| db.import_map(dep.crate_id)).collect();
+ krate.data(db).dependencies.iter().map(|dep| ImportMap::of(db, dep.crate_id)).collect();
let mut op = fst::map::OpBuilder::new();
@@ -458,7 +465,7 @@ pub fn search_dependencies(
fn search_maps(
_db: &dyn DefDatabase,
- import_maps: &[Arc<ImportMap>],
+ import_maps: &[&ImportMap],
mut stream: fst::map::Union<'_>,
query: &Query,
) -> FxHashSet<(ItemInNs, Complete)> {
@@ -467,7 +474,7 @@ fn search_maps(
for &IndexedValue { index: import_map_idx, value } in indexed_values {
let end = (value & 0xFFFF_FFFF) as usize;
let start = (value >> 32) as usize;
- let ImportMap { item_to_info_map, importables, .. } = &*import_maps[import_map_idx];
+ let ImportMap { item_to_info_map, importables, .. } = import_maps[import_map_idx];
let importables = &importables[start..end];
let iter = importables
@@ -546,9 +553,9 @@ mod tests {
.into_iter()
.filter_map(|(dependency, _)| {
let dependency_krate = dependency.krate(&db)?;
- let dependency_imports = db.import_map(dependency_krate);
+ let dependency_imports = ImportMap::of(&db, dependency_krate);
- let (path, mark) = match assoc_item_path(&db, &dependency_imports, dependency) {
+ let (path, mark) = match assoc_item_path(&db, dependency_imports, dependency) {
Some(assoc_item_path) => (assoc_item_path, "a"),
None => (
render_path(&db, &dependency_imports.import_info_for(dependency)?[0]),
@@ -618,7 +625,7 @@ mod tests {
let cdata = &krate.extra_data(&db);
let name = cdata.display_name.as_ref()?;
- let map = db.import_map(krate);
+ let map = ImportMap::of(&db, krate);
Some(format!("{name}:\n{}\n", map.fmt_for_test(&db)))
})
diff --git a/crates/hir-def/src/item_tree.rs b/crates/hir-def/src/item_tree.rs
index 9825dbfe1c..e7ab2b390f 100644
--- a/crates/hir-def/src/item_tree.rs
+++ b/crates/hir-def/src/item_tree.rs
@@ -192,45 +192,22 @@ pub(crate) fn file_item_tree_query(
}
}
-#[salsa_macros::tracked(returns(deref))]
+#[salsa_macros::tracked(returns(ref))]
pub(crate) fn block_item_tree_query(
db: &dyn DefDatabase,
block: BlockId,
krate: Crate,
-) -> Arc<ItemTree> {
+) -> ItemTree {
let _p = tracing::info_span!("block_item_tree_query", ?block).entered();
- static EMPTY: OnceLock<Arc<ItemTree>> = OnceLock::new();
-
let loc = block.lookup(db);
let block = loc.ast_id.to_node(db);
let ctx = lower::Ctx::new(db, loc.ast_id.file_id, krate);
let mut item_tree = ctx.lower_block(&block);
- let ItemTree { top_level, top_attrs, attrs, vis, big_data, small_data } = &item_tree;
- if small_data.is_empty()
- && big_data.is_empty()
- && top_level.is_empty()
- && attrs.is_empty()
- && top_attrs.is_empty()
- && vis.arena.is_empty()
- {
- EMPTY
- .get_or_init(|| {
- Arc::new(ItemTree {
- top_level: Box::new([]),
- attrs: FxHashMap::default(),
- small_data: FxHashMap::default(),
- big_data: FxHashMap::default(),
- top_attrs: AttrsOrCfg::empty(),
- vis: ItemVisibilities { arena: ThinVec::new() },
- })
- })
- .clone()
- } else {
- item_tree.shrink_to_fit();
- Arc::new(item_tree)
- }
+ item_tree.shrink_to_fit();
+ item_tree
}
+
/// The item tree of a source file.
#[derive(Debug, Default, Eq, PartialEq)]
pub struct ItemTree {
diff --git a/crates/hir-def/src/item_tree/lower.rs b/crates/hir-def/src/item_tree/lower.rs
index 31c6ef867d..31e409d86e 100644
--- a/crates/hir-def/src/item_tree/lower.rs
+++ b/crates/hir-def/src/item_tree/lower.rs
@@ -16,7 +16,6 @@ use syntax::{
AstNode,
ast::{self, HasModuleItem, HasName},
};
-use triomphe::Arc;
use crate::{
db::DefDatabase,
@@ -29,20 +28,20 @@ use crate::{
},
};
-pub(super) struct Ctx<'a> {
- pub(super) db: &'a dyn DefDatabase,
+pub(super) struct Ctx<'db> {
+ pub(super) db: &'db dyn DefDatabase,
tree: ItemTree,
- source_ast_id_map: Arc<AstIdMap>,
+ source_ast_id_map: &'db AstIdMap,
span_map: OnceCell<SpanMap>,
file: HirFileId,
- cfg_options: OnceCell<&'a CfgOptions>,
+ cfg_options: OnceCell<&'db CfgOptions>,
krate: Crate,
top_level: Vec<ModItemId>,
visibilities: FxIndexSet<RawVisibility>,
}
-impl<'a> Ctx<'a> {
- pub(super) fn new(db: &'a dyn DefDatabase, file: HirFileId, krate: Crate) -> Self {
+impl<'db> Ctx<'db> {
+ pub(super) fn new(db: &'db dyn DefDatabase, file: HirFileId, krate: Crate) -> Self {
Self {
db,
tree: ItemTree::default(),
@@ -57,7 +56,7 @@ impl<'a> Ctx<'a> {
}
#[inline]
- pub(super) fn cfg_options(&self) -> &'a CfgOptions {
+ pub(super) fn cfg_options(&self) -> &'db CfgOptions {
self.cfg_options.get_or_init(|| self.krate.cfg_options(self.db))
}
diff --git a/crates/hir-def/src/lib.rs b/crates/hir-def/src/lib.rs
index de674be05f..9a7fbc812f 100644
--- a/crates/hir-def/src/lib.rs
+++ b/crates/hir-def/src/lib.rs
@@ -49,7 +49,6 @@ pub mod visibility;
use intern::{Interned, Symbol};
pub use rustc_abi as layout;
use thin_vec::ThinVec;
-use triomphe::Arc;
pub use crate::signatures::LocalFieldId;
@@ -86,14 +85,19 @@ use crate::{
builtin_type::BuiltinType,
db::DefDatabase,
expr_store::ExpressionStoreSourceMap,
- hir::generics::{GenericParams, LocalLifetimeParamId, LocalTypeOrConstParamId},
+ hir::{
+ ExprId,
+ generics::{GenericParams, LocalLifetimeParamId, LocalTypeOrConstParamId},
+ },
nameres::{
LocalDefMap,
assoc::{ImplItems, TraitItems},
block_def_map, crate_def_map, crate_local_def_map,
diagnostics::DefDiagnostics,
},
- signatures::{EnumVariants, InactiveEnumVariantCode, VariantFields},
+ signatures::{
+ ConstSignature, EnumVariants, InactiveEnumVariantCode, StaticSignature, VariantFields,
+ },
};
type FxIndexMap<K, V> = indexmap::IndexMap<K, V, rustc_hash::FxBuildHasher>;
@@ -255,14 +259,15 @@ impl_intern!(StructId, StructLoc, intern_struct, lookup_intern_struct);
impl StructId {
pub fn fields(self, db: &dyn DefDatabase) -> &VariantFields {
- VariantFields::firewall(db, self.into())
+ VariantFields::of(db, self.into())
}
pub fn fields_with_source_map(
self,
db: &dyn DefDatabase,
- ) -> (Arc<VariantFields>, Arc<ExpressionStoreSourceMap>) {
- VariantFields::query(db, self.into())
+ ) -> (&VariantFields, &ExpressionStoreSourceMap) {
+ let r = VariantFields::with_source_map(db, self.into());
+ (&r.0, &r.1)
}
}
@@ -271,14 +276,15 @@ impl_intern!(UnionId, UnionLoc, intern_union, lookup_intern_union);
impl UnionId {
pub fn fields(self, db: &dyn DefDatabase) -> &VariantFields {
- VariantFields::firewall(db, self.into())
+ VariantFields::of(db, self.into())
}
pub fn fields_with_source_map(
self,
db: &dyn DefDatabase,
- ) -> (Arc<VariantFields>, Arc<ExpressionStoreSourceMap>) {
- VariantFields::query(db, self.into())
+ ) -> (&VariantFields, &ExpressionStoreSourceMap) {
+ let r = VariantFields::with_source_map(db, self.into());
+ (&r.0, &r.1)
}
}
@@ -306,6 +312,19 @@ impl_intern!(ConstId, ConstLoc, intern_const, lookup_intern_const);
pub type StaticLoc = AssocItemLoc<ast::Static>;
impl_intern!(StaticId, StaticLoc, intern_static, lookup_intern_static);
+/// An anonymous const expression that appears in a type position (e.g., array lengths,
+/// const generic arguments like `{ N + 1 }`). Unlike named constants, these don't have
+/// their own `Body` — their expressions live in the parent's signature `ExpressionStore`.
+#[derive(Debug, Hash, PartialEq, Eq, Clone)]
+pub struct AnonConstLoc {
+ /// The owner store containing this expression.
+ pub owner: ExpressionStoreOwnerId,
+ /// The ExprId within the owner's ExpressionStore that is the root
+ /// of this anonymous const expression.
+ pub expr: ExprId,
+}
+impl_intern!(AnonConstId, AnonConstLoc, intern_anon_const, lookup_intern_anon_const);
+
pub type TraitLoc = ItemLoc<ast::Trait>;
impl_intern!(TraitId, TraitLoc, intern_trait, lookup_intern_trait);
@@ -377,14 +396,15 @@ impl_loc!(EnumVariantLoc, id: Variant, parent: EnumId);
impl EnumVariantId {
pub fn fields(self, db: &dyn DefDatabase) -> &VariantFields {
- VariantFields::firewall(db, self.into())
+ VariantFields::of(db, self.into())
}
pub fn fields_with_source_map(
self,
db: &dyn DefDatabase,
- ) -> (Arc<VariantFields>, Arc<ExpressionStoreSourceMap>) {
- VariantFields::query(db, self.into())
+ ) -> (&VariantFields, &ExpressionStoreSourceMap) {
+ let r = VariantFields::with_source_map(db, self.into());
+ (&r.0, &r.1)
}
}
@@ -706,46 +726,47 @@ impl From<DefWithBodyId> for ModuleDefId {
pub enum GeneralConstId {
ConstId(ConstId),
StaticId(StaticId),
+ AnonConstId(AnonConstId),
}
-impl_from!(ConstId, StaticId for GeneralConstId);
+impl_from!(ConstId, StaticId, AnonConstId for GeneralConstId);
impl GeneralConstId {
- pub fn generic_def(self, _db: &dyn DefDatabase) -> Option<GenericDefId> {
+ pub fn generic_def(self, db: &dyn DefDatabase) -> Option<GenericDefId> {
match self {
GeneralConstId::ConstId(it) => Some(it.into()),
GeneralConstId::StaticId(it) => Some(it.into()),
+ GeneralConstId::AnonConstId(it) => Some(it.lookup(db).owner.generic_def(db)),
}
}
pub fn name(self, db: &dyn DefDatabase) -> String {
match self {
GeneralConstId::StaticId(it) => {
- db.static_signature(it).name.display(db, Edition::CURRENT).to_string()
+ StaticSignature::of(db, it).name.display(db, Edition::CURRENT).to_string()
}
GeneralConstId::ConstId(const_id) => {
- db.const_signature(const_id).name.as_ref().map_or_else(
+ ConstSignature::of(db, const_id).name.as_ref().map_or_else(
|| "_".to_owned(),
|name| name.display(db, Edition::CURRENT).to_string(),
)
}
+ GeneralConstId::AnonConstId(_) => "{anon const}".to_owned(),
}
}
}
-/// The defs which have a body (have root expressions for type inference).
+/// The defs which have a body.
#[derive(Debug, PartialOrd, Ord, Clone, Copy, PartialEq, Eq, Hash, salsa_macros::Supertype)]
pub enum DefWithBodyId {
+ /// A function body.
FunctionId(FunctionId),
+ /// A static item initializer.
StaticId(StaticId),
+ /// A const item initializer
ConstId(ConstId),
+ /// An enum variant discrimiant
VariantId(EnumVariantId),
- // /// All fields of a variant are inference roots
- // VariantId(VariantId),
- // /// The signature can contain inference roots in a bunch of places
- // /// like const parameters or const arguments in paths
- // This should likely be kept on its own with a separate query
- // GenericDefId(GenericDefId),
}
impl_from!(FunctionId, ConstId, StaticId for DefWithBodyId);
@@ -814,6 +835,62 @@ impl_from!(
for GenericDefId
);
+/// Owner of an expression store - either a body or a signature.
+/// This is used for queries that operate on expression stores generically,
+/// such as `expr_scopes`.
+// NOTE: This type cannot be `salsa::Supertype` as its variants are overlapping.
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord /* !salsa::Supertype */)]
+pub enum ExpressionStoreOwnerId {
+ Signature(GenericDefId),
+ /// A body, something with a root expression.
+ ///
+ /// An enum variant's body is considered its discriminant initializer.
+ Body(DefWithBodyId),
+ VariantFields(VariantId),
+}
+
+impl ExpressionStoreOwnerId {
+ // FIXME: Check callers of this, this method likely can be removed
+ pub fn as_def_with_body(self) -> Option<DefWithBodyId> {
+ if let Self::Body(v) = self { Some(v) } else { None }
+ }
+
+ pub fn generic_def(self, db: &dyn DefDatabase) -> GenericDefId {
+ match self {
+ ExpressionStoreOwnerId::Signature(generic_def_id) => generic_def_id,
+ ExpressionStoreOwnerId::Body(def_with_body_id) => match def_with_body_id {
+ DefWithBodyId::FunctionId(id) => GenericDefId::FunctionId(id),
+ DefWithBodyId::StaticId(id) => GenericDefId::StaticId(id),
+ DefWithBodyId::ConstId(id) => GenericDefId::ConstId(id),
+ DefWithBodyId::VariantId(it) => it.lookup(db).parent.into(),
+ },
+ ExpressionStoreOwnerId::VariantFields(variant_id) => match variant_id {
+ VariantId::EnumVariantId(it) => it.lookup(db).parent.into(),
+ VariantId::StructId(it) => it.into(),
+ VariantId::UnionId(it) => it.into(),
+ },
+ }
+ }
+}
+
+impl From<GenericDefId> for ExpressionStoreOwnerId {
+ fn from(id: GenericDefId) -> Self {
+ ExpressionStoreOwnerId::Signature(id)
+ }
+}
+
+impl From<DefWithBodyId> for ExpressionStoreOwnerId {
+ fn from(id: DefWithBodyId) -> Self {
+ ExpressionStoreOwnerId::Body(id)
+ }
+}
+
+impl From<VariantId> for ExpressionStoreOwnerId {
+ fn from(id: VariantId) -> Self {
+ ExpressionStoreOwnerId::VariantFields(id)
+ }
+}
+
impl GenericDefId {
pub fn file_id_and_params_of(
self,
@@ -954,7 +1031,9 @@ impl From<VariantId> for AttrDefId {
}
}
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, salsa_macros::Supertype, salsa::Update)]
+#[derive(
+ Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, salsa_macros::Supertype, salsa::Update,
+)]
pub enum VariantId {
EnumVariantId(EnumVariantId),
StructId(StructId),
@@ -964,14 +1043,15 @@ impl_from!(EnumVariantId, StructId, UnionId for VariantId);
impl VariantId {
pub fn fields(self, db: &dyn DefDatabase) -> &VariantFields {
- VariantFields::firewall(db, self)
+ VariantFields::of(db, self)
}
pub fn fields_with_source_map(
self,
db: &dyn DefDatabase,
- ) -> (Arc<VariantFields>, Arc<ExpressionStoreSourceMap>) {
- VariantFields::query(db, self)
+ ) -> (&VariantFields, &ExpressionStoreSourceMap) {
+ let r = VariantFields::with_source_map(db, self);
+ (&r.0, &r.1)
}
pub fn file_id(self, db: &dyn DefDatabase) -> HirFileId {
@@ -1172,6 +1252,16 @@ impl HasModule for DefWithBodyId {
}
}
+impl HasModule for ExpressionStoreOwnerId {
+ fn module(&self, db: &dyn DefDatabase) -> ModuleId {
+ match self {
+ ExpressionStoreOwnerId::Signature(def) => def.module(db),
+ ExpressionStoreOwnerId::Body(def) => def.module(db),
+ ExpressionStoreOwnerId::VariantFields(variant_id) => variant_id.module(db),
+ }
+ }
+}
+
impl HasModule for GenericDefId {
fn module(&self, db: &dyn DefDatabase) -> ModuleId {
match self {
diff --git a/crates/hir-def/src/macro_expansion_tests/mod.rs b/crates/hir-def/src/macro_expansion_tests/mod.rs
index 8ee93dcaa3..8317c56caf 100644
--- a/crates/hir-def/src/macro_expansion_tests/mod.rs
+++ b/crates/hir-def/src/macro_expansion_tests/mod.rs
@@ -45,6 +45,7 @@ use tt::{TextRange, TextSize};
use crate::{
AdtId, Lookup, ModuleDefId,
db::DefDatabase,
+ expr_store::Body,
nameres::{DefMap, ModuleSource, crate_def_map},
src::HasSource,
test_db::TestDB,
@@ -276,7 +277,7 @@ fn resolve_macro_call_id(
_ => continue,
};
- let (body, sm) = db.body_with_source_map(body);
+ let (body, sm) = Body::with_source_map(db, body);
if let Some(it) = body
.blocks(db)
.find_map(|block| resolve_macro_call_id(db, block.1, ast_id, ast_ptr))
diff --git a/crates/hir-def/src/nameres/assoc.rs b/crates/hir-def/src/nameres/assoc.rs
index 9d2b2109fb..f5a852b39c 100644
--- a/crates/hir-def/src/nameres/assoc.rs
+++ b/crates/hir-def/src/nameres/assoc.rs
@@ -17,7 +17,6 @@ use syntax::{
ast::{self, HasModuleItem, HasName},
};
use thin_vec::ThinVec;
-use triomphe::Arc;
use crate::{
AssocItemId, AstIdWithPath, ConstLoc, FunctionId, FunctionLoc, ImplId, ItemContainerId,
@@ -133,14 +132,14 @@ impl ImplItems {
}
}
-struct AssocItemCollector<'a> {
- db: &'a dyn DefDatabase,
+struct AssocItemCollector<'db> {
+ db: &'db dyn DefDatabase,
module_id: ModuleId,
- def_map: &'a DefMap,
- local_def_map: &'a LocalDefMap,
- ast_id_map: Arc<AstIdMap>,
+ def_map: &'db DefMap,
+ local_def_map: &'db LocalDefMap,
+ ast_id_map: &'db AstIdMap,
span_map: SpanMap,
- cfg_options: &'a CfgOptions,
+ cfg_options: &'db CfgOptions,
file_id: HirFileId,
diagnostics: Vec<DefDiagnostic>,
container: ItemContainerId,
@@ -150,9 +149,9 @@ struct AssocItemCollector<'a> {
macro_calls: ThinVec<(AstId<ast::Item>, MacroCallId)>,
}
-impl<'a> AssocItemCollector<'a> {
+impl<'db> AssocItemCollector<'db> {
fn new(
- db: &'a dyn DefDatabase,
+ db: &'db dyn DefDatabase,
module_id: ModuleId,
container: ItemContainerId,
file_id: HirFileId,
diff --git a/crates/hir-def/src/nameres/tests/incremental.rs b/crates/hir-def/src/nameres/tests/incremental.rs
index 7fedfa03bb..5b75c078ec 100644
--- a/crates/hir-def/src/nameres/tests/incremental.rs
+++ b/crates/hir-def/src/nameres/tests/incremental.rs
@@ -166,15 +166,15 @@ fn no() {}
[
"crate_local_def_map",
"file_item_tree_query",
- "ast_id_map_shim",
+ "ast_id_map",
"parse_shim",
"real_span_map_shim",
"file_item_tree_query",
- "ast_id_map_shim",
+ "ast_id_map",
"parse_shim",
"real_span_map_shim",
"file_item_tree_query",
- "ast_id_map_shim",
+ "ast_id_map",
"parse_shim",
"real_span_map_shim",
"EnumVariants::of_",
@@ -183,7 +183,7 @@ fn no() {}
expect![[r#"
[
"parse_shim",
- "ast_id_map_shim",
+ "ast_id_map",
"file_item_tree_query",
"real_span_map_shim",
"EnumVariants::of_",
@@ -224,21 +224,21 @@ pub struct S {}
[
"crate_local_def_map",
"file_item_tree_query",
- "ast_id_map_shim",
+ "ast_id_map",
"parse_shim",
"real_span_map_shim",
"decl_macro_expander_shim",
"file_item_tree_query",
- "ast_id_map_shim",
+ "ast_id_map",
"parse_shim",
"real_span_map_shim",
"file_item_tree_query",
- "ast_id_map_shim",
+ "ast_id_map",
"parse_shim",
"real_span_map_shim",
"macro_def_shim",
"file_item_tree_query",
- "ast_id_map_shim",
+ "ast_id_map",
"parse_macro_expansion_shim",
"macro_arg_shim",
]
@@ -246,12 +246,12 @@ pub struct S {}
expect![[r#"
[
"parse_shim",
- "ast_id_map_shim",
+ "ast_id_map",
"file_item_tree_query",
"real_span_map_shim",
"macro_arg_shim",
"parse_macro_expansion_shim",
- "ast_id_map_shim",
+ "ast_id_map",
"file_item_tree_query",
]
"#]],
@@ -282,26 +282,26 @@ fn f() { foo }
[
"crate_local_def_map",
"file_item_tree_query",
- "ast_id_map_shim",
+ "ast_id_map",
"parse_shim",
"real_span_map_shim",
"crate_local_def_map",
"proc_macros_for_crate_shim",
"file_item_tree_query",
- "ast_id_map_shim",
+ "ast_id_map",
"parse_shim",
"real_span_map_shim",
"file_item_tree_query",
- "ast_id_map_shim",
+ "ast_id_map",
"parse_shim",
"real_span_map_shim",
"file_item_tree_query",
- "ast_id_map_shim",
+ "ast_id_map",
"parse_shim",
"real_span_map_shim",
"macro_def_shim",
"file_item_tree_query",
- "ast_id_map_shim",
+ "ast_id_map",
"parse_macro_expansion_shim",
"expand_proc_macro_shim",
"macro_arg_shim",
@@ -311,13 +311,13 @@ fn f() { foo }
expect![[r#"
[
"parse_shim",
- "ast_id_map_shim",
+ "ast_id_map",
"file_item_tree_query",
"real_span_map_shim",
"macro_arg_shim",
"expand_proc_macro_shim",
"parse_macro_expansion_shim",
- "ast_id_map_shim",
+ "ast_id_map",
"file_item_tree_query",
]
"#]],
@@ -406,38 +406,38 @@ pub struct S {}
[
"crate_local_def_map",
"file_item_tree_query",
- "ast_id_map_shim",
+ "ast_id_map",
"parse_shim",
"real_span_map_shim",
"crate_local_def_map",
"proc_macros_for_crate_shim",
"file_item_tree_query",
- "ast_id_map_shim",
+ "ast_id_map",
"parse_shim",
"real_span_map_shim",
"decl_macro_expander_shim",
"file_item_tree_query",
- "ast_id_map_shim",
+ "ast_id_map",
"parse_shim",
"real_span_map_shim",
"file_item_tree_query",
- "ast_id_map_shim",
+ "ast_id_map",
"parse_shim",
"real_span_map_shim",
"macro_def_shim",
"file_item_tree_query",
- "ast_id_map_shim",
+ "ast_id_map",
"parse_macro_expansion_shim",
"macro_arg_shim",
"decl_macro_expander_shim",
"macro_def_shim",
"file_item_tree_query",
- "ast_id_map_shim",
+ "ast_id_map",
"parse_macro_expansion_shim",
"macro_arg_shim",
"macro_def_shim",
"file_item_tree_query",
- "ast_id_map_shim",
+ "ast_id_map",
"parse_macro_expansion_shim",
"expand_proc_macro_shim",
"macro_arg_shim",
@@ -447,7 +447,7 @@ pub struct S {}
expect![[r#"
[
"parse_shim",
- "ast_id_map_shim",
+ "ast_id_map",
"file_item_tree_query",
"real_span_map_shim",
"macro_arg_shim",
@@ -523,29 +523,29 @@ m!(Z);
[
"crate_local_def_map",
"file_item_tree_query",
- "ast_id_map_shim",
+ "ast_id_map",
"parse_shim",
"real_span_map_shim",
"decl_macro_expander_shim",
"file_item_tree_query",
- "ast_id_map_shim",
+ "ast_id_map",
"parse_shim",
"real_span_map_shim",
"file_item_tree_query",
- "ast_id_map_shim",
+ "ast_id_map",
"parse_shim",
"real_span_map_shim",
"macro_def_shim",
"file_item_tree_query",
- "ast_id_map_shim",
+ "ast_id_map",
"parse_macro_expansion_shim",
"macro_arg_shim",
"file_item_tree_query",
- "ast_id_map_shim",
+ "ast_id_map",
"parse_macro_expansion_shim",
"macro_arg_shim",
"file_item_tree_query",
- "ast_id_map_shim",
+ "ast_id_map",
"parse_macro_expansion_shim",
"macro_arg_shim",
]
@@ -572,7 +572,7 @@ m!(Z);
expect![[r#"
[
"parse_shim",
- "ast_id_map_shim",
+ "ast_id_map",
"file_item_tree_query",
"real_span_map_shim",
"macro_arg_shim",
@@ -610,7 +610,7 @@ pub type Ty = ();
expect![[r#"
[
"file_item_tree_query",
- "ast_id_map_shim",
+ "ast_id_map",
"parse_shim",
"real_span_map_shim",
]
@@ -630,7 +630,7 @@ pub type Ty = ();
expect![[r#"
[
"parse_shim",
- "ast_id_map_shim",
+ "ast_id_map",
"file_item_tree_query",
"real_span_map_shim",
]
diff --git a/crates/hir-def/src/resolver.rs b/crates/hir-def/src/resolver.rs
index d32e53fc6b..bb292ac1a6 100644
--- a/crates/hir-def/src/resolver.rs
+++ b/crates/hir-def/src/resolver.rs
@@ -13,14 +13,13 @@ use rustc_hash::FxHashSet;
use smallvec::{SmallVec, smallvec};
use span::SyntaxContext;
use syntax::ast::HasName;
-use triomphe::Arc;
use crate::{
- AdtId, AstIdLoc, ConstId, ConstParamId, DefWithBodyId, EnumId, EnumVariantId, ExternBlockId,
- ExternCrateId, FunctionId, FxIndexMap, GenericDefId, GenericParamId, HasModule, ImplId,
- ItemContainerId, LifetimeParamId, Lookup, Macro2Id, MacroId, MacroRulesId, ModuleDefId,
- ModuleId, ProcMacroId, StaticId, StructId, TraitId, TypeAliasId, TypeOrConstParamId,
- TypeParamId, UseId, VariantId,
+ AdtId, AstIdLoc, ConstId, ConstParamId, DefWithBodyId, EnumId, EnumVariantId,
+ ExpressionStoreOwnerId, ExternBlockId, ExternCrateId, FunctionId, FxIndexMap, GenericDefId,
+ GenericParamId, HasModule, ImplId, ItemContainerId, LifetimeParamId, Lookup, Macro2Id, MacroId,
+ MacroRulesId, ModuleDefId, ModuleId, ProcMacroId, StaticId, StructId, TraitId, TypeAliasId,
+ TypeOrConstParamId, TypeParamId, UseId, VariantId,
builtin_type::BuiltinType,
db::DefDatabase,
expr_store::{
@@ -36,6 +35,7 @@ use crate::{
lang_item::LangItemTarget,
nameres::{DefMap, LocalDefMap, MacroSubNs, ResolvePathResultPrefixInfo, block_def_map},
per_ns::PerNs,
+ signatures::ImplSignature,
src::HasSource,
type_ref::LifetimeRef,
visibility::{RawVisibility, Visibility},
@@ -65,13 +65,13 @@ impl fmt::Debug for ModuleItemMap<'_> {
}
#[derive(Clone)]
-struct ExprScope {
- owner: DefWithBodyId,
- expr_scopes: Arc<ExprScopes>,
+struct ExprScope<'db> {
+ owner: ExpressionStoreOwnerId,
+ expr_scopes: &'db ExprScopes,
scope_id: ScopeId,
}
-impl fmt::Debug for ExprScope {
+impl fmt::Debug for ExprScope<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("ExprScope")
.field("owner", &self.owner)
@@ -86,9 +86,9 @@ enum Scope<'db> {
BlockScope(ModuleItemMap<'db>),
/// Brings the generic parameters of an item into scope as well as the `Self` type alias /
/// generic for ADTs and impls.
- GenericParams { def: GenericDefId, params: Arc<GenericParams> },
+ GenericParams { def: GenericDefId, params: &'db GenericParams },
/// Local bindings
- ExprScope(ExprScope),
+ ExprScope(ExprScope<'db>),
/// Macro definition inside bodies that affects all paths after it in the same block.
MacroDefScope(MacroDefId),
}
@@ -653,7 +653,7 @@ impl<'db> Resolver<'db> {
match scope {
Scope::BlockScope(m) => traits.extend(m.def_map[m.module_id].scope.traits()),
&Scope::GenericParams { def: GenericDefId::ImplId(impl_), .. } => {
- let impl_data = db.impl_signature(impl_);
+ let impl_data = ImplSignature::of(db, impl_);
if let Some(target_trait) = impl_data.target_trait
&& let Some(TypeNs::TraitId(trait_)) = self
.resolve_path_in_type_ns_fully(db, &impl_data.store[target_trait.path])
@@ -724,19 +724,19 @@ impl<'db> Resolver<'db> {
pub fn generic_params(&self) -> Option<&GenericParams> {
self.scopes().find_map(|scope| match scope {
- Scope::GenericParams { params, .. } => Some(&**params),
+ &Scope::GenericParams { params, .. } => Some(params),
_ => None,
})
}
- pub fn all_generic_params(&self) -> impl Iterator<Item = (&GenericParams, &GenericDefId)> {
+ pub fn all_generic_params(&self) -> impl Iterator<Item = (&GenericParams, GenericDefId)> {
self.scopes().filter_map(|scope| match scope {
- Scope::GenericParams { params, def } => Some((&**params, def)),
+ &Scope::GenericParams { params, def } => Some((params, def)),
_ => None,
})
}
- pub fn body_owner(&self) -> Option<DefWithBodyId> {
+ pub fn expression_store_owner(&self) -> Option<ExpressionStoreOwnerId> {
self.scopes().find_map(|scope| match scope {
Scope::ExprScope(it) => Some(it.owner),
_ => None,
@@ -854,25 +854,30 @@ impl<'db> Resolver<'db> {
pub fn update_to_inner_scope(
&mut self,
db: &'db dyn DefDatabase,
- owner: DefWithBodyId,
+ owner: impl Into<ExpressionStoreOwnerId>,
+ expr_id: ExprId,
+ ) -> UpdateGuard {
+ self.update_to_inner_scope_(db, owner.into(), expr_id)
+ }
+
+ fn update_to_inner_scope_(
+ &mut self,
+ db: &'db dyn DefDatabase,
+ owner: ExpressionStoreOwnerId,
expr_id: ExprId,
) -> UpdateGuard {
#[inline(always)]
fn append_expr_scope<'db>(
db: &'db dyn DefDatabase,
resolver: &mut Resolver<'db>,
- owner: DefWithBodyId,
- expr_scopes: &Arc<ExprScopes>,
+ owner: ExpressionStoreOwnerId,
+ expr_scopes: &'db ExprScopes,
scope_id: ScopeId,
) {
if let Some(macro_id) = expr_scopes.macro_def(scope_id) {
resolver.scopes.push(Scope::MacroDefScope(**macro_id));
}
- resolver.scopes.push(Scope::ExprScope(ExprScope {
- owner,
- expr_scopes: expr_scopes.clone(),
- scope_id,
- }));
+ resolver.scopes.push(Scope::ExprScope(ExprScope { owner, expr_scopes, scope_id }));
if let Some(block) = expr_scopes.block(scope_id) {
let def_map = block_def_map(db, block);
let local_def_map = block.lookup(db).module.only_local_def_map(db);
@@ -890,21 +895,20 @@ impl<'db> Resolver<'db> {
let start = self.scopes.len();
let innermost_scope = self.scopes().find(|scope| !matches!(scope, Scope::MacroDefScope(_)));
match innermost_scope {
- Some(&Scope::ExprScope(ExprScope { scope_id, ref expr_scopes, owner })) => {
- let expr_scopes = expr_scopes.clone();
+ Some(&Scope::ExprScope(ExprScope { scope_id, expr_scopes, owner })) => {
let scope_chain = expr_scopes
.scope_chain(expr_scopes.scope_for(expr_id))
.take_while(|&it| it != scope_id);
for scope_id in scope_chain {
- append_expr_scope(db, self, owner, &expr_scopes, scope_id);
+ append_expr_scope(db, self, owner, expr_scopes, scope_id);
}
}
_ => {
- let expr_scopes = db.expr_scopes(owner);
+ let expr_scopes = ExprScopes::of(db, owner);
let scope_chain = expr_scopes.scope_chain(expr_scopes.scope_for(expr_id));
for scope_id in scope_chain {
- append_expr_scope(db, self, owner, &expr_scopes, scope_id);
+ append_expr_scope(db, self, owner, expr_scopes, scope_id);
}
}
}
@@ -1016,7 +1020,7 @@ impl<'db> Scope<'db> {
})
});
}
- &Scope::GenericParams { ref params, def: parent } => {
+ &Scope::GenericParams { params, def: parent } => {
if let GenericDefId::ImplId(impl_) = parent {
acc.add(&Name::new_symbol_root(sym::Self_), ScopeDef::ImplSelfType(impl_));
} else if let GenericDefId::AdtId(adt) = parent {
@@ -1026,7 +1030,7 @@ impl<'db> Scope<'db> {
for (local_id, param) in params.iter_type_or_consts() {
if let Some(name) = &param.name() {
let id = TypeOrConstParamId { parent, local_id };
- let data = &db.generic_params(parent)[local_id];
+ let data = &GenericParams::of(db, parent)[local_id];
acc.add(
name,
ScopeDef::GenericParam(match data {
@@ -1060,20 +1064,21 @@ impl<'db> Scope<'db> {
pub fn resolver_for_scope(
db: &dyn DefDatabase,
- owner: DefWithBodyId,
+ owner: impl Into<ExpressionStoreOwnerId> + HasResolver,
scope_id: Option<ScopeId>,
) -> Resolver<'_> {
- let r = owner.resolver(db);
- let scopes = db.expr_scopes(owner);
- resolver_for_scope_(db, scopes, scope_id, r, owner)
+ let store_owner = owner.into();
+ let r = store_owner.resolver(db);
+ let scopes = ExprScopes::of(db, store_owner);
+ resolver_for_scope_(db, scopes, scope_id, r, store_owner)
}
fn resolver_for_scope_<'db>(
db: &'db dyn DefDatabase,
- scopes: Arc<ExprScopes>,
+ scopes: &'db ExprScopes,
scope_id: Option<ScopeId>,
mut r: Resolver<'db>,
- owner: DefWithBodyId,
+ owner: ExpressionStoreOwnerId,
) -> Resolver<'db> {
let scope_chain = scopes.scope_chain(scope_id).collect::<Vec<_>>();
r.scopes.reserve(scope_chain.len());
@@ -1093,7 +1098,7 @@ fn resolver_for_scope_<'db>(
r = r.push_scope(Scope::MacroDefScope(**macro_id));
}
- r = r.push_expr_scope(owner, Arc::clone(&scopes), scope);
+ r = r.push_expr_scope(owner, scopes, scope);
}
r
}
@@ -1109,7 +1114,7 @@ impl<'db> Resolver<'db> {
db: &'db dyn DefDatabase,
def: GenericDefId,
) -> Resolver<'db> {
- let params = db.generic_params(def);
+ let params = GenericParams::of(db, def);
self.push_scope(Scope::GenericParams { def, params })
}
@@ -1124,8 +1129,8 @@ impl<'db> Resolver<'db> {
fn push_expr_scope(
self,
- owner: DefWithBodyId,
- expr_scopes: Arc<ExprScopes>,
+ owner: ExpressionStoreOwnerId,
+ expr_scopes: &'db ExprScopes,
scope_id: ScopeId,
) -> Resolver<'db> {
self.push_scope(Scope::ExprScope(ExprScope { owner, expr_scopes, scope_id }))
@@ -1409,6 +1414,16 @@ impl HasResolver for GenericDefId {
}
}
+impl HasResolver for ExpressionStoreOwnerId {
+ fn resolver(self, db: &dyn DefDatabase) -> Resolver<'_> {
+ match self {
+ ExpressionStoreOwnerId::Signature(def) => def.resolver(db),
+ ExpressionStoreOwnerId::Body(def) => def.resolver(db),
+ ExpressionStoreOwnerId::VariantFields(variant_id) => variant_id.resolver(db),
+ }
+ }
+}
+
impl HasResolver for EnumVariantId {
fn resolver(self, db: &dyn DefDatabase) -> Resolver<'_> {
self.lookup(db).parent.resolver(db)
diff --git a/crates/hir-def/src/signatures.rs b/crates/hir-def/src/signatures.rs
index 37c8f762fe..6d704274f4 100644
--- a/crates/hir-def/src/signatures.rs
+++ b/crates/hir-def/src/signatures.rs
@@ -24,7 +24,7 @@ use crate::{
attrs::AttrFlags,
db::DefDatabase,
expr_store::{
- ExpressionStore, ExpressionStoreSourceMap,
+ Body, ExpressionStore, ExpressionStoreBuilder, ExpressionStoreSourceMap,
lower::{
ExprCollector, lower_function, lower_generic_params, lower_trait, lower_type_alias,
},
@@ -32,7 +32,7 @@ use crate::{
hir::{ExprId, PatId, generics::GenericParams},
item_tree::{FieldsShape, RawVisibility, visibility_from_ast},
src::HasSource,
- type_ref::{TraitRef, TypeBound, TypeRefId},
+ type_ref::{ConstRef, TraitRef, TypeBound, TypeRefId},
};
#[inline]
@@ -43,8 +43,8 @@ fn as_name_opt(name: Option<ast::Name>) -> Name {
#[derive(Debug, PartialEq, Eq)]
pub struct StructSignature {
pub name: Name,
- pub generic_params: Arc<GenericParams>,
- pub store: Arc<ExpressionStore>,
+ pub generic_params: GenericParams,
+ pub store: ExpressionStore,
pub flags: StructFlags,
pub shape: FieldsShape,
}
@@ -71,8 +71,18 @@ bitflags! {
}
}
+#[salsa::tracked]
impl StructSignature {
- pub fn query(db: &dyn DefDatabase, id: StructId) -> (Arc<Self>, Arc<ExpressionStoreSourceMap>) {
+ #[salsa::tracked(returns(deref))]
+ pub fn of(db: &dyn DefDatabase, id: StructId) -> Arc<Self> {
+ Self::with_source_map(db, id).0.clone()
+ }
+
+ #[salsa::tracked(returns(ref))]
+ pub fn with_source_map(
+ db: &dyn DefDatabase,
+ id: StructId,
+ ) -> (Arc<Self>, ExpressionStoreSourceMap) {
let loc = id.lookup(db);
let InFile { file_id, value: source } = loc.source(db);
let attrs = AttrFlags::query(db, id.into());
@@ -115,10 +125,12 @@ impl StructSignature {
shape,
name: as_name_opt(source.name()),
}),
- Arc::new(source_map),
+ source_map,
)
}
+}
+impl StructSignature {
#[inline]
pub fn repr(&self, db: &dyn DefDatabase, id: StructId) -> Option<ReprOptions> {
if self.flags.contains(StructFlags::HAS_REPR) {
@@ -141,13 +153,23 @@ fn adt_shape(adt_kind: ast::StructKind) -> FieldsShape {
#[derive(Debug, PartialEq, Eq)]
pub struct UnionSignature {
pub name: Name,
- pub generic_params: Arc<GenericParams>,
- pub store: Arc<ExpressionStore>,
+ pub generic_params: GenericParams,
+ pub store: ExpressionStore,
pub flags: StructFlags,
}
+#[salsa::tracked]
impl UnionSignature {
- pub fn query(db: &dyn DefDatabase, id: UnionId) -> (Arc<Self>, Arc<ExpressionStoreSourceMap>) {
+ #[salsa::tracked(returns(deref))]
+ pub fn of(db: &dyn DefDatabase, id: UnionId) -> Arc<Self> {
+ Self::with_source_map(db, id).0.clone()
+ }
+
+ #[salsa::tracked(returns(ref))]
+ pub fn with_source_map(
+ db: &dyn DefDatabase,
+ id: UnionId,
+ ) -> (Arc<Self>, ExpressionStoreSourceMap) {
let loc = id.lookup(db);
let attrs = AttrFlags::query(db, id.into());
let mut flags = StructFlags::empty();
@@ -177,7 +199,7 @@ impl UnionSignature {
flags,
name: as_name_opt(source.name()),
}),
- Arc::new(source_map),
+ source_map,
)
}
}
@@ -195,13 +217,23 @@ bitflags! {
#[derive(Debug, PartialEq, Eq)]
pub struct EnumSignature {
pub name: Name,
- pub generic_params: Arc<GenericParams>,
- pub store: Arc<ExpressionStore>,
+ pub generic_params: GenericParams,
+ pub store: ExpressionStore,
pub flags: EnumFlags,
}
+#[salsa::tracked]
impl EnumSignature {
- pub fn query(db: &dyn DefDatabase, id: EnumId) -> (Arc<Self>, Arc<ExpressionStoreSourceMap>) {
+ #[salsa::tracked(returns(deref))]
+ pub fn of(db: &dyn DefDatabase, id: EnumId) -> Arc<Self> {
+ Self::with_source_map(db, id).0.clone()
+ }
+
+ #[salsa::tracked(returns(ref))]
+ pub fn with_source_map(
+ db: &dyn DefDatabase,
+ id: EnumId,
+ ) -> (Arc<Self>, ExpressionStoreSourceMap) {
let loc = id.lookup(db);
let attrs = AttrFlags::query(db, id.into());
let mut flags = EnumFlags::empty();
@@ -229,10 +261,12 @@ impl EnumSignature {
flags,
name: as_name_opt(source.name()),
}),
- Arc::new(source_map),
+ source_map,
)
}
+}
+impl EnumSignature {
pub fn variant_body_type(db: &dyn DefDatabase, id: EnumId) -> IntegerType {
match AttrFlags::repr(db, id.into()) {
Some(ReprOptions { int: Some(builtin), .. }) => builtin,
@@ -256,14 +290,24 @@ bitflags::bitflags! {
#[derive(Debug, PartialEq, Eq)]
pub struct ConstSignature {
pub name: Option<Name>,
- // generic_params: Arc<GenericParams>,
- pub store: Arc<ExpressionStore>,
+ // generic_params: GenericParams,
+ pub store: ExpressionStore,
pub type_ref: TypeRefId,
pub flags: ConstFlags,
}
+#[salsa::tracked]
impl ConstSignature {
- pub fn query(db: &dyn DefDatabase, id: ConstId) -> (Arc<Self>, Arc<ExpressionStoreSourceMap>) {
+ #[salsa::tracked(returns(deref))]
+ pub fn of(db: &dyn DefDatabase, id: ConstId) -> Arc<Self> {
+ Self::with_source_map(db, id).0.clone()
+ }
+
+ #[salsa::tracked(returns(ref))]
+ pub fn with_source_map(
+ db: &dyn DefDatabase,
+ id: ConstId,
+ ) -> (Arc<Self>, ExpressionStoreSourceMap) {
let loc = id.lookup(db);
let module = loc.container.module(db);
@@ -282,15 +326,17 @@ impl ConstSignature {
(
Arc::new(ConstSignature {
- store: Arc::new(store),
+ store,
type_ref,
flags,
name: source.value.name().map(|it| it.as_name()),
}),
- Arc::new(source_map),
+ source_map,
)
}
+}
+impl ConstSignature {
pub fn has_body(&self) -> bool {
self.flags.contains(ConstFlags::HAS_BODY)
}
@@ -312,13 +358,24 @@ bitflags::bitflags! {
pub struct StaticSignature {
pub name: Name,
- // generic_params: Arc<GenericParams>,
- pub store: Arc<ExpressionStore>,
+ // generic_params: GenericParams,
+ pub store: ExpressionStore,
pub type_ref: TypeRefId,
pub flags: StaticFlags,
}
+
+#[salsa::tracked]
impl StaticSignature {
- pub fn query(db: &dyn DefDatabase, id: StaticId) -> (Arc<Self>, Arc<ExpressionStoreSourceMap>) {
+ #[salsa::tracked(returns(deref))]
+ pub fn of(db: &dyn DefDatabase, id: StaticId) -> Arc<Self> {
+ Self::with_source_map(db, id).0.clone()
+ }
+
+ #[salsa::tracked(returns(ref))]
+ pub fn with_source_map(
+ db: &dyn DefDatabase,
+ id: StaticId,
+ ) -> (Arc<Self>, ExpressionStoreSourceMap) {
let loc = id.lookup(db);
let module = loc.container.module(db);
@@ -351,12 +408,12 @@ impl StaticSignature {
(
Arc::new(StaticSignature {
- store: Arc::new(store),
+ store,
type_ref,
flags,
name: as_name_opt(source.value.name()),
}),
- Arc::new(source_map),
+ source_map,
)
}
}
@@ -372,15 +429,25 @@ bitflags::bitflags! {
#[derive(Debug, PartialEq, Eq)]
pub struct ImplSignature {
- pub generic_params: Arc<GenericParams>,
- pub store: Arc<ExpressionStore>,
+ pub generic_params: GenericParams,
+ pub store: ExpressionStore,
pub self_ty: TypeRefId,
pub target_trait: Option<TraitRef>,
pub flags: ImplFlags,
}
+#[salsa::tracked]
impl ImplSignature {
- pub fn query(db: &dyn DefDatabase, id: ImplId) -> (Arc<Self>, Arc<ExpressionStoreSourceMap>) {
+ #[salsa::tracked(returns(deref))]
+ pub fn of(db: &dyn DefDatabase, id: ImplId) -> Arc<Self> {
+ Self::with_source_map(db, id).0.clone()
+ }
+
+ #[salsa::tracked(returns(ref))]
+ pub fn with_source_map(
+ db: &dyn DefDatabase,
+ id: ImplId,
+ ) -> (Arc<Self>, ExpressionStoreSourceMap) {
let loc = id.lookup(db);
let mut flags = ImplFlags::empty();
@@ -399,17 +466,13 @@ impl ImplSignature {
crate::expr_store::lower::lower_impl(db, loc.container, src, id);
(
- Arc::new(ImplSignature {
- store: Arc::new(store),
- generic_params,
- self_ty,
- target_trait,
- flags,
- }),
- Arc::new(source_map),
+ Arc::new(ImplSignature { store, generic_params, self_ty, target_trait, flags }),
+ source_map,
)
}
+}
+impl ImplSignature {
#[inline]
pub fn is_negative(&self) -> bool {
self.flags.contains(ImplFlags::NEGATIVE)
@@ -439,13 +502,23 @@ bitflags::bitflags! {
#[derive(Debug, PartialEq, Eq)]
pub struct TraitSignature {
pub name: Name,
- pub generic_params: Arc<GenericParams>,
- pub store: Arc<ExpressionStore>,
+ pub generic_params: GenericParams,
+ pub store: ExpressionStore,
pub flags: TraitFlags,
}
+#[salsa::tracked]
impl TraitSignature {
- pub fn query(db: &dyn DefDatabase, id: TraitId) -> (Arc<Self>, Arc<ExpressionStoreSourceMap>) {
+ #[salsa::tracked(returns(deref))]
+ pub fn of(db: &dyn DefDatabase, id: TraitId) -> Arc<Self> {
+ Self::with_source_map(db, id).0.clone()
+ }
+
+ #[salsa::tracked(returns(ref))]
+ pub fn with_source_map(
+ db: &dyn DefDatabase,
+ id: TraitId,
+ ) -> (Arc<Self>, ExpressionStoreSourceMap) {
let loc = id.lookup(db);
let mut flags = TraitFlags::empty();
@@ -483,10 +556,7 @@ impl TraitSignature {
let name = as_name_opt(source.value.name());
let (store, source_map, generic_params) = lower_trait(db, loc.container, source, id);
- (
- Arc::new(TraitSignature { store: Arc::new(store), generic_params, flags, name }),
- Arc::new(source_map),
- )
+ (Arc::new(TraitSignature { store, generic_params, flags, name }), source_map)
}
}
@@ -516,19 +586,26 @@ bitflags! {
#[derive(Debug, PartialEq, Eq)]
pub struct FunctionSignature {
pub name: Name,
- pub generic_params: Arc<GenericParams>,
- pub store: Arc<ExpressionStore>,
+ pub generic_params: GenericParams,
+ pub store: ExpressionStore,
pub params: Box<[TypeRefId]>,
pub ret_type: Option<TypeRefId>,
pub abi: Option<Symbol>,
pub flags: FnFlags,
}
+#[salsa::tracked]
impl FunctionSignature {
- pub fn query(
+ #[salsa::tracked(returns(deref))]
+ pub fn of(db: &dyn DefDatabase, id: FunctionId) -> Arc<Self> {
+ Self::with_source_map(db, id).0.clone()
+ }
+
+ #[salsa::tracked(returns(ref))]
+ pub fn with_source_map(
db: &dyn DefDatabase,
id: FunctionId,
- ) -> (Arc<Self>, Arc<ExpressionStoreSourceMap>) {
+ ) -> (Arc<Self>, ExpressionStoreSourceMap) {
let loc = id.lookup(db);
let module = loc.container.module(db);
@@ -589,17 +666,19 @@ impl FunctionSignature {
(
Arc::new(FunctionSignature {
generic_params,
- store: Arc::new(store),
+ store,
params,
ret_type,
abi,
flags,
name,
}),
- Arc::new(source_map),
+ source_map,
)
}
+}
+impl FunctionSignature {
pub fn has_body(&self) -> bool {
self.flags.contains(FnFlags::HAS_BODY)
}
@@ -656,7 +735,7 @@ impl FunctionSignature {
}
pub fn is_intrinsic(db: &dyn DefDatabase, id: FunctionId) -> bool {
- let data = db.function_signature(id);
+ let data = FunctionSignature::of(db, id);
data.flags.contains(FnFlags::RUSTC_INTRINSIC)
// Keep this around for a bit until extern "rustc-intrinsic" abis are no longer used
|| match &data.abi {
@@ -683,18 +762,25 @@ bitflags! {
#[derive(Debug, PartialEq, Eq)]
pub struct TypeAliasSignature {
pub name: Name,
- pub generic_params: Arc<GenericParams>,
- pub store: Arc<ExpressionStore>,
+ pub generic_params: GenericParams,
+ pub store: ExpressionStore,
pub bounds: Box<[TypeBound]>,
pub ty: Option<TypeRefId>,
pub flags: TypeAliasFlags,
}
+#[salsa::tracked]
impl TypeAliasSignature {
- pub fn query(
+ #[salsa::tracked(returns(deref))]
+ pub fn of(db: &dyn DefDatabase, id: TypeAliasId) -> Arc<Self> {
+ Self::with_source_map(db, id).0.clone()
+ }
+
+ #[salsa::tracked(returns(ref))]
+ pub fn with_source_map(
db: &dyn DefDatabase,
id: TypeAliasId,
- ) -> (Arc<Self>, Arc<ExpressionStoreSourceMap>) {
+ ) -> (Arc<Self>, ExpressionStoreSourceMap) {
let loc = id.lookup(db);
let mut flags = TypeAliasFlags::empty();
@@ -714,28 +800,21 @@ impl TypeAliasSignature {
lower_type_alias(db, loc.container.module(db), source, id);
(
- Arc::new(TypeAliasSignature {
- store: Arc::new(store),
- generic_params,
- flags,
- bounds,
- name,
- ty,
- }),
- Arc::new(source_map),
+ Arc::new(TypeAliasSignature { store, generic_params, flags, bounds, name, ty }),
+ source_map,
)
}
}
#[derive(Debug, PartialEq, Eq)]
pub struct FunctionBody {
- pub store: Arc<ExpressionStore>,
+ pub store: ExpressionStore,
pub parameters: Box<[PatId]>,
}
#[derive(Debug, PartialEq, Eq)]
pub struct SimpleBody {
- pub store: Arc<ExpressionStore>,
+ pub store: ExpressionStore,
}
pub type StaticBody = SimpleBody;
pub type ConstBody = SimpleBody;
@@ -743,7 +822,7 @@ pub type EnumVariantBody = SimpleBody;
#[derive(Debug, PartialEq, Eq)]
pub struct VariantFieldsBody {
- pub store: Arc<ExpressionStore>,
+ pub store: ExpressionStore,
pub fields: Box<[Option<ExprId>]>,
}
@@ -754,7 +833,7 @@ pub struct FieldData {
pub type_ref: TypeRefId,
pub visibility: RawVisibility,
pub is_unsafe: bool,
- pub default_value: Option<ExprId>,
+ pub default_value: Option<ConstRef>,
}
pub type LocalFieldId = Idx<FieldData>;
@@ -762,17 +841,17 @@ pub type LocalFieldId = Idx<FieldData>;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct VariantFields {
fields: Arena<FieldData>,
- pub store: Arc<ExpressionStore>,
+ pub store: ExpressionStore,
pub shape: FieldsShape,
}
#[salsa::tracked]
impl VariantFields {
- #[salsa::tracked(returns(clone))]
- pub(crate) fn query(
+ #[salsa::tracked(returns(ref))]
+ pub fn with_source_map(
db: &dyn DefDatabase,
id: VariantId,
- ) -> (Arc<Self>, Arc<ExpressionStoreSourceMap>) {
+ ) -> (Arc<Self>, ExpressionStoreSourceMap) {
let (shape, result) = match id {
VariantId::EnumVariantId(id) => {
let loc = id.lookup(db);
@@ -809,20 +888,26 @@ impl VariantFields {
}
};
match result {
- Some((fields, store, source_map)) => (
- Arc::new(VariantFields { fields, store: Arc::new(store), shape }),
- Arc::new(source_map),
- ),
+ Some((fields, store, source_map)) => {
+ (Arc::new(VariantFields { fields, store, shape }), source_map)
+ }
None => {
- let (store, source_map) = ExpressionStore::empty_singleton();
- (Arc::new(VariantFields { fields: Arena::default(), store, shape }), source_map)
+ let source_map = ExpressionStoreSourceMap::default();
+ (
+ Arc::new(VariantFields {
+ fields: Arena::default(),
+ store: ExpressionStoreBuilder::default().finish().0,
+ shape,
+ }),
+ source_map,
+ )
}
}
}
#[salsa::tracked(returns(deref))]
- pub(crate) fn firewall(db: &dyn DefDatabase, id: VariantId) -> Arc<Self> {
- Self::query(db, id).0
+ pub fn of(db: &dyn DefDatabase, id: VariantId) -> Arc<Self> {
+ Self::with_source_map(db, id).0.clone()
}
}
@@ -873,7 +958,7 @@ fn lower_fields<Field: ast::HasAttrs + ast::HasVisibility>(
override_visibility: Option<Option<ast::Visibility>>,
) -> Option<(Arena<FieldData>, ExpressionStore, ExpressionStoreSourceMap)> {
let cfg_options = module.krate(db).cfg_options(db);
- let mut col = ExprCollector::new(db, module, fields.file_id);
+ let mut col = ExprCollector::signature(db, module, fields.file_id);
let override_visibility = override_visibility.map(|vis| {
LazyCell::new(|| {
let span_map = db.span_map(fields.file_id);
@@ -907,9 +992,9 @@ fn lower_fields<Field: ast::HasAttrs + ast::HasVisibility>(
// Check if field has default value (only for record fields)
let default_value = ast::RecordField::cast(field.syntax().clone())
- .and_then(|rf| rf.eq_token().is_some().then_some(rf.expr()))
+ .and_then(|rf| rf.eq_token().is_some().then_some(rf.default_val()))
.flatten()
- .map(|expr| col.collect_expr_opt(Some(expr)));
+ .map(|expr| col.lower_const_arg(expr));
arena.alloc(FieldData { name, type_ref, visibility, is_unsafe, default_value });
idx += 1;
@@ -1014,9 +1099,9 @@ impl EnumVariants {
}
// The outer if condition is whether this variant has const ctor or not
if !matches!(variant.shape, FieldsShape::Unit) {
- let body = db.body(v.into());
+ let body = Body::of(db, v.into());
// A variant with explicit discriminant
- if !matches!(body[body.body_expr], crate::hir::Expr::Missing) {
+ if !matches!(body[body.root_expr()], crate::hir::Expr::Missing) {
return false;
}
}
diff --git a/crates/hir-def/src/src.rs b/crates/hir-def/src/src.rs
index 6fe016f1e6..e33fd95908 100644
--- a/crates/hir-def/src/src.rs
+++ b/crates/hir-def/src/src.rs
@@ -7,7 +7,7 @@ use syntax::{AstNode, AstPtr, ast};
use crate::{
AstIdLoc, GenericDefId, LocalFieldId, LocalLifetimeParamId, LocalTypeOrConstParamId, Lookup,
- UseId, VariantId, attrs::AttrFlags, db::DefDatabase,
+ UseId, VariantId, attrs::AttrFlags, db::DefDatabase, hir::generics::GenericParams,
};
pub trait HasSource {
@@ -76,7 +76,7 @@ impl HasChildSource<LocalTypeOrConstParamId> for GenericDefId {
&self,
db: &dyn DefDatabase,
) -> InFile<ArenaMap<LocalTypeOrConstParamId, Self::Value>> {
- let generic_params = db.generic_params(*self);
+ let generic_params = GenericParams::of(db, *self);
let mut idx_iter = generic_params.iter_type_or_consts().map(|(idx, _)| idx);
let (file_id, generic_params_list) = self.file_id_and_params_of(db);
@@ -110,7 +110,7 @@ impl HasChildSource<LocalLifetimeParamId> for GenericDefId {
&self,
db: &dyn DefDatabase,
) -> InFile<ArenaMap<LocalLifetimeParamId, Self::Value>> {
- let generic_params = db.generic_params(*self);
+ let generic_params = GenericParams::of(db, *self);
let idx_iter = generic_params.iter_lt().map(|(idx, _)| idx);
let (file_id, generic_params_list) = self.file_id_and_params_of(db);
diff --git a/crates/hir-def/src/test_db.rs b/crates/hir-def/src/test_db.rs
index e8377fde49..0d260279f9 100644
--- a/crates/hir-def/src/test_db.rs
+++ b/crates/hir-def/src/test_db.rs
@@ -15,6 +15,7 @@ use triomphe::Arc;
use crate::{
Lookup, ModuleDefId, ModuleId,
db::DefDatabase,
+ expr_store::{Body, scope::ExprScopes},
nameres::{DefMap, ModuleSource, block_def_map, crate_def_map},
src::HasSource,
};
@@ -284,8 +285,8 @@ impl TestDB {
// Find the innermost block expression that has a `DefMap`.
let (def_with_body, file_id) = fn_def?;
let def_with_body = def_with_body.into();
- let source_map = self.body_with_source_map(def_with_body).1;
- let scopes = self.expr_scopes(def_with_body);
+ let source_map = &Body::with_source_map(self, def_with_body).1;
+ let scopes = ExprScopes::body_expr_scopes(self, def_with_body);
let root_syntax_node = self.parse(file_id).syntax_node();
let scope_iter =
diff --git a/crates/hir-def/src/visibility.rs b/crates/hir-def/src/visibility.rs
index cb5eed1b8b..81a61ec20f 100644
--- a/crates/hir-def/src/visibility.rs
+++ b/crates/hir-def/src/visibility.rs
@@ -6,11 +6,11 @@ use base_db::Crate;
use hir_expand::{InFile, Lookup};
use la_arena::ArenaMap;
use syntax::ast::{self, HasVisibility};
-use triomphe::Arc;
use crate::{
AssocItemId, HasModule, ItemContainerId, LocalFieldId, ModuleId, TraitId, VariantId,
- db::DefDatabase, nameres::DefMap, resolver::HasResolver, src::HasSource,
+ db::DefDatabase, nameres::DefMap, resolver::HasResolver, signatures::VariantFields,
+ src::HasSource,
};
pub use crate::item_tree::{RawVisibility, VisibilityExplicitness};
@@ -277,23 +277,26 @@ impl Visibility {
}
}
-/// Resolve visibility of all specific fields of a struct or union variant.
-pub(crate) fn field_visibilities_query(
- db: &dyn DefDatabase,
- variant_id: VariantId,
-) -> Arc<ArenaMap<LocalFieldId, Visibility>> {
- let variant_fields = variant_id.fields(db);
- let fields = variant_fields.fields();
- if fields.is_empty() {
- return Arc::default();
- }
- let resolver = variant_id.module(db).resolver(db);
- let mut res = ArenaMap::default();
- for (field_id, field_data) in fields.iter() {
- res.insert(field_id, Visibility::resolve(db, &resolver, &field_data.visibility));
+#[salsa::tracked]
+impl VariantFields {
+ /// Resolve visibility of all specific fields of a struct or union variant.
+ #[salsa::tracked(returns(ref))]
+ pub fn field_visibilities(
+ db: &dyn DefDatabase,
+ variant_id: VariantId,
+ ) -> ArenaMap<LocalFieldId, Visibility> {
+ let variant_fields = variant_id.fields(db);
+ let fields = variant_fields.fields();
+ if fields.is_empty() {
+ return ArenaMap::default();
+ }
+ let resolver = variant_id.module(db).resolver(db);
+ let mut res = ArenaMap::with_capacity(fields.len());
+ for (field_id, field_data) in fields.iter() {
+ res.insert(field_id, Visibility::resolve(db, &resolver, &field_data.visibility));
+ }
+ res
}
- res.shrink_to_fit();
- Arc::new(res)
}
pub fn visibility_from_ast(
diff --git a/crates/hir-expand/src/db.rs b/crates/hir-expand/src/db.rs
index 363465fdda..020731cf9a 100644
--- a/crates/hir-expand/src/db.rs
+++ b/crates/hir-expand/src/db.rs
@@ -58,8 +58,8 @@ pub trait ExpandDatabase: RootQueryDb {
fn proc_macros_for_crate(&self, krate: Crate) -> Option<Arc<CrateProcMacros>>;
#[salsa::invoke(ast_id_map)]
- #[salsa::lru(1024)]
- fn ast_id_map(&self, file_id: HirFileId) -> Arc<AstIdMap>;
+ #[salsa::transparent]
+ fn ast_id_map(&self, file_id: HirFileId) -> &AstIdMap;
#[salsa::transparent]
fn resolve_span(&self, span: Span) -> FileRange;
@@ -334,8 +334,9 @@ pub fn expand_speculative(
Some((node.syntax_node(), token))
}
-fn ast_id_map(db: &dyn ExpandDatabase, file_id: HirFileId) -> triomphe::Arc<AstIdMap> {
- triomphe::Arc::new(AstIdMap::from_source(&db.parse_or_expand(file_id)))
+#[salsa::tracked(lru = 1024, returns(ref))]
+fn ast_id_map(db: &dyn ExpandDatabase, file_id: HirFileId) -> AstIdMap {
+ AstIdMap::from_source(&db.parse_or_expand(file_id))
}
/// Main public API -- parses a hir file, not caring whether it's a real
diff --git a/crates/hir-ty/src/builtin_derive.rs b/crates/hir-ty/src/builtin_derive.rs
index 5a93c2b536..92629b7a05 100644
--- a/crates/hir-ty/src/builtin_derive.rs
+++ b/crates/hir-ty/src/builtin_derive.rs
@@ -80,7 +80,7 @@ pub(crate) fn generics_of<'db>(interner: DbInterner<'db>, id: BuiltinDeriveImplI
pub fn generic_params_count(db: &dyn HirDatabase, id: BuiltinDeriveImplId) -> usize {
let loc = id.loc(db);
- let adt_params = GenericParams::new(db, loc.adt.into());
+ let adt_params = GenericParams::of(db, loc.adt.into());
let extra_params_count = match loc.trait_ {
BuiltinDeriveImplTrait::Copy
| BuiltinDeriveImplTrait::Clone
@@ -128,12 +128,12 @@ pub fn impl_trait<'db>(
))
}
BuiltinDeriveImplTrait::CoerceUnsized | BuiltinDeriveImplTrait::DispatchFromDyn => {
- let generic_params = GenericParams::new(db, loc.adt.into());
+ let generic_params = GenericParams::of(db, loc.adt.into());
let interner = DbInterner::new_no_crate(db);
let args = GenericArgs::identity_for_item(interner, loc.adt.into());
let self_ty = Ty::new_adt(interner, loc.adt, args);
let Some((pointee_param_idx, _, new_param_ty)) =
- coerce_pointee_params(interner, loc, &generic_params, trait_id)
+ coerce_pointee_params(interner, loc, generic_params, trait_id)
else {
// Malformed derive.
return EarlyBinder::bind(TraitRef::new(
@@ -152,7 +152,7 @@ pub fn impl_trait<'db>(
#[salsa::tracked(returns(ref))]
pub fn predicates<'db>(db: &'db dyn HirDatabase, impl_: BuiltinDeriveImplId) -> GenericPredicates {
let loc = impl_.loc(db);
- let generic_params = GenericParams::new(db, loc.adt.into());
+ let generic_params = GenericParams::of(db, loc.adt.into());
let interner = DbInterner::new_with(db, loc.module(db).krate(db));
let adt_predicates = GenericPredicates::query(db, loc.adt.into());
let trait_id = loc
@@ -168,7 +168,7 @@ pub fn predicates<'db>(db: &'db dyn HirDatabase, impl_: BuiltinDeriveImplId) ->
| BuiltinDeriveImplTrait::PartialOrd
| BuiltinDeriveImplTrait::Eq
| BuiltinDeriveImplTrait::PartialEq => {
- simple_trait_predicates(interner, loc, &generic_params, adt_predicates, trait_id)
+ simple_trait_predicates(interner, loc, generic_params, adt_predicates, trait_id)
}
BuiltinDeriveImplTrait::Default => {
if matches!(loc.adt, AdtId::EnumId(_)) {
@@ -178,12 +178,12 @@ pub fn predicates<'db>(db: &'db dyn HirDatabase, impl_: BuiltinDeriveImplId) ->
.store(),
))
} else {
- simple_trait_predicates(interner, loc, &generic_params, adt_predicates, trait_id)
+ simple_trait_predicates(interner, loc, generic_params, adt_predicates, trait_id)
}
}
BuiltinDeriveImplTrait::CoerceUnsized | BuiltinDeriveImplTrait::DispatchFromDyn => {
let Some((pointee_param_idx, pointee_param_id, new_param_ty)) =
- coerce_pointee_params(interner, loc, &generic_params, trait_id)
+ coerce_pointee_params(interner, loc, generic_params, trait_id)
else {
// Malformed derive.
return GenericPredicates::from_explicit_own_predicates(StoredEarlyBinder::bind(
diff --git a/crates/hir-ty/src/consteval.rs b/crates/hir-ty/src/consteval.rs
index 07e9f70fae..928396c63a 100644
--- a/crates/hir-ty/src/consteval.rs
+++ b/crates/hir-ty/src/consteval.rs
@@ -5,10 +5,11 @@ mod tests;
use base_db::Crate;
use hir_def::{
- ConstId, EnumVariantId, GeneralConstId, HasModule, StaticId,
+ ConstId, EnumVariantId, ExpressionStoreOwnerId, GeneralConstId, GenericDefId, HasModule,
+ StaticId,
attrs::AttrFlags,
builtin_type::{BuiltinInt, BuiltinType, BuiltinUint},
- expr_store::Body,
+ expr_store::{Body, ExpressionStore},
hir::{Expr, ExprId, Literal},
};
use hir_expand::Lookup;
@@ -235,6 +236,7 @@ pub fn try_const_usize<'db>(db: &'db dyn HirDatabase, c: Const<'db>) -> Option<u
let ec = db.const_eval_static(id).ok()?;
try_const_usize(db, ec)
}
+ GeneralConstId::AnonConstId(_) => None,
},
ConstKind::Value(val) => Some(u128::from_le_bytes(pad16(&val.value.inner().memory, false))),
ConstKind::Error(_) => None,
@@ -258,6 +260,7 @@ pub fn try_const_isize<'db>(db: &'db dyn HirDatabase, c: &Const<'db>) -> Option<
let ec = db.const_eval_static(id).ok()?;
try_const_isize(db, &ec)
}
+ GeneralConstId::AnonConstId(_) => None,
},
ConstKind::Value(val) => Some(i128::from_le_bytes(pad16(&val.value.inner().memory, true))),
ConstKind::Error(_) => None,
@@ -271,9 +274,9 @@ pub(crate) fn const_eval_discriminant_variant(
) -> Result<i128, ConstEvalError> {
let interner = DbInterner::new_no_crate(db);
let def = variant_id.into();
- let body = db.body(def);
+ let body = Body::of(db, def);
let loc = variant_id.lookup(db);
- if matches!(body[body.body_expr], Expr::Missing) {
+ if matches!(body[body.root_expr()], Expr::Missing) {
let prev_idx = loc.index.checked_sub(1);
let value = match prev_idx {
Some(prev_idx) => {
@@ -292,7 +295,7 @@ pub(crate) fn const_eval_discriminant_variant(
let mir_body = db.monomorphized_mir_body(
def,
GenericArgs::empty(interner).store(),
- ParamEnvAndCrate { param_env: db.trait_environment_for_body(def), krate: def.krate(db) }
+ ParamEnvAndCrate { param_env: db.trait_environment(def.into()), krate: def.krate(db) }
.store(),
)?;
let c = interpret_mir(db, mir_body, false, None)?.0?;
@@ -309,23 +312,23 @@ pub(crate) fn const_eval_discriminant_variant(
// and make this function private. See the fixme comment on `InferenceContext::resolve_all`.
pub(crate) fn eval_to_const<'db>(expr: ExprId, ctx: &mut InferenceContext<'_, 'db>) -> Const<'db> {
let infer = ctx.fixme_resolve_all_clone();
- fn has_closure(body: &Body, expr: ExprId) -> bool {
- if matches!(body[expr], Expr::Closure { .. }) {
+ fn has_closure(store: &ExpressionStore, expr: ExprId) -> bool {
+ if matches!(store[expr], Expr::Closure { .. }) {
return true;
}
let mut r = false;
- body.walk_child_exprs(expr, |idx| r |= has_closure(body, idx));
+ store.walk_child_exprs(expr, |idx| r |= has_closure(store, idx));
r
}
- if has_closure(ctx.body, expr) {
+ if has_closure(ctx.store, expr) {
// Type checking clousres need an isolated body (See the above FIXME). Bail out early to prevent panic.
return Const::error(ctx.interner());
}
- if let Expr::Path(p) = &ctx.body[expr] {
+ if let Expr::Path(p) = &ctx.store[expr] {
let mut ctx = TyLoweringContext::new(
ctx.db,
&ctx.resolver,
- ctx.body,
+ ctx.store,
ctx.generic_def,
LifetimeElisionKind::Infer,
);
@@ -333,7 +336,9 @@ pub(crate) fn eval_to_const<'db>(expr: ExprId, ctx: &mut InferenceContext<'_, 'd
return c;
}
}
- if let Ok(mir_body) = lower_body_to_mir(ctx.db, ctx.owner, ctx.body, &infer, expr)
+ if let Some(body_owner) = ctx.owner.as_def_with_body()
+ && let Ok(mir_body) =
+ lower_body_to_mir(ctx.db, body_owner, Body::of(ctx.db, body_owner), &infer, expr)
&& let Ok((Ok(result), _)) = interpret_mir(ctx.db, Arc::new(mir_body), true, None)
{
return result;
@@ -370,8 +375,12 @@ pub(crate) fn const_eval<'db>(
let body = db.monomorphized_mir_body(
def.into(),
subst,
- ParamEnvAndCrate { param_env: db.trait_environment(def.into()), krate: def.krate(db) }
- .store(),
+ ParamEnvAndCrate {
+ param_env: db
+ .trait_environment(ExpressionStoreOwnerId::from(GenericDefId::from(def))),
+ krate: def.krate(db),
+ }
+ .store(),
)?;
let c = interpret_mir(db, body, false, trait_env.as_ref().map(|env| env.as_ref()))?.0?;
Ok(c.store())
@@ -407,7 +416,8 @@ pub(crate) fn const_eval_static<'db>(
def.into(),
GenericArgs::empty(interner).store(),
ParamEnvAndCrate {
- param_env: db.trait_environment_for_body(def.into()),
+ param_env: db
+ .trait_environment(ExpressionStoreOwnerId::from(GenericDefId::from(def))),
krate: def.krate(db),
}
.store(),
diff --git a/crates/hir-ty/src/consteval/tests.rs b/crates/hir-ty/src/consteval/tests.rs
index 5f6bcb4a60..31cf86476f 100644
--- a/crates/hir-ty/src/consteval/tests.rs
+++ b/crates/hir-ty/src/consteval/tests.rs
@@ -1,5 +1,5 @@
use base_db::RootQueryDb;
-use hir_def::db::DefDatabase;
+use hir_def::signatures::ConstSignature;
use hir_expand::EditionedFileId;
use rustc_apfloat::{
Float,
@@ -131,7 +131,11 @@ fn eval_goal(db: &TestDB, file_id: EditionedFileId) -> Result<Const<'_>, ConstEv
.declarations()
.find_map(|x| match x {
hir_def::ModuleDefId::ConstId(x) => {
- if db.const_signature(x).name.as_ref()?.display(db, file_id.edition(db)).to_string()
+ if ConstSignature::of(db, x)
+ .name
+ .as_ref()?
+ .display(db, file_id.edition(db))
+ .to_string()
== "GOAL"
{
Some(x)
diff --git a/crates/hir-ty/src/db.rs b/crates/hir-ty/src/db.rs
index 70474fc469..a0fb75397a 100644
--- a/crates/hir-ty/src/db.rs
+++ b/crates/hir-ty/src/db.rs
@@ -5,9 +5,9 @@ use base_db::{Crate, target::TargetLoadError};
use either::Either;
use hir_def::{
AdtId, BuiltinDeriveImplId, CallableDefId, ConstId, ConstParamId, DefWithBodyId, EnumVariantId,
- FunctionId, GenericDefId, ImplId, LifetimeParamId, LocalFieldId, StaticId, TraitId,
- TypeAliasId, VariantId, builtin_derive::BuiltinDeriveImplMethod, db::DefDatabase, hir::ExprId,
- layout::TargetDataLayout,
+ ExpressionStoreOwnerId, FunctionId, GenericDefId, ImplId, LifetimeParamId, LocalFieldId,
+ StaticId, TraitId, TypeAliasId, VariantId, builtin_derive::BuiltinDeriveImplMethod,
+ db::DefDatabase, hir::ExprId, layout::TargetDataLayout,
};
use la_arena::ArenaMap;
use salsa::plumbing::AsId;
@@ -178,13 +178,9 @@ pub trait HirDatabase: DefDatabase + std::fmt::Debug {
def: CallableDefId,
) -> EarlyBinder<'db, PolyFnSig<'db>>;
- #[salsa::invoke(crate::lower::trait_environment_for_body_query)]
- #[salsa::transparent]
- fn trait_environment_for_body<'db>(&'db self, def: DefWithBodyId) -> ParamEnv<'db>;
-
#[salsa::invoke(crate::lower::trait_environment)]
#[salsa::transparent]
- fn trait_environment<'db>(&'db self, def: GenericDefId) -> ParamEnv<'db>;
+ fn trait_environment<'db>(&'db self, def: ExpressionStoreOwnerId) -> ParamEnv<'db>;
#[salsa::invoke(crate::lower::generic_defaults_with_diagnostics_query)]
#[salsa::cycle(cycle_result = crate::lower::generic_defaults_with_diagnostics_cycle_result)]
@@ -240,7 +236,7 @@ pub struct InternedOpaqueTyId {
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
-pub struct InternedClosure(pub DefWithBodyId, pub ExprId);
+pub struct InternedClosure(pub ExpressionStoreOwnerId, pub ExprId);
#[salsa_macros::interned(no_lifetime, debug, revisions = usize::MAX)]
#[derive(PartialOrd, Ord)]
@@ -249,7 +245,7 @@ pub struct InternedClosureId {
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
-pub struct InternedCoroutine(pub DefWithBodyId, pub ExprId);
+pub struct InternedCoroutine(pub ExpressionStoreOwnerId, pub ExprId);
#[salsa_macros::interned(no_lifetime, debug, revisions = usize::MAX)]
#[derive(PartialOrd, Ord)]
diff --git a/crates/hir-ty/src/diagnostics/decl_check.rs b/crates/hir-ty/src/diagnostics/decl_check.rs
index 0931b85965..89d8c0e91d 100644
--- a/crates/hir-ty/src/diagnostics/decl_check.rs
+++ b/crates/hir-ty/src/diagnostics/decl_check.rs
@@ -17,8 +17,17 @@ use std::fmt;
use hir_def::{
AdtId, ConstId, EnumId, EnumVariantId, FunctionId, HasModule, ItemContainerId, Lookup,
- ModuleDefId, ModuleId, StaticId, StructId, TraitId, TypeAliasId, UnionId, attrs::AttrFlags,
- db::DefDatabase, hir::Pat, item_tree::FieldsShape, signatures::StaticFlags, src::HasSource,
+ ModuleDefId, ModuleId, StaticId, StructId, TraitId, TypeAliasId, UnionId,
+ attrs::AttrFlags,
+ db::DefDatabase,
+ expr_store::Body,
+ hir::Pat,
+ item_tree::FieldsShape,
+ signatures::{
+ ConstSignature, EnumSignature, FunctionSignature, StaticFlags, StaticSignature,
+ StructSignature, TraitSignature, TypeAliasSignature, UnionSignature,
+ },
+ src::HasSource,
};
use hir_expand::{
HirFileId,
@@ -178,7 +187,7 @@ impl<'a> DeclValidator<'a> {
fn validate_trait(&mut self, trait_id: TraitId) {
// Check the trait name.
- let data = self.db.trait_signature(trait_id);
+ let data = TraitSignature::of(self.db, trait_id);
self.create_incorrect_case_diagnostic_for_item_name(
trait_id,
&data.name,
@@ -197,7 +206,7 @@ impl<'a> DeclValidator<'a> {
// Check the function name.
// Skipped if function is an associated item of a trait implementation.
if !self.is_trait_impl_container(container) {
- let data = self.db.function_signature(func);
+ let data = FunctionSignature::of(self.db, func);
// Don't run the lint on extern "[not Rust]" fn items with the
// #[no_mangle] attribute.
@@ -223,7 +232,7 @@ impl<'a> DeclValidator<'a> {
/// Check incorrect names for patterns inside the function body.
/// This includes function parameters except for trait implementation associated functions.
fn validate_func_body(&mut self, func: FunctionId) {
- let body = self.db.body(func.into());
+ let body = Body::of(self.db, func.into());
let edition = self.edition(func);
let mut pats_replacements = body
.pats()
@@ -250,7 +259,7 @@ impl<'a> DeclValidator<'a> {
return;
}
- let source_map = self.db.body_with_source_map(func.into()).1;
+ let source_map = &Body::with_source_map(self.db, func.into()).1;
for (id, replacement) in pats_replacements {
let Ok(source_ptr) = source_map.pat_syntax(id) else {
continue;
@@ -292,7 +301,7 @@ impl<'a> DeclValidator<'a> {
fn validate_struct(&mut self, struct_id: StructId) {
// Check the structure name.
- let data = self.db.struct_signature(struct_id);
+ let data = StructSignature::of(self.db, struct_id);
// rustc implementation excuses repr(C) since C structs predominantly don't
// use camel case.
@@ -385,7 +394,7 @@ impl<'a> DeclValidator<'a> {
fn validate_union(&mut self, union_id: UnionId) {
// Check the union name.
- let data = self.db.union_signature(union_id);
+ let data = UnionSignature::of(self.db, union_id);
// rustc implementation excuses repr(C) since C unions predominantly don't
// use camel case.
@@ -473,7 +482,7 @@ impl<'a> DeclValidator<'a> {
fn validate_enum(&mut self, enum_id: EnumId) {
// Check the enum name.
- let data = self.db.enum_signature(enum_id);
+ let data = EnumSignature::of(self.db, enum_id);
// rustc implementation excuses repr(C) since C structs predominantly don't
// use camel case.
@@ -644,7 +653,7 @@ impl<'a> DeclValidator<'a> {
return;
}
- let data = self.db.const_signature(const_id);
+ let data = ConstSignature::of(self.db, const_id);
let Some(name) = &data.name else {
return;
};
@@ -657,7 +666,7 @@ impl<'a> DeclValidator<'a> {
}
fn validate_static(&mut self, static_id: StaticId) {
- let data = self.db.static_signature(static_id);
+ let data = StaticSignature::of(self.db, static_id);
if data.flags.contains(StaticFlags::EXTERN) {
cov_mark::hit!(extern_static_incorrect_case_ignored);
return;
@@ -683,7 +692,7 @@ impl<'a> DeclValidator<'a> {
}
// Check the type alias name.
- let data = self.db.type_alias_signature(type_alias_id);
+ let data = TypeAliasSignature::of(self.db, type_alias_id);
self.create_incorrect_case_diagnostic_for_item_name(
type_alias_id,
&data.name,
diff --git a/crates/hir-ty/src/diagnostics/expr.rs b/crates/hir-ty/src/diagnostics/expr.rs
index 4e1bb6f4c5..33d9dd538d 100644
--- a/crates/hir-ty/src/diagnostics/expr.rs
+++ b/crates/hir-ty/src/diagnostics/expr.rs
@@ -21,7 +21,7 @@ use syntax::{
ast::{self, UnaryOp},
};
use tracing::debug;
-use triomphe::Arc;
+
use typed_arena::Arena;
use crate::{
@@ -76,9 +76,9 @@ impl BodyValidationDiagnostic {
validate_lints: bool,
) -> Vec<BodyValidationDiagnostic> {
let _p = tracing::info_span!("BodyValidationDiagnostic::collect").entered();
- let infer = InferenceResult::for_body(db, owner);
- let body = db.body(owner);
- let env = db.trait_environment_for_body(owner);
+ let infer = InferenceResult::of(db, owner);
+ let body = Body::of(db, owner);
+ let env = db.trait_environment(owner.into());
let interner = DbInterner::new_with(db, owner.krate(db));
let infcx =
interner.infer_ctxt().build(TypingMode::typeck_for_body(interner, owner.into()));
@@ -98,7 +98,7 @@ impl BodyValidationDiagnostic {
struct ExprValidator<'db> {
owner: DefWithBodyId,
- body: Arc<Body>,
+ body: &'db Body,
infer: &'db InferenceResult,
env: ParamEnv<'db>,
diagnostics: Vec<BodyValidationDiagnostic>,
@@ -116,10 +116,10 @@ impl<'db> ExprValidator<'db> {
let db = self.db();
let mut filter_map_next_checker = None;
// we'll pass &mut self while iterating over body.exprs, so they need to be disjoint
- let body = Arc::clone(&self.body);
+ let body = self.body;
if matches!(self.owner, DefWithBodyId::FunctionId(_)) {
- self.check_for_trailing_return(body.body_expr, &body);
+ self.check_for_trailing_return(body.root_expr(), body);
}
for (id, expr) in body.exprs() {
@@ -141,7 +141,7 @@ impl<'db> ExprValidator<'db> {
self.validate_call(id, expr, &mut filter_map_next_checker);
}
Expr::Closure { body: body_expr, .. } => {
- self.check_for_trailing_return(*body_expr, &body);
+ self.check_for_trailing_return(*body_expr, body);
}
Expr::If { .. } => {
self.check_for_unnecessary_else(id, expr);
@@ -240,7 +240,7 @@ impl<'db> ExprValidator<'db> {
.as_reference()
.map(|(match_expr_ty, ..)| match_expr_ty == pat_ty)
.unwrap_or(false))
- && types_of_subpatterns_do_match(arm.pat, &self.body, self.infer)
+ && types_of_subpatterns_do_match(arm.pat, self.body, self.infer)
{
// If we had a NotUsefulMatchArm diagnostic, we could
// check the usefulness of each pattern as we added it
@@ -388,7 +388,7 @@ impl<'db> ExprValidator<'db> {
pat: PatId,
have_errors: &mut bool,
) -> DeconstructedPat<'a, 'db> {
- let mut patcx = match_check::PatCtxt::new(self.db(), self.infer, &self.body);
+ let mut patcx = match_check::PatCtxt::new(self.db(), self.infer, self.body);
let pattern = patcx.lower_pattern(pat);
let pattern = cx.lower_pat(&pattern);
if !patcx.errors.is_empty() {
@@ -451,7 +451,7 @@ impl<'db> ExprValidator<'db> {
&& last_then_expr_ty.is_never()
{
// Only look at sources if the then branch diverges and we have an else branch.
- let source_map = self.db().body_with_source_map(self.owner).1;
+ let source_map = &Body::with_source_map(self.db(), self.owner).1;
let Ok(source_ptr) = source_map.expr_syntax(id) else {
return;
};
diff --git a/crates/hir-ty/src/diagnostics/match_check.rs b/crates/hir-ty/src/diagnostics/match_check.rs
index 8e6101e6a0..f559c26bf5 100644
--- a/crates/hir-ty/src/diagnostics/match_check.rs
+++ b/crates/hir-ty/src/diagnostics/match_check.rs
@@ -14,6 +14,7 @@ use hir_def::{
expr_store::{Body, path::Path},
hir::PatId,
item_tree::FieldsShape,
+ signatures::{StructSignature, UnionSignature},
};
use hir_expand::name::Name;
use rustc_type_ir::inherent::IntoKind;
@@ -340,12 +341,12 @@ impl<'db> HirDisplay<'db> for Pat<'db> {
VariantId::StructId(s) => write!(
f,
"{}",
- f.db.struct_signature(s).name.display(f.db, f.edition())
+ StructSignature::of(f.db, s).name.display(f.db, f.edition())
)?,
VariantId::UnionId(u) => write!(
f,
"{}",
- f.db.union_signature(u).name.display(f.db, f.edition())
+ UnionSignature::of(f.db, u).name.display(f.db, f.edition())
)?,
};
diff --git a/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs b/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs
index eda7e7e249..bc3d9bbec6 100644
--- a/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs
+++ b/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs
@@ -4,6 +4,7 @@ use std::{cell::LazyCell, fmt};
use hir_def::{
EnumId, EnumVariantId, HasModule, LocalFieldId, ModuleId, VariantId, attrs::AttrFlags,
+ signatures::VariantFields,
};
use intern::sym;
use rustc_pattern_analysis::{
@@ -363,7 +364,8 @@ impl<'a, 'db> PatCx for MatchCheckCtx<'a, 'db> {
let adt = adt_def.def_id().0;
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(|| VariantFields::field_visibilities(self.db, variant));
self.list_variant_fields(*ty, variant)
.map(move |(fid, ty)| {
diff --git a/crates/hir-ty/src/diagnostics/unsafe_check.rs b/crates/hir-ty/src/diagnostics/unsafe_check.rs
index 21f263723b..09c648139c 100644
--- a/crates/hir-ty/src/diagnostics/unsafe_check.rs
+++ b/crates/hir-ty/src/diagnostics/unsafe_check.rs
@@ -5,11 +5,12 @@ use std::mem;
use either::Either;
use hir_def::{
- AdtId, CallableDefId, DefWithBodyId, FieldId, FunctionId, VariantId,
- expr_store::{Body, path::Path},
+ AdtId, CallableDefId, DefWithBodyId, ExpressionStoreOwnerId, FieldId, FunctionId, GenericDefId,
+ VariantId,
+ expr_store::{Body, ExpressionStore, path::Path},
hir::{AsmOperand, Expr, ExprId, ExprOrPatId, InlineAsmKind, Pat, PatId, Statement, UnaryOp},
resolver::{HasResolver, ResolveValueResult, Resolver, ValueNs},
- signatures::StaticFlags,
+ signatures::{FunctionSignature, StaticFlags, StaticSignature},
type_ref::Rawness,
};
use rustc_type_ir::inherent::IntoKind;
@@ -34,15 +35,15 @@ pub fn missing_unsafe(db: &dyn HirDatabase, def: DefWithBodyId) -> MissingUnsafe
let _p = tracing::info_span!("missing_unsafe").entered();
let is_unsafe = match def {
- DefWithBodyId::FunctionId(it) => db.function_signature(it).is_unsafe(),
+ DefWithBodyId::FunctionId(it) => FunctionSignature::of(db, it).is_unsafe(),
DefWithBodyId::StaticId(_) | DefWithBodyId::ConstId(_) | DefWithBodyId::VariantId(_) => {
false
}
};
let mut res = MissingUnsafeResult { fn_is_unsafe: is_unsafe, ..MissingUnsafeResult::default() };
- let body = db.body(def);
- let infer = InferenceResult::for_body(db, def);
+ let body = Body::of(db, def);
+ let infer = InferenceResult::of(db, def);
let mut callback = |diag| match diag {
UnsafeDiagnostic::UnsafeOperation { node, inside_unsafe_block, reason } => {
if inside_unsafe_block == InsideUnsafeBlock::No {
@@ -55,8 +56,8 @@ pub fn missing_unsafe(db: &dyn HirDatabase, def: DefWithBodyId) -> MissingUnsafe
}
}
};
- let mut visitor = UnsafeVisitor::new(db, infer, &body, def, &mut callback);
- visitor.walk_expr(body.body_expr);
+ let mut visitor = UnsafeVisitor::new(db, infer, body, def.into(), &mut callback);
+ visitor.walk_expr(body.root_expr());
if !is_unsafe {
// Unsafety in function parameter patterns (that can only be union destructuring)
@@ -109,8 +110,8 @@ pub fn unsafe_operations_for_body(
callback(node);
}
};
- let mut visitor = UnsafeVisitor::new(db, infer, body, def, &mut visitor_callback);
- visitor.walk_expr(body.body_expr);
+ let mut visitor = UnsafeVisitor::new(db, infer, body, def.into(), &mut visitor_callback);
+ visitor.walk_expr(body.root_expr());
for &param in &body.params {
visitor.walk_pat(param);
}
@@ -119,8 +120,8 @@ pub fn unsafe_operations_for_body(
pub fn unsafe_operations(
db: &dyn HirDatabase,
infer: &InferenceResult,
- def: DefWithBodyId,
- body: &Body,
+ def: ExpressionStoreOwnerId,
+ body: &ExpressionStore,
current: ExprId,
callback: &mut dyn FnMut(ExprOrPatId, InsideUnsafeBlock),
) {
@@ -137,9 +138,9 @@ pub fn unsafe_operations(
struct UnsafeVisitor<'db> {
db: &'db dyn HirDatabase,
infer: &'db InferenceResult,
- body: &'db Body,
+ body: &'db ExpressionStore,
resolver: Resolver<'db>,
- def: DefWithBodyId,
+ def: ExpressionStoreOwnerId,
inside_unsafe_block: InsideUnsafeBlock,
inside_assignment: bool,
inside_union_destructure: bool,
@@ -156,13 +157,16 @@ impl<'db> UnsafeVisitor<'db> {
fn new(
db: &'db dyn HirDatabase,
infer: &'db InferenceResult,
- body: &'db Body,
- def: DefWithBodyId,
+ body: &'db ExpressionStore,
+ def: ExpressionStoreOwnerId,
unsafe_expr_cb: &'db mut dyn FnMut(UnsafeDiagnostic),
) -> Self {
let resolver = def.resolver(db);
let def_target_features = match def {
- DefWithBodyId::FunctionId(func) => TargetFeatures::from_fn(db, func),
+ ExpressionStoreOwnerId::Body(DefWithBodyId::FunctionId(func))
+ | ExpressionStoreOwnerId::Signature(GenericDefId::FunctionId(func)) => {
+ TargetFeatures::from_fn(db, func)
+ }
_ => TargetFeatures::default(),
};
let krate = resolver.krate();
@@ -431,7 +435,7 @@ impl<'db> UnsafeVisitor<'db> {
let hygiene = self.body.expr_or_pat_path_hygiene(node);
let value_or_partial = self.resolver.resolve_path_in_value_ns(self.db, path, hygiene);
if let Some(ResolveValueResult::ValueNs(ValueNs::StaticId(id))) = value_or_partial {
- let static_data = self.db.static_signature(id);
+ let static_data = StaticSignature::of(self.db, id);
if static_data.flags.contains(StaticFlags::MUTABLE) {
self.on_unsafe_op(node, UnsafetyReason::MutableStatic);
} else if static_data.flags.contains(StaticFlags::EXTERN)
diff --git a/crates/hir-ty/src/display.rs b/crates/hir-ty/src/display.rs
index 4e77e8be36..d680588645 100644
--- a/crates/hir-ty/src/display.rs
+++ b/crates/hir-ty/src/display.rs
@@ -10,15 +10,18 @@ use std::{
use base_db::{Crate, FxIndexMap};
use either::Either;
use hir_def::{
- FindPathConfig, GenericDefId, GenericParamId, HasModule, LocalFieldId, Lookup, ModuleDefId,
- ModuleId, TraitId,
+ ExpressionStoreOwnerId, FindPathConfig, GenericDefId, GenericParamId, HasModule, LocalFieldId,
+ Lookup, ModuleDefId, ModuleId, TraitId,
expr_store::{ExpressionStore, path::Path},
find_path::{self, PrefixKind},
- hir::generics::{TypeOrConstParamData, TypeParamProvenance, WherePredicate},
+ hir::generics::{GenericParams, TypeOrConstParamData, TypeParamProvenance, WherePredicate},
item_scope::ItemInNs,
item_tree::FieldsShape,
lang_item::LangItems,
- signatures::VariantFields,
+ signatures::{
+ EnumSignature, FunctionSignature, StructSignature, TraitSignature, TypeAliasSignature,
+ UnionSignature, VariantFields,
+ },
type_ref::{
ConstRef, LifetimeRef, LifetimeRefId, TraitBoundModifier, TypeBound, TypeRef, TypeRefId,
UseArgRef,
@@ -671,7 +674,9 @@ fn write_projection<'db>(
write!(
f,
">::{}",
- f.db.type_alias_signature(alias.def_id.expect_type_alias()).name.display(f.db, f.edition())
+ TypeAliasSignature::of(f.db, alias.def_id.expect_type_alias())
+ .name
+ .display(f.db, f.edition())
)?;
let proj_params = &alias.args.as_slice()[trait_ref.args.len()..];
hir_fmt_generics(f, proj_params, None, None)
@@ -853,7 +858,7 @@ fn render_const_scalar_inner<'db>(
}
TyKind::Adt(adt, _) if b.len() == 2 * size_of::<usize>() => match adt.def_id().0 {
hir_def::AdtId::StructId(s) => {
- let data = f.db.struct_signature(s);
+ let data = StructSignature::of(f.db, s);
write!(f, "&{}", data.name.display(f.db, f.edition()))?;
Ok(())
}
@@ -911,14 +916,16 @@ fn render_const_scalar_inner<'db>(
};
match def {
hir_def::AdtId::StructId(s) => {
- let data = f.db.struct_signature(s);
+ let data = StructSignature::of(f.db, s);
write!(f, "{}", data.name.display(f.db, f.edition()))?;
let field_types = f.db.field_types(s.into());
render_variant_after_name(
s.fields(f.db),
f,
field_types,
- f.db.trait_environment(def.into()),
+ f.db.trait_environment(ExpressionStoreOwnerId::from(GenericDefId::from(
+ def,
+ ))),
&layout,
args,
b,
@@ -926,7 +933,7 @@ fn render_const_scalar_inner<'db>(
)
}
hir_def::AdtId::UnionId(u) => {
- write!(f, "{}", f.db.union_signature(u).name.display(f.db, f.edition()))
+ write!(f, "{}", UnionSignature::of(f.db, u).name.display(f.db, f.edition()))
}
hir_def::AdtId::EnumId(e) => {
let Ok(target_data_layout) = f.db.target_data_layout(f.krate()) else {
@@ -950,7 +957,9 @@ fn render_const_scalar_inner<'db>(
var_id.fields(f.db),
f,
field_types,
- f.db.trait_environment(def.into()),
+ f.db.trait_environment(ExpressionStoreOwnerId::from(GenericDefId::from(
+ def,
+ ))),
var_layout,
args,
b,
@@ -1152,11 +1161,13 @@ impl<'db> HirDisplay<'db> for Ty<'db> {
write!(f, "fn ")?;
f.start_location_link(def.into());
match def {
- CallableDefId::FunctionId(ff) => {
- write!(f, "{}", db.function_signature(ff).name.display(f.db, f.edition()))?
- }
+ CallableDefId::FunctionId(ff) => write!(
+ f,
+ "{}",
+ FunctionSignature::of(db, ff).name.display(f.db, f.edition())
+ )?,
CallableDefId::StructId(s) => {
- write!(f, "{}", db.struct_signature(s).name.display(f.db, f.edition()))?
+ write!(f, "{}", StructSignature::of(db, s).name.display(f.db, f.edition()))?
}
CallableDefId::EnumVariantId(e) => {
let loc = e.lookup(db);
@@ -1235,9 +1246,11 @@ impl<'db> HirDisplay<'db> for Ty<'db> {
match f.display_kind {
DisplayKind::Diagnostics | DisplayKind::Test => {
let name = match def_id {
- hir_def::AdtId::StructId(it) => db.struct_signature(it).name.clone(),
- hir_def::AdtId::UnionId(it) => db.union_signature(it).name.clone(),
- hir_def::AdtId::EnumId(it) => db.enum_signature(it).name.clone(),
+ hir_def::AdtId::StructId(it) => {
+ StructSignature::of(db, it).name.clone()
+ }
+ hir_def::AdtId::UnionId(it) => UnionSignature::of(db, it).name.clone(),
+ hir_def::AdtId::EnumId(it) => EnumSignature::of(db, it).name.clone(),
};
write!(f, "{}", name.display(f.db, f.edition()))?;
}
@@ -1272,7 +1285,7 @@ impl<'db> HirDisplay<'db> for Ty<'db> {
write_projection(f, &alias_ty, trait_bounds_need_parens)?
}
TyKind::Foreign(alias) => {
- let type_alias = db.type_alias_signature(alias.0);
+ let type_alias = TypeAliasSignature::of(db, alias.0);
f.start_location_link(alias.0.into());
write!(f, "{}", type_alias.name.display(f.db, f.edition()))?;
f.end_location_link();
@@ -1336,8 +1349,8 @@ impl<'db> HirDisplay<'db> for Ty<'db> {
}
let sig = interner.signature_unclosure(substs.as_closure().sig(), Safety::Safe);
let sig = sig.skip_binder();
- let InternedClosure(def, _) = db.lookup_intern_closure(id);
- let infer = InferenceResult::for_body(db, def);
+ let InternedClosure(owner, _) = db.lookup_intern_closure(id);
+ let infer = InferenceResult::of(db, owner);
let (_, kind) = infer.closure_info(id);
match f.closure_style {
ClosureStyle::ImplFn => write!(f, "impl {kind:?}(")?,
@@ -1526,7 +1539,7 @@ impl<'db> HirDisplay<'db> for Ty<'db> {
let InternedCoroutine(owner, expr_id) = coroutine_id.0.loc(db);
let CoroutineArgsParts { resume_ty, yield_ty, return_ty, .. } =
subst.split_coroutine_args();
- let body = db.body(owner);
+ let body = ExpressionStore::of(db, owner);
let expr = &body[expr_id];
match expr {
hir_def::hir::Expr::Closure {
@@ -1867,7 +1880,7 @@ fn write_bounds_like_dyn_trait<'db>(
// existential) here, which is the only thing that's
// possible in actual Rust, and hence don't print it
f.start_location_link(trait_.into());
- write!(f, "{}", f.db.trait_signature(trait_).name.display(f.db, f.edition()))?;
+ write!(f, "{}", TraitSignature::of(f.db, trait_).name.display(f.db, f.edition()))?;
f.end_location_link();
if is_fn_trait {
if let [_self, params @ ..] = trait_ref.trait_ref.args.as_slice()
@@ -1930,7 +1943,7 @@ fn write_bounds_like_dyn_trait<'db>(
angle_open = true;
}
let assoc_ty_id = projection.def_id().expect_type_alias();
- let type_alias = f.db.type_alias_signature(assoc_ty_id);
+ let type_alias = TypeAliasSignature::of(f.db, assoc_ty_id);
f.start_location_link(assoc_ty_id.into());
write!(f, "{}", type_alias.name.display(f.db, f.edition()))?;
f.end_location_link();
@@ -2021,7 +2034,7 @@ impl<'db> HirDisplay<'db> for TraitRef<'db> {
fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result {
let trait_ = self.def_id.0;
f.start_location_link(trait_.into());
- write!(f, "{}", f.db.trait_signature(trait_).name.display(f.db, f.edition()))?;
+ write!(f, "{}", TraitSignature::of(f.db, trait_).name.display(f.db, f.edition()))?;
f.end_location_link();
let substs = self.args.as_slice();
hir_fmt_generic_args(f, &substs[1..], None, Some(self.self_ty()))
@@ -2128,7 +2141,7 @@ impl<'db> HirDisplayWithExpressionStore<'db> for LifetimeRefId {
LifetimeRef::Placeholder => write!(f, "'_"),
LifetimeRef::Error => write!(f, "'{{error}}"),
&LifetimeRef::Param(lifetime_param_id) => {
- let generic_params = f.db.generic_params(lifetime_param_id.parent);
+ let generic_params = GenericParams::of(f.db, lifetime_param_id.parent);
write!(
f,
"{}",
@@ -2144,7 +2157,7 @@ impl<'db> HirDisplayWithExpressionStore<'db> for TypeRefId {
match &store[*self] {
TypeRef::Never => write!(f, "!")?,
TypeRef::TypeParam(param) => {
- let generic_params = f.db.generic_params(param.parent());
+ let generic_params = GenericParams::of(f.db, param.parent());
match generic_params[param.local_id()].name() {
Some(name) => write!(f, "{}", name.display(f.db, f.edition()))?,
None => {
diff --git a/crates/hir-ty/src/drop.rs b/crates/hir-ty/src/drop.rs
index 9d6869eee9..ddc4e4ce85 100644
--- a/crates/hir-ty/src/drop.rs
+++ b/crates/hir-ty/src/drop.rs
@@ -1,6 +1,9 @@
//! Utilities for computing drop info about types.
-use hir_def::{AdtId, signatures::StructFlags};
+use hir_def::{
+ AdtId,
+ signatures::{StructFlags, StructSignature},
+};
use rustc_hash::FxHashSet;
use rustc_type_ir::inherent::{AdtDef, IntoKind};
use stdx::never;
@@ -73,8 +76,7 @@ fn has_drop_glue_impl<'db>(
}
match adt_id {
AdtId::StructId(id) => {
- if db
- .struct_signature(id)
+ if StructSignature::of(db, id)
.flags
.intersects(StructFlags::IS_MANUALLY_DROP | StructFlags::IS_PHANTOM_DATA)
{
@@ -132,9 +134,9 @@ fn has_drop_glue_impl<'db>(
TyKind::Slice(ty) => has_drop_glue_impl(infcx, ty, env, visited),
TyKind::Closure(closure_id, subst) => {
let owner = db.lookup_intern_closure(closure_id.0).0;
- let infer = InferenceResult::for_body(db, owner);
+ let infer = InferenceResult::of(db, owner);
let (captures, _) = infer.closure_info(closure_id.0);
- let env = db.trait_environment_for_body(owner);
+ let env = db.trait_environment(owner);
captures
.iter()
.map(|capture| has_drop_glue_impl(infcx, capture.ty(db, subst), env, visited))
diff --git a/crates/hir-ty/src/dyn_compatibility.rs b/crates/hir-ty/src/dyn_compatibility.rs
index 59cfd3fdc9..4c300affd8 100644
--- a/crates/hir-ty/src/dyn_compatibility.rs
+++ b/crates/hir-ty/src/dyn_compatibility.rs
@@ -4,8 +4,10 @@ use std::ops::ControlFlow;
use hir_def::{
AssocItemId, ConstId, FunctionId, GenericDefId, HasModule, TraitId, TypeAliasId,
- TypeOrConstParamId, TypeParamId, hir::generics::LocalTypeOrConstParamId,
- nameres::crate_def_map, signatures::TraitFlags,
+ TypeOrConstParamId, TypeParamId,
+ hir::generics::{GenericParams, LocalTypeOrConstParamId},
+ nameres::crate_def_map,
+ signatures::{FunctionSignature, TraitFlags, TraitSignature},
};
use rustc_hash::FxHashSet;
use rustc_type_ir::{
@@ -298,7 +300,7 @@ where
if def_map.is_unstable_feature_enabled(&intern::sym::generic_associated_type_extended) {
ControlFlow::Continue(())
} else {
- let generic_params = db.generic_params(item.into());
+ let generic_params = GenericParams::of(db, item.into());
if !generic_params.is_empty() {
cb(DynCompatibilityViolation::GAT(it))
} else {
@@ -318,7 +320,7 @@ fn virtual_call_violations_for_method<F>(
where
F: FnMut(MethodViolationCode) -> ControlFlow<()>,
{
- let func_data = db.function_signature(func);
+ let func_data = FunctionSignature::of(db, func);
if !func_data.has_self_param() {
cb(MethodViolationCode::StaticMethod)?;
}
@@ -349,7 +351,7 @@ where
cb(mvc)?;
}
- let generic_params = db.generic_params(func.into());
+ let generic_params = GenericParams::of(db, func.into());
if generic_params.len_type_or_consts() > 0 {
cb(MethodViolationCode::Generic)?;
}
@@ -371,7 +373,7 @@ where
trait_ref: pred_trait_ref,
polarity: PredicatePolarity::Positive,
}) = pred
- && let trait_data = db.trait_signature(pred_trait_ref.def_id.0)
+ && let trait_data = TraitSignature::of(db, pred_trait_ref.def_id.0)
&& trait_data.flags.contains(TraitFlags::AUTO)
&& let rustc_type_ir::TyKind::Param(ParamTy { index: 0, .. }) =
pred_trait_ref.self_ty().kind()
diff --git a/crates/hir-ty/src/dyn_compatibility/tests.rs b/crates/hir-ty/src/dyn_compatibility/tests.rs
index 5c9b06e39a..a70f98a0fe 100644
--- a/crates/hir-ty/src/dyn_compatibility/tests.rs
+++ b/crates/hir-ty/src/dyn_compatibility/tests.rs
@@ -1,6 +1,6 @@
use std::ops::ControlFlow;
-use hir_def::db::DefDatabase;
+use hir_def::signatures::TraitSignature;
use rustc_hash::{FxHashMap, FxHashSet};
use syntax::ToSmolStr;
use test_fixture::WithFixture;
@@ -40,8 +40,7 @@ fn check_dyn_compatibility<'a>(
.declarations()
.filter_map(|def| {
if let hir_def::ModuleDefId::TraitId(trait_id) = def {
- let name = db
- .trait_signature(trait_id)
+ let name = TraitSignature::of(&db, trait_id)
.name
.display_no_db(file_id.edition(&db))
.to_smolstr();
diff --git a/crates/hir-ty/src/generics.rs b/crates/hir-ty/src/generics.rs
index b1500bcdb7..822942eec3 100644
--- a/crates/hir-ty/src/generics.rs
+++ b/crates/hir-ty/src/generics.rs
@@ -20,24 +20,23 @@ use hir_def::{
},
};
use itertools::chain;
-use triomphe::Arc;
-pub fn generics(db: &dyn DefDatabase, def: GenericDefId) -> Generics {
+pub fn generics(db: &dyn DefDatabase, def: GenericDefId) -> Generics<'_> {
let parent_generics = parent_generic_def(db, def).map(|def| Box::new(generics(db, def)));
- let (params, store) = db.generic_params_and_store(def);
+ let (params, store) = GenericParams::with_store(db, def);
let has_trait_self_param = params.trait_self_param().is_some();
Generics { def, params, parent_generics, has_trait_self_param, store }
}
#[derive(Clone, Debug)]
-pub struct Generics {
+pub struct Generics<'db> {
def: GenericDefId,
- params: Arc<GenericParams>,
- store: Arc<ExpressionStore>,
- parent_generics: Option<Box<Generics>>,
+ params: &'db GenericParams,
+ store: &'db ExpressionStore,
+ parent_generics: Option<Box<Generics<'db>>>,
has_trait_self_param: bool,
}
-impl<T> ops::Index<T> for Generics
+impl<T> ops::Index<T> for Generics<'_>
where
GenericParams: ops::Index<T>,
{
@@ -47,13 +46,13 @@ where
}
}
-impl Generics {
+impl<'db> Generics<'db> {
pub(crate) fn def(&self) -> GenericDefId {
self.def
}
pub(crate) fn store(&self) -> &ExpressionStore {
- &self.store
+ self.store
}
pub(crate) fn where_predicates(&self) -> impl Iterator<Item = &WherePredicate> {
@@ -97,7 +96,7 @@ impl Generics {
) -> impl Iterator<Item = ((GenericParamId, GenericParamDataRef<'_>), &ExpressionStore)> + '_
{
self.iter_parent()
- .zip(self.parent_generics().into_iter().flat_map(|it| std::iter::repeat(&*it.store)))
+ .zip(self.parent_generics().into_iter().flat_map(|it| std::iter::repeat(it.store)))
}
/// Iterate over the params without parent params.
@@ -185,7 +184,7 @@ impl Generics {
if param.parent == self.def {
let idx = param.local_id.into_raw().into_u32() as usize;
debug_assert!(
- idx <= self.params.len_type_or_consts(),
+ idx < self.params.len_type_or_consts(),
"idx: {} len: {}",
idx,
self.params.len_type_or_consts()
@@ -219,7 +218,7 @@ impl Generics {
}
}
- pub(crate) fn parent_generics(&self) -> Option<&Generics> {
+ pub(crate) fn parent_generics(&self) -> Option<&Generics<'db>> {
self.parent_generics.as_deref()
}
}
@@ -243,7 +242,7 @@ pub(crate) fn parent_generic_def(db: &dyn DefDatabase, def: GenericDefId) -> Opt
}
fn from_toc_id<'a>(
- it: &'a Generics,
+ it: &'a Generics<'a>,
) -> impl Fn(
(LocalTypeOrConstParamId, &'a TypeOrConstParamData),
) -> (GenericParamId, GenericParamDataRef<'a>) {
@@ -263,7 +262,7 @@ fn from_toc_id<'a>(
}
fn from_lt_id<'a>(
- it: &'a Generics,
+ it: &'a Generics<'a>,
) -> impl Fn((LocalLifetimeParamId, &'a LifetimeParamData)) -> (GenericParamId, GenericParamDataRef<'a>)
{
move |(local_id, p): (_, _)| {
diff --git a/crates/hir-ty/src/infer.rs b/crates/hir-ty/src/infer.rs
index 991acda14b..d14e9d6526 100644
--- a/crates/hir-ty/src/infer.rs
+++ b/crates/hir-ty/src/infer.rs
@@ -33,14 +33,15 @@ use std::{cell::OnceCell, convert::identity, iter};
use base_db::Crate;
use either::Either;
use hir_def::{
- AdtId, AssocItemId, ConstId, DefWithBodyId, FieldId, FunctionId, GenericDefId, GenericParamId,
- ItemContainerId, LocalFieldId, Lookup, TraitId, TupleFieldId, TupleId, TypeAliasId, VariantId,
- expr_store::{Body, ExpressionStore, HygieneId, path::Path},
+ AdtId, AssocItemId, ConstId, ConstParamId, DefWithBodyId, ExpressionStoreOwnerId, FieldId,
+ FunctionId, GenericDefId, GenericParamId, ItemContainerId, LocalFieldId, Lookup, TraitId,
+ TupleFieldId, TupleId, TypeAliasId, TypeOrConstParamId, VariantId,
+ expr_store::{Body, ExpressionStore, HygieneId, RootExprOrigin, path::Path},
hir::{BindingAnnotation, BindingId, ExprId, ExprOrPatId, LabelId, PatId},
lang_item::LangItems,
layout::Integer,
resolver::{HasResolver, ResolveValueResult, Resolver, TypeNs, ValueNs},
- signatures::{ConstSignature, EnumSignature, StaticSignature},
+ signatures::{ConstSignature, EnumSignature, FunctionSignature, StaticSignature},
type_ref::{ConstRef, LifetimeRefId, TypeRef, TypeRefId},
};
use hir_expand::{mod_path::ModPath, name::Name};
@@ -104,19 +105,18 @@ pub fn infer_query_with_inspect<'db>(
) -> InferenceResult {
let _p = tracing::info_span!("infer_query").entered();
let resolver = def.resolver(db);
- let body = db.body(def);
- let mut ctx = InferenceContext::new(db, def, &body, resolver);
+ let body = Body::of(db, def);
+ let mut ctx =
+ InferenceContext::new(db, ExpressionStoreOwnerId::Body(def), &body.store, resolver);
if let Some(inspect) = inspect {
ctx.table.infer_ctxt.attach_obligation_inspector(inspect);
}
match def {
- DefWithBodyId::FunctionId(f) => {
- ctx.collect_fn(f);
- }
- DefWithBodyId::ConstId(c) => ctx.collect_const(c, &db.const_signature(c)),
- DefWithBodyId::StaticId(s) => ctx.collect_static(&db.static_signature(s)),
+ DefWithBodyId::FunctionId(f) => ctx.collect_fn(f, body.self_param, &body.params),
+ DefWithBodyId::ConstId(c) => ctx.collect_const(c, ConstSignature::of(db, c)),
+ DefWithBodyId::StaticId(s) => ctx.collect_static(StaticSignature::of(db, s)),
DefWithBodyId::VariantId(v) => {
ctx.return_ty = match EnumSignature::variant_body_type(db, v.lookup(db).parent) {
hir_def::layout::IntegerType::Pointer(signed) => match signed {
@@ -143,10 +143,113 @@ pub fn infer_query_with_inspect<'db>(
}
}
- ctx.infer_body();
+ ctx.infer_body(body.root_expr());
+
+ ctx.infer_mut_body(body.root_expr());
+
+ infer_finalize(ctx)
+}
+
+fn infer_cycle_result(db: &dyn HirDatabase, _: salsa::Id, _: DefWithBodyId) -> InferenceResult {
+ InferenceResult {
+ has_errors: true,
+ ..InferenceResult::new(Ty::new_error(DbInterner::new_no_crate(db), ErrorGuaranteed))
+ }
+}
+
+/// Infer types for all const expressions in an item's signature.
+///
+/// This handles const expressions that appear in type positions within a generic
+/// item's signature, such as array lengths (`[T; N]`) and const generic arguments
+/// (`Foo<{ expr }>`). Each root expression is inferred independently within
+/// a shared `InferenceContext`, accumulating results into a single `InferenceResult`.
+fn infer_signature_query(db: &dyn HirDatabase, def: GenericDefId) -> InferenceResult {
+ let _p = tracing::info_span!("infer_signature_query").entered();
+ let store = ExpressionStore::of(db, def.into());
+ let mut roots = store.expr_roots_with_origins().peekable();
+ let Some(_) = roots.peek() else {
+ return InferenceResult::new(crate::next_solver::default_types(db).types.error);
+ };
+
+ let resolver = def.resolver(db);
+ let owner = ExpressionStoreOwnerId::Signature(def);
+
+ let mut ctx = InferenceContext::new(db, owner, store, resolver);
+
+ for (root_expr, origin) in roots {
+ let expected = match origin {
+ // Array lengths are always `usize`.
+ RootExprOrigin::ArrayLength => Expectation::has_type(ctx.types.types.usize),
+ // Const parameter default: look up the param's declared type.
+ RootExprOrigin::ConstParam(local_id) => Expectation::has_type(db.const_param_ty_ns(
+ ConstParamId::from_unchecked(TypeOrConstParamId { parent: def, local_id }),
+ )),
+ // Path const generic args: determining the expected type requires
+ // path resolution.
+ // FIXME
+ RootExprOrigin::GenericArgsPath => Expectation::None,
+ RootExprOrigin::BodyRoot => Expectation::None,
+ };
+ ctx.infer_expr(root_expr, &expected, ExprIsRead::Yes);
+ }
+
+ infer_finalize(ctx)
+}
+
+fn infer_variant_fields_query(db: &dyn HirDatabase, def: VariantId) -> InferenceResult {
+ let _p = tracing::info_span!("infer_variant_fields_query").entered();
+ let store = ExpressionStore::of(db, def.into());
+ let mut roots = store.expr_roots_with_origins().peekable();
+ let Some(_) = roots.peek() else {
+ return InferenceResult::new(crate::next_solver::default_types(db).types.error);
+ };
+
+ let resolver = def.resolver(db);
+ let owner = ExpressionStoreOwnerId::VariantFields(def);
+
+ let mut ctx = InferenceContext::new(db, owner, store, resolver);
+
+ for (root_expr, origin) in roots {
+ let expected = match origin {
+ // Array lengths are always `usize`.
+ RootExprOrigin::ArrayLength => Expectation::has_type(ctx.types.types.usize),
+ // unreachable
+ RootExprOrigin::ConstParam(_) => Expectation::None,
+ // Path const generic args: determining the expected type requires
+ // path resolution.
+ // FIXME
+ RootExprOrigin::GenericArgsPath => Expectation::None,
+ RootExprOrigin::BodyRoot => Expectation::None,
+ };
+ ctx.infer_expr(root_expr, &expected, ExprIsRead::Yes);
+ }
+
+ infer_finalize(ctx)
+}
+
+fn infer_signature_cycle_result(
+ db: &dyn HirDatabase,
+ _: salsa::Id,
+ _: GenericDefId,
+) -> InferenceResult {
+ InferenceResult {
+ has_errors: true,
+ ..InferenceResult::new(Ty::new_error(DbInterner::new_no_crate(db), ErrorGuaranteed))
+ }
+}
- ctx.infer_mut_body();
+fn infer_variant_fields_cycle_result(
+ db: &dyn HirDatabase,
+ _: salsa::Id,
+ _: VariantId,
+) -> InferenceResult {
+ InferenceResult {
+ has_errors: true,
+ ..InferenceResult::new(Ty::new_error(DbInterner::new_no_crate(db), ErrorGuaranteed))
+ }
+}
+fn infer_finalize(mut ctx: InferenceContext<'_, '_>) -> InferenceResult {
ctx.handle_opaque_type_uses();
ctx.type_inference_fallback();
@@ -171,14 +274,6 @@ pub fn infer_query_with_inspect<'db>(
ctx.resolve_all()
}
-
-fn infer_cycle_result(db: &dyn HirDatabase, _: salsa::Id, _: DefWithBodyId) -> InferenceResult {
- InferenceResult {
- has_errors: true,
- ..InferenceResult::new(Ty::new_error(DbInterner::new_no_crate(db), ErrorGuaranteed))
- }
-}
-
/// Binding modes inferred for patterns.
/// <https://doc.rust-lang.org/reference/patterns.html#binding-modes>
#[derive(Copy, Clone, Debug, Eq, PartialEq, Default)]
@@ -552,12 +647,39 @@ pub struct InferenceResult {
#[salsa::tracked]
impl InferenceResult {
#[salsa::tracked(returns(ref), cycle_result = infer_cycle_result)]
- pub fn for_body(db: &dyn HirDatabase, def: DefWithBodyId) -> InferenceResult {
+ fn for_body(db: &dyn HirDatabase, def: DefWithBodyId) -> InferenceResult {
infer_query(db, def)
}
+
+ /// Infer types for all const expressions in an item's signature.
+ ///
+ /// Returns an `InferenceResult` containing type information for array lengths,
+ /// const generic arguments, and other const expressions appearing in type
+ /// positions within the item's signature.
+ #[salsa::tracked(returns(ref), cycle_result = infer_signature_cycle_result)]
+ fn for_signature(db: &dyn HirDatabase, def: GenericDefId) -> InferenceResult {
+ infer_signature_query(db, def)
+ }
+
+ #[salsa::tracked(returns(ref), cycle_result = infer_variant_fields_cycle_result)]
+ fn for_variant_fields(db: &dyn HirDatabase, def: VariantId) -> InferenceResult {
+ infer_variant_fields_query(db, def)
+ }
}
impl InferenceResult {
+ pub fn of(db: &dyn HirDatabase, def: impl Into<ExpressionStoreOwnerId>) -> &InferenceResult {
+ match def.into() {
+ ExpressionStoreOwnerId::Signature(generic_def_id) => {
+ Self::for_signature(db, generic_def_id)
+ }
+ ExpressionStoreOwnerId::Body(def_with_body_id) => Self::for_body(db, def_with_body_id),
+ ExpressionStoreOwnerId::VariantFields(variant_id) => {
+ Self::for_variant_fields(db, variant_id)
+ }
+ }
+ }
+
fn new(error_ty: Ty<'_>) -> Self {
Self {
method_resolutions: Default::default(),
@@ -754,8 +876,8 @@ impl InferenceResult {
#[derive(Clone, Debug)]
pub(crate) struct InferenceContext<'body, 'db> {
pub(crate) db: &'db dyn HirDatabase,
- pub(crate) owner: DefWithBodyId,
- pub(crate) body: &'body Body,
+ pub(crate) owner: ExpressionStoreOwnerId,
+ pub(crate) store: &'body ExpressionStore,
/// Generally you should not resolve things via this resolver. Instead create a TyLoweringContext
/// and resolve the path via its methods. This will ensure proper error reporting.
pub(crate) resolver: Resolver<'db>,
@@ -855,11 +977,21 @@ fn find_continuable<'a, 'db>(
impl<'body, 'db> InferenceContext<'body, 'db> {
fn new(
db: &'db dyn HirDatabase,
- owner: DefWithBodyId,
- body: &'body Body,
+ owner: ExpressionStoreOwnerId,
+ store: &'body ExpressionStore,
resolver: Resolver<'db>,
) -> Self {
- let trait_env = db.trait_environment_for_body(owner);
+ let trait_env = match owner {
+ ExpressionStoreOwnerId::Signature(generic_def_id) => {
+ db.trait_environment(ExpressionStoreOwnerId::from(generic_def_id))
+ }
+ ExpressionStoreOwnerId::Body(def_with_body_id) => {
+ db.trait_environment(ExpressionStoreOwnerId::Body(def_with_body_id))
+ }
+ ExpressionStoreOwnerId::VariantFields(variant_id) => {
+ db.trait_environment(ExpressionStoreOwnerId::VariantFields(variant_id))
+ }
+ };
let table = unify::InferenceTable::new(db, trait_env, resolver.krate(), Some(owner));
let types = crate::next_solver::default_types(db);
InferenceContext {
@@ -878,13 +1010,8 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
return_coercion: None,
db,
owner,
- generic_def: match owner {
- DefWithBodyId::FunctionId(it) => it.into(),
- DefWithBodyId::StaticId(it) => it.into(),
- DefWithBodyId::ConstId(it) => it.into(),
- DefWithBodyId::VariantId(it) => it.lookup(db).parent.into(),
- },
- body,
+ generic_def: owner.generic_def(db),
+ store,
traits_in_scope: resolver.traits_in_scope(db),
resolver,
diverges: Diverges::Maybe,
@@ -908,7 +1035,9 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
fn target_features(&self) -> (&TargetFeatures<'db>, TargetFeatureIsSafeInTarget) {
let (target_features, target_feature_is_safe) = self.target_features.get_or_init(|| {
let target_features = match self.owner {
- DefWithBodyId::FunctionId(id) => TargetFeatures::from_fn(self.db, id),
+ ExpressionStoreOwnerId::Body(DefWithBodyId::FunctionId(id)) => {
+ TargetFeatures::from_fn(self.db, id)
+ }
_ => TargetFeatures::default(),
};
let target_feature_is_safe = match &self.krate().workspace_data(self.db).target {
@@ -1102,12 +1231,12 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
self.return_ty = return_ty;
}
- fn collect_fn(&mut self, func: FunctionId) {
- let data = self.db.function_signature(func);
+ fn collect_fn(&mut self, func: FunctionId, self_param: Option<BindingId>, params: &[PatId]) {
+ let data = FunctionSignature::of(self.db, func);
let mut param_tys = self.with_ty_lowering(
&data.store,
InferenceTyDiagnosticSource::Signature,
- LifetimeElisionKind::for_fn_params(&data),
+ LifetimeElisionKind::for_fn_params(data),
|ctx| data.params.iter().map(|&type_ref| ctx.lower_ty(type_ref)).collect::<Vec<_>>(),
);
@@ -1130,13 +1259,13 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
param_tys.push(va_list_ty);
}
let mut param_tys = param_tys.into_iter().chain(iter::repeat(self.table.next_ty_var()));
- if let Some(self_param) = self.body.self_param
+ if let Some(self_param) = self_param
&& let Some(ty) = param_tys.next()
{
let ty = self.process_user_written_ty(ty);
self.write_binding_ty(self_param, ty);
}
- for (ty, pat) in param_tys.zip(&*self.body.params) {
+ for (ty, pat) in param_tys.zip(params) {
let ty = self.process_user_written_ty(ty);
self.infer_top_pat(*pat, ty, None);
@@ -1170,12 +1299,12 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
&self.table.infer_ctxt
}
- fn infer_body(&mut self) {
+ fn infer_body(&mut self, body_expr: ExprId) {
match self.return_coercion {
- Some(_) => self.infer_return(self.body.body_expr),
+ Some(_) => self.infer_return(body_expr),
None => {
_ = self.infer_expr_coerce(
- self.body.body_expr,
+ body_expr,
&Expectation::has_type(self.return_ty),
ExprIsRead::Yes,
)
@@ -1282,7 +1411,7 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
f: impl FnOnce(&mut TyLoweringContext<'db, '_>) -> R,
) -> R {
self.with_ty_lowering(
- self.body,
+ self.store,
InferenceTyDiagnosticSource::Body,
LifetimeElisionKind::Infer,
f,
@@ -1324,7 +1453,7 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
pub(crate) fn make_body_ty(&mut self, type_ref: TypeRefId) -> Ty<'db> {
self.make_ty(
type_ref,
- self.body,
+ self.store,
InferenceTyDiagnosticSource::Body,
LifetimeElisionKind::Infer,
)
@@ -1332,7 +1461,7 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
pub(crate) fn make_body_const(&mut self, const_ref: ConstRef, ty: Ty<'db>) -> Const<'db> {
let const_ = self.with_ty_lowering(
- self.body,
+ self.store,
InferenceTyDiagnosticSource::Body,
LifetimeElisionKind::Infer,
|ctx| ctx.lower_const(const_ref, ty),
@@ -1342,7 +1471,7 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
pub(crate) fn make_path_as_body_const(&mut self, path: &Path, ty: Ty<'db>) -> Const<'db> {
let const_ = self.with_ty_lowering(
- self.body,
+ self.store,
InferenceTyDiagnosticSource::Body,
LifetimeElisionKind::Infer,
|ctx| ctx.lower_path_as_const(path, ty),
@@ -1356,7 +1485,7 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
pub(crate) fn make_body_lifetime(&mut self, lifetime_ref: LifetimeRefId) -> Region<'db> {
let lt = self.with_ty_lowering(
- self.body,
+ self.store,
InferenceTyDiagnosticSource::Body,
LifetimeElisionKind::Infer,
|ctx| ctx.lower_lifetime(lifetime_ref),
@@ -1571,7 +1700,7 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
let mut ctx = TyLoweringContext::new(
self.db,
&self.resolver,
- &self.body.store,
+ self.store,
&self.diagnostics,
InferenceTyDiagnosticSource::Body,
self.generic_def,
diff --git a/crates/hir-ty/src/infer/cast.rs b/crates/hir-ty/src/infer/cast.rs
index fc38361d7e..e5ee734474 100644
--- a/crates/hir-ty/src/infer/cast.rs
+++ b/crates/hir-ty/src/infer/cast.rs
@@ -1,6 +1,10 @@
//! Type cast logic. Basically coercion + additional casts.
-use hir_def::{AdtId, hir::ExprId, signatures::TraitFlags};
+use hir_def::{
+ AdtId,
+ hir::ExprId,
+ signatures::{TraitFlags, TraitSignature},
+};
use rustc_ast_ir::Mutability;
use rustc_hash::FxHashSet;
use rustc_type_ir::{
@@ -383,8 +387,7 @@ impl<'db> CastCheck<'db> {
.chain(
elaborate::supertrait_def_ids(ctx.interner(), src_principal)
.filter(|trait_| {
- ctx.db
- .trait_signature(trait_.0)
+ TraitSignature::of(ctx.db, trait_.0)
.flags
.contains(TraitFlags::AUTO)
}),
diff --git a/crates/hir-ty/src/infer/closure/analysis.rs b/crates/hir-ty/src/infer/closure/analysis.rs
index 5a3eba1a71..ce0ccfe82f 100644
--- a/crates/hir-ty/src/infer/closure/analysis.rs
+++ b/crates/hir-ty/src/infer/closure/analysis.rs
@@ -4,14 +4,15 @@ use std::{cmp, mem};
use base_db::Crate;
use hir_def::{
- DefWithBodyId, FieldId, HasModule, VariantId,
- expr_store::path::Path,
+ ExpressionStoreOwnerId, FieldId, HasModule, VariantId,
+ expr_store::{Body, ExpressionStore, path::Path},
hir::{
Array, AsmOperand, BinaryOp, BindingId, CaptureBy, Expr, ExprId, ExprOrPatId, Pat, PatId,
RecordSpread, Statement, UnaryOp,
},
item_tree::FieldsShape,
resolver::ValueNs,
+ signatures::VariantFields,
};
use rustc_ast_ir::Mutability;
use rustc_hash::{FxHashMap, FxHashSet};
@@ -179,9 +180,26 @@ impl CapturedItem {
}
/// Converts the place to a name that can be inserted into source code.
- pub fn place_to_name(&self, owner: DefWithBodyId, db: &dyn HirDatabase) -> String {
- let body = db.body(owner);
- let mut result = body[self.place.local].name.as_str().to_owned();
+ pub fn place_to_name(&self, owner: ExpressionStoreOwnerId, db: &dyn HirDatabase) -> String {
+ let krate = owner.krate(db);
+ let edition = krate.data(db).edition;
+ let mut result = match owner {
+ ExpressionStoreOwnerId::Signature(generic_def_id) => {
+ ExpressionStore::of(db, generic_def_id.into())[self.place.local]
+ .name
+ .display(db, edition)
+ .to_string()
+ }
+ ExpressionStoreOwnerId::Body(def_with_body_id) => Body::of(db, def_with_body_id)
+ [self.place.local]
+ .name
+ .display(db, edition)
+ .to_string(),
+ ExpressionStoreOwnerId::VariantFields(variant_id) => {
+ let fields = VariantFields::of(db, variant_id);
+ fields.store[self.place.local].name.display(db, edition).to_string()
+ }
+ };
for proj in &self.place.projections {
match proj {
HirPlaceProjection::Deref => {}
@@ -213,11 +231,30 @@ impl CapturedItem {
result
}
- pub fn display_place_source_code(&self, owner: DefWithBodyId, db: &dyn HirDatabase) -> String {
- let body = db.body(owner);
+ pub fn display_place_source_code(
+ &self,
+ owner: ExpressionStoreOwnerId,
+ db: &dyn HirDatabase,
+ ) -> String {
let krate = owner.krate(db);
let edition = krate.data(db).edition;
- let mut result = body[self.place.local].name.display(db, edition).to_string();
+ let mut result = match owner {
+ ExpressionStoreOwnerId::Signature(generic_def_id) => {
+ ExpressionStore::of(db, generic_def_id.into())[self.place.local]
+ .name
+ .display(db, edition)
+ .to_string()
+ }
+ ExpressionStoreOwnerId::Body(def_with_body_id) => Body::of(db, def_with_body_id)
+ [self.place.local]
+ .name
+ .display(db, edition)
+ .to_string(),
+ ExpressionStoreOwnerId::VariantFields(variant_id) => {
+ let fields = VariantFields::of(db, variant_id);
+ fields.store[self.place.local].name.display(db, edition).to_string()
+ }
+ };
for proj in &self.place.projections {
match proj {
// In source code autoderef kicks in.
@@ -258,11 +295,26 @@ impl CapturedItem {
result
}
- pub fn display_place(&self, owner: DefWithBodyId, db: &dyn HirDatabase) -> String {
- let body = db.body(owner);
+ pub fn display_place(&self, owner: ExpressionStoreOwnerId, db: &dyn HirDatabase) -> String {
let krate = owner.krate(db);
let edition = krate.data(db).edition;
- let mut result = body[self.place.local].name.display(db, edition).to_string();
+ let mut result = match owner {
+ ExpressionStoreOwnerId::Signature(generic_def_id) => {
+ ExpressionStore::of(db, generic_def_id.into())[self.place.local]
+ .name
+ .display(db, edition)
+ .to_string()
+ }
+ ExpressionStoreOwnerId::Body(def_with_body_id) => Body::of(db, def_with_body_id)
+ [self.place.local]
+ .name
+ .display(db, edition)
+ .to_string(),
+ ExpressionStoreOwnerId::VariantFields(variant_id) => {
+ let fields = VariantFields::of(db, variant_id);
+ fields.store[self.place.local].name.display(db, edition).to_string()
+ }
+ };
let mut field_need_paren = false;
for proj in &self.place.projections {
match proj {
@@ -346,7 +398,7 @@ impl<'db> InferenceContext<'_, 'db> {
if path.type_anchor().is_some() {
return None;
}
- let hygiene = self.body.expr_or_pat_path_hygiene(id);
+ let hygiene = self.store.expr_or_pat_path_hygiene(id);
self.resolver.resolve_path_in_value_ns_fully(self.db, path, hygiene).and_then(|result| {
match result {
ValueNs::LocalBinding(binding) => {
@@ -365,7 +417,7 @@ impl<'db> InferenceContext<'_, 'db> {
/// Changes `current_capture_span_stack` to contain the stack of spans for this expr.
fn place_of_expr_without_adjust(&mut self, tgt_expr: ExprId) -> Option<HirPlace> {
self.current_capture_span_stack.clear();
- match &self.body[tgt_expr] {
+ match &self.store[tgt_expr] {
Expr::Path(p) => {
let resolver_guard =
self.resolver.update_to_inner_scope(self.db, self.owner, tgt_expr);
@@ -416,7 +468,7 @@ impl<'db> InferenceContext<'_, 'db> {
let mut actual_truncate_to = 0;
for &span in &*span_stack {
actual_truncate_to += 1;
- if !span.is_ref_span(self.body) {
+ if !span.is_ref_span(self.store) {
remained -= 1;
if remained == 0 {
break;
@@ -424,7 +476,7 @@ impl<'db> InferenceContext<'_, 'db> {
}
}
if actual_truncate_to < span_stack.len()
- && span_stack[actual_truncate_to].is_ref_span(self.body)
+ && span_stack[actual_truncate_to].is_ref_span(self.store)
{
// Include the ref operator if there is one, we will fix it later (in `strip_captures_ref_span()`) if it's incorrect.
actual_truncate_to += 1;
@@ -533,7 +585,7 @@ impl<'db> InferenceContext<'_, 'db> {
}
fn walk_expr_without_adjust(&mut self, tgt_expr: ExprId) {
- match &self.body[tgt_expr] {
+ match &self.store[tgt_expr] {
Expr::OffsetOf(_) => (),
Expr::InlineAsm(e) => e.operands.iter().for_each(|(_, op)| match op {
AsmOperand::In { expr, .. }
@@ -733,7 +785,7 @@ impl<'db> InferenceContext<'_, 'db> {
self.consume_with_pat(rhs_place, target);
self.inside_assignment = false;
}
- None => self.body.walk_pats(target, &mut |pat| match &self.body[pat] {
+ None => self.store.walk_pats(target, &mut |pat| match &self.store[pat] {
Pat::Path(path) => self.mutate_path_pat(path, pat),
&Pat::Expr(expr) => {
let place = self.place_of_expr(expr);
@@ -775,7 +827,7 @@ impl<'db> InferenceContext<'_, 'db> {
update_result: &mut impl FnMut(CaptureKind),
mut for_mut: BorrowKind,
) {
- match &self.body[p] {
+ match &self.store[p] {
Pat::Ref { .. }
| Pat::Box { .. }
| Pat::Missing
@@ -819,13 +871,13 @@ impl<'db> InferenceContext<'_, 'db> {
if self.result.pat_adjustments.get(&p).is_some_and(|it| !it.is_empty()) {
for_mut = BorrowKind::Mut { kind: MutBorrowKind::ClosureCapture };
}
- self.body.walk_pats_shallow(p, |p| self.walk_pat_inner(p, update_result, for_mut));
+ self.store.walk_pats_shallow(p, |p| self.walk_pat_inner(p, update_result, for_mut));
}
fn is_upvar(&self, place: &HirPlace) -> bool {
if let Some(c) = self.current_closure {
let InternedClosure(_, root) = self.db.lookup_intern_closure(c);
- return self.body.is_binding_upvar(place.local, root);
+ return self.store.is_binding_upvar(place.local, root);
}
false
}
@@ -858,7 +910,7 @@ impl<'db> InferenceContext<'_, 'db> {
if ty.is_raw_ptr() || ty.is_union() {
capture.kind = CaptureKind::ByRef(BorrowKind::Shared);
self.truncate_capture_spans(capture, 0);
- capture.place.projections.truncate(0);
+ capture.place.projections.clear();
continue;
}
for (i, p) in capture.place.projections.iter().enumerate() {
@@ -866,7 +918,7 @@ impl<'db> InferenceContext<'_, 'db> {
&self.table.infer_ctxt,
self.table.param_env,
ty,
- self.owner.module(self.db).krate(self.db),
+ self.owner.krate(self.db),
);
if ty.is_raw_ptr() || ty.is_union() {
capture.kind = CaptureKind::ByRef(BorrowKind::Shared);
@@ -938,7 +990,7 @@ impl<'db> InferenceContext<'_, 'db> {
self.current_capture_span_stack
.extend((0..adjustments_count).map(|_| MirSpan::PatId(tgt_pat)));
'reset_span_stack: {
- match &self.body[tgt_pat] {
+ match &self.store[tgt_pat] {
Pat::Missing | Pat::Wild => (),
Pat::Tuple { args, ellipsis } => {
let (al, ar) = args.split_at(ellipsis.map_or(args.len(), |it| it as usize));
@@ -1089,7 +1141,7 @@ impl<'db> InferenceContext<'_, 'db> {
fn analyze_closure(&mut self, closure: InternedClosureId) -> FnTrait {
let InternedClosure(_, root) = self.db.lookup_intern_closure(closure);
self.current_closure = Some(closure);
- let Expr::Closure { body, capture_by, .. } = &self.body[root] else {
+ let Expr::Closure { body, capture_by, .. } = &self.store[root] else {
unreachable!("Closure expression id is always closure");
};
self.consume_expr(*body);
@@ -1133,7 +1185,7 @@ impl<'db> InferenceContext<'_, 'db> {
for capture in &mut captures {
if matches!(capture.kind, CaptureKind::ByValue) {
for span_stack in &mut capture.span_stacks {
- if span_stack[span_stack.len() - 1].is_ref_span(self.body) {
+ if span_stack[span_stack.len() - 1].is_ref_span(self.store) {
span_stack.truncate(span_stack.len() - 1);
}
}
@@ -1149,7 +1201,7 @@ impl<'db> InferenceContext<'_, 'db> {
let kind = self.analyze_closure(closure);
for (derefed_callee, callee_ty, params, expr) in exprs {
- if let &Expr::Call { callee, .. } = &self.body[expr] {
+ if let &Expr::Call { callee, .. } = &self.store[expr] {
let mut adjustments =
self.result.expr_adjustments.remove(&callee).unwrap_or_default().into_vec();
self.write_fn_trait_method_resolution(
diff --git a/crates/hir-ty/src/infer/coerce.rs b/crates/hir-ty/src/infer/coerce.rs
index e79868f4ae..47a7049248 100644
--- a/crates/hir-ty/src/infer/coerce.rs
+++ b/crates/hir-ty/src/infer/coerce.rs
@@ -1718,6 +1718,9 @@ fn coerce<'db>(
fn is_capturing_closure(db: &dyn HirDatabase, closure: InternedClosureId) -> bool {
let InternedClosure(owner, expr) = closure.loc(db);
- upvars_mentioned(db, owner)
+ let Some(body_owner) = owner.as_def_with_body() else {
+ return false;
+ };
+ upvars_mentioned(db, body_owner)
.is_some_and(|upvars| upvars.get(&expr).is_some_and(|upvars| !upvars.is_empty()))
}
diff --git a/crates/hir-ty/src/infer/expr.rs b/crates/hir-ty/src/infer/expr.rs
index 45b181eff8..dc57b1d1c2 100644
--- a/crates/hir-ty/src/infer/expr.rs
+++ b/crates/hir-ty/src/infer/expr.rs
@@ -11,6 +11,7 @@ use hir_def::{
InlineAsmKind, LabelId, Literal, Pat, PatId, RecordSpread, Statement, UnaryOp,
},
resolver::ValueNs,
+ signatures::{FunctionSignature, VariantFields},
};
use hir_def::{FunctionId, hir::ClosureKind};
use hir_expand::name::Name;
@@ -155,7 +156,7 @@ impl<'db> InferenceContext<'_, 'db> {
/// it is matching against. This is used to determine whether we should
/// perform `NeverToAny` coercions.
fn pat_guaranteed_to_constitute_read_for_never(&self, pat: PatId) -> bool {
- match &self.body[pat] {
+ match &self.store[pat] {
// Does not constitute a read.
Pat::Wild => false,
@@ -197,25 +198,25 @@ impl<'db> InferenceContext<'_, 'db> {
// FIXME(tschottdorf): this is problematic as the HIR is being scraped, but
// ref bindings are be implicit after #42640 (default match binding modes). See issue #44848.
fn contains_explicit_ref_binding(&self, pat: PatId) -> bool {
- if let Pat::Bind { id, .. } = self.body[pat]
- && matches!(self.body[id].mode, BindingAnnotation::Ref | BindingAnnotation::RefMut)
+ if let Pat::Bind { id, .. } = self.store[pat]
+ && matches!(self.store[id].mode, BindingAnnotation::Ref | BindingAnnotation::RefMut)
{
return true;
}
let mut result = false;
- self.body.walk_pats_shallow(pat, |pat| result |= self.contains_explicit_ref_binding(pat));
+ self.store.walk_pats_shallow(pat, |pat| result |= self.contains_explicit_ref_binding(pat));
result
}
fn is_syntactic_place_expr(&self, expr: ExprId) -> bool {
- match &self.body[expr] {
+ match &self.store[expr] {
// Lang item paths cannot currently be local variables or statics.
Expr::Path(Path::LangItem(_, _)) => false,
Expr::Path(Path::Normal(path)) => path.type_anchor.is_none(),
Expr::Path(path) => self
.resolver
- .resolve_path_in_value_ns_fully(self.db, path, self.body.expr_path_hygiene(expr))
+ .resolve_path_in_value_ns_fully(self.db, path, self.store.expr_path_hygiene(expr))
.is_none_or(|res| matches!(res, ValueNs::LocalBinding(_) | ValueNs::StaticId(_))),
Expr::Underscore => true,
Expr::UnaryOp { op: UnaryOp::Deref, .. } => true,
@@ -311,7 +312,7 @@ impl<'db> InferenceContext<'_, 'db> {
) -> Ty<'db> {
self.db.unwind_if_revision_cancelled();
- let expr = &self.body[tgt_expr];
+ let expr = &self.store[tgt_expr];
tracing::trace!(?expr);
let ty = match expr {
Expr::Missing => self.err_ty(),
@@ -608,7 +609,7 @@ impl<'db> InferenceContext<'_, 'db> {
Some(def) => {
let field_types = self.db.field_types(def);
let variant_data = def.fields(self.db);
- let visibilities = self.db.field_visibilities(def);
+ let visibilities = VariantFields::field_visibilities(self.db, def);
for field in fields.iter() {
let field_def = {
match variant_data.field(&field.name) {
@@ -717,7 +718,7 @@ impl<'db> InferenceContext<'_, 'db> {
// instantiations in RHS can be coerced to it. Note that this
// cannot happen in destructuring assignments because of how
// they are desugared.
- let lhs_ty = match &self.body[target] {
+ let lhs_ty = match &self.store[target] {
// LHS of assignment doesn't constitute reads.
&Pat::Expr(expr) => {
Some(self.infer_expr(expr, &Expectation::none(), ExprIsRead::No))
@@ -728,7 +729,7 @@ impl<'db> InferenceContext<'_, 'db> {
let resolution = self.resolver.resolve_path_in_value_ns_fully(
self.db,
path,
- self.body.pat_path_hygiene(target),
+ self.store.pat_path_hygiene(target),
);
self.resolver.reset_to_guard(resolver_guard);
@@ -1351,7 +1352,7 @@ impl<'db> InferenceContext<'_, 'db> {
ExprIsRead::Yes,
);
let usize = self.types.types.usize;
- let len = match self.body[repeat] {
+ let len = match self.store[repeat] {
Expr::Underscore => {
self.write_expr_ty(repeat, usize);
self.table.next_const_var()
@@ -1491,7 +1492,7 @@ impl<'db> InferenceContext<'_, 'db> {
} else {
ExprIsRead::No
};
- let ty = if contains_explicit_ref_binding(this.body, *pat) {
+ let ty = if contains_explicit_ref_binding(this.store, *pat) {
this.infer_expr(
*expr,
&Expectation::has_type(decl_ty),
@@ -1624,7 +1625,8 @@ impl<'db> InferenceContext<'_, 'db> {
},
_ => return None,
};
- let is_visible = self.db.field_visibilities(field_id.parent)[field_id.local_id]
+ let is_visible = VariantFields::field_visibilities(self.db, field_id.parent)
+ [field_id.local_id]
.is_visible_from(self.db, self.resolver.module());
if !is_visible {
if private_field.is_none() {
@@ -2117,7 +2119,7 @@ impl<'db> InferenceContext<'_, 'db> {
// the return value of an argument-position async block to an argument-position
// closure wrapped in a block.
// See <https://github.com/rust-lang/rust/issues/112225>.
- let is_closure = if let Expr::Closure { closure_kind, .. } = self.body[*arg] {
+ let is_closure = if let Expr::Closure { closure_kind, .. } = self.store[*arg] {
!matches!(closure_kind, ClosureKind::Coroutine(_))
} else {
false
@@ -2194,7 +2196,7 @@ impl<'db> InferenceContext<'_, 'db> {
_ => return Default::default(),
};
- let data = self.db.function_signature(func);
+ let data = FunctionSignature::of(self.db, func);
let Some(legacy_const_generics_indices) = data.legacy_const_generics_indices(self.db, func)
else {
return Default::default();
diff --git a/crates/hir-ty/src/infer/mutability.rs b/crates/hir-ty/src/infer/mutability.rs
index 45fa141b6d..bfe43fc928 100644
--- a/crates/hir-ty/src/infer/mutability.rs
+++ b/crates/hir-ty/src/infer/mutability.rs
@@ -14,8 +14,8 @@ use crate::{
};
impl<'db> InferenceContext<'_, 'db> {
- pub(crate) fn infer_mut_body(&mut self) {
- self.infer_mut_expr(self.body.body_expr, Mutability::Not);
+ pub(crate) fn infer_mut_body(&mut self, body_expr: ExprId) {
+ self.infer_mut_expr(body_expr, Mutability::Not);
}
fn infer_mut_expr(&mut self, tgt_expr: ExprId, mut mutability: Mutability) {
@@ -52,7 +52,7 @@ impl<'db> InferenceContext<'_, 'db> {
}
fn infer_mut_expr_without_adjust(&mut self, tgt_expr: ExprId, mutability: Mutability) {
- match &self.body[tgt_expr] {
+ match &self.store[tgt_expr] {
Expr::Missing => (),
Expr::InlineAsm(e) => {
e.operands.iter().for_each(|(_, op)| match op {
@@ -173,7 +173,7 @@ impl<'db> InferenceContext<'_, 'db> {
self.infer_mut_expr(*rhs, Mutability::Not);
}
&Expr::Assignment { target, value } => {
- self.body.walk_pats(target, &mut |pat| match self.body[pat] {
+ self.store.walk_pats(target, &mut |pat| match self.store[pat] {
Pat::Expr(expr) => self.infer_mut_expr(expr, Mutability::Mut),
Pat::ConstBlock(block) => self.infer_mut_expr(block, Mutability::Not),
_ => {}
@@ -220,8 +220,8 @@ impl<'db> InferenceContext<'_, 'db> {
/// `let (ref x0, ref x1) = *it;` we should use `Deref`.
fn pat_bound_mutability(&self, pat: PatId) -> Mutability {
let mut r = Mutability::Not;
- self.body.walk_bindings_in_pat(pat, |b| {
- if self.body[b].mode == BindingAnnotation::RefMut {
+ self.store.walk_bindings_in_pat(pat, |b| {
+ if self.store[b].mode == BindingAnnotation::RefMut {
r = Mutability::Mut;
}
});
diff --git a/crates/hir-ty/src/infer/pat.rs b/crates/hir-ty/src/infer/pat.rs
index 87fd0dace3..8033680dcc 100644
--- a/crates/hir-ty/src/infer/pat.rs
+++ b/crates/hir-ty/src/infer/pat.rs
@@ -3,9 +3,10 @@
use std::{cmp, iter};
use hir_def::{
- HasModule,
- expr_store::{Body, path::Path},
+ HasModule as _,
+ expr_store::{ExpressionStore, path::Path},
hir::{Binding, BindingAnnotation, BindingId, Expr, ExprId, Literal, Pat, PatId},
+ signatures::VariantFields,
};
use hir_expand::name::Name;
use rustc_ast_ir::Mutability;
@@ -60,7 +61,7 @@ impl<'db> InferenceContext<'_, 'db> {
Some(def) => {
let field_types = self.db.field_types(def);
let variant_data = def.fields(self.db);
- let visibilities = self.db.field_visibilities(def);
+ let visibilities = VariantFields::field_visibilities(self.db, def);
let (pre, post) = match ellipsis {
Some(idx) => subs.split_at(idx as usize),
@@ -129,7 +130,7 @@ impl<'db> InferenceContext<'_, 'db> {
Some(def) => {
let field_types = self.db.field_types(def);
let variant_data = def.fields(self.db);
- let visibilities = self.db.field_visibilities(def);
+ let visibilities = VariantFields::field_visibilities(self.db, def);
let substs = ty.as_adt().map(TupleExt::tail);
@@ -260,14 +261,14 @@ impl<'db> InferenceContext<'_, 'db> {
) -> Ty<'db> {
let mut expected = self.table.structurally_resolve_type(expected);
- if matches!(&self.body[pat], Pat::Ref { .. }) || self.inside_assignment {
+ if matches!(&self.store[pat], Pat::Ref { .. }) || self.inside_assignment {
cov_mark::hit!(match_ergonomics_ref);
// When you encounter a `&pat` pattern, reset to Move.
// This is so that `w` is by value: `let (_, &w) = &(1, &2);`
// Destructuring assignments also reset the binding mode and
// don't do match ergonomics.
default_bm = BindingMode::Move;
- } else if self.is_non_ref_pat(self.body, pat) {
+ } else if self.is_non_ref_pat(self.store, pat) {
let mut pat_adjustments = Vec::new();
while let TyKind::Ref(_lifetime, inner, mutability) = expected.kind() {
pat_adjustments.push(expected.store());
@@ -289,7 +290,7 @@ impl<'db> InferenceContext<'_, 'db> {
let default_bm = default_bm;
let expected = expected;
- let ty = match &self.body[pat] {
+ let ty = match &self.store[pat] {
Pat::Tuple { args, ellipsis } => {
self.infer_tuple_pat_like(pat, expected, default_bm, *ellipsis, args, decl)
}
@@ -485,7 +486,7 @@ impl<'db> InferenceContext<'_, 'db> {
expected: Ty<'db>,
decl: Option<DeclContext>,
) -> Ty<'db> {
- let Binding { mode, .. } = self.body[binding];
+ let Binding { mode, .. } = self.store[binding];
let mode = if mode == BindingAnnotation::Unannotated {
default_bm
} else {
@@ -569,7 +570,7 @@ impl<'db> InferenceContext<'_, 'db> {
fn infer_lit_pat(&mut self, expr: ExprId, expected: Ty<'db>) -> Ty<'db> {
// Like slice patterns, byte string patterns can denote both `&[u8; N]` and `&[u8]`.
- if let Expr::Literal(Literal::ByteString(_)) = self.body[expr]
+ if let Expr::Literal(Literal::ByteString(_)) = self.store[expr]
&& let TyKind::Ref(_, inner, _) = expected.kind()
{
let inner = self.table.try_structurally_resolve_type(inner);
@@ -590,14 +591,14 @@ impl<'db> InferenceContext<'_, 'db> {
self.infer_expr(expr, &Expectation::has_type(expected), ExprIsRead::Yes)
}
- fn is_non_ref_pat(&mut self, body: &hir_def::expr_store::Body, pat: PatId) -> bool {
- match &body[pat] {
+ fn is_non_ref_pat(&mut self, store: &hir_def::expr_store::ExpressionStore, pat: PatId) -> bool {
+ match &store[pat] {
Pat::Tuple { .. }
| Pat::TupleStruct { .. }
| Pat::Record { .. }
| Pat::Range { .. }
| Pat::Slice { .. } => true,
- Pat::Or(pats) => pats.iter().all(|p| self.is_non_ref_pat(body, *p)),
+ Pat::Or(pats) => pats.iter().all(|p| self.is_non_ref_pat(store, *p)),
Pat::Path(path) => {
// A const is a reference pattern, but other value ns things aren't (see #16131).
let resolved = self.resolve_value_path_inner(path, pat.into(), true);
@@ -605,7 +606,7 @@ impl<'db> InferenceContext<'_, 'db> {
}
Pat::ConstBlock(..) => false,
Pat::Lit(expr) => !matches!(
- body[*expr],
+ store[*expr],
Expr::Literal(Literal::String(..) | Literal::CString(..) | Literal::ByteString(..))
),
Pat::Wild
@@ -670,10 +671,10 @@ impl<'db> InferenceContext<'_, 'db> {
}
}
-pub(super) fn contains_explicit_ref_binding(body: &Body, pat_id: PatId) -> bool {
+pub(super) fn contains_explicit_ref_binding(store: &ExpressionStore, pat_id: PatId) -> bool {
let mut res = false;
- body.walk_pats(pat_id, &mut |pat| {
- res |= matches!(body[pat], Pat::Bind { id, .. } if matches!(body[id].mode, BindingAnnotation::Ref | BindingAnnotation::RefMut));
+ store.walk_pats(pat_id, &mut |pat| {
+ res |= matches!(store[pat], Pat::Bind { id, .. } if matches!(store[id].mode, BindingAnnotation::Ref | BindingAnnotation::RefMut));
});
res
}
diff --git a/crates/hir-ty/src/infer/path.rs b/crates/hir-ty/src/infer/path.rs
index 40c6fdf3cc..71d68ccd47 100644
--- a/crates/hir-ty/src/infer/path.rs
+++ b/crates/hir-ty/src/infer/path.rs
@@ -4,6 +4,7 @@ use hir_def::{
AdtId, AssocItemId, GenericDefId, ItemContainerId, Lookup,
expr_store::path::{Path, PathSegment},
resolver::{ResolveValueResult, TypeNs, ValueNs},
+ signatures::{ConstSignature, FunctionSignature},
};
use hir_expand::name::Name;
use rustc_type_ir::inherent::{SliceLike, Ty as _};
@@ -136,7 +137,7 @@ impl<'db> InferenceContext<'_, 'db> {
let mut ctx = TyLoweringContext::new(
self.db,
&self.resolver,
- self.body,
+ self.store,
&self.diagnostics,
InferenceTyDiagnosticSource::Body,
self.generic_def,
@@ -159,7 +160,7 @@ impl<'db> InferenceContext<'_, 'db> {
let ty = self.table.process_user_written_ty(ty);
self.resolve_ty_assoc_item(ty, last.name, id).map(|(it, substs)| (it, Some(substs)))?
} else {
- let hygiene = self.body.expr_or_pat_path_hygiene(id);
+ let hygiene = self.store.expr_or_pat_path_hygiene(id);
// FIXME: report error, unresolved first path segment
let value_or_partial = path_ctx.resolve_path_in_value_ns(hygiene)?;
@@ -263,7 +264,7 @@ impl<'db> InferenceContext<'_, 'db> {
trait_.trait_items(self.db).items.iter().map(|(_name, id)| *id).find_map(|item| {
match item {
AssocItemId::FunctionId(func) => {
- if segment.name == &self.db.function_signature(func).name {
+ if segment.name == &FunctionSignature::of(self.db, func).name {
Some(CandidateId::FunctionId(func))
} else {
None
@@ -271,7 +272,7 @@ impl<'db> InferenceContext<'_, 'db> {
}
AssocItemId::ConstId(konst) => {
- if self.db.const_signature(konst).name.as_ref() == Some(segment.name) {
+ if ConstSignature::of(self.db, konst).name.as_ref() == Some(segment.name) {
Some(CandidateId::ConstId(konst))
} else {
None
diff --git a/crates/hir-ty/src/infer/unify.rs b/crates/hir-ty/src/infer/unify.rs
index 2057159c46..d093412b42 100644
--- a/crates/hir-ty/src/infer/unify.rs
+++ b/crates/hir-ty/src/infer/unify.rs
@@ -3,7 +3,7 @@
use std::fmt;
use base_db::Crate;
-use hir_def::{AdtId, DefWithBodyId, GenericParamId};
+use hir_def::{AdtId, ExpressionStoreOwnerId, GenericParamId};
use hir_expand::name::Name;
use intern::sym;
use rustc_hash::FxHashSet;
@@ -147,7 +147,7 @@ impl<'db> InferenceTable<'db> {
db: &'db dyn HirDatabase,
trait_env: ParamEnv<'db>,
krate: Crate,
- owner: Option<DefWithBodyId>,
+ owner: Option<ExpressionStoreOwnerId>,
) -> Self {
let interner = DbInterner::new_with(db, krate);
let typing_mode = match owner {
diff --git a/crates/hir-ty/src/inhabitedness.rs b/crates/hir-ty/src/inhabitedness.rs
index 402e9ce969..74d66123ea 100644
--- a/crates/hir-ty/src/inhabitedness.rs
+++ b/crates/hir-ty/src/inhabitedness.rs
@@ -1,7 +1,9 @@
//! Type inhabitedness logic.
use std::ops::ControlFlow::{self, Break, Continue};
-use hir_def::{AdtId, EnumVariantId, ModuleId, VariantId, visibility::Visibility};
+use hir_def::{
+ AdtId, EnumVariantId, ModuleId, VariantId, signatures::VariantFields, visibility::Visibility,
+};
use rustc_hash::FxHashSet;
use rustc_type_ir::{
TypeSuperVisitable, TypeVisitable, TypeVisitor,
@@ -151,7 +153,11 @@ impl<'a, 'db> UninhabitedFrom<'a, 'db> {
let is_enum = matches!(variant, VariantId::EnumVariantId(..));
let field_tys = self.db().field_types(variant);
- let field_vis = if is_enum { None } else { Some(self.db().field_visibilities(variant)) };
+ let field_vis = if is_enum {
+ None
+ } else {
+ Some(VariantFields::field_visibilities(self.db(), variant))
+ };
for (fid, _) in fields.iter() {
self.visit_field(field_vis.as_ref().map(|it| it[fid]), &field_tys[fid].get(), subst)?;
diff --git a/crates/hir-ty/src/lang_items.rs b/crates/hir-ty/src/lang_items.rs
index 18feb0f46a..ae53276f56 100644
--- a/crates/hir-ty/src/lang_items.rs
+++ b/crates/hir-ty/src/lang_items.rs
@@ -1,13 +1,17 @@
//! Functions to detect special lang items
-use hir_def::{AdtId, TraitId, lang_item::LangItems, signatures::StructFlags};
+use hir_def::{
+ AdtId, TraitId,
+ lang_item::LangItems,
+ signatures::{StructFlags, StructSignature},
+};
use intern::{Symbol, sym};
use crate::db::HirDatabase;
pub fn is_box(db: &dyn HirDatabase, adt: AdtId) -> bool {
let AdtId::StructId(id) = adt else { return false };
- db.struct_signature(id).flags.contains(StructFlags::IS_BOX)
+ StructSignature::of(db, id).flags.contains(StructFlags::IS_BOX)
}
pub fn lang_items_for_bin_op(
diff --git a/crates/hir-ty/src/layout.rs b/crates/hir-ty/src/layout.rs
index 525100439f..54332122d0 100644
--- a/crates/hir-ty/src/layout.rs
+++ b/crates/hir-ty/src/layout.rs
@@ -333,7 +333,7 @@ pub fn layout_of_ty_query(
}
TyKind::Closure(id, args) => {
let def = db.lookup_intern_closure(id.0);
- let infer = InferenceResult::for_body(db, def.0);
+ let infer = InferenceResult::of(db, def.0);
let (captures, _) = infer.closure_info(id.0);
let fields = captures
.iter()
diff --git a/crates/hir-ty/src/layout/adt.rs b/crates/hir-ty/src/layout/adt.rs
index d249591718..6090ddfd45 100644
--- a/crates/hir-ty/src/layout/adt.rs
+++ b/crates/hir-ty/src/layout/adt.rs
@@ -5,7 +5,7 @@ use std::{cmp, ops::Bound};
use hir_def::{
AdtId, VariantId,
attrs::AttrFlags,
- signatures::{StructFlags, VariantFields},
+ signatures::{StructFlags, StructSignature, VariantFields},
};
use rustc_abi::{Integer, ReprOptions, TargetDataLayout};
use rustc_index::IndexVec;
@@ -41,7 +41,7 @@ pub fn layout_of_adt_query(
};
let (variants, repr, is_special_no_niche) = match def {
AdtId::StructId(s) => {
- let sig = db.struct_signature(s);
+ let sig = StructSignature::of(db, s);
let mut r = SmallVec::<[_; 1]>::new();
r.push(handle_variant(s.into(), s.fields(db))?);
(
diff --git a/crates/hir-ty/src/layout/tests.rs b/crates/hir-ty/src/layout/tests.rs
index 8c91be1d78..484ecebba5 100644
--- a/crates/hir-ty/src/layout/tests.rs
+++ b/crates/hir-ty/src/layout/tests.rs
@@ -1,6 +1,12 @@
use base_db::target::TargetData;
use either::Either;
-use hir_def::{HasModule, db::DefDatabase};
+use hir_def::{
+ DefWithBodyId, ExpressionStoreOwnerId, GenericDefId, HasModule,
+ expr_store::Body,
+ signatures::{
+ EnumSignature, FunctionSignature, StructSignature, TypeAliasSignature, UnionSignature,
+ },
+};
use project_model::{Sysroot, toolchain_info::QueryConfig};
use rustc_hash::FxHashMap;
use rustc_type_ir::inherent::GenericArgs as _;
@@ -49,18 +55,15 @@ fn eval_goal(
let adt_or_type_alias_id = scope.declarations().find_map(|x| match x {
hir_def::ModuleDefId::AdtId(x) => {
let name = match x {
- hir_def::AdtId::StructId(x) => db
- .struct_signature(x)
+ hir_def::AdtId::StructId(x) => StructSignature::of(&db, x)
.name
.display_no_db(file_id.edition(&db))
.to_smolstr(),
- hir_def::AdtId::UnionId(x) => db
- .union_signature(x)
+ hir_def::AdtId::UnionId(x) => UnionSignature::of(&db, x)
.name
.display_no_db(file_id.edition(&db))
.to_smolstr(),
- hir_def::AdtId::EnumId(x) => db
- .enum_signature(x)
+ hir_def::AdtId::EnumId(x) => EnumSignature::of(&db, x)
.name
.display_no_db(file_id.edition(&db))
.to_smolstr(),
@@ -68,8 +71,7 @@ fn eval_goal(
(name == "Goal").then_some(Either::Left(x))
}
hir_def::ModuleDefId::TypeAliasId(x) => {
- let name = db
- .type_alias_signature(x)
+ let name = TypeAliasSignature::of(&db, x)
.name
.display_no_db(file_id.edition(&db))
.to_smolstr();
@@ -90,10 +92,13 @@ fn eval_goal(
),
Either::Right(ty_id) => db.ty(ty_id.into()).instantiate_identity(),
};
- let param_env = db.trait_environment(match adt_or_type_alias_id {
- Either::Left(adt) => hir_def::GenericDefId::AdtId(adt),
- Either::Right(ty) => hir_def::GenericDefId::TypeAliasId(ty),
- });
+ let param_env = db.trait_environment(
+ match adt_or_type_alias_id {
+ Either::Left(adt) => hir_def::GenericDefId::AdtId(adt),
+ Either::Right(ty) => hir_def::GenericDefId::TypeAliasId(ty),
+ }
+ .into(),
+ );
let krate = match adt_or_type_alias_id {
Either::Left(it) => it.krate(&db),
Either::Right(it) => it.krate(&db),
@@ -123,8 +128,7 @@ fn eval_expr(
.declarations()
.find_map(|x| match x {
hir_def::ModuleDefId::FunctionId(x) => {
- let name = db
- .function_signature(x)
+ let name = FunctionSignature::of(&db, x)
.name
.display_no_db(file_id.edition(&db))
.to_smolstr();
@@ -133,15 +137,16 @@ fn eval_expr(
_ => None,
})
.unwrap();
- let hir_body = db.body(function_id.into());
+ let hir_body = Body::of(&db, function_id.into());
let b = hir_body
.bindings()
.find(|x| x.1.name.display_no_db(file_id.edition(&db)).to_smolstr() == "goal")
.unwrap()
.0;
- let infer = InferenceResult::for_body(&db, function_id.into());
+ let infer = InferenceResult::of(&db, DefWithBodyId::from(function_id));
let goal_ty = infer.type_of_binding[b].clone();
- let param_env = db.trait_environment(function_id.into());
+ let param_env =
+ db.trait_environment(ExpressionStoreOwnerId::from(GenericDefId::from(function_id)));
let krate = function_id.krate(&db);
db.layout_of_ty(goal_ty, ParamEnvAndCrate { param_env, krate }.store())
})
@@ -379,6 +384,11 @@ struct Goal(Foo<S>);
#[test]
fn simd_types() {
+ let size = 16;
+ #[cfg(not(target_arch = "s390x"))]
+ let align = 16;
+ #[cfg(target_arch = "s390x")]
+ let align = 8;
check_size_and_align(
r#"
#[repr(simd)]
@@ -386,8 +396,8 @@ fn simd_types() {
struct Goal(SimdType);
"#,
"",
- 16,
- 16,
+ size,
+ align,
);
}
diff --git a/crates/hir-ty/src/lib.rs b/crates/hir-ty/src/lib.rs
index 8d87276a0b..e6b8329ca8 100644
--- a/crates/hir-ty/src/lib.rs
+++ b/crates/hir-ty/src/lib.rs
@@ -61,8 +61,8 @@ mod tests;
use std::{hash::Hash, ops::ControlFlow};
use hir_def::{
- CallableDefId, GenericDefId, TypeAliasId, TypeOrConstParamId, TypeParamId,
- hir::generics::GenericParams, resolver::TypeNs, type_ref::Rawness,
+ CallableDefId, ExpressionStoreOwnerId, GenericDefId, TypeAliasId, TypeOrConstParamId,
+ TypeParamId, hir::generics::GenericParams, resolver::TypeNs, type_ref::Rawness,
};
use hir_expand::name::Name;
use indexmap::{IndexMap, map::Entry};
@@ -507,7 +507,7 @@ pub fn associated_type_shorthand_candidates(
let mut dedup_map = FxHashSet::default();
let param_ty = Ty::new_param(interner, param, param_idx(db, param.into()).unwrap() as u32);
// We use the ParamEnv and not the predicates because the ParamEnv elaborates bounds.
- let param_env = db.trait_environment(def);
+ let param_env = db.trait_environment(ExpressionStoreOwnerId::from(def));
for clause in param_env.clauses {
let ClauseKind::Trait(trait_clause) = clause.kind().skip_binder() else { continue };
if trait_clause.self_ty() != param_ty {
diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs
index 49594f34fd..7259099107 100644
--- a/crates/hir-ty/src/lower.rs
+++ b/crates/hir-ty/src/lower.rs
@@ -13,10 +13,10 @@ use std::{cell::OnceCell, iter, mem};
use arrayvec::ArrayVec;
use either::Either;
use hir_def::{
- AdtId, AssocItemId, CallableDefId, ConstId, ConstParamId, DefWithBodyId, EnumId, EnumVariantId,
- FunctionId, GeneralConstId, GenericDefId, GenericParamId, HasModule, ImplId, ItemContainerId,
- LifetimeParamId, LocalFieldId, Lookup, StaticId, StructId, TraitId, TypeAliasId,
- TypeOrConstParamId, TypeParamId, UnionId, VariantId,
+ AdtId, AssocItemId, CallableDefId, ConstId, ConstParamId, EnumId, EnumVariantId,
+ ExpressionStoreOwnerId, FunctionId, GeneralConstId, GenericDefId, GenericParamId, HasModule,
+ ImplId, ItemContainerId, LifetimeParamId, LocalFieldId, Lookup, StaticId, StructId, TraitId,
+ TypeAliasId, TypeOrConstParamId, TypeParamId, UnionId, VariantId,
builtin_type::BuiltinType,
expr_store::{ExpressionStore, HygieneId, path::Path},
hir::generics::{
@@ -26,7 +26,10 @@ use hir_def::{
item_tree::FieldsShape,
lang_item::LangItems,
resolver::{HasResolver, LifetimeNs, Resolver, TypeNs, ValueNs},
- signatures::{FunctionSignature, TraitFlags, TypeAliasFlags},
+ signatures::{
+ ConstSignature, FunctionSignature, ImplSignature, StaticSignature, StructSignature,
+ TraitFlags, TraitSignature, TypeAliasFlags, TypeAliasSignature,
+ },
type_ref::{
ConstRef, FnType, LifetimeRefId, PathId, TraitBoundModifier, TraitRef as HirTraitRef,
TypeBound, TypeRef, TypeRefId,
@@ -178,7 +181,7 @@ pub struct TyLoweringContext<'db, 'a> {
resolver: &'a Resolver<'db>,
store: &'a ExpressionStore,
def: GenericDefId,
- generics: OnceCell<Generics>,
+ generics: OnceCell<Generics<'db>>,
in_binders: DebruijnIndex,
impl_trait_mode: ImplTraitLoweringState,
/// Tracks types with explicit `?Sized` bounds.
@@ -279,11 +282,12 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
}
pub(crate) fn lower_const(&mut self, const_ref: ConstRef, const_type: Ty<'db>) -> Const<'db> {
- let const_ref = &self.store[const_ref.expr];
- match const_ref {
- hir_def::hir::Expr::Path(path) => {
- self.path_to_const(path).unwrap_or_else(|| unknown_const(const_type))
- }
+ let expr_id = const_ref.expr;
+ let expr = &self.store[expr_id];
+ match expr {
+ hir_def::hir::Expr::Path(path) => self
+ .path_to_const(path)
+ .unwrap_or_else(|| Const::new(self.interner, ConstKind::Error(ErrorGuaranteed))),
hir_def::hir::Expr::Literal(literal) => {
intern_const_ref(self.db, literal, const_type, self.resolver.krate())
}
@@ -300,20 +304,74 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
self.resolver.krate(),
)
} else {
- unknown_const(const_type)
+ Const::new(self.interner, ConstKind::Error(ErrorGuaranteed))
}
}
// For unsigned integers, chars, bools, etc., negation is not meaningful
- _ => unknown_const(const_type),
+ _ => Const::new(self.interner, ConstKind::Error(ErrorGuaranteed)),
}
} else {
- unknown_const(const_type)
+ // Complex negation expression (e.g. `-N` where N is a const param)
+ self.lower_const_as_unevaluated(expr_id, const_type)
}
}
- _ => unknown_const(const_type),
+ hir_def::hir::Expr::Underscore => {
+ Const::new(self.interner, ConstKind::Error(ErrorGuaranteed))
+ }
+ // Any other complex expression becomes an unevaluated anonymous const.
+ _ => self.lower_const_as_unevaluated(expr_id, const_type),
}
}
+ /// Lower a complex const expression to an `UnevaluatedConst` backed by an `AnonConstId`.
+ ///
+ /// The `expected_ty_ref` is `None` for array lengths (implicitly `usize`) or
+ /// `Some(type_ref_id)` for const generic arguments where the expected type comes
+ /// from the const parameter declaration.
+ fn lower_const_as_unevaluated(
+ &mut self,
+ _expr: hir_def::hir::ExprId,
+ _expected_ty: Ty<'db>,
+ ) -> Const<'db> {
+ // /// Build the identity generic args for the current generic context.
+ // ///
+ // /// This maps each generic parameter to itself (as a `ParamTy`, `ParamConst`,
+ // /// or `EarlyParamRegion`), which is the correct substitution when creating
+ // /// an `UnevaluatedConst` during type lowering — the anon const inherits the
+ // /// parent's generics and they haven't been substituted yet.
+ // fn current_generic_args(&self) -> GenericArgs<'db> {
+ // let generics = self.generics();
+ // let interner = self.interner;
+ // GenericArgs::new_from_iter(
+ // interner,
+ // generics.iter_id().enumerate().map(|(index, id)| match id {
+ // GenericParamId::TypeParamId(id) => {
+ // GenericArg::from(Ty::new_param(interner, id, index as u32))
+ // }
+ // GenericParamId::ConstParamId(id) => GenericArg::from(Const::new_param(
+ // interner,
+ // ParamConst { id, index: index as u32 },
+ // )),
+ // GenericParamId::LifetimeParamId(id) => GenericArg::from(Region::new_early_param(
+ // interner,
+ // EarlyParamRegion { id, index: index as u32 },
+ // )),
+ // }),
+ // )
+ // }
+ // let loc = AnonConstLoc { owner: self.def, expr };
+ // let id = loc.intern(self.db);
+ // let args = self.current_generic_args();
+ // Const::new(
+ // self.interner,
+ // ConstKind::Unevaluated(UnevaluatedConst::new(
+ // GeneralConstId::AnonConstId(id).into(),
+ // args,
+ // )),
+ // )
+ Const::new(self.interner, ConstKind::Error(ErrorGuaranteed))
+ }
+
pub(crate) fn path_to_const(&mut self, path: &Path) -> Option<Const<'db>> {
match self.resolver.resolve_path_in_value_ns_fully(self.db, path, HygieneId::ROOT) {
Some(ValueNs::GenericParam(p)) => {
@@ -349,7 +407,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
self.path_to_const(path).unwrap_or_else(|| unknown_const(const_type))
}
- fn generics(&self) -> &Generics {
+ fn generics(&self) -> &Generics<'db> {
self.generics.get_or_init(|| generics(self.db, self.def))
}
@@ -727,7 +785,8 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
match b.kind().skip_binder() {
rustc_type_ir::ClauseKind::Trait(t) => {
let id = t.def_id();
- let is_auto = db.trait_signature(id.0).flags.contains(TraitFlags::AUTO);
+ let is_auto =
+ TraitSignature::of(db, id.0).flags.contains(TraitFlags::AUTO);
if is_auto {
auto_traits.push(t.def_id().0);
} else {
@@ -1111,7 +1170,7 @@ pub(crate) fn impl_trait_with_diagnostics<'db>(
db: &'db dyn HirDatabase,
impl_id: ImplId,
) -> Option<(StoredEarlyBinder<(TraitId, StoredGenericArgs)>, Diagnostics)> {
- let impl_data = db.impl_signature(impl_id);
+ let impl_data = ImplSignature::of(db, impl_id);
let resolver = impl_id.resolver(db);
let mut ctx = TyLoweringContext::new(
db,
@@ -1196,7 +1255,7 @@ impl ImplTraits {
def: hir_def::FunctionId,
) -> Option<Box<StoredEarlyBinder<ImplTraits>>> {
// FIXME unify with fn_sig_for_fn instead of doing lowering twice, maybe
- let data = db.function_signature(def);
+ let data = FunctionSignature::of(db, def);
let resolver = def.resolver(db);
let mut ctx_ret = TyLoweringContext::new(
db,
@@ -1224,7 +1283,7 @@ impl ImplTraits {
db: &dyn HirDatabase,
def: hir_def::TypeAliasId,
) -> Option<Box<StoredEarlyBinder<ImplTraits>>> {
- let data = db.type_alias_signature(def);
+ let data = TypeAliasSignature::of(db, def);
let resolver = def.resolver(db);
let mut ctx = TyLoweringContext::new(
db,
@@ -1314,7 +1373,7 @@ fn type_for_fn(db: &dyn HirDatabase, def: FunctionId) -> StoredEarlyBinder<Store
/// Build the declared type of a const.
fn type_for_const(db: &dyn HirDatabase, def: ConstId) -> StoredEarlyBinder<StoredTy> {
let resolver = def.resolver(db);
- let data = db.const_signature(def);
+ let data = ConstSignature::of(db, def);
let parent = def.loc(db).container;
let mut ctx = TyLoweringContext::new(
db,
@@ -1330,7 +1389,7 @@ fn type_for_const(db: &dyn HirDatabase, def: ConstId) -> StoredEarlyBinder<Store
/// Build the declared type of a static.
fn type_for_static(db: &dyn HirDatabase, def: StaticId) -> StoredEarlyBinder<StoredTy> {
let resolver = def.resolver(db);
- let data = db.static_signature(def);
+ let data = StaticSignature::of(db, def);
let mut ctx = TyLoweringContext::new(
db,
&resolver,
@@ -1347,7 +1406,7 @@ fn type_for_struct_constructor(
db: &dyn HirDatabase,
def: StructId,
) -> Option<StoredEarlyBinder<StoredTy>> {
- let struct_data = db.struct_signature(def);
+ let struct_data = StructSignature::of(db, def);
match struct_data.shape {
FieldsShape::Record => None,
FieldsShape::Unit => Some(type_for_adt(db, def.into())),
@@ -1422,7 +1481,7 @@ pub(crate) fn type_for_type_alias_with_diagnostics<'db>(
db: &'db dyn HirDatabase,
t: TypeAliasId,
) -> (StoredEarlyBinder<StoredTy>, Diagnostics) {
- let type_alias_data = db.type_alias_signature(t);
+ let type_alias_data = TypeAliasSignature::of(db, t);
let mut diags = None;
let resolver = t.resolver(db);
let interner = DbInterner::new_no_crate(db);
@@ -1485,7 +1544,7 @@ pub(crate) fn impl_self_ty_with_diagnostics<'db>(
) -> (StoredEarlyBinder<StoredTy>, Diagnostics) {
let resolver = impl_id.resolver(db);
- let impl_data = db.impl_signature(impl_id);
+ let impl_data = ImplSignature::of(db, impl_id);
let mut ctx = TyLoweringContext::new(
db,
&resolver,
@@ -1531,14 +1590,14 @@ pub(crate) fn const_param_ty_with_diagnostics<'db>(
_: (),
def: ConstParamId,
) -> (StoredTy, Diagnostics) {
- let (parent_data, store) = db.generic_params_and_store(def.parent());
+ let (parent_data, store) = GenericParams::with_store(db, def.parent());
let data = &parent_data[def.local_id()];
let resolver = def.parent().resolver(db);
let interner = DbInterner::new_no_crate(db);
let mut ctx = TyLoweringContext::new(
db,
&resolver,
- &store,
+ store,
def.parent(),
LifetimeElisionKind::AnonymousReportError,
);
@@ -1629,7 +1688,7 @@ impl SupertraitsInfo {
));
let resolver = trait_.resolver(db);
- let signature = db.trait_signature(trait_);
+ let signature = TraitSignature::of(db, trait_);
for pred in signature.generic_params.where_predicates() {
let (WherePredicate::TypeBound { target, bound }
| WherePredicate::ForLifetime { lifetimes: _, target, bound }) = pred
@@ -1900,7 +1959,7 @@ fn type_alias_bounds_with_diagnostics<'db>(
db: &'db dyn HirDatabase,
type_alias: TypeAliasId,
) -> (TypeAliasBounds<StoredEarlyBinder<StoredClauses>>, Diagnostics) {
- let type_alias_data = db.type_alias_signature(type_alias);
+ let type_alias_data = TypeAliasSignature::of(db, type_alias);
let resolver = hir_def::resolver::HasResolver::resolver(type_alias, db);
let mut ctx = TyLoweringContext::new(
db,
@@ -2079,16 +2138,6 @@ impl GenericPredicates {
}
}
-pub(crate) fn trait_environment_for_body_query(
- db: &dyn HirDatabase,
- def: DefWithBodyId,
-) -> ParamEnv<'_> {
- let Some(def) = def.as_generic_def_id(db) else {
- return ParamEnv::empty();
- };
- db.trait_environment(def)
-}
-
pub(crate) fn param_env_from_predicates<'db>(
interner: DbInterner<'db>,
predicates: &'db GenericPredicates,
@@ -2103,7 +2152,12 @@ pub(crate) fn param_env_from_predicates<'db>(
ParamEnv { clauses }
}
-pub(crate) fn trait_environment<'db>(db: &'db dyn HirDatabase, def: GenericDefId) -> ParamEnv<'db> {
+pub(crate) fn trait_environment<'db>(
+ db: &'db dyn HirDatabase,
+ def: ExpressionStoreOwnerId,
+) -> ParamEnv<'db> {
+ let def = def.generic_def(db);
+
return ParamEnv { clauses: trait_environment_query(db, def).as_ref() };
#[salsa::tracked(returns(ref))]
@@ -2303,7 +2357,7 @@ fn generic_predicates(db: &dyn HirDatabase, def: GenericDefId) -> (GenericPredic
fn push_const_arg_has_type_predicates<'db>(
db: &'db dyn HirDatabase,
predicates: &mut Vec<Clause<'db>>,
- generics: &Generics,
+ generics: &Generics<'db>,
) {
let interner = DbInterner::new_no_crate(db);
let const_params_offset = generics.len_parent() + generics.len_lifetimes_self();
@@ -2356,10 +2410,11 @@ pub(crate) fn generic_defaults_with_diagnostics_query(
}
let resolver = def.resolver(db);
+ let store_for_self = generic_params.store();
let mut ctx = TyLoweringContext::new(
db,
&resolver,
- generic_params.store(),
+ store_for_self,
def,
LifetimeElisionKind::AnonymousReportError,
)
@@ -2377,6 +2432,7 @@ pub(crate) fn generic_defaults_with_diagnostics_query(
})
.collect::<Vec<_>>();
ctx.diagnostics.clear(); // Don't include diagnostics from the parent.
+ ctx.store = store_for_self;
defaults.extend(generic_params.iter_self().map(|(_id, p)| {
let (result, has_default) = handle_generic_param(&mut ctx, idx, p);
has_any_default |= has_default;
@@ -2447,7 +2503,7 @@ pub(crate) fn callable_item_signature<'db>(
}
fn fn_sig_for_fn(db: &dyn HirDatabase, def: FunctionId) -> StoredEarlyBinder<StoredPolyFnSig> {
- let data = db.function_signature(def);
+ let data = FunctionSignature::of(db, def);
let resolver = def.resolver(db);
let interner = DbInterner::new_no_crate(db);
let mut ctx_params = TyLoweringContext::new(
@@ -2455,7 +2511,7 @@ fn fn_sig_for_fn(db: &dyn HirDatabase, def: FunctionId) -> StoredEarlyBinder<Sto
&resolver,
&data.store,
def.into(),
- LifetimeElisionKind::for_fn_params(&data),
+ LifetimeElisionKind::for_fn_params(data),
);
let params = data.params.iter().map(|&tr| ctx_params.lower_ty(tr));
@@ -2533,7 +2589,7 @@ pub(crate) fn associated_ty_item_bounds<'db>(
db: &'db dyn HirDatabase,
type_alias: TypeAliasId,
) -> EarlyBinder<'db, BoundExistentialPredicates<'db>> {
- let type_alias_data = db.type_alias_signature(type_alias);
+ let type_alias_data = TypeAliasSignature::of(db, type_alias);
let resolver = hir_def::resolver::HasResolver::resolver(type_alias, db);
let interner = DbInterner::new_no_crate(db);
let mut ctx = TyLoweringContext::new(
@@ -2555,7 +2611,7 @@ pub(crate) fn associated_ty_item_bounds<'db>(
.map_bound(|c| match c {
rustc_type_ir::ClauseKind::Trait(t) => {
let id = t.def_id();
- let is_auto = db.trait_signature(id.0).flags.contains(TraitFlags::AUTO);
+ let is_auto = TraitSignature::of(db, id.0).flags.contains(TraitFlags::AUTO);
if is_auto {
Some(ExistentialPredicate::AutoTrait(t.def_id()))
} else {
diff --git a/crates/hir-ty/src/lower/path.rs b/crates/hir-ty/src/lower/path.rs
index 81a944128d..889f0792d3 100644
--- a/crates/hir-ty/src/lower/path.rs
+++ b/crates/hir-ty/src/lower/path.rs
@@ -14,7 +14,7 @@ use hir_def::{
GenericParamDataRef, TypeOrConstParamData, TypeParamData, TypeParamProvenance,
},
resolver::{ResolveValueResult, TypeNs, ValueNs},
- signatures::TraitFlags,
+ signatures::{TraitFlags, TraitSignature},
type_ref::{TypeRef, TypeRefId},
};
use rustc_type_ir::{
@@ -625,10 +625,7 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> {
GenericDefId::TraitId(trait_) => {
// RTN is prohibited anyways if we got here.
let is_rtn = args.parenthesized == GenericArgsParentheses::ReturnTypeNotation;
- let is_fn_trait = self
- .ctx
- .db
- .trait_signature(trait_)
+ let is_fn_trait = TraitSignature::of(self.ctx.db, trait_)
.flags
.contains(TraitFlags::RUSTC_PAREN_SUGAR);
is_rtn || !is_fn_trait
@@ -1024,7 +1021,7 @@ pub(crate) trait GenericArgsLowerer<'db> {
fn check_generic_args_len<'db>(
args_and_bindings: Option<&HirGenericArgs>,
def: GenericDefId,
- def_generics: &Generics,
+ def_generics: &Generics<'db>,
infer_args: bool,
lifetime_elision: &LifetimeElisionKind<'db>,
lowering_assoc_type_generics: bool,
diff --git a/crates/hir-ty/src/method_resolution.rs b/crates/hir-ty/src/method_resolution.rs
index ad4d79e68a..05b9ea5d74 100644
--- a/crates/hir-ty/src/method_resolution.rs
+++ b/crates/hir-ty/src/method_resolution.rs
@@ -17,11 +17,12 @@ use hir_def::{
ImplId, ItemContainerId, ModuleId, TraitId,
attrs::AttrFlags,
builtin_derive::BuiltinDeriveImplMethod,
- expr_store::path::GenericArgs as HirGenericArgs,
- hir::ExprId,
+ expr_store::{Body, path::GenericArgs as HirGenericArgs},
+ hir::{ExprId, generics::GenericParams},
lang_item::LangItems,
nameres::{DefMap, block_def_map, crate_def_map},
resolver::Resolver,
+ signatures::{ConstSignature, FunctionSignature},
};
use intern::{Symbol, sym};
use rustc_hash::{FxHashMap, FxHashSet};
@@ -366,7 +367,7 @@ pub fn lookup_impl_const<'db>(
};
let trait_ref = TraitRef::new_from_args(interner, trait_id.into(), subs);
- let const_signature = db.const_signature(const_id);
+ let const_signature = ConstSignature::of(db, const_id);
let name = match const_signature.name.as_ref() {
Some(name) => name,
None => return (const_id, subs),
@@ -396,7 +397,7 @@ pub fn is_dyn_method<'db>(
let ItemContainerId::TraitId(trait_id) = func.loc(db).container else {
return None;
};
- let trait_params = db.generic_params(trait_id.into()).len();
+ let trait_params = GenericParams::of(db, trait_id.into()).len();
let fn_params = fn_subst.len() - trait_params;
let trait_ref = TraitRef::new_from_args(
interner,
@@ -432,14 +433,14 @@ pub(crate) fn lookup_impl_method_query<'db>(
let ItemContainerId::TraitId(trait_id) = func.loc(db).container else {
return (Either::Left(func), fn_subst);
};
- let trait_params = db.generic_params(trait_id.into()).len();
+ let trait_params = GenericParams::of(db, trait_id.into()).len();
let trait_ref = TraitRef::new_from_args(
interner,
trait_id.into(),
GenericArgs::new_from_slice(&fn_subst[..trait_params]),
);
- let name = &db.function_signature(func).name;
+ let name = &FunctionSignature::of(db, func).name;
let Some((impl_fn, impl_subst)) =
lookup_impl_assoc_item_for_trait_ref(&infcx, trait_ref, env.param_env, name).and_then(
|(assoc, impl_args)| {
@@ -623,7 +624,7 @@ impl InherentImpls {
// To better support custom derives, collect impls in all unnamed const items.
// const _: () = { ... };
for konst in module_data.scope.unnamed_consts() {
- let body = db.body(konst.into());
+ let body = Body::of(db, konst.into());
for (_, block_def_map) in body.blocks(db) {
collect(db, block_def_map, map);
}
@@ -766,7 +767,7 @@ impl TraitImpls {
// To better support custom derives, collect impls in all unnamed const items.
// const _: () = { ... };
for konst in module_data.scope.unnamed_consts() {
- let body = db.body(konst.into());
+ let body = Body::of(db, konst.into());
for (_, block_def_map) in body.blocks(db) {
collect(db, block_def_map, lang_items, map);
}
diff --git a/crates/hir-ty/src/method_resolution/confirm.rs b/crates/hir-ty/src/method_resolution/confirm.rs
index 0024ca16a5..ec589085a8 100644
--- a/crates/hir-ty/src/method_resolution/confirm.rs
+++ b/crates/hir-ty/src/method_resolution/confirm.rs
@@ -456,7 +456,7 @@ impl<'a, 'b, 'db> ConfirmContext<'a, 'b, 'db> {
substs_from_args_and_bindings(
self.db(),
- self.ctx.body,
+ self.ctx.store,
generic_args,
self.candidate.into(),
true,
diff --git a/crates/hir-ty/src/method_resolution/probe.rs b/crates/hir-ty/src/method_resolution/probe.rs
index fc2bd87ee4..8c76bfbc07 100644
--- a/crates/hir-ty/src/method_resolution/probe.rs
+++ b/crates/hir-ty/src/method_resolution/probe.rs
@@ -5,7 +5,8 @@ use std::{cell::RefCell, convert::Infallible, ops::ControlFlow};
use hir_def::{
AssocItemId, FunctionId, GenericParamId, ImplId, ItemContainerId, TraitId,
- signatures::TraitFlags,
+ hir::generics::GenericParams,
+ signatures::{FunctionSignature, TraitFlags, TraitSignature},
};
use hir_expand::name::Name;
use rustc_ast_ir::Mutability;
@@ -1605,7 +1606,8 @@ impl<'a, 'db, Choice: ProbeChoice<'db>> ProbeContext<'a, 'db, Choice> {
// Some trait methods are excluded for arrays before 2021.
// (`array.into_iter()` wants a slice iterator for compatibility.)
if self_ty.is_array() && !self.ctx.edition.at_least_2021() {
- let trait_signature = self.db().trait_signature(poly_trait_ref.def_id().0);
+ let trait_signature =
+ TraitSignature::of(self.db(), poly_trait_ref.def_id().0);
if trait_signature
.flags
.contains(TraitFlags::SKIP_ARRAY_DURING_METHOD_DISPATCH)
@@ -1619,7 +1621,8 @@ impl<'a, 'db, Choice: ProbeChoice<'db>> ProbeContext<'a, 'db, Choice> {
if self_ty.boxed_ty().is_some_and(Ty::is_slice)
&& !self.ctx.edition.at_least_2024()
{
- let trait_signature = self.db().trait_signature(poly_trait_ref.def_id().0);
+ let trait_signature =
+ TraitSignature::of(self.db(), poly_trait_ref.def_id().0);
if trait_signature
.flags
.contains(TraitFlags::SKIP_BOXED_SLICE_DURING_METHOD_DISPATCH)
@@ -1963,7 +1966,7 @@ impl<'a, 'db, Choice: ProbeChoice<'db>> ProbeContext<'a, 'db, Choice> {
// associated value (i.e., methods, constants).
match item {
CandidateId::FunctionId(id) if self.mode == Mode::MethodCall => {
- self.db().function_signature(id).has_self_param()
+ FunctionSignature::of(self.db(), id).has_self_param()
}
_ => true,
}
@@ -2008,7 +2011,7 @@ impl<'a, 'db, Choice: ProbeChoice<'db>> ProbeContext<'a, 'db, Choice> {
// we are given do not include type/lifetime parameters for the
// method yet. So create fresh variables here for those too,
// if there are any.
- let generics = self.db().generic_params(method.into());
+ let generics = GenericParams::of(self.db(), method.into());
let xform_fn_sig = if generics.is_empty() {
fn_sig.instantiate(self.interner(), args)
diff --git a/crates/hir-ty/src/mir.rs b/crates/hir-ty/src/mir.rs
index bf17c78468..a8865cd54e 100644
--- a/crates/hir-ty/src/mir.rs
+++ b/crates/hir-ty/src/mir.rs
@@ -6,7 +6,7 @@ use base_db::Crate;
use either::Either;
use hir_def::{
DefWithBodyId, FieldId, StaticId, TupleFieldId, UnionId, VariantId,
- expr_store::Body,
+ expr_store::ExpressionStore,
hir::{BindingAnnotation, BindingId, Expr, ExprId, Ordering, PatId},
};
use la_arena::{Arena, ArenaMap, Idx, RawIdx};
@@ -1210,12 +1210,12 @@ pub enum MirSpan {
}
impl MirSpan {
- pub fn is_ref_span(&self, body: &Body) -> bool {
+ pub fn is_ref_span(&self, store: &ExpressionStore) -> bool {
match *self {
- MirSpan::ExprId(expr) => matches!(body[expr], Expr::Ref { .. }),
+ MirSpan::ExprId(expr) => matches!(store[expr], Expr::Ref { .. }),
// FIXME: Figure out if this is correct wrt. match ergonomics.
MirSpan::BindingId(binding) => {
- matches!(body[binding].mode, BindingAnnotation::Ref | BindingAnnotation::RefMut)
+ matches!(store[binding].mode, BindingAnnotation::Ref | BindingAnnotation::RefMut)
}
MirSpan::PatId(_) | MirSpan::SelfParam | MirSpan::Unknown => false,
}
diff --git a/crates/hir-ty/src/mir/borrowck.rs b/crates/hir-ty/src/mir/borrowck.rs
index dece61a57d..3ff2db15aa 100644
--- a/crates/hir-ty/src/mir/borrowck.rs
+++ b/crates/hir-ty/src/mir/borrowck.rs
@@ -5,7 +5,7 @@
use std::iter;
-use hir_def::{DefWithBodyId, HasModule};
+use hir_def::{DefWithBodyId, ExpressionStoreOwnerId, HasModule};
use la_arena::ArenaMap;
use rustc_hash::FxHashMap;
use rustc_type_ir::inherent::GenericArgs as _;
@@ -99,7 +99,7 @@ pub fn borrowck_query(
let _p = tracing::info_span!("borrowck_query").entered();
let module = def.module(db);
let interner = DbInterner::new_with(db, module.krate(db));
- let env = db.trait_environment_for_body(def);
+ let env = db.trait_environment(ExpressionStoreOwnerId::from(def));
let mut res = vec![];
// This calculates opaques defining scope which is a bit costly therefore is put outside `all_mir_bodies()`.
let typing_mode = TypingMode::borrowck(interner, def.into());
@@ -121,11 +121,11 @@ fn make_fetch_closure_field<'db>(
db: &'db dyn HirDatabase,
) -> impl FnOnce(InternedClosureId, GenericArgs<'db>, usize) -> Ty<'db> + use<'db> {
|c: InternedClosureId, subst: GenericArgs<'db>, f: usize| {
- let InternedClosure(def, _) = db.lookup_intern_closure(c);
- let infer = InferenceResult::for_body(db, def);
+ let InternedClosure(owner, _) = db.lookup_intern_closure(c);
+ let interner = DbInterner::new_no_crate(db);
+ let infer = InferenceResult::of(db, owner);
let (captures, _) = infer.closure_info(c);
let parent_subst = subst.as_closure().parent_args();
- let interner = DbInterner::new_no_crate(db);
captures.get(f).expect("broken closure field").ty.get().instantiate(interner, parent_subst)
}
}
diff --git a/crates/hir-ty/src/mir/eval.rs b/crates/hir-ty/src/mir/eval.rs
index ec0723c3f8..505db1776f 100644
--- a/crates/hir-ty/src/mir/eval.rs
+++ b/crates/hir-ty/src/mir/eval.rs
@@ -5,14 +5,17 @@ use std::{borrow::Cow, cell::RefCell, fmt::Write, iter, mem, ops::Range};
use base_db::{Crate, target::TargetLoadError};
use either::Either;
use hir_def::{
- AdtId, DefWithBodyId, EnumVariantId, FunctionId, GeneralConstId, HasModule, ItemContainerId,
- Lookup, StaticId, VariantId,
- expr_store::HygieneId,
+ AdtId, DefWithBodyId, EnumVariantId, ExpressionStoreOwnerId, FunctionId, GeneralConstId,
+ HasModule, ItemContainerId, Lookup, StaticId, VariantId,
+ expr_store::{Body, HygieneId},
item_tree::FieldsShape,
lang_item::LangItems,
layout::{TagEncoding, Variants},
resolver::{HasResolver, TypeNs, ValueNs},
- signatures::{StaticFlags, StructFlags},
+ signatures::{
+ EnumSignature, FunctionSignature, StaticFlags, StaticSignature, StructFlags,
+ StructSignature, TraitSignature,
+ },
};
use hir_expand::{InFile, mod_path::path, name::Name};
use intern::sym;
@@ -386,7 +389,7 @@ impl MirEvalError {
for (func, span, def) in stack.iter().take(30).rev() {
match func {
Either::Left(func) => {
- let function_name = db.function_signature(*func);
+ let function_name = FunctionSignature::of(db, *func);
writeln!(
f,
"In function {} ({:?})",
@@ -398,7 +401,7 @@ impl MirEvalError {
writeln!(f, "In {closure:?}")?;
}
}
- let source_map = db.body_with_source_map(*def).1;
+ let source_map = &Body::with_source_map(db, *def).1;
let span: InFile<SyntaxNodePtr> = match span {
MirSpan::ExprId(e) => match source_map.expr_syntax(*e) {
Ok(s) => s.map(|it| it.into()),
@@ -441,7 +444,7 @@ impl MirEvalError {
)?;
}
MirEvalError::MirLowerError(func, err) => {
- let function_name = db.function_signature(*func);
+ let function_name = FunctionSignature::of(db, *func);
let self_ = match func.lookup(db).container {
ItemContainerId::ImplId(impl_id) => Some({
db.impl_self_ty(impl_id)
@@ -450,7 +453,10 @@ impl MirEvalError {
.to_string()
}),
ItemContainerId::TraitId(it) => Some(
- db.trait_signature(it).name.display(db, display_target.edition).to_string(),
+ TraitSignature::of(db, it)
+ .name
+ .display(db, display_target.edition)
+ .to_string(),
),
_ => None,
};
@@ -660,7 +666,7 @@ impl<'db> Evaluator<'db> {
db,
random_state: oorandom::Rand64::new(0),
param_env: trait_env.unwrap_or_else(|| ParamEnvAndCrate {
- param_env: db.trait_environment_for_body(owner),
+ param_env: db.trait_environment(ExpressionStoreOwnerId::from(owner)),
krate: crate_id,
}),
crate_id,
@@ -730,8 +736,8 @@ impl<'db> Evaluator<'db> {
self.param_env.param_env,
ty,
|c, subst, f| {
- let InternedClosure(def, _) = self.db.lookup_intern_closure(c);
- let infer = InferenceResult::for_body(self.db, def);
+ let InternedClosure(owner, _) = self.db.lookup_intern_closure(c);
+ let infer = InferenceResult::of(self.db, owner);
let (captures, _) = infer.closure_info(c);
let parent_subst = subst.as_closure().parent_args();
captures
@@ -893,8 +899,8 @@ impl<'db> Evaluator<'db> {
OperandKind::Copy(p) | OperandKind::Move(p) => self.place_ty(p, locals)?,
OperandKind::Constant { konst: _, ty } => ty.as_ref(),
&OperandKind::Static(s) => {
- let ty = InferenceResult::for_body(self.db, s.into())
- .expr_ty(self.db.body(s.into()).body_expr);
+ let ty = InferenceResult::of(self.db, DefWithBodyId::from(s))
+ .expr_ty(Body::of(self.db, s.into()).root_expr());
Ty::new_ref(
self.interner(),
Region::new_static(self.interner()),
@@ -1954,6 +1960,9 @@ impl<'db> Evaluator<'db> {
MirEvalError::ConstEvalError(name, Box::new(e))
})?
}
+ GeneralConstId::AnonConstId(_) => {
+ not_supported!("anonymous const evaluation")
+ }
};
if let ConstKind::Value(value) = result_owner.kind() {
break 'b value;
@@ -2818,15 +2827,15 @@ impl<'db> Evaluator<'db> {
if let Some(o) = self.static_locations.get(&st) {
return Ok(*o);
};
- let static_data = self.db.static_signature(st);
+ let static_data = StaticSignature::of(self.db, st);
let result = if !static_data.flags.contains(StaticFlags::EXTERN) {
let konst = self.db.const_eval_static(st).map_err(|e| {
MirEvalError::ConstEvalError(static_data.name.as_str().to_owned(), Box::new(e))
})?;
self.allocate_const_in_heap(locals, konst)?
} else {
- let ty = InferenceResult::for_body(self.db, st.into())
- .expr_ty(self.db.body(st.into()).body_expr);
+ let ty = InferenceResult::of(self.db, DefWithBodyId::from(st))
+ .expr_ty(Body::of(self.db, st.into()).root_expr());
let Some((size, align)) = self.size_align_of(ty, locals)? else {
not_supported!("unsized extern static");
};
@@ -2849,7 +2858,7 @@ impl<'db> Evaluator<'db> {
let edition = self.crate_id.data(self.db).edition;
let name = format!(
"{}::{}",
- self.db.enum_signature(loc.parent).name.display(db, edition),
+ EnumSignature::of(self.db, loc.parent).name.display(db, edition),
loc.parent
.enum_variants(self.db)
.variant_name_by_id(variant)
@@ -2909,7 +2918,7 @@ impl<'db> Evaluator<'db> {
let id = adt_def.def_id().0;
match id {
AdtId::StructId(s) => {
- let data = self.db.struct_signature(s);
+ let data = StructSignature::of(self.db, s);
if data.flags.contains(StructFlags::IS_MANUALLY_DROP) {
return Ok(());
}
diff --git a/crates/hir-ty/src/mir/eval/shim.rs b/crates/hir-ty/src/mir/eval/shim.rs
index 76c8701ea2..ff6c99ca53 100644
--- a/crates/hir-ty/src/mir/eval/shim.rs
+++ b/crates/hir-ty/src/mir/eval/shim.rs
@@ -45,7 +45,7 @@ impl<'db> Evaluator<'db> {
return Ok(false);
}
- let function_data = self.db.function_signature(def);
+ let function_data = FunctionSignature::of(self.db, def);
let attrs = AttrFlags::query(self.db, def.into());
let is_intrinsic = FunctionSignature::is_intrinsic(self.db, def);
@@ -152,8 +152,8 @@ impl<'db> Evaluator<'db> {
not_supported!("wrong arg count for clone");
};
let addr = Address::from_bytes(arg.get(self)?)?;
- let InternedClosure(closure_owner, _) = self.db.lookup_intern_closure(id.0);
- let infer = InferenceResult::for_body(self.db, closure_owner);
+ let InternedClosure(owner, _) = self.db.lookup_intern_closure(id.0);
+ let infer = InferenceResult::of(self.db, owner);
let (captures, _) = infer.closure_info(id.0);
let layout = self.layout(self_ty)?;
let db = self.db;
@@ -840,7 +840,7 @@ impl<'db> Evaluator<'db> {
// cases.
let [lhs, rhs] = args else {
return Err(MirEvalError::InternalError(
- "wrapping_add args are not provided".into(),
+ "ptr_guaranteed_cmp args are not provided".into(),
));
};
let ans = lhs.get(self)? == rhs.get(self)?;
diff --git a/crates/hir-ty/src/mir/eval/tests.rs b/crates/hir-ty/src/mir/eval/tests.rs
index 61dd7757c9..6bf966c3ef 100644
--- a/crates/hir-ty/src/mir/eval/tests.rs
+++ b/crates/hir-ty/src/mir/eval/tests.rs
@@ -1,4 +1,4 @@
-use hir_def::{HasModule, db::DefDatabase};
+use hir_def::{GenericDefId, HasModule, signatures::FunctionSignature};
use hir_expand::EditionedFileId;
use span::Edition;
use syntax::{TextRange, TextSize};
@@ -25,7 +25,7 @@ fn eval_main(db: &TestDB, file_id: EditionedFileId) -> Result<(String, String),
.declarations()
.find_map(|x| match x {
hir_def::ModuleDefId::FunctionId(x) => {
- if db.function_signature(x).name.display(db, Edition::CURRENT).to_string()
+ if FunctionSignature::of(db, x).name.display(db, Edition::CURRENT).to_string()
== "main"
{
Some(x)
@@ -41,7 +41,7 @@ fn eval_main(db: &TestDB, file_id: EditionedFileId) -> Result<(String, String),
func_id.into(),
GenericArgs::empty(interner).store(),
crate::ParamEnvAndCrate {
- param_env: db.trait_environment(func_id.into()),
+ param_env: db.trait_environment(GenericDefId::from(func_id).into()),
krate: func_id.krate(db),
}
.store(),
diff --git a/crates/hir-ty/src/mir/lower.rs b/crates/hir-ty/src/mir/lower.rs
index 2e849bcf3a..44785d948a 100644
--- a/crates/hir-ty/src/mir/lower.rs
+++ b/crates/hir-ty/src/mir/lower.rs
@@ -4,16 +4,17 @@ use std::{fmt::Write, iter, mem};
use base_db::Crate;
use hir_def::{
- AdtId, DefWithBodyId, EnumVariantId, GeneralConstId, GenericParamId, HasModule,
- ItemContainerId, LocalFieldId, Lookup, TraitId, TupleId,
+ AdtId, DefWithBodyId, EnumVariantId, ExpressionStoreOwnerId, GeneralConstId, GenericParamId,
+ HasModule, ItemContainerId, LocalFieldId, Lookup, TraitId, TupleId,
expr_store::{Body, ExpressionStore, HygieneId, path::Path},
hir::{
ArithOp, Array, BinaryOp, BindingAnnotation, BindingId, ExprId, LabelId, Literal, MatchArm,
- Pat, PatId, RecordFieldPat, RecordLitField, RecordSpread,
+ Pat, PatId, RecordFieldPat, RecordLitField, RecordSpread, generics::GenericParams,
},
item_tree::FieldsShape,
lang_item::LangItems,
resolver::{HasResolver, ResolveValueResult, Resolver, ValueNs},
+ signatures::{ConstSignature, EnumSignature, FunctionSignature, StaticSignature},
};
use hir_expand::name::Name;
use la_arena::ArenaMap;
@@ -185,7 +186,7 @@ impl MirLowerError {
}
}
MirLowerError::MissingFunctionDefinition(owner, it) => {
- let body = db.body(*owner);
+ let body = Body::of(db, *owner);
writeln!(
f,
"Missing function definition for {}",
@@ -202,13 +203,13 @@ impl MirLowerError {
MirLowerError::GenericArgNotProvided(id, subst) => {
let param_name = match *id {
GenericParamId::TypeParamId(id) => {
- db.generic_params(id.parent())[id.local_id()].name().cloned()
+ GenericParams::of(db, id.parent())[id.local_id()].name().cloned()
}
GenericParamId::ConstParamId(id) => {
- db.generic_params(id.parent())[id.local_id()].name().cloned()
+ GenericParams::of(db, id.parent())[id.local_id()].name().cloned()
}
GenericParamId::LifetimeParamId(id) => {
- Some(db.generic_params(id.parent)[id.local_id].name.clone())
+ Some(GenericParams::of(db, id.parent)[id.local_id].name.clone())
}
};
writeln!(
@@ -307,7 +308,7 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> {
closures: vec![],
};
let resolver = owner.resolver(db);
- let env = db.trait_environment_for_body(owner);
+ let env = db.trait_environment(ExpressionStoreOwnerId::from(owner));
let interner = DbInterner::new_with(db, resolver.krate());
// FIXME(next-solver): Is `non_body_analysis()` correct here? Don't we want to reveal opaque types defined by this body?
let infcx = interner.infer_ctxt().build(TypingMode::non_body_analysis());
@@ -472,7 +473,7 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> {
if let DefWithBodyId::FunctionId(f) = self.owner {
let assoc = f.lookup(self.db);
if let ItemContainerId::TraitId(t) = assoc.container {
- let name = &self.db.function_signature(f).name;
+ let name = &FunctionSignature::of(self.db, f).name;
return Err(MirLowerError::TraitFunctionDefinition(t, name.clone()));
}
}
@@ -1546,6 +1547,9 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> {
MirLowerError::ConstEvalError(name.into(), Box::new(e))
})?
}
+ GeneralConstId::AnonConstId(_) => {
+ return Err(MirLowerError::IncompleteExpr);
+ }
}
};
let ty = self
@@ -1553,6 +1557,7 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> {
.value_ty(match const_id {
GeneralConstId::ConstId(id) => id.into(),
GeneralConstId::StaticId(id) => id.into(),
+ GeneralConstId::AnonConstId(_) => unreachable!("handled above"),
})
.unwrap()
.instantiate(self.interner(), subst);
@@ -1989,7 +1994,7 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> {
let loc = variant.lookup(db);
let name = format!(
"{}::{}",
- self.db.enum_signature(loc.parent).name.display(db, edition),
+ EnumSignature::of(db, loc.parent).name.display(db, edition),
loc.parent
.enum_variants(self.db)
.variant_name_by_id(variant)
@@ -2106,8 +2111,10 @@ pub fn mir_body_for_closure_query<'db>(
closure: InternedClosureId,
) -> Result<'db, Arc<MirBody>> {
let InternedClosure(owner, expr) = db.lookup_intern_closure(closure);
- let body = db.body(owner);
- let infer = InferenceResult::for_body(db, owner);
+ let body_owner =
+ owner.as_def_with_body().expect("MIR lowering should only happen for body-owned closures");
+ let body = Body::of(db, body_owner);
+ let infer = InferenceResult::of(db, body_owner);
let Expr::Closure { args, body: root, .. } = &body[expr] else {
implementation_error!("closure expression is not closure");
};
@@ -2115,7 +2122,7 @@ pub fn mir_body_for_closure_query<'db>(
implementation_error!("closure expression is not closure");
};
let (captures, kind) = infer.closure_info(closure);
- let mut ctx = MirLowerCtx::new(db, owner, &body.store, infer);
+ let mut ctx = MirLowerCtx::new(db, body_owner, &body.store, infer);
// 0 is return local
ctx.result.locals.alloc(Local { ty: infer.expr_ty(*root).store() });
let closure_local = ctx.result.locals.alloc(Local {
@@ -2138,7 +2145,7 @@ pub fn mir_body_for_closure_query<'db>(
});
ctx.result.param_locals.push(closure_local);
let sig = ctx.interner().signature_unclosure(substs.as_closure().sig(), Safety::Safe);
- let resolver_guard = ctx.resolver.update_to_inner_scope(db, owner, expr);
+ let resolver_guard = ctx.resolver.update_to_inner_scope(db, body_owner, expr);
let current = ctx.lower_params_and_bindings(
args.iter().zip(sig.skip_binder().inputs().iter()).map(|(it, y)| (*it, *y)),
None,
@@ -2222,13 +2229,12 @@ pub fn mir_body_query<'db>(
let edition = krate.data(db).edition;
let detail = match def {
DefWithBodyId::FunctionId(it) => {
- db.function_signature(it).name.display(db, edition).to_string()
+ FunctionSignature::of(db, it).name.display(db, edition).to_string()
}
DefWithBodyId::StaticId(it) => {
- db.static_signature(it).name.display(db, edition).to_string()
+ StaticSignature::of(db, it).name.display(db, edition).to_string()
}
- DefWithBodyId::ConstId(it) => db
- .const_signature(it)
+ DefWithBodyId::ConstId(it) => ConstSignature::of(db, it)
.name
.clone()
.unwrap_or_else(Name::missing)
@@ -2243,9 +2249,9 @@ pub fn mir_body_query<'db>(
}
};
let _p = tracing::info_span!("mir_body_query", ?detail).entered();
- let body = db.body(def);
- let infer = InferenceResult::for_body(db, def);
- let mut result = lower_body_to_mir(db, def, &body, infer, body.body_expr)?;
+ let body = Body::of(db, def);
+ let infer = InferenceResult::of(db, def);
+ let mut result = lower_body_to_mir(db, def, body, infer, body.root_expr())?;
result.shrink_to_fit();
Ok(Arc::new(result))
}
@@ -2269,7 +2275,7 @@ pub fn lower_body_to_mir<'db>(
// but this is currently also used for `X` in `[(); X]` which live in the same expression store
root_expr: ExprId,
) -> Result<'db, MirBody> {
- let is_root = root_expr == body.body_expr;
+ let is_root = root_expr == body.root_expr();
// Extract params and self_param only when lowering the body's root expression for a function.
if is_root && let DefWithBodyId::FunctionId(fid) = owner {
let callable_sig =
diff --git a/crates/hir-ty/src/mir/pretty.rs b/crates/hir-ty/src/mir/pretty.rs
index 96b90a3f40..4b654a0fbe 100644
--- a/crates/hir-ty/src/mir/pretty.rs
+++ b/crates/hir-ty/src/mir/pretty.rs
@@ -6,7 +6,11 @@ use std::{
};
use either::Either;
-use hir_def::{expr_store::Body, hir::BindingId};
+use hir_def::{
+ expr_store::Body,
+ hir::BindingId,
+ signatures::{ConstSignature, EnumSignature, FunctionSignature, StaticSignature},
+};
use hir_expand::{Lookup, name::Name};
use la_arena::ArenaMap;
@@ -38,19 +42,19 @@ macro_rules! wln {
impl MirBody {
pub fn pretty_print(&self, db: &dyn HirDatabase, display_target: DisplayTarget) -> String {
- let hir_body = db.body(self.owner);
- let mut ctx = MirPrettyCtx::new(self, &hir_body, db, display_target);
+ let hir_body = Body::of(db, self.owner);
+ let mut ctx = MirPrettyCtx::new(self, hir_body, db, display_target);
ctx.for_body(|this| match ctx.body.owner {
hir_def::DefWithBodyId::FunctionId(id) => {
- let data = db.function_signature(id);
+ let data = FunctionSignature::of(db, id);
w!(this, "fn {}() ", data.name.display(db, this.display_target.edition));
}
hir_def::DefWithBodyId::StaticId(id) => {
- let data = db.static_signature(id);
+ let data = StaticSignature::of(db, id);
w!(this, "static {}: _ = ", data.name.display(db, this.display_target.edition));
}
hir_def::DefWithBodyId::ConstId(id) => {
- let data = db.const_signature(id);
+ let data = ConstSignature::of(db, id);
w!(
this,
"const {}: _ = ",
@@ -66,7 +70,7 @@ impl MirBody {
w!(
this,
"enum {}::{} = ",
- db.enum_signature(loc.parent).name.display(db, edition),
+ EnumSignature::of(db, loc.parent).name.display(db, edition),
loc.parent
.enum_variants(db)
.variant_name_by_id(id)
diff --git a/crates/hir-ty/src/next_solver/def_id.rs b/crates/hir-ty/src/next_solver/def_id.rs
index aa6caefc4a..00161d6d08 100644
--- a/crates/hir-ty/src/next_solver/def_id.rs
+++ b/crates/hir-ty/src/next_solver/def_id.rs
@@ -1,9 +1,13 @@
//! Definition of `SolverDefId`
use hir_def::{
- AdtId, AttrDefId, BuiltinDeriveImplId, CallableDefId, ConstId, DefWithBodyId, EnumId,
- EnumVariantId, FunctionId, GeneralConstId, GenericDefId, ImplId, StaticId, StructId, TraitId,
- TypeAliasId, UnionId,
+ AdtId, AnonConstId, AttrDefId, BuiltinDeriveImplId, CallableDefId, ConstId, DefWithBodyId,
+ EnumId, EnumVariantId, ExpressionStoreOwnerId, FunctionId, GeneralConstId, GenericDefId,
+ ImplId, StaticId, StructId, TraitId, TypeAliasId, UnionId, VariantId,
+ signatures::{
+ ConstSignature, EnumSignature, FunctionSignature, StaticSignature, StructSignature,
+ TraitSignature, TypeAliasSignature, UnionSignature,
+ },
};
use rustc_type_ir::inherent;
use stdx::impl_from;
@@ -12,13 +16,13 @@ use crate::db::{InternedClosureId, InternedCoroutineId, InternedOpaqueTyId};
use super::DbInterner;
-#[derive(Debug, PartialOrd, Ord, Clone, Copy, PartialEq, Eq, Hash, salsa::Supertype)]
+#[derive(Debug, PartialOrd, Ord, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Ctor {
Struct(StructId),
Enum(EnumVariantId),
}
-#[derive(PartialOrd, Ord, Clone, Copy, PartialEq, Eq, Hash, salsa::Supertype)]
+#[derive(PartialOrd, Ord, Clone, Copy, PartialEq, Eq, Hash)]
pub enum SolverDefId {
AdtId(AdtId),
ConstId(ConstId),
@@ -26,13 +30,13 @@ pub enum SolverDefId {
ImplId(ImplId),
BuiltinDeriveImplId(BuiltinDeriveImplId),
StaticId(StaticId),
+ AnonConstId(AnonConstId),
TraitId(TraitId),
TypeAliasId(TypeAliasId),
InternedClosureId(InternedClosureId),
InternedCoroutineId(InternedCoroutineId),
InternedOpaqueTyId(InternedOpaqueTyId),
EnumVariantId(EnumVariantId),
- // FIXME(next-solver): Do we need the separation of `Ctor`? It duplicates some variants.
Ctor(Ctor),
}
@@ -42,32 +46,33 @@ impl std::fmt::Debug for SolverDefId {
let db = interner.db;
match *self {
SolverDefId::AdtId(AdtId::StructId(id)) => {
- f.debug_tuple("AdtId").field(&db.struct_signature(id).name.as_str()).finish()
+ f.debug_tuple("AdtId").field(&StructSignature::of(db, id).name.as_str()).finish()
}
SolverDefId::AdtId(AdtId::EnumId(id)) => {
- f.debug_tuple("AdtId").field(&db.enum_signature(id).name.as_str()).finish()
+ f.debug_tuple("AdtId").field(&EnumSignature::of(db, id).name.as_str()).finish()
}
SolverDefId::AdtId(AdtId::UnionId(id)) => {
- f.debug_tuple("AdtId").field(&db.union_signature(id).name.as_str()).finish()
+ f.debug_tuple("AdtId").field(&UnionSignature::of(db, id).name.as_str()).finish()
}
SolverDefId::ConstId(id) => f
.debug_tuple("ConstId")
- .field(&db.const_signature(id).name.as_ref().map_or("_", |name| name.as_str()))
+ .field(&ConstSignature::of(db, id).name.as_ref().map_or("_", |name| name.as_str()))
+ .finish(),
+ SolverDefId::FunctionId(id) => f
+ .debug_tuple("FunctionId")
+ .field(&FunctionSignature::of(db, id).name.as_str())
.finish(),
- SolverDefId::FunctionId(id) => {
- f.debug_tuple("FunctionId").field(&db.function_signature(id).name.as_str()).finish()
- }
SolverDefId::ImplId(id) => f.debug_tuple("ImplId").field(&id).finish(),
SolverDefId::BuiltinDeriveImplId(id) => f.debug_tuple("ImplId").field(&id).finish(),
SolverDefId::StaticId(id) => {
- f.debug_tuple("StaticId").field(&db.static_signature(id).name.as_str()).finish()
+ f.debug_tuple("StaticId").field(&StaticSignature::of(db, id).name.as_str()).finish()
}
SolverDefId::TraitId(id) => {
- f.debug_tuple("TraitId").field(&db.trait_signature(id).name.as_str()).finish()
+ f.debug_tuple("TraitId").field(&TraitSignature::of(db, id).name.as_str()).finish()
}
SolverDefId::TypeAliasId(id) => f
.debug_tuple("TypeAliasId")
- .field(&db.type_alias_signature(id).name.as_str())
+ .field(&TypeAliasSignature::of(db, id).name.as_str())
.finish(),
SolverDefId::InternedClosureId(id) => {
f.debug_tuple("InternedClosureId").field(&id).finish()
@@ -83,20 +88,21 @@ impl std::fmt::Debug for SolverDefId {
f.debug_tuple("EnumVariantId")
.field(&format_args!(
"\"{}::{}\"",
- db.enum_signature(parent_enum).name.as_str(),
+ EnumSignature::of(db, parent_enum).name.as_str(),
parent_enum.enum_variants(db).variant_name_by_id(id).unwrap().as_str()
))
.finish()
}
+ SolverDefId::AnonConstId(id) => f.debug_tuple("AnonConstId").field(&id).finish(),
SolverDefId::Ctor(Ctor::Struct(id)) => {
- f.debug_tuple("Ctor").field(&db.struct_signature(id).name.as_str()).finish()
+ f.debug_tuple("Ctor").field(&StructSignature::of(db, id).name.as_str()).finish()
}
SolverDefId::Ctor(Ctor::Enum(id)) => {
let parent_enum = id.loc(db).parent;
f.debug_tuple("Ctor")
.field(&format_args!(
"\"{}::{}\"",
- db.enum_signature(parent_enum).name.as_str(),
+ EnumSignature::of(db, parent_enum).name.as_str(),
parent_enum.enum_variants(db).variant_name_by_id(id).unwrap().as_str()
))
.finish()
@@ -112,6 +118,7 @@ impl_from!(
ImplId,
BuiltinDeriveImplId,
StaticId,
+ AnonConstId,
TraitId,
TypeAliasId,
InternedClosureId,
@@ -142,6 +149,7 @@ impl From<GeneralConstId> for SolverDefId {
match value {
GeneralConstId::ConstId(const_id) => SolverDefId::ConstId(const_id),
GeneralConstId::StaticId(static_id) => SolverDefId::StaticId(static_id),
+ GeneralConstId::AnonConstId(anon_const_id) => SolverDefId::AnonConstId(anon_const_id),
}
}
}
@@ -158,6 +166,28 @@ impl From<DefWithBodyId> for SolverDefId {
}
}
+impl From<VariantId> for SolverDefId {
+ #[inline]
+ fn from(value: VariantId) -> Self {
+ match value {
+ VariantId::EnumVariantId(id) => id.into(),
+ VariantId::StructId(id) => id.into(),
+ VariantId::UnionId(id) => id.into(),
+ }
+ }
+}
+
+impl From<ExpressionStoreOwnerId> for SolverDefId {
+ #[inline]
+ fn from(value: ExpressionStoreOwnerId) -> Self {
+ match value {
+ ExpressionStoreOwnerId::Body(body_id) => body_id.into(),
+ ExpressionStoreOwnerId::Signature(sig_id) => sig_id.into(),
+ ExpressionStoreOwnerId::VariantFields(variant_id) => variant_id.into(),
+ }
+ }
+}
+
impl TryFrom<SolverDefId> for AttrDefId {
type Error = ();
#[inline]
@@ -176,7 +206,8 @@ impl TryFrom<SolverDefId> for AttrDefId {
SolverDefId::BuiltinDeriveImplId(_)
| SolverDefId::InternedClosureId(_)
| SolverDefId::InternedCoroutineId(_)
- | SolverDefId::InternedOpaqueTyId(_) => Err(()),
+ | SolverDefId::InternedOpaqueTyId(_)
+ | SolverDefId::AnonConstId(_) => Err(()),
}
}
}
@@ -199,6 +230,7 @@ impl TryFrom<SolverDefId> for DefWithBodyId {
| SolverDefId::InternedClosureId(_)
| SolverDefId::InternedCoroutineId(_)
| SolverDefId::Ctor(Ctor::Struct(_))
+ | SolverDefId::AnonConstId(_)
| SolverDefId::AdtId(_) => return Err(()),
};
Ok(id)
@@ -222,6 +254,7 @@ impl TryFrom<SolverDefId> for GenericDefId {
| SolverDefId::InternedOpaqueTyId(_)
| SolverDefId::EnumVariantId(_)
| SolverDefId::BuiltinDeriveImplId(_)
+ | SolverDefId::AnonConstId(_)
| SolverDefId::Ctor(_) => return Err(()),
})
}
@@ -343,6 +376,7 @@ impl From<GeneralConstIdWrapper> for SolverDefId {
match value.0 {
GeneralConstId::ConstId(id) => SolverDefId::ConstId(id),
GeneralConstId::StaticId(id) => SolverDefId::StaticId(id),
+ GeneralConstId::AnonConstId(id) => SolverDefId::AnonConstId(id),
}
}
}
@@ -353,6 +387,7 @@ impl TryFrom<SolverDefId> for GeneralConstIdWrapper {
match value {
SolverDefId::ConstId(it) => Ok(Self(it.into())),
SolverDefId::StaticId(it) => Ok(Self(it.into())),
+ SolverDefId::AnonConstId(it) => Ok(Self(it.into())),
_ => Err(()),
}
}
diff --git a/crates/hir-ty/src/next_solver/fulfill/errors.rs b/crates/hir-ty/src/next_solver/fulfill/errors.rs
index 8f798b4ade..0e8218b33a 100644
--- a/crates/hir-ty/src/next_solver/fulfill/errors.rs
+++ b/crates/hir-ty/src/next_solver/fulfill/errors.rs
@@ -617,6 +617,7 @@ impl<'db> NextSolverError<'db> {
}
mod wf {
+ use hir_def::signatures::ImplSignature;
use hir_def::{GeneralConstId, ItemContainerId};
use rustc_type_ir::inherent::{
AdtDef, BoundExistentialPredicates, GenericArgs as _, IntoKind, SliceLike, Term as _,
@@ -1054,7 +1055,7 @@ mod wf {
if let GeneralConstId::ConstId(uv_def) = uv.def.0
&& let ItemContainerId::ImplId(impl_) =
uv_def.loc(self.interner().db).container
- && self.interner().db.impl_signature(impl_).target_trait.is_none()
+ && ImplSignature::of(self.interner().db, impl_).target_trait.is_none()
{
return; // Subtree is handled by above function
} else {
diff --git a/crates/hir-ty/src/next_solver/generics.rs b/crates/hir-ty/src/next_solver/generics.rs
index a8288b4e82..f31de21796 100644
--- a/crates/hir-ty/src/next_solver/generics.rs
+++ b/crates/hir-ty/src/next_solver/generics.rs
@@ -55,7 +55,7 @@ pub(crate) fn generics(interner: DbInterner<'_>, def: SolverDefId) -> Generics {
let (parent, own_params) = match (def.try_into(), def) {
(Ok(def), _) => (
parent_generic_def(db, def),
- own_params_for_generic_params(def, &db.generic_params(def)),
+ own_params_for_generic_params(def, GenericParams::of(db, def)),
),
(_, SolverDefId::InternedOpaqueTyId(id)) => {
match db.lookup_intern_impl_trait_id(id) {
diff --git a/crates/hir-ty/src/next_solver/interner.rs b/crates/hir-ty/src/next_solver/interner.rs
index e17bdac68c..5b81c7675d 100644
--- a/crates/hir-ty/src/next_solver/interner.rs
+++ b/crates/hir-ty/src/next_solver/interner.rs
@@ -10,11 +10,15 @@ pub use tls_db::{attach_db, attach_db_allow_change, with_attached_db};
use base_db::Crate;
use hir_def::{
- AdtId, CallableDefId, DefWithBodyId, EnumVariantId, HasModule, ItemContainerId, StructId,
- UnionId, VariantId,
+ AdtId, CallableDefId, DefWithBodyId, EnumVariantId, ExpressionStoreOwnerId, HasModule,
+ ItemContainerId, StructId, UnionId, VariantId,
attrs::AttrFlags,
+ expr_store::{Body, ExpressionStore},
lang_item::LangItems,
- signatures::{FieldData, FnFlags, ImplFlags, StructFlags, TraitFlags},
+ signatures::{
+ EnumSignature, FieldData, FnFlags, FunctionSignature, ImplFlags, ImplSignature,
+ StructFlags, StructSignature, TraitFlags, TraitSignature, UnionSignature,
+ },
};
use la_arena::Idx;
use rustc_abi::{ReprFlags, ReprOptions};
@@ -548,7 +552,7 @@ impl AdtDef {
let db = interner.db();
let (flags, variants, repr) = match def_id {
AdtId::StructId(struct_id) => {
- let data = db.struct_signature(struct_id);
+ let data = StructSignature::of(db, struct_id);
let flags = AdtFlags {
is_enum: false,
@@ -775,15 +779,15 @@ impl fmt::Debug for AdtDef {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
crate::with_attached_db(|db| match self.inner().id {
AdtId::StructId(struct_id) => {
- let data = db.struct_signature(struct_id);
+ let data = StructSignature::of(db, struct_id);
f.write_str(data.name.as_str())
}
AdtId::UnionId(union_id) => {
- let data = db.union_signature(union_id);
+ let data = UnionSignature::of(db, union_id);
f.write_str(data.name.as_str())
}
AdtId::EnumId(enum_id) => {
- let data = db.enum_signature(enum_id);
+ let data = EnumSignature::of(db, enum_id);
f.write_str(data.name.as_str())
}
})
@@ -1193,7 +1197,8 @@ impl<'db> Interner for DbInterner<'db> {
| SolverDefId::ImplId(_)
| SolverDefId::BuiltinDeriveImplId(_)
| SolverDefId::InternedClosureId(_)
- | SolverDefId::InternedCoroutineId(_) => {
+ | SolverDefId::InternedCoroutineId(_)
+ | SolverDefId::AnonConstId(_) => {
return VariancesOf::empty(self);
}
};
@@ -1230,7 +1235,7 @@ impl<'db> Interner for DbInterner<'db> {
SolverDefId::InternedOpaqueTyId(_) => AliasTyKind::Opaque,
SolverDefId::TypeAliasId(type_alias) => match type_alias.loc(self.db).container {
ItemContainerId::ImplId(impl_)
- if self.db.impl_signature(impl_).target_trait.is_none() =>
+ if ImplSignature::of(self.db, impl_).target_trait.is_none() =>
{
AliasTyKind::Inherent
}
@@ -1249,7 +1254,7 @@ impl<'db> Interner for DbInterner<'db> {
SolverDefId::InternedOpaqueTyId(_) => AliasTermKind::OpaqueTy,
SolverDefId::TypeAliasId(type_alias) => match type_alias.loc(self.db).container {
ItemContainerId::ImplId(impl_)
- if self.db.impl_signature(impl_).target_trait.is_none() =>
+ if ImplSignature::of(self.db, impl_).target_trait.is_none() =>
{
AliasTermKind::InherentTy
}
@@ -1260,7 +1265,9 @@ impl<'db> Interner for DbInterner<'db> {
},
// rustc creates an `AnonConst` for consts, and evaluates them with CTFE (normalizing projections
// via selection, similar to ours `find_matching_impl()`, and not with the trait solver), so mimic it.
- SolverDefId::ConstId(_) => AliasTermKind::UnevaluatedConst,
+ SolverDefId::ConstId(_) | SolverDefId::AnonConstId(_) => {
+ AliasTermKind::UnevaluatedConst
+ }
_ => unimplemented!("Unexpected alias: {:?}", alias.def_id),
}
}
@@ -1308,22 +1315,10 @@ impl<'db> Interner for DbInterner<'db> {
SolverDefId::TypeAliasId(it) => it.lookup(self.db()).container,
SolverDefId::ConstId(it) => it.lookup(self.db()).container,
SolverDefId::InternedClosureId(it) => {
- return self
- .db()
- .lookup_intern_closure(it)
- .0
- .as_generic_def_id(self.db())
- .unwrap()
- .into();
+ return self.db().lookup_intern_closure(it).0.generic_def(self.db()).into();
}
SolverDefId::InternedCoroutineId(it) => {
- return self
- .db()
- .lookup_intern_coroutine(it)
- .0
- .as_generic_def_id(self.db())
- .unwrap()
- .into();
+ return self.db().lookup_intern_coroutine(it).0.generic_def(self.db()).into();
}
SolverDefId::StaticId(_)
| SolverDefId::AdtId(_)
@@ -1332,7 +1327,8 @@ impl<'db> Interner for DbInterner<'db> {
| SolverDefId::BuiltinDeriveImplId(_)
| SolverDefId::EnumVariantId(..)
| SolverDefId::Ctor(..)
- | SolverDefId::InternedOpaqueTyId(..) => panic!(),
+ | SolverDefId::InternedOpaqueTyId(..)
+ | SolverDefId::AnonConstId(_) => panic!(),
};
match container {
@@ -1361,8 +1357,8 @@ impl<'db> Interner for DbInterner<'db> {
// FIXME: Make this a query? I don't believe this can be accessed from bodies other than
// the current infer query, except with revealed opaques - is it rare enough to not matter?
let InternedCoroutine(owner, expr_id) = def_id.0.loc(self.db);
- let body = self.db.body(owner);
- let expr = &body[expr_id];
+ let store = ExpressionStore::of(self.db, owner);
+ let expr = &store[expr_id];
match *expr {
hir_def::hir::Expr::Closure { closure_kind, .. } => match closure_kind {
hir_def::hir::ClosureKind::Coroutine(movability) => match movability {
@@ -1795,6 +1791,7 @@ impl<'db> Interner for DbInterner<'db> {
| SolverDefId::InternedCoroutineId(_)
| SolverDefId::InternedOpaqueTyId(_)
| SolverDefId::EnumVariantId(_)
+ | SolverDefId::AnonConstId(_)
| SolverDefId::Ctor(_) => return None,
};
module.block(self.db)
@@ -1933,7 +1930,7 @@ impl<'db> Interner for DbInterner<'db> {
fn impl_is_default(self, impl_def_id: Self::ImplId) -> bool {
match impl_def_id {
- AnyImplId::ImplId(impl_id) => self.db.impl_signature(impl_id).is_default(),
+ AnyImplId::ImplId(impl_id) => ImplSignature::of(self.db, impl_id).is_default(),
AnyImplId::BuiltinDeriveImplId(_) => false,
}
}
@@ -1960,7 +1957,7 @@ impl<'db> Interner for DbInterner<'db> {
let AnyImplId::ImplId(impl_id) = impl_id else {
return ImplPolarity::Positive;
};
- let impl_data = self.db().impl_signature(impl_id);
+ let impl_data = ImplSignature::of(self.db(), impl_id);
if impl_data.flags.contains(ImplFlags::NEGATIVE) {
ImplPolarity::Negative
} else {
@@ -1969,12 +1966,12 @@ impl<'db> Interner for DbInterner<'db> {
}
fn trait_is_auto(self, trait_: Self::TraitId) -> bool {
- let trait_data = self.db().trait_signature(trait_.0);
+ let trait_data = TraitSignature::of(self.db(), trait_.0);
trait_data.flags.contains(TraitFlags::AUTO)
}
fn trait_is_alias(self, trait_: Self::TraitId) -> bool {
- let trait_data = self.db().trait_signature(trait_.0);
+ let trait_data = TraitSignature::of(self.db(), trait_.0);
trait_data.flags.contains(TraitFlags::ALIAS)
}
@@ -1983,7 +1980,7 @@ impl<'db> Interner for DbInterner<'db> {
}
fn trait_is_fundamental(self, trait_: Self::TraitId) -> bool {
- let trait_data = self.db().trait_signature(trait_.0);
+ let trait_data = TraitSignature::of(self.db(), trait_.0);
trait_data.flags.contains(TraitFlags::FUNDAMENTAL)
}
@@ -2006,9 +2003,9 @@ impl<'db> Interner for DbInterner<'db> {
// FIXME: Make this a query? I don't believe this can be accessed from bodies other than
// the current infer query, except with revealed opaques - is it rare enough to not matter?
let InternedCoroutine(owner, expr_id) = def_id.0.loc(self.db);
- let body = self.db.body(owner);
+ let store = ExpressionStore::of(self.db, owner);
matches!(
- body[expr_id],
+ store[expr_id],
hir_def::hir::Expr::Closure {
closure_kind: hir_def::hir::ClosureKind::Coroutine(_),
..
@@ -2020,9 +2017,9 @@ impl<'db> Interner for DbInterner<'db> {
// FIXME: Make this a query? I don't believe this can be accessed from bodies other than
// the current infer query, except with revealed opaques - is it rare enough to not matter?
let InternedCoroutine(owner, expr_id) = def_id.0.loc(self.db);
- let body = self.db.body(owner);
+ let store = ExpressionStore::of(self.db, owner);
matches!(
- body[expr_id],
+ store[expr_id],
hir_def::hir::Expr::Closure { closure_kind: hir_def::hir::ClosureKind::Async, .. }
| hir_def::hir::Expr::Async { .. }
)
@@ -2143,7 +2140,7 @@ impl<'db> Interner for DbInterner<'db> {
crate::opaques::opaque_types_defined_by(self.db, def_id, &mut result);
// Collect coroutines.
- let body = self.db.body(def_id);
+ let body = Body::of(self.db, def_id);
body.exprs().for_each(|(expr_id, expr)| {
if matches!(
expr,
@@ -2154,8 +2151,10 @@ impl<'db> Interner for DbInterner<'db> {
..
}
) {
- let coroutine =
- InternedCoroutineId::new(self.db, InternedCoroutine(def_id, expr_id));
+ let coroutine = InternedCoroutineId::new(
+ self.db,
+ InternedCoroutine(ExpressionStoreOwnerId::Body(def_id), expr_id),
+ );
result.push(coroutine.into());
}
});
@@ -2184,7 +2183,7 @@ impl<'db> Interner for DbInterner<'db> {
CallableDefId::FunctionId(id) => id,
_ => return false,
};
- self.db().function_signature(id).flags.contains(FnFlags::CONST)
+ FunctionSignature::of(self.db(), id).flags.contains(FnFlags::CONST)
}
fn impl_is_const(self, _def_id: Self::ImplId) -> bool {
@@ -2232,11 +2231,11 @@ impl<'db> Interner for DbInterner<'db> {
}
fn trait_is_coinductive(self, trait_: Self::TraitId) -> bool {
- self.db().trait_signature(trait_.0).flags.contains(TraitFlags::COINDUCTIVE)
+ TraitSignature::of(self.db(), trait_.0).flags.contains(TraitFlags::COINDUCTIVE)
}
fn trait_is_unsafe(self, trait_: Self::TraitId) -> bool {
- self.db().trait_signature(trait_.0).flags.contains(TraitFlags::UNSAFE)
+ TraitSignature::of(self.db(), trait_.0).flags.contains(TraitFlags::UNSAFE)
}
fn impl_self_is_guaranteed_unsized(self, _def_id: Self::ImplId) -> bool {
diff --git a/crates/hir-ty/src/next_solver/ir_print.rs b/crates/hir-ty/src/next_solver/ir_print.rs
index 65931549db..e0732b3473 100644
--- a/crates/hir-ty/src/next_solver/ir_print.rs
+++ b/crates/hir-ty/src/next_solver/ir_print.rs
@@ -1,5 +1,6 @@
//! Things related to IR printing in the next-trait-solver.
+use hir_def::signatures::{TraitSignature, TypeAliasSignature};
use rustc_type_ir::{self as ty, ir_print::IrPrint};
use super::SolverDefId;
@@ -14,7 +15,7 @@ impl<'db> IrPrint<ty::AliasTy<Self>> for DbInterner<'db> {
crate::with_attached_db(|db| match t.def_id {
SolverDefId::TypeAliasId(id) => fmt.write_str(&format!(
"AliasTy({:?}[{:?}])",
- db.type_alias_signature(id).name.as_str(),
+ TypeAliasSignature::of(db, id).name.as_str(),
t.args
)),
SolverDefId::InternedOpaqueTyId(id) => {
@@ -34,7 +35,7 @@ impl<'db> IrPrint<ty::AliasTerm<Self>> for DbInterner<'db> {
crate::with_attached_db(|db| match t.def_id {
SolverDefId::TypeAliasId(id) => fmt.write_str(&format!(
"AliasTerm({:?}[{:?}])",
- db.type_alias_signature(id).name.as_str(),
+ TypeAliasSignature::of(db, id).name.as_str(),
t.args
)),
SolverDefId::InternedOpaqueTyId(id) => {
@@ -58,13 +59,13 @@ impl<'db> IrPrint<ty::TraitRef<Self>> for DbInterner<'db> {
fmt.write_str(&format!(
"{:?}: {}",
self_ty,
- db.trait_signature(trait_).name.as_str()
+ TraitSignature::of(db, trait_).name.as_str()
))
} else {
fmt.write_str(&format!(
"{:?}: {}<{:?}>",
self_ty,
- db.trait_signature(trait_).name.as_str(),
+ TraitSignature::of(db, trait_).name.as_str(),
trait_args
))
}
@@ -121,7 +122,7 @@ impl<'db> IrPrint<ty::ExistentialTraitRef<Self>> for DbInterner<'db> {
let trait_ = t.def_id.0;
fmt.write_str(&format!(
"ExistentialTraitRef({:?}[{:?}])",
- db.trait_signature(trait_).name.as_str(),
+ TraitSignature::of(db, trait_).name.as_str(),
t.args
))
})
@@ -146,7 +147,7 @@ impl<'db> IrPrint<ty::ExistentialProjection<Self>> for DbInterner<'db> {
};
fmt.write_str(&format!(
"ExistentialProjection(({:?}[{:?}]) -> {:?})",
- db.type_alias_signature(id).name.as_str(),
+ TypeAliasSignature::of(db, id).name.as_str(),
t.args,
t.term
))
@@ -172,7 +173,7 @@ impl<'db> IrPrint<ty::ProjectionPredicate<Self>> for DbInterner<'db> {
};
fmt.write_str(&format!(
"ProjectionPredicate(({:?}[{:?}]) -> {:?})",
- db.type_alias_signature(id).name.as_str(),
+ TypeAliasSignature::of(db, id).name.as_str(),
t.projection_term.args,
t.term
))
diff --git a/crates/hir-ty/src/next_solver/solver.rs b/crates/hir-ty/src/next_solver/solver.rs
index 15d6e2e451..848bb110af 100644
--- a/crates/hir-ty/src/next_solver/solver.rs
+++ b/crates/hir-ty/src/next_solver/solver.rs
@@ -1,6 +1,9 @@
//! Defining `SolverContext` for next-trait-solver.
-use hir_def::{AssocItemId, GeneralConstId};
+use hir_def::{
+ AssocItemId, GeneralConstId,
+ signatures::{ConstSignature, TypeAliasSignature},
+};
use rustc_next_trait_solver::delegate::SolverDelegate;
use rustc_type_ir::{
AliasTyKind, GenericArgKind, InferCtxtLike, Interner, PredicatePolarity, TypeFlags,
@@ -18,7 +21,7 @@ use crate::next_solver::{
};
use super::{
- DbInterner, ErrorGuaranteed, GenericArg, SolverDefId, Span,
+ Const, DbInterner, ErrorGuaranteed, GenericArg, SolverDefId, Span,
infer::{DbInternerInferExt, InferCtxt, canonical::instantiate::CanonicalExt},
};
@@ -181,52 +184,53 @@ impl<'db> SolverDelegate for SolverContext<'db> {
return Ok(None);
};
let impl_items = impl_id.impl_items(self.0.interner.db());
- let id =
- match trait_assoc_def_id {
- SolverDefId::TypeAliasId(trait_assoc_id) => {
- let trait_assoc_data = self.0.interner.db.type_alias_signature(trait_assoc_id);
- impl_items
- .items
- .iter()
- .find_map(|(impl_assoc_name, impl_assoc_id)| {
- if let AssocItemId::TypeAliasId(impl_assoc_id) = *impl_assoc_id
- && *impl_assoc_name == trait_assoc_data.name
- {
- Some(impl_assoc_id)
- } else {
- None
- }
- })
- .or_else(|| {
- if trait_assoc_data.ty.is_some() { Some(trait_assoc_id) } else { None }
- })
- .map(SolverDefId::TypeAliasId)
- }
- SolverDefId::ConstId(trait_assoc_id) => {
- let trait_assoc_data = self.0.interner.db.const_signature(trait_assoc_id);
- let trait_assoc_name = trait_assoc_data
- .name
- .as_ref()
- .expect("unnamed consts should not get passed to the solver");
- impl_items
- .items
- .iter()
- .find_map(|(impl_assoc_name, impl_assoc_id)| {
- if let AssocItemId::ConstId(impl_assoc_id) = *impl_assoc_id
- && impl_assoc_name == trait_assoc_name
- {
- Some(impl_assoc_id)
- } else {
- None
- }
- })
- .or_else(|| {
+ let id = match trait_assoc_def_id {
+ SolverDefId::TypeAliasId(trait_assoc_id) => {
+ let trait_assoc_data = TypeAliasSignature::of(self.0.interner.db, trait_assoc_id);
+ impl_items
+ .items
+ .iter()
+ .find_map(|(impl_assoc_name, impl_assoc_id)| {
+ if let AssocItemId::TypeAliasId(impl_assoc_id) = *impl_assoc_id
+ && *impl_assoc_name == trait_assoc_data.name
+ {
+ Some(impl_assoc_id)
+ } else {
+ None
+ }
+ })
+ .or_else(|| {
+ if trait_assoc_data.ty.is_some() { Some(trait_assoc_id) } else { None }
+ })
+ .map(SolverDefId::TypeAliasId)
+ }
+ SolverDefId::ConstId(trait_assoc_id) => {
+ let trait_assoc_data = ConstSignature::of(self.0.interner.db, trait_assoc_id);
+ let trait_assoc_name = trait_assoc_data
+ .name
+ .as_ref()
+ .expect("unnamed consts should not get passed to the solver");
+ impl_items
+ .items
+ .iter()
+ .find_map(|(impl_assoc_name, impl_assoc_id)| {
+ if let AssocItemId::ConstId(impl_assoc_id) = *impl_assoc_id
+ && impl_assoc_name == trait_assoc_name
+ {
+ Some(impl_assoc_id)
+ } else {
+ None
+ }
+ })
+ .or_else(
+ || {
if trait_assoc_data.has_body() { Some(trait_assoc_id) } else { None }
- })
- .map(SolverDefId::ConstId)
- }
- _ => panic!("Unexpected SolverDefId"),
- };
+ },
+ )
+ .map(SolverDefId::ConstId)
+ }
+ _ => panic!("Unexpected SolverDefId"),
+ };
Ok(id)
}
@@ -256,6 +260,11 @@ impl<'db> SolverDelegate for SolverContext<'db> {
let ec = self.cx().db.const_eval_static(c).ok()?;
Some(ec)
}
+ // TODO: Wire up const_eval_anon query in Phase 5.
+ // For now, return an error const so normalization resolves the
+ // unevaluated const to Error (matching the old behavior where
+ // complex expressions produced ConstKind::Error directly).
+ GeneralConstId::AnonConstId(_) => Some(Const::error(self.cx())),
}
}
diff --git a/crates/hir-ty/src/next_solver/ty.rs b/crates/hir-ty/src/next_solver/ty.rs
index 1173028a10..192cdb70ae 100644
--- a/crates/hir-ty/src/next_solver/ty.rs
+++ b/crates/hir-ty/src/next_solver/ty.rs
@@ -4,7 +4,7 @@ use std::ops::ControlFlow;
use hir_def::{
AdtId, HasModule, TypeParamId,
- hir::generics::{TypeOrConstParamData, TypeParamProvenance},
+ hir::generics::{GenericParams, TypeOrConstParamData, TypeParamProvenance},
};
use hir_def::{TraitId, type_ref::Rawness};
use intern::{Interned, InternedRef, impl_internable};
@@ -690,7 +690,7 @@ impl<'db> Ty<'db> {
),
TyKind::Param(param) => {
// FIXME: We shouldn't use `param.id` here.
- let generic_params = db.generic_params(param.id.parent());
+ let generic_params = GenericParams::of(db, param.id.parent());
let param_data = &generic_params[param.id.local_id()];
match param_data {
TypeOrConstParamData::TypeParamData(p) => match p.provenance {
@@ -714,7 +714,7 @@ impl<'db> Ty<'db> {
}
TyKind::Coroutine(coroutine_id, _args) => {
let InternedCoroutine(owner, _) = coroutine_id.0.loc(db);
- let krate = owner.module(db).krate(db);
+ let krate = owner.krate(db);
if let Some(future_trait) = hir_def::lang_item::lang_items(db, krate).Future {
// This is only used by type walking.
// Parameters will be walked outside, and projection predicate is not used.
diff --git a/crates/hir-ty/src/opaques.rs b/crates/hir-ty/src/opaques.rs
index 27ae5e39d5..ce93a33422 100644
--- a/crates/hir-ty/src/opaques.rs
+++ b/crates/hir-ty/src/opaques.rs
@@ -1,7 +1,8 @@
//! Handling of opaque types, detection of defining scope and hidden type.
use hir_def::{
- AssocItemId, AssocItemLoc, DefWithBodyId, FunctionId, HasModule, ItemContainerId, TypeAliasId,
+ AssocItemId, AssocItemLoc, DefWithBodyId, ExpressionStoreOwnerId, FunctionId, GenericDefId,
+ HasModule, ItemContainerId, TypeAliasId, signatures::ImplSignature,
};
use hir_expand::name::Name;
use la_arena::ArenaMap;
@@ -55,7 +56,7 @@ pub(crate) fn opaque_types_defined_by(
};
let extend_with_atpit_from_container = |container| match container {
ItemContainerId::ImplId(impl_id) => {
- if db.impl_signature(impl_id).target_trait.is_some() {
+ if ImplSignature::of(db, impl_id).target_trait.is_some() {
extend_with_atpit_from_assoc_items(&impl_id.impl_items(db).items);
}
}
@@ -94,7 +95,7 @@ pub(crate) fn rpit_hidden_types<'db>(
db: &'db dyn HirDatabase,
function: FunctionId,
) -> ArenaMap<ImplTraitIdx, StoredEarlyBinder<StoredTy>> {
- let infer = InferenceResult::for_body(db, function.into());
+ let infer = InferenceResult::of(db, DefWithBodyId::from(function));
let mut result = ArenaMap::new();
for (opaque, hidden_type) in infer.return_position_impl_trait_types(db) {
result.insert(opaque, StoredEarlyBinder::bind(hidden_type.store()));
@@ -122,13 +123,14 @@ pub(crate) fn tait_hidden_types<'db>(
let infcx = interner.infer_ctxt().build(TypingMode::non_body_analysis());
let mut ocx = ObligationCtxt::new(&infcx);
let cause = ObligationCause::dummy();
- let param_env = db.trait_environment(type_alias.into());
+ let param_env =
+ db.trait_environment(ExpressionStoreOwnerId::from(GenericDefId::from(type_alias)));
let defining_bodies = tait_defining_bodies(db, &loc);
let mut result = ArenaMap::with_capacity(taits_count);
for defining_body in defining_bodies {
- let infer = InferenceResult::for_body(db, defining_body);
+ let infer = InferenceResult::of(db, defining_body);
for (&opaque, hidden_type) in &infer.type_of_opaque {
let ImplTraitId::TypeAliasImplTrait(opaque_owner, opaque_idx) = opaque.loc(db) else {
continue;
@@ -195,7 +197,7 @@ fn tait_defining_bodies(
};
match loc.container {
ItemContainerId::ImplId(impl_id) => {
- if db.impl_signature(impl_id).target_trait.is_some() {
+ if ImplSignature::of(db, impl_id).target_trait.is_some() {
return from_assoc_items(&impl_id.impl_items(db).items);
}
}
diff --git a/crates/hir-ty/src/representability.rs b/crates/hir-ty/src/representability.rs
index 7e40f2d7ac..bae204c4ef 100644
--- a/crates/hir-ty/src/representability.rs
+++ b/crates/hir-ty/src/representability.rs
@@ -1,6 +1,6 @@
//! Detecting whether a type is infinitely-sized.
-use hir_def::{AdtId, VariantId};
+use hir_def::{AdtId, VariantId, hir::generics::GenericParams};
use rustc_type_ir::inherent::{AdtDef, IntoKind};
use crate::{
@@ -88,7 +88,7 @@ fn representability_adt_ty<'db>(
}
fn params_in_repr(db: &dyn HirDatabase, def_id: AdtId) -> Box<[bool]> {
- let generics = db.generic_params(def_id.into());
+ let generics = GenericParams::of(db, def_id.into());
let mut params_in_repr = (0..generics.len_lifetimes() + generics.len_type_or_consts())
.map(|_| false)
.collect::<Box<[bool]>>();
diff --git a/crates/hir-ty/src/specialization.rs b/crates/hir-ty/src/specialization.rs
index d97a35549c..90cbcfea6a 100644
--- a/crates/hir-ty/src/specialization.rs
+++ b/crates/hir-ty/src/specialization.rs
@@ -1,6 +1,9 @@
//! Impl specialization related things
-use hir_def::{HasModule, ImplId, nameres::crate_def_map};
+use hir_def::{
+ ExpressionStoreOwnerId, GenericDefId, HasModule, ImplId, nameres::crate_def_map,
+ signatures::ImplSignature,
+};
use intern::sym;
use tracing::debug;
@@ -45,11 +48,13 @@ fn specializes_query(
specializing_impl_def_id: ImplId,
parent_impl_def_id: ImplId,
) -> bool {
- let trait_env = db.trait_environment(specializing_impl_def_id.into());
+ let trait_env = db.trait_environment(ExpressionStoreOwnerId::from(GenericDefId::from(
+ specializing_impl_def_id,
+ )));
let interner = DbInterner::new_with(db, specializing_impl_def_id.krate(db));
- let specializing_impl_signature = db.impl_signature(specializing_impl_def_id);
- let parent_impl_signature = db.impl_signature(parent_impl_def_id);
+ let specializing_impl_signature = ImplSignature::of(db, specializing_impl_def_id);
+ let parent_impl_signature = ImplSignature::of(db, parent_impl_def_id);
// We determine whether there's a subset relationship by:
//
diff --git a/crates/hir-ty/src/tests.rs b/crates/hir-ty/src/tests.rs
index 67ab89f5ec..430a570444 100644
--- a/crates/hir-ty/src/tests.rs
+++ b/crates/hir-ty/src/tests.rs
@@ -16,9 +16,9 @@ mod traits;
use base_db::{Crate, SourceDatabase};
use expect_test::Expect;
use hir_def::{
- AssocItemId, DefWithBodyId, HasModule, Lookup, ModuleDefId, ModuleId, SyntheticSyntax,
- db::DefDatabase,
- expr_store::{Body, BodySourceMap},
+ AssocItemId, DefWithBodyId, GenericDefId, HasModule, Lookup, ModuleDefId, ModuleId,
+ SyntheticSyntax,
+ expr_store::{Body, BodySourceMap, ExpressionStore, ExpressionStoreSourceMap},
hir::{ExprId, Pat, PatId},
item_scope::ItemScope,
nameres::DefMap,
@@ -34,7 +34,6 @@ use syntax::{
ast::{self, AstNode, HasName},
};
use test_fixture::WithFixture;
-use triomphe::Arc;
use crate::{
InferenceResult,
@@ -146,15 +145,15 @@ fn check_impl(
let mut unexpected_type_mismatches = String::new();
for (def, krate) in defs {
let display_target = DisplayTarget::from_crate(&db, krate);
- let (body, body_source_map) = db.body_with_source_map(def);
- let inference_result = InferenceResult::for_body(&db, def);
+ let (body, body_source_map) = Body::with_source_map(&db, def);
+ let inference_result = InferenceResult::of(&db, def);
for (pat, ty) in inference_result.type_of_pat.iter() {
let mut ty = ty.as_ref();
if let Pat::Bind { id, .. } = body[pat] {
ty = inference_result.type_of_binding[id].as_ref();
}
- let node = match pat_node(&body_source_map, pat, &db) {
+ let node = match pat_node(body_source_map, pat, &db) {
Some(value) => value,
None => continue,
};
@@ -171,7 +170,7 @@ fn check_impl(
for (expr, ty) in inference_result.type_of_expr.iter() {
let ty = ty.as_ref();
- let node = match expr_node(&body_source_map, expr, &db) {
+ let node = match expr_node(body_source_map, expr, &db) {
Some(value) => value,
None => continue,
};
@@ -202,9 +201,9 @@ fn check_impl(
for (expr_or_pat, mismatch) in inference_result.type_mismatches() {
let Some(node) = (match expr_or_pat {
hir_def::hir::ExprOrPatId::ExprId(expr) => {
- expr_node(&body_source_map, expr, &db)
+ expr_node(body_source_map, expr, &db)
}
- hir_def::hir::ExprOrPatId::PatId(pat) => pat_node(&body_source_map, pat, &db),
+ hir_def::hir::ExprOrPatId::PatId(pat) => pat_node(body_source_map, pat, &db),
}) else {
continue;
};
@@ -223,7 +222,7 @@ fn check_impl(
}
for (type_ref, ty) in inference_result.placeholder_types() {
- let node = match type_node(&body_source_map, type_ref, &db) {
+ let node = match type_node(body_source_map, type_ref, &db) {
Some(value) => value,
None => continue,
};
@@ -321,16 +320,20 @@ fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String {
let mut buf = String::new();
let mut infer_def = |inference_result: &InferenceResult,
- body: Arc<Body>,
- body_source_map: Arc<BodySourceMap>,
+ store: &ExpressionStore,
+ source_map: &ExpressionStoreSourceMap,
+ self_param: Option<(
+ hir_def::hir::BindingId,
+ Option<InFile<hir_def::expr_store::SelfParamPtr>>,
+ )>,
krate: Crate| {
let display_target = DisplayTarget::from_crate(&db, krate);
let mut types: Vec<(InFile<SyntaxNode>, Ty<'_>)> = Vec::new();
let mut mismatches: Vec<(InFile<SyntaxNode>, &TypeMismatch)> = Vec::new();
- if let Some(self_param) = body.self_param {
- let ty = &inference_result.type_of_binding[self_param];
- if let Some(syntax_ptr) = body_source_map.self_param_syntax() {
+ if let Some((binding_id, syntax_ptr)) = self_param {
+ let ty = &inference_result.type_of_binding[binding_id];
+ if let Some(syntax_ptr) = syntax_ptr {
let root = db.parse_or_expand(syntax_ptr.file_id);
let node = syntax_ptr.map(|ptr| ptr.to_node(&root).syntax().clone());
types.push((node, ty.as_ref()));
@@ -338,10 +341,10 @@ fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String {
}
for (pat, mut ty) in inference_result.type_of_pat.iter() {
- if let Pat::Bind { id, .. } = body[pat] {
+ if let Pat::Bind { id, .. } = store[pat] {
ty = &inference_result.type_of_binding[id];
}
- let node = match body_source_map.pat_syntax(pat) {
+ let node = match source_map.pat_syntax(pat) {
Ok(sp) => {
let root = db.parse_or_expand(sp.file_id);
sp.map(|ptr| ptr.to_node(&root).syntax().clone())
@@ -355,7 +358,7 @@ fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String {
}
for (expr, ty) in inference_result.type_of_expr.iter() {
- let node = match body_source_map.expr_syntax(expr) {
+ let node = match source_map.expr_syntax(expr) {
Ok(sp) => {
let root = db.parse_or_expand(sp.file_id);
sp.map(|ptr| ptr.to_node(&root).syntax().clone())
@@ -414,16 +417,56 @@ fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String {
let def_map = module.def_map(&db);
let mut defs: Vec<(DefWithBodyId, Crate)> = Vec::new();
+ let mut generic_defs: Vec<(GenericDefId, Crate)> = Vec::new();
visit_module(&db, def_map, module, &mut |it| {
- let def = match it {
- ModuleDefId::FunctionId(it) => it.into(),
- ModuleDefId::EnumVariantId(it) => it.into(),
- ModuleDefId::ConstId(it) => it.into(),
- ModuleDefId::StaticId(it) => it.into(),
- _ => return,
- };
- defs.push((def, module.krate(&db)))
+ let krate = module.krate(&db);
+ match it {
+ ModuleDefId::FunctionId(it) => {
+ defs.push((it.into(), krate));
+ generic_defs.push((it.into(), krate));
+ }
+ ModuleDefId::EnumVariantId(it) => {
+ defs.push((it.into(), krate));
+ }
+ ModuleDefId::ConstId(it) => {
+ defs.push((it.into(), krate));
+ generic_defs.push((it.into(), krate));
+ }
+ ModuleDefId::StaticId(it) => {
+ defs.push((it.into(), krate));
+ generic_defs.push((it.into(), krate));
+ }
+ ModuleDefId::AdtId(it) => {
+ generic_defs.push((it.into(), krate));
+ }
+ ModuleDefId::TraitId(it) => {
+ generic_defs.push((it.into(), krate));
+ }
+ ModuleDefId::TypeAliasId(it) => {
+ generic_defs.push((it.into(), krate));
+ }
+ _ => {}
+ }
});
+ // Also collect impls
+ for impl_id in def_map[module].scope.impls() {
+ generic_defs.push((impl_id.into(), module.krate(&db)));
+ let impl_data = impl_id.impl_items(&db);
+ for &(_, item) in impl_data.items.iter() {
+ match item {
+ AssocItemId::FunctionId(it) => {
+ generic_defs.push((it.into(), module.krate(&db)));
+ }
+ AssocItemId::ConstId(it) => {
+ generic_defs.push((it.into(), module.krate(&db)));
+ }
+ AssocItemId::TypeAliasId(it) => {
+ generic_defs.push((it.into(), module.krate(&db)));
+ }
+ }
+ }
+ }
+
defs.sort_by_key(|(def, _)| match def {
DefWithBodyId::FunctionId(it) => {
let loc = it.lookup(&db);
@@ -443,9 +486,22 @@ fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String {
}
});
for (def, krate) in defs {
- let (body, source_map) = db.body_with_source_map(def);
- let infer = InferenceResult::for_body(&db, def);
- infer_def(infer, body, source_map, krate);
+ let (body, source_map) = Body::with_source_map(&db, def);
+ let infer = InferenceResult::of(&db, def);
+ let self_param = body.self_param.map(|id| (id, source_map.self_param_syntax()));
+ infer_def(infer, body, source_map, self_param, krate);
+ }
+
+ // Also infer signature const expressions (array lengths, const generic args, etc.)
+ generic_defs.dedup();
+ for (def, krate) in generic_defs {
+ let (store, source_map) = ExpressionStore::with_source_map(&db, def.into());
+ // Skip if there are no const expressions in the signature
+ if store.const_expr_origins().is_empty() {
+ continue;
+ }
+ let infer = InferenceResult::of(&db, def);
+ infer_def(infer, store, source_map, None, krate);
}
buf.truncate(buf.trim_end().len());
@@ -465,14 +521,14 @@ pub(crate) fn visit_module(
for &(_, item) in impl_data.items.iter() {
match item {
AssocItemId::FunctionId(it) => {
- let body = db.body(it.into());
+ let body = Body::of(db, it.into());
cb(it.into());
- visit_body(db, &body, cb);
+ visit_body(db, body, cb);
}
AssocItemId::ConstId(it) => {
- let body = db.body(it.into());
+ let body = Body::of(db, it.into());
cb(it.into());
- visit_body(db, &body, cb);
+ visit_body(db, body, cb);
}
AssocItemId::TypeAliasId(it) => {
cb(it.into());
@@ -491,22 +547,22 @@ pub(crate) fn visit_module(
cb(decl);
match decl {
ModuleDefId::FunctionId(it) => {
- let body = db.body(it.into());
- visit_body(db, &body, cb);
+ let body = Body::of(db, it.into());
+ visit_body(db, body, cb);
}
ModuleDefId::ConstId(it) => {
- let body = db.body(it.into());
- visit_body(db, &body, cb);
+ let body = Body::of(db, it.into());
+ visit_body(db, body, cb);
}
ModuleDefId::StaticId(it) => {
- let body = db.body(it.into());
- visit_body(db, &body, cb);
+ let body = Body::of(db, it.into());
+ visit_body(db, body, cb);
}
ModuleDefId::AdtId(hir_def::AdtId::EnumId(it)) => {
it.enum_variants(db).variants.iter().for_each(|&(it, _, _)| {
- let body = db.body(it.into());
+ let body = Body::of(db, it.into());
cb(it.into());
- visit_body(db, &body, cb);
+ visit_body(db, body, cb);
});
}
ModuleDefId::TraitId(it) => {
@@ -596,16 +652,14 @@ fn salsa_bug() {
let module = db.module_for_file(pos.file_id.file_id(&db));
let crate_def_map = module.def_map(&db);
visit_module(&db, crate_def_map, module, &mut |def| {
- InferenceResult::for_body(
- &db,
- match def {
- ModuleDefId::FunctionId(it) => it.into(),
- ModuleDefId::EnumVariantId(it) => it.into(),
- ModuleDefId::ConstId(it) => it.into(),
- ModuleDefId::StaticId(it) => it.into(),
- _ => return,
- },
- );
+ let body_def: DefWithBodyId = match def {
+ ModuleDefId::FunctionId(it) => it.into(),
+ ModuleDefId::EnumVariantId(it) => it.into(),
+ ModuleDefId::ConstId(it) => it.into(),
+ ModuleDefId::StaticId(it) => it.into(),
+ _ => return,
+ };
+ InferenceResult::of(&db, body_def);
});
});
@@ -640,16 +694,14 @@ fn salsa_bug() {
let module = db.module_for_file(pos.file_id.file_id(&db));
let crate_def_map = module.def_map(&db);
visit_module(&db, crate_def_map, module, &mut |def| {
- InferenceResult::for_body(
- &db,
- match def {
- ModuleDefId::FunctionId(it) => it.into(),
- ModuleDefId::EnumVariantId(it) => it.into(),
- ModuleDefId::ConstId(it) => it.into(),
- ModuleDefId::StaticId(it) => it.into(),
- _ => return,
- },
- );
+ let body_def: DefWithBodyId = match def {
+ ModuleDefId::FunctionId(it) => it.into(),
+ ModuleDefId::EnumVariantId(it) => it.into(),
+ ModuleDefId::ConstId(it) => it.into(),
+ ModuleDefId::StaticId(it) => it.into(),
+ _ => return,
+ };
+ InferenceResult::of(&db, body_def);
});
})
}
diff --git a/crates/hir-ty/src/tests/closure_captures.rs b/crates/hir-ty/src/tests/closure_captures.rs
index f089120cd7..9e68756821 100644
--- a/crates/hir-ty/src/tests/closure_captures.rs
+++ b/crates/hir-ty/src/tests/closure_captures.rs
@@ -1,5 +1,8 @@
use expect_test::{Expect, expect};
-use hir_def::db::DefDatabase;
+use hir_def::{
+ DefWithBodyId,
+ expr_store::{Body, ExpressionStore},
+};
use hir_expand::{HirFileId, files::InFileWrapper};
use itertools::Itertools;
use span::TextRange;
@@ -28,19 +31,20 @@ fn check_closure_captures(#[rust_analyzer::rust_fixture] ra_fixture: &str, expec
let mut captures_info = Vec::new();
for def in defs {
- let def = match def {
+ let def: DefWithBodyId = match def {
hir_def::ModuleDefId::FunctionId(it) => it.into(),
hir_def::ModuleDefId::EnumVariantId(it) => it.into(),
hir_def::ModuleDefId::ConstId(it) => it.into(),
hir_def::ModuleDefId::StaticId(it) => it.into(),
_ => continue,
};
- let infer = InferenceResult::for_body(&db, def);
+ let infer = InferenceResult::of(&db, def);
let db = &db;
captures_info.extend(infer.closure_info.iter().flat_map(
|(closure_id, (captures, _))| {
let closure = db.lookup_intern_closure(*closure_id);
- let source_map = db.body_with_source_map(closure.0).1;
+ let body_owner = closure.0;
+ let source_map = ExpressionStore::with_source_map(db, body_owner).1;
let closure_text_range = source_map
.expr_syntax(closure.1)
.expect("failed to map closure to SyntaxNode")
@@ -56,7 +60,8 @@ fn check_closure_captures(#[rust_analyzer::rust_fixture] ra_fixture: &str, expec
}
// FIXME: Deduplicate this with hir::Local::sources().
- let (body, source_map) = db.body_with_source_map(closure.0);
+ let (body, source_map) =
+ Body::with_source_map(db, body_owner.as_def_with_body().unwrap());
let local_text_range =
match body.self_param.zip(source_map.self_param_syntax()) {
Some((param, source)) if param == capture.local() => {
@@ -71,7 +76,7 @@ fn check_closure_captures(#[rust_analyzer::rust_fixture] ra_fixture: &str, expec
.map(|it| format!("{it:?}"))
.join(", "),
};
- let place = capture.display_place(closure.0, db);
+ let place = capture.display_place(body_owner, db);
let capture_ty = capture
.ty
.get()
diff --git a/crates/hir-ty/src/tests/incremental.rs b/crates/hir-ty/src/tests/incremental.rs
index faa7b80a89..e806999cb4 100644
--- a/crates/hir-ty/src/tests/incremental.rs
+++ b/crates/hir-ty/src/tests/incremental.rs
@@ -24,7 +24,7 @@ fn foo() -> i32 {
let crate_def_map = module.def_map(&db);
visit_module(&db, crate_def_map, module, &mut |def| {
if let ModuleDefId::FunctionId(it) = def {
- InferenceResult::for_body(&db, it.into());
+ InferenceResult::of(&db, DefWithBodyId::from(it));
}
});
},
@@ -34,21 +34,21 @@ fn foo() -> i32 {
"source_root_crates_shim",
"crate_local_def_map",
"file_item_tree_query",
- "ast_id_map_shim",
+ "ast_id_map",
"parse_shim",
"real_span_map_shim",
"InferenceResult::for_body_",
- "function_signature_shim",
- "function_signature_with_source_map_shim",
+ "FunctionSignature::of_",
+ "FunctionSignature::with_source_map_",
"AttrFlags::query_",
- "body_shim",
- "body_with_source_map_shim",
+ "Body::of_",
+ "Body::with_source_map_",
"trait_environment_query",
"lang_items",
"crate_lang_items",
"GenericPredicates::query_with_diagnostics_",
"ImplTraits::return_type_impl_traits_",
- "expr_scopes_shim",
+ "ExprScopes::body_expr_scopes_",
]
"#]],
);
@@ -69,7 +69,7 @@ fn foo() -> i32 {
let crate_def_map = module.def_map(&db);
visit_module(&db, crate_def_map, module, &mut |def| {
if let ModuleDefId::FunctionId(it) = def {
- InferenceResult::for_body(&db, it.into());
+ InferenceResult::of(&db, DefWithBodyId::from(it));
}
});
},
@@ -77,14 +77,14 @@ fn foo() -> i32 {
expect_test::expect![[r#"
[
"parse_shim",
- "ast_id_map_shim",
+ "ast_id_map",
"file_item_tree_query",
"real_span_map_shim",
"AttrFlags::query_",
- "function_signature_with_source_map_shim",
- "function_signature_shim",
- "body_with_source_map_shim",
- "body_shim",
+ "FunctionSignature::with_source_map_",
+ "FunctionSignature::of_",
+ "Body::with_source_map_",
+ "Body::of_",
]
"#]],
);
@@ -112,7 +112,7 @@ fn baz() -> i32 {
let crate_def_map = module.def_map(&db);
visit_module(&db, crate_def_map, module, &mut |def| {
if let ModuleDefId::FunctionId(it) = def {
- InferenceResult::for_body(&db, it.into());
+ InferenceResult::of(&db, DefWithBodyId::from(it));
}
});
},
@@ -122,41 +122,41 @@ fn baz() -> i32 {
"source_root_crates_shim",
"crate_local_def_map",
"file_item_tree_query",
- "ast_id_map_shim",
+ "ast_id_map",
"parse_shim",
"real_span_map_shim",
"InferenceResult::for_body_",
- "function_signature_shim",
- "function_signature_with_source_map_shim",
+ "FunctionSignature::of_",
+ "FunctionSignature::with_source_map_",
"AttrFlags::query_",
- "body_shim",
- "body_with_source_map_shim",
+ "Body::of_",
+ "Body::with_source_map_",
"trait_environment_query",
"lang_items",
"crate_lang_items",
"GenericPredicates::query_with_diagnostics_",
"ImplTraits::return_type_impl_traits_",
- "expr_scopes_shim",
+ "ExprScopes::body_expr_scopes_",
"InferenceResult::for_body_",
- "function_signature_shim",
- "function_signature_with_source_map_shim",
+ "FunctionSignature::of_",
+ "FunctionSignature::with_source_map_",
"AttrFlags::query_",
- "body_shim",
- "body_with_source_map_shim",
+ "Body::of_",
+ "Body::with_source_map_",
"trait_environment_query",
"GenericPredicates::query_with_diagnostics_",
"ImplTraits::return_type_impl_traits_",
- "expr_scopes_shim",
+ "ExprScopes::body_expr_scopes_",
"InferenceResult::for_body_",
- "function_signature_shim",
- "function_signature_with_source_map_shim",
+ "FunctionSignature::of_",
+ "FunctionSignature::with_source_map_",
"AttrFlags::query_",
- "body_shim",
- "body_with_source_map_shim",
+ "Body::of_",
+ "Body::with_source_map_",
"trait_environment_query",
"GenericPredicates::query_with_diagnostics_",
"ImplTraits::return_type_impl_traits_",
- "expr_scopes_shim",
+ "ExprScopes::body_expr_scopes_",
]
"#]],
);
@@ -182,7 +182,7 @@ fn baz() -> i32 {
let crate_def_map = module.def_map(&db);
visit_module(&db, crate_def_map, module, &mut |def| {
if let ModuleDefId::FunctionId(it) = def {
- InferenceResult::for_body(&db, it.into());
+ InferenceResult::of(&db, DefWithBodyId::from(it));
}
});
},
@@ -190,26 +190,26 @@ fn baz() -> i32 {
expect_test::expect![[r#"
[
"parse_shim",
- "ast_id_map_shim",
+ "ast_id_map",
"file_item_tree_query",
"real_span_map_shim",
"AttrFlags::query_",
- "function_signature_with_source_map_shim",
- "function_signature_shim",
- "body_with_source_map_shim",
- "body_shim",
+ "FunctionSignature::with_source_map_",
+ "FunctionSignature::of_",
+ "Body::with_source_map_",
+ "Body::of_",
"AttrFlags::query_",
- "function_signature_with_source_map_shim",
- "function_signature_shim",
- "body_with_source_map_shim",
- "body_shim",
+ "FunctionSignature::with_source_map_",
+ "FunctionSignature::of_",
+ "Body::with_source_map_",
+ "Body::of_",
"InferenceResult::for_body_",
- "expr_scopes_shim",
+ "ExprScopes::body_expr_scopes_",
"AttrFlags::query_",
- "function_signature_with_source_map_shim",
- "function_signature_shim",
- "body_with_source_map_shim",
- "body_shim",
+ "FunctionSignature::with_source_map_",
+ "FunctionSignature::of_",
+ "Body::with_source_map_",
+ "Body::of_",
]
"#]],
);
@@ -242,7 +242,7 @@ $0",
"source_root_crates_shim",
"crate_local_def_map",
"file_item_tree_query",
- "ast_id_map_shim",
+ "ast_id_map",
"parse_shim",
"real_span_map_shim",
"TraitImpls::for_crate_",
@@ -279,7 +279,7 @@ pub struct NewStruct {
expect_test::expect![[r#"
[
"parse_shim",
- "ast_id_map_shim",
+ "ast_id_map",
"file_item_tree_query",
"real_span_map_shim",
"crate_local_def_map",
@@ -317,7 +317,7 @@ $0",
"source_root_crates_shim",
"crate_local_def_map",
"file_item_tree_query",
- "ast_id_map_shim",
+ "ast_id_map",
"parse_shim",
"real_span_map_shim",
"TraitImpls::for_crate_",
@@ -355,7 +355,7 @@ pub enum SomeEnum {
expect_test::expect![[r#"
[
"parse_shim",
- "ast_id_map_shim",
+ "ast_id_map",
"file_item_tree_query",
"real_span_map_shim",
"crate_local_def_map",
@@ -393,7 +393,7 @@ $0",
"source_root_crates_shim",
"crate_local_def_map",
"file_item_tree_query",
- "ast_id_map_shim",
+ "ast_id_map",
"parse_shim",
"real_span_map_shim",
"TraitImpls::for_crate_",
@@ -428,7 +428,7 @@ fn bar() -> f32 {
expect_test::expect![[r#"
[
"parse_shim",
- "ast_id_map_shim",
+ "ast_id_map",
"file_item_tree_query",
"real_span_map_shim",
"crate_local_def_map",
@@ -470,7 +470,7 @@ $0",
"source_root_crates_shim",
"crate_local_def_map",
"file_item_tree_query",
- "ast_id_map_shim",
+ "ast_id_map",
"parse_shim",
"real_span_map_shim",
"TraitImpls::for_crate_",
@@ -513,7 +513,7 @@ impl SomeStruct {
expect_test::expect![[r#"
[
"parse_shim",
- "ast_id_map_shim",
+ "ast_id_map",
"file_item_tree_query",
"real_span_map_shim",
"crate_local_def_map",
@@ -562,7 +562,7 @@ fn main() {
});
for def in defs {
- let _inference_result = InferenceResult::for_body(&db, def);
+ let _inference_result = InferenceResult::of(&db, def);
}
},
&[("trait_solve_shim", 0)],
@@ -571,23 +571,23 @@ fn main() {
"source_root_crates_shim",
"crate_local_def_map",
"file_item_tree_query",
- "ast_id_map_shim",
+ "ast_id_map",
"parse_shim",
"real_span_map_shim",
"TraitItems::query_with_diagnostics_",
- "body_shim",
- "body_with_source_map_shim",
+ "Body::of_",
+ "Body::with_source_map_",
"AttrFlags::query_",
"ImplItems::of_",
"InferenceResult::for_body_",
- "trait_signature_shim",
- "trait_signature_with_source_map_shim",
+ "TraitSignature::of_",
+ "TraitSignature::with_source_map_",
"AttrFlags::query_",
- "function_signature_shim",
- "function_signature_with_source_map_shim",
+ "FunctionSignature::of_",
+ "FunctionSignature::with_source_map_",
"AttrFlags::query_",
- "body_shim",
- "body_with_source_map_shim",
+ "Body::of_",
+ "Body::with_source_map_",
"trait_environment_query",
"lang_items",
"crate_lang_items",
@@ -595,14 +595,14 @@ fn main() {
"GenericPredicates::query_with_diagnostics_",
"ImplTraits::return_type_impl_traits_",
"InferenceResult::for_body_",
- "function_signature_shim",
- "function_signature_with_source_map_shim",
+ "FunctionSignature::of_",
+ "FunctionSignature::with_source_map_",
"trait_environment_query",
"GenericPredicates::query_with_diagnostics_",
"ImplTraits::return_type_impl_traits_",
- "expr_scopes_shim",
- "struct_signature_shim",
- "struct_signature_with_source_map_shim",
+ "ExprScopes::body_expr_scopes_",
+ "StructSignature::of_",
+ "StructSignature::with_source_map_",
"AttrFlags::query_",
"GenericPredicates::query_with_diagnostics_",
"value_ty_query",
@@ -611,8 +611,8 @@ fn main() {
"TraitImpls::for_crate_and_deps_",
"TraitImpls::for_crate_",
"impl_trait_with_diagnostics_query",
- "impl_signature_shim",
- "impl_signature_with_source_map_shim",
+ "ImplSignature::of_",
+ "ImplSignature::with_source_map_",
"impl_self_ty_with_diagnostics_query",
"AttrFlags::query_",
"GenericPredicates::query_with_diagnostics_",
@@ -658,47 +658,47 @@ fn main() {
});
for def in defs {
- let _inference_result = InferenceResult::for_body(&db, def);
+ let _inference_result = InferenceResult::of(&db, def);
}
},
&[("trait_solve_shim", 0)],
expect_test::expect![[r#"
[
"parse_shim",
- "ast_id_map_shim",
+ "ast_id_map",
"file_item_tree_query",
"real_span_map_shim",
"crate_local_def_map",
"TraitItems::query_with_diagnostics_",
- "body_with_source_map_shim",
+ "Body::with_source_map_",
"AttrFlags::query_",
- "body_shim",
+ "Body::of_",
"ImplItems::of_",
"InferenceResult::for_body_",
"AttrFlags::query_",
- "trait_signature_with_source_map_shim",
+ "TraitSignature::with_source_map_",
"AttrFlags::query_",
- "function_signature_with_source_map_shim",
- "function_signature_shim",
- "body_with_source_map_shim",
- "body_shim",
+ "FunctionSignature::with_source_map_",
+ "FunctionSignature::of_",
+ "Body::with_source_map_",
+ "Body::of_",
"crate_lang_items",
"GenericPredicates::query_with_diagnostics_",
"GenericPredicates::query_with_diagnostics_",
"ImplTraits::return_type_impl_traits_",
"InferenceResult::for_body_",
- "function_signature_with_source_map_shim",
+ "FunctionSignature::with_source_map_",
"GenericPredicates::query_with_diagnostics_",
"ImplTraits::return_type_impl_traits_",
- "expr_scopes_shim",
- "struct_signature_with_source_map_shim",
+ "ExprScopes::body_expr_scopes_",
+ "StructSignature::with_source_map_",
"AttrFlags::query_",
"GenericPredicates::query_with_diagnostics_",
"InherentImpls::for_crate_",
"callable_item_signature_query",
"TraitImpls::for_crate_",
- "impl_signature_with_source_map_shim",
- "impl_signature_shim",
+ "ImplSignature::with_source_map_",
+ "ImplSignature::of_",
"impl_trait_with_diagnostics_query",
"impl_self_ty_with_diagnostics_query",
"AttrFlags::query_",
@@ -716,6 +716,7 @@ fn execute_assert_events(
) {
crate::attach_db(db, || {
let (executed, events) = db.log_executed(f);
+ expect.assert_debug_eq(&executed);
for (event, count) in required {
let n = executed.iter().filter(|it| it.contains(event)).count();
assert_eq!(
@@ -731,6 +732,5 @@ fn execute_assert_events(
.collect::<Vec<_>>(),
);
}
- expect.assert_debug_eq(&executed);
});
}
diff --git a/crates/hir-ty/src/tests/patterns.rs b/crates/hir-ty/src/tests/patterns.rs
index 8c7d29f993..42dc074309 100644
--- a/crates/hir-ty/src/tests/patterns.rs
+++ b/crates/hir-ty/src/tests/patterns.rs
@@ -421,6 +421,8 @@ fn infer_pattern_match_byte_string_literal() {
254..256 '&v': &'? [u8; 3]
255..256 'v': [u8; 3]
257..259 '{}': ()
+ 199..200 '3': usize
+ 62..63 'N': usize
"#]],
);
}
diff --git a/crates/hir-ty/src/tests/regression.rs b/crates/hir-ty/src/tests/regression.rs
index d88801a57b..e4fc7e56c6 100644
--- a/crates/hir-ty/src/tests/regression.rs
+++ b/crates/hir-ty/src/tests/regression.rs
@@ -2754,6 +2754,7 @@ where
664..680 'filter...ter_fn': dyn Fn(&'? T) -> bool + 'static
691..698 'loop {}': !
696..698 '{}': ()
+ 512..513 'N': usize
"#]],
);
}
diff --git a/crates/hir-ty/src/tests/regression/new_solver.rs b/crates/hir-ty/src/tests/regression/new_solver.rs
index f47a26d429..e6b3244cda 100644
--- a/crates/hir-ty/src/tests/regression/new_solver.rs
+++ b/crates/hir-ty/src/tests/regression/new_solver.rs
@@ -34,6 +34,7 @@ impl Space for [u8; 1] {
223..227 'iter': IntoIter<u8>
230..231 'a': Vec<u8>
230..243 'a.into_iter()': IntoIter<u8>
+ 322..323 '1': usize
"#]],
);
}
@@ -472,6 +473,8 @@ fn foo() {
249..257 'to_bytes': fn to_bytes() -> [u8; _]
249..259 'to_bytes()': [u8; _]
249..268 'to_byt..._vec()': Vec<<[u8; _] as Foo>::Item>
+ 205..206 '_': usize
+ 156..157 'N': usize
"#]],
);
}
@@ -541,6 +544,11 @@ fn test_at_most() {
617..620 'num': Between<0, 1, char>
623..626 ''9'': char
623..641 ''9'.at...:<1>()': Between<0, 1, char>
+ 320..335 '{ Consts::MAX }': usize
+ 322..333 'Consts::MAX': usize
+ 421..422 '0': i32
+ 144..159 '{ Consts::MAX }': usize
+ 146..157 'Consts::MAX': usize
"#]],
);
}
diff --git a/crates/hir-ty/src/tests/simple.rs b/crates/hir-ty/src/tests/simple.rs
index dab8bdb54b..3ea21f8265 100644
--- a/crates/hir-ty/src/tests/simple.rs
+++ b/crates/hir-ty/src/tests/simple.rs
@@ -3868,6 +3868,8 @@ fn main() {
208..209 'c': u8
213..214 'a': A
213..221 'a.into()': [u8; 2]
+ 33..34 '2': usize
+ 111..112 '3': usize
"#]],
);
}
@@ -4061,6 +4063,8 @@ fn foo() {
248..282 'LazyLo..._LOCK)': &'? [u32; _]
264..281 '&VALUE...Y_LOCK': &'? LazyLock<[u32; _]>
265..281 'VALUES...Y_LOCK': LazyLock<[u32; _]>
+ 197..202 '{ 0 }': usize
+ 199..200 '0': usize
"#]],
);
}
@@ -4109,3 +4113,38 @@ fn foo() {
"#,
);
}
+
+#[test]
+fn signature_inference() {
+ check_infer(
+ r#"
+trait Trait<const A: u8> {}
+struct S<T: Trait<2>, const C: f32 = 0.0>
+where
+ (): Trait<2>
+{
+ field: [(); { C as usize }],
+ field2: *mut S<T, 5.0>
+}
+
+struct S2<const C: u16>;
+
+type Alias = S2<0>;
+impl S2<0> {}
+enum E {
+ V(S2<0>) = 0,
+}
+union U {
+ field: S2<0>
+}
+ "#,
+ expect![[r#"
+ 242..243 '0': isize
+ 46..47 '2': i32
+ 65..68 '0.0': f32
+ 90..91 '2': i32
+ 200..201 '0': i32
+ 212..213 '0': i32
+ "#]],
+ );
+}
diff --git a/crates/hir-ty/src/tests/traits.rs b/crates/hir-ty/src/tests/traits.rs
index 74e9a8dac0..22359d8f1f 100644
--- a/crates/hir-ty/src/tests/traits.rs
+++ b/crates/hir-ty/src/tests/traits.rs
@@ -1271,6 +1271,7 @@ fn bar() {
241..245 'R::B': fn B<(), i32>(i32) -> R<(), i32>
241..248 'R::B(7)': R<(), i32>
246..247 '7': i32
+ 46..47 '2': usize
"#]],
);
}
@@ -3781,6 +3782,8 @@ fn main() {
371..373 'v4': usize
376..378 'v3': [u8; 4]
376..389 'v3.do_thing()': usize
+ 86..87 '4': usize
+ 192..193 '2': usize
"#]],
)
}
@@ -3820,6 +3823,9 @@ fn main() {
240..242 'v2': [u8; 2]
245..246 'v': [u8; 2]
245..257 'v.do_thing()': [u8; 2]
+ 130..131 'L': usize
+ 102..103 'L': usize
+ 130..131 'L': usize
"#]],
)
}
diff --git a/crates/hir-ty/src/traits.rs b/crates/hir-ty/src/traits.rs
index fb598fe5ac..878696c721 100644
--- a/crates/hir-ty/src/traits.rs
+++ b/crates/hir-ty/src/traits.rs
@@ -7,7 +7,11 @@ use hir_def::{
AdtId, AssocItemId, HasModule, ImplId, Lookup, TraitId,
lang_item::LangItems,
nameres::DefMap,
- signatures::{ConstFlags, EnumFlags, FnFlags, StructFlags, TraitFlags, TypeAliasFlags},
+ signatures::{
+ ConstFlags, ConstSignature, EnumFlags, EnumSignature, FnFlags, FunctionSignature,
+ StructFlags, StructSignature, TraitFlags, TraitSignature, TypeAliasFlags,
+ TypeAliasSignature, UnionSignature,
+ },
};
use hir_expand::name::Name;
use intern::sym;
@@ -279,21 +283,18 @@ pub fn is_inherent_impl_coherent(db: &dyn HirDatabase, def_map: &DefMap, impl_id
| TyKind::Float(_) => true,
TyKind::Adt(adt_def, _) => match adt_def.def_id().0 {
- hir_def::AdtId::StructId(id) => db
- .struct_signature(id)
+ hir_def::AdtId::StructId(id) => StructSignature::of(db, id)
.flags
.contains(StructFlags::RUSTC_HAS_INCOHERENT_INHERENT_IMPLS),
- hir_def::AdtId::UnionId(id) => db
- .union_signature(id)
+ hir_def::AdtId::UnionId(id) => UnionSignature::of(db, id)
.flags
.contains(StructFlags::RUSTC_HAS_INCOHERENT_INHERENT_IMPLS),
- hir_def::AdtId::EnumId(it) => db
- .enum_signature(it)
+ hir_def::AdtId::EnumId(it) => EnumSignature::of(db, it)
.flags
.contains(EnumFlags::RUSTC_HAS_INCOHERENT_INHERENT_IMPLS),
},
TyKind::Dynamic(it, _) => it.principal_def_id().is_some_and(|trait_id| {
- db.trait_signature(trait_id.0)
+ TraitSignature::of(db, trait_id.0)
.flags
.contains(TraitFlags::RUSTC_HAS_INCOHERENT_INHERENT_IMPLS)
}),
@@ -304,14 +305,13 @@ pub fn is_inherent_impl_coherent(db: &dyn HirDatabase, def_map: &DefMap, impl_id
rustc_has_incoherent_inherent_impls
&& !items.items.is_empty()
&& items.items.iter().all(|&(_, assoc)| match assoc {
- AssocItemId::FunctionId(it) => {
- db.function_signature(it).flags.contains(FnFlags::RUSTC_ALLOW_INCOHERENT_IMPL)
- }
- AssocItemId::ConstId(it) => {
- db.const_signature(it).flags.contains(ConstFlags::RUSTC_ALLOW_INCOHERENT_IMPL)
- }
- AssocItemId::TypeAliasId(it) => db
- .type_alias_signature(it)
+ AssocItemId::FunctionId(it) => FunctionSignature::of(db, it)
+ .flags
+ .contains(FnFlags::RUSTC_ALLOW_INCOHERENT_IMPL),
+ AssocItemId::ConstId(it) => ConstSignature::of(db, it)
+ .flags
+ .contains(ConstFlags::RUSTC_ALLOW_INCOHERENT_IMPL),
+ AssocItemId::TypeAliasId(it) => TypeAliasSignature::of(db, it)
.flags
.contains(TypeAliasFlags::RUSTC_ALLOW_INCOHERENT_IMPL),
})
@@ -350,7 +350,7 @@ pub fn check_orphan_rules<'db>(db: &'db dyn HirDatabase, impl_: ImplId) -> bool
let AdtId::StructId(s) = adt_def.def_id().0 else {
break ty;
};
- let struct_signature = db.struct_signature(s);
+ let struct_signature = StructSignature::of(db, s);
if struct_signature.flags.contains(StructFlags::FUNDAMENTAL) {
let next = subs.types().next();
match next {
diff --git a/crates/hir-ty/src/upvars.rs b/crates/hir-ty/src/upvars.rs
index ee864ab068..489895fe3c 100644
--- a/crates/hir-ty/src/upvars.rs
+++ b/crates/hir-ty/src/upvars.rs
@@ -44,10 +44,10 @@ pub fn upvars_mentioned(
db: &dyn HirDatabase,
owner: DefWithBodyId,
) -> Option<Box<FxHashMap<ExprId, Upvars>>> {
- let body = db.body(owner);
+ let body = Body::of(db, owner);
let mut resolver = owner.resolver(db);
let mut result = FxHashMap::default();
- handle_expr_outside_closure(db, &mut resolver, owner, &body, body.body_expr, &mut result);
+ handle_expr_outside_closure(db, &mut resolver, owner, body, body.root_expr(), &mut result);
return if result.is_empty() {
None
} else {
@@ -198,7 +198,7 @@ fn resolve_maybe_upvar<'db>(
#[cfg(test)]
mod tests {
use expect_test::{Expect, expect};
- use hir_def::{ModuleDefId, db::DefDatabase, nameres::crate_def_map};
+ use hir_def::{ModuleDefId, expr_store::Body, nameres::crate_def_map};
use itertools::Itertools;
use span::Edition;
use test_fixture::WithFixture;
@@ -219,7 +219,7 @@ mod tests {
})
.exactly_one()
.unwrap_or_else(|_| panic!("expected one function"));
- let (body, source_map) = db.body_with_source_map(func.into());
+ let (body, source_map) = Body::with_source_map(&db, func.into());
let Some(upvars) = upvars_mentioned(&db, func.into()) else {
expectation.assert_eq("");
return;
diff --git a/crates/hir-ty/src/utils.rs b/crates/hir-ty/src/utils.rs
index be64f55ea5..509109543c 100644
--- a/crates/hir-ty/src/utils.rs
+++ b/crates/hir-ty/src/utils.rs
@@ -4,6 +4,7 @@
use base_db::target::{self, TargetData};
use hir_def::{
EnumId, EnumVariantId, FunctionId, Lookup, TraitId, attrs::AttrFlags, lang_item::LangItems,
+ signatures::FunctionSignature,
};
use intern::sym;
use rustc_abi::TargetDataLayout;
@@ -79,7 +80,7 @@ pub fn is_fn_unsafe_to_call(
call_edition: Edition,
target_feature_is_safe: TargetFeatureIsSafeInTarget,
) -> Unsafety {
- let data = db.function_signature(func);
+ let data = FunctionSignature::of(db, func);
if data.is_unsafe() {
return Unsafety::Unsafe;
}
diff --git a/crates/hir-ty/src/variance.rs b/crates/hir-ty/src/variance.rs
index 6f415a5289..1945b04bb3 100644
--- a/crates/hir-ty/src/variance.rs
+++ b/crates/hir-ty/src/variance.rs
@@ -13,7 +13,10 @@
//! by the next salsa version. If not, we will likely have to adapt and go with the rustc approach
//! while installing firewall per item queries to prevent invalidation issues.
-use hir_def::{AdtId, GenericDefId, GenericParamId, VariantId, signatures::StructFlags};
+use hir_def::{
+ AdtId, GenericDefId, GenericParamId, VariantId,
+ signatures::{StructFlags, StructSignature},
+};
use rustc_ast_ir::Mutability;
use rustc_type_ir::{
Variance,
@@ -45,7 +48,7 @@ fn variances_of_query(db: &dyn HirDatabase, def: GenericDefId) -> StoredVariance
GenericDefId::FunctionId(_) => (),
GenericDefId::AdtId(adt) => {
if let AdtId::StructId(id) = adt {
- let flags = &db.struct_signature(id).flags;
+ let flags = &StructSignature::of(db, id).flags;
let types = || crate::next_solver::default_types(db);
if flags.contains(StructFlags::IS_UNSAFE_CELL) {
return types().one_invariant.store();
@@ -113,7 +116,7 @@ pub(crate) fn variances_of_cycle_initial(
struct Context<'db> {
db: &'db dyn HirDatabase,
- generics: Generics,
+ generics: Generics<'db>,
variances: Box<[Variance]>,
}
diff --git a/crates/hir/src/attrs.rs b/crates/hir/src/attrs.rs
index cfb95e07c3..27e7985146 100644
--- a/crates/hir/src/attrs.rs
+++ b/crates/hir/src/attrs.rs
@@ -7,6 +7,7 @@ use hir_def::{
TraitId, TypeOrConstParamId,
attrs::{AttrFlags, Docs, IsInnerDoc},
expr_store::path::Path,
+ hir::generics::GenericParams,
item_scope::ItemInNs,
per_ns::Namespace,
resolver::{HasResolver, Resolver, TypeNs},
@@ -26,9 +27,9 @@ use intern::Symbol;
use stdx::never;
use crate::{
- Adt, AsAssocItem, AssocItem, BuiltinType, Const, ConstParam, DocLinkDef, Enum, ExternCrateDecl,
- Field, Function, GenericParam, HasCrate, Impl, LangItem, LifetimeParam, Macro, Module,
- ModuleDef, Static, Struct, Trait, Type, TypeAlias, TypeParam, Union, Variant, VariantDef,
+ Adt, AsAssocItem, AssocItem, BuiltinType, Const, ConstParam, DocLinkDef, Enum, EnumVariant,
+ ExternCrateDecl, Field, Function, GenericParam, HasCrate, Impl, LangItem, LifetimeParam, Macro,
+ Module, ModuleDef, Static, Struct, Trait, Type, TypeAlias, TypeParam, Union, Variant,
};
#[derive(Debug, Clone, Copy)]
@@ -199,7 +200,7 @@ macro_rules! impl_has_attrs {
}
impl_has_attrs![
- (Variant, EnumVariantId),
+ (EnumVariant, EnumVariantId),
(Static, StaticId),
(Const, ConstId),
(Trait, TraitId),
@@ -377,7 +378,7 @@ fn resolve_assoc_or_field(
let ty = match base_def {
TypeNs::SelfType(id) => Impl::from(id).self_ty(db),
TypeNs::GenericParam(param) => {
- let generic_params = db.generic_params(param.parent());
+ let generic_params = GenericParams::of(db, param.parent());
if generic_params[param.local_id()].is_trait_self() {
// `Self::assoc` in traits should refer to the trait itself.
let parent_trait = |container| match container {
@@ -406,7 +407,7 @@ fn resolve_assoc_or_field(
TypeNs::AdtId(id) | TypeNs::AdtSelfType(id) => Adt::from(id).ty(db),
TypeNs::EnumVariantId(id) => {
// Enum variants don't have path candidates.
- let variant = Variant::from(id);
+ let variant = EnumVariant::from(id);
return resolve_field(db, variant.into(), name, ns);
}
TypeNs::TypeAliasId(id) => {
@@ -443,7 +444,7 @@ fn resolve_assoc_or_field(
.id
.enum_variants(db)
.variant(&name)
- .map(|variant| DocLinkDef::ModuleDef(ModuleDef::Variant(variant.into())));
+ .map(|variant| DocLinkDef::ModuleDef(ModuleDef::EnumVariant(variant.into())));
}
};
resolve_field(db, variant_def, name, ns)
@@ -505,7 +506,7 @@ fn resolve_impl_trait_item<'db>(
fn resolve_field(
db: &dyn HirDatabase,
- def: VariantDef,
+ def: Variant,
name: Name,
ns: Option<Namespace>,
) -> Option<DocLinkDef> {
diff --git a/crates/hir/src/display.rs b/crates/hir/src/display.rs
index 91fdcb8e63..4bfdd239f9 100644
--- a/crates/hir/src/display.rs
+++ b/crates/hir/src/display.rs
@@ -4,10 +4,13 @@ use either::Either;
use hir_def::{
AdtId, BuiltinDeriveImplId, FunctionId, GenericDefId, ImplId, ItemContainerId,
builtin_derive::BuiltinDeriveImplMethod,
- expr_store::ExpressionStore,
+ expr_store::{Body, ExpressionStore},
hir::generics::{GenericParams, TypeOrConstParamData, TypeParamProvenance, WherePredicate},
item_tree::FieldsShape,
- signatures::{StaticFlags, TraitFlags},
+ signatures::{
+ ConstSignature, FunctionSignature, ImplSignature, StaticFlags, StaticSignature, TraitFlags,
+ TraitSignature, TypeAliasSignature,
+ },
type_ref::{TypeBound, TypeRef, TypeRefId},
};
use hir_expand::name::Name;
@@ -26,9 +29,9 @@ use rustc_type_ir::inherent::IntoKind;
use crate::{
Adt, AnyFunctionId, AsAssocItem, AssocItem, AssocItemContainer, Const, ConstParam, Crate, Enum,
- ExternCrateDecl, Field, Function, GenericParam, HasCrate, HasVisibility, Impl, LifetimeParam,
- Macro, Module, SelfParam, Static, Struct, StructKind, Trait, TraitRef, TupleField, Type,
- TypeAlias, TypeNs, TypeOrConstParam, TypeParam, Union, Variant,
+ EnumVariant, ExternCrateDecl, Field, Function, GenericParam, HasCrate, HasVisibility, Impl,
+ LifetimeParam, Macro, Module, SelfParam, Static, Struct, StructKind, Trait, TraitRef,
+ TupleField, Type, TypeAlias, TypeNs, TypeOrConstParam, TypeParam, Union,
};
fn write_builtin_derive_impl_method<'db>(
@@ -38,7 +41,7 @@ fn write_builtin_derive_impl_method<'db>(
) -> Result {
let db = f.db;
let loc = impl_.loc(db);
- let (adt_params, _adt_params_store) = db.generic_params_and_store(loc.adt.into());
+ let adt_params = GenericParams::of(db, loc.adt.into());
if f.show_container_bounds() && !adt_params.is_empty() {
f.write_str("impl")?;
@@ -94,22 +97,22 @@ impl<'db> HirDisplay<'db> for Function {
// Write container (trait or impl)
let container_params = match container {
ItemContainerId::TraitId(trait_) => {
- let (params, params_store) = f.db.generic_params_and_store(trait_.into());
+ let (params, params_store) = GenericParams::with_store(f.db, trait_.into());
if f.show_container_bounds() && !params.is_empty() {
write_trait_header(trait_.into(), f)?;
f.write_char('\n')?;
- has_disaplayable_predicates(f.db, &params, &params_store)
+ has_disaplayable_predicates(f.db, params, params_store)
.then_some((params, params_store))
} else {
None
}
}
ItemContainerId::ImplId(impl_) => {
- let (params, params_store) = f.db.generic_params_and_store(impl_.into());
+ let (params, params_store) = GenericParams::with_store(f.db, impl_.into());
if f.show_container_bounds() && !params.is_empty() {
write_impl_header(impl_, f)?;
f.write_char('\n')?;
- has_disaplayable_predicates(f.db, &params, &params_store)
+ has_disaplayable_predicates(f.db, params, params_store)
.then_some((params, params_store))
} else {
None
@@ -131,7 +134,7 @@ impl<'db> HirDisplay<'db> for Function {
_ => unreachable!(),
};
write!(f, "\n // Bounds from {container_name}:",)?;
- write_where_predicates(&container_params, &container_params_store, f)?;
+ write_where_predicates(container_params, container_params_store, f)?;
}
Ok(())
}
@@ -140,7 +143,7 @@ impl<'db> HirDisplay<'db> for Function {
fn write_function<'db>(f: &mut HirFormatter<'_, 'db>, func_id: FunctionId) -> Result<bool> {
let db = f.db;
let func = Function::from(func_id);
- let data = db.function_signature(func_id);
+ let data = FunctionSignature::of(db, func_id);
let mut module = func.module(db);
// Block-local impls are "hoisted" to the nearest (non-block) module.
@@ -189,7 +192,7 @@ fn write_function<'db>(f: &mut HirFormatter<'_, 'db>, func_id: FunctionId) -> Re
let comma = if too_long_param { ",\n " } else { ", " };
// FIXME: Use resolved `param.ty` once we no longer discard lifetimes
- let body = db.body(func_id.into());
+ let body = Body::of(db, func_id.into());
for (type_ref, param) in data.params.iter().zip(func.assoc_fn_params(db)).skip(skip_self) {
if !first {
f.write_str(comma)?;
@@ -268,7 +271,7 @@ fn write_impl_header<'db>(impl_: ImplId, f: &mut HirFormatter<'_, 'db>) -> Resul
let def_id = GenericDefId::ImplId(impl_);
write_generic_params(def_id, f)?;
- let impl_data = db.impl_signature(impl_);
+ let impl_data = ImplSignature::of(db, impl_);
if let Some(target_trait) = &impl_data.target_trait {
f.write_char(' ')?;
hir_display_with_store(&impl_data.store[target_trait.path], &impl_data.store).hir_fmt(f)?;
@@ -297,7 +300,7 @@ impl<'db> HirDisplay<'db> for SelfParam {
}
},
};
- let data = f.db.function_signature(func);
+ let data = FunctionSignature::of(f.db, func);
let param = *data.params.first().unwrap();
match &data.store[param] {
TypeRef::Path(p) if p.is_self_type() => f.write_str("self"),
@@ -440,7 +443,7 @@ fn write_fields<'db>(
}
fn write_variants<'db>(
- variants: &[Variant],
+ variants: &[EnumVariant],
has_where_clause: bool,
limit: usize,
f: &mut HirFormatter<'_, 'db>,
@@ -494,7 +497,7 @@ impl<'db> HirDisplay<'db> for TupleField {
}
}
-impl<'db> HirDisplay<'db> for Variant {
+impl<'db> HirDisplay<'db> for EnumVariant {
fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result {
write!(f, "{}", self.name(f.db).display(f.db, f.edition()))?;
let data = self.id.fields(f.db);
@@ -569,7 +572,7 @@ impl<'db> HirDisplay<'db> for TypeOrConstParam {
impl<'db> HirDisplay<'db> for TypeParam {
fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result {
- let params = f.db.generic_params(self.id.parent());
+ let params = GenericParams::of(f.db, self.id.parent());
let param_data = &params[self.id.local_id()];
let krate = self.id.parent().krate(f.db).id;
let ty = self.ty(f.db).ty;
@@ -657,7 +660,7 @@ fn write_generic_params_or_args<'db>(
f: &mut HirFormatter<'_, 'db>,
include_defaults: bool,
) -> Result {
- let (params, store) = f.db.generic_params_and_store(def);
+ let (params, store) = GenericParams::with_store(f.db, def);
if params.iter_lt().next().is_none()
&& params.iter_type_or_consts().all(|it| it.1.const_param().is_none())
&& params
@@ -693,17 +696,17 @@ fn write_generic_params_or_args<'db>(
write!(f, "{}", name.display(f.db, f.edition()))?;
if include_defaults && let Some(default) = &ty.default {
f.write_str(" = ")?;
- default.hir_fmt(f, &store)?;
+ default.hir_fmt(f, store)?;
}
}
TypeOrConstParamData::ConstParamData(c) => {
delim(f)?;
write!(f, "const {}: ", name.display(f.db, f.edition()))?;
- c.ty.hir_fmt(f, &store)?;
+ c.ty.hir_fmt(f, store)?;
if include_defaults && let Some(default) = &c.default {
f.write_str(" = ")?;
- default.hir_fmt(f, &store)?;
+ default.hir_fmt(f, store)?;
}
}
}
@@ -715,13 +718,13 @@ fn write_generic_params_or_args<'db>(
}
fn write_where_clause<'db>(def: GenericDefId, f: &mut HirFormatter<'_, 'db>) -> Result<bool> {
- let (params, store) = f.db.generic_params_and_store(def);
- if !has_disaplayable_predicates(f.db, &params, &store) {
+ let (params, store) = GenericParams::with_store(f.db, def);
+ if !has_disaplayable_predicates(f.db, params, store) {
return Ok(false);
}
f.write_str("\nwhere")?;
- write_where_predicates(&params, &store, f)?;
+ write_where_predicates(params, store, f)?;
Ok(true)
}
@@ -736,7 +739,7 @@ fn has_disaplayable_predicates(
pred,
WherePredicate::TypeBound { target, .. }
if matches!(store[*target],
- TypeRef::TypeParam(id) if db.generic_params(id.parent())[id.local_id()].name().is_none()
+ TypeRef::TypeParam(id) if GenericParams::of(db,id.parent())[id.local_id()].name().is_none()
)
)
})
@@ -752,7 +755,7 @@ fn write_where_predicates<'db>(
// unnamed type targets are displayed inline with the argument itself, e.g. `f: impl Y`.
let is_unnamed_type_target = |target: TypeRefId| {
matches!(store[target],
- TypeRef::TypeParam(id) if f.db.generic_params(id.parent())[id.local_id()].name().is_none()
+ TypeRef::TypeParam(id) if GenericParams::of(f.db,id.parent())[id.local_id()].name().is_none()
)
};
@@ -816,7 +819,7 @@ impl<'db> HirDisplay<'db> for Const {
module = module.nearest_non_block_module(db);
}
write_visibility(module.id, self.visibility(db), f)?;
- let data = db.const_signature(self.id);
+ let data = ConstSignature::of(db, self.id);
f.write_str("const ")?;
match &data.name {
Some(name) => write!(f, "{}: ", name.display(f.db, f.edition()))?,
@@ -830,7 +833,7 @@ impl<'db> HirDisplay<'db> for Const {
impl<'db> HirDisplay<'db> for Static {
fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result {
write_visibility(self.module(f.db).id, self.visibility(f.db), f)?;
- let data = f.db.static_signature(self.id);
+ let data = StaticSignature::of(f.db, self.id);
f.write_str("static ")?;
if data.flags.contains(StaticFlags::MUTABLE) {
f.write_str("mut ")?;
@@ -889,7 +892,7 @@ impl<'db> HirDisplay<'db> for Trait {
fn write_trait_header<'db>(trait_: Trait, f: &mut HirFormatter<'_, 'db>) -> Result {
write_visibility(trait_.module(f.db).id, trait_.visibility(f.db), f)?;
- let data = f.db.trait_signature(trait_.id);
+ let data = TraitSignature::of(f.db, trait_.id);
if data.flags.contains(TraitFlags::UNSAFE) {
f.write_str("unsafe ")?;
}
@@ -904,7 +907,7 @@ fn write_trait_header<'db>(trait_: Trait, f: &mut HirFormatter<'_, 'db>) -> Resu
impl<'db> HirDisplay<'db> for TypeAlias {
fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result {
write_visibility(self.module(f.db).id, self.visibility(f.db), f)?;
- let data = f.db.type_alias_signature(self.id);
+ let data = TypeAliasSignature::of(f.db, self.id);
write!(f, "type {}", data.name.display(f.db, f.edition()))?;
let def_id = GenericDefId::TypeAliasId(self.id);
write_generic_params(def_id, f)?;
diff --git a/crates/hir/src/from_id.rs b/crates/hir/src/from_id.rs
index fc20f4b46b..0a48be5473 100644
--- a/crates/hir/src/from_id.rs
+++ b/crates/hir/src/from_id.rs
@@ -4,15 +4,15 @@
//! are splitting the hir.
use hir_def::{
- AdtId, AssocItemId, BuiltinDeriveImplId, DefWithBodyId, EnumVariantId, FieldId, GenericDefId,
- GenericParamId, ModuleDefId, VariantId,
+ AdtId, AssocItemId, BuiltinDeriveImplId, DefWithBodyId, EnumVariantId, ExpressionStoreOwnerId,
+ FieldId, FunctionId, GenericDefId, GenericParamId, ImplId, ModuleDefId, VariantId,
hir::{BindingId, LabelId},
};
use hir_ty::next_solver::AnyImplId;
use crate::{
- Adt, AnyFunctionId, AssocItem, BuiltinType, DefWithBody, Field, GenericDef, GenericParam,
- ItemInNs, Label, Local, ModuleDef, Variant, VariantDef,
+ Adt, AnyFunctionId, AssocItem, BuiltinType, DefWithBody, EnumVariant, ExpressionStoreOwner,
+ Field, Function, GenericDef, GenericParam, Impl, ItemInNs, Label, Local, ModuleDef, Variant,
};
macro_rules! from_id {
@@ -71,6 +71,15 @@ impl From<Adt> for AdtId {
}
}
+impl From<VariantId> for Variant {
+ fn from(v: VariantId) -> Self {
+ match v {
+ VariantId::EnumVariantId(it) => Variant::EnumVariant(it.into()),
+ VariantId::StructId(it) => Variant::Struct(it.into()),
+ VariantId::UnionId(it) => Variant::Union(it.into()),
+ }
+ }
+}
impl From<GenericParamId> for GenericParam {
fn from(id: GenericParamId) -> Self {
match id {
@@ -91,14 +100,14 @@ impl From<GenericParam> for GenericParamId {
}
}
-impl From<EnumVariantId> for Variant {
+impl From<EnumVariantId> for EnumVariant {
fn from(id: EnumVariantId) -> Self {
- Variant { id }
+ EnumVariant { id }
}
}
-impl From<Variant> for EnumVariantId {
- fn from(def: Variant) -> Self {
+impl From<EnumVariant> for EnumVariantId {
+ fn from(def: EnumVariant) -> Self {
def.id
}
}
@@ -109,7 +118,7 @@ impl From<ModuleDefId> for ModuleDef {
ModuleDefId::ModuleId(it) => ModuleDef::Module(it.into()),
ModuleDefId::FunctionId(it) => ModuleDef::Function(it.into()),
ModuleDefId::AdtId(it) => ModuleDef::Adt(it.into()),
- ModuleDefId::EnumVariantId(it) => ModuleDef::Variant(it.into()),
+ ModuleDefId::EnumVariantId(it) => ModuleDef::EnumVariant(it.into()),
ModuleDefId::ConstId(it) => ModuleDef::Const(it.into()),
ModuleDefId::StaticId(it) => ModuleDef::Static(it.into()),
ModuleDefId::TraitId(it) => ModuleDef::Trait(it.into()),
@@ -130,7 +139,7 @@ impl TryFrom<ModuleDef> for ModuleDefId {
AnyFunctionId::BuiltinDeriveImplMethod { .. } => return Err(()),
},
ModuleDef::Adt(it) => ModuleDefId::AdtId(it.into()),
- ModuleDef::Variant(it) => ModuleDefId::EnumVariantId(it.into()),
+ ModuleDef::EnumVariant(it) => ModuleDefId::EnumVariantId(it.into()),
ModuleDef::Const(it) => ModuleDefId::ConstId(it.into()),
ModuleDef::Static(it) => ModuleDefId::StaticId(it.into()),
ModuleDef::Trait(it) => ModuleDefId::TraitId(it.into()),
@@ -151,7 +160,7 @@ impl TryFrom<DefWithBody> for DefWithBodyId {
},
DefWithBody::Static(it) => DefWithBodyId::StaticId(it.id),
DefWithBody::Const(it) => DefWithBodyId::ConstId(it.id),
- DefWithBody::Variant(it) => DefWithBodyId::VariantId(it.into()),
+ DefWithBody::EnumVariant(it) => DefWithBodyId::VariantId(it.into()),
})
}
}
@@ -162,7 +171,7 @@ impl From<DefWithBodyId> for DefWithBody {
DefWithBodyId::FunctionId(it) => DefWithBody::Function(it.into()),
DefWithBodyId::StaticId(it) => DefWithBody::Static(it.into()),
DefWithBodyId::ConstId(it) => DefWithBody::Const(it.into()),
- DefWithBodyId::VariantId(it) => DefWithBody::Variant(it.into()),
+ DefWithBodyId::VariantId(it) => DefWithBody::EnumVariant(it.into()),
}
}
}
@@ -209,22 +218,12 @@ impl From<Adt> for GenericDefId {
}
}
-impl From<VariantId> for VariantDef {
- fn from(def: VariantId) -> Self {
- match def {
- VariantId::StructId(it) => VariantDef::Struct(it.into()),
- VariantId::EnumVariantId(it) => VariantDef::Variant(it.into()),
- VariantId::UnionId(it) => VariantDef::Union(it.into()),
- }
- }
-}
-
-impl From<VariantDef> for VariantId {
- fn from(def: VariantDef) -> Self {
+impl From<Variant> for VariantId {
+ fn from(def: Variant) -> Self {
match def {
- VariantDef::Struct(it) => VariantId::StructId(it.id),
- VariantDef::Variant(it) => VariantId::EnumVariantId(it.into()),
- VariantDef::Union(it) => VariantId::UnionId(it.id),
+ Variant::Struct(it) => VariantId::StructId(it.id),
+ Variant::EnumVariant(it) => VariantId::EnumVariantId(it.into()),
+ Variant::Union(it) => VariantId::UnionId(it.id),
}
}
}
@@ -255,14 +254,19 @@ impl TryFrom<AssocItem> for GenericDefId {
}
}
+impl From<(ExpressionStoreOwnerId, BindingId)> for Local {
+ fn from((parent, binding_id): (ExpressionStoreOwnerId, BindingId)) -> Self {
+ Local { parent, binding_id }
+ }
+}
impl From<(DefWithBodyId, BindingId)> for Local {
fn from((parent, binding_id): (DefWithBodyId, BindingId)) -> Self {
- Local { parent, binding_id }
+ Local { parent: parent.into(), binding_id }
}
}
-impl From<(DefWithBodyId, LabelId)> for Label {
- fn from((parent, label_id): (DefWithBodyId, LabelId)) -> Self {
+impl From<(ExpressionStoreOwnerId, LabelId)> for Label {
+ fn from((parent, label_id): (ExpressionStoreOwnerId, LabelId)) -> Self {
Label { parent, label_id }
}
}
@@ -317,3 +321,43 @@ impl From<hir_def::FunctionId> for crate::Function {
crate::Function { id: AnyFunctionId::FunctionId(value) }
}
}
+
+impl TryFrom<ExpressionStoreOwner> for ExpressionStoreOwnerId {
+ type Error = ();
+
+ fn try_from(v: ExpressionStoreOwner) -> Result<Self, Self::Error> {
+ match v {
+ ExpressionStoreOwner::Signature(generic_def_id) => {
+ Ok(Self::Signature(generic_def_id.try_into()?))
+ }
+ ExpressionStoreOwner::Body(def_with_body_id) => {
+ Ok(Self::Body(def_with_body_id.try_into()?))
+ }
+ ExpressionStoreOwner::VariantFields(variant_id) => {
+ Ok(Self::VariantFields(variant_id.into()))
+ }
+ }
+ }
+}
+
+impl TryFrom<Function> for FunctionId {
+ type Error = ();
+
+ fn try_from(v: Function) -> Result<Self, Self::Error> {
+ match v.id {
+ AnyFunctionId::FunctionId(id) => Ok(id),
+ _ => Err(()),
+ }
+ }
+}
+
+impl TryFrom<Impl> for ImplId {
+ type Error = ();
+
+ fn try_from(v: Impl) -> Result<Self, Self::Error> {
+ match v.id {
+ AnyImplId::ImplId(id) => Ok(id),
+ _ => Err(()),
+ }
+ }
+}
diff --git a/crates/hir/src/has_source.rs b/crates/hir/src/has_source.rs
index e032a16989..f9badc0b79 100644
--- a/crates/hir/src/has_source.rs
+++ b/crates/hir/src/has_source.rs
@@ -3,6 +3,7 @@
use either::Either;
use hir_def::{
CallableDefId, Lookup, MacroId, VariantId,
+ expr_store::ExpressionStore,
nameres::{ModuleOrigin, ModuleSource},
src::{HasChildSource, HasSource as _},
};
@@ -12,9 +13,9 @@ use syntax::{AstNode, ast};
use tt::TextRange;
use crate::{
- Adt, AnyFunctionId, Callee, Const, Enum, ExternCrateDecl, Field, FieldSource, Function, Impl,
- InlineAsmOperand, Label, LifetimeParam, LocalSource, Macro, Module, Param, SelfParam, Static,
- Struct, Trait, TypeAlias, TypeOrConstParam, Union, Variant, VariantDef, db::HirDatabase,
+ Adt, AnyFunctionId, Callee, Const, Enum, EnumVariant, ExternCrateDecl, Field, FieldSource,
+ Function, Impl, InlineAsmOperand, Label, LifetimeParam, LocalSource, Macro, Module, Param,
+ SelfParam, Static, Struct, Trait, TypeAlias, TypeOrConstParam, Union, Variant, db::HirDatabase,
};
pub trait HasSource: Sized {
@@ -123,13 +124,13 @@ impl HasSource for Adt {
}
}
}
-impl HasSource for VariantDef {
+impl HasSource for Variant {
type Ast = ast::VariantDef;
fn source(self, db: &dyn HirDatabase) -> Option<InFile<Self::Ast>> {
match self {
- VariantDef::Struct(s) => Some(s.source(db)?.map(ast::VariantDef::Struct)),
- VariantDef::Union(u) => Some(u.source(db)?.map(ast::VariantDef::Union)),
- VariantDef::Variant(v) => Some(v.source(db)?.map(ast::VariantDef::Variant)),
+ Variant::Struct(s) => Some(s.source(db)?.map(ast::VariantDef::Struct)),
+ Variant::Union(u) => Some(u.source(db)?.map(ast::VariantDef::Union)),
+ Variant::EnumVariant(v) => Some(v.source(db)?.map(ast::VariantDef::Variant)),
}
}
}
@@ -151,7 +152,7 @@ impl HasSource for Enum {
Some(self.id.lookup(db).source(db))
}
}
-impl HasSource for Variant {
+impl HasSource for EnumVariant {
type Ast = ast::Variant;
fn source(self, db: &dyn HirDatabase) -> Option<InFile<ast::Variant>> {
Some(self.id.lookup(db).source(db))
@@ -293,7 +294,7 @@ impl HasSource for Param<'_> {
}
Callee::Closure(closure, _) => {
let InternedClosure(owner, expr_id) = db.lookup_intern_closure(closure);
- let (_, source_map) = db.body_with_source_map(owner);
+ let (_, source_map) = ExpressionStore::with_source_map(db, owner);
let ast @ InFile { file_id, value } = source_map.expr_syntax(expr_id).ok()?;
let root = db.parse_or_expand(file_id);
match value.to_node(&root) {
@@ -327,8 +328,7 @@ impl HasSource for Label {
type Ast = ast::Label;
fn source(self, db: &dyn HirDatabase) -> Option<InFile<Self::Ast>> {
- let (_body, source_map) = db.body_with_source_map(self.parent);
- let src = source_map.label_syntax(self.label_id);
+ let src = ExpressionStore::with_source_map(db, self.parent).1.label_syntax(self.label_id);
let root = src.file_syntax(db);
src.map(|ast| ast.to_node(&root).left()).transpose()
}
@@ -345,7 +345,7 @@ impl HasSource for ExternCrateDecl {
impl HasSource for InlineAsmOperand {
type Ast = ast::AsmOperandNamed;
fn source(self, db: &dyn HirDatabase) -> Option<InFile<Self::Ast>> {
- let source_map = db.body_with_source_map(self.owner).1;
+ let (_, source_map) = ExpressionStore::with_source_map(db, self.owner);
if let Ok(src) = source_map.expr_syntax(self.expr) {
let root = src.file_syntax(db);
return src
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index 0b3515fd04..bc5e164830 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -49,16 +49,16 @@ use base_db::{CrateDisplayName, CrateOrigin, LangCrateOrigin};
use either::Either;
use hir_def::{
AdtId, AssocItemId, AssocItemLoc, BuiltinDeriveImplId, CallableDefId, ConstId, ConstParamId,
- DefWithBodyId, EnumId, EnumVariantId, ExternBlockId, ExternCrateId, FunctionId, GenericDefId,
- HasModule, ImplId, ItemContainerId, LifetimeParamId, LocalFieldId, Lookup, MacroExpander,
- MacroId, StaticId, StructId, SyntheticSyntax, TupleId, TypeAliasId, TypeOrConstParamId,
- TypeParamId, UnionId,
+ DefWithBodyId, EnumId, EnumVariantId, ExpressionStoreOwnerId, ExternBlockId, ExternCrateId,
+ FunctionId, GenericDefId, HasModule, ImplId, ItemContainerId, LifetimeParamId, LocalFieldId,
+ Lookup, MacroExpander, MacroId, StaticId, StructId, SyntheticSyntax, TupleId, TypeAliasId,
+ TypeOrConstParamId, TypeParamId, UnionId,
attrs::AttrFlags,
builtin_derive::BuiltinDeriveImplMethod,
- expr_store::{ExpressionStoreDiagnostics, ExpressionStoreSourceMap},
+ expr_store::{ExpressionStore, ExpressionStoreDiagnostics, ExpressionStoreSourceMap},
hir::{
BindingAnnotation, BindingId, Expr, ExprId, ExprOrPatId, LabelId, Pat,
- generics::{LifetimeParamData, TypeOrConstParamData, TypeParamProvenance},
+ generics::{GenericParams, LifetimeParamData, TypeOrConstParamData, TypeParamProvenance},
},
item_tree::ImportAlias,
lang_item::LangItemTarget,
@@ -69,7 +69,11 @@ use hir_def::{
},
per_ns::PerNs,
resolver::{HasResolver, Resolver},
- signatures::{EnumSignature, ImplFlags, StaticFlags, StructFlags, TraitFlags, VariantFields},
+ signatures::{
+ ConstSignature, EnumSignature, FunctionSignature, ImplFlags, ImplSignature, StaticFlags,
+ StaticSignature, StructFlags, StructSignature, TraitFlags, TraitSignature,
+ TypeAliasSignature, UnionSignature, VariantFields,
+ },
src::HasSource as _,
visibility::visibility_from_ast,
};
@@ -141,6 +145,7 @@ pub use {
Complete,
FindPathConfig,
attrs::{Docs, IsInnerDoc},
+ expr_store::Body,
find_path::PrefixKind,
import_map,
lang_item::{LangItemEnum as LangItem, crate_lang_items},
@@ -351,8 +356,7 @@ pub enum ModuleDef {
Function(Function),
Adt(Adt),
// Can't be directly declared, but can be imported.
- // FIXME: Rename to `EnumVariant`
- Variant(Variant),
+ EnumVariant(EnumVariant),
Const(Const),
Static(Static),
Trait(Trait),
@@ -364,7 +368,7 @@ impl_from!(
Module,
Function,
Adt(Struct, Enum, Union),
- Variant,
+ EnumVariant,
Const,
Static,
Trait,
@@ -374,12 +378,12 @@ impl_from!(
for ModuleDef
);
-impl From<VariantDef> for ModuleDef {
- fn from(var: VariantDef) -> Self {
+impl From<Variant> for ModuleDef {
+ fn from(var: Variant) -> Self {
match var {
- VariantDef::Struct(t) => Adt::from(t).into(),
- VariantDef::Union(t) => Adt::from(t).into(),
- VariantDef::Variant(t) => t.into(),
+ Variant::Struct(t) => Adt::from(t).into(),
+ Variant::Union(t) => Adt::from(t).into(),
+ Variant::EnumVariant(t) => t.into(),
}
}
}
@@ -390,7 +394,7 @@ impl ModuleDef {
ModuleDef::Module(it) => it.parent(db),
ModuleDef::Function(it) => Some(it.module(db)),
ModuleDef::Adt(it) => Some(it.module(db)),
- ModuleDef::Variant(it) => Some(it.module(db)),
+ ModuleDef::EnumVariant(it) => Some(it.module(db)),
ModuleDef::Const(it) => Some(it.module(db)),
ModuleDef::Static(it) => Some(it.module(db)),
ModuleDef::Trait(it) => Some(it.module(db)),
@@ -423,7 +427,7 @@ impl ModuleDef {
ModuleDef::Adt(it) => it.name(db),
ModuleDef::Trait(it) => it.name(db),
ModuleDef::Function(it) => it.name(db),
- ModuleDef::Variant(it) => it.name(db),
+ ModuleDef::EnumVariant(it) => it.name(db),
ModuleDef::TypeAlias(it) => it.name(db),
ModuleDef::Static(it) => it.name(db),
ModuleDef::Macro(it) => it.name(db),
@@ -452,7 +456,7 @@ impl ModuleDef {
ModuleDef::Module(it) => it.id.into(),
ModuleDef::Const(it) => it.id.into(),
ModuleDef::Static(it) => it.id.into(),
- ModuleDef::Variant(it) => it.id.into(),
+ ModuleDef::EnumVariant(it) => it.id.into(),
ModuleDef::BuiltinType(_) | ModuleDef::Macro(_) => return Vec::new(),
};
@@ -481,7 +485,7 @@ impl ModuleDef {
ModuleDef::Function(it) => Some(it.into()),
ModuleDef::Const(it) => Some(it.into()),
ModuleDef::Static(it) => Some(it.into()),
- ModuleDef::Variant(it) => Some(it.into()),
+ ModuleDef::EnumVariant(it) => Some(it.into()),
ModuleDef::Module(_)
| ModuleDef::Adt(_)
@@ -500,7 +504,7 @@ impl ModuleDef {
ModuleDef::Trait(it) => Some(it.into()),
ModuleDef::TypeAlias(it) => Some(it.into()),
ModuleDef::Module(_)
- | ModuleDef::Variant(_)
+ | ModuleDef::EnumVariant(_)
| ModuleDef::Static(_)
| ModuleDef::Const(_)
| ModuleDef::BuiltinType(_)
@@ -508,12 +512,27 @@ impl ModuleDef {
}
}
+ pub fn as_generic_def(self) -> Option<GenericDef> {
+ match self {
+ ModuleDef::Function(it) => Some(it.into()),
+ ModuleDef::Adt(it) => Some(it.into()),
+ ModuleDef::Trait(it) => Some(it.into()),
+ ModuleDef::TypeAlias(it) => Some(it.into()),
+ ModuleDef::Static(it) => Some(it.into()),
+ ModuleDef::Const(it) => Some(it.into()),
+ ModuleDef::EnumVariant(_)
+ | ModuleDef::Module(_)
+ | ModuleDef::BuiltinType(_)
+ | ModuleDef::Macro(_) => None,
+ }
+ }
+
pub fn attrs(&self, db: &dyn HirDatabase) -> Option<AttrsWithOwner> {
Some(match self {
ModuleDef::Module(it) => it.attrs(db),
ModuleDef::Function(it) => HasAttrs::attrs(*it, db),
ModuleDef::Adt(it) => it.attrs(db),
- ModuleDef::Variant(it) => it.attrs(db),
+ ModuleDef::EnumVariant(it) => it.attrs(db),
ModuleDef::Const(it) => it.attrs(db),
ModuleDef::Static(it) => it.attrs(db),
ModuleDef::Trait(it) => it.attrs(db),
@@ -543,7 +562,7 @@ impl HasVisibility for ModuleDef {
ModuleDef::Static(it) => it.visibility(db),
ModuleDef::Trait(it) => it.visibility(db),
ModuleDef::TypeAlias(it) => it.visibility(db),
- ModuleDef::Variant(it) => it.visibility(db),
+ ModuleDef::EnumVariant(it) => it.visibility(db),
ModuleDef::Macro(it) => it.visibility(db),
ModuleDef::BuiltinType(_) => Visibility::Public,
}
@@ -714,8 +733,8 @@ impl Module {
ModuleDef::Adt(adt) => {
match adt {
Adt::Struct(s) => {
- let source_map = db.struct_signature_with_source_map(s.id).1;
- expr_store_diagnostics(db, acc, &source_map);
+ let source_map = &StructSignature::with_source_map(db, s.id).1;
+ expr_store_diagnostics(db, acc, source_map);
let source_map = &s.id.fields_with_source_map(db).1;
expr_store_diagnostics(db, acc, source_map);
push_ty_diagnostics(
@@ -726,8 +745,8 @@ impl Module {
);
}
Adt::Union(u) => {
- let source_map = db.union_signature_with_source_map(u.id).1;
- expr_store_diagnostics(db, acc, &source_map);
+ let source_map = &UnionSignature::with_source_map(db, u.id).1;
+ expr_store_diagnostics(db, acc, source_map);
let source_map = &u.id.fields_with_source_map(db).1;
expr_store_diagnostics(db, acc, source_map);
push_ty_diagnostics(
@@ -738,8 +757,8 @@ impl Module {
);
}
Adt::Enum(e) => {
- let source_map = db.enum_signature_with_source_map(e.id).1;
- expr_store_diagnostics(db, acc, &source_map);
+ let source_map = &EnumSignature::with_source_map(db, e.id).1;
+ expr_store_diagnostics(db, acc, source_map);
let (variants, diagnostics) = e.id.enum_variants_with_diagnostics(db);
let file = e.id.lookup(db).id.file_id;
let ast_id_map = db.ast_id_map(file);
@@ -774,13 +793,13 @@ impl Module {
}
ModuleDef::Macro(m) => emit_macro_def_diagnostics(db, acc, m),
ModuleDef::TypeAlias(type_alias) => {
- let source_map = db.type_alias_signature_with_source_map(type_alias.id).1;
- expr_store_diagnostics(db, acc, &source_map);
+ let source_map = &TypeAliasSignature::with_source_map(db, type_alias.id).1;
+ expr_store_diagnostics(db, acc, source_map);
push_ty_diagnostics(
db,
acc,
db.type_for_type_alias_with_diagnostics(type_alias.id).1,
- &source_map,
+ source_map,
);
acc.extend(def.diagnostics(db, style_lints));
}
@@ -800,8 +819,8 @@ impl Module {
continue;
};
let loc = impl_id.lookup(db);
- let (impl_signature, source_map) = db.impl_signature_with_source_map(impl_id);
- expr_store_diagnostics(db, acc, &source_map);
+ let (impl_signature, source_map) = ImplSignature::with_source_map(db, impl_id);
+ expr_store_diagnostics(db, acc, source_map);
let file_id = loc.id.file_id;
if file_id.macro_file().is_some_and(|it| it.kind(db) == MacroKind::DeriveBuiltIn) {
@@ -873,9 +892,9 @@ impl Module {
if let (false, Some(trait_)) = (impl_is_negative, trait_) {
let items = &trait_.id.trait_items(db).items;
let required_items = items.iter().filter(|&(_, assoc)| match *assoc {
- AssocItemId::FunctionId(it) => !db.function_signature(it).has_body(),
- AssocItemId::ConstId(id) => !db.const_signature(id).has_body(),
- AssocItemId::TypeAliasId(it) => db.type_alias_signature(it).ty.is_none(),
+ AssocItemId::FunctionId(it) => !FunctionSignature::of(db, it).has_body(),
+ AssocItemId::ConstId(id) => !ConstSignature::of(db, id).has_body(),
+ AssocItemId::TypeAliasId(it) => TypeAliasSignature::of(db, it).ty.is_none(),
});
impl_assoc_items_scratch.extend(impl_id.impl_items(db).items.iter().cloned());
@@ -913,7 +932,7 @@ impl Module {
let self_ty = structurally_normalize_ty(
&infcx,
self_ty,
- db.trait_environment(impl_id.into()),
+ db.trait_environment(GenericDefId::from(impl_id).into()),
);
let self_ty_is_guaranteed_unsized = matches!(
self_ty.kind(),
@@ -968,7 +987,7 @@ impl Module {
continue;
}
- if db.function_signature(*fn_).is_default() {
+ if FunctionSignature::of(db, *fn_).is_default() {
return false;
}
}
@@ -992,12 +1011,12 @@ impl Module {
impl_assoc_items_scratch.clear();
}
- push_ty_diagnostics(db, acc, db.impl_self_ty_with_diagnostics(impl_id).1, &source_map);
+ push_ty_diagnostics(db, acc, db.impl_self_ty_with_diagnostics(impl_id).1, source_map);
push_ty_diagnostics(
db,
acc,
db.impl_trait_with_diagnostics(impl_id).and_then(|it| it.1),
- &source_map,
+ source_map,
);
for &(_, item) in impl_id.impl_items(db).items.iter() {
@@ -1280,7 +1299,7 @@ impl HasVisibility for Module {
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Field {
- pub(crate) parent: VariantDef,
+ pub(crate) parent: Variant,
pub(crate) id: LocalFieldId,
}
@@ -1304,7 +1323,7 @@ impl<'db> InstantiatedField<'db> {
#[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)]
pub struct TupleField {
- pub owner: DefWithBodyId,
+ pub owner: ExpressionStoreOwnerId,
pub tuple: TupleId,
pub index: u32,
}
@@ -1316,7 +1335,7 @@ impl TupleField {
pub fn ty<'db>(&self, db: &'db dyn HirDatabase) -> Type<'db> {
let interner = DbInterner::new_no_crate(db);
- let ty = InferenceResult::for_body(db, self.owner)
+ let ty = InferenceResult::of(db, self.owner)
.tuple_field_access_type(self.tuple)
.as_slice()
.get(self.index as usize)
@@ -1386,9 +1405,9 @@ impl Field {
) -> Type<'db> {
let var_id = self.parent.into();
let def_id: AdtId = match self.parent {
- VariantDef::Struct(it) => it.id.into(),
- VariantDef::Union(it) => it.id.into(),
- VariantDef::Variant(it) => it.parent_enum(db).id.into(),
+ Variant::Struct(it) => it.id.into(),
+ Variant::Union(it) => it.id.into(),
+ Variant::EnumVariant(it) => it.parent_enum(db).id.into(),
};
let interner = DbInterner::new_no_crate(db);
let args = generic_args_from_tys(interner, def_id.into(), generics.map(|ty| ty.ty));
@@ -1414,7 +1433,7 @@ impl Field {
.map(|layout| Layout(layout, db.target_data_layout(self.krate(db).into()).unwrap()))
}
- pub fn parent_def(&self, _db: &dyn HirDatabase) -> VariantDef {
+ pub fn parent_def(&self, _db: &dyn HirDatabase) -> Variant {
self.parent
}
}
@@ -1440,7 +1459,7 @@ impl Struct {
}
pub fn name(self, db: &dyn HirDatabase) -> Name {
- db.struct_signature(self.id).name.clone()
+ StructSignature::of(db, self.id).name.clone()
}
pub fn fields(self, db: &dyn HirDatabase) -> Vec<Field> {
@@ -1533,7 +1552,7 @@ pub struct Union {
impl Union {
pub fn name(self, db: &dyn HirDatabase) -> Name {
- db.union_signature(self.id).name.clone()
+ UnionSignature::of(db, self.id).name.clone()
}
pub fn module(self, db: &dyn HirDatabase) -> Module {
@@ -1592,11 +1611,11 @@ impl Enum {
}
pub fn name(self, db: &dyn HirDatabase) -> Name {
- db.enum_signature(self.id).name.clone()
+ EnumSignature::of(db, self.id).name.clone()
}
- pub fn variants(self, db: &dyn HirDatabase) -> Vec<Variant> {
- self.id.enum_variants(db).variants.iter().map(|&(id, _, _)| Variant { id }).collect()
+ pub fn variants(self, db: &dyn HirDatabase) -> Vec<EnumVariant> {
+ self.id.enum_variants(db).variants.iter().map(|&(id, _, _)| EnumVariant { id }).collect()
}
pub fn num_variants(self, db: &dyn HirDatabase) -> usize {
@@ -1688,19 +1707,18 @@ impl<'db> InstantiatedEnum<'db> {
}
}
-impl From<&Variant> for DefWithBodyId {
- fn from(&v: &Variant) -> Self {
+impl From<&EnumVariant> for DefWithBodyId {
+ fn from(&v: &EnumVariant) -> Self {
DefWithBodyId::VariantId(v.into())
}
}
-// FIXME: Rename to `EnumVariant`
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
-pub struct Variant {
+pub struct EnumVariant {
pub(crate) id: EnumVariantId,
}
-impl Variant {
+impl EnumVariant {
pub fn module(self, db: &dyn HirDatabase) -> Module {
Module { id: self.id.module(db) }
}
@@ -1737,7 +1755,7 @@ impl Variant {
}
pub fn value(self, db: &dyn HirDatabase) -> Option<ast::Expr> {
- self.source(db)?.value.expr()
+ self.source(db)?.value.const_arg()?.expr()
}
pub fn eval(self, db: &dyn HirDatabase) -> Result<i128, ConstEvalError> {
@@ -1774,7 +1792,7 @@ impl Variant {
// FIXME: Rename to `EnumVariant`
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct InstantiatedVariant<'db> {
- pub(crate) inner: Variant,
+ pub(crate) inner: EnumVariant,
pub(crate) args: GenericArgs<'db>,
}
@@ -1805,7 +1823,7 @@ pub enum StructKind {
}
/// Variants inherit visibility from the parent enum.
-impl HasVisibility for Variant {
+impl HasVisibility for EnumVariant {
fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
self.parent_enum(db).visibility(db)
}
@@ -1914,35 +1932,78 @@ impl HasVisibility for Adt {
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
-pub enum VariantDef {
+pub enum Variant {
Struct(Struct),
Union(Union),
- Variant(Variant),
+ EnumVariant(EnumVariant),
}
-impl_from!(Struct, Union, Variant for VariantDef);
+impl_from!(Struct, Union, EnumVariant for Variant);
-impl VariantDef {
+impl Variant {
pub fn fields(self, db: &dyn HirDatabase) -> Vec<Field> {
match self {
- VariantDef::Struct(it) => it.fields(db),
- VariantDef::Union(it) => it.fields(db),
- VariantDef::Variant(it) => it.fields(db),
+ Variant::Struct(it) => it.fields(db),
+ Variant::Union(it) => it.fields(db),
+ Variant::EnumVariant(it) => it.fields(db),
}
}
pub fn module(self, db: &dyn HirDatabase) -> Module {
match self {
- VariantDef::Struct(it) => it.module(db),
- VariantDef::Union(it) => it.module(db),
- VariantDef::Variant(it) => it.module(db),
+ Variant::Struct(it) => it.module(db),
+ Variant::Union(it) => it.module(db),
+ Variant::EnumVariant(it) => it.module(db),
}
}
pub fn name(&self, db: &dyn HirDatabase) -> Name {
match self {
- VariantDef::Struct(s) => (*s).name(db),
- VariantDef::Union(u) => (*u).name(db),
- VariantDef::Variant(e) => (*e).name(db),
+ Variant::Struct(s) => (*s).name(db),
+ Variant::Union(u) => (*u).name(db),
+ Variant::EnumVariant(e) => (*e).name(db),
+ }
+ }
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub enum ExpressionStoreOwner {
+ Body(DefWithBody),
+ Signature(GenericDef),
+ VariantFields(Variant),
+}
+
+impl From<GenericDef> for ExpressionStoreOwner {
+ fn from(v: GenericDef) -> Self {
+ Self::Signature(v)
+ }
+}
+
+impl From<DefWithBody> for ExpressionStoreOwner {
+ fn from(v: DefWithBody) -> Self {
+ Self::Body(v)
+ }
+}
+
+impl From<ExpressionStoreOwnerId> for ExpressionStoreOwner {
+ fn from(v: ExpressionStoreOwnerId) -> Self {
+ match v {
+ ExpressionStoreOwnerId::Signature(generic_def_id) => {
+ Self::Signature(generic_def_id.into())
+ }
+ ExpressionStoreOwnerId::Body(def_with_body_id) => Self::Body(def_with_body_id.into()),
+ ExpressionStoreOwnerId::VariantFields(variant_id) => {
+ Self::VariantFields(variant_id.into())
+ }
+ }
+ }
+}
+
+impl ExpressionStoreOwner {
+ pub fn module(self, db: &dyn HirDatabase) -> Module {
+ match self {
+ Self::Body(body) => body.module(db),
+ Self::Signature(generic_def) => generic_def.module(db),
+ Self::VariantFields(variant) => variant.module(db),
}
}
}
@@ -1953,9 +2014,9 @@ pub enum DefWithBody {
Function(Function),
Static(Static),
Const(Const),
- Variant(Variant),
+ EnumVariant(EnumVariant),
}
-impl_from!(Function, Const, Static, Variant for DefWithBody);
+impl_from!(Function, Const, Static, EnumVariant for DefWithBody);
impl DefWithBody {
pub fn module(self, db: &dyn HirDatabase) -> Module {
@@ -1963,7 +2024,7 @@ impl DefWithBody {
DefWithBody::Const(c) => c.module(db),
DefWithBody::Function(f) => f.module(db),
DefWithBody::Static(s) => s.module(db),
- DefWithBody::Variant(v) => v.module(db),
+ DefWithBody::EnumVariant(v) => v.module(db),
}
}
@@ -1972,7 +2033,7 @@ impl DefWithBody {
DefWithBody::Function(f) => Some(f.name(db)),
DefWithBody::Static(s) => Some(s.name(db)),
DefWithBody::Const(c) => c.name(db),
- DefWithBody::Variant(v) => Some(v.name(db)),
+ DefWithBody::EnumVariant(v) => Some(v.name(db)),
}
}
@@ -1982,7 +2043,7 @@ impl DefWithBody {
DefWithBody::Function(it) => it.ret_type(db),
DefWithBody::Static(it) => it.ty(db),
DefWithBody::Const(it) => it.ty(db),
- DefWithBody::Variant(it) => it.parent_enum(db).variant_body_ty(db),
+ DefWithBody::EnumVariant(it) => it.parent_enum(db).variant_body_ty(db),
}
}
@@ -1994,7 +2055,7 @@ impl DefWithBody {
},
DefWithBody::Static(it) => it.id.into(),
DefWithBody::Const(it) => it.id.into(),
- DefWithBody::Variant(it) => it.into(),
+ DefWithBody::EnumVariant(it) => it.into(),
})
}
@@ -2003,7 +2064,7 @@ impl DefWithBody {
let Some(id) = self.id() else {
return String::new();
};
- let body = db.body(id);
+ let body = Body::of(db, id);
body.pretty_print(db, id, Edition::CURRENT)
}
@@ -2030,17 +2091,17 @@ impl DefWithBody {
};
let krate = self.module(db).id.krate(db);
- let (body, source_map) = db.body_with_source_map(id);
+ let (body, source_map) = Body::with_source_map(db, id);
let sig_source_map = match self {
DefWithBody::Function(id) => match id.id {
- AnyFunctionId::FunctionId(id) => db.function_signature_with_source_map(id).1,
+ AnyFunctionId::FunctionId(id) => &FunctionSignature::with_source_map(db, id).1,
AnyFunctionId::BuiltinDeriveImplMethod { .. } => return,
},
- DefWithBody::Static(id) => db.static_signature_with_source_map(id.into()).1,
- DefWithBody::Const(id) => db.const_signature_with_source_map(id.into()).1,
- DefWithBody::Variant(variant) => {
+ DefWithBody::Static(id) => &StaticSignature::with_source_map(db, id.into()).1,
+ DefWithBody::Const(id) => &ConstSignature::with_source_map(db, id.into()).1,
+ DefWithBody::EnumVariant(variant) => {
let enum_id = variant.parent_enum(db).id;
- db.enum_signature_with_source_map(enum_id).1
+ &EnumSignature::with_source_map(db, enum_id).1
}
};
@@ -2048,17 +2109,11 @@ impl DefWithBody {
Module { id: def_map.root_module_id() }.diagnostics(db, acc, style_lints);
}
- expr_store_diagnostics(db, acc, &source_map);
+ expr_store_diagnostics(db, acc, source_map);
- let infer = InferenceResult::for_body(db, id);
+ let infer = InferenceResult::of(db, id);
for d in infer.diagnostics() {
- acc.extend(AnyDiagnostic::inference_diagnostic(
- db,
- id,
- d,
- &source_map,
- &sig_source_map,
- ));
+ acc.extend(AnyDiagnostic::inference_diagnostic(db, id, d, source_map, sig_source_map));
}
for (pat_or_expr, mismatch) in infer.type_mismatches() {
@@ -2180,7 +2235,7 @@ impl DefWithBody {
{
need_mut = &mir::MutabilityReason::Not;
}
- let local = Local { parent: id, binding_id };
+ let local = Local { parent: id.into(), binding_id };
let is_mut = body[binding_id].mode == BindingAnnotation::Mutable;
match (need_mut, is_mut) {
@@ -2237,7 +2292,7 @@ impl DefWithBody {
}
for diagnostic in BodyValidationDiagnostic::collect(db, id, style_lints) {
- acc.extend(AnyDiagnostic::body_validation_diagnostic(db, diagnostic, &source_map));
+ acc.extend(AnyDiagnostic::body_validation_diagnostic(db, diagnostic, source_map));
}
for diag in hir_ty::diagnostics::incorrect_case(db, id.into()) {
@@ -2251,7 +2306,7 @@ impl DefWithBody {
db: &'db dyn HirDatabase,
) -> impl Iterator<Item = Type<'db>> {
self.id().into_iter().flat_map(move |def_id| {
- let infer = InferenceResult::for_body(db, def_id);
+ let infer = InferenceResult::of(db, def_id);
let resolver = def_id.resolver(db);
infer.expression_types().map(move |(_, ty)| Type::new_with_resolver(db, &resolver, ty))
@@ -2261,7 +2316,7 @@ impl DefWithBody {
/// Returns an iterator over the inferred types of all patterns in this body.
pub fn pattern_types<'db>(self, db: &'db dyn HirDatabase) -> impl Iterator<Item = Type<'db>> {
self.id().into_iter().flat_map(move |def_id| {
- let infer = InferenceResult::for_body(db, def_id);
+ let infer = InferenceResult::of(db, def_id);
let resolver = def_id.resolver(db);
infer.pattern_types().map(move |(_, ty)| Type::new_with_resolver(db, &resolver, ty))
@@ -2271,7 +2326,7 @@ impl DefWithBody {
/// Returns an iterator over the inferred types of all bindings in this body.
pub fn binding_types<'db>(self, db: &'db dyn HirDatabase) -> impl Iterator<Item = Type<'db>> {
self.id().into_iter().flat_map(move |def_id| {
- let infer = InferenceResult::for_body(db, def_id);
+ let infer = InferenceResult::of(db, def_id);
let resolver = def_id.resolver(db);
infer.binding_types().map(move |(_, ty)| Type::new_with_resolver(db, &resolver, ty))
@@ -2339,7 +2394,7 @@ impl Function {
pub fn name(self, db: &dyn HirDatabase) -> Name {
match self.id {
- AnyFunctionId::FunctionId(id) => db.function_signature(id).name.clone(),
+ AnyFunctionId::FunctionId(id) => FunctionSignature::of(db, id).name.clone(),
AnyFunctionId::BuiltinDeriveImplMethod { method, .. } => {
Name::new_symbol_root(method.name())
}
@@ -2541,7 +2596,7 @@ impl Function {
pub fn has_self_param(self, db: &dyn HirDatabase) -> bool {
match self.id {
- AnyFunctionId::FunctionId(id) => db.function_signature(id).has_self_param(),
+ AnyFunctionId::FunctionId(id) => FunctionSignature::of(db, id).has_self_param(),
AnyFunctionId::BuiltinDeriveImplMethod { method, .. } => match method {
BuiltinDeriveImplMethod::clone
| BuiltinDeriveImplMethod::fmt
@@ -2576,7 +2631,7 @@ impl Function {
pub fn num_params(self, db: &dyn HirDatabase) -> usize {
match self.id {
- AnyFunctionId::FunctionId(id) => db.function_signature(id).params.len(),
+ AnyFunctionId::FunctionId(id) => FunctionSignature::of(db, id).params.len(),
AnyFunctionId::BuiltinDeriveImplMethod { .. } => {
self.fn_sig(db).1.skip_binder().inputs().len()
}
@@ -2620,21 +2675,21 @@ impl Function {
pub fn is_const(self, db: &dyn HirDatabase) -> bool {
match self.id {
- AnyFunctionId::FunctionId(id) => db.function_signature(id).is_const(),
+ AnyFunctionId::FunctionId(id) => FunctionSignature::of(db, id).is_const(),
AnyFunctionId::BuiltinDeriveImplMethod { .. } => false,
}
}
pub fn is_async(self, db: &dyn HirDatabase) -> bool {
match self.id {
- AnyFunctionId::FunctionId(id) => db.function_signature(id).is_async(),
+ AnyFunctionId::FunctionId(id) => FunctionSignature::of(db, id).is_async(),
AnyFunctionId::BuiltinDeriveImplMethod { .. } => false,
}
}
pub fn is_varargs(self, db: &dyn HirDatabase) -> bool {
match self.id {
- AnyFunctionId::FunctionId(id) => db.function_signature(id).is_varargs(),
+ AnyFunctionId::FunctionId(id) => FunctionSignature::of(db, id).is_varargs(),
AnyFunctionId::BuiltinDeriveImplMethod { .. } => false,
}
}
@@ -2687,7 +2742,7 @@ impl Function {
AnyFunctionId::FunctionId(id) => {
self.exported_main(db)
|| self.module(db).is_crate_root(db)
- && db.function_signature(id).name == sym::main
+ && FunctionSignature::of(db, id).name == sym::main
}
AnyFunctionId::BuiltinDeriveImplMethod { .. } => false,
}
@@ -2764,7 +2819,7 @@ impl Function {
/// This is false in the case of required (not provided) trait methods.
pub fn has_body(self, db: &dyn HirDatabase) -> bool {
match self.id {
- AnyFunctionId::FunctionId(id) => db.function_signature(id).has_body(),
+ AnyFunctionId::FunctionId(id) => FunctionSignature::of(db, id).has_body(),
AnyFunctionId::BuiltinDeriveImplMethod { .. } => true,
}
}
@@ -2792,7 +2847,7 @@ impl Function {
id.into(),
GenericArgs::empty(interner).store(),
ParamEnvAndCrate {
- param_env: db.trait_environment(id.into()),
+ param_env: db.trait_environment(GenericDefId::from(id).into()),
krate: id.module(db).krate(db),
}
.store(),
@@ -2878,24 +2933,26 @@ impl<'db> Param<'db> {
match self.func {
Callee::Def(CallableDefId::FunctionId(it)) => {
let parent = DefWithBodyId::FunctionId(it);
- let body = db.body(parent);
+ let body = Body::of(db, parent);
if let Some(self_param) = body.self_param.filter(|_| self.idx == 0) {
- Some(Local { parent, binding_id: self_param })
+ Some(Local { parent: parent.into(), binding_id: self_param })
} else if let Pat::Bind { id, .. } =
&body[body.params[self.idx - body.self_param.is_some() as usize]]
{
- Some(Local { parent, binding_id: *id })
+ Some(Local { parent: parent.into(), binding_id: *id })
} else {
None
}
}
Callee::Closure(closure, _) => {
let c = db.lookup_intern_closure(closure);
- let body = db.body(c.0);
- if let Expr::Closure { args, .. } = &body[c.1]
- && let Pat::Bind { id, .. } = &body[args[self.idx]]
+ let body_owner = c.0;
+ let store = ExpressionStore::of(db, c.0);
+
+ if let Expr::Closure { args, .. } = &store[c.1]
+ && let Pat::Bind { id, .. } = &store[args[self.idx]]
{
- return Some(Local { parent: c.0, binding_id: *id });
+ return Some(Local { parent: body_owner, binding_id: *id });
}
None
}
@@ -2917,7 +2974,7 @@ impl SelfParam {
pub fn access(self, db: &dyn HirDatabase) -> Access {
match self.func.id {
AnyFunctionId::FunctionId(id) => {
- let func_data = db.function_signature(id);
+ let func_data = FunctionSignature::of(db, id);
func_data
.params
.first()
@@ -3046,7 +3103,7 @@ impl Const {
}
pub fn name(self, db: &dyn HirDatabase) -> Option<Name> {
- db.const_signature(self.id).name.clone()
+ ConstSignature::of(db, self.id).name.clone()
}
pub fn value(self, db: &dyn HirDatabase) -> Option<ast::Expr> {
@@ -3119,11 +3176,11 @@ impl Static {
}
pub fn name(self, db: &dyn HirDatabase) -> Name {
- db.static_signature(self.id).name.clone()
+ StaticSignature::of(db, self.id).name.clone()
}
pub fn is_mut(self, db: &dyn HirDatabase) -> bool {
- db.static_signature(self.id).flags.contains(StaticFlags::MUTABLE)
+ StaticSignature::of(db, self.id).flags.contains(StaticFlags::MUTABLE)
}
pub fn value(self, db: &dyn HirDatabase) -> Option<ast::Expr> {
@@ -3179,7 +3236,7 @@ impl Trait {
}
pub fn name(self, db: &dyn HirDatabase) -> Name {
- db.trait_signature(self.id).name.clone()
+ TraitSignature::of(db, self.id).name.clone()
}
pub fn direct_supertraits(self, db: &dyn HirDatabase) -> Vec<Trait> {
@@ -3209,11 +3266,11 @@ impl Trait {
}
pub fn is_auto(self, db: &dyn HirDatabase) -> bool {
- db.trait_signature(self.id).flags.contains(TraitFlags::AUTO)
+ TraitSignature::of(db, self.id).flags.contains(TraitFlags::AUTO)
}
pub fn is_unsafe(&self, db: &dyn HirDatabase) -> bool {
- db.trait_signature(self.id).flags.contains(TraitFlags::UNSAFE)
+ TraitSignature::of(db, self.id).flags.contains(TraitFlags::UNSAFE)
}
pub fn type_or_const_param_count(
@@ -3221,7 +3278,7 @@ impl Trait {
db: &dyn HirDatabase,
count_required_only: bool,
) -> usize {
- db.generic_params(self.id.into())
+ GenericParams::of(db,self.id.into())
.iter_type_or_consts()
.filter(|(_, ty)| !matches!(ty, TypeOrConstParamData::TypeParamData(ty) if ty.provenance != TypeParamProvenance::TypeParamList))
.filter(|(_, ty)| !count_required_only || !ty.has_default())
@@ -3289,7 +3346,7 @@ impl TypeAlias {
}
pub fn name(self, db: &dyn HirDatabase) -> Name {
- db.type_alias_signature(self.id).name.clone()
+ TypeAliasSignature::of(db, self.id).name.clone()
}
}
@@ -3731,7 +3788,18 @@ impl AsAssocItem for DefWithBody {
match self {
DefWithBody::Function(it) => it.as_assoc_item(db),
DefWithBody::Const(it) => it.as_assoc_item(db),
- DefWithBody::Static(_) | DefWithBody::Variant(_) => None,
+ DefWithBody::Static(_) | DefWithBody::EnumVariant(_) => None,
+ }
+ }
+}
+
+impl AsAssocItem for GenericDef {
+ fn as_assoc_item(self, db: &dyn HirDatabase) -> Option<AssocItem> {
+ match self {
+ GenericDef::Function(it) => it.as_assoc_item(db),
+ GenericDef::Const(it) => it.as_assoc_item(db),
+ GenericDef::TypeAlias(it) => it.as_assoc_item(db),
+ _ => None,
}
}
}
@@ -3918,7 +3986,7 @@ impl AssocItem {
db,
acc,
db.type_for_type_alias_with_diagnostics(type_alias.id).1,
- &db.type_alias_signature_with_source_map(type_alias.id).1,
+ &TypeAliasSignature::with_source_map(db, type_alias.id).1,
);
for diag in hir_ty::diagnostics::incorrect_case(db, type_alias.id.into()) {
acc.push(diag.into());
@@ -3971,12 +4039,36 @@ impl_from!(
);
impl GenericDef {
+ pub fn name(self, db: &dyn HirDatabase) -> Option<Name> {
+ match self {
+ GenericDef::Function(it) => Some(it.name(db)),
+ GenericDef::Adt(it) => Some(it.name(db)),
+ GenericDef::Trait(it) => Some(it.name(db)),
+ GenericDef::TypeAlias(it) => Some(it.name(db)),
+ GenericDef::Impl(_) => None,
+ GenericDef::Const(it) => it.name(db),
+ GenericDef::Static(it) => Some(it.name(db)),
+ }
+ }
+
+ pub fn module(self, db: &dyn HirDatabase) -> Module {
+ match self {
+ GenericDef::Function(it) => it.module(db),
+ GenericDef::Adt(it) => it.module(db),
+ GenericDef::Trait(it) => it.module(db),
+ GenericDef::TypeAlias(it) => it.module(db),
+ GenericDef::Impl(it) => it.module(db),
+ GenericDef::Const(it) => it.module(db),
+ GenericDef::Static(it) => it.module(db),
+ }
+ }
+
pub fn params(self, db: &dyn HirDatabase) -> Vec<GenericParam> {
let Ok(id) = self.try_into() else {
// Let's pretend builtin derive impls don't have generic parameters.
return Vec::new();
};
- let generics = db.generic_params(id);
+ let generics = GenericParams::of(db, id);
let ty_params = generics.iter_type_or_consts().map(|(local_id, _)| {
let toc = TypeOrConstParam { id: TypeOrConstParamId { parent: id, local_id } };
match toc.split(db) {
@@ -3996,7 +4088,7 @@ impl GenericDef {
// Let's pretend builtin derive impls don't have generic parameters.
return Vec::new();
};
- let generics = db.generic_params(id);
+ let generics = GenericParams::of(db, id);
generics
.iter_lt()
.map(|(local_id, _)| LifetimeParam { id: LifetimeParamId { parent: id, local_id } })
@@ -4008,7 +4100,7 @@ impl GenericDef {
// Let's pretend builtin derive impls don't have generic parameters.
return Vec::new();
};
- let generics = db.generic_params(id);
+ let generics = GenericParams::of(db, id);
generics
.iter_type_or_consts()
.map(|(local_id, _)| TypeOrConstParam {
@@ -4038,31 +4130,31 @@ impl GenericDef {
pub fn diagnostics<'db>(self, db: &'db dyn HirDatabase, acc: &mut Vec<AnyDiagnostic<'db>>) {
let Some(def) = self.id() else { return };
- let generics = db.generic_params(def);
+ let generics = GenericParams::of(db, def);
if generics.is_empty() && generics.has_no_predicates() {
return;
}
let source_map = match def {
- GenericDefId::AdtId(AdtId::EnumId(it)) => db.enum_signature_with_source_map(it).1,
- GenericDefId::AdtId(AdtId::StructId(it)) => db.struct_signature_with_source_map(it).1,
- GenericDefId::AdtId(AdtId::UnionId(it)) => db.union_signature_with_source_map(it).1,
+ GenericDefId::AdtId(AdtId::EnumId(it)) => &EnumSignature::with_source_map(db, it).1,
+ GenericDefId::AdtId(AdtId::StructId(it)) => &StructSignature::with_source_map(db, it).1,
+ GenericDefId::AdtId(AdtId::UnionId(it)) => &UnionSignature::with_source_map(db, it).1,
GenericDefId::ConstId(_) => return,
- GenericDefId::FunctionId(it) => db.function_signature_with_source_map(it).1,
- GenericDefId::ImplId(it) => db.impl_signature_with_source_map(it).1,
+ GenericDefId::FunctionId(it) => &FunctionSignature::with_source_map(db, it).1,
+ GenericDefId::ImplId(it) => &ImplSignature::with_source_map(db, it).1,
GenericDefId::StaticId(_) => return,
- GenericDefId::TraitId(it) => db.trait_signature_with_source_map(it).1,
- GenericDefId::TypeAliasId(it) => db.type_alias_signature_with_source_map(it).1,
+ GenericDefId::TraitId(it) => &TraitSignature::with_source_map(db, it).1,
+ GenericDefId::TypeAliasId(it) => &TypeAliasSignature::with_source_map(db, it).1,
};
- expr_store_diagnostics(db, acc, &source_map);
- push_ty_diagnostics(db, acc, db.generic_defaults_with_diagnostics(def).1, &source_map);
+ expr_store_diagnostics(db, acc, source_map);
+ push_ty_diagnostics(db, acc, db.generic_defaults_with_diagnostics(def).1, source_map);
push_ty_diagnostics(
db,
acc,
GenericPredicates::query_with_diagnostics(db, def).1.clone(),
- &source_map,
+ source_map,
);
for (param_id, param) in generics.iter_type_or_consts() {
if let TypeOrConstParamData::ConstParamData(_) = param {
@@ -4073,7 +4165,7 @@ impl GenericDef {
TypeOrConstParamId { parent: def, local_id: param_id },
))
.1,
- &source_map,
+ source_map,
);
}
}
@@ -4134,7 +4226,7 @@ impl<'db> GenericSubstitution<'db> {
_ => None,
})
.map(|container| {
- db.generic_params(container)
+ GenericParams::of(db, container)
.iter_type_or_consts()
.filter_map(|param| match param.1 {
TypeOrConstParamData::TypeParamData(param) => Some(param.name.clone()),
@@ -4142,7 +4234,7 @@ impl<'db> GenericSubstitution<'db> {
})
.collect::<Vec<_>>()
});
- let generics = db.generic_params(self.def);
+ let generics = GenericParams::of(db, self.def);
let type_params = generics.iter_type_or_consts().filter_map(|param| match param.1 {
TypeOrConstParamData::TypeParamData(param) => Some(param.name.clone()),
TypeOrConstParamData::ConstParamData(_) => None,
@@ -4170,7 +4262,7 @@ impl<'db> GenericSubstitution<'db> {
/// A single local definition.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct Local {
- pub(crate) parent: DefWithBodyId,
+ pub(crate) parent: ExpressionStoreOwnerId,
pub(crate) binding_id: BindingId,
}
@@ -4232,7 +4324,7 @@ impl Local {
pub fn as_self_param(self, db: &dyn HirDatabase) -> Option<SelfParam> {
match self.parent {
- DefWithBodyId::FunctionId(func) if self.is_self(db) => {
+ ExpressionStoreOwnerId::Body(DefWithBodyId::FunctionId(func)) if self.is_self(db) => {
Some(SelfParam { func: func.into() })
}
_ => None,
@@ -4240,8 +4332,7 @@ impl Local {
}
pub fn name(self, db: &dyn HirDatabase) -> Name {
- let body = db.body(self.parent);
- body[self.binding_id].name.clone()
+ ExpressionStore::of(db, self.parent)[self.binding_id].name.clone()
}
pub fn is_self(self, db: &dyn HirDatabase) -> bool {
@@ -4249,16 +4340,17 @@ impl Local {
}
pub fn is_mut(self, db: &dyn HirDatabase) -> bool {
- let body = db.body(self.parent);
- body[self.binding_id].mode == BindingAnnotation::Mutable
+ ExpressionStore::of(db, self.parent)[self.binding_id].mode == BindingAnnotation::Mutable
}
pub fn is_ref(self, db: &dyn HirDatabase) -> bool {
- let body = db.body(self.parent);
- matches!(body[self.binding_id].mode, BindingAnnotation::Ref | BindingAnnotation::RefMut)
+ matches!(
+ ExpressionStore::of(db, self.parent)[self.binding_id].mode,
+ BindingAnnotation::Ref | BindingAnnotation::RefMut
+ )
}
- pub fn parent(self, _db: &dyn HirDatabase) -> DefWithBody {
+ pub fn parent(self, _db: &dyn HirDatabase) -> ExpressionStoreOwner {
self.parent.into()
}
@@ -4272,67 +4364,91 @@ impl Local {
pub fn ty(self, db: &dyn HirDatabase) -> Type<'_> {
let def = self.parent;
- let infer = InferenceResult::for_body(db, def);
+ let infer = InferenceResult::of(db, def);
let ty = infer.binding_ty(self.binding_id);
Type::new(db, def, ty)
}
/// All definitions for this local. Example: `let (a$0, _) | (_, a$0) = it;`
pub fn sources(self, db: &dyn HirDatabase) -> Vec<LocalSource> {
- let (body, source_map) = db.body_with_source_map(self.parent);
- match body.self_param.zip(source_map.self_param_syntax()) {
- Some((param, source)) if param == self.binding_id => {
- let root = source.file_syntax(db);
- vec![LocalSource {
- local: self,
- source: source.map(|ast| Either::Right(ast.to_node(&root))),
- }]
+ let b;
+ let (_, source_map) = match self.parent {
+ ExpressionStoreOwnerId::Signature(generic_def_id) => {
+ ExpressionStore::with_source_map(db, generic_def_id.into())
}
- _ => source_map
- .patterns_for_binding(self.binding_id)
- .iter()
- .map(|&definition| {
- let src = source_map.pat_syntax(definition).unwrap(); // Hmm...
- let root = src.file_syntax(db);
- LocalSource {
+ ExpressionStoreOwnerId::Body(def_with_body_id) => {
+ b = Body::with_source_map(db, def_with_body_id);
+ if let Some((param, source)) = b.0.self_param.zip(b.1.self_param_syntax())
+ && param == self.binding_id
+ {
+ let root = source.file_syntax(db);
+ return vec![LocalSource {
local: self,
- source: src.map(|ast| match ast.to_node(&root) {
- Either::Right(ast::Pat::IdentPat(it)) => Either::Left(it),
- _ => unreachable!("local with non ident-pattern"),
- }),
- }
- })
- .collect(),
- }
+ source: source.map(|ast| Either::Right(ast.to_node(&root))),
+ }];
+ }
+ (&b.0.store, &b.1.store)
+ }
+ ExpressionStoreOwnerId::VariantFields(def) => {
+ ExpressionStore::with_source_map(db, def.into())
+ }
+ };
+ source_map
+ .patterns_for_binding(self.binding_id)
+ .iter()
+ .map(|&definition| {
+ let src = source_map.pat_syntax(definition).unwrap(); // Hmm...
+ let root = src.file_syntax(db);
+ LocalSource {
+ local: self,
+ source: src.map(|ast| match ast.to_node(&root) {
+ Either::Right(ast::Pat::IdentPat(it)) => Either::Left(it),
+ _ => unreachable!("local with non ident-pattern"),
+ }),
+ }
+ })
+ .collect()
}
/// The leftmost definition for this local. Example: `let (a$0, _) | (_, a) = it;`
pub fn primary_source(self, db: &dyn HirDatabase) -> LocalSource {
- let (body, source_map) = db.body_with_source_map(self.parent);
- match body.self_param.zip(source_map.self_param_syntax()) {
- Some((param, source)) if param == self.binding_id => {
- let root = source.file_syntax(db);
+ let b;
+ let (_, source_map) = match self.parent {
+ ExpressionStoreOwnerId::Signature(generic_def_id) => {
+ ExpressionStore::with_source_map(db, generic_def_id.into())
+ }
+ ExpressionStoreOwnerId::Body(def_with_body_id) => {
+ b = Body::with_source_map(db, def_with_body_id);
+ if let Some((param, source)) = b.0.self_param.zip(b.1.self_param_syntax())
+ && param == self.binding_id
+ {
+ let root = source.file_syntax(db);
+ return LocalSource {
+ local: self,
+ source: source.map(|ast| Either::Right(ast.to_node(&root))),
+ };
+ }
+ (&b.0.store, &b.1.store)
+ }
+ ExpressionStoreOwnerId::VariantFields(def) => {
+ ExpressionStore::with_source_map(db, def.into())
+ }
+ };
+ source_map
+ .patterns_for_binding(self.binding_id)
+ .first()
+ .map(|&definition| {
+ let src = source_map.pat_syntax(definition).unwrap(); // Hmm...
+ let root = src.file_syntax(db);
LocalSource {
local: self,
- source: source.map(|ast| Either::Right(ast.to_node(&root))),
+ source: src.map(|ast| match ast.to_node(&root) {
+ Either::Right(ast::Pat::IdentPat(it)) => Either::Left(it),
+ _ => unreachable!("local with non ident-pattern"),
+ }),
}
- }
- _ => source_map
- .patterns_for_binding(self.binding_id)
- .first()
- .map(|&definition| {
- let src = source_map.pat_syntax(definition).unwrap(); // Hmm...
- let root = src.file_syntax(db);
- LocalSource {
- local: self,
- source: src.map(|ast| match ast.to_node(&root) {
- Either::Right(ast::Pat::IdentPat(it)) => Either::Left(it),
- _ => unreachable!("local with non ident-pattern"),
- }),
- }
- })
- .unwrap(),
- }
+ })
+ .unwrap()
}
}
@@ -4417,7 +4533,7 @@ impl ToolModule {
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct Label {
- pub(crate) parent: DefWithBodyId,
+ pub(crate) parent: ExpressionStoreOwnerId,
pub(crate) label_id: LabelId,
}
@@ -4426,13 +4542,12 @@ impl Label {
self.parent(db).module(db)
}
- pub fn parent(self, _db: &dyn HirDatabase) -> DefWithBody {
+ pub fn parent(self, _db: &dyn HirDatabase) -> ExpressionStoreOwner {
self.parent.into()
}
pub fn name(self, db: &dyn HirDatabase) -> Name {
- let body = db.body(self.parent);
- body[self.label_id].name.clone()
+ ExpressionStore::of(db, self.parent)[self.label_id].name.clone()
}
}
@@ -4543,7 +4658,7 @@ impl TypeParam {
/// Is this type parameter implicitly introduced (eg. `Self` in a trait or an `impl Trait`
/// argument)?
pub fn is_implicit(self, db: &dyn HirDatabase) -> bool {
- let params = db.generic_params(self.id.parent());
+ let params = GenericParams::of(db, self.id.parent());
let data = &params[self.id.local_id()];
match data.type_param().unwrap().provenance {
TypeParamProvenance::TypeParamList => false,
@@ -4598,7 +4713,7 @@ pub struct LifetimeParam {
impl LifetimeParam {
pub fn name(self, db: &dyn HirDatabase) -> Name {
- let params = db.generic_params(self.id.parent);
+ let params = GenericParams::of(db, self.id.parent);
params[self.id.local_id].name.clone()
}
@@ -4622,7 +4737,7 @@ impl ConstParam {
}
pub fn name(self, db: &dyn HirDatabase) -> Name {
- let params = db.generic_params(self.id.parent());
+ let params = GenericParams::of(db, self.id.parent());
match params[self.id.local_id()].name() {
Some(it) => it.clone(),
None => {
@@ -4669,7 +4784,7 @@ pub struct TypeOrConstParam {
impl TypeOrConstParam {
pub fn name(self, db: &dyn HirDatabase) -> Name {
- let params = db.generic_params(self.id.parent);
+ let params = GenericParams::of(db, self.id.parent);
match params[self.id.local_id].name() {
Some(n) => n.clone(),
_ => Name::missing(),
@@ -4685,7 +4800,7 @@ impl TypeOrConstParam {
}
pub fn split(self, db: &dyn HirDatabase) -> Either<ConstParam, TypeParam> {
- let params = db.generic_params(self.id.parent);
+ let params = GenericParams::of(db, self.id.parent);
match &params[self.id.local_id] {
TypeOrConstParamData::TypeParamData(_) => {
Either::Right(TypeParam { id: TypeParamId::from_unchecked(self.id) })
@@ -4704,7 +4819,7 @@ impl TypeOrConstParam {
}
pub fn as_type_param(self, db: &dyn HirDatabase) -> Option<TypeParam> {
- let params = db.generic_params(self.id.parent);
+ let params = GenericParams::of(db, self.id.parent);
match &params[self.id.local_id] {
TypeOrConstParamData::TypeParamData(_) => {
Some(TypeParam { id: TypeParamId::from_unchecked(self.id) })
@@ -4714,7 +4829,7 @@ impl TypeOrConstParam {
}
pub fn as_const_param(self, db: &dyn HirDatabase) -> Option<ConstParam> {
- let params = db.generic_params(self.id.parent);
+ let params = GenericParams::of(db, self.id.parent);
match &params[self.id.local_id] {
TypeOrConstParamData::TypeParamData(_) => None,
TypeOrConstParamData::ConstParamData(_) => {
@@ -4741,7 +4856,7 @@ impl Impl {
result.extend(module.scope.builtin_derive_impls().map(Impl::from));
for unnamed_const in module.scope.unnamed_consts() {
- for (_, block_def_map) in db.body(unnamed_const.into()).blocks(db) {
+ for (_, block_def_map) in Body::of(db, unnamed_const.into()).blocks(db) {
extend_with_def_map(db, block_def_map, result);
}
}
@@ -4898,14 +5013,14 @@ impl Impl {
pub fn is_negative(self, db: &dyn HirDatabase) -> bool {
match self.id {
- AnyImplId::ImplId(id) => db.impl_signature(id).flags.contains(ImplFlags::NEGATIVE),
+ AnyImplId::ImplId(id) => ImplSignature::of(db, id).flags.contains(ImplFlags::NEGATIVE),
AnyImplId::BuiltinDeriveImplId(_) => false,
}
}
pub fn is_unsafe(self, db: &dyn HirDatabase) -> bool {
match self.id {
- AnyImplId::ImplId(id) => db.impl_signature(id).flags.contains(ImplFlags::UNSAFE),
+ AnyImplId::ImplId(id) => ImplSignature::of(db, id).flags.contains(ImplFlags::UNSAFE),
AnyImplId::BuiltinDeriveImplId(_) => false,
}
}
@@ -5012,7 +5127,7 @@ impl<'db> Closure<'db> {
return Vec::new();
};
let owner = db.lookup_intern_closure(id).0;
- let infer = InferenceResult::for_body(db, owner);
+ let infer = InferenceResult::of(db, owner);
let info = infer.closure_info(id);
info.0
.iter()
@@ -5032,9 +5147,12 @@ impl<'db> Closure<'db> {
return Vec::new();
};
let owner = db.lookup_intern_closure(id).0;
- let infer = InferenceResult::for_body(db, owner);
+ let Some(body_owner) = owner.as_def_with_body() else {
+ return Vec::new();
+ };
+ let infer = InferenceResult::of(db, body_owner);
let (captures, _) = infer.closure_info(id);
- let env = body_param_env_from_has_crate(db, owner);
+ let env = body_param_env_from_has_crate(db, body_owner);
captures.iter().map(|capture| Type { env, ty: capture.ty(db, self.subst) }).collect()
}
@@ -5042,7 +5160,10 @@ impl<'db> Closure<'db> {
match self.id {
AnyClosureId::ClosureId(id) => {
let owner = db.lookup_intern_closure(id).0;
- let infer = InferenceResult::for_body(db, owner);
+ let Some(body_owner) = owner.as_def_with_body() else {
+ return FnTrait::FnOnce;
+ };
+ let infer = InferenceResult::of(db, body_owner);
let info = infer.closure_info(id);
info.1.into()
}
@@ -5125,7 +5246,7 @@ impl FnTrait {
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct ClosureCapture<'db> {
- owner: DefWithBodyId,
+ owner: ExpressionStoreOwnerId,
closure: InternedClosureId,
capture: hir_ty::CapturedItem,
_marker: PhantomCovariantLifetime<'db>,
@@ -5184,17 +5305,16 @@ pub enum CaptureKind {
#[derive(Debug, Clone)]
pub struct CaptureUsages {
- parent: DefWithBodyId,
+ parent: ExpressionStoreOwnerId,
spans: SmallVec<[mir::MirSpan; 3]>,
}
impl CaptureUsages {
pub fn sources(&self, db: &dyn HirDatabase) -> Vec<CaptureUsageSource> {
- let (body, source_map) = db.body_with_source_map(self.parent);
-
+ let (body, source_map) = ExpressionStore::with_source_map(db, self.parent);
let mut result = Vec::with_capacity(self.spans.len());
for &span in self.spans.iter() {
- let is_ref = span.is_ref_span(&body);
+ let is_ref = span.is_ref_span(body);
match span {
mir::MirSpan::ExprId(expr) => {
if let Ok(expr) = source_map.expr_syntax(expr) {
@@ -5362,7 +5482,7 @@ impl<'db> Type<'db> {
fn is_phantom_data(db: &dyn HirDatabase, adt_id: AdtId) -> bool {
match adt_id {
AdtId::StructId(s) => {
- let flags = db.struct_signature(s).flags;
+ let flags = StructSignature::of(db, s).flags;
flags.contains(StructFlags::IS_PHANTOM_DATA)
}
AdtId::UnionId(_) | AdtId::EnumId(_) => false,
@@ -5956,8 +6076,8 @@ impl<'db> Type<'db> {
// for a nicer IDE experience. However, method resolution is always done on real code (either
// existing code or code to be inserted), and there using PostAnalysis is dangerous - we may
// suggest invalid methods. So we're using the TypingMode of the body we're in.
- let typing_mode = if let Some(body_owner) = resolver.body_owner() {
- TypingMode::analysis_in_body(interner, body_owner.into())
+ let typing_mode = if let Some(store_owner) = resolver.expression_store_owner() {
+ TypingMode::analysis_in_body(interner, store_owner.into())
} else {
TypingMode::non_body_analysis()
};
@@ -6362,18 +6482,19 @@ impl<'db> TypeNs<'db> {
#[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)]
pub struct InlineAsmOperand {
- owner: DefWithBodyId,
+ owner: ExpressionStoreOwnerId,
expr: ExprId,
index: usize,
}
impl InlineAsmOperand {
- pub fn parent(self, _db: &dyn HirDatabase) -> DefWithBody {
+ pub fn parent(self, _db: &dyn HirDatabase) -> ExpressionStoreOwner {
self.owner.into()
}
pub fn name(&self, db: &dyn HirDatabase) -> Option<Name> {
- match &db.body(self.owner)[self.expr] {
+ let body = ExpressionStore::of(db, self.owner);
+ match &body[self.expr] {
hir_def::hir::Expr::InlineAsm(e) => e.operands.get(self.index)?.0.clone(),
_ => None,
}
@@ -6403,7 +6524,7 @@ enum Callee<'db> {
pub enum CallableKind<'db> {
Function(Function),
TupleStruct(Struct),
- TupleEnumVariant(Variant),
+ TupleEnumVariant(EnumVariant),
Closure(Closure<'db>),
FnPtr,
FnImpl(FnTrait),
@@ -6753,7 +6874,7 @@ impl HasCrate for Field {
}
}
-impl HasCrate for Variant {
+impl HasCrate for EnumVariant {
fn krate(&self, db: &dyn HirDatabase) -> Crate {
self.module(db).krate(db)
}
@@ -6922,9 +7043,9 @@ impl_has_name!(
Struct,
Union,
Enum,
- Variant,
+ EnumVariant,
Adt,
- VariantDef,
+ Variant,
DefWithBody,
Function,
ExternCrateDecl,
@@ -7113,7 +7234,7 @@ fn generic_args_from_tys<'db>(
}
fn has_non_default_type_params(db: &dyn HirDatabase, generic_def: GenericDefId) -> bool {
- let params = db.generic_params(generic_def);
+ let params = GenericParams::of(db, generic_def);
let defaults = db.generic_defaults(generic_def);
params
.iter_type_or_consts()
@@ -7134,7 +7255,7 @@ fn param_env_from_resolver<'db>(
ParamEnvAndCrate {
param_env: resolver
.generic_def()
- .map_or_else(ParamEnv::empty, |generic_def| db.trait_environment(generic_def)),
+ .map_or_else(ParamEnv::empty, |generic_def| db.trait_environment(generic_def.into())),
krate: resolver.krate(),
}
}
@@ -7143,14 +7264,14 @@ fn param_env_from_has_crate<'db>(
db: &'db dyn HirDatabase,
id: impl hir_def::HasModule + Into<GenericDefId> + Copy,
) -> ParamEnvAndCrate<'db> {
- ParamEnvAndCrate { param_env: db.trait_environment(id.into()), krate: id.krate(db) }
+ ParamEnvAndCrate { param_env: db.trait_environment(id.into().into()), krate: id.krate(db) }
}
fn body_param_env_from_has_crate<'db>(
db: &'db dyn HirDatabase,
- id: impl hir_def::HasModule + Into<DefWithBodyId> + Copy,
+ id: impl hir_def::HasModule + Into<ExpressionStoreOwnerId> + Copy,
) -> ParamEnvAndCrate<'db> {
- ParamEnvAndCrate { param_env: db.trait_environment_for_body(id.into()), krate: id.krate(db) }
+ ParamEnvAndCrate { param_env: db.trait_environment(id.into()), krate: id.krate(db) }
}
fn empty_param_env<'db>(krate: base_db::Crate) -> ParamEnvAndCrate<'db> {
diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs
index c816fe967c..4e9e3c44be 100644
--- a/crates/hir/src/semantics.rs
+++ b/crates/hir/src/semantics.rs
@@ -13,9 +13,10 @@ use std::{
use base_db::FxIndexSet;
use either::Either;
use hir_def::{
- BuiltinDeriveImplId, DefWithBodyId, HasModule, MacroId, StructId, TraitId, VariantId,
+ BuiltinDeriveImplId, DefWithBodyId, ExpressionStoreOwnerId, HasModule, MacroId, StructId,
+ TraitId, VariantId,
attrs::parse_extra_crate_attrs,
- expr_store::{Body, ExprOrPatSource, HygieneId, path::Path},
+ expr_store::{Body, ExprOrPatSource, ExpressionStore, HygieneId, path::Path},
hir::{BindingId, Expr, ExprId, ExprOrPatId, Pat},
nameres::{ModuleOrigin, crate_def_map},
resolver::{self, HasResolver, Resolver, TypeNs, ValueNs},
@@ -31,7 +32,7 @@ use hir_expand::{
};
use hir_ty::{
InferenceResult,
- diagnostics::{unsafe_operations, unsafe_operations_for_body},
+ diagnostics::unsafe_operations,
infer_query_with_inspect,
next_solver::{
AnyImplId, DbInterner, Span,
@@ -54,10 +55,10 @@ use syntax::{
use crate::{
Adjust, Adjustment, Adt, AnyFunctionId, AutoBorrow, BindingMode, BuiltinAttr, Callable, Const,
- ConstParam, Crate, DefWithBody, DeriveHelper, Enum, Field, Function, GenericSubstitution,
- HasSource, Impl, InFile, InlineAsmOperand, ItemInNs, Label, LifetimeParam, Local, Macro,
- Module, ModuleDef, Name, OverloadedDeref, ScopeDef, Static, Struct, ToolModule, Trait,
- TupleField, Type, TypeAlias, TypeParam, Union, Variant, VariantDef,
+ ConstParam, Crate, DeriveHelper, Enum, EnumVariant, ExpressionStoreOwner, Field, Function,
+ GenericSubstitution, HasSource, Impl, InFile, InlineAsmOperand, ItemInNs, Label, LifetimeParam,
+ Local, Macro, Module, ModuleDef, Name, OverloadedDeref, ScopeDef, Static, Struct, ToolModule,
+ Trait, TupleField, Type, TypeAlias, TypeParam, Union, Variant,
db::HirDatabase,
semantics::source_to_def::{ChildContainer, SourceToDefCache, SourceToDefCtx},
source_analyzer::{SourceAnalyzer, resolve_hir_path},
@@ -90,7 +91,7 @@ impl PathResolution {
}
PathResolution::Def(
ModuleDef::Const(_)
- | ModuleDef::Variant(_)
+ | ModuleDef::EnumVariant(_)
| ModuleDef::Macro(_)
| ModuleDef::Function(_)
| ModuleDef::Module(_)
@@ -367,8 +368,8 @@ impl<DB: HirDatabase + ?Sized> Semantics<'_, DB> {
self.imp.resolve_try_expr(try_expr)
}
- pub fn resolve_variant(&self, record_lit: ast::RecordExpr) -> Option<VariantDef> {
- self.imp.resolve_variant(record_lit).map(VariantDef::from)
+ pub fn resolve_variant(&self, record_lit: ast::RecordExpr) -> Option<Variant> {
+ self.imp.resolve_variant(record_lit).map(Variant::from)
}
pub fn file_to_module_def(&self, file: impl Into<FileId>) -> Option<Module> {
@@ -409,7 +410,7 @@ impl<DB: HirDatabase + ?Sized> Semantics<'_, DB> {
self.imp.to_def(e)
}
- pub fn to_enum_variant_def(&self, v: &ast::Variant) -> Option<Variant> {
+ pub fn to_enum_variant_def(&self, v: &ast::Variant) -> Option<EnumVariant> {
self.imp.to_def(v)
}
@@ -785,16 +786,21 @@ impl<'db> SemanticsImpl<'db> {
/// Checks if renaming `renamed` to `new_name` may introduce conflicts with other locals,
/// and returns the conflicting locals.
pub fn rename_conflicts(&self, to_be_renamed: &Local, new_name: &Name) -> Vec<Local> {
- let body = self.db.body(to_be_renamed.parent);
+ // FIXME: signatures
+ let Some(def) = to_be_renamed.parent.as_def_with_body() else {
+ return Vec::new();
+ };
+ let body = Body::of(self.db, def);
let resolver = to_be_renamed.parent.resolver(self.db);
- let starting_expr = body.binding_owner(to_be_renamed.binding_id).unwrap_or(body.body_expr);
+ let starting_expr =
+ body.binding_owner(to_be_renamed.binding_id).unwrap_or(body.root_expr());
let mut visitor = RenameConflictsVisitor {
- body: &body,
+ body,
conflicts: FxHashSet::default(),
db: self.db,
new_name: new_name.symbol().clone(),
old_name: to_be_renamed.name(self.db).symbol().clone(),
- owner: to_be_renamed.parent,
+ owner: def,
to_be_renamed: to_be_renamed.binding_id,
resolver,
};
@@ -1913,36 +1919,32 @@ impl<'db> SemanticsImpl<'db> {
self.db.parse_macro_expansion(file_id).value.1.matched_arm
}
- pub fn get_unsafe_ops(&self, def: DefWithBody) -> FxHashSet<ExprOrPatSource> {
- let Ok(def) = DefWithBodyId::try_from(def) else {
- return FxHashSet::default();
- };
- let (body, source_map) = self.db.body_with_source_map(def);
- let infer = InferenceResult::for_body(self.db, def);
+ pub fn get_unsafe_ops(&self, def: ExpressionStoreOwner) -> FxHashSet<ExprOrPatSource> {
+ let Ok(def) = ExpressionStoreOwnerId::try_from(def) else { return Default::default() };
+ let (body, source_map) = ExpressionStore::with_source_map(self.db, def);
+ let infer = InferenceResult::of(self.db, def);
let mut res = FxHashSet::default();
- unsafe_operations_for_body(self.db, infer, def, &body, &mut |node| {
- if let Ok(node) = source_map.expr_or_pat_syntax(node) {
- res.insert(node);
- }
- });
+ for root in body.expr_roots() {
+ unsafe_operations(self.db, infer, def, body, root, &mut |node, _| {
+ if let Ok(node) = source_map.expr_or_pat_syntax(node) {
+ res.insert(node);
+ }
+ });
+ }
res
}
pub fn get_unsafe_ops_for_unsafe_block(&self, block: ast::BlockExpr) -> Vec<ExprOrPatSource> {
always!(block.unsafe_token().is_some());
+ let Some(sa) = self.analyze(block.syntax()) else { return vec![] };
+ let Some((def, store, sm, Some(infer))) = sa.def() else { return vec![] };
let block = self.wrap_node_infile(ast::Expr::from(block));
- let Some(def) = self.body_for(block.syntax()) else { return Vec::new() };
- let Ok(def) = def.try_into() else {
- return Vec::new();
- };
- let (body, source_map) = self.db.body_with_source_map(def);
- let infer = InferenceResult::for_body(self.db, def);
- let Some(ExprOrPatId::ExprId(block)) = source_map.node_expr(block.as_ref()) else {
+ let Some(ExprOrPatId::ExprId(block)) = sm.node_expr(block.as_ref()) else {
return Vec::new();
};
let mut res = Vec::default();
- unsafe_operations(self.db, infer, def, &body, block, &mut |node, _| {
- if let Ok(node) = source_map.expr_or_pat_syntax(node) {
+ unsafe_operations(self.db, infer, def, store, block, &mut |node, _| {
+ if let Ok(node) = sm.expr_or_pat_syntax(node) {
res.push(node);
}
});
@@ -1994,7 +1996,7 @@ impl<'db> SemanticsImpl<'db> {
pub fn resolve_offset_of_field(
&self,
name_ref: &ast::NameRef,
- ) -> Option<(Either<Variant, Field>, GenericSubstitution<'db>)> {
+ ) -> Option<(Either<EnumVariant, Field>, GenericSubstitution<'db>)> {
self.analyze_no_infer(name_ref.syntax())?.resolve_offset_of_field(self.db, name_ref)
}
@@ -2114,13 +2116,9 @@ impl<'db> SemanticsImpl<'db> {
Some(res)
}
- pub fn body_for(&self, node: InFile<&SyntaxNode>) -> Option<DefWithBody> {
+ pub fn store_owner_for(&self, node: InFile<&SyntaxNode>) -> Option<ExpressionStoreOwner> {
let container = self.with_ctx(|ctx| ctx.find_container(node))?;
-
- match container {
- ChildContainer::DefWithBodyId(def) => Some(def.into()),
- _ => None,
- }
+ container.as_expression_store_owner().map(|id| id.into())
}
/// Returns none if the file of the node is not part of a crate.
@@ -2149,7 +2147,7 @@ impl<'db> SemanticsImpl<'db> {
node: InFile<&SyntaxNode>,
offset: Option<TextSize>,
// replace this, just make the inference result a `LazyCell`
- infer_body: bool,
+ infer: bool,
) -> Option<SourceAnalyzer<'db>> {
let _p = tracing::info_span!("SemanticsImpl::analyze_impl").entered();
@@ -2157,26 +2155,42 @@ impl<'db> SemanticsImpl<'db> {
let resolver = match container {
ChildContainer::DefWithBodyId(def) => {
- return Some(if infer_body {
+ return Some(if infer {
SourceAnalyzer::new_for_body(self.db, def, node, offset)
} else {
SourceAnalyzer::new_for_body_no_infer(self.db, def, node, offset)
});
}
ChildContainer::VariantId(def) => {
- return Some(SourceAnalyzer::new_variant_body(self.db, def, node, offset));
+ return Some(SourceAnalyzer::new_variant_body(self.db, def, node, offset, infer));
}
ChildContainer::TraitId(it) => {
- return Some(SourceAnalyzer::new_generic_def(self.db, it.into(), node, offset));
+ return Some(if infer {
+ SourceAnalyzer::new_generic_def(self.db, it.into(), node, offset)
+ } else {
+ SourceAnalyzer::new_generic_def_no_infer(self.db, it.into(), node, offset)
+ });
}
ChildContainer::ImplId(it) => {
- return Some(SourceAnalyzer::new_generic_def(self.db, it.into(), node, offset));
+ return Some(if infer {
+ SourceAnalyzer::new_generic_def(self.db, it.into(), node, offset)
+ } else {
+ SourceAnalyzer::new_generic_def_no_infer(self.db, it.into(), node, offset)
+ });
}
ChildContainer::EnumId(it) => {
- return Some(SourceAnalyzer::new_generic_def(self.db, it.into(), node, offset));
+ return Some(if infer {
+ SourceAnalyzer::new_generic_def(self.db, it.into(), node, offset)
+ } else {
+ SourceAnalyzer::new_generic_def_no_infer(self.db, it.into(), node, offset)
+ });
}
ChildContainer::GenericDefId(it) => {
- return Some(SourceAnalyzer::new_generic_def(self.db, it, node, offset));
+ return Some(if infer {
+ SourceAnalyzer::new_generic_def(self.db, it, node, offset)
+ } else {
+ SourceAnalyzer::new_generic_def_no_infer(self.db, it, node, offset)
+ });
}
ChildContainer::ModuleId(it) => it.resolver(self.db),
};
@@ -2259,7 +2273,7 @@ impl<'db> SemanticsImpl<'db> {
let Some(def) = def else { return false };
let enclosing_node = enclosing_item.as_ref().either(|i| i.syntax(), |v| v.syntax());
- let (body, source_map) = self.db.body_with_source_map(def);
+ let (body, source_map) = Body::with_source_map(self.db, def);
let file_id = self.find_file(expr.syntax()).file_id;
@@ -2310,7 +2324,7 @@ impl<'db> SemanticsImpl<'db> {
let sa = self.analyze(element.either(|e| e.syntax(), |s| s.syntax()))?;
let store = sa.store()?;
let mut resolver = sa.resolver.clone();
- let def = resolver.body_owner()?;
+ let def = resolver.expression_store_owner()?;
let is_not_generated = |path: &Path| {
!path.mod_path().and_then(|path| path.as_ident()).is_some_and(Name::is_generated)
@@ -2501,7 +2515,7 @@ to_def_impls![
(crate::Function, ast::Fn, fn_to_def),
(crate::Field, ast::RecordField, record_field_to_def),
(crate::Field, ast::TupleField, tuple_field_to_def),
- (crate::Variant, ast::Variant, enum_variant_to_def),
+ (crate::EnumVariant, ast::Variant, enum_variant_to_def),
(crate::TypeParam, ast::TypeParam, type_param_to_def),
(crate::LifetimeParam, ast::LifetimeParam, lifetime_param_to_def),
(crate::ConstParam, ast::ConstParam, const_param_to_def),
@@ -2560,13 +2574,18 @@ impl<'db> SemanticsScope<'db> {
Crate { id: self.resolver.krate() }
}
+ // FIXME: This is a weird function, we shouldn't have this?
pub fn containing_function(&self) -> Option<Function> {
- self.resolver.body_owner().and_then(|owner| match owner {
- DefWithBodyId::FunctionId(id) => Some(id.into()),
+ self.resolver.expression_store_owner().and_then(|owner| match owner {
+ ExpressionStoreOwnerId::Body(DefWithBodyId::FunctionId(id)) => Some(id.into()),
_ => None,
})
}
+ pub fn expression_store_owner(&self) -> Option<ExpressionStoreOwner> {
+ self.resolver.expression_store_owner().map(Into::into)
+ }
+
pub(crate) fn resolver(&self) -> &Resolver<'db> {
&self.resolver
}
@@ -2588,14 +2607,18 @@ impl<'db> SemanticsScope<'db> {
resolver::ScopeDef::ImplSelfType(it) => ScopeDef::ImplSelfType(it.into()),
resolver::ScopeDef::AdtSelfType(it) => ScopeDef::AdtSelfType(it.into()),
resolver::ScopeDef::GenericParam(id) => ScopeDef::GenericParam(id.into()),
- resolver::ScopeDef::Local(binding_id) => match self.resolver.body_owner() {
- Some(parent) => ScopeDef::Local(Local { parent, binding_id }),
- None => continue,
- },
- resolver::ScopeDef::Label(label_id) => match self.resolver.body_owner() {
- Some(parent) => ScopeDef::Label(Label { parent, label_id }),
- None => continue,
- },
+ resolver::ScopeDef::Local(binding_id) => {
+ match self.resolver.expression_store_owner() {
+ Some(parent) => ScopeDef::Local(Local { parent, binding_id }),
+ None => continue,
+ }
+ }
+ resolver::ScopeDef::Label(label_id) => {
+ match self.resolver.expression_store_owner() {
+ Some(parent) => ScopeDef::Label(Label { parent, label_id }),
+ None => continue,
+ }
+ }
};
f(name.clone(), def)
}
diff --git a/crates/hir/src/semantics/child_by_source.rs b/crates/hir/src/semantics/child_by_source.rs
index 143cc14c33..f6d1bec575 100644
--- a/crates/hir/src/semantics/child_by_source.rs
+++ b/crates/hir/src/semantics/child_by_source.rs
@@ -18,8 +18,10 @@ use hir_def::{
DynMap,
keys::{self, Key},
},
+ expr_store::Body,
hir::generics::GenericParams,
item_scope::ItemScope,
+ signatures::{EnumSignature, ImplSignature, TraitSignature},
src::{HasChildSource, HasSource},
};
@@ -49,7 +51,7 @@ impl ChildBySource for TraitId {
data.items.iter().for_each(|&(_, item)| {
add_assoc_item(db, res, file_id, item);
});
- let (_, source_map) = db.trait_signature_with_source_map(*self);
+ let (_, source_map) = TraitSignature::with_source_map(db, *self);
source_map.expansions().filter(|(ast, _)| ast.file_id == file_id).for_each(
|(ast, &exp_id)| {
res[keys::MACRO_CALL].insert(ast.value, exp_id);
@@ -74,7 +76,7 @@ impl ChildBySource for ImplId {
data.items.iter().for_each(|&(_, item)| {
add_assoc_item(db, res, file_id, item);
});
- let (_, source_map) = db.impl_signature_with_source_map(*self);
+ let (_, source_map) = ImplSignature::with_source_map(db, *self);
source_map.expansions().filter(|(ast, _)| ast.file_id == file_id).for_each(
|(ast, &exp_id)| {
res[keys::MACRO_CALL].insert(ast.value, exp_id);
@@ -204,7 +206,7 @@ impl ChildBySource for EnumId {
self.enum_variants(db).variants.iter().for_each(|&(variant, _, _)| {
res[keys::ENUM_VARIANT].insert(ast_id_map.get(variant.lookup(db).id.value), variant);
});
- let (_, source_map) = db.enum_signature_with_source_map(*self);
+ let (_, source_map) = EnumSignature::with_source_map(db, *self);
source_map
.expansions()
.filter(|(ast, _)| ast.file_id == file_id)
@@ -214,7 +216,7 @@ impl ChildBySource for EnumId {
impl ChildBySource for DefWithBodyId {
fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap, file_id: HirFileId) {
- let (body, sm) = db.body_with_source_map(*self);
+ let (body, sm) = Body::with_source_map(db, *self);
if let &DefWithBodyId::VariantId(v) = self {
VariantId::EnumVariantId(v).child_by_source_to(db, res, file_id)
}
@@ -239,8 +241,7 @@ impl ChildBySource for GenericDefId {
return;
}
- let (generic_params, _, source_map) =
- GenericParams::generic_params_and_store_and_source_map(db, *self);
+ let (generic_params, _, source_map) = GenericParams::with_source_map(db, *self);
let mut toc_idx_iter = generic_params.iter_type_or_consts().map(|(idx, _)| idx);
let lts_idx_iter = generic_params.iter_lt().map(|(idx, _)| idx);
diff --git a/crates/hir/src/semantics/source_to_def.rs b/crates/hir/src/semantics/source_to_def.rs
index d222c3dc7e..a9a779a287 100644
--- a/crates/hir/src/semantics/source_to_def.rs
+++ b/crates/hir/src/semantics/source_to_def.rs
@@ -88,13 +88,14 @@
use either::Either;
use hir_def::{
AdtId, BlockId, BuiltinDeriveImplId, ConstId, ConstParamId, DefWithBodyId, EnumId,
- EnumVariantId, ExternBlockId, ExternCrateId, FieldId, FunctionId, GenericDefId, GenericParamId,
- ImplId, LifetimeParamId, Lookup, MacroId, ModuleId, StaticId, StructId, TraitId, TypeAliasId,
- TypeParamId, UnionId, UseId, VariantId,
+ EnumVariantId, ExpressionStoreOwnerId, ExternBlockId, ExternCrateId, FieldId, FunctionId,
+ GenericDefId, GenericParamId, ImplId, LifetimeParamId, Lookup, MacroId, ModuleId, StaticId,
+ StructId, TraitId, TypeAliasId, TypeParamId, UnionId, UseId, VariantId,
dyn_map::{
DynMap,
keys::{self, Key},
},
+ expr_store::{Body, ExpressionStore},
hir::{BindingId, Expr, LabelId},
nameres::{block_def_map, crate_def_map},
};
@@ -334,8 +335,8 @@ impl SourceToDefCtx<'_, '_> {
_ => None,
})
.position(|it| it == *src.value)?;
- let container = self.find_pat_or_label_container(src.syntax_ref())?;
- let source_map = self.db.body_with_source_map(container).1;
+ let container = self.find_container(src.syntax_ref())?.as_expression_store_owner()?;
+ let (_, source_map) = ExpressionStore::with_source_map(self.db, container);
let expr = source_map.node_expr(src.with_value(&ast::Expr::AsmExpr(asm)))?.as_expr()?;
Some(InlineAsmOperand { owner: container, expr, index })
}
@@ -343,13 +344,13 @@ impl SourceToDefCtx<'_, '_> {
pub(super) fn bind_pat_to_def(
&mut self,
src: InFile<&ast::IdentPat>,
- ) -> Option<(DefWithBodyId, BindingId)> {
- let container = self.find_pat_or_label_container(src.syntax_ref())?;
- let (body, source_map) = self.db.body_with_source_map(container);
+ ) -> Option<(ExpressionStoreOwnerId, BindingId)> {
+ let container = self.find_container(src.syntax_ref())?.as_expression_store_owner()?;
+ let (store, source_map) = ExpressionStore::with_source_map(self.db, container);
let src = src.cloned().map(ast::Pat::from);
let pat_id = source_map.node_pat(src.as_ref())?;
// the pattern could resolve to a constant, verify that this is not the case
- if let crate::Pat::Bind { id, .. } = body[pat_id.as_pat()?] {
+ if let crate::Pat::Bind { id, .. } = store[pat_id.as_pat()?] {
Some((container, id))
} else {
None
@@ -359,17 +360,19 @@ impl SourceToDefCtx<'_, '_> {
&mut self,
src: InFile<&ast::SelfParam>,
) -> Option<(DefWithBodyId, BindingId)> {
- let container = self.find_pat_or_label_container(src.syntax_ref())?;
- let body = self.db.body(container);
+ let container = self
+ .find_container(src.syntax_ref())?
+ .as_expression_store_owner()?
+ .as_def_with_body()?;
+ let body = Body::of(self.db, container);
Some((container, body.self_param?))
}
pub(super) fn label_to_def(
&mut self,
src: InFile<&ast::Label>,
- ) -> Option<(DefWithBodyId, LabelId)> {
- let container = self.find_pat_or_label_container(src.syntax_ref())?;
- let source_map = self.db.body_with_source_map(container).1;
-
+ ) -> Option<(ExpressionStoreOwnerId, LabelId)> {
+ let container = self.find_container(src.syntax_ref())?.as_expression_store_owner()?;
+ let (_, source_map) = ExpressionStore::with_source_map(self.db, container);
let label_id = source_map.node_label(src)?;
Some((container, label_id))
}
@@ -377,13 +380,14 @@ impl SourceToDefCtx<'_, '_> {
pub(super) fn label_ref_to_def(
&mut self,
src: InFile<&ast::Lifetime>,
- ) -> Option<(DefWithBodyId, LabelId)> {
+ ) -> Option<(ExpressionStoreOwnerId, LabelId)> {
let break_or_continue = ast::Expr::cast(src.value.syntax().parent()?)?;
- let container = self.find_pat_or_label_container(src.syntax_ref())?;
- let (body, source_map) = self.db.body_with_source_map(container);
+ let container = self.find_container(src.syntax_ref())?.as_expression_store_owner()?;
+ let (store, source_map) = ExpressionStore::with_source_map(self.db, container);
let break_or_continue =
source_map.node_expr(src.with_value(&break_or_continue))?.as_expr()?;
- let (Expr::Break { label, .. } | Expr::Continue { label }) = body[break_or_continue] else {
+ let (Expr::Break { label, .. } | Expr::Continue { label }) = store[break_or_continue]
+ else {
return None;
};
Some((container, label?))
@@ -557,29 +561,6 @@ impl SourceToDefCtx<'_, '_> {
})
}
- // FIXME: Remove this when we do inference in signatures
- fn find_pat_or_label_container(&mut self, src: InFile<&SyntaxNode>) -> Option<DefWithBodyId> {
- self.parent_ancestors_with_macros(src, |this, InFile { file_id, value }, _| {
- let item = match ast::Item::cast(value.clone()) {
- Some(it) => it,
- None => {
- let variant = ast::Variant::cast(value)?;
- return this
- .enum_variant_to_def(InFile::new(file_id, &variant))
- .map(Into::into);
- }
- };
- match &item {
- ast::Item::Fn(it) => this.fn_to_def(InFile::new(file_id, it)).map(Into::into),
- ast::Item::Const(it) => this.const_to_def(InFile::new(file_id, it)).map(Into::into),
- ast::Item::Static(it) => {
- this.static_to_def(InFile::new(file_id, it)).map(Into::into)
- }
- _ => None,
- }
- })
- }
-
/// Skips the attributed item that caused the macro invocation we are climbing up
fn parent_ancestors_with_macros<T>(
&mut self,
@@ -756,4 +737,22 @@ impl ChildContainer {
ChildContainer::GenericDefId(it) => it.child_by_source(db, file_id),
}
}
+
+ pub(crate) fn as_expression_store_owner(self) -> Option<ExpressionStoreOwnerId> {
+ match self {
+ ChildContainer::DefWithBodyId(it) => Some(it.into()),
+ ChildContainer::ModuleId(_) => None,
+ ChildContainer::TraitId(it) => {
+ Some(ExpressionStoreOwnerId::Signature(GenericDefId::TraitId(it)))
+ }
+ ChildContainer::EnumId(it) => {
+ Some(ExpressionStoreOwnerId::Signature(GenericDefId::AdtId(it.into())))
+ }
+ ChildContainer::ImplId(it) => {
+ Some(ExpressionStoreOwnerId::Signature(GenericDefId::ImplId(it)))
+ }
+ ChildContainer::VariantId(_) => None,
+ ChildContainer::GenericDefId(it) => Some(it.into()),
+ }
+ }
}
diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs
index c6f2d151f5..1a34fa9134 100644
--- a/crates/hir/src/source_analyzer.rs
+++ b/crates/hir/src/source_analyzer.rs
@@ -9,18 +9,18 @@ use std::iter::{self, once};
use either::Either;
use hir_def::{
- AdtId, AssocItemId, CallableDefId, ConstId, DefWithBodyId, FieldId, FunctionId, GenericDefId,
- LocalFieldId, ModuleDefId, StructId, TraitId, VariantId,
+ AdtId, AssocItemId, CallableDefId, ConstId, DefWithBodyId, ExpressionStoreOwnerId, FieldId,
+ FunctionId, GenericDefId, LocalFieldId, ModuleDefId, StructId, TraitId, VariantId,
expr_store::{
Body, BodySourceMap, ExpressionStore, ExpressionStoreSourceMap, HygieneId,
lower::ExprCollector,
path::Path,
scope::{ExprScopes, ScopeId},
},
- hir::{BindingId, Expr, ExprId, ExprOrPatId, Pat, PatId},
+ hir::{BindingId, Expr, ExprId, ExprOrPatId, Pat, PatId, generics::GenericParams},
lang_item::LangItems,
nameres::MacroSubNs,
- resolver::{HasResolver, Resolver, TypeNs, ValueNs, resolver_for_scope},
+ resolver::{Resolver, TypeNs, ValueNs, resolver_for_scope},
type_ref::{Mutability, TypeRef, TypeRefId},
};
use hir_expand::{
@@ -55,12 +55,11 @@ use syntax::{
SyntaxKind, SyntaxNode, TextRange, TextSize,
ast::{self, AstNode, RangeItem, RangeOp},
};
-use triomphe::Arc;
use crate::{
Adt, AnyFunctionId, AssocItem, BindingMode, BuiltinAttr, BuiltinType, Callable, Const,
- DeriveHelper, Field, Function, GenericSubstitution, Local, Macro, ModuleDef, Static, Struct,
- ToolModule, Trait, TupleField, Type, TypeAlias, Variant,
+ DeriveHelper, EnumVariant, Field, Function, GenericSubstitution, Local, Macro, ModuleDef,
+ Static, Struct, ToolModule, Trait, TupleField, Type, TypeAlias,
db::HirDatabase,
semantics::{PathResolution, PathResolutionPerNs},
};
@@ -78,21 +77,23 @@ pub(crate) struct SourceAnalyzer<'db> {
pub(crate) enum BodyOrSig<'db> {
Body {
def: DefWithBodyId,
- body: Arc<Body>,
- source_map: Arc<BodySourceMap>,
+ body: &'db Body,
+ source_map: &'db BodySourceMap,
infer: Option<&'db InferenceResult>,
},
- // To be folded into body once it is considered one
VariantFields {
def: VariantId,
- store: Arc<ExpressionStore>,
- source_map: Arc<ExpressionStoreSourceMap>,
+ store: &'db ExpressionStore,
+ source_map: &'db ExpressionStoreSourceMap,
+ infer: Option<&'db InferenceResult>,
},
Sig {
def: GenericDefId,
- store: Arc<ExpressionStore>,
- source_map: Arc<ExpressionStoreSourceMap>,
- // infer: Option<Arc<InferenceResult>>,
+ store: &'db ExpressionStore,
+ source_map: &'db ExpressionStoreSourceMap,
+ infer: Option<&'db InferenceResult>,
+ #[expect(dead_code)]
+ generics: &'db GenericParams,
},
}
@@ -103,7 +104,7 @@ impl<'db> SourceAnalyzer<'db> {
node: InFile<&SyntaxNode>,
offset: Option<TextSize>,
) -> SourceAnalyzer<'db> {
- Self::new_for_body_(db, def, node, offset, Some(InferenceResult::for_body(db, def)))
+ Self::new_for_body_(db, def, node, offset, Some(InferenceResult::of(db, def)))
}
pub(crate) fn new_for_body_no_infer(
@@ -122,10 +123,10 @@ impl<'db> SourceAnalyzer<'db> {
offset: Option<TextSize>,
infer: Option<&'db InferenceResult>,
) -> SourceAnalyzer<'db> {
- let (body, source_map) = db.body_with_source_map(def);
- let scopes = db.expr_scopes(def);
+ let (body, source_map) = Body::with_source_map(db, def);
+ let scopes = ExprScopes::of(db, def);
let scope = match offset {
- None => scope_for(db, &scopes, &source_map, node),
+ None => scope_for(db, scopes, source_map, node),
Some(offset) => {
debug_assert!(
node.text_range().contains_inclusive(offset),
@@ -133,7 +134,7 @@ impl<'db> SourceAnalyzer<'db> {
offset,
node.text_range()
);
- scope_for_offset(db, &scopes, &source_map, node.file_id, offset)
+ scope_for_offset(db, scopes, source_map, node.file_id, offset)
}
};
let resolver = resolver_for_scope(db, def, scope);
@@ -147,14 +148,47 @@ impl<'db> SourceAnalyzer<'db> {
pub(crate) fn new_generic_def(
db: &'db dyn HirDatabase,
def: GenericDefId,
- InFile { file_id, .. }: InFile<&SyntaxNode>,
- _offset: Option<TextSize>,
+ node: InFile<&SyntaxNode>,
+ offset: Option<TextSize>,
+ ) -> SourceAnalyzer<'db> {
+ Self::new_generic_def_(db, def, node, offset, true)
+ }
+
+ pub(crate) fn new_generic_def_no_infer(
+ db: &'db dyn HirDatabase,
+ def: GenericDefId,
+ node: InFile<&SyntaxNode>,
+ offset: Option<TextSize>,
) -> SourceAnalyzer<'db> {
- let (_params, store, source_map) = db.generic_params_and_store_and_source_map(def);
- let resolver = def.resolver(db);
+ Self::new_generic_def_(db, def, node, offset, false)
+ }
+
+ pub(crate) fn new_generic_def_(
+ db: &'db dyn HirDatabase,
+ def: GenericDefId,
+ node @ InFile { file_id, .. }: InFile<&SyntaxNode>,
+ offset: Option<TextSize>,
+ infer: bool,
+ ) -> SourceAnalyzer<'db> {
+ let (generics, store, source_map) = GenericParams::with_source_map(db, def);
+ let scopes = ExprScopes::of(db, def);
+ let scope = match offset {
+ None => scope_for(db, scopes, source_map, node),
+ Some(offset) => {
+ debug_assert!(
+ node.text_range().contains_inclusive(offset),
+ "{:?} not in {:?}",
+ offset,
+ node.text_range()
+ );
+ scope_for_offset(db, scopes, source_map, node.file_id, offset)
+ }
+ };
+ let resolver = resolver_for_scope(db, def, scope);
+ let infer = if infer { Some(InferenceResult::of(db, def)) } else { None };
SourceAnalyzer {
resolver,
- body_or_sig: Some(BodyOrSig::Sig { def, store, source_map }),
+ body_or_sig: Some(BodyOrSig::Sig { def, store, source_map, generics, infer }),
file_id,
}
}
@@ -162,17 +196,33 @@ impl<'db> SourceAnalyzer<'db> {
pub(crate) fn new_variant_body(
db: &'db dyn HirDatabase,
def: VariantId,
- InFile { file_id, .. }: InFile<&SyntaxNode>,
- _offset: Option<TextSize>,
+ node @ InFile { file_id, .. }: InFile<&SyntaxNode>,
+ offset: Option<TextSize>,
+ infer: bool,
) -> SourceAnalyzer<'db> {
let (fields, source_map) = def.fields_with_source_map(db);
- let resolver = def.resolver(db);
+ let scopes = ExprScopes::of(db, def);
+ let scope = match offset {
+ None => scope_for(db, scopes, source_map, node),
+ Some(offset) => {
+ debug_assert!(
+ node.text_range().contains_inclusive(offset),
+ "{:?} not in {:?}",
+ offset,
+ node.text_range()
+ );
+ scope_for_offset(db, scopes, source_map, node.file_id, offset)
+ }
+ };
+ let resolver = resolver_for_scope(db, def, scope);
+ let infer = if infer { Some(InferenceResult::of(db, def)) } else { None };
SourceAnalyzer {
resolver,
body_or_sig: Some(BodyOrSig::VariantFields {
def,
- store: fields.store.clone(),
- source_map: source_map.clone(),
+ store: &fields.store,
+ source_map,
+ infer,
}),
file_id,
}
@@ -185,29 +235,40 @@ impl<'db> SourceAnalyzer<'db> {
SourceAnalyzer { resolver, body_or_sig: None, file_id: node.file_id }
}
- // FIXME: Remove this
- fn body_(&self) -> Option<(DefWithBodyId, &Body, &BodySourceMap, Option<&InferenceResult>)> {
- self.body_or_sig.as_ref().and_then(|it| match it {
- BodyOrSig::Body { def, body, source_map, infer } => {
- Some((*def, &**body, &**source_map, infer.as_deref()))
- }
- _ => None,
+ fn owner(&self) -> Option<ExpressionStoreOwnerId> {
+ self.body_or_sig.as_ref().map(|it| match *it {
+ BodyOrSig::VariantFields { def, .. } => def.into(),
+ BodyOrSig::Sig { def, .. } => def.into(),
+ BodyOrSig::Body { def, .. } => def.into(),
})
}
fn infer(&self) -> Option<&InferenceResult> {
self.body_or_sig.as_ref().and_then(|it| match it {
- BodyOrSig::Sig { .. } => None,
- BodyOrSig::VariantFields { .. } => None,
- BodyOrSig::Body { infer, .. } => infer.as_deref(),
+ BodyOrSig::VariantFields { infer, .. }
+ | BodyOrSig::Sig { infer, .. }
+ | BodyOrSig::Body { infer, .. } => infer.as_deref(),
})
}
- fn body(&self) -> Option<&Body> {
- self.body_or_sig.as_ref().and_then(|it| match it {
- BodyOrSig::Sig { .. } => None,
- BodyOrSig::VariantFields { .. } => None,
- BodyOrSig::Body { body, .. } => Some(&**body),
+ pub(crate) fn def(
+ &self,
+ ) -> Option<(
+ ExpressionStoreOwnerId,
+ &ExpressionStore,
+ &ExpressionStoreSourceMap,
+ Option<&InferenceResult>,
+ )> {
+ self.body_or_sig.as_ref().map(|it| match *it {
+ BodyOrSig::VariantFields { def, store, source_map, infer, .. } => {
+ (def.into(), store, source_map, infer)
+ }
+ BodyOrSig::Sig { def, store, source_map, infer, .. } => {
+ (def.into(), store, source_map, infer)
+ }
+ BodyOrSig::Body { def, body, source_map, infer, .. } => {
+ (def.into(), &body.store, &source_map.store, infer)
+ }
})
}
@@ -232,11 +293,13 @@ impl<'db> SourceAnalyzer<'db> {
}
fn trait_environment(&self, db: &'db dyn HirDatabase) -> ParamEnvAndCrate<'db> {
- self.param_and(
- self.body_()
- .map(|(def, ..)| def)
- .map_or_else(ParamEnv::empty, |def| db.trait_environment_for_body(def)),
- )
+ self.param_and(self.body_or_sig.as_ref().map_or_else(ParamEnv::empty, |body_or_sig| {
+ match *body_or_sig {
+ BodyOrSig::Body { def, .. } => db.trait_environment(def.into()),
+ BodyOrSig::VariantFields { def, .. } => db.trait_environment(def.into()),
+ BodyOrSig::Sig { def, .. } => db.trait_environment(def.into()),
+ }
+ }))
}
pub(crate) fn expr_id(&self, expr: ast::Expr) -> Option<ExprOrPatId> {
@@ -371,7 +434,10 @@ impl<'db> SourceAnalyzer<'db> {
db: &'db dyn HirDatabase,
_param: &ast::SelfParam,
) -> Option<Type<'db>> {
- let binding = self.body()?.self_param?;
+ let binding = match self.body_or_sig.as_ref()? {
+ BodyOrSig::Sig { .. } | BodyOrSig::VariantFields { .. } => return None,
+ BodyOrSig::Body { body, .. } => body.self_param?,
+ };
let ty = self.infer()?.binding_ty(binding);
Some(Type::new_with_resolver(db, &self.resolver, ty))
}
@@ -472,7 +538,7 @@ impl<'db> SourceAnalyzer<'db> {
&self,
field: &ast::FieldExpr,
) -> Option<Either<Field, TupleField>> {
- let (def, ..) = self.body_()?;
+ let def = self.owner()?;
let expr_id = self.expr_id(field.clone().into())?.as_expr()?;
self.infer()?.field_resolution(expr_id).map(|it| {
it.map_either(Into::into, |f| TupleField { owner: def, tuple: f.tuple, index: f.index })
@@ -499,7 +565,7 @@ impl<'db> SourceAnalyzer<'db> {
field: &ast::FieldExpr,
) -> Option<(Either<Either<Field, TupleField>, Function>, Option<GenericSubstitution<'db>>)>
{
- let (def, ..) = self.body_()?;
+ let def = self.owner()?;
let expr_id = self.expr_id(field.clone().into())?.as_expr()?;
let inference_result = self.infer()?;
match inference_result.field_resolution(expr_id) {
@@ -771,7 +837,7 @@ impl<'db> SourceAnalyzer<'db> {
name_hygiene(db, InFile::new(self.file_id, ast_name.syntax())),
) {
Some(ValueNs::LocalBinding(binding_id)) => {
- Some(Local { binding_id, parent: self.resolver.body_owner()? })
+ Some(Local { binding_id, parent: self.resolver.expression_store_owner()? })
}
_ => None,
}
@@ -831,8 +897,8 @@ impl<'db> SourceAnalyzer<'db> {
},
};
- let body_owner = self.resolver.body_owner();
- let res = resolve_hir_value_path(db, &self.resolver, body_owner, path, HygieneId::ROOT)?;
+ let store_owner = self.resolver.expression_store_owner();
+ let res = resolve_hir_value_path(db, &self.resolver, store_owner, path, HygieneId::ROOT)?;
match res {
PathResolution::Def(def) => Some(def),
_ => None,
@@ -843,7 +909,7 @@ impl<'db> SourceAnalyzer<'db> {
let name = name.as_name();
self.resolver
.all_generic_params()
- .find_map(|(params, parent)| params.find_type_by_name(&name, *parent))
+ .find_map(|(params, parent)| params.find_type_by_name(&name, parent))
.map(crate::TypeParam::from)
}
@@ -851,7 +917,7 @@ impl<'db> SourceAnalyzer<'db> {
&self,
db: &'db dyn HirDatabase,
name_ref: &ast::NameRef,
- ) -> Option<(Either<crate::Variant, crate::Field>, GenericSubstitution<'db>)> {
+ ) -> Option<(Either<crate::EnumVariant, crate::Field>, GenericSubstitution<'db>)> {
let offset_of_expr = ast::OffsetOfExpr::cast(name_ref.syntax().parent()?)?;
let container = offset_of_expr.ty()?;
let container = self.type_of_type(db, &container)?;
@@ -902,7 +968,7 @@ impl<'db> SourceAnalyzer<'db> {
let variants = id.enum_variants(db);
let variant = variants.variant(&field_name.as_name())?;
container = Either::Left((variant, subst));
- (Either::Left(Variant { id: variant }), id.into(), subst)
+ (Either::Left(EnumVariant { id: variant }), id.into(), subst)
}
},
_ => return None,
@@ -982,7 +1048,10 @@ impl<'db> SourceAnalyzer<'db> {
if let Some(VariantId::EnumVariantId(variant)) =
infer.variant_resolution_for_expr_or_pat(expr_id)
{
- return Some((PathResolution::Def(ModuleDef::Variant(variant.into())), None));
+ return Some((
+ PathResolution::Def(ModuleDef::EnumVariant(variant.into())),
+ None,
+ ));
}
prefer_value_ns = true;
} else if let Some(path_pat) = parent().and_then(ast::PathPat::cast) {
@@ -1014,14 +1083,20 @@ impl<'db> SourceAnalyzer<'db> {
if let Some(VariantId::EnumVariantId(variant)) =
infer.variant_resolution_for_expr_or_pat(expr_or_pat_id)
{
- return Some((PathResolution::Def(ModuleDef::Variant(variant.into())), None));
+ return Some((
+ PathResolution::Def(ModuleDef::EnumVariant(variant.into())),
+ None,
+ ));
}
} else if let Some(rec_lit) = parent().and_then(ast::RecordExpr::cast) {
let expr_id = self.expr_id(rec_lit.into())?;
if let Some(VariantId::EnumVariantId(variant)) =
infer.variant_resolution_for_expr_or_pat(expr_id)
{
- return Some((PathResolution::Def(ModuleDef::Variant(variant.into())), None));
+ return Some((
+ PathResolution::Def(ModuleDef::EnumVariant(variant.into())),
+ None,
+ ));
}
} else {
let record_pat = parent().and_then(ast::RecordPat::cast).map(ast::Pat::from);
@@ -1032,7 +1107,7 @@ impl<'db> SourceAnalyzer<'db> {
let variant_res_for_pat = infer.variant_resolution_for_pat(pat_id.as_pat()?);
if let Some(VariantId::EnumVariantId(variant)) = variant_res_for_pat {
return Some((
- PathResolution::Def(ModuleDef::Variant(variant.into())),
+ PathResolution::Def(ModuleDef::EnumVariant(variant.into())),
None,
));
}
@@ -1045,7 +1120,7 @@ impl<'db> SourceAnalyzer<'db> {
}
// FIXME: collectiong here shouldnt be necessary?
- let mut collector = ExprCollector::new(db, self.resolver.module(), self.file_id);
+ let mut collector = ExprCollector::body(db, self.resolver.module(), self.file_id);
let hir_path =
collector.lower_path(path.clone(), &mut ExprCollector::impl_trait_error_allocator)?;
let parent_hir_path = path
@@ -1253,7 +1328,7 @@ impl<'db> SourceAnalyzer<'db> {
db: &dyn HirDatabase,
path: &ast::Path,
) -> Option<PathResolutionPerNs> {
- let mut collector = ExprCollector::new(db, self.resolver.module(), self.file_id);
+ let mut collector = ExprCollector::body(db, self.resolver.module(), self.file_id);
let hir_path =
collector.lower_path(path.clone(), &mut ExprCollector::impl_trait_error_allocator)?;
let (store, _) = collector.store.finish();
@@ -1366,7 +1441,7 @@ impl<'db> SourceAnalyzer<'db> {
db: &'db dyn HirDatabase,
macro_expr: InFile<&ast::MacroExpr>,
) -> bool {
- if let Some((def, body, sm, Some(infer))) = self.body_()
+ if let Some((def, body, sm, Some(infer))) = self.def()
&& let Some(expanded_expr) = sm.macro_expansion_expr(macro_expr)
{
let mut is_unsafe = false;
@@ -1400,7 +1475,7 @@ impl<'db> SourceAnalyzer<'db> {
resolve_hir_value_path(
db,
&self.resolver,
- self.resolver.body_owner(),
+ self.resolver.expression_store_owner(),
&Path::from_known_path_with_no_generic(ModPath::from_segments(
PathKind::Plain,
Some(name.clone()),
@@ -1416,9 +1491,9 @@ impl<'db> SourceAnalyzer<'db> {
asm: InFile<&ast::AsmExpr>,
line: usize,
offset: TextSize,
- ) -> Option<(DefWithBodyId, (ExprId, TextRange, usize))> {
- let (def, _, body_source_map, _) = self.body_()?;
- let (expr, args) = body_source_map.asm_template_args(asm)?;
+ ) -> Option<(ExpressionStoreOwnerId, (ExprId, TextRange, usize))> {
+ let (def, _, sm, _) = self.def()?;
+ let (expr, args) = sm.asm_template_args(asm)?;
Some(def).zip(
args.get(line)?
.iter()
@@ -1439,7 +1514,7 @@ impl<'db> SourceAnalyzer<'db> {
resolve_hir_value_path(
db,
&self.resolver,
- self.resolver.body_owner(),
+ self.resolver.expression_store_owner(),
&Path::from_known_path_with_no_generic(ModPath::from_segments(
PathKind::Plain,
Some(name.clone()),
@@ -1453,9 +1528,9 @@ impl<'db> SourceAnalyzer<'db> {
pub(crate) fn as_asm_parts(
&self,
asm: InFile<&ast::AsmExpr>,
- ) -> Option<(DefWithBodyId, (ExprId, &[Vec<(TextRange, usize)>]))> {
- let (def, _, body_source_map, _) = self.body_()?;
- Some(def).zip(body_source_map.asm_template_args(asm))
+ ) -> Option<(ExpressionStoreOwnerId, (ExprId, &[Vec<(TextRange, usize)>]))> {
+ let (def, _, sm, _) = self.def()?;
+ Some(def).zip(sm.asm_template_args(asm))
}
fn resolve_impl_method_or_trait_def(
@@ -1473,11 +1548,11 @@ impl<'db> SourceAnalyzer<'db> {
func: FunctionId,
substs: GenericArgs<'db>,
) -> (Function, GenericArgs<'db>) {
- let owner = match self.resolver.body_owner() {
+ let owner = match self.resolver.expression_store_owner() {
Some(it) => it,
None => return (func.into(), substs),
};
- let env = self.param_and(db.trait_environment_for_body(owner));
+ let env = self.param_and(db.trait_environment(owner));
let (func, args) = db.lookup_impl_method(env, func, substs);
match func {
Either::Left(func) => (func.into(), args),
@@ -1493,11 +1568,11 @@ impl<'db> SourceAnalyzer<'db> {
const_id: ConstId,
subs: GenericArgs<'db>,
) -> (ConstId, GenericArgs<'db>) {
- let owner = match self.resolver.body_owner() {
+ let owner = match self.resolver.expression_store_owner() {
Some(it) => it,
None => return (const_id, subs),
};
- let env = self.param_and(db.trait_environment_for_body(owner));
+ let env = self.param_and(db.trait_environment(owner));
let interner = DbInterner::new_with(db, env.krate);
let infcx = interner.infer_ctxt().build(TypingMode::PostAnalysis);
method_resolution::lookup_impl_const(&infcx, env.param_env, const_id, subs)
@@ -1526,7 +1601,7 @@ impl<'db> SourceAnalyzer<'db> {
fn scope_for(
db: &dyn HirDatabase,
scopes: &ExprScopes,
- source_map: &BodySourceMap,
+ source_map: &ExpressionStoreSourceMap,
node: InFile<&SyntaxNode>,
) -> Option<ScopeId> {
node.ancestors_with_macros(db)
@@ -1545,7 +1620,7 @@ fn scope_for(
fn scope_for_offset(
db: &dyn HirDatabase,
scopes: &ExprScopes,
- source_map: &BodySourceMap,
+ source_map: &ExpressionStoreSourceMap,
from_file: HirFileId,
offset: TextSize,
) -> Option<ScopeId> {
@@ -1579,7 +1654,7 @@ fn scope_for_offset(
fn adjust(
db: &dyn HirDatabase,
scopes: &ExprScopes,
- source_map: &BodySourceMap,
+ source_map: &ExpressionStoreSourceMap,
expr_range: TextRange,
from_file: HirFileId,
offset: TextSize,
@@ -1684,7 +1759,7 @@ fn resolve_hir_path_(
TypeNs::AdtSelfType(it) | TypeNs::AdtId(it) => {
PathResolution::Def(Adt::from(it).into())
}
- TypeNs::EnumVariantId(it) => PathResolution::Def(Variant::from(it).into()),
+ TypeNs::EnumVariantId(it) => PathResolution::Def(EnumVariant::from(it).into()),
TypeNs::TypeAliasId(it) => PathResolution::Def(TypeAlias::from(it).into()),
TypeNs::BuiltinType(it) => PathResolution::Def(BuiltinType::from(it).into()),
TypeNs::TraitId(it) => PathResolution::Def(Trait::from(it).into()),
@@ -1708,7 +1783,7 @@ fn resolve_hir_path_(
}
};
- let body_owner = resolver.body_owner();
+ let body_owner = resolver.expression_store_owner();
let values = || resolve_hir_value_path(db, resolver, body_owner, path, hygiene);
let items = || {
@@ -1754,21 +1829,21 @@ fn resolve_hir_path_(
fn resolve_hir_value_path(
db: &dyn HirDatabase,
resolver: &Resolver<'_>,
- body_owner: Option<DefWithBodyId>,
+ store_owner: Option<ExpressionStoreOwnerId>,
path: &Path,
hygiene: HygieneId,
) -> Option<PathResolution> {
resolver.resolve_path_in_value_ns_fully(db, path, hygiene).and_then(|val| {
let res = match val {
ValueNs::LocalBinding(binding_id) => {
- let var = Local { parent: body_owner?, binding_id };
+ let var = Local { parent: store_owner?, binding_id };
PathResolution::Local(var)
}
ValueNs::FunctionId(it) => PathResolution::Def(Function::from(it).into()),
ValueNs::ConstId(it) => PathResolution::Def(Const::from(it).into()),
ValueNs::StaticId(it) => PathResolution::Def(Static::from(it).into()),
ValueNs::StructId(it) => PathResolution::Def(Struct::from(it).into()),
- ValueNs::EnumVariantId(it) => PathResolution::Def(Variant::from(it).into()),
+ ValueNs::EnumVariantId(it) => PathResolution::Def(EnumVariant::from(it).into()),
ValueNs::ImplSelf(impl_id) => PathResolution::SelfType(impl_id.into()),
ValueNs::GenericParam(id) => PathResolution::ConstParam(id.into()),
};
@@ -1833,7 +1908,7 @@ fn resolve_hir_path_qualifier(
TypeNs::AdtSelfType(it) | TypeNs::AdtId(it) => {
PathResolution::Def(Adt::from(it).into())
}
- TypeNs::EnumVariantId(it) => PathResolution::Def(Variant::from(it).into()),
+ TypeNs::EnumVariantId(it) => PathResolution::Def(EnumVariant::from(it).into()),
TypeNs::TypeAliasId(it) => PathResolution::Def(TypeAlias::from(it).into()),
TypeNs::BuiltinType(it) => PathResolution::Def(BuiltinType::from(it).into()),
TypeNs::TraitId(it) => PathResolution::Def(Trait::from(it).into()),
diff --git a/crates/hir/src/symbols.rs b/crates/hir/src/symbols.rs
index c088f3aa0c..ff56544d82 100644
--- a/crates/hir/src/symbols.rs
+++ b/crates/hir/src/symbols.rs
@@ -8,9 +8,11 @@ use hir_def::{
AdtId, AssocItemId, AstIdLoc, Complete, DefWithBodyId, ExternCrateId, HasModule, ImplId,
Lookup, MacroId, ModuleDefId, ModuleId, TraitId,
db::DefDatabase,
+ expr_store::Body,
item_scope::{ImportId, ImportOrExternCrate, ImportOrGlob},
nameres::crate_def_map,
per_ns::Item,
+ signatures::{EnumSignature, ImplSignature, TraitSignature},
src::{HasChildSource, HasSource},
visibility::{Visibility, VisibilityExplicitness},
};
@@ -185,7 +187,7 @@ impl<'a> SymbolCollector<'a> {
}
ModuleDefId::AdtId(AdtId::EnumId(id)) => {
this.push_decl(id, name, false, None);
- let enum_name = Symbol::intern(this.db.enum_signature(id).name.as_str());
+ let enum_name = Symbol::intern(EnumSignature::of(this.db, id).name.as_str());
this.with_container_name(Some(enum_name), |this| {
let variants = id.enum_variants(this.db);
for (variant_id, variant_name, _) in &variants.variants {
@@ -386,7 +388,7 @@ impl<'a> SymbolCollector<'a> {
return;
}
let body_id = body_id.into();
- let body = self.db.body(body_id);
+ let body = Body::of(self.db, body_id);
// Descend into the blocks and enqueue collection of all modules within.
for (_, def_map) in body.blocks(self.db) {
@@ -397,7 +399,7 @@ impl<'a> SymbolCollector<'a> {
}
fn collect_from_impl(&mut self, impl_id: ImplId) {
- let impl_data = self.db.impl_signature(impl_id);
+ let impl_data = ImplSignature::of(self.db, impl_id);
let impl_name = Some(
hir_display_with_store(impl_data.self_ty, &impl_data.store)
.display(
@@ -419,7 +421,7 @@ impl<'a> SymbolCollector<'a> {
}
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 = TraitSignature::of(self.db, trait_id);
self.with_container_name(Some(Symbol::intern(trait_data.name.as_str())), |s| {
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));
diff --git a/crates/hir/src/term_search/expr.rs b/crates/hir/src/term_search/expr.rs
index e56f9e91e3..e3d0121e49 100644
--- a/crates/hir/src/term_search/expr.rs
+++ b/crates/hir/src/term_search/expr.rs
@@ -10,8 +10,8 @@ use itertools::Itertools;
use span::Edition;
use crate::{
- Adt, AsAssocItem, AssocItemContainer, Const, ConstParam, Field, Function, Local, ModuleDef,
- SemanticsScope, Static, Struct, StructKind, Trait, Type, Variant,
+ Adt, AsAssocItem, AssocItemContainer, Const, ConstParam, EnumVariant, Field, Function, Local,
+ ModuleDef, SemanticsScope, Static, Struct, StructKind, Trait, Type,
};
/// Helper function to get path to `ModuleDef`
@@ -80,7 +80,7 @@ pub enum Expr<'db> {
params: Vec<Expr<'db>>,
},
/// Enum variant construction
- Variant { variant: Variant, generics: Vec<Type<'db>>, params: Vec<Expr<'db>> },
+ Variant { variant: EnumVariant, generics: Vec<Type<'db>>, params: Vec<Expr<'db>> },
/// Struct construction
Struct { strukt: Struct, generics: Vec<Type<'db>>, params: Vec<Expr<'db>> },
/// Tuple construction
@@ -222,7 +222,7 @@ impl<'db> Expr<'db> {
StructKind::Unit => String::new(),
};
- let prefix = mod_item_path_str(sema_scope, &ModuleDef::Variant(*variant))?;
+ let prefix = mod_item_path_str(sema_scope, &ModuleDef::EnumVariant(*variant))?;
Ok(format!("{prefix}{inner}"))
}
Expr::Struct { strukt, params, .. } => {
diff --git a/crates/hir/src/term_search/tactics.rs b/crates/hir/src/term_search/tactics.rs
index 8622aa1378..c7ef4e5d5d 100644
--- a/crates/hir/src/term_search/tactics.rs
+++ b/crates/hir/src/term_search/tactics.rs
@@ -53,7 +53,7 @@ pub(super) fn trivial<'a, 'lt, 'db, DB: HirDatabase>(
ScopeDef::GenericParam(GenericParam::ConstParam(it)) => Some(Expr::ConstParam(*it)),
ScopeDef::Local(it) => {
if ctx.config.enable_borrowcheck {
- let borrowck = db.borrowck(it.parent).ok()?;
+ let borrowck = db.borrowck(it.parent.as_def_with_body()?).ok()?;
let invalid = borrowck.iter().any(|b| {
b.partially_moved.iter().any(|moved| {
diff --git a/crates/ide-assists/src/handlers/add_explicit_enum_discriminant.rs b/crates/ide-assists/src/handlers/add_explicit_enum_discriminant.rs
index 7960373e61..75c5f84b85 100644
--- a/crates/ide-assists/src/handlers/add_explicit_enum_discriminant.rs
+++ b/crates/ide-assists/src/handlers/add_explicit_enum_discriminant.rs
@@ -47,7 +47,7 @@ pub(crate) fn add_explicit_enum_discriminant(
// Don't offer the assist if the enum has no variants or if all variants already have an
// explicit discriminant.
- if variant_list.variants().all(|variant_node| variant_node.expr().is_some()) {
+ if variant_list.variants().all(|variant_node| variant_node.const_arg().is_some()) {
return None;
}
@@ -72,7 +72,9 @@ fn add_variant_discriminant(
variant_node: &ast::Variant,
radix: &mut Radix,
) {
- if let Some(expr) = variant_node.expr() {
+ if let Some(expr) = variant_node.const_arg()
+ && let Some(expr) = expr.expr()
+ {
*radix = expr_radix(&expr).unwrap_or(*radix);
return;
}
diff --git a/crates/ide-assists/src/handlers/add_missing_match_arms.rs b/crates/ide-assists/src/handlers/add_missing_match_arms.rs
index 8124fecff6..b063e5ffce 100644
--- a/crates/ide-assists/src/handlers/add_missing_match_arms.rs
+++ b/crates/ide-assists/src/handlers/add_missing_match_arms.rs
@@ -3,14 +3,14 @@ use std::iter::{self, Peekable};
use either::Either;
use hir::{Adt, AsAssocItem, Crate, FindPathConfig, HasAttrs, ModuleDef, Semantics};
use ide_db::RootDatabase;
-use ide_db::assists::ExprFillDefaultMode;
use ide_db::syntax_helpers::suggest_name;
use ide_db::{famous_defs::FamousDefs, helpers::mod_path_to_ast};
use itertools::Itertools;
-use syntax::ToSmolStr;
-use syntax::ast::edit::{AstNodeEdit, IndentLevel};
+use syntax::ast::edit::IndentLevel;
use syntax::ast::syntax_factory::SyntaxFactory;
use syntax::ast::{self, AstNode, MatchArmList, MatchExpr, Pat, make};
+use syntax::syntax_editor::{Position, SyntaxEditor};
+use syntax::{SyntaxKind, SyntaxNode, ToSmolStr};
use crate::{AssistContext, AssistId, Assists, utils};
@@ -80,9 +80,16 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>)
let module = scope.module();
let cfg = ctx.config.find_path_config(ctx.sema.is_nightly(scope.krate()));
let self_ty = if ctx.config.prefer_self_ty {
- scope
- .containing_function()
- .and_then(|function| function.as_assoc_item(ctx.db())?.implementing_ty(ctx.db()))
+ scope.expression_store_owner().and_then(|def| {
+ match def {
+ hir::ExpressionStoreOwner::Body(def_with_body) => {
+ def_with_body.as_assoc_item(ctx.db())
+ }
+ hir::ExpressionStoreOwner::Signature(def) => def.as_assoc_item(ctx.db()),
+ hir::ExpressionStoreOwner::VariantFields(_) => None,
+ }?
+ .implementing_ty(ctx.db())
+ })
} else {
None
};
@@ -224,61 +231,26 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>)
// having any hidden variants means that we need a catch-all arm
needs_catch_all_arm |= has_hidden_variants;
- let missing_arms = missing_pats
+ let mut missing_arms = missing_pats
.filter(|(_, hidden)| {
// filter out hidden patterns because they're handled by the catch-all arm
!hidden
})
- .map(|(pat, _)| {
- make.match_arm(
- pat,
- None,
- match ctx.config.expr_fill_default {
- ExprFillDefaultMode::Todo => make::ext::expr_todo(),
- ExprFillDefaultMode::Underscore => make::ext::expr_underscore(),
- ExprFillDefaultMode::Default => make::ext::expr_todo(),
- },
- )
- });
-
- let mut arms: Vec<_> = match_arm_list
- .arms()
- .filter(|arm| {
- if matches!(arm.pat(), Some(ast::Pat::WildcardPat(_))) {
- if arm.expr().is_none_or(is_empty_expr) {
- false
- } else {
- cov_mark::hit!(add_missing_match_arms_empty_expr);
- true
- }
- } else {
- true
- }
- })
- .map(|arm| arm.reset_indent().indent(IndentLevel(1)))
- .collect();
-
- let first_new_arm_idx = arms.len();
- arms.extend(missing_arms);
+ .map(|(pat, _)| make.match_arm(pat, None, utils::expr_fill_default(ctx.config)))
+ .collect::<Vec<_>>();
if needs_catch_all_arm && !has_catch_all_arm {
cov_mark::hit!(added_wildcard_pattern);
let arm = make.match_arm(
make.wildcard_pat().into(),
None,
- match ctx.config.expr_fill_default {
- ExprFillDefaultMode::Todo => make::ext::expr_todo(),
- ExprFillDefaultMode::Underscore => make::ext::expr_underscore(),
- ExprFillDefaultMode::Default => make::ext::expr_todo(),
- },
+ utils::expr_fill_default(ctx.config),
);
- arms.push(arm);
+ missing_arms.push(arm);
}
- let new_match_arm_list = make.match_arm_list(arms);
-
// FIXME: Hack for syntax trees not having great support for macros
- // Just replace the element that the original range came from
+ // Just edit the element that the original range came from
let old_place = {
// Find the original element
let file = ctx.sema.parse(arm_list_range.file_id);
@@ -295,25 +267,27 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>)
};
let mut editor = builder.make_editor(&old_place);
- let new_match_arm_list = new_match_arm_list.indent(IndentLevel::from_node(&old_place));
- editor.replace(old_place, new_match_arm_list.syntax());
+ let mut arms_edit = ArmsEdit { match_arm_list, place: old_place, last_arm: None };
+
+ arms_edit.remove_wildcard_arms(ctx, &mut editor);
+ arms_edit.add_comma_after_last_arm(ctx, &make, &mut editor);
+ arms_edit.append_arms(&missing_arms, &make, &mut editor);
if let Some(cap) = ctx.config.snippet_cap {
- if let Some(it) = new_match_arm_list
- .arms()
- .nth(first_new_arm_idx)
+ if let Some(it) = missing_arms
+ .first()
.and_then(|arm| arm.syntax().descendants().find_map(ast::WildcardPat::cast))
{
editor.add_annotation(it.syntax(), builder.make_placeholder_snippet(cap));
}
- for arm in new_match_arm_list.arms().skip(first_new_arm_idx) {
+ for arm in &missing_arms {
if let Some(expr) = arm.expr() {
editor.add_annotation(expr.syntax(), builder.make_placeholder_snippet(cap));
}
}
- if let Some(arm) = new_match_arm_list.arms().skip(first_new_arm_idx).last() {
+ if let Some(arm) = missing_arms.last() {
editor.add_annotation(arm.syntax(), builder.make_tabstop_after(cap));
}
}
@@ -372,6 +346,101 @@ fn cursor_at_trivial_match_arm_list(
None
}
+struct ArmsEdit {
+ match_arm_list: MatchArmList,
+ place: SyntaxNode,
+ last_arm: Option<ast::MatchArm>,
+}
+
+impl ArmsEdit {
+ fn remove_wildcard_arms(&mut self, ctx: &AssistContext<'_>, editor: &mut SyntaxEditor) {
+ for arm in self.match_arm_list.arms() {
+ if !matches!(arm.pat(), Some(Pat::WildcardPat(_))) {
+ self.last_arm = Some(arm);
+ continue;
+ }
+ if !arm.expr().is_none_or(is_empty_expr) {
+ cov_mark::hit!(add_missing_match_arms_empty_expr);
+ self.last_arm = Some(arm);
+ continue;
+ }
+ let Some(range) = self.cover_edit_range(ctx, &arm) else { continue };
+
+ let prev = match range.start() {
+ syntax::NodeOrToken::Node(node) => {
+ node.first_token().and_then(|it| it.prev_token())
+ }
+ syntax::NodeOrToken::Token(tok) => tok.prev_token(),
+ };
+ if let Some(prev) = prev
+ && prev.kind() == SyntaxKind::WHITESPACE
+ {
+ editor.delete(prev);
+ }
+
+ editor.delete_all(range);
+ }
+ }
+
+ fn append_arms(&self, arms: &[ast::MatchArm], make: &SyntaxFactory, editor: &mut SyntaxEditor) {
+ let Some(mut before) = self.place.last_token() else {
+ stdx::never!("match arm list not contain any token");
+ return;
+ };
+ if let Some(prev) = before.prev_token()
+ && prev.kind() == SyntaxKind::WHITESPACE
+ {
+ before = prev;
+ }
+ let open_curly =
+ !self.place.text().contains_char('\n') || before.kind() == SyntaxKind::WHITESPACE;
+ let indent = IndentLevel::from_node(&self.place);
+ let arm_indent = indent + 1;
+ let indent = make.whitespace(&format!("\n{indent}"));
+ let arm_indent = make.whitespace(&format!("\n{arm_indent}"));
+ let elements = arms
+ .iter()
+ .flat_map(|arm| [arm_indent.clone().into(), arm.syntax().clone().into()])
+ .chain(open_curly.then(|| indent.clone().into()))
+ .collect();
+
+ if before.kind() == SyntaxKind::WHITESPACE {
+ editor.replace_with_many(before, elements);
+ } else {
+ editor.insert_all(Position::before(before), elements);
+ }
+ }
+
+ fn add_comma_after_last_arm(
+ &self,
+ ctx: &AssistContext<'_>,
+ make: &SyntaxFactory,
+ editor: &mut SyntaxEditor,
+ ) {
+ if let Some(last_arm) = &self.last_arm
+ && last_arm.comma_token().is_none()
+ && last_arm.expr().is_none_or(|it| !it.is_block_like())
+ && let Some(range) = self.cover_edit_range(ctx, last_arm)
+ {
+ editor.insert(Position::after(range.end()), make.token(syntax::T![,]));
+ }
+ }
+
+ fn cover_edit_range(
+ &self,
+ ctx: &AssistContext<'_>,
+ node: &impl AstNode,
+ ) -> Option<std::ops::RangeInclusive<syntax::SyntaxElement>> {
+ let range = ctx.sema.original_range_opt(node.syntax())?;
+
+ if !self.place.text_range().contains_range(range.range) {
+ return None;
+ }
+
+ Some(utils::cover_edit_range(&self.place, range.range))
+ }
+}
+
fn is_variant_missing(existing_pats: &[Pat], var: &Pat) -> bool {
!existing_pats.iter().any(|pat| does_pat_match_variant(pat, var))
}
@@ -409,7 +478,7 @@ enum ExtendedEnum {
enum ExtendedVariant {
True,
False,
- Variant { variant: hir::Variant, use_self: bool },
+ Variant { variant: hir::EnumVariant, use_self: bool },
}
impl ExtendedVariant {
@@ -1749,7 +1818,7 @@ enum Test {
fn foo(t: Test) {
m!(match t {
- Test::A=>(),
+ Test::A => (),
Test::B => ${1:todo!()},
Test::C => ${2:todo!()},$0
});
@@ -2188,6 +2257,35 @@ fn foo(t: E) {
}
#[test]
+ fn keep_comments() {
+ check_assist(
+ add_missing_match_arms,
+ r#"
+enum E { A, B, C }
+
+fn foo(t: E) -> i32 {
+ match $0t {
+ // variant a
+ E::A => 2
+ // comment on end
+ }
+}"#,
+ r#"
+enum E { A, B, C }
+
+fn foo(t: E) -> i32 {
+ match t {
+ // variant a
+ E::A => 2,
+ // comment on end
+ E::B => ${1:todo!()},
+ E::C => ${2:todo!()},$0
+ }
+}"#,
+ );
+ }
+
+ #[test]
fn not_applicable_when_match_arm_list_cannot_be_upmapped() {
check_assist_not_applicable(
add_missing_match_arms,
diff --git a/crates/ide-assists/src/handlers/auto_import.rs b/crates/ide-assists/src/handlers/auto_import.rs
index da5c123957..de5dfdf4d9 100644
--- a/crates/ide-assists/src/handlers/auto_import.rs
+++ b/crates/ide-assists/src/handlers/auto_import.rs
@@ -268,7 +268,7 @@ pub(crate) fn relevance_score(
hir::Adt::Union(it) => it.ty(ctx.db()),
hir::Adt::Enum(it) => it.ty(ctx.db()),
}),
- hir::ModuleDef::Variant(variant) => Some(variant.constructor_ty(ctx.db())),
+ hir::ModuleDef::EnumVariant(variant) => Some(variant.constructor_ty(ctx.db())),
hir::ModuleDef::Const(it) => Some(it.ty(ctx.db())),
hir::ModuleDef::Static(it) => Some(it.ty(ctx.db())),
hir::ModuleDef::TypeAlias(it) => Some(it.ty(ctx.db())),
diff --git a/crates/ide-assists/src/handlers/convert_bool_then.rs b/crates/ide-assists/src/handlers/convert_bool_then.rs
index 236436989e..b3bfe5b8c4 100644
--- a/crates/ide-assists/src/handlers/convert_bool_then.rs
+++ b/crates/ide-assists/src/handlers/convert_bool_then.rs
@@ -237,7 +237,7 @@ pub(crate) fn convert_bool_then_to_if(acc: &mut Assists, ctx: &AssistContext<'_>
fn option_variants(
sema: &Semantics<'_, RootDatabase>,
expr: &SyntaxNode,
-) -> Option<(hir::Variant, hir::Variant)> {
+) -> Option<(hir::EnumVariant, hir::EnumVariant)> {
let fam = FamousDefs(sema, sema.scope(expr)?.krate());
let option_variants = fam.core_option_Option()?.variants(sema.db);
match &*option_variants {
@@ -254,7 +254,7 @@ fn option_variants(
/// If any of these conditions are met it is impossible to rewrite this as a `bool::then` call.
fn is_invalid_body(
sema: &Semantics<'_, RootDatabase>,
- some_variant: hir::Variant,
+ some_variant: hir::EnumVariant,
expr: &ast::Expr,
) -> bool {
let mut invalid = false;
@@ -277,7 +277,7 @@ fn is_invalid_body(
&& let Some(ast::Expr::PathExpr(p)) = call.expr()
{
let res = p.path().and_then(|p| sema.resolve_path(&p));
- if let Some(hir::PathResolution::Def(hir::ModuleDef::Variant(v))) = res {
+ if let Some(hir::PathResolution::Def(hir::ModuleDef::EnumVariant(v))) = res {
return invalid |= v != some_variant;
}
}
@@ -290,11 +290,11 @@ fn is_invalid_body(
fn block_is_none_variant(
sema: &Semantics<'_, RootDatabase>,
block: &ast::BlockExpr,
- none_variant: hir::Variant,
+ none_variant: hir::EnumVariant,
) -> bool {
block_as_lone_tail(block).and_then(|e| match e {
ast::Expr::PathExpr(pat) => match sema.resolve_path(&pat.path()?)? {
- hir::PathResolution::Def(hir::ModuleDef::Variant(v)) => Some(v),
+ hir::PathResolution::Def(hir::ModuleDef::EnumVariant(v)) => Some(v),
_ => None,
},
_ => None,
diff --git a/crates/ide-assists/src/handlers/convert_for_to_while_let.rs b/crates/ide-assists/src/handlers/convert_for_to_while_let.rs
index d409374c16..15f324eff3 100644
--- a/crates/ide-assists/src/handlers/convert_for_to_while_let.rs
+++ b/crates/ide-assists/src/handlers/convert_for_to_while_let.rs
@@ -24,8 +24,8 @@ use crate::{AssistContext, AssistId, Assists};
// ```
// fn main() {
// let x = vec![1, 2, 3];
-// let mut tmp = x.into_iter();
-// while let Some(v) = tmp.next() {
+// let mut iter = x.into_iter();
+// while let Some(v) = iter.next() {
// let y = v * 2;
// };
// }
@@ -71,7 +71,7 @@ pub(crate) fn convert_for_loop_to_while_let(
let mut new_name = suggest_name::NameGenerator::new_from_scope_locals(
ctx.sema.scope(for_loop.syntax()),
);
- let tmp_var = new_name.suggest_name("tmp");
+ let tmp_var = new_name.suggest_name("iter");
let mut_expr = make.let_stmt(
make.ident_pat(false, true, make.name(&tmp_var)).into(),
@@ -188,8 +188,8 @@ fn main() {
r"
fn main() {
let mut x = vec![1, 2, 3];
- let mut tmp = x.into_iter();
- while let Some(v) = tmp.next() {
+ let mut iter = x.into_iter();
+ while let Some(v) = iter.next() {
v *= 2;
};
}",
@@ -211,8 +211,8 @@ fn main() {
r"
fn main() {
let mut x = vec![1, 2, 3];
- let mut tmp = x.into_iter();
- 'a: while let Some(v) = tmp.next() {
+ let mut iter = x.into_iter();
+ 'a: while let Some(v) = iter.next() {
v *= 2;
break 'a;
};
@@ -236,10 +236,10 @@ fn main() {
r"
fn main() {
let mut x = vec![1, 2, 3];
- let mut tmp = x.into_iter();
+ let mut iter = x.into_iter();
#[allow(unused)]
#[deny(unsafe_code)]
- while let Some(v) = tmp.next() {
+ while let Some(v) = iter.next() {
v *= 2;
};
}",
@@ -275,8 +275,8 @@ impl<T> core::iter::Iterator for core::ops::Range<T> {
}
fn main() {
- let mut tmp = 0..92;
- while let Some(x) = tmp.next() {
+ let mut iter = 0..92;
+ while let Some(x) = iter.next() {
print!("{}", x);
}
}"#,
@@ -330,8 +330,8 @@ impl S {
fn main() {
let x = S;
- let mut tmp = x.iter();
- while let Some(v) = tmp.next() {
+ let mut iter = x.iter();
+ while let Some(v) = iter.next() {
let a = v * 2;
}
}
@@ -356,8 +356,8 @@ fn main() {
struct NoIterMethod;
fn main() {
let x = NoIterMethod;
- let mut tmp = (&x).into_iter();
- while let Some(v) = tmp.next() {
+ let mut iter = (&x).into_iter();
+ while let Some(v) = iter.next() {
let a = v * 2;
}
}
@@ -382,8 +382,8 @@ fn main() {
struct NoIterMethod;
fn main() {
let x = NoIterMethod;
- let mut tmp = (&mut x).into_iter();
- while let Some(v) = tmp.next() {
+ let mut iter = (&mut x).into_iter();
+ while let Some(v) = iter.next() {
let a = v * 2;
}
}
@@ -423,8 +423,8 @@ impl S {
fn main() {
let x = S;
- let mut tmp = x.iter_mut();
- while let Some(v) = tmp.next() {
+ let mut iter = x.iter_mut();
+ while let Some(v) = iter.next() {
let a = v * 2;
}
}
@@ -448,8 +448,8 @@ fn main() {
fn main() {
let mut x = vec![1, 2, 3];
let y = &mut x;
- let mut tmp = y.into_iter();
- while let Some(v) = tmp.next() {
+ let mut iter = y.into_iter();
+ while let Some(v) = iter.next() {
*v *= 2;
}
}",
@@ -471,8 +471,8 @@ fn main() {
"#,
r#"
fn main() {
- let mut tmp = core::iter::repeat(92).take(1);
- while let Some(a) = tmp.next() {
+ let mut iter = core::iter::repeat(92).take(1);
+ while let Some(a) = iter.next() {
println!("{}", a);
}
}
diff --git a/crates/ide-assists/src/handlers/convert_named_struct_to_tuple_struct.rs b/crates/ide-assists/src/handlers/convert_named_struct_to_tuple_struct.rs
index 42fceb8533..aaf727058c 100644
--- a/crates/ide-assists/src/handlers/convert_named_struct_to_tuple_struct.rs
+++ b/crates/ide-assists/src/handlers/convert_named_struct_to_tuple_struct.rs
@@ -158,11 +158,11 @@ fn edit_struct_def(
fn edit_struct_references(
ctx: &AssistContext<'_>,
builder: &mut SourceChangeBuilder,
- strukt: Either<hir::Struct, hir::Variant>,
+ strukt: Either<hir::Struct, hir::EnumVariant>,
) {
let strukt_def = match strukt {
Either::Left(s) => Definition::Adt(hir::Adt::Struct(s)),
- Either::Right(v) => Definition::Variant(v),
+ Either::Right(v) => Definition::EnumVariant(v),
};
let usages = strukt_def.usages(&ctx.sema).include_self_refs().all();
@@ -242,7 +242,7 @@ where
{
let make = SyntaxFactory::without_mappings();
let orig = ctx.sema.original_range_opt(field_list.syntax())?;
- let list_range = cover_edit_range(source, orig.range);
+ let list_range = cover_edit_range(source.syntax(), orig.range);
let l_curly = match list_range.start() {
NodeOrToken::Node(node) => node.first_token()?,
@@ -265,7 +265,7 @@ where
for name_ref in fields(&field_list) {
let Some(orig) = ctx.sema.original_range_opt(name_ref.syntax()) else { continue };
- let name_range = cover_edit_range(source, orig.range);
+ let name_range = cover_edit_range(source.syntax(), orig.range);
if let Some(colon) = next_non_trivia_token(name_range.end().clone())
&& colon.kind() == T![:]
@@ -306,7 +306,7 @@ fn edit_field_references(
// Only edit the field reference if it's part of a `.field` access
if name_ref.syntax().parent().and_then(ast::FieldExpr::cast).is_some() {
edit.replace_all(
- cover_edit_range(&source, r.range),
+ cover_edit_range(source.syntax(), r.range),
vec![make.name_ref(&index.to_string()).syntax().clone().into()],
);
}
diff --git a/crates/ide-assists/src/handlers/convert_tuple_struct_to_named_struct.rs b/crates/ide-assists/src/handlers/convert_tuple_struct_to_named_struct.rs
index f1eae83866..ae41e6c015 100644
--- a/crates/ide-assists/src/handlers/convert_tuple_struct_to_named_struct.rs
+++ b/crates/ide-assists/src/handlers/convert_tuple_struct_to_named_struct.rs
@@ -142,12 +142,12 @@ fn edit_struct_def(
fn edit_struct_references(
ctx: &AssistContext<'_>,
edit: &mut SourceChangeBuilder,
- strukt: Either<hir::Struct, hir::Variant>,
+ strukt: Either<hir::Struct, hir::EnumVariant>,
names: &[ast::Name],
) {
let strukt_def = match strukt {
Either::Left(s) => Definition::Adt(hir::Adt::Struct(s)),
- Either::Right(v) => Definition::Variant(v),
+ Either::Right(v) => Definition::EnumVariant(v),
};
let usages = strukt_def.usages(&ctx.sema).include_self_refs().all();
@@ -191,7 +191,7 @@ fn process_struct_name_reference(
full_path,
generate_record_pat_list(&tuple_struct_pat, names),
);
- editor.replace_all(cover_edit_range(source, range), vec![new.syntax().clone().into()]);
+ editor.replace_all(cover_edit_range(source.syntax(), range), vec![new.syntax().clone().into()]);
},
ast::PathExpr(path_expr) => {
let call_expr = path_expr.syntax().parent().and_then(ast::CallExpr::cast)?;
@@ -207,7 +207,7 @@ fn process_struct_name_reference(
let mut first_insert = vec![];
for (expr, name) in arg_list.args().zip(names) {
let range = ctx.sema.original_range_opt(expr.syntax())?.range;
- let place = cover_edit_range(source, range);
+ let place = cover_edit_range(source.syntax(), range);
let elements = vec![
make.name_ref(&name.text()).syntax().clone().into(),
make.token(T![:]).into(),
@@ -236,7 +236,7 @@ fn process_delimiter(
first_insert: Vec<syntax::SyntaxElement>,
) {
let Some(range) = ctx.sema.original_range_opt(list.syntax()) else { return };
- let place = cover_edit_range(source, range.range);
+ let place = cover_edit_range(source.syntax(), range.range);
let l_paren = match place.start() {
syntax::NodeOrToken::Node(node) => node.first_token(),
@@ -290,7 +290,7 @@ fn edit_field_references(
&& let Some(original) = ctx.sema.original_range_opt(name_ref.syntax())
{
editor.replace_all(
- cover_edit_range(&source, original.range),
+ cover_edit_range(source.syntax(), original.range),
vec![name.syntax().clone().into()],
);
}
diff --git a/crates/ide-assists/src/handlers/destructure_struct_binding.rs b/crates/ide-assists/src/handlers/destructure_struct_binding.rs
index 0f5ef0548c..ec4a83b642 100644
--- a/crates/ide-assists/src/handlers/destructure_struct_binding.rs
+++ b/crates/ide-assists/src/handlers/destructure_struct_binding.rs
@@ -17,7 +17,7 @@ use syntax::{
use crate::{
assist_context::{AssistContext, Assists, SourceChangeBuilder},
- utils::ref_field_expr::determine_ref_and_parens,
+ utils::{cover_edit_range, ref_field_expr::determine_ref_and_parens},
};
// Assist: destructure_struct_binding
@@ -358,6 +358,7 @@ fn update_usages(
data: &StructEditData,
field_names: &FxHashMap<SmolStr, SmolStr>,
) {
+ let source = ctx.source_file().syntax();
let make = SyntaxFactory::with_mappings();
let edits = data
.usages
@@ -366,7 +367,9 @@ fn update_usages(
.collect_vec();
editor.add_mappings(make.finish_with_mappings());
for (old, new) in edits {
- editor.replace(old, new);
+ if let Some(range) = ctx.sema.original_range_opt(&old) {
+ editor.replace_all(cover_edit_range(source, range.range), vec![new.into()]);
+ }
}
}
@@ -1006,4 +1009,33 @@ mod tests {
"#,
)
}
+
+ #[test]
+ fn record_struct_usage_in_macro_call() {
+ // exact repro from #20716: struct field access inside write! must not panic
+ check_assist(
+ destructure_struct_binding,
+ r#"
+//- minicore: write, fmt
+use core::fmt::Write;
+struct Foo { y: i8 }
+
+fn main() {
+ let mut s = String::new();
+ let $0x = Foo { y: 8 };
+ write!(s, "{}", x.y).unwrap();
+}
+"#,
+ r#"
+use core::fmt::Write;
+struct Foo { y: i8 }
+
+fn main() {
+ let mut s = String::new();
+ let Foo { y } = Foo { y: 8 };
+ write!(s, "{}", y).unwrap();
+}
+"#,
+ )
+ }
}
diff --git a/crates/ide-assists/src/handlers/destructure_tuple_binding.rs b/crates/ide-assists/src/handlers/destructure_tuple_binding.rs
index d51a3a26a3..23c11b258c 100644
--- a/crates/ide-assists/src/handlers/destructure_tuple_binding.rs
+++ b/crates/ide-assists/src/handlers/destructure_tuple_binding.rs
@@ -14,7 +14,7 @@ use syntax::{
use crate::{
assist_context::{AssistContext, Assists, SourceChangeBuilder},
- utils::ref_field_expr::determine_ref_and_parens,
+ utils::{cover_edit_range, ref_field_expr::determine_ref_and_parens},
};
// Assist: destructure_tuple_binding
@@ -98,7 +98,9 @@ fn destructure_tuple_edit_impl(
assignment_edit.apply(&mut syntax_editor, &syntax_factory);
if let Some(usages_edit) = current_file_usages_edit {
- usages_edit.into_iter().for_each(|usage_edit| usage_edit.apply(edit, &mut syntax_editor))
+ usages_edit
+ .into_iter()
+ .for_each(|usage_edit| usage_edit.apply(ctx, edit, &mut syntax_editor))
}
syntax_editor.add_mappings(syntax_factory.finish_with_mappings());
@@ -311,14 +313,25 @@ enum EditTupleUsage {
}
impl EditTupleUsage {
- fn apply(self, edit: &mut SourceChangeBuilder, syntax_editor: &mut SyntaxEditor) {
+ fn apply(
+ self,
+ ctx: &AssistContext<'_>,
+ edit: &mut SourceChangeBuilder,
+ syntax_editor: &mut SyntaxEditor,
+ ) {
match self {
EditTupleUsage::NoIndex(range) => {
edit.insert(range.start(), "/*");
edit.insert(range.end(), "*/");
}
EditTupleUsage::ReplaceExpr(target_expr, replace_with) => {
- syntax_editor.replace(target_expr.syntax(), replace_with.syntax())
+ if let Some(range) = ctx.sema.original_range_opt(target_expr.syntax()) {
+ let source = ctx.source_file().syntax();
+ syntax_editor.replace_all(
+ cover_edit_range(source, range.range),
+ vec![replace_with.syntax().clone().into()],
+ );
+ }
}
}
}
@@ -349,24 +362,6 @@ fn detect_tuple_index(usage: &FileReference, data: &TupleData) -> Option<TupleIn
if let Some(field_expr) = ast::FieldExpr::cast(node) {
let idx = field_expr.name_ref()?.as_tuple_field()?;
if idx < data.field_names.len() {
- // special case: in macro call -> range of `field_expr` in applied macro, NOT range in actual file!
- if field_expr.syntax().ancestors().any(|a| ast::MacroStmts::can_cast(a.kind())) {
- cov_mark::hit!(destructure_tuple_macro_call);
-
- // issue: cannot differentiate between tuple index passed into macro or tuple index as result of macro:
- // ```rust
- // macro_rules! m {
- // ($t1:expr, $t2:expr) => { $t1; $t2.0 }
- // }
- // let t = (1,2);
- // m!(t.0, t)
- // ```
- // -> 2 tuple index usages detected!
- //
- // -> only handle `t`
- return None;
- }
-
Some(TupleIndex { index: idx, field_expr })
} else {
// tuple index out of range
@@ -1437,7 +1432,6 @@ fn main() {
#[test]
fn detect_macro_call() {
- cov_mark::check!(destructure_tuple_macro_call);
check_in_place_assist(
r#"
macro_rules! m {
@@ -1456,7 +1450,7 @@ macro_rules! m {
fn main() {
let ($0_0, _1) = (1,2);
- m!(/*t*/.0);
+ m!(_0);
}
"#,
)
@@ -1548,7 +1542,6 @@ fn main() {
m!(t.0);
}
"#,
- // FIXME: replace `t.0` with `_0` (cannot detect range of tuple index in macro call)
r#"
macro_rules! m {
($e:expr) => { "foo"; $e };
@@ -1556,10 +1549,9 @@ macro_rules! m {
fn main() {
let ($0_0, _1) = (1,2);
- m!(/*t*/.0);
+ m!(_0);
}
"#,
- // FIXME: replace `t.0` with `_0`
r#"
macro_rules! m {
($e:expr) => { "foo"; $e };
@@ -1567,7 +1559,7 @@ macro_rules! m {
fn main() {
let t @ ($0_0, _1) = (1,2);
- m!(t.0);
+ m!(_0);
}
"#,
)
@@ -1586,7 +1578,6 @@ fn main() {
m!((t).0);
}
"#,
- // FIXME: replace `(t).0` with `_0`
r#"
macro_rules! m {
($e:expr) => { "foo"; $e };
@@ -1594,10 +1585,9 @@ macro_rules! m {
fn main() {
let ($0_0, _1) = (1,2);
- m!((/*t*/).0);
+ m!(_0);
}
"#,
- // FIXME: replace `(t).0` with `_0`
r#"
macro_rules! m {
($e:expr) => { "foo"; $e };
@@ -1605,7 +1595,7 @@ macro_rules! m {
fn main() {
let t @ ($0_0, _1) = (1,2);
- m!((t).0);
+ m!(_0);
}
"#,
)
@@ -1653,7 +1643,6 @@ fn main() {
m!(t, t.0);
}
"#,
- // FIXME: replace `t.0` in macro call (not IN macro) with `_0`
r#"
macro_rules! m {
($t:expr, $i:expr) => { $t.0 + $i };
@@ -1661,10 +1650,9 @@ macro_rules! m {
fn main() {
let ($0_0, _1) = (1,2);
- m!(/*t*/, /*t*/.0);
+ m!(t, _0);
}
"#,
- // FIXME: replace `t.0` in macro call with `_0`
r#"
macro_rules! m {
($t:expr, $i:expr) => { $t.0 + $i };
@@ -1672,13 +1660,41 @@ macro_rules! m {
fn main() {
let t @ ($0_0, _1) = (1,2);
- m!(t, t.0);
+ m!(t, _0);
}
"#,
)
}
}
+ mod in_macro_expr {
+ use super::assist::*;
+
+ // exact repro from #20716: tuple index inside write! must not panic
+ #[test]
+ fn tuple_index_in_write_macro() {
+ check_in_place_assist(
+ r#"
+//- minicore: write, fmt
+use core::fmt::Write;
+fn main() {
+ let mut s = String::new();
+ let $0x = (2i32, 3i32);
+ write!(s, "{}", x.0).unwrap();
+}
+"#,
+ r#"
+use core::fmt::Write;
+fn main() {
+ let mut s = String::new();
+ let ($0_0, _1) = (2i32, 3i32);
+ write!(s, "{}", _0).unwrap();
+}
+"#,
+ )
+ }
+ }
+
mod refs {
use super::assist::*;
diff --git a/crates/ide-assists/src/handlers/desugar_try_expr.rs b/crates/ide-assists/src/handlers/desugar_try_expr.rs
index 4022030159..865dc86221 100644
--- a/crates/ide-assists/src/handlers/desugar_try_expr.rs
+++ b/crates/ide-assists/src/handlers/desugar_try_expr.rs
@@ -1,9 +1,6 @@
use std::iter;
-use ide_db::{
- assists::{AssistId, ExprFillDefaultMode},
- ty_filter::TryEnum,
-};
+use ide_db::{assists::AssistId, ty_filter::TryEnum};
use syntax::{
AstNode, T,
ast::{
@@ -80,16 +77,9 @@ pub(crate) fn desugar_try_expr(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op
)
.into(),
};
- let sad_expr = match try_enum {
- TryEnum::Option => make.expr_return(Some(make.expr_path(make.ident_path("None")))),
- TryEnum::Result => make.expr_return(Some(
- make.expr_call(
- make.expr_path(make.ident_path("Err")),
- make.arg_list(iter::once(make.expr_path(make.ident_path("err")))),
- )
- .into(),
- )),
- };
+ let sad_expr = make.expr_return(Some(sad_expr(try_enum, &make, || {
+ make.expr_path(make.ident_path("err"))
+ })));
let happy_arm = make.match_arm(
try_enum.happy_pattern(make.ident_pat(false, false, make.name("it")).into()),
@@ -123,48 +113,18 @@ pub(crate) fn desugar_try_expr(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op
let mut editor = builder.make_editor(let_stmt.syntax());
let indent_level = IndentLevel::from_node(let_stmt.syntax());
+ let fill_expr = || crate::utils::expr_fill_default(ctx.config);
let new_let_stmt = make.let_else_stmt(
try_enum.happy_pattern(pat),
- let_stmt.ty(),
+ let_stmt.ty().map(|ty| match try_enum {
+ TryEnum::Option => make.ty_option(ty).into(),
+ TryEnum::Result => make.ty_result(ty, make.ty_infer().into()).into(),
+ }),
expr,
make.block_expr(
iter::once(
make.expr_stmt(
- make.expr_return(Some(match try_enum {
- TryEnum::Option => make.expr_path(make.ident_path("None")),
- TryEnum::Result => make
- .expr_call(
- make.expr_path(make.ident_path("Err")),
- make.arg_list(iter::once(
- match ctx.config.expr_fill_default {
- ExprFillDefaultMode::Todo => make
- .expr_macro(
- make.ident_path("todo"),
- make.token_tree(
- syntax::SyntaxKind::L_PAREN,
- [],
- ),
- )
- .into(),
- ExprFillDefaultMode::Underscore => {
- make.expr_underscore().into()
- }
- ExprFillDefaultMode::Default => make
- .expr_macro(
- make.ident_path("todo"),
- make.token_tree(
- syntax::SyntaxKind::L_PAREN,
- [],
- ),
- )
- .into(),
- },
- )),
- )
- .into(),
- }))
- .indent(indent_level + 1)
- .into(),
+ make.expr_return(Some(sad_expr(try_enum, &make, fill_expr))).into(),
)
.into(),
),
@@ -181,6 +141,15 @@ pub(crate) fn desugar_try_expr(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op
Some(())
}
+fn sad_expr(try_enum: TryEnum, make: &SyntaxFactory, err: impl Fn() -> ast::Expr) -> ast::Expr {
+ match try_enum {
+ TryEnum::Option => make.expr_path(make.ident_path("None")),
+ TryEnum::Result => make
+ .expr_call(make.expr_path(make.ident_path("Err")), make.arg_list(iter::once(err())))
+ .into(),
+ }
+}
+
#[cfg(test)]
mod tests {
use super::*;
@@ -282,4 +251,46 @@ fn test() {
"Replace try expression with let else",
);
}
+
+ #[test]
+ fn test_desugar_try_expr_option_let_else_with_type() {
+ check_assist_by_label(
+ desugar_try_expr,
+ r#"
+//- minicore: try, option
+fn test() {
+ let pat: bool = Some(true)$0?;
+}
+ "#,
+ r#"
+fn test() {
+ let Some(pat): Option<bool> = Some(true) else {
+ return None;
+ };
+}
+ "#,
+ "Replace try expression with let else",
+ );
+ }
+
+ #[test]
+ fn test_desugar_try_expr_result_let_else_with_type() {
+ check_assist_by_label(
+ desugar_try_expr,
+ r#"
+//- minicore: try, result
+fn test() {
+ let pat: bool = Ok(true)$0?;
+}
+ "#,
+ r#"
+fn test() {
+ let Ok(pat): Result<bool, _> = Ok(true) else {
+ return Err(todo!());
+ };
+}
+ "#,
+ "Replace try expression with let else",
+ );
+ }
}
diff --git a/crates/ide-assists/src/handlers/expand_glob_import.rs b/crates/ide-assists/src/handlers/expand_glob_import.rs
index 7eca4d3f2a..6c5c21bfc9 100644
--- a/crates/ide-assists/src/handlers/expand_glob_import.rs
+++ b/crates/ide-assists/src/handlers/expand_glob_import.rs
@@ -317,7 +317,7 @@ fn find_refs_in_mod(
.into_iter()
.map(|v| Ref {
visible_name: v.name(ctx.db()),
- def: Definition::Variant(v),
+ def: Definition::EnumVariant(v),
is_pub: true,
})
.collect(),
@@ -379,7 +379,7 @@ fn find_imported_defs(ctx: &AssistContext<'_>, use_item: Use) -> Vec<Definition>
| Definition::Module(_)
| Definition::Function(_)
| Definition::Adt(_)
- | Definition::Variant(_)
+ | Definition::EnumVariant(_)
| Definition::Const(_)
| Definition::Static(_)
| Definition::Trait(_)
diff --git a/crates/ide-assists/src/handlers/expand_rest_pattern.rs b/crates/ide-assists/src/handlers/expand_rest_pattern.rs
index 867ac48518..a7e78dfc9c 100644
--- a/crates/ide-assists/src/handlers/expand_rest_pattern.rs
+++ b/crates/ide-assists/src/handlers/expand_rest_pattern.rs
@@ -102,7 +102,7 @@ fn expand_tuple_struct_rest_pattern(
let fields = match ctx.sema.type_of_pat(&pat.clone().into())?.original.as_adt()? {
hir::Adt::Struct(s) if s.kind(ctx.sema.db) == StructKind::Tuple => s.fields(ctx.sema.db),
hir::Adt::Enum(_) => match ctx.sema.resolve_path(&path)? {
- PathResolution::Def(hir::ModuleDef::Variant(v))
+ PathResolution::Def(hir::ModuleDef::EnumVariant(v))
if v.kind(ctx.sema.db) == StructKind::Tuple =>
{
v.fields(ctx.sema.db)
diff --git a/crates/ide-assists/src/handlers/extract_module.rs b/crates/ide-assists/src/handlers/extract_module.rs
index a17ae4885e..dcbeaefa21 100644
--- a/crates/ide-assists/src/handlers/extract_module.rs
+++ b/crates/ide-assists/src/handlers/extract_module.rs
@@ -728,7 +728,7 @@ fn check_def_in_mod_and_out_sel(
}
Definition::Function(x) => check_item!(x),
Definition::Adt(x) => check_item!(x),
- Definition::Variant(x) => check_item!(x),
+ Definition::EnumVariant(x) => check_item!(x),
Definition::Const(x) => check_item!(x),
Definition::Static(x) => check_item!(x),
Definition::Trait(x) => check_item!(x),
diff --git a/crates/ide-assists/src/handlers/extract_struct_from_enum_variant.rs b/crates/ide-assists/src/handlers/extract_struct_from_enum_variant.rs
index 386652a422..4c46a51bef 100644
--- a/crates/ide-assists/src/handlers/extract_struct_from_enum_variant.rs
+++ b/crates/ide-assists/src/handlers/extract_struct_from_enum_variant.rs
@@ -1,7 +1,7 @@
use std::iter;
use either::Either;
-use hir::{HasCrate, Module, ModuleDef, Name, Variant};
+use hir::{EnumVariant, HasCrate, Module, ModuleDef, Name};
use ide_db::{
FxHashSet, RootDatabase,
defs::Definition,
@@ -16,9 +16,7 @@ use syntax::{
SyntaxKind::*,
SyntaxNode, T,
ast::{
- self, AstNode, HasAttrs, HasGenericParams, HasName, HasVisibility,
- edit::{AstNodeEdit, IndentLevel},
- make,
+ self, AstNode, HasAttrs, HasGenericParams, HasName, HasVisibility, edit::AstNodeEdit, make,
},
match_ast, ted,
};
@@ -63,7 +61,7 @@ pub(crate) fn extract_struct_from_enum_variant(
let edition = enum_hir.krate(ctx.db()).edition(ctx.db());
let variant_hir_name = variant_hir.name(ctx.db());
let enum_module_def = ModuleDef::from(enum_hir);
- let usages = Definition::Variant(variant_hir).usages(&ctx.sema).all();
+ let usages = Definition::EnumVariant(variant_hir).usages(&ctx.sema).all();
let mut visited_modules_set = FxHashSet::default();
let current_module = enum_hir.module(ctx.db());
@@ -163,7 +161,7 @@ fn extract_field_list_if_applicable(
}
}
-fn existing_definition(db: &RootDatabase, variant_name: &ast::Name, variant: &Variant) -> bool {
+fn existing_definition(db: &RootDatabase, variant_name: &ast::Name, variant: &EnumVariant) -> bool {
variant
.parent_enum(db)
.module(db)
@@ -175,7 +173,7 @@ fn existing_definition(db: &RootDatabase, variant_name: &ast::Name, variant: &Va
def,
ModuleDef::Module(_)
| ModuleDef::Adt(_)
- | ModuleDef::Variant(_)
+ | ModuleDef::EnumVariant(_)
| ModuleDef::Trait(_)
| ModuleDef::TypeAlias(_)
| ModuleDef::BuiltinType(_)
@@ -290,7 +288,6 @@ fn create_struct_def(
field_list.clone().into()
}
};
- let field_list = field_list.indent(IndentLevel::single());
let strukt = make::struct_(enum_vis, name, generics, field_list).clone_for_update();
diff --git a/crates/ide-assists/src/handlers/extract_variable.rs b/crates/ide-assists/src/handlers/extract_variable.rs
index 7071106970..e5ce02cf53 100644
--- a/crates/ide-assists/src/handlers/extract_variable.rs
+++ b/crates/ide-assists/src/handlers/extract_variable.rs
@@ -465,7 +465,7 @@ fn like_const_value(ctx: &AssistContext<'_>, path_resolution: hir::PathResolutio
match path_resolution {
hir::PathResolution::Def(def) => match def {
hir::ModuleDef::Adt(adt) => adt_like_const_value(Some(adt)),
- hir::ModuleDef::Variant(variant) => variant.kind(db) == hir::StructKind::Unit,
+ hir::ModuleDef::EnumVariant(variant) => variant.kind(db) == hir::StructKind::Unit,
hir::ModuleDef::TypeAlias(ty) => adt_like_const_value(ty.ty(db).as_adt()),
hir::ModuleDef::Const(_) | hir::ModuleDef::Static(_) => true,
hir::ModuleDef::Trait(_)
diff --git a/crates/ide-assists/src/handlers/fix_visibility.rs b/crates/ide-assists/src/handlers/fix_visibility.rs
index 5134b98f1b..440f2d5f17 100644
--- a/crates/ide-assists/src/handlers/fix_visibility.rs
+++ b/crates/ide-assists/src/handlers/fix_visibility.rs
@@ -173,7 +173,7 @@ fn target_data_for_def(
// FIXME
hir::ModuleDef::Macro(_) => return None,
// Enum variants can't be private, we can't modify builtin types
- hir::ModuleDef::Variant(_) | hir::ModuleDef::BuiltinType(_) => return None,
+ hir::ModuleDef::EnumVariant(_) | hir::ModuleDef::BuiltinType(_) => return None,
};
Some((offset, target, target_file, target_name))
diff --git a/crates/ide-assists/src/handlers/generate_blanket_trait_impl.rs b/crates/ide-assists/src/handlers/generate_blanket_trait_impl.rs
index b0fa9e6b3e..e022a27e51 100644
--- a/crates/ide-assists/src/handlers/generate_blanket_trait_impl.rs
+++ b/crates/ide-assists/src/handlers/generate_blanket_trait_impl.rs
@@ -5,15 +5,15 @@ use crate::{
use hir::{HasCrate, Semantics};
use ide_db::{
RootDatabase,
- assists::{AssistId, AssistKind, ExprFillDefaultMode},
+ assists::{AssistId, AssistKind},
famous_defs::FamousDefs,
syntax_helpers::suggest_name,
};
use syntax::{
AstNode,
ast::{
- self, AssocItem, BlockExpr, GenericParam, HasAttrs, HasGenericParams, HasName,
- HasTypeBounds, HasVisibility, edit::AstNodeEdit, make,
+ self, AssocItem, GenericParam, HasAttrs, HasGenericParams, HasName, HasTypeBounds,
+ HasVisibility, edit::AstNodeEdit, make,
},
syntax_editor::Position,
};
@@ -269,7 +269,7 @@ fn todo_fn(f: &ast::Fn, config: &AssistConfig) -> ast::Fn {
f.generic_param_list(),
f.where_clause(),
params,
- default_block(config),
+ make::block_expr(None, Some(crate::utils::expr_fill_default(config))),
f.ret_type(),
f.async_token().is_some(),
f.const_token().is_some(),
@@ -278,15 +278,6 @@ fn todo_fn(f: &ast::Fn, config: &AssistConfig) -> ast::Fn {
)
}
-fn default_block(config: &AssistConfig) -> BlockExpr {
- let expr = match config.expr_fill_default {
- ExprFillDefaultMode::Todo => make::ext::expr_todo(),
- ExprFillDefaultMode::Underscore => make::ext::expr_underscore(),
- ExprFillDefaultMode::Default => make::ext::expr_todo(),
- };
- make::block_expr(None, Some(expr))
-}
-
fn cfg_attrs(node: &impl HasAttrs) -> impl Iterator<Item = ast::Attr> {
node.attrs().filter(|attr| attr.as_simple_call().is_some_and(|(name, _arg)| name == "cfg"))
}
diff --git a/crates/ide-assists/src/handlers/generate_default_from_new.rs b/crates/ide-assists/src/handlers/generate_default_from_new.rs
index 485184723b..2d92bf5146 100644
--- a/crates/ide-assists/src/handlers/generate_default_from_new.rs
+++ b/crates/ide-assists/src/handlers/generate_default_from_new.rs
@@ -1,8 +1,12 @@
use ide_db::famous_defs::FamousDefs;
-use stdx::format_to;
use syntax::{
AstNode,
- ast::{self, HasGenericParams, HasName, HasTypeBounds, Impl, syntax_factory::SyntaxFactory},
+ ast::{
+ self, HasGenericParams, HasName, HasTypeBounds, Impl,
+ edit::{AstNodeEdit, IndentLevel},
+ syntax_factory::SyntaxFactory,
+ },
+ syntax_editor::Position,
};
use crate::{
@@ -62,32 +66,32 @@ pub(crate) fn generate_default_from_new(acc: &mut Assists, ctx: &AssistContext<'
return None;
}
- let insert_location = impl_.syntax().text_range();
+ let target = impl_.syntax().text_range();
acc.add(
AssistId::generate("generate_default_from_new"),
"Generate a Default impl from a new fn",
- insert_location,
+ target,
move |builder| {
- let default_code = " fn default() -> Self {
- Self::new()
- }";
let make = SyntaxFactory::without_mappings();
- let code =
- generate_trait_impl_text_from_impl(&impl_, self_ty, "Default", default_code, &make);
- builder.insert(insert_location.end(), code);
+ let default_impl = generate_default_impl(&make, &impl_, self_ty);
+ let indent = IndentLevel::from_node(impl_.syntax());
+ let default_impl = default_impl.indent(indent);
+
+ let mut editor = builder.make_editor(impl_.syntax());
+ editor.insert_all(
+ Position::after(impl_.syntax()),
+ vec![
+ make.whitespace(&format!("\n\n{indent}")).into(),
+ default_impl.syntax().clone().into(),
+ ],
+ );
+ builder.add_file_edits(ctx.vfs_file_id(), editor);
},
)
}
-// FIXME: based on from utils::generate_impl_text_inner
-fn generate_trait_impl_text_from_impl(
- impl_: &ast::Impl,
- self_ty: ast::Type,
- trait_text: &str,
- code: &str,
- make: &SyntaxFactory,
-) -> String {
+fn generate_default_impl(make: &SyntaxFactory, impl_: &ast::Impl, self_ty: ast::Type) -> ast::Impl {
let generic_params = impl_.generic_param_list().map(|generic_params| {
let lifetime_params =
generic_params.lifetime_params().map(ast::GenericParam::LifetimeParam);
@@ -109,26 +113,45 @@ fn generate_trait_impl_text_from_impl(
make.generic_param_list(itertools::chain(lifetime_params, ty_or_const_params))
});
- let mut buf = String::with_capacity(code.len());
- buf.push_str("\n\n");
-
- // `impl{generic_params} {trait_text} for {impl_.self_ty()}`
- buf.push_str("impl");
- if let Some(generic_params) = &generic_params {
- format_to!(buf, "{generic_params}")
- }
- format_to!(buf, " {trait_text} for {self_ty}");
-
- match impl_.where_clause() {
- Some(where_clause) => {
- format_to!(buf, "\n{where_clause}\n{{\n{code}\n}}");
- }
- None => {
- format_to!(buf, " {{\n{code}\n}}");
- }
- }
-
- buf
+ let trait_ty: ast::Type = make.ty_path(make.ident_path("Default")).into();
+
+ let self_new_path = make.path_concat(make.ident_path("Self"), make.ident_path("new"));
+ let self_new_call =
+ make.expr_call(make.expr_path(self_new_path), make.arg_list(std::iter::empty()));
+ let fn_body = make.block_expr(std::iter::empty(), Some(self_new_call.into()));
+ let self_ty_ret: ast::Type = make.ty_path(make.ident_path("Self")).into();
+ let default_fn = make
+ .fn_(
+ [],
+ None,
+ make.name("default"),
+ None,
+ None,
+ make.param_list(None, std::iter::empty()),
+ fn_body,
+ Some(make.ret_type(self_ty_ret)),
+ false,
+ false,
+ false,
+ false,
+ )
+ .indent(1.into());
+ let body = make.assoc_item_list(Some(ast::AssocItem::from(default_fn)));
+
+ make.impl_trait(
+ [],
+ false,
+ None,
+ None,
+ generic_params,
+ None,
+ false,
+ trait_ty,
+ self_ty,
+ None,
+ impl_.where_clause(),
+ Some(body),
+ )
}
fn is_default_implemented(ctx: &AssistContext<'_>, impl_: &Impl) -> bool {
@@ -631,12 +654,12 @@ mod test {
}
}
-impl Default for Example {
- fn default() -> Self {
- Self::new()
+ impl Default for Example {
+ fn default() -> Self {
+ Self::new()
+ }
}
}
-}
"#,
);
}
diff --git a/crates/ide-assists/src/handlers/generate_deref.rs b/crates/ide-assists/src/handlers/generate_deref.rs
index 494c87e6d1..5534dc1cd3 100644
--- a/crates/ide-assists/src/handlers/generate_deref.rs
+++ b/crates/ide-assists/src/handlers/generate_deref.rs
@@ -1,16 +1,15 @@
-use std::fmt::Display;
-
use hir::{ModPath, ModuleDef};
-use ide_db::{RootDatabase, famous_defs::FamousDefs};
+use ide_db::{FileId, RootDatabase, famous_defs::FamousDefs};
use syntax::{
- AstNode, Edition, SyntaxNode,
- ast::{self, HasName},
+ Edition,
+ ast::{self, AstNode, HasName, edit::AstNodeEdit, syntax_factory::SyntaxFactory},
+ syntax_editor::Position,
};
use crate::{
AssistId,
assist_context::{AssistContext, Assists, SourceChangeBuilder},
- utils::generate_trait_impl_text_intransitive,
+ utils::generate_trait_impl_intransitive_with_item,
};
// Assist: generate_deref
@@ -64,6 +63,7 @@ fn generate_record_deref(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<(
let field_type = field.ty()?;
let field_name = field.name()?;
let target = field.syntax().text_range();
+ let file_id = ctx.vfs_file_id();
acc.add(
AssistId::generate("generate_deref"),
format!("Generate `{deref_type_to_generate:?}` impl using `{field_name}`"),
@@ -72,9 +72,10 @@ fn generate_record_deref(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<(
generate_edit(
ctx.db(),
edit,
+ file_id,
strukt,
- field_type.syntax(),
- field_name.syntax(),
+ field_type,
+ &field_name.to_string(),
deref_type_to_generate,
trait_path,
module.krate(ctx.db()).edition(ctx.db()),
@@ -105,6 +106,7 @@ fn generate_tuple_deref(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()
let field_type = field.ty()?;
let target = field.syntax().text_range();
+ let file_id = ctx.vfs_file_id();
acc.add(
AssistId::generate("generate_deref"),
format!("Generate `{deref_type_to_generate:?}` impl using `{field}`"),
@@ -113,9 +115,10 @@ fn generate_tuple_deref(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()
generate_edit(
ctx.db(),
edit,
+ file_id,
strukt,
- field_type.syntax(),
- field_list_index,
+ field_type,
+ &field_list_index.to_string(),
deref_type_to_generate,
trait_path,
module.krate(ctx.db()).edition(ctx.db()),
@@ -127,35 +130,81 @@ fn generate_tuple_deref(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()
fn generate_edit(
db: &RootDatabase,
edit: &mut SourceChangeBuilder,
+ file_id: FileId,
strukt: ast::Struct,
- field_type_syntax: &SyntaxNode,
- field_name: impl Display,
+ field_type: ast::Type,
+ field_name: &str,
deref_type: DerefType,
trait_path: ModPath,
edition: Edition,
) {
- let start_offset = strukt.syntax().text_range().end();
- let impl_code = match deref_type {
- DerefType::Deref => format!(
- r#" type Target = {field_type_syntax};
-
- fn deref(&self) -> &Self::Target {{
- &self.{field_name}
- }}"#,
- ),
- DerefType::DerefMut => format!(
- r#" fn deref_mut(&mut self) -> &mut Self::Target {{
- &mut self.{field_name}
- }}"#,
- ),
+ let make = SyntaxFactory::with_mappings();
+ let strukt_adt = ast::Adt::Struct(strukt.clone());
+ let trait_ty = make.ty(&trait_path.display(db, edition).to_string());
+
+ let assoc_items: Vec<ast::AssocItem> = match deref_type {
+ DerefType::Deref => {
+ let target_alias =
+ make.ty_alias([], "Target", None, None, None, Some((field_type, None)));
+ let ret_ty =
+ make.ty_ref(make.ty_path(make.path_from_text("Self::Target")).into(), false);
+ let field_expr = make.expr_field(make.expr_path(make.ident_path("self")), field_name);
+ let body = make.block_expr([], Some(make.expr_ref(field_expr.into(), false)));
+ let fn_ = make
+ .fn_(
+ [],
+ None,
+ make.name("deref"),
+ None,
+ None,
+ make.param_list(Some(make.self_param()), []),
+ body,
+ Some(make.ret_type(ret_ty)),
+ false,
+ false,
+ false,
+ false,
+ )
+ .indent(1.into());
+ vec![ast::AssocItem::TypeAlias(target_alias), ast::AssocItem::Fn(fn_)]
+ }
+ DerefType::DerefMut => {
+ let ret_ty =
+ make.ty_ref(make.ty_path(make.path_from_text("Self::Target")).into(), true);
+ let field_expr = make.expr_field(make.expr_path(make.ident_path("self")), field_name);
+ let body = make.block_expr([], Some(make.expr_ref(field_expr.into(), true)));
+ let fn_ = make
+ .fn_(
+ [],
+ None,
+ make.name("deref_mut"),
+ None,
+ None,
+ make.param_list(Some(make.mut_self_param()), []),
+ body,
+ Some(make.ret_type(ret_ty)),
+ false,
+ false,
+ false,
+ false,
+ )
+ .indent(1.into());
+ vec![ast::AssocItem::Fn(fn_)]
+ }
};
- let strukt_adt = ast::Adt::Struct(strukt);
- let deref_impl = generate_trait_impl_text_intransitive(
- &strukt_adt,
- &trait_path.display(db, edition).to_string(),
- &impl_code,
+
+ let body = make.assoc_item_list(assoc_items);
+ let indent = strukt.indent_level();
+ let impl_ = generate_trait_impl_intransitive_with_item(&make, &strukt_adt, trait_ty, body)
+ .indent(indent);
+
+ let mut editor = edit.make_editor(strukt.syntax());
+ editor.insert_all(
+ Position::after(strukt.syntax()),
+ vec![make.whitespace(&format!("\n\n{indent}")).into(), impl_.syntax().clone().into()],
);
- edit.insert(start_offset, deref_impl);
+ editor.add_mappings(make.finish_with_mappings());
+ edit.add_file_edits(file_id, editor);
}
fn existing_deref_impl(
diff --git a/crates/ide-assists/src/handlers/generate_from_impl_for_enum.rs b/crates/ide-assists/src/handlers/generate_from_impl_for_enum.rs
index 24f271ded8..1adb3f4fe4 100644
--- a/crates/ide-assists/src/handlers/generate_from_impl_for_enum.rs
+++ b/crates/ide-assists/src/handlers/generate_from_impl_for_enum.rs
@@ -1,10 +1,11 @@
use hir::next_solver::{DbInterner, TypingMode};
use ide_db::{RootDatabase, famous_defs::FamousDefs};
-use syntax::ast::{self, AstNode, HasName};
+use syntax::ast::{self, AstNode, HasName, edit::AstNodeEdit, syntax_factory::SyntaxFactory};
+use syntax::syntax_editor::Position;
use crate::{
AssistContext, AssistId, Assists,
- utils::{generate_trait_impl_text_intransitive, is_selected},
+ utils::{generate_trait_impl_intransitive_with_item, is_selected},
};
// Assist: generate_from_impl_for_enum
@@ -33,39 +34,72 @@ pub(crate) fn generate_from_impl_for_enum(
let variants = selected_variants(ctx, &variant)?;
let target = variant.syntax().text_range();
+ let file_id = ctx.vfs_file_id();
acc.add(
AssistId::generate("generate_from_impl_for_enum"),
"Generate `From` impl for this enum variant(s)",
target,
|edit| {
- let start_offset = variant.parent_enum().syntax().text_range().end();
- let from_impl = variants
- .into_iter()
- .map(|variant_info| {
- let from_trait = format!("From<{}>", variant_info.ty);
- let impl_code = generate_impl_code(variant_info);
- generate_trait_impl_text_intransitive(&adt, &from_trait, &impl_code)
- })
- .collect::<String>();
- edit.insert(start_offset, from_impl);
+ let make = SyntaxFactory::with_mappings();
+ let indent = adt.indent_level();
+ let mut elements = Vec::new();
+
+ for variant_info in variants {
+ let impl_ = build_from_impl(&make, &adt, variant_info).indent(indent);
+ elements.push(make.whitespace(&format!("\n\n{indent}")).into());
+ elements.push(impl_.syntax().clone().into());
+ }
+
+ let mut editor = edit.make_editor(adt.syntax());
+ editor.insert_all(Position::after(adt.syntax()), elements);
+ editor.add_mappings(make.finish_with_mappings());
+ edit.add_file_edits(file_id, editor);
},
)
}
-fn generate_impl_code(VariantInfo { name, field_name, ty }: VariantInfo) -> String {
- if let Some(field) = field_name {
- format!(
- r#" fn from({field}: {ty}) -> Self {{
- Self::{name} {{ {field} }}
- }}"#
- )
+fn build_from_impl(make: &SyntaxFactory, adt: &ast::Adt, variant_info: VariantInfo) -> ast::Impl {
+ let VariantInfo { name, field_name, ty } = variant_info;
+ let trait_ty = make.ty(&format!("From<{ty}>"));
+ let ret_ty = make.ret_type(make.ty_path(make.ident_path("Self")).into());
+
+ let (params, body_expr) = if let Some(field) = field_name {
+ let field_str = field.to_string();
+ let param = make.param(make.ident_pat(false, false, make.name(&field_str)).into(), ty);
+ let field_item = make.record_expr_field(make.name_ref(&field_str), None);
+ let record = make.record_expr(
+ make.path_from_text(&format!("Self::{name}")),
+ make.record_expr_field_list([field_item]),
+ );
+ (make.param_list(None, [param]), ast::Expr::from(record))
} else {
- format!(
- r#" fn from(v: {ty}) -> Self {{
- Self::{name}(v)
- }}"#
+ let param = make.param(make.ident_pat(false, false, make.name("v")).into(), ty);
+ let call = make.expr_call(
+ make.expr_path(make.path_from_text(&format!("Self::{name}"))),
+ make.arg_list([make.expr_path(make.ident_path("v"))]),
+ );
+ (make.param_list(None, [param]), ast::Expr::from(call))
+ };
+
+ let from_fn = make
+ .fn_(
+ [],
+ None,
+ make.name("from"),
+ None,
+ None,
+ params,
+ make.block_expr([], Some(body_expr)),
+ Some(ret_ty),
+ false,
+ false,
+ false,
+ false,
)
- }
+ .indent(1.into());
+
+ let body = make.assoc_item_list([ast::AssocItem::Fn(from_fn)]);
+ generate_trait_impl_intransitive_with_item(make, adt, trait_ty, body)
}
struct VariantInfo {
diff --git a/crates/ide-assists/src/handlers/generate_function.rs b/crates/ide-assists/src/handlers/generate_function.rs
index f62eccaf19..fbf6241e43 100644
--- a/crates/ide-assists/src/handlers/generate_function.rs
+++ b/crates/ide-assists/src/handlers/generate_function.rs
@@ -4,7 +4,6 @@ use hir::{
};
use ide_db::{
FileId, FxHashMap, FxHashSet, RootDatabase, SnippetCap,
- assists::ExprFillDefaultMode,
defs::{Definition, NameRefClass},
famous_defs::FamousDefs,
helpers::is_editable_crate,
@@ -24,7 +23,7 @@ use syntax::{
use crate::{
AssistContext, AssistId, Assists,
- utils::{convert_reference_type, find_struct_impl},
+ utils::{convert_reference_type, expr_fill_default, find_struct_impl},
};
// Assist: generate_function
@@ -286,11 +285,7 @@ impl FunctionBuilder {
target_module,
&mut necessary_generic_params,
);
- let placeholder_expr = match ctx.config.expr_fill_default {
- ExprFillDefaultMode::Todo => make::ext::expr_todo(),
- ExprFillDefaultMode::Underscore => make::ext::expr_underscore(),
- ExprFillDefaultMode::Default => make::ext::expr_todo(),
- };
+ let placeholder_expr = expr_fill_default(ctx.config);
fn_body = make::block_expr(vec![], Some(placeholder_expr));
};
@@ -345,11 +340,7 @@ impl FunctionBuilder {
let (generic_param_list, where_clause) =
fn_generic_params(ctx, necessary_generic_params, &target)?;
- let placeholder_expr = match ctx.config.expr_fill_default {
- ExprFillDefaultMode::Todo => make::ext::expr_todo(),
- ExprFillDefaultMode::Underscore => make::ext::expr_underscore(),
- ExprFillDefaultMode::Default => make::ext::expr_todo(),
- };
+ let placeholder_expr = expr_fill_default(ctx.config);
let fn_body = make::block_expr(vec![], Some(placeholder_expr));
Some(Self {
@@ -465,11 +456,7 @@ fn make_fn_body_as_new_function(
let adt_info = adt_info.as_ref()?;
let path_self = make::ext::ident_path("Self");
- let placeholder_expr = match ctx.config.expr_fill_default {
- ExprFillDefaultMode::Todo => make::ext::expr_todo(),
- ExprFillDefaultMode::Underscore => make::ext::expr_underscore(),
- ExprFillDefaultMode::Default => make::ext::expr_todo(),
- };
+ let placeholder_expr = expr_fill_default(ctx.config);
let tail_expr = if let Some(strukt) = adt_info.adt.as_struct() {
match strukt.kind(ctx.db()) {
StructKind::Record => {
diff --git a/crates/ide-assists/src/handlers/generate_getter_or_setter.rs b/crates/ide-assists/src/handlers/generate_getter_or_setter.rs
index 92a654743b..62ffd3d965 100644
--- a/crates/ide-assists/src/handlers/generate_getter_or_setter.rs
+++ b/crates/ide-assists/src/handlers/generate_getter_or_setter.rs
@@ -218,14 +218,14 @@ fn generate_getter_from_info(
ctx: &AssistContext<'_>,
info: &AssistInfo,
record_field_info: &RecordFieldInfo,
- syntax_factory: &SyntaxFactory,
+ make: &SyntaxFactory,
) -> ast::Fn {
let (ty, body) = if matches!(info.assist_type, AssistType::MutGet) {
- let self_expr = syntax_factory.expr_path(syntax_factory.ident_path("self"));
+ let self_expr = make.expr_path(make.ident_path("self"));
(
- syntax_factory.ty_ref(record_field_info.field_ty.clone(), true),
- syntax_factory.expr_ref(
- syntax_factory.expr_field(self_expr, &record_field_info.field_name.text()).into(),
+ make.ty_ref(record_field_info.field_ty.clone(), true),
+ make.expr_ref(
+ make.expr_field(self_expr, &record_field_info.field_name.text()).into(),
true,
),
)
@@ -239,21 +239,20 @@ fn generate_getter_from_info(
.map(|conversion| {
cov_mark::hit!(convert_reference_type);
(
- conversion.convert_type(ctx.db(), module),
- conversion.getter(record_field_info.field_name.to_string()),
+ conversion.convert_type_with_factory(make, ctx.db(), module),
+ conversion.getter(make, record_field_info.field_name.to_string()),
)
})
})()
.unwrap_or_else(|| {
(
- syntax_factory.ty_ref(record_field_info.field_ty.clone(), false),
- syntax_factory.expr_ref(
- syntax_factory
- .expr_field(
- syntax_factory.expr_path(syntax_factory.ident_path("self")),
- &record_field_info.field_name.text(),
- )
- .into(),
+ make.ty_ref(record_field_info.field_ty.clone(), false),
+ make.expr_ref(
+ make.expr_field(
+ make.expr_path(make.ident_path("self")),
+ &record_field_info.field_name.text(),
+ )
+ .into(),
false,
),
)
@@ -261,18 +260,18 @@ fn generate_getter_from_info(
};
let self_param = if matches!(info.assist_type, AssistType::MutGet) {
- syntax_factory.mut_self_param()
+ make.mut_self_param()
} else {
- syntax_factory.self_param()
+ make.self_param()
};
let strukt = &info.strukt;
- let fn_name = syntax_factory.name(&record_field_info.fn_name);
- let params = syntax_factory.param_list(Some(self_param), []);
- let ret_type = Some(syntax_factory.ret_type(ty));
- let body = syntax_factory.block_expr([], Some(body));
+ let fn_name = make.name(&record_field_info.fn_name);
+ let params = make.param_list(Some(self_param), []);
+ let ret_type = Some(make.ret_type(ty));
+ let body = make.block_expr([], Some(body));
- syntax_factory.fn_(
+ make.fn_(
None,
strukt.visibility(),
fn_name,
@@ -291,32 +290,29 @@ fn generate_getter_from_info(
fn generate_setter_from_info(
info: &AssistInfo,
record_field_info: &RecordFieldInfo,
- syntax_factory: &SyntaxFactory,
+ make: &SyntaxFactory,
) -> ast::Fn {
let strukt = &info.strukt;
let field_name = &record_field_info.fn_name;
- let fn_name = syntax_factory.name(&format!("set_{field_name}"));
+ let fn_name = make.name(&format!("set_{field_name}"));
let field_ty = &record_field_info.field_ty;
// Make the param list
// `(&mut self, $field_name: $field_ty)`
- let field_param = syntax_factory.param(
- syntax_factory.ident_pat(false, false, syntax_factory.name(field_name)).into(),
- field_ty.clone(),
- );
- let params = syntax_factory.param_list(Some(syntax_factory.mut_self_param()), [field_param]);
+ let field_param =
+ make.param(make.ident_pat(false, false, make.name(field_name)).into(), field_ty.clone());
+ let params = make.param_list(Some(make.mut_self_param()), [field_param]);
// Make the assignment body
// `self.$field_name = $field_name`
- let self_expr = syntax_factory.expr_path(syntax_factory.ident_path("self"));
- let lhs = syntax_factory.expr_field(self_expr, field_name);
- let rhs = syntax_factory.expr_path(syntax_factory.ident_path(field_name));
- let assign_stmt =
- syntax_factory.expr_stmt(syntax_factory.expr_assignment(lhs.into(), rhs).into());
- let body = syntax_factory.block_expr([assign_stmt.into()], None);
+ let self_expr = make.expr_path(make.ident_path("self"));
+ let lhs = make.expr_field(self_expr, field_name);
+ let rhs = make.expr_path(make.ident_path(field_name));
+ let assign_stmt = make.expr_stmt(make.expr_assignment(lhs.into(), rhs).into());
+ let body = make.block_expr([assign_stmt.into()], None);
// Make the setter fn
- syntax_factory.fn_(
+ make.fn_(
None,
strukt.visibility(),
fn_name,
diff --git a/crates/ide-assists/src/handlers/generate_impl.rs b/crates/ide-assists/src/handlers/generate_impl.rs
index bbd42481ef..2d1235792d 100644
--- a/crates/ide-assists/src/handlers/generate_impl.rs
+++ b/crates/ide-assists/src/handlers/generate_impl.rs
@@ -1,15 +1,21 @@
use syntax::{
- ast::{self, AstNode, HasGenericParams, HasName, edit::AstNodeEdit, make},
+ ast::{
+ self, AstNode, HasGenericParams, HasName, edit::AstNodeEdit, syntax_factory::SyntaxFactory,
+ },
syntax_editor::{Position, SyntaxEditor},
};
use crate::{
AssistContext, AssistId, Assists,
- utils::{self, DefaultMethods, IgnoreAssocItems},
+ utils::{
+ self, DefaultMethods, IgnoreAssocItems, generate_impl_with_factory,
+ generate_trait_impl_intransitive,
+ },
};
fn insert_impl(
editor: &mut SyntaxEditor,
+ make: &SyntaxFactory,
impl_: &ast::Impl,
nominal: &impl AstNodeEdit,
) -> ast::Impl {
@@ -20,7 +26,7 @@ fn insert_impl(
Position::after(nominal.syntax()),
vec![
// Add a blank line after the ADT, and indentation for the impl to match the ADT
- make::tokens::whitespace(&format!("\n\n{indent}")).into(),
+ make.whitespace(&format!("\n\n{indent}")).into(),
impl_.syntax().clone().into(),
],
);
@@ -59,12 +65,13 @@ pub(crate) fn generate_impl(acc: &mut Assists, ctx: &AssistContext<'_>) -> Optio
format!("Generate impl for `{name}`"),
target,
|edit| {
+ let make = SyntaxFactory::with_mappings();
// Generate the impl
- let impl_ = utils::generate_impl(&nominal);
+ let impl_ = generate_impl_with_factory(&make, &nominal);
let mut editor = edit.make_editor(nominal.syntax());
- let impl_ = insert_impl(&mut editor, &impl_, &nominal);
+ let impl_ = insert_impl(&mut editor, &make, &impl_, &nominal);
// Add a tabstop after the left curly brace
if let Some(cap) = ctx.config.snippet_cap
&& let Some(l_curly) = impl_.assoc_item_list().and_then(|it| it.l_curly_token())
@@ -73,6 +80,7 @@ pub(crate) fn generate_impl(acc: &mut Assists, ctx: &AssistContext<'_>) -> Optio
editor.add_annotation(l_curly, tabstop);
}
+ editor.add_mappings(make.finish_with_mappings());
edit.add_file_edits(ctx.vfs_file_id(), editor);
},
)
@@ -109,12 +117,13 @@ pub(crate) fn generate_trait_impl(acc: &mut Assists, ctx: &AssistContext<'_>) ->
format!("Generate trait impl for `{name}`"),
target,
|edit| {
+ let make = SyntaxFactory::with_mappings();
// Generate the impl
- let impl_ = utils::generate_trait_impl_intransitive(&nominal, make::ty_placeholder());
+ let impl_ = generate_trait_impl_intransitive(&make, &nominal, make.ty_placeholder());
let mut editor = edit.make_editor(nominal.syntax());
- let impl_ = insert_impl(&mut editor, &impl_, &nominal);
+ let impl_ = insert_impl(&mut editor, &make, &impl_, &nominal);
// Make the trait type a placeholder snippet
if let Some(cap) = ctx.config.snippet_cap {
if let Some(trait_) = impl_.trait_() {
@@ -128,6 +137,7 @@ pub(crate) fn generate_trait_impl(acc: &mut Assists, ctx: &AssistContext<'_>) ->
}
}
+ editor.add_mappings(make.finish_with_mappings());
edit.add_file_edits(ctx.vfs_file_id(), editor);
},
)
@@ -166,9 +176,10 @@ pub(crate) fn generate_impl_trait(acc: &mut Assists, ctx: &AssistContext<'_>) ->
format!("Generate `{name}` impl for type"),
target,
|edit| {
+ let make = SyntaxFactory::with_mappings();
let mut editor = edit.make_editor(trait_.syntax());
- let holder_arg = ast::GenericArg::TypeArg(make::type_arg(make::ty_placeholder()));
+ let holder_arg = ast::GenericArg::TypeArg(make.type_arg(make.ty_placeholder()));
let missing_items = utils::filter_assoc_items(
&ctx.sema,
&hir_trait.items(ctx.db()),
@@ -177,11 +188,11 @@ pub(crate) fn generate_impl_trait(acc: &mut Assists, ctx: &AssistContext<'_>) ->
);
let trait_gen_args = trait_.generic_param_list().map(|list| {
- make::generic_arg_list(list.generic_params().map(|_| holder_arg.clone()))
+ make.generic_arg_list(list.generic_params().map(|_| holder_arg.clone()), false)
});
let make_impl_ = |body| {
- make::impl_trait(
+ make.impl_trait(
None,
trait_.unsafe_token().is_some(),
None,
@@ -189,13 +200,12 @@ pub(crate) fn generate_impl_trait(acc: &mut Assists, ctx: &AssistContext<'_>) ->
None,
None,
false,
- make::ty(&name.text()),
- make::ty_placeholder(),
+ make.ty(&name.text()),
+ make.ty_placeholder(),
None,
None,
body,
)
- .clone_for_update()
};
let impl_ = if missing_items.is_empty() {
@@ -210,11 +220,12 @@ pub(crate) fn generate_impl_trait(acc: &mut Assists, ctx: &AssistContext<'_>) ->
&impl_,
&target_scope,
);
- let assoc_item_list = make::assoc_item_list(Some(assoc_items));
+ let assoc_item_list = make.assoc_item_list(assoc_items);
make_impl_(Some(assoc_item_list))
};
- let impl_ = insert_impl(&mut editor, &impl_, &trait_);
+ let impl_ = insert_impl(&mut editor, &make, &impl_, &trait_);
+ editor.add_mappings(make.finish_with_mappings());
if let Some(cap) = ctx.config.snippet_cap {
if let Some(generics) = impl_.trait_().and_then(|it| it.generic_arg_list()) {
diff --git a/crates/ide-assists/src/handlers/generate_new.rs b/crates/ide-assists/src/handlers/generate_new.rs
index 793211a27b..301d13c095 100644
--- a/crates/ide-assists/src/handlers/generate_new.rs
+++ b/crates/ide-assists/src/handlers/generate_new.rs
@@ -3,7 +3,10 @@ use ide_db::{
use_trivial_constructor::use_trivial_constructor,
};
use syntax::{
- ast::{self, AstNode, HasName, HasVisibility, StructKind, edit::AstNodeEdit, make},
+ ast::{
+ self, AstNode, HasName, HasVisibility, StructKind, edit::AstNodeEdit,
+ syntax_factory::SyntaxFactory,
+ },
syntax_editor::Position,
};
@@ -36,6 +39,7 @@ use crate::{
pub(crate) fn generate_new(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
let strukt = ctx.find_node_at_offset::<ast::Struct>()?;
+ let make = SyntaxFactory::without_mappings();
let field_list = match strukt.kind() {
StructKind::Record(named) => {
named.fields().filter_map(|f| Some((f.name()?, f.ty()?))).collect::<Vec<_>>()
@@ -55,7 +59,7 @@ pub(crate) fn generate_new(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option
Some(name) => name,
None => name_generator.suggest_name(&format!("_{i}")),
};
- Some((make::name(name.as_str()), f.ty()?))
+ Some((make.name(name.as_str()), f.ty()?))
})
.collect::<Vec<_>>()
}
@@ -70,6 +74,7 @@ pub(crate) fn generate_new(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option
let target = strukt.syntax().text_range();
acc.add(AssistId::generate("generate_new"), "Generate `new`", target, |builder| {
+ let make = SyntaxFactory::with_mappings();
let trivial_constructors = field_list
.iter()
.map(|(name, ty)| {
@@ -95,63 +100,63 @@ pub(crate) fn generate_new(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option
edition,
)?;
- Some((make::name_ref(&name.text()), Some(expr)))
+ Some((make.name_ref(&name.text()), Some(expr)))
})
.collect::<Vec<_>>();
let params = field_list.iter().enumerate().filter_map(|(i, (name, ty))| {
if trivial_constructors[i].is_none() {
- Some(make::param(make::ident_pat(false, false, name.clone()).into(), ty.clone()))
+ Some(make.param(make.ident_pat(false, false, name.clone()).into(), ty.clone()))
} else {
None
}
});
- let params = make::param_list(None, params);
+ let params = make.param_list(None, params);
let fields = field_list.iter().enumerate().map(|(i, (name, _))| {
if let Some(constructor) = trivial_constructors[i].clone() {
constructor
} else {
- (make::name_ref(&name.text()), None)
+ (make.name_ref(&name.text()), None)
}
});
let tail_expr: ast::Expr = match strukt.kind() {
StructKind::Record(_) => {
- let fields = fields.map(|(name, expr)| make::record_expr_field(name, expr));
- let fields = make::record_expr_field_list(fields);
- make::record_expr(make::ext::ident_path("Self"), fields).into()
+ let fields = fields.map(|(name, expr)| make.record_expr_field(name, expr));
+ let fields = make.record_expr_field_list(fields);
+ make.record_expr(make.ident_path("Self"), fields).into()
}
StructKind::Tuple(_) => {
let args = fields.map(|(arg, expr)| {
- let arg = || make::expr_path(make::path_unqualified(make::path_segment(arg)));
+ let arg = || make.expr_path(make.path_unqualified(make.path_segment(arg)));
expr.unwrap_or_else(arg)
});
- let arg_list = make::arg_list(args);
- make::expr_call(make::expr_path(make::ext::ident_path("Self")), arg_list).into()
+ let arg_list = make.arg_list(args);
+ make.expr_call(make.expr_path(make.ident_path("Self")), arg_list).into()
}
StructKind::Unit => unreachable!(),
};
- let body = make::block_expr(None, tail_expr.into());
-
- let ret_type = make::ret_type(make::ty_path(make::ext::ident_path("Self")));
-
- let fn_ = make::fn_(
- None,
- strukt.visibility(),
- make::name("new"),
- None,
- None,
- params,
- body,
- Some(ret_type),
- false,
- false,
- false,
- false,
- )
- .clone_for_update()
- .indent(1.into());
+ let body = make.block_expr(None, tail_expr.into());
+
+ let ret_type = make.ret_type(make.ty_path(make.ident_path("Self")).into());
+
+ let fn_ = make
+ .fn_(
+ [],
+ strukt.visibility(),
+ make.name("new"),
+ None,
+ None,
+ params,
+ body,
+ Some(ret_type),
+ false,
+ false,
+ false,
+ false,
+ )
+ .indent(1.into());
let mut editor = builder.make_editor(strukt.syntax());
@@ -164,32 +169,30 @@ pub(crate) fn generate_new(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option
editor.insert_all(
Position::after(l_curly),
vec![
- make::tokens::whitespace(&format!("\n{}", impl_def.indent_level() + 1))
- .into(),
+ make.whitespace(&format!("\n{}", impl_def.indent_level() + 1)).into(),
fn_.syntax().clone().into(),
- make::tokens::whitespace("\n").into(),
+ make.whitespace("\n").into(),
],
);
fn_.syntax().clone()
} else {
- let items = vec![ast::AssocItem::Fn(fn_)];
- let list = make::assoc_item_list(Some(items));
+ let list = make.assoc_item_list([ast::AssocItem::Fn(fn_)]);
editor.insert(Position::after(impl_def.syntax()), list.syntax());
list.syntax().clone()
}
} else {
// Generate a new impl to add the method to
let indent_level = strukt.indent_level();
- let body = vec![ast::AssocItem::Fn(fn_)];
- let list = make::assoc_item_list(Some(body));
- let impl_def = generate_impl_with_item(&ast::Adt::Struct(strukt.clone()), Some(list))
- .indent(strukt.indent_level());
+ let list = make.assoc_item_list([ast::AssocItem::Fn(fn_)]);
+ let impl_def =
+ generate_impl_with_item(&make, &ast::Adt::Struct(strukt.clone()), Some(list))
+ .indent(strukt.indent_level());
// Insert it after the adt
editor.insert_all(
Position::after(strukt.syntax()),
vec![
- make::tokens::whitespace(&format!("\n\n{indent_level}")).into(),
+ make.whitespace(&format!("\n\n{indent_level}")).into(),
impl_def.syntax().clone().into(),
],
);
@@ -233,6 +236,7 @@ pub(crate) fn generate_new(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option
}
}
+ editor.add_mappings(make.finish_with_mappings());
builder.add_file_edits(ctx.vfs_file_id(), editor);
})
}
diff --git a/crates/ide-assists/src/handlers/merge_match_arms.rs b/crates/ide-assists/src/handlers/merge_match_arms.rs
index 08170f81b2..6e84af5f91 100644
--- a/crates/ide-assists/src/handlers/merge_match_arms.rs
+++ b/crates/ide-assists/src/handlers/merge_match_arms.rs
@@ -160,8 +160,11 @@ fn get_arm_types<'db>(
}
}
ast::Pat::IdentPat(ident_pat) => {
- if let Some(name) = ident_pat.name() {
+ if let Some(name) = ident_pat.name()
+ && ctx.sema.to_def(ident_pat).is_some()
+ {
let pat_type = ctx.sema.type_of_binding_in_pat(ident_pat);
+
map.insert(name.text().to_string(), pat_type);
}
}
@@ -213,6 +216,40 @@ fn main() {
}
#[test]
+ fn merge_match_arms_ambiguous_ident_patterns() {
+ check_assist(
+ merge_match_arms,
+ r#"
+#[derive(Debug)]
+enum X { A, B, C }
+use X::*;
+
+fn main() {
+ let x = A;
+ let y = match x {
+ A => { 1i32$0 }
+ B => { 1i32 }
+ C => { 2i32 }
+ }
+}
+"#,
+ r#"
+#[derive(Debug)]
+enum X { A, B, C }
+use X::*;
+
+fn main() {
+ let x = A;
+ let y = match x {
+ A | B => { 1i32 },
+ C => { 2i32 }
+ }
+}
+"#,
+ );
+ }
+
+ #[test]
fn merge_match_arms_multiple_patterns() {
check_assist(
merge_match_arms,
diff --git a/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs b/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs
index 7c024263b4..f54f7a02d2 100644
--- a/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs
+++ b/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs
@@ -4,7 +4,7 @@ use itertools::Itertools;
use syntax::{
SyntaxKind::WHITESPACE,
T,
- ast::{self, AstNode, HasName, make},
+ ast::{self, AstNode, HasName, syntax_factory::SyntaxFactory},
syntax_editor::{Position, SyntaxEditor},
};
@@ -12,8 +12,8 @@ use crate::{
AssistConfig, AssistId,
assist_context::{AssistContext, Assists},
utils::{
- DefaultMethods, IgnoreAssocItems, add_trait_assoc_items_to_impl, filter_assoc_items,
- gen_trait_fn_body, generate_trait_impl,
+ DefaultMethods, IgnoreAssocItems, add_trait_assoc_items_to_impl_with_factory,
+ filter_assoc_items, gen_trait_fn_body, generate_trait_impl,
},
};
@@ -127,6 +127,7 @@ fn add_assist(
let label = format!("Convert to manual `impl {replace_trait_path} for {annotated_name}`");
acc.add(AssistId::refactor("replace_derive_with_manual_impl"), label, target, |builder| {
+ let make = SyntaxFactory::without_mappings();
let insert_after = Position::after(adt.syntax());
let impl_is_unsafe = trait_.map(|s| s.is_unsafe(ctx.db())).unwrap_or(false);
let impl_def = impl_def_from_trait(
@@ -142,7 +143,7 @@ fn add_assist(
let mut editor = builder.make_editor(attr.syntax());
update_attribute(&mut editor, old_derives, old_tree, old_trait_path, attr);
- let trait_path = make::ty_path(replace_trait_path.clone());
+ let trait_path = make.ty_path(replace_trait_path.clone()).into();
let (impl_def, first_assoc_item) = if let Some(impl_def) = impl_def {
(
@@ -150,7 +151,7 @@ fn add_assist(
impl_def.assoc_item_list().and_then(|list| list.assoc_items().next()),
)
} else {
- (generate_trait_impl(impl_is_unsafe, adt, trait_path), None)
+ (generate_trait_impl(&make, impl_is_unsafe, adt, trait_path), None)
};
if let Some(cap) = ctx.config.snippet_cap {
@@ -174,7 +175,7 @@ fn add_assist(
editor.insert_all(
insert_after,
- vec![make::tokens::blank_line().into(), impl_def.syntax().clone().into()],
+ vec![make.whitespace("\n\n").into(), impl_def.syntax().clone().into()],
);
builder.add_file_edits(ctx.vfs_file_id(), editor);
})
@@ -205,10 +206,19 @@ fn impl_def_from_trait(
if trait_items.is_empty() {
return None;
}
- let impl_def = generate_trait_impl(impl_is_unsafe, adt, make::ty_path(trait_path.clone()));
-
- let assoc_items =
- add_trait_assoc_items_to_impl(sema, config, &trait_items, trait_, &impl_def, &target_scope);
+ let make = SyntaxFactory::without_mappings();
+ let trait_ty = make.ty_path(trait_path.clone()).into();
+ let impl_def = generate_trait_impl(&make, impl_is_unsafe, adt, trait_ty);
+
+ let assoc_items = add_trait_assoc_items_to_impl_with_factory(
+ &make,
+ sema,
+ config,
+ &trait_items,
+ trait_,
+ &impl_def,
+ &target_scope,
+ );
let assoc_item_list = if let Some((first, other)) =
assoc_items.split_first().map(|(first, other)| (first.clone_subtree(), other))
{
@@ -222,12 +232,12 @@ fn impl_def_from_trait(
} else {
Some(first.clone())
};
- let items = first_item.into_iter().chain(other.iter().cloned()).collect();
- make::assoc_item_list(Some(items))
+ let items: Vec<ast::AssocItem> =
+ first_item.into_iter().chain(other.iter().cloned()).collect();
+ make.assoc_item_list(items)
} else {
- make::assoc_item_list(None)
- }
- .clone_for_update();
+ make.assoc_item_list_empty()
+ };
let impl_def = impl_def.clone_subtree();
let mut editor = SyntaxEditor::new(impl_def.syntax().clone());
@@ -243,6 +253,7 @@ fn update_attribute(
old_trait_path: &ast::Path,
attr: &ast::Attr,
) {
+ let make = SyntaxFactory::without_mappings();
let new_derives = old_derives
.iter()
.filter(|t| t.to_string() != old_trait_path.to_string())
@@ -257,13 +268,13 @@ fn update_attribute(
.collect::<Vec<_>>()
});
// ...which are interspersed with ", "
- let tt = Itertools::intersperse(tt, vec![make::token(T![,]), make::tokens::single_space()]);
+ let tt = Itertools::intersperse(tt, vec![make.token(T![,]), make.whitespace(" ")]);
// ...wrap them into the appropriate `NodeOrToken` variant
let tt = tt.flatten().map(syntax::NodeOrToken::Token);
// ...and make them into a flat list of tokens
let tt = tt.collect::<Vec<_>>();
- let new_tree = make::token_tree(T!['('], tt).clone_for_update();
+ let new_tree = make.token_tree(T!['('], tt);
editor.replace(old_tree.syntax(), new_tree.syntax());
} else {
// Remove the attr and any trailing whitespace
diff --git a/crates/ide-assists/src/handlers/replace_qualified_name_with_use.rs b/crates/ide-assists/src/handlers/replace_qualified_name_with_use.rs
index 009fc077ce..cdf20586ef 100644
--- a/crates/ide-assists/src/handlers/replace_qualified_name_with_use.rs
+++ b/crates/ide-assists/src/handlers/replace_qualified_name_with_use.rs
@@ -102,7 +102,7 @@ fn target_path(ctx: &AssistContext<'_>, mut original_path: ast::Path) -> Option<
}
match ctx.sema.resolve_path(&original_path)? {
- PathResolution::Def(ModuleDef::Variant(_)) if on_first => original_path.qualifier(),
+ PathResolution::Def(ModuleDef::EnumVariant(_)) if on_first => original_path.qualifier(),
PathResolution::Def(def) if def.as_assoc_item(ctx.db()).is_some() => {
on_first.then_some(original_path.qualifier()?)
}
diff --git a/crates/ide-assists/src/handlers/unmerge_match_arm.rs b/crates/ide-assists/src/handlers/unmerge_match_arm.rs
index 7b0f2dc65a..c4c03d3e35 100644
--- a/crates/ide-assists/src/handlers/unmerge_match_arm.rs
+++ b/crates/ide-assists/src/handlers/unmerge_match_arm.rs
@@ -38,11 +38,18 @@ pub(crate) fn unmerge_match_arm(acc: &mut Assists, ctx: &AssistContext<'_>) -> O
}
let match_arm = ast::MatchArm::cast(or_pat.syntax().parent()?)?;
let match_arm_body = match_arm.expr()?;
+ let pats_after = pipe_token
+ .siblings_with_tokens(Direction::Next)
+ .filter_map(|it| ast::Pat::cast(it.into_node()?))
+ .collect::<Vec<_>>();
// We don't need to check for leading pipe because it is directly under `MatchArm`
// without `OrPat`.
let new_parent = match_arm.syntax().parent()?;
+ if pats_after.is_empty() {
+ return None;
+ }
acc.add(
AssistId::refactor_rewrite("unmerge_match_arm"),
@@ -51,10 +58,6 @@ pub(crate) fn unmerge_match_arm(acc: &mut Assists, ctx: &AssistContext<'_>) -> O
|edit| {
let make = SyntaxFactory::with_mappings();
let mut editor = edit.make_editor(&new_parent);
- let pats_after = pipe_token
- .siblings_with_tokens(Direction::Next)
- .filter_map(|it| ast::Pat::cast(it.into_node()?))
- .collect::<Vec<_>>();
// It is guaranteed that `pats_after` has at least one element
let new_pat = if pats_after.len() == 1 {
pats_after[0].clone()
@@ -191,6 +194,21 @@ fn main() {
}
#[test]
+ fn unmerge_match_arm_trailing_pipe() {
+ check_assist_not_applicable(
+ unmerge_match_arm,
+ r#"
+fn main() {
+ let y = match 0 {
+ 0 |$0 => { 1i32 }
+ 1 => { 2i32 }
+ };
+}
+"#,
+ );
+ }
+
+ #[test]
fn unmerge_match_arm_multiple_pipes() {
check_assist(
unmerge_match_arm,
diff --git a/crates/ide-assists/src/tests/generated.rs b/crates/ide-assists/src/tests/generated.rs
index 8ba46799d5..66d5cf834f 100644
--- a/crates/ide-assists/src/tests/generated.rs
+++ b/crates/ide-assists/src/tests/generated.rs
@@ -507,8 +507,8 @@ fn main() {
r#####"
fn main() {
let x = vec![1, 2, 3];
- let mut tmp = x.into_iter();
- while let Some(v) = tmp.next() {
+ let mut iter = x.into_iter();
+ while let Some(v) = iter.next() {
let y = v * 2;
};
}
diff --git a/crates/ide-assists/src/utils.rs b/crates/ide-assists/src/utils.rs
index 0657e7243a..10057f8681 100644
--- a/crates/ide-assists/src/utils.rs
+++ b/crates/ide-assists/src/utils.rs
@@ -103,11 +103,11 @@ pub(crate) fn wrap_paren(expr: ast::Expr, make: &SyntaxFactory, prec: ExprPreced
}
pub(crate) fn wrap_paren_in_call(expr: ast::Expr, make: &SyntaxFactory) -> ast::Expr {
- if needs_parens_in_call(&expr) { make.expr_paren(expr).into() } else { expr }
+ if needs_parens_in_call(make, &expr) { make.expr_paren(expr).into() } else { expr }
}
-fn needs_parens_in_call(param: &ast::Expr) -> bool {
- let call = make::expr_call(make::ext::expr_unit(), make::arg_list(Vec::new()));
+fn needs_parens_in_call(make: &SyntaxFactory, param: &ast::Expr) -> bool {
+ let call = make.expr_call(make.expr_unit(), make.arg_list(Vec::new()));
let callable = call.expr().expect("invalid make call");
param.needs_parens_in_place_of(call.syntax(), callable.syntax())
}
@@ -203,6 +203,9 @@ pub fn filter_assoc_items(
/// [`filter_assoc_items()`]), clones each item for update and applies path transformation to it,
/// then inserts into `impl_`. Returns the modified `impl_` and the first associated item that got
/// inserted.
+///
+/// Legacy: prefer [`add_trait_assoc_items_to_impl_with_factory`] when a [`SyntaxFactory`] is
+/// available.
#[must_use]
pub fn add_trait_assoc_items_to_impl(
sema: &Semantics<'_, RootDatabase>,
@@ -248,15 +251,79 @@ pub fn add_trait_assoc_items_to_impl(
.filter_map(|item| match item {
ast::AssocItem::Fn(fn_) if fn_.body().is_none() => {
let fn_ = fn_.clone_subtree();
- let new_body = &make::block_expr(
- None,
- Some(match config.expr_fill_default {
- ExprFillDefaultMode::Todo => make::ext::expr_todo(),
- ExprFillDefaultMode::Underscore => make::ext::expr_underscore(),
- ExprFillDefaultMode::Default => make::ext::expr_todo(),
- }),
- );
- let new_body = AstNodeEdit::indent(new_body, IndentLevel::single());
+ let new_body = make::block_expr(None, Some(expr_fill_default(config)));
+ let mut fn_editor = SyntaxEditor::new(fn_.syntax().clone());
+ fn_.replace_or_insert_body(&mut fn_editor, new_body.clone_for_update());
+ let new_fn_ = fn_editor.finish().new_root().clone();
+ ast::AssocItem::cast(new_fn_)
+ }
+ ast::AssocItem::TypeAlias(type_alias) => {
+ let type_alias = type_alias.clone_subtree();
+ if let Some(type_bound_list) = type_alias.type_bound_list() {
+ let mut type_alias_editor = SyntaxEditor::new(type_alias.syntax().clone());
+ type_bound_list.remove(&mut type_alias_editor);
+ let type_alias = type_alias_editor.finish().new_root().clone();
+ ast::AssocItem::cast(type_alias)
+ } else {
+ Some(ast::AssocItem::TypeAlias(type_alias))
+ }
+ }
+ item => Some(item),
+ })
+ .map(|item| AstNodeEdit::indent(&item, new_indent_level))
+ .collect()
+}
+
+/// [`SyntaxFactory`]-based variant of [`add_trait_assoc_items_to_impl`].
+#[must_use]
+pub fn add_trait_assoc_items_to_impl_with_factory(
+ make: &SyntaxFactory,
+ sema: &Semantics<'_, RootDatabase>,
+ config: &AssistConfig,
+ original_items: &[InFile<ast::AssocItem>],
+ trait_: hir::Trait,
+ impl_: &ast::Impl,
+ target_scope: &hir::SemanticsScope<'_>,
+) -> Vec<ast::AssocItem> {
+ let new_indent_level = IndentLevel::from_node(impl_.syntax()) + 1;
+ original_items
+ .iter()
+ .map(|InFile { file_id, value: original_item }| {
+ let mut cloned_item = {
+ if let Some(macro_file) = file_id.macro_file() {
+ let span_map = sema.db.expansion_span_map(macro_file);
+ let item_prettified = prettify_macro_expansion(
+ sema.db,
+ original_item.syntax().clone(),
+ &span_map,
+ target_scope.krate().into(),
+ );
+ if let Some(formatted) = ast::AssocItem::cast(item_prettified) {
+ return formatted;
+ } else {
+ stdx::never!("formatted `AssocItem` could not be cast back to `AssocItem`");
+ }
+ }
+ original_item
+ }
+ .reset_indent();
+
+ if let Some(source_scope) = sema.scope(original_item.syntax()) {
+ let transform =
+ PathTransform::trait_impl(target_scope, &source_scope, trait_, impl_.clone());
+ cloned_item = ast::AssocItem::cast(transform.apply(cloned_item.syntax())).unwrap();
+ }
+ cloned_item.remove_attrs_and_docs();
+ cloned_item
+ })
+ .filter_map(|item| match item {
+ ast::AssocItem::Fn(fn_) if fn_.body().is_none() => {
+ let fn_ = fn_.clone_subtree();
+ let fill_expr: ast::Expr = match config.expr_fill_default {
+ ExprFillDefaultMode::Todo | ExprFillDefaultMode::Default => make.expr_todo(),
+ ExprFillDefaultMode::Underscore => make.expr_underscore().into(),
+ };
+ let new_body = make.block_expr(None::<ast::Stmt>, Some(fill_expr));
let mut fn_editor = SyntaxEditor::new(fn_.syntax().clone());
fn_.replace_or_insert_body(&mut fn_editor, new_body);
let new_fn_ = fn_editor.finish().new_root().clone();
@@ -465,6 +532,15 @@ fn check_pat_variant_nested_or_literal_with_depth(
}
}
+pub(crate) fn expr_fill_default(config: &AssistConfig) -> ast::Expr {
+ let make = SyntaxFactory::without_mappings();
+ match config.expr_fill_default {
+ ExprFillDefaultMode::Todo => make.expr_todo(),
+ ExprFillDefaultMode::Underscore => make.expr_underscore().into(),
+ ExprFillDefaultMode::Default => make.expr_todo(),
+ }
+}
+
// Uses a syntax-driven approach to find any impl blocks for the struct that
// exist within the module/file
//
@@ -553,29 +629,6 @@ pub(crate) fn generate_impl_text(adt: &ast::Adt, code: &str) -> String {
generate_impl_text_inner(adt, None, true, code)
}
-/// Generates the surrounding `impl <trait> for Type { <code> }` including type
-/// and lifetime parameters, with `<trait>` appended to `impl`'s generic parameters' bounds.
-///
-/// This is useful for traits like `PartialEq`, since `impl<T> PartialEq for U<T>` often requires `T: PartialEq`.
-// FIXME: migrate remaining uses to `generate_trait_impl`
-#[allow(dead_code)]
-pub(crate) fn generate_trait_impl_text(adt: &ast::Adt, trait_text: &str, code: &str) -> String {
- generate_impl_text_inner(adt, Some(trait_text), true, code)
-}
-
-/// Generates the surrounding `impl <trait> for Type { <code> }` including type
-/// and lifetime parameters, with `impl`'s generic parameters' bounds kept as-is.
-///
-/// This is useful for traits like `From<T>`, since `impl<T> From<T> for U<T>` doesn't require `T: From<T>`.
-// FIXME: migrate remaining uses to `generate_trait_impl_intransitive`
-pub(crate) fn generate_trait_impl_text_intransitive(
- adt: &ast::Adt,
- trait_text: &str,
- code: &str,
-) -> String {
- generate_impl_text_inner(adt, Some(trait_text), false, code)
-}
-
fn generate_impl_text_inner(
adt: &ast::Adt,
trait_text: Option<&str>,
@@ -656,10 +709,15 @@ fn generate_impl_text_inner(
/// Generates the corresponding `impl Type {}` including type and lifetime
/// parameters.
pub(crate) fn generate_impl_with_item(
+ make: &SyntaxFactory,
adt: &ast::Adt,
body: Option<ast::AssocItemList>,
) -> ast::Impl {
- generate_impl_inner(false, adt, None, true, body)
+ generate_impl_inner_with_factory(make, false, adt, None, true, body)
+}
+
+pub(crate) fn generate_impl_with_factory(make: &SyntaxFactory, adt: &ast::Adt) -> ast::Impl {
+ generate_impl_inner_with_factory(make, false, adt, None, true, None)
}
pub(crate) fn generate_impl(adt: &ast::Adt) -> ast::Impl {
@@ -670,16 +728,34 @@ pub(crate) fn generate_impl(adt: &ast::Adt) -> ast::Impl {
/// and lifetime parameters, with `<trait>` appended to `impl`'s generic parameters' bounds.
///
/// This is useful for traits like `PartialEq`, since `impl<T> PartialEq for U<T>` often requires `T: PartialEq`.
-pub(crate) fn generate_trait_impl(is_unsafe: bool, adt: &ast::Adt, trait_: ast::Type) -> ast::Impl {
- generate_impl_inner(is_unsafe, adt, Some(trait_), true, None)
+pub(crate) fn generate_trait_impl(
+ make: &SyntaxFactory,
+ is_unsafe: bool,
+ adt: &ast::Adt,
+ trait_: ast::Type,
+) -> ast::Impl {
+ generate_impl_inner_with_factory(make, is_unsafe, adt, Some(trait_), true, None)
}
/// Generates the corresponding `impl <trait> for Type {}` including type
/// and lifetime parameters, with `impl`'s generic parameters' bounds kept as-is.
///
/// This is useful for traits like `From<T>`, since `impl<T> From<T> for U<T>` doesn't require `T: From<T>`.
-pub(crate) fn generate_trait_impl_intransitive(adt: &ast::Adt, trait_: ast::Type) -> ast::Impl {
- generate_impl_inner(false, adt, Some(trait_), false, None)
+pub(crate) fn generate_trait_impl_intransitive(
+ make: &SyntaxFactory,
+ adt: &ast::Adt,
+ trait_: ast::Type,
+) -> ast::Impl {
+ generate_impl_inner_with_factory(make, false, adt, Some(trait_), false, None)
+}
+
+pub(crate) fn generate_trait_impl_intransitive_with_item(
+ make: &SyntaxFactory,
+ adt: &ast::Adt,
+ trait_: ast::Type,
+ body: ast::AssocItemList,
+) -> ast::Impl {
+ generate_impl_inner_with_factory(make, false, adt, Some(trait_), false, Some(body))
}
fn generate_impl_inner(
@@ -752,6 +828,76 @@ fn generate_impl_inner(
.clone_for_update()
}
+fn generate_impl_inner_with_factory(
+ make: &SyntaxFactory,
+ is_unsafe: bool,
+ adt: &ast::Adt,
+ trait_: Option<ast::Type>,
+ trait_is_transitive: bool,
+ body: Option<ast::AssocItemList>,
+) -> ast::Impl {
+ // Ensure lifetime params are before type & const params
+ let generic_params = adt.generic_param_list().map(|generic_params| {
+ let lifetime_params =
+ generic_params.lifetime_params().map(ast::GenericParam::LifetimeParam);
+ let ty_or_const_params = generic_params.type_or_const_params().filter_map(|param| {
+ let param = match param {
+ ast::TypeOrConstParam::Type(param) => {
+ // remove defaults since they can't be specified in impls
+ let mut bounds =
+ param.type_bound_list().map_or_else(Vec::new, |it| it.bounds().collect());
+ if let Some(trait_) = &trait_ {
+ // Add the current trait to `bounds` if the trait is transitive,
+ // meaning `impl<T> Trait for U<T>` requires `T: Trait`.
+ if trait_is_transitive {
+ bounds.push(make.type_bound(trait_.clone()));
+ }
+ };
+ // `{ty_param}: {bounds}`
+ let param = make.type_param(param.name()?, make.type_bound_list(bounds));
+ ast::GenericParam::TypeParam(param)
+ }
+ ast::TypeOrConstParam::Const(param) => {
+ // remove defaults since they can't be specified in impls
+ let param = make.const_param(param.name()?, param.ty()?);
+ ast::GenericParam::ConstParam(param)
+ }
+ };
+ Some(param)
+ });
+
+ make.generic_param_list(itertools::chain(lifetime_params, ty_or_const_params))
+ });
+ let generic_args =
+ generic_params.as_ref().map(|params| params.to_generic_args().clone_for_update());
+ let adt_assoc_bounds =
+ trait_.as_ref().zip(generic_params.as_ref()).and_then(|(trait_, params)| {
+ generic_param_associated_bounds_with_factory(make, adt, trait_, params)
+ });
+
+ let ty: ast::Type = make.ty_path(make.ident_path(&adt.name().unwrap().text())).into();
+
+ let cfg_attrs =
+ adt.attrs().filter(|attr| attr.as_simple_call().is_some_and(|(name, _arg)| name == "cfg"));
+ match trait_ {
+ Some(trait_) => make.impl_trait(
+ cfg_attrs,
+ is_unsafe,
+ None,
+ None,
+ generic_params,
+ generic_args,
+ false,
+ trait_,
+ ty,
+ adt_assoc_bounds,
+ adt.where_clause(),
+ body,
+ ),
+ None => make.impl_(cfg_attrs, generic_params, generic_args, ty, adt.where_clause(), body),
+ }
+}
+
fn generic_param_associated_bounds(
adt: &ast::Adt,
trait_: &ast::Type,
@@ -797,6 +943,52 @@ fn generic_param_associated_bounds(
trait_where_clause.peek().is_some().then(|| make::where_clause(trait_where_clause))
}
+fn generic_param_associated_bounds_with_factory(
+ make: &SyntaxFactory,
+ adt: &ast::Adt,
+ trait_: &ast::Type,
+ generic_params: &ast::GenericParamList,
+) -> Option<ast::WhereClause> {
+ let in_type_params = |name: &ast::NameRef| {
+ generic_params
+ .generic_params()
+ .filter_map(|param| match param {
+ ast::GenericParam::TypeParam(type_param) => type_param.name(),
+ _ => None,
+ })
+ .any(|param| param.text() == name.text())
+ };
+ let adt_body = match adt {
+ ast::Adt::Enum(e) => e.variant_list().map(|it| it.syntax().clone()),
+ ast::Adt::Struct(s) => s.field_list().map(|it| it.syntax().clone()),
+ ast::Adt::Union(u) => u.record_field_list().map(|it| it.syntax().clone()),
+ };
+ let mut trait_where_clause = adt_body
+ .into_iter()
+ .flat_map(|it| it.descendants())
+ .filter_map(ast::Path::cast)
+ .filter_map(|path| {
+ let qualifier = path.qualifier()?.as_single_segment()?;
+ let qualifier = qualifier
+ .name_ref()
+ .or_else(|| match qualifier.type_anchor()?.ty()? {
+ ast::Type::PathType(path_type) => path_type.path()?.as_single_name_ref(),
+ _ => None,
+ })
+ .filter(in_type_params)?;
+ Some((qualifier, path.segment()?.name_ref()?))
+ })
+ .map(|(qualifier, assoc_name)| {
+ let segments = [qualifier, assoc_name].map(|nr| make.path_segment(nr));
+ let path = make.path_from_segments(segments, false);
+ let bounds = [make.type_bound(trait_.clone())];
+ make.where_pred(either::Either::Right(make.ty_path(path).into()), bounds)
+ })
+ .unique_by(|it| it.syntax().to_string())
+ .peekable();
+ trait_where_clause.peek().is_some().then(|| make.where_clause(trait_where_clause))
+}
+
pub(crate) fn add_method_to_adt(
builder: &mut SourceChangeBuilder,
adt: &ast::Adt,
@@ -843,8 +1035,8 @@ enum ReferenceConversionType {
}
impl<'db> ReferenceConversion<'db> {
- pub(crate) fn convert_type(&self, db: &'db dyn HirDatabase, module: hir::Module) -> ast::Type {
- let ty = match self.conversion {
+ fn type_to_string(&self, db: &'db dyn HirDatabase, module: hir::Module) -> String {
+ match self.conversion {
ReferenceConversionType::Copy => self
.ty
.display_source_code(db, module.into(), true)
@@ -894,25 +1086,38 @@ impl<'db> ReferenceConversion<'db> {
.unwrap_or_else(|_| "_".to_owned());
format!("Result<&{first_type_argument_name}, &{second_type_argument_name}>")
}
- };
+ }
+ }
+ pub(crate) fn convert_type(&self, db: &'db dyn HirDatabase, module: hir::Module) -> ast::Type {
+ let ty = self.type_to_string(db, module);
make::ty(&ty)
}
- pub(crate) fn getter(&self, field_name: String) -> ast::Expr {
- let expr = make::expr_field(make::ext::expr_self(), &field_name);
+ pub(crate) fn convert_type_with_factory(
+ &self,
+ make: &SyntaxFactory,
+ db: &'db dyn HirDatabase,
+ module: hir::Module,
+ ) -> ast::Type {
+ let ty = self.type_to_string(db, module);
+ make.ty(&ty)
+ }
+
+ pub(crate) fn getter(&self, make: &SyntaxFactory, field_name: String) -> ast::Expr {
+ let expr = make.expr_field(make.expr_self(), &field_name);
match self.conversion {
- ReferenceConversionType::Copy => expr,
+ ReferenceConversionType::Copy => expr.into(),
ReferenceConversionType::AsRefStr
| ReferenceConversionType::AsRefSlice
| ReferenceConversionType::Dereferenced
| ReferenceConversionType::Option
| ReferenceConversionType::Result => {
if self.impls_deref {
- make::expr_ref(expr, false)
+ make.expr_ref(expr.into(), false)
} else {
- make::expr_method_call(expr, make::name_ref("as_ref"), make::arg_list([]))
+ make.expr_method_call(expr.into(), make.name_ref("as_ref"), make.arg_list([]))
.into()
}
}
@@ -1218,10 +1423,10 @@ pub(crate) fn cover_let_chain(mut expr: ast::Expr, range: TextRange) -> Option<a
}
pub(crate) fn cover_edit_range(
- source: &impl AstNode,
+ source: &SyntaxNode,
range: TextRange,
) -> std::ops::RangeInclusive<syntax::SyntaxElement> {
- let node = match source.syntax().covering_element(range) {
+ let node = match source.covering_element(range) {
NodeOrToken::Node(node) => node,
NodeOrToken::Token(t) => t.parent().unwrap(),
};
diff --git a/crates/ide-completion/src/completions.rs b/crates/ide-completion/src/completions.rs
index 355687b203..1fb1fd4e57 100644
--- a/crates/ide-completion/src/completions.rs
+++ b/crates/ide-completion/src/completions.rs
@@ -26,7 +26,7 @@ pub(crate) mod vis;
use std::iter;
-use hir::{HasAttrs, Name, ScopeDef, Variant, sym};
+use hir::{EnumVariant, HasAttrs, Name, ScopeDef, sym};
use ide_db::{RootDatabase, SymbolKind, imports::import_assets::LocatedImport};
use syntax::{SmolStr, ToSmolStr, ast};
@@ -426,7 +426,7 @@ impl Completions {
&mut self,
ctx: &CompletionContext<'_>,
path_ctx: &PathCompletionCtx<'_>,
- variant: hir::Variant,
+ variant: hir::EnumVariant,
path: hir::ModPath,
) {
if !ctx.check_stability_and_hidden(variant) {
@@ -443,7 +443,7 @@ impl Completions {
&mut self,
ctx: &CompletionContext<'_>,
path_ctx: &PathCompletionCtx<'_>,
- variant: hir::Variant,
+ variant: hir::EnumVariant,
local_name: Option<hir::Name>,
) {
if !ctx.check_stability_and_hidden(variant) {
@@ -569,7 +569,7 @@ impl Completions {
ctx: &CompletionContext<'_>,
pattern_ctx: &PatternContext,
path_ctx: Option<&PathCompletionCtx<'_>>,
- variant: hir::Variant,
+ variant: hir::EnumVariant,
local_name: Option<hir::Name>,
) {
if !ctx.check_stability_and_hidden(variant) {
@@ -589,7 +589,7 @@ impl Completions {
&mut self,
ctx: &CompletionContext<'_>,
pattern_ctx: &PatternContext,
- variant: hir::Variant,
+ variant: hir::EnumVariant,
path: hir::ModPath,
) {
if !ctx.check_stability_and_hidden(variant) {
@@ -644,9 +644,9 @@ fn enum_variants_with_paths(
ctx: &CompletionContext<'_>,
enum_: hir::Enum,
impl_: Option<&ast::Impl>,
- cb: impl Fn(&mut Completions, &CompletionContext<'_>, hir::Variant, hir::ModPath),
+ cb: impl Fn(&mut Completions, &CompletionContext<'_>, hir::EnumVariant, hir::ModPath),
) {
- let mut process_variant = |variant: Variant| {
+ let mut process_variant = |variant: EnumVariant| {
let self_path = hir::ModPath::from_segments(
hir::PathKind::Plain,
iter::once(Name::new_symbol_root(sym::Self_)).chain(iter::once(variant.name(ctx.db))),
diff --git a/crates/ide-completion/src/completions/pattern.rs b/crates/ide-completion/src/completions/pattern.rs
index 6e9328165d..e7597bf95c 100644
--- a/crates/ide-completion/src/completions/pattern.rs
+++ b/crates/ide-completion/src/completions/pattern.rs
@@ -91,7 +91,7 @@ pub(crate) fn complete_pattern(
acc.add_struct_pat(ctx, pattern_ctx, strukt, Some(name.clone()));
true
}
- hir::ModuleDef::Variant(variant)
+ hir::ModuleDef::EnumVariant(variant)
if refutable || single_variant_enum(variant.parent_enum(ctx.db)) =>
{
acc.add_variant_pat(ctx, pattern_ctx, None, variant, Some(name.clone()));
@@ -190,7 +190,7 @@ pub(crate) fn complete_pattern_path(
let add_completion = match res {
ScopeDef::ModuleDef(hir::ModuleDef::Macro(mac)) => mac.is_fn_like(ctx.db),
ScopeDef::ModuleDef(hir::ModuleDef::Adt(_)) => true,
- ScopeDef::ModuleDef(hir::ModuleDef::Variant(_)) => true,
+ ScopeDef::ModuleDef(hir::ModuleDef::EnumVariant(_)) => true,
ScopeDef::ModuleDef(hir::ModuleDef::Module(_)) => true,
ScopeDef::ImplSelfType(_) => true,
_ => false,
diff --git a/crates/ide-completion/src/completions/type.rs b/crates/ide-completion/src/completions/type.rs
index abcf9fca6f..8ff9c3258e 100644
--- a/crates/ide-completion/src/completions/type.rs
+++ b/crates/ide-completion/src/completions/type.rs
@@ -23,7 +23,9 @@ pub(crate) fn complete_type_path(
ScopeDef::GenericParam(LifetimeParam(_)) => location.complete_lifetimes(),
ScopeDef::Label(_) => false,
// no values in type places
- ScopeDef::ModuleDef(Function(_) | Variant(_) | Static(_)) | ScopeDef::Local(_) => false,
+ ScopeDef::ModuleDef(Function(_) | EnumVariant(_) | Static(_)) | ScopeDef::Local(_) => {
+ false
+ }
// unless its a constant in a generic arg list position
ScopeDef::ModuleDef(Const(_)) | ScopeDef::GenericParam(ConstParam(_)) => {
location.complete_consts()
diff --git a/crates/ide-completion/src/context.rs b/crates/ide-completion/src/context.rs
index 97afd07b00..4fd0348156 100644
--- a/crates/ide-completion/src/context.rs
+++ b/crates/ide-completion/src/context.rs
@@ -288,7 +288,7 @@ pub(crate) struct PatternContext {
pub(crate) record_pat: Option<ast::RecordPat>,
pub(crate) impl_or_trait: Option<Either<ast::Impl, ast::Trait>>,
/// List of missing variants in a match expr
- pub(crate) missing_variants: Vec<hir::Variant>,
+ pub(crate) missing_variants: Vec<hir::EnumVariant>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
@@ -527,7 +527,7 @@ impl CompletionContext<'_> {
hir::ModuleDef::Module(it) => self.is_visible(it),
hir::ModuleDef::Function(it) => self.is_visible(it),
hir::ModuleDef::Adt(it) => self.is_visible(it),
- hir::ModuleDef::Variant(it) => self.is_visible(it),
+ hir::ModuleDef::EnumVariant(it) => self.is_visible(it),
hir::ModuleDef::Const(it) => self.is_visible(it),
hir::ModuleDef::Static(it) => self.is_visible(it),
hir::ModuleDef::Trait(it) => self.is_visible(it),
diff --git a/crates/ide-completion/src/context/analysis.rs b/crates/ide-completion/src/context/analysis.rs
index bf899539a2..a3494b964f 100644
--- a/crates/ide-completion/src/context/analysis.rs
+++ b/crates/ide-completion/src/context/analysis.rs
@@ -1,7 +1,7 @@
//! Module responsible for analyzing the code surrounding the cursor for completion.
use std::iter;
-use hir::{ExpandResult, InFile, Semantics, Type, TypeInfo, Variant};
+use hir::{EnumVariant, ExpandResult, InFile, Semantics, Type, TypeInfo};
use ide_db::{
RootDatabase, active_parameter::ActiveParameter, syntax_helpers::node_ext::find_loops,
};
@@ -781,7 +781,7 @@ fn expected_type_and_name<'db>(
ast::TupleStructPat(it) => {
let fields = it.path().and_then(|path| match sema.resolve_path(&path)? {
hir::PathResolution::Def(hir::ModuleDef::Adt(adt)) => Some(adt.as_struct()?.fields(sema.db)),
- hir::PathResolution::Def(hir::ModuleDef::Variant(variant)) => Some(variant.fields(sema.db)),
+ hir::PathResolution::Def(hir::ModuleDef::EnumVariant(variant)) => Some(variant.fields(sema.db)),
_ => None,
});
let nr = it.fields().take_while(|it| it.syntax().text_range().end() <= token.text_range().start()).count();
@@ -1149,7 +1149,7 @@ fn classify_name_ref<'db>(
hir::ModuleDef::Adt(adt) => {
sema.source(adt)?.value.generic_param_list()
}
- hir::ModuleDef::Variant(variant) => {
+ hir::ModuleDef::EnumVariant(variant) => {
sema.source(variant.parent_enum(sema.db))?.value.generic_param_list()
}
hir::ModuleDef::Trait(trait_) => {
@@ -1825,7 +1825,7 @@ fn pattern_context_for(
});
(!variant_already_present).then_some(*variant)
- }).collect::<Vec<Variant>>())
+ }).collect::<Vec<EnumVariant>>())
});
if let Some(missing_variants_) = missing_variants_opt {
diff --git a/crates/ide-completion/src/render.rs b/crates/ide-completion/src/render.rs
index 765304d818..d77e793295 100644
--- a/crates/ide-completion/src/render.rs
+++ b/crates/ide-completion/src/render.rs
@@ -408,7 +408,7 @@ fn render_resolution_path(
let ctx = ctx.import_to_add(import_to_add);
return render_fn(ctx, path_ctx, Some(local_name), func);
}
- ScopeDef::ModuleDef(Variant(var)) => {
+ ScopeDef::ModuleDef(EnumVariant(var)) => {
let ctx = ctx.clone().import_to_add(import_to_add.clone());
if let Some(item) =
render_variant_lit(ctx, path_ctx, Some(local_name.clone()), var, None)
@@ -476,7 +476,7 @@ fn render_resolution_path(
}
// Filtered out above
ScopeDef::ModuleDef(
- ModuleDef::Function(_) | ModuleDef::Variant(_) | ModuleDef::Macro(_),
+ ModuleDef::Function(_) | ModuleDef::EnumVariant(_) | ModuleDef::Macro(_),
) => (),
ScopeDef::ModuleDef(ModuleDef::Const(konst)) => set_item_relevance(konst.ty(db)),
ScopeDef::ModuleDef(ModuleDef::Static(stat)) => set_item_relevance(stat.ty(db)),
@@ -528,7 +528,7 @@ fn res_to_kind(resolution: ScopeDef) -> CompletionItemKind {
match resolution {
ScopeDef::Unknown => CompletionItemKind::UnresolvedReference,
ScopeDef::ModuleDef(Function(_)) => CompletionItemKind::SymbolKind(SymbolKind::Function),
- ScopeDef::ModuleDef(Variant(_)) => CompletionItemKind::SymbolKind(SymbolKind::Variant),
+ ScopeDef::ModuleDef(EnumVariant(_)) => CompletionItemKind::SymbolKind(SymbolKind::Variant),
ScopeDef::ModuleDef(Macro(_)) => CompletionItemKind::SymbolKind(SymbolKind::Macro),
ScopeDef::ModuleDef(Module(..)) => CompletionItemKind::SymbolKind(SymbolKind::Module),
ScopeDef::ModuleDef(Adt(adt)) => CompletionItemKind::SymbolKind(match adt {
@@ -559,7 +559,7 @@ fn scope_def_docs(db: &RootDatabase, resolution: ScopeDef) -> Option<Documentati
match resolution {
ScopeDef::ModuleDef(Module(it)) => it.docs(db),
ScopeDef::ModuleDef(Adt(it)) => it.docs(db),
- ScopeDef::ModuleDef(Variant(it)) => it.docs(db),
+ ScopeDef::ModuleDef(EnumVariant(it)) => it.docs(db),
ScopeDef::ModuleDef(Const(it)) => it.docs(db),
ScopeDef::ModuleDef(Static(it)) => it.docs(db),
ScopeDef::ModuleDef(Trait(it)) => it.docs(db),
diff --git a/crates/ide-completion/src/render/literal.rs b/crates/ide-completion/src/render/literal.rs
index 8b14f05b72..6e49af980a 100644
--- a/crates/ide-completion/src/render/literal.rs
+++ b/crates/ide-completion/src/render/literal.rs
@@ -23,7 +23,7 @@ pub(crate) fn render_variant_lit(
ctx: RenderContext<'_>,
path_ctx: &PathCompletionCtx<'_>,
local_name: Option<hir::Name>,
- variant: hir::Variant,
+ variant: hir::EnumVariant,
path: Option<hir::ModPath>,
) -> Option<Builder> {
let _p = tracing::info_span!("render_variant_lit").entered();
@@ -150,7 +150,7 @@ fn render(
#[derive(Clone, Copy)]
enum Variant {
Struct(hir::Struct),
- EnumVariant(hir::Variant),
+ EnumVariant(hir::EnumVariant),
}
impl Variant {
diff --git a/crates/ide-completion/src/render/pattern.rs b/crates/ide-completion/src/render/pattern.rs
index 60474a31b4..fb35d7b9b6 100644
--- a/crates/ide-completion/src/render/pattern.rs
+++ b/crates/ide-completion/src/render/pattern.rs
@@ -47,7 +47,7 @@ pub(crate) fn render_variant_pat(
ctx: RenderContext<'_>,
pattern_ctx: &PatternContext,
path_ctx: Option<&PathCompletionCtx<'_>>,
- variant: hir::Variant,
+ variant: hir::EnumVariant,
local_name: Option<Name>,
path: Option<&hir::ModPath>,
) -> Option<CompletionItem> {
diff --git a/crates/ide-db/src/active_parameter.rs b/crates/ide-db/src/active_parameter.rs
index f5a5b76c33..8bd4c6c46b 100644
--- a/crates/ide-db/src/active_parameter.rs
+++ b/crates/ide-db/src/active_parameter.rs
@@ -113,7 +113,7 @@ pub fn generic_def_for_node(
sema: &Semantics<'_, RootDatabase>,
generic_arg_list: &ast::GenericArgList,
token: &SyntaxToken,
-) -> Option<(hir::GenericDef, usize, bool, Option<hir::Variant>)> {
+) -> Option<(hir::GenericDef, usize, bool, Option<hir::EnumVariant>)> {
let parent = generic_arg_list.syntax().parent()?;
let mut variant = None;
let def = match_ast! {
@@ -125,7 +125,7 @@ pub fn generic_def_for_node(
hir::PathResolution::Def(hir::ModuleDef::Function(it)) => it.into(),
hir::PathResolution::Def(hir::ModuleDef::Trait(it)) => it.into(),
hir::PathResolution::Def(hir::ModuleDef::TypeAlias(it)) => it.into(),
- hir::PathResolution::Def(hir::ModuleDef::Variant(it)) => {
+ hir::PathResolution::Def(hir::ModuleDef::EnumVariant(it)) => {
variant = Some(it);
it.parent_enum(sema.db).into()
},
diff --git a/crates/ide-db/src/defs.rs b/crates/ide-db/src/defs.rs
index 788f9b73fa..82cff37296 100644
--- a/crates/ide-db/src/defs.rs
+++ b/crates/ide-db/src/defs.rs
@@ -14,11 +14,12 @@ use arrayvec::ArrayVec;
use either::Either;
use hir::{
Adt, AsAssocItem, AsExternAssocItem, AssocItem, AttributeTemplate, BuiltinAttr, BuiltinType,
- Const, Crate, DefWithBody, DeriveHelper, DisplayTarget, DocLinkDef, ExternAssocItem,
- ExternCrateDecl, Field, Function, GenericDef, GenericParam, GenericSubstitution, HasContainer,
- HasVisibility, HirDisplay, Impl, InlineAsmOperand, ItemContainer, Label, Local, Macro, Module,
- ModuleDef, Name, PathResolution, Semantics, Static, StaticLifetime, Struct, ToolModule, Trait,
- TupleField, TypeAlias, Variant, VariantDef, Visibility,
+ Const, Crate, DefWithBody, DeriveHelper, DisplayTarget, DocLinkDef, EnumVariant,
+ ExpressionStoreOwner, ExternAssocItem, ExternCrateDecl, Field, Function, GenericDef,
+ GenericParam, GenericSubstitution, HasContainer, HasVisibility, HirDisplay, Impl,
+ InlineAsmOperand, ItemContainer, Label, Local, Macro, Module, ModuleDef, Name, PathResolution,
+ Semantics, Static, StaticLifetime, Struct, ToolModule, Trait, TupleField, TypeAlias, Variant,
+ Visibility,
};
use span::Edition;
use stdx::{format_to, impl_from};
@@ -38,7 +39,7 @@ pub enum Definition {
Crate(Crate),
Function(Function),
Adt(Adt),
- Variant(Variant),
+ EnumVariant(EnumVariant),
Const(Const),
Static(Static),
Trait(Trait),
@@ -85,7 +86,7 @@ impl Definition {
Definition::Static(it) => it.module(db),
Definition::Trait(it) => it.module(db),
Definition::TypeAlias(it) => it.module(db),
- Definition::Variant(it) => it.module(db),
+ Definition::EnumVariant(it) => it.module(db),
Definition::SelfType(it) => it.module(db),
Definition::Local(it) => it.module(db),
Definition::GenericParam(it) => it.module(db),
@@ -123,7 +124,7 @@ impl Definition {
Definition::Static(it) => container_to_definition(it.container(db)),
Definition::Trait(it) => container_to_definition(it.container(db)),
Definition::TypeAlias(it) => container_to_definition(it.container(db)),
- Definition::Variant(it) => Some(Adt::Enum(it.parent_enum(db)).into()),
+ Definition::EnumVariant(it) => Some(Adt::Enum(it.parent_enum(db)).into()),
Definition::SelfType(it) => Some(it.module(db).into()),
Definition::Local(it) => it.parent(db).try_into().ok(),
Definition::GenericParam(it) => Some(it.parent().into()),
@@ -151,7 +152,7 @@ impl Definition {
Definition::Static(it) => it.visibility(db),
Definition::Trait(it) => it.visibility(db),
Definition::TypeAlias(it) => it.visibility(db),
- Definition::Variant(it) => it.visibility(db),
+ Definition::EnumVariant(it) => it.visibility(db),
Definition::ExternCrateDecl(it) => it.visibility(db),
Definition::Macro(it) => it.visibility(db),
Definition::BuiltinType(_) | Definition::TupleField(_) => Visibility::Public,
@@ -179,7 +180,7 @@ impl Definition {
}
Definition::Function(it) => it.name(db),
Definition::Adt(it) => it.name(db),
- Definition::Variant(it) => it.name(db),
+ Definition::EnumVariant(it) => it.name(db),
Definition::Const(it) => it.name(db)?,
Definition::Static(it) => it.name(db),
Definition::Trait(it) => it.name(db),
@@ -227,7 +228,7 @@ impl Definition {
Definition::Crate(it) => it.docs_with_rangemap(db),
Definition::Function(it) => it.docs_with_rangemap(db),
Definition::Adt(it) => it.docs_with_rangemap(db),
- Definition::Variant(it) => it.docs_with_rangemap(db),
+ Definition::EnumVariant(it) => it.docs_with_rangemap(db),
Definition::Const(it) => it.docs_with_rangemap(db),
Definition::Static(it) => it.docs_with_rangemap(db),
Definition::Trait(it) => it.docs_with_rangemap(db),
@@ -315,7 +316,7 @@ impl Definition {
Definition::Crate(it) => it.display(db, display_target).to_string(),
Definition::Function(it) => it.display(db, display_target).to_string(),
Definition::Adt(it) => it.display(db, display_target).to_string(),
- Definition::Variant(it) => it.display(db, display_target).to_string(),
+ Definition::EnumVariant(it) => it.display(db, display_target).to_string(),
Definition::Const(it) => it.display(db, display_target).to_string(),
Definition::Static(it) => it.display(db, display_target).to_string(),
Definition::Trait(it) => it.display(db, display_target).to_string(),
@@ -556,7 +557,7 @@ impl<'db> NameClass<'db> {
ast::Rename(it) => classify_rename(sema, it)?,
ast::SelfParam(it) => Definition::Local(sema.to_def(&it)?),
ast::RecordField(it) => Definition::Field(sema.to_def(&it)?),
- ast::Variant(it) => Definition::Variant(sema.to_def(&it)?),
+ ast::Variant(it) => Definition::EnumVariant(sema.to_def(&it)?),
ast::TypeParam(it) => Definition::GenericParam(sema.to_def(&it)?.into()),
ast::ConstParam(it) => Definition::GenericParam(sema.to_def(&it)?.into()),
ast::AsmOperandNamed(it) => Definition::InlineAsmOperand(sema.to_def(&it)?),
@@ -848,7 +849,7 @@ impl<'db> NameRefClass<'db> {
ast::OffsetOfExpr(_) => {
let (def, subst) = sema.resolve_offset_of_field(name_ref)?;
let def = match def {
- Either::Left(variant) => Definition::Variant(variant),
+ Either::Left(variant) => Definition::EnumVariant(variant),
Either::Right(field) => Definition::Field(field),
};
Some(NameRefClass::Definition(def, Some(subst)))
@@ -891,7 +892,7 @@ impl<'db> NameRefClass<'db> {
}
impl_from!(
- Field, Module, Function, Adt, Variant, Const, Static, Trait, TypeAlias, BuiltinType, Local,
+ Field, Module, Function, Adt, EnumVariant, Const, Static, Trait, TypeAlias, BuiltinType, Local,
GenericParam, Label, Macro, ExternCrateDecl
for Definition
);
@@ -967,7 +968,7 @@ impl From<ModuleDef> for Definition {
ModuleDef::Module(it) => Definition::Module(it),
ModuleDef::Function(it) => Definition::Function(it),
ModuleDef::Adt(it) => Definition::Adt(it),
- ModuleDef::Variant(it) => Definition::Variant(it),
+ ModuleDef::EnumVariant(it) => Definition::EnumVariant(it),
ModuleDef::Const(it) => Definition::Const(it),
ModuleDef::Static(it) => Definition::Static(it),
ModuleDef::Trait(it) => Definition::Trait(it),
@@ -988,8 +989,8 @@ impl From<DocLinkDef> for Definition {
}
}
-impl From<VariantDef> for Definition {
- fn from(def: VariantDef) -> Self {
+impl From<Variant> for Definition {
+ fn from(def: Variant) -> Self {
ModuleDef::from(def).into()
}
}
@@ -1001,7 +1002,7 @@ impl TryFrom<DefWithBody> for Definition {
DefWithBody::Function(it) => Ok(it.into()),
DefWithBody::Static(it) => Ok(it.into()),
DefWithBody::Const(it) => Ok(it.into()),
- DefWithBody::Variant(it) => Ok(it.into()),
+ DefWithBody::EnumVariant(it) => Ok(it.into()),
}
}
}
@@ -1020,6 +1021,17 @@ impl From<GenericDef> for Definition {
}
}
+impl TryFrom<ExpressionStoreOwner> for Definition {
+ type Error = ();
+ fn try_from(def: ExpressionStoreOwner) -> Result<Self, Self::Error> {
+ match def {
+ ExpressionStoreOwner::Body(def_with_body) => def_with_body.try_into(),
+ ExpressionStoreOwner::Signature(generic_def) => Ok(generic_def.into()),
+ ExpressionStoreOwner::VariantFields(it) => Ok(it.into()),
+ }
+ }
+}
+
impl TryFrom<Definition> for GenericDef {
type Error = ();
fn try_from(def: Definition) -> Result<Self, Self::Error> {
diff --git a/crates/ide-db/src/documentation.rs b/crates/ide-db/src/documentation.rs
index 4c4691cca2..407049f4b3 100644
--- a/crates/ide-db/src/documentation.rs
+++ b/crates/ide-db/src/documentation.rs
@@ -58,8 +58,22 @@ macro_rules! impl_has_docs {
}
impl_has_docs![
- Variant, Field, Static, Const, Trait, TypeAlias, Macro, Function, Adt, Module, Impl, Crate,
- AssocItem, Struct, Union, Enum,
+ EnumVariant,
+ Field,
+ Static,
+ Const,
+ Trait,
+ TypeAlias,
+ Macro,
+ Function,
+ Adt,
+ Module,
+ Impl,
+ Crate,
+ AssocItem,
+ Struct,
+ Union,
+ Enum,
];
impl HasDocs for hir::ExternCrateDecl {
diff --git a/crates/ide-db/src/lib.rs b/crates/ide-db/src/lib.rs
index 023b32b361..cde0705d8a 100644
--- a/crates/ide-db/src/lib.rs
+++ b/crates/ide-db/src/lib.rs
@@ -312,7 +312,7 @@ impl SymbolKind {
pub fn from_module_def(db: &dyn HirDatabase, it: hir::ModuleDef) -> Self {
match it {
hir::ModuleDef::Const(..) => SymbolKind::Const,
- hir::ModuleDef::Variant(..) => SymbolKind::Variant,
+ hir::ModuleDef::EnumVariant(..) => SymbolKind::Variant,
hir::ModuleDef::Function(..) => SymbolKind::Function,
hir::ModuleDef::Macro(mac) if mac.is_proc_macro() => SymbolKind::ProcMacro,
hir::ModuleDef::Macro(..) => SymbolKind::Macro,
diff --git a/crates/ide-db/src/path_transform.rs b/crates/ide-db/src/path_transform.rs
index 01a326a0dc..508f841340 100644
--- a/crates/ide-db/src/path_transform.rs
+++ b/crates/ide-db/src/path_transform.rs
@@ -580,7 +580,7 @@ impl Ctx<'_> {
}
}
- if let hir::ModuleDef::Variant(v) = def
+ if let hir::ModuleDef::EnumVariant(v) = def
&& v.kind(self.source_scope.db) != hir::StructKind::Unit
{
return None;
diff --git a/crates/ide-db/src/prime_caches.rs b/crates/ide-db/src/prime_caches.rs
index 015b06e8e0..d264428212 100644
--- a/crates/ide-db/src/prime_caches.rs
+++ b/crates/ide-db/src/prime_caches.rs
@@ -4,7 +4,7 @@
//! various caches, it's not really advanced at the moment.
use std::panic::AssertUnwindSafe;
-use hir::{Symbol, db::DefDatabase};
+use hir::{Symbol, import_map::ImportMap};
use rustc_hash::FxHashMap;
use salsa::{Cancelled, Database};
@@ -123,7 +123,7 @@ pub fn parallel_prime_caches(
Ok::<_, crossbeam_channel::SendError<_>>(())
};
let handle_import_map = |crate_id| {
- let cancelled = Cancelled::catch(|| _ = db.import_map(crate_id));
+ let cancelled = Cancelled::catch(|| _ = ImportMap::of(&db, crate_id));
match cancelled {
Ok(()) => {
diff --git a/crates/ide-db/src/rename.rs b/crates/ide-db/src/rename.rs
index b03a5b6efb..b18ed69d80 100644
--- a/crates/ide-db/src/rename.rs
+++ b/crates/ide-db/src/rename.rs
@@ -170,7 +170,7 @@ impl Definition {
hir::Adt::Union(it) => name_range(it, sema).and_then(syn_ctx_is_root),
hir::Adt::Enum(it) => name_range(it, sema).and_then(syn_ctx_is_root),
},
- Definition::Variant(it) => name_range(it, sema).and_then(syn_ctx_is_root),
+ Definition::EnumVariant(it) => name_range(it, sema).and_then(syn_ctx_is_root),
Definition::Const(it) => name_range(it, sema).and_then(syn_ctx_is_root),
Definition::Static(it) => name_range(it, sema).and_then(syn_ctx_is_root),
Definition::Trait(it) => name_range(it, sema).and_then(syn_ctx_is_root),
diff --git a/crates/ide-db/src/search.rs b/crates/ide-db/src/search.rs
index 3822eaae2c..25acb47f7b 100644
--- a/crates/ide-db/src/search.rs
+++ b/crates/ide-db/src/search.rs
@@ -10,9 +10,9 @@ use std::{cell::LazyCell, cmp::Reverse};
use base_db::{RootQueryDb, SourceDatabase};
use either::Either;
use hir::{
- Adt, AsAssocItem, DefWithBody, EditionedFileId, FileRange, FileRangeWrapper, HasAttrs,
- HasContainer, HasSource, InFile, InFileWrapper, InRealFile, InlineAsmOperand, ItemContainer,
- ModuleSource, PathResolution, Semantics, Visibility,
+ Adt, AsAssocItem, DefWithBody, EditionedFileId, ExpressionStoreOwner, FileRange,
+ FileRangeWrapper, HasAttrs, HasContainer, HasSource, InFile, InFileWrapper, InRealFile,
+ InlineAsmOperand, ItemContainer, ModuleSource, PathResolution, Semantics, Visibility,
};
use memchr::memmem::Finder;
use parser::SyntaxKind;
@@ -310,10 +310,26 @@ impl Definition {
if let Definition::Local(var) = self {
let def = match var.parent(db) {
- DefWithBody::Function(f) => f.source(db).map(|src| src.syntax().cloned()),
- DefWithBody::Const(c) => c.source(db).map(|src| src.syntax().cloned()),
- DefWithBody::Static(s) => s.source(db).map(|src| src.syntax().cloned()),
- DefWithBody::Variant(v) => v.source(db).map(|src| src.syntax().cloned()),
+ ExpressionStoreOwner::Body(def) => match def {
+ DefWithBody::Function(f) => f.source(db).map(|src| src.syntax().cloned()),
+ DefWithBody::Const(c) => c.source(db).map(|src| src.syntax().cloned()),
+ DefWithBody::Static(s) => s.source(db).map(|src| src.syntax().cloned()),
+ DefWithBody::EnumVariant(v) => v.source(db).map(|src| src.syntax().cloned()),
+ },
+ ExpressionStoreOwner::Signature(def) => match def {
+ hir::GenericDef::Function(it) => it.source(db).map(|src| src.syntax().cloned()),
+ hir::GenericDef::Adt(it) => it.source(db).map(|src| src.syntax().cloned()),
+ hir::GenericDef::Trait(it) => it.source(db).map(|src| src.syntax().cloned()),
+ hir::GenericDef::TypeAlias(it) => {
+ it.source(db).map(|src| src.syntax().cloned())
+ }
+ hir::GenericDef::Impl(it) => it.source(db).map(|src| src.syntax().cloned()),
+ hir::GenericDef::Const(it) => it.source(db).map(|src| src.syntax().cloned()),
+ hir::GenericDef::Static(it) => it.source(db).map(|src| src.syntax().cloned()),
+ },
+ ExpressionStoreOwner::VariantFields(it) => {
+ it.source(db).map(|src| src.syntax().cloned())
+ }
};
return match def {
Some(def) => SearchScope::file_range(
@@ -325,10 +341,26 @@ impl Definition {
if let Definition::InlineAsmOperand(op) = self {
let def = match op.parent(db) {
- DefWithBody::Function(f) => f.source(db).map(|src| src.syntax().cloned()),
- DefWithBody::Const(c) => c.source(db).map(|src| src.syntax().cloned()),
- DefWithBody::Static(s) => s.source(db).map(|src| src.syntax().cloned()),
- DefWithBody::Variant(v) => v.source(db).map(|src| src.syntax().cloned()),
+ ExpressionStoreOwner::Body(def) => match def {
+ DefWithBody::Function(f) => f.source(db).map(|src| src.syntax().cloned()),
+ DefWithBody::Const(c) => c.source(db).map(|src| src.syntax().cloned()),
+ DefWithBody::Static(s) => s.source(db).map(|src| src.syntax().cloned()),
+ DefWithBody::EnumVariant(v) => v.source(db).map(|src| src.syntax().cloned()),
+ },
+ ExpressionStoreOwner::Signature(def) => match def {
+ hir::GenericDef::Function(it) => it.source(db).map(|src| src.syntax().cloned()),
+ hir::GenericDef::Adt(it) => it.source(db).map(|src| src.syntax().cloned()),
+ hir::GenericDef::Trait(it) => it.source(db).map(|src| src.syntax().cloned()),
+ hir::GenericDef::TypeAlias(it) => {
+ it.source(db).map(|src| src.syntax().cloned())
+ }
+ hir::GenericDef::Impl(it) => it.source(db).map(|src| src.syntax().cloned()),
+ hir::GenericDef::Const(it) => it.source(db).map(|src| src.syntax().cloned()),
+ hir::GenericDef::Static(it) => it.source(db).map(|src| src.syntax().cloned()),
+ },
+ ExpressionStoreOwner::VariantFields(it) => {
+ it.source(db).map(|src| src.syntax().cloned())
+ }
};
return match def {
Some(def) => SearchScope::file_range(
diff --git a/crates/ide-db/src/test_data/test_symbol_index_collection.txt b/crates/ide-db/src/test_data/test_symbol_index_collection.txt
index 46d938b5a5..02a023038a 100644
--- a/crates/ide-db/src/test_data/test_symbol_index_collection.txt
+++ b/crates/ide-db/src/test_data/test_symbol_index_collection.txt
@@ -8,8 +8,8 @@
[
FileSymbol {
name: "A",
- def: Variant(
- Variant {
+ def: EnumVariant(
+ EnumVariant {
id: EnumVariantId(
7c00,
),
@@ -80,8 +80,8 @@
},
FileSymbol {
name: "B",
- def: Variant(
- Variant {
+ def: EnumVariant(
+ EnumVariant {
id: EnumVariantId(
7c01,
),
diff --git a/crates/ide-diagnostics/src/handlers/missing_fields.rs b/crates/ide-diagnostics/src/handlers/missing_fields.rs
index d5f25dfaf2..050d5477f6 100644
--- a/crates/ide-diagnostics/src/handlers/missing_fields.rs
+++ b/crates/ide-diagnostics/src/handlers/missing_fields.rs
@@ -588,14 +588,14 @@ fn test_fn() {
fn test_fill_struct_fields_default() {
check_fix(
r#"
-//- minicore: default, option
+//- minicore: default, option, slice
struct TestWithDefault(usize);
impl Default for TestWithDefault {
pub fn default() -> Self {
Self(0)
}
}
-struct TestStruct { one: i32, two: TestWithDefault }
+struct TestStruct { one: i32, two: TestWithDefault, r: &'static [i32] }
fn test_fn() {
let s = TestStruct{ $0 };
@@ -608,10 +608,10 @@ impl Default for TestWithDefault {
Self(0)
}
}
-struct TestStruct { one: i32, two: TestWithDefault }
+struct TestStruct { one: i32, two: TestWithDefault, r: &'static [i32] }
fn test_fn() {
- let s = TestStruct{ one: 0, two: TestWithDefault::default() };
+ let s = TestStruct{ one: 0, two: TestWithDefault::default(), r: <&'static [i32]>::default() };
}
",
);
diff --git a/crates/ide-diagnostics/src/handlers/missing_lifetime.rs b/crates/ide-diagnostics/src/handlers/missing_lifetime.rs
index 5cb710b66b..b10cdaa14e 100644
--- a/crates/ide-diagnostics/src/handlers/missing_lifetime.rs
+++ b/crates/ide-diagnostics/src/handlers/missing_lifetime.rs
@@ -115,4 +115,20 @@ struct A<'a, T> {
"#,
);
}
+
+ // FIXME: Ideally, should emit generic default forbidden as well
+ #[test]
+ fn regression_16280() {
+ check_diagnostics(
+ r#"
+trait Traitor<'a, const M: Traitor = Traitor> {
+ fn crash<const Traitor: Traitor = Traitor, const M: Traitor = Traitor>(&self) -> Traitor {
+ // ^^^^^^^ error: missing lifetime specifier
+ // ^^^^^^^ error: missing lifetime specifier
+ Traitor
+ }
+}
+"#,
+ );
+ }
}
diff --git a/crates/ide-diagnostics/src/handlers/no_such_field.rs b/crates/ide-diagnostics/src/handlers/no_such_field.rs
index 619bb2307c..944622bb1d 100644
--- a/crates/ide-diagnostics/src/handlers/no_such_field.rs
+++ b/crates/ide-diagnostics/src/handlers/no_such_field.rs
@@ -64,20 +64,20 @@ fn missing_record_expr_field_fixes(
let module;
let def_file_id;
let record_fields = match def_id {
- hir::VariantDef::Struct(s) => {
+ hir::Variant::Struct(s) => {
module = s.module(sema.db);
let source = s.source(sema.db)?;
def_file_id = source.file_id;
let fields = source.value.field_list()?;
record_field_list(fields)?
}
- hir::VariantDef::Union(u) => {
+ hir::Variant::Union(u) => {
module = u.module(sema.db);
let source = u.source(sema.db)?;
def_file_id = source.file_id;
source.value.record_field_list()?
}
- hir::VariantDef::Variant(e) => {
+ hir::Variant::EnumVariant(e) => {
module = e.module(sema.db);
let source = e.source(sema.db)?;
def_file_id = source.file_id;
@@ -116,7 +116,7 @@ fn missing_record_expr_field_fixes(
let mut new_field = new_field.to_string();
// FIXME: check submodule instead of FileId
- if usage_file_id != def_file_id && !matches!(def_id, hir::VariantDef::Variant(_)) {
+ if usage_file_id != def_file_id && !matches!(def_id, hir::Variant::EnumVariant(_)) {
new_field = format!("pub(crate) {new_field}");
}
new_field = format!("\n{indent}{new_field}{postfix}");
diff --git a/crates/ide-diagnostics/src/handlers/trait_impl_redundant_assoc_item.rs b/crates/ide-diagnostics/src/handlers/trait_impl_redundant_assoc_item.rs
index cb3aac3717..f4054610f2 100644
--- a/crates/ide-diagnostics/src/handlers/trait_impl_redundant_assoc_item.rs
+++ b/crates/ide-diagnostics/src/handlers/trait_impl_redundant_assoc_item.rs
@@ -6,6 +6,7 @@ use ide_db::{
source_change::SourceChangeBuilder,
};
use syntax::ToSmolStr;
+use syntax::ast::edit::AstNodeEdit;
use crate::{Diagnostic, DiagnosticCode, DiagnosticsContext};
@@ -23,6 +24,7 @@ pub(crate) fn trait_impl_redundant_assoc_item(
let default_range = d.impl_.syntax_node_ptr().text_range();
let trait_name = d.trait_.name(db).display_no_db(ctx.edition).to_smolstr();
+ let indent_level = d.trait_.source(db).map_or(0, |it| it.value.indent_level().0) + 1;
let (redundant_item_name, diagnostic_range, redundant_item_def) = match assoc_item {
hir::AssocItem::Function(id) => {
@@ -30,7 +32,7 @@ pub(crate) fn trait_impl_redundant_assoc_item(
(
format!("`fn {redundant_assoc_item_name}`"),
function.source(db).map(|it| it.syntax().text_range()).unwrap_or(default_range),
- format!("\n {};", function.display(db, ctx.display_target)),
+ format!("\n{};", function.display(db, ctx.display_target)),
)
}
hir::AssocItem::Const(id) => {
@@ -38,7 +40,7 @@ pub(crate) fn trait_impl_redundant_assoc_item(
(
format!("`const {redundant_assoc_item_name}`"),
constant.source(db).map(|it| it.syntax().text_range()).unwrap_or(default_range),
- format!("\n {};", constant.display(db, ctx.display_target)),
+ format!("\n{};", constant.display(db, ctx.display_target)),
)
}
hir::AssocItem::TypeAlias(id) => {
@@ -46,10 +48,8 @@ pub(crate) fn trait_impl_redundant_assoc_item(
(
format!("`type {redundant_assoc_item_name}`"),
type_alias.source(db).map(|it| it.syntax().text_range()).unwrap_or(default_range),
- format!(
- "\n type {};",
- type_alias.name(ctx.sema.db).display_no_db(ctx.edition).to_smolstr()
- ),
+ // FIXME cannot generate generic parameter and bounds
+ format!("\ntype {};", type_alias.name(ctx.sema.db).display_no_db(ctx.edition)),
)
}
};
@@ -65,7 +65,7 @@ pub(crate) fn trait_impl_redundant_assoc_item(
.with_fixes(quickfix_for_redundant_assoc_item(
ctx,
d,
- redundant_item_def,
+ stdx::indent_string(&redundant_item_def, indent_level),
diagnostic_range,
))
}
@@ -192,6 +192,89 @@ impl Marker for Foo {
}
#[test]
+ fn quickfix_indentations() {
+ check_fix(
+ r#"
+mod indent {
+ trait Marker {
+ fn boo();
+ }
+ struct Foo;
+ impl Marker for Foo {
+ fn$0 bar<T: Copy>(_a: i32, _b: T) -> String {}
+ fn boo() {}
+ }
+}
+ "#,
+ r#"
+mod indent {
+ trait Marker {
+ fn bar<T>(_a: i32, _b: T) -> String
+ where
+ T: Copy,;
+ fn boo();
+ }
+ struct Foo;
+ impl Marker for Foo {
+ fn bar<T: Copy>(_a: i32, _b: T) -> String {}
+ fn boo() {}
+ }
+}
+ "#,
+ );
+
+ check_fix(
+ r#"
+mod indent {
+ trait Marker {
+ fn foo () {}
+ }
+ struct Foo;
+ impl Marker for Foo {
+ const FLAG: bool$0 = false;
+ }
+}
+ "#,
+ r#"
+mod indent {
+ trait Marker {
+ const FLAG: bool;
+ fn foo () {}
+ }
+ struct Foo;
+ impl Marker for Foo {
+ const FLAG: bool = false;
+ }
+}
+ "#,
+ );
+
+ check_fix(
+ r#"
+mod indent {
+ trait Marker {
+ }
+ struct Foo;
+ impl Marker for Foo {
+ type T = i32;$0
+ }
+}
+ "#,
+ r#"
+mod indent {
+ trait Marker {
+ type T;
+ }
+ struct Foo;
+ impl Marker for Foo {
+ type T = i32;
+ }
+}
+ "#,
+ );
+ }
+
+ #[test]
fn quickfix_dont_work() {
check_no_fix(
r#"
diff --git a/crates/ide-diagnostics/src/handlers/typed_hole.rs b/crates/ide-diagnostics/src/handlers/typed_hole.rs
index 577c582a20..fd1674e2a4 100644
--- a/crates/ide-diagnostics/src/handlers/typed_hole.rs
+++ b/crates/ide-diagnostics/src/handlers/typed_hole.rs
@@ -442,4 +442,30 @@ fn rdtscp() -> u64 {
}"#,
);
}
+
+ #[test]
+ fn asm_sym_with_macro_expr_fragment() {
+ // Regression test for issue #21582
+ // When `$e:expr` captures a path and is used in `sym $e`, the path gets
+ // wrapped in parentheses during macro expansion due to invisible delimiters.
+ // This should not cause false positive typed-hole errors.
+ check_diagnostics(
+ r#"
+//- minicore: asm
+macro_rules! m {
+ ($e:expr) => {
+ core::arch::asm!("/*{f}*/", f = sym $e, out("ax") _)
+ };
+}
+
+fn generic<T>() {}
+
+fn main() {
+ unsafe {
+ m!(generic::<i32>);
+ }
+}
+"#,
+ );
+ }
}
diff --git a/crates/ide/src/doc_links.rs b/crates/ide/src/doc_links.rs
index d854c1c450..33bed9501a 100644
--- a/crates/ide/src/doc_links.rs
+++ b/crates/ide/src/doc_links.rs
@@ -219,7 +219,7 @@ pub(crate) fn resolve_doc_path_for_def(
Definition::Crate(it) => it.resolve_doc_path(db, link, ns, is_inner_doc),
Definition::Function(it) => it.resolve_doc_path(db, link, ns, is_inner_doc),
Definition::Adt(it) => it.resolve_doc_path(db, link, ns, is_inner_doc),
- Definition::Variant(it) => it.resolve_doc_path(db, link, ns, is_inner_doc),
+ Definition::EnumVariant(it) => it.resolve_doc_path(db, link, ns, is_inner_doc),
Definition::Const(it) => it.resolve_doc_path(db, link, ns, is_inner_doc),
Definition::Static(it) => it.resolve_doc_path(db, link, ns, is_inner_doc),
Definition::Trait(it) => it.resolve_doc_path(db, link, ns, is_inner_doc),
@@ -678,7 +678,7 @@ fn filename_and_frag_for_def(
Definition::Function(f) => {
format!("fn.{}.html", f.name(db).as_str())
}
- Definition::Variant(ev) => {
+ Definition::EnumVariant(ev) => {
let def = Definition::Adt(ev.parent_enum(db).into());
let (_, file, _) = filename_and_frag_for_def(db, def)?;
return Some((def, file, Some(format!("variant.{}", ev.name(db).as_str()))));
@@ -703,9 +703,9 @@ fn filename_and_frag_for_def(
},
Definition::Field(field) => {
let def = match field.parent_def(db) {
- hir::VariantDef::Struct(it) => Definition::Adt(it.into()),
- hir::VariantDef::Union(it) => Definition::Adt(it.into()),
- hir::VariantDef::Variant(it) => Definition::Variant(it),
+ hir::Variant::Struct(it) => Definition::Adt(it.into()),
+ hir::Variant::Union(it) => Definition::Adt(it.into()),
+ hir::Variant::EnumVariant(it) => Definition::EnumVariant(it),
};
let (_, file, _) = filename_and_frag_for_def(db, def)?;
return Some((def, file, Some(format!("structfield.{}", field.name(db).as_str()))));
diff --git a/crates/ide/src/doc_links/tests.rs b/crates/ide/src/doc_links/tests.rs
index a61a6c677f..509c55a31e 100644
--- a/crates/ide/src/doc_links/tests.rs
+++ b/crates/ide/src/doc_links/tests.rs
@@ -113,7 +113,7 @@ fn node_to_def<'db>(
ast::Struct(it) => sema.to_def(&it).map(|def| (def.docs_with_rangemap(sema.db), Definition::Adt(hir::Adt::Struct(def)))),
ast::Union(it) => sema.to_def(&it).map(|def| (def.docs_with_rangemap(sema.db), Definition::Adt(hir::Adt::Union(def)))),
ast::Enum(it) => sema.to_def(&it).map(|def| (def.docs_with_rangemap(sema.db), Definition::Adt(hir::Adt::Enum(def)))),
- ast::Variant(it) => sema.to_def(&it).map(|def| (def.docs_with_rangemap(sema.db), Definition::Variant(def))),
+ ast::Variant(it) => sema.to_def(&it).map(|def| (def.docs_with_rangemap(sema.db), Definition::EnumVariant(def))),
ast::Trait(it) => sema.to_def(&it).map(|def| (def.docs_with_rangemap(sema.db), Definition::Trait(def))),
ast::Static(it) => sema.to_def(&it).map(|def| (def.docs_with_rangemap(sema.db), Definition::Static(def))),
ast::Const(it) => sema.to_def(&it).map(|def| (def.docs_with_rangemap(sema.db), Definition::Const(def))),
diff --git a/crates/ide/src/hover/render.rs b/crates/ide/src/hover/render.rs
index cf5f137cdd..af78e9a40c 100644
--- a/crates/ide/src/hover/render.rs
+++ b/crates/ide/src/hover/render.rs
@@ -5,7 +5,7 @@ use either::Either;
use hir::{
Adt, AsAssocItem, AsExternAssocItem, CaptureKind, DisplayTarget, DropGlue,
DynCompatibilityViolation, HasCrate, HasSource, HirDisplay, Layout, LayoutError,
- MethodViolationCode, Name, Semantics, Symbol, Trait, Type, TypeInfo, VariantDef,
+ MethodViolationCode, Name, Semantics, Symbol, Trait, Type, TypeInfo, Variant,
db::ExpandDatabase,
};
use ide_db::{
@@ -366,14 +366,14 @@ fn definition_owner_name(db: &RootDatabase, def: Definition, edition: Edition) -
let parent_name = parent.name(db);
let parent_name = parent_name.display(db, edition).to_string();
return match parent {
- VariantDef::Variant(variant) => {
+ Variant::EnumVariant(variant) => {
let enum_name = variant.parent_enum(db).name(db);
Some(format!("{}::{parent_name}", enum_name.display(db, edition)))
}
_ => Some(parent_name),
};
}
- Definition::Variant(e) => Some(e.parent_enum(db).name(db)),
+ Definition::EnumVariant(e) => Some(e.parent_enum(db).name(db)),
Definition::GenericParam(generic_param) => match generic_param.parent() {
hir::GenericDef::Adt(it) => Some(it.name(db)),
hir::GenericDef::Trait(it) => Some(it.name(db)),
@@ -470,7 +470,7 @@ pub(super) fn definition(
Definition::Adt(adt @ (Adt::Struct(_) | Adt::Union(_))) => {
adt.display_limited(db, config.max_fields_count, display_target).to_string()
}
- Definition::Variant(variant) => {
+ Definition::EnumVariant(variant) => {
variant.display_limited(db, config.max_fields_count, display_target).to_string()
}
Definition::Adt(adt @ Adt::Enum(_)) => {
@@ -499,7 +499,7 @@ pub(super) fn definition(
};
let docs = def.docs_with_rangemap(db, famous_defs, display_target);
let value = || match def {
- Definition::Variant(it) => {
+ Definition::EnumVariant(it) => {
if !it.parent_enum(db).is_data_carrying(db) {
match it.eval(db) {
Ok(it) => {
@@ -596,7 +596,7 @@ pub(super) fn definition(
|_| {
let var_def = it.parent_def(db);
match var_def {
- hir::VariantDef::Struct(s) => {
+ hir::Variant::Struct(s) => {
Adt::from(s).layout(db).ok().and_then(|layout| layout.field_offset(it))
}
_ => None,
@@ -627,7 +627,7 @@ pub(super) fn definition(
|_| None,
|_| None,
),
- Definition::Variant(it) => render_memory_layout(
+ Definition::EnumVariant(it) => render_memory_layout(
config.memory_layout,
|| it.layout(db),
|_| None,
@@ -710,7 +710,7 @@ pub(super) fn definition(
has_dtor: Some(enum_drop_glue > fields_drop_glue),
}
}
- Definition::Variant(variant) => {
+ Definition::EnumVariant(variant) => {
let fields_drop_glue = variant
.fields(db)
.iter()
diff --git a/crates/ide/src/inlay_hints/discriminant.rs b/crates/ide/src/inlay_hints/discriminant.rs
index 5b9267126f..e845faec56 100644
--- a/crates/ide/src/inlay_hints/discriminant.rs
+++ b/crates/ide/src/inlay_hints/discriminant.rs
@@ -46,7 +46,7 @@ fn variant_hints(
enum_: &ast::Enum,
variant: &ast::Variant,
) -> Option<()> {
- if variant.expr().is_some() {
+ if variant.const_arg().is_some() {
return None;
}
diff --git a/crates/ide/src/inlay_hints/implicit_drop.rs b/crates/ide/src/inlay_hints/implicit_drop.rs
index e5e4c899ec..3af529e8c5 100644
--- a/crates/ide/src/inlay_hints/implicit_drop.rs
+++ b/crates/ide/src/inlay_hints/implicit_drop.rs
@@ -7,7 +7,7 @@
//! ```
use hir::{
DefWithBody,
- db::{DefDatabase as _, HirDatabase as _},
+ db::HirDatabase as _,
mir::{MirSpan, TerminatorKind},
};
use ide_db::{FileRange, famous_defs::FamousDefs};
@@ -35,7 +35,7 @@ pub(super) fn hints(
let def: DefWithBody = def.into();
let def = def.try_into().ok()?;
- let (hir, source_map) = sema.db.body_with_source_map(def);
+ let (hir, source_map) = hir::Body::with_source_map(sema.db, def);
let mir = sema.db.mir_body(def).ok()?;
diff --git a/crates/ide/src/inlay_hints/param_name.rs b/crates/ide/src/inlay_hints/param_name.rs
index f1e62a5ab8..08588bbed0 100644
--- a/crates/ide/src/inlay_hints/param_name.rs
+++ b/crates/ide/src/inlay_hints/param_name.rs
@@ -374,7 +374,7 @@ fn is_adt_constructor_similar_to_param_name(
hir::PathResolution::Def(hir::ModuleDef::Adt(_)) => {
Some(to_lower_snake_case(&path.segment()?.name_ref()?.text()) == param_name)
}
- hir::PathResolution::Def(hir::ModuleDef::Function(_) | hir::ModuleDef::Variant(_)) => {
+ hir::PathResolution::Def(hir::ModuleDef::Function(_) | hir::ModuleDef::EnumVariant(_)) => {
if to_lower_snake_case(&path.segment()?.name_ref()?.text()) == param_name {
return Some(true);
}
diff --git a/crates/ide/src/moniker.rs b/crates/ide/src/moniker.rs
index 1c1389ca7a..335e1b5b13 100644
--- a/crates/ide/src/moniker.rs
+++ b/crates/ide/src/moniker.rs
@@ -205,7 +205,7 @@ pub(crate) fn def_to_kind(db: &RootDatabase, def: Definition) -> SymbolInformati
Definition::Adt(Adt::Struct(..)) => Struct,
Definition::Adt(Adt::Union(..)) => Union,
Definition::Adt(Adt::Enum(..)) => Enum,
- Definition::Variant(..) => EnumMember,
+ Definition::EnumVariant(..) => EnumMember,
Definition::Const(..) => Constant,
Definition::Static(..) => StaticVariable,
Definition::Trait(..) => Trait,
diff --git a/crates/ide/src/navigation_target.rs b/crates/ide/src/navigation_target.rs
index 185df92e2d..92020321f4 100644
--- a/crates/ide/src/navigation_target.rs
+++ b/crates/ide/src/navigation_target.rs
@@ -276,7 +276,7 @@ impl<'db> TryToNav for FileSymbol<'db> {
Some(it.display(db, display_target).to_string())
}
hir::ModuleDef::Adt(it) => Some(it.display(db, display_target).to_string()),
- hir::ModuleDef::Variant(it) => {
+ hir::ModuleDef::EnumVariant(it) => {
Some(it.display(db, display_target).to_string())
}
hir::ModuleDef::Const(it) => {
@@ -319,7 +319,7 @@ impl TryToNav for Definition {
Definition::GenericParam(it) => it.try_to_nav(sema),
Definition::Function(it) => it.try_to_nav(sema),
Definition::Adt(it) => it.try_to_nav(sema),
- Definition::Variant(it) => it.try_to_nav(sema),
+ Definition::EnumVariant(it) => it.try_to_nav(sema),
Definition::Const(it) => it.try_to_nav(sema),
Definition::Static(it) => it.try_to_nav(sema),
Definition::Trait(it) => it.try_to_nav(sema),
@@ -347,7 +347,7 @@ impl TryToNav for hir::ModuleDef {
hir::ModuleDef::Module(it) => Some(it.to_nav(sema.db)),
hir::ModuleDef::Function(it) => it.try_to_nav(sema),
hir::ModuleDef::Adt(it) => it.try_to_nav(sema),
- hir::ModuleDef::Variant(it) => it.try_to_nav(sema),
+ hir::ModuleDef::EnumVariant(it) => it.try_to_nav(sema),
hir::ModuleDef::Const(it) => it.try_to_nav(sema),
hir::ModuleDef::Static(it) => it.try_to_nav(sema),
hir::ModuleDef::Trait(it) => it.try_to_nav(sema),
@@ -406,7 +406,7 @@ impl ToNavFromAst for hir::Enum {
container_name(db, self)
}
}
-impl ToNavFromAst for hir::Variant {
+impl ToNavFromAst for hir::EnumVariant {
const KIND: SymbolKind = SymbolKind::Variant;
}
impl ToNavFromAst for hir::Union {
diff --git a/crates/ide/src/references.rs b/crates/ide/src/references.rs
index 6464c47716..9392651c17 100644
--- a/crates/ide/src/references.rs
+++ b/crates/ide/src/references.rs
@@ -299,7 +299,7 @@ fn retain_adt_literal_usages(
});
usages.references.retain(|_, it| !it.is_empty());
}
- Definition::Adt(_) | Definition::Variant(_) => {
+ Definition::Adt(_) | Definition::EnumVariant(_) => {
refs.for_each(|it| {
it.retain(|reference| reference.name.as_name_ref().is_some_and(is_lit_name_ref))
});
@@ -377,7 +377,7 @@ fn is_enum_lit_name_ref(
let path_is_variant_of_enum = |path: ast::Path| {
matches!(
sema.resolve_path(&path),
- Some(PathResolution::Def(hir::ModuleDef::Variant(variant)))
+ Some(PathResolution::Def(hir::ModuleDef::EnumVariant(variant)))
if variant.parent_enum(sema.db) == enum_
)
};
diff --git a/crates/ide/src/rename.rs b/crates/ide/src/rename.rs
index ae19e77509..900a885a64 100644
--- a/crates/ide/src/rename.rs
+++ b/crates/ide/src/rename.rs
@@ -480,7 +480,7 @@ fn rename_to_self(
}
let fn_def = match local.parent(sema.db) {
- hir::DefWithBody::Function(func) => func,
+ hir::ExpressionStoreOwner::Body(hir::DefWithBody::Function(func)) => func,
_ => bail!("Cannot rename local to self outside of function"),
};
@@ -743,7 +743,7 @@ fn rename_self_to_param(
}
let fn_def = match local.parent(sema.db) {
- hir::DefWithBody::Function(func) => func,
+ hir::ExpressionStoreOwner::Body(hir::DefWithBody::Function(func)) => func,
_ => bail!("Cannot rename local to self outside of function"),
};
diff --git a/crates/ide/src/runnables.rs b/crates/ide/src/runnables.rs
index 42efa7142b..a0a6a24559 100644
--- a/crates/ide/src/runnables.rs
+++ b/crates/ide/src/runnables.rs
@@ -494,7 +494,7 @@ fn module_def_doctest(sema: &Semantics<'_, RootDatabase>, def: Definition) -> Op
Definition::Module(it) => it.attrs(db),
Definition::Function(it) => it.attrs(db),
Definition::Adt(it) => it.attrs(db),
- Definition::Variant(it) => it.attrs(db),
+ Definition::EnumVariant(it) => it.attrs(db),
Definition::Const(it) => it.attrs(db),
Definition::Static(it) => it.attrs(db),
Definition::Trait(it) => it.attrs(db),
diff --git a/crates/ide/src/signature_help.rs b/crates/ide/src/signature_help.rs
index f86974b4ec..9eb01b12f2 100644
--- a/crates/ide/src/signature_help.rs
+++ b/crates/ide/src/signature_help.rs
@@ -497,7 +497,7 @@ fn signature_help_for_tuple_struct_pat(
};
let db = sema.db;
- let fields: Vec<_> = if let PathResolution::Def(ModuleDef::Variant(variant)) = path_res {
+ let fields: Vec<_> = if let PathResolution::Def(ModuleDef::EnumVariant(variant)) = path_res {
let en = variant.parent_enum(db);
res.doc = en.docs(db).map(Documentation::into_owned);
@@ -623,7 +623,7 @@ fn signature_help_for_record_<'db>(
let db = sema.db;
let path_res = sema.resolve_path(path)?;
- if let PathResolution::Def(ModuleDef::Variant(variant)) = path_res {
+ if let PathResolution::Def(ModuleDef::EnumVariant(variant)) = path_res {
fields = variant.fields(db);
let en = variant.parent_enum(db);
diff --git a/crates/ide/src/syntax_highlighting.rs b/crates/ide/src/syntax_highlighting.rs
index ce1df6a1e7..217b13b4ef 100644
--- a/crates/ide/src/syntax_highlighting.rs
+++ b/crates/ide/src/syntax_highlighting.rs
@@ -14,7 +14,9 @@ mod tests;
use std::ops::ControlFlow;
use either::Either;
-use hir::{DefWithBody, EditionedFileId, InFile, InRealFile, MacroKind, Semantics};
+use hir::{
+ DefWithBody, EditionedFileId, ExpressionStoreOwner, InFile, InRealFile, MacroKind, Semantics,
+};
use ide_db::{FxHashMap, FxHashSet, MiniCore, Ranker, RootDatabase, SymbolKind};
use syntax::{
AstNode, AstToken, NodeOrToken,
@@ -256,8 +258,8 @@ fn traverse(
let mut inside_attribute = false;
// FIXME: accommodate range highlighting
- let mut body_stack: Vec<Option<DefWithBody>> = vec![];
- let mut per_body_cache: FxHashMap<DefWithBody, FxHashSet<_>> = FxHashMap::default();
+ let mut body_stack: Vec<Option<ExpressionStoreOwner>> = vec![];
+ let mut per_body_cache: FxHashMap<ExpressionStoreOwner, FxHashSet<_>> = FxHashMap::default();
// Walk all nodes, keeping track of whether we are inside a macro or not.
// If in macro, expand it first and highlight the expanded code.
@@ -288,19 +290,18 @@ fn traverse(
inside_attribute = false
}
Enter(NodeOrToken::Node(node)) => {
+ // FIXME: ExpressionStore signatures and variant fields
+ // Maybe we can re-use child container stuff here
if let Some(item) = <Either<ast::Item, ast::Variant>>::cast(node.clone()) {
match item {
Either::Left(item) => {
match &item {
- ast::Item::Fn(it) => {
- body_stack.push(sema.to_def(it).map(Into::into))
- }
- ast::Item::Const(it) => {
- body_stack.push(sema.to_def(it).map(Into::into))
- }
- ast::Item::Static(it) => {
- body_stack.push(sema.to_def(it).map(Into::into))
- }
+ ast::Item::Fn(it) => body_stack
+ .push(sema.to_def(it).map(DefWithBody::from).map(Into::into)),
+ ast::Item::Const(it) => body_stack
+ .push(sema.to_def(it).map(DefWithBody::from).map(Into::into)),
+ ast::Item::Static(it) => body_stack
+ .push(sema.to_def(it).map(DefWithBody::from).map(Into::into)),
_ => (),
}
@@ -329,7 +330,9 @@ fn traverse(
}
}
}
- Either::Right(it) => body_stack.push(sema.to_def(&it).map(Into::into)),
+ Either::Right(it) => {
+ body_stack.push(sema.to_def(&it).map(DefWithBody::from).map(Into::into))
+ }
}
}
}
@@ -392,11 +395,11 @@ fn traverse(
let descended = descend_token(sema, InRealFile::new(file_id, token));
let body = match &descended.value {
NodeOrToken::Node(n) => {
- sema.body_for(InFile::new(descended.file_id, n.syntax()))
- }
- NodeOrToken::Token(t) => {
- t.parent().and_then(|it| sema.body_for(InFile::new(descended.file_id, &it)))
+ sema.store_owner_for(InFile::new(descended.file_id, n.syntax()))
}
+ NodeOrToken::Token(t) => t
+ .parent()
+ .and_then(|it| sema.store_owner_for(InFile::new(descended.file_id, &it))),
};
(descended, body)
}
diff --git a/crates/ide/src/syntax_highlighting/highlight.rs b/crates/ide/src/syntax_highlighting/highlight.rs
index a94bbc9f04..0e101ab235 100644
--- a/crates/ide/src/syntax_highlighting/highlight.rs
+++ b/crates/ide/src/syntax_highlighting/highlight.rs
@@ -538,7 +538,7 @@ pub(super) fn highlight_def(
(Highlight::new(h), Some(adt.attrs(sema.db)))
}
- Definition::Variant(variant) => {
+ Definition::EnumVariant(variant) => {
(Highlight::new(HlTag::Symbol(SymbolKind::Variant)), Some(variant.attrs(sema.db)))
}
Definition::Const(konst) => {
diff --git a/crates/ide/src/syntax_highlighting/inject.rs b/crates/ide/src/syntax_highlighting/inject.rs
index 291333f09c..74a8d93dfe 100644
--- a/crates/ide/src/syntax_highlighting/inject.rs
+++ b/crates/ide/src/syntax_highlighting/inject.rs
@@ -209,7 +209,7 @@ fn module_def_to_hl_tag(db: &dyn HirDatabase, def: Definition) -> HlTag {
Definition::Adt(hir::Adt::Struct(_)) => SymbolKind::Struct,
Definition::Adt(hir::Adt::Enum(_)) => SymbolKind::Enum,
Definition::Adt(hir::Adt::Union(_)) => SymbolKind::Union,
- Definition::Variant(_) => SymbolKind::Variant,
+ Definition::EnumVariant(_) => SymbolKind::Variant,
Definition::Const(_) => SymbolKind::Const,
Definition::Static(_) => SymbolKind::Static,
Definition::Trait(_) => SymbolKind::Trait,
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_general.html b/crates/ide/src/syntax_highlighting/test_data/highlight_general.html
index c6dbc435c0..1184739cc2 100644
--- a/crates/ide/src/syntax_highlighting/test_data/highlight_general.html
+++ b/crates/ide/src/syntax_highlighting/test_data/highlight_general.html
@@ -105,7 +105,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
<span class="keyword control">loop</span> <span class="brace">{</span><span class="brace">}</span>
<span class="brace">}</span>
-<span class="keyword">fn</span> <span class="function declaration">const_param</span><span class="angle">&lt;</span><span class="keyword const">const</span> <span class="const_param const declaration">FOO</span><span class="colon">:</span> <span class="builtin_type">usize</span><span class="angle">&gt;</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">usize</span> <span class="brace">{</span>
+<span class="keyword">fn</span> <span class="function declaration">const_param</span><span class="angle">&lt;</span><span class="keyword const">const</span> <span class="const_param const declaration">FOO</span><span class="colon">:</span> <span class="builtin_type">usize</span><span class="angle">&gt;</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">usize</span> <span class="keyword">where</span> <span class="bracket">[</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span> <span class="const_param const">FOO</span><span class="bracket">]</span><span class="colon">:</span> <span class="trait default_library library">Sized</span> <span class="brace">{</span>
<span class="function">const_param</span><span class="operator">::</span><span class="angle">&lt;</span><span class="brace">{</span> <span class="const_param const">FOO</span> <span class="brace">}</span><span class="angle">&gt;</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>
<span class="const_param const">FOO</span>
<span class="brace">}</span>
diff --git a/crates/ide/src/syntax_highlighting/tests.rs b/crates/ide/src/syntax_highlighting/tests.rs
index c6aebd0b0c..aecd1d3fdb 100644
--- a/crates/ide/src/syntax_highlighting/tests.rs
+++ b/crates/ide/src/syntax_highlighting/tests.rs
@@ -210,7 +210,7 @@ fn never() -> ! {
loop {}
}
-fn const_param<const FOO: usize>() -> usize {
+fn const_param<const FOO: usize>() -> usize where [(); FOO]: Sized {
const_param::<{ FOO }>();
FOO
}
diff --git a/crates/intern/Cargo.toml b/crates/intern/Cargo.toml
index ad73c191c0..39320ebd1c 100644
--- a/crates/intern/Cargo.toml
+++ b/crates/intern/Cargo.toml
@@ -22,3 +22,6 @@ rayon.workspace = true
[lints]
workspace = true
+
+[features]
+prevent-gc = []
diff --git a/crates/intern/src/gc.rs b/crates/intern/src/gc.rs
index 937de26831..f4e8f75e71 100644
--- a/crates/intern/src/gc.rs
+++ b/crates/intern/src/gc.rs
@@ -110,6 +110,10 @@ impl GarbageCollector {
/// the added storages must form a DAG.
/// - [`GcInternedVisit`] and [`GcInternedSliceVisit`] must mark all values reachable from the node.
pub unsafe fn collect(mut self) {
+ if cfg!(feature = "prevent-gc") {
+ return;
+ }
+
let total_nodes = self.storages.iter().map(|storage| storage.len()).sum();
self.alive.clear();
self.alive.reserve(total_nodes);
diff --git a/crates/parser/src/grammar/expressions/atom.rs b/crates/parser/src/grammar/expressions/atom.rs
index b75474ee2b..3214fd90f2 100644
--- a/crates/parser/src/grammar/expressions/atom.rs
+++ b/crates/parser/src/grammar/expressions/atom.rs
@@ -407,8 +407,18 @@ pub(crate) fn parse_asm_expr(p: &mut Parser<'_>, m: Marker) -> Option<CompletedM
op.complete(p, ASM_CONST);
op_n.complete(p, ASM_OPERAND_NAMED);
} else if p.eat_contextual_kw(T![sym]) {
+ // test asm_sym_paren
+ // fn foo() {
+ // builtin#asm("", f = sym (foo::bar));
+ // }
dir_spec.abandon(p);
- paths::type_path(p);
+ if p.at(T!['(']) {
+ p.bump(T!['(']);
+ paths::type_path(p);
+ p.expect(T![')']);
+ } else {
+ paths::type_path(p);
+ }
op.complete(p, ASM_SYM);
op_n.complete(p, ASM_OPERAND_NAMED);
} else if allow_templates {
diff --git a/crates/parser/src/grammar/items/adt.rs b/crates/parser/src/grammar/items/adt.rs
index a375696140..cfba4c3a77 100644
--- a/crates/parser/src/grammar/items/adt.rs
+++ b/crates/parser/src/grammar/items/adt.rs
@@ -96,7 +96,9 @@ pub(crate) fn variant_list(p: &mut Parser<'_>) {
// test variant_discriminant
// enum E { X(i32) = 10 }
if p.eat(T![=]) {
+ let m = p.start();
expressions::expr(p);
+ m.complete(p, CONST_ARG);
}
m.complete(p, VARIANT);
} else {
@@ -139,7 +141,9 @@ pub(crate) fn record_field_list(p: &mut Parser<'_>) {
// test record_field_default_values
// struct S { f: f32 = 0.0 }
if p.eat(T![=]) {
+ let m = p.start();
expressions::expr(p);
+ m.complete(p, CONST_ARG);
}
m.complete(p, RECORD_FIELD);
} else {
diff --git a/crates/parser/test_data/generated/runner.rs b/crates/parser/test_data/generated/runner.rs
index 9f919f6cea..4c001104fe 100644
--- a/crates/parser/test_data/generated/runner.rs
+++ b/crates/parser/test_data/generated/runner.rs
@@ -25,6 +25,8 @@ mod ok {
#[test]
fn asm_label() { run_and_expect_no_errors("test_data/parser/inline/ok/asm_label.rs"); }
#[test]
+ fn asm_sym_paren() { run_and_expect_no_errors("test_data/parser/inline/ok/asm_sym_paren.rs"); }
+ #[test]
fn assoc_const_eq() {
run_and_expect_no_errors("test_data/parser/inline/ok/assoc_const_eq.rs");
}
diff --git a/crates/parser/test_data/parser/inline/ok/asm_sym_paren.rast b/crates/parser/test_data/parser/inline/ok/asm_sym_paren.rast
new file mode 100644
index 0000000000..d189f63f2a
--- /dev/null
+++ b/crates/parser/test_data/parser/inline/ok/asm_sym_paren.rast
@@ -0,0 +1,49 @@
+SOURCE_FILE
+ FN
+ FN_KW "fn"
+ WHITESPACE " "
+ NAME
+ IDENT "foo"
+ PARAM_LIST
+ L_PAREN "("
+ R_PAREN ")"
+ WHITESPACE " "
+ BLOCK_EXPR
+ STMT_LIST
+ L_CURLY "{"
+ WHITESPACE "\n "
+ EXPR_STMT
+ ASM_EXPR
+ BUILTIN_KW "builtin"
+ POUND "#"
+ ASM_KW "asm"
+ L_PAREN "("
+ LITERAL
+ STRING "\"\""
+ COMMA ","
+ WHITESPACE " "
+ ASM_OPERAND_NAMED
+ NAME
+ IDENT "f"
+ WHITESPACE " "
+ EQ "="
+ WHITESPACE " "
+ ASM_SYM
+ SYM_KW "sym"
+ WHITESPACE " "
+ L_PAREN "("
+ PATH
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "foo"
+ COLON2 "::"
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "bar"
+ R_PAREN ")"
+ R_PAREN ")"
+ SEMICOLON ";"
+ WHITESPACE "\n"
+ R_CURLY "}"
+ WHITESPACE "\n"
diff --git a/crates/parser/test_data/parser/inline/ok/asm_sym_paren.rs b/crates/parser/test_data/parser/inline/ok/asm_sym_paren.rs
new file mode 100644
index 0000000000..7b2f80704c
--- /dev/null
+++ b/crates/parser/test_data/parser/inline/ok/asm_sym_paren.rs
@@ -0,0 +1,3 @@
+fn foo() {
+ builtin#asm("", f = sym (foo::bar));
+}
diff --git a/crates/parser/test_data/parser/inline/ok/record_field_default_values.rast b/crates/parser/test_data/parser/inline/ok/record_field_default_values.rast
index 33088f2cab..e53b886bbf 100644
--- a/crates/parser/test_data/parser/inline/ok/record_field_default_values.rast
+++ b/crates/parser/test_data/parser/inline/ok/record_field_default_values.rast
@@ -21,8 +21,9 @@ SOURCE_FILE
WHITESPACE " "
EQ "="
WHITESPACE " "
- LITERAL
- FLOAT_NUMBER "0.0"
+ CONST_ARG
+ LITERAL
+ FLOAT_NUMBER "0.0"
WHITESPACE " "
R_CURLY "}"
WHITESPACE "\n"
diff --git a/crates/parser/test_data/parser/inline/ok/variant_discriminant.rast b/crates/parser/test_data/parser/inline/ok/variant_discriminant.rast
index 9f0c5a7610..3494085e88 100644
--- a/crates/parser/test_data/parser/inline/ok/variant_discriminant.rast
+++ b/crates/parser/test_data/parser/inline/ok/variant_discriminant.rast
@@ -23,8 +23,9 @@ SOURCE_FILE
WHITESPACE " "
EQ "="
WHITESPACE " "
- LITERAL
- INT_NUMBER "10"
+ CONST_ARG
+ LITERAL
+ INT_NUMBER "10"
WHITESPACE " "
R_CURLY "}"
WHITESPACE "\n"
diff --git a/crates/parser/test_data/parser/ok/0019_enums.rast b/crates/parser/test_data/parser/ok/0019_enums.rast
index dd47e3aa47..51837e5372 100644
--- a/crates/parser/test_data/parser/ok/0019_enums.rast
+++ b/crates/parser/test_data/parser/ok/0019_enums.rast
@@ -78,8 +78,9 @@ SOURCE_FILE
WHITESPACE " "
EQ "="
WHITESPACE " "
- LITERAL
- INT_NUMBER "92"
+ CONST_ARG
+ LITERAL
+ INT_NUMBER "92"
COMMA ","
WHITESPACE "\n "
VARIANT
diff --git a/crates/rust-analyzer/Cargo.toml b/crates/rust-analyzer/Cargo.toml
index d1283ca59e..beb83a8173 100644
--- a/crates/rust-analyzer/Cargo.toml
+++ b/crates/rust-analyzer/Cargo.toml
@@ -94,6 +94,8 @@ test-utils.workspace = true
test-fixture.workspace = true
syntax-bridge.workspace = true
+intern = { path = "../intern", features = ["prevent-gc"] }
+
[features]
jemalloc = ["jemallocator", "profile/jemalloc"]
force-always-assert = ["stdx/force-always-assert"]
diff --git a/crates/rust-analyzer/src/cli/analysis_stats.rs b/crates/rust-analyzer/src/cli/analysis_stats.rs
index ad1cca08cb..74828cba02 100644
--- a/crates/rust-analyzer/src/cli/analysis_stats.rs
+++ b/crates/rust-analyzer/src/cli/analysis_stats.rs
@@ -10,15 +10,15 @@ use std::{
use cfg::{CfgAtom, CfgDiff};
use hir::{
- Adt, AssocItem, Crate, DefWithBody, FindPathConfig, HasCrate, HasSource, HirDisplay, ModuleDef,
- Name, crate_lang_items,
+ Adt, AssocItem, Crate, DefWithBody, FindPathConfig, GenericDef, HasCrate, HasSource,
+ HirDisplay, ModuleDef, Name, Variant, VariantId, crate_lang_items,
db::{DefDatabase, ExpandDatabase, HirDatabase},
next_solver::{DbInterner, GenericArgs},
};
use hir_def::{
- SyntheticSyntax,
- expr_store::BodySourceMap,
- hir::{ExprId, PatId},
+ DefWithBodyId, ExpressionStoreOwnerId, GenericDefId, SyntheticSyntax,
+ expr_store::{Body, BodySourceMap, ExpressionStore},
+ hir::{ExprId, PatId, generics::GenericParams},
};
use hir_ty::InferenceResult;
use ide::{
@@ -229,6 +229,8 @@ impl flags::AnalysisStats {
eprint!(" crates: {num_crates}");
let mut num_decls = 0;
let mut bodies = Vec::new();
+ let mut signatures = Vec::new();
+ let mut variants = Vec::new();
let mut adts = Vec::new();
let mut file_ids = Vec::new();
@@ -246,10 +248,15 @@ impl flags::AnalysisStats {
match decl {
ModuleDef::Function(f) => bodies.push(DefWithBody::from(f)),
ModuleDef::Adt(a) => {
- if let Adt::Enum(e) = a {
- for v in e.variants(db) {
- bodies.push(DefWithBody::from(v));
+ match a {
+ Adt::Enum(e) => {
+ for v in e.variants(db) {
+ bodies.push(DefWithBody::from(v));
+ variants.push(Variant::EnumVariant(v));
+ }
}
+ Adt::Struct(it) => variants.push(Variant::Struct(it)),
+ Adt::Union(it) => variants.push(Variant::Union(it)),
}
adts.push(a)
}
@@ -267,24 +274,32 @@ impl flags::AnalysisStats {
},
_ => (),
};
+ if let Some(g) = decl.as_generic_def() {
+ signatures.push(g);
+ }
}
for impl_def in module.impl_defs(db) {
+ signatures.push(impl_def.into());
for item in impl_def.items(db) {
num_decls += 1;
match item {
- AssocItem::Function(f) => bodies.push(DefWithBody::from(f)),
+ AssocItem::Function(f) => {
+ bodies.push(DefWithBody::from(f));
+ signatures.push(f.into())
+ }
AssocItem::Const(c) => {
bodies.push(DefWithBody::from(c));
+ signatures.push(c.into());
}
- _ => (),
+ AssocItem::TypeAlias(t) => signatures.push(t.into()),
}
}
}
}
}
eprintln!(
- ", mods: {}, decls: {num_decls}, bodies: {}, adts: {}, consts: {}",
+ ", mods: {}, decls: {num_decls}, bodies: {}, adts: {}, consts: {}, signatures: {}, variants: {}",
visited_modules.len(),
bodies.len(),
adts.len(),
@@ -292,6 +307,8 @@ impl flags::AnalysisStats {
.iter()
.filter(|it| matches!(it, DefWithBody::Const(_) | DefWithBody::Static(_)))
.count(),
+ signatures.len(),
+ variants.len()
);
eprintln!(" Workspace:");
@@ -327,15 +344,15 @@ impl flags::AnalysisStats {
}
if !self.skip_lowering {
- self.run_body_lowering(db, &vfs, &bodies, verbosity);
+ self.run_body_lowering(db, &vfs, &bodies, &signatures, &variants, verbosity);
}
if !self.skip_inference {
- self.run_inference(db, &vfs, &bodies, verbosity);
+ self.run_inference(db, &vfs, &bodies, &signatures, &variants, verbosity);
}
if !self.skip_mir_stats {
- self.run_mir_lowering(db, &bodies, verbosity);
+ self.run_mir_lowering(db, &bodies, &signatures, &variants, verbosity);
}
if !self.skip_data_layout {
@@ -343,7 +360,7 @@ impl flags::AnalysisStats {
}
if !self.skip_const_eval {
- self.run_const_eval(db, &bodies, verbosity);
+ self.run_const_eval(db, &bodies, &signatures, &variants, verbosity);
}
});
@@ -384,7 +401,7 @@ impl flags::AnalysisStats {
let mut fail = 0;
for &a in adts {
let interner = DbInterner::new_no_crate(db);
- let generic_params = db.generic_params(a.into());
+ let generic_params = GenericParams::of(db, a.into());
if generic_params.iter_type_or_consts().next().is_some()
|| generic_params.iter_lt().next().is_some()
{
@@ -396,7 +413,7 @@ impl flags::AnalysisStats {
hir_def::AdtId::from(a),
GenericArgs::empty(interner).store(),
hir_ty::ParamEnvAndCrate {
- param_env: db.trait_environment(a.into()),
+ param_env: db.trait_environment(GenericDefId::from(a).into()),
krate: a.krate(db).into(),
}
.store(),
@@ -416,7 +433,14 @@ impl flags::AnalysisStats {
report_metric("data layout time", data_layout_time.time.as_millis() as u64, "ms");
}
- fn run_const_eval(&self, db: &RootDatabase, bodies: &[DefWithBody], verbosity: Verbosity) {
+ fn run_const_eval(
+ &self,
+ db: &RootDatabase,
+ bodies: &[DefWithBody],
+ _signatures: &[GenericDef],
+ _variants: &[Variant],
+ verbosity: Verbosity,
+ ) {
let len = bodies
.iter()
.filter(|body| matches!(body, DefWithBody::Const(_) | DefWithBody::Static(_)))
@@ -431,7 +455,9 @@ impl flags::AnalysisStats {
let mut all = 0;
let mut fail = 0;
for &b in bodies {
- bar.set_message(move || format!("const eval: {}", full_name(db, b, b.module(db))));
+ bar.set_message(move || {
+ format!("const eval: {}", full_name(db, || b.name(db), b.module(db)))
+ });
let res = match b {
DefWithBody::Const(c) => c.eval(db),
DefWithBody::Static(s) => s.eval(db),
@@ -687,7 +713,14 @@ impl flags::AnalysisStats {
bar.finish_and_clear();
}
- fn run_mir_lowering(&self, db: &RootDatabase, bodies: &[DefWithBody], verbosity: Verbosity) {
+ fn run_mir_lowering(
+ &self,
+ db: &RootDatabase,
+ bodies: &[DefWithBody],
+ _signatures: &[GenericDef],
+ _variants: &[Variant],
+ verbosity: Verbosity,
+ ) {
let mut bar = match verbosity {
Verbosity::Quiet | Verbosity::Spammy => ProgressReport::hidden(),
_ if self.parallel || self.output.is_some() => ProgressReport::hidden(),
@@ -698,14 +731,14 @@ impl flags::AnalysisStats {
let mut fail = 0;
for &body in bodies {
bar.set_message(move || {
- format!("mir lowering: {}", full_name(db, body, body.module(db)))
+ format!("mir lowering: {}", full_name(db, || body.name(db), body.module(db)))
});
bar.inc(1);
- if matches!(body, DefWithBody::Variant(_)) {
+ if matches!(body, DefWithBody::EnumVariant(_)) {
continue;
}
let module = body.module(db);
- if !self.should_process(db, body, module) {
+ if !self.should_process(db, || body.name(db), module) {
continue;
}
@@ -743,6 +776,8 @@ impl flags::AnalysisStats {
db: &RootDatabase,
vfs: &Vfs,
bodies: &[DefWithBody],
+ signatures: &[GenericDef],
+ variants: &[Variant],
verbosity: Verbosity,
) {
let mut bar = match verbosity {
@@ -753,12 +788,31 @@ impl flags::AnalysisStats {
if self.parallel {
let mut inference_sw = self.stop_watch();
- let bodies = bodies.iter().filter_map(|&body| body.try_into().ok()).collect::<Vec<_>>();
+ let bodies = bodies
+ .iter()
+ .filter_map(|&body| body.try_into().ok())
+ .collect::<Vec<DefWithBodyId>>();
bodies
.par_iter()
.map_with(db.clone(), |snap, &body| {
- snap.body(body);
- InferenceResult::for_body(snap, body);
+ InferenceResult::of(snap, body);
+ })
+ .count();
+ let signatures = signatures
+ .iter()
+ .filter_map(|&signatures| signatures.try_into().ok())
+ .collect::<Vec<GenericDefId>>();
+ signatures
+ .par_iter()
+ .map_with(db.clone(), |snap, &signatures| {
+ InferenceResult::of(snap, signatures);
+ })
+ .count();
+ let variants = variants.iter().copied().map(Into::into).collect::<Vec<VariantId>>();
+ variants
+ .par_iter()
+ .map_with(db.clone(), |snap, &variants| {
+ InferenceResult::of(snap, variants);
})
.count();
eprintln!("{:<20} {}", "Parallel Inference:", inference_sw.elapsed());
@@ -782,7 +836,7 @@ impl flags::AnalysisStats {
let display_target = module.krate(db).to_display_target(db);
if let Some(only_name) = self.only.as_deref()
&& name.display(db, Edition::LATEST).to_string() != only_name
- && full_name(db, body_id, module) != only_name
+ && full_name(db, || body_id.name(db), module) != only_name
{
continue;
}
@@ -792,7 +846,9 @@ impl flags::AnalysisStats {
DefWithBody::Function(it) => it.source(db).map(|it| it.syntax().cloned()),
DefWithBody::Static(it) => it.source(db).map(|it| it.syntax().cloned()),
DefWithBody::Const(it) => it.source(db).map(|it| it.syntax().cloned()),
- DefWithBody::Variant(it) => it.source(db).map(|it| it.syntax().cloned()),
+ DefWithBody::EnumVariant(it) => {
+ it.source(db).map(|it| it.syntax().cloned())
+ }
};
if let Some(src) = source {
let original_file = src.file_id.original_file(db);
@@ -800,33 +856,44 @@ impl flags::AnalysisStats {
let syntax_range = src.text_range();
format!(
"processing: {} ({} {:?})",
- full_name(db, body_id, module),
+ full_name(db, || body_id.name(db), module),
path,
syntax_range
)
} else {
- format!("processing: {}", full_name(db, body_id, module))
+ format!("processing: {}", full_name(db, || body_id.name(db), module))
}
} else {
- format!("processing: {}", full_name(db, body_id, module))
+ format!("processing: {}", full_name(db, || body_id.name(db), module))
}
};
if verbosity.is_spammy() {
bar.println(msg());
}
bar.set_message(msg);
- let body = db.body(body_def_id);
+ let body = Body::of(db, body_def_id);
let inference_result =
- catch_unwind(AssertUnwindSafe(|| InferenceResult::for_body(db, body_def_id)));
+ catch_unwind(AssertUnwindSafe(|| InferenceResult::of(db, body_def_id)));
let inference_result = match inference_result {
Ok(inference_result) => inference_result,
Err(p) => {
if let Some(s) = p.downcast_ref::<&str>() {
- eprintln!("infer panicked for {}: {}", full_name(db, body_id, module), s);
+ eprintln!(
+ "infer panicked for {}: {}",
+ full_name(db, || body_id.name(db), module),
+ s
+ );
} else if let Some(s) = p.downcast_ref::<String>() {
- eprintln!("infer panicked for {}: {}", full_name(db, body_id, module), s);
+ eprintln!(
+ "infer panicked for {}: {}",
+ full_name(db, || body_id.name(db), module),
+ s
+ );
} else {
- eprintln!("infer panicked for {}", full_name(db, body_id, module));
+ eprintln!(
+ "infer panicked for {}",
+ full_name(db, || body_id.name(db), module)
+ );
}
panics += 1;
bar.inc(1);
@@ -834,7 +901,7 @@ impl flags::AnalysisStats {
}
};
// This query is LRU'd, so actually calling it will skew the timing results.
- let sm = || db.body_with_source_map(body_def_id).1;
+ let sm = || &Body::with_source_map(db, body_def_id).1;
// region:expressions
let (previous_exprs, previous_unknown, previous_partially_unknown) =
@@ -845,7 +912,7 @@ impl flags::AnalysisStats {
let unknown_or_partial = if ty.is_ty_error() {
num_exprs_unknown += 1;
if verbosity.is_spammy() {
- if let Some((path, start, end)) = expr_syntax_range(db, vfs, &sm(), expr_id)
+ if let Some((path, start, end)) = expr_syntax_range(db, vfs, sm(), expr_id)
{
bar.println(format!(
"{} {}:{}-{}:{}: Unknown type",
@@ -872,7 +939,7 @@ impl flags::AnalysisStats {
};
if self.only.is_some() && verbosity.is_spammy() {
// in super-verbose mode for just one function, we print every single expression
- if let Some((_, start, end)) = expr_syntax_range(db, vfs, &sm(), expr_id) {
+ if let Some((_, start, end)) = expr_syntax_range(db, vfs, sm(), expr_id) {
bar.println(format!(
"{}:{}-{}:{}: {}",
start.line + 1,
@@ -891,14 +958,14 @@ impl flags::AnalysisStats {
if unknown_or_partial && self.output == Some(OutputFormat::Csv) {
println!(
r#"{},type,"{}""#,
- location_csv_expr(db, vfs, &sm(), expr_id),
+ location_csv_expr(db, vfs, sm(), expr_id),
ty.display(db, display_target)
);
}
if let Some(mismatch) = inference_result.type_mismatch_for_expr(expr_id) {
num_expr_type_mismatches += 1;
if verbosity.is_verbose() {
- if let Some((path, start, end)) = expr_syntax_range(db, vfs, &sm(), expr_id)
+ if let Some((path, start, end)) = expr_syntax_range(db, vfs, sm(), expr_id)
{
bar.println(format!(
"{} {}:{}-{}:{}: Expected {}, got {}",
@@ -922,7 +989,7 @@ impl flags::AnalysisStats {
if self.output == Some(OutputFormat::Csv) {
println!(
r#"{},mismatch,"{}","{}""#,
- location_csv_expr(db, vfs, &sm(), expr_id),
+ location_csv_expr(db, vfs, sm(), expr_id),
mismatch.expected.as_ref().display(db, display_target),
mismatch.actual.as_ref().display(db, display_target)
);
@@ -932,7 +999,7 @@ impl flags::AnalysisStats {
if verbosity.is_spammy() {
bar.println(format!(
"In {}: {} exprs, {} unknown, {} partial",
- full_name(db, body_id, module),
+ full_name(db, || body_id.name(db), module),
num_exprs - previous_exprs,
num_exprs_unknown - previous_unknown,
num_exprs_partially_unknown - previous_partially_unknown
@@ -949,7 +1016,7 @@ impl flags::AnalysisStats {
let unknown_or_partial = if ty.is_ty_error() {
num_pats_unknown += 1;
if verbosity.is_spammy() {
- if let Some((path, start, end)) = pat_syntax_range(db, vfs, &sm(), pat_id) {
+ if let Some((path, start, end)) = pat_syntax_range(db, vfs, sm(), pat_id) {
bar.println(format!(
"{} {}:{}-{}:{}: Unknown type",
path,
@@ -975,7 +1042,7 @@ impl flags::AnalysisStats {
};
if self.only.is_some() && verbosity.is_spammy() {
// in super-verbose mode for just one function, we print every single pattern
- if let Some((_, start, end)) = pat_syntax_range(db, vfs, &sm(), pat_id) {
+ if let Some((_, start, end)) = pat_syntax_range(db, vfs, sm(), pat_id) {
bar.println(format!(
"{}:{}-{}:{}: {}",
start.line + 1,
@@ -994,14 +1061,14 @@ impl flags::AnalysisStats {
if unknown_or_partial && self.output == Some(OutputFormat::Csv) {
println!(
r#"{},type,"{}""#,
- location_csv_pat(db, vfs, &sm(), pat_id),
+ location_csv_pat(db, vfs, sm(), pat_id),
ty.display(db, display_target)
);
}
if let Some(mismatch) = inference_result.type_mismatch_for_pat(pat_id) {
num_pat_type_mismatches += 1;
if verbosity.is_verbose() {
- if let Some((path, start, end)) = pat_syntax_range(db, vfs, &sm(), pat_id) {
+ if let Some((path, start, end)) = pat_syntax_range(db, vfs, sm(), pat_id) {
bar.println(format!(
"{} {}:{}-{}:{}: Expected {}, got {}",
path,
@@ -1024,7 +1091,7 @@ impl flags::AnalysisStats {
if self.output == Some(OutputFormat::Csv) {
println!(
r#"{},mismatch,"{}","{}""#,
- location_csv_pat(db, vfs, &sm(), pat_id),
+ location_csv_pat(db, vfs, sm(), pat_id),
mismatch.expected.as_ref().display(db, display_target),
mismatch.actual.as_ref().display(db, display_target)
);
@@ -1034,7 +1101,7 @@ impl flags::AnalysisStats {
if verbosity.is_spammy() {
bar.println(format!(
"In {}: {} pats, {} unknown, {} partial",
- full_name(db, body_id, module),
+ full_name(db, || body_id.name(db), module),
num_pats - previous_pats,
num_pats_unknown - previous_unknown,
num_pats_partially_unknown - previous_partially_unknown
@@ -1078,20 +1145,104 @@ impl flags::AnalysisStats {
db: &RootDatabase,
vfs: &Vfs,
bodies: &[DefWithBody],
+ signatures: &[GenericDef],
+ variants: &[Variant],
verbosity: Verbosity,
) {
let mut bar = match verbosity {
Verbosity::Quiet | Verbosity::Spammy => ProgressReport::hidden(),
_ if self.output.is_some() => ProgressReport::hidden(),
- _ => ProgressReport::new(bodies.len()),
+ _ => ProgressReport::new(bodies.len() + signatures.len() + variants.len()),
};
let mut sw = self.stop_watch();
bar.tick();
+ for &signature in signatures {
+ let Ok(signature_id) = signature.try_into() else { continue };
+ let module = signature.module(db);
+ if !self.should_process(db, || signature.name(db), module) {
+ continue;
+ }
+ let msg = move || {
+ if verbosity.is_verbose() {
+ let source = match signature {
+ GenericDef::Function(it) => it.source(db).map(|it| it.syntax().cloned()),
+ GenericDef::Static(it) => it.source(db).map(|it| it.syntax().cloned()),
+ GenericDef::Const(it) => it.source(db).map(|it| it.syntax().cloned()),
+ GenericDef::Adt(adt) => adt.source(db).map(|it| it.syntax().cloned()),
+ GenericDef::Trait(it) => it.source(db).map(|it| it.syntax().cloned()),
+ GenericDef::TypeAlias(type_alias) => {
+ type_alias.source(db).map(|it| it.syntax().cloned())
+ }
+ GenericDef::Impl(it) => it.source(db).map(|it| it.syntax().cloned()),
+ };
+ if let Some(src) = source {
+ let original_file = src.file_id.original_file(db);
+ let path = vfs.file_path(original_file.file_id(db));
+ let syntax_range = src.text_range();
+ format!(
+ "processing: {} ({} {:?})",
+ full_name(db, || signature.name(db), module),
+ path,
+ syntax_range
+ )
+ } else {
+ format!("processing: {}", full_name(db, || signature.name(db), module))
+ }
+ } else {
+ format!("processing: {}", full_name(db, || signature.name(db), module))
+ }
+ };
+ if verbosity.is_spammy() {
+ bar.println(msg());
+ }
+ bar.set_message(msg);
+ ExpressionStore::of(db, ExpressionStoreOwnerId::Signature(signature_id));
+ bar.inc(1);
+ }
+
+ for &variant in variants {
+ let variant_id = variant.into();
+ let module = variant.module(db);
+ if !self.should_process(db, || Some(variant.name(db)), module) {
+ continue;
+ }
+ let msg = move || {
+ if verbosity.is_verbose() {
+ let source = match variant {
+ Variant::EnumVariant(it) => it.source(db).map(|it| it.syntax().cloned()),
+ Variant::Struct(it) => it.source(db).map(|it| it.syntax().cloned()),
+ Variant::Union(it) => it.source(db).map(|it| it.syntax().cloned()),
+ };
+ if let Some(src) = source {
+ let original_file = src.file_id.original_file(db);
+ let path = vfs.file_path(original_file.file_id(db));
+ let syntax_range = src.text_range();
+ format!(
+ "processing: {} ({} {:?})",
+ full_name(db, || Some(variant.name(db)), module),
+ path,
+ syntax_range
+ )
+ } else {
+ format!("processing: {}", full_name(db, || Some(variant.name(db)), module))
+ }
+ } else {
+ format!("processing: {}", full_name(db, || Some(variant.name(db)), module))
+ }
+ };
+ if verbosity.is_spammy() {
+ bar.println(msg());
+ }
+ bar.set_message(msg);
+ ExpressionStore::of(db, ExpressionStoreOwnerId::VariantFields(variant_id));
+ bar.inc(1);
+ }
+
for &body_id in bodies {
let Ok(body_def_id) = body_id.try_into() else { continue };
let module = body_id.module(db);
- if !self.should_process(db, body_id, module) {
+ if !self.should_process(db, || body_id.name(db), module) {
continue;
}
let msg = move || {
@@ -1100,7 +1251,9 @@ impl flags::AnalysisStats {
DefWithBody::Function(it) => it.source(db).map(|it| it.syntax().cloned()),
DefWithBody::Static(it) => it.source(db).map(|it| it.syntax().cloned()),
DefWithBody::Const(it) => it.source(db).map(|it| it.syntax().cloned()),
- DefWithBody::Variant(it) => it.source(db).map(|it| it.syntax().cloned()),
+ DefWithBody::EnumVariant(it) => {
+ it.source(db).map(|it| it.syntax().cloned())
+ }
};
if let Some(src) = source {
let original_file = src.file_id.original_file(db);
@@ -1108,28 +1261,28 @@ impl flags::AnalysisStats {
let syntax_range = src.text_range();
format!(
"processing: {} ({} {:?})",
- full_name(db, body_id, module),
+ full_name(db, || body_id.name(db), module),
path,
syntax_range
)
} else {
- format!("processing: {}", full_name(db, body_id, module))
+ format!("processing: {}", full_name(db, || body_id.name(db), module))
}
} else {
- format!("processing: {}", full_name(db, body_id, module))
+ format!("processing: {}", full_name(db, || body_id.name(db), module))
}
};
if verbosity.is_spammy() {
bar.println(msg());
}
bar.set_message(msg);
- db.body(body_def_id);
+ Body::of(db, body_def_id);
bar.inc(1);
}
bar.finish_and_clear();
let body_lowering_time = sw.elapsed();
- eprintln!("{:<20} {}", "Body lowering:", body_lowering_time);
+ eprintln!("{:<20} {}", "Expression Store Lowering:", body_lowering_time);
report_metric("body lowering time", body_lowering_time.time.as_millis() as u64, "ms");
}
@@ -1283,12 +1436,17 @@ impl flags::AnalysisStats {
eprintln!("{:<20} {} ({} files)", "IDE:", ide_time, file_ids.len());
}
- fn should_process(&self, db: &RootDatabase, body_id: DefWithBody, module: hir::Module) -> bool {
+ fn should_process(
+ &self,
+ db: &RootDatabase,
+ name_fn: impl Fn() -> Option<Name>,
+ module: hir::Module,
+ ) -> bool {
if let Some(only_name) = self.only.as_deref() {
- let name = body_id.name(db).unwrap_or_else(Name::missing);
+ let name = name_fn().unwrap_or_else(Name::missing);
if name.display(db, Edition::LATEST).to_string() != only_name
- && full_name(db, body_id, module) != only_name
+ && full_name(db, name_fn, module) != only_name
{
return false;
}
@@ -1301,7 +1459,7 @@ impl flags::AnalysisStats {
}
}
-fn full_name(db: &RootDatabase, body_id: DefWithBody, module: hir::Module) -> String {
+fn full_name(db: &RootDatabase, name: impl Fn() -> Option<Name>, module: hir::Module) -> String {
module
.krate(db)
.display_name(db)
@@ -1313,7 +1471,7 @@ fn full_name(db: &RootDatabase, body_id: DefWithBody, module: hir::Module) -> St
.into_iter()
.filter_map(|it| it.name(db))
.rev()
- .chain(Some(body_id.name(db).unwrap_or_else(Name::missing)))
+ .chain(Some(name().unwrap_or_else(Name::missing)))
.map(|it| it.display(db, Edition::LATEST).to_string()),
)
.join("::")
diff --git a/crates/rust-analyzer/src/flycheck.rs b/crates/rust-analyzer/src/flycheck.rs
index cdaf944bba..c41696bf3f 100644
--- a/crates/rust-analyzer/src/flycheck.rs
+++ b/crates/rust-analyzer/src/flycheck.rs
@@ -1021,7 +1021,7 @@ impl JsonLinesParser<CheckMessage> for CheckParser {
}
}
-#[derive(Deserialize)]
+#[derive(Deserialize, Debug)]
#[serde(untagged)]
enum JsonMessage {
Cargo(cargo_metadata::Message),
diff --git a/crates/rust-analyzer/src/handlers/notification.rs b/crates/rust-analyzer/src/handlers/notification.rs
index 138310b78f..09b6794e4f 100644
--- a/crates/rust-analyzer/src/handlers/notification.rs
+++ b/crates/rust-analyzer/src/handlers/notification.rs
@@ -295,8 +295,9 @@ pub(crate) fn handle_did_change_watched_files(
for change in params.changes.iter().unique_by(|&it| &it.uri) {
if let Ok(path) = from_proto::abs_path(&change.uri) {
if !trigger_flycheck {
+ // Trigger if no workspaces contain this file.
trigger_flycheck =
- state.config.workspace_roots().iter().any(|root| !path.starts_with(root));
+ state.config.workspace_roots().iter().all(|root| !path.starts_with(root));
}
state.loader.handle.invalidate(path);
}
diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs
index 83edbc722b..7c494de6f7 100644
--- a/crates/rust-analyzer/src/main_loop.rs
+++ b/crates/rust-analyzer/src/main_loop.rs
@@ -92,7 +92,7 @@ impl fmt::Display for Event {
Event::DeferredTask(_) => write!(f, "Event::DeferredTask"),
Event::TestResult(_) => write!(f, "Event::TestResult"),
Event::DiscoverProject(_) => write!(f, "Event::DiscoverProject"),
- Event::FetchWorkspaces(_) => write!(f, "Event::SwitchWorkspaces"),
+ Event::FetchWorkspaces(_) => write!(f, "Event::FetchWorkspaces"),
}
}
}
@@ -303,15 +303,6 @@ impl GlobalState {
.map(Some)
}
- fn trigger_garbage_collection(&mut self) {
- if cfg!(test) {
- // Slow tests run the main loop in multiple threads, but GC isn't thread safe.
- return;
- }
-
- self.analysis_host.trigger_garbage_collection();
- }
-
fn handle_event(&mut self, event: Event) {
let loop_start = Instant::now();
let _p = tracing::info_span!("GlobalState::handle_event", event = %event).entered();
@@ -392,7 +383,7 @@ impl GlobalState {
));
}
PrimeCachesProgress::End { cancelled } => {
- self.trigger_garbage_collection();
+ self.analysis_host.trigger_garbage_collection();
self.prime_caches_queue.op_completed(());
if cancelled {
self.prime_caches_queue
@@ -551,7 +542,7 @@ impl GlobalState {
&& self.fmt_pool.handle.is_empty()
&& current_revision != self.last_gc_revision
{
- self.trigger_garbage_collection();
+ self.analysis_host.trigger_garbage_collection();
self.last_gc_revision = current_revision;
}
}
diff --git a/crates/span/src/ast_id.rs b/crates/span/src/ast_id.rs
index f52604e139..f6500a9b4d 100644
--- a/crates/span/src/ast_id.rs
+++ b/crates/span/src/ast_id.rs
@@ -206,6 +206,11 @@ impl ErasedFileAstId {
self.0 >> (HASH_BITS + INDEX_BITS)
}
+ #[inline]
+ pub fn is_root(self) -> bool {
+ self.kind() == ErasedFileAstIdKind::Root as u32
+ }
+
fn ast_id_for(
node: &SyntaxNode,
index_map: &mut ErasedAstIdNextIndexMap,
@@ -220,14 +225,16 @@ impl ErasedFileAstId {
.or_else(|| asm_expr_ast_id(node, index_map))
}
- fn should_alloc(node: &SyntaxNode) -> bool {
+ fn should_alloc(node: &SyntaxNode) -> Option<ErasedFileAstIdKind> {
let kind = node.kind();
should_alloc_has_name(kind)
- || should_alloc_assoc_item(kind)
- || ast::ExternBlock::can_cast(kind)
- || ast::Use::can_cast(kind)
- || ast::Impl::can_cast(kind)
- || ast::AsmExpr::can_cast(kind)
+ .or_else(|| should_alloc_assoc_item(kind))
+ .or_else(|| {
+ ast::ExternBlock::can_cast(kind).then_some(ErasedFileAstIdKind::ExternBlock)
+ })
+ .or_else(|| ast::Use::can_cast(kind).then_some(ErasedFileAstIdKind::Use))
+ .or_else(|| ast::Impl::can_cast(kind).then_some(ErasedFileAstIdKind::Impl))
+ .or_else(|| ast::AsmExpr::can_cast(kind).then_some(ErasedFileAstIdKind::AsmExpr))
}
#[inline]
@@ -478,8 +485,8 @@ macro_rules! register_has_name_ast_id {
}
}
- fn should_alloc_has_name(kind: SyntaxKind) -> bool {
- false $( || ast::$ident::can_cast(kind) )*
+ fn should_alloc_has_name(kind: SyntaxKind) -> Option<ErasedFileAstIdKind> {
+ $( if ast::$ident::can_cast(kind) { Some(ErasedFileAstIdKind::$ident) } else )* { None }
}
};
}
@@ -528,8 +535,8 @@ macro_rules! register_assoc_item_ast_id {
}
}
- fn should_alloc_assoc_item(kind: SyntaxKind) -> bool {
- false $( || ast::$ident::can_cast(kind) )*
+ fn should_alloc_assoc_item(kind: SyntaxKind) -> Option<ErasedFileAstIdKind> {
+ $( if ast::$ident::can_cast(kind) { Some(ErasedFileAstIdKind::$ident) } else )* { None }
}
};
}
@@ -612,22 +619,49 @@ impl AstIdMap {
syntax::WalkEvent::Enter(node) => {
if ast::BlockExpr::can_cast(node.kind()) {
blocks.push((node, ContainsItems::No));
- } else if ErasedFileAstId::should_alloc(&node) {
+ } else if let Some(kind) = ErasedFileAstId::should_alloc(&node) {
// Allocate blocks on-demand, only if they have items.
// We don't associate items with blocks, only with items, since block IDs can be quite unstable.
// FIXME: Is this the correct thing to do? Macro calls might actually be more incremental if
// associated with blocks (not sure). Either way it's not a big deal.
+ let is_item = matches!(
+ kind,
+ ErasedFileAstIdKind::Enum
+ | ErasedFileAstIdKind::Struct
+ | ErasedFileAstIdKind::Union
+ | ErasedFileAstIdKind::ExternCrate
+ | ErasedFileAstIdKind::MacroDef
+ | ErasedFileAstIdKind::MacroRules
+ | ErasedFileAstIdKind::Module
+ | ErasedFileAstIdKind::Static
+ | ErasedFileAstIdKind::Trait
+ | ErasedFileAstIdKind::Const
+ | ErasedFileAstIdKind::Fn
+ | ErasedFileAstIdKind::TypeAlias
+ | ErasedFileAstIdKind::ExternBlock
+ | ErasedFileAstIdKind::Use
+ | ErasedFileAstIdKind::Impl
+ );
if let Some((
last_block_node,
already_allocated @ ContainsItems::No,
)) = blocks.last_mut()
+ && (is_item
+ || (kind == ErasedFileAstIdKind::MacroCall && {
+ let mut anc = node.ancestors();
+ _ = anc.next();
+ anc.next().is_some_and(|it| {
+ it.kind() == SyntaxKind::MACRO_EXPR
+ }) && anc.next().is_some_and(|it| {
+ it.kind() == SyntaxKind::EXPR_STMT
+ || it.kind() == SyntaxKind::STMT_LIST
+ })
+ }))
{
- let block_ast_id = block_expr_ast_id(
- last_block_node,
- &mut index_map,
- parent_of(parent_idx, &res),
- )
- .expect("not a BlockExpr");
+ let parent = parent_of(parent_idx, &res);
+ let block_ast_id =
+ block_expr_ast_id(last_block_node, &mut index_map, parent)
+ .expect("not a BlockExpr");
res.arena
.alloc((SyntaxNodePtr::new(last_block_node), block_ast_id));
*already_allocated = ContainsItems::Yes;
@@ -645,8 +679,9 @@ impl AstIdMap {
}
syntax::WalkEvent::Leave(node) => {
if ast::BlockExpr::can_cast(node.kind()) {
- assert_eq!(
- blocks.pop().map(|it| it.0),
+ let block = blocks.pop();
+ debug_assert_eq!(
+ block.map(|it| it.0),
Some(node),
"left a BlockExpr we never entered"
);
diff --git a/crates/stdx/src/lib.rs b/crates/stdx/src/lib.rs
index a1af4cc6be..275e0e5ac8 100644
--- a/crates/stdx/src/lib.rs
+++ b/crates/stdx/src/lib.rs
@@ -1,5 +1,6 @@
//! Missing batteries for standard libraries.
+use std::borrow::Cow;
use std::io as sio;
use std::process::Command;
use std::{cmp::Ordering, ops, time::Instant};
@@ -250,6 +251,24 @@ pub fn dedent_by(spaces: usize, text: &str) -> String {
.collect()
}
+/// Indent non empty lines, including the first line
+#[must_use]
+pub fn indent_string(s: &str, indent_level: u8) -> String {
+ if indent_level == 0 || s.is_empty() {
+ return s.to_owned();
+ }
+ let indent_str = " ".repeat(indent_level as usize);
+ s.split_inclusive("\n")
+ .map(|line| {
+ if line.trim_end().is_empty() {
+ Cow::Borrowed(line)
+ } else {
+ format!("{indent_str}{line}").into()
+ }
+ })
+ .collect()
+}
+
pub fn equal_range_by<T, F>(slice: &[T], mut key: F) -> ops::Range<usize>
where
F: FnMut(&T) -> Ordering,
diff --git a/crates/syntax/rust.ungram b/crates/syntax/rust.ungram
index 544053408f..3113fc7430 100644
--- a/crates/syntax/rust.ungram
+++ b/crates/syntax/rust.ungram
@@ -245,7 +245,7 @@ RecordFieldList =
RecordField =
Attr* Visibility? 'unsafe'?
- Name ':' Type ('=' Expr)?
+ Name ':' Type ('=' default_val:ConstArg)?
TupleFieldList =
'(' fields:(TupleField (',' TupleField)* ','?)? ')'
@@ -268,7 +268,7 @@ VariantList =
Variant =
Attr* Visibility?
- Name FieldList? ('=' Expr)?
+ Name FieldList? ('=' ConstArg)?
Union =
Attr* Visibility?
diff --git a/crates/syntax/src/ast/edit.rs b/crates/syntax/src/ast/edit.rs
index 194d06900a..b706d7f722 100644
--- a/crates/syntax/src/ast/edit.rs
+++ b/crates/syntax/src/ast/edit.rs
@@ -50,7 +50,7 @@ impl ops::AddAssign<u8> for IndentLevel {
}
impl IndentLevel {
- pub fn single() -> IndentLevel {
+ pub fn zero() -> IndentLevel {
IndentLevel(0)
}
pub fn is_zero(&self) -> bool {
diff --git a/crates/syntax/src/ast/edit_in_place.rs b/crates/syntax/src/ast/edit_in_place.rs
index 2b7dc5cd76..7f59ae4213 100644
--- a/crates/syntax/src/ast/edit_in_place.rs
+++ b/crates/syntax/src/ast/edit_in_place.rs
@@ -591,7 +591,7 @@ impl ast::AssocItemList {
normalize_ws_between_braces(self.syntax());
(IndentLevel::from_token(&l_curly) + 1, ted::Position::after(&l_curly), "\n")
}
- None => (IndentLevel::single(), ted::Position::last_child_of(self.syntax()), "\n"),
+ None => (IndentLevel::zero(), ted::Position::last_child_of(self.syntax()), "\n"),
},
};
let elements: Vec<SyntaxElement> = vec![
diff --git a/crates/syntax/src/ast/generated/nodes.rs b/crates/syntax/src/ast/generated/nodes.rs
index c4e72eafa7..7334de0fd9 100644
--- a/crates/syntax/src/ast/generated/nodes.rs
+++ b/crates/syntax/src/ast/generated/nodes.rs
@@ -1337,7 +1337,7 @@ impl ast::HasName for RecordField {}
impl ast::HasVisibility for RecordField {}
impl RecordField {
#[inline]
- pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
+ pub fn default_val(&self) -> Option<ConstArg> { support::child(&self.syntax) }
#[inline]
pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
#[inline]
@@ -1896,7 +1896,7 @@ impl ast::HasName for Variant {}
impl ast::HasVisibility for Variant {}
impl Variant {
#[inline]
- pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
+ pub fn const_arg(&self) -> Option<ConstArg> { support::child(&self.syntax) }
#[inline]
pub fn field_list(&self) -> Option<FieldList> { support::child(&self.syntax) }
#[inline]
diff --git a/crates/syntax/src/ast/make.rs b/crates/syntax/src/ast/make.rs
index f5d1d009a5..00971569a2 100644
--- a/crates/syntax/src/ast/make.rs
+++ b/crates/syntax/src/ast/make.rs
@@ -74,10 +74,18 @@ pub mod ext {
expr_from_text("_")
}
pub fn expr_ty_default(ty: &ast::Type) -> ast::Expr {
- expr_from_text(&format!("{ty}::default()"))
+ if !ty.needs_angles_in_path() {
+ expr_from_text(&format!("{ty}::default()"))
+ } else {
+ expr_from_text(&format!("<{ty}>::default()"))
+ }
}
pub fn expr_ty_new(ty: &ast::Type) -> ast::Expr {
- expr_from_text(&format!("{ty}::new()"))
+ if !ty.needs_angles_in_path() {
+ expr_from_text(&format!("{ty}::new()"))
+ } else {
+ expr_from_text(&format!("<{ty}>::new()"))
+ }
}
pub fn expr_self() -> ast::Expr {
expr_from_text("self")
diff --git a/crates/syntax/src/ast/node_ext.rs b/crates/syntax/src/ast/node_ext.rs
index 76cfea9d5b..63e4608d0f 100644
--- a/crates/syntax/src/ast/node_ext.rs
+++ b/crates/syntax/src/ast/node_ext.rs
@@ -717,6 +717,10 @@ impl ast::Type {
None
}
}
+
+ pub fn needs_angles_in_path(&self) -> bool {
+ !matches!(self, ast::Type::PathType(_)) || self.generic_arg_list().is_some()
+ }
}
#[derive(Debug, Clone, PartialEq, Eq)]
diff --git a/crates/syntax/src/ast/syntax_factory/constructors.rs b/crates/syntax/src/ast/syntax_factory/constructors.rs
index 55c80ed167..44114a7802 100644
--- a/crates/syntax/src/ast/syntax_factory/constructors.rs
+++ b/crates/syntax/src/ast/syntax_factory/constructors.rs
@@ -29,6 +29,10 @@ impl SyntaxFactory {
make::ext::expr_todo().clone_for_update()
}
+ pub fn expr_self(&self) -> ast::Expr {
+ make::ext::expr_self().clone_for_update()
+ }
+
pub fn lifetime(&self, text: &str) -> ast::Lifetime {
make::lifetime(text).clone_for_update()
}
@@ -59,6 +63,26 @@ impl SyntaxFactory {
ast
}
+ pub fn type_bound(&self, bound: ast::Type) -> ast::TypeBound {
+ make::type_bound(bound).clone_for_update()
+ }
+
+ pub fn type_bound_list(
+ &self,
+ bounds: impl IntoIterator<Item = ast::TypeBound>,
+ ) -> Option<ast::TypeBoundList> {
+ let (bounds, input) = iterator_input(bounds);
+ let ast = make::type_bound_list(bounds)?.clone_for_update();
+
+ if let Some(mut mapping) = self.mappings() {
+ let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
+ builder.map_children(input, ast.bounds().map(|b| b.syntax().clone()));
+ builder.finish(&mut mapping);
+ }
+
+ Some(ast)
+ }
+
pub fn type_param(
&self,
name: ast::Name,
@@ -1450,6 +1474,22 @@ impl SyntaxFactory {
ast
}
+ pub fn record_expr_field_list(
+ &self,
+ fields: impl IntoIterator<Item = ast::RecordExprField>,
+ ) -> ast::RecordExprFieldList {
+ let (fields, input) = iterator_input(fields);
+ let ast = make::record_expr_field_list(fields).clone_for_update();
+
+ if let Some(mut mapping) = self.mappings() {
+ let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
+ builder.map_children(input, ast.fields().map(|f| f.syntax().clone()));
+ builder.finish(&mut mapping);
+ }
+
+ ast
+ }
+
pub fn record_expr_field(
&self,
name: ast::NameRef,
@@ -1460,7 +1500,20 @@ impl SyntaxFactory {
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
- builder.map_node(name.syntax().clone(), ast.name_ref().unwrap().syntax().clone());
+ if let Some(ast_name_ref) = ast.name_ref() {
+ // NameRef is a direct child
+ builder.map_node(name.syntax().clone(), ast_name_ref.syntax().clone());
+ } else {
+ // NameRef is nested inside PathExpr > Path > PathSegment.
+ // map_node requires the output to be a direct child of the builder's parent, so
+ // we need a separate builder scoped to PathSegment.
+ let ast::Expr::PathExpr(path_expr) = ast.expr().unwrap() else { unreachable!() };
+ let path_segment = path_expr.path().unwrap().segment().unwrap();
+ let inner_name_ref = path_segment.name_ref().unwrap();
+ let mut inner_builder = SyntaxMappingBuilder::new(path_segment.syntax().clone());
+ inner_builder.map_node(name.syntax().clone(), inner_name_ref.syntax().clone());
+ inner_builder.finish(&mut mapping);
+ }
if let Some(expr) = expr {
builder.map_node(expr.syntax().clone(), ast.expr().unwrap().syntax().clone());
}
@@ -1665,8 +1718,10 @@ impl SyntaxFactory {
}
if let Some(discriminant) = discriminant {
- builder
- .map_node(discriminant.syntax().clone(), ast.expr().unwrap().syntax().clone());
+ builder.map_node(
+ discriminant.syntax().clone(),
+ ast.const_arg().unwrap().syntax().clone(),
+ );
}
builder.finish(&mut mapping);
@@ -1759,6 +1814,10 @@ impl SyntaxFactory {
ast
}
+ pub fn assoc_item_list_empty(&self) -> ast::AssocItemList {
+ make::assoc_item_list(None).clone_for_update()
+ }
+
pub fn attr_outer(&self, meta: ast::Meta) -> ast::Attr {
let ast = make::attr_outer(meta.clone()).clone_for_update();
diff --git a/crates/syntax/src/syntax_editor/edits.rs b/crates/syntax/src/syntax_editor/edits.rs
index ad08928923..44f0a8038e 100644
--- a/crates/syntax/src/syntax_editor/edits.rs
+++ b/crates/syntax/src/syntax_editor/edits.rs
@@ -210,7 +210,7 @@ impl ast::AssocItemList {
normalize_ws_between_braces(editor, self.syntax());
(IndentLevel::from_token(&l_curly) + 1, Position::after(&l_curly), "\n")
}
- None => (IndentLevel::single(), Position::last_child_of(self.syntax()), "\n"),
+ None => (IndentLevel::zero(), Position::last_child_of(self.syntax()), "\n"),
},
};
@@ -242,7 +242,7 @@ impl ast::VariantList {
normalize_ws_between_braces(editor, self.syntax());
(IndentLevel::from_token(&l_curly) + 1, Position::after(&l_curly))
}
- None => (IndentLevel::single(), Position::last_child_of(self.syntax())),
+ None => (IndentLevel::zero(), Position::last_child_of(self.syntax())),
},
};
let elements: Vec<SyntaxElement> = vec![
diff --git a/crates/test-utils/src/minicore.rs b/crates/test-utils/src/minicore.rs
index c34475bbdf..86fb080732 100644
--- a/crates/test-utils/src/minicore.rs
+++ b/crates/test-utils/src/minicore.rs
@@ -1503,6 +1503,19 @@ pub mod slice {
loop {}
}
}
+
+ // region:default
+ impl<T> const Default for &[T] {
+ fn default() -> Self {
+ &[]
+ }
+ }
+ impl<T> const Default for &mut [T] {
+ fn default() -> Self {
+ &mut []
+ }
+ }
+ // endregion:default
}
// endregion:slice
diff --git a/editors/code/package-lock.json b/editors/code/package-lock.json
index 047dbba11f..b51dc4d132 100644
--- a/editors/code/package-lock.json
+++ b/editors/code/package-lock.json
@@ -738,9 +738,9 @@
}
},
"node_modules/@eslint/config-array/node_modules/brace-expansion": {
- "version": "1.1.12",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
- "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
+ "version": "1.1.13",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.13.tgz",
+ "integrity": "sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -799,9 +799,9 @@
}
},
"node_modules/@eslint/eslintrc/node_modules/brace-expansion": {
- "version": "1.1.12",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
- "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
+ "version": "1.1.13",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.13.tgz",
+ "integrity": "sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -1817,9 +1817,9 @@
]
},
"node_modules/@vscode/vsce/node_modules/brace-expansion": {
- "version": "1.1.12",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
- "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
+ "version": "1.1.13",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.13.tgz",
+ "integrity": "sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -2060,9 +2060,9 @@
"license": "BSD-2-Clause"
},
"node_modules/brace-expansion": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
- "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.3.tgz",
+ "integrity": "sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA==",
"license": "MIT",
"dependencies": {
"balanced-match": "^1.0.0"
@@ -3416,9 +3416,9 @@
}
},
"node_modules/eslint/node_modules/brace-expansion": {
- "version": "1.1.12",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
- "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
+ "version": "1.1.13",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.13.tgz",
+ "integrity": "sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -3895,9 +3895,9 @@
}
},
"node_modules/glob/node_modules/brace-expansion": {
- "version": "5.0.4",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.4.tgz",
- "integrity": "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg==",
+ "version": "5.0.5",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz",
+ "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -4822,9 +4822,9 @@
}
},
"node_modules/micromatch/node_modules/picomatch": {
- "version": "2.3.1",
- "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
- "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz",
+ "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==",
"dev": true,
"license": "MIT",
"engines": {
@@ -5463,9 +5463,9 @@
"license": "ISC"
},
"node_modules/picomatch": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz",
- "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==",
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz",
+ "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==",
"dev": true,
"license": "MIT",
"engines": {
diff --git a/rust-version b/rust-version
index db9492636f..68f38716db 100644
--- a/rust-version
+++ b/rust-version
@@ -1 +1 @@
-eda4fc7733ee89e484d7120cafbd80dcb2fce66e
+1174f784096deb8e4ba93f7e4b5ccb7bb4ba2c55