From 50c2faad9213618e84ea322519c874dead7ecc65 Mon Sep 17 00:00:00 2001 From: Vincent Esche Date: Fri, 6 Jun 2025 09:37:54 +0200 Subject: [PATCH 01/56] Make `Semantics<'db, dyn HirDatabase>` actually usable --- .../rust-analyzer/crates/hir/src/semantics.rs | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics.rs b/src/tools/rust-analyzer/crates/hir/src/semantics.rs index 4a2e8e379fb83..953e2e7a02509 100644 --- a/src/tools/rust-analyzer/crates/hir/src/semantics.rs +++ b/src/tools/rust-analyzer/crates/hir/src/semantics.rs @@ -159,13 +159,13 @@ pub struct SemanticsImpl<'db> { macro_call_cache: RefCell, MacroCallId>>, } -impl fmt::Debug for Semantics<'_, DB> { +impl fmt::Debug for Semantics<'_, DB> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "Semantics {{ ... }}") } } -impl<'db, DB> ops::Deref for Semantics<'db, DB> { +impl<'db, DB: ?Sized> ops::Deref for Semantics<'db, DB> { type Target = SemanticsImpl<'db>; fn deref(&self) -> &Self::Target { @@ -173,12 +173,28 @@ impl<'db, DB> ops::Deref for Semantics<'db, DB> { } } +// Note: while this variant of `Semantics<'_, _>` might seem unused, as it does not +// find actual use within the rust-analyzer project itself, it exists to enable the use +// within e.g. tracked salsa functions in third-party crates that build upon `ra_ap_hir`. +impl Semantics<'_, dyn HirDatabase> { + /// Creates an instance that's weakly coupled to its underlying database type. + pub fn new_dyn(db: &'_ dyn HirDatabase) -> Semantics<'_, dyn HirDatabase> { + let impl_ = SemanticsImpl::new(db); + Semantics { db, imp: impl_ } + } +} + impl Semantics<'_, DB> { + /// Creates an instance that's strongly coupled to its underlying database type. pub fn new(db: &DB) -> Semantics<'_, DB> { let impl_ = SemanticsImpl::new(db); Semantics { db, imp: impl_ } } +} +// Note: We take `DB` as `?Sized` here in order to support type-erased +// use of `Semantics` via `Semantics<'_, dyn HirDatabase>`: +impl Semantics<'_, DB> { pub fn hir_file_for(&self, syntax_node: &SyntaxNode) -> HirFileId { self.imp.find_file(syntax_node).file_id } From a5bf989466dfda69750ddf488772fd621c9258d9 Mon Sep 17 00:00:00 2001 From: Chayim Refael Friedman Date: Sun, 8 Jun 2025 01:07:55 +0300 Subject: [PATCH 02/56] Remove the optimization of builtin attrs in `is_inside_macro_call()` `#[cfg_attr]` is a builtin attr, but it may still contain a macro. --- src/tools/rust-analyzer/crates/hir/src/semantics.rs | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics.rs b/src/tools/rust-analyzer/crates/hir/src/semantics.rs index 4a2e8e379fb83..52a8012f407a1 100644 --- a/src/tools/rust-analyzer/crates/hir/src/semantics.rs +++ b/src/tools/rust-analyzer/crates/hir/src/semantics.rs @@ -25,7 +25,6 @@ use hir_expand::{ builtin::{BuiltinFnLikeExpander, EagerExpander}, db::ExpandDatabase, files::{FileRangeWrapper, HirFileRange, InRealFile}, - inert_attr_macro::find_builtin_attr_idx, mod_path::{ModPath, PathKind}, name::AsName, }; @@ -953,13 +952,6 @@ impl<'db> SemanticsImpl<'db> { let Some(item) = ast::Item::cast(ancestor) else { return false; }; - // Optimization to skip the semantic check. - if item.attrs().all(|attr| { - attr.simple_name() - .is_some_and(|attr| find_builtin_attr_idx(&Symbol::intern(&attr)).is_some()) - }) { - return false; - } self.with_ctx(|ctx| { if ctx.item_to_macro_call(token.with_value(&item)).is_some() { return true; From ac34cb4b4729114fe7f6dc3d1d0d6a00dc1322a6 Mon Sep 17 00:00:00 2001 From: Chayim Refael Friedman Date: Sun, 8 Jun 2025 01:44:14 +0300 Subject: [PATCH 03/56] Correctly handle attr macros placed in cfg_attr in speculative expansion --- .../rust-analyzer/crates/hir-expand/src/db.rs | 46 +++++++++++-------- 1 file changed, 26 insertions(+), 20 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/db.rs b/src/tools/rust-analyzer/crates/hir-expand/src/db.rs index 7cb1b6c02075b..6fd9c497c1f72 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/db.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/db.rs @@ -13,7 +13,7 @@ use crate::{ AstId, BuiltinAttrExpander, BuiltinDeriveExpander, BuiltinFnLikeExpander, EagerCallInfo, EagerExpander, EditionedFileId, ExpandError, ExpandResult, ExpandTo, HirFileId, MacroCallId, MacroCallKind, MacroCallLoc, MacroDefId, MacroDefKind, - attrs::{AttrId, collect_attrs}, + attrs::{AttrId, AttrInput, RawAttrs, collect_attrs}, builtin::pseudo_derive_attr_expansion, cfg_process, declarative::DeclarativeMacroExpander, @@ -241,30 +241,36 @@ pub fn expand_speculative( let attr_arg = match loc.kind { MacroCallKind::Attr { invoc_attr_index, .. } => { - let attr = if loc.def.is_attribute_derive() { + if loc.def.is_attribute_derive() { // for pseudo-derive expansion we actually pass the attribute itself only - ast::Attr::cast(speculative_args.clone()) + ast::Attr::cast(speculative_args.clone()).and_then(|attr| attr.token_tree()).map( + |token_tree| { + let mut tree = syntax_node_to_token_tree( + token_tree.syntax(), + span_map, + span, + DocCommentDesugarMode::ProcMacro, + ); + *tree.top_subtree_delimiter_mut() = tt::Delimiter::invisible_spanned(span); + tree + }, + ) } else { // Attributes may have an input token tree, build the subtree and map for this as well // then try finding a token id for our token if it is inside this input subtree. let item = ast::Item::cast(speculative_args.clone())?; - collect_attrs(&item) - .nth(invoc_attr_index.ast_index()) - .and_then(|x| Either::left(x.1)) - }?; - match attr.token_tree() { - Some(token_tree) => { - let mut tree = syntax_node_to_token_tree( - token_tree.syntax(), - span_map, - span, - DocCommentDesugarMode::ProcMacro, - ); - *tree.top_subtree_delimiter_mut() = tt::Delimiter::invisible_spanned(span); - - Some(tree) - } - _ => None, + let attrs = RawAttrs::new_expanded(db, &item, span_map, loc.krate.cfg_options(db)); + attrs.iter().find(|attr| attr.id == invoc_attr_index).and_then(|attr| { + match attr.input.as_deref()? { + AttrInput::TokenTree(tt) => { + let mut attr_arg = tt.clone(); + attr_arg.top_subtree_delimiter_mut().kind = + tt::DelimiterKind::Invisible; + Some(attr_arg) + } + AttrInput::Literal(_) => None, + } + }) } } _ => None, From 95fdb2d81188cc04d3b26689da6e2d8cf3b0bb33 Mon Sep 17 00:00:00 2001 From: Chayim Refael Friedman Date: Tue, 10 Jun 2025 14:04:21 +0300 Subject: [PATCH 04/56] Do not error at impls for unsized types that do not include `where Self: Sized` items --- .../crates/hir-ty/src/dyn_compatibility.rs | 2 +- .../crates/hir-ty/src/generics.rs | 2 +- src/tools/rust-analyzer/crates/hir/src/lib.rs | 34 ++++++++++++++++++- .../handlers/trait_impl_missing_assoc_item.rs | 29 ++++++++++++++++ 4 files changed, 64 insertions(+), 3 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs b/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs index ed8d8dc26240e..48094945c1144 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs @@ -122,7 +122,7 @@ pub fn dyn_compatibility_of_trait_query( res } -fn generics_require_sized_self(db: &dyn HirDatabase, def: GenericDefId) -> bool { +pub fn generics_require_sized_self(db: &dyn HirDatabase, def: GenericDefId) -> bool { let krate = def.module(db).krate(); let Some(sized) = LangItem::Sized.resolve_trait(db, krate) else { return false; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/generics.rs b/src/tools/rust-analyzer/crates/hir-ty/src/generics.rs index bb4aaf7889589..a3ed39934cd8b 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/generics.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/generics.rs @@ -229,7 +229,7 @@ impl Generics { } /// Returns a Substitution that replaces each parameter by itself (i.e. `Ty::Param`). - pub(crate) fn placeholder_subst(&self, db: &dyn HirDatabase) -> Substitution { + pub fn placeholder_subst(&self, db: &dyn HirDatabase) -> Substitution { Substitution::from_iter( Interner, self.iter_id().map(|id| match id { diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs index e8218cf8611fd..969fd3eb480c9 100644 --- a/src/tools/rust-analyzer/crates/hir/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs @@ -846,7 +846,7 @@ impl Module { ) } - let missing: Vec<_> = required_items + let mut missing: Vec<_> = required_items .filter(|(name, id)| { !impl_assoc_items_scratch.iter().any(|(impl_name, impl_item)| { discriminant(impl_item) == discriminant(id) && impl_name == name @@ -854,6 +854,38 @@ impl Module { }) .map(|(name, item)| (name.clone(), AssocItem::from(*item))) .collect(); + + if !missing.is_empty() { + let self_ty = db.impl_self_ty(impl_def.id).substitute( + Interner, + &hir_ty::generics::generics(db, impl_def.id.into()).placeholder_subst(db), + ); + let self_ty = if let TyKind::Alias(AliasTy::Projection(projection)) = + self_ty.kind(Interner) + { + db.normalize_projection( + projection.clone(), + db.trait_environment(impl_def.id.into()), + ) + } else { + self_ty + }; + let self_ty_is_guaranteed_unsized = matches!( + self_ty.kind(Interner), + TyKind::Dyn(..) | TyKind::Slice(..) | TyKind::Str + ); + if self_ty_is_guaranteed_unsized { + missing.retain(|(_, assoc_item)| { + let assoc_item = match *assoc_item { + AssocItem::Function(it) => it.id.into(), + AssocItem::Const(it) => it.id.into(), + AssocItem::TypeAlias(it) => it.id.into(), + }; + !hir_ty::dyn_compatibility::generics_require_sized_self(db, assoc_item) + }); + } + } + if !missing.is_empty() { acc.push( TraitImplMissingAssocItems { diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/trait_impl_missing_assoc_item.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/trait_impl_missing_assoc_item.rs index fa7ba90a756b1..0e18ce9674044 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/trait_impl_missing_assoc_item.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/trait_impl_missing_assoc_item.rs @@ -127,4 +127,33 @@ impl !Trait for () {} "#, ) } + + #[test] + fn impl_sized_for_unsized() { + check_diagnostics( + r#" +//- minicore: sized +trait Trait { + type Item + where + Self: Sized; + + fn item() + where + Self: Sized; +} + +trait OtherTrait {} + +impl Trait for () { + type Item = (); + fn item() {} +} + +// Items with Self: Sized bound not required to be implemented for unsized types. +impl Trait for str {} +impl Trait for dyn OtherTrait {} + "#, + ) + } } From bb4a1ec431c699a4cd59cd408951e664dd485437 Mon Sep 17 00:00:00 2001 From: Wilfred Hughes Date: Tue, 10 Jun 2025 12:17:15 +0100 Subject: [PATCH 05/56] [minor] Fix typos --- src/tools/rust-analyzer/crates/hir-def/src/lib.rs | 2 +- src/tools/rust-analyzer/docs/book/README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs index b41ff026bcaa4..1e8859a9cc9c5 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs @@ -1245,7 +1245,7 @@ pub struct SyntheticSyntax; // Crate authors can opt their type out of completions in some cases. // This is done with the `#[rust_analyzer::completions(...)]` attribute. // -// All completeable things support `#[rust_analyzer::completions(ignore_flyimport)]`, +// All completable things support `#[rust_analyzer::completions(ignore_flyimport)]`, // which causes the thing to get excluded from flyimport completion. It will still // be completed when in scope. This is analogous to the setting `rust-analyzer.completion.autoimport.exclude` // with `"type": "always"`. diff --git a/src/tools/rust-analyzer/docs/book/README.md b/src/tools/rust-analyzer/docs/book/README.md index 464ea02512f74..0a3161f3af38d 100644 --- a/src/tools/rust-analyzer/docs/book/README.md +++ b/src/tools/rust-analyzer/docs/book/README.md @@ -19,7 +19,7 @@ mdbook will rebuild the documentation as changes are made. ## Making updates -While not required, installing the mdbook binary can be helfpul in order to see the changes. +While not required, installing the mdbook binary can be helpful in order to see the changes. Start with the mdbook [User Guide](https://rust-lang.github.io/mdBook/guide/installation.html) to familiarize yourself with the tool. ## Generated documentation From 3c10e1a5f04917fa52ddc19697a49a1fffadfeb7 Mon Sep 17 00:00:00 2001 From: Chayim Refael Friedman Date: Wed, 11 Jun 2025 01:03:35 +0300 Subject: [PATCH 06/56] Fix proc macro server handling of strings with minuses It used to decompose them thinking they were numbers. --- .../proc-macro-test/imp/src/lib.rs | 1 + .../crates/proc-macro-srv/src/server_impl.rs | 54 ++++++++----------- .../crates/proc-macro-srv/src/tests/mod.rs | 2 + 3 files changed, 26 insertions(+), 31 deletions(-) diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/imp/src/lib.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/imp/src/lib.rs index 6820e4b335393..2a72e50f911e3 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/imp/src/lib.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/imp/src/lib.rs @@ -31,6 +31,7 @@ pub fn fn_like_mk_literals(_args: TokenStream) -> TokenStream { TokenTree::from(Literal::byte_string(b"byte_string")), TokenTree::from(Literal::character('c')), TokenTree::from(Literal::string("string")), + TokenTree::from(Literal::string("-string")), TokenTree::from(Literal::c_string(c"cstring")), // as of 2022-07-21, there's no method on `Literal` to build a raw // string or a raw byte string diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl.rs index ad28599033485..dd576f23ae9fd 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl.rs @@ -199,37 +199,29 @@ pub(super) fn from_token_tree( } bridge::TokenTree::Literal(literal) => { - let token_trees = - if let Some((_minus, symbol)) = literal.symbol.as_str().split_once('-') { - let punct = tt::Punct { - spacing: tt::Spacing::Alone, - span: literal.span, - char: '-' as char, - }; - let leaf: tt::Leaf = tt::Leaf::from(punct); - let minus_tree = tt::TokenTree::from(leaf); - - let literal = tt::Literal { - symbol: Symbol::intern(symbol), - suffix: literal.suffix, - span: literal.span, - kind: literal_kind_to_internal(literal.kind), - }; - let leaf: tt::Leaf = tt::Leaf::from(literal); - let tree = tt::TokenTree::from(leaf); - vec![minus_tree, tree] - } else { - let literal = tt::Literal { - symbol: literal.symbol, - suffix: literal.suffix, - span: literal.span, - kind: literal_kind_to_internal(literal.kind), - }; - - let leaf: tt::Leaf = tt::Leaf::from(literal); - let tree = tt::TokenTree::from(leaf); - vec![tree] - }; + let mut token_trees = Vec::new(); + let mut symbol = literal.symbol; + if matches!( + literal.kind, + proc_macro::bridge::LitKind::Integer | proc_macro::bridge::LitKind::Float + ) && symbol.as_str().starts_with('-') + { + token_trees.push(tt::TokenTree::Leaf(tt::Leaf::Punct(tt::Punct { + spacing: tt::Spacing::Alone, + span: literal.span, + char: '-' as char, + }))); + symbol = Symbol::intern(&symbol.as_str()[1..]); + } + let literal = tt::Literal { + symbol, + suffix: literal.suffix, + span: literal.span, + kind: literal_kind_to_internal(literal.kind), + }; + let leaf: tt::Leaf = tt::Leaf::from(literal); + let tree = tt::TokenTree::from(leaf); + token_trees.push(tree); TokenStream { token_trees } } diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/mod.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/mod.rs index 3a6ce639d135f..d1ea89d2dcafd 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/mod.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/mod.rs @@ -244,6 +244,7 @@ fn test_fn_like_mk_literals() { LITERAL ByteStr byte_string 1 LITERAL Char c 1 LITERAL Str string 1 + LITERAL Str -string 1 LITERAL CStr cstring 1 LITERAL Float 3.14f64 1 PUNCH - [alone] 1 @@ -266,6 +267,7 @@ fn test_fn_like_mk_literals() { LITERAL ByteStr byte_string 42:2@0..100#ROOT2024 LITERAL Char c 42:2@0..100#ROOT2024 LITERAL Str string 42:2@0..100#ROOT2024 + LITERAL Str -string 42:2@0..100#ROOT2024 LITERAL CStr cstring 42:2@0..100#ROOT2024 LITERAL Float 3.14f64 42:2@0..100#ROOT2024 PUNCH - [alone] 42:2@0..100#ROOT2024 From ac4e3657764256fc2411ccbc0e23c451c4338107 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Tue, 10 Jun 2025 08:52:41 +0200 Subject: [PATCH 07/56] fix: Hide dyn inlay hints for incomplete `impl`s --- .../crates/ide/src/inlay_hints/implied_dyn_trait.rs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/implied_dyn_trait.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/implied_dyn_trait.rs index 32d130503a473..cd01c07583210 100644 --- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/implied_dyn_trait.rs +++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/implied_dyn_trait.rs @@ -22,9 +22,14 @@ pub(super) fn hints( let parent = paren.as_ref().and_then(|it| it.parent()).unwrap_or(parent); if ast::TypeBound::can_cast(parent.kind()) || ast::TypeAnchor::can_cast(parent.kind()) - || ast::Impl::cast(parent) - .and_then(|it| it.trait_()) - .is_some_and(|it| it.syntax() == path.syntax()) + || ast::Impl::cast(parent).is_some_and(|it| { + it.trait_().map_or( + // only show it for impl type if the impl is not incomplete, otherwise we + // are likely typing a trait impl + it.assoc_item_list().is_none_or(|it| it.l_curly_token().is_none()), + |trait_| trait_.syntax() == path.syntax(), + ) + }) { return None; } @@ -85,6 +90,7 @@ impl T {} // ^ dyn impl T for (T) {} // ^^^ dyn +impl T "#, ); } From fb169ff8a71a77078de98ecd05d42fd48d020db4 Mon Sep 17 00:00:00 2001 From: David Barsky Date: Sun, 8 Jun 2025 13:17:56 -0400 Subject: [PATCH 08/56] hir-ty: test (the absence of) incremental trait solving --- .../crates/hir-ty/src/tests/incremental.rs | 88 ++++++++++++++++++- 1 file changed, 87 insertions(+), 1 deletion(-) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/incremental.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/incremental.rs index e8e3812c69d36..6ac260ac768b9 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/incremental.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/incremental.rs @@ -1,5 +1,5 @@ use base_db::SourceDatabase; -use hir_def::ModuleDefId; +use hir_def::{DefWithBodyId, ModuleDefId}; use test_fixture::WithFixture; use crate::{db::HirDatabase, test_db::TestDB}; @@ -359,3 +359,89 @@ impl SomeStruct { assert_eq!(expected, actual); } } + +#[test] +fn add_struct_invalidates_trait_solve() { + let (mut db, file_id) = TestDB::with_single_file( + " +//- /main.rs crate:main +struct SomeStruct; + +trait Trait { + fn method(&self) -> T; +} +impl Trait for SomeStruct {} + +fn main() { + let s = SomeStruct; + s.method(); + s.$0 +}", + ); + + { + let events = db.log_executed(|| { + let module = db.module_for_file(file_id.file_id(&db)); + let crate_def_map = module.def_map(&db); + let mut defs: Vec = vec![]; + visit_module(&db, crate_def_map, module.local_id, &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); + }); + + for def in defs { + let _inference_result = db.infer(def); + } + }); + assert!(format!("{events:?}").contains("trait_solve_shim")) + } + + let new_text = " +//- /main.rs crate:main +struct AnotherStruct; + +struct SomeStruct; + +trait Trait { + fn method(&self) -> T; +} +impl Trait for SomeStruct {} + +fn main() { + let s = SomeStruct; + s.method(); + s.$0 +}"; + + db.set_file_text(file_id.file_id(&db), new_text); + + { + let events = db.log_executed(|| { + let module = db.module_for_file(file_id.file_id(&db)); + let crate_def_map = module.def_map(&db); + let mut defs: Vec = vec![]; + + visit_module(&db, crate_def_map, module.local_id, &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); + }); + + for def in defs { + let _inference_result = db.infer(def); + } + }); + assert!(format!("{events:?}").contains("trait_solve_shim")) + } +} From af079f827e08bff74a1be3882e201b21df4dcb7c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 11 Jun 2025 21:01:40 +0000 Subject: [PATCH 09/56] chore(deps-dev): bump brace-expansion in /editors/code Bumps [brace-expansion](https://github.com/juliangruber/brace-expansion) from 1.1.11 to 1.1.12. - [Release notes](https://github.com/juliangruber/brace-expansion/releases) - [Commits](https://github.com/juliangruber/brace-expansion/compare/1.1.11...v1.1.12) --- updated-dependencies: - dependency-name: brace-expansion dependency-version: 1.1.12 dependency-type: indirect ... Signed-off-by: dependabot[bot] --- .../editors/code/package-lock.json | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/tools/rust-analyzer/editors/code/package-lock.json b/src/tools/rust-analyzer/editors/code/package-lock.json index ab431140c10da..57d67a69b2e72 100644 --- a/src/tools/rust-analyzer/editors/code/package-lock.json +++ b/src/tools/rust-analyzer/editors/code/package-lock.json @@ -695,9 +695,9 @@ } }, "node_modules/@eslint/config-array/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, "license": "MIT", "dependencies": { @@ -756,9 +756,9 @@ } }, "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, "license": "MIT", "dependencies": { @@ -1407,9 +1407,9 @@ ] }, "node_modules/@vscode/vsce/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, "license": "MIT", "dependencies": { @@ -1599,9 +1599,9 @@ "license": "ISC" }, "node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" @@ -2981,9 +2981,9 @@ } }, "node_modules/eslint/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, "license": "MIT", "dependencies": { From 8e06cef0be365e128bdb3a1c4c728fc8664a51bb Mon Sep 17 00:00:00 2001 From: Chayim Refael Friedman Date: Wed, 21 May 2025 00:04:59 +0300 Subject: [PATCH 10/56] Use stable AST IDs Instead of simple numbering, we hash important bits, like the name of the item. This will allow for much better incrementality, e.g. when you add an item. Currently, this invalidates the IDs of all following items, which invalidates pretty much everything. --- .../crates/hir-def/src/expr_store/lower.rs | 22 +- .../crates/hir-def/src/item_tree/pretty.rs | 6 +- .../crates/hir-def/src/item_tree/tests.rs | 64 +- .../hir-def/src/macro_expansion_tests/mbe.rs | 22 +- .../src/macro_expansion_tests/proc_macros.rs | 6 +- .../crates/hir-expand/src/builtin/quote.rs | 4 +- .../crates/hir-expand/src/files.rs | 4 +- .../rust-analyzer/crates/mbe/src/tests.rs | 232 ++--- .../proc-macro-api/src/legacy_protocol/msg.rs | 13 +- .../crates/proc-macro-api/src/process.rs | 14 +- .../proc-macro-srv-cli/src/main_loop.rs | 7 +- .../crates/proc-macro-srv/src/dylib.rs | 15 +- .../crates/proc-macro-srv/src/lib.rs | 32 +- .../crates/proc-macro-srv/src/proc_macros.rs | 8 +- .../src/server_impl/rust_analyzer_span.rs | 17 +- .../crates/proc-macro-srv/src/tests/mod.rs | 344 +++---- .../crates/proc-macro-srv/src/tests/utils.rs | 34 +- .../rust-analyzer/crates/span/Cargo.toml | 3 + .../rust-analyzer/crates/span/src/ast_id.rs | 903 +++++++++++++++--- .../rust-analyzer/crates/span/src/lib.rs | 24 +- .../rust-analyzer/crates/span/src/map.rs | 2 +- .../crates/syntax/src/ast/node_ext.rs | 10 + 22 files changed, 1230 insertions(+), 556 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs index 29871f5e04dbc..b7a482a85dbbc 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs @@ -2141,26 +2141,10 @@ impl ExprCollector<'_> { block: ast::BlockExpr, mk_block: impl FnOnce(Option, Box<[Statement]>, Option) -> Expr, ) -> ExprId { - let block_has_items = { - let statement_has_item = block.statements().any(|stmt| match stmt { - ast::Stmt::Item(_) => true, - // Macro calls can be both items and expressions. The syntax library always treats - // them as expressions here, so we undo that. - ast::Stmt::ExprStmt(es) => matches!(es.expr(), Some(ast::Expr::MacroExpr(_))), - _ => false, - }); - statement_has_item - || matches!(block.tail_expr(), Some(ast::Expr::MacroExpr(_))) - || (block.may_carry_attributes() && block.attrs().next().is_some()) - }; - - let block_id = if block_has_items { - let file_local_id = self.expander.ast_id_map().ast_id(&block); + let block_id = self.expander.ast_id_map().ast_id_for_block(&block).map(|file_local_id| { let ast_id = self.expander.in_file(file_local_id); - Some(self.db.intern_block(BlockLoc { ast_id, module: self.module })) - } else { - None - }; + self.db.intern_block(BlockLoc { ast_id, module: self.module }) + }); let (module, def_map) = match block_id.map(|block_id| (block_def_map(self.db, block_id), block_id)) { diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs index 47c6eb13293f5..51172c0a1ee31 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs @@ -353,8 +353,8 @@ impl Printer<'_> { let MacroCall { path, ast_id, expand_to, ctxt } = &self.tree[it]; let _ = writeln!( self, - "// AstId: {:?}, SyntaxContextId: {}, ExpandTo: {:?}", - ast_id.erase().into_raw(), + "// AstId: {:#?}, SyntaxContextId: {}, ExpandTo: {:?}", + ast_id.erase(), ctxt, expand_to ); @@ -377,7 +377,7 @@ impl Printer<'_> { } fn print_ast_id(&mut self, ast_id: ErasedFileAstId) { - wln!(self, "// AstId: {:?}", ast_id.into_raw()); + wln!(self, "// AstId: {ast_id:#?}"); } } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/tests.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/tests.rs index 824fbfa5921a7..abfff283ef648 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/tests.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/tests.rs @@ -35,23 +35,23 @@ use a::{c, d::{e}}; #![no_std] #![doc = " another file comment"] - // AstId: 1 + // AstId: ExternCrate[5A82, 0] pub(self) extern crate self as renamed; - // AstId: 2 + // AstId: ExternCrate[7E1C, 0] pub(super) extern crate bli; - // AstId: 3 + // AstId: Use[0000, 0] pub use crate::path::{nested, items as renamed, Trait as _}; - // AstId: 4 + // AstId: Use[0000, 1] pub(self) use globs::*; #[doc = " docs on import"] - // AstId: 5 + // AstId: Use[0000, 2] pub(self) use crate::{A, B}; - // AstId: 6 + // AstId: Use[0000, 3] pub(self) use a::{c, d::{e}}; "##]], ); @@ -75,18 +75,18 @@ extern "C" { "#, expect![[r##" #[on_extern_block] - // AstId: 1 + // AstId: ExternBlock[0000, 0] extern "C" { #[on_extern_type] - // AstId: 2 + // AstId: TypeAlias[9FDF, 0] pub(self) type ExType; #[on_extern_static] - // AstId: 3 + // AstId: Static[43C1, 0] pub(self) static EX_STATIC = _; #[on_extern_fn] - // AstId: 4 + // AstId: Fn[452D, 0] pub(self) fn ex_fn; } "##]], @@ -124,39 +124,39 @@ enum E { } "#, expect![[r#" - // AstId: 1 + // AstId: Struct[DFF3, 0] pub(self) struct Unit; #[derive(Debug)] - // AstId: 2 + // AstId: Struct[C7A1, 0] pub(self) struct Struct { #[doc = " fld docs"] pub(self) fld, } - // AstId: 3 + // AstId: Struct[DAC2, 0] pub(self) struct Tuple( #[attr] pub(self) 0, ); - // AstId: 4 + // AstId: Union[2DBB, 0] pub(self) union Ize { pub(self) a, pub(self) b, } - // AstId: 5 + // AstId: Enum[7FF8, 0] pub(self) enum E - // AstId: 6 + // AstId: Variant[C717, 0] #[doc = " comment on Unit"] Unit, - // AstId: 7 + // AstId: Variant[AEAB, 0] #[doc = " comment on Tuple"] Tuple( pub(self) 0, ), - // AstId: 8 + // AstId: Variant[4B1B, 0] Struct { #[doc = " comment on a: u8"] pub(self) a, @@ -185,23 +185,23 @@ trait Tr: SuperTrait + 'lifetime { } "#, expect![[r#" - // AstId: 1 + // AstId: Static[B393, 0] pub static ST = _; - // AstId: 2 + // AstId: Const[B309, 0] pub(self) const _ = _; #[attr] #[inner_attr_in_fn] - // AstId: 3 + // AstId: Fn[75E3, 0] pub(self) fn f; - // AstId: 4 + // AstId: Trait[2998, 0] pub(self) trait Tr { - // AstId: 6 + // AstId: TypeAlias[9F08, 0] pub(self) type Assoc; - // AstId: 7 + // AstId: Fn[6C0C, 0] pub(self) fn method; } "#]], @@ -226,16 +226,16 @@ mod outline; expect![[r##" #[doc = " outer"] #[doc = " inner"] - // AstId: 1 + // AstId: Module[CF93, 0] pub(self) mod inline { - // AstId: 3 + // AstId: Use[0000, 0] pub(self) use super::*; - // AstId: 4 + // AstId: Fn[1B26, 0] pub(self) fn fn_in_module; } - // AstId: 2 + // AstId: Module[8994, 0] pub(self) mod outline; "##]], ); @@ -254,13 +254,13 @@ pub macro m2() {} m!(); "#, expect![[r#" - // AstId: 1 + // AstId: MacroRules[88CE, 0] macro_rules! m { ... } - // AstId: 2 + // AstId: MacroDef[DC34, 0] pub macro m2 { ... } - // AstId: 3, SyntaxContextId: ROOT2024, ExpandTo: Items + // AstId: MacroCall[612F, 0], SyntaxContextId: ROOT2024, ExpandTo: Items m!(...); "#]], ); @@ -273,7 +273,7 @@ fn pub_self() { pub(self) struct S; "#, expect![[r#" - // AstId: 1 + // AstId: Struct[42E2, 0] pub(self) struct S; "#]], ) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe.rs b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe.rs index 38fc4b3d118ae..eea50d16f5a00 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe.rs @@ -35,9 +35,9 @@ macro_rules! f { }; } -struct#0:1@58..64#14336# MyTraitMap2#0:2@31..42#ROOT2024# {#0:1@72..73#14336# - map#0:1@86..89#14336#:#0:1@89..90#14336# #0:1@89..90#14336#::#0:1@91..93#14336#std#0:1@93..96#14336#::#0:1@96..98#14336#collections#0:1@98..109#14336#::#0:1@109..111#14336#HashSet#0:1@111..118#14336#<#0:1@118..119#14336#(#0:1@119..120#14336#)#0:1@120..121#14336#>#0:1@121..122#14336#,#0:1@122..123#14336# -}#0:1@132..133#14336# +struct#0:MacroRules[8C8E, 0]@58..64#14336# MyTraitMap2#0:MacroCall[D499, 0]@31..42#ROOT2024# {#0:MacroRules[8C8E, 0]@72..73#14336# + map#0:MacroRules[8C8E, 0]@86..89#14336#:#0:MacroRules[8C8E, 0]@89..90#14336# #0:MacroRules[8C8E, 0]@89..90#14336#::#0:MacroRules[8C8E, 0]@91..93#14336#std#0:MacroRules[8C8E, 0]@93..96#14336#::#0:MacroRules[8C8E, 0]@96..98#14336#collections#0:MacroRules[8C8E, 0]@98..109#14336#::#0:MacroRules[8C8E, 0]@109..111#14336#HashSet#0:MacroRules[8C8E, 0]@111..118#14336#<#0:MacroRules[8C8E, 0]@118..119#14336#(#0:MacroRules[8C8E, 0]@119..120#14336#)#0:MacroRules[8C8E, 0]@120..121#14336#>#0:MacroRules[8C8E, 0]@121..122#14336#,#0:MacroRules[8C8E, 0]@122..123#14336# +}#0:MacroRules[8C8E, 0]@132..133#14336# "#]], ); } @@ -75,12 +75,12 @@ macro_rules! f { }; } -fn#0:2@30..32#ROOT2024# main#0:2@33..37#ROOT2024#(#0:2@37..38#ROOT2024#)#0:2@38..39#ROOT2024# {#0:2@40..41#ROOT2024# - 1#0:2@50..51#ROOT2024#;#0:2@51..52#ROOT2024# - 1.0#0:2@61..64#ROOT2024#;#0:2@64..65#ROOT2024# - (#0:2@74..75#ROOT2024#(#0:2@75..76#ROOT2024#1#0:2@76..77#ROOT2024#,#0:2@77..78#ROOT2024# )#0:2@78..79#ROOT2024#,#0:2@79..80#ROOT2024# )#0:2@80..81#ROOT2024#.#0:2@81..82#ROOT2024#0#0:2@82..85#ROOT2024#.#0:2@82..85#ROOT2024#0#0:2@82..85#ROOT2024#;#0:2@85..86#ROOT2024# - let#0:2@95..98#ROOT2024# x#0:2@99..100#ROOT2024# =#0:2@101..102#ROOT2024# 1#0:2@103..104#ROOT2024#;#0:2@104..105#ROOT2024# -}#0:2@110..111#ROOT2024# +fn#0:MacroCall[D499, 0]@30..32#ROOT2024# main#0:MacroCall[D499, 0]@33..37#ROOT2024#(#0:MacroCall[D499, 0]@37..38#ROOT2024#)#0:MacroCall[D499, 0]@38..39#ROOT2024# {#0:MacroCall[D499, 0]@40..41#ROOT2024# + 1#0:MacroCall[D499, 0]@50..51#ROOT2024#;#0:MacroCall[D499, 0]@51..52#ROOT2024# + 1.0#0:MacroCall[D499, 0]@61..64#ROOT2024#;#0:MacroCall[D499, 0]@64..65#ROOT2024# + (#0:MacroCall[D499, 0]@74..75#ROOT2024#(#0:MacroCall[D499, 0]@75..76#ROOT2024#1#0:MacroCall[D499, 0]@76..77#ROOT2024#,#0:MacroCall[D499, 0]@77..78#ROOT2024# )#0:MacroCall[D499, 0]@78..79#ROOT2024#,#0:MacroCall[D499, 0]@79..80#ROOT2024# )#0:MacroCall[D499, 0]@80..81#ROOT2024#.#0:MacroCall[D499, 0]@81..82#ROOT2024#0#0:MacroCall[D499, 0]@82..85#ROOT2024#.#0:MacroCall[D499, 0]@82..85#ROOT2024#0#0:MacroCall[D499, 0]@82..85#ROOT2024#;#0:MacroCall[D499, 0]@85..86#ROOT2024# + let#0:MacroCall[D499, 0]@95..98#ROOT2024# x#0:MacroCall[D499, 0]@99..100#ROOT2024# =#0:MacroCall[D499, 0]@101..102#ROOT2024# 1#0:MacroCall[D499, 0]@103..104#ROOT2024#;#0:MacroCall[D499, 0]@104..105#ROOT2024# +}#0:MacroCall[D499, 0]@110..111#ROOT2024# "#]], @@ -171,7 +171,7 @@ fn main(foo: ()) { } fn main(foo: ()) { - /* error: unresolved macro unresolved */"helloworld!"#0:3@236..321#ROOT2024#; + /* error: unresolved macro unresolved */"helloworld!"#0:Fn[B9C7, 0]@236..321#ROOT2024#; } } @@ -197,7 +197,7 @@ macro_rules! mk_struct { #[macro_use] mod foo; -struct#1:1@59..65#14336# Foo#0:2@32..35#ROOT2024#(#1:1@70..71#14336#u32#0:2@41..44#ROOT2024#)#1:1@74..75#14336#;#1:1@75..76#14336# +struct#1:MacroRules[E572, 0]@59..65#14336# Foo#0:MacroCall[BDD3, 0]@32..35#ROOT2024#(#1:MacroRules[E572, 0]@70..71#14336#u32#0:MacroCall[BDD3, 0]@41..44#ROOT2024#)#1:MacroRules[E572, 0]@74..75#14336#;#1:MacroRules[E572, 0]@75..76#14336# "#]], ); } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/proc_macros.rs b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/proc_macros.rs index b2e1adc3650d4..d5ae6f8d885d4 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/proc_macros.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/proc_macros.rs @@ -181,9 +181,9 @@ fn foo(&self) { self.0. 1; } -fn#0:1@45..47#ROOT2024# foo#0:1@48..51#ROOT2024#(#0:1@51..52#ROOT2024#�:1@52..53#ROOT2024#self#0:1@53..57#ROOT2024# )#0:1@57..58#ROOT2024# {#0:1@59..60#ROOT2024# - self#0:1@65..69#ROOT2024# .#0:1@69..70#ROOT2024#0#0:1@70..71#ROOT2024#.#0:1@71..72#ROOT2024#1#0:1@73..74#ROOT2024#;#0:1@74..75#ROOT2024# -}#0:1@76..77#ROOT2024#"#]], +fn#0:Fn[4D85, 0]@45..47#ROOT2024# foo#0:Fn[4D85, 0]@48..51#ROOT2024#(#0:Fn[4D85, 0]@51..52#ROOT2024#�:Fn[4D85, 0]@52..53#ROOT2024#self#0:Fn[4D85, 0]@53..57#ROOT2024# )#0:Fn[4D85, 0]@57..58#ROOT2024# {#0:Fn[4D85, 0]@59..60#ROOT2024# + self#0:Fn[4D85, 0]@65..69#ROOT2024# .#0:Fn[4D85, 0]@69..70#ROOT2024#0#0:Fn[4D85, 0]@70..71#ROOT2024#.#0:Fn[4D85, 0]@71..72#ROOT2024#1#0:Fn[4D85, 0]@73..74#ROOT2024#;#0:Fn[4D85, 0]@74..75#ROOT2024# +}#0:Fn[4D85, 0]@76..77#ROOT2024#"#]], ); } diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/builtin/quote.rs b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/quote.rs index 62b7b638e7b67..d5874f829ba5f 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/builtin/quote.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/quote.rs @@ -277,8 +277,8 @@ mod tests { assert_eq!(quoted.to_string(), "hello"); let t = format!("{quoted:#?}"); expect![[r#" - SUBTREE $$ 937550:0@0..0#ROOT2024 937550:0@0..0#ROOT2024 - IDENT hello 937550:0@0..0#ROOT2024"#]] + SUBTREE $$ 937550:Root[0000, 0]@0..0#ROOT2024 937550:Root[0000, 0]@0..0#ROOT2024 + IDENT hello 937550:Root[0000, 0]@0..0#ROOT2024"#]] .assert_eq(&t); } diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/files.rs b/src/tools/rust-analyzer/crates/hir-expand/src/files.rs index 8024823cbc5cb..e8f6b82434ee4 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/files.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/files.rs @@ -2,7 +2,7 @@ use std::borrow::Borrow; use either::Either; -use span::{AstIdNode, ErasedFileAstId, FileAstId, FileId, SyntaxContext}; +use span::{ErasedFileAstId, FileAstId, FileId, SyntaxContext}; use syntax::{AstNode, AstPtr, SyntaxNode, SyntaxNodePtr, SyntaxToken, TextRange, TextSize}; use crate::{ @@ -106,7 +106,7 @@ impl FileRange { /// It is stable across reparses, and can be used as salsa key/value. pub type AstId = crate::InFile>; -impl AstId { +impl AstId { pub fn to_node(&self, db: &dyn ExpandDatabase) -> N { self.to_ptr(db).to_node(&db.parse_or_expand(self.file_id)) } diff --git a/src/tools/rust-analyzer/crates/mbe/src/tests.rs b/src/tools/rust-analyzer/crates/mbe/src/tests.rs index 769455faac041..56034516ef3b2 100644 --- a/src/tools/rust-analyzer/crates/mbe/src/tests.rs +++ b/src/tools/rust-analyzer/crates/mbe/src/tests.rs @@ -3,7 +3,9 @@ // FIXME: Move more of the nameres independent tests from // crates\hir-def\src\macro_expansion_tests\mod.rs to this use expect_test::expect; -use span::{Edition, EditionedFileId, ErasedFileAstId, FileId, Span, SpanAnchor, SyntaxContext}; +use span::{ + Edition, EditionedFileId, FileId, ROOT_ERASED_FILE_AST_ID, Span, SpanAnchor, SyntaxContext, +}; use stdx::format_to; use tt::{TextRange, TextSize}; @@ -24,7 +26,7 @@ fn check_( def_edition, SpanAnchor { file_id: EditionedFileId::new(FileId::from_raw(0), def_edition), - ast_id: ErasedFileAstId::from_raw(0), + ast_id: ROOT_ERASED_FILE_AST_ID, }, SyntaxContext::root(Edition::CURRENT), decl, @@ -37,7 +39,7 @@ fn check_( }; let call_anchor = SpanAnchor { file_id: EditionedFileId::new(FileId::from_raw(1), call_edition), - ast_id: ErasedFileAstId::from_raw(0), + ast_id: ROOT_ERASED_FILE_AST_ID, }; let arg_tt = syntax_bridge::parse_to_token_tree( call_edition, @@ -110,8 +112,8 @@ fn unbalanced_brace() { "#, r#""#, expect![[r#" - SUBTREE $$ 1:0@0..0#ROOT2024 1:0@0..0#ROOT2024 - SUBTREE {} 0:0@9..10#ROOT2024 0:0@11..12#ROOT2024 + SUBTREE $$ 1:Root[0000, 0]@0..0#ROOT2024 1:Root[0000, 0]@0..0#ROOT2024 + SUBTREE {} 0:Root[0000, 0]@9..10#ROOT2024 0:Root[0000, 0]@11..12#ROOT2024 {}"#]], ); @@ -133,25 +135,25 @@ fn token_mapping_smoke_test() { struct MyTraitMap2 "#, expect![[r#" - SUBTREE $$ 1:0@0..20#ROOT2024 1:0@0..20#ROOT2024 - IDENT struct 0:0@34..40#ROOT2024 - IDENT MyTraitMap2 1:0@8..19#ROOT2024 - SUBTREE {} 0:0@48..49#ROOT2024 0:0@100..101#ROOT2024 - IDENT map 0:0@58..61#ROOT2024 - PUNCH : [alone] 0:0@61..62#ROOT2024 - PUNCH : [joint] 0:0@63..64#ROOT2024 - PUNCH : [alone] 0:0@64..65#ROOT2024 - IDENT std 0:0@65..68#ROOT2024 - PUNCH : [joint] 0:0@68..69#ROOT2024 - PUNCH : [alone] 0:0@69..70#ROOT2024 - IDENT collections 0:0@70..81#ROOT2024 - PUNCH : [joint] 0:0@81..82#ROOT2024 - PUNCH : [alone] 0:0@82..83#ROOT2024 - IDENT HashSet 0:0@83..90#ROOT2024 - PUNCH < [alone] 0:0@90..91#ROOT2024 - SUBTREE () 0:0@91..92#ROOT2024 0:0@92..93#ROOT2024 - PUNCH > [joint] 0:0@93..94#ROOT2024 - PUNCH , [alone] 0:0@94..95#ROOT2024 + SUBTREE $$ 1:Root[0000, 0]@0..20#ROOT2024 1:Root[0000, 0]@0..20#ROOT2024 + IDENT struct 0:Root[0000, 0]@34..40#ROOT2024 + IDENT MyTraitMap2 1:Root[0000, 0]@8..19#ROOT2024 + SUBTREE {} 0:Root[0000, 0]@48..49#ROOT2024 0:Root[0000, 0]@100..101#ROOT2024 + IDENT map 0:Root[0000, 0]@58..61#ROOT2024 + PUNCH : [alone] 0:Root[0000, 0]@61..62#ROOT2024 + PUNCH : [joint] 0:Root[0000, 0]@63..64#ROOT2024 + PUNCH : [alone] 0:Root[0000, 0]@64..65#ROOT2024 + IDENT std 0:Root[0000, 0]@65..68#ROOT2024 + PUNCH : [joint] 0:Root[0000, 0]@68..69#ROOT2024 + PUNCH : [alone] 0:Root[0000, 0]@69..70#ROOT2024 + IDENT collections 0:Root[0000, 0]@70..81#ROOT2024 + PUNCH : [joint] 0:Root[0000, 0]@81..82#ROOT2024 + PUNCH : [alone] 0:Root[0000, 0]@82..83#ROOT2024 + IDENT HashSet 0:Root[0000, 0]@83..90#ROOT2024 + PUNCH < [alone] 0:Root[0000, 0]@90..91#ROOT2024 + SUBTREE () 0:Root[0000, 0]@91..92#ROOT2024 0:Root[0000, 0]@92..93#ROOT2024 + PUNCH > [joint] 0:Root[0000, 0]@93..94#ROOT2024 + PUNCH , [alone] 0:Root[0000, 0]@94..95#ROOT2024 struct MyTraitMap2 { map: ::std::collections::HashSet<()>, @@ -180,28 +182,28 @@ fn main() { } "#, expect![[r#" - SUBTREE $$ 1:0@0..63#ROOT2024 1:0@0..63#ROOT2024 - IDENT fn 1:0@1..3#ROOT2024 - IDENT main 1:0@4..8#ROOT2024 - SUBTREE () 1:0@8..9#ROOT2024 1:0@9..10#ROOT2024 - SUBTREE {} 1:0@11..12#ROOT2024 1:0@61..62#ROOT2024 - LITERAL Integer 1 1:0@17..18#ROOT2024 - PUNCH ; [alone] 1:0@18..19#ROOT2024 - LITERAL Float 1.0 1:0@24..27#ROOT2024 - PUNCH ; [alone] 1:0@27..28#ROOT2024 - SUBTREE () 1:0@33..34#ROOT2024 1:0@39..40#ROOT2024 - SUBTREE () 1:0@34..35#ROOT2024 1:0@37..38#ROOT2024 - LITERAL Integer 1 1:0@35..36#ROOT2024 - PUNCH , [alone] 1:0@36..37#ROOT2024 - PUNCH , [alone] 1:0@38..39#ROOT2024 - PUNCH . [alone] 1:0@40..41#ROOT2024 - LITERAL Float 0.0 1:0@41..44#ROOT2024 - PUNCH ; [alone] 1:0@44..45#ROOT2024 - IDENT let 1:0@50..53#ROOT2024 - IDENT x 1:0@54..55#ROOT2024 - PUNCH = [alone] 1:0@56..57#ROOT2024 - LITERAL Integer 1 1:0@58..59#ROOT2024 - PUNCH ; [alone] 1:0@59..60#ROOT2024 + SUBTREE $$ 1:Root[0000, 0]@0..63#ROOT2024 1:Root[0000, 0]@0..63#ROOT2024 + IDENT fn 1:Root[0000, 0]@1..3#ROOT2024 + IDENT main 1:Root[0000, 0]@4..8#ROOT2024 + SUBTREE () 1:Root[0000, 0]@8..9#ROOT2024 1:Root[0000, 0]@9..10#ROOT2024 + SUBTREE {} 1:Root[0000, 0]@11..12#ROOT2024 1:Root[0000, 0]@61..62#ROOT2024 + LITERAL Integer 1 1:Root[0000, 0]@17..18#ROOT2024 + PUNCH ; [alone] 1:Root[0000, 0]@18..19#ROOT2024 + LITERAL Float 1.0 1:Root[0000, 0]@24..27#ROOT2024 + PUNCH ; [alone] 1:Root[0000, 0]@27..28#ROOT2024 + SUBTREE () 1:Root[0000, 0]@33..34#ROOT2024 1:Root[0000, 0]@39..40#ROOT2024 + SUBTREE () 1:Root[0000, 0]@34..35#ROOT2024 1:Root[0000, 0]@37..38#ROOT2024 + LITERAL Integer 1 1:Root[0000, 0]@35..36#ROOT2024 + PUNCH , [alone] 1:Root[0000, 0]@36..37#ROOT2024 + PUNCH , [alone] 1:Root[0000, 0]@38..39#ROOT2024 + PUNCH . [alone] 1:Root[0000, 0]@40..41#ROOT2024 + LITERAL Float 0.0 1:Root[0000, 0]@41..44#ROOT2024 + PUNCH ; [alone] 1:Root[0000, 0]@44..45#ROOT2024 + IDENT let 1:Root[0000, 0]@50..53#ROOT2024 + IDENT x 1:Root[0000, 0]@54..55#ROOT2024 + PUNCH = [alone] 1:Root[0000, 0]@56..57#ROOT2024 + LITERAL Integer 1 1:Root[0000, 0]@58..59#ROOT2024 + PUNCH ; [alone] 1:Root[0000, 0]@59..60#ROOT2024 fn main(){ 1; @@ -227,14 +229,14 @@ fn expr_2021() { const { 1 }, "#, expect![[r#" - SUBTREE $$ 1:0@0..25#ROOT2024 1:0@0..25#ROOT2024 - IDENT _ 1:0@5..6#ROOT2024 - PUNCH ; [joint] 0:0@36..37#ROOT2024 - SUBTREE () 0:0@34..35#ROOT2024 0:0@34..35#ROOT2024 - IDENT const 1:0@12..17#ROOT2024 - SUBTREE {} 1:0@18..19#ROOT2024 1:0@22..23#ROOT2024 - LITERAL Integer 1 1:0@20..21#ROOT2024 - PUNCH ; [alone] 0:0@39..40#ROOT2024 + SUBTREE $$ 1:Root[0000, 0]@0..25#ROOT2024 1:Root[0000, 0]@0..25#ROOT2024 + IDENT _ 1:Root[0000, 0]@5..6#ROOT2024 + PUNCH ; [joint] 0:Root[0000, 0]@36..37#ROOT2024 + SUBTREE () 0:Root[0000, 0]@34..35#ROOT2024 0:Root[0000, 0]@34..35#ROOT2024 + IDENT const 1:Root[0000, 0]@12..17#ROOT2024 + SUBTREE {} 1:Root[0000, 0]@18..19#ROOT2024 1:Root[0000, 0]@22..23#ROOT2024 + LITERAL Integer 1 1:Root[0000, 0]@20..21#ROOT2024 + PUNCH ; [alone] 0:Root[0000, 0]@39..40#ROOT2024 _; (const { @@ -255,13 +257,13 @@ fn expr_2021() { expect![[r#" ExpandError { inner: ( - 1:0@5..6#ROOT2024, + 1:Root[0000, 0]@5..6#ROOT2024, NoMatchingRule, ), } - SUBTREE $$ 1:0@0..8#ROOT2024 1:0@0..8#ROOT2024 - PUNCH ; [alone] 0:0@39..40#ROOT2024 + SUBTREE $$ 1:Root[0000, 0]@0..8#ROOT2024 1:Root[0000, 0]@0..8#ROOT2024 + PUNCH ; [alone] 0:Root[0000, 0]@39..40#ROOT2024 ;"#]], ); @@ -279,13 +281,13 @@ fn expr_2021() { expect![[r#" ExpandError { inner: ( - 1:0@5..10#ROOT2024, + 1:Root[0000, 0]@5..10#ROOT2024, NoMatchingRule, ), } - SUBTREE $$ 1:0@0..18#ROOT2024 1:0@0..18#ROOT2024 - PUNCH ; [alone] 0:0@39..40#ROOT2024 + SUBTREE $$ 1:Root[0000, 0]@0..18#ROOT2024 1:Root[0000, 0]@0..18#ROOT2024 + PUNCH ; [alone] 0:Root[0000, 0]@39..40#ROOT2024 ;"#]], ); @@ -305,26 +307,26 @@ fn expr_2021() { break 'foo bar, "#, expect![[r#" - SUBTREE $$ 1:0@0..76#ROOT2024 1:0@0..76#ROOT2024 - LITERAL Integer 4 1:0@5..6#ROOT2024 - PUNCH ; [joint] 0:0@41..42#ROOT2024 - LITERAL Str literal 1:0@12..21#ROOT2024 - PUNCH ; [joint] 0:0@41..42#ROOT2024 - SUBTREE () 0:0@39..40#ROOT2024 0:0@39..40#ROOT2024 - IDENT funcall 1:0@27..34#ROOT2024 - SUBTREE () 1:0@34..35#ROOT2024 1:0@35..36#ROOT2024 - PUNCH ; [joint] 0:0@41..42#ROOT2024 - SUBTREE () 0:0@39..40#ROOT2024 0:0@39..40#ROOT2024 - IDENT future 1:0@42..48#ROOT2024 - PUNCH . [alone] 1:0@48..49#ROOT2024 - IDENT await 1:0@49..54#ROOT2024 - PUNCH ; [joint] 0:0@41..42#ROOT2024 - SUBTREE () 0:0@39..40#ROOT2024 0:0@39..40#ROOT2024 - IDENT break 1:0@60..65#ROOT2024 - PUNCH ' [joint] 1:0@66..67#ROOT2024 - IDENT foo 1:0@67..70#ROOT2024 - IDENT bar 1:0@71..74#ROOT2024 - PUNCH ; [alone] 0:0@44..45#ROOT2024 + SUBTREE $$ 1:Root[0000, 0]@0..76#ROOT2024 1:Root[0000, 0]@0..76#ROOT2024 + LITERAL Integer 4 1:Root[0000, 0]@5..6#ROOT2024 + PUNCH ; [joint] 0:Root[0000, 0]@41..42#ROOT2024 + LITERAL Str literal 1:Root[0000, 0]@12..21#ROOT2024 + PUNCH ; [joint] 0:Root[0000, 0]@41..42#ROOT2024 + SUBTREE () 0:Root[0000, 0]@39..40#ROOT2024 0:Root[0000, 0]@39..40#ROOT2024 + IDENT funcall 1:Root[0000, 0]@27..34#ROOT2024 + SUBTREE () 1:Root[0000, 0]@34..35#ROOT2024 1:Root[0000, 0]@35..36#ROOT2024 + PUNCH ; [joint] 0:Root[0000, 0]@41..42#ROOT2024 + SUBTREE () 0:Root[0000, 0]@39..40#ROOT2024 0:Root[0000, 0]@39..40#ROOT2024 + IDENT future 1:Root[0000, 0]@42..48#ROOT2024 + PUNCH . [alone] 1:Root[0000, 0]@48..49#ROOT2024 + IDENT await 1:Root[0000, 0]@49..54#ROOT2024 + PUNCH ; [joint] 0:Root[0000, 0]@41..42#ROOT2024 + SUBTREE () 0:Root[0000, 0]@39..40#ROOT2024 0:Root[0000, 0]@39..40#ROOT2024 + IDENT break 1:Root[0000, 0]@60..65#ROOT2024 + PUNCH ' [joint] 1:Root[0000, 0]@66..67#ROOT2024 + IDENT foo 1:Root[0000, 0]@67..70#ROOT2024 + IDENT bar 1:Root[0000, 0]@71..74#ROOT2024 + PUNCH ; [alone] 0:Root[0000, 0]@44..45#ROOT2024 4; "literal"; @@ -346,13 +348,13 @@ fn expr_2021() { expect![[r#" ExpandError { inner: ( - 1:0@5..6#ROOT2024, + 1:Root[0000, 0]@5..6#ROOT2024, NoMatchingRule, ), } - SUBTREE $$ 1:0@0..8#ROOT2024 1:0@0..8#ROOT2024 - PUNCH ; [alone] 0:0@44..45#ROOT2024 + SUBTREE $$ 1:Root[0000, 0]@0..8#ROOT2024 1:Root[0000, 0]@0..8#ROOT2024 + PUNCH ; [alone] 0:Root[0000, 0]@44..45#ROOT2024 ;"#]], ); @@ -370,88 +372,88 @@ fn minus_belongs_to_literal() { check( "-1", expect![[r#" - SUBTREE $$ 1:0@0..2#ROOT2024 1:0@0..2#ROOT2024 - PUNCH - [alone] 0:0@10..11#ROOT2024 - LITERAL Integer 1 0:0@11..12#ROOT2024 + SUBTREE $$ 1:Root[0000, 0]@0..2#ROOT2024 1:Root[0000, 0]@0..2#ROOT2024 + PUNCH - [alone] 0:Root[0000, 0]@10..11#ROOT2024 + LITERAL Integer 1 0:Root[0000, 0]@11..12#ROOT2024 -1"#]], ); check( "- 1", expect![[r#" - SUBTREE $$ 1:0@0..3#ROOT2024 1:0@0..3#ROOT2024 - PUNCH - [alone] 0:0@10..11#ROOT2024 - LITERAL Integer 1 0:0@11..12#ROOT2024 + SUBTREE $$ 1:Root[0000, 0]@0..3#ROOT2024 1:Root[0000, 0]@0..3#ROOT2024 + PUNCH - [alone] 0:Root[0000, 0]@10..11#ROOT2024 + LITERAL Integer 1 0:Root[0000, 0]@11..12#ROOT2024 -1"#]], ); check( "-2", expect![[r#" - SUBTREE $$ 1:0@0..2#ROOT2024 1:0@0..2#ROOT2024 - PUNCH - [alone] 0:0@25..26#ROOT2024 - LITERAL Integer 2 0:0@27..28#ROOT2024 + SUBTREE $$ 1:Root[0000, 0]@0..2#ROOT2024 1:Root[0000, 0]@0..2#ROOT2024 + PUNCH - [alone] 0:Root[0000, 0]@25..26#ROOT2024 + LITERAL Integer 2 0:Root[0000, 0]@27..28#ROOT2024 -2"#]], ); check( "- 2", expect![[r#" - SUBTREE $$ 1:0@0..3#ROOT2024 1:0@0..3#ROOT2024 - PUNCH - [alone] 0:0@25..26#ROOT2024 - LITERAL Integer 2 0:0@27..28#ROOT2024 + SUBTREE $$ 1:Root[0000, 0]@0..3#ROOT2024 1:Root[0000, 0]@0..3#ROOT2024 + PUNCH - [alone] 0:Root[0000, 0]@25..26#ROOT2024 + LITERAL Integer 2 0:Root[0000, 0]@27..28#ROOT2024 -2"#]], ); check( "-3.0", expect![[r#" - SUBTREE $$ 1:0@0..4#ROOT2024 1:0@0..4#ROOT2024 - PUNCH - [alone] 0:0@43..44#ROOT2024 - LITERAL Float 3.0 0:0@45..48#ROOT2024 + SUBTREE $$ 1:Root[0000, 0]@0..4#ROOT2024 1:Root[0000, 0]@0..4#ROOT2024 + PUNCH - [alone] 0:Root[0000, 0]@43..44#ROOT2024 + LITERAL Float 3.0 0:Root[0000, 0]@45..48#ROOT2024 -3.0"#]], ); check( "- 3.0", expect![[r#" - SUBTREE $$ 1:0@0..5#ROOT2024 1:0@0..5#ROOT2024 - PUNCH - [alone] 0:0@43..44#ROOT2024 - LITERAL Float 3.0 0:0@45..48#ROOT2024 + SUBTREE $$ 1:Root[0000, 0]@0..5#ROOT2024 1:Root[0000, 0]@0..5#ROOT2024 + PUNCH - [alone] 0:Root[0000, 0]@43..44#ROOT2024 + LITERAL Float 3.0 0:Root[0000, 0]@45..48#ROOT2024 -3.0"#]], ); check( "@1", expect![[r#" - SUBTREE $$ 1:0@0..2#ROOT2024 1:0@0..2#ROOT2024 - LITERAL Integer 1 1:0@1..2#ROOT2024 + SUBTREE $$ 1:Root[0000, 0]@0..2#ROOT2024 1:Root[0000, 0]@0..2#ROOT2024 + LITERAL Integer 1 1:Root[0000, 0]@1..2#ROOT2024 1"#]], ); check( "@-1", expect![[r#" - SUBTREE $$ 1:0@0..3#ROOT2024 1:0@0..3#ROOT2024 - PUNCH - [alone] 1:0@1..2#ROOT2024 - LITERAL Integer 1 1:0@2..3#ROOT2024 + SUBTREE $$ 1:Root[0000, 0]@0..3#ROOT2024 1:Root[0000, 0]@0..3#ROOT2024 + PUNCH - [alone] 1:Root[0000, 0]@1..2#ROOT2024 + LITERAL Integer 1 1:Root[0000, 0]@2..3#ROOT2024 -1"#]], ); check( "@1.0", expect![[r#" - SUBTREE $$ 1:0@0..4#ROOT2024 1:0@0..4#ROOT2024 - LITERAL Float 1.0 1:0@1..4#ROOT2024 + SUBTREE $$ 1:Root[0000, 0]@0..4#ROOT2024 1:Root[0000, 0]@0..4#ROOT2024 + LITERAL Float 1.0 1:Root[0000, 0]@1..4#ROOT2024 1.0"#]], ); check( "@-1.0", expect![[r#" - SUBTREE $$ 1:0@0..5#ROOT2024 1:0@0..5#ROOT2024 - PUNCH - [alone] 1:0@1..2#ROOT2024 - LITERAL Float 1.0 1:0@2..5#ROOT2024 + SUBTREE $$ 1:Root[0000, 0]@0..5#ROOT2024 1:Root[0000, 0]@0..5#ROOT2024 + PUNCH - [alone] 1:Root[0000, 0]@1..2#ROOT2024 + LITERAL Float 1.0 1:Root[0000, 0]@2..5#ROOT2024 -1.0"#]], ); @@ -460,16 +462,16 @@ fn minus_belongs_to_literal() { expect![[r#" ExpandError { inner: ( - 1:0@1..2#ROOT2024, + 1:Root[0000, 0]@1..2#ROOT2024, BindingError( "expected literal", ), ), } - SUBTREE $$ 1:0@0..6#ROOT2024 1:0@0..6#ROOT2024 - PUNCH - [joint] 1:0@1..2#ROOT2024 - PUNCH - [alone] 1:0@2..3#ROOT2024 + SUBTREE $$ 1:Root[0000, 0]@0..6#ROOT2024 1:Root[0000, 0]@0..6#ROOT2024 + PUNCH - [joint] 1:Root[0000, 0]@1..2#ROOT2024 + PUNCH - [alone] 1:Root[0000, 0]@2..3#ROOT2024 --"#]], ); diff --git a/src/tools/rust-analyzer/crates/proc-macro-api/src/legacy_protocol/msg.rs b/src/tools/rust-analyzer/crates/proc-macro-api/src/legacy_protocol/msg.rs index 55185aa492ded..4e1526fe48bde 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-api/src/legacy_protocol/msg.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-api/src/legacy_protocol/msg.rs @@ -22,9 +22,10 @@ pub const HAS_GLOBAL_SPANS: u32 = 3; pub const RUST_ANALYZER_SPAN_SUPPORT: u32 = 4; /// Whether literals encode their kind as an additional u32 field and idents their rawness as a u32 field. pub const EXTENDED_LEAF_DATA: u32 = 5; +pub const HASHED_AST_ID: u32 = 6; /// Current API version of the proc-macro protocol. -pub const CURRENT_API_VERSION: u32 = EXTENDED_LEAF_DATA; +pub const CURRENT_API_VERSION: u32 = HASHED_AST_ID; /// Represents requests sent from the client to the proc-macro-srv. #[derive(Debug, Serialize, Deserialize)] @@ -54,7 +55,7 @@ pub enum SpanMode { Id, /// Rust Analyzer-specific span handling mode. - RustAnalyzer, + RustAnalyzer { fixup_ast_id: u32 }, } /// Represents responses sent from the proc-macro-srv to the client. @@ -201,7 +202,9 @@ type ProtocolWrite = for<'o, 'msg> fn(out: &'o mut W, msg: &'msg str) #[cfg(test)] mod tests { use intern::{Symbol, sym}; - use span::{Edition, ErasedFileAstId, Span, SpanAnchor, SyntaxContext, TextRange, TextSize}; + use span::{ + Edition, ROOT_ERASED_FILE_AST_ID, Span, SpanAnchor, SyntaxContext, TextRange, TextSize, + }; use tt::{ Delimiter, DelimiterKind, Ident, Leaf, Literal, Punct, Spacing, TopSubtree, TopSubtreeBuilder, @@ -215,7 +218,7 @@ mod tests { span::FileId::from_raw(0xe4e4e), span::Edition::CURRENT, ), - ast_id: ErasedFileAstId::from_raw(0), + ast_id: ROOT_ERASED_FILE_AST_ID, }; let mut builder = TopSubtreeBuilder::new(Delimiter { @@ -305,7 +308,7 @@ mod tests { #[test] fn test_proc_macro_rpc_works() { let tt = fixture_token_tree(); - for v in RUST_ANALYZER_SPAN_SUPPORT..=CURRENT_API_VERSION { + for v in HASHED_AST_ID..=CURRENT_API_VERSION { let mut span_data_table = Default::default(); let task = ExpandMacro { data: ExpandMacroData { diff --git a/src/tools/rust-analyzer/crates/proc-macro-api/src/process.rs b/src/tools/rust-analyzer/crates/proc-macro-api/src/process.rs index fcea75ef672a1..e3b0614546de5 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-api/src/process.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-api/src/process.rs @@ -8,6 +8,7 @@ use std::{ }; use paths::AbsPath; +use span::FIXUP_ERASED_FILE_AST_ID_MARKER; use stdx::JodChild; use crate::{ @@ -15,8 +16,7 @@ use crate::{ legacy_protocol::{ json::{read_json, write_json}, msg::{ - CURRENT_API_VERSION, Message, RUST_ANALYZER_SPAN_SUPPORT, Request, Response, - ServerConfig, SpanMode, + CURRENT_API_VERSION, HASHED_AST_ID, Message, Request, Response, ServerConfig, SpanMode, }, }, }; @@ -71,7 +71,9 @@ impl ProcMacroServerProcess { Ok(v) => { tracing::info!("Proc-macro server version: {v}"); srv.version = v; - if srv.version >= RUST_ANALYZER_SPAN_SUPPORT { + if srv.version >= HASHED_AST_ID { + // We don't enable spans on versions prior to `HASHED_AST_ID`, because their ast id layout + // is different. if let Ok(mode) = srv.enable_rust_analyzer_spans() { srv.mode = mode; } @@ -111,7 +113,11 @@ impl ProcMacroServerProcess { /// Enable support for rust-analyzer span mode if the server supports it. fn enable_rust_analyzer_spans(&self) -> Result { - let request = Request::SetConfig(ServerConfig { span_mode: SpanMode::RustAnalyzer }); + let request = Request::SetConfig(ServerConfig { + span_mode: SpanMode::RustAnalyzer { + fixup_ast_id: FIXUP_ERASED_FILE_AST_ID_MARKER.into_raw(), + }, + }); let response = self.send_task(request)?; match response { diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv-cli/src/main_loop.rs b/src/tools/rust-analyzer/crates/proc-macro-srv-cli/src/main_loop.rs index f54dff1f2d822..25a49fbff9fd7 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv-cli/src/main_loop.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-srv-cli/src/main_loop.rs @@ -26,7 +26,7 @@ pub(crate) fn run() -> io::Result<()> { let write_response = |msg: msg::Response| msg.write(write_json, &mut io::stdout().lock()); let env = EnvSnapshot::default(); - let srv = proc_macro_srv::ProcMacroSrv::new(&env); + let mut srv = proc_macro_srv::ProcMacroSrv::new(&env); let mut span_mode = SpanMode::Id; @@ -78,7 +78,7 @@ pub(crate) fn run() -> io::Result<()> { }) .map_err(msg::PanicMessage) }), - SpanMode::RustAnalyzer => msg::Response::ExpandMacroExtended({ + SpanMode::RustAnalyzer { .. } => msg::Response::ExpandMacroExtended({ let mut span_data_table = deserialize_span_data_index_map(&span_data_table); let def_site = span_data_table[def_site]; @@ -122,6 +122,9 @@ pub(crate) fn run() -> io::Result<()> { msg::Request::ApiVersionCheck {} => msg::Response::ApiVersionCheck(CURRENT_API_VERSION), msg::Request::SetConfig(config) => { span_mode = config.span_mode; + if let SpanMode::RustAnalyzer { fixup_ast_id } = span_mode { + srv.set_fixup_ast_id(fixup_ast_id); + } msg::Response::SetConfig(config) } }; diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/dylib.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/dylib.rs index c49159df9916d..c64a9833e3ff0 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/dylib.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/dylib.rs @@ -3,6 +3,7 @@ mod version; use proc_macro::bridge; +use span::ErasedFileAstId; use std::{fmt, fs, io, time::SystemTime}; use libloading::Library; @@ -161,14 +162,20 @@ impl Expander { def_site: S, call_site: S, mixed_site: S, + fixup_ast_id: ErasedFileAstId, ) -> Result, String> where ::TokenStream: Default, { - let result = self - .inner - .proc_macros - .expand(macro_name, macro_body, attributes, def_site, call_site, mixed_site); + let result = self.inner.proc_macros.expand( + macro_name, + macro_body, + attributes, + def_site, + call_site, + mixed_site, + fixup_ast_id, + ); result.map_err(|e| e.into_string().unwrap_or_default()) } diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/lib.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/lib.rs index 223c5a54b7034..22afa018de017 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/lib.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/lib.rs @@ -41,7 +41,7 @@ use std::{ }; use paths::{Utf8Path, Utf8PathBuf}; -use span::{Span, TokenId}; +use span::{ErasedFileAstId, FIXUP_ERASED_FILE_AST_ID_MARKER, Span, TokenId}; use crate::server_impl::TokenStream; @@ -57,11 +57,16 @@ pub const RUSTC_VERSION_STRING: &str = env!("RUSTC_VERSION"); pub struct ProcMacroSrv<'env> { expanders: Mutex>>, env: &'env EnvSnapshot, + fixup_ast_id: ErasedFileAstId, } impl<'env> ProcMacroSrv<'env> { pub fn new(env: &'env EnvSnapshot) -> Self { - Self { expanders: Default::default(), env } + Self { expanders: Default::default(), env, fixup_ast_id: FIXUP_ERASED_FILE_AST_ID_MARKER } + } + + pub fn set_fixup_ast_id(&mut self, fixup_ast_id: u32) { + self.fixup_ast_id = ErasedFileAstId::from_raw(fixup_ast_id); } } @@ -101,6 +106,7 @@ impl ProcMacroSrv<'_> { def_site, call_site, mixed_site, + self.fixup_ast_id, ) .map(|tt| tt.0) }); @@ -156,25 +162,41 @@ impl ProcMacroSrv<'_> { pub trait ProcMacroSrvSpan: Copy + Send { type Server: proc_macro::bridge::server::Server>; - fn make_server(call_site: Self, def_site: Self, mixed_site: Self) -> Self::Server; + fn make_server( + call_site: Self, + def_site: Self, + mixed_site: Self, + fixup_ast_id: ErasedFileAstId, + ) -> Self::Server; } impl ProcMacroSrvSpan for TokenId { type Server = server_impl::token_id::TokenIdServer; - fn make_server(call_site: Self, def_site: Self, mixed_site: Self) -> Self::Server { + fn make_server( + call_site: Self, + def_site: Self, + mixed_site: Self, + _fixup_ast_id: ErasedFileAstId, + ) -> Self::Server { Self::Server { call_site, def_site, mixed_site } } } impl ProcMacroSrvSpan for Span { type Server = server_impl::rust_analyzer_span::RaSpanServer; - fn make_server(call_site: Self, def_site: Self, mixed_site: Self) -> Self::Server { + fn make_server( + call_site: Self, + def_site: Self, + mixed_site: Self, + fixup_ast_id: ErasedFileAstId, + ) -> Self::Server { Self::Server { call_site, def_site, mixed_site, tracked_env_vars: Default::default(), tracked_paths: Default::default(), + fixup_ast_id, } } } diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/proc_macros.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/proc_macros.rs index 18532706c4aaa..3b9c45894c607 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/proc_macros.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/proc_macros.rs @@ -1,6 +1,7 @@ //! Proc macro ABI use proc_macro::bridge; +use span::ErasedFileAstId; use crate::{ProcMacroKind, ProcMacroSrvSpan, server_impl::TopSubtree}; @@ -22,6 +23,7 @@ impl ProcMacros { def_site: S, call_site: S, mixed_site: S, + fixup_ast_id: ErasedFileAstId, ) -> Result, crate::PanicMessage> { let parsed_body = crate::server_impl::TokenStream::with_subtree(macro_body); @@ -37,7 +39,7 @@ impl ProcMacros { { let res = client.run( &bridge::server::SameThread, - S::make_server(call_site, def_site, mixed_site), + S::make_server(call_site, def_site, mixed_site, fixup_ast_id), parsed_body, cfg!(debug_assertions), ); @@ -48,7 +50,7 @@ impl ProcMacros { bridge::client::ProcMacro::Bang { name, client } if *name == macro_name => { let res = client.run( &bridge::server::SameThread, - S::make_server(call_site, def_site, mixed_site), + S::make_server(call_site, def_site, mixed_site, fixup_ast_id), parsed_body, cfg!(debug_assertions), ); @@ -59,7 +61,7 @@ impl ProcMacros { bridge::client::ProcMacro::Attr { name, client } if *name == macro_name => { let res = client.run( &bridge::server::SameThread, - S::make_server(call_site, def_site, mixed_site), + S::make_server(call_site, def_site, mixed_site, fixup_ast_id), parsed_attributes, parsed_body, cfg!(debug_assertions), diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs index 5d1271ba81e1f..b071ad80f5b6e 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs @@ -11,7 +11,7 @@ use std::{ use intern::Symbol; use proc_macro::bridge::{self, server}; -use span::{FIXUP_ERASED_FILE_AST_ID_MARKER, Span}; +use span::{ErasedFileAstId, Span}; use tt::{TextRange, TextSize}; use crate::server_impl::{from_token_tree, literal_from_str, token_stream::TokenStreamBuilder}; @@ -28,6 +28,7 @@ pub struct RaSpanServer { pub call_site: Span, pub def_site: Span, pub mixed_site: Span, + pub fixup_ast_id: ErasedFileAstId, } impl server::Types for RaSpanServer { @@ -181,10 +182,10 @@ impl server::Span for RaSpanServer { fn join(&mut self, first: Self::Span, second: Self::Span) -> Option { // We can't modify the span range for fixup spans, those are meaningful to fixup, so just // prefer the non-fixup span. - if first.anchor.ast_id == FIXUP_ERASED_FILE_AST_ID_MARKER { + if first.anchor.ast_id == self.fixup_ast_id { return Some(second); } - if second.anchor.ast_id == FIXUP_ERASED_FILE_AST_ID_MARKER { + if second.anchor.ast_id == self.fixup_ast_id { return Some(first); } // FIXME: Once we can talk back to the client, implement a "long join" request for anchors @@ -213,7 +214,7 @@ impl server::Span for RaSpanServer { end: Bound, ) -> Option { // We can't modify the span range for fixup spans, those are meaningful to fixup. - if span.anchor.ast_id == FIXUP_ERASED_FILE_AST_ID_MARKER { + if span.anchor.ast_id == self.fixup_ast_id { return Some(span); } let length = span.range.len().into(); @@ -256,7 +257,7 @@ impl server::Span for RaSpanServer { fn end(&mut self, span: Self::Span) -> Self::Span { // We can't modify the span range for fixup spans, those are meaningful to fixup. - if span.anchor.ast_id == FIXUP_ERASED_FILE_AST_ID_MARKER { + if span.anchor.ast_id == self.fixup_ast_id { return span; } Span { range: TextRange::empty(span.range.end()), ..span } @@ -264,7 +265,7 @@ impl server::Span for RaSpanServer { fn start(&mut self, span: Self::Span) -> Self::Span { // We can't modify the span range for fixup spans, those are meaningful to fixup. - if span.anchor.ast_id == FIXUP_ERASED_FILE_AST_ID_MARKER { + if span.anchor.ast_id == self.fixup_ast_id { return span; } Span { range: TextRange::empty(span.range.start()), ..span } @@ -318,7 +319,7 @@ mod tests { range: TextRange::empty(TextSize::new(0)), anchor: span::SpanAnchor { file_id: EditionedFileId::current_edition(FileId::from_raw(0)), - ast_id: span::ErasedFileAstId::from_raw(0), + ast_id: span::ROOT_ERASED_FILE_AST_ID, }, ctx: SyntaxContext::root(span::Edition::CURRENT), }; @@ -360,7 +361,7 @@ mod tests { range: TextRange::empty(TextSize::new(0)), anchor: span::SpanAnchor { file_id: EditionedFileId::current_edition(FileId::from_raw(0)), - ast_id: span::ErasedFileAstId::from_raw(0), + ast_id: span::ROOT_ERASED_FILE_AST_ID, }, ctx: SyntaxContext::root(span::Edition::CURRENT), }; diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/mod.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/mod.rs index d1ea89d2dcafd..08495f50bff44 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/mod.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/mod.rs @@ -21,14 +21,14 @@ fn test_derive_empty() { SUBTREE $$ 1 1"#]], expect![[r#" - SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024 - IDENT struct 42:2@0..6#ROOT2024 - IDENT S 42:2@7..8#ROOT2024 - PUNCH ; [alone] 42:2@8..9#ROOT2024 + SUBTREE $$ 42:Root[0000, 0]@0..100#ROOT2024 42:Root[0000, 0]@0..100#ROOT2024 + IDENT struct 42:Root[0000, 0]@0..6#ROOT2024 + IDENT S 42:Root[0000, 0]@7..8#ROOT2024 + PUNCH ; [alone] 42:Root[0000, 0]@8..9#ROOT2024 - SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024"#]], + SUBTREE $$ 42:Root[0000, 0]@0..100#ROOT2024 42:Root[0000, 0]@0..100#ROOT2024"#]], ); } @@ -52,19 +52,19 @@ fn test_derive_error() { LITERAL Str #[derive(DeriveError)] struct S ; 1 PUNCH ; [alone] 1"#]], expect![[r#" - SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024 - IDENT struct 42:2@0..6#ROOT2024 - IDENT S 42:2@7..8#ROOT2024 - PUNCH ; [alone] 42:2@8..9#ROOT2024 + SUBTREE $$ 42:Root[0000, 0]@0..100#ROOT2024 42:Root[0000, 0]@0..100#ROOT2024 + IDENT struct 42:Root[0000, 0]@0..6#ROOT2024 + IDENT S 42:Root[0000, 0]@7..8#ROOT2024 + PUNCH ; [alone] 42:Root[0000, 0]@8..9#ROOT2024 - SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024 - IDENT compile_error 42:2@0..100#ROOT2024 - PUNCH ! [alone] 42:2@0..100#ROOT2024 - SUBTREE () 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024 - LITERAL Str #[derive(DeriveError)] struct S ; 42:2@0..100#ROOT2024 - PUNCH ; [alone] 42:2@0..100#ROOT2024"#]], + SUBTREE $$ 42:Root[0000, 0]@0..100#ROOT2024 42:Root[0000, 0]@0..100#ROOT2024 + IDENT compile_error 42:Root[0000, 0]@0..100#ROOT2024 + PUNCH ! [alone] 42:Root[0000, 0]@0..100#ROOT2024 + SUBTREE () 42:Root[0000, 0]@0..100#ROOT2024 42:Root[0000, 0]@0..100#ROOT2024 + LITERAL Str #[derive(DeriveError)] struct S ; 42:Root[0000, 0]@0..100#ROOT2024 + PUNCH ; [alone] 42:Root[0000, 0]@0..100#ROOT2024"#]], ); } @@ -94,25 +94,25 @@ fn test_fn_like_macro_noop() { PUNCH , [alone] 1 SUBTREE [] 1 1"#]], expect![[r#" - SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024 - IDENT ident 42:2@0..5#ROOT2024 - PUNCH , [alone] 42:2@5..6#ROOT2024 - LITERAL Integer 0 42:2@7..8#ROOT2024 - PUNCH , [alone] 42:2@8..9#ROOT2024 - LITERAL Integer 1 42:2@10..11#ROOT2024 - PUNCH , [alone] 42:2@11..12#ROOT2024 - SUBTREE [] 42:2@13..14#ROOT2024 42:2@14..15#ROOT2024 - - - - SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024 - IDENT ident 42:2@0..5#ROOT2024 - PUNCH , [alone] 42:2@5..6#ROOT2024 - LITERAL Integer 0 42:2@7..8#ROOT2024 - PUNCH , [alone] 42:2@8..9#ROOT2024 - LITERAL Integer 1 42:2@10..11#ROOT2024 - PUNCH , [alone] 42:2@11..12#ROOT2024 - SUBTREE [] 42:2@13..14#ROOT2024 42:2@14..15#ROOT2024"#]], + SUBTREE $$ 42:Root[0000, 0]@0..100#ROOT2024 42:Root[0000, 0]@0..100#ROOT2024 + IDENT ident 42:Root[0000, 0]@0..5#ROOT2024 + PUNCH , [alone] 42:Root[0000, 0]@5..6#ROOT2024 + LITERAL Integer 0 42:Root[0000, 0]@7..8#ROOT2024 + PUNCH , [alone] 42:Root[0000, 0]@8..9#ROOT2024 + LITERAL Integer 1 42:Root[0000, 0]@10..11#ROOT2024 + PUNCH , [alone] 42:Root[0000, 0]@11..12#ROOT2024 + SUBTREE [] 42:Root[0000, 0]@13..14#ROOT2024 42:Root[0000, 0]@14..15#ROOT2024 + + + + SUBTREE $$ 42:Root[0000, 0]@0..100#ROOT2024 42:Root[0000, 0]@0..100#ROOT2024 + IDENT ident 42:Root[0000, 0]@0..5#ROOT2024 + PUNCH , [alone] 42:Root[0000, 0]@5..6#ROOT2024 + LITERAL Integer 0 42:Root[0000, 0]@7..8#ROOT2024 + PUNCH , [alone] 42:Root[0000, 0]@8..9#ROOT2024 + LITERAL Integer 1 42:Root[0000, 0]@10..11#ROOT2024 + PUNCH , [alone] 42:Root[0000, 0]@11..12#ROOT2024 + SUBTREE [] 42:Root[0000, 0]@13..14#ROOT2024 42:Root[0000, 0]@14..15#ROOT2024"#]], ); } @@ -134,17 +134,17 @@ fn test_fn_like_macro_clone_ident_subtree() { PUNCH , [alone] 1 SUBTREE [] 1 1"#]], expect![[r#" - SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024 - IDENT ident 42:2@0..5#ROOT2024 - PUNCH , [alone] 42:2@5..6#ROOT2024 - SUBTREE [] 42:2@7..8#ROOT2024 42:2@8..9#ROOT2024 + SUBTREE $$ 42:Root[0000, 0]@0..100#ROOT2024 42:Root[0000, 0]@0..100#ROOT2024 + IDENT ident 42:Root[0000, 0]@0..5#ROOT2024 + PUNCH , [alone] 42:Root[0000, 0]@5..6#ROOT2024 + SUBTREE [] 42:Root[0000, 0]@7..8#ROOT2024 42:Root[0000, 0]@8..9#ROOT2024 - SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024 - IDENT ident 42:2@0..5#ROOT2024 - PUNCH , [alone] 42:2@5..6#ROOT2024 - SUBTREE [] 42:2@7..9#ROOT2024 42:2@7..9#ROOT2024"#]], + SUBTREE $$ 42:Root[0000, 0]@0..100#ROOT2024 42:Root[0000, 0]@0..100#ROOT2024 + IDENT ident 42:Root[0000, 0]@0..5#ROOT2024 + PUNCH , [alone] 42:Root[0000, 0]@5..6#ROOT2024 + SUBTREE [] 42:Root[0000, 0]@7..9#ROOT2024 42:Root[0000, 0]@7..9#ROOT2024"#]], ); } @@ -162,13 +162,13 @@ fn test_fn_like_macro_clone_raw_ident() { SUBTREE $$ 1 1 IDENT r#async 1"#]], expect![[r#" - SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024 - IDENT r#async 42:2@0..7#ROOT2024 + SUBTREE $$ 42:Root[0000, 0]@0..100#ROOT2024 42:Root[0000, 0]@0..100#ROOT2024 + IDENT r#async 42:Root[0000, 0]@0..7#ROOT2024 - SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024 - IDENT r#async 42:2@0..7#ROOT2024"#]], + SUBTREE $$ 42:Root[0000, 0]@0..100#ROOT2024 42:Root[0000, 0]@0..100#ROOT2024 + IDENT r#async 42:Root[0000, 0]@0..7#ROOT2024"#]], ); } @@ -187,14 +187,14 @@ fn test_fn_like_fn_like_span_join() { SUBTREE $$ 1 1 IDENT r#joined 1"#]], expect![[r#" - SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024 - IDENT foo 42:2@0..3#ROOT2024 - IDENT bar 42:2@8..11#ROOT2024 + SUBTREE $$ 42:Root[0000, 0]@0..100#ROOT2024 42:Root[0000, 0]@0..100#ROOT2024 + IDENT foo 42:Root[0000, 0]@0..3#ROOT2024 + IDENT bar 42:Root[0000, 0]@8..11#ROOT2024 - SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024 - IDENT r#joined 42:2@0..11#ROOT2024"#]], + SUBTREE $$ 42:Root[0000, 0]@0..100#ROOT2024 42:Root[0000, 0]@0..100#ROOT2024 + IDENT r#joined 42:Root[0000, 0]@0..11#ROOT2024"#]], ); } @@ -216,17 +216,17 @@ fn test_fn_like_fn_like_span_ops() { IDENT resolved_at_def_site 1 IDENT start_span 1"#]], expect![[r#" - SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024 - IDENT set_def_site 42:2@0..12#ROOT2024 - IDENT resolved_at_def_site 42:2@13..33#ROOT2024 - IDENT start_span 42:2@34..44#ROOT2024 + SUBTREE $$ 42:Root[0000, 0]@0..100#ROOT2024 42:Root[0000, 0]@0..100#ROOT2024 + IDENT set_def_site 42:Root[0000, 0]@0..12#ROOT2024 + IDENT resolved_at_def_site 42:Root[0000, 0]@13..33#ROOT2024 + IDENT start_span 42:Root[0000, 0]@34..44#ROOT2024 - SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024 - IDENT set_def_site 41:1@0..150#ROOT2024 - IDENT resolved_at_def_site 42:2@13..33#ROOT2024 - IDENT start_span 42:2@34..34#ROOT2024"#]], + SUBTREE $$ 42:Root[0000, 0]@0..100#ROOT2024 42:Root[0000, 0]@0..100#ROOT2024 + IDENT set_def_site 41:Root[0000, 0]@0..150#ROOT2024 + IDENT resolved_at_def_site 42:Root[0000, 0]@13..33#ROOT2024 + IDENT start_span 42:Root[0000, 0]@34..34#ROOT2024"#]], ); } @@ -259,28 +259,28 @@ fn test_fn_like_mk_literals() { PUNCH - [alone] 1 LITERAL Integer 123 1"#]], expect![[r#" - SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024 - - - - SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024 - LITERAL ByteStr byte_string 42:2@0..100#ROOT2024 - LITERAL Char c 42:2@0..100#ROOT2024 - LITERAL Str string 42:2@0..100#ROOT2024 - LITERAL Str -string 42:2@0..100#ROOT2024 - LITERAL CStr cstring 42:2@0..100#ROOT2024 - LITERAL Float 3.14f64 42:2@0..100#ROOT2024 - PUNCH - [alone] 42:2@0..100#ROOT2024 - LITERAL Float 3.14f64 42:2@0..100#ROOT2024 - LITERAL Float 3.14 42:2@0..100#ROOT2024 - PUNCH - [alone] 42:2@0..100#ROOT2024 - LITERAL Float 3.14 42:2@0..100#ROOT2024 - LITERAL Integer 123i64 42:2@0..100#ROOT2024 - PUNCH - [alone] 42:2@0..100#ROOT2024 - LITERAL Integer 123i64 42:2@0..100#ROOT2024 - LITERAL Integer 123 42:2@0..100#ROOT2024 - PUNCH - [alone] 42:2@0..100#ROOT2024 - LITERAL Integer 123 42:2@0..100#ROOT2024"#]], + SUBTREE $$ 42:Root[0000, 0]@0..100#ROOT2024 42:Root[0000, 0]@0..100#ROOT2024 + + + + SUBTREE $$ 42:Root[0000, 0]@0..100#ROOT2024 42:Root[0000, 0]@0..100#ROOT2024 + LITERAL ByteStr byte_string 42:Root[0000, 0]@0..100#ROOT2024 + LITERAL Char c 42:Root[0000, 0]@0..100#ROOT2024 + LITERAL Str string 42:Root[0000, 0]@0..100#ROOT2024 + LITERAL Str -string 42:Root[0000, 0]@0..100#ROOT2024 + LITERAL CStr cstring 42:Root[0000, 0]@0..100#ROOT2024 + LITERAL Float 3.14f64 42:Root[0000, 0]@0..100#ROOT2024 + PUNCH - [alone] 42:Root[0000, 0]@0..100#ROOT2024 + LITERAL Float 3.14f64 42:Root[0000, 0]@0..100#ROOT2024 + LITERAL Float 3.14 42:Root[0000, 0]@0..100#ROOT2024 + PUNCH - [alone] 42:Root[0000, 0]@0..100#ROOT2024 + LITERAL Float 3.14 42:Root[0000, 0]@0..100#ROOT2024 + LITERAL Integer 123i64 42:Root[0000, 0]@0..100#ROOT2024 + PUNCH - [alone] 42:Root[0000, 0]@0..100#ROOT2024 + LITERAL Integer 123i64 42:Root[0000, 0]@0..100#ROOT2024 + LITERAL Integer 123 42:Root[0000, 0]@0..100#ROOT2024 + PUNCH - [alone] 42:Root[0000, 0]@0..100#ROOT2024 + LITERAL Integer 123 42:Root[0000, 0]@0..100#ROOT2024"#]], ); } @@ -298,13 +298,13 @@ fn test_fn_like_mk_idents() { IDENT standard 1 IDENT r#raw 1"#]], expect![[r#" - SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024 + SUBTREE $$ 42:Root[0000, 0]@0..100#ROOT2024 42:Root[0000, 0]@0..100#ROOT2024 - SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024 - IDENT standard 42:2@0..100#ROOT2024 - IDENT r#raw 42:2@0..100#ROOT2024"#]], + SUBTREE $$ 42:Root[0000, 0]@0..100#ROOT2024 42:Root[0000, 0]@0..100#ROOT2024 + IDENT standard 42:Root[0000, 0]@0..100#ROOT2024 + IDENT r#raw 42:Root[0000, 0]@0..100#ROOT2024"#]], ); } @@ -360,51 +360,51 @@ fn test_fn_like_macro_clone_literals() { PUNCH , [alone] 1 LITERAL CStr null 1"#]], expect![[r#" - SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024 - LITERAL Integer 1u16 42:2@0..4#ROOT2024 - PUNCH , [alone] 42:2@4..5#ROOT2024 - LITERAL Integer 2_u32 42:2@6..11#ROOT2024 - PUNCH , [alone] 42:2@11..12#ROOT2024 - PUNCH - [alone] 42:2@13..14#ROOT2024 - LITERAL Integer 4i64 42:2@14..18#ROOT2024 - PUNCH , [alone] 42:2@18..19#ROOT2024 - LITERAL Float 3.14f32 42:2@20..27#ROOT2024 - PUNCH , [alone] 42:2@27..28#ROOT2024 - LITERAL Str hello bridge 42:2@29..43#ROOT2024 - PUNCH , [alone] 42:2@43..44#ROOT2024 - LITERAL Str suffixedsuffix 42:2@45..61#ROOT2024 - PUNCH , [alone] 42:2@61..62#ROOT2024 - LITERAL StrRaw(2) raw 42:2@63..73#ROOT2024 - PUNCH , [alone] 42:2@73..74#ROOT2024 - LITERAL Char a 42:2@75..78#ROOT2024 - PUNCH , [alone] 42:2@78..79#ROOT2024 - LITERAL Byte b 42:2@80..84#ROOT2024 - PUNCH , [alone] 42:2@84..85#ROOT2024 - LITERAL CStr null 42:2@86..93#ROOT2024 - - - - SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024 - LITERAL Integer 1u16 42:2@0..4#ROOT2024 - PUNCH , [alone] 42:2@4..5#ROOT2024 - LITERAL Integer 2_u32 42:2@6..11#ROOT2024 - PUNCH , [alone] 42:2@11..12#ROOT2024 - PUNCH - [alone] 42:2@13..14#ROOT2024 - LITERAL Integer 4i64 42:2@14..18#ROOT2024 - PUNCH , [alone] 42:2@18..19#ROOT2024 - LITERAL Float 3.14f32 42:2@20..27#ROOT2024 - PUNCH , [alone] 42:2@27..28#ROOT2024 - LITERAL Str hello bridge 42:2@29..43#ROOT2024 - PUNCH , [alone] 42:2@43..44#ROOT2024 - LITERAL Str suffixedsuffix 42:2@45..61#ROOT2024 - PUNCH , [alone] 42:2@61..62#ROOT2024 - LITERAL StrRaw(2) raw 42:2@63..73#ROOT2024 - PUNCH , [alone] 42:2@73..74#ROOT2024 - LITERAL Char a 42:2@75..78#ROOT2024 - PUNCH , [alone] 42:2@78..79#ROOT2024 - LITERAL Byte b 42:2@80..84#ROOT2024 - PUNCH , [alone] 42:2@84..85#ROOT2024 - LITERAL CStr null 42:2@86..93#ROOT2024"#]], + SUBTREE $$ 42:Root[0000, 0]@0..100#ROOT2024 42:Root[0000, 0]@0..100#ROOT2024 + LITERAL Integer 1u16 42:Root[0000, 0]@0..4#ROOT2024 + PUNCH , [alone] 42:Root[0000, 0]@4..5#ROOT2024 + LITERAL Integer 2_u32 42:Root[0000, 0]@6..11#ROOT2024 + PUNCH , [alone] 42:Root[0000, 0]@11..12#ROOT2024 + PUNCH - [alone] 42:Root[0000, 0]@13..14#ROOT2024 + LITERAL Integer 4i64 42:Root[0000, 0]@14..18#ROOT2024 + PUNCH , [alone] 42:Root[0000, 0]@18..19#ROOT2024 + LITERAL Float 3.14f32 42:Root[0000, 0]@20..27#ROOT2024 + PUNCH , [alone] 42:Root[0000, 0]@27..28#ROOT2024 + LITERAL Str hello bridge 42:Root[0000, 0]@29..43#ROOT2024 + PUNCH , [alone] 42:Root[0000, 0]@43..44#ROOT2024 + LITERAL Str suffixedsuffix 42:Root[0000, 0]@45..61#ROOT2024 + PUNCH , [alone] 42:Root[0000, 0]@61..62#ROOT2024 + LITERAL StrRaw(2) raw 42:Root[0000, 0]@63..73#ROOT2024 + PUNCH , [alone] 42:Root[0000, 0]@73..74#ROOT2024 + LITERAL Char a 42:Root[0000, 0]@75..78#ROOT2024 + PUNCH , [alone] 42:Root[0000, 0]@78..79#ROOT2024 + LITERAL Byte b 42:Root[0000, 0]@80..84#ROOT2024 + PUNCH , [alone] 42:Root[0000, 0]@84..85#ROOT2024 + LITERAL CStr null 42:Root[0000, 0]@86..93#ROOT2024 + + + + SUBTREE $$ 42:Root[0000, 0]@0..100#ROOT2024 42:Root[0000, 0]@0..100#ROOT2024 + LITERAL Integer 1u16 42:Root[0000, 0]@0..4#ROOT2024 + PUNCH , [alone] 42:Root[0000, 0]@4..5#ROOT2024 + LITERAL Integer 2_u32 42:Root[0000, 0]@6..11#ROOT2024 + PUNCH , [alone] 42:Root[0000, 0]@11..12#ROOT2024 + PUNCH - [alone] 42:Root[0000, 0]@13..14#ROOT2024 + LITERAL Integer 4i64 42:Root[0000, 0]@14..18#ROOT2024 + PUNCH , [alone] 42:Root[0000, 0]@18..19#ROOT2024 + LITERAL Float 3.14f32 42:Root[0000, 0]@20..27#ROOT2024 + PUNCH , [alone] 42:Root[0000, 0]@27..28#ROOT2024 + LITERAL Str hello bridge 42:Root[0000, 0]@29..43#ROOT2024 + PUNCH , [alone] 42:Root[0000, 0]@43..44#ROOT2024 + LITERAL Str suffixedsuffix 42:Root[0000, 0]@45..61#ROOT2024 + PUNCH , [alone] 42:Root[0000, 0]@61..62#ROOT2024 + LITERAL StrRaw(2) raw 42:Root[0000, 0]@63..73#ROOT2024 + PUNCH , [alone] 42:Root[0000, 0]@73..74#ROOT2024 + LITERAL Char a 42:Root[0000, 0]@75..78#ROOT2024 + PUNCH , [alone] 42:Root[0000, 0]@78..79#ROOT2024 + LITERAL Byte b 42:Root[0000, 0]@80..84#ROOT2024 + PUNCH , [alone] 42:Root[0000, 0]@84..85#ROOT2024 + LITERAL CStr null 42:Root[0000, 0]@86..93#ROOT2024"#]], ); } @@ -442,33 +442,33 @@ fn test_fn_like_macro_negative_literals() { PUNCH - [alone] 1 LITERAL Float 2.7 1"#]], expect![[r#" - SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024 - PUNCH - [alone] 42:2@0..1#ROOT2024 - LITERAL Integer 1u16 42:2@1..5#ROOT2024 - PUNCH , [alone] 42:2@5..6#ROOT2024 - PUNCH - [alone] 42:2@7..8#ROOT2024 - LITERAL Integer 2_u32 42:2@9..14#ROOT2024 - PUNCH , [alone] 42:2@14..15#ROOT2024 - PUNCH - [alone] 42:2@16..17#ROOT2024 - LITERAL Float 3.14f32 42:2@17..24#ROOT2024 - PUNCH , [alone] 42:2@24..25#ROOT2024 - PUNCH - [alone] 42:2@26..27#ROOT2024 - LITERAL Float 2.7 42:2@28..31#ROOT2024 - - - - SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024 - PUNCH - [alone] 42:2@0..1#ROOT2024 - LITERAL Integer 1u16 42:2@1..5#ROOT2024 - PUNCH , [alone] 42:2@5..6#ROOT2024 - PUNCH - [alone] 42:2@7..8#ROOT2024 - LITERAL Integer 2_u32 42:2@9..14#ROOT2024 - PUNCH , [alone] 42:2@14..15#ROOT2024 - PUNCH - [alone] 42:2@16..17#ROOT2024 - LITERAL Float 3.14f32 42:2@17..24#ROOT2024 - PUNCH , [alone] 42:2@24..25#ROOT2024 - PUNCH - [alone] 42:2@26..27#ROOT2024 - LITERAL Float 2.7 42:2@28..31#ROOT2024"#]], + SUBTREE $$ 42:Root[0000, 0]@0..100#ROOT2024 42:Root[0000, 0]@0..100#ROOT2024 + PUNCH - [alone] 42:Root[0000, 0]@0..1#ROOT2024 + LITERAL Integer 1u16 42:Root[0000, 0]@1..5#ROOT2024 + PUNCH , [alone] 42:Root[0000, 0]@5..6#ROOT2024 + PUNCH - [alone] 42:Root[0000, 0]@7..8#ROOT2024 + LITERAL Integer 2_u32 42:Root[0000, 0]@9..14#ROOT2024 + PUNCH , [alone] 42:Root[0000, 0]@14..15#ROOT2024 + PUNCH - [alone] 42:Root[0000, 0]@16..17#ROOT2024 + LITERAL Float 3.14f32 42:Root[0000, 0]@17..24#ROOT2024 + PUNCH , [alone] 42:Root[0000, 0]@24..25#ROOT2024 + PUNCH - [alone] 42:Root[0000, 0]@26..27#ROOT2024 + LITERAL Float 2.7 42:Root[0000, 0]@28..31#ROOT2024 + + + + SUBTREE $$ 42:Root[0000, 0]@0..100#ROOT2024 42:Root[0000, 0]@0..100#ROOT2024 + PUNCH - [alone] 42:Root[0000, 0]@0..1#ROOT2024 + LITERAL Integer 1u16 42:Root[0000, 0]@1..5#ROOT2024 + PUNCH , [alone] 42:Root[0000, 0]@5..6#ROOT2024 + PUNCH - [alone] 42:Root[0000, 0]@7..8#ROOT2024 + LITERAL Integer 2_u32 42:Root[0000, 0]@9..14#ROOT2024 + PUNCH , [alone] 42:Root[0000, 0]@14..15#ROOT2024 + PUNCH - [alone] 42:Root[0000, 0]@16..17#ROOT2024 + LITERAL Float 3.14f32 42:Root[0000, 0]@17..24#ROOT2024 + PUNCH , [alone] 42:Root[0000, 0]@24..25#ROOT2024 + PUNCH - [alone] 42:Root[0000, 0]@26..27#ROOT2024 + LITERAL Float 2.7 42:Root[0000, 0]@28..31#ROOT2024"#]], ); } @@ -498,21 +498,21 @@ fn test_attr_macro() { LITERAL Str #[attr_error(some arguments)] mod m {} 1 PUNCH ; [alone] 1"#]], expect![[r#" - SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024 - IDENT mod 42:2@0..3#ROOT2024 - IDENT m 42:2@4..5#ROOT2024 - SUBTREE {} 42:2@6..7#ROOT2024 42:2@7..8#ROOT2024 - - SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024 - IDENT some 42:2@0..4#ROOT2024 - IDENT arguments 42:2@5..14#ROOT2024 - - SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024 - IDENT compile_error 42:2@0..100#ROOT2024 - PUNCH ! [alone] 42:2@0..100#ROOT2024 - SUBTREE () 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024 - LITERAL Str #[attr_error(some arguments)] mod m {} 42:2@0..100#ROOT2024 - PUNCH ; [alone] 42:2@0..100#ROOT2024"#]], + SUBTREE $$ 42:Root[0000, 0]@0..100#ROOT2024 42:Root[0000, 0]@0..100#ROOT2024 + IDENT mod 42:Root[0000, 0]@0..3#ROOT2024 + IDENT m 42:Root[0000, 0]@4..5#ROOT2024 + SUBTREE {} 42:Root[0000, 0]@6..7#ROOT2024 42:Root[0000, 0]@7..8#ROOT2024 + + SUBTREE $$ 42:Root[0000, 0]@0..100#ROOT2024 42:Root[0000, 0]@0..100#ROOT2024 + IDENT some 42:Root[0000, 0]@0..4#ROOT2024 + IDENT arguments 42:Root[0000, 0]@5..14#ROOT2024 + + SUBTREE $$ 42:Root[0000, 0]@0..100#ROOT2024 42:Root[0000, 0]@0..100#ROOT2024 + IDENT compile_error 42:Root[0000, 0]@0..100#ROOT2024 + PUNCH ! [alone] 42:Root[0000, 0]@0..100#ROOT2024 + SUBTREE () 42:Root[0000, 0]@0..100#ROOT2024 42:Root[0000, 0]@0..100#ROOT2024 + LITERAL Str #[attr_error(some arguments)] mod m {} 42:Root[0000, 0]@0..100#ROOT2024 + PUNCH ; [alone] 42:Root[0000, 0]@0..100#ROOT2024"#]], ); } diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/utils.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/utils.rs index a0a45b269e4ab..e0a69608decdd 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/utils.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/utils.rs @@ -1,7 +1,10 @@ //! utils used in proc-macro tests use expect_test::Expect; -use span::{EditionedFileId, ErasedFileAstId, FileId, Span, SpanAnchor, SyntaxContext, TokenId}; +use span::{ + EditionedFileId, FIXUP_ERASED_FILE_AST_ID_MARKER, FileId, ROOT_ERASED_FILE_AST_ID, Span, + SpanAnchor, SyntaxContext, TokenId, +}; use tt::TextRange; use crate::{EnvSnapshot, ProcMacroSrv, dylib, proc_macro_test_dylib_path}; @@ -65,8 +68,17 @@ fn assert_expand_impl( let input_ts_string = format!("{input_ts:?}"); let attr_ts_string = attr_ts.as_ref().map(|it| format!("{it:?}")); - let res = - expander.expand(macro_name, input_ts, attr_ts, def_site, call_site, mixed_site).unwrap(); + let res = expander + .expand( + macro_name, + input_ts, + attr_ts, + def_site, + call_site, + mixed_site, + FIXUP_ERASED_FILE_AST_ID_MARKER, + ) + .unwrap(); expect.assert_eq(&format!( "{input_ts_string}\n\n{}\n\n{res:?}", attr_ts_string.unwrap_or_default() @@ -76,7 +88,7 @@ fn assert_expand_impl( range: TextRange::new(0.into(), 150.into()), anchor: SpanAnchor { file_id: EditionedFileId::current_edition(FileId::from_raw(41)), - ast_id: ErasedFileAstId::from_raw(1), + ast_id: ROOT_ERASED_FILE_AST_ID, }, ctx: SyntaxContext::root(span::Edition::CURRENT), }; @@ -84,7 +96,7 @@ fn assert_expand_impl( range: TextRange::new(0.into(), 100.into()), anchor: SpanAnchor { file_id: EditionedFileId::current_edition(FileId::from_raw(42)), - ast_id: ErasedFileAstId::from_raw(2), + ast_id: ROOT_ERASED_FILE_AST_ID, }, ctx: SyntaxContext::root(span::Edition::CURRENT), }; @@ -98,7 +110,17 @@ fn assert_expand_impl( let fixture_string = format!("{fixture:?}"); let attr_string = attr.as_ref().map(|it| format!("{it:?}")); - let res = expander.expand(macro_name, fixture, attr, def_site, call_site, mixed_site).unwrap(); + let res = expander + .expand( + macro_name, + fixture, + attr, + def_site, + call_site, + mixed_site, + FIXUP_ERASED_FILE_AST_ID_MARKER, + ) + .unwrap(); expect_spanned .assert_eq(&format!("{fixture_string}\n\n{}\n\n{res:#?}", attr_string.unwrap_or_default())); } diff --git a/src/tools/rust-analyzer/crates/span/Cargo.toml b/src/tools/rust-analyzer/crates/span/Cargo.toml index b3b401c3db44a..966962bab381b 100644 --- a/src/tools/rust-analyzer/crates/span/Cargo.toml +++ b/src/tools/rust-analyzer/crates/span/Cargo.toml @@ -22,6 +22,9 @@ vfs.workspace = true syntax.workspace = true stdx.workspace = true +[dev-dependencies] +syntax.workspace = true + [features] default = ["salsa"] diff --git a/src/tools/rust-analyzer/crates/span/src/ast_id.rs b/src/tools/rust-analyzer/crates/span/src/ast_id.rs index 228fba1fa0966..51a693ca011b5 100644 --- a/src/tools/rust-analyzer/crates/span/src/ast_id.rs +++ b/src/tools/rust-analyzer/crates/span/src/ast_id.rs @@ -4,137 +4,534 @@ //! Specifically, it enumerates all items in a file and uses position of a an //! item as an ID. That way, id's don't change unless the set of items itself //! changes. +//! +//! These IDs are tricky. If one of them invalidates, its interned ID invalidates, +//! and this can cause *a lot* to be recomputed. For example, if you invalidate the ID +//! of a struct, and that struct has an impl (any impl!) this will cause the `Self` +//! type of the impl to invalidate, which will cause the all impls queries to be +//! invalidated, which will cause every trait solve query in this crate *and* all +//! transitive reverse dependencies to be invalidated, which is pretty much the worst +//! thing that can happen incrementality wise. +//! +//! So we want these IDs to stay as stable as possible. For top-level items, we store +//! their kind and name, which should be unique, but since they can still not be, we +//! also store an index disambiguator. For nested items, we also store the ID of their +//! parent. For macro calls, we store the macro name and an index. There aren't usually +//! a lot of macro calls in item position, and invalidation in bodies is not much of +//! a problem, so this should be enough. use std::{ any::type_name, fmt, - hash::{BuildHasher, BuildHasherDefault, Hash, Hasher}, + hash::{BuildHasher, Hash, Hasher}, marker::PhantomData, }; use la_arena::{Arena, Idx, RawIdx}; -use rustc_hash::FxHasher; -use syntax::{AstNode, AstPtr, SyntaxNode, SyntaxNodePtr, ast}; +use rustc_hash::{FxBuildHasher, FxHashMap}; +use syntax::{ + AstNode, AstPtr, SyntaxKind, SyntaxNode, SyntaxNodePtr, + ast::{self, HasName}, + match_ast, +}; + +// The first index is always the root node's AstId +/// The root ast id always points to the encompassing file, using this in spans is discouraged as +/// any range relative to it will be effectively absolute, ruining the entire point of anchored +/// relative text ranges. +pub const ROOT_ERASED_FILE_AST_ID: ErasedFileAstId = + ErasedFileAstId(pack_hash_index_and_kind(0, 0, ErasedFileAstIdKind::Root as u32)); + +/// ErasedFileAstId used as the span for syntax node fixups. Any Span containing this file id is to be +/// considered fake. +pub const FIXUP_ERASED_FILE_AST_ID_MARKER: ErasedFileAstId = + ErasedFileAstId(pack_hash_index_and_kind(0, 0, ErasedFileAstIdKind::Fixup as u32)); -/// See crates\hir-expand\src\ast_id_map.rs /// This is a type erased FileAstId. -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[derive(Clone, Copy, PartialEq, Eq, Hash)] pub struct ErasedFileAstId(u32); +impl fmt::Debug for ErasedFileAstId { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let kind = self.kind(); + macro_rules! kind { + ($($kind:ident),* $(,)?) => { + if false { + // Ensure we covered all variants. + match ErasedFileAstIdKind::Root { + $( ErasedFileAstIdKind::$kind => {} )* + } + unreachable!() + } + $( else if kind == ErasedFileAstIdKind::$kind as u32 { + stringify!($kind) + } )* + else { + "Unknown" + } + }; + } + let kind = kind!( + Root, + Enum, + Struct, + Union, + ExternCrate, + MacroDef, + MacroRules, + Module, + Static, + Trait, + TraitAlias, + Variant, + Const, + Fn, + MacroCall, + TypeAlias, + ExternBlock, + Use, + Impl, + BlockExpr, + Fixup, + ); + if f.alternate() { + write!(f, "{kind}[{:04X}, {}]", self.hash_value(), self.index()) + } else { + f.debug_struct("ErasedFileAstId") + .field("kind", &format_args!("{kind}")) + .field("index", &self.index()) + .field("hash", &format_args!("{:04X}", self.hash_value())) + .finish() + } + } +} + +#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)] +enum ErasedFileAstIdKind { + Root, + // The following are associated with `ErasedHasNameFileAstId`. + Enum, + Struct, + Union, + ExternCrate, + MacroDef, + MacroRules, + Module, + Static, + Trait, + TraitAlias, + // Until here associated with `ErasedHasNameFileAstId`. + // The following are associated with `ErasedAssocItemFileAstId`. + Variant, + Const, + Fn, + MacroCall, + TypeAlias, + // Until here associated with `ErasedAssocItemFileAstId`. + // Extern blocks don't really have any identifying property unfortunately. + ExternBlock, + // FIXME: If we store the final `UseTree` instead of the top-level `Use`, we can store its name, + // and be way more granular for incrementality, at the expense of increased memory usage. + // Use IDs aren't used a lot. The main thing that stores them is the def map. So everything that + // uses the def map will be invalidated. That includes infers, and so is pretty bad, but our + // def map incrementality story is pretty bad anyway and needs to be improved (see + // https://rust-lang.zulipchat.com/#narrow/channel/185405-t-compiler.2Frust-analyzer/topic/.60infer.60.20queries.20and.20splitting.20.60DefMap.60). + // So I left this as-is for now, as the def map improvement should also mitigate this. + Use, + /// Associated with [`ImplFileAstId`]. + Impl, + /// Associated with [`BlockExprFileAstId`]. + BlockExpr, + /// Keep this last. + Fixup, +} + +// First hash, then index, then kind. +const HASH_BITS: u32 = 16; +const INDEX_BITS: u32 = 11; +const KIND_BITS: u32 = 5; +const _: () = assert!(ErasedFileAstIdKind::Fixup as u32 <= ((1 << KIND_BITS) - 1)); +const _: () = assert!(HASH_BITS + INDEX_BITS + KIND_BITS == u32::BITS); + +#[inline] +const fn u16_hash(hash: u64) -> u16 { + // We do basically the same as `FxHasher`. We don't use rustc-hash and truncate because the + // higher bits have more entropy, but unlike rustc-hash we don't rotate because it rotates + // for hashmaps that just use the low bits, but we compare all bits. + const K: u16 = 0xecc5; + let (part1, part2, part3, part4) = + (hash as u16, (hash >> 16) as u16, (hash >> 32) as u16, (hash >> 48) as u16); + part1 + .wrapping_add(part2) + .wrapping_mul(K) + .wrapping_add(part3) + .wrapping_mul(K) + .wrapping_add(part4) + .wrapping_mul(K) +} + +#[inline] +const fn pack_hash_index_and_kind(hash: u16, index: u32, kind: u32) -> u32 { + (hash as u32) | (index << HASH_BITS) | (kind << (HASH_BITS + INDEX_BITS)) +} + impl ErasedFileAstId { - pub const fn into_raw(self) -> u32 { - self.0 + #[inline] + fn hash_value(self) -> u16 { + self.0 as u16 } - pub const fn from_raw(u32: u32) -> Self { - Self(u32) + + #[inline] + fn index(self) -> u32 { + (self.0 << KIND_BITS) >> (HASH_BITS + KIND_BITS) } -} -impl fmt::Display for ErasedFileAstId { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.0.fmt(f) + #[inline] + fn kind(self) -> u32 { + self.0 >> (HASH_BITS + INDEX_BITS) } -} -impl fmt::Debug for ErasedFileAstId { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.0.fmt(f) + + fn ast_id_for( + node: &SyntaxNode, + index_map: &mut ErasedAstIdNextIndexMap, + parent: Option<&ErasedFileAstId>, + ) -> Option { + // Blocks are deliberately not here - we only want to allocate a block if it contains items. + has_name_ast_id(node, index_map) + .or_else(|| assoc_item_ast_id(node, index_map, parent)) + .or_else(|| extern_block_ast_id(node, index_map)) + .or_else(|| use_ast_id(node, index_map)) + .or_else(|| impl_ast_id(node, index_map)) + } + + fn should_alloc(node: &SyntaxNode) -> bool { + should_alloc_has_name(node) + || should_alloc_assoc_item(node) + || ast::ExternBlock::can_cast(node.kind()) + || ast::Use::can_cast(node.kind()) + || ast::Impl::can_cast(node.kind()) + } + + #[inline] + pub fn into_raw(self) -> u32 { + self.0 + } + + #[inline] + pub fn from_raw(v: u32) -> Self { + Self(v) } } +pub trait AstIdNode: AstNode {} + /// `AstId` points to an AST node in a specific file. -pub struct FileAstId { +pub struct FileAstId { raw: ErasedFileAstId, - covariant: PhantomData N>, + _marker: PhantomData N>, } -impl Clone for FileAstId { +/// Traits are manually implemented because `derive` adds redundant bounds. +impl Clone for FileAstId { + #[inline] fn clone(&self) -> FileAstId { *self } } -impl Copy for FileAstId {} +impl Copy for FileAstId {} -impl PartialEq for FileAstId { +impl PartialEq for FileAstId { fn eq(&self, other: &Self) -> bool { self.raw == other.raw } } -impl Eq for FileAstId {} -impl Hash for FileAstId { +impl Eq for FileAstId {} +impl Hash for FileAstId { fn hash(&self, hasher: &mut H) { self.raw.hash(hasher); } } -impl fmt::Debug for FileAstId { +impl fmt::Debug for FileAstId { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "FileAstId::<{}>({})", type_name::(), self.raw) + write!(f, "FileAstId::<{}>({:?})", type_name::(), self.raw) } } -impl FileAstId { +impl FileAstId { // Can't make this a From implementation because of coherence + #[inline] pub fn upcast(self) -> FileAstId where N: Into, { - FileAstId { raw: self.raw, covariant: PhantomData } + FileAstId { raw: self.raw, _marker: PhantomData } } + #[inline] pub fn erase(self) -> ErasedFileAstId { self.raw } } -pub trait AstIdNode: AstNode {} -macro_rules! register_ast_id_node { +#[derive(Hash)] +struct ErasedHasNameFileAstId<'a> { + kind: SyntaxKind, + name: &'a str, +} + +/// This holds the ast ID for variants too (they're a kind of assoc item). +#[derive(Hash)] +struct ErasedAssocItemFileAstId<'a> { + /// Subtle: items in `extern` blocks **do not** store the ID of the extern block here. + /// Instead this is left empty. The reason is that `ExternBlockFileAstId` is pretty unstable + /// (it contains only an index), and extern blocks don't introduce a new scope, so storing + /// the extern block ID will do more harm to incrementality than help. + parent: Option, + properties: ErasedHasNameFileAstId<'a>, +} + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +struct ImplFileAstId<'a> { + /// This can be `None` if the `Self` type is not a named type, or if it is inside a macro call. + self_ty_name: Option<&'a str>, + /// This can be `None` if this is an inherent impl, or if the trait name is inside a macro call. + trait_name: Option<&'a str>, +} + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +struct BlockExprFileAstId { + parent: Option, +} + +impl AstIdNode for ast::ExternBlock {} + +fn extern_block_ast_id( + node: &SyntaxNode, + index_map: &mut ErasedAstIdNextIndexMap, +) -> Option { + if ast::ExternBlock::can_cast(node.kind()) { + Some(index_map.new_id(ErasedFileAstIdKind::ExternBlock, ())) + } else { + None + } +} + +impl AstIdNode for ast::Use {} + +fn use_ast_id( + node: &SyntaxNode, + index_map: &mut ErasedAstIdNextIndexMap, +) -> Option { + if ast::Use::can_cast(node.kind()) { + Some(index_map.new_id(ErasedFileAstIdKind::Use, ())) + } else { + None + } +} + +impl AstIdNode for ast::Impl {} + +fn impl_ast_id( + node: &SyntaxNode, + index_map: &mut ErasedAstIdNextIndexMap, +) -> Option { + if let Some(node) = ast::Impl::cast(node.clone()) { + let type_as_name = |ty: Option| match ty? { + ast::Type::PathType(it) => Some(it.path()?.segment()?.name_ref()?), + _ => None, + }; + let self_ty_name = type_as_name(node.self_ty()); + let trait_name = type_as_name(node.trait_()); + let data = ImplFileAstId { + self_ty_name: self_ty_name.as_ref().map(|it| it.text_non_mutable()), + trait_name: trait_name.as_ref().map(|it| it.text_non_mutable()), + }; + Some(index_map.new_id(ErasedFileAstIdKind::Impl, data)) + } else { + None + } +} + +// Blocks aren't `AstIdNode`s deliberately, because unlike other nodes, not all blocks get their own +// ast id, only if they have items. To account for that we have a different, fallible, API for blocks. +// impl !AstIdNode for ast::BlockExpr {} + +fn block_expr_ast_id( + node: &SyntaxNode, + index_map: &mut ErasedAstIdNextIndexMap, + parent: Option<&ErasedFileAstId>, +) -> Option { + if ast::BlockExpr::can_cast(node.kind()) { + Some( + index_map.new_id( + ErasedFileAstIdKind::BlockExpr, + BlockExprFileAstId { parent: parent.copied() }, + ), + ) + } else { + None + } +} + +#[derive(Default)] +struct ErasedAstIdNextIndexMap(FxHashMap<(ErasedFileAstIdKind, u16), u32>); + +impl ErasedAstIdNextIndexMap { + #[inline] + fn new_id(&mut self, kind: ErasedFileAstIdKind, data: impl Hash) -> ErasedFileAstId { + let hash = FxBuildHasher.hash_one(&data); + let initial_hash = u16_hash(hash); + // Even though 2^INDEX_BITS=2048 items with the same hash seems like a lot, + // it could happen with macro calls or `use`s in macro-generated files. So we want + // to handle it gracefully. We just increment the hash. + let mut hash = initial_hash; + let index = loop { + match self.0.entry((kind, hash)) { + std::collections::hash_map::Entry::Occupied(mut entry) => { + let i = entry.get_mut(); + if *i < ((1 << INDEX_BITS) - 1) { + *i += 1; + break *i; + } + } + std::collections::hash_map::Entry::Vacant(entry) => { + entry.insert(0); + break 0; + } + } + hash = hash.wrapping_add(1); + if hash == initial_hash { + // That's 2^27=134,217,728 items! + panic!("you have way too many items in the same file!"); + } + }; + let kind = kind as u32; + ErasedFileAstId(pack_hash_index_and_kind(hash, index, kind)) + } +} + +macro_rules! register_enum_ast_id { (impl AstIdNode for $($ident:ident),+ ) => { $( impl AstIdNode for ast::$ident {} )+ - fn should_alloc_id(kind: syntax::SyntaxKind) -> bool { - $( - ast::$ident::can_cast(kind) - )||+ + }; +} +register_enum_ast_id! { + impl AstIdNode for + Item, AnyHasGenericParams, Adt, Macro, + AssocItem +} + +macro_rules! register_has_name_ast_id { + (impl AstIdNode for $($ident:ident = $name_method:ident),+ ) => { + $( + impl AstIdNode for ast::$ident {} + )+ + + fn has_name_ast_id(node: &SyntaxNode, index_map: &mut ErasedAstIdNextIndexMap) -> Option { + let kind = node.kind(); + match_ast! { + match node { + $( + ast::$ident(node) => { + let name = node.$name_method(); + let name = name.as_ref().map_or("", |it| it.text_non_mutable()); + let result = ErasedHasNameFileAstId { + kind, + name, + }; + Some(index_map.new_id(ErasedFileAstIdKind::$ident, result)) + }, + )* + _ => None, + } + } + } + + fn should_alloc_has_name(node: &SyntaxNode) -> bool { + let kind = node.kind(); + false $( || ast::$ident::can_cast(kind) )* } }; } -register_ast_id_node! { +register_has_name_ast_id! { impl AstIdNode for - Item, AnyHasGenericParams, - Adt, - Enum, - Variant, - Struct, - Union, - AssocItem, - Const, - Fn, - MacroCall, - TypeAlias, - ExternBlock, - ExternCrate, - Impl, - Macro, - MacroDef, - MacroRules, - Module, - Static, - Trait, - TraitAlias, - Use, - BlockExpr, ConstArg + Enum = name, + Struct = name, + Union = name, + ExternCrate = name_ref, + MacroDef = name, + MacroRules = name, + Module = name, + Static = name, + Trait = name, + TraitAlias = name +} + +macro_rules! register_assoc_item_ast_id { + (impl AstIdNode for $($ident:ident = $name_callback:expr),+ ) => { + $( + impl AstIdNode for ast::$ident {} + )+ + + fn assoc_item_ast_id( + node: &SyntaxNode, + index_map: &mut ErasedAstIdNextIndexMap, + parent: Option<&ErasedFileAstId>, + ) -> Option { + let kind = node.kind(); + match_ast! { + match node { + $( + ast::$ident(node) => { + let name = $name_callback(node); + let name = name.as_ref().map_or("", |it| it.text_non_mutable()); + let properties = ErasedHasNameFileAstId { + kind, + name, + }; + let result = ErasedAssocItemFileAstId { + parent: parent.copied(), + properties, + }; + Some(index_map.new_id(ErasedFileAstIdKind::$ident, result)) + }, + )* + _ => None, + } + } + } + + fn should_alloc_assoc_item(node: &SyntaxNode) -> bool { + let kind = node.kind(); + false $( || ast::$ident::can_cast(kind) )* + } + }; +} +register_assoc_item_ast_id! { + impl AstIdNode for + Variant = |it: ast::Variant| it.name(), + Const = |it: ast::Const| it.name(), + Fn = |it: ast::Fn| it.name(), + MacroCall = |it: ast::MacroCall| it.path().and_then(|path| path.segment()?.name_ref()), + TypeAlias = |it: ast::TypeAlias| it.name() } /// Maps items' `SyntaxNode`s to `ErasedFileAstId`s and back. #[derive(Default)] pub struct AstIdMap { - /// Maps stable id to unstable ptr. - arena: Arena, - /// Reverse: map ptr to id. - map: hashbrown::HashTable>, + /// An arena of the ptrs and their associated ID. + arena: Arena<(SyntaxNodePtr, ErasedFileAstId)>, + /// Map ptr to id. + ptr_map: hashbrown::HashTable, + /// Map id to ptr. + id_map: hashbrown::HashTable, } +type ArenaId = Idx<(SyntaxNodePtr, ErasedFileAstId)>; + impl fmt::Debug for AstIdMap { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("AstIdMap").field("arena", &self.arena).finish() @@ -148,31 +545,116 @@ impl PartialEq for AstIdMap { } impl Eq for AstIdMap {} +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +enum ContainsItems { + Yes, + No, +} + impl AstIdMap { pub fn from_source(node: &SyntaxNode) -> AstIdMap { assert!(node.parent().is_none()); let mut res = AstIdMap::default(); + let mut index_map = ErasedAstIdNextIndexMap::default(); + + // Ensure we allocate the root. + res.arena.alloc((SyntaxNodePtr::new(node), ROOT_ERASED_FILE_AST_ID)); - // make sure to allocate the root node - if !should_alloc_id(node.kind()) { - res.alloc(node); - } // By walking the tree in breadth-first order we make sure that parents // get lower ids then children. That is, adding a new child does not // change parent's id. This means that, say, adding a new function to a // trait does not change ids of top-level items, which helps caching. - bdfs(node, |it| { - if should_alloc_id(it.kind()) { - res.alloc(&it); - TreeOrder::BreadthFirst - } else { - TreeOrder::DepthFirst + + // This contains the stack of the `BlockExpr`s we are under. We do this + // so we only allocate `BlockExpr`s if they contain items. + // The general idea is: when we enter a block we push `(block, false)` here. + // Items inside the block are attributed to the block's container, not the block. + // For the first item we find inside a block, we make this `(block, true)` + // and create an ast id for the block. When exiting the block we pop it, + // whether or not we created an ast id for it. + // It may seem that with this setup we will generate an ID for blocks that + // have no items directly but have items inside other items inside them. + // This is true, but it doesn't matter, because such blocks can't exist. + // After all, the block will then contain the *outer* item, so we allocate + // an ID for it anyway. + let mut blocks = Vec::new(); + let mut curr_layer = vec![(node.clone(), None)]; + let mut next_layer = vec![]; + while !curr_layer.is_empty() { + curr_layer.drain(..).for_each(|(node, parent_idx)| { + let mut preorder = node.preorder(); + while let Some(event) = preorder.next() { + match event { + syntax::WalkEvent::Enter(node) => { + if ast::BlockExpr::can_cast(node.kind()) { + blocks.push((node, ContainsItems::No)); + } else if 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. + if let Some(( + last_block_node, + already_allocated @ ContainsItems::No, + )) = blocks.last_mut() + { + let block_ast_id = block_expr_ast_id( + last_block_node, + &mut index_map, + parent_of(parent_idx, &res), + ) + .expect("not a BlockExpr"); + res.arena + .alloc((SyntaxNodePtr::new(last_block_node), block_ast_id)); + *already_allocated = ContainsItems::Yes; + } + + let parent = parent_of(parent_idx, &res); + let ast_id = + ErasedFileAstId::ast_id_for(&node, &mut index_map, parent) + .expect("this node should have an ast id"); + let idx = res.arena.alloc((SyntaxNodePtr::new(&node), ast_id)); + + next_layer.extend(node.children().map(|child| (child, Some(idx)))); + preorder.skip_subtree(); + } + } + syntax::WalkEvent::Leave(node) => { + if ast::BlockExpr::can_cast(node.kind()) { + assert_eq!( + blocks.pop().map(|it| it.0), + Some(node), + "left a BlockExpr we never entered" + ); + } + } + } + } + }); + std::mem::swap(&mut curr_layer, &mut next_layer); + assert!(blocks.is_empty(), "didn't leave all BlockExprs"); + } + + res.ptr_map = hashbrown::HashTable::with_capacity(res.arena.len()); + res.id_map = hashbrown::HashTable::with_capacity(res.arena.len()); + for (idx, (ptr, ast_id)) in res.arena.iter() { + let ptr_hash = hash_ptr(ptr); + let ast_id_hash = hash_ast_id(ast_id); + match res.ptr_map.entry( + ptr_hash, + |idx2| *idx2 == idx, + |&idx| hash_ptr(&res.arena[idx].0), + ) { + hashbrown::hash_table::Entry::Occupied(_) => unreachable!(), + hashbrown::hash_table::Entry::Vacant(entry) => { + entry.insert(idx); + } } - }); - res.map = hashbrown::HashTable::with_capacity(res.arena.len()); - for (idx, ptr) in res.arena.iter() { - let hash = hash_ptr(ptr); - match res.map.entry(hash, |&idx2| idx2 == idx, |&idx| hash_ptr(&res.arena[idx])) { + match res.id_map.entry( + ast_id_hash, + |idx2| *idx2 == idx, + |&idx| hash_ast_id(&res.arena[idx].1), + ) { hashbrown::hash_table::Entry::Occupied(_) => unreachable!(), hashbrown::hash_table::Entry::Vacant(entry) => { entry.insert(idx); @@ -180,98 +662,235 @@ impl AstIdMap { } } res.arena.shrink_to_fit(); - res + return res; + + fn parent_of(parent_idx: Option, res: &AstIdMap) -> Option<&ErasedFileAstId> { + let mut parent = parent_idx.map(|parent_idx| &res.arena[parent_idx].1); + if parent.is_some_and(|parent| parent.kind() == ErasedFileAstIdKind::ExternBlock as u32) + { + // See the comment on `ErasedAssocItemFileAstId` for why is this. + // FIXME: Technically there could be an extern block inside another item, e.g.: + // ``` + // fn foo() { + // extern "C" { + // fn bar(); + // } + // } + // ``` + // Here we want to make `foo()` the parent of `bar()`, but we make it `None`. + // Shouldn't be a big deal though. + parent = None; + } + parent + } } /// The [`AstId`] of the root node pub fn root(&self) -> SyntaxNodePtr { - self.arena[Idx::from_raw(RawIdx::from_u32(0))] + self.arena[Idx::from_raw(RawIdx::from_u32(0))].0 } pub fn ast_id(&self, item: &N) -> FileAstId { - let raw = self.erased_ast_id(item.syntax()); - FileAstId { raw, covariant: PhantomData } + self.ast_id_for_ptr(AstPtr::new(item)) + } + + /// Blocks may not be allocated (if they have no items), so they have a different API. + pub fn ast_id_for_block(&self, block: &ast::BlockExpr) -> Option> { + self.ast_id_for_ptr_for_block(AstPtr::new(block)) } pub fn ast_id_for_ptr(&self, ptr: AstPtr) -> FileAstId { let ptr = ptr.syntax_node_ptr(); - let hash = hash_ptr(&ptr); - match self.map.find(hash, |&idx| self.arena[idx] == ptr) { - Some(&raw) => FileAstId { - raw: ErasedFileAstId(raw.into_raw().into_u32()), - covariant: PhantomData, - }, - None => panic!( - "Can't find {:?} in AstIdMap:\n{:?}", + FileAstId { raw: self.erased_ast_id(ptr), _marker: PhantomData } + } + + /// Blocks may not be allocated (if they have no items), so they have a different API. + pub fn ast_id_for_ptr_for_block( + &self, + ptr: AstPtr, + ) -> Option> { + let ptr = ptr.syntax_node_ptr(); + self.try_erased_ast_id(ptr).map(|raw| FileAstId { raw, _marker: PhantomData }) + } + + fn erased_ast_id(&self, ptr: SyntaxNodePtr) -> ErasedFileAstId { + self.try_erased_ast_id(ptr).unwrap_or_else(|| { + panic!( + "Can't find SyntaxNodePtr {:?} in AstIdMap:\n{:?}", ptr, self.arena.iter().map(|(_id, i)| i).collect::>(), - ), - } + ) + }) } - pub fn get(&self, id: FileAstId) -> AstPtr { - AstPtr::try_from_raw(self.arena[Idx::from_raw(RawIdx::from_u32(id.raw.into_raw()))]) - .unwrap() + fn try_erased_ast_id(&self, ptr: SyntaxNodePtr) -> Option { + let hash = hash_ptr(&ptr); + let idx = *self.ptr_map.find(hash, |&idx| self.arena[idx].0 == ptr)?; + Some(self.arena[idx].1) } - pub fn get_erased(&self, id: ErasedFileAstId) -> SyntaxNodePtr { - self.arena[Idx::from_raw(RawIdx::from_u32(id.into_raw()))] + // Don't bound on `AstIdNode` here, because `BlockExpr`s are also valid here (`ast::BlockExpr` + // doesn't always have a matching `FileAstId`, but a `FileAstId` always has + // a matching node). + pub fn get(&self, id: FileAstId) -> AstPtr { + let ptr = self.get_erased(id.raw); + AstPtr::try_from_raw(ptr) + .unwrap_or_else(|| panic!("AstIdMap node mismatch with node `{ptr:?}`")) } - fn erased_ast_id(&self, item: &SyntaxNode) -> ErasedFileAstId { - let ptr = SyntaxNodePtr::new(item); - let hash = hash_ptr(&ptr); - match self.map.find(hash, |&idx| self.arena[idx] == ptr) { - Some(&idx) => ErasedFileAstId(idx.into_raw().into_u32()), + pub fn get_erased(&self, id: ErasedFileAstId) -> SyntaxNodePtr { + let hash = hash_ast_id(&id); + match self.id_map.find(hash, |&idx| self.arena[idx].1 == id) { + Some(&idx) => self.arena[idx].0, None => panic!( - "Can't find {:?} in AstIdMap:\n{:?}\n source text: {}", - item, + "Can't find ast id {:?} in AstIdMap:\n{:?}", + id, self.arena.iter().map(|(_id, i)| i).collect::>(), - item ), } } - - fn alloc(&mut self, item: &SyntaxNode) -> ErasedFileAstId { - ErasedFileAstId(self.arena.alloc(SyntaxNodePtr::new(item)).into_raw().into_u32()) - } } +#[inline] fn hash_ptr(ptr: &SyntaxNodePtr) -> u64 { - BuildHasherDefault::::default().hash_one(ptr) -} - -#[derive(Copy, Clone, PartialEq, Eq)] -enum TreeOrder { - BreadthFirst, - DepthFirst, -} - -/// Walks the subtree in bdfs order, calling `f` for each node. What is bdfs -/// order? It is a mix of breadth-first and depth first orders. Nodes for which -/// `f` returns [`TreeOrder::BreadthFirst`] are visited breadth-first, all the other nodes are explored -/// [`TreeOrder::DepthFirst`]. -/// -/// In other words, the size of the bfs queue is bound by the number of "true" -/// nodes. -fn bdfs(node: &SyntaxNode, mut f: impl FnMut(SyntaxNode) -> TreeOrder) { - let mut curr_layer = vec![node.clone()]; - let mut next_layer = vec![]; - while !curr_layer.is_empty() { - curr_layer.drain(..).for_each(|node| { - let mut preorder = node.preorder(); - while let Some(event) = preorder.next() { - match event { - syntax::WalkEvent::Enter(node) => { - if f(node.clone()) == TreeOrder::BreadthFirst { - next_layer.extend(node.children()); - preorder.skip_subtree(); - } - } - syntax::WalkEvent::Leave(_) => {} - } + FxBuildHasher.hash_one(ptr) +} + +#[inline] +fn hash_ast_id(ptr: &ErasedFileAstId) -> u64 { + FxBuildHasher.hash_one(ptr) +} + +#[cfg(test)] +mod tests { + use syntax::{AstNode, Edition, SourceFile, SyntaxKind, SyntaxNodePtr, WalkEvent, ast}; + + use crate::AstIdMap; + + #[test] + fn check_all_nodes() { + let syntax = SourceFile::parse( + r#" +extern crate foo; +fn foo() { + union U {} +} +struct S; +macro_rules! m {} +macro m2() {} +trait Trait {} +impl Trait for S {} +impl S {} +impl m!() {} +impl m2!() for m!() {} +type T = i32; +enum E { + V1(), + V2 {}, + V3, +} +struct S; // duplicate +extern "C" { + static S: i32; +} +static mut S: i32 = 0; +const FOO: i32 = 0; + "#, + Edition::CURRENT, + ) + .syntax_node(); + let ast_id_map = AstIdMap::from_source(&syntax); + for node in syntax.preorder() { + let WalkEvent::Enter(node) = node else { continue }; + if !matches!( + node.kind(), + SyntaxKind::EXTERN_CRATE + | SyntaxKind::FN + | SyntaxKind::UNION + | SyntaxKind::STRUCT + | SyntaxKind::MACRO_RULES + | SyntaxKind::MACRO_DEF + | SyntaxKind::MACRO_CALL + | SyntaxKind::TRAIT + | SyntaxKind::IMPL + | SyntaxKind::TYPE_ALIAS + | SyntaxKind::ENUM + | SyntaxKind::VARIANT + | SyntaxKind::EXTERN_BLOCK + | SyntaxKind::STATIC + | SyntaxKind::CONST + ) { + continue; } - }); - std::mem::swap(&mut curr_layer, &mut next_layer); + let ptr = SyntaxNodePtr::new(&node); + let ast_id = ast_id_map.erased_ast_id(ptr); + let turn_back = ast_id_map.get_erased(ast_id); + assert_eq!(ptr, turn_back); + } + } + + #[test] + fn different_names_get_different_hashes() { + let syntax = SourceFile::parse( + r#" +fn foo() {} +fn bar() {} + "#, + Edition::CURRENT, + ) + .syntax_node(); + let ast_id_map = AstIdMap::from_source(&syntax); + let fns = syntax.descendants().filter_map(ast::Fn::cast).collect::>(); + let [foo_fn, bar_fn] = fns.as_slice() else { + panic!("not exactly 2 functions"); + }; + let foo_fn_id = ast_id_map.ast_id(foo_fn); + let bar_fn_id = ast_id_map.ast_id(bar_fn); + assert_ne!(foo_fn_id.raw.hash_value(), bar_fn_id.raw.hash_value(), "hashes are equal"); + } + + #[test] + fn different_parents_get_different_hashes() { + let syntax = SourceFile::parse( + r#" +fn foo() { + m!(); +} +fn bar() { + m!(); +} + "#, + Edition::CURRENT, + ) + .syntax_node(); + let ast_id_map = AstIdMap::from_source(&syntax); + let macro_calls = syntax.descendants().filter_map(ast::MacroCall::cast).collect::>(); + let [macro_call_foo, macro_call_bar] = macro_calls.as_slice() else { + panic!("not exactly 2 macro calls"); + }; + let macro_call_foo_id = ast_id_map.ast_id(macro_call_foo); + let macro_call_bar_id = ast_id_map.ast_id(macro_call_bar); + assert_ne!( + macro_call_foo_id.raw.hash_value(), + macro_call_bar_id.raw.hash_value(), + "hashes are equal" + ); + } + + #[test] + fn blocks_with_no_items_have_no_id() { + let syntax = SourceFile::parse( + r#" +fn foo() { + let foo = 1; + bar(foo); +} + "#, + Edition::CURRENT, + ) + .syntax_node(); + let ast_id_map = AstIdMap::from_source(&syntax); + let block = syntax.descendants().find_map(ast::BlockExpr::cast).expect("no block"); + assert!(ast_id_map.ast_id_for_block(&block).is_none()); } } diff --git a/src/tools/rust-analyzer/crates/span/src/lib.rs b/src/tools/rust-analyzer/crates/span/src/lib.rs index f81648ac42c58..b81d08eed6d88 100644 --- a/src/tools/rust-analyzer/crates/span/src/lib.rs +++ b/src/tools/rust-analyzer/crates/span/src/lib.rs @@ -6,7 +6,10 @@ mod hygiene; mod map; pub use self::{ - ast_id::{AstIdMap, AstIdNode, ErasedFileAstId, FileAstId}, + ast_id::{ + AstIdMap, AstIdNode, ErasedFileAstId, FIXUP_ERASED_FILE_AST_ID_MARKER, FileAstId, + ROOT_ERASED_FILE_AST_ID, + }, hygiene::{SyntaxContext, Transparency}, map::{RealSpanMap, SpanMap}, }; @@ -15,19 +18,6 @@ pub use syntax::Edition; pub use text_size::{TextRange, TextSize}; pub use vfs::FileId; -// The first index is always the root node's AstId -/// The root ast id always points to the encompassing file, using this in spans is discouraged as -/// any range relative to it will be effectively absolute, ruining the entire point of anchored -/// relative text ranges. -pub const ROOT_ERASED_FILE_AST_ID: ErasedFileAstId = ErasedFileAstId::from_raw(0); - -/// FileId used as the span for syntax node fixups. Any Span containing this file id is to be -/// considered fake. -pub const FIXUP_ERASED_FILE_AST_ID_MARKER: ErasedFileAstId = - // we pick the second to last for this in case we ever consider making this a NonMaxU32, this - // is required to be stable for the proc-macro-server - ErasedFileAstId::from_raw(!0 - 1); - pub type Span = SpanData; impl Span { @@ -60,7 +50,7 @@ impl fmt::Debug for SpanData { if f.alternate() { fmt::Debug::fmt(&self.anchor.file_id.file_id().index(), f)?; f.write_char(':')?; - fmt::Debug::fmt(&self.anchor.ast_id.into_raw(), f)?; + write!(f, "{:#?}", self.anchor.ast_id)?; f.write_char('@')?; fmt::Debug::fmt(&self.range, f)?; f.write_char('#')?; @@ -85,7 +75,7 @@ impl fmt::Display for Span { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Debug::fmt(&self.anchor.file_id.file_id().index(), f)?; f.write_char(':')?; - fmt::Debug::fmt(&self.anchor.ast_id.into_raw(), f)?; + write!(f, "{:#?}", self.anchor.ast_id)?; f.write_char('@')?; fmt::Debug::fmt(&self.range, f)?; f.write_char('#')?; @@ -101,7 +91,7 @@ pub struct SpanAnchor { impl fmt::Debug for SpanAnchor { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_tuple("SpanAnchor").field(&self.file_id).field(&self.ast_id.into_raw()).finish() + f.debug_tuple("SpanAnchor").field(&self.file_id).field(&self.ast_id).finish() } } diff --git a/src/tools/rust-analyzer/crates/span/src/map.rs b/src/tools/rust-analyzer/crates/span/src/map.rs index cc7a886643a9b..f58201793da28 100644 --- a/src/tools/rust-analyzer/crates/span/src/map.rs +++ b/src/tools/rust-analyzer/crates/span/src/map.rs @@ -169,7 +169,7 @@ impl fmt::Display for RealSpanMap { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { writeln!(f, "RealSpanMap({:?}):", self.file_id)?; for span in self.pairs.iter() { - writeln!(f, "{}: {}", u32::from(span.0), span.1.into_raw())?; + writeln!(f, "{}: {:#?}", u32::from(span.0), span.1)?; } Ok(()) } diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/node_ext.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/node_ext.rs index dcf853427e530..f5530c5fffd20 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/ast/node_ext.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/ast/node_ext.rs @@ -30,6 +30,16 @@ impl ast::Name { pub fn text(&self) -> TokenText<'_> { text_of_first_token(self.syntax()) } + pub fn text_non_mutable(&self) -> &str { + fn first_token(green_ref: &GreenNodeData) -> &GreenTokenData { + green_ref.children().next().and_then(NodeOrToken::into_token).unwrap() + } + + match self.syntax().green() { + Cow::Borrowed(green_ref) => first_token(green_ref).text(), + Cow::Owned(_) => unreachable!(), + } + } } impl ast::NameRef { From cd1298a2798c19dcb768290e0968468be5afe974 Mon Sep 17 00:00:00 2001 From: Chayim Refael Friedman Date: Wed, 21 May 2025 13:13:34 +0300 Subject: [PATCH 11/56] Avoid referring to the item tree except in the def map Item tree IDs are very unstable (adding an item of a kind invalidates all following items of the same kind). Instead use ast ids, which, since the previous commit, are pretty stable. --- .../rust-analyzer/crates/hir-def/src/attr.rs | 158 ++++--- .../rust-analyzer/crates/hir-def/src/db.rs | 36 +- .../crates/hir-def/src/expr_store/expander.rs | 7 + .../crates/hir-def/src/expr_store/lower.rs | 19 +- .../crates/hir-def/src/expr_store/pretty.rs | 76 ++-- .../crates/hir-def/src/item_tree.rs | 42 +- .../crates/hir-def/src/item_tree/lower.rs | 2 +- .../crates/hir-def/src/item_tree/pretty.rs | 2 +- .../crates/hir-def/src/item_tree/tests.rs | 2 +- .../crates/hir-def/src/lang_item.rs | 2 +- .../rust-analyzer/crates/hir-def/src/lib.rs | 187 ++++---- .../crates/hir-def/src/nameres.rs | 2 - .../crates/hir-def/src/nameres/assoc.rs | 212 ++++++---- .../crates/hir-def/src/nameres/collector.rs | 176 ++++---- .../crates/hir-def/src/nameres/diagnostics.rs | 25 +- .../hir-def/src/nameres/path_resolution.rs | 34 +- .../crates/hir-def/src/resolver.rs | 36 +- .../crates/hir-def/src/signatures.rs | 400 +++++++++--------- .../rust-analyzer/crates/hir-def/src/src.rs | 106 +++-- .../crates/hir-def/src/visibility.rs | 82 ++-- .../crates/hir-expand/src/files.rs | 9 +- .../crates/hir-ty/src/chalk_db.rs | 2 +- .../hir-ty/src/diagnostics/decl_check.rs | 4 +- .../diagnostics/match_check/pat_analysis.rs | 2 +- .../rust-analyzer/crates/hir-ty/src/drop.rs | 2 +- .../crates/hir-ty/src/inhabitedness.rs | 2 +- .../crates/hir-ty/src/layout/adt.rs | 2 +- .../crates/hir-ty/src/mir/eval.rs | 9 +- .../crates/hir-ty/src/mir/eval/shim.rs | 7 +- .../crates/hir-ty/src/mir/lower.rs | 9 +- .../crates/hir-ty/src/mir/pretty.rs | 13 +- .../rust-analyzer/crates/hir-ty/src/tests.rs | 2 +- .../crates/hir-ty/src/tests/incremental.rs | 3 +- .../rust-analyzer/crates/hir-ty/src/utils.rs | 4 +- .../crates/hir-ty/src/variance.rs | 2 +- src/tools/rust-analyzer/crates/hir/src/lib.rs | 233 ++++------ .../hir/src/semantics/child_by_source.rs | 25 +- 37 files changed, 981 insertions(+), 955 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/attr.rs b/src/tools/rust-analyzer/crates/hir-def/src/attr.rs index bb6222b1d4648..a7328809a823b 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/attr.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/attr.rs @@ -14,6 +14,7 @@ use intern::{Symbol, sym}; use la_arena::{ArenaMap, Idx, RawIdx}; use mbe::DelimiterKind; use rustc_abi::ReprOptions; +use span::AstIdNode; use syntax::{ AstPtr, ast::{self, HasAttrs}, @@ -22,10 +23,10 @@ use triomphe::Arc; use tt::iter::{TtElement, TtIter}; use crate::{ - AdtId, AttrDefId, GenericParamId, HasModule, ItemTreeLoc, LocalFieldId, Lookup, MacroId, + AdtId, AstIdLoc, AttrDefId, GenericParamId, HasModule, LocalFieldId, Lookup, MacroId, VariantId, db::DefDatabase, - item_tree::{AttrOwner, FieldParent, ItemTreeNode}, + item_tree::AttrOwner, lang_item::LangItem, nameres::{ModuleOrigin, ModuleSource}, src::{HasChildSource, HasSource}, @@ -42,6 +43,15 @@ pub struct AttrsWithOwner { } impl Attrs { + pub fn new( + db: &dyn DefDatabase, + owner: &dyn ast::HasAttrs, + span_map: SpanMapRef<'_>, + cfg_options: &CfgOptions, + ) -> Self { + Attrs(RawAttrs::new_expanded(db, owner, span_map, cfg_options)) + } + pub fn get(&self, id: AttrId) -> Option<&Attr> { (**self).iter().find(|attr| attr.id == id) } @@ -94,44 +104,64 @@ impl Attrs { v: VariantId, ) -> Arc> { let _p = tracing::info_span!("fields_attrs_query").entered(); - // FIXME: There should be some proper form of mapping between item tree field ids and hir field ids let mut res = ArenaMap::default(); - let item_tree; - let (parent, fields, krate) = match v { + let (fields, file_id, krate) = match v { VariantId::EnumVariantId(it) => { let loc = it.lookup(db); let krate = loc.parent.lookup(db).container.krate; - item_tree = loc.id.item_tree(db); - let variant = &item_tree[loc.id.value]; - (FieldParent::EnumVariant(loc.id.value), &variant.fields, krate) + let source = loc.source(db); + (source.value.field_list(), source.file_id, krate) } VariantId::StructId(it) => { let loc = it.lookup(db); let krate = loc.container.krate; - item_tree = loc.id.item_tree(db); - let struct_ = &item_tree[loc.id.value]; - (FieldParent::Struct(loc.id.value), &struct_.fields, krate) + let source = loc.source(db); + (source.value.field_list(), source.file_id, krate) } VariantId::UnionId(it) => { let loc = it.lookup(db); let krate = loc.container.krate; - item_tree = loc.id.item_tree(db); - let union_ = &item_tree[loc.id.value]; - (FieldParent::Union(loc.id.value), &union_.fields, krate) + let source = loc.source(db); + ( + source.value.record_field_list().map(ast::FieldList::RecordFieldList), + source.file_id, + krate, + ) } }; + let Some(fields) = fields else { + return Arc::new(res); + }; let cfg_options = krate.cfg_options(db); - - let mut idx = 0; - for (id, _field) in fields.iter().enumerate() { - let attrs = item_tree.attrs(db, krate, AttrOwner::make_field_indexed(parent, id)); - if attrs.is_cfg_enabled(cfg_options) { - res.insert(Idx::from_raw(RawIdx::from(idx)), attrs); - idx += 1; + let span_map = db.span_map(file_id); + + match fields { + ast::FieldList::RecordFieldList(fields) => { + let mut idx = 0; + for field in fields.fields() { + let attrs = + Attrs(RawAttrs::new_expanded(db, &field, span_map.as_ref(), cfg_options)); + if attrs.is_cfg_enabled(cfg_options).is_ok() { + res.insert(Idx::from_raw(RawIdx::from(idx)), attrs); + idx += 1; + } + } + } + ast::FieldList::TupleFieldList(fields) => { + let mut idx = 0; + for field in fields.fields() { + let attrs = + Attrs(RawAttrs::new_expanded(db, &field, span_map.as_ref(), cfg_options)); + if attrs.is_cfg_enabled(cfg_options).is_ok() { + res.insert(Idx::from_raw(RawIdx::from(idx)), attrs); + idx += 1; + } + } } } + res.shrink_to_fit(); Arc::new(res) } } @@ -167,11 +197,10 @@ impl Attrs { } #[inline] - pub(crate) fn is_cfg_enabled(&self, cfg_options: &CfgOptions) -> bool { - match self.cfg() { - None => true, - Some(cfg) => cfg_options.check(&cfg) != Some(false), - } + pub(crate) fn is_cfg_enabled(&self, cfg_options: &CfgOptions) -> Result<(), CfgExpr> { + self.cfgs().try_for_each(|cfg| { + if cfg_options.check(&cfg) != Some(false) { Ok(()) } else { Err(cfg) } + }) } #[inline] @@ -488,12 +517,12 @@ impl AttrsWithOwner { pub(crate) fn attrs_query(db: &dyn DefDatabase, def: AttrDefId) -> Attrs { let _p = tracing::info_span!("attrs_query").entered(); // FIXME: this should use `Trace` to avoid duplication in `source_map` below - let raw_attrs = match def { + match def { AttrDefId::ModuleId(module) => { let def_map = module.def_map(db); let mod_data = &def_map[module.local_id]; - match mod_data.origin { + let raw_attrs = match mod_data.origin { ModuleOrigin::File { definition, declaration_tree_id, .. } => { let decl_attrs = declaration_tree_id .item_tree(db) @@ -515,34 +544,33 @@ impl AttrsWithOwner { let tree = db.block_item_tree(id); tree.raw_attrs(AttrOwner::TopLevel).clone() } - } - } - AttrDefId::FieldId(it) => { - return db.fields_attrs(it.parent)[it.local_id].clone(); + }; + Attrs::expand_cfg_attr(db, module.krate, raw_attrs) } - AttrDefId::EnumVariantId(it) => attrs_from_item_tree_loc(db, it), + AttrDefId::FieldId(it) => db.fields_attrs(it.parent)[it.local_id].clone(), + AttrDefId::EnumVariantId(it) => attrs_from_ast_id_loc(db, it), AttrDefId::AdtId(it) => match it { - AdtId::StructId(it) => attrs_from_item_tree_loc(db, it), - AdtId::EnumId(it) => attrs_from_item_tree_loc(db, it), - AdtId::UnionId(it) => attrs_from_item_tree_loc(db, it), + AdtId::StructId(it) => attrs_from_ast_id_loc(db, it), + AdtId::EnumId(it) => attrs_from_ast_id_loc(db, it), + AdtId::UnionId(it) => attrs_from_ast_id_loc(db, it), }, - AttrDefId::TraitId(it) => attrs_from_item_tree_loc(db, it), - AttrDefId::TraitAliasId(it) => attrs_from_item_tree_loc(db, it), + AttrDefId::TraitId(it) => attrs_from_ast_id_loc(db, it), + AttrDefId::TraitAliasId(it) => attrs_from_ast_id_loc(db, it), AttrDefId::MacroId(it) => match it { - MacroId::Macro2Id(it) => attrs_from_item_tree_loc(db, it), - MacroId::MacroRulesId(it) => attrs_from_item_tree_loc(db, it), - MacroId::ProcMacroId(it) => attrs_from_item_tree_loc(db, it), + MacroId::Macro2Id(it) => attrs_from_ast_id_loc(db, it), + MacroId::MacroRulesId(it) => attrs_from_ast_id_loc(db, it), + MacroId::ProcMacroId(it) => attrs_from_ast_id_loc(db, it), }, - AttrDefId::ImplId(it) => attrs_from_item_tree_loc(db, it), - AttrDefId::ConstId(it) => attrs_from_item_tree_loc(db, it), - AttrDefId::StaticId(it) => attrs_from_item_tree_loc(db, it), - AttrDefId::FunctionId(it) => attrs_from_item_tree_loc(db, it), - AttrDefId::TypeAliasId(it) => attrs_from_item_tree_loc(db, it), + AttrDefId::ImplId(it) => attrs_from_ast_id_loc(db, it), + AttrDefId::ConstId(it) => attrs_from_ast_id_loc(db, it), + AttrDefId::StaticId(it) => attrs_from_ast_id_loc(db, it), + AttrDefId::FunctionId(it) => attrs_from_ast_id_loc(db, it), + AttrDefId::TypeAliasId(it) => attrs_from_ast_id_loc(db, it), AttrDefId::GenericParamId(it) => match it { GenericParamId::ConstParamId(it) => { let src = it.parent().child_source(db); // FIXME: We should be never getting `None` here. - return Attrs(match src.value.get(it.local_id()) { + Attrs(match src.value.get(it.local_id()) { Some(val) => RawAttrs::new_expanded( db, val, @@ -550,12 +578,12 @@ impl AttrsWithOwner { def.krate(db).cfg_options(db), ), None => RawAttrs::EMPTY, - }); + }) } GenericParamId::TypeParamId(it) => { let src = it.parent().child_source(db); // FIXME: We should be never getting `None` here. - return Attrs(match src.value.get(it.local_id()) { + Attrs(match src.value.get(it.local_id()) { Some(val) => RawAttrs::new_expanded( db, val, @@ -563,12 +591,12 @@ impl AttrsWithOwner { def.krate(db).cfg_options(db), ), None => RawAttrs::EMPTY, - }); + }) } GenericParamId::LifetimeParamId(it) => { let src = it.parent.child_source(db); // FIXME: We should be never getting `None` here. - return Attrs(match src.value.get(it.local_id) { + Attrs(match src.value.get(it.local_id) { Some(val) => RawAttrs::new_expanded( db, val, @@ -576,16 +604,13 @@ impl AttrsWithOwner { def.krate(db).cfg_options(db), ), None => RawAttrs::EMPTY, - }); + }) } }, - AttrDefId::ExternBlockId(it) => attrs_from_item_tree_loc(db, it), - AttrDefId::ExternCrateId(it) => attrs_from_item_tree_loc(db, it), - AttrDefId::UseId(it) => attrs_from_item_tree_loc(db, it), - }; - - let attrs = raw_attrs.expand_cfg_attr(db, def.krate(db)); - Attrs(attrs) + AttrDefId::ExternBlockId(it) => attrs_from_ast_id_loc(db, it), + AttrDefId::ExternCrateId(it) => attrs_from_ast_id_loc(db, it), + AttrDefId::UseId(it) => attrs_from_ast_id_loc(db, it), + } } pub fn source_map(&self, db: &dyn DefDatabase) -> AttrSourceMap { @@ -787,14 +812,15 @@ fn any_has_attrs<'db>( id.lookup(db).source(db).map(ast::AnyHasAttrs::new) } -fn attrs_from_item_tree_loc<'db, N: ItemTreeNode>( +fn attrs_from_ast_id_loc<'db, N: AstIdNode + HasAttrs>( db: &(dyn DefDatabase + 'db), - lookup: impl Lookup>, -) -> RawAttrs { - let id = lookup.lookup(db).item_tree_id(); - let tree = id.item_tree(db); - let attr_owner = N::attr_owner(id.value); - tree.raw_attrs(attr_owner).clone() + lookup: impl Lookup + HasModule>, +) -> Attrs { + let loc = lookup.lookup(db); + let source = loc.source(db); + let span_map = db.span_map(source.file_id); + let cfg_options = loc.krate(db).cfg_options(db); + Attrs(RawAttrs::new_expanded(db, &source.value, span_map.as_ref(), cfg_options)) } pub(crate) fn fields_attrs_source_map( diff --git a/src/tools/rust-analyzer/crates/hir-def/src/db.rs b/src/tools/rust-analyzer/crates/hir-def/src/db.rs index 4a9a3b12cfab4..362c0daa9bbe9 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/db.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/db.rs @@ -1,8 +1,11 @@ //! Defines database & queries for name resolution. use base_db::{Crate, RootQueryDb, SourceDatabase}; use either::Either; -use hir_expand::{EditionedFileId, HirFileId, MacroCallId, MacroDefId, db::ExpandDatabase}; -use intern::sym; +use hir_expand::{ + EditionedFileId, HirFileId, InFile, Lookup, MacroCallId, MacroDefId, MacroDefKind, + db::ExpandDatabase, +}; +use intern::{Symbol, sym}; use la_arena::ArenaMap; use syntax::{AstPtr, ast}; use thin_vec::ThinVec; @@ -11,8 +14,8 @@ use triomphe::Arc; use crate::{ AttrDefId, BlockId, BlockLoc, ConstId, ConstLoc, DefWithBodyId, EnumId, EnumLoc, EnumVariantId, EnumVariantLoc, ExternBlockId, ExternBlockLoc, ExternCrateId, ExternCrateLoc, FunctionId, - FunctionLoc, GenericDefId, ImplId, ImplLoc, LocalFieldId, Macro2Id, Macro2Loc, MacroId, - MacroRulesId, MacroRulesLoc, MacroRulesLocFlags, ProcMacroId, ProcMacroLoc, StaticId, + FunctionLoc, GenericDefId, ImplId, ImplLoc, LocalFieldId, Macro2Id, Macro2Loc, MacroExpander, + MacroId, MacroRulesId, MacroRulesLoc, MacroRulesLocFlags, ProcMacroId, ProcMacroLoc, StaticId, StaticLoc, StructId, StructLoc, TraitAliasId, TraitAliasLoc, TraitId, TraitLoc, TypeAliasId, TypeAliasLoc, UnionId, UnionLoc, UseId, UseLoc, VariantId, attr::{Attrs, AttrsWithOwner}, @@ -123,6 +126,8 @@ pub trait DefDatabase: InternDatabase + ExpandDatabase + SourceDatabase { id: VariantId, ) -> (Arc, Arc); + // FIXME: Should we make this transparent? The only unstable thing in `enum_variants_with_diagnostics()` + // is ast ids, and ast ids are pretty stable now. #[salsa::tracked] fn enum_variants(&self, id: EnumId) -> Arc { self.enum_variants_with_diagnostics(id).0 @@ -263,6 +268,9 @@ pub trait DefDatabase: InternDatabase + ExpandDatabase + SourceDatabase { e: TypeAliasId, ) -> (Arc, Arc); + #[salsa::invoke(crate::signatures::extern_block_abi_query)] + fn extern_block_abi(&self, extern_block: ExternBlockId) -> Option; + // endregion:data #[salsa::invoke(Body::body_with_source_map_query)] @@ -399,10 +407,6 @@ fn crate_supports_no_std(db: &dyn DefDatabase, crate_id: Crate) -> bool { } fn macro_def(db: &dyn DefDatabase, id: MacroId) -> MacroDefId { - use hir_expand::InFile; - - use crate::{Lookup, MacroDefKind, MacroExpander}; - let kind = |expander, file_id, m| { let in_file = InFile::new(file_id, m); match expander { @@ -418,11 +422,9 @@ fn macro_def(db: &dyn DefDatabase, id: MacroId) -> MacroDefId { MacroId::Macro2Id(it) => { let loc: Macro2Loc = it.lookup(db); - let item_tree = loc.id.item_tree(db); - let makro = &item_tree[loc.id.value]; MacroDefId { krate: loc.container.krate, - kind: kind(loc.expander, loc.id.file_id(), makro.ast_id.upcast()), + kind: kind(loc.expander, loc.id.file_id, loc.id.value.upcast()), local_inner: false, allow_internal_unsafe: loc.allow_internal_unsafe, edition: loc.edition, @@ -431,11 +433,9 @@ fn macro_def(db: &dyn DefDatabase, id: MacroId) -> MacroDefId { MacroId::MacroRulesId(it) => { let loc: MacroRulesLoc = it.lookup(db); - let item_tree = loc.id.item_tree(db); - let makro = &item_tree[loc.id.value]; MacroDefId { krate: loc.container.krate, - kind: kind(loc.expander, loc.id.file_id(), makro.ast_id.upcast()), + kind: kind(loc.expander, loc.id.file_id, loc.id.value.upcast()), local_inner: loc.flags.contains(MacroRulesLocFlags::LOCAL_INNER), allow_internal_unsafe: loc .flags @@ -446,15 +446,9 @@ fn macro_def(db: &dyn DefDatabase, id: MacroId) -> MacroDefId { MacroId::ProcMacroId(it) => { let loc = it.lookup(db); - let item_tree = loc.id.item_tree(db); - let makro = &item_tree[loc.id.value]; MacroDefId { krate: loc.container.krate, - kind: MacroDefKind::ProcMacro( - InFile::new(loc.id.file_id(), makro.ast_id), - loc.expander, - loc.kind, - ), + kind: MacroDefKind::ProcMacro(loc.id, loc.expander, loc.kind), local_inner: false, allow_internal_unsafe: false, edition: loc.edition, diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/expander.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/expander.rs index 3823fb5a1e755..23b9712d1e6c1 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/expander.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/expander.rs @@ -6,6 +6,7 @@ use base_db::Crate; use cfg::CfgOptions; use drop_bomb::DropBomb; use hir_expand::AstId; +use hir_expand::span_map::SpanMapRef; use hir_expand::{ ExpandError, ExpandErrorKind, ExpandResult, HirFileId, InFile, Lookup, MacroCallId, eager::EagerCallBackFn, mod_path::ModPath, span_map::SpanMap, @@ -223,9 +224,15 @@ impl Expander { } } + #[inline] pub(super) fn ast_id_map(&self) -> &AstIdMap { &self.ast_id_map } + + #[inline] + pub(super) fn span_map(&self) -> SpanMapRef<'_> { + self.span_map.as_ref() + } } #[derive(Debug)] diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs index b7a482a85dbbc..89eeaf00bc3d0 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs @@ -10,9 +10,10 @@ use std::mem; use cfg::CfgOptions; use either::Either; use hir_expand::{ - HirFileId, InFile, Lookup, MacroDefId, + HirFileId, InFile, MacroDefId, mod_path::tool_path, name::{AsName, Name}, + span_map::SpanMapRef, }; use intern::{Symbol, sym}; use rustc_hash::FxHashMap; @@ -30,8 +31,8 @@ use triomphe::Arc; use tt::TextRange; use crate::{ - AdtId, BlockId, BlockLoc, DefWithBodyId, FunctionId, GenericDefId, ImplId, ItemTreeLoc, - MacroId, ModuleDefId, ModuleId, TraitAliasId, TraitId, TypeAliasId, UnresolvedMacro, + AdtId, BlockId, BlockLoc, DefWithBodyId, FunctionId, GenericDefId, ImplId, MacroId, + ModuleDefId, ModuleId, TraitAliasId, TraitId, TypeAliasId, UnresolvedMacro, builtin_type::BuiltinUint, db::DefDatabase, expr_store::{ @@ -564,6 +565,11 @@ impl ExprCollector<'_> { } } + #[inline] + pub(crate) fn span_map(&self) -> SpanMapRef<'_> { + self.expander.span_map() + } + pub fn lower_lifetime_ref(&mut self, lifetime: ast::Lifetime) -> LifetimeRefId { // FIXME: Keyword check? let lifetime_ref = match &*lifetime.text() { @@ -2244,11 +2250,8 @@ impl ExprCollector<'_> { match resolved.take_values() { Some(ModuleDefId::ConstId(_)) => (None, Pat::Path(name.into())), Some(ModuleDefId::EnumVariantId(variant)) - if { - let loc = variant.lookup(self.db); - let tree = loc.item_tree_id().item_tree(self.db); - tree[loc.id.value].shape != FieldsShape::Record - } => + // FIXME: This can cause a cycle if the user is writing invalid code + if self.db.variant_fields(variant.into()).shape != FieldsShape::Record => { (None, Pat::Path(name.into())) } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/pretty.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/pretty.rs index f12a9b7a5445b..7b452721dfe2b 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/pretty.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/pretty.rs @@ -9,9 +9,10 @@ use std::{ use hir_expand::{Lookup, mod_path::PathKind}; use itertools::Itertools; use span::Edition; +use syntax::ast::HasName; use crate::{ - AdtId, DefWithBodyId, GenericDefId, ItemTreeLoc, TypeParamId, VariantId, + AdtId, DefWithBodyId, GenericDefId, TypeParamId, VariantId, expr_store::path::{GenericArg, GenericArgs}, hir::{ Array, BindingAnnotation, CaptureBy, ClosureKind, Literal, Movability, Statement, @@ -19,6 +20,7 @@ use crate::{ }, lang_item::LangItemTarget, signatures::{FnFlags, FunctionSignature, StructSignature}, + src::HasSource, type_ref::{ConstRef, LifetimeRef, Mutability, TraitBoundModifier, TypeBound, UseArgRef}, }; use crate::{LifetimeParamId, signatures::StructFlags}; @@ -48,6 +50,17 @@ pub enum LineFormat { Indentation, } +fn item_name(db: &dyn DefDatabase, id: Id, default: &str) -> String +where + Id: Lookup, + Loc: HasSource, + Loc::Value: ast::HasName, +{ + let loc = id.lookup(db); + let source = loc.source(db); + source.value.name().map_or_else(|| default.to_owned(), |name| name.to_string()) +} + pub fn print_body_hir( db: &dyn DefDatabase, body: &Body, @@ -55,31 +68,14 @@ pub fn print_body_hir( edition: Edition, ) -> String { let header = match owner { - DefWithBodyId::FunctionId(it) => { - it.lookup(db).id.resolved(db, |it| format!("fn {}", it.name.display(db, edition))) - } - DefWithBodyId::StaticId(it) => it - .lookup(db) - .id - .resolved(db, |it| format!("static {} = ", it.name.display(db, edition))), - DefWithBodyId::ConstId(it) => it.lookup(db).id.resolved(db, |it| { - format!( - "const {} = ", - match &it.name { - Some(name) => name.display(db, edition).to_string(), - None => "_".to_owned(), - } - ) - }), - DefWithBodyId::VariantId(it) => { - let loc = it.lookup(db); - let enum_loc = loc.parent.lookup(db); - format!( - "enum {}::{}", - enum_loc.id.item_tree(db)[enum_loc.id.value].name.display(db, edition), - loc.id.item_tree(db)[loc.id.value].name.display(db, edition), - ) - } + DefWithBodyId::FunctionId(it) => format!("fn {}", item_name(db, it, "")), + DefWithBodyId::StaticId(it) => format!("static {} = ", item_name(db, it, "")), + DefWithBodyId::ConstId(it) => format!("const {} = ", item_name(db, it, "_")), + DefWithBodyId::VariantId(it) => format!( + "enum {}::{}", + item_name(db, it.lookup(db).parent, ""), + item_name(db, it, "") + ), }; let mut p = Printer { @@ -116,22 +112,13 @@ pub fn print_body_hir( pub fn print_variant_body_hir(db: &dyn DefDatabase, owner: VariantId, edition: Edition) -> String { let header = match owner { - VariantId::StructId(it) => { - it.lookup(db).id.resolved(db, |it| format!("struct {}", it.name.display(db, edition))) - } - VariantId::EnumVariantId(enum_variant_id) => { - let loc = enum_variant_id.lookup(db); - let enum_loc = loc.parent.lookup(db); - format!( - "enum {}::{}", - enum_loc.id.item_tree(db)[enum_loc.id.value].name.display(db, edition), - loc.id.item_tree(db)[loc.id.value].name.display(db, edition), - ) - } - VariantId::UnionId(union_id) => union_id - .lookup(db) - .id - .resolved(db, |it| format!("union {}", it.name.display(db, edition))), + VariantId::StructId(it) => format!("struct {}", item_name(db, it, "")), + VariantId::EnumVariantId(it) => format!( + "enum {}::{}", + item_name(db, it.lookup(db).parent, ""), + item_name(db, it, "") + ), + VariantId::UnionId(it) => format!("union {}", item_name(db, it, "")), }; let fields = db.variant_fields(owner); @@ -1089,10 +1076,7 @@ impl Printer<'_> { w!(self, "builtin#lang("); macro_rules! write_name { ($it:ident) => {{ - let loc = $it.lookup(self.db); - let tree = loc.item_tree_id().item_tree(self.db); - let name = &tree[loc.id.value].name; - w!(self, "{}", name.display(self.db, self.edition)); + w!(self, "{}", item_name(self.db, $it, "")); }}; } match *it { diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs index 1b97eb72b6f20..65dc35337a52f 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs @@ -46,7 +46,7 @@ use std::{ use ast::{AstNode, StructKind}; use base_db::Crate; use hir_expand::{ - ExpandTo, HirFileId, InFile, + ExpandTo, HirFileId, attrs::RawAttrs, mod_path::{ModPath, PathKind}, name::Name, @@ -62,6 +62,8 @@ use triomphe::Arc; use crate::{BlockId, Lookup, attr::Attrs, db::DefDatabase}; +pub(crate) use crate::item_tree::lower::{lower_use_tree, visibility_from_ast}; + #[derive(Copy, Clone, Eq, PartialEq)] pub struct RawVisibilityId(u32); @@ -446,6 +448,7 @@ impl TreeId { } } + #[inline] pub fn file_id(self) -> HirFileId { self.file } @@ -878,43 +881,6 @@ pub struct Macro2 { pub ast_id: FileAstId, } -impl Use { - /// Maps a `UseTree` contained in this import back to its AST node. - pub fn use_tree_to_ast( - &self, - db: &dyn DefDatabase, - file_id: HirFileId, - index: Idx, - ) -> ast::UseTree { - // Re-lower the AST item and get the source map. - // Note: The AST unwraps are fine, since if they fail we should have never obtained `index`. - let ast = InFile::new(file_id, self.ast_id).to_node(db); - let ast_use_tree = ast.use_tree().expect("missing `use_tree`"); - let (_, source_map) = lower::lower_use_tree(db, ast_use_tree, &mut |range| { - db.span_map(file_id).span_for_range(range).ctx - }) - .expect("failed to lower use tree"); - source_map[index].clone() - } - - /// Maps a `UseTree` contained in this import back to its AST node. - pub fn use_tree_source_map( - &self, - db: &dyn DefDatabase, - file_id: HirFileId, - ) -> Arena { - // Re-lower the AST item and get the source map. - // Note: The AST unwraps are fine, since if they fail we should have never obtained `index`. - let ast = InFile::new(file_id, self.ast_id).to_node(db); - let ast_use_tree = ast.use_tree().expect("missing `use_tree`"); - lower::lower_use_tree(db, ast_use_tree, &mut |range| { - db.span_map(file_id).span_for_range(range).ctx - }) - .expect("failed to lower use tree") - .1 - } -} - #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum ImportKind { /// The `ModPath` is imported normally. diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs index b490e1683c01f..57765427693dd 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs @@ -626,7 +626,7 @@ fn private_vis() -> RawVisibility { ) } -fn visibility_from_ast( +pub(crate) fn visibility_from_ast( db: &dyn DefDatabase, node: Option, span_for_range: &mut dyn FnMut(::tt::TextRange) -> SyntaxContext, diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs index 51172c0a1ee31..8ff14751c671e 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs @@ -258,7 +258,7 @@ impl Printer<'_> { let Enum { name, visibility, variants, ast_id } = &self.tree[it]; self.print_ast_id(ast_id.erase()); self.print_visibility(*visibility); - w!(self, "enum {}", name.display(self.db, self.edition)); + w!(self, "enum {} {{", name.display(self.db, self.edition)); let edition = self.edition; self.indented(|this| { for variant in FileItemTreeId::range_iter(variants.clone()) { diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/tests.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/tests.rs index abfff283ef648..7a85e8d175e60 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/tests.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/tests.rs @@ -147,7 +147,7 @@ enum E { } // AstId: Enum[7FF8, 0] - pub(self) enum E + pub(self) enum E { // AstId: Variant[C717, 0] #[doc = " comment on Unit"] Unit, diff --git a/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs b/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs index 4ad44775ea141..1614ef0da435c 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs @@ -125,7 +125,7 @@ pub fn crate_lang_items(db: &dyn DefDatabase, krate: Crate) -> Option { lang_items.collect_lang_item(db, e, LangItemTarget::EnumId); - db.enum_variants(e).variants.iter().for_each(|&(id, _)| { + db.enum_variants(e).variants.iter().for_each(|&(id, _, _)| { lang_items.collect_lang_item(db, id, LangItemTarget::EnumVariant); }); } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs index 1e8859a9cc9c5..dcc18666a57d1 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs @@ -74,12 +74,11 @@ use hir_expand::{ name::Name, proc_macro::{CustomProcMacroExpander, ProcMacroKind}, }; -use item_tree::ExternBlock; use la_arena::Idx; use nameres::DefMap; use span::{AstIdNode, Edition, FileAstId, SyntaxContext}; use stdx::impl_from; -use syntax::ast; +use syntax::{AstNode, ast}; pub use hir_expand::{Intern, Lookup, tt}; @@ -88,10 +87,6 @@ use crate::{ builtin_type::BuiltinType, db::DefDatabase, hir::generics::{LocalLifetimeParamId, LocalTypeOrConstParamId}, - item_tree::{ - Const, Enum, ExternCrate, Function, Impl, ItemTreeId, ItemTreeNode, Macro2, MacroRules, - Static, Struct, Trait, TraitAlias, TypeAlias, Union, Use, Variant, - }, nameres::{LocalDefMap, block_def_map, crate_def_map, crate_local_def_map}, signatures::VariantFields, }; @@ -113,70 +108,110 @@ pub struct ImportPathConfig { } #[derive(Debug)] -pub struct ItemLoc { +pub struct ItemLoc { pub container: ModuleId, - pub id: ItemTreeId, + pub id: AstId, } -impl Clone for ItemLoc { +impl Clone for ItemLoc { fn clone(&self) -> Self { *self } } -impl Copy for ItemLoc {} +impl Copy for ItemLoc {} -impl PartialEq for ItemLoc { +impl PartialEq for ItemLoc { fn eq(&self, other: &Self) -> bool { self.container == other.container && self.id == other.id } } -impl Eq for ItemLoc {} +impl Eq for ItemLoc {} -impl Hash for ItemLoc { +impl Hash for ItemLoc { fn hash(&self, state: &mut H) { self.container.hash(state); self.id.hash(state); } } +impl HasModule for ItemLoc { + #[inline] + fn module(&self, _db: &dyn DefDatabase) -> ModuleId { + self.container + } +} + #[derive(Debug)] -pub struct AssocItemLoc { +pub struct AssocItemLoc { pub container: ItemContainerId, - pub id: ItemTreeId, + pub id: AstId, } -impl Clone for AssocItemLoc { +impl Clone for AssocItemLoc { fn clone(&self) -> Self { *self } } -impl Copy for AssocItemLoc {} +impl Copy for AssocItemLoc {} -impl PartialEq for AssocItemLoc { +impl PartialEq for AssocItemLoc { fn eq(&self, other: &Self) -> bool { self.container == other.container && self.id == other.id } } -impl Eq for AssocItemLoc {} +impl Eq for AssocItemLoc {} -impl Hash for AssocItemLoc { +impl Hash for AssocItemLoc { fn hash(&self, state: &mut H) { self.container.hash(state); self.id.hash(state); } } -pub trait ItemTreeLoc { +impl HasModule for AssocItemLoc { + #[inline] + fn module(&self, db: &dyn DefDatabase) -> ModuleId { + self.container.module(db) + } +} + +pub trait AstIdLoc { type Container; - type Id; - fn item_tree_id(&self) -> ItemTreeId; + type Ast: AstNode; + fn ast_id(&self) -> AstId; fn container(&self) -> Self::Container; } +impl AstIdLoc for ItemLoc { + type Container = ModuleId; + type Ast = N; + #[inline] + fn ast_id(&self) -> AstId { + self.id + } + #[inline] + fn container(&self) -> Self::Container { + self.container + } +} + +impl AstIdLoc for AssocItemLoc { + type Container = ItemContainerId; + type Ast = N; + #[inline] + fn ast_id(&self) -> AstId { + self.id + } + #[inline] + fn container(&self) -> Self::Container { + self.container + } +} + macro_rules! impl_intern { ($id:ident, $loc:ident, $intern:ident, $lookup:ident) => { impl_intern_key!($id, $loc); @@ -186,74 +221,68 @@ macro_rules! impl_intern { macro_rules! impl_loc { ($loc:ident, $id:ident: $id_ty:ident, $container:ident: $container_type:ident) => { - impl ItemTreeLoc for $loc { + impl AstIdLoc for $loc { type Container = $container_type; - type Id = $id_ty; - fn item_tree_id(&self) -> ItemTreeId { + type Ast = ast::$id_ty; + fn ast_id(&self) -> AstId { self.$id } fn container(&self) -> Self::Container { self.$container } } + + impl HasModule for $loc { + #[inline] + fn module(&self, db: &dyn DefDatabase) -> ModuleId { + self.$container.module(db) + } + } }; } -type FunctionLoc = AssocItemLoc; +type FunctionLoc = AssocItemLoc; impl_intern!(FunctionId, FunctionLoc, intern_function, lookup_intern_function); -impl_loc!(FunctionLoc, id: Function, container: ItemContainerId); -type StructLoc = ItemLoc; +type StructLoc = ItemLoc; impl_intern!(StructId, StructLoc, intern_struct, lookup_intern_struct); -impl_loc!(StructLoc, id: Struct, container: ModuleId); -pub type UnionLoc = ItemLoc; +pub type UnionLoc = ItemLoc; impl_intern!(UnionId, UnionLoc, intern_union, lookup_intern_union); -impl_loc!(UnionLoc, id: Union, container: ModuleId); -pub type EnumLoc = ItemLoc; +pub type EnumLoc = ItemLoc; impl_intern!(EnumId, EnumLoc, intern_enum, lookup_intern_enum); -impl_loc!(EnumLoc, id: Enum, container: ModuleId); -type ConstLoc = AssocItemLoc; +type ConstLoc = AssocItemLoc; impl_intern!(ConstId, ConstLoc, intern_const, lookup_intern_const); -impl_loc!(ConstLoc, id: Const, container: ItemContainerId); -pub type StaticLoc = AssocItemLoc; +pub type StaticLoc = AssocItemLoc; impl_intern!(StaticId, StaticLoc, intern_static, lookup_intern_static); -impl_loc!(StaticLoc, id: Static, container: ItemContainerId); -pub type TraitLoc = ItemLoc; +pub type TraitLoc = ItemLoc; impl_intern!(TraitId, TraitLoc, intern_trait, lookup_intern_trait); -impl_loc!(TraitLoc, id: Trait, container: ModuleId); -pub type TraitAliasLoc = ItemLoc; +pub type TraitAliasLoc = ItemLoc; impl_intern!(TraitAliasId, TraitAliasLoc, intern_trait_alias, lookup_intern_trait_alias); -impl_loc!(TraitAliasLoc, id: TraitAlias, container: ModuleId); -type TypeAliasLoc = AssocItemLoc; +type TypeAliasLoc = AssocItemLoc; impl_intern!(TypeAliasId, TypeAliasLoc, intern_type_alias, lookup_intern_type_alias); -impl_loc!(TypeAliasLoc, id: TypeAlias, container: ItemContainerId); -type ImplLoc = ItemLoc; +type ImplLoc = ItemLoc; impl_intern!(ImplId, ImplLoc, intern_impl, lookup_intern_impl); -impl_loc!(ImplLoc, id: Impl, container: ModuleId); -type UseLoc = ItemLoc; +type UseLoc = ItemLoc; impl_intern!(UseId, UseLoc, intern_use, lookup_intern_use); -impl_loc!(UseLoc, id: Use, container: ModuleId); -type ExternCrateLoc = ItemLoc; +type ExternCrateLoc = ItemLoc; impl_intern!(ExternCrateId, ExternCrateLoc, intern_extern_crate, lookup_intern_extern_crate); -impl_loc!(ExternCrateLoc, id: ExternCrate, container: ModuleId); -type ExternBlockLoc = ItemLoc; +type ExternBlockLoc = ItemLoc; impl_intern!(ExternBlockId, ExternBlockLoc, intern_extern_block, lookup_intern_extern_block); -impl_loc!(ExternBlockLoc, id: ExternBlock, container: ModuleId); #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct EnumVariantLoc { - pub id: ItemTreeId, + pub id: AstId, pub parent: EnumId, pub index: u32, } @@ -262,18 +291,18 @@ impl_loc!(EnumVariantLoc, id: Variant, parent: EnumId); #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct Macro2Loc { pub container: ModuleId, - pub id: ItemTreeId, + pub id: AstId, pub expander: MacroExpander, pub allow_internal_unsafe: bool, pub edition: Edition, } impl_intern!(Macro2Id, Macro2Loc, intern_macro2, lookup_intern_macro2); -impl_loc!(Macro2Loc, id: Macro2, container: ModuleId); +impl_loc!(Macro2Loc, id: MacroDef, container: ModuleId); #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct MacroRulesLoc { pub container: ModuleId, - pub id: ItemTreeId, + pub id: AstId, pub expander: MacroExpander, pub flags: MacroRulesLocFlags, pub edition: Edition, @@ -301,13 +330,13 @@ pub enum MacroExpander { #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct ProcMacroLoc { pub container: CrateRootModuleId, - pub id: ItemTreeId, + pub id: AstId, pub expander: CustomProcMacroExpander, pub kind: ProcMacroKind, pub edition: Edition, } impl_intern!(ProcMacroId, ProcMacroLoc, intern_proc_macro, lookup_intern_proc_macro); -impl_loc!(ProcMacroLoc, id: Function, container: CrateRootModuleId); +impl_loc!(ProcMacroLoc, id: Fn, container: CrateRootModuleId); #[derive(Debug, Hash, PartialEq, Eq, Clone)] pub struct BlockLoc { @@ -338,6 +367,18 @@ impl CrateRootModuleId { } } +impl HasModule for CrateRootModuleId { + #[inline] + fn module(&self, _db: &dyn DefDatabase) -> ModuleId { + ModuleId { krate: self.krate, block: None, local_id: DefMap::ROOT } + } + + #[inline] + fn krate(&self, _db: &dyn DefDatabase) -> Crate { + self.krate + } +} + impl PartialEq for CrateRootModuleId { fn eq(&self, other: &ModuleId) -> bool { other.block.is_none() && other.local_id == DefMap::ROOT && self.krate == other.krate @@ -466,6 +507,13 @@ impl ModuleId { } } +impl HasModule for ModuleId { + #[inline] + fn module(&self, _db: &dyn DefDatabase) -> ModuleId { + *self + } +} + /// An ID of a module, **local** to a `DefMap`. pub type LocalModuleId = Idx; @@ -642,15 +690,10 @@ impl GeneralConstId { pub fn name(self, db: &dyn DefDatabase) -> String { match self { GeneralConstId::StaticId(it) => { - let loc = it.lookup(db); - let tree = loc.item_tree_id().item_tree(db); - let name = tree[loc.id.value].name.display(db, Edition::CURRENT); - name.to_string() + db.static_signature(it).name.display(db, Edition::CURRENT).to_string() } GeneralConstId::ConstId(const_id) => { - let loc = const_id.lookup(db); - let tree = loc.item_tree_id().item_tree(db); - tree[loc.id.value].name.as_ref().map_or_else( + db.const_signature(const_id).name.as_ref().map_or_else( || "_".to_owned(), |name| name.display(db, Edition::CURRENT).to_string(), ) @@ -768,8 +811,8 @@ impl GenericDefId { GenericDefId::TraitId(it) => file_id_and_params_of_item_loc(db, it), GenericDefId::TraitAliasId(it) => file_id_and_params_of_item_loc(db, it), GenericDefId::ImplId(it) => file_id_and_params_of_item_loc(db, it), - GenericDefId::ConstId(it) => (it.lookup(db).id.file_id(), None), - GenericDefId::StaticId(it) => (it.lookup(db).id.file_id(), None), + GenericDefId::ConstId(it) => (it.lookup(db).id.file_id, None), + GenericDefId::StaticId(it) => (it.lookup(db).id.file_id, None), } } @@ -935,9 +978,9 @@ impl VariantId { pub fn file_id(self, db: &dyn DefDatabase) -> HirFileId { match self { - VariantId::EnumVariantId(it) => it.lookup(db).id.file_id(), - VariantId::StructId(it) => it.lookup(db).id.file_id(), - VariantId::UnionId(it) => it.lookup(db).id.file_id(), + VariantId::EnumVariantId(it) => it.lookup(db).id.file_id, + VariantId::StructId(it) => it.lookup(db).id.file_id, + VariantId::UnionId(it) => it.lookup(db).id.file_id, } } @@ -977,7 +1020,7 @@ pub trait HasModule { impl HasModule for ItemId where - N: ItemTreeNode, + N: AstIdNode, ItemId: Lookup> + Copy, { #[inline] @@ -1003,7 +1046,7 @@ where #[inline] fn module_for_assoc_item_loc<'db>( db: &(dyn 'db + DefDatabase), - id: impl Lookup>, + id: impl Lookup>, ) -> ModuleId { id.lookup(db).container.module(db) } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs index f337f83156a96..c908e457540b3 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs @@ -171,12 +171,10 @@ pub struct DefMap { /// ExternCrateId being None implies it being imported from the general prelude import. macro_use_prelude: FxHashMap)>, - // FIXME: AstId's are fairly unstable /// Tracks which custom derives are in scope for an item, to allow resolution of derive helper /// attributes. // FIXME: Figure out a better way for the IDE layer to resolve these? derive_helpers_in_scope: FxHashMap, Vec<(Name, MacroId, MacroCallId)>>, - // FIXME: AstId's are fairly unstable /// A mapping from [`hir_expand::MacroDefId`] to [`crate::MacroId`]. pub macro_def_to_macro_id: FxHashMap, diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/assoc.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/assoc.rs index 86225d33b4e16..cf123d14f502a 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/assoc.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/assoc.rs @@ -1,14 +1,28 @@ //! Expansion of associated items -use hir_expand::{AstId, InFile, Intern, Lookup, MacroCallKind, MacroDefKind, name::Name}; -use syntax::ast; +use std::mem; + +use cfg::CfgOptions; +use hir_expand::{ + AstId, ExpandTo, HirFileId, InFile, Intern, Lookup, MacroCallKind, MacroDefKind, + mod_path::ModPath, + name::{AsName, Name}, + span_map::SpanMap, +}; +use intern::Interned; +use span::AstIdMap; +use syntax::{ + AstNode, + ast::{self, HasModuleItem, HasName}, +}; +use thin_vec::ThinVec; use triomphe::Arc; use crate::{ AssocItemId, AstIdWithPath, ConstLoc, FunctionId, FunctionLoc, ImplId, ItemContainerId, ItemLoc, MacroCallId, ModuleId, TraitId, TypeAliasId, TypeAliasLoc, + attr::Attrs, db::DefDatabase, - item_tree::{AssocItem, ItemTree, ItemTreeId, MacroCall, ModItem, TreeId}, macro_call_as_call_id, nameres::{ DefMap, LocalDefMap, MacroSubNs, @@ -20,9 +34,8 @@ use crate::{ #[derive(Debug, Clone, PartialEq, Eq)] pub struct TraitItems { pub items: Box<[(Name, AssocItemId)]>, - // box it as the vec is usually empty anyways - // FIXME: AstIds are rather unstable... - pub macro_calls: Option, MacroCallId)>>>, + // `ThinVec` as the vec is usually empty anyways + pub macro_calls: ThinVec<(AstId, MacroCallId)>, } impl TraitItems { @@ -35,12 +48,12 @@ impl TraitItems { db: &dyn DefDatabase, tr: TraitId, ) -> (Arc, DefDiagnostics) { - let ItemLoc { container: module_id, id: tree_id } = tr.lookup(db); + let ItemLoc { container: module_id, id: ast_id } = tr.lookup(db); - let collector = AssocItemCollector::new(db, module_id, ItemContainerId::TraitId(tr)); - let item_tree = tree_id.item_tree(db); - let (items, macro_calls, diagnostics) = - collector.collect(&item_tree, tree_id.tree_id(), &item_tree[tree_id.value].items); + let collector = + AssocItemCollector::new(db, module_id, ItemContainerId::TraitId(tr), ast_id.file_id); + let source = ast_id.with_value(collector.ast_id_map.get(ast_id.value)).to_node(db); + let (items, macro_calls, diagnostics) = collector.collect(source.assoc_item_list()); (Arc::new(TraitItems { macro_calls, items }), DefDiagnostics::new(diagnostics)) } @@ -76,16 +89,15 @@ impl TraitItems { } pub fn macro_calls(&self) -> impl Iterator, MacroCallId)> + '_ { - self.macro_calls.iter().flat_map(|it| it.iter()).copied() + self.macro_calls.iter().copied() } } #[derive(Debug, PartialEq, Eq)] pub struct ImplItems { pub items: Box<[(Name, AssocItemId)]>, - // box it as the vec is usually empty anyways - // FIXME: AstIds are rather unstable... - pub macro_calls: Option, MacroCallId)>>>, + // `ThinVec` as the vec is usually empty anyways + pub macro_calls: ThinVec<(AstId, MacroCallId)>, } impl ImplItems { @@ -99,18 +111,18 @@ impl ImplItems { id: ImplId, ) -> (Arc, DefDiagnostics) { let _p = tracing::info_span!("impl_items_with_diagnostics_query").entered(); - let ItemLoc { container: module_id, id: tree_id } = id.lookup(db); + let ItemLoc { container: module_id, id: ast_id } = id.lookup(db); - let collector = AssocItemCollector::new(db, module_id, ItemContainerId::ImplId(id)); - let item_tree = tree_id.item_tree(db); - let (items, macro_calls, diagnostics) = - collector.collect(&item_tree, tree_id.tree_id(), &item_tree[tree_id.value].items); + let collector = + AssocItemCollector::new(db, module_id, ItemContainerId::ImplId(id), ast_id.file_id); + let source = ast_id.with_value(collector.ast_id_map.get(ast_id.value)).to_node(db); + let (items, macro_calls, diagnostics) = collector.collect(source.assoc_item_list()); (Arc::new(ImplItems { items, macro_calls }), DefDiagnostics::new(diagnostics)) } pub fn macro_calls(&self) -> impl Iterator, MacroCallId)> + '_ { - self.macro_calls.iter().flat_map(|it| it.iter()).copied() + self.macro_calls.iter().copied() } } @@ -119,67 +131,73 @@ struct AssocItemCollector<'a> { module_id: ModuleId, def_map: &'a DefMap, local_def_map: &'a LocalDefMap, + ast_id_map: Arc, + span_map: SpanMap, + cfg_options: &'a CfgOptions, + file_id: HirFileId, diagnostics: Vec, container: ItemContainerId, depth: usize, items: Vec<(Name, AssocItemId)>, - macro_calls: Vec<(AstId, MacroCallId)>, + macro_calls: ThinVec<(AstId, MacroCallId)>, } impl<'a> AssocItemCollector<'a> { - fn new(db: &'a dyn DefDatabase, module_id: ModuleId, container: ItemContainerId) -> Self { + fn new( + db: &'a dyn DefDatabase, + module_id: ModuleId, + container: ItemContainerId, + file_id: HirFileId, + ) -> Self { let (def_map, local_def_map) = module_id.local_def_map(db); Self { db, module_id, def_map, local_def_map, + ast_id_map: db.ast_id_map(file_id), + span_map: db.span_map(file_id), + cfg_options: module_id.krate.cfg_options(db), + file_id, container, items: Vec::new(), depth: 0, - macro_calls: Vec::new(), + macro_calls: ThinVec::new(), diagnostics: Vec::new(), } } fn collect( mut self, - item_tree: &ItemTree, - tree_id: TreeId, - assoc_items: &[AssocItem], - ) -> ( - Box<[(Name, AssocItemId)]>, - Option, MacroCallId)>>>, - Vec, - ) { - self.items.reserve(assoc_items.len()); - for &item in assoc_items { - self.collect_item(item_tree, tree_id, item); + item_list: Option, + ) -> (Box<[(Name, AssocItemId)]>, ThinVec<(AstId, MacroCallId)>, Vec) + { + if let Some(item_list) = item_list { + for item in item_list.assoc_items() { + self.collect_item(item); + } } - ( - self.items.into_boxed_slice(), - if self.macro_calls.is_empty() { None } else { Some(Box::new(self.macro_calls)) }, - self.diagnostics, - ) + self.macro_calls.shrink_to_fit(); + (self.items.into_boxed_slice(), self.macro_calls, self.diagnostics) } - fn collect_item(&mut self, item_tree: &ItemTree, tree_id: TreeId, item: AssocItem) { - let attrs = item_tree.attrs(self.db, self.module_id.krate, ModItem::from(item).into()); - if !attrs.is_cfg_enabled(self.module_id.krate.cfg_options(self.db)) { + fn collect_item(&mut self, item: ast::AssocItem) { + let ast_id = self.ast_id_map.ast_id(&item); + let attrs = Attrs::new(self.db, &item, self.span_map.as_ref(), self.cfg_options); + if let Err(cfg) = attrs.is_cfg_enabled(self.cfg_options) { self.diagnostics.push(DefDiagnostic::unconfigured_code( self.module_id.local_id, - tree_id, - ModItem::from(item).into(), - attrs.cfg().unwrap(), - self.module_id.krate.cfg_options(self.db).clone(), + InFile::new(self.file_id, ast_id.erase()), + cfg, + self.cfg_options.clone(), )); return; } + let ast_id = InFile::new(self.file_id, ast_id.upcast()); 'attrs: for attr in &*attrs { - let ast_id = AstId::new(tree_id.file_id(), item.ast_id(item_tree).upcast()); let ast_id_with_path = AstIdWithPath { path: attr.path.clone(), ast_id }; match self.def_map.resolve_attr_macro( @@ -223,34 +241,51 @@ impl<'a> AssocItemCollector<'a> { } } - self.record_item(item_tree, tree_id, item); + self.record_item(item); } - fn record_item(&mut self, item_tree: &ItemTree, tree_id: TreeId, item: AssocItem) { + fn record_item(&mut self, item: ast::AssocItem) { match item { - AssocItem::Function(id) => { - let item = &item_tree[id]; - let def = - FunctionLoc { container: self.container, id: ItemTreeId::new(tree_id, id) } - .intern(self.db); - self.items.push((item.name.clone(), def.into())); + ast::AssocItem::Fn(function) => { + let Some(name) = function.name() else { return }; + let ast_id = self.ast_id_map.ast_id(&function); + let def = FunctionLoc { + container: self.container, + id: InFile::new(self.file_id, ast_id), + } + .intern(self.db); + self.items.push((name.as_name(), def.into())); + } + ast::AssocItem::TypeAlias(type_alias) => { + let Some(name) = type_alias.name() else { return }; + let ast_id = self.ast_id_map.ast_id(&type_alias); + let def = TypeAliasLoc { + container: self.container, + id: InFile::new(self.file_id, ast_id), + } + .intern(self.db); + self.items.push((name.as_name(), def.into())); } - AssocItem::TypeAlias(id) => { - let item = &item_tree[id]; + ast::AssocItem::Const(konst) => { + let Some(name) = konst.name() else { return }; + let ast_id = self.ast_id_map.ast_id(&konst); let def = - TypeAliasLoc { container: self.container, id: ItemTreeId::new(tree_id, id) } + ConstLoc { container: self.container, id: InFile::new(self.file_id, ast_id) } .intern(self.db); - self.items.push((item.name.clone(), def.into())); - } - AssocItem::Const(id) => { - let item = &item_tree[id]; - let Some(name) = item.name.clone() else { return }; - let def = ConstLoc { container: self.container, id: ItemTreeId::new(tree_id, id) } - .intern(self.db); - self.items.push((name, def.into())); + self.items.push((name.as_name(), def.into())); } - AssocItem::MacroCall(call) => { - let MacroCall { ast_id, expand_to, ctxt, ref path } = item_tree[call]; + ast::AssocItem::MacroCall(call) => { + let ast_id = self.ast_id_map.ast_id(&call); + let ast_id = InFile::new(self.file_id, ast_id); + let Some(path) = call.path() else { return }; + let range = path.syntax().text_range(); + let Some(path) = ModPath::from_src(self.db, path, &mut |range| { + self.span_map.span_for_range(range).ctx + }) else { + return; + }; + let path = Interned::new(path); + let ctxt = self.span_map.span_for_range(range).ctx; let resolver = |path: &_| { self.def_map @@ -268,10 +303,10 @@ impl<'a> AssocItemCollector<'a> { }; match macro_call_as_call_id( self.db, - InFile::new(tree_id.file_id(), ast_id), - path, + ast_id, + &path, ctxt, - expand_to, + ExpandTo::Items, self.module_id.krate(), resolver, &mut |ptr, call_id| { @@ -281,8 +316,7 @@ impl<'a> AssocItemCollector<'a> { // FIXME: Expansion error? Ok(call_id) => match call_id.value { Some(call_id) => { - self.macro_calls - .push((InFile::new(tree_id.file_id(), ast_id.upcast()), call_id)); + self.macro_calls.push((ast_id.upcast(), call_id)); self.collect_macro_items(call_id); } None => (), @@ -291,11 +325,11 @@ impl<'a> AssocItemCollector<'a> { self.diagnostics.push(DefDiagnostic::unresolved_macro_call( self.module_id.local_id, MacroCallKind::FnLike { - ast_id: InFile::new(tree_id.file_id(), ast_id), - expand_to, + ast_id, + expand_to: ExpandTo::Items, eager: None, }, - Clone::clone(path), + (*path).clone(), )); } } @@ -308,13 +342,29 @@ impl<'a> AssocItemCollector<'a> { tracing::warn!("macro expansion is too deep"); return; } - let tree_id = TreeId::new(macro_call_id.into(), None); - let item_tree = self.db.file_item_tree(macro_call_id.into()); + let (syntax, span_map) = self.db.parse_macro_expansion(macro_call_id).value; + let old_file_id = mem::replace(&mut self.file_id, macro_call_id.into()); + let old_ast_id_map = mem::replace(&mut self.ast_id_map, self.db.ast_id_map(self.file_id)); + let old_span_map = mem::replace(&mut self.span_map, SpanMap::ExpansionSpanMap(span_map)); self.depth += 1; - for item in item_tree.top_level_items().iter().filter_map(ModItem::as_assoc_item) { - self.collect_item(&item_tree, tree_id, item); + + let items = ast::MacroItems::cast(syntax.syntax_node()).expect("not `MacroItems`"); + for item in items.items() { + let item = match item { + ast::Item::Fn(it) => ast::AssocItem::from(it), + ast::Item::Const(it) => it.into(), + ast::Item::TypeAlias(it) => it.into(), + ast::Item::MacroCall(it) => it.into(), + // FIXME: Should error on disallowed item kinds. + _ => continue, + }; + self.collect_item(item); } + self.depth -= 1; + self.file_id = old_file_id; + self.ast_id_map = old_ast_id_map; + self.span_map = old_span_map; } } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs index 350c97c398256..34a129a88eaa1 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs @@ -9,8 +9,8 @@ use base_db::{BuiltDependency, Crate, CrateOrigin, LangCrateOrigin}; use cfg::{CfgAtom, CfgExpr, CfgOptions}; use either::Either; use hir_expand::{ - EditionedFileId, ExpandTo, HirFileId, InFile, MacroCallId, MacroCallKind, MacroDefId, - MacroDefKind, + EditionedFileId, ErasedAstId, ExpandTo, HirFileId, InFile, MacroCallId, MacroCallKind, + MacroDefId, MacroDefKind, attrs::{Attr, AttrId}, builtin::{find_builtin_attr, find_builtin_derive, find_builtin_macro}, mod_path::{ModPath, PathKind}, @@ -35,9 +35,8 @@ use crate::{ db::DefDatabase, item_scope::{GlobId, ImportId, ImportOrExternCrate, PerNsGlobImports}, item_tree::{ - self, AttrOwner, FieldsShape, FileItemTreeId, ImportAlias, ImportKind, ItemTree, - ItemTreeId, ItemTreeNode, Macro2, MacroCall, MacroRules, Mod, ModItem, ModKind, TreeId, - UseTreeKind, + self, FieldsShape, FileItemTreeId, ImportAlias, ImportKind, ItemTree, ItemTreeId, + ItemTreeNode, Macro2, MacroCall, MacroRules, Mod, ModItem, ModKind, TreeId, UseTreeKind, }, macro_call_as_call_id, nameres::{ @@ -141,6 +140,7 @@ struct ImportSource { id: UseId, is_prelude: bool, kind: ImportKind, + item_tree_id: ItemTreeId, } #[derive(Debug, Eq, PartialEq)] @@ -166,7 +166,7 @@ impl Import { path, alias, visibility: visibility.clone(), - source: ImportSource { use_tree: idx, id, is_prelude, kind }, + source: ImportSource { use_tree: idx, id, is_prelude, kind, item_tree_id }, }); }); } @@ -576,13 +576,7 @@ impl DefCollector<'_> { /// use a dummy expander that always errors. This comes with the drawback of macros potentially /// going out of sync with what the build system sees (since we resolve using VFS state, but /// Cargo builds only on-disk files). We could and probably should add diagnostics for that. - fn export_proc_macro( - &mut self, - def: ProcMacroDef, - id: ItemTreeId, - ast_id: AstId, - fn_id: FunctionId, - ) { + fn export_proc_macro(&mut self, def: ProcMacroDef, ast_id: AstId, fn_id: FunctionId) { let kind = def.kind.to_basedb_kind(); let (expander, kind) = match self.proc_macros.iter().find(|(n, _, _)| n == &def.name) { Some(_) @@ -598,7 +592,7 @@ impl DefCollector<'_> { let proc_macro_id = ProcMacroLoc { container: self.def_map.crate_root(), - id, + id: ast_id, expander, kind, edition: self.def_map.data.edition, @@ -866,6 +860,7 @@ impl DefCollector<'_> { kind: kind @ (ImportKind::Plain | ImportKind::TypeOnly), id, use_tree, + item_tree_id, .. } => { let name = match &import.alias { @@ -887,9 +882,33 @@ impl DefCollector<'_> { let imp = ImportOrExternCrate::Import(ImportId { use_: id, idx: use_tree }); tracing::debug!("resolved import {:?} ({:?}) to {:?}", name, import, def); + // `extern crate crate_name` things can be re-exported as `pub use crate_name`. + // But they cannot be re-exported as `pub use self::crate_name`, `pub use crate::crate_name` + // or `pub use ::crate_name`. + // + // This has been historically allowed, but may be not allowed in future + // https://github.com/rust-lang/rust/issues/127909 + if let Some(def) = def.types.as_mut() { + let is_extern_crate_reimport_without_prefix = || { + let Some(ImportOrExternCrate::ExternCrate(_)) = def.import else { + return false; + }; + let item_tree = item_tree_id.item_tree(self.db); + let use_kind = item_tree[item_tree_id.value].use_tree.kind(); + let UseTreeKind::Single { path, .. } = use_kind else { + return false; + }; + matches!(path.kind, PathKind::Plain | PathKind::SELF) + && path.segments().len() < 2 + }; + if is_extern_crate_reimport_without_prefix() { + def.vis = vis; + } + } + self.update(module_id, &[(name.cloned(), def)], vis, Some(imp)); } - ImportSource { kind: ImportKind::Glob, id, is_prelude, use_tree } => { + ImportSource { kind: ImportKind::Glob, id, is_prelude, use_tree, .. } => { tracing::debug!("glob import: {:?}", import); let glob = GlobId { use_: id, idx: use_tree }; match def.take_types() { @@ -978,7 +997,7 @@ impl DefCollector<'_> { .enum_variants(e) .variants .iter() - .map(|&(variant, ref name)| { + .map(|&(variant, ref name, _)| { let res = PerNs::both(variant.into(), variant.into(), vis, None); (Some(name.clone()), res) }) @@ -1150,33 +1169,8 @@ impl DefCollector<'_> { vis: Visibility, def_import_type: Option, ) -> bool { - // `extern crate crate_name` things can be re-exported as `pub use crate_name`. - // But they cannot be re-exported as `pub use self::crate_name`, `pub use crate::crate_name` - // or `pub use ::crate_name`. - // - // This has been historically allowed, but may be not allowed in future - // https://github.com/rust-lang/rust/issues/127909 if let Some(def) = defs.types.as_mut() { - let is_extern_crate_reimport_without_prefix = || { - let Some(ImportOrExternCrate::ExternCrate(_)) = def.import else { - return false; - }; - let Some(ImportOrExternCrate::Import(id)) = def_import_type else { - return false; - }; - let use_id = id.use_.lookup(self.db).id; - let item_tree = use_id.item_tree(self.db); - let use_kind = item_tree[use_id.value].use_tree.kind(); - let UseTreeKind::Single { path, .. } = use_kind else { - return false; - }; - path.segments().len() < 2 - }; - if is_extern_crate_reimport_without_prefix() { - def.vis = vis; - } else { - def.vis = def.vis.min(vis, &self.def_map).unwrap_or(vis); - } + def.vis = def.vis.min(vis, &self.def_map).unwrap_or(vis); } if let Some(def) = defs.values.as_mut() { def.vis = def.vis.min(vis, &self.def_map).unwrap_or(vis); @@ -1648,7 +1642,8 @@ impl DefCollector<'_> { import: Import { ref path, - source: ImportSource { use_tree, id, is_prelude: _, kind: _ }, + source: + ImportSource { use_tree, id, is_prelude: _, kind: _, item_tree_id: _ }, .. }, .. @@ -1730,7 +1725,26 @@ impl ModCollector<'_, '_> { let attrs = self.item_tree.attrs(db, krate, item.into()); if let Some(cfg) = attrs.cfg() { if !self.is_cfg_enabled(&cfg) { - self.emit_unconfigured_diagnostic(self.tree_id, item.into(), &cfg); + let ast_id = match item { + ModItem::Use(it) => self.item_tree[it].ast_id.erase(), + ModItem::ExternCrate(it) => self.item_tree[it].ast_id.erase(), + ModItem::ExternBlock(it) => self.item_tree[it].ast_id.erase(), + ModItem::Function(it) => self.item_tree[it].ast_id.erase(), + ModItem::Struct(it) => self.item_tree[it].ast_id.erase(), + ModItem::Union(it) => self.item_tree[it].ast_id.erase(), + ModItem::Enum(it) => self.item_tree[it].ast_id.erase(), + ModItem::Const(it) => self.item_tree[it].ast_id.erase(), + ModItem::Static(it) => self.item_tree[it].ast_id.erase(), + ModItem::Trait(it) => self.item_tree[it].ast_id.erase(), + ModItem::TraitAlias(it) => self.item_tree[it].ast_id.erase(), + ModItem::Impl(it) => self.item_tree[it].ast_id.erase(), + ModItem::TypeAlias(it) => self.item_tree[it].ast_id.erase(), + ModItem::Mod(it) => self.item_tree[it].ast_id.erase(), + ModItem::MacroCall(it) => self.item_tree[it].ast_id.erase(), + ModItem::MacroRules(it) => self.item_tree[it].ast_id.erase(), + ModItem::Macro2(it) => self.item_tree[it].ast_id.erase(), + }; + self.emit_unconfigured_diagnostic(InFile::new(self.file_id(), ast_id), &cfg); return; } } @@ -1751,7 +1765,7 @@ impl ModCollector<'_, '_> { ModItem::Use(item_tree_id) => { let id = UseLoc { container: module, - id: ItemTreeId::new(self.tree_id, item_tree_id), + id: InFile::new(self.file_id(), self.item_tree[item_tree_id].ast_id), } .intern(db); let is_prelude = attrs.by_key(sym::prelude_import).exists(); @@ -1770,16 +1784,16 @@ impl ModCollector<'_, '_> { ) } ModItem::ExternCrate(item_tree_id) => { + let item_tree::ExternCrate { name, visibility, alias, ast_id } = + &self.item_tree[item_tree_id]; + let id = ExternCrateLoc { container: module, - id: ItemTreeId::new(self.tree_id, item_tree_id), + id: InFile::new(self.tree_id.file_id(), *ast_id), } .intern(db); def_map.modules[self.module_id].scope.define_extern_crate_decl(id); - let item_tree::ExternCrate { name, visibility, alias, ast_id } = - &self.item_tree[item_tree_id]; - let is_self = *name == sym::self_; let resolved = if is_self { cov_mark::hit!(extern_crate_self_as); @@ -1846,7 +1860,7 @@ impl ModCollector<'_, '_> { ModItem::ExternBlock(block) => { let extern_block_id = ExternBlockLoc { container: module, - id: ItemTreeId::new(self.tree_id, block), + id: InFile::new(self.file_id(), self.item_tree[block].ast_id), } .intern(db); self.def_collector.def_map.modules[self.module_id] @@ -1861,15 +1875,20 @@ impl ModCollector<'_, '_> { ModItem::MacroRules(id) => self.collect_macro_rules(id, module), ModItem::Macro2(id) => self.collect_macro_def(id, module), ModItem::Impl(imp) => { - let impl_id = - ImplLoc { container: module, id: ItemTreeId::new(self.tree_id, imp) } - .intern(db); + let impl_id = ImplLoc { + container: module, + id: InFile::new(self.file_id(), self.item_tree[imp].ast_id), + } + .intern(db); self.def_collector.def_map.modules[self.module_id].scope.define_impl(impl_id) } ModItem::Function(id) => { let it = &self.item_tree[id]; - let fn_id = - FunctionLoc { container, id: ItemTreeId::new(self.tree_id, id) }.intern(db); + let fn_id = FunctionLoc { + container, + id: InFile::new(self.tree_id.file_id(), it.ast_id), + } + .intern(db); let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]); @@ -1880,7 +1899,6 @@ impl ModCollector<'_, '_> { if let Some(proc_macro) = attrs.parse_proc_macro_decl(&it.name) { self.def_collector.export_proc_macro( proc_macro, - ItemTreeId::new(self.tree_id, id), InFile::new(self.file_id(), self.item_tree[id].ast_id()), fn_id, ); @@ -1895,7 +1913,7 @@ impl ModCollector<'_, '_> { let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]); update_def( self.def_collector, - StructLoc { container: module, id: ItemTreeId::new(self.tree_id, id) } + StructLoc { container: module, id: InFile::new(self.file_id(), it.ast_id) } .intern(db) .into(), &it.name, @@ -1909,7 +1927,7 @@ impl ModCollector<'_, '_> { let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]); update_def( self.def_collector, - UnionLoc { container: module, id: ItemTreeId::new(self.tree_id, id) } + UnionLoc { container: module, id: InFile::new(self.file_id(), it.ast_id) } .intern(db) .into(), &it.name, @@ -1919,9 +1937,11 @@ impl ModCollector<'_, '_> { } ModItem::Enum(id) => { let it = &self.item_tree[id]; - let enum_ = - EnumLoc { container: module, id: ItemTreeId::new(self.tree_id, id) } - .intern(db); + let enum_ = EnumLoc { + container: module, + id: InFile::new(self.tree_id.file_id(), it.ast_id), + } + .intern(db); let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]); update_def(self.def_collector, enum_.into(), &it.name, vis, false); @@ -1929,7 +1949,8 @@ impl ModCollector<'_, '_> { ModItem::Const(id) => { let it = &self.item_tree[id]; let const_id = - ConstLoc { container, id: ItemTreeId::new(self.tree_id, id) }.intern(db); + ConstLoc { container, id: InFile::new(self.tree_id.file_id(), it.ast_id) } + .intern(db); match &it.name { Some(name) => { @@ -1951,7 +1972,7 @@ impl ModCollector<'_, '_> { let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]); update_def( self.def_collector, - StaticLoc { container, id: ItemTreeId::new(self.tree_id, id) } + StaticLoc { container, id: InFile::new(self.file_id(), it.ast_id) } .intern(db) .into(), &it.name, @@ -1965,7 +1986,7 @@ impl ModCollector<'_, '_> { let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]); update_def( self.def_collector, - TraitLoc { container: module, id: ItemTreeId::new(self.tree_id, id) } + TraitLoc { container: module, id: InFile::new(self.file_id(), it.ast_id) } .intern(db) .into(), &it.name, @@ -1979,9 +2000,12 @@ impl ModCollector<'_, '_> { let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]); update_def( self.def_collector, - TraitAliasLoc { container: module, id: ItemTreeId::new(self.tree_id, id) } - .intern(db) - .into(), + TraitAliasLoc { + container: module, + id: InFile::new(self.file_id(), it.ast_id), + } + .intern(db) + .into(), &it.name, vis, false, @@ -1993,7 +2017,7 @@ impl ModCollector<'_, '_> { let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]); update_def( self.def_collector, - TypeAliasLoc { container, id: ItemTreeId::new(self.tree_id, id) } + TypeAliasLoc { container, id: InFile::new(self.file_id(), it.ast_id) } .intern(db) .into(), &it.name, @@ -2110,8 +2134,10 @@ impl ModCollector<'_, '_> { match is_enabled { Err(cfg) => { self.emit_unconfigured_diagnostic( - self.tree_id, - AttrOwner::ModItem(module_id.into()), + InFile::new( + self.file_id(), + self.item_tree[module_id].ast_id.erase(), + ), &cfg, ); } @@ -2352,7 +2378,7 @@ impl ModCollector<'_, '_> { let macro_id = MacroRulesLoc { container: module, - id: ItemTreeId::new(self.tree_id, id), + id: InFile::new(self.file_id(), mac.ast_id), flags, expander, edition: self.def_collector.def_map.data.edition, @@ -2420,7 +2446,7 @@ impl ModCollector<'_, '_> { let macro_id = Macro2Loc { container: module, - id: ItemTreeId::new(self.tree_id, id), + id: InFile::new(self.file_id(), mac.ast_id), expander, allow_internal_unsafe, edition: self.def_collector.def_map.data.edition, @@ -2565,16 +2591,16 @@ impl ModCollector<'_, '_> { self.def_collector.cfg_options.check(cfg) != Some(false) } - fn emit_unconfigured_diagnostic(&mut self, tree_id: TreeId, item: AttrOwner, cfg: &CfgExpr) { + fn emit_unconfigured_diagnostic(&mut self, ast_id: ErasedAstId, cfg: &CfgExpr) { self.def_collector.def_map.diagnostics.push(DefDiagnostic::unconfigured_code( self.module_id, - tree_id, - item, + ast_id, cfg.clone(), self.def_collector.cfg_options.clone(), )); } + #[inline] fn file_id(&self) -> HirFileId { self.tree_id.file_id() } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/diagnostics.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/diagnostics.rs index de3d2f48367f7..c495a07449196 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/diagnostics.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/diagnostics.rs @@ -3,22 +3,18 @@ use std::ops::Not; use cfg::{CfgExpr, CfgOptions}; -use hir_expand::{ExpandErrorKind, MacroCallKind, attrs::AttrId, mod_path::ModPath}; +use hir_expand::{ErasedAstId, ExpandErrorKind, MacroCallKind, attrs::AttrId, mod_path::ModPath}; use la_arena::Idx; use syntax::ast; -use crate::{ - AstId, - item_tree::{self, AttrOwner, ItemTreeId, TreeId}, - nameres::LocalModuleId, -}; +use crate::{AstId, nameres::LocalModuleId}; #[derive(Debug, PartialEq, Eq)] pub enum DefDiagnosticKind { UnresolvedModule { ast: AstId, candidates: Box<[String]> }, UnresolvedExternCrate { ast: AstId }, - UnresolvedImport { id: ItemTreeId, index: Idx }, - UnconfiguredCode { tree: TreeId, item: AttrOwner, cfg: CfgExpr, opts: CfgOptions }, + UnresolvedImport { id: AstId, index: Idx }, + UnconfiguredCode { ast_id: ErasedAstId, cfg: CfgExpr, opts: CfgOptions }, UnresolvedMacroCall { ast: MacroCallKind, path: ModPath }, UnimplementedBuiltinMacro { ast: AstId }, InvalidDeriveTarget { ast: AstId, id: usize }, @@ -28,7 +24,7 @@ pub enum DefDiagnosticKind { } #[derive(Clone, Debug, PartialEq, Eq)] -pub struct DefDiagnostics(Option>>); +pub struct DefDiagnostics(Option>); impl DefDiagnostics { pub fn new(diagnostics: Vec) -> Self { @@ -36,12 +32,12 @@ impl DefDiagnostics { diagnostics .is_empty() .not() - .then(|| triomphe::Arc::new(diagnostics.into_boxed_slice())), + .then(|| triomphe::ThinArc::from_header_and_iter((), diagnostics.into_iter())), ) } pub fn iter(&self) -> impl Iterator { - self.0.as_ref().into_iter().flat_map(|it| &***it) + self.0.as_ref().into_iter().flat_map(|it| &it.slice) } } @@ -75,7 +71,7 @@ impl DefDiagnostic { pub(super) fn unresolved_import( container: LocalModuleId, - id: ItemTreeId, + id: AstId, index: Idx, ) -> Self { Self { in_module: container, kind: DefDiagnosticKind::UnresolvedImport { id, index } } @@ -92,14 +88,13 @@ impl DefDiagnostic { pub fn unconfigured_code( container: LocalModuleId, - tree: TreeId, - item: AttrOwner, + ast_id: ErasedAstId, cfg: CfgExpr, opts: CfgOptions, ) -> Self { Self { in_module: container, - kind: DefDiagnosticKind::UnconfiguredCode { tree, item, cfg, opts }, + kind: DefDiagnosticKind::UnconfiguredCode { ast_id, cfg, opts }, } } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/path_resolution.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/path_resolution.rs index 74ce33a6419e1..e0e32a777356c 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/path_resolution.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/path_resolution.rs @@ -12,7 +12,6 @@ use either::Either; use hir_expand::{ - Lookup, mod_path::{ModPath, PathKind}, name::Name, }; @@ -529,23 +528,22 @@ impl DefMap { // enum variant cov_mark::hit!(can_import_enum_variant); - let res = - db.enum_variants(e).variants.iter().find(|(_, name)| name == segment).map( - |&(variant, _)| { - let item_tree_id = variant.lookup(db).id; - match item_tree_id.item_tree(db)[item_tree_id.value].shape { - FieldsShape::Record => { - PerNs::types(variant.into(), Visibility::Public, None) - } - FieldsShape::Tuple | FieldsShape::Unit => PerNs::both( - variant.into(), - variant.into(), - Visibility::Public, - None, - ), - } - }, - ); + let res = db + .enum_variants(e) + .variants + .iter() + .find(|(_, name, _)| name == segment) + .map(|&(variant, _, shape)| match shape { + FieldsShape::Record => { + PerNs::types(variant.into(), Visibility::Public, None) + } + FieldsShape::Tuple | FieldsShape::Unit => PerNs::both( + variant.into(), + variant.into(), + Visibility::Public, + None, + ), + }); // FIXME: Need to filter visibility here and below? Not sure. return match res { Some(res) => { diff --git a/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs b/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs index 16988ddf04b26..491b6204bce2c 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs @@ -5,21 +5,22 @@ use base_db::Crate; use hir_expand::{ MacroDefId, mod_path::{ModPath, PathKind}, - name::Name, + name::{AsName, Name}, }; use intern::{Symbol, sym}; use itertools::Itertools as _; use rustc_hash::FxHashSet; use smallvec::{SmallVec, smallvec}; use span::SyntaxContext; +use syntax::ast::HasName; use triomphe::Arc; use crate::{ - AdtId, ConstId, ConstParamId, CrateRootModuleId, DefWithBodyId, EnumId, EnumVariantId, - ExternBlockId, ExternCrateId, FunctionId, FxIndexMap, GenericDefId, GenericParamId, HasModule, - ImplId, ItemContainerId, ItemTreeLoc, LifetimeParamId, LocalModuleId, Lookup, Macro2Id, - MacroId, MacroRulesId, ModuleDefId, ModuleId, ProcMacroId, StaticId, StructId, TraitAliasId, - TraitId, TypeAliasId, TypeOrConstParamId, TypeParamId, UseId, VariantId, + AdtId, AstIdLoc, ConstId, ConstParamId, CrateRootModuleId, DefWithBodyId, EnumId, + EnumVariantId, ExternBlockId, ExternCrateId, FunctionId, FxIndexMap, GenericDefId, + GenericParamId, HasModule, ImplId, ItemContainerId, LifetimeParamId, LocalModuleId, Lookup, + Macro2Id, MacroId, MacroRulesId, ModuleDefId, ModuleId, ProcMacroId, StaticId, StructId, + TraitAliasId, TraitId, TypeAliasId, TypeOrConstParamId, TypeParamId, UseId, VariantId, builtin_type::BuiltinType, db::DefDatabase, expr_store::{ @@ -32,10 +33,10 @@ use crate::{ generics::{GenericParams, TypeOrConstParamData}, }, item_scope::{BUILTIN_SCOPE, BuiltinShadowMode, ImportOrExternCrate, ImportOrGlob, ItemScope}, - item_tree::ImportAlias, lang_item::LangItemTarget, nameres::{DefMap, LocalDefMap, MacroSubNs, ResolvePathResultPrefixInfo, block_def_map}, per_ns::PerNs, + src::HasSource, type_ref::LifetimeRef, visibility::{RawVisibility, Visibility}, }; @@ -627,14 +628,14 @@ impl<'db> Resolver<'db> { .extern_crate_decls() .filter_map(|id| { let loc = id.lookup(db); - let tree = loc.item_tree_id().item_tree(db); - match &tree[loc.id.value].alias { - Some(alias) => match alias { - ImportAlias::Underscore => None, - ImportAlias::Alias(name) => Some(name.clone()), - }, - None => Some(tree[loc.id.value].name.clone()), - } + let extern_crate = loc.source(db); + // If there is a rename (`as x`), extract the renamed name, or remove the `extern crate` + // if it is an underscore. + extern_crate + .value + .rename() + .map(|a| a.name().map(|it| it.as_name())) + .unwrap_or_else(|| extern_crate.value.name_ref().map(|it| it.as_name())) }) } @@ -1471,10 +1472,7 @@ impl HasResolver for MacroRulesId { fn lookup_resolver( db: &dyn DefDatabase, - lookup: impl Lookup< - Database = dyn DefDatabase, - Data = impl ItemTreeLoc, - >, + lookup: impl Lookup>, ) -> Resolver<'_> { lookup.lookup(db).container().resolver(db) } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/signatures.rs b/src/tools/rust-analyzer/crates/hir-def/src/signatures.rs index 44cfd72c48f5e..b7d29f54d08ee 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/signatures.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/signatures.rs @@ -4,21 +4,25 @@ use std::ops::Not as _; use bitflags::bitflags; use cfg::{CfgExpr, CfgOptions}; -use either::Either; -use hir_expand::{InFile, Intern, Lookup, name::Name}; +use hir_expand::{ + InFile, Intern, Lookup, + name::{AsName, Name}, +}; use intern::{Symbol, sym}; use la_arena::{Arena, Idx}; use rustc_abi::{IntegerType, ReprOptions}; use syntax::{ - AstNode, SyntaxNodePtr, - ast::{self, HasGenericParams, IsString}, + NodeOrToken, SyntaxNodePtr, T, + ast::{self, HasGenericParams, HasName, HasVisibility, IsString}, }; use thin_vec::ThinVec; use triomphe::Arc; use crate::{ - ConstId, EnumId, EnumVariantId, EnumVariantLoc, FunctionId, HasModule, ImplId, ItemContainerId, - ModuleId, StaticId, StructId, TraitAliasId, TraitId, TypeAliasId, UnionId, VariantId, + ConstId, EnumId, EnumVariantId, EnumVariantLoc, ExternBlockId, FunctionId, HasModule, ImplId, + ItemContainerId, ModuleId, StaticId, StructId, TraitAliasId, TraitId, TypeAliasId, UnionId, + VariantId, + attr::Attrs, db::DefDatabase, expr_store::{ ExpressionStore, ExpressionStoreSourceMap, @@ -28,15 +32,17 @@ use crate::{ }, }, hir::{ExprId, PatId, generics::GenericParams}, - item_tree::{ - AttrOwner, Field, FieldParent, FieldsShape, FileItemTreeId, ItemTree, ItemTreeId, ModItem, - RawVisibility, RawVisibilityId, - }, + item_tree::{FieldsShape, RawVisibility, visibility_from_ast}, lang_item::LangItem, src::HasSource, type_ref::{TraitRef, TypeBound, TypeRefId}, }; +#[inline] +fn as_name_opt(name: Option) -> Name { + name.map_or_else(Name::missing, |it| it.as_name()) +} + #[derive(Debug, PartialEq, Eq)] pub struct StructSignature { pub name: Name, @@ -70,8 +76,8 @@ bitflags! { impl StructSignature { pub fn query(db: &dyn DefDatabase, id: StructId) -> (Arc, Arc) { let loc = id.lookup(db); - let item_tree = loc.id.item_tree(db); - let attrs = item_tree.attrs(db, loc.container.krate, ModItem::from(loc.id.value).into()); + let InFile { file_id, value: source } = loc.source(db); + let attrs = db.attrs(id.into()); let mut flags = StructFlags::empty(); if attrs.by_key(sym::rustc_has_incoherent_inherent_impls).exists() { @@ -91,23 +97,23 @@ impl StructSignature { } } let repr = attrs.repr(); + let shape = adt_shape(source.kind()); - let hir_expand::files::InFileWrapper { file_id, value } = loc.source(db); let (store, generic_params, source_map) = lower_generic_params( db, loc.container, id.into(), file_id, - value.generic_param_list(), - value.where_clause(), + source.generic_param_list(), + source.where_clause(), ); ( Arc::new(StructSignature { generic_params, store, flags, - shape: item_tree[loc.id.value].shape, - name: item_tree[loc.id.value].name.clone(), + shape, + name: as_name_opt(source.name()), repr, }), Arc::new(source_map), @@ -115,6 +121,15 @@ impl StructSignature { } } +#[inline] +fn adt_shape(adt_kind: ast::StructKind) -> FieldsShape { + match adt_kind { + ast::StructKind::Record(_) => FieldsShape::Record, + ast::StructKind::Tuple(_) => FieldsShape::Tuple, + ast::StructKind::Unit => FieldsShape::Unit, + } +} + #[derive(Debug, PartialEq, Eq)] pub struct UnionSignature { pub name: Name, @@ -127,9 +142,7 @@ pub struct UnionSignature { impl UnionSignature { pub fn query(db: &dyn DefDatabase, id: UnionId) -> (Arc, Arc) { let loc = id.lookup(db); - let krate = loc.container.krate; - let item_tree = loc.id.item_tree(db); - let attrs = item_tree.attrs(db, krate, ModItem::from(loc.id.value).into()); + let attrs = db.attrs(id.into()); let mut flags = StructFlags::empty(); if attrs.by_key(sym::rustc_has_incoherent_inherent_impls).exists() { flags |= StructFlags::RUSTC_HAS_INCOHERENT_INHERENT_IMPLS; @@ -140,14 +153,14 @@ impl UnionSignature { let repr = attrs.repr(); - let hir_expand::files::InFileWrapper { file_id, value } = loc.source(db); + let InFile { file_id, value: source } = loc.source(db); let (store, generic_params, source_map) = lower_generic_params( db, loc.container, id.into(), file_id, - value.generic_param_list(), - value.where_clause(), + source.generic_param_list(), + source.where_clause(), ); ( Arc::new(UnionSignature { @@ -155,7 +168,7 @@ impl UnionSignature { store, flags, repr, - name: item_tree[loc.id.value].name.clone(), + name: as_name_opt(source.name()), }), Arc::new(source_map), ) @@ -181,8 +194,7 @@ pub struct EnumSignature { impl EnumSignature { pub fn query(db: &dyn DefDatabase, id: EnumId) -> (Arc, Arc) { let loc = id.lookup(db); - let item_tree = loc.id.item_tree(db); - let attrs = item_tree.attrs(db, loc.container.krate, ModItem::from(loc.id.value).into()); + let attrs = db.attrs(id.into()); let mut flags = EnumFlags::empty(); if attrs.by_key(sym::rustc_has_incoherent_inherent_impls).exists() { flags |= EnumFlags::RUSTC_HAS_INCOHERENT_INHERENT_IMPLS; @@ -190,14 +202,14 @@ impl EnumSignature { let repr = attrs.repr(); - let hir_expand::files::InFileWrapper { file_id, value } = loc.source(db); + let InFile { file_id, value: source } = loc.source(db); let (store, generic_params, source_map) = lower_generic_params( db, loc.container, id.into(), file_id, - value.generic_param_list(), - value.where_clause(), + source.generic_param_list(), + source.where_clause(), ); ( @@ -206,7 +218,7 @@ impl EnumSignature { store, flags, repr, - name: item_tree[loc.id.value].name.clone(), + name: as_name_opt(source.name()), }), Arc::new(source_map), ) @@ -239,10 +251,9 @@ pub struct ConstSignature { impl ConstSignature { pub fn query(db: &dyn DefDatabase, id: ConstId) -> (Arc, Arc) { let loc = id.lookup(db); - let item_tree = loc.id.item_tree(db); let module = loc.container.module(db); - let attrs = item_tree.attrs(db, module.krate, ModItem::from(loc.id.value).into()); + let attrs = db.attrs(id.into()); let mut flags = ConstFlags::empty(); if attrs.by_key(sym::rustc_allow_incoherent_impl).exists() { flags |= ConstFlags::RUSTC_ALLOW_INCOHERENT_IMPL; @@ -253,14 +264,14 @@ impl ConstSignature { } let (store, source_map, type_ref) = - crate::expr_store::lower::lower_type_ref(db, module, source.map(|it| it.ty())); + crate::expr_store::lower::lower_type_ref(db, module, source.as_ref().map(|it| it.ty())); ( Arc::new(ConstSignature { store: Arc::new(store), type_ref, flags, - name: item_tree[loc.id.value].name.clone(), + name: source.value.name().map(|it| it.as_name()), }), Arc::new(source_map), ) @@ -295,10 +306,9 @@ pub struct StaticSignature { impl StaticSignature { pub fn query(db: &dyn DefDatabase, id: StaticId) -> (Arc, Arc) { let loc = id.lookup(db); - let item_tree = loc.id.item_tree(db); let module = loc.container.module(db); - let attrs = item_tree.attrs(db, module.krate, ModItem::from(loc.id.value).into()); + let attrs = db.attrs(id.into()); let mut flags = StaticFlags::empty(); if attrs.by_key(sym::rustc_allow_incoherent_impl).exists() { flags |= StaticFlags::RUSTC_ALLOW_INCOHERENT_IMPL; @@ -323,14 +333,14 @@ impl StaticSignature { } let (store, source_map, type_ref) = - crate::expr_store::lower::lower_type_ref(db, module, source.map(|it| it.ty())); + crate::expr_store::lower::lower_type_ref(db, module, source.as_ref().map(|it| it.ty())); ( Arc::new(StaticSignature { store: Arc::new(store), type_ref, flags, - name: item_tree[loc.id.value].name.clone(), + name: as_name_opt(source.value.name()), }), Arc::new(source_map), ) @@ -407,10 +417,9 @@ pub struct TraitSignature { impl TraitSignature { pub fn query(db: &dyn DefDatabase, id: TraitId) -> (Arc, Arc) { let loc = id.lookup(db); - let item_tree = loc.id.item_tree(db); let mut flags = TraitFlags::empty(); - let attrs = item_tree.attrs(db, loc.container.krate, ModItem::from(loc.id.value).into()); + let attrs = db.attrs(id.into()); let source = loc.source(db); if source.value.auto_token().is_some() { flags.insert(TraitFlags::AUTO); @@ -446,15 +455,11 @@ impl TraitSignature { flags |= TraitFlags::SKIP_BOXED_SLICE_DURING_METHOD_DISPATCH; } + 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: item_tree[loc.id.value].name.clone(), - }), + Arc::new(TraitSignature { store: Arc::new(store), generic_params, flags, name }), Arc::new(source_map), ) } @@ -473,17 +478,13 @@ impl TraitAliasSignature { id: TraitAliasId, ) -> (Arc, Arc) { let loc = id.lookup(db); - let item_tree = loc.id.item_tree(db); let source = loc.source(db); + let name = as_name_opt(source.value.name()); let (store, source_map, generic_params) = lower_trait_alias(db, loc.container, source, id); ( - Arc::new(TraitAliasSignature { - generic_params, - store: Arc::new(store), - name: item_tree[loc.id.value].name.clone(), - }), + Arc::new(TraitAliasSignature { generic_params, store: Arc::new(store), name }), Arc::new(source_map), ) } @@ -530,10 +531,9 @@ impl FunctionSignature { ) -> (Arc, Arc) { let loc = id.lookup(db); let module = loc.container.module(db); - let item_tree = loc.id.item_tree(db); let mut flags = FnFlags::empty(); - let attrs = item_tree.attrs(db, module.krate, ModItem::from(loc.id.value).into()); + let attrs = db.attrs(id.into()); if attrs.by_key(sym::rustc_allow_incoherent_impl).exists() { flags.insert(FnFlags::RUSTC_ALLOW_INCOHERENT_IMPL); } @@ -568,6 +568,7 @@ impl FunctionSignature { flags.insert(FnFlags::HAS_BODY); } + let name = as_name_opt(source.value.name()); let abi = source.value.abi().map(|abi| { abi.abi_string().map_or_else(|| sym::C, |it| Symbol::intern(it.text_without_quotes())) }); @@ -588,7 +589,7 @@ impl FunctionSignature { abi, flags, legacy_const_generics_indices, - name: item_tree[loc.id.value].name.clone(), + name, }), Arc::new(source_map), ) @@ -662,14 +663,9 @@ impl TypeAliasSignature { id: TypeAliasId, ) -> (Arc, Arc) { let loc = id.lookup(db); - let item_tree = loc.id.item_tree(db); let mut flags = TypeAliasFlags::empty(); - let attrs = item_tree.attrs( - db, - loc.container.module(db).krate(), - ModItem::from(loc.id.value).into(), - ); + let attrs = db.attrs(id.into()); if attrs.by_key(sym::rustc_has_incoherent_inherent_impls).exists() { flags.insert(TypeAliasFlags::RUSTC_HAS_INCOHERENT_INHERENT_IMPL); } @@ -680,6 +676,7 @@ impl TypeAliasSignature { flags.insert(TypeAliasFlags::IS_EXTERN); } let source = loc.source(db); + let name = as_name_opt(source.value.name()); let (store, source_map, generic_params, bounds, ty) = lower_type_alias(db, loc.container.module(db), source, id); @@ -689,7 +686,7 @@ impl TypeAliasSignature { generic_params, flags, bounds, - name: item_tree[loc.id.value].name.clone(), + name, ty, }), Arc::new(source_map), @@ -743,104 +740,41 @@ impl VariantFields { let (shape, (fields, store, source_map)) = match id { VariantId::EnumVariantId(id) => { let loc = id.lookup(db); - let item_tree = loc.id.item_tree(db); let parent = loc.parent.lookup(db); - let variant = &item_tree[loc.id.value]; - ( - variant.shape, - lower_fields( - db, - parent.container, - &item_tree, - FieldParent::EnumVariant(loc.id.value), - loc.source(db).map(|src| { - variant.fields.iter().zip( - src.field_list() - .map(|it| { - match it { - ast::FieldList::RecordFieldList(record_field_list) => { - Either::Left(record_field_list.fields().map(|it| { - (SyntaxNodePtr::new(it.syntax()), it.ty()) - })) - } - ast::FieldList::TupleFieldList(field_list) => { - Either::Right(field_list.fields().map(|it| { - (SyntaxNodePtr::new(it.syntax()), it.ty()) - })) - } - } - .into_iter() - }) - .into_iter() - .flatten(), - ) - }), - Some(item_tree[parent.id.value].visibility), - ), - ) + let source = loc.source(db); + let shape = adt_shape(source.value.kind()); + let span_map = db.span_map(source.file_id); + let override_visibility = visibility_from_ast( + db, + source.value.parent_enum().visibility(), + &mut |range| span_map.span_for_range(range).ctx, + ); + let fields = lower_field_list( + db, + parent.container, + source.map(|src| src.field_list()), + Some(override_visibility), + ); + (shape, fields) } VariantId::StructId(id) => { let loc = id.lookup(db); - let item_tree = loc.id.item_tree(db); - let strukt = &item_tree[loc.id.value]; - ( - strukt.shape, - lower_fields( - db, - loc.container, - &item_tree, - FieldParent::Struct(loc.id.value), - loc.source(db).map(|src| { - strukt.fields.iter().zip( - src.field_list() - .map(|it| { - match it { - ast::FieldList::RecordFieldList(record_field_list) => { - Either::Left(record_field_list.fields().map(|it| { - (SyntaxNodePtr::new(it.syntax()), it.ty()) - })) - } - ast::FieldList::TupleFieldList(field_list) => { - Either::Right(field_list.fields().map(|it| { - (SyntaxNodePtr::new(it.syntax()), it.ty()) - })) - } - } - .into_iter() - }) - .into_iter() - .flatten(), - ) - }), - None, - ), - ) + let source = loc.source(db); + let shape = adt_shape(source.value.kind()); + let fields = + lower_field_list(db, loc.container, source.map(|src| src.field_list()), None); + (shape, fields) } VariantId::UnionId(id) => { let loc = id.lookup(db); - let item_tree = loc.id.item_tree(db); - let union = &item_tree[loc.id.value]; - ( - FieldsShape::Record, - lower_fields( - db, - loc.container, - &item_tree, - FieldParent::Union(loc.id.value), - loc.source(db).map(|src| { - union.fields.iter().zip( - src.record_field_list() - .map(|it| { - it.fields() - .map(|it| (SyntaxNodePtr::new(it.syntax()), it.ty())) - }) - .into_iter() - .flatten(), - ) - }), - None, - ), - ) + let source = loc.source(db); + let fields = lower_field_list( + db, + loc.container, + source.map(|src| src.record_field_list().map(ast::FieldList::RecordFieldList)), + None, + ); + (FieldsShape::Record, fields) } }; @@ -860,39 +794,81 @@ impl VariantFields { } } -fn lower_fields<'a>( +fn lower_field_list( db: &dyn DefDatabase, module: ModuleId, - item_tree: &ItemTree, - parent: FieldParent, - fields: InFile))>>, - override_visibility: Option, + fields: InFile>, + override_visibility: Option, +) -> (Arena, ExpressionStore, ExpressionStoreSourceMap) { + let file_id = fields.file_id; + match fields.value { + Some(ast::FieldList::RecordFieldList(fields)) => lower_fields( + db, + module, + InFile::new(file_id, fields.fields().map(|field| (field.ty(), field))), + |_, field| as_name_opt(field.name()), + override_visibility, + ), + Some(ast::FieldList::TupleFieldList(fields)) => lower_fields( + db, + module, + InFile::new(file_id, fields.fields().map(|field| (field.ty(), field))), + |idx, _| Name::new_tuple_field(idx), + override_visibility, + ), + None => lower_fields( + db, + module, + InFile::new(file_id, std::iter::empty::<(Option, ast::RecordField)>()), + |_, _| Name::missing(), + None, + ), + } +} + +fn lower_fields( + db: &dyn DefDatabase, + module: ModuleId, + fields: InFile, Field)>>, + mut field_name: impl FnMut(usize, &Field) -> Name, + override_visibility: Option, ) -> (Arena, ExpressionStore, ExpressionStoreSourceMap) { let mut arena = Arena::new(); let cfg_options = module.krate.cfg_options(db); let mut col = ExprCollector::new(db, module, fields.file_id); - for (idx, (field, (ptr, ty))) in fields.value.enumerate() { - let attr_owner = AttrOwner::make_field_indexed(parent, idx); - let attrs = item_tree.attrs(db, module.krate, attr_owner); - if attrs.is_cfg_enabled(cfg_options) { - arena.alloc(FieldData { - name: field.name.clone(), - type_ref: col - .lower_type_ref_opt(ty, &mut ExprCollector::impl_trait_error_allocator), - visibility: item_tree[override_visibility.unwrap_or(field.visibility)].clone(), - is_unsafe: field.is_unsafe, - }); - } else { - col.source_map.diagnostics.push( - crate::expr_store::ExpressionStoreDiagnostics::InactiveCode { - node: InFile::new(fields.file_id, ptr), - cfg: attrs.cfg().unwrap(), - opts: cfg_options.clone(), - }, - ); + let mut idx = 0; + for (ty, field) in fields.value { + match Attrs::is_cfg_enabled_for(db, &field, col.span_map(), cfg_options) { + Ok(()) => { + let type_ref = + col.lower_type_ref_opt(ty, &mut ExprCollector::impl_trait_error_allocator); + let visibility = override_visibility.clone().unwrap_or_else(|| { + visibility_from_ast(db, field.visibility(), &mut |range| { + col.span_map().span_for_range(range).ctx + }) + }); + let is_unsafe = field + .syntax() + .children_with_tokens() + .filter_map(NodeOrToken::into_token) + .any(|token| token.kind() == T![unsafe]); + let name = field_name(idx, &field); + arena.alloc(FieldData { name, type_ref, visibility, is_unsafe }); + idx += 1; + } + Err(cfg) => { + col.source_map.diagnostics.push( + crate::expr_store::ExpressionStoreDiagnostics::InactiveCode { + node: InFile::new(fields.file_id, SyntaxNodePtr::new(field.syntax())), + cfg, + opts: cfg_options.clone(), + }, + ); + } } } let store = col.store.finish(); + arena.shrink_to_fit(); (arena, store, col.source_map) } @@ -905,7 +881,7 @@ pub struct InactiveEnumVariantCode { #[derive(Debug, Clone, PartialEq, Eq)] pub struct EnumVariants { - pub variants: Box<[(EnumVariantId, Name)]>, + pub variants: Box<[(EnumVariantId, Name, FieldsShape)]>, } impl EnumVariants { @@ -914,30 +890,38 @@ impl EnumVariants { e: EnumId, ) -> (Arc, Option>>) { let loc = e.lookup(db); - let item_tree = loc.id.item_tree(db); + let source = loc.source(db); + let ast_id_map = db.ast_id_map(source.file_id); + let span_map = db.span_map(source.file_id); let mut diagnostics = ThinVec::new(); let cfg_options = loc.container.krate.cfg_options(db); let mut index = 0; - let variants = FileItemTreeId::range_iter(item_tree[loc.id.value].variants.clone()) + let Some(variants) = source.value.variant_list() else { + return (Arc::new(EnumVariants { variants: Box::default() }), None); + }; + let variants = variants + .variants() .filter_map(|variant| { - let attrs = item_tree.attrs(db, loc.container.krate, variant.into()); - if attrs.is_cfg_enabled(cfg_options) { - let enum_variant = EnumVariantLoc { - id: ItemTreeId::new(loc.id.tree_id(), variant), - parent: e, - index, + let ast_id = ast_id_map.ast_id(&variant); + match Attrs::is_cfg_enabled_for(db, &variant, span_map.as_ref(), cfg_options) { + Ok(()) => { + let enum_variant = + EnumVariantLoc { id: source.with_value(ast_id), parent: e, index } + .intern(db); + index += 1; + let name = as_name_opt(variant.name()); + let shape = adt_shape(variant.kind()); + Some((enum_variant, name, shape)) + } + Err(cfg) => { + diagnostics.push(InactiveEnumVariantCode { + ast_id, + cfg, + opts: cfg_options.clone(), + }); + None } - .intern(db); - index += 1; - Some((enum_variant, item_tree[variant].name.clone())) - } else { - diagnostics.push(InactiveEnumVariantCode { - ast_id: item_tree[variant].ast_id, - cfg: attrs.cfg().unwrap(), - opts: cfg_options.clone(), - }); - None } }) .collect(); @@ -949,12 +933,18 @@ impl EnumVariants { } pub fn variant(&self, name: &Name) -> Option { - self.variants.iter().find_map(|(v, n)| if n == name { Some(*v) } else { None }) + self.variants.iter().find_map(|(v, n, _)| if n == name { Some(*v) } else { None }) + } + + pub fn variant_name_by_id(&self, variant_id: EnumVariantId) -> Option { + self.variants + .iter() + .find_map(|(id, name, _)| if *id == variant_id { Some(name.clone()) } else { None }) } // [Adopted from rustc](https://github.com/rust-lang/rust/blob/bd53aa3bf7a24a70d763182303bd75e5fc51a9af/compiler/rustc_middle/src/ty/adt.rs#L446-L448) pub fn is_payload_free(&self, db: &dyn DefDatabase) -> bool { - self.variants.iter().all(|&(v, _)| { + self.variants.iter().all(|&(v, _, _)| { // The condition check order is slightly modified from rustc // to improve performance by early returning with relatively fast checks let variant = &db.variant_fields(v.into()); @@ -973,3 +963,17 @@ impl EnumVariants { }) } } + +pub(crate) fn extern_block_abi_query( + db: &dyn DefDatabase, + extern_block: ExternBlockId, +) -> Option { + let source = extern_block.lookup(db).source(db); + source.value.abi().map(|abi| { + match abi.abi_string() { + Some(tok) => Symbol::intern(tok.text_without_quotes()), + // `extern` default to be `extern "C"`. + _ => sym::C, + } + }) +} diff --git a/src/tools/rust-analyzer/crates/hir-def/src/src.rs b/src/tools/rust-analyzer/crates/hir-def/src/src.rs index 3867f39b8b173..aa373a27b0d52 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/src.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/src.rs @@ -1,15 +1,13 @@ //! Utilities for mapping between hir IDs and the surface syntax. use either::Either; -use hir_expand::InFile; -use la_arena::ArenaMap; +use hir_expand::{AstId, InFile}; +use la_arena::{Arena, ArenaMap, Idx}; use syntax::{AstNode, AstPtr, ast}; use crate::{ - GenericDefId, ItemTreeLoc, LocalFieldId, LocalLifetimeParamId, LocalTypeOrConstParamId, Lookup, - UseId, VariantId, - db::DefDatabase, - item_tree::{AttrOwner, FieldParent, ItemTreeNode}, + AstIdLoc, GenericDefId, LocalFieldId, LocalLifetimeParamId, LocalTypeOrConstParamId, Lookup, + UseId, VariantId, attr::Attrs, db::DefDatabase, }; pub trait HasSource { @@ -23,18 +21,13 @@ pub trait HasSource { impl HasSource for T where - T: ItemTreeLoc, - T::Id: ItemTreeNode, + T: AstIdLoc, { - type Value = ::Source; + type Value = T::Ast; fn ast_ptr(&self, db: &dyn DefDatabase) -> InFile> { - let id = self.item_tree_id(); - let file_id = id.file_id(); - let tree = id.item_tree(db); - let ast_id_map = db.ast_id_map(file_id); - let node = &tree[id.value]; - - InFile::new(file_id, ast_id_map.get(node.ast_id())) + let id = self.ast_id(); + let ast_id_map = db.ast_id_map(id.file_id); + InFile::new(id.file_id, ast_id_map.get(id.value)) } } @@ -43,18 +36,37 @@ pub trait HasChildSource { fn child_source(&self, db: &dyn DefDatabase) -> InFile>; } +/// Maps a `UseTree` contained in this import back to its AST node. +pub fn use_tree_to_ast( + db: &dyn DefDatabase, + use_ast_id: AstId, + index: Idx, +) -> ast::UseTree { + use_tree_source_map(db, use_ast_id)[index].clone() +} + +/// Maps a `UseTree` contained in this import back to its AST node. +fn use_tree_source_map(db: &dyn DefDatabase, use_ast_id: AstId) -> Arena { + // Re-lower the AST item and get the source map. + // Note: The AST unwraps are fine, since if they fail we should have never obtained `index`. + let ast = use_ast_id.to_node(db); + let ast_use_tree = ast.use_tree().expect("missing `use_tree`"); + let mut span_map = None; + crate::item_tree::lower_use_tree(db, ast_use_tree, &mut |range| { + span_map.get_or_insert_with(|| db.span_map(use_ast_id.file_id)).span_for_range(range).ctx + }) + .expect("failed to lower use tree") + .1 +} + impl HasChildSource> for UseId { type Value = ast::UseTree; fn child_source( &self, db: &dyn DefDatabase, ) -> InFile, Self::Value>> { - let loc = &self.lookup(db); - let use_ = &loc.id.item_tree(db)[loc.id.value]; - InFile::new( - loc.id.file_id(), - use_.use_tree_source_map(db, loc.id.file_id()).into_iter().collect(), - ) + let loc = self.lookup(db); + InFile::new(loc.id.file_id, use_tree_source_map(db, loc.id).into_iter().collect()) } } @@ -124,49 +136,30 @@ impl HasChildSource for VariantId { type Value = Either; fn child_source(&self, db: &dyn DefDatabase) -> InFile> { - let item_tree; - let (src, parent, container) = match *self { + let (src, container) = match *self { VariantId::EnumVariantId(it) => { let lookup = it.lookup(db); - item_tree = lookup.id.item_tree(db); - ( - lookup.source(db).map(|it| it.kind()), - FieldParent::EnumVariant(lookup.id.value), - lookup.parent.lookup(db).container, - ) + (lookup.source(db).map(|it| it.kind()), lookup.parent.lookup(db).container) } VariantId::StructId(it) => { let lookup = it.lookup(db); - item_tree = lookup.id.item_tree(db); - ( - lookup.source(db).map(|it| it.kind()), - FieldParent::Struct(lookup.id.value), - lookup.container, - ) + (lookup.source(db).map(|it| it.kind()), lookup.container) } VariantId::UnionId(it) => { let lookup = it.lookup(db); - item_tree = lookup.id.item_tree(db); - ( - lookup.source(db).map(|it| it.kind()), - FieldParent::Union(lookup.id.value), - lookup.container, - ) + (lookup.source(db).map(|it| it.kind()), lookup.container) } }; - + let span_map = db.span_map(src.file_id); let mut map = ArenaMap::new(); match &src.value { ast::StructKind::Tuple(fl) => { let cfg_options = container.krate.cfg_options(db); let mut idx = 0; - for (i, fd) in fl.fields().enumerate() { - let attrs = item_tree.attrs( - db, - container.krate, - AttrOwner::make_field_indexed(parent, i), - ); - if !attrs.is_cfg_enabled(cfg_options) { + for fd in fl.fields() { + let enabled = + Attrs::is_cfg_enabled_for(db, &fd, span_map.as_ref(), cfg_options).is_ok(); + if !enabled { continue; } map.insert( @@ -179,13 +172,10 @@ impl HasChildSource for VariantId { ast::StructKind::Record(fl) => { let cfg_options = container.krate.cfg_options(db); let mut idx = 0; - for (i, fd) in fl.fields().enumerate() { - let attrs = item_tree.attrs( - db, - container.krate, - AttrOwner::make_field_indexed(parent, i), - ); - if !attrs.is_cfg_enabled(cfg_options) { + for fd in fl.fields() { + let enabled = + Attrs::is_cfg_enabled_for(db, &fd, span_map.as_ref(), cfg_options).is_ok(); + if !enabled { continue; } map.insert( @@ -195,7 +185,7 @@ impl HasChildSource for VariantId { idx += 1; } } - _ => (), + ast::StructKind::Unit => (), } InFile::new(src.file_id, map) } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/visibility.rs b/src/tools/rust-analyzer/crates/hir-def/src/visibility.rs index 3c67ee9fe5b3a..14d67ea804ff2 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/visibility.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/visibility.rs @@ -2,16 +2,18 @@ use std::iter; -use hir_expand::Lookup; +use hir_expand::{InFile, Lookup}; use la_arena::ArenaMap; +use syntax::ast::{self, HasVisibility}; use triomphe::Arc; use crate::{ - ConstId, FunctionId, HasModule, ItemContainerId, ItemLoc, ItemTreeLoc, LocalFieldId, - LocalModuleId, ModuleId, TraitId, TypeAliasId, VariantId, + ConstId, FunctionId, HasModule, ItemContainerId, LocalFieldId, LocalModuleId, ModuleId, + TraitId, TypeAliasId, VariantId, db::DefDatabase, nameres::DefMap, resolver::{HasResolver, Resolver}, + src::HasSource, }; pub use crate::item_tree::{RawVisibility, VisibilityExplicitness}; @@ -217,49 +219,69 @@ pub(crate) fn field_visibilities_query( for (field_id, field_data) in fields.iter() { res.insert(field_id, Visibility::resolve(db, &resolver, &field_data.visibility)); } + res.shrink_to_fit(); Arc::new(res) } +pub fn visibility_from_ast( + db: &dyn DefDatabase, + resolver: &Resolver<'_>, + ast_vis: InFile>, +) -> Visibility { + let mut span_map = None; + let raw_vis = crate::item_tree::visibility_from_ast(db, ast_vis.value, &mut |range| { + span_map.get_or_insert_with(|| db.span_map(ast_vis.file_id)).span_for_range(range).ctx + }); + Visibility::resolve(db, resolver, &raw_vis) +} + +fn trait_item_visibility( + db: &dyn DefDatabase, + resolver: &Resolver<'_>, + container: ItemContainerId, +) -> Option { + match container { + ItemContainerId::TraitId(trait_) => Some(trait_visibility(db, resolver, trait_)), + _ => None, + } +} + /// Resolve visibility of a function. pub(crate) fn function_visibility_query(db: &dyn DefDatabase, def: FunctionId) -> Visibility { - let resolver = def.resolver(db); let loc = def.lookup(db); - let tree = loc.item_tree_id().item_tree(db); - if let ItemContainerId::TraitId(trait_id) = loc.container { - trait_vis(db, &resolver, trait_id) - } else { - Visibility::resolve(db, &resolver, &tree[tree[loc.id.value].visibility]) - } + let resolver = def.resolver(db); + trait_item_visibility(db, &resolver, loc.container).unwrap_or_else(|| { + let source = loc.source(db); + visibility_from_ast(db, &resolver, source.map(|src| src.visibility())) + }) } /// Resolve visibility of a const. pub(crate) fn const_visibility_query(db: &dyn DefDatabase, def: ConstId) -> Visibility { - let resolver = def.resolver(db); let loc = def.lookup(db); - let tree = loc.item_tree_id().item_tree(db); - if let ItemContainerId::TraitId(trait_id) = loc.container { - trait_vis(db, &resolver, trait_id) - } else { - Visibility::resolve(db, &resolver, &tree[tree[loc.id.value].visibility]) - } + let resolver = def.resolver(db); + trait_item_visibility(db, &resolver, loc.container).unwrap_or_else(|| { + let source = loc.source(db); + visibility_from_ast(db, &resolver, source.map(|src| src.visibility())) + }) } /// Resolve visibility of a type alias. pub(crate) fn type_alias_visibility_query(db: &dyn DefDatabase, def: TypeAliasId) -> Visibility { - let resolver = def.resolver(db); let loc = def.lookup(db); - let tree = loc.item_tree_id().item_tree(db); - if let ItemContainerId::TraitId(trait_id) = loc.container { - trait_vis(db, &resolver, trait_id) - } else { - Visibility::resolve(db, &resolver, &tree[tree[loc.id.value].visibility]) - } + let resolver = def.resolver(db); + trait_item_visibility(db, &resolver, loc.container).unwrap_or_else(|| { + let source = loc.source(db); + visibility_from_ast(db, &resolver, source.map(|src| src.visibility())) + }) } -#[inline] -fn trait_vis(db: &dyn DefDatabase, resolver: &Resolver<'_>, trait_id: TraitId) -> Visibility { - let ItemLoc { id: tree_id, .. } = trait_id.lookup(db); - let item_tree = tree_id.item_tree(db); - let tr_def = &item_tree[tree_id.value]; - Visibility::resolve(db, resolver, &item_tree[tr_def.visibility]) +pub(crate) fn trait_visibility( + db: &dyn DefDatabase, + resolver: &Resolver<'_>, + def: TraitId, +) -> Visibility { + let loc = def.lookup(db); + let source = loc.source(db); + visibility_from_ast(db, resolver, source.map(|src| src.visibility())) } diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/files.rs b/src/tools/rust-analyzer/crates/hir-expand/src/files.rs index e8f6b82434ee4..a73a22370d240 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/files.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/files.rs @@ -2,7 +2,7 @@ use std::borrow::Borrow; use either::Either; -use span::{ErasedFileAstId, FileAstId, FileId, SyntaxContext}; +use span::{AstIdNode, ErasedFileAstId, FileAstId, FileId, SyntaxContext}; use syntax::{AstNode, AstPtr, SyntaxNode, SyntaxNodePtr, SyntaxToken, TextRange, TextSize}; use crate::{ @@ -122,6 +122,13 @@ impl AstId { pub fn erase(&self) -> ErasedAstId { crate::InFile::new(self.file_id, self.value.erase()) } + #[inline] + pub fn upcast(self) -> AstId + where + N: Into, + { + self.map(|it| it.upcast()) + } } pub type ErasedAstId = crate::InFile; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs index 22b96b55cbb9d..710ac6e54223c 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs @@ -817,7 +817,7 @@ pub(crate) fn adt_datum_query( .enum_variants(id) .variants .iter() - .map(|&(variant_id, _)| variant_id_to_fields(variant_id.into())) + .map(|&(variant_id, _, _)| variant_id_to_fields(variant_id.into())) .collect(); (rust_ir::AdtKind::Enum, variants) } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check.rs index 099100a73288d..fae129fddbfe5 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check.rs @@ -397,7 +397,7 @@ impl<'a> DeclValidator<'a> { fn validate_enum_variants(&mut self, enum_id: EnumId) { let data = self.db.enum_variants(enum_id); - for (variant_id, _) in data.variants.iter() { + for (variant_id, _, _) in data.variants.iter() { self.validate_enum_variant_fields(*variant_id); } @@ -405,7 +405,7 @@ impl<'a> DeclValidator<'a> { let mut enum_variants_replacements = data .variants .iter() - .filter_map(|(_, name)| { + .filter_map(|(_, name, _)| { to_camel_case(&name.display_no_db(edition).to_smolstr()).map(|new_name| { Replacement { current_name: name.clone(), diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs index dd82a0f45ca44..0914b5aac5070 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs @@ -465,7 +465,7 @@ impl PatCx for MatchCheckCtx<'_> { ConstructorSet::NoConstructors } else { let mut variants = IndexVec::with_capacity(enum_data.variants.len()); - for &(variant, _) in enum_data.variants.iter() { + for &(variant, _, _) in enum_data.variants.iter() { let is_uninhabited = is_enum_variant_uninhabited_from( cx.db, variant, diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/drop.rs b/src/tools/rust-analyzer/crates/hir-ty/src/drop.rs index 70763759ef0ee..b9b0f9828661b 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/drop.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/drop.rs @@ -71,7 +71,7 @@ pub(crate) fn has_drop_glue(db: &dyn HirDatabase, ty: Ty, env: Arc { AdtId::EnumId(e) => { let enum_data = self.db.enum_variants(e); - for &(variant, _) in enum_data.variants.iter() { + for &(variant, _, _) in enum_data.variants.iter() { let variant_inhabitedness = self.visit_variant(variant.into(), subst); match variant_inhabitedness { Break(VisiblyUninhabited) => (), diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/layout/adt.rs b/src/tools/rust-analyzer/crates/hir-ty/src/layout/adt.rs index 3a020bf050d68..a886c33d157b0 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/layout/adt.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/layout/adt.rs @@ -60,7 +60,7 @@ pub fn layout_of_adt_query( let r = variants .variants .iter() - .map(|&(v, _)| handle_variant(v.into(), &db.variant_fields(v.into()))) + .map(|&(v, _, _)| handle_variant(v.into(), &db.variant_fields(v.into()))) .collect::, _>>()?; (r, db.enum_signature(e).repr.unwrap_or_default(), false) } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs index 21e5428520e2a..8fb8d64779bd7 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs @@ -2771,12 +2771,15 @@ impl Evaluator<'_> { Err(e) => { let db = self.db; let loc = variant.lookup(db); - let enum_loc = loc.parent.lookup(db); let edition = self.crate_id.data(self.db).edition; let name = format!( "{}::{}", - enum_loc.id.item_tree(db)[enum_loc.id.value].name.display(db, edition), - loc.id.item_tree(db)[loc.id.value].name.display(db, edition), + self.db.enum_signature(loc.parent).name.display(db, edition), + self.db + .enum_variants(loc.parent) + .variant_name_by_id(variant) + .unwrap() + .display(db, edition), ); Err(MirEvalError::ConstEvalError(name, Box::new(e))) } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs index 90c52ee96f1ff..512a275aa7594 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs @@ -65,9 +65,7 @@ impl Evaluator<'_> { Some(abi) => *abi == sym::rust_dash_intrinsic, None => match def.lookup(self.db).container { hir_def::ItemContainerId::ExternBlockId(block) => { - let id = block.lookup(self.db).id; - id.item_tree(self.db)[id.value].abi.as_ref() - == Some(&sym::rust_dash_intrinsic) + self.db.extern_block_abi(block) == Some(sym::rust_dash_intrinsic) } _ => false, }, @@ -87,8 +85,7 @@ impl Evaluator<'_> { } let is_extern_c = match def.lookup(self.db).container { hir_def::ItemContainerId::ExternBlockId(block) => { - let id = block.lookup(self.db).id; - id.item_tree(self.db)[id.value].abi.as_ref() == Some(&sym::C) + self.db.extern_block_abi(block) == Some(sym::C) } _ => false, }; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs index 99d935153037a..ef1f215500c24 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs @@ -1922,11 +1922,14 @@ impl<'ctx> MirLowerCtx<'ctx> { let edition = self.edition(); let db = self.db; let loc = variant.lookup(db); - let enum_loc = loc.parent.lookup(db); let name = format!( "{}::{}", - enum_loc.id.item_tree(db)[enum_loc.id.value].name.display(db, edition), - loc.id.item_tree(db)[loc.id.value].name.display(db, edition), + self.db.enum_signature(loc.parent).name.display(db, edition), + self.db + .enum_variants(loc.parent) + .variant_name_by_id(variant) + .unwrap() + .display(db, edition), ); Err(MirLowerError::ConstEvalError(name.into(), Box::new(e))) } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/pretty.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/pretty.rs index 7ae6e907e7adb..91dc2627d1847 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/pretty.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/pretty.rs @@ -63,16 +63,15 @@ impl MirBody { } hir_def::DefWithBodyId::VariantId(id) => { let loc = id.lookup(db); - let enum_loc = loc.parent.lookup(db); + let edition = this.display_target.edition; w!( this, "enum {}::{} = ", - enum_loc.id.item_tree(db)[enum_loc.id.value] - .name - .display(db, this.display_target.edition), - loc.id.item_tree(db)[loc.id.value] - .name - .display(db, this.display_target.edition), + db.enum_signature(loc.parent).name.display(db, edition), + db.enum_variants(loc.parent) + .variant_name_by_id(id) + .unwrap() + .display(db, edition), ) } }); diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests.rs index 2b75bd6f16040..48af7b2e32a2e 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/tests.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests.rs @@ -479,7 +479,7 @@ pub(crate) fn visit_module( visit_body(db, &body, cb); } ModuleDefId::AdtId(hir_def::AdtId::EnumId(it)) => { - db.enum_variants(it).variants.iter().for_each(|&(it, _)| { + db.enum_variants(it).variants.iter().for_each(|&(it, _, _)| { let body = db.body(it.into()); cb(it.into()); visit_body(db, &body, cb); diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/incremental.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/incremental.rs index 6ac260ac768b9..a055ef879d6a5 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/incremental.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/incremental.rs @@ -353,6 +353,7 @@ impl SomeStruct { "impl_self_ty_with_diagnostics_shim".to_owned(), "struct_signature_shim".to_owned(), "struct_signature_with_source_map_shim".to_owned(), + "attrs_shim".to_owned(), "type_for_adt_tracked".to_owned(), ]; @@ -442,6 +443,6 @@ fn main() { let _inference_result = db.infer(def); } }); - assert!(format!("{events:?}").contains("trait_solve_shim")) + assert!(!format!("{events:?}").contains("trait_solve_shim")) } } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs b/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs index 1e0ff423ded62..f797e60b05e71 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs @@ -293,9 +293,7 @@ pub fn is_fn_unsafe_to_call( let loc = func.lookup(db); match loc.container { hir_def::ItemContainerId::ExternBlockId(block) => { - let id = block.lookup(db).id; - let is_intrinsic_block = - id.item_tree(db)[id.value].abi.as_ref() == Some(&sym::rust_dash_intrinsic); + let is_intrinsic_block = db.extern_block_abi(block) == Some(sym::rust_dash_intrinsic); if is_intrinsic_block { // legacy intrinsics // extern "rust-intrinsic" intrinsics are unsafe unless they have the rustc_safe_intrinsic attribute diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/variance.rs b/src/tools/rust-analyzer/crates/hir-ty/src/variance.rs index d6b43aeed4d00..62478d4fd86c5 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/variance.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/variance.rs @@ -213,7 +213,7 @@ impl Context<'_> { AdtId::StructId(s) => add_constraints_from_variant(VariantId::StructId(s)), AdtId::UnionId(u) => add_constraints_from_variant(VariantId::UnionId(u)), AdtId::EnumId(e) => { - db.enum_variants(e).variants.iter().for_each(|&(variant, _)| { + db.enum_variants(e).variants.iter().for_each(|&(variant, _, _)| { add_constraints_from_variant(VariantId::EnumVariantId(variant)) }); } diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs index 969fd3eb480c9..c746b88c5b117 100644 --- a/src/tools/rust-analyzer/crates/hir/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs @@ -52,12 +52,14 @@ use hir_def::{ BindingAnnotation, BindingId, Expr, ExprId, ExprOrPatId, LabelId, Pat, generics::{LifetimeParamData, TypeOrConstParamData, TypeParamProvenance}, }, - item_tree::{AttrOwner, FieldParent, ImportAlias, ItemTreeFieldId, ItemTreeNode}, + item_tree::ImportAlias, layout::{self, ReprOptions, TargetDataLayout}, nameres::{self, diagnostics::DefDiagnostic}, per_ns::PerNs, resolver::{HasResolver, Resolver}, signatures::{ImplFlags, StaticFlags, TraitFlags, VariantFields}, + src::HasSource as _, + visibility::visibility_from_ast, }; use hir_expand::{ AstId, MacroCallKind, RenderedExpandError, ValueResult, attrs::collect_attrs, @@ -81,11 +83,11 @@ use itertools::Itertools; use nameres::diagnostics::DefDiagnosticKind; use rustc_hash::FxHashSet; use smallvec::SmallVec; -use span::{Edition, FileId}; +use span::{AstIdNode, Edition, FileId}; use stdx::{format_to, impl_from, never}; use syntax::{ AstNode, AstPtr, SmolStr, SyntaxNode, SyntaxNodePtr, T, TextRange, ToSmolStr, - ast::{self, HasAttrs as _, HasName}, + ast::{self, HasAttrs as _, HasName, HasVisibility as _}, format_smolstr, }; use triomphe::{Arc, ThinArc}; @@ -687,7 +689,7 @@ impl Module { let source_map = db.enum_signature_with_source_map(e.id).1; expr_store_diagnostics(db, acc, &source_map); let (variants, diagnostics) = db.enum_variants_with_diagnostics(e.id); - let file = e.id.lookup(db).id.file_id(); + let file = e.id.lookup(db).id.file_id; let ast_id_map = db.ast_id_map(file); if let Some(diagnostics) = &diagnostics { for diag in diagnostics.iter() { @@ -704,7 +706,7 @@ impl Module { ); } } - for &(v, _) in &variants.variants { + for &(v, _, _) in &variants.variants { let source_map = db.variant_fields_with_source_map(v.into()).1; push_ty_diagnostics( db, @@ -742,12 +744,10 @@ impl Module { GenericDef::Impl(impl_def).diagnostics(db, acc); let loc = impl_def.id.lookup(db); - let tree = loc.id.item_tree(db); let source_map = db.impl_signature_with_source_map(impl_def.id).1; expr_store_diagnostics(db, acc, &source_map); - let node = &tree[loc.id.value]; - let file_id = loc.id.file_id(); + let file_id = loc.id.file_id; if file_id.macro_file().is_some_and(|it| it.kind(db) == MacroKind::DeriveBuiltIn) { // these expansion come from us, diagnosing them is a waste of resources // FIXME: Once we diagnose the inputs to builtin derives, we should at least extract those diagnostics somehow @@ -765,11 +765,11 @@ impl Module { } if inherent_impls.invalid_impls().contains(&impl_def.id) { - acc.push(IncoherentImpl { impl_: ast_id_map.get(node.ast_id()), file_id }.into()) + acc.push(IncoherentImpl { impl_: ast_id_map.get(loc.id.value), file_id }.into()) } if !impl_def.check_orphan_rules(db) { - acc.push(TraitImplOrphan { impl_: ast_id_map.get(node.ast_id()), file_id }.into()) + acc.push(TraitImplOrphan { impl_: ast_id_map.get(loc.id.value), file_id }.into()) } let trait_ = impl_def.trait_(db); @@ -808,11 +808,11 @@ impl Module { // unsafe negative impl (true, _, true, _) | // unsafe impl for safe trait - (true, false, _, false) => acc.push(TraitImplIncorrectSafety { impl_: ast_id_map.get(node.ast_id()), file_id, should_be_safe: true }.into()), + (true, false, _, false) => acc.push(TraitImplIncorrectSafety { impl_: ast_id_map.get(loc.id.value), file_id, should_be_safe: true }.into()), // safe impl for unsafe trait (false, true, false, _) | // safe impl of dangling drop - (false, false, _, true) => acc.push(TraitImplIncorrectSafety { impl_: ast_id_map.get(node.ast_id()), file_id, should_be_safe: false }.into()), + (false, false, _, true) => acc.push(TraitImplIncorrectSafety { impl_: ast_id_map.get(loc.id.value), file_id, should_be_safe: false }.into()), _ => (), }; @@ -839,7 +839,7 @@ impl Module { TraitImplRedundantAssocItems { trait_, file_id, - impl_: ast_id_map.get(node.ast_id()), + impl_: ast_id_map.get(loc.id.value), assoc_item: (name, assoc_item), } .into(), @@ -889,7 +889,7 @@ impl Module { if !missing.is_empty() { acc.push( TraitImplMissingAssocItems { - impl_: ast_id_map.get(node.ast_id()), + impl_: ast_id_map.get(loc.id.value), file_id, missing, } @@ -1076,73 +1076,25 @@ fn emit_def_diagnostic_( ) } DefDiagnosticKind::UnresolvedImport { id, index } => { - let file_id = id.file_id(); - let item_tree = id.item_tree(db); - let import = &item_tree[id.value]; + let file_id = id.file_id; - let use_tree = import.use_tree_to_ast(db, file_id, *index); + let use_tree = hir_def::src::use_tree_to_ast(db, *id, *index); acc.push( UnresolvedImport { decl: InFile::new(file_id, AstPtr::new(&use_tree)) }.into(), ); } - DefDiagnosticKind::UnconfiguredCode { tree, item, cfg, opts } => { - let item_tree = tree.item_tree(db); - let ast_id_map = db.ast_id_map(tree.file_id()); - // FIXME: This parses... We could probably store relative ranges for the children things - // here in the item tree? - (|| { - let process_field_list = - |field_list: Option<_>, idx: ItemTreeFieldId| match field_list? { - ast::FieldList::RecordFieldList(it) => Some(SyntaxNodePtr::new( - it.fields().nth(idx.into_raw().into_u32() as usize)?.syntax(), - )), - ast::FieldList::TupleFieldList(it) => Some(SyntaxNodePtr::new( - it.fields().nth(idx.into_raw().into_u32() as usize)?.syntax(), - )), - }; - let ptr = match *item { - AttrOwner::ModItem(it) => { - ast_id_map.get(it.ast_id(&item_tree)).syntax_node_ptr() - } - AttrOwner::TopLevel => ast_id_map.root(), - AttrOwner::Variant(it) => { - ast_id_map.get(item_tree[it].ast_id).syntax_node_ptr() - } - AttrOwner::Field(FieldParent::EnumVariant(parent), idx) => process_field_list( - ast_id_map - .get(item_tree[parent].ast_id) - .to_node(&db.parse_or_expand(tree.file_id())) - .field_list(), - idx, - )?, - AttrOwner::Field(FieldParent::Struct(parent), idx) => process_field_list( - ast_id_map - .get(item_tree[parent.index()].ast_id) - .to_node(&db.parse_or_expand(tree.file_id())) - .field_list(), - idx, - )?, - AttrOwner::Field(FieldParent::Union(parent), idx) => SyntaxNodePtr::new( - ast_id_map - .get(item_tree[parent.index()].ast_id) - .to_node(&db.parse_or_expand(tree.file_id())) - .record_field_list()? - .fields() - .nth(idx.into_raw().into_u32() as usize)? - .syntax(), - ), - }; - acc.push( - InactiveCode { - node: InFile::new(tree.file_id(), ptr), - cfg: cfg.clone(), - opts: opts.clone(), - } - .into(), - ); - Some(()) - })(); + DefDiagnosticKind::UnconfiguredCode { ast_id, cfg, opts } => { + let ast_id_map = db.ast_id_map(ast_id.file_id); + let ptr = ast_id_map.get_erased(ast_id.value); + acc.push( + InactiveCode { + node: InFile::new(ast_id.file_id, ptr), + cfg: cfg.clone(), + opts: opts.clone(), + } + .into(), + ); } DefDiagnosticKind::UnresolvedMacroCall { ast, path } => { let (node, precise_location) = precise_macro_call_location(ast, db); @@ -1478,12 +1430,8 @@ impl Struct { impl HasVisibility for Struct { fn visibility(&self, db: &dyn HirDatabase) -> Visibility { let loc = self.id.lookup(db); - let item_tree = loc.id.item_tree(db); - Visibility::resolve( - db, - &self.id.resolver(db), - &item_tree[item_tree[loc.id.value].visibility], - ) + let source = loc.source(db); + visibility_from_ast(db, &self.id.resolver(db), source.map(|src| src.visibility())) } } @@ -1536,12 +1484,8 @@ impl Union { impl HasVisibility for Union { fn visibility(&self, db: &dyn HirDatabase) -> Visibility { let loc = self.id.lookup(db); - let item_tree = loc.id.item_tree(db); - Visibility::resolve( - db, - &self.id.resolver(db), - &item_tree[item_tree[loc.id.value].visibility], - ) + let source = loc.source(db); + visibility_from_ast(db, &self.id.resolver(db), source.map(|src| src.visibility())) } } @@ -1560,7 +1504,7 @@ impl Enum { } pub fn variants(self, db: &dyn HirDatabase) -> Vec { - db.enum_variants(self.id).variants.iter().map(|&(id, _)| Variant { id }).collect() + db.enum_variants(self.id).variants.iter().map(|&(id, _, _)| Variant { id }).collect() } pub fn num_variants(self, db: &dyn HirDatabase) -> usize { @@ -1629,12 +1573,8 @@ impl Enum { impl HasVisibility for Enum { fn visibility(&self, db: &dyn HirDatabase) -> Visibility { let loc = self.id.lookup(db); - let item_tree = loc.id.item_tree(db); - Visibility::resolve( - db, - &self.id.resolver(db), - &item_tree[item_tree[loc.id.value].visibility], - ) + let source = loc.source(db); + visibility_from_ast(db, &self.id.resolver(db), source.map(|src| src.visibility())) } } @@ -2708,10 +2648,9 @@ impl ExternCrateDecl { pub fn resolved_crate(self, db: &dyn HirDatabase) -> Option { let loc = self.id.lookup(db); - let item_tree = loc.id.item_tree(db); let krate = loc.container.krate(); - let name = &item_tree[loc.id.value].name; - if *name == sym::self_ { + let name = self.name(db); + if name == sym::self_ { Some(krate.into()) } else { krate.data(db).dependencies.iter().find_map(|dep| { @@ -2722,25 +2661,29 @@ impl ExternCrateDecl { pub fn name(self, db: &dyn HirDatabase) -> Name { let loc = self.id.lookup(db); - let item_tree = loc.id.item_tree(db); - item_tree[loc.id.value].name.clone() + let source = loc.source(db); + as_name_opt(source.value.name_ref()) } pub fn alias(self, db: &dyn HirDatabase) -> Option { let loc = self.id.lookup(db); - let item_tree = loc.id.item_tree(db); - item_tree[loc.id.value].alias.clone() + let source = loc.source(db); + let rename = source.value.rename()?; + if let Some(name) = rename.name() { + Some(ImportAlias::Alias(name.as_name())) + } else if rename.underscore_token().is_some() { + Some(ImportAlias::Underscore) + } else { + None + } } /// Returns the name under which this crate is made accessible, taking `_` into account. pub fn alias_or_name(self, db: &dyn HirDatabase) -> Option { - let loc = self.id.lookup(db); - let item_tree = loc.id.item_tree(db); - - match &item_tree[loc.id.value].alias { + match self.alias(db) { Some(ImportAlias::Underscore) => None, - Some(ImportAlias::Alias(alias)) => Some(alias.clone()), - None => Some(item_tree[loc.id.value].name.clone()), + Some(ImportAlias::Alias(alias)) => Some(alias), + None => Some(self.name(db)), } } } @@ -2748,12 +2691,8 @@ impl ExternCrateDecl { impl HasVisibility for ExternCrateDecl { fn visibility(&self, db: &dyn HirDatabase) -> Visibility { let loc = self.id.lookup(db); - let item_tree = loc.id.item_tree(db); - Visibility::resolve( - db, - &self.id.resolver(db), - &item_tree[item_tree[loc.id.value].visibility], - ) + let source = loc.source(db); + visibility_from_ast(db, &self.id.resolver(db), source.map(|src| src.visibility())) } } @@ -2873,12 +2812,8 @@ impl Static { impl HasVisibility for Static { fn visibility(&self, db: &dyn HirDatabase) -> Visibility { let loc = self.id.lookup(db); - let item_tree = loc.id.item_tree(db); - Visibility::resolve( - db, - &self.id.resolver(db), - &item_tree[item_tree[loc.id.value].visibility], - ) + let source = loc.source(db); + visibility_from_ast(db, &self.id.resolver(db), source.map(|src| src.visibility())) } } @@ -2967,11 +2902,7 @@ impl Trait { } fn all_macro_calls(&self, db: &dyn HirDatabase) -> Box<[(AstId, MacroCallId)]> { - db.trait_items(self.id) - .macro_calls - .as_ref() - .map(|it| it.as_ref().clone().into_boxed_slice()) - .unwrap_or_default() + db.trait_items(self.id).macro_calls.to_vec().into_boxed_slice() } /// `#[rust_analyzer::completions(...)]` mode. @@ -2983,12 +2914,8 @@ impl Trait { impl HasVisibility for Trait { fn visibility(&self, db: &dyn HirDatabase) -> Visibility { let loc = self.id.lookup(db); - let item_tree = loc.id.item_tree(db); - Visibility::resolve( - db, - &self.id.resolver(db), - &item_tree[item_tree[loc.id.value].visibility], - ) + let source = loc.source(db); + visibility_from_ast(db, &self.id.resolver(db), source.map(|src| src.visibility())) } } @@ -3010,12 +2937,8 @@ impl TraitAlias { impl HasVisibility for TraitAlias { fn visibility(&self, db: &dyn HirDatabase) -> Visibility { let loc = self.id.lookup(db); - let item_tree = loc.id.item_tree(db); - Visibility::resolve( - db, - &self.id.resolver(db), - &item_tree[item_tree[loc.id.value].visibility], - ) + let source = loc.source(db); + visibility_from_ast(db, &self.id.resolver(db), source.map(|src| src.visibility())) } } @@ -3163,25 +3086,23 @@ impl Macro { match self.id { MacroId::Macro2Id(id) => { let loc = id.lookup(db); - let item_tree = loc.id.item_tree(db); - item_tree[loc.id.value].name.clone() + let source = loc.source(db); + as_name_opt(source.value.name()) } MacroId::MacroRulesId(id) => { let loc = id.lookup(db); - let item_tree = loc.id.item_tree(db); - item_tree[loc.id.value].name.clone() + let source = loc.source(db); + as_name_opt(source.value.name()) } MacroId::ProcMacroId(id) => { let loc = id.lookup(db); - let item_tree = loc.id.item_tree(db); + let source = loc.source(db); match loc.kind { ProcMacroKind::CustomDerive => db .attrs(id.into()) .parse_proc_macro_derive() - .map_or_else(|| item_tree[loc.id.value].name.clone(), |(it, _)| it), - ProcMacroKind::Bang | ProcMacroKind::Attr => { - item_tree[loc.id.value].name.clone() - } + .map_or_else(|| as_name_opt(source.value.name()), |(it, _)| it), + ProcMacroKind::Bang | ProcMacroKind::Attr => as_name_opt(source.value.name()), } } } @@ -3278,12 +3199,8 @@ impl HasVisibility for Macro { match self.id { MacroId::Macro2Id(id) => { let loc = id.lookup(db); - let item_tree = loc.id.item_tree(db); - Visibility::resolve( - db, - &id.resolver(db), - &item_tree[item_tree[loc.id.value].visibility], - ) + let source = loc.source(db); + visibility_from_ast(db, &id.resolver(db), source.map(|src| src.visibility())) } MacroId::MacroRulesId(_) => Visibility::Public, MacroId::ProcMacroId(_) => Visibility::Public, @@ -3437,7 +3354,7 @@ fn as_assoc_item<'db, ID, DEF, LOC>( where ID: Lookup>, DEF: From, - LOC: ItemTreeNode, + LOC: AstIdNode, { match id.lookup(db).container { ItemContainerId::TraitId(_) | ItemContainerId::ImplId(_) => Some(ctor(DEF::from(id))), @@ -3453,7 +3370,7 @@ fn as_extern_assoc_item<'db, ID, DEF, LOC>( where ID: Lookup>, DEF: From, - LOC: ItemTreeNode, + LOC: AstIdNode, { match id.lookup(db).container { ItemContainerId::ExternBlockId(_) => Some(ctor(DEF::from(id))), @@ -4545,11 +4462,7 @@ impl Impl { } fn all_macro_calls(&self, db: &dyn HirDatabase) -> Box<[(AstId, MacroCallId)]> { - db.impl_items(self.id) - .macro_calls - .as_ref() - .map(|it| it.as_ref().clone().into_boxed_slice()) - .unwrap_or_default() + db.impl_items(self.id).macro_calls.to_vec().into_boxed_slice() } } @@ -6510,3 +6423,7 @@ pub fn resolve_absolute_path<'a, I: Iterator + Clone + 'a>( }) .flatten() } + +fn as_name_opt(name: Option) -> Name { + name.map_or_else(Name::missing, |name| name.as_name()) +} diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics/child_by_source.rs b/src/tools/rust-analyzer/crates/hir/src/semantics/child_by_source.rs index 1a6d63c88c626..ea44451a8ee4a 100644 --- a/src/tools/rust-analyzer/crates/hir/src/semantics/child_by_source.rs +++ b/src/tools/rust-analyzer/crates/hir/src/semantics/child_by_source.rs @@ -6,10 +6,11 @@ use either::Either; use hir_expand::{HirFileId, attrs::collect_attrs}; +use span::AstIdNode; use syntax::{AstPtr, ast}; use hir_def::{ - AdtId, AssocItemId, DefWithBodyId, EnumId, FieldId, GenericDefId, ImplId, ItemTreeLoc, + AdtId, AssocItemId, AstIdLoc, DefWithBodyId, EnumId, FieldId, GenericDefId, ImplId, LifetimeParamId, Lookup, MacroId, ModuleDefId, ModuleId, TraitId, TypeOrConstParamId, VariantId, db::DefDatabase, @@ -19,7 +20,6 @@ use hir_def::{ }, hir::generics::GenericParams, item_scope::ItemScope, - item_tree::ItemTreeNode, nameres::DefMap, src::{HasChildSource, HasSource}, }; @@ -113,7 +113,7 @@ impl ChildBySource for ItemScope { ids.iter().for_each(|&id| { if let MacroId::MacroRulesId(id) = id { let loc = id.lookup(db); - if loc.id.file_id() == file_id { + if loc.id.file_id == file_id { res[keys::MACRO_RULES].insert(loc.ast_ptr(db).value, id); } } @@ -199,16 +199,14 @@ impl ChildBySource for VariantId { impl ChildBySource for EnumId { fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap, file_id: HirFileId) { let loc = &self.lookup(db); - if file_id != loc.id.file_id() { + if file_id != loc.id.file_id { return; } - let tree = loc.id.item_tree(db); - let ast_id_map = db.ast_id_map(loc.id.file_id()); + let ast_id_map = db.ast_id_map(loc.id.file_id); - db.enum_variants(*self).variants.iter().for_each(|&(variant, _)| { - res[keys::ENUM_VARIANT] - .insert(ast_id_map.get(tree[variant.lookup(db).id.value].ast_id), variant); + db.enum_variants(*self).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); source_map @@ -287,15 +285,14 @@ fn insert_item_loc( res: &mut DynMap, file_id: HirFileId, id: ID, - key: Key, + key: Key, ) where ID: Lookup + 'static, - Data: ItemTreeLoc, - N: ItemTreeNode, - N::Source: 'static, + Data: AstIdLoc, + N: AstIdNode + 'static, { let loc = id.lookup(db); - if loc.item_tree_id().file_id() == file_id { + if loc.ast_id().file_id == file_id { res[key].insert(loc.ast_ptr(db).value, id) } } From bb5f1bfa139b3538042c56cc1fdc6e87388d470c Mon Sep 17 00:00:00 2001 From: Chayim Refael Friedman Date: Wed, 21 May 2025 13:42:48 +0300 Subject: [PATCH 12/56] Remove most of the item tree I'm joking, but now that the def map is the only thing that uses the item tree, we can remove a lot of things from it that aren't needed for the def map. --- .../crates/hir-def/src/item_tree.rs | 158 +------------- .../crates/hir-def/src/item_tree/lower.rs | 196 ++---------------- .../crates/hir-def/src/item_tree/pretty.rs | 96 ++------- .../crates/hir-def/src/item_tree/tests.rs | 45 +--- 4 files changed, 52 insertions(+), 443 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs index 65dc35337a52f..07d1500fc097f 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs @@ -29,7 +29,6 @@ //! //! In general, any item in the `ItemTree` stores its `AstId`, which allows mapping it back to its //! surface syntax. -#![allow(unexpected_cfgs)] mod lower; mod pretty; @@ -51,7 +50,7 @@ use hir_expand::{ mod_path::{ModPath, PathKind}, name::Name, }; -use intern::{Interned, Symbol}; +use intern::Interned; use la_arena::{Arena, Idx, RawIdx}; use rustc_hash::FxHashMap; use smallvec::SmallVec; @@ -237,7 +236,6 @@ impl ItemTree { structs, unions, enums, - variants, consts, statics, traits, @@ -258,7 +256,6 @@ impl ItemTree { structs.shrink_to_fit(); unions.shrink_to_fit(); enums.shrink_to_fit(); - variants.shrink_to_fit(); consts.shrink_to_fit(); statics.shrink_to_fit(); traits.shrink_to_fit(); @@ -310,7 +307,6 @@ struct ItemTreeData { structs: Arena, unions: Arena, enums: Arena, - variants: Arena, consts: Arena, statics: Arena, traits: Arena, @@ -340,41 +336,15 @@ pub enum AttrOwner { ModItem(ModItem), /// Inner attributes of the source file. TopLevel, - - Variant(FileItemTreeId), - // while not relevant to early name resolution, fields can contain visibility - Field(FieldParent, ItemTreeFieldId), } -impl AttrOwner { - pub fn make_field_indexed(parent: FieldParent, idx: usize) -> Self { - AttrOwner::Field(parent, ItemTreeFieldId::from_raw(RawIdx::from_u32(idx as u32))) +impl From for AttrOwner { + #[inline] + fn from(value: ModItem) -> Self { + AttrOwner::ModItem(value) } } -#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] -pub enum FieldParent { - Struct(FileItemTreeId), - Union(FileItemTreeId), - EnumVariant(FileItemTreeId), -} - -pub type ItemTreeFieldId = Idx; - -macro_rules! from_attrs { - ( $( $var:ident($t:ty) ),+ $(,)? ) => { - $( - impl From<$t> for AttrOwner { - fn from(t: $t) -> AttrOwner { - AttrOwner::$var(t) - } - } - )+ - }; -} - -from_attrs!(ModItem(ModItem), Variant(FileItemTreeId)); - /// Trait implemented by all nodes in the item tree. pub trait ItemTreeNode: Clone { type Source: AstIdNode; @@ -383,7 +353,6 @@ pub trait ItemTreeNode: Clone { /// Looks up an instance of `Self` in an item tree. fn lookup(tree: &ItemTree, index: Idx) -> &Self; - fn attr_owner(id: FileItemTreeId) -> AttrOwner; } pub struct FileItemTreeId(Idx); @@ -547,10 +516,6 @@ macro_rules! mod_items { fn lookup(tree: &ItemTree, index: Idx) -> &Self { &tree.data().$fld[index] } - - fn attr_owner(id: FileItemTreeId) -> AttrOwner { - AttrOwner::ModItem(ModItem::$typ(id)) - } } impl Index> for ItemTree { @@ -624,22 +589,6 @@ impl Index> for ItemTree { } } -impl ItemTreeNode for Variant { - type Source = ast::Variant; - - fn ast_id(&self) -> FileAstId { - self.ast_id - } - - fn lookup(tree: &ItemTree, index: Idx) -> &Self { - &tree.data().variants[index] - } - - fn attr_owner(id: FileItemTreeId) -> AttrOwner { - AttrOwner::Variant(id) - } -} - #[derive(Debug, Clone, Eq, PartialEq)] pub struct Use { pub visibility: RawVisibilityId, @@ -712,7 +661,6 @@ pub struct ExternCrate { #[derive(Debug, Clone, Eq, PartialEq)] pub struct ExternBlock { - pub abi: Option, pub ast_id: FileAstId, pub children: Box<[ModItem]>, } @@ -728,7 +676,6 @@ pub struct Function { pub struct Struct { pub name: Name, pub visibility: RawVisibilityId, - pub fields: Box<[Field]>, pub shape: FieldsShape, pub ast_id: FileAstId, } @@ -737,7 +684,6 @@ pub struct Struct { pub struct Union { pub name: Name, pub visibility: RawVisibilityId, - pub fields: Box<[Field]>, pub ast_id: FileAstId, } @@ -745,18 +691,9 @@ pub struct Union { pub struct Enum { pub name: Name, pub visibility: RawVisibilityId, - pub variants: Range>, pub ast_id: FileAstId, } -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct Variant { - pub name: Name, - pub fields: Box<[Field]>, - pub shape: FieldsShape, - pub ast_id: FileAstId, -} - #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub enum FieldsShape { Record, @@ -788,16 +725,6 @@ impl VisibilityExplicitness { } } -// FIXME: Remove this from item tree? -/// A single field of an enum variant or struct -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct Field { - pub name: Name, - pub visibility: RawVisibilityId, - // FIXME: Not an item tree property - pub is_unsafe: bool, -} - #[derive(Debug, Clone, Eq, PartialEq)] pub struct Const { /// `None` for `const _: () = ();` @@ -817,7 +744,6 @@ pub struct Static { pub struct Trait { pub name: Name, pub visibility: RawVisibilityId, - pub items: Box<[AssocItem]>, pub ast_id: FileAstId, } @@ -830,7 +756,6 @@ pub struct TraitAlias { #[derive(Debug, Clone, Eq, PartialEq)] pub struct Impl { - pub items: Box<[AssocItem]>, pub ast_id: FileAstId, } @@ -971,76 +896,3 @@ impl UseTree { } } } - -macro_rules! impl_froms { - ($e:ident { $($v:ident ($t:ty)),* $(,)? }) => { - $( - impl From<$t> for $e { - fn from(it: $t) -> $e { - $e::$v(it) - } - } - )* - } -} - -impl ModItem { - pub fn as_assoc_item(&self) -> Option { - match self { - ModItem::Use(_) - | ModItem::ExternCrate(_) - | ModItem::ExternBlock(_) - | ModItem::Struct(_) - | ModItem::Union(_) - | ModItem::Enum(_) - | ModItem::Static(_) - | ModItem::Trait(_) - | ModItem::TraitAlias(_) - | ModItem::Impl(_) - | ModItem::Mod(_) - | ModItem::MacroRules(_) - | ModItem::Macro2(_) => None, - &ModItem::MacroCall(call) => Some(AssocItem::MacroCall(call)), - &ModItem::Const(konst) => Some(AssocItem::Const(konst)), - &ModItem::TypeAlias(alias) => Some(AssocItem::TypeAlias(alias)), - &ModItem::Function(func) => Some(AssocItem::Function(func)), - } - } -} - -#[derive(Debug, Copy, Clone, Eq, PartialEq)] -pub enum AssocItem { - Function(FileItemTreeId), - TypeAlias(FileItemTreeId), - Const(FileItemTreeId), - MacroCall(FileItemTreeId), -} - -impl_froms!(AssocItem { - Function(FileItemTreeId), - TypeAlias(FileItemTreeId), - Const(FileItemTreeId), - MacroCall(FileItemTreeId), -}); - -impl From for ModItem { - fn from(item: AssocItem) -> Self { - match item { - AssocItem::Function(it) => it.into(), - AssocItem::TypeAlias(it) => it.into(), - AssocItem::Const(it) => it.into(), - AssocItem::MacroCall(it) => it.into(), - } - } -} - -impl AssocItem { - pub fn ast_id(self, tree: &ItemTree) -> FileAstId { - match self { - AssocItem::Function(id) => tree[id].ast_id.upcast(), - AssocItem::TypeAlias(id) => tree[id].ast_id.upcast(), - AssocItem::Const(id) => tree[id].ast_id.upcast(), - AssocItem::MacroCall(id) => tree[id].ast_id.upcast(), - } - } -} diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs index 57765427693dd..d9588cb487d6b 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs @@ -8,23 +8,22 @@ use hir_expand::{ name::AsName, span_map::{SpanMap, SpanMapRef}, }; -use intern::{Symbol, sym}; use la_arena::Arena; use span::{AstIdMap, SyntaxContext}; use syntax::{ AstNode, - ast::{self, HasModuleItem, HasName, IsString}, + ast::{self, HasModuleItem, HasName}, }; use triomphe::Arc; use crate::{ db::DefDatabase, item_tree::{ - AssocItem, AttrOwner, Const, Enum, ExternBlock, ExternCrate, Field, FieldParent, - FieldsShape, FileItemTreeId, Function, Idx, Impl, ImportAlias, Interned, ItemTree, - ItemTreeData, Macro2, MacroCall, MacroRules, Mod, ModItem, ModKind, ModPath, Name, Range, - RawAttrs, RawIdx, RawVisibility, RawVisibilityId, Static, Struct, StructKind, Trait, - TraitAlias, TypeAlias, Union, Use, UseTree, UseTreeKind, Variant, VisibilityExplicitness, + AttrOwner, Const, Enum, ExternBlock, ExternCrate, FieldsShape, FileItemTreeId, Function, + Idx, Impl, ImportAlias, Interned, ItemTree, ItemTreeData, Macro2, MacroCall, MacroRules, + Mod, ModItem, ModKind, ModPath, RawAttrs, RawVisibility, RawVisibilityId, Static, Struct, + StructKind, Trait, TraitAlias, TypeAlias, Union, Use, UseTree, UseTreeKind, + VisibilityExplicitness, }, }; @@ -163,118 +162,23 @@ impl<'a> Ctx<'a> { } } - fn lower_assoc_item(&mut self, item_node: &ast::AssocItem) -> Option { - let item: AssocItem = match item_node { - ast::AssocItem::Fn(ast) => self.lower_function(ast).map(Into::into), - ast::AssocItem::TypeAlias(ast) => self.lower_type_alias(ast).map(Into::into), - ast::AssocItem::Const(ast) => Some(self.lower_const(ast).into()), - ast::AssocItem::MacroCall(ast) => self.lower_macro_call(ast).map(Into::into), - }?; - let attrs = RawAttrs::new(self.db, item_node, self.span_map()); - self.add_attrs( - match item { - AssocItem::Function(it) => AttrOwner::ModItem(ModItem::Function(it)), - AssocItem::TypeAlias(it) => AttrOwner::ModItem(ModItem::TypeAlias(it)), - AssocItem::Const(it) => AttrOwner::ModItem(ModItem::Const(it)), - AssocItem::MacroCall(it) => AttrOwner::ModItem(ModItem::MacroCall(it)), - }, - attrs, - ); - Some(item) - } - fn lower_struct(&mut self, strukt: &ast::Struct) -> Option> { let visibility = self.lower_visibility(strukt); let name = strukt.name()?.as_name(); let ast_id = self.source_ast_id_map.ast_id(strukt); - let (fields, kind, attrs) = self.lower_fields(&strukt.kind()); - let res = Struct { name, visibility, fields, shape: kind, ast_id }; + let shape = adt_shape(strukt.kind()); + let res = Struct { name, visibility, shape, ast_id }; let id = id(self.data().structs.alloc(res)); - for (idx, attr) in attrs { - self.add_attrs( - AttrOwner::Field( - FieldParent::Struct(id), - Idx::from_raw(RawIdx::from_u32(idx as u32)), - ), - attr, - ); - } Some(id) } - fn lower_fields( - &mut self, - strukt_kind: &ast::StructKind, - ) -> (Box<[Field]>, FieldsShape, Vec<(usize, RawAttrs)>) { - match strukt_kind { - ast::StructKind::Record(it) => { - let mut fields = vec![]; - let mut attrs = vec![]; - - for (i, field) in it.fields().enumerate() { - let data = self.lower_record_field(&field); - fields.push(data); - let attr = RawAttrs::new(self.db, &field, self.span_map()); - if !attr.is_empty() { - attrs.push((i, attr)) - } - } - (fields.into(), FieldsShape::Record, attrs) - } - ast::StructKind::Tuple(it) => { - let mut fields = vec![]; - let mut attrs = vec![]; - - for (i, field) in it.fields().enumerate() { - let data = self.lower_tuple_field(i, &field); - fields.push(data); - let attr = RawAttrs::new(self.db, &field, self.span_map()); - if !attr.is_empty() { - attrs.push((i, attr)) - } - } - (fields.into(), FieldsShape::Tuple, attrs) - } - ast::StructKind::Unit => (Box::default(), FieldsShape::Unit, Vec::default()), - } - } - - fn lower_record_field(&mut self, field: &ast::RecordField) -> Field { - let name = match field.name() { - Some(name) => name.as_name(), - None => Name::missing(), - }; - let visibility = self.lower_visibility(field); - - Field { name, visibility, is_unsafe: field.unsafe_token().is_some() } - } - - fn lower_tuple_field(&mut self, idx: usize, field: &ast::TupleField) -> Field { - let name = Name::new_tuple_field(idx); - let visibility = self.lower_visibility(field); - Field { name, visibility, is_unsafe: false } - } - fn lower_union(&mut self, union: &ast::Union) -> Option> { let visibility = self.lower_visibility(union); let name = union.name()?.as_name(); let ast_id = self.source_ast_id_map.ast_id(union); - let (fields, _, attrs) = match union.record_field_list() { - Some(record_field_list) => self.lower_fields(&StructKind::Record(record_field_list)), - None => (Box::default(), FieldsShape::Record, Vec::default()), - }; - let res = Union { name, visibility, fields, ast_id }; + let res = Union { name, visibility, ast_id }; let id = id(self.data().unions.alloc(res)); - for (idx, attr) in attrs { - self.add_attrs( - AttrOwner::Field( - FieldParent::Union(id), - Idx::from_raw(RawIdx::from_u32(idx as u32)), - ), - attr, - ); - } Some(id) } @@ -282,48 +186,11 @@ impl<'a> Ctx<'a> { let visibility = self.lower_visibility(enum_); let name = enum_.name()?.as_name(); let ast_id = self.source_ast_id_map.ast_id(enum_); - let variants = match &enum_.variant_list() { - Some(variant_list) => self.lower_variants(variant_list), - None => { - FileItemTreeId(self.next_variant_idx())..FileItemTreeId(self.next_variant_idx()) - } - }; - let res = Enum { name, visibility, variants, ast_id }; + let res = Enum { name, visibility, ast_id }; let id = id(self.data().enums.alloc(res)); Some(id) } - fn lower_variants(&mut self, variants: &ast::VariantList) -> Range> { - let start = self.next_variant_idx(); - for variant in variants.variants() { - let idx = self.lower_variant(&variant); - self.add_attrs(id(idx).into(), RawAttrs::new(self.db, &variant, self.span_map())); - } - let end = self.next_variant_idx(); - FileItemTreeId(start)..FileItemTreeId(end) - } - - fn lower_variant(&mut self, variant: &ast::Variant) -> Idx { - let name = match variant.name() { - Some(name) => name.as_name(), - None => Name::missing(), - }; - let (fields, kind, attrs) = self.lower_fields(&variant.kind()); - let ast_id = self.source_ast_id_map.ast_id(variant); - let res = Variant { name, fields, shape: kind, ast_id }; - let id = self.data().variants.alloc(res); - for (idx, attr) in attrs { - self.add_attrs( - AttrOwner::Field( - FieldParent::EnumVariant(FileItemTreeId(id)), - Idx::from_raw(RawIdx::from_u32(idx as u32)), - ), - attr, - ); - } - id - } - fn lower_function(&mut self, func: &ast::Fn) -> Option> { let visibility = self.lower_visibility(func); let name = func.name()?.as_name(); @@ -390,14 +257,7 @@ impl<'a> Ctx<'a> { let visibility = self.lower_visibility(trait_def); let ast_id = self.source_ast_id_map.ast_id(trait_def); - let items = trait_def - .assoc_item_list() - .into_iter() - .flat_map(|list| list.assoc_items()) - .filter_map(|item_node| self.lower_assoc_item(&item_node)) - .collect(); - - let def = Trait { name, visibility, items, ast_id }; + let def = Trait { name, visibility, ast_id }; let id = id(self.data().traits.alloc(def)); Some(id) } @@ -417,16 +277,9 @@ impl<'a> Ctx<'a> { fn lower_impl(&mut self, impl_def: &ast::Impl) -> FileItemTreeId { let ast_id = self.source_ast_id_map.ast_id(impl_def); - // We cannot use `assoc_items()` here as that does not include macro calls. - let items = impl_def - .assoc_item_list() - .into_iter() - .flat_map(|it| it.assoc_items()) - .filter_map(|item| self.lower_assoc_item(&item)) - .collect(); // Note that trait impls don't get implicit `Self` unlike traits, because here they are a // type alias rather than a type parameter, so this is handled by the resolver. - let res = Impl { items, ast_id }; + let res = Impl { ast_id }; id(self.data().impls.alloc(res)) } @@ -489,7 +342,6 @@ impl<'a> Ctx<'a> { fn lower_extern_block(&mut self, block: &ast::ExternBlock) -> FileItemTreeId { let ast_id = self.source_ast_id_map.ast_id(block); - let abi = block.abi().map(lower_abi); let children: Box<[_]> = block.extern_item_list().map_or(Box::new([]), |list| { list.extern_items() .filter_map(|item| { @@ -510,7 +362,7 @@ impl<'a> Ctx<'a> { .collect() }); - let res = ExternBlock { abi, ast_id, children }; + let res = ExternBlock { ast_id, children }; id(self.data().extern_blocks.alloc(res)) } @@ -520,20 +372,6 @@ impl<'a> Ctx<'a> { }); self.data().vis.alloc(vis) } - - fn next_variant_idx(&self) -> Idx { - Idx::from_raw(RawIdx::from( - self.tree.data.as_ref().map_or(0, |data| data.variants.len() as u32), - )) - } -} - -fn lower_abi(abi: ast::Abi) -> Symbol { - match abi.abi_string() { - Some(tok) => Symbol::intern(tok.text_without_quotes()), - // `extern` default to be `extern "C"`. - _ => sym::C, - } } struct UseTreeLowering<'a> { @@ -647,3 +485,11 @@ pub(crate) fn visibility_from_ast( }; RawVisibility::Module(Interned::new(path), VisibilityExplicitness::Explicit) } + +fn adt_shape(kind: StructKind) -> FieldsShape { + match kind { + StructKind::Record(_) => FieldsShape::Record, + StructKind::Tuple(_) => FieldsShape::Tuple, + StructKind::Unit => FieldsShape::Unit, + } +} diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs index 8ff14751c671e..0c62b86dae28b 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs @@ -2,15 +2,13 @@ use std::fmt::{self, Write}; -use la_arena::{Idx, RawIdx}; use span::{Edition, ErasedFileAstId}; use crate::{ item_tree::{ - AttrOwner, Const, DefDatabase, Enum, ExternBlock, ExternCrate, Field, FieldParent, - FieldsShape, FileItemTreeId, Function, Impl, ItemTree, Macro2, MacroCall, MacroRules, Mod, - ModItem, ModKind, RawAttrs, RawVisibilityId, Static, Struct, Trait, TraitAlias, TypeAlias, - Union, Use, UseTree, UseTreeKind, Variant, + AttrOwner, Const, DefDatabase, Enum, ExternBlock, ExternCrate, FieldsShape, Function, Impl, + ItemTree, Macro2, MacroCall, MacroRules, Mod, ModItem, ModKind, RawAttrs, RawVisibilityId, + Static, Struct, Trait, TraitAlias, TypeAlias, Union, Use, UseTree, UseTreeKind, }, visibility::RawVisibility, }; @@ -118,44 +116,14 @@ impl Printer<'_> { }; } - fn print_fields(&mut self, parent: FieldParent, kind: FieldsShape, fields: &[Field]) { - let edition = self.edition; + fn print_fields(&mut self, kind: FieldsShape) { match kind { FieldsShape::Record => { self.whitespace(); - w!(self, "{{"); - self.indented(|this| { - for (idx, Field { name, visibility, is_unsafe }) in fields.iter().enumerate() { - this.print_attrs_of( - AttrOwner::Field(parent, Idx::from_raw(RawIdx::from(idx as u32))), - "\n", - ); - this.print_visibility(*visibility); - if *is_unsafe { - w!(this, "unsafe "); - } - - wln!(this, "{},", name.display(self.db, edition)); - } - }); - w!(self, "}}"); + w!(self, "{{ ... }}"); } FieldsShape::Tuple => { - w!(self, "("); - self.indented(|this| { - for (idx, Field { name, visibility, is_unsafe }) in fields.iter().enumerate() { - this.print_attrs_of( - AttrOwner::Field(parent, Idx::from_raw(RawIdx::from(idx as u32))), - "\n", - ); - this.print_visibility(*visibility); - if *is_unsafe { - w!(this, "unsafe "); - } - wln!(this, "{},", name.display(self.db, edition)); - } - }); - w!(self, ")"); + w!(self, "(...)"); } FieldsShape::Unit => {} } @@ -214,13 +182,9 @@ impl Printer<'_> { wln!(self, ";"); } ModItem::ExternBlock(it) => { - let ExternBlock { abi, ast_id, children } = &self.tree[it]; + let ExternBlock { ast_id, children } = &self.tree[it]; self.print_ast_id(ast_id.erase()); - w!(self, "extern "); - if let Some(abi) = abi { - w!(self, "\"{}\" ", abi); - } - w!(self, "{{"); + w!(self, "extern {{"); self.indented(|this| { for child in &**children { this.print_mod_item(*child); @@ -235,11 +199,11 @@ impl Printer<'_> { wln!(self, "fn {};", name.display(self.db, self.edition)); } ModItem::Struct(it) => { - let Struct { visibility, name, fields, shape: kind, ast_id } = &self.tree[it]; + let Struct { visibility, name, shape: kind, ast_id } = &self.tree[it]; self.print_ast_id(ast_id.erase()); self.print_visibility(*visibility); w!(self, "struct {}", name.display(self.db, self.edition)); - self.print_fields(FieldParent::Struct(it), *kind, fields); + self.print_fields(*kind); if matches!(kind, FieldsShape::Record) { wln!(self); } else { @@ -247,30 +211,18 @@ impl Printer<'_> { } } ModItem::Union(it) => { - let Union { name, visibility, fields, ast_id } = &self.tree[it]; + let Union { name, visibility, ast_id } = &self.tree[it]; self.print_ast_id(ast_id.erase()); self.print_visibility(*visibility); w!(self, "union {}", name.display(self.db, self.edition)); - self.print_fields(FieldParent::Union(it), FieldsShape::Record, fields); + self.print_fields(FieldsShape::Record); wln!(self); } ModItem::Enum(it) => { - let Enum { name, visibility, variants, ast_id } = &self.tree[it]; + let Enum { name, visibility, ast_id } = &self.tree[it]; self.print_ast_id(ast_id.erase()); self.print_visibility(*visibility); - w!(self, "enum {} {{", name.display(self.db, self.edition)); - let edition = self.edition; - self.indented(|this| { - for variant in FileItemTreeId::range_iter(variants.clone()) { - let Variant { name, fields, shape: kind, ast_id } = &this.tree[variant]; - this.print_ast_id(ast_id.erase()); - this.print_attrs_of(variant, "\n"); - w!(this, "{}", name.display(self.db, edition)); - this.print_fields(FieldParent::EnumVariant(variant), *kind, fields); - wln!(this, ","); - } - }); - wln!(self, "}}"); + w!(self, "enum {} {{ ... }}", name.display(self.db, self.edition)); } ModItem::Const(it) => { let Const { name, visibility, ast_id } = &self.tree[it]; @@ -293,16 +245,10 @@ impl Printer<'_> { wln!(self); } ModItem::Trait(it) => { - let Trait { name, visibility, items, ast_id } = &self.tree[it]; + let Trait { name, visibility, ast_id } = &self.tree[it]; self.print_ast_id(ast_id.erase()); self.print_visibility(*visibility); - w!(self, "trait {} {{", name.display(self.db, self.edition)); - self.indented(|this| { - for item in &**items { - this.print_mod_item((*item).into()); - } - }); - wln!(self, "}}"); + w!(self, "trait {} {{ ... }}", name.display(self.db, self.edition)); } ModItem::TraitAlias(it) => { let TraitAlias { name, visibility, ast_id } = &self.tree[it]; @@ -311,15 +257,9 @@ impl Printer<'_> { wln!(self, "trait {} = ..;", name.display(self.db, self.edition)); } ModItem::Impl(it) => { - let Impl { items, ast_id } = &self.tree[it]; + let Impl { ast_id } = &self.tree[it]; self.print_ast_id(ast_id.erase()); - w!(self, "impl {{"); - self.indented(|this| { - for item in &**items { - this.print_mod_item((*item).into()); - } - }); - wln!(self, "}}"); + w!(self, "impl {{ ... }}"); } ModItem::TypeAlias(it) => { let TypeAlias { name, visibility, ast_id } = &self.tree[it]; diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/tests.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/tests.rs index 7a85e8d175e60..e39efd31c6c19 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/tests.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/tests.rs @@ -73,10 +73,10 @@ extern "C" { fn ex_fn(); } "#, - expect![[r##" + expect![[r#" #[on_extern_block] // AstId: ExternBlock[0000, 0] - extern "C" { + extern { #[on_extern_type] // AstId: TypeAlias[9FDF, 0] pub(self) type ExType; @@ -89,7 +89,7 @@ extern "C" { // AstId: Fn[452D, 0] pub(self) fn ex_fn; } - "##]], + "#]], ); } @@ -129,39 +129,16 @@ enum E { #[derive(Debug)] // AstId: Struct[C7A1, 0] - pub(self) struct Struct { - #[doc = " fld docs"] - pub(self) fld, - } + pub(self) struct Struct { ... } // AstId: Struct[DAC2, 0] - pub(self) struct Tuple( - #[attr] - pub(self) 0, - ); + pub(self) struct Tuple(...); // AstId: Union[2DBB, 0] - pub(self) union Ize { - pub(self) a, - pub(self) b, - } + pub(self) union Ize { ... } // AstId: Enum[7FF8, 0] - pub(self) enum E { - // AstId: Variant[C717, 0] - #[doc = " comment on Unit"] - Unit, - // AstId: Variant[AEAB, 0] - #[doc = " comment on Tuple"] - Tuple( - pub(self) 0, - ), - // AstId: Variant[4B1B, 0] - Struct { - #[doc = " comment on a: u8"] - pub(self) a, - }, - } + pub(self) enum E { ... } "#]], ); } @@ -197,13 +174,7 @@ trait Tr: SuperTrait + 'lifetime { pub(self) fn f; // AstId: Trait[2998, 0] - pub(self) trait Tr { - // AstId: TypeAlias[9F08, 0] - pub(self) type Assoc; - - // AstId: Fn[6C0C, 0] - pub(self) fn method; - } + pub(self) trait Tr { ... } "#]], ); } From c09ac193652df29b86e4ccee64978514b6e07ceb Mon Sep 17 00:00:00 2001 From: Chayim Refael Friedman Date: Wed, 21 May 2025 14:59:21 +0300 Subject: [PATCH 13/56] Ignore ast id hashes in typos check --- src/tools/rust-analyzer/.typos.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tools/rust-analyzer/.typos.toml b/src/tools/rust-analyzer/.typos.toml index e938bddd4b126..cdbc003a80882 100644 --- a/src/tools/rust-analyzer/.typos.toml +++ b/src/tools/rust-analyzer/.typos.toml @@ -18,6 +18,7 @@ extend-ignore-re = [ "INOUT", "optin", "=Pn", + "\\[[0-9A-F]{4},", # AstId hex hashes # ignore `// spellchecker:off` until `// spellchecker:on` "(?s)(#|//)\\s*spellchecker:off.*?\\n\\s*(#|//)\\s*spellchecker:on", ] From 1babfe7a828331ed8af373db0d02a66f9fc1a319 Mon Sep 17 00:00:00 2001 From: Chayim Refael Friedman Date: Wed, 21 May 2025 15:24:07 +0300 Subject: [PATCH 14/56] LRU ast id map We can do that and it's pretty heavy. --- src/tools/rust-analyzer/crates/hir-expand/src/db.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/db.rs b/src/tools/rust-analyzer/crates/hir-expand/src/db.rs index 7cb1b6c02075b..b7df3ee2f9118 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/db.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/db.rs @@ -60,6 +60,7 @@ pub trait ExpandDatabase: RootQueryDb { fn proc_macros_for_crate(&self, krate: Crate) -> Option>; #[salsa::invoke(ast_id_map)] + #[salsa::lru(1024)] fn ast_id_map(&self, file_id: HirFileId) -> Arc; #[salsa::transparent] From c1d085975bc8e9f8e6af4fc07b33e1494f22b13a Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 12 Jun 2025 08:52:19 +0200 Subject: [PATCH 15/56] `ItemTree`'s `ItemVisibilities` has no identity, so deduplicate --- .../rust-analyzer/crates/base-db/src/input.rs | 4 +-- .../rust-analyzer/crates/base-db/src/lib.rs | 2 ++ .../crates/hir-def/src/expr_store/lower.rs | 3 +- .../crates/hir-def/src/item_tree.rs | 31 +++---------------- .../crates/hir-def/src/item_tree/lower.rs | 30 ++++++++++++++++-- .../rust-analyzer/crates/hir/src/symbols.rs | 3 +- .../rust-analyzer/crates/ide/src/runnables.rs | 4 +-- 7 files changed, 39 insertions(+), 38 deletions(-) diff --git a/src/tools/rust-analyzer/crates/base-db/src/input.rs b/src/tools/rust-analyzer/crates/base-db/src/input.rs index 745238167bc17..2a87b152487b1 100644 --- a/src/tools/rust-analyzer/crates/base-db/src/input.rs +++ b/src/tools/rust-analyzer/crates/base-db/src/input.rs @@ -20,12 +20,10 @@ use span::Edition; use triomphe::Arc; use vfs::{AbsPathBuf, AnchoredPath, FileId, VfsPath, file_set::FileSet}; -use crate::{CrateWorkspaceData, EditionedFileId, RootQueryDb}; +use crate::{CrateWorkspaceData, EditionedFileId, FxIndexSet, RootQueryDb}; pub type ProcMacroPaths = FxHashMap>; -type FxIndexSet = indexmap::IndexSet; - #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct SourceRootId(pub u32); diff --git a/src/tools/rust-analyzer/crates/base-db/src/lib.rs b/src/tools/rust-analyzer/crates/base-db/src/lib.rs index 4d4e6cae0373a..478fae67c807c 100644 --- a/src/tools/rust-analyzer/crates/base-db/src/lib.rs +++ b/src/tools/rust-analyzer/crates/base-db/src/lib.rs @@ -28,6 +28,8 @@ use syntax::{Parse, SyntaxError, ast}; use triomphe::Arc; pub use vfs::{AnchoredPath, AnchoredPathBuf, FileId, VfsPath, file_set::FileSet}; +pub type FxIndexSet = indexmap::IndexSet; + #[macro_export] macro_rules! impl_intern_key { ($id:ident, $loc:ident) => { diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs index 89eeaf00bc3d0..4ba31c1e20bfe 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs @@ -7,6 +7,7 @@ mod path; use std::mem; +use base_db::FxIndexSet; use cfg::CfgOptions; use either::Either; use hir_expand::{ @@ -66,8 +67,6 @@ use crate::{ pub use self::path::hir_segment_to_ast_segment; -type FxIndexSet = indexmap::IndexSet>; - pub(super) fn lower_body( db: &dyn DefDatabase, owner: DefWithBodyId, diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs index 07d1500fc097f..81c8f56456450 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs @@ -246,7 +246,7 @@ impl ItemTree { macro_calls, macro_rules, macro_defs, - vis, + vis: _, } = &mut **data; uses.shrink_to_fit(); @@ -266,36 +266,13 @@ impl ItemTree { macro_calls.shrink_to_fit(); macro_rules.shrink_to_fit(); macro_defs.shrink_to_fit(); - - vis.arena.shrink_to_fit(); } } } #[derive(Default, Debug, Eq, PartialEq)] struct ItemVisibilities { - arena: Arena, -} - -impl ItemVisibilities { - fn alloc(&mut self, vis: RawVisibility) -> RawVisibilityId { - match &vis { - RawVisibility::Public => RawVisibilityId::PUB, - RawVisibility::Module(path, explicitiy) if path.segments().is_empty() => { - match (path.kind, explicitiy) { - (PathKind::SELF, VisibilityExplicitness::Explicit) => { - RawVisibilityId::PRIV_EXPLICIT - } - (PathKind::SELF, VisibilityExplicitness::Implicit) => { - RawVisibilityId::PRIV_IMPLICIT - } - (PathKind::Crate, _) => RawVisibilityId::PUB_CRATE, - _ => RawVisibilityId(self.arena.alloc(vis).into_raw().into()), - } - } - _ => RawVisibilityId(self.arena.alloc(vis).into_raw().into()), - } - } + arena: Box<[RawVisibility]>, } #[derive(Default, Debug, Eq, PartialEq)] @@ -577,7 +554,7 @@ impl Index for ItemTree { VisibilityExplicitness::Explicit, ) }), - _ => &self.data().vis.arena[Idx::from_raw(index.0.into())], + _ => &self.data().vis.arena[index.0 as usize], } } } @@ -702,7 +679,7 @@ pub enum FieldsShape { } /// Visibility of an item, not yet resolved. -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum RawVisibility { /// `pub(in module)`, `pub(crate)` or `pub(super)`. Also private, which is /// equivalent to `pub(self)`. diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs index d9588cb487d6b..26d209c972f7c 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs @@ -2,6 +2,7 @@ use std::{cell::OnceCell, collections::hash_map::Entry}; +use base_db::FxIndexSet; use hir_expand::{ HirFileId, mod_path::PathKind, @@ -37,6 +38,7 @@ pub(super) struct Ctx<'a> { source_ast_id_map: Arc, span_map: OnceCell, file: HirFileId, + visibilities: FxIndexSet, } impl<'a> Ctx<'a> { @@ -47,6 +49,7 @@ impl<'a> Ctx<'a> { source_ast_id_map: db.ast_id_map(file), file, span_map: OnceCell::new(), + visibilities: FxIndexSet::default(), } } @@ -57,6 +60,9 @@ impl<'a> Ctx<'a> { pub(super) fn lower_module_items(mut self, item_owner: &dyn HasModuleItem) -> ItemTree { self.tree.top_level = item_owner.items().flat_map(|item| self.lower_mod_item(&item)).collect(); + if let Some(data) = &mut self.tree.data { + data.vis.arena = self.visibilities.into_iter().collect(); + } self.tree } @@ -90,6 +96,9 @@ impl<'a> Ctx<'a> { } } + if let Some(data) = &mut self.tree.data { + data.vis.arena = self.visibilities.into_iter().collect(); + } self.tree } @@ -115,7 +124,9 @@ impl<'a> Ctx<'a> { } } } - + if let Some(data) = &mut self.tree.data { + data.vis.arena = self.visibilities.into_iter().collect(); + } self.tree } @@ -370,7 +381,22 @@ impl<'a> Ctx<'a> { let vis = visibility_from_ast(self.db, item.visibility(), &mut |range| { self.span_map().span_for_range(range).ctx }); - self.data().vis.alloc(vis) + match &vis { + RawVisibility::Public => RawVisibilityId::PUB, + RawVisibility::Module(path, explicitiy) if path.segments().is_empty() => { + match (path.kind, explicitiy) { + (PathKind::SELF, VisibilityExplicitness::Explicit) => { + RawVisibilityId::PRIV_EXPLICIT + } + (PathKind::SELF, VisibilityExplicitness::Implicit) => { + RawVisibilityId::PRIV_IMPLICIT + } + (PathKind::Crate, _) => RawVisibilityId::PUB_CRATE, + _ => RawVisibilityId(self.visibilities.insert_full(vis).0 as u32), + } + } + _ => RawVisibilityId(self.visibilities.insert_full(vis).0 as u32), + } } } diff --git a/src/tools/rust-analyzer/crates/hir/src/symbols.rs b/src/tools/rust-analyzer/crates/hir/src/symbols.rs index e87ab87407ff2..a0815c3131b1f 100644 --- a/src/tools/rust-analyzer/crates/hir/src/symbols.rs +++ b/src/tools/rust-analyzer/crates/hir/src/symbols.rs @@ -1,5 +1,6 @@ //! File symbol extraction. +use base_db::FxIndexSet; use either::Either; use hir_def::{ AdtId, AssocItemId, Complete, DefWithBodyId, ExternCrateId, HasModule, ImplId, Lookup, MacroId, @@ -21,8 +22,6 @@ use syntax::{AstNode, AstPtr, SmolStr, SyntaxNode, SyntaxNodePtr, ToSmolStr, ast use crate::{HasCrate, Module, ModuleDef, Semantics}; -pub type FxIndexSet = indexmap::IndexSet>; - /// The actual data that is stored in the index. It should be as compact as /// possible. #[derive(Debug, Clone, PartialEq, Eq, Hash)] diff --git a/src/tools/rust-analyzer/crates/ide/src/runnables.rs b/src/tools/rust-analyzer/crates/ide/src/runnables.rs index ab139602404cb..f48150b369f2a 100644 --- a/src/tools/rust-analyzer/crates/ide/src/runnables.rs +++ b/src/tools/rust-analyzer/crates/ide/src/runnables.rs @@ -5,11 +5,11 @@ use ast::HasName; use cfg::{CfgAtom, CfgExpr}; use hir::{ AsAssocItem, AttrsWithOwner, HasAttrs, HasCrate, HasSource, ModPath, Name, PathKind, Semantics, - Symbol, db::HirDatabase, sym, symbols::FxIndexSet, + Symbol, db::HirDatabase, sym, }; use ide_assists::utils::{has_test_related_attribute, test_related_attribute_syn}; use ide_db::{ - FilePosition, FxHashMap, FxIndexMap, RootDatabase, SymbolKind, + FilePosition, FxHashMap, FxIndexMap, FxIndexSet, RootDatabase, SymbolKind, base_db::RootQueryDb, defs::Definition, documentation::docs_from_attrs, From 2972e77d38d9ebb4ced8a1b50f46b2a06dd0b90e Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 12 Jun 2025 09:36:22 +0200 Subject: [PATCH 16/56] fix: Do not force descend into derives for goto IDE features Doing so can cause us to duplicate navigation targets for the same ranges which breaks convenience features of some editors where go to def can trigger find all references --- src/tools/rust-analyzer/crates/hir/src/semantics.rs | 5 +++-- src/tools/rust-analyzer/crates/ide/src/goto_declaration.rs | 2 +- src/tools/rust-analyzer/crates/ide/src/goto_definition.rs | 2 +- .../rust-analyzer/crates/ide/src/goto_type_definition.rs | 2 +- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics.rs b/src/tools/rust-analyzer/crates/hir/src/semantics.rs index 47607a51d38f4..10498958242a8 100644 --- a/src/tools/rust-analyzer/crates/hir/src/semantics.rs +++ b/src/tools/rust-analyzer/crates/hir/src/semantics.rs @@ -244,7 +244,7 @@ impl Semantics<'_, DB> { offset: TextSize, ) -> impl Iterator + 'slf { node.token_at_offset(offset) - .map(move |token| self.descend_into_macros_no_opaque(token)) + .map(move |token| self.descend_into_macros_no_opaque(token, true)) .map(|descendants| descendants.into_iter().filter_map(move |it| it.value.parent())) // re-order the tokens from token_at_offset by returning the ancestors with the smaller first nodes first // See algo::ancestors_at_offset, which uses the same approach @@ -1009,10 +1009,11 @@ impl<'db> SemanticsImpl<'db> { pub fn descend_into_macros_no_opaque( &self, token: SyntaxToken, + always_descend_into_derives: bool, ) -> SmallVec<[InFile; 1]> { let mut res = smallvec![]; let token = self.wrap_token_infile(token); - self.descend_into_macros_all(token.clone(), true, &mut |t, ctx| { + self.descend_into_macros_all(token.clone(), always_descend_into_derives, &mut |t, ctx| { if !ctx.is_opaque(self.db) { // Don't descend into opaque contexts res.push(t); diff --git a/src/tools/rust-analyzer/crates/ide/src/goto_declaration.rs b/src/tools/rust-analyzer/crates/ide/src/goto_declaration.rs index 38c032d382e3d..267e8ff7128be 100644 --- a/src/tools/rust-analyzer/crates/ide/src/goto_declaration.rs +++ b/src/tools/rust-analyzer/crates/ide/src/goto_declaration.rs @@ -29,7 +29,7 @@ pub(crate) fn goto_declaration( .find(|it| matches!(it.kind(), IDENT | T![self] | T![super] | T![crate] | T![Self]))?; let range = original_token.text_range(); let info: Vec = sema - .descend_into_macros_no_opaque(original_token) + .descend_into_macros_no_opaque(original_token, false) .iter() .filter_map(|token| { let parent = token.value.parent()?; diff --git a/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs b/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs index 7917aab8bf782..574803fb9e882 100644 --- a/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs +++ b/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs @@ -88,7 +88,7 @@ pub(crate) fn goto_definition( } let navs = sema - .descend_into_macros_no_opaque(original_token.clone()) + .descend_into_macros_no_opaque(original_token.clone(), false) .into_iter() .filter_map(|token| { let parent = token.value.parent()?; diff --git a/src/tools/rust-analyzer/crates/ide/src/goto_type_definition.rs b/src/tools/rust-analyzer/crates/ide/src/goto_type_definition.rs index a6c7ea29b09e6..9781e7116dec6 100644 --- a/src/tools/rust-analyzer/crates/ide/src/goto_type_definition.rs +++ b/src/tools/rust-analyzer/crates/ide/src/goto_type_definition.rs @@ -70,7 +70,7 @@ pub(crate) fn goto_type_definition( } let range = token.text_range(); - sema.descend_into_macros_no_opaque(token) + sema.descend_into_macros_no_opaque(token,false) .into_iter() .filter_map(|token| { sema From d4a371961741fd599b1514ef924b736f6f8f9f6d Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 12 Jun 2025 09:46:01 +0200 Subject: [PATCH 17/56] Remove `ItemTreeId` --- .../rust-analyzer/crates/hir-def/src/attr.rs | 19 ++++--- .../crates/hir-def/src/item_tree.rs | 53 ------------------- .../crates/hir-def/src/nameres.rs | 34 +++++++----- .../crates/hir-def/src/nameres/collector.rs | 32 ++++++----- 4 files changed, 52 insertions(+), 86 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/attr.rs b/src/tools/rust-analyzer/crates/hir-def/src/attr.rs index a7328809a823b..cc9a2fdf4c7bb 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/attr.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/attr.rs @@ -523,10 +523,15 @@ impl AttrsWithOwner { let mod_data = &def_map[module.local_id]; let raw_attrs = match mod_data.origin { - ModuleOrigin::File { definition, declaration_tree_id, .. } => { + ModuleOrigin::File { + definition, + declaration_tree_id, + file_item_tree_id, + .. + } => { let decl_attrs = declaration_tree_id .item_tree(db) - .raw_attrs(AttrOwner::ModItem(declaration_tree_id.value.into())) + .raw_attrs(AttrOwner::ModItem(file_item_tree_id.into())) .clone(); let tree = db.file_item_tree(definition.into()); let def_attrs = tree.raw_attrs(AttrOwner::TopLevel).clone(); @@ -536,10 +541,12 @@ impl AttrsWithOwner { let tree = db.file_item_tree(definition.into()); tree.raw_attrs(AttrOwner::TopLevel).clone() } - ModuleOrigin::Inline { definition_tree_id, .. } => definition_tree_id - .item_tree(db) - .raw_attrs(AttrOwner::ModItem(definition_tree_id.value.into())) - .clone(), + ModuleOrigin::Inline { definition_tree_id, file_item_tree_id, .. } => { + definition_tree_id + .item_tree(db) + .raw_attrs(AttrOwner::ModItem(file_item_tree_id.into())) + .clone() + } ModuleOrigin::BlockExpr { id, .. } => { let tree = db.block_item_tree(id); tree.raw_attrs(AttrOwner::TopLevel).clone() diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs index 81c8f56456450..ec2b65c9c00d2 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs @@ -404,59 +404,6 @@ impl TreeId { } } -#[derive(Debug)] -pub struct ItemTreeId { - tree: TreeId, - pub value: FileItemTreeId, -} - -impl ItemTreeId { - pub fn new(tree: TreeId, idx: FileItemTreeId) -> Self { - Self { tree, value: idx } - } - - pub fn file_id(self) -> HirFileId { - self.tree.file - } - - pub fn tree_id(self) -> TreeId { - self.tree - } - - pub fn item_tree(self, db: &dyn DefDatabase) -> Arc { - self.tree.item_tree(db) - } - - pub fn resolved(self, db: &dyn DefDatabase, cb: impl FnOnce(&N) -> R) -> R - where - ItemTree: Index, Output = N>, - { - cb(&self.tree.item_tree(db)[self.value]) - } -} - -impl Copy for ItemTreeId {} -impl Clone for ItemTreeId { - fn clone(&self) -> Self { - *self - } -} - -impl PartialEq for ItemTreeId { - fn eq(&self, other: &Self) -> bool { - self.tree == other.tree && self.value == other.value - } -} - -impl Eq for ItemTreeId {} - -impl Hash for ItemTreeId { - fn hash(&self, state: &mut H) { - self.tree.hash(state); - self.value.hash(state); - } -} - macro_rules! mod_items { ( $( $typ:ident in $fld:ident -> $ast:ty ),+ $(,)? ) => { #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs index c908e457540b3..e62fd3dab7a33 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs @@ -80,7 +80,7 @@ use crate::{ LocalModuleId, Lookup, MacroExpander, MacroId, ModuleId, ProcMacroId, UseId, db::DefDatabase, item_scope::{BuiltinShadowMode, ItemScope}, - item_tree::{ItemTreeId, Mod, TreeId}, + item_tree::{FileItemTreeId, Mod, TreeId}, nameres::{diagnostics::DefDiagnostic, path_resolution::ResolveMode}, per_ns::PerNs, visibility::{Visibility, VisibilityExplicitness}, @@ -289,11 +289,13 @@ pub enum ModuleOrigin { File { is_mod_rs: bool, declaration: FileAstId, - declaration_tree_id: ItemTreeId, + declaration_tree_id: TreeId, + file_item_tree_id: FileItemTreeId, definition: EditionedFileId, }, Inline { - definition_tree_id: ItemTreeId, + definition_tree_id: TreeId, + file_item_tree_id: FileItemTreeId, definition: FileAstId, }, /// Pseudo-module introduced by a block scope (contains only inner items). @@ -309,7 +311,7 @@ impl ModuleOrigin { &ModuleOrigin::File { declaration, declaration_tree_id, .. } => { Some(AstId::new(declaration_tree_id.file_id(), declaration)) } - &ModuleOrigin::Inline { definition, definition_tree_id } => { + &ModuleOrigin::Inline { definition, definition_tree_id, file_item_tree_id: _ } => { Some(AstId::new(definition_tree_id.file_id(), definition)) } ModuleOrigin::CrateRoot { .. } | ModuleOrigin::BlockExpr { .. } => None, @@ -341,12 +343,14 @@ impl ModuleOrigin { let sf = db.parse(editioned_file_id).tree(); InFile::new(editioned_file_id.into(), ModuleSource::SourceFile(sf)) } - &ModuleOrigin::Inline { definition, definition_tree_id } => InFile::new( - definition_tree_id.file_id(), - ModuleSource::Module( - AstId::new(definition_tree_id.file_id(), definition).to_node(db), - ), - ), + &ModuleOrigin::Inline { definition, definition_tree_id, file_item_tree_id: _ } => { + InFile::new( + definition_tree_id.file_id(), + ModuleSource::Module( + AstId::new(definition_tree_id.file_id(), definition).to_node(db), + ), + ) + } ModuleOrigin::BlockExpr { block, .. } => { InFile::new(block.file_id, ModuleSource::BlockExpr(block.to_node(db))) } @@ -773,10 +777,12 @@ impl ModuleData { ErasedAstId::new(definition.into(), ROOT_ERASED_FILE_AST_ID).to_range(db), ) } - &ModuleOrigin::Inline { definition, definition_tree_id } => InFile::new( - definition_tree_id.file_id(), - AstId::new(definition_tree_id.file_id(), definition).to_range(db), - ), + &ModuleOrigin::Inline { definition, definition_tree_id, file_item_tree_id: _ } => { + InFile::new( + definition_tree_id.file_id(), + AstId::new(definition_tree_id.file_id(), definition).to_range(db), + ) + } ModuleOrigin::BlockExpr { block, .. } => InFile::new(block.file_id, block.to_range(db)), } } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs index 34a129a88eaa1..e2231857fdb36 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs @@ -35,8 +35,8 @@ use crate::{ db::DefDatabase, item_scope::{GlobId, ImportId, ImportOrExternCrate, PerNsGlobImports}, item_tree::{ - self, FieldsShape, FileItemTreeId, ImportAlias, ImportKind, ItemTree, ItemTreeId, - ItemTreeNode, Macro2, MacroCall, MacroRules, Mod, ModItem, ModKind, TreeId, UseTreeKind, + self, FieldsShape, FileItemTreeId, ImportAlias, ImportKind, ItemTree, ItemTreeNode, Macro2, + MacroCall, MacroRules, Mod, ModItem, ModKind, TreeId, UseTreeKind, }, macro_call_as_call_id, nameres::{ @@ -140,7 +140,8 @@ struct ImportSource { id: UseId, is_prelude: bool, kind: ImportKind, - item_tree_id: ItemTreeId, + tree: TreeId, + item: FileItemTreeId, } #[derive(Debug, Eq, PartialEq)] @@ -154,19 +155,20 @@ struct Import { impl Import { fn from_use( tree: &ItemTree, - item_tree_id: ItemTreeId, + tree_id: TreeId, + item: FileItemTreeId, id: UseId, is_prelude: bool, mut cb: impl FnMut(Self), ) { - let it = &tree[item_tree_id.value]; + let it = &tree[item]; let visibility = &tree[it.visibility]; it.use_tree.expand(|idx, path, kind, alias| { cb(Self { path, alias, visibility: visibility.clone(), - source: ImportSource { use_tree: idx, id, is_prelude, kind, item_tree_id }, + source: ImportSource { use_tree: idx, id, is_prelude, kind, tree: tree_id, item }, }); }); } @@ -860,7 +862,8 @@ impl DefCollector<'_> { kind: kind @ (ImportKind::Plain | ImportKind::TypeOnly), id, use_tree, - item_tree_id, + tree, + item, .. } => { let name = match &import.alias { @@ -893,8 +896,8 @@ impl DefCollector<'_> { let Some(ImportOrExternCrate::ExternCrate(_)) = def.import else { return false; }; - let item_tree = item_tree_id.item_tree(self.db); - let use_kind = item_tree[item_tree_id.value].use_tree.kind(); + let item_tree = tree.item_tree(self.db); + let use_kind = item_tree[item].use_tree.kind(); let UseTreeKind::Single { path, .. } = use_kind else { return false; }; @@ -1643,7 +1646,7 @@ impl DefCollector<'_> { Import { ref path, source: - ImportSource { use_tree, id, is_prelude: _, kind: _, item_tree_id: _ }, + ImportSource { use_tree, id, is_prelude: _, kind: _, tree: _, item: _ }, .. }, .. @@ -1771,7 +1774,8 @@ impl ModCollector<'_, '_> { let is_prelude = attrs.by_key(sym::prelude_import).exists(); Import::from_use( self.item_tree, - ItemTreeId::new(self.tree_id, item_tree_id), + self.tree_id, + item_tree_id, id, is_prelude, |import| { @@ -2207,13 +2211,15 @@ impl ModCollector<'_, '_> { let origin = match definition { None => ModuleOrigin::Inline { definition: declaration, - definition_tree_id: ItemTreeId::new(self.tree_id, mod_tree_id), + definition_tree_id: self.tree_id, + file_item_tree_id: mod_tree_id, }, Some((definition, is_mod_rs)) => ModuleOrigin::File { declaration, definition, is_mod_rs, - declaration_tree_id: ItemTreeId::new(self.tree_id, mod_tree_id), + declaration_tree_id: self.tree_id, + file_item_tree_id: mod_tree_id, }, }; From a265cdd10e400f05a55e4624d28470e861ed7723 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 12 Jun 2025 10:17:45 +0200 Subject: [PATCH 18/56] Remove `FileItemTreeId` --- .../rust-analyzer/crates/hir-def/src/attr.rs | 19 +-- .../crates/hir-def/src/item_tree.rs | 115 ++++++------------ .../crates/hir-def/src/item_tree/lower.rs | 102 ++++++++-------- .../crates/hir-def/src/nameres.rs | 30 ++--- .../crates/hir-def/src/nameres/collector.rs | 31 ++--- 5 files changed, 116 insertions(+), 181 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/attr.rs b/src/tools/rust-analyzer/crates/hir-def/src/attr.rs index cc9a2fdf4c7bb..e1bf6fde8a522 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/attr.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/attr.rs @@ -523,15 +523,10 @@ impl AttrsWithOwner { let mod_data = &def_map[module.local_id]; let raw_attrs = match mod_data.origin { - ModuleOrigin::File { - definition, - declaration_tree_id, - file_item_tree_id, - .. - } => { + ModuleOrigin::File { definition, declaration_tree_id, declaration, .. } => { let decl_attrs = declaration_tree_id .item_tree(db) - .raw_attrs(AttrOwner::ModItem(file_item_tree_id.into())) + .raw_attrs(AttrOwner::ModItem(declaration.into())) .clone(); let tree = db.file_item_tree(definition.into()); let def_attrs = tree.raw_attrs(AttrOwner::TopLevel).clone(); @@ -541,12 +536,10 @@ impl AttrsWithOwner { let tree = db.file_item_tree(definition.into()); tree.raw_attrs(AttrOwner::TopLevel).clone() } - ModuleOrigin::Inline { definition_tree_id, file_item_tree_id, .. } => { - definition_tree_id - .item_tree(db) - .raw_attrs(AttrOwner::ModItem(file_item_tree_id.into())) - .clone() - } + ModuleOrigin::Inline { definition_tree_id, definition } => definition_tree_id + .item_tree(db) + .raw_attrs(AttrOwner::ModItem(definition.into())) + .clone(), ModuleOrigin::BlockExpr { id, .. } => { let tree = db.block_item_tree(id); tree.raw_attrs(AttrOwner::TopLevel).clone() diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs index ec2b65c9c00d2..578f5fdee2fc9 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs @@ -37,8 +37,8 @@ mod tests; use std::{ fmt::{self, Debug}, - hash::{Hash, Hasher}, - ops::{Index, Range}, + hash::Hash, + ops::Index, sync::OnceLock, }; @@ -51,7 +51,7 @@ use hir_expand::{ name::Name, }; use intern::Interned; -use la_arena::{Arena, Idx, RawIdx}; +use la_arena::{Arena, Idx}; use rustc_hash::FxHashMap; use smallvec::SmallVec; use span::{AstIdNode, Edition, FileAstId, SyntaxContext}; @@ -277,23 +277,23 @@ struct ItemVisibilities { #[derive(Default, Debug, Eq, PartialEq)] struct ItemTreeData { - uses: Arena, - extern_crates: Arena, - extern_blocks: Arena, - functions: Arena, - structs: Arena, - unions: Arena, - enums: Arena, - consts: Arena, - statics: Arena, - traits: Arena, - trait_aliases: Arena, - impls: Arena, - type_aliases: Arena, - mods: Arena, - macro_calls: Arena, - macro_rules: Arena, - macro_defs: Arena, + uses: FxHashMap, Use>, + extern_crates: FxHashMap, ExternCrate>, + extern_blocks: FxHashMap, ExternBlock>, + functions: FxHashMap, Function>, + structs: FxHashMap, Struct>, + unions: FxHashMap, Union>, + enums: FxHashMap, Enum>, + consts: FxHashMap, Const>, + statics: FxHashMap, Static>, + traits: FxHashMap, Trait>, + trait_aliases: FxHashMap, TraitAlias>, + impls: FxHashMap, Impl>, + type_aliases: FxHashMap, TypeAlias>, + mods: FxHashMap, Mod>, + macro_calls: FxHashMap, MacroCall>, + macro_rules: FxHashMap, MacroRules>, + macro_defs: FxHashMap, Macro2>, vis: ItemVisibilities, } @@ -329,51 +329,11 @@ pub trait ItemTreeNode: Clone { fn ast_id(&self) -> FileAstId; /// Looks up an instance of `Self` in an item tree. - fn lookup(tree: &ItemTree, index: Idx) -> &Self; + fn lookup(tree: &ItemTree, index: FileAstId) -> &Self; } -pub struct FileItemTreeId(Idx); - -impl FileItemTreeId { - pub fn range_iter(range: Range) -> impl Iterator + Clone { - (range.start.index().into_raw().into_u32()..range.end.index().into_raw().into_u32()) - .map(RawIdx::from_u32) - .map(Idx::from_raw) - .map(Self) - } -} - -impl FileItemTreeId { - pub fn index(&self) -> Idx { - self.0 - } -} - -impl Clone for FileItemTreeId { - fn clone(&self) -> Self { - *self - } -} -impl Copy for FileItemTreeId {} - -impl PartialEq for FileItemTreeId { - fn eq(&self, other: &FileItemTreeId) -> bool { - self.0 == other.0 - } -} -impl Eq for FileItemTreeId {} - -impl Hash for FileItemTreeId { - fn hash(&self, state: &mut H) { - self.0.hash(state) - } -} - -impl fmt::Debug for FileItemTreeId { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.0.fmt(f) - } -} +#[allow(type_alias_bounds)] +pub type ItemTreeAstId = FileAstId; /// Identifies a particular [`ItemTree`]. #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] @@ -409,21 +369,21 @@ macro_rules! mod_items { #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] pub enum ModItem { $( - $typ(FileItemTreeId<$typ>), + $typ(FileAstId<$ast>), )+ } impl ModItem { - pub fn ast_id(&self, tree: &ItemTree) -> FileAstId { + pub fn ast_id(self) -> FileAstId { match self { - $(ModItem::$typ(it) => tree[it.index()].ast_id().upcast()),+ + $(ModItem::$typ(it) => it.upcast()),+ } } } $( - impl From> for ModItem { - fn from(id: FileItemTreeId<$typ>) -> ModItem { + impl From> for ModItem { + fn from(id: FileAstId<$ast>) -> ModItem { ModItem::$typ(id) } } @@ -433,20 +393,20 @@ macro_rules! mod_items { impl ItemTreeNode for $typ { type Source = $ast; - fn ast_id(&self) -> FileAstId { + fn ast_id(&self) -> FileAstId<$ast> { self.ast_id } - fn lookup(tree: &ItemTree, index: Idx) -> &Self { - &tree.data().$fld[index] + fn lookup(tree: &ItemTree, index: FileAstId<$ast>) -> &Self { + &tree.data().$fld[&index] } } - impl Index> for ItemTree { + impl Index> for ItemTree { type Output = $typ; - fn index(&self, index: Idx<$typ>) -> &Self::Output { - &self.data().$fld[index] + fn index(&self, index: FileAstId<$ast>) -> &Self::Output { + &self.data().$fld[&index] } } )+ @@ -506,13 +466,6 @@ impl Index for ItemTree { } } -impl Index> for ItemTree { - type Output = N; - fn index(&self, id: FileItemTreeId) -> &N { - N::lookup(self, id.index()) - } -} - #[derive(Debug, Clone, Eq, PartialEq)] pub struct Use { pub visibility: RawVisibilityId, diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs index 26d209c972f7c..17b115b6ec5f6 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs @@ -20,18 +20,14 @@ use triomphe::Arc; use crate::{ db::DefDatabase, item_tree::{ - AttrOwner, Const, Enum, ExternBlock, ExternCrate, FieldsShape, FileItemTreeId, Function, - Idx, Impl, ImportAlias, Interned, ItemTree, ItemTreeData, Macro2, MacroCall, MacroRules, - Mod, ModItem, ModKind, ModPath, RawAttrs, RawVisibility, RawVisibilityId, Static, Struct, + AttrOwner, Const, Enum, ExternBlock, ExternCrate, FieldsShape, Function, Impl, ImportAlias, + Interned, ItemTree, ItemTreeAstId, ItemTreeData, Macro2, MacroCall, MacroRules, Mod, + ModItem, ModKind, ModPath, RawAttrs, RawVisibility, RawVisibilityId, Static, Struct, StructKind, Trait, TraitAlias, TypeAlias, Union, Use, UseTree, UseTreeKind, VisibilityExplicitness, }, }; -fn id(index: Idx) -> FileItemTreeId { - FileItemTreeId(index) -} - pub(super) struct Ctx<'a> { db: &'a dyn DefDatabase, tree: ItemTree, @@ -173,36 +169,36 @@ impl<'a> Ctx<'a> { } } - fn lower_struct(&mut self, strukt: &ast::Struct) -> Option> { + fn lower_struct(&mut self, strukt: &ast::Struct) -> Option> { let visibility = self.lower_visibility(strukt); let name = strukt.name()?.as_name(); let ast_id = self.source_ast_id_map.ast_id(strukt); let shape = adt_shape(strukt.kind()); let res = Struct { name, visibility, shape, ast_id }; - let id = id(self.data().structs.alloc(res)); + self.data().structs.insert(ast_id, res); - Some(id) + Some(ast_id) } - fn lower_union(&mut self, union: &ast::Union) -> Option> { + fn lower_union(&mut self, union: &ast::Union) -> Option> { let visibility = self.lower_visibility(union); let name = union.name()?.as_name(); let ast_id = self.source_ast_id_map.ast_id(union); let res = Union { name, visibility, ast_id }; - let id = id(self.data().unions.alloc(res)); - Some(id) + self.data().unions.insert(ast_id, res); + Some(ast_id) } - fn lower_enum(&mut self, enum_: &ast::Enum) -> Option> { + fn lower_enum(&mut self, enum_: &ast::Enum) -> Option> { let visibility = self.lower_visibility(enum_); let name = enum_.name()?.as_name(); let ast_id = self.source_ast_id_map.ast_id(enum_); let res = Enum { name, visibility, ast_id }; - let id = id(self.data().enums.alloc(res)); - Some(id) + self.data().enums.insert(ast_id, res); + Some(ast_id) } - fn lower_function(&mut self, func: &ast::Fn) -> Option> { + fn lower_function(&mut self, func: &ast::Fn) -> Option> { let visibility = self.lower_visibility(func); let name = func.name()?.as_name(); @@ -210,39 +206,41 @@ impl<'a> Ctx<'a> { let res = Function { name, visibility, ast_id }; - let id = id(self.data().functions.alloc(res)); - Some(id) + self.data().functions.insert(ast_id, res); + Some(ast_id) } fn lower_type_alias( &mut self, type_alias: &ast::TypeAlias, - ) -> Option> { + ) -> Option> { let name = type_alias.name()?.as_name(); let visibility = self.lower_visibility(type_alias); let ast_id = self.source_ast_id_map.ast_id(type_alias); let res = TypeAlias { name, visibility, ast_id }; - let id = id(self.data().type_aliases.alloc(res)); - Some(id) + self.data().type_aliases.insert(ast_id, res); + Some(ast_id) } - fn lower_static(&mut self, static_: &ast::Static) -> Option> { + fn lower_static(&mut self, static_: &ast::Static) -> Option> { let name = static_.name()?.as_name(); let visibility = self.lower_visibility(static_); let ast_id = self.source_ast_id_map.ast_id(static_); let res = Static { name, visibility, ast_id }; - Some(id(self.data().statics.alloc(res))) + self.data().statics.insert(ast_id, res); + Some(ast_id) } - fn lower_const(&mut self, konst: &ast::Const) -> FileItemTreeId { + fn lower_const(&mut self, konst: &ast::Const) -> ItemTreeAstId { let name = konst.name().map(|it| it.as_name()); let visibility = self.lower_visibility(konst); let ast_id = self.source_ast_id_map.ast_id(konst); let res = Const { name, visibility, ast_id }; - id(self.data().consts.alloc(res)) + self.data().consts.insert(ast_id, res); + ast_id } - fn lower_module(&mut self, module: &ast::Module) -> Option> { + fn lower_module(&mut self, module: &ast::Module) -> Option> { let name = module.name()?.as_name(); let visibility = self.lower_visibility(module); let kind = if module.semicolon_token().is_some() { @@ -260,41 +258,43 @@ impl<'a> Ctx<'a> { }; let ast_id = self.source_ast_id_map.ast_id(module); let res = Mod { name, visibility, kind, ast_id }; - Some(id(self.data().mods.alloc(res))) + self.data().mods.insert(ast_id, res); + Some(ast_id) } - fn lower_trait(&mut self, trait_def: &ast::Trait) -> Option> { + fn lower_trait(&mut self, trait_def: &ast::Trait) -> Option> { let name = trait_def.name()?.as_name(); let visibility = self.lower_visibility(trait_def); let ast_id = self.source_ast_id_map.ast_id(trait_def); let def = Trait { name, visibility, ast_id }; - let id = id(self.data().traits.alloc(def)); - Some(id) + self.data().traits.insert(ast_id, def); + Some(ast_id) } fn lower_trait_alias( &mut self, trait_alias_def: &ast::TraitAlias, - ) -> Option> { + ) -> Option> { let name = trait_alias_def.name()?.as_name(); let visibility = self.lower_visibility(trait_alias_def); let ast_id = self.source_ast_id_map.ast_id(trait_alias_def); let alias = TraitAlias { name, visibility, ast_id }; - let id = id(self.data().trait_aliases.alloc(alias)); - Some(id) + self.data().trait_aliases.insert(ast_id, alias); + Some(ast_id) } - fn lower_impl(&mut self, impl_def: &ast::Impl) -> FileItemTreeId { + fn lower_impl(&mut self, impl_def: &ast::Impl) -> ItemTreeAstId { let ast_id = self.source_ast_id_map.ast_id(impl_def); // Note that trait impls don't get implicit `Self` unlike traits, because here they are a // type alias rather than a type parameter, so this is handled by the resolver. let res = Impl { ast_id }; - id(self.data().impls.alloc(res)) + self.data().impls.insert(ast_id, res); + ast_id } - fn lower_use(&mut self, use_item: &ast::Use) -> Option> { + fn lower_use(&mut self, use_item: &ast::Use) -> Option> { let visibility = self.lower_visibility(use_item); let ast_id = self.source_ast_id_map.ast_id(use_item); let (use_tree, _) = lower_use_tree(self.db, use_item.use_tree()?, &mut |range| { @@ -302,13 +302,14 @@ impl<'a> Ctx<'a> { })?; let res = Use { visibility, ast_id, use_tree }; - Some(id(self.data().uses.alloc(res))) + self.data().uses.insert(ast_id, res); + Some(ast_id) } fn lower_extern_crate( &mut self, extern_crate: &ast::ExternCrate, - ) -> Option> { + ) -> Option> { let name = extern_crate.name_ref()?.as_name(); let alias = extern_crate.rename().map(|a| { a.name().map(|it| it.as_name()).map_or(ImportAlias::Underscore, ImportAlias::Alias) @@ -317,10 +318,11 @@ impl<'a> Ctx<'a> { let ast_id = self.source_ast_id_map.ast_id(extern_crate); let res = ExternCrate { name, alias, visibility, ast_id }; - Some(id(self.data().extern_crates.alloc(res))) + self.data().extern_crates.insert(ast_id, res); + Some(ast_id) } - fn lower_macro_call(&mut self, m: &ast::MacroCall) -> Option> { + fn lower_macro_call(&mut self, m: &ast::MacroCall) -> Option> { let span_map = self.span_map(); let path = m.path()?; let range = path.syntax().text_range(); @@ -330,28 +332,31 @@ impl<'a> Ctx<'a> { let ast_id = self.source_ast_id_map.ast_id(m); let expand_to = hir_expand::ExpandTo::from_call_site(m); let res = MacroCall { path, ast_id, expand_to, ctxt: span_map.span_for_range(range).ctx }; - Some(id(self.data().macro_calls.alloc(res))) + self.data().macro_calls.insert(ast_id, res); + Some(ast_id) } - fn lower_macro_rules(&mut self, m: &ast::MacroRules) -> Option> { + fn lower_macro_rules(&mut self, m: &ast::MacroRules) -> Option> { let name = m.name()?; let ast_id = self.source_ast_id_map.ast_id(m); let res = MacroRules { name: name.as_name(), ast_id }; - Some(id(self.data().macro_rules.alloc(res))) + self.data().macro_rules.insert(ast_id, res); + Some(ast_id) } - fn lower_macro_def(&mut self, m: &ast::MacroDef) -> Option> { + fn lower_macro_def(&mut self, m: &ast::MacroDef) -> Option> { let name = m.name()?; let ast_id = self.source_ast_id_map.ast_id(m); let visibility = self.lower_visibility(m); let res = Macro2 { name: name.as_name(), ast_id, visibility }; - Some(id(self.data().macro_defs.alloc(res))) + self.data().macro_defs.insert(ast_id, res); + Some(ast_id) } - fn lower_extern_block(&mut self, block: &ast::ExternBlock) -> FileItemTreeId { + fn lower_extern_block(&mut self, block: &ast::ExternBlock) -> ItemTreeAstId { let ast_id = self.source_ast_id_map.ast_id(block); let children: Box<[_]> = block.extern_item_list().map_or(Box::new([]), |list| { list.extern_items() @@ -374,7 +379,8 @@ impl<'a> Ctx<'a> { }); let res = ExternBlock { ast_id, children }; - id(self.data().extern_blocks.alloc(res)) + self.data().extern_blocks.insert(ast_id, res); + ast_id } fn lower_visibility(&mut self, item: &dyn ast::HasVisibility) -> RawVisibilityId { diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs index e62fd3dab7a33..610bb6b00b024 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs @@ -80,7 +80,7 @@ use crate::{ LocalModuleId, Lookup, MacroExpander, MacroId, ModuleId, ProcMacroId, UseId, db::DefDatabase, item_scope::{BuiltinShadowMode, ItemScope}, - item_tree::{FileItemTreeId, Mod, TreeId}, + item_tree::TreeId, nameres::{diagnostics::DefDiagnostic, path_resolution::ResolveMode}, per_ns::PerNs, visibility::{Visibility, VisibilityExplicitness}, @@ -290,12 +290,10 @@ pub enum ModuleOrigin { is_mod_rs: bool, declaration: FileAstId, declaration_tree_id: TreeId, - file_item_tree_id: FileItemTreeId, definition: EditionedFileId, }, Inline { definition_tree_id: TreeId, - file_item_tree_id: FileItemTreeId, definition: FileAstId, }, /// Pseudo-module introduced by a block scope (contains only inner items). @@ -311,7 +309,7 @@ impl ModuleOrigin { &ModuleOrigin::File { declaration, declaration_tree_id, .. } => { Some(AstId::new(declaration_tree_id.file_id(), declaration)) } - &ModuleOrigin::Inline { definition, definition_tree_id, file_item_tree_id: _ } => { + &ModuleOrigin::Inline { definition, definition_tree_id } => { Some(AstId::new(definition_tree_id.file_id(), definition)) } ModuleOrigin::CrateRoot { .. } | ModuleOrigin::BlockExpr { .. } => None, @@ -343,14 +341,12 @@ impl ModuleOrigin { let sf = db.parse(editioned_file_id).tree(); InFile::new(editioned_file_id.into(), ModuleSource::SourceFile(sf)) } - &ModuleOrigin::Inline { definition, definition_tree_id, file_item_tree_id: _ } => { - InFile::new( - definition_tree_id.file_id(), - ModuleSource::Module( - AstId::new(definition_tree_id.file_id(), definition).to_node(db), - ), - ) - } + &ModuleOrigin::Inline { definition, definition_tree_id } => InFile::new( + definition_tree_id.file_id(), + ModuleSource::Module( + AstId::new(definition_tree_id.file_id(), definition).to_node(db), + ), + ), ModuleOrigin::BlockExpr { block, .. } => { InFile::new(block.file_id, ModuleSource::BlockExpr(block.to_node(db))) } @@ -777,12 +773,10 @@ impl ModuleData { ErasedAstId::new(definition.into(), ROOT_ERASED_FILE_AST_ID).to_range(db), ) } - &ModuleOrigin::Inline { definition, definition_tree_id, file_item_tree_id: _ } => { - InFile::new( - definition_tree_id.file_id(), - AstId::new(definition_tree_id.file_id(), definition).to_range(db), - ) - } + &ModuleOrigin::Inline { definition, definition_tree_id } => InFile::new( + definition_tree_id.file_id(), + AstId::new(definition_tree_id.file_id(), definition).to_range(db), + ), ModuleOrigin::BlockExpr { block, .. } => InFile::new(block.file_id, block.to_range(db)), } } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs index e2231857fdb36..a8ee92d813720 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs @@ -35,7 +35,7 @@ use crate::{ db::DefDatabase, item_scope::{GlobId, ImportId, ImportOrExternCrate, PerNsGlobImports}, item_tree::{ - self, FieldsShape, FileItemTreeId, ImportAlias, ImportKind, ItemTree, ItemTreeNode, Macro2, + self, FieldsShape, ImportAlias, ImportKind, ItemTree, ItemTreeAstId, ItemTreeNode, Macro2, MacroCall, MacroRules, Mod, ModItem, ModKind, TreeId, UseTreeKind, }, macro_call_as_call_id, @@ -141,7 +141,7 @@ struct ImportSource { is_prelude: bool, kind: ImportKind, tree: TreeId, - item: FileItemTreeId, + item: FileAstId, } #[derive(Debug, Eq, PartialEq)] @@ -156,7 +156,7 @@ impl Import { fn from_use( tree: &ItemTree, tree_id: TreeId, - item: FileItemTreeId, + item: FileAstId, id: UseId, is_prelude: bool, mut cb: impl FnMut(Self), @@ -2084,7 +2084,7 @@ impl ModCollector<'_, '_> { ); } - fn collect_module(&mut self, module_id: FileItemTreeId, attrs: &Attrs) { + fn collect_module(&mut self, module_id: ItemTreeAstId, attrs: &Attrs) { let path_attr = attrs.by_key(sym::path).string_value_unescape(); let is_macro_use = attrs.by_key(sym::macro_use).exists(); let module = &self.item_tree[module_id]; @@ -2096,7 +2096,6 @@ impl ModCollector<'_, '_> { module.ast_id, None, &self.item_tree[module.visibility], - module_id, ); let Some(mod_dir) = @@ -2151,7 +2150,6 @@ impl ModCollector<'_, '_> { ast_id.value, Some((file_id, is_mod_rs)), &self.item_tree[module.visibility], - module_id, ); ModCollector { def_collector: self.def_collector, @@ -2179,7 +2177,6 @@ impl ModCollector<'_, '_> { ast_id.value, None, &self.item_tree[module.visibility], - module_id, ); self.def_collector.def_map.diagnostics.push( DefDiagnostic::unresolved_module(self.module_id, ast_id, candidates), @@ -2196,7 +2193,6 @@ impl ModCollector<'_, '_> { declaration: FileAstId, definition: Option<(EditionedFileId, bool)>, visibility: &crate::visibility::RawVisibility, - mod_tree_id: FileItemTreeId, ) -> LocalModuleId { let def_map = &mut self.def_collector.def_map; let vis = def_map @@ -2209,17 +2205,14 @@ impl ModCollector<'_, '_> { ) .unwrap_or(Visibility::Public); let origin = match definition { - None => ModuleOrigin::Inline { - definition: declaration, - definition_tree_id: self.tree_id, - file_item_tree_id: mod_tree_id, - }, + None => { + ModuleOrigin::Inline { definition: declaration, definition_tree_id: self.tree_id } + } Some((definition, is_mod_rs)) => ModuleOrigin::File { declaration, definition, is_mod_rs, declaration_tree_id: self.tree_id, - file_item_tree_id: mod_tree_id, }, }; @@ -2294,11 +2287,7 @@ impl ModCollector<'_, '_> { attr.path.display(self.def_collector.db, Edition::LATEST) ); - let ast_id = AstIdWithPath::new( - self.file_id(), - mod_item.ast_id(self.item_tree), - attr.path.clone(), - ); + let ast_id = AstIdWithPath::new(self.file_id(), mod_item.ast_id(), attr.path.clone()); self.def_collector.unresolved_macros.push(MacroDirective { module_id: self.module_id, depth: self.macro_depth + 1, @@ -2317,7 +2306,7 @@ impl ModCollector<'_, '_> { Ok(()) } - fn collect_macro_rules(&mut self, id: FileItemTreeId, module: ModuleId) { + fn collect_macro_rules(&mut self, id: ItemTreeAstId, module: ModuleId) { let krate = self.def_collector.def_map.krate; let mac = &self.item_tree[id]; let attrs = self.item_tree.attrs(self.def_collector.db, krate, ModItem::from(id).into()); @@ -2402,7 +2391,7 @@ impl ModCollector<'_, '_> { ); } - fn collect_macro_def(&mut self, id: FileItemTreeId, module: ModuleId) { + fn collect_macro_def(&mut self, id: ItemTreeAstId, module: ModuleId) { let krate = self.def_collector.def_map.krate; let mac = &self.item_tree[id]; let ast_id = InFile::new(self.file_id(), mac.ast_id.upcast()); From 834579f1485e81fd937d329d5bea23fe076c7084 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 12 Jun 2025 10:25:21 +0200 Subject: [PATCH 19/56] `AttrOwner` needs no `ModItem` --- .../rust-analyzer/crates/hir-def/src/attr.rs | 4 +- .../rust-analyzer/crates/hir-def/src/db.rs | 4 +- .../crates/hir-def/src/item_tree.rs | 32 +++++++------- .../crates/hir-def/src/nameres/collector.rs | 43 +++++++------------ 4 files changed, 36 insertions(+), 47 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/attr.rs b/src/tools/rust-analyzer/crates/hir-def/src/attr.rs index e1bf6fde8a522..08986d68e5f78 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/attr.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/attr.rs @@ -526,7 +526,7 @@ impl AttrsWithOwner { ModuleOrigin::File { definition, declaration_tree_id, declaration, .. } => { let decl_attrs = declaration_tree_id .item_tree(db) - .raw_attrs(AttrOwner::ModItem(declaration.into())) + .raw_attrs(AttrOwner::Item(declaration.erase())) .clone(); let tree = db.file_item_tree(definition.into()); let def_attrs = tree.raw_attrs(AttrOwner::TopLevel).clone(); @@ -538,7 +538,7 @@ impl AttrsWithOwner { } ModuleOrigin::Inline { definition_tree_id, definition } => definition_tree_id .item_tree(db) - .raw_attrs(AttrOwner::ModItem(definition.into())) + .raw_attrs(AttrOwner::Item(definition.erase())) .clone(), ModuleOrigin::BlockExpr { id, .. } => { let tree = db.block_item_tree(id); diff --git a/src/tools/rust-analyzer/crates/hir-def/src/db.rs b/src/tools/rust-analyzer/crates/hir-def/src/db.rs index 362c0daa9bbe9..95e33dde58f08 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/db.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/db.rs @@ -24,7 +24,7 @@ use crate::{ }, hir::generics::GenericParams, import_map::ImportMap, - item_tree::{AttrOwner, ItemTree}, + item_tree::ItemTree, lang_item::{self, LangItem}, nameres::{ assoc::{ImplItems, TraitItems}, @@ -376,7 +376,7 @@ fn include_macro_invoc( fn crate_supports_no_std(db: &dyn DefDatabase, crate_id: Crate) -> bool { let file = crate_id.data(db).root_file_id(db); let item_tree = db.file_item_tree(file.into()); - let attrs = item_tree.raw_attrs(AttrOwner::TopLevel); + let attrs = item_tree.raw_attrs(crate::item_tree::AttrOwner::TopLevel); for attr in &**attrs { match attr.path().as_ident() { Some(ident) if *ident == sym::no_std => return true, diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs index 578f5fdee2fc9..4b3890ae9680b 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs @@ -51,10 +51,10 @@ use hir_expand::{ name::Name, }; use intern::Interned; -use la_arena::{Arena, Idx}; +use la_arena::Idx; use rustc_hash::FxHashMap; use smallvec::SmallVec; -use span::{AstIdNode, Edition, FileAstId, SyntaxContext}; +use span::{AstIdNode, Edition, ErasedFileAstId, FileAstId, SyntaxContext}; use stdx::never; use syntax::{SyntaxKind, ast, match_ast}; use triomphe::Arc; @@ -90,6 +90,7 @@ impl fmt::Debug for RawVisibilityId { #[derive(Debug, Default, Eq, PartialEq)] pub struct ItemTree { top_level: SmallVec<[ModItem; 1]>, + // Consider splitting this into top level RawAttrs and the map? attrs: FxHashMap, data: Option>, @@ -174,7 +175,7 @@ impl ItemTree { /// Returns an iterator over all items located at the top level of the `HirFileId` this /// `ItemTree` was created from. - pub fn top_level_items(&self) -> &[ModItem] { + pub(crate) fn top_level_items(&self) -> &[ModItem] { &self.top_level } @@ -310,7 +311,7 @@ pub struct ItemTreeDataStats { #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] pub enum AttrOwner { /// Attributes on an item. - ModItem(ModItem), + Item(ErasedFileAstId), /// Inner attributes of the source file. TopLevel, } @@ -318,7 +319,7 @@ pub enum AttrOwner { impl From for AttrOwner { #[inline] fn from(value: ModItem) -> Self { - AttrOwner::ModItem(value) + AttrOwner::Item(value.ast_id().erase()) } } @@ -365,25 +366,25 @@ impl TreeId { } macro_rules! mod_items { - ( $( $typ:ident in $fld:ident -> $ast:ty ),+ $(,)? ) => { + ($mod_item:ident -> $( $typ:ident in $fld:ident -> $ast:ty ),+ $(,)? ) => { #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] - pub enum ModItem { + pub(crate) enum $mod_item { $( $typ(FileAstId<$ast>), )+ } - impl ModItem { - pub fn ast_id(self) -> FileAstId { + impl $mod_item { + pub(crate) fn ast_id(self) -> FileAstId { match self { - $(ModItem::$typ(it) => it.upcast()),+ + $($mod_item::$typ(it) => it.upcast()),+ } } } $( - impl From> for ModItem { - fn from(id: FileAstId<$ast>) -> ModItem { + impl From> for $mod_item { + fn from(id: FileAstId<$ast>) -> $mod_item { ModItem::$typ(id) } } @@ -414,6 +415,7 @@ macro_rules! mod_items { } mod_items! { +ModItem -> Use in uses -> ast::Use, ExternCrate in extern_crates -> ast::ExternCrate, ExternBlock in extern_blocks -> ast::ExternBlock, @@ -539,7 +541,7 @@ pub struct ExternCrate { #[derive(Debug, Clone, Eq, PartialEq)] pub struct ExternBlock { pub ast_id: FileAstId, - pub children: Box<[ModItem]>, + pub(crate) children: Box<[ModItem]>, } #[derive(Debug, Clone, Eq, PartialEq)] @@ -647,12 +649,12 @@ pub struct TypeAlias { pub struct Mod { pub name: Name, pub visibility: RawVisibilityId, - pub kind: ModKind, + pub(crate) kind: ModKind, pub ast_id: FileAstId, } #[derive(Debug, Clone, Eq, PartialEq)] -pub enum ModKind { +pub(crate) enum ModKind { /// `mod m { ... }` Inline { items: Box<[ModItem]> }, /// `mod m;` diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs index a8ee92d813720..703cb79b55ef7 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs @@ -35,8 +35,8 @@ use crate::{ db::DefDatabase, item_scope::{GlobId, ImportId, ImportOrExternCrate, PerNsGlobImports}, item_tree::{ - self, FieldsShape, ImportAlias, ImportKind, ItemTree, ItemTreeAstId, ItemTreeNode, Macro2, - MacroCall, MacroRules, Mod, ModItem, ModKind, TreeId, UseTreeKind, + self, AttrOwner, FieldsShape, ImportAlias, ImportKind, ItemTree, ItemTreeAstId, + ItemTreeNode, Macro2, MacroCall, MacroRules, Mod, ModItem, ModKind, TreeId, UseTreeKind, }, macro_call_as_call_id, nameres::{ @@ -246,7 +246,7 @@ struct DefCollector<'a> { /// This also stores the attributes to skip when we resolve derive helpers and non-macro /// non-builtin attributes in general. // FIXME: There has to be a better way to do this - skip_attrs: FxHashMap, AttrId>, + skip_attrs: FxHashMap>, AttrId>, } impl DefCollector<'_> { @@ -472,7 +472,7 @@ impl DefCollector<'_> { attr.path().clone(), )); - self.skip_attrs.insert(ast_id.ast_id.with_value(*mod_item), attr.id); + self.skip_attrs.insert(ast_id.ast_id.with_value(mod_item.ast_id()), attr.id); Some((idx, directive, *mod_item, *tree)) } @@ -1371,7 +1371,9 @@ impl DefCollector<'_> { let mut recollect_without = |collector: &mut Self| { // Remove the original directive since we resolved it. let mod_dir = collector.mod_dirs[&directive.module_id].clone(); - collector.skip_attrs.insert(InFile::new(file_id, *mod_item), attr.id); + collector + .skip_attrs + .insert(InFile::new(file_id, mod_item.ast_id()), attr.id); let item_tree = tree.item_tree(self.db); ModCollector { @@ -1728,25 +1730,7 @@ impl ModCollector<'_, '_> { let attrs = self.item_tree.attrs(db, krate, item.into()); if let Some(cfg) = attrs.cfg() { if !self.is_cfg_enabled(&cfg) { - let ast_id = match item { - ModItem::Use(it) => self.item_tree[it].ast_id.erase(), - ModItem::ExternCrate(it) => self.item_tree[it].ast_id.erase(), - ModItem::ExternBlock(it) => self.item_tree[it].ast_id.erase(), - ModItem::Function(it) => self.item_tree[it].ast_id.erase(), - ModItem::Struct(it) => self.item_tree[it].ast_id.erase(), - ModItem::Union(it) => self.item_tree[it].ast_id.erase(), - ModItem::Enum(it) => self.item_tree[it].ast_id.erase(), - ModItem::Const(it) => self.item_tree[it].ast_id.erase(), - ModItem::Static(it) => self.item_tree[it].ast_id.erase(), - ModItem::Trait(it) => self.item_tree[it].ast_id.erase(), - ModItem::TraitAlias(it) => self.item_tree[it].ast_id.erase(), - ModItem::Impl(it) => self.item_tree[it].ast_id.erase(), - ModItem::TypeAlias(it) => self.item_tree[it].ast_id.erase(), - ModItem::Mod(it) => self.item_tree[it].ast_id.erase(), - ModItem::MacroCall(it) => self.item_tree[it].ast_id.erase(), - ModItem::MacroRules(it) => self.item_tree[it].ast_id.erase(), - ModItem::Macro2(it) => self.item_tree[it].ast_id.erase(), - }; + let ast_id = item.ast_id().erase(); self.emit_unconfigured_diagnostic(InFile::new(self.file_id(), ast_id), &cfg); return; } @@ -2256,8 +2240,11 @@ impl ModCollector<'_, '_> { mod_item: ModItem, container: ItemContainerId, ) -> Result<(), ()> { - let mut ignore_up_to = - self.def_collector.skip_attrs.get(&InFile::new(self.file_id(), mod_item)).copied(); + let mut ignore_up_to = self + .def_collector + .skip_attrs + .get(&InFile::new(self.file_id(), mod_item.ast_id())) + .copied(); let iter = attrs .iter() .dedup_by(|a, b| { @@ -2309,7 +2296,7 @@ impl ModCollector<'_, '_> { fn collect_macro_rules(&mut self, id: ItemTreeAstId, module: ModuleId) { let krate = self.def_collector.def_map.krate; let mac = &self.item_tree[id]; - let attrs = self.item_tree.attrs(self.def_collector.db, krate, ModItem::from(id).into()); + let attrs = self.item_tree.attrs(self.def_collector.db, krate, AttrOwner::Item(id.erase())); let ast_id = InFile::new(self.file_id(), mac.ast_id.upcast()); let export_attr = || attrs.by_key(sym::macro_export); @@ -2398,7 +2385,7 @@ impl ModCollector<'_, '_> { // Case 1: builtin macros let mut helpers_opt = None; - let attrs = self.item_tree.attrs(self.def_collector.db, krate, ModItem::from(id).into()); + let attrs = self.item_tree.attrs(self.def_collector.db, krate, AttrOwner::Item(id.erase())); let expander = if attrs.by_key(sym::rustc_builtin_macro).exists() { if let Some(expander) = find_builtin_macro(&mac.name) { match expander { From e51cad90edc6498e7464164a2d97b1c9e17fa9df Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 12 Jun 2025 11:06:32 +0200 Subject: [PATCH 20/56] Coalesce item tree data maps --- .../crates/hir-def/src/item_tree.rs | 157 +++++++----------- .../crates/hir-def/src/item_tree/lower.rs | 63 +++---- .../crates/hir-def/src/item_tree/pretty.rs | 41 ++--- .../crates/hir-def/src/nameres/collector.rs | 58 +++---- 4 files changed, 138 insertions(+), 181 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs index 4b3890ae9680b..b295767399a1b 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs @@ -89,11 +89,12 @@ impl fmt::Debug for RawVisibilityId { /// The item tree of a source file. #[derive(Debug, Default, Eq, PartialEq)] pub struct ItemTree { - top_level: SmallVec<[ModItem; 1]>, + top_level: SmallVec<[ModItemId; 1]>, // Consider splitting this into top level RawAttrs and the map? attrs: FxHashMap, - data: Option>, + vis: ItemVisibilities, + data: FxHashMap, ModItem>, } impl ItemTree { @@ -130,14 +131,15 @@ impl ItemTree { if let Some(attrs) = top_attrs { item_tree.attrs.insert(AttrOwner::TopLevel, attrs); } - if item_tree.data.is_none() && item_tree.top_level.is_empty() && item_tree.attrs.is_empty() + if item_tree.data.is_empty() && item_tree.top_level.is_empty() && item_tree.attrs.is_empty() { EMPTY .get_or_init(|| { Arc::new(ItemTree { top_level: SmallVec::new_const(), attrs: FxHashMap::default(), - data: None, + data: FxHashMap::default(), + vis: ItemVisibilities { arena: Box::new([]) }, }) }) .clone() @@ -156,14 +158,15 @@ impl ItemTree { let ctx = lower::Ctx::new(db, loc.ast_id.file_id); let mut item_tree = ctx.lower_block(&block); - if item_tree.data.is_none() && item_tree.top_level.is_empty() && item_tree.attrs.is_empty() + if item_tree.data.is_empty() && item_tree.top_level.is_empty() && item_tree.attrs.is_empty() { EMPTY .get_or_init(|| { Arc::new(ItemTree { top_level: SmallVec::new_const(), attrs: FxHashMap::default(), - data: None, + data: FxHashMap::default(), + vis: ItemVisibilities { arena: Box::new([]) }, }) }) .clone() @@ -175,7 +178,7 @@ impl ItemTree { /// Returns an iterator over all items located at the top level of the `HirFileId` this /// `ItemTree` was created from. - pub(crate) fn top_level_items(&self) -> &[ModItem] { + pub(crate) fn top_level_items(&self) -> &[ModItemId] { &self.top_level } @@ -200,74 +203,33 @@ impl ItemTree { /// /// For more detail, see [`ItemTreeDataStats`]. pub fn item_tree_stats(&self) -> ItemTreeDataStats { - match self.data { - Some(ref data) => ItemTreeDataStats { - traits: data.traits.len(), - impls: data.impls.len(), - mods: data.mods.len(), - macro_calls: data.macro_calls.len(), - macro_rules: data.macro_rules.len(), - }, - None => ItemTreeDataStats::default(), + let mut traits = 0; + let mut impls = 0; + let mut mods = 0; + let mut macro_calls = 0; + let mut macro_rules = 0; + for item in self.data.values() { + match item { + ModItem::Trait(_) => traits += 1, + ModItem::Impl(_) => impls += 1, + ModItem::Mod(_) => mods += 1, + ModItem::MacroCall(_) => macro_calls += 1, + ModItem::MacroRules(_) => macro_rules += 1, + _ => {} + } } + ItemTreeDataStats { traits, impls, mods, macro_calls, macro_rules } } pub fn pretty_print(&self, db: &dyn DefDatabase, edition: Edition) -> String { pretty::print_item_tree(db, self, edition) } - fn data(&self) -> &ItemTreeData { - self.data.as_ref().expect("attempted to access data of empty ItemTree") - } - - fn data_mut(&mut self) -> &mut ItemTreeData { - self.data.get_or_insert_with(Box::default) - } - fn shrink_to_fit(&mut self) { - let ItemTree { top_level, attrs, data } = self; + let ItemTree { top_level, attrs, data, vis: _ } = self; top_level.shrink_to_fit(); attrs.shrink_to_fit(); - if let Some(data) = data { - let ItemTreeData { - uses, - extern_crates, - extern_blocks, - functions, - structs, - unions, - enums, - consts, - statics, - traits, - trait_aliases, - impls, - type_aliases, - mods, - macro_calls, - macro_rules, - macro_defs, - vis: _, - } = &mut **data; - - uses.shrink_to_fit(); - extern_crates.shrink_to_fit(); - extern_blocks.shrink_to_fit(); - functions.shrink_to_fit(); - structs.shrink_to_fit(); - unions.shrink_to_fit(); - enums.shrink_to_fit(); - consts.shrink_to_fit(); - statics.shrink_to_fit(); - traits.shrink_to_fit(); - trait_aliases.shrink_to_fit(); - impls.shrink_to_fit(); - type_aliases.shrink_to_fit(); - mods.shrink_to_fit(); - macro_calls.shrink_to_fit(); - macro_rules.shrink_to_fit(); - macro_defs.shrink_to_fit(); - } + data.shrink_to_fit(); } } @@ -276,29 +238,26 @@ struct ItemVisibilities { arena: Box<[RawVisibility]>, } -#[derive(Default, Debug, Eq, PartialEq)] -struct ItemTreeData { - uses: FxHashMap, Use>, - extern_crates: FxHashMap, ExternCrate>, - extern_blocks: FxHashMap, ExternBlock>, - functions: FxHashMap, Function>, - structs: FxHashMap, Struct>, - unions: FxHashMap, Union>, - enums: FxHashMap, Enum>, - consts: FxHashMap, Const>, - statics: FxHashMap, Static>, - traits: FxHashMap, Trait>, - trait_aliases: FxHashMap, TraitAlias>, - impls: FxHashMap, Impl>, - type_aliases: FxHashMap, TypeAlias>, - mods: FxHashMap, Mod>, - macro_calls: FxHashMap, MacroCall>, - macro_rules: FxHashMap, MacroRules>, - macro_defs: FxHashMap, Macro2>, - - vis: ItemVisibilities, +#[derive(Debug, Clone, Eq, PartialEq)] +enum ModItem { + Const(Const), + Enum(Enum), + ExternBlock(ExternBlock), + ExternCrate(ExternCrate), + Function(Function), + Impl(Impl), + Macro2(Macro2), + MacroCall(MacroCall), + MacroRules(MacroRules), + Mod(Mod), + Static(Static), + Struct(Struct), + Trait(Trait), + TraitAlias(TraitAlias), + TypeAlias(TypeAlias), + Union(Union), + Use(Use), } - #[derive(Default, Debug, Eq, PartialEq)] pub struct ItemTreeDataStats { pub traits: usize, @@ -316,9 +275,9 @@ pub enum AttrOwner { TopLevel, } -impl From for AttrOwner { +impl From for AttrOwner { #[inline] - fn from(value: ModItem) -> Self { + fn from(value: ModItemId) -> Self { AttrOwner::Item(value.ast_id().erase()) } } @@ -385,7 +344,7 @@ macro_rules! mod_items { $( impl From> for $mod_item { fn from(id: FileAstId<$ast>) -> $mod_item { - ModItem::$typ(id) + ModItemId::$typ(id) } } )+ @@ -399,7 +358,10 @@ macro_rules! mod_items { } fn lookup(tree: &ItemTree, index: FileAstId<$ast>) -> &Self { - &tree.data().$fld[&index] + match &tree.data[&index.upcast()] { + ModItem::$typ(item) => item, + _ => panic!("expected item of type `{}` at index `{:?}`", stringify!($typ), index), + } } } @@ -407,7 +369,10 @@ macro_rules! mod_items { type Output = $typ; fn index(&self, index: FileAstId<$ast>) -> &Self::Output { - &self.data().$fld[&index] + match &self.data[&index.upcast()] { + ModItem::$typ(item) => item, + _ => panic!("expected item of type `{}` at index `{:?}`", stringify!($typ), index), + } } } )+ @@ -415,7 +380,7 @@ macro_rules! mod_items { } mod_items! { -ModItem -> +ModItemId -> Use in uses -> ast::Use, ExternCrate in extern_crates -> ast::ExternCrate, ExternBlock in extern_blocks -> ast::ExternBlock, @@ -463,7 +428,7 @@ impl Index for ItemTree { VisibilityExplicitness::Explicit, ) }), - _ => &self.data().vis.arena[index.0 as usize], + _ => &self.vis.arena[index.0 as usize], } } } @@ -541,7 +506,7 @@ pub struct ExternCrate { #[derive(Debug, Clone, Eq, PartialEq)] pub struct ExternBlock { pub ast_id: FileAstId, - pub(crate) children: Box<[ModItem]>, + pub(crate) children: Box<[ModItemId]>, } #[derive(Debug, Clone, Eq, PartialEq)] @@ -656,7 +621,7 @@ pub struct Mod { #[derive(Debug, Clone, Eq, PartialEq)] pub(crate) enum ModKind { /// `mod m { ... }` - Inline { items: Box<[ModItem]> }, + Inline { items: Box<[ModItemId]> }, /// `mod m;` Outline, } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs index 17b115b6ec5f6..f3e71effe4b78 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs @@ -21,10 +21,9 @@ use crate::{ db::DefDatabase, item_tree::{ AttrOwner, Const, Enum, ExternBlock, ExternCrate, FieldsShape, Function, Impl, ImportAlias, - Interned, ItemTree, ItemTreeAstId, ItemTreeData, Macro2, MacroCall, MacroRules, Mod, - ModItem, ModKind, ModPath, RawAttrs, RawVisibility, RawVisibilityId, Static, Struct, - StructKind, Trait, TraitAlias, TypeAlias, Union, Use, UseTree, UseTreeKind, - VisibilityExplicitness, + Interned, ItemTree, ItemTreeAstId, Macro2, MacroCall, MacroRules, Mod, ModItem, ModItemId, + ModKind, ModPath, RawAttrs, RawVisibility, RawVisibilityId, Static, Struct, StructKind, + Trait, TraitAlias, TypeAlias, Union, Use, UseTree, UseTreeKind, VisibilityExplicitness, }, }; @@ -56,9 +55,7 @@ impl<'a> Ctx<'a> { pub(super) fn lower_module_items(mut self, item_owner: &dyn HasModuleItem) -> ItemTree { self.tree.top_level = item_owner.items().flat_map(|item| self.lower_mod_item(&item)).collect(); - if let Some(data) = &mut self.tree.data { - data.vis.arena = self.visibilities.into_iter().collect(); - } + self.tree.vis.arena = self.visibilities.into_iter().collect(); self.tree } @@ -92,9 +89,7 @@ impl<'a> Ctx<'a> { } } - if let Some(data) = &mut self.tree.data { - data.vis.arena = self.visibilities.into_iter().collect(); - } + self.tree.vis.arena = self.visibilities.into_iter().collect(); self.tree } @@ -120,18 +115,12 @@ impl<'a> Ctx<'a> { } } } - if let Some(data) = &mut self.tree.data { - data.vis.arena = self.visibilities.into_iter().collect(); - } + self.tree.vis.arena = self.visibilities.into_iter().collect(); self.tree } - fn data(&mut self) -> &mut ItemTreeData { - self.tree.data_mut() - } - - fn lower_mod_item(&mut self, item: &ast::Item) -> Option { - let mod_item: ModItem = match item { + fn lower_mod_item(&mut self, item: &ast::Item) -> Option { + let mod_item: ModItemId = match item { ast::Item::Struct(ast) => self.lower_struct(ast)?.into(), ast::Item::Union(ast) => self.lower_union(ast)?.into(), ast::Item::Enum(ast) => self.lower_enum(ast)?.into(), @@ -175,7 +164,7 @@ impl<'a> Ctx<'a> { let ast_id = self.source_ast_id_map.ast_id(strukt); let shape = adt_shape(strukt.kind()); let res = Struct { name, visibility, shape, ast_id }; - self.data().structs.insert(ast_id, res); + self.tree.data.insert(ast_id.upcast(), ModItem::Struct(res)); Some(ast_id) } @@ -185,7 +174,7 @@ impl<'a> Ctx<'a> { let name = union.name()?.as_name(); let ast_id = self.source_ast_id_map.ast_id(union); let res = Union { name, visibility, ast_id }; - self.data().unions.insert(ast_id, res); + self.tree.data.insert(ast_id.upcast(), ModItem::Union(res)); Some(ast_id) } @@ -194,7 +183,7 @@ impl<'a> Ctx<'a> { let name = enum_.name()?.as_name(); let ast_id = self.source_ast_id_map.ast_id(enum_); let res = Enum { name, visibility, ast_id }; - self.data().enums.insert(ast_id, res); + self.tree.data.insert(ast_id.upcast(), ModItem::Enum(res)); Some(ast_id) } @@ -206,7 +195,7 @@ impl<'a> Ctx<'a> { let res = Function { name, visibility, ast_id }; - self.data().functions.insert(ast_id, res); + self.tree.data.insert(ast_id.upcast(), ModItem::Function(res)); Some(ast_id) } @@ -218,7 +207,7 @@ impl<'a> Ctx<'a> { let visibility = self.lower_visibility(type_alias); let ast_id = self.source_ast_id_map.ast_id(type_alias); let res = TypeAlias { name, visibility, ast_id }; - self.data().type_aliases.insert(ast_id, res); + self.tree.data.insert(ast_id.upcast(), ModItem::TypeAlias(res)); Some(ast_id) } @@ -227,7 +216,7 @@ impl<'a> Ctx<'a> { let visibility = self.lower_visibility(static_); let ast_id = self.source_ast_id_map.ast_id(static_); let res = Static { name, visibility, ast_id }; - self.data().statics.insert(ast_id, res); + self.tree.data.insert(ast_id.upcast(), ModItem::Static(res)); Some(ast_id) } @@ -236,7 +225,7 @@ impl<'a> Ctx<'a> { let visibility = self.lower_visibility(konst); let ast_id = self.source_ast_id_map.ast_id(konst); let res = Const { name, visibility, ast_id }; - self.data().consts.insert(ast_id, res); + self.tree.data.insert(ast_id.upcast(), ModItem::Const(res)); ast_id } @@ -258,7 +247,7 @@ impl<'a> Ctx<'a> { }; let ast_id = self.source_ast_id_map.ast_id(module); let res = Mod { name, visibility, kind, ast_id }; - self.data().mods.insert(ast_id, res); + self.tree.data.insert(ast_id.upcast(), ModItem::Mod(res)); Some(ast_id) } @@ -268,7 +257,7 @@ impl<'a> Ctx<'a> { let ast_id = self.source_ast_id_map.ast_id(trait_def); let def = Trait { name, visibility, ast_id }; - self.data().traits.insert(ast_id, def); + self.tree.data.insert(ast_id.upcast(), ModItem::Trait(def)); Some(ast_id) } @@ -281,7 +270,7 @@ impl<'a> Ctx<'a> { let ast_id = self.source_ast_id_map.ast_id(trait_alias_def); let alias = TraitAlias { name, visibility, ast_id }; - self.data().trait_aliases.insert(ast_id, alias); + self.tree.data.insert(ast_id.upcast(), ModItem::TraitAlias(alias)); Some(ast_id) } @@ -290,7 +279,7 @@ impl<'a> Ctx<'a> { // Note that trait impls don't get implicit `Self` unlike traits, because here they are a // type alias rather than a type parameter, so this is handled by the resolver. let res = Impl { ast_id }; - self.data().impls.insert(ast_id, res); + self.tree.data.insert(ast_id.upcast(), ModItem::Impl(res)); ast_id } @@ -302,7 +291,7 @@ impl<'a> Ctx<'a> { })?; let res = Use { visibility, ast_id, use_tree }; - self.data().uses.insert(ast_id, res); + self.tree.data.insert(ast_id.upcast(), ModItem::Use(res)); Some(ast_id) } @@ -318,7 +307,7 @@ impl<'a> Ctx<'a> { let ast_id = self.source_ast_id_map.ast_id(extern_crate); let res = ExternCrate { name, alias, visibility, ast_id }; - self.data().extern_crates.insert(ast_id, res); + self.tree.data.insert(ast_id.upcast(), ModItem::ExternCrate(res)); Some(ast_id) } @@ -332,7 +321,7 @@ impl<'a> Ctx<'a> { let ast_id = self.source_ast_id_map.ast_id(m); let expand_to = hir_expand::ExpandTo::from_call_site(m); let res = MacroCall { path, ast_id, expand_to, ctxt: span_map.span_for_range(range).ctx }; - self.data().macro_calls.insert(ast_id, res); + self.tree.data.insert(ast_id.upcast(), ModItem::MacroCall(res)); Some(ast_id) } @@ -341,7 +330,7 @@ impl<'a> Ctx<'a> { let ast_id = self.source_ast_id_map.ast_id(m); let res = MacroRules { name: name.as_name(), ast_id }; - self.data().macro_rules.insert(ast_id, res); + self.tree.data.insert(ast_id.upcast(), ModItem::MacroRules(res)); Some(ast_id) } @@ -352,7 +341,7 @@ impl<'a> Ctx<'a> { let visibility = self.lower_visibility(m); let res = Macro2 { name: name.as_name(), ast_id, visibility }; - self.data().macro_defs.insert(ast_id, res); + self.tree.data.insert(ast_id.upcast(), ModItem::Macro2(res)); Some(ast_id) } @@ -365,7 +354,7 @@ impl<'a> Ctx<'a> { // (in other words, the knowledge that they're in an extern block must not be used). // This is because an extern block can contain macros whose ItemTree's top-level items // should be considered to be in an extern block too. - let mod_item: ModItem = match &item { + let mod_item: ModItemId = match &item { ast::ExternItem::Fn(ast) => self.lower_function(ast)?.into(), ast::ExternItem::Static(ast) => self.lower_static(ast)?.into(), ast::ExternItem::TypeAlias(ty) => self.lower_type_alias(ty)?.into(), @@ -379,7 +368,7 @@ impl<'a> Ctx<'a> { }); let res = ExternBlock { ast_id, children }; - self.data().extern_blocks.insert(ast_id, res); + self.tree.data.insert(ast_id.upcast(), ModItem::ExternBlock(res)); ast_id } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs index 0c62b86dae28b..9a5ca738362b3 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs @@ -7,8 +7,9 @@ use span::{Edition, ErasedFileAstId}; use crate::{ item_tree::{ AttrOwner, Const, DefDatabase, Enum, ExternBlock, ExternCrate, FieldsShape, Function, Impl, - ItemTree, Macro2, MacroCall, MacroRules, Mod, ModItem, ModKind, RawAttrs, RawVisibilityId, - Static, Struct, Trait, TraitAlias, TypeAlias, Union, Use, UseTree, UseTreeKind, + ItemTree, Macro2, MacroCall, MacroRules, Mod, ModItemId, ModKind, RawAttrs, + RawVisibilityId, Static, Struct, Trait, TraitAlias, TypeAlias, Union, Use, UseTree, + UseTreeKind, }, visibility::RawVisibility, }; @@ -159,11 +160,11 @@ impl Printer<'_> { } } - fn print_mod_item(&mut self, item: ModItem) { + fn print_mod_item(&mut self, item: ModItemId) { self.print_attrs_of(item, "\n"); match item { - ModItem::Use(it) => { + ModItemId::Use(it) => { let Use { visibility, use_tree, ast_id } = &self.tree[it]; self.print_ast_id(ast_id.erase()); self.print_visibility(*visibility); @@ -171,7 +172,7 @@ impl Printer<'_> { self.print_use_tree(use_tree); wln!(self, ";"); } - ModItem::ExternCrate(it) => { + ModItemId::ExternCrate(it) => { let ExternCrate { name, alias, visibility, ast_id } = &self.tree[it]; self.print_ast_id(ast_id.erase()); self.print_visibility(*visibility); @@ -181,7 +182,7 @@ impl Printer<'_> { } wln!(self, ";"); } - ModItem::ExternBlock(it) => { + ModItemId::ExternBlock(it) => { let ExternBlock { ast_id, children } = &self.tree[it]; self.print_ast_id(ast_id.erase()); w!(self, "extern {{"); @@ -192,13 +193,13 @@ impl Printer<'_> { }); wln!(self, "}}"); } - ModItem::Function(it) => { + ModItemId::Function(it) => { let Function { name, visibility, ast_id } = &self.tree[it]; self.print_ast_id(ast_id.erase()); self.print_visibility(*visibility); wln!(self, "fn {};", name.display(self.db, self.edition)); } - ModItem::Struct(it) => { + ModItemId::Struct(it) => { let Struct { visibility, name, shape: kind, ast_id } = &self.tree[it]; self.print_ast_id(ast_id.erase()); self.print_visibility(*visibility); @@ -210,7 +211,7 @@ impl Printer<'_> { wln!(self, ";"); } } - ModItem::Union(it) => { + ModItemId::Union(it) => { let Union { name, visibility, ast_id } = &self.tree[it]; self.print_ast_id(ast_id.erase()); self.print_visibility(*visibility); @@ -218,13 +219,13 @@ impl Printer<'_> { self.print_fields(FieldsShape::Record); wln!(self); } - ModItem::Enum(it) => { + ModItemId::Enum(it) => { let Enum { name, visibility, ast_id } = &self.tree[it]; self.print_ast_id(ast_id.erase()); self.print_visibility(*visibility); w!(self, "enum {} {{ ... }}", name.display(self.db, self.edition)); } - ModItem::Const(it) => { + ModItemId::Const(it) => { let Const { name, visibility, ast_id } = &self.tree[it]; self.print_ast_id(ast_id.erase()); self.print_visibility(*visibility); @@ -235,7 +236,7 @@ impl Printer<'_> { } wln!(self, " = _;"); } - ModItem::Static(it) => { + ModItemId::Static(it) => { let Static { name, visibility, ast_id } = &self.tree[it]; self.print_ast_id(ast_id.erase()); self.print_visibility(*visibility); @@ -244,24 +245,24 @@ impl Printer<'_> { w!(self, " = _;"); wln!(self); } - ModItem::Trait(it) => { + ModItemId::Trait(it) => { let Trait { name, visibility, ast_id } = &self.tree[it]; self.print_ast_id(ast_id.erase()); self.print_visibility(*visibility); w!(self, "trait {} {{ ... }}", name.display(self.db, self.edition)); } - ModItem::TraitAlias(it) => { + ModItemId::TraitAlias(it) => { let TraitAlias { name, visibility, ast_id } = &self.tree[it]; self.print_ast_id(ast_id.erase()); self.print_visibility(*visibility); wln!(self, "trait {} = ..;", name.display(self.db, self.edition)); } - ModItem::Impl(it) => { + ModItemId::Impl(it) => { let Impl { ast_id } = &self.tree[it]; self.print_ast_id(ast_id.erase()); w!(self, "impl {{ ... }}"); } - ModItem::TypeAlias(it) => { + ModItemId::TypeAlias(it) => { let TypeAlias { name, visibility, ast_id } = &self.tree[it]; self.print_ast_id(ast_id.erase()); self.print_visibility(*visibility); @@ -269,7 +270,7 @@ impl Printer<'_> { w!(self, ";"); wln!(self); } - ModItem::Mod(it) => { + ModItemId::Mod(it) => { let Mod { name, visibility, kind, ast_id } = &self.tree[it]; self.print_ast_id(ast_id.erase()); self.print_visibility(*visibility); @@ -289,7 +290,7 @@ impl Printer<'_> { } } } - ModItem::MacroCall(it) => { + ModItemId::MacroCall(it) => { let MacroCall { path, ast_id, expand_to, ctxt } = &self.tree[it]; let _ = writeln!( self, @@ -300,12 +301,12 @@ impl Printer<'_> { ); wln!(self, "{}!(...);", path.display(self.db, self.edition)); } - ModItem::MacroRules(it) => { + ModItemId::MacroRules(it) => { let MacroRules { name, ast_id } = &self.tree[it]; self.print_ast_id(ast_id.erase()); wln!(self, "macro_rules! {} {{ ... }}", name.display(self.db, self.edition)); } - ModItem::Macro2(it) => { + ModItemId::Macro2(it) => { let Macro2 { name, visibility, ast_id } = &self.tree[it]; self.print_ast_id(ast_id.erase()); self.print_visibility(*visibility); diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs index 703cb79b55ef7..3dc76dcb8fb01 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs @@ -36,7 +36,7 @@ use crate::{ item_scope::{GlobId, ImportId, ImportOrExternCrate, PerNsGlobImports}, item_tree::{ self, AttrOwner, FieldsShape, ImportAlias, ImportKind, ItemTree, ItemTreeAstId, - ItemTreeNode, Macro2, MacroCall, MacroRules, Mod, ModItem, ModKind, TreeId, UseTreeKind, + ItemTreeNode, Macro2, MacroCall, MacroRules, Mod, ModItemId, ModKind, TreeId, UseTreeKind, }, macro_call_as_call_id, nameres::{ @@ -208,7 +208,7 @@ enum MacroDirectiveKind { Attr { ast_id: AstIdWithPath, attr: Attr, - mod_item: ModItem, + mod_item: ModItemId, /* is this needed? */ tree: TreeId, }, } @@ -1436,9 +1436,9 @@ impl DefCollector<'_> { let item_tree = tree.item_tree(self.db); let ast_adt_id: FileAstId = match *mod_item { - ModItem::Struct(strukt) => item_tree[strukt].ast_id().upcast(), - ModItem::Union(union) => item_tree[union].ast_id().upcast(), - ModItem::Enum(enum_) => item_tree[enum_].ast_id().upcast(), + ModItemId::Struct(strukt) => item_tree[strukt].ast_id().upcast(), + ModItemId::Union(union) => item_tree[union].ast_id().upcast(), + ModItemId::Enum(enum_) => item_tree[enum_].ast_id().upcast(), _ => { let diag = DefDiagnostic::invalid_derive_target( directive.module_id, @@ -1682,12 +1682,12 @@ struct ModCollector<'a, 'b> { } impl ModCollector<'_, '_> { - fn collect_in_top_module(&mut self, items: &[ModItem]) { + fn collect_in_top_module(&mut self, items: &[ModItemId]) { let module = self.def_collector.def_map.module_id(self.module_id); self.collect(items, module.into()) } - fn collect(&mut self, items: &[ModItem], container: ItemContainerId) { + fn collect(&mut self, items: &[ModItemId], container: ItemContainerId) { let krate = self.def_collector.def_map.krate; let is_crate_root = self.module_id == DefMap::ROOT && self.def_collector.def_map.block.is_none(); @@ -1726,7 +1726,7 @@ impl ModCollector<'_, '_> { .unwrap_or(Visibility::Public) }; - let mut process_mod_item = |item: ModItem| { + let mut process_mod_item = |item: ModItemId| { let attrs = self.item_tree.attrs(db, krate, item.into()); if let Some(cfg) = attrs.cfg() { if !self.is_cfg_enabled(&cfg) { @@ -1748,8 +1748,8 @@ impl ModCollector<'_, '_> { self.def_collector.crate_local_def_map.unwrap_or(&self.def_collector.local_def_map); match item { - ModItem::Mod(m) => self.collect_module(m, &attrs), - ModItem::Use(item_tree_id) => { + ModItemId::Mod(m) => self.collect_module(m, &attrs), + ModItemId::Use(item_tree_id) => { let id = UseLoc { container: module, id: InFile::new(self.file_id(), self.item_tree[item_tree_id].ast_id), @@ -1771,7 +1771,7 @@ impl ModCollector<'_, '_> { }, ) } - ModItem::ExternCrate(item_tree_id) => { + ModItemId::ExternCrate(item_tree_id) => { let item_tree::ExternCrate { name, visibility, alias, ast_id } = &self.item_tree[item_tree_id]; @@ -1845,7 +1845,7 @@ impl ModCollector<'_, '_> { ); } } - ModItem::ExternBlock(block) => { + ModItemId::ExternBlock(block) => { let extern_block_id = ExternBlockLoc { container: module, id: InFile::new(self.file_id(), self.item_tree[block].ast_id), @@ -1859,10 +1859,12 @@ impl ModCollector<'_, '_> { ItemContainerId::ExternBlockId(extern_block_id), ) } - ModItem::MacroCall(mac) => self.collect_macro_call(&self.item_tree[mac], container), - ModItem::MacroRules(id) => self.collect_macro_rules(id, module), - ModItem::Macro2(id) => self.collect_macro_def(id, module), - ModItem::Impl(imp) => { + ModItemId::MacroCall(mac) => { + self.collect_macro_call(&self.item_tree[mac], container) + } + ModItemId::MacroRules(id) => self.collect_macro_rules(id, module), + ModItemId::Macro2(id) => self.collect_macro_def(id, module), + ModItemId::Impl(imp) => { let impl_id = ImplLoc { container: module, id: InFile::new(self.file_id(), self.item_tree[imp].ast_id), @@ -1870,7 +1872,7 @@ impl ModCollector<'_, '_> { .intern(db); self.def_collector.def_map.modules[self.module_id].scope.define_impl(impl_id) } - ModItem::Function(id) => { + ModItemId::Function(id) => { let it = &self.item_tree[id]; let fn_id = FunctionLoc { container, @@ -1895,7 +1897,7 @@ impl ModCollector<'_, '_> { update_def(self.def_collector, fn_id.into(), &it.name, vis, false); } - ModItem::Struct(id) => { + ModItemId::Struct(id) => { let it = &self.item_tree[id]; let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]); @@ -1909,7 +1911,7 @@ impl ModCollector<'_, '_> { !matches!(it.shape, FieldsShape::Record), ); } - ModItem::Union(id) => { + ModItemId::Union(id) => { let it = &self.item_tree[id]; let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]); @@ -1923,7 +1925,7 @@ impl ModCollector<'_, '_> { false, ); } - ModItem::Enum(id) => { + ModItemId::Enum(id) => { let it = &self.item_tree[id]; let enum_ = EnumLoc { container: module, @@ -1934,7 +1936,7 @@ impl ModCollector<'_, '_> { let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]); update_def(self.def_collector, enum_.into(), &it.name, vis, false); } - ModItem::Const(id) => { + ModItemId::Const(id) => { let it = &self.item_tree[id]; let const_id = ConstLoc { container, id: InFile::new(self.tree_id.file_id(), it.ast_id) } @@ -1954,7 +1956,7 @@ impl ModCollector<'_, '_> { } } } - ModItem::Static(id) => { + ModItemId::Static(id) => { let it = &self.item_tree[id]; let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]); @@ -1968,7 +1970,7 @@ impl ModCollector<'_, '_> { false, ); } - ModItem::Trait(id) => { + ModItemId::Trait(id) => { let it = &self.item_tree[id]; let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]); @@ -1982,7 +1984,7 @@ impl ModCollector<'_, '_> { false, ); } - ModItem::TraitAlias(id) => { + ModItemId::TraitAlias(id) => { let it = &self.item_tree[id]; let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]); @@ -1999,7 +2001,7 @@ impl ModCollector<'_, '_> { false, ); } - ModItem::TypeAlias(id) => { + ModItemId::TypeAlias(id) => { let it = &self.item_tree[id]; let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]); @@ -2022,12 +2024,12 @@ impl ModCollector<'_, '_> { if is_crate_root { items .iter() - .filter(|it| matches!(it, ModItem::ExternCrate(..))) + .filter(|it| matches!(it, ModItemId::ExternCrate(..))) .copied() .for_each(&mut process_mod_item); items .iter() - .filter(|it| !matches!(it, ModItem::ExternCrate(..))) + .filter(|it| !matches!(it, ModItemId::ExternCrate(..))) .copied() .for_each(process_mod_item); } else { @@ -2237,7 +2239,7 @@ impl ModCollector<'_, '_> { fn resolve_attributes( &mut self, attrs: &Attrs, - mod_item: ModItem, + mod_item: ModItemId, container: ItemContainerId, ) -> Result<(), ()> { let mut ignore_up_to = self From 762efdfce85ebe2e675d3bbf191ff01d967e0032 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 12 Jun 2025 11:25:20 +0200 Subject: [PATCH 21/56] Ditch the unnecessary smallvec --- .../crates/hir-def/src/item_tree.rs | 11 +++++------ .../crates/hir-def/src/item_tree/lower.rs | 16 ++++++++++------ 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs index b295767399a1b..9f8d7b9e31225 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs @@ -53,7 +53,6 @@ use hir_expand::{ use intern::Interned; use la_arena::Idx; use rustc_hash::FxHashMap; -use smallvec::SmallVec; use span::{AstIdNode, Edition, ErasedFileAstId, FileAstId, SyntaxContext}; use stdx::never; use syntax::{SyntaxKind, ast, match_ast}; @@ -89,11 +88,12 @@ impl fmt::Debug for RawVisibilityId { /// The item tree of a source file. #[derive(Debug, Default, Eq, PartialEq)] pub struct ItemTree { - top_level: SmallVec<[ModItemId; 1]>, + top_level: Box<[ModItemId]>, // Consider splitting this into top level RawAttrs and the map? attrs: FxHashMap, vis: ItemVisibilities, + // FIXME: They values store the key, turn this into a FxHashSet instead? data: FxHashMap, ModItem>, } @@ -136,7 +136,7 @@ impl ItemTree { EMPTY .get_or_init(|| { Arc::new(ItemTree { - top_level: SmallVec::new_const(), + top_level: Box::new([]), attrs: FxHashMap::default(), data: FxHashMap::default(), vis: ItemVisibilities { arena: Box::new([]) }, @@ -163,7 +163,7 @@ impl ItemTree { EMPTY .get_or_init(|| { Arc::new(ItemTree { - top_level: SmallVec::new_const(), + top_level: Box::new([]), attrs: FxHashMap::default(), data: FxHashMap::default(), vis: ItemVisibilities { arena: Box::new([]) }, @@ -226,8 +226,7 @@ impl ItemTree { } fn shrink_to_fit(&mut self) { - let ItemTree { top_level, attrs, data, vis: _ } = self; - top_level.shrink_to_fit(); + let ItemTree { top_level: _, attrs, data, vis: _ } = self; attrs.shrink_to_fit(); data.shrink_to_fit(); } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs index f3e71effe4b78..a7038356b3ba2 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs @@ -33,6 +33,7 @@ pub(super) struct Ctx<'a> { source_ast_id_map: Arc, span_map: OnceCell, file: HirFileId, + top_level: Vec, visibilities: FxIndexSet, } @@ -45,6 +46,7 @@ impl<'a> Ctx<'a> { file, span_map: OnceCell::new(), visibilities: FxIndexSet::default(), + top_level: Vec::new(), } } @@ -53,14 +55,14 @@ impl<'a> Ctx<'a> { } pub(super) fn lower_module_items(mut self, item_owner: &dyn HasModuleItem) -> ItemTree { - self.tree.top_level = - item_owner.items().flat_map(|item| self.lower_mod_item(&item)).collect(); + self.top_level = item_owner.items().flat_map(|item| self.lower_mod_item(&item)).collect(); self.tree.vis.arena = self.visibilities.into_iter().collect(); + self.tree.top_level = self.top_level.into_boxed_slice(); self.tree } pub(super) fn lower_macro_stmts(mut self, stmts: ast::MacroStmts) -> ItemTree { - self.tree.top_level = stmts + self.top_level = stmts .statements() .filter_map(|stmt| { match stmt { @@ -84,18 +86,19 @@ impl<'a> Ctx<'a> { if let Some(call) = tail_macro.macro_call() { cov_mark::hit!(macro_stmt_with_trailing_macro_expr); if let Some(mod_item) = self.lower_mod_item(&call.into()) { - self.tree.top_level.push(mod_item); + self.top_level.push(mod_item); } } } self.tree.vis.arena = self.visibilities.into_iter().collect(); + self.tree.top_level = self.top_level.into_boxed_slice(); self.tree } pub(super) fn lower_block(mut self, block: &ast::BlockExpr) -> ItemTree { self.tree.attrs.insert(AttrOwner::TopLevel, RawAttrs::new(self.db, block, self.span_map())); - self.tree.top_level = block + self.top_level = block .statements() .filter_map(|stmt| match stmt { ast::Stmt::Item(item) => self.lower_mod_item(&item), @@ -111,11 +114,12 @@ impl<'a> Ctx<'a> { if let Some(ast::Expr::MacroExpr(expr)) = block.tail_expr() { if let Some(call) = expr.macro_call() { if let Some(mod_item) = self.lower_mod_item(&call.into()) { - self.tree.top_level.push(mod_item); + self.top_level.push(mod_item); } } } self.tree.vis.arena = self.visibilities.into_iter().collect(); + self.tree.top_level = self.top_level.into_boxed_slice(); self.tree } From dfa9d68270a7456e93258eb4218b22831e916624 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 12 Jun 2025 11:41:46 +0200 Subject: [PATCH 22/56] Remove `AttrOwner` --- .../rust-analyzer/crates/hir-def/src/attr.rs | 16 ++--- .../rust-analyzer/crates/hir-def/src/db.rs | 2 +- .../crates/hir-def/src/item_tree.rs | 66 +++++++++---------- .../crates/hir-def/src/item_tree/lower.rs | 18 ++--- .../crates/hir-def/src/item_tree/pretty.rs | 15 ++--- .../crates/hir-def/src/nameres/collector.rs | 10 +-- 6 files changed, 59 insertions(+), 68 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/attr.rs b/src/tools/rust-analyzer/crates/hir-def/src/attr.rs index 08986d68e5f78..d63bd391fd596 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/attr.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/attr.rs @@ -26,7 +26,6 @@ use crate::{ AdtId, AstIdLoc, AttrDefId, GenericParamId, HasModule, LocalFieldId, Lookup, MacroId, VariantId, db::DefDatabase, - item_tree::AttrOwner, lang_item::LangItem, nameres::{ModuleOrigin, ModuleSource}, src::{HasChildSource, HasSource}, @@ -526,23 +525,22 @@ impl AttrsWithOwner { ModuleOrigin::File { definition, declaration_tree_id, declaration, .. } => { let decl_attrs = declaration_tree_id .item_tree(db) - .raw_attrs(AttrOwner::Item(declaration.erase())) + .raw_attrs(declaration.upcast()) .clone(); let tree = db.file_item_tree(definition.into()); - let def_attrs = tree.raw_attrs(AttrOwner::TopLevel).clone(); + let def_attrs = tree.top_level_raw_attrs().clone(); decl_attrs.merge(def_attrs) } ModuleOrigin::CrateRoot { definition } => { let tree = db.file_item_tree(definition.into()); - tree.raw_attrs(AttrOwner::TopLevel).clone() + tree.top_level_raw_attrs().clone() + } + ModuleOrigin::Inline { definition_tree_id, definition } => { + definition_tree_id.item_tree(db).raw_attrs(definition.upcast()).clone() } - ModuleOrigin::Inline { definition_tree_id, definition } => definition_tree_id - .item_tree(db) - .raw_attrs(AttrOwner::Item(definition.erase())) - .clone(), ModuleOrigin::BlockExpr { id, .. } => { let tree = db.block_item_tree(id); - tree.raw_attrs(AttrOwner::TopLevel).clone() + tree.top_level_raw_attrs().clone() } }; Attrs::expand_cfg_attr(db, module.krate, raw_attrs) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/db.rs b/src/tools/rust-analyzer/crates/hir-def/src/db.rs index 95e33dde58f08..5f996931396b1 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/db.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/db.rs @@ -376,7 +376,7 @@ fn include_macro_invoc( fn crate_supports_no_std(db: &dyn DefDatabase, crate_id: Crate) -> bool { let file = crate_id.data(db).root_file_id(db); let item_tree = db.file_item_tree(file.into()); - let attrs = item_tree.raw_attrs(crate::item_tree::AttrOwner::TopLevel); + let attrs = item_tree.top_level_raw_attrs(); for attr in &**attrs { match attr.path().as_ident() { Some(ident) if *ident == sym::no_std => return true, diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs index 9f8d7b9e31225..79f4b174e1974 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs @@ -53,7 +53,7 @@ use hir_expand::{ use intern::Interned; use la_arena::Idx; use rustc_hash::FxHashMap; -use span::{AstIdNode, Edition, ErasedFileAstId, FileAstId, SyntaxContext}; +use span::{AstIdNode, Edition, FileAstId, SyntaxContext}; use stdx::never; use syntax::{SyntaxKind, ast, match_ast}; use triomphe::Arc; @@ -89,9 +89,8 @@ impl fmt::Debug for RawVisibilityId { #[derive(Debug, Default, Eq, PartialEq)] pub struct ItemTree { top_level: Box<[ModItemId]>, - // Consider splitting this into top level RawAttrs and the map? - attrs: FxHashMap, - + top_attrs: RawAttrs, + attrs: FxHashMap, RawAttrs>, vis: ItemVisibilities, // FIXME: They values store the key, turn this into a FxHashSet instead? data: FxHashMap, ModItem>, @@ -104,12 +103,13 @@ impl ItemTree { let ctx = lower::Ctx::new(db, file_id); let syntax = db.parse_or_expand(file_id); - let mut top_attrs = None; let mut item_tree = match_ast! { match syntax { ast::SourceFile(file) => { - top_attrs = Some(RawAttrs::new(db, &file, ctx.span_map())); - ctx.lower_module_items(&file) + let top_attrs = RawAttrs::new(db, &file, ctx.span_map()); + let mut item_tree = ctx.lower_module_items(&file); + item_tree.top_attrs = top_attrs; + item_tree }, ast::MacroItems(items) => { ctx.lower_module_items(&items) @@ -128,10 +128,10 @@ impl ItemTree { } }; - if let Some(attrs) = top_attrs { - item_tree.attrs.insert(AttrOwner::TopLevel, attrs); - } - if item_tree.data.is_empty() && item_tree.top_level.is_empty() && item_tree.attrs.is_empty() + if item_tree.data.is_empty() + && item_tree.top_level.is_empty() + && item_tree.attrs.is_empty() + && item_tree.top_attrs.is_empty() { EMPTY .get_or_init(|| { @@ -139,6 +139,7 @@ impl ItemTree { top_level: Box::new([]), attrs: FxHashMap::default(), data: FxHashMap::default(), + top_attrs: RawAttrs::EMPTY, vis: ItemVisibilities { arena: Box::new([]) }, }) }) @@ -158,7 +159,10 @@ impl ItemTree { let ctx = lower::Ctx::new(db, loc.ast_id.file_id); let mut item_tree = ctx.lower_block(&block); - if item_tree.data.is_empty() && item_tree.top_level.is_empty() && item_tree.attrs.is_empty() + if item_tree.data.is_empty() + && item_tree.top_level.is_empty() + && item_tree.attrs.is_empty() + && item_tree.top_attrs.is_empty() { EMPTY .get_or_init(|| { @@ -166,6 +170,7 @@ impl ItemTree { top_level: Box::new([]), attrs: FxHashMap::default(), data: FxHashMap::default(), + top_attrs: RawAttrs::EMPTY, vis: ItemVisibilities { arena: Box::new([]) }, }) }) @@ -182,20 +187,26 @@ impl ItemTree { &self.top_level } + /// Returns the inner attributes of the source file. + pub fn top_level_raw_attrs(&self) -> &RawAttrs { + &self.top_attrs + } + /// Returns the inner attributes of the source file. pub fn top_level_attrs(&self, db: &dyn DefDatabase, krate: Crate) -> Attrs { - Attrs::expand_cfg_attr( - db, - krate, - self.attrs.get(&AttrOwner::TopLevel).unwrap_or(&RawAttrs::EMPTY).clone(), - ) + Attrs::expand_cfg_attr(db, krate, self.top_attrs.clone()) } - pub(crate) fn raw_attrs(&self, of: AttrOwner) -> &RawAttrs { + pub(crate) fn raw_attrs(&self, of: FileAstId) -> &RawAttrs { self.attrs.get(&of).unwrap_or(&RawAttrs::EMPTY) } - pub(crate) fn attrs(&self, db: &dyn DefDatabase, krate: Crate, of: AttrOwner) -> Attrs { + pub(crate) fn attrs( + &self, + db: &dyn DefDatabase, + krate: Crate, + of: FileAstId, + ) -> Attrs { Attrs::expand_cfg_attr(db, krate, self.raw_attrs(of).clone()) } @@ -226,7 +237,7 @@ impl ItemTree { } fn shrink_to_fit(&mut self) { - let ItemTree { top_level: _, attrs, data, vis: _ } = self; + let ItemTree { top_level: _, attrs, data, vis: _, top_attrs: _ } = self; attrs.shrink_to_fit(); data.shrink_to_fit(); } @@ -266,21 +277,6 @@ pub struct ItemTreeDataStats { pub macro_rules: usize, } -#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] -pub enum AttrOwner { - /// Attributes on an item. - Item(ErasedFileAstId), - /// Inner attributes of the source file. - TopLevel, -} - -impl From for AttrOwner { - #[inline] - fn from(value: ModItemId) -> Self { - AttrOwner::Item(value.ast_id().erase()) - } -} - /// Trait implemented by all nodes in the item tree. pub trait ItemTreeNode: Clone { type Source: AstIdNode; diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs index a7038356b3ba2..c3089eef90990 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs @@ -10,7 +10,7 @@ use hir_expand::{ span_map::{SpanMap, SpanMapRef}, }; use la_arena::Arena; -use span::{AstIdMap, SyntaxContext}; +use span::{AstIdMap, FileAstId, SyntaxContext}; use syntax::{ AstNode, ast::{self, HasModuleItem, HasName}, @@ -20,10 +20,10 @@ use triomphe::Arc; use crate::{ db::DefDatabase, item_tree::{ - AttrOwner, Const, Enum, ExternBlock, ExternCrate, FieldsShape, Function, Impl, ImportAlias, - Interned, ItemTree, ItemTreeAstId, Macro2, MacroCall, MacroRules, Mod, ModItem, ModItemId, - ModKind, ModPath, RawAttrs, RawVisibility, RawVisibilityId, Static, Struct, StructKind, - Trait, TraitAlias, TypeAlias, Union, Use, UseTree, UseTreeKind, VisibilityExplicitness, + Const, Enum, ExternBlock, ExternCrate, FieldsShape, Function, Impl, ImportAlias, Interned, + ItemTree, ItemTreeAstId, Macro2, MacroCall, MacroRules, Mod, ModItem, ModItemId, ModKind, + ModPath, RawAttrs, RawVisibility, RawVisibilityId, Static, Struct, StructKind, Trait, + TraitAlias, TypeAlias, Union, Use, UseTree, UseTreeKind, VisibilityExplicitness, }, }; @@ -97,7 +97,7 @@ impl<'a> Ctx<'a> { } pub(super) fn lower_block(mut self, block: &ast::BlockExpr) -> ItemTree { - self.tree.attrs.insert(AttrOwner::TopLevel, RawAttrs::new(self.db, block, self.span_map())); + self.tree.top_attrs = RawAttrs::new(self.db, block, self.span_map()); self.top_level = block .statements() .filter_map(|stmt| match stmt { @@ -144,12 +144,12 @@ impl<'a> Ctx<'a> { ast::Item::ExternBlock(ast) => self.lower_extern_block(ast).into(), }; let attrs = RawAttrs::new(self.db, item, self.span_map()); - self.add_attrs(mod_item.into(), attrs); + self.add_attrs(mod_item.ast_id(), attrs); Some(mod_item) } - fn add_attrs(&mut self, item: AttrOwner, attrs: RawAttrs) { + fn add_attrs(&mut self, item: FileAstId, attrs: RawAttrs) { if !attrs.is_empty() { match self.tree.attrs.entry(item) { Entry::Occupied(mut entry) => { @@ -365,7 +365,7 @@ impl<'a> Ctx<'a> { ast::ExternItem::MacroCall(call) => self.lower_macro_call(call)?.into(), }; let attrs = RawAttrs::new(self.db, &item, self.span_map()); - self.add_attrs(mod_item.into(), attrs); + self.add_attrs(mod_item.ast_id(), attrs); Some(mod_item) }) .collect() diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs index 9a5ca738362b3..11b91568987fd 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs @@ -6,10 +6,9 @@ use span::{Edition, ErasedFileAstId}; use crate::{ item_tree::{ - AttrOwner, Const, DefDatabase, Enum, ExternBlock, ExternCrate, FieldsShape, Function, Impl, - ItemTree, Macro2, MacroCall, MacroRules, Mod, ModItemId, ModKind, RawAttrs, - RawVisibilityId, Static, Struct, Trait, TraitAlias, TypeAlias, Union, Use, UseTree, - UseTreeKind, + Const, DefDatabase, Enum, ExternBlock, ExternCrate, FieldsShape, Function, Impl, ItemTree, + Macro2, MacroCall, MacroRules, Mod, ModItemId, ModKind, RawAttrs, RawVisibilityId, Static, + Struct, Trait, TraitAlias, TypeAlias, Union, Use, UseTree, UseTreeKind, }, visibility::RawVisibility, }; @@ -18,9 +17,7 @@ pub(super) fn print_item_tree(db: &dyn DefDatabase, tree: &ItemTree, edition: Ed let mut p = Printer { db, tree, buf: String::new(), indent_level: 0, needs_indent: true, edition }; - if let Some(attrs) = tree.attrs.get(&AttrOwner::TopLevel) { - p.print_attrs(attrs, true, "\n"); - } + p.print_attrs(&tree.top_attrs, true, "\n"); p.blank(); for item in tree.top_level_items() { @@ -102,8 +99,8 @@ impl Printer<'_> { } } - fn print_attrs_of(&mut self, of: impl Into, separated_by: &str) { - if let Some(attrs) = self.tree.attrs.get(&of.into()) { + fn print_attrs_of(&mut self, of: ModItemId, separated_by: &str) { + if let Some(attrs) = self.tree.attrs.get(&of.ast_id()) { self.print_attrs(attrs, false, separated_by); } } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs index 3dc76dcb8fb01..a6be3f1fbf6eb 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs @@ -35,8 +35,8 @@ use crate::{ db::DefDatabase, item_scope::{GlobId, ImportId, ImportOrExternCrate, PerNsGlobImports}, item_tree::{ - self, AttrOwner, FieldsShape, ImportAlias, ImportKind, ItemTree, ItemTreeAstId, - ItemTreeNode, Macro2, MacroCall, MacroRules, Mod, ModItemId, ModKind, TreeId, UseTreeKind, + self, FieldsShape, ImportAlias, ImportKind, ItemTree, ItemTreeAstId, ItemTreeNode, Macro2, + MacroCall, MacroRules, Mod, ModItemId, ModKind, TreeId, UseTreeKind, }, macro_call_as_call_id, nameres::{ @@ -1727,7 +1727,7 @@ impl ModCollector<'_, '_> { }; let mut process_mod_item = |item: ModItemId| { - let attrs = self.item_tree.attrs(db, krate, item.into()); + let attrs = self.item_tree.attrs(db, krate, item.ast_id()); if let Some(cfg) = attrs.cfg() { if !self.is_cfg_enabled(&cfg) { let ast_id = item.ast_id().erase(); @@ -2298,7 +2298,7 @@ impl ModCollector<'_, '_> { fn collect_macro_rules(&mut self, id: ItemTreeAstId, module: ModuleId) { let krate = self.def_collector.def_map.krate; let mac = &self.item_tree[id]; - let attrs = self.item_tree.attrs(self.def_collector.db, krate, AttrOwner::Item(id.erase())); + let attrs = self.item_tree.attrs(self.def_collector.db, krate, id.upcast()); let ast_id = InFile::new(self.file_id(), mac.ast_id.upcast()); let export_attr = || attrs.by_key(sym::macro_export); @@ -2387,7 +2387,7 @@ impl ModCollector<'_, '_> { // Case 1: builtin macros let mut helpers_opt = None; - let attrs = self.item_tree.attrs(self.def_collector.db, krate, AttrOwner::Item(id.erase())); + let attrs = self.item_tree.attrs(self.def_collector.db, krate, id.upcast()); let expander = if attrs.by_key(sym::rustc_builtin_macro).exists() { if let Some(expander) = find_builtin_macro(&mac.name) { match expander { From 6a0f4e59a898f07045e4b05d3ed66f3179100971 Mon Sep 17 00:00:00 2001 From: Chayim Refael Friedman Date: Thu, 12 Jun 2025 13:22:44 +0300 Subject: [PATCH 23/56] Fix comparison of proc macros Comparing the TypeId is not enough, they also contain data. --- .../hir-def/src/macro_expansion_tests/mod.rs | 6 ++- .../crates/hir-expand/src/proc_macro.rs | 4 +- .../crates/load-cargo/src/lib.rs | 6 ++- .../crates/test-fixture/src/lib.rs | 42 ++++++++++++++++++- 4 files changed, 52 insertions(+), 6 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mod.rs b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mod.rs index dc4334ee0816c..b5321560918e0 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mod.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mod.rs @@ -14,7 +14,7 @@ mod builtin_fn_macro; mod mbe; mod proc_macros; -use std::{iter, ops::Range, sync}; +use std::{any::TypeId, iter, ops::Range, sync}; use base_db::RootQueryDb; use expect_test::Expect; @@ -380,4 +380,8 @@ impl ProcMacroExpander for IdentityWhenValidProcMacroExpander { panic!("got invalid macro input: {:?}", parse.errors()); } } + + fn eq_dyn(&self, other: &dyn ProcMacroExpander) -> bool { + other.type_id() == TypeId::of::() + } } diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/proc_macro.rs b/src/tools/rust-analyzer/crates/hir-expand/src/proc_macro.rs index 1cd975b980df7..1c8ebb6f5355f 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/proc_macro.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/proc_macro.rs @@ -34,9 +34,7 @@ pub trait ProcMacroExpander: fmt::Debug + Send + Sync + RefUnwindSafe + Any { current_dir: String, ) -> Result; - fn eq_dyn(&self, other: &dyn ProcMacroExpander) -> bool { - other.type_id() == self.type_id() - } + fn eq_dyn(&self, other: &dyn ProcMacroExpander) -> bool; } impl PartialEq for dyn ProcMacroExpander { diff --git a/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs b/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs index 30e2d5416cf69..89b8631cd25fb 100644 --- a/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs +++ b/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs @@ -2,7 +2,7 @@ //! for incorporating changes. // Note, don't remove any public api from this. This API is consumed by external tools // to run rust-analyzer as a library. -use std::{collections::hash_map::Entry, mem, path::Path, sync}; +use std::{any::Any, collections::hash_map::Entry, mem, path::Path, sync}; use crossbeam_channel::{Receiver, unbounded}; use hir_expand::proc_macro::{ @@ -512,6 +512,10 @@ impl ProcMacroExpander for Expander { Err(err) => Err(ProcMacroExpansionError::System(err.to_string())), } } + + fn eq_dyn(&self, other: &dyn ProcMacroExpander) -> bool { + (other as &dyn Any).downcast_ref::() == Some(self) + } } #[cfg(test)] diff --git a/src/tools/rust-analyzer/crates/test-fixture/src/lib.rs b/src/tools/rust-analyzer/crates/test-fixture/src/lib.rs index 8eb48f8d93e7c..8937e53175abd 100644 --- a/src/tools/rust-analyzer/crates/test-fixture/src/lib.rs +++ b/src/tools/rust-analyzer/crates/test-fixture/src/lib.rs @@ -1,5 +1,5 @@ //! A set of high-level utility fixture methods to use in tests. -use std::{mem, str::FromStr, sync}; +use std::{any::TypeId, mem, str::FromStr, sync}; use base_db::{ Crate, CrateDisplayName, CrateGraphBuilder, CrateName, CrateOrigin, CrateWorkspaceData, @@ -677,6 +677,10 @@ impl ProcMacroExpander for IdentityProcMacroExpander { ) -> Result { Ok(subtree.clone()) } + + fn eq_dyn(&self, other: &dyn ProcMacroExpander) -> bool { + other.type_id() == TypeId::of::() + } } // Expands to a macro_rules! macro, for issue #18089. @@ -708,6 +712,10 @@ impl ProcMacroExpander for Issue18089ProcMacroExpander { #subtree }) } + + fn eq_dyn(&self, other: &dyn ProcMacroExpander) -> bool { + other.type_id() == TypeId::of::() + } } // Pastes the attribute input as its output @@ -728,6 +736,10 @@ impl ProcMacroExpander for AttributeInputReplaceProcMacroExpander { .cloned() .ok_or_else(|| ProcMacroExpansionError::Panic("Expected attribute input".into())) } + + fn eq_dyn(&self, other: &dyn ProcMacroExpander) -> bool { + other.type_id() == TypeId::of::() + } } #[derive(Debug)] @@ -759,6 +771,10 @@ impl ProcMacroExpander for Issue18840ProcMacroExpander { top_subtree_delimiter_mut.close = def_site; Ok(result) } + + fn eq_dyn(&self, other: &dyn ProcMacroExpander) -> bool { + other.type_id() == TypeId::of::() + } } #[derive(Debug)] @@ -790,6 +806,10 @@ impl ProcMacroExpander for MirrorProcMacroExpander { traverse(&mut builder, input.iter()); Ok(builder.build()) } + + fn eq_dyn(&self, other: &dyn ProcMacroExpander) -> bool { + other.type_id() == TypeId::of::() + } } // Replaces every literal with an empty string literal and every identifier with its first letter, @@ -830,6 +850,10 @@ impl ProcMacroExpander for ShortenProcMacroExpander { } } } + + fn eq_dyn(&self, other: &dyn ProcMacroExpander) -> bool { + other.type_id() == TypeId::of::() + } } // Reads ident type within string quotes, for issue #17479. @@ -855,6 +879,10 @@ impl ProcMacroExpander for Issue17479ProcMacroExpander { #symbol() }) } + + fn eq_dyn(&self, other: &dyn ProcMacroExpander) -> bool { + other.type_id() == TypeId::of::() + } } // Reads ident type within string quotes, for issue #17479. @@ -906,6 +934,10 @@ impl ProcMacroExpander for Issue18898ProcMacroExpander { } }) } + + fn eq_dyn(&self, other: &dyn ProcMacroExpander) -> bool { + other.type_id() == TypeId::of::() + } } // Reads ident type within string quotes, for issue #17479. @@ -933,6 +965,10 @@ impl ProcMacroExpander for DisallowCfgProcMacroExpander { } Ok(subtree.clone()) } + + fn eq_dyn(&self, other: &dyn ProcMacroExpander) -> bool { + other.type_id() == TypeId::of::() + } } // Generates a new type by adding a suffix to the original name @@ -987,4 +1023,8 @@ impl ProcMacroExpander for GenerateSuffixedTypeProcMacroExpander { Ok(ret) } + + fn eq_dyn(&self, other: &dyn ProcMacroExpander) -> bool { + other.type_id() == TypeId::of::() + } } From 724537f31fe69f73678d139135c77f73193da120 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 12 Jun 2025 11:51:33 +0200 Subject: [PATCH 24/56] Shrink `ModItem` by usize --- .../crates/hir-def/src/item_tree.rs | 30 ++++++++++++++----- .../crates/hir-def/src/item_tree/lower.rs | 25 +++++++--------- .../crates/hir-def/src/nameres/collector.rs | 2 +- .../rust-analyzer/crates/intern/src/symbol.rs | 1 + 4 files changed, 34 insertions(+), 24 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs index 79f4b174e1974..2a277e4c5476e 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs @@ -51,7 +51,7 @@ use hir_expand::{ name::Name, }; use intern::Interned; -use la_arena::Idx; +use la_arena::{Idx, RawIdx}; use rustc_hash::FxHashMap; use span::{AstIdNode, Edition, FileAstId, SyntaxContext}; use stdx::never; @@ -437,10 +437,10 @@ pub struct Use { #[derive(Debug, Clone, Eq, PartialEq)] pub struct UseTree { - pub index: Idx, kind: UseTreeKind, } +// FIXME: Would be nice to encode `None` into this #[derive(Debug, Clone, PartialEq, Eq)] pub enum ImportAlias { /// Unnamed alias, as in `use Foo as _;` @@ -655,15 +655,17 @@ pub enum ImportKind { TypeOnly, } -impl UseTree { +impl Use { /// Expands the `UseTree` into individually imported `ModPath`s. pub fn expand( &self, mut cb: impl FnMut(Idx, ModPath, ImportKind, Option), ) { - self.expand_impl(None, &mut cb) + self.use_tree.expand_impl(None, &mut 0, &mut cb) } +} +impl UseTree { /// The [`UseTreeKind`] of this `UseTree`. pub fn kind(&self) -> &UseTreeKind { &self.kind @@ -672,6 +674,7 @@ impl UseTree { fn expand_impl( &self, prefix: Option, + counting_index: &mut u32, cb: &mut impl FnMut(Idx, ModPath, ImportKind, Option), ) { fn concat_mod_paths( @@ -707,17 +710,27 @@ impl UseTree { match &self.kind { UseTreeKind::Single { path, alias } => { if let Some((path, kind)) = concat_mod_paths(prefix, path) { - cb(self.index, path, kind, alias.clone()); + cb(Idx::from_raw(RawIdx::from_u32(*counting_index)), path, kind, alias.clone()); } } UseTreeKind::Glob { path: Some(path) } => { if let Some((path, _)) = concat_mod_paths(prefix, path) { - cb(self.index, path, ImportKind::Glob, None); + cb( + Idx::from_raw(RawIdx::from_u32(*counting_index)), + path, + ImportKind::Glob, + None, + ); } } UseTreeKind::Glob { path: None } => { if let Some(prefix) = prefix { - cb(self.index, prefix, ImportKind::Glob, None); + cb( + Idx::from_raw(RawIdx::from_u32(*counting_index)), + prefix, + ImportKind::Glob, + None, + ); } } UseTreeKind::Prefixed { prefix: additional_prefix, list } => { @@ -729,7 +742,8 @@ impl UseTree { None => prefix, }; for tree in &**list { - tree.expand_impl(prefix.clone(), cb); + *counting_index += 1; + tree.expand_impl(prefix.clone(), counting_index, cb); } } } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs index c3089eef90990..ab60b7ad70362 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs @@ -424,17 +424,15 @@ impl UseTreeLowering<'_> { } }; + self.mapping.alloc(tree.clone()); let list = use_tree_list .use_trees() .filter_map(|tree| self.lower_use_tree(tree, span_for_range)) .collect(); - Some( - self.use_tree( - UseTreeKind::Prefixed { prefix: prefix.map(Interned::new), list }, - tree, - ), - ) + Some(UseTree { + kind: UseTreeKind::Prefixed { prefix: prefix.map(Interned::new), list }, + }) } else { let is_glob = tree.star_token().is_some(); let path = match tree.path() { @@ -453,23 +451,20 @@ impl UseTreeLowering<'_> { if path.is_none() { cov_mark::hit!(glob_enum_group); } - Some(self.use_tree(UseTreeKind::Glob { path: path.map(Interned::new) }, tree)) + self.mapping.alloc(tree.clone()); + Some(UseTree { kind: UseTreeKind::Glob { path: path.map(Interned::new) } }) } // Globs can't be renamed (_, Some(_), true) | (None, None, false) => None, // `bla::{ as Name}` is invalid (None, Some(_), false) => None, - (Some(path), alias, false) => Some( - self.use_tree(UseTreeKind::Single { path: Interned::new(path), alias }, tree), - ), + (Some(path), alias, false) => { + self.mapping.alloc(tree.clone()); + Some(UseTree { kind: UseTreeKind::Single { path: Interned::new(path), alias } }) + } } } } - - fn use_tree(&mut self, kind: UseTreeKind, ast: ast::UseTree) -> UseTree { - let index = self.mapping.alloc(ast); - UseTree { index, kind } - } } pub(crate) fn lower_use_tree( diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs index a6be3f1fbf6eb..9801875ee4ae7 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs @@ -163,7 +163,7 @@ impl Import { ) { let it = &tree[item]; let visibility = &tree[it.visibility]; - it.use_tree.expand(|idx, path, kind, alias| { + it.expand(|idx, path, kind, alias| { cb(Self { path, alias, diff --git a/src/tools/rust-analyzer/crates/intern/src/symbol.rs b/src/tools/rust-analyzer/crates/intern/src/symbol.rs index 8b2d6e8717d23..3b962a86f1769 100644 --- a/src/tools/rust-analyzer/crates/intern/src/symbol.rs +++ b/src/tools/rust-analyzer/crates/intern/src/symbol.rs @@ -112,6 +112,7 @@ impl TaggedArcPtr { } } +// FIXME: This should have more than one niche #[derive(PartialEq, Eq, Hash)] pub struct Symbol { repr: TaggedArcPtr, From b1c86333b7e7acdde8b6e677c2d23a4de7df5cea Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 12 Jun 2025 12:02:53 +0200 Subject: [PATCH 25/56] Remove dead code --- .../crates/hir-def/src/item_tree.rs | 70 +++++++------------ .../crates/hir-def/src/nameres/collector.rs | 16 ++--- 2 files changed, 35 insertions(+), 51 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs index 2a277e4c5476e..0836d5758becd 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs @@ -63,13 +63,13 @@ use crate::{BlockId, Lookup, attr::Attrs, db::DefDatabase}; pub(crate) use crate::item_tree::lower::{lower_use_tree, visibility_from_ast}; #[derive(Copy, Clone, Eq, PartialEq)] -pub struct RawVisibilityId(u32); +pub(crate) struct RawVisibilityId(u32); impl RawVisibilityId { - pub const PUB: Self = RawVisibilityId(u32::MAX); - pub const PRIV_IMPLICIT: Self = RawVisibilityId(u32::MAX - 1); - pub const PRIV_EXPLICIT: Self = RawVisibilityId(u32::MAX - 2); - pub const PUB_CRATE: Self = RawVisibilityId(u32::MAX - 3); + const PUB: Self = RawVisibilityId(u32::MAX); + const PRIV_IMPLICIT: Self = RawVisibilityId(u32::MAX - 1); + const PRIV_EXPLICIT: Self = RawVisibilityId(u32::MAX - 2); + const PUB_CRATE: Self = RawVisibilityId(u32::MAX - 3); } impl fmt::Debug for RawVisibilityId { @@ -188,12 +188,12 @@ impl ItemTree { } /// Returns the inner attributes of the source file. - pub fn top_level_raw_attrs(&self) -> &RawAttrs { + pub(crate) fn top_level_raw_attrs(&self) -> &RawAttrs { &self.top_attrs } /// Returns the inner attributes of the source file. - pub fn top_level_attrs(&self, db: &dyn DefDatabase, krate: Crate) -> Attrs { + pub(crate) fn top_level_attrs(&self, db: &dyn DefDatabase, krate: Crate) -> Attrs { Attrs::expand_cfg_attr(db, krate, self.top_attrs.clone()) } @@ -278,17 +278,12 @@ pub struct ItemTreeDataStats { } /// Trait implemented by all nodes in the item tree. -pub trait ItemTreeNode: Clone { +pub(crate) trait ItemTreeNode: Clone { type Source: AstIdNode; - - fn ast_id(&self) -> FileAstId; - - /// Looks up an instance of `Self` in an item tree. - fn lookup(tree: &ItemTree, index: FileAstId) -> &Self; } #[allow(type_alias_bounds)] -pub type ItemTreeAstId = FileAstId; +pub(crate) type ItemTreeAstId = FileAstId; /// Identifies a particular [`ItemTree`]. #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] @@ -298,11 +293,11 @@ pub struct TreeId { } impl TreeId { - pub fn new(file: HirFileId, block: Option) -> Self { + pub(crate) fn new(file: HirFileId, block: Option) -> Self { Self { file, block } } - pub fn item_tree(&self, db: &dyn DefDatabase) -> Arc { + pub(crate) fn item_tree(&self, db: &dyn DefDatabase) -> Arc { match self.block { Some(block) => db.block_item_tree(block), None => db.file_item_tree(self.file), @@ -314,7 +309,7 @@ impl TreeId { self.file } - pub fn is_block(self) -> bool { + pub(crate) fn is_block(self) -> bool { self.block.is_some() } } @@ -347,17 +342,6 @@ macro_rules! mod_items { $( impl ItemTreeNode for $typ { type Source = $ast; - - fn ast_id(&self) -> FileAstId<$ast> { - self.ast_id - } - - fn lookup(tree: &ItemTree, index: FileAstId<$ast>) -> &Self { - match &tree.data[&index.upcast()] { - ModItem::$typ(item) => item, - _ => panic!("expected item of type `{}` at index `{:?}`", stringify!($typ), index), - } - } } impl Index> for ItemTree { @@ -430,9 +414,9 @@ impl Index for ItemTree { #[derive(Debug, Clone, Eq, PartialEq)] pub struct Use { - pub visibility: RawVisibilityId, - pub ast_id: FileAstId, - pub use_tree: UseTree, + pub(crate) visibility: RawVisibilityId, + pub(crate) ast_id: FileAstId, + pub(crate) use_tree: UseTree, } #[derive(Debug, Clone, Eq, PartialEq)] @@ -494,7 +478,7 @@ pub enum UseTreeKind { pub struct ExternCrate { pub name: Name, pub alias: Option, - pub visibility: RawVisibilityId, + pub(crate) visibility: RawVisibilityId, pub ast_id: FileAstId, } @@ -507,14 +491,14 @@ pub struct ExternBlock { #[derive(Debug, Clone, Eq, PartialEq)] pub struct Function { pub name: Name, - pub visibility: RawVisibilityId, + pub(crate) visibility: RawVisibilityId, pub ast_id: FileAstId, } #[derive(Debug, Clone, Eq, PartialEq)] pub struct Struct { pub name: Name, - pub visibility: RawVisibilityId, + pub(crate) visibility: RawVisibilityId, pub shape: FieldsShape, pub ast_id: FileAstId, } @@ -522,14 +506,14 @@ pub struct Struct { #[derive(Debug, Clone, Eq, PartialEq)] pub struct Union { pub name: Name, - pub visibility: RawVisibilityId, + pub(crate) visibility: RawVisibilityId, pub ast_id: FileAstId, } #[derive(Debug, Clone, Eq, PartialEq)] pub struct Enum { pub name: Name, - pub visibility: RawVisibilityId, + pub(crate) visibility: RawVisibilityId, pub ast_id: FileAstId, } @@ -568,28 +552,28 @@ impl VisibilityExplicitness { pub struct Const { /// `None` for `const _: () = ();` pub name: Option, - pub visibility: RawVisibilityId, + pub(crate) visibility: RawVisibilityId, pub ast_id: FileAstId, } #[derive(Debug, Clone, Eq, PartialEq)] pub struct Static { pub name: Name, - pub visibility: RawVisibilityId, + pub(crate) visibility: RawVisibilityId, pub ast_id: FileAstId, } #[derive(Debug, Clone, Eq, PartialEq)] pub struct Trait { pub name: Name, - pub visibility: RawVisibilityId, + pub(crate) visibility: RawVisibilityId, pub ast_id: FileAstId, } #[derive(Debug, Clone, Eq, PartialEq)] pub struct TraitAlias { pub name: Name, - pub visibility: RawVisibilityId, + pub(crate) visibility: RawVisibilityId, pub ast_id: FileAstId, } @@ -601,14 +585,14 @@ pub struct Impl { #[derive(Debug, Clone, PartialEq, Eq)] pub struct TypeAlias { pub name: Name, - pub visibility: RawVisibilityId, + pub(crate) visibility: RawVisibilityId, pub ast_id: FileAstId, } #[derive(Debug, Clone, Eq, PartialEq)] pub struct Mod { pub name: Name, - pub visibility: RawVisibilityId, + pub(crate) visibility: RawVisibilityId, pub(crate) kind: ModKind, pub ast_id: FileAstId, } @@ -641,7 +625,7 @@ pub struct MacroRules { #[derive(Debug, Clone, Eq, PartialEq)] pub struct Macro2 { pub name: Name, - pub visibility: RawVisibilityId, + pub(crate) visibility: RawVisibilityId, pub ast_id: FileAstId, } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs index 9801875ee4ae7..4d19df019523b 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs @@ -35,8 +35,8 @@ use crate::{ db::DefDatabase, item_scope::{GlobId, ImportId, ImportOrExternCrate, PerNsGlobImports}, item_tree::{ - self, FieldsShape, ImportAlias, ImportKind, ItemTree, ItemTreeAstId, ItemTreeNode, Macro2, - MacroCall, MacroRules, Mod, ModItemId, ModKind, TreeId, UseTreeKind, + self, FieldsShape, ImportAlias, ImportKind, ItemTree, ItemTreeAstId, Macro2, MacroCall, + MacroRules, Mod, ModItemId, ModKind, TreeId, UseTreeKind, }, macro_call_as_call_id, nameres::{ @@ -1436,9 +1436,9 @@ impl DefCollector<'_> { let item_tree = tree.item_tree(self.db); let ast_adt_id: FileAstId = match *mod_item { - ModItemId::Struct(strukt) => item_tree[strukt].ast_id().upcast(), - ModItemId::Union(union) => item_tree[union].ast_id().upcast(), - ModItemId::Enum(enum_) => item_tree[enum_].ast_id().upcast(), + ModItemId::Struct(strukt) => item_tree[strukt].ast_id.upcast(), + ModItemId::Union(union) => item_tree[union].ast_id.upcast(), + ModItemId::Enum(enum_) => item_tree[enum_].ast_id.upcast(), _ => { let diag = DefDiagnostic::invalid_derive_target( directive.module_id, @@ -1889,7 +1889,7 @@ impl ModCollector<'_, '_> { if let Some(proc_macro) = attrs.parse_proc_macro_decl(&it.name) { self.def_collector.export_proc_macro( proc_macro, - InFile::new(self.file_id(), self.item_tree[id].ast_id()), + InFile::new(self.file_id(), self.item_tree[id].ast_id), fn_id, ); } @@ -2369,7 +2369,7 @@ impl ModCollector<'_, '_> { } .intern(self.def_collector.db); self.def_collector.def_map.macro_def_to_macro_id.insert( - InFile::new(self.file_id(), self.item_tree[id].ast_id()).erase(), + InFile::new(self.file_id(), self.item_tree[id].ast_id).erase(), macro_id.into(), ); self.def_collector.define_macro_rules( @@ -2437,7 +2437,7 @@ impl ModCollector<'_, '_> { } .intern(self.def_collector.db); self.def_collector.def_map.macro_def_to_macro_id.insert( - InFile::new(self.file_id(), self.item_tree[id].ast_id()).erase(), + InFile::new(self.file_id(), self.item_tree[id].ast_id).erase(), macro_id.into(), ); self.def_collector.define_macro_def( From 4d811e34cc111b8145b9206467f99a8dfa3b4fe2 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 12 Jun 2025 12:50:04 +0200 Subject: [PATCH 26/56] Return item tree query results by ref --- .../rust-analyzer/crates/hir-def/src/attr.rs | 3 +- .../rust-analyzer/crates/hir-def/src/db.rs | 10 +- .../crates/hir-def/src/item_tree.rs | 158 ++++++++---------- .../crates/hir-def/src/nameres/collector.rs | 10 +- 4 files changed, 82 insertions(+), 99 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/attr.rs b/src/tools/rust-analyzer/crates/hir-def/src/attr.rs index d63bd391fd596..b509e69b0d37b 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/attr.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/attr.rs @@ -26,6 +26,7 @@ use crate::{ AdtId, AstIdLoc, AttrDefId, GenericParamId, HasModule, LocalFieldId, Lookup, MacroId, VariantId, db::DefDatabase, + item_tree::block_item_tree_query, lang_item::LangItem, nameres::{ModuleOrigin, ModuleSource}, src::{HasChildSource, HasSource}, @@ -539,7 +540,7 @@ impl AttrsWithOwner { definition_tree_id.item_tree(db).raw_attrs(definition.upcast()).clone() } ModuleOrigin::BlockExpr { id, .. } => { - let tree = db.block_item_tree(id); + let tree = block_item_tree_query(db, id); tree.top_level_raw_attrs().clone() } }; diff --git a/src/tools/rust-analyzer/crates/hir-def/src/db.rs b/src/tools/rust-analyzer/crates/hir-def/src/db.rs index 5f996931396b1..27fe62c4f0d9d 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/db.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/db.rs @@ -24,7 +24,7 @@ use crate::{ }, hir::generics::GenericParams, import_map::ImportMap, - item_tree::ItemTree, + item_tree::{ItemTree, file_item_tree_query}, lang_item::{self, LangItem}, nameres::{ assoc::{ImplItems, TraitItems}, @@ -108,11 +108,9 @@ pub trait DefDatabase: InternDatabase + ExpandDatabase + SourceDatabase { fn expand_proc_attr_macros(&self) -> bool; /// Computes an [`ItemTree`] for the given file or macro expansion. - #[salsa::invoke(ItemTree::file_item_tree_query)] - fn file_item_tree(&self, file_id: HirFileId) -> Arc; - - #[salsa::invoke(ItemTree::block_item_tree_query)] - fn block_item_tree(&self, block_id: BlockId) -> Arc; + #[salsa::invoke(file_item_tree_query)] + #[salsa::transparent] + fn file_item_tree(&self, file_id: HirFileId) -> &ItemTree; /// Turns a MacroId into a MacroDefId, describing the macro's definition post name resolution. #[salsa::invoke(macro_def)] diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs index 0836d5758becd..90a5dd2dc7d1b 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs @@ -85,6 +85,74 @@ impl fmt::Debug for RawVisibilityId { } } +#[salsa_macros::tracked(returns(ref))] +pub(crate) fn file_item_tree_query(db: &dyn DefDatabase, file_id: HirFileId) -> ItemTree { + let _p = tracing::info_span!("file_item_tree_query", ?file_id).entered(); + + let ctx = lower::Ctx::new(db, file_id); + let syntax = db.parse_or_expand(file_id); + let mut item_tree = match_ast! { + match syntax { + ast::SourceFile(file) => { + let top_attrs = RawAttrs::new(db, &file, ctx.span_map()); + let mut item_tree = ctx.lower_module_items(&file); + item_tree.top_attrs = top_attrs; + item_tree + }, + ast::MacroItems(items) => { + ctx.lower_module_items(&items) + }, + ast::MacroStmts(stmts) => { + // The produced statements can include items, which should be added as top-level + // items. + ctx.lower_macro_stmts(stmts) + }, + _ => { + if never!(syntax.kind() == SyntaxKind::ERROR, "{:?} from {:?} {}", file_id, syntax, syntax) { + return Default::default(); + } + panic!("cannot create item tree for file {file_id:?} from {syntax:?} {syntax}"); + }, + } + }; + + item_tree.shrink_to_fit(); + item_tree +} + +#[salsa_macros::tracked(returns(ref))] +pub(crate) fn block_item_tree_query(db: &dyn DefDatabase, block: BlockId) -> Arc { + let _p = tracing::info_span!("block_item_tree_query", ?block).entered(); + // Blocks have a tendency to be empty due to macro calls that do not expand to items, + // so deduplicate this case via `Arc` to reduce the size of the query storage here. + static EMPTY: OnceLock> = 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); + let mut item_tree = ctx.lower_block(&block); + if item_tree.data.is_empty() + && item_tree.top_level.is_empty() + && item_tree.attrs.is_empty() + && item_tree.top_attrs.is_empty() + { + EMPTY + .get_or_init(|| { + Arc::new(ItemTree { + top_level: Box::new([]), + attrs: FxHashMap::default(), + data: FxHashMap::default(), + top_attrs: RawAttrs::EMPTY, + vis: ItemVisibilities { arena: Box::new([]) }, + }) + }) + .clone() + } else { + item_tree.shrink_to_fit(); + Arc::new(item_tree) + } +} /// The item tree of a source file. #[derive(Debug, Default, Eq, PartialEq)] pub struct ItemTree { @@ -97,90 +165,6 @@ pub struct ItemTree { } impl ItemTree { - pub(crate) fn file_item_tree_query(db: &dyn DefDatabase, file_id: HirFileId) -> Arc { - let _p = tracing::info_span!("file_item_tree_query", ?file_id).entered(); - static EMPTY: OnceLock> = OnceLock::new(); - - let ctx = lower::Ctx::new(db, file_id); - let syntax = db.parse_or_expand(file_id); - let mut item_tree = match_ast! { - match syntax { - ast::SourceFile(file) => { - let top_attrs = RawAttrs::new(db, &file, ctx.span_map()); - let mut item_tree = ctx.lower_module_items(&file); - item_tree.top_attrs = top_attrs; - item_tree - }, - ast::MacroItems(items) => { - ctx.lower_module_items(&items) - }, - ast::MacroStmts(stmts) => { - // The produced statements can include items, which should be added as top-level - // items. - ctx.lower_macro_stmts(stmts) - }, - _ => { - if never!(syntax.kind() == SyntaxKind::ERROR, "{:?} from {:?} {}", file_id, syntax, syntax) { - return Default::default(); - } - panic!("cannot create item tree for file {file_id:?} from {syntax:?} {syntax}"); - }, - } - }; - - if item_tree.data.is_empty() - && item_tree.top_level.is_empty() - && item_tree.attrs.is_empty() - && item_tree.top_attrs.is_empty() - { - EMPTY - .get_or_init(|| { - Arc::new(ItemTree { - top_level: Box::new([]), - attrs: FxHashMap::default(), - data: FxHashMap::default(), - top_attrs: RawAttrs::EMPTY, - vis: ItemVisibilities { arena: Box::new([]) }, - }) - }) - .clone() - } else { - item_tree.shrink_to_fit(); - Arc::new(item_tree) - } - } - - pub(crate) fn block_item_tree_query(db: &dyn DefDatabase, block: BlockId) -> Arc { - let _p = tracing::info_span!("block_item_tree_query", ?block).entered(); - static EMPTY: OnceLock> = 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); - let mut item_tree = ctx.lower_block(&block); - if item_tree.data.is_empty() - && item_tree.top_level.is_empty() - && item_tree.attrs.is_empty() - && item_tree.top_attrs.is_empty() - { - EMPTY - .get_or_init(|| { - Arc::new(ItemTree { - top_level: Box::new([]), - attrs: FxHashMap::default(), - data: FxHashMap::default(), - top_attrs: RawAttrs::EMPTY, - vis: ItemVisibilities { arena: Box::new([]) }, - }) - }) - .clone() - } else { - item_tree.shrink_to_fit(); - Arc::new(item_tree) - } - } - /// Returns an iterator over all items located at the top level of the `HirFileId` this /// `ItemTree` was created from. pub(crate) fn top_level_items(&self) -> &[ModItemId] { @@ -297,10 +281,10 @@ impl TreeId { Self { file, block } } - pub(crate) fn item_tree(&self, db: &dyn DefDatabase) -> Arc { + pub(crate) fn item_tree<'db>(&self, db: &'db dyn DefDatabase) -> &'db ItemTree { match self.block { - Some(block) => db.block_item_tree(block), - None => db.file_item_tree(self.file), + Some(block) => block_item_tree_query(db, block), + None => file_item_tree_query(db, self.file), } } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs index 4d19df019523b..3b2488c8ea6df 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs @@ -357,7 +357,7 @@ impl DefCollector<'_> { macro_depth: 0, module_id: DefMap::ROOT, tree_id: TreeId::new(file_id.into(), None), - item_tree: &item_tree, + item_tree, mod_dir: ModDir::root(), } .collect_in_top_module(item_tree.top_level_items()); @@ -378,7 +378,7 @@ impl DefCollector<'_> { macro_depth: 0, module_id: DefMap::ROOT, tree_id, - item_tree: &item_tree, + item_tree, mod_dir: ModDir::root(), } .collect_in_top_module(item_tree.top_level_items()); @@ -1381,7 +1381,7 @@ impl DefCollector<'_> { macro_depth: directive.depth, module_id: directive.module_id, tree_id: *tree, - item_tree: &item_tree, + item_tree, mod_dir, } .collect(&[*mod_item], directive.container); @@ -1570,7 +1570,7 @@ impl DefCollector<'_> { macro_depth: depth, tree_id: TreeId::new(file_id, None), module_id, - item_tree: &item_tree, + item_tree, mod_dir, } .collect(item_tree.top_level_items(), container); @@ -2142,7 +2142,7 @@ impl ModCollector<'_, '_> { macro_depth: self.macro_depth, module_id, tree_id: TreeId::new(file_id.into(), None), - item_tree: &item_tree, + item_tree, mod_dir, } .collect_in_top_module(item_tree.top_level_items()); From 4b3ad4bd10df55d8beb4cb0c77a303ee3255b020 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 12 Jun 2025 14:01:46 +0200 Subject: [PATCH 27/56] Fix tests --- .../crates/hir-def/src/nameres/tests/incremental.rs | 12 ++++++------ .../crates/hir-ty/src/tests/incremental.rs | 8 ++++---- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/incremental.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/incremental.rs index 948e8bed66dea..7a4ea62f12ac1 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/incremental.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/incremental.rs @@ -348,7 +348,7 @@ m!(Z); assert_eq!(module_data.scope.resolutions().count(), 4); }); let n_recalculated_item_trees = - events.iter().filter(|it| it.contains("file_item_tree_shim")).count(); + events.iter().filter(|it| it.contains("file_item_tree_query")).count(); assert_eq!(n_recalculated_item_trees, 6); let n_reparsed_macros = events.iter().filter(|it| it.contains("parse_macro_expansion_shim")).count(); @@ -370,7 +370,7 @@ m!(Z); assert_eq!(module_data.scope.resolutions().count(), 4); }); let n_recalculated_item_trees = - events.iter().filter(|it| it.contains("file_item_tree_shim")).count(); + events.iter().filter(|it| it.contains("file_item_tree_query")).count(); assert_eq!(n_recalculated_item_trees, 1, "{events:#?}"); let n_reparsed_macros = events.iter().filter(|it| it.contains("parse_macro_expansion_shim")).count(); @@ -405,10 +405,10 @@ pub type Ty = (); db.file_item_tree(pos.file_id.into()); }); let n_calculated_item_trees = - events.iter().filter(|it| it.contains("file_item_tree_shim")).count(); - assert_eq!(n_calculated_item_trees, 1); + events.iter().filter(|it| it.contains("file_item_tree_query")).count(); + assert_eq!(n_calculated_item_trees, 1, "{events:#?}"); let n_parsed_files = events.iter().filter(|it| it.contains("parse")).count(); - assert_eq!(n_parsed_files, 1); + assert_eq!(n_parsed_files, 1, "{events:#?}"); } // FIXME(salsa-transition): bring this back @@ -446,6 +446,6 @@ pub type Ty = (); } }); let n_reparsed_files = events.iter().filter(|it| it.contains("parse(")).count(); - assert_eq!(n_reparsed_files, 0); + assert_eq!(n_reparsed_files, 0, "{events:?}"); } } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/incremental.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/incremental.rs index a055ef879d6a5..74f6bbb03089f 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/incremental.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/incremental.rs @@ -156,7 +156,7 @@ pub struct NewStruct { let expected = vec![ "parse_shim".to_owned(), "ast_id_map_shim".to_owned(), - "file_item_tree_shim".to_owned(), + "file_item_tree_query".to_owned(), "real_span_map_shim".to_owned(), "crate_local_def_map".to_owned(), "trait_impls_in_crate_shim".to_owned(), @@ -216,7 +216,7 @@ pub enum SomeEnum { let expected = vec![ "parse_shim".to_owned(), "ast_id_map_shim".to_owned(), - "file_item_tree_shim".to_owned(), + "file_item_tree_query".to_owned(), "real_span_map_shim".to_owned(), "crate_local_def_map".to_owned(), "trait_impls_in_crate_shim".to_owned(), @@ -273,7 +273,7 @@ fn bar() -> f32 { let expected = vec![ "parse_shim".to_owned(), "ast_id_map_shim".to_owned(), - "file_item_tree_shim".to_owned(), + "file_item_tree_query".to_owned(), "real_span_map_shim".to_owned(), "crate_local_def_map".to_owned(), "trait_impls_in_crate_shim".to_owned(), @@ -342,7 +342,7 @@ impl SomeStruct { let expected = vec![ "parse_shim".to_owned(), "ast_id_map_shim".to_owned(), - "file_item_tree_shim".to_owned(), + "file_item_tree_query".to_owned(), "real_span_map_shim".to_owned(), "crate_local_def_map".to_owned(), "trait_impls_in_crate_shim".to_owned(), From af663097420196e1b0150e51be720b5c35ab5d88 Mon Sep 17 00:00:00 2001 From: Chayim Refael Friedman Date: Thu, 12 Jun 2025 15:32:08 +0300 Subject: [PATCH 28/56] Support spans with proc macro servers from before the ast id changes The only thing changed is the value of the fixup ast id, so we just swap it. --- .../proc-macro-api/src/legacy_protocol/msg.rs | 4 +- .../crates/proc-macro-api/src/lib.rs | 70 ++++++++++++++++--- .../crates/proc-macro-api/src/process.rs | 14 ++-- .../proc-macro-srv-cli/src/main_loop.rs | 7 +- .../crates/proc-macro-srv/src/dylib.rs | 15 ++-- .../crates/proc-macro-srv/src/lib.rs | 32 ++------- .../crates/proc-macro-srv/src/proc_macros.rs | 8 +-- .../src/server_impl/rust_analyzer_span.rs | 13 ++-- .../crates/proc-macro-srv/src/tests/utils.rs | 28 ++------ .../rust-analyzer/crates/span/src/ast_id.rs | 7 +- 10 files changed, 96 insertions(+), 102 deletions(-) diff --git a/src/tools/rust-analyzer/crates/proc-macro-api/src/legacy_protocol/msg.rs b/src/tools/rust-analyzer/crates/proc-macro-api/src/legacy_protocol/msg.rs index 4e1526fe48bde..165936269d35d 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-api/src/legacy_protocol/msg.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-api/src/legacy_protocol/msg.rs @@ -55,7 +55,7 @@ pub enum SpanMode { Id, /// Rust Analyzer-specific span handling mode. - RustAnalyzer { fixup_ast_id: u32 }, + RustAnalyzer, } /// Represents responses sent from the proc-macro-srv to the client. @@ -308,7 +308,7 @@ mod tests { #[test] fn test_proc_macro_rpc_works() { let tt = fixture_token_tree(); - for v in HASHED_AST_ID..=CURRENT_API_VERSION { + for v in RUST_ANALYZER_SPAN_SUPPORT..=CURRENT_API_VERSION { let mut span_data_table = Default::default(); let task = ExpandMacro { data: ExpandMacroData { diff --git a/src/tools/rust-analyzer/crates/proc-macro-api/src/lib.rs b/src/tools/rust-analyzer/crates/proc-macro-api/src/lib.rs index 25c30b6db4a4c..516c7418bde8f 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-api/src/lib.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-api/src/lib.rs @@ -12,13 +12,13 @@ pub mod legacy_protocol { mod process; use paths::{AbsPath, AbsPathBuf}; -use span::Span; +use span::{ErasedFileAstId, FIXUP_ERASED_FILE_AST_ID_MARKER, Span}; use std::{fmt, io, sync::Arc, time::SystemTime}; use crate::{ legacy_protocol::msg::{ - ExpandMacro, ExpandMacroData, ExpnGlobals, FlatTree, HAS_GLOBAL_SPANS, PanicMessage, - RUST_ANALYZER_SPAN_SUPPORT, Request, Response, SpanDataIndexMap, + ExpandMacro, ExpandMacroData, ExpnGlobals, FlatTree, HAS_GLOBAL_SPANS, HASHED_AST_ID, + PanicMessage, RUST_ANALYZER_SPAN_SUPPORT, Request, Response, SpanDataIndexMap, deserialize_span_data_index_map, flat::serialize_span_data_index_map, }, process::ProcMacroServerProcess, @@ -161,6 +161,38 @@ impl ProcMacro { self.kind } + fn needs_fixup_change(&self) -> bool { + let version = self.process.version(); + (RUST_ANALYZER_SPAN_SUPPORT..HASHED_AST_ID).contains(&version) + } + + /// On some server versions, the fixup ast id is different than ours. So change it to match. + fn change_fixup_to_match_old_server(&self, tt: &mut tt::TopSubtree) { + const OLD_FIXUP_AST_ID: ErasedFileAstId = ErasedFileAstId::from_raw(!0 - 1); + let change_ast_id = |ast_id: &mut ErasedFileAstId| { + if *ast_id == FIXUP_ERASED_FILE_AST_ID_MARKER { + *ast_id = OLD_FIXUP_AST_ID; + } else if *ast_id == OLD_FIXUP_AST_ID { + // Swap between them, that means no collision plus the change can be reversed by doing itself. + *ast_id = FIXUP_ERASED_FILE_AST_ID_MARKER; + } + }; + + for tt in &mut tt.0 { + match tt { + tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident { span, .. })) + | tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal { span, .. })) + | tt::TokenTree::Leaf(tt::Leaf::Punct(tt::Punct { span, .. })) => { + change_ast_id(&mut span.anchor.ast_id); + } + tt::TokenTree::Subtree(subtree) => { + change_ast_id(&mut subtree.delimiter.open.anchor.ast_id); + change_ast_id(&mut subtree.delimiter.close.anchor.ast_id); + } + } + } + } + /// Expands the procedural macro by sending an expansion request to the server. /// This includes span information and environmental context. pub fn expand( @@ -173,6 +205,20 @@ impl ProcMacro { mixed_site: Span, current_dir: String, ) -> Result, PanicMessage>, ServerError> { + let (mut subtree, mut attr) = (subtree, attr); + let (mut subtree_changed, mut attr_changed); + if self.needs_fixup_change() { + subtree_changed = tt::TopSubtree::from_subtree(subtree); + self.change_fixup_to_match_old_server(&mut subtree_changed); + subtree = subtree_changed.view(); + + if let Some(attr) = &mut attr { + attr_changed = tt::TopSubtree::from_subtree(*attr); + self.change_fixup_to_match_old_server(&mut attr_changed); + *attr = attr_changed.view(); + } + } + let version = self.process.version(); let mut span_data_table = SpanDataIndexMap::default(); @@ -205,15 +251,23 @@ impl ProcMacro { let response = self.process.send_task(Request::ExpandMacro(Box::new(task)))?; match response { - Response::ExpandMacro(it) => { - Ok(it.map(|tree| FlatTree::to_subtree_resolved(tree, version, &span_data_table))) - } + Response::ExpandMacro(it) => Ok(it.map(|tree| { + let mut expanded = FlatTree::to_subtree_resolved(tree, version, &span_data_table); + if self.needs_fixup_change() { + self.change_fixup_to_match_old_server(&mut expanded); + } + expanded + })), Response::ExpandMacroExtended(it) => Ok(it.map(|resp| { - FlatTree::to_subtree_resolved( + let mut expanded = FlatTree::to_subtree_resolved( resp.tree, version, &deserialize_span_data_index_map(&resp.span_data_table), - ) + ); + if self.needs_fixup_change() { + self.change_fixup_to_match_old_server(&mut expanded); + } + expanded })), _ => Err(ServerError { message: "unexpected response".to_owned(), io: None }), } diff --git a/src/tools/rust-analyzer/crates/proc-macro-api/src/process.rs b/src/tools/rust-analyzer/crates/proc-macro-api/src/process.rs index e3b0614546de5..fcea75ef672a1 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-api/src/process.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-api/src/process.rs @@ -8,7 +8,6 @@ use std::{ }; use paths::AbsPath; -use span::FIXUP_ERASED_FILE_AST_ID_MARKER; use stdx::JodChild; use crate::{ @@ -16,7 +15,8 @@ use crate::{ legacy_protocol::{ json::{read_json, write_json}, msg::{ - CURRENT_API_VERSION, HASHED_AST_ID, Message, Request, Response, ServerConfig, SpanMode, + CURRENT_API_VERSION, Message, RUST_ANALYZER_SPAN_SUPPORT, Request, Response, + ServerConfig, SpanMode, }, }, }; @@ -71,9 +71,7 @@ impl ProcMacroServerProcess { Ok(v) => { tracing::info!("Proc-macro server version: {v}"); srv.version = v; - if srv.version >= HASHED_AST_ID { - // We don't enable spans on versions prior to `HASHED_AST_ID`, because their ast id layout - // is different. + if srv.version >= RUST_ANALYZER_SPAN_SUPPORT { if let Ok(mode) = srv.enable_rust_analyzer_spans() { srv.mode = mode; } @@ -113,11 +111,7 @@ impl ProcMacroServerProcess { /// Enable support for rust-analyzer span mode if the server supports it. fn enable_rust_analyzer_spans(&self) -> Result { - let request = Request::SetConfig(ServerConfig { - span_mode: SpanMode::RustAnalyzer { - fixup_ast_id: FIXUP_ERASED_FILE_AST_ID_MARKER.into_raw(), - }, - }); + let request = Request::SetConfig(ServerConfig { span_mode: SpanMode::RustAnalyzer }); let response = self.send_task(request)?; match response { diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv-cli/src/main_loop.rs b/src/tools/rust-analyzer/crates/proc-macro-srv-cli/src/main_loop.rs index 25a49fbff9fd7..f54dff1f2d822 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv-cli/src/main_loop.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-srv-cli/src/main_loop.rs @@ -26,7 +26,7 @@ pub(crate) fn run() -> io::Result<()> { let write_response = |msg: msg::Response| msg.write(write_json, &mut io::stdout().lock()); let env = EnvSnapshot::default(); - let mut srv = proc_macro_srv::ProcMacroSrv::new(&env); + let srv = proc_macro_srv::ProcMacroSrv::new(&env); let mut span_mode = SpanMode::Id; @@ -78,7 +78,7 @@ pub(crate) fn run() -> io::Result<()> { }) .map_err(msg::PanicMessage) }), - SpanMode::RustAnalyzer { .. } => msg::Response::ExpandMacroExtended({ + SpanMode::RustAnalyzer => msg::Response::ExpandMacroExtended({ let mut span_data_table = deserialize_span_data_index_map(&span_data_table); let def_site = span_data_table[def_site]; @@ -122,9 +122,6 @@ pub(crate) fn run() -> io::Result<()> { msg::Request::ApiVersionCheck {} => msg::Response::ApiVersionCheck(CURRENT_API_VERSION), msg::Request::SetConfig(config) => { span_mode = config.span_mode; - if let SpanMode::RustAnalyzer { fixup_ast_id } = span_mode { - srv.set_fixup_ast_id(fixup_ast_id); - } msg::Response::SetConfig(config) } }; diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/dylib.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/dylib.rs index c64a9833e3ff0..c49159df9916d 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/dylib.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/dylib.rs @@ -3,7 +3,6 @@ mod version; use proc_macro::bridge; -use span::ErasedFileAstId; use std::{fmt, fs, io, time::SystemTime}; use libloading::Library; @@ -162,20 +161,14 @@ impl Expander { def_site: S, call_site: S, mixed_site: S, - fixup_ast_id: ErasedFileAstId, ) -> Result, String> where ::TokenStream: Default, { - let result = self.inner.proc_macros.expand( - macro_name, - macro_body, - attributes, - def_site, - call_site, - mixed_site, - fixup_ast_id, - ); + let result = self + .inner + .proc_macros + .expand(macro_name, macro_body, attributes, def_site, call_site, mixed_site); result.map_err(|e| e.into_string().unwrap_or_default()) } diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/lib.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/lib.rs index 22afa018de017..223c5a54b7034 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/lib.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/lib.rs @@ -41,7 +41,7 @@ use std::{ }; use paths::{Utf8Path, Utf8PathBuf}; -use span::{ErasedFileAstId, FIXUP_ERASED_FILE_AST_ID_MARKER, Span, TokenId}; +use span::{Span, TokenId}; use crate::server_impl::TokenStream; @@ -57,16 +57,11 @@ pub const RUSTC_VERSION_STRING: &str = env!("RUSTC_VERSION"); pub struct ProcMacroSrv<'env> { expanders: Mutex>>, env: &'env EnvSnapshot, - fixup_ast_id: ErasedFileAstId, } impl<'env> ProcMacroSrv<'env> { pub fn new(env: &'env EnvSnapshot) -> Self { - Self { expanders: Default::default(), env, fixup_ast_id: FIXUP_ERASED_FILE_AST_ID_MARKER } - } - - pub fn set_fixup_ast_id(&mut self, fixup_ast_id: u32) { - self.fixup_ast_id = ErasedFileAstId::from_raw(fixup_ast_id); + Self { expanders: Default::default(), env } } } @@ -106,7 +101,6 @@ impl ProcMacroSrv<'_> { def_site, call_site, mixed_site, - self.fixup_ast_id, ) .map(|tt| tt.0) }); @@ -162,41 +156,25 @@ impl ProcMacroSrv<'_> { pub trait ProcMacroSrvSpan: Copy + Send { type Server: proc_macro::bridge::server::Server>; - fn make_server( - call_site: Self, - def_site: Self, - mixed_site: Self, - fixup_ast_id: ErasedFileAstId, - ) -> Self::Server; + fn make_server(call_site: Self, def_site: Self, mixed_site: Self) -> Self::Server; } impl ProcMacroSrvSpan for TokenId { type Server = server_impl::token_id::TokenIdServer; - fn make_server( - call_site: Self, - def_site: Self, - mixed_site: Self, - _fixup_ast_id: ErasedFileAstId, - ) -> Self::Server { + fn make_server(call_site: Self, def_site: Self, mixed_site: Self) -> Self::Server { Self::Server { call_site, def_site, mixed_site } } } impl ProcMacroSrvSpan for Span { type Server = server_impl::rust_analyzer_span::RaSpanServer; - fn make_server( - call_site: Self, - def_site: Self, - mixed_site: Self, - fixup_ast_id: ErasedFileAstId, - ) -> Self::Server { + fn make_server(call_site: Self, def_site: Self, mixed_site: Self) -> Self::Server { Self::Server { call_site, def_site, mixed_site, tracked_env_vars: Default::default(), tracked_paths: Default::default(), - fixup_ast_id, } } } diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/proc_macros.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/proc_macros.rs index 3b9c45894c607..18532706c4aaa 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/proc_macros.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/proc_macros.rs @@ -1,7 +1,6 @@ //! Proc macro ABI use proc_macro::bridge; -use span::ErasedFileAstId; use crate::{ProcMacroKind, ProcMacroSrvSpan, server_impl::TopSubtree}; @@ -23,7 +22,6 @@ impl ProcMacros { def_site: S, call_site: S, mixed_site: S, - fixup_ast_id: ErasedFileAstId, ) -> Result, crate::PanicMessage> { let parsed_body = crate::server_impl::TokenStream::with_subtree(macro_body); @@ -39,7 +37,7 @@ impl ProcMacros { { let res = client.run( &bridge::server::SameThread, - S::make_server(call_site, def_site, mixed_site, fixup_ast_id), + S::make_server(call_site, def_site, mixed_site), parsed_body, cfg!(debug_assertions), ); @@ -50,7 +48,7 @@ impl ProcMacros { bridge::client::ProcMacro::Bang { name, client } if *name == macro_name => { let res = client.run( &bridge::server::SameThread, - S::make_server(call_site, def_site, mixed_site, fixup_ast_id), + S::make_server(call_site, def_site, mixed_site), parsed_body, cfg!(debug_assertions), ); @@ -61,7 +59,7 @@ impl ProcMacros { bridge::client::ProcMacro::Attr { name, client } if *name == macro_name => { let res = client.run( &bridge::server::SameThread, - S::make_server(call_site, def_site, mixed_site, fixup_ast_id), + S::make_server(call_site, def_site, mixed_site), parsed_attributes, parsed_body, cfg!(debug_assertions), diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs index b071ad80f5b6e..a1863efafbb76 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs @@ -11,7 +11,7 @@ use std::{ use intern::Symbol; use proc_macro::bridge::{self, server}; -use span::{ErasedFileAstId, Span}; +use span::{FIXUP_ERASED_FILE_AST_ID_MARKER, Span}; use tt::{TextRange, TextSize}; use crate::server_impl::{from_token_tree, literal_from_str, token_stream::TokenStreamBuilder}; @@ -28,7 +28,6 @@ pub struct RaSpanServer { pub call_site: Span, pub def_site: Span, pub mixed_site: Span, - pub fixup_ast_id: ErasedFileAstId, } impl server::Types for RaSpanServer { @@ -182,10 +181,10 @@ impl server::Span for RaSpanServer { fn join(&mut self, first: Self::Span, second: Self::Span) -> Option { // We can't modify the span range for fixup spans, those are meaningful to fixup, so just // prefer the non-fixup span. - if first.anchor.ast_id == self.fixup_ast_id { + if first.anchor.ast_id == FIXUP_ERASED_FILE_AST_ID_MARKER { return Some(second); } - if second.anchor.ast_id == self.fixup_ast_id { + if second.anchor.ast_id == FIXUP_ERASED_FILE_AST_ID_MARKER { return Some(first); } // FIXME: Once we can talk back to the client, implement a "long join" request for anchors @@ -214,7 +213,7 @@ impl server::Span for RaSpanServer { end: Bound, ) -> Option { // We can't modify the span range for fixup spans, those are meaningful to fixup. - if span.anchor.ast_id == self.fixup_ast_id { + if span.anchor.ast_id == FIXUP_ERASED_FILE_AST_ID_MARKER { return Some(span); } let length = span.range.len().into(); @@ -257,7 +256,7 @@ impl server::Span for RaSpanServer { fn end(&mut self, span: Self::Span) -> Self::Span { // We can't modify the span range for fixup spans, those are meaningful to fixup. - if span.anchor.ast_id == self.fixup_ast_id { + if span.anchor.ast_id == FIXUP_ERASED_FILE_AST_ID_MARKER { return span; } Span { range: TextRange::empty(span.range.end()), ..span } @@ -265,7 +264,7 @@ impl server::Span for RaSpanServer { fn start(&mut self, span: Self::Span) -> Self::Span { // We can't modify the span range for fixup spans, those are meaningful to fixup. - if span.anchor.ast_id == self.fixup_ast_id { + if span.anchor.ast_id == FIXUP_ERASED_FILE_AST_ID_MARKER { return span; } Span { range: TextRange::empty(span.range.start()), ..span } diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/utils.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/utils.rs index e0a69608decdd..10af5662b5c05 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/utils.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/utils.rs @@ -2,8 +2,7 @@ use expect_test::Expect; use span::{ - EditionedFileId, FIXUP_ERASED_FILE_AST_ID_MARKER, FileId, ROOT_ERASED_FILE_AST_ID, Span, - SpanAnchor, SyntaxContext, TokenId, + EditionedFileId, FileId, ROOT_ERASED_FILE_AST_ID, Span, SpanAnchor, SyntaxContext, TokenId, }; use tt::TextRange; @@ -68,17 +67,8 @@ fn assert_expand_impl( let input_ts_string = format!("{input_ts:?}"); let attr_ts_string = attr_ts.as_ref().map(|it| format!("{it:?}")); - let res = expander - .expand( - macro_name, - input_ts, - attr_ts, - def_site, - call_site, - mixed_site, - FIXUP_ERASED_FILE_AST_ID_MARKER, - ) - .unwrap(); + let res = + expander.expand(macro_name, input_ts, attr_ts, def_site, call_site, mixed_site).unwrap(); expect.assert_eq(&format!( "{input_ts_string}\n\n{}\n\n{res:?}", attr_ts_string.unwrap_or_default() @@ -110,17 +100,7 @@ fn assert_expand_impl( let fixture_string = format!("{fixture:?}"); let attr_string = attr.as_ref().map(|it| format!("{it:?}")); - let res = expander - .expand( - macro_name, - fixture, - attr, - def_site, - call_site, - mixed_site, - FIXUP_ERASED_FILE_AST_ID_MARKER, - ) - .unwrap(); + let res = expander.expand(macro_name, fixture, attr, def_site, call_site, mixed_site).unwrap(); expect_spanned .assert_eq(&format!("{fixture_string}\n\n{}\n\n{res:#?}", attr_string.unwrap_or_default())); } diff --git a/src/tools/rust-analyzer/crates/span/src/ast_id.rs b/src/tools/rust-analyzer/crates/span/src/ast_id.rs index 51a693ca011b5..8e9597119812a 100644 --- a/src/tools/rust-analyzer/crates/span/src/ast_id.rs +++ b/src/tools/rust-analyzer/crates/span/src/ast_id.rs @@ -108,7 +108,8 @@ impl fmt::Debug for ErasedFileAstId { #[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)] enum ErasedFileAstIdKind { - Root, + /// This needs to not change because it's depended upon by the proc macro server. + Fixup, // The following are associated with `ErasedHasNameFileAstId`. Enum, Struct, @@ -143,7 +144,7 @@ enum ErasedFileAstIdKind { /// Associated with [`BlockExprFileAstId`]. BlockExpr, /// Keep this last. - Fixup, + Root, } // First hash, then index, then kind. @@ -218,7 +219,7 @@ impl ErasedFileAstId { } #[inline] - pub fn from_raw(v: u32) -> Self { + pub const fn from_raw(v: u32) -> Self { Self(v) } } From f6b64d153332b2f3d5f8e1116405f4f1d9beea4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Fri, 13 Jun 2025 07:55:07 +0200 Subject: [PATCH 29/56] Fix link to good first issues --- src/tools/rust-analyzer/docs/book/src/contributing/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/rust-analyzer/docs/book/src/contributing/README.md b/src/tools/rust-analyzer/docs/book/src/contributing/README.md index 05286b5429244..5f4a74eba28aa 100644 --- a/src/tools/rust-analyzer/docs/book/src/contributing/README.md +++ b/src/tools/rust-analyzer/docs/book/src/contributing/README.md @@ -30,7 +30,7 @@ Discussion happens in this Zulip stream: # Issue Labels -* [good-first-issue](https://github.com/rust-lang/rust-analyzer/labels/good%20first%20issue) +* [good-first-issue](https://github.com/rust-lang/rust-analyzer/issues?q=is%3Aissue%20state%3Aopen%20label%3A%22good%20first%20issue%22) are good issues to get into the project. * [E-has-instructions](https://github.com/rust-lang/rust-analyzer/issues?q=is%3Aopen+is%3Aissue+label%3AE-has-instructions) issues have links to the code in question and tests. From d0524505269c3e020f48d03f42740faf0536fc9a Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Fri, 13 Jun 2025 08:09:44 +0200 Subject: [PATCH 30/56] Store item tree visibilities in a thin vec --- .../crates/hir-def/src/item_tree.rs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs index 90a5dd2dc7d1b..85a43de6ff728 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs @@ -56,6 +56,7 @@ use rustc_hash::FxHashMap; use span::{AstIdNode, Edition, FileAstId, SyntaxContext}; use stdx::never; use syntax::{SyntaxKind, ast, match_ast}; +use thin_vec::ThinVec; use triomphe::Arc; use crate::{BlockId, Lookup, attr::Attrs, db::DefDatabase}; @@ -144,7 +145,7 @@ pub(crate) fn block_item_tree_query(db: &dyn DefDatabase, block: BlockId) -> Arc attrs: FxHashMap::default(), data: FxHashMap::default(), top_attrs: RawAttrs::EMPTY, - vis: ItemVisibilities { arena: Box::new([]) }, + vis: ItemVisibilities { arena: ThinVec::new() }, }) }) .clone() @@ -229,29 +230,40 @@ impl ItemTree { #[derive(Default, Debug, Eq, PartialEq)] struct ItemVisibilities { - arena: Box<[RawVisibility]>, + arena: ThinVec, } #[derive(Debug, Clone, Eq, PartialEq)] enum ModItem { Const(Const), Enum(Enum), + // 32 ExternBlock(ExternBlock), + // 40 ExternCrate(ExternCrate), Function(Function), Impl(Impl), Macro2(Macro2), + // 32 MacroCall(MacroCall), MacroRules(MacroRules), + // 40 Mod(Mod), Static(Static), + // 32 Struct(Struct), Trait(Trait), TraitAlias(TraitAlias), TypeAlias(TypeAlias), Union(Union), + // 40 Use(Use), } + +// `ModItem` is stored a bunch in `ItemTree`'s so we pay the max for each item. It should stay as small as possible. +#[cfg(target_pointer_width = "64")] +const _: [(); std::mem::size_of::()] = [(); std::mem::size_of::<[usize; 5]>()]; + #[derive(Default, Debug, Eq, PartialEq)] pub struct ItemTreeDataStats { pub traits: usize, From e39c1e971b77b50800c5b1e6f2c099302d2172f7 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Fri, 13 Jun 2025 08:24:50 +0200 Subject: [PATCH 31/56] Split mod items into small and big variants --- .../crates/hir-def/src/item_tree.rs | 103 ++++++++++-------- .../crates/hir-def/src/item_tree/lower.rs | 43 ++++---- .../rust-analyzer/crates/intern/src/symbol.rs | 1 - 3 files changed, 81 insertions(+), 66 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs index 85a43de6ff728..5b9da1723114b 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs @@ -133,7 +133,8 @@ pub(crate) fn block_item_tree_query(db: &dyn DefDatabase, block: BlockId) -> Arc let ctx = lower::Ctx::new(db, loc.ast_id.file_id); let mut item_tree = ctx.lower_block(&block); - if item_tree.data.is_empty() + if item_tree.small_data.is_empty() + && item_tree.big_data.is_empty() && item_tree.top_level.is_empty() && item_tree.attrs.is_empty() && item_tree.top_attrs.is_empty() @@ -143,7 +144,8 @@ pub(crate) fn block_item_tree_query(db: &dyn DefDatabase, block: BlockId) -> Arc Arc::new(ItemTree { top_level: Box::new([]), attrs: FxHashMap::default(), - data: FxHashMap::default(), + small_data: FxHashMap::default(), + big_data: FxHashMap::default(), top_attrs: RawAttrs::EMPTY, vis: ItemVisibilities { arena: ThinVec::new() }, }) @@ -162,7 +164,8 @@ pub struct ItemTree { attrs: FxHashMap, RawAttrs>, vis: ItemVisibilities, // FIXME: They values store the key, turn this into a FxHashSet instead? - data: FxHashMap, ModItem>, + big_data: FxHashMap, BigModItem>, + small_data: FxHashMap, SmallModItem>, } impl ItemTree { @@ -204,13 +207,18 @@ impl ItemTree { let mut mods = 0; let mut macro_calls = 0; let mut macro_rules = 0; - for item in self.data.values() { + for item in self.small_data.values() { match item { - ModItem::Trait(_) => traits += 1, - ModItem::Impl(_) => impls += 1, - ModItem::Mod(_) => mods += 1, - ModItem::MacroCall(_) => macro_calls += 1, - ModItem::MacroRules(_) => macro_rules += 1, + SmallModItem::Trait(_) => traits += 1, + SmallModItem::Impl(_) => impls += 1, + SmallModItem::MacroRules(_) => macro_rules += 1, + _ => {} + } + } + for item in self.big_data.values() { + match item { + BigModItem::Mod(_) => mods += 1, + BigModItem::MacroCall(_) => macro_calls += 1, _ => {} } } @@ -222,9 +230,10 @@ impl ItemTree { } fn shrink_to_fit(&mut self) { - let ItemTree { top_level: _, attrs, data, vis: _, top_attrs: _ } = self; + let ItemTree { top_level: _, attrs, big_data, small_data, vis: _, top_attrs: _ } = self; attrs.shrink_to_fit(); - data.shrink_to_fit(); + big_data.shrink_to_fit(); + small_data.shrink_to_fit(); } } @@ -234,35 +243,37 @@ struct ItemVisibilities { } #[derive(Debug, Clone, Eq, PartialEq)] -enum ModItem { +enum SmallModItem { Const(Const), Enum(Enum), - // 32 - ExternBlock(ExternBlock), - // 40 - ExternCrate(ExternCrate), Function(Function), Impl(Impl), Macro2(Macro2), - // 32 - MacroCall(MacroCall), MacroRules(MacroRules), - // 40 - Mod(Mod), Static(Static), - // 32 - Struct(Struct), Trait(Trait), TraitAlias(TraitAlias), TypeAlias(TypeAlias), Union(Union), - // 40 +} + +#[derive(Debug, Clone, Eq, PartialEq)] +enum BigModItem { + ExternBlock(ExternBlock), + ExternCrate(ExternCrate), + MacroCall(MacroCall), + Mod(Mod), + Struct(Struct), Use(Use), } -// `ModItem` is stored a bunch in `ItemTree`'s so we pay the max for each item. It should stay as small as possible. +// `ModItem` is stored a bunch in `ItemTree`'s so we pay the max for each item. It should stay as +// small as possible which is why we split them in two, most common ones are 3 usize but some rarer +// ones are 5. +#[cfg(target_pointer_width = "64")] +const _: [(); std::mem::size_of::()] = [(); std::mem::size_of::<[usize; 5]>()]; #[cfg(target_pointer_width = "64")] -const _: [(); std::mem::size_of::()] = [(); std::mem::size_of::<[usize; 5]>()]; +const _: [(); std::mem::size_of::()] = [(); std::mem::size_of::<[usize; 3]>()]; #[derive(Default, Debug, Eq, PartialEq)] pub struct ItemTreeDataStats { @@ -343,9 +354,12 @@ macro_rules! mod_items { impl Index> for ItemTree { type Output = $typ; + #[allow(unused_imports)] fn index(&self, index: FileAstId<$ast>) -> &Self::Output { - match &self.data[&index.upcast()] { - ModItem::$typ(item) => item, + use BigModItem::*; + use SmallModItem::*; + match &self.$fld[&index.upcast()] { + $typ(item) => item, _ => panic!("expected item of type `{}` at index `{:?}`", stringify!($typ), index), } } @@ -356,23 +370,23 @@ macro_rules! mod_items { mod_items! { ModItemId -> - Use in uses -> ast::Use, - ExternCrate in extern_crates -> ast::ExternCrate, - ExternBlock in extern_blocks -> ast::ExternBlock, - Function in functions -> ast::Fn, - Struct in structs -> ast::Struct, - Union in unions -> ast::Union, - Enum in enums -> ast::Enum, - Const in consts -> ast::Const, - Static in statics -> ast::Static, - Trait in traits -> ast::Trait, - TraitAlias in trait_aliases -> ast::TraitAlias, - Impl in impls -> ast::Impl, - TypeAlias in type_aliases -> ast::TypeAlias, - Mod in mods -> ast::Module, - MacroCall in macro_calls -> ast::MacroCall, - MacroRules in macro_rules -> ast::MacroRules, - Macro2 in macro_defs -> ast::MacroDef, + Use in big_data -> ast::Use, + ExternCrate in big_data -> ast::ExternCrate, + ExternBlock in big_data -> ast::ExternBlock, + Function in small_data -> ast::Fn, + Struct in big_data -> ast::Struct, + Union in small_data -> ast::Union, + Enum in small_data -> ast::Enum, + Const in small_data -> ast::Const, + Static in small_data -> ast::Static, + Trait in small_data -> ast::Trait, + TraitAlias in small_data -> ast::TraitAlias, + Impl in small_data -> ast::Impl, + TypeAlias in small_data -> ast::TypeAlias, + Mod in big_data -> ast::Module, + MacroCall in big_data -> ast::MacroCall, + MacroRules in small_data -> ast::MacroRules, + Macro2 in small_data -> ast::MacroDef, } impl Index for ItemTree { @@ -421,6 +435,7 @@ pub struct UseTree { } // FIXME: Would be nice to encode `None` into this +// We could just use a `Name` where `_` well means `_` .. #[derive(Debug, Clone, PartialEq, Eq)] pub enum ImportAlias { /// Unnamed alias, as in `use Foo as _;` diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs index ab60b7ad70362..6ae745bb9a40a 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs @@ -20,10 +20,11 @@ use triomphe::Arc; use crate::{ db::DefDatabase, item_tree::{ - Const, Enum, ExternBlock, ExternCrate, FieldsShape, Function, Impl, ImportAlias, Interned, - ItemTree, ItemTreeAstId, Macro2, MacroCall, MacroRules, Mod, ModItem, ModItemId, ModKind, - ModPath, RawAttrs, RawVisibility, RawVisibilityId, Static, Struct, StructKind, Trait, - TraitAlias, TypeAlias, Union, Use, UseTree, UseTreeKind, VisibilityExplicitness, + BigModItem, Const, Enum, ExternBlock, ExternCrate, FieldsShape, Function, Impl, + ImportAlias, Interned, ItemTree, ItemTreeAstId, Macro2, MacroCall, MacroRules, Mod, + ModItemId, ModKind, ModPath, RawAttrs, RawVisibility, RawVisibilityId, SmallModItem, + Static, Struct, StructKind, Trait, TraitAlias, TypeAlias, Union, Use, UseTree, UseTreeKind, + VisibilityExplicitness, }, }; @@ -168,7 +169,7 @@ impl<'a> Ctx<'a> { let ast_id = self.source_ast_id_map.ast_id(strukt); let shape = adt_shape(strukt.kind()); let res = Struct { name, visibility, shape, ast_id }; - self.tree.data.insert(ast_id.upcast(), ModItem::Struct(res)); + self.tree.big_data.insert(ast_id.upcast(), BigModItem::Struct(res)); Some(ast_id) } @@ -178,7 +179,7 @@ impl<'a> Ctx<'a> { let name = union.name()?.as_name(); let ast_id = self.source_ast_id_map.ast_id(union); let res = Union { name, visibility, ast_id }; - self.tree.data.insert(ast_id.upcast(), ModItem::Union(res)); + self.tree.small_data.insert(ast_id.upcast(), SmallModItem::Union(res)); Some(ast_id) } @@ -187,7 +188,7 @@ impl<'a> Ctx<'a> { let name = enum_.name()?.as_name(); let ast_id = self.source_ast_id_map.ast_id(enum_); let res = Enum { name, visibility, ast_id }; - self.tree.data.insert(ast_id.upcast(), ModItem::Enum(res)); + self.tree.small_data.insert(ast_id.upcast(), SmallModItem::Enum(res)); Some(ast_id) } @@ -199,7 +200,7 @@ impl<'a> Ctx<'a> { let res = Function { name, visibility, ast_id }; - self.tree.data.insert(ast_id.upcast(), ModItem::Function(res)); + self.tree.small_data.insert(ast_id.upcast(), SmallModItem::Function(res)); Some(ast_id) } @@ -211,7 +212,7 @@ impl<'a> Ctx<'a> { let visibility = self.lower_visibility(type_alias); let ast_id = self.source_ast_id_map.ast_id(type_alias); let res = TypeAlias { name, visibility, ast_id }; - self.tree.data.insert(ast_id.upcast(), ModItem::TypeAlias(res)); + self.tree.small_data.insert(ast_id.upcast(), SmallModItem::TypeAlias(res)); Some(ast_id) } @@ -220,7 +221,7 @@ impl<'a> Ctx<'a> { let visibility = self.lower_visibility(static_); let ast_id = self.source_ast_id_map.ast_id(static_); let res = Static { name, visibility, ast_id }; - self.tree.data.insert(ast_id.upcast(), ModItem::Static(res)); + self.tree.small_data.insert(ast_id.upcast(), SmallModItem::Static(res)); Some(ast_id) } @@ -229,7 +230,7 @@ impl<'a> Ctx<'a> { let visibility = self.lower_visibility(konst); let ast_id = self.source_ast_id_map.ast_id(konst); let res = Const { name, visibility, ast_id }; - self.tree.data.insert(ast_id.upcast(), ModItem::Const(res)); + self.tree.small_data.insert(ast_id.upcast(), SmallModItem::Const(res)); ast_id } @@ -251,7 +252,7 @@ impl<'a> Ctx<'a> { }; let ast_id = self.source_ast_id_map.ast_id(module); let res = Mod { name, visibility, kind, ast_id }; - self.tree.data.insert(ast_id.upcast(), ModItem::Mod(res)); + self.tree.big_data.insert(ast_id.upcast(), BigModItem::Mod(res)); Some(ast_id) } @@ -261,7 +262,7 @@ impl<'a> Ctx<'a> { let ast_id = self.source_ast_id_map.ast_id(trait_def); let def = Trait { name, visibility, ast_id }; - self.tree.data.insert(ast_id.upcast(), ModItem::Trait(def)); + self.tree.small_data.insert(ast_id.upcast(), SmallModItem::Trait(def)); Some(ast_id) } @@ -274,7 +275,7 @@ impl<'a> Ctx<'a> { let ast_id = self.source_ast_id_map.ast_id(trait_alias_def); let alias = TraitAlias { name, visibility, ast_id }; - self.tree.data.insert(ast_id.upcast(), ModItem::TraitAlias(alias)); + self.tree.small_data.insert(ast_id.upcast(), SmallModItem::TraitAlias(alias)); Some(ast_id) } @@ -283,7 +284,7 @@ impl<'a> Ctx<'a> { // Note that trait impls don't get implicit `Self` unlike traits, because here they are a // type alias rather than a type parameter, so this is handled by the resolver. let res = Impl { ast_id }; - self.tree.data.insert(ast_id.upcast(), ModItem::Impl(res)); + self.tree.small_data.insert(ast_id.upcast(), SmallModItem::Impl(res)); ast_id } @@ -295,7 +296,7 @@ impl<'a> Ctx<'a> { })?; let res = Use { visibility, ast_id, use_tree }; - self.tree.data.insert(ast_id.upcast(), ModItem::Use(res)); + self.tree.big_data.insert(ast_id.upcast(), BigModItem::Use(res)); Some(ast_id) } @@ -311,7 +312,7 @@ impl<'a> Ctx<'a> { let ast_id = self.source_ast_id_map.ast_id(extern_crate); let res = ExternCrate { name, alias, visibility, ast_id }; - self.tree.data.insert(ast_id.upcast(), ModItem::ExternCrate(res)); + self.tree.big_data.insert(ast_id.upcast(), BigModItem::ExternCrate(res)); Some(ast_id) } @@ -325,7 +326,7 @@ impl<'a> Ctx<'a> { let ast_id = self.source_ast_id_map.ast_id(m); let expand_to = hir_expand::ExpandTo::from_call_site(m); let res = MacroCall { path, ast_id, expand_to, ctxt: span_map.span_for_range(range).ctx }; - self.tree.data.insert(ast_id.upcast(), ModItem::MacroCall(res)); + self.tree.big_data.insert(ast_id.upcast(), BigModItem::MacroCall(res)); Some(ast_id) } @@ -334,7 +335,7 @@ impl<'a> Ctx<'a> { let ast_id = self.source_ast_id_map.ast_id(m); let res = MacroRules { name: name.as_name(), ast_id }; - self.tree.data.insert(ast_id.upcast(), ModItem::MacroRules(res)); + self.tree.small_data.insert(ast_id.upcast(), SmallModItem::MacroRules(res)); Some(ast_id) } @@ -345,7 +346,7 @@ impl<'a> Ctx<'a> { let visibility = self.lower_visibility(m); let res = Macro2 { name: name.as_name(), ast_id, visibility }; - self.tree.data.insert(ast_id.upcast(), ModItem::Macro2(res)); + self.tree.small_data.insert(ast_id.upcast(), SmallModItem::Macro2(res)); Some(ast_id) } @@ -372,7 +373,7 @@ impl<'a> Ctx<'a> { }); let res = ExternBlock { ast_id, children }; - self.tree.data.insert(ast_id.upcast(), ModItem::ExternBlock(res)); + self.tree.big_data.insert(ast_id.upcast(), BigModItem::ExternBlock(res)); ast_id } diff --git a/src/tools/rust-analyzer/crates/intern/src/symbol.rs b/src/tools/rust-analyzer/crates/intern/src/symbol.rs index 3b962a86f1769..8b2d6e8717d23 100644 --- a/src/tools/rust-analyzer/crates/intern/src/symbol.rs +++ b/src/tools/rust-analyzer/crates/intern/src/symbol.rs @@ -112,7 +112,6 @@ impl TaggedArcPtr { } } -// FIXME: This should have more than one niche #[derive(PartialEq, Eq, Hash)] pub struct Symbol { repr: TaggedArcPtr, From 4f1a07ca583b1da018034c6637b1099fa46f009d Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Fri, 13 Jun 2025 08:43:56 +0200 Subject: [PATCH 32/56] Remove ast ids from item tree mod items --- .../crates/hir-def/src/item_tree.rs | 50 +++---- .../crates/hir-def/src/item_tree/lower.rs | 40 +++--- .../crates/hir-def/src/item_tree/pretty.rs | 68 +++++----- .../crates/hir-def/src/nameres/collector.rs | 124 +++++++----------- 4 files changed, 121 insertions(+), 161 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs index 5b9da1723114b..bf482d33e7392 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs @@ -212,13 +212,13 @@ impl ItemTree { SmallModItem::Trait(_) => traits += 1, SmallModItem::Impl(_) => impls += 1, SmallModItem::MacroRules(_) => macro_rules += 1, + SmallModItem::MacroCall(_) => macro_calls += 1, _ => {} } } for item in self.big_data.values() { match item { BigModItem::Mod(_) => mods += 1, - BigModItem::MacroCall(_) => macro_calls += 1, _ => {} } } @@ -246,11 +246,14 @@ struct ItemVisibilities { enum SmallModItem { Const(Const), Enum(Enum), + ExternBlock(ExternBlock), Function(Function), Impl(Impl), Macro2(Macro2), + MacroCall(MacroCall), MacroRules(MacroRules), Static(Static), + Struct(Struct), Trait(Trait), TraitAlias(TraitAlias), TypeAlias(TypeAlias), @@ -259,11 +262,8 @@ enum SmallModItem { #[derive(Debug, Clone, Eq, PartialEq)] enum BigModItem { - ExternBlock(ExternBlock), ExternCrate(ExternCrate), - MacroCall(MacroCall), Mod(Mod), - Struct(Struct), Use(Use), } @@ -370,23 +370,23 @@ macro_rules! mod_items { mod_items! { ModItemId -> - Use in big_data -> ast::Use, + Const in small_data -> ast::Const, + Enum in small_data -> ast::Enum, + ExternBlock in small_data -> ast::ExternBlock, ExternCrate in big_data -> ast::ExternCrate, - ExternBlock in big_data -> ast::ExternBlock, Function in small_data -> ast::Fn, - Struct in big_data -> ast::Struct, - Union in small_data -> ast::Union, - Enum in small_data -> ast::Enum, - Const in small_data -> ast::Const, + Impl in small_data -> ast::Impl, + Macro2 in small_data -> ast::MacroDef, + MacroCall in small_data -> ast::MacroCall, + MacroRules in small_data -> ast::MacroRules, + Mod in big_data -> ast::Module, Static in small_data -> ast::Static, + Struct in small_data -> ast::Struct, Trait in small_data -> ast::Trait, TraitAlias in small_data -> ast::TraitAlias, - Impl in small_data -> ast::Impl, TypeAlias in small_data -> ast::TypeAlias, - Mod in big_data -> ast::Module, - MacroCall in big_data -> ast::MacroCall, - MacroRules in small_data -> ast::MacroRules, - Macro2 in small_data -> ast::MacroDef, + Union in small_data -> ast::Union, + Use in big_data -> ast::Use, } impl Index for ItemTree { @@ -425,7 +425,6 @@ impl Index for ItemTree { #[derive(Debug, Clone, Eq, PartialEq)] pub struct Use { pub(crate) visibility: RawVisibilityId, - pub(crate) ast_id: FileAstId, pub(crate) use_tree: UseTree, } @@ -490,12 +489,10 @@ pub struct ExternCrate { pub name: Name, pub alias: Option, pub(crate) visibility: RawVisibilityId, - pub ast_id: FileAstId, } #[derive(Debug, Clone, Eq, PartialEq)] pub struct ExternBlock { - pub ast_id: FileAstId, pub(crate) children: Box<[ModItemId]>, } @@ -503,7 +500,6 @@ pub struct ExternBlock { pub struct Function { pub name: Name, pub(crate) visibility: RawVisibilityId, - pub ast_id: FileAstId, } #[derive(Debug, Clone, Eq, PartialEq)] @@ -511,21 +507,18 @@ pub struct Struct { pub name: Name, pub(crate) visibility: RawVisibilityId, pub shape: FieldsShape, - pub ast_id: FileAstId, } #[derive(Debug, Clone, Eq, PartialEq)] pub struct Union { pub name: Name, pub(crate) visibility: RawVisibilityId, - pub ast_id: FileAstId, } #[derive(Debug, Clone, Eq, PartialEq)] pub struct Enum { pub name: Name, pub(crate) visibility: RawVisibilityId, - pub ast_id: FileAstId, } #[derive(Debug, Copy, Clone, PartialEq, Eq)] @@ -564,40 +557,33 @@ pub struct Const { /// `None` for `const _: () = ();` pub name: Option, pub(crate) visibility: RawVisibilityId, - pub ast_id: FileAstId, } #[derive(Debug, Clone, Eq, PartialEq)] pub struct Static { pub name: Name, pub(crate) visibility: RawVisibilityId, - pub ast_id: FileAstId, } #[derive(Debug, Clone, Eq, PartialEq)] pub struct Trait { pub name: Name, pub(crate) visibility: RawVisibilityId, - pub ast_id: FileAstId, } #[derive(Debug, Clone, Eq, PartialEq)] pub struct TraitAlias { pub name: Name, pub(crate) visibility: RawVisibilityId, - pub ast_id: FileAstId, } #[derive(Debug, Clone, Eq, PartialEq)] -pub struct Impl { - pub ast_id: FileAstId, -} +pub struct Impl {} #[derive(Debug, Clone, PartialEq, Eq)] pub struct TypeAlias { pub name: Name, pub(crate) visibility: RawVisibilityId, - pub ast_id: FileAstId, } #[derive(Debug, Clone, Eq, PartialEq)] @@ -605,7 +591,6 @@ pub struct Mod { pub name: Name, pub(crate) visibility: RawVisibilityId, pub(crate) kind: ModKind, - pub ast_id: FileAstId, } #[derive(Debug, Clone, Eq, PartialEq)] @@ -620,7 +605,6 @@ pub(crate) enum ModKind { pub struct MacroCall { /// Path to the called macro. pub path: Interned, - pub ast_id: FileAstId, pub expand_to: ExpandTo, pub ctxt: SyntaxContext, } @@ -629,7 +613,6 @@ pub struct MacroCall { pub struct MacroRules { /// The name of the declared macro. pub name: Name, - pub ast_id: FileAstId, } /// "Macros 2.0" macro definition. @@ -637,7 +620,6 @@ pub struct MacroRules { pub struct Macro2 { pub name: Name, pub(crate) visibility: RawVisibilityId, - pub ast_id: FileAstId, } #[derive(Clone, Copy, Debug, Eq, PartialEq)] diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs index 6ae745bb9a40a..fe1b8e3134254 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs @@ -168,8 +168,8 @@ impl<'a> Ctx<'a> { let name = strukt.name()?.as_name(); let ast_id = self.source_ast_id_map.ast_id(strukt); let shape = adt_shape(strukt.kind()); - let res = Struct { name, visibility, shape, ast_id }; - self.tree.big_data.insert(ast_id.upcast(), BigModItem::Struct(res)); + let res = Struct { name, visibility, shape }; + self.tree.small_data.insert(ast_id.upcast(), SmallModItem::Struct(res)); Some(ast_id) } @@ -178,7 +178,7 @@ impl<'a> Ctx<'a> { let visibility = self.lower_visibility(union); let name = union.name()?.as_name(); let ast_id = self.source_ast_id_map.ast_id(union); - let res = Union { name, visibility, ast_id }; + let res = Union { name, visibility }; self.tree.small_data.insert(ast_id.upcast(), SmallModItem::Union(res)); Some(ast_id) } @@ -187,7 +187,7 @@ impl<'a> Ctx<'a> { let visibility = self.lower_visibility(enum_); let name = enum_.name()?.as_name(); let ast_id = self.source_ast_id_map.ast_id(enum_); - let res = Enum { name, visibility, ast_id }; + let res = Enum { name, visibility }; self.tree.small_data.insert(ast_id.upcast(), SmallModItem::Enum(res)); Some(ast_id) } @@ -198,7 +198,7 @@ impl<'a> Ctx<'a> { let ast_id = self.source_ast_id_map.ast_id(func); - let res = Function { name, visibility, ast_id }; + let res = Function { name, visibility }; self.tree.small_data.insert(ast_id.upcast(), SmallModItem::Function(res)); Some(ast_id) @@ -211,7 +211,7 @@ impl<'a> Ctx<'a> { let name = type_alias.name()?.as_name(); let visibility = self.lower_visibility(type_alias); let ast_id = self.source_ast_id_map.ast_id(type_alias); - let res = TypeAlias { name, visibility, ast_id }; + let res = TypeAlias { name, visibility }; self.tree.small_data.insert(ast_id.upcast(), SmallModItem::TypeAlias(res)); Some(ast_id) } @@ -220,7 +220,7 @@ impl<'a> Ctx<'a> { let name = static_.name()?.as_name(); let visibility = self.lower_visibility(static_); let ast_id = self.source_ast_id_map.ast_id(static_); - let res = Static { name, visibility, ast_id }; + let res = Static { name, visibility }; self.tree.small_data.insert(ast_id.upcast(), SmallModItem::Static(res)); Some(ast_id) } @@ -229,7 +229,7 @@ impl<'a> Ctx<'a> { let name = konst.name().map(|it| it.as_name()); let visibility = self.lower_visibility(konst); let ast_id = self.source_ast_id_map.ast_id(konst); - let res = Const { name, visibility, ast_id }; + let res = Const { name, visibility }; self.tree.small_data.insert(ast_id.upcast(), SmallModItem::Const(res)); ast_id } @@ -251,7 +251,7 @@ impl<'a> Ctx<'a> { } }; let ast_id = self.source_ast_id_map.ast_id(module); - let res = Mod { name, visibility, kind, ast_id }; + let res = Mod { name, visibility, kind }; self.tree.big_data.insert(ast_id.upcast(), BigModItem::Mod(res)); Some(ast_id) } @@ -261,7 +261,7 @@ impl<'a> Ctx<'a> { let visibility = self.lower_visibility(trait_def); let ast_id = self.source_ast_id_map.ast_id(trait_def); - let def = Trait { name, visibility, ast_id }; + let def = Trait { name, visibility }; self.tree.small_data.insert(ast_id.upcast(), SmallModItem::Trait(def)); Some(ast_id) } @@ -274,7 +274,7 @@ impl<'a> Ctx<'a> { let visibility = self.lower_visibility(trait_alias_def); let ast_id = self.source_ast_id_map.ast_id(trait_alias_def); - let alias = TraitAlias { name, visibility, ast_id }; + let alias = TraitAlias { name, visibility }; self.tree.small_data.insert(ast_id.upcast(), SmallModItem::TraitAlias(alias)); Some(ast_id) } @@ -283,7 +283,7 @@ impl<'a> Ctx<'a> { let ast_id = self.source_ast_id_map.ast_id(impl_def); // Note that trait impls don't get implicit `Self` unlike traits, because here they are a // type alias rather than a type parameter, so this is handled by the resolver. - let res = Impl { ast_id }; + let res = Impl {}; self.tree.small_data.insert(ast_id.upcast(), SmallModItem::Impl(res)); ast_id } @@ -295,7 +295,7 @@ impl<'a> Ctx<'a> { self.span_map().span_for_range(range).ctx })?; - let res = Use { visibility, ast_id, use_tree }; + let res = Use { visibility, use_tree }; self.tree.big_data.insert(ast_id.upcast(), BigModItem::Use(res)); Some(ast_id) } @@ -311,7 +311,7 @@ impl<'a> Ctx<'a> { let visibility = self.lower_visibility(extern_crate); let ast_id = self.source_ast_id_map.ast_id(extern_crate); - let res = ExternCrate { name, alias, visibility, ast_id }; + let res = ExternCrate { name, alias, visibility }; self.tree.big_data.insert(ast_id.upcast(), BigModItem::ExternCrate(res)); Some(ast_id) } @@ -325,8 +325,8 @@ impl<'a> Ctx<'a> { })?); let ast_id = self.source_ast_id_map.ast_id(m); let expand_to = hir_expand::ExpandTo::from_call_site(m); - let res = MacroCall { path, ast_id, expand_to, ctxt: span_map.span_for_range(range).ctx }; - self.tree.big_data.insert(ast_id.upcast(), BigModItem::MacroCall(res)); + let res = MacroCall { path, expand_to, ctxt: span_map.span_for_range(range).ctx }; + self.tree.small_data.insert(ast_id.upcast(), SmallModItem::MacroCall(res)); Some(ast_id) } @@ -334,7 +334,7 @@ impl<'a> Ctx<'a> { let name = m.name()?; let ast_id = self.source_ast_id_map.ast_id(m); - let res = MacroRules { name: name.as_name(), ast_id }; + let res = MacroRules { name: name.as_name() }; self.tree.small_data.insert(ast_id.upcast(), SmallModItem::MacroRules(res)); Some(ast_id) } @@ -345,7 +345,7 @@ impl<'a> Ctx<'a> { let ast_id = self.source_ast_id_map.ast_id(m); let visibility = self.lower_visibility(m); - let res = Macro2 { name: name.as_name(), ast_id, visibility }; + let res = Macro2 { name: name.as_name(), visibility }; self.tree.small_data.insert(ast_id.upcast(), SmallModItem::Macro2(res)); Some(ast_id) } @@ -372,8 +372,8 @@ impl<'a> Ctx<'a> { .collect() }); - let res = ExternBlock { ast_id, children }; - self.tree.big_data.insert(ast_id.upcast(), BigModItem::ExternBlock(res)); + let res = ExternBlock { children }; + self.tree.small_data.insert(ast_id.upcast(), SmallModItem::ExternBlock(res)); ast_id } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs index 11b91568987fd..eb97081128eda 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs @@ -161,16 +161,16 @@ impl Printer<'_> { self.print_attrs_of(item, "\n"); match item { - ModItemId::Use(it) => { - let Use { visibility, use_tree, ast_id } = &self.tree[it]; + ModItemId::Use(ast_id) => { + let Use { visibility, use_tree } = &self.tree[ast_id]; self.print_ast_id(ast_id.erase()); self.print_visibility(*visibility); w!(self, "use "); self.print_use_tree(use_tree); wln!(self, ";"); } - ModItemId::ExternCrate(it) => { - let ExternCrate { name, alias, visibility, ast_id } = &self.tree[it]; + ModItemId::ExternCrate(ast_id) => { + let ExternCrate { name, alias, visibility } = &self.tree[ast_id]; self.print_ast_id(ast_id.erase()); self.print_visibility(*visibility); w!(self, "extern crate {}", name.display(self.db, self.edition)); @@ -179,8 +179,8 @@ impl Printer<'_> { } wln!(self, ";"); } - ModItemId::ExternBlock(it) => { - let ExternBlock { ast_id, children } = &self.tree[it]; + ModItemId::ExternBlock(ast_id) => { + let ExternBlock { children } = &self.tree[ast_id]; self.print_ast_id(ast_id.erase()); w!(self, "extern {{"); self.indented(|this| { @@ -190,14 +190,14 @@ impl Printer<'_> { }); wln!(self, "}}"); } - ModItemId::Function(it) => { - let Function { name, visibility, ast_id } = &self.tree[it]; + ModItemId::Function(ast_id) => { + let Function { name, visibility } = &self.tree[ast_id]; self.print_ast_id(ast_id.erase()); self.print_visibility(*visibility); wln!(self, "fn {};", name.display(self.db, self.edition)); } - ModItemId::Struct(it) => { - let Struct { visibility, name, shape: kind, ast_id } = &self.tree[it]; + ModItemId::Struct(ast_id) => { + let Struct { visibility, name, shape: kind } = &self.tree[ast_id]; self.print_ast_id(ast_id.erase()); self.print_visibility(*visibility); w!(self, "struct {}", name.display(self.db, self.edition)); @@ -208,22 +208,22 @@ impl Printer<'_> { wln!(self, ";"); } } - ModItemId::Union(it) => { - let Union { name, visibility, ast_id } = &self.tree[it]; + ModItemId::Union(ast_id) => { + let Union { name, visibility } = &self.tree[ast_id]; self.print_ast_id(ast_id.erase()); self.print_visibility(*visibility); w!(self, "union {}", name.display(self.db, self.edition)); self.print_fields(FieldsShape::Record); wln!(self); } - ModItemId::Enum(it) => { - let Enum { name, visibility, ast_id } = &self.tree[it]; + ModItemId::Enum(ast_id) => { + let Enum { name, visibility } = &self.tree[ast_id]; self.print_ast_id(ast_id.erase()); self.print_visibility(*visibility); w!(self, "enum {} {{ ... }}", name.display(self.db, self.edition)); } - ModItemId::Const(it) => { - let Const { name, visibility, ast_id } = &self.tree[it]; + ModItemId::Const(ast_id) => { + let Const { name, visibility } = &self.tree[ast_id]; self.print_ast_id(ast_id.erase()); self.print_visibility(*visibility); w!(self, "const "); @@ -233,8 +233,8 @@ impl Printer<'_> { } wln!(self, " = _;"); } - ModItemId::Static(it) => { - let Static { name, visibility, ast_id } = &self.tree[it]; + ModItemId::Static(ast_id) => { + let Static { name, visibility } = &self.tree[ast_id]; self.print_ast_id(ast_id.erase()); self.print_visibility(*visibility); w!(self, "static "); @@ -242,33 +242,33 @@ impl Printer<'_> { w!(self, " = _;"); wln!(self); } - ModItemId::Trait(it) => { - let Trait { name, visibility, ast_id } = &self.tree[it]; + ModItemId::Trait(ast_id) => { + let Trait { name, visibility } = &self.tree[ast_id]; self.print_ast_id(ast_id.erase()); self.print_visibility(*visibility); w!(self, "trait {} {{ ... }}", name.display(self.db, self.edition)); } - ModItemId::TraitAlias(it) => { - let TraitAlias { name, visibility, ast_id } = &self.tree[it]; + ModItemId::TraitAlias(ast_id) => { + let TraitAlias { name, visibility } = &self.tree[ast_id]; self.print_ast_id(ast_id.erase()); self.print_visibility(*visibility); wln!(self, "trait {} = ..;", name.display(self.db, self.edition)); } - ModItemId::Impl(it) => { - let Impl { ast_id } = &self.tree[it]; + ModItemId::Impl(ast_id) => { + let Impl {} = &self.tree[ast_id]; self.print_ast_id(ast_id.erase()); w!(self, "impl {{ ... }}"); } - ModItemId::TypeAlias(it) => { - let TypeAlias { name, visibility, ast_id } = &self.tree[it]; + ModItemId::TypeAlias(ast_id) => { + let TypeAlias { name, visibility } = &self.tree[ast_id]; self.print_ast_id(ast_id.erase()); self.print_visibility(*visibility); w!(self, "type {}", name.display(self.db, self.edition)); w!(self, ";"); wln!(self); } - ModItemId::Mod(it) => { - let Mod { name, visibility, kind, ast_id } = &self.tree[it]; + ModItemId::Mod(ast_id) => { + let Mod { name, visibility, kind } = &self.tree[ast_id]; self.print_ast_id(ast_id.erase()); self.print_visibility(*visibility); w!(self, "mod {}", name.display(self.db, self.edition)); @@ -287,8 +287,8 @@ impl Printer<'_> { } } } - ModItemId::MacroCall(it) => { - let MacroCall { path, ast_id, expand_to, ctxt } = &self.tree[it]; + ModItemId::MacroCall(ast_id) => { + let MacroCall { path, expand_to, ctxt } = &self.tree[ast_id]; let _ = writeln!( self, "// AstId: {:#?}, SyntaxContextId: {}, ExpandTo: {:?}", @@ -298,13 +298,13 @@ impl Printer<'_> { ); wln!(self, "{}!(...);", path.display(self.db, self.edition)); } - ModItemId::MacroRules(it) => { - let MacroRules { name, ast_id } = &self.tree[it]; + ModItemId::MacroRules(ast_id) => { + let MacroRules { name } = &self.tree[ast_id]; self.print_ast_id(ast_id.erase()); wln!(self, "macro_rules! {} {{ ... }}", name.display(self.db, self.edition)); } - ModItemId::Macro2(it) => { - let Macro2 { name, visibility, ast_id } = &self.tree[it]; + ModItemId::Macro2(ast_id) => { + let Macro2 { name, visibility } = &self.tree[ast_id]; self.print_ast_id(ast_id.erase()); self.print_visibility(*visibility); wln!(self, "macro {} {{ ... }}", name.display(self.db, self.edition)); diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs index 3b2488c8ea6df..185cc0596b6cc 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs @@ -1434,11 +1434,10 @@ impl DefCollector<'_> { // normal (as that would just be an identity expansion with extra output) // Instead we treat derive attributes special and apply them separately. - let item_tree = tree.item_tree(self.db); let ast_adt_id: FileAstId = match *mod_item { - ModItemId::Struct(strukt) => item_tree[strukt].ast_id.upcast(), - ModItemId::Union(union) => item_tree[union].ast_id.upcast(), - ModItemId::Enum(enum_) => item_tree[enum_].ast_id.upcast(), + ModItemId::Struct(ast_id) => ast_id.upcast(), + ModItemId::Union(ast_id) => ast_id.upcast(), + ModItemId::Enum(ast_id) => ast_id.upcast(), _ => { let diag = DefDiagnostic::invalid_derive_target( directive.module_id, @@ -1750,11 +1749,9 @@ impl ModCollector<'_, '_> { match item { ModItemId::Mod(m) => self.collect_module(m, &attrs), ModItemId::Use(item_tree_id) => { - let id = UseLoc { - container: module, - id: InFile::new(self.file_id(), self.item_tree[item_tree_id].ast_id), - } - .intern(db); + let id = + UseLoc { container: module, id: InFile::new(self.file_id(), item_tree_id) } + .intern(db); let is_prelude = attrs.by_key(sym::prelude_import).exists(); Import::from_use( self.item_tree, @@ -1772,12 +1769,12 @@ impl ModCollector<'_, '_> { ) } ModItemId::ExternCrate(item_tree_id) => { - let item_tree::ExternCrate { name, visibility, alias, ast_id } = + let item_tree::ExternCrate { name, visibility, alias } = &self.item_tree[item_tree_id]; let id = ExternCrateLoc { container: module, - id: InFile::new(self.tree_id.file_id(), *ast_id), + id: InFile::new(self.tree_id.file_id(), item_tree_id), } .intern(db); def_map.modules[self.module_id].scope.define_extern_crate_decl(id); @@ -1840,7 +1837,7 @@ impl ModCollector<'_, '_> { self.def_collector.def_map.diagnostics.push( DefDiagnostic::unresolved_extern_crate( module_id, - InFile::new(self.file_id(), *ast_id), + InFile::new(self.file_id(), item_tree_id), ), ); } @@ -1848,7 +1845,7 @@ impl ModCollector<'_, '_> { ModItemId::ExternBlock(block) => { let extern_block_id = ExternBlockLoc { container: module, - id: InFile::new(self.file_id(), self.item_tree[block].ast_id), + id: InFile::new(self.file_id(), block), } .intern(db); self.def_collector.def_map.modules[self.module_id] @@ -1859,26 +1856,20 @@ impl ModCollector<'_, '_> { ItemContainerId::ExternBlockId(extern_block_id), ) } - ModItemId::MacroCall(mac) => { - self.collect_macro_call(&self.item_tree[mac], container) - } + ModItemId::MacroCall(mac) => self.collect_macro_call(mac, container), ModItemId::MacroRules(id) => self.collect_macro_rules(id, module), ModItemId::Macro2(id) => self.collect_macro_def(id, module), ModItemId::Impl(imp) => { - let impl_id = ImplLoc { - container: module, - id: InFile::new(self.file_id(), self.item_tree[imp].ast_id), - } - .intern(db); + let impl_id = + ImplLoc { container: module, id: InFile::new(self.file_id(), imp) } + .intern(db); self.def_collector.def_map.modules[self.module_id].scope.define_impl(impl_id) } ModItemId::Function(id) => { let it = &self.item_tree[id]; - let fn_id = FunctionLoc { - container, - id: InFile::new(self.tree_id.file_id(), it.ast_id), - } - .intern(db); + let fn_id = + FunctionLoc { container, id: InFile::new(self.tree_id.file_id(), id) } + .intern(db); let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]); @@ -1889,7 +1880,7 @@ impl ModCollector<'_, '_> { if let Some(proc_macro) = attrs.parse_proc_macro_decl(&it.name) { self.def_collector.export_proc_macro( proc_macro, - InFile::new(self.file_id(), self.item_tree[id].ast_id), + InFile::new(self.file_id(), id), fn_id, ); } @@ -1903,7 +1894,7 @@ impl ModCollector<'_, '_> { let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]); update_def( self.def_collector, - StructLoc { container: module, id: InFile::new(self.file_id(), it.ast_id) } + StructLoc { container: module, id: InFile::new(self.file_id(), id) } .intern(db) .into(), &it.name, @@ -1917,7 +1908,7 @@ impl ModCollector<'_, '_> { let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]); update_def( self.def_collector, - UnionLoc { container: module, id: InFile::new(self.file_id(), it.ast_id) } + UnionLoc { container: module, id: InFile::new(self.file_id(), id) } .intern(db) .into(), &it.name, @@ -1927,11 +1918,9 @@ impl ModCollector<'_, '_> { } ModItemId::Enum(id) => { let it = &self.item_tree[id]; - let enum_ = EnumLoc { - container: module, - id: InFile::new(self.tree_id.file_id(), it.ast_id), - } - .intern(db); + let enum_ = + EnumLoc { container: module, id: InFile::new(self.tree_id.file_id(), id) } + .intern(db); let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]); update_def(self.def_collector, enum_.into(), &it.name, vis, false); @@ -1939,7 +1928,7 @@ impl ModCollector<'_, '_> { ModItemId::Const(id) => { let it = &self.item_tree[id]; let const_id = - ConstLoc { container, id: InFile::new(self.tree_id.file_id(), it.ast_id) } + ConstLoc { container, id: InFile::new(self.tree_id.file_id(), id) } .intern(db); match &it.name { @@ -1962,7 +1951,7 @@ impl ModCollector<'_, '_> { let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]); update_def( self.def_collector, - StaticLoc { container, id: InFile::new(self.file_id(), it.ast_id) } + StaticLoc { container, id: InFile::new(self.file_id(), id) } .intern(db) .into(), &it.name, @@ -1976,7 +1965,7 @@ impl ModCollector<'_, '_> { let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]); update_def( self.def_collector, - TraitLoc { container: module, id: InFile::new(self.file_id(), it.ast_id) } + TraitLoc { container: module, id: InFile::new(self.file_id(), id) } .intern(db) .into(), &it.name, @@ -1990,12 +1979,9 @@ impl ModCollector<'_, '_> { let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]); update_def( self.def_collector, - TraitAliasLoc { - container: module, - id: InFile::new(self.file_id(), it.ast_id), - } - .intern(db) - .into(), + TraitAliasLoc { container: module, id: InFile::new(self.file_id(), id) } + .intern(db) + .into(), &it.name, vis, false, @@ -2007,7 +1993,7 @@ impl ModCollector<'_, '_> { let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]); update_def( self.def_collector, - TypeAliasLoc { container, id: InFile::new(self.file_id(), it.ast_id) } + TypeAliasLoc { container, id: InFile::new(self.file_id(), id) } .intern(db) .into(), &it.name, @@ -2070,16 +2056,16 @@ impl ModCollector<'_, '_> { ); } - fn collect_module(&mut self, module_id: ItemTreeAstId, attrs: &Attrs) { + fn collect_module(&mut self, module_ast_id: ItemTreeAstId, attrs: &Attrs) { let path_attr = attrs.by_key(sym::path).string_value_unescape(); let is_macro_use = attrs.by_key(sym::macro_use).exists(); - let module = &self.item_tree[module_id]; + let module = &self.item_tree[module_ast_id]; match &module.kind { // inline module, just recurse ModKind::Inline { items } => { let module_id = self.push_child_module( module.name.clone(), - module.ast_id, + module_ast_id, None, &self.item_tree[module.visibility], ); @@ -2104,7 +2090,7 @@ impl ModCollector<'_, '_> { } // out of line module, resolve, parse and recurse ModKind::Outline => { - let ast_id = AstId::new(self.file_id(), module.ast_id); + let ast_id = AstId::new(self.file_id(), module_ast_id); let db = self.def_collector.db; match self.mod_dir.resolve_declaration( db, @@ -2123,10 +2109,7 @@ impl ModCollector<'_, '_> { match is_enabled { Err(cfg) => { self.emit_unconfigured_diagnostic( - InFile::new( - self.file_id(), - self.item_tree[module_id].ast_id.erase(), - ), + InFile::new(self.file_id(), module_ast_id.erase()), &cfg, ); } @@ -2295,11 +2278,11 @@ impl ModCollector<'_, '_> { Ok(()) } - fn collect_macro_rules(&mut self, id: ItemTreeAstId, module: ModuleId) { + fn collect_macro_rules(&mut self, ast_id: ItemTreeAstId, module: ModuleId) { let krate = self.def_collector.def_map.krate; - let mac = &self.item_tree[id]; - let attrs = self.item_tree.attrs(self.def_collector.db, krate, id.upcast()); - let ast_id = InFile::new(self.file_id(), mac.ast_id.upcast()); + let mac = &self.item_tree[ast_id]; + let attrs = self.item_tree.attrs(self.def_collector.db, krate, ast_id.upcast()); + let f_ast_id = InFile::new(self.file_id(), ast_id.upcast()); let export_attr = || attrs.by_key(sym::macro_export); @@ -2346,7 +2329,7 @@ impl ModCollector<'_, '_> { self.def_collector .def_map .diagnostics - .push(DefDiagnostic::unimplemented_builtin_macro(self.module_id, ast_id)); + .push(DefDiagnostic::unimplemented_builtin_macro(self.module_id, f_ast_id)); return; } } @@ -2362,16 +2345,13 @@ impl ModCollector<'_, '_> { let macro_id = MacroRulesLoc { container: module, - id: InFile::new(self.file_id(), mac.ast_id), + id: InFile::new(self.file_id(), ast_id), flags, expander, edition: self.def_collector.def_map.data.edition, } .intern(self.def_collector.db); - self.def_collector.def_map.macro_def_to_macro_id.insert( - InFile::new(self.file_id(), self.item_tree[id].ast_id).erase(), - macro_id.into(), - ); + self.def_collector.def_map.macro_def_to_macro_id.insert(f_ast_id.erase(), macro_id.into()); self.def_collector.define_macro_rules( self.module_id, mac.name.clone(), @@ -2380,14 +2360,14 @@ impl ModCollector<'_, '_> { ); } - fn collect_macro_def(&mut self, id: ItemTreeAstId, module: ModuleId) { + fn collect_macro_def(&mut self, ast_id: ItemTreeAstId, module: ModuleId) { let krate = self.def_collector.def_map.krate; - let mac = &self.item_tree[id]; - let ast_id = InFile::new(self.file_id(), mac.ast_id.upcast()); + let mac = &self.item_tree[ast_id]; + let attrs = self.item_tree.attrs(self.def_collector.db, krate, ast_id.upcast()); + let f_ast_id = InFile::new(self.file_id(), ast_id.upcast()); // Case 1: builtin macros let mut helpers_opt = None; - let attrs = self.item_tree.attrs(self.def_collector.db, krate, id.upcast()); let expander = if attrs.by_key(sym::rustc_builtin_macro).exists() { if let Some(expander) = find_builtin_macro(&mac.name) { match expander { @@ -2419,7 +2399,7 @@ impl ModCollector<'_, '_> { self.def_collector .def_map .diagnostics - .push(DefDiagnostic::unimplemented_builtin_macro(self.module_id, ast_id)); + .push(DefDiagnostic::unimplemented_builtin_macro(self.module_id, f_ast_id)); return; } } else { @@ -2430,16 +2410,13 @@ impl ModCollector<'_, '_> { let macro_id = Macro2Loc { container: module, - id: InFile::new(self.file_id(), mac.ast_id), + id: InFile::new(self.file_id(), ast_id), expander, allow_internal_unsafe, edition: self.def_collector.def_map.data.edition, } .intern(self.def_collector.db); - self.def_collector.def_map.macro_def_to_macro_id.insert( - InFile::new(self.file_id(), self.item_tree[id].ast_id).erase(), - macro_id.into(), - ); + self.def_collector.def_map.macro_def_to_macro_id.insert(f_ast_id.erase(), macro_id.into()); self.def_collector.define_macro_def( self.module_id, mac.name.clone(), @@ -2458,9 +2435,10 @@ impl ModCollector<'_, '_> { fn collect_macro_call( &mut self, - &MacroCall { ref path, ast_id, expand_to, ctxt }: &MacroCall, + ast_id: FileAstId, container: ItemContainerId, ) { + let &MacroCall { ref path, expand_to, ctxt } = &self.item_tree[ast_id]; let ast_id = AstIdWithPath::new(self.file_id(), ast_id, path.clone()); let db = self.def_collector.db; From 68f6a23c5874cef60bcab58c76a50225609ba09f Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Fri, 13 Jun 2025 09:45:04 +0200 Subject: [PATCH 33/56] `cargo update` Updating adler2 v2.0.0 -> v2.0.1 Updating anyhow v1.0.97 -> v1.0.98 Updating bitflags v2.9.0 -> v2.9.1 Updating borsh v1.5.5 -> v1.5.7 Updating boxcar v0.2.12 -> v0.2.13 Updating camino v1.1.9 -> v1.1.10 Updating cc v1.2.16 -> v1.2.26 Updating cfg-if v1.0.0 -> v1.0.1 Updating flate2 v1.1.1 -> v1.1.2 Updating foldhash v0.1.4 -> v0.1.5 Updating getrandom v0.2.15 -> v0.2.16 Updating hashbrown v0.15.2 -> v0.15.4 Updating hermit-abi v0.3.9 -> v0.5.2 Updating icu_collections v1.5.0 -> v2.0.0 Adding icu_locale_core v2.0.0 Removing icu_locid v1.5.0 Removing icu_locid_transform v1.5.0 Removing icu_locid_transform_data v1.5.0 Updating icu_normalizer v1.5.0 -> v2.0.0 Updating icu_normalizer_data v1.5.0 -> v2.0.0 Updating icu_properties v1.5.1 -> v2.0.1 Updating icu_properties_data v1.5.0 -> v2.0.1 Updating icu_provider v1.5.0 -> v2.0.0 Removing icu_provider_macros v1.5.0 Updating idna_adapter v1.2.0 -> v1.2.1 Updating kqueue v1.0.8 -> v1.1.1 Updating libloading v0.8.7 -> v0.8.8 Updating libmimalloc-sys v0.1.40 -> v0.1.42 Updating litemap v0.7.5 -> v0.8.0 Updating lock_api v0.4.12 -> v0.4.13 Updating log v0.4.26 -> v0.4.27 Updating memchr v2.7.4 -> v2.7.5 Updating mimalloc v0.1.44 -> v0.1.46 Updating miniz_oxide v0.8.5 -> v0.8.9 Updating mio v1.0.3 -> v1.0.4 Updating num_cpus v1.16.0 -> v1.17.0 Updating once_cell v1.21.1 -> v1.21.3 Updating parking_lot v0.12.3 -> v0.12.4 Updating parking_lot_core v0.9.10 -> v0.9.11 Updating portable-atomic v1.11.0 -> v1.11.1 Adding potential_utf v0.1.2 Updating proc-macro2 v1.0.94 -> v1.0.95 Updating redox_syscall v0.5.10 -> v0.5.13 Updating rustc-demangle v0.1.24 -> v0.1.25 Updating rustc_apfloat v0.2.2+llvm-462a31f5a5ab -> v0.2.3+llvm-462a31f5a5ab Updating serde_spanned v0.6.8 -> v0.6.9 Updating smallvec v1.14.0 -> v1.15.1 Updating syn v2.0.100 -> v2.0.103 Updating synstructure v0.13.1 -> v0.13.2 Updating tenthash v1.0.0 -> v1.1.0 Updating thread_local v1.1.8 -> v1.1.9 Updating time v0.3.40 -> v0.3.41 Updating time-macros v0.2.21 -> v0.2.22 Updating tinystr v0.7.6 -> v0.8.1 Updating toml v0.8.20 -> v0.8.23 Updating toml_datetime v0.6.8 -> v0.6.11 Updating toml_edit v0.22.24 -> v0.22.27 Adding toml_write v0.1.2 Updating tracing-attributes v0.1.28 -> v0.1.29 Updating tracing-core v0.1.33 -> v0.1.34 Removing utf16_iter v1.0.5 Updating wasi v0.11.0+wasi-snapshot-preview1 -> v0.11.1+wasi-snapshot-preview1 Updating windows v0.61.1 -> v0.61.3 Updating windows-core v0.61.0 -> v0.61.2 Updating windows-future v0.2.0 -> v0.2.1 Updating windows-link v0.1.1 -> v0.1.3 Updating windows-result v0.3.2 -> v0.3.4 Updating windows-strings v0.4.0 -> v0.4.2 Adding windows-sys v0.60.2 Updating windows-targets v0.53.0 -> v0.53.2 Adding windows-threading v0.1.0 Updating winnow v0.7.3 -> v0.7.11 Removing write16 v1.0.0 Updating writeable v0.5.5 -> v0.6.1 Updating yoke v0.7.5 -> v0.8.0 Updating yoke-derive v0.7.5 -> v0.8.0 Adding zerotrie v0.2.2 Updating zerovec v0.10.4 -> v0.11.2 Updating zerovec-derive v0.10.3 -> v0.11.1 --- src/tools/rust-analyzer/Cargo.lock | 413 +++++++++++++++-------------- 1 file changed, 207 insertions(+), 206 deletions(-) diff --git a/src/tools/rust-analyzer/Cargo.lock b/src/tools/rust-analyzer/Cargo.lock index 01de430925dca..a7c8ea4a00fe0 100644 --- a/src/tools/rust-analyzer/Cargo.lock +++ b/src/tools/rust-analyzer/Cargo.lock @@ -13,9 +13,9 @@ dependencies = [ [[package]] name = "adler2" -version = "2.0.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" [[package]] name = "allocator-api2" @@ -25,9 +25,9 @@ checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" [[package]] name = "anyhow" -version = "1.0.97" +version = "1.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcfed56ad506cb2c684a14971b8861fdc3baaaae314b9e5f9bb532cbe3ba7a4f" +checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" [[package]] name = "arbitrary" @@ -100,30 +100,30 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.9.0" +version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" +checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" [[package]] name = "borsh" -version = "1.5.5" +version = "1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5430e3be710b68d984d1391c854eb431a9d548640711faa54eecb1df93db91cc" +checksum = "ad8646f98db542e39fc66e68a20b2144f6a732636df7c2354e74645faaa433ce" dependencies = [ "cfg_aliases", ] [[package]] name = "boxcar" -version = "0.2.12" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66bb12751a83493ef4b8da1120451a262554e216a247f14b48cb5e8fe7ed8bdf" +checksum = "26c4925bc979b677330a8c7fe7a8c94af2dbb4a2d37b4a20a80d884400f46baa" [[package]] name = "camino" -version = "1.1.9" +version = "1.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b96ec4966b5813e2c0507c1f86115c8c5abaadc3980879c3424042a02fd1ad3" +checksum = "0da45bc31171d8d6960122e222a67740df867c1dd53b4d51caa297084c185cab" dependencies = [ "serde", ] @@ -153,9 +153,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.16" +version = "1.2.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be714c154be609ec7f5dad223a33bf1482fff90472de28f7362806e6d4832b8c" +checksum = "956a5e21988b87f372569b66183b78babf23ebc2e744b733e4350a752c4dafac" dependencies = [ "shlex", ] @@ -178,9 +178,9 @@ dependencies = [ [[package]] name = "cfg-if" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" [[package]] name = "cfg_aliases" @@ -206,7 +206,7 @@ version = "0.102.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72f0a61621a088af69fee8df39ec63cf5b6d0b9ab663a740cdeb376aabf2f244" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "chalk-derive", ] @@ -374,7 +374,7 @@ dependencies = [ "libc", "option-ext", "redox_users", - "windows-sys 0.59.0", + "windows-sys 0.60.2", ] [[package]] @@ -461,9 +461,9 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" [[package]] name = "flate2" -version = "1.1.1" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ced92e76e966ca2fd84c8f7aa01a4aea65b0eb6648d72f7c8f3e2764a67fece" +checksum = "4a3d7db9596fecd151c5f638c0ee5d5bd487b6e0ea232e5dc96d5250f6f94b1d" dependencies = [ "crc32fast", "miniz_oxide", @@ -471,9 +471,9 @@ dependencies = [ [[package]] name = "foldhash" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0d2fde1f7b3d48b8395d5f2de76c18a528bd6a9cdde438df747bfcba3e05d6f" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" [[package]] name = "form_urlencoded" @@ -501,9 +501,9 @@ checksum = "7ab85b9b05e3978cc9a9cf8fea7f01b494e1a09ed3037e16ba39edc7a29eb61a" [[package]] name = "getrandom" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" dependencies = [ "cfg-if", "libc", @@ -524,9 +524,9 @@ checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" [[package]] name = "hashbrown" -version = "0.15.2" +version = "0.15.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" +checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5" dependencies = [ "allocator-api2", "equivalent", @@ -539,7 +539,7 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7382cf6263419f2d8df38c55d7da83da5c18aef87fc7a7fc1fb1e344edfe14c1" dependencies = [ - "hashbrown 0.15.2", + "hashbrown 0.15.4", ] [[package]] @@ -550,9 +550,9 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "hermit-abi" -version = "0.3.9" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" +checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" [[package]] name = "hir" @@ -588,7 +588,7 @@ version = "0.0.0" dependencies = [ "arrayvec", "base-db", - "bitflags 2.9.0", + "bitflags 2.9.1", "cfg", "cov-mark", "drop_bomb", @@ -655,7 +655,7 @@ version = "0.0.0" dependencies = [ "arrayvec", "base-db", - "bitflags 2.9.0", + "bitflags 2.9.1", "chalk-derive", "chalk-ir", "chalk-recursive", @@ -705,21 +705,22 @@ dependencies = [ [[package]] name = "icu_collections" -version = "1.5.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" +checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47" dependencies = [ "displaydoc", + "potential_utf", "yoke", "zerofrom", "zerovec", ] [[package]] -name = "icu_locid" -version = "1.5.0" +name = "icu_locale_core" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" +checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a" dependencies = [ "displaydoc", "litemap", @@ -728,31 +729,11 @@ dependencies = [ "zerovec", ] -[[package]] -name = "icu_locid_transform" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" -dependencies = [ - "displaydoc", - "icu_locid", - "icu_locid_transform_data", - "icu_provider", - "tinystr", - "zerovec", -] - -[[package]] -name = "icu_locid_transform_data" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" - [[package]] name = "icu_normalizer" -version = "1.5.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" +checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979" dependencies = [ "displaydoc", "icu_collections", @@ -760,67 +741,54 @@ dependencies = [ "icu_properties", "icu_provider", "smallvec", - "utf16_iter", - "utf8_iter", - "write16", "zerovec", ] [[package]] name = "icu_normalizer_data" -version = "1.5.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" +checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3" [[package]] name = "icu_properties" -version = "1.5.1" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" +checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b" dependencies = [ "displaydoc", "icu_collections", - "icu_locid_transform", + "icu_locale_core", "icu_properties_data", "icu_provider", - "tinystr", + "potential_utf", + "zerotrie", "zerovec", ] [[package]] name = "icu_properties_data" -version = "1.5.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" +checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632" [[package]] name = "icu_provider" -version = "1.5.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" +checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af" dependencies = [ "displaydoc", - "icu_locid", - "icu_provider_macros", + "icu_locale_core", "stable_deref_trait", "tinystr", "writeable", "yoke", "zerofrom", + "zerotrie", "zerovec", ] -[[package]] -name = "icu_provider_macros" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "ide" version = "0.0.0" @@ -898,7 +866,7 @@ version = "0.0.0" dependencies = [ "arrayvec", "base-db", - "bitflags 2.9.0", + "bitflags 2.9.1", "cov-mark", "crossbeam-channel", "either", @@ -976,9 +944,9 @@ dependencies = [ [[package]] name = "idna_adapter" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" +checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" dependencies = [ "icu_normalizer", "icu_properties", @@ -991,7 +959,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e" dependencies = [ "equivalent", - "hashbrown 0.15.2", + "hashbrown 0.15.4", "serde", ] @@ -1001,7 +969,7 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f37dccff2791ab604f9babef0ba14fbe0be30bd368dc541e2b08d07c8aa908f3" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "inotify-sys", "libc", ] @@ -1057,9 +1025,9 @@ checksum = "a037eddb7d28de1d0fc42411f501b53b75838d313908078d6698d064f3029b24" [[package]] name = "kqueue" -version = "1.0.8" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7447f1ca1b7b563588a205fe93dea8df60fd981423a768bc1c0ded35ed147d0c" +checksum = "eac30106d7dce88daf4a3fcb4879ea939476d5074a9b7ddd0fb97fa4bed5596a" dependencies = [ "kqueue-sys", "libc", @@ -1099,19 +1067,19 @@ checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" [[package]] name = "libloading" -version = "0.8.7" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a793df0d7afeac54f95b471d3af7f0d4fb975699f972341a4b76988d49cdf0c" +checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667" dependencies = [ "cfg-if", - "windows-targets 0.53.0", + "windows-targets 0.53.2", ] [[package]] name = "libmimalloc-sys" -version = "0.1.40" +version = "0.1.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07d0e07885d6a754b9c7993f2625187ad694ee985d60f23355ff0e7077261502" +checksum = "ec9d6fac27761dabcd4ee73571cdb06b7022dc99089acbe5435691edffaac0f4" dependencies = [ "cc", "libc", @@ -1123,7 +1091,7 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "libc", "redox_syscall", ] @@ -1149,9 +1117,9 @@ dependencies = [ [[package]] name = "litemap" -version = "0.7.5" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23fb14cb19457329c82206317a5663005a4d404783dc74f4252769b0d5f42856" +checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" [[package]] name = "load-cargo" @@ -1174,9 +1142,9 @@ dependencies = [ [[package]] name = "lock_api" -version = "0.4.12" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765" dependencies = [ "autocfg", "scopeguard", @@ -1184,9 +1152,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.26" +version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30bde2b3dc3671ae49d8e2e9f044c7c005836e7a023ee57cffa25ab82764bb9e" +checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" [[package]] name = "lsp-server" @@ -1249,9 +1217,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.7.4" +version = "2.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" [[package]] name = "memmap2" @@ -1273,32 +1241,32 @@ dependencies = [ [[package]] name = "mimalloc" -version = "0.1.44" +version = "0.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99585191385958383e13f6b822e6b6d8d9cf928e7d286ceb092da92b43c87bc1" +checksum = "995942f432bbb4822a7e9c3faa87a695185b0d09273ba85f097b54f4e458f2af" dependencies = [ "libmimalloc-sys", ] [[package]] name = "miniz_oxide" -version = "0.8.5" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e3e04debbb59698c15bacbb6d93584a8c0ca9cc3213cb423d31f760d8843ce5" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" dependencies = [ "adler2", ] [[package]] name = "mio" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" +checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" dependencies = [ "libc", "log", "wasi", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -1316,7 +1284,7 @@ version = "0.30.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "cfg-if", "cfg_aliases", "libc", @@ -1334,7 +1302,7 @@ version = "8.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2fee8403b3d66ac7b26aee6e40a897d85dc5ce26f44da36b8b73e987cc52e943" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "filetime", "fsevent-sys", "inotify", @@ -1370,9 +1338,9 @@ checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" [[package]] name = "num_cpus" -version = "1.16.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +checksum = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b" dependencies = [ "hermit-abi", "libc", @@ -1398,9 +1366,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.21.1" +version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d75b0bedcc4fe52caa0e03d9f1151a323e4aa5e2d78ba3580400cd3c9e2bc4bc" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" [[package]] name = "oorandom" @@ -1416,9 +1384,9 @@ checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" [[package]] name = "parking_lot" -version = "0.12.3" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13" dependencies = [ "lock_api", "parking_lot_core", @@ -1426,9 +1394,9 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.10" +version = "0.9.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" dependencies = [ "cfg-if", "libc", @@ -1506,9 +1474,18 @@ checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" [[package]] name = "portable-atomic" -version = "1.11.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "350e9b48cbc6b0e028b0473b114454c6316e57336ee184ceab6e53f72c178b3e" +checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" + +[[package]] +name = "potential_utf" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5a7c30837279ca13e7c867e9e40053bc68740f988cb07f7ca6df43cc734b585" +dependencies = [ + "zerovec", +] [[package]] name = "powerfmt" @@ -1569,9 +1546,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.94" +version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84" +checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" dependencies = [ "unicode-ident", ] @@ -1650,7 +1627,7 @@ version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57206b407293d2bcd3af849ce869d52068623f19e1b5ff8e8778e3309439682b" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "memchr", "unicase", ] @@ -1691,7 +1668,7 @@ version = "0.113.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c33b8fa229789975647ca5426be432c7c327ebde89ab15889928185dbcee3230" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "ra-ap-rustc_hashes", "ra-ap-rustc_index", "tracing", @@ -1783,11 +1760,11 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.10" +version = "0.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b8c0c260b63a8219631167be35e6a988e9554dbd323f8bd08439c8ed1302bd1" +checksum = "0d04b7d0ee6b4a0207a0a7adb104d23ecb0b47d6beae7152d0fa34b692b29fd6" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", ] [[package]] @@ -1881,9 +1858,9 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.24" +version = "0.1.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" +checksum = "989e6739f80c4ad5b13e0fd7fe89531180375b18520cc8c82080e4dc4035b84f" [[package]] name = "rustc-hash" @@ -1911,11 +1888,11 @@ checksum = "781442f29170c5c93b7185ad559492601acdc71d5bb0706f5868094f45cfcd08" [[package]] name = "rustc_apfloat" -version = "0.2.2+llvm-462a31f5a5ab" +version = "0.2.3+llvm-462a31f5a5ab" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "121e2195ff969977a4e2b5c9965ea867fce7e4cb5aee5b09dee698a7932d574f" +checksum = "486c2179b4796f65bfe2ee33679acf0927ac83ecf583ad6c91c3b4570911b9ad" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "smallvec", ] @@ -1934,7 +1911,7 @@ dependencies = [ "boxcar", "crossbeam-queue", "dashmap", - "hashbrown 0.15.2", + "hashbrown 0.15.4", "hashlink", "indexmap", "parking_lot", @@ -2052,9 +2029,9 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "0.6.8" +version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" +checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3" dependencies = [ "serde", ] @@ -2076,9 +2053,9 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "smallvec" -version = "1.14.0" +version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcf8323ef1faaee30a44a340193b1ac6814fd9b7b4e88e9d4519a3e4abe1cfd" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" [[package]] name = "smol_str" @@ -2127,9 +2104,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.100" +version = "2.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0" +checksum = "e4307e30089d6fd6aff212f2da3a1f9e32f3223b1f010fb09b7c95f90f3ca1e8" dependencies = [ "proc-macro2", "quote", @@ -2138,9 +2115,9 @@ dependencies = [ [[package]] name = "synstructure" -version = "0.13.1" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", @@ -2183,9 +2160,9 @@ dependencies = [ [[package]] name = "tenthash" -version = "1.0.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d092d622df8bb64e5de8dc86a3667702d5f1e0fe2f0604c6035540703c8cd1e" +checksum = "e5c4bcc0a4fa333239f43662d15fbf995f384b2aeaf89c4ab4c83353d6cbb952" [[package]] name = "test-fixture" @@ -2270,12 +2247,11 @@ dependencies = [ [[package]] name = "thread_local" -version = "1.1.8" +version = "1.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" +checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" dependencies = [ "cfg-if", - "once_cell", ] [[package]] @@ -2311,9 +2287,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.40" +version = "0.3.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d9c75b47bdff86fa3334a3db91356b8d7d86a9b839dab7d0bdc5c3d3a077618" +checksum = "8a7619e19bc266e0f9c5e6686659d394bc57973859340060a69221e57dbc0c40" dependencies = [ "deranged", "itoa", @@ -2334,9 +2310,9 @@ checksum = "c9e9a38711f559d9e3ce1cdb06dd7c5b8ea546bc90052da6d06bb76da74bb07c" [[package]] name = "time-macros" -version = "0.2.21" +version = "0.2.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29aa485584182073ed57fd5004aa09c371f021325014694e432313345865fd04" +checksum = "3526739392ec93fd8b359c8e98514cb3e8e021beb4e5f597b00a0221f8ed8a49" dependencies = [ "num-conv", "time-core", @@ -2344,9 +2320,9 @@ dependencies = [ [[package]] name = "tinystr" -version = "0.7.6" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" +checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b" dependencies = [ "displaydoc", "zerovec", @@ -2354,9 +2330,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.20" +version = "0.8.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd87a5cdd6ffab733b2f74bc4fd7ee5fff6634124999ac278c35fc78c6120148" +checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" dependencies = [ "serde", "serde_spanned", @@ -2366,26 +2342,33 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.6.8" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" +checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" dependencies = [ "serde", ] [[package]] name = "toml_edit" -version = "0.22.24" +version = "0.22.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17b4795ff5edd201c7cd6dca065ae59972ce77d1b80fa0a84d94950ece7d1474" +checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" dependencies = [ "indexmap", "serde", "serde_spanned", "toml_datetime", + "toml_write", "winnow", ] +[[package]] +name = "toml_write" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" + [[package]] name = "toolchain" version = "0.0.0" @@ -2407,9 +2390,9 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.28" +version = "0.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" +checksum = "1b1ffbcf9c6f6b99d386e7444eb608ba646ae452a36b39737deb9663b610f662" dependencies = [ "proc-macro2", "quote", @@ -2418,9 +2401,9 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.33" +version = "0.1.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" +checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" dependencies = [ "once_cell", "valuable", @@ -2527,12 +2510,6 @@ dependencies = [ "serde", ] -[[package]] -name = "utf16_iter" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" - [[package]] name = "utf8_iter" version = "1.0.4" @@ -2586,9 +2563,9 @@ dependencies = [ [[package]] name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" +version = "0.11.1+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] name = "winapi-util" @@ -2601,9 +2578,9 @@ dependencies = [ [[package]] name = "windows" -version = "0.61.1" +version = "0.61.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5ee8f3d025738cb02bad7868bbb5f8a6327501e870bf51f1b455b0a2454a419" +checksum = "9babd3a767a4c1aef6900409f85f5d53ce2544ccdfaa86dad48c91782c6d6893" dependencies = [ "windows-collections", "windows-core", @@ -2623,9 +2600,9 @@ dependencies = [ [[package]] name = "windows-core" -version = "0.61.0" +version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4763c1de310c86d75a878046489e2e5ba02c649d185f21c67d4cf8a56d098980" +checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" dependencies = [ "windows-implement", "windows-interface", @@ -2636,12 +2613,13 @@ dependencies = [ [[package]] name = "windows-future" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a1d6bbefcb7b60acd19828e1bc965da6fcf18a7e39490c5f8be71e54a19ba32" +checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e" dependencies = [ "windows-core", "windows-link", + "windows-threading", ] [[package]] @@ -2668,9 +2646,9 @@ dependencies = [ [[package]] name = "windows-link" -version = "0.1.1" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38" +checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" [[package]] name = "windows-numerics" @@ -2684,18 +2662,18 @@ dependencies = [ [[package]] name = "windows-result" -version = "0.3.2" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c64fd11a4fd95df68efcfee5f44a294fe71b8bc6a91993e2791938abcc712252" +checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" dependencies = [ "windows-link", ] [[package]] name = "windows-strings" -version = "0.4.0" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a2ba9642430ee452d5a7aa78d72907ebe8cfda358e8cb7918a2050581322f97" +checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" dependencies = [ "windows-link", ] @@ -2727,6 +2705,15 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets 0.53.2", +] + [[package]] name = "windows-targets" version = "0.48.5" @@ -2760,9 +2747,9 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.53.0" +version = "0.53.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1e4c7e8ceaaf9cb7d7507c974735728ab453b67ef8f18febdd7c11fe59dca8b" +checksum = "c66f69fcc9ce11da9966ddb31a40968cad001c5bedeb5c2b82ede4253ab48aef" dependencies = [ "windows_aarch64_gnullvm 0.53.0", "windows_aarch64_msvc 0.53.0", @@ -2774,6 +2761,15 @@ dependencies = [ "windows_x86_64_msvc 0.53.0", ] +[[package]] +name = "windows-threading" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b66463ad2e0ea3bbf808b7f1d371311c80e115c0b71d60efc142cafbcfb057a6" +dependencies = [ + "windows-link", +] + [[package]] name = "windows_aarch64_gnullvm" version = "0.48.5" @@ -2914,9 +2910,9 @@ checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" [[package]] name = "winnow" -version = "0.7.3" +version = "0.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e7f4ea97f6f78012141bcdb6a216b2609f0979ada50b20ca5b52dde2eac2bb1" +checksum = "74c7b26e3480b707944fc872477815d29a8e429d2f93a1ce000f5fa84a15cbcd" dependencies = [ "memchr", ] @@ -2927,17 +2923,11 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23f6174b2566cc4a74f95e1367ec343e7fa80c93cc8087f5c4a3d6a1088b2118" -[[package]] -name = "write16" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" - [[package]] name = "writeable" -version = "0.5.5" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" +checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" [[package]] name = "xflags" @@ -2992,9 +2982,9 @@ dependencies = [ [[package]] name = "yoke" -version = "0.7.5" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" +checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc" dependencies = [ "serde", "stable_deref_trait", @@ -3004,9 +2994,9 @@ dependencies = [ [[package]] name = "yoke-derive" -version = "0.7.5" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" +checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" dependencies = [ "proc-macro2", "quote", @@ -3035,11 +3025,22 @@ dependencies = [ "synstructure", ] +[[package]] +name = "zerotrie" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", +] + [[package]] name = "zerovec" -version = "0.10.4" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" +checksum = "4a05eb080e015ba39cc9e23bbe5e7fb04d5fb040350f99f34e338d5fdd294428" dependencies = [ "yoke", "zerofrom", @@ -3048,9 +3049,9 @@ dependencies = [ [[package]] name = "zerovec-derive" -version = "0.10.3" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" +checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" dependencies = [ "proc-macro2", "quote", From 05b7cdcf8e74c45ef3fc1a21557044fd539f8c76 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Fri, 13 Jun 2025 10:08:20 +0200 Subject: [PATCH 34/56] `cargo upgrade` --- src/tools/rust-analyzer/Cargo.lock | 159 ++++++++++++++---- src/tools/rust-analyzer/Cargo.toml | 42 ++--- .../rust-analyzer/crates/hir-def/Cargo.toml | 2 +- .../crates/hir-def/src/lang_item.rs | 1 + .../rust-analyzer/crates/hir-ty/Cargo.toml | 2 +- .../crates/hir-ty/src/chalk_db.rs | 14 +- .../rust-analyzer/crates/ide-db/Cargo.toml | 2 +- src/tools/rust-analyzer/crates/ide/Cargo.toml | 2 +- .../crates/intern/src/symbol/symbols.rs | 1 + .../proc-macro-srv/proc-macro-test/Cargo.toml | 2 +- .../rust-analyzer/crates/profile/Cargo.toml | 4 +- .../project-model/src/cargo_workspace.rs | 8 +- .../crates/project-model/src/sysroot.rs | 2 +- .../crates/rust-analyzer/Cargo.toml | 14 +- .../rust-analyzer/crates/stdx/Cargo.toml | 4 +- .../rust-analyzer/crates/syntax/Cargo.toml | 2 +- .../rust-analyzer/lib/lsp-server/Cargo.toml | 4 +- .../rust-analyzer/lib/lsp-server/src/msg.rs | 4 +- .../rust-analyzer/lib/lsp-server/src/stdio.rs | 2 +- src/tools/rust-analyzer/xtask/Cargo.toml | 6 +- 20 files changed, 189 insertions(+), 88 deletions(-) diff --git a/src/tools/rust-analyzer/Cargo.lock b/src/tools/rust-analyzer/Cargo.lock index a7c8ea4a00fe0..c2b4e21483e7a 100644 --- a/src/tools/rust-analyzer/Cargo.lock +++ b/src/tools/rust-analyzer/Cargo.lock @@ -60,7 +60,7 @@ dependencies = [ "cfg-if", "libc", "miniz_oxide", - "object", + "object 0.36.7", "rustc-demangle", "windows-targets 0.52.6", ] @@ -130,21 +130,38 @@ dependencies = [ [[package]] name = "cargo-platform" -version = "0.1.9" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e35af189006b9c0f00a064685c727031e3ed2d8020f7ba284d78cc2671bd36ea" +checksum = "84982c6c0ae343635a3a4ee6dedef965513735c8b183caa7289fa6e27399ebd4" dependencies = [ "serde", ] +[[package]] +name = "cargo-util-schemas" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e63d2780ac94487eb9f1fea7b0d56300abc9eb488800854ca217f102f5caccca" +dependencies = [ + "semver", + "serde", + "serde-untagged", + "serde-value", + "thiserror 1.0.69", + "toml", + "unicode-xid", + "url", +] + [[package]] name = "cargo_metadata" -version = "0.19.2" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd5eb614ed4c27c5d706420e4320fbe3216ab31fa1c33cd8246ac36dae4479ba" +checksum = "4f7835cfc6135093070e95eb2b53e5d9b5c403dc3a6be6040ee026270aa82502" dependencies = [ "camino", "cargo-platform", + "cargo-util-schemas", "semver", "serde", "serde_json", @@ -190,9 +207,9 @@ checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] name = "chalk-derive" -version = "0.102.0" +version = "0.103.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "feb14e3ff0ebac26d8e58b6ed1417afb60c4a0a44b6425546ee7eb9c75ebb336" +checksum = "eb4899682de915ca7c0b025bdd0a3d34c75fe12184122fda6805a7baddaa293c" dependencies = [ "proc-macro2", "quote", @@ -202,9 +219,9 @@ dependencies = [ [[package]] name = "chalk-ir" -version = "0.102.0" +version = "0.103.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72f0a61621a088af69fee8df39ec63cf5b6d0b9ab663a740cdeb376aabf2f244" +checksum = "90a37d2ab99352b4caca135061e7b4ac67024b648c28ed0b787feec4bea4caed" dependencies = [ "bitflags 2.9.1", "chalk-derive", @@ -212,9 +229,9 @@ dependencies = [ [[package]] name = "chalk-recursive" -version = "0.102.0" +version = "0.103.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbd3415cc540015533aa4a8ad007696d585dd9c5f81e7c099872f1dd4bf14894" +checksum = "c855be60e646664bc37c2496d3dc81ca5ef60520930e5e0f0057a0575aff6c19" dependencies = [ "chalk-derive", "chalk-ir", @@ -225,9 +242,9 @@ dependencies = [ [[package]] name = "chalk-solve" -version = "0.102.0" +version = "0.103.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "747707b0c082b3ecf4b1ae28d0d8df708a46cddd22a386f9cc85a312a4de25ff" +checksum = "477ac6cdfd2013e9f93b09b036c2b607a67b2e728f4777b8422d55a79e9e3a34" dependencies = [ "chalk-derive", "chalk-ir", @@ -431,6 +448,16 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" +[[package]] +name = "erased-serde" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e004d887f51fcb9fef17317a2f3525c887d8aa3f4f50fed920816a688284a5b7" +dependencies = [ + "serde", + "typeid", +] + [[package]] name = "expect-test" version = "1.5.1" @@ -1336,6 +1363,15 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + [[package]] name = "num_cpus" version = "1.17.0" @@ -1364,6 +1400,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "object" +version = "0.37.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03fd943161069e1768b4b3d050890ba48730e590f57e56d4aa04e7e090e61b4a" +dependencies = [ + "memchr", +] + [[package]] name = "once_cell" version = "1.21.3" @@ -1382,6 +1427,15 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" +[[package]] +name = "ordered-float" +version = "2.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68f19d67e5a2795c94e73e0bb1cc1a7edeb2e28efd39e2e1c9b7a40c1108b11c" +dependencies = [ + "num-traits", +] + [[package]] name = "parking_lot" version = "0.12.4" @@ -1413,7 +1467,7 @@ dependencies = [ "edition", "expect-test", "ra-ap-rustc_lexer", - "rustc-literal-escaper", + "rustc-literal-escaper 0.0.3", "stdx", "tracing", ] @@ -1519,7 +1573,7 @@ dependencies = [ "libc", "libloading", "memmap2", - "object", + "object 0.37.1", "paths", "proc-macro-test", "ra-ap-rustc_lexer", @@ -1573,7 +1627,7 @@ dependencies = [ "libc", "perf-event", "tikv-jemalloc-ctl", - "windows-sys 0.59.0", + "windows-sys 0.60.2", ] [[package]] @@ -1664,9 +1718,9 @@ dependencies = [ [[package]] name = "ra-ap-rustc_abi" -version = "0.113.0" +version = "0.116.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c33b8fa229789975647ca5426be432c7c327ebde89ab15889928185dbcee3230" +checksum = "a967e3a9cd3e38b543f503978e0eccee461e3aea3f7b10e944959bff41dbe612" dependencies = [ "bitflags 2.9.1", "ra-ap-rustc_hashes", @@ -1676,18 +1730,18 @@ dependencies = [ [[package]] name = "ra-ap-rustc_hashes" -version = "0.113.0" +version = "0.116.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d68a3e389927002f552938a90b04787f6435f55b46fc5691360470d1cb2e99d" +checksum = "1ea4c755ecbbffa5743c251344f484ebe571ec7bc5b36d80b2a8ae775d1a7a40" dependencies = [ "rustc-stable-hash", ] [[package]] name = "ra-ap-rustc_index" -version = "0.113.0" +version = "0.116.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32502273df2838d0ca13f1c67e2a48feef940e591f9771869f07e2db2acede53" +checksum = "aca7ad7cf911538c619caa2162339fe98637e9e46f11bb0484ef96735df4d64a" dependencies = [ "ra-ap-rustc_index_macros", "smallvec", @@ -1695,9 +1749,9 @@ dependencies = [ [[package]] name = "ra-ap-rustc_index_macros" -version = "0.113.0" +version = "0.116.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a32f081864ae34c7ae6634edfa7a95ab9260ba85015e8b1d347580eda79d14f" +checksum = "8767ba551c9355bc3031be072cc4bb0381106e5e7cd275e72b7a8c76051c4070" dependencies = [ "proc-macro2", "quote", @@ -1706,9 +1760,9 @@ dependencies = [ [[package]] name = "ra-ap-rustc_lexer" -version = "0.113.0" +version = "0.116.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed34c51974718c5bd90d876d1364d9725159fc8030c2382b9cb837034152ed68" +checksum = "6101374afb267e6c27e4e2eb0b1352e9f3504c1a8f716f619cd39244e2ed92ab" dependencies = [ "memchr", "unicode-properties", @@ -1717,19 +1771,19 @@ dependencies = [ [[package]] name = "ra-ap-rustc_parse_format" -version = "0.113.0" +version = "0.116.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff0440e5d27facbf4ff13ea651e48c2f6e360b3dbfc56251b41d60719b965fb8" +checksum = "ecd88a19f00da4f43e6727d5013444cbc399804b5046dfa2bbcd28ebed3970ce" dependencies = [ "ra-ap-rustc_lexer", - "rustc-literal-escaper", + "rustc-literal-escaper 0.0.2", ] [[package]] name = "ra-ap-rustc_pattern_analysis" -version = "0.113.0" +version = "0.116.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6056efa57aba3aa0cc69a0bf1a8281624c23ad25b05748d11ebcd4668037bfc" +checksum = "bb332dd32d7850a799862533b1c021e6062558861a4ad57817bf522499fbb892" dependencies = [ "ra-ap-rustc_index", "rustc-hash 2.1.1", @@ -1851,7 +1905,7 @@ dependencies = [ "vfs", "vfs-notify", "walkdir", - "windows-sys 0.59.0", + "windows-sys 0.60.2", "xflags", "xshell", ] @@ -1880,6 +1934,12 @@ version = "0.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0041b6238913c41fe704213a4a9329e2f685a156d1781998128b4149c230ad04" +[[package]] +name = "rustc-literal-escaper" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78744cd17f5d01c75b709e49807d1363e02a940ccee2e9e72435843fdb0d076e" + [[package]] name = "rustc-stable-hash" version = "0.1.2" @@ -1992,6 +2052,27 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "serde-untagged" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "299d9c19d7d466db4ab10addd5703e4c615dec2a5a16dbbafe191045e87ee66e" +dependencies = [ + "erased-serde", + "serde", + "typeid", +] + +[[package]] +name = "serde-value" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3a1a3341211875ef120e117ea7fd5228530ae7e7036a779fdc9117be6b3282c" +dependencies = [ + "ordered-float", + "serde", +] + [[package]] name = "serde_derive" version = "1.0.219" @@ -2099,7 +2180,7 @@ dependencies = [ "libc", "miow", "tracing", - "windows-sys 0.59.0", + "windows-sys 0.60.2", ] [[package]] @@ -2135,7 +2216,7 @@ dependencies = [ "rayon", "rowan", "rustc-hash 2.1.1", - "rustc-literal-escaper", + "rustc-literal-escaper 0.0.3", "rustc_apfloat", "smol_str", "stdx", @@ -2468,6 +2549,12 @@ version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6af6ae20167a9ece4bcb41af5b80f8a1f1df981f6391189ce00fd257af04126a" +[[package]] +name = "typeid" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc7d623258602320d5c55d1bc22793b57daff0ec7efc270ea7d55ce1d5f5471c" + [[package]] name = "ungrammar" version = "1.16.1" @@ -3060,9 +3147,9 @@ dependencies = [ [[package]] name = "zip" -version = "3.0.0" +version = "4.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12598812502ed0105f607f941c386f43d441e00148fce9dec3ca5ffb0bde9308" +checksum = "153a6fff49d264c4babdcfa6b4d534747f520e56e8f0f384f3b808c4b64cc1fd" dependencies = [ "arbitrary", "crc32fast", diff --git a/src/tools/rust-analyzer/Cargo.toml b/src/tools/rust-analyzer/Cargo.toml index 975fe277b2208..c5f061cad7d1d 100644 --- a/src/tools/rust-analyzer/Cargo.toml +++ b/src/tools/rust-analyzer/Cargo.toml @@ -87,11 +87,11 @@ vfs-notify = { path = "./crates/vfs-notify", version = "0.0.0" } vfs = { path = "./crates/vfs", version = "0.0.0" } edition = { path = "./crates/edition", version = "0.0.0" } -ra-ap-rustc_lexer = { version = "0.113", default-features = false } -ra-ap-rustc_parse_format = { version = "0.113", default-features = false } -ra-ap-rustc_index = { version = "0.113", default-features = false } -ra-ap-rustc_abi = { version = "0.113", default-features = false } -ra-ap-rustc_pattern_analysis = { version = "0.113", default-features = false } +ra-ap-rustc_lexer = { version = "0.116", default-features = false } +ra-ap-rustc_parse_format = { version = "0.116", default-features = false } +ra-ap-rustc_index = { version = "0.116", default-features = false } +ra-ap-rustc_abi = { version = "0.116", default-features = false } +ra-ap-rustc_pattern_analysis = { version = "0.116", default-features = false } # local crates that aren't published to crates.io. These should not have versions. @@ -101,35 +101,35 @@ la-arena = { version = "0.3.1" } lsp-server = { version = "0.7.8" } # non-local crates -anyhow = "1.0.97" +anyhow = "1.0.98" arrayvec = "0.7.6" -bitflags = "2.9.0" -cargo_metadata = "0.19.2" -camino = "1.1.9" -chalk-solve = { version = "0.102.0", default-features = false } -chalk-ir = "0.102.0" -chalk-recursive = { version = "0.102.0", default-features = false } -chalk-derive = "0.102.0" +bitflags = "2.9.1" +cargo_metadata = "0.20.0" +camino = "1.1.10" +chalk-solve = { version = "0.103.0", default-features = false } +chalk-ir = "0.103.0" +chalk-recursive = { version = "0.103.0", default-features = false } +chalk-derive = "0.103.0" crossbeam-channel = "0.5.15" dissimilar = "1.0.10" dot = "0.1.4" either = "1.15.0" expect-test = "1.5.1" -indexmap = { version = "2.8.0", features = ["serde"] } +indexmap = { version = "2.9.0", features = ["serde"] } itertools = "0.14.0" -libc = "0.2.171" -libloading = "0.8.6" +libc = "0.2.172" +libloading = "0.8.8" memmap2 = "0.9.5" nohash-hasher = "0.2.0" oorandom = "11.1.5" -object = { version = "0.36.7", default-features = false, features = [ +object = { version = "0.37.1", default-features = false, features = [ "std", "read_core", "elf", "macho", "pe", ] } -process-wrap = { version = "8.2.0", features = ["std"] } +process-wrap = { version = "8.2.1", features = ["std"] } pulldown-cmark-to-cmark = "10.0.4" pulldown-cmark = { version = "0.9.6", default-features = false } rayon = "1.10.0" @@ -141,8 +141,8 @@ serde = { version = "1.0.219" } serde_derive = { version = "1.0.219" } serde_json = "1.0.140" rustc-hash = "2.1.1" -rustc-literal-escaper = "0.0.2" -smallvec = { version = "1.14.0", features = [ +rustc-literal-escaper = "0.0.3" +smallvec = { version = "1.15.1", features = [ "const_new", "union", "const_generics", @@ -166,7 +166,7 @@ xshell = "0.2.7" # We need to freeze the version of the crate, as the raw-api feature is considered unstable dashmap = { version = "=6.1.0", features = ["raw-api", "inline"] } # We need to freeze the version of the crate, as it needs to match with dashmap -hashbrown = { version = "0.14.0", features = [ +hashbrown = { version = "0.14.*", features = [ "inline-more", ], default-features = false } diff --git a/src/tools/rust-analyzer/crates/hir-def/Cargo.toml b/src/tools/rust-analyzer/crates/hir-def/Cargo.toml index c1c89e8d1cc3a..c6922eca49f27 100644 --- a/src/tools/rust-analyzer/crates/hir-def/Cargo.toml +++ b/src/tools/rust-analyzer/crates/hir-def/Cargo.toml @@ -25,7 +25,7 @@ rustc-hash.workspace = true tracing.workspace = true smallvec.workspace = true triomphe.workspace = true -rustc_apfloat = "0.2.2" +rustc_apfloat = "0.2.3" text-size.workspace = true salsa.workspace = true salsa-macros.workspace = true diff --git a/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs b/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs index 1614ef0da435c..8f071cd953a9c 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs @@ -377,6 +377,7 @@ language_item_table! { AsyncFnMut, sym::async_fn_mut, async_fn_mut_trait, Target::Trait, GenericRequirement::Exact(1); AsyncFnOnce, sym::async_fn_once, async_fn_once_trait, Target::Trait, GenericRequirement::Exact(1); + AsyncFnOnceOutput, sym::async_fn_once_output,async_fn_once_output, Target::AssocTy, GenericRequirement::None; FnOnceOutput, sym::fn_once_output, fn_once_output, Target::AssocTy, GenericRequirement::None; Future, sym::future_trait, future_trait, Target::Trait, GenericRequirement::Exact(0); diff --git a/src/tools/rust-analyzer/crates/hir-ty/Cargo.toml b/src/tools/rust-analyzer/crates/hir-ty/Cargo.toml index efa544cf39651..8b65126e7b749 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/Cargo.toml +++ b/src/tools/rust-analyzer/crates/hir-ty/Cargo.toml @@ -31,7 +31,7 @@ la-arena.workspace = true triomphe.workspace = true typed-arena = "2.0.2" indexmap.workspace = true -rustc_apfloat = "0.2.2" +rustc_apfloat = "0.2.3" query-group.workspace = true salsa.workspace = true salsa-macros.workspace = true diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs index 710ac6e54223c..f658e23665895 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs @@ -261,10 +261,20 @@ impl chalk_solve::RustIrDatabase for ChalkContext<'_> { &self, well_known_trait: WellKnownTrait, ) -> Option> { - let lang_attr = lang_item_from_well_known_trait(well_known_trait); - let trait_ = lang_attr.resolve_trait(self.db, self.krate)?; + let lang_item = lang_item_from_well_known_trait(well_known_trait); + let trait_ = lang_item.resolve_trait(self.db, self.krate)?; Some(to_chalk_trait_id(trait_)) } + fn well_known_assoc_type_id( + &self, + assoc_type: rust_ir::WellKnownAssocType, + ) -> Option> { + let lang_item = match assoc_type { + rust_ir::WellKnownAssocType::AsyncFnOnceOutput => LangItem::AsyncFnOnceOutput, + }; + let alias = lang_item.resolve_type_alias(self.db, self.krate)?; + Some(to_assoc_type_id(alias)) + } fn program_clauses_for_env( &self, diff --git a/src/tools/rust-analyzer/crates/ide-db/Cargo.toml b/src/tools/rust-analyzer/crates/ide-db/Cargo.toml index 583318de26df0..acde1d665dae1 100644 --- a/src/tools/rust-analyzer/crates/ide-db/Cargo.toml +++ b/src/tools/rust-analyzer/crates/ide-db/Cargo.toml @@ -22,7 +22,7 @@ either.workspace = true itertools.workspace = true arrayvec.workspace = true indexmap.workspace = true -memchr = "2.7.4" +memchr = "2.7.5" salsa.workspace = true salsa-macros.workspace = true query-group.workspace = true diff --git a/src/tools/rust-analyzer/crates/ide/Cargo.toml b/src/tools/rust-analyzer/crates/ide/Cargo.toml index 1d19daf2f5aa9..2f8ed88fbb5d1 100644 --- a/src/tools/rust-analyzer/crates/ide/Cargo.toml +++ b/src/tools/rust-analyzer/crates/ide/Cargo.toml @@ -25,7 +25,7 @@ dot.workspace = true smallvec.workspace = true triomphe.workspace = true nohash-hasher.workspace = true -rustc_apfloat = "0.2.2" +rustc_apfloat = "0.2.3" # local deps cfg.workspace = true diff --git a/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs b/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs index fc922dd849fba..d5cbb7328c14a 100644 --- a/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs +++ b/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs @@ -222,6 +222,7 @@ define_symbols! { fn_once_output, fn_once, async_fn_once, + async_fn_once_output, async_fn_mut, async_fn, fn_ptr_addr, diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/Cargo.toml b/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/Cargo.toml index eddefb33c0ff1..c416d997a89a4 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/Cargo.toml +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/Cargo.toml @@ -9,4 +9,4 @@ license = "MIT OR Apache-2.0" [lib] [build-dependencies] -cargo_metadata = "0.19.2" +cargo_metadata = "0.20.0" diff --git a/src/tools/rust-analyzer/crates/profile/Cargo.toml b/src/tools/rust-analyzer/crates/profile/Cargo.toml index 1fb13832720e6..bae891c198425 100644 --- a/src/tools/rust-analyzer/crates/profile/Cargo.toml +++ b/src/tools/rust-analyzer/crates/profile/Cargo.toml @@ -12,7 +12,7 @@ rust-version.workspace = true [lib] [dependencies] -cfg-if = "1.0.0" +cfg-if = "1.0.1" jemalloc-ctl = { version = "0.5.4", package = "tikv-jemalloc-ctl", optional = true } [target.'cfg(all(target_os = "linux", not(target_env = "ohos")))'.dependencies] @@ -22,7 +22,7 @@ perf-event = "=0.4.7" libc.workspace = true [target.'cfg(windows)'.dependencies] -windows-sys = { version = "0.59", features = [ +windows-sys = { version = "0.60", features = [ "Win32_System_Threading", "Win32_System_ProcessStatus", ] } diff --git a/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs b/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs index bb02284a5130c..1fade7b33233b 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs @@ -492,7 +492,7 @@ impl CargoWorkspace { is_virtual_workspace &= manifest != ws_manifest_path; let pkg = packages.alloc(PackageData { id: id.repr.clone(), - name, + name: name.to_string(), version, manifest: manifest.clone(), targets: Vec::new(), @@ -547,10 +547,12 @@ impl CargoWorkspace { .flat_map(|dep| DepKind::iter(&dep.dep_kinds).map(move |kind| (dep, kind))); for (dep_node, kind) in dependencies { let &pkg = pkg_by_id.get(&dep_node.pkg).unwrap(); - let dep = PackageDependency { name: dep_node.name.clone(), pkg, kind }; + let dep = PackageDependency { name: dep_node.name.to_string(), pkg, kind }; packages[source].dependencies.push(dep); } - packages[source].active_features.extend(node.features); + packages[source] + .active_features + .extend(node.features.into_iter().map(|it| it.to_string())); } CargoWorkspace { diff --git a/src/tools/rust-analyzer/crates/project-model/src/sysroot.rs b/src/tools/rust-analyzer/crates/project-model/src/sysroot.rs index d4055d9a0af91..ebd86e3dc48a7 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/sysroot.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/sysroot.rs @@ -339,7 +339,7 @@ impl Sysroot { Some(_) => { tracing::warn!("unknown rustc-std-workspace-* crate: {}", package.name) } - None => match &*package.name { + None => match &**package.name { "core" => real_core = Some(package.id.clone()), "alloc" => real_alloc = Some(package.id.clone()), "std" => real_std = Some(package.id.clone()), diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml b/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml index b59d06838e0f2..5e63521d7474c 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml +++ b/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml @@ -29,7 +29,7 @@ indexmap.workspace = true itertools.workspace = true scip = "0.5.2" lsp-types = { version = "=0.95.0", features = ["proposed"] } -parking_lot = "0.12.3" +parking_lot = "0.12.4" xflags = "0.3.2" oorandom = "11.1.5" rayon.workspace = true @@ -37,19 +37,19 @@ rustc-hash.workspace = true serde_json = { workspace = true, features = ["preserve_order"] } serde.workspace = true serde_derive.workspace = true -tenthash = "1.0.0" -num_cpus = "1.16.0" -mimalloc = { version = "0.1.44", default-features = false, optional = true } +tenthash = "1.1.0" +num_cpus = "1.17.0" +mimalloc = { version = "0.1.46", default-features = false, optional = true } lsp-server.workspace = true tracing.workspace = true tracing-subscriber.workspace = true tracing-tree.workspace = true triomphe.workspace = true -toml = "0.8.20" +toml = "0.8.23" nohash-hasher.workspace = true walkdir = "2.5.0" semver.workspace = true -memchr = "2.7.4" +memchr = "2.7.5" cargo_metadata.workspace = true process-wrap.workspace = true @@ -75,7 +75,7 @@ vfs.workspace = true paths.workspace = true [target.'cfg(windows)'.dependencies] -windows-sys = { version = "0.59", features = [ +windows-sys = { version = "0.60", features = [ "Win32_System_Diagnostics_Debug", "Win32_System_Threading", ] } diff --git a/src/tools/rust-analyzer/crates/stdx/Cargo.toml b/src/tools/rust-analyzer/crates/stdx/Cargo.toml index b37aded6f68c2..a6d5781660819 100644 --- a/src/tools/rust-analyzer/crates/stdx/Cargo.toml +++ b/src/tools/rust-analyzer/crates/stdx/Cargo.toml @@ -12,7 +12,7 @@ rust-version.workspace = true [lib] [dependencies] -backtrace = { version = "0.3.74", optional = true } +backtrace = { version = "0.3.75", optional = true } jod-thread = "1.0.0" crossbeam-channel.workspace = true itertools.workspace = true @@ -25,7 +25,7 @@ libc.workspace = true [target.'cfg(windows)'.dependencies] miow = "0.6.0" -windows-sys = { version = "0.59", features = ["Win32_Foundation"] } +windows-sys = { version = "0.60", features = ["Win32_Foundation"] } [features] # Uncomment to enable for the whole crate graph diff --git a/src/tools/rust-analyzer/crates/syntax/Cargo.toml b/src/tools/rust-analyzer/crates/syntax/Cargo.toml index 4c7704803ef3b..9d3aaa8d4e338 100644 --- a/src/tools/rust-analyzer/crates/syntax/Cargo.toml +++ b/src/tools/rust-analyzer/crates/syntax/Cargo.toml @@ -27,7 +27,7 @@ stdx.workspace = true [dev-dependencies] rayon.workspace = true expect-test = "1.5.1" -rustc_apfloat = "0.2.2" +rustc_apfloat = "0.2.3" test-utils.workspace = true diff --git a/src/tools/rust-analyzer/lib/lsp-server/Cargo.toml b/src/tools/rust-analyzer/lib/lsp-server/Cargo.toml index 1dc6d3ce5db8f..35a5a4d82b247 100644 --- a/src/tools/rust-analyzer/lib/lsp-server/Cargo.toml +++ b/src/tools/rust-analyzer/lib/lsp-server/Cargo.toml @@ -7,7 +7,7 @@ repository = "https://github.com/rust-lang/rust-analyzer/tree/master/lib/lsp-ser edition = "2024" [dependencies] -log = "0.4.26" +log = "0.4.27" serde_json = "1.0.140" serde = { version = "1.0.219" } serde_derive = { version = "1.0.219" } @@ -15,7 +15,7 @@ crossbeam-channel.workspace = true [dev-dependencies] lsp-types = "=0.95" -ctrlc = "3.4.5" +ctrlc = "3.4.7" [lints] workspace = true diff --git a/src/tools/rust-analyzer/lib/lsp-server/src/msg.rs b/src/tools/rust-analyzer/lib/lsp-server/src/msg.rs index 2749557b91a07..399d674e41d25 100644 --- a/src/tools/rust-analyzer/lib/lsp-server/src/msg.rs +++ b/src/tools/rust-analyzer/lib/lsp-server/src/msg.rs @@ -283,12 +283,12 @@ fn read_msg_text(inp: &mut dyn BufRead) -> io::Result> { buf.resize(size, 0); inp.read_exact(&mut buf)?; let buf = String::from_utf8(buf).map_err(invalid_data)?; - log::debug!("< {}", buf); + log::debug!("< {buf}"); Ok(Some(buf)) } fn write_msg_text(out: &mut dyn Write, msg: &str) -> io::Result<()> { - log::debug!("> {}", msg); + log::debug!("> {msg}"); write!(out, "Content-Length: {}\r\n\r\n", msg.len())?; out.write_all(msg.as_bytes())?; out.flush()?; diff --git a/src/tools/rust-analyzer/lib/lsp-server/src/stdio.rs b/src/tools/rust-analyzer/lib/lsp-server/src/stdio.rs index c558b6c6e7708..eccc89fd59c3a 100644 --- a/src/tools/rust-analyzer/lib/lsp-server/src/stdio.rs +++ b/src/tools/rust-analyzer/lib/lsp-server/src/stdio.rs @@ -38,7 +38,7 @@ pub(crate) fn stdio_transport() -> (Sender, Receiver, IoThread while let Some(msg) = Message::read(&mut stdin)? { let is_exit = matches!(&msg, Message::Notification(n) if n.is_exit()); - debug!("sending message {:#?}", msg); + debug!("sending message {msg:#?}"); if let Err(e) = reader_sender.send(msg) { return Err(io::Error::other(e)); } diff --git a/src/tools/rust-analyzer/xtask/Cargo.toml b/src/tools/rust-analyzer/xtask/Cargo.toml index bb7d83c4b7d93..8cd5811c0a6d1 100644 --- a/src/tools/rust-analyzer/xtask/Cargo.toml +++ b/src/tools/rust-analyzer/xtask/Cargo.toml @@ -9,14 +9,14 @@ rust-version.workspace = true [dependencies] anyhow.workspace = true directories = "6.0" -flate2 = "1.1.0" +flate2 = "1.1.2" write-json = "0.1.4" xshell.workspace = true xflags = "0.3.2" time = { version = "0.3", default-features = false } -zip = { version = "3.0", default-features = false, features = ["deflate-flate2", "time"] } +zip = { version = "4.0", default-features = false, features = ["deflate-flate2", "time"] } stdx.workspace = true -proc-macro2 = "1.0.94" +proc-macro2 = "1.0.95" quote = "1.0.40" ungrammar = "1.16.1" either.workspace = true From 63e17071197d05d02c78cea508326ae4ea675009 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Fri, 13 Jun 2025 09:05:50 +0200 Subject: [PATCH 35/56] Remove unnecessary item tree query calls --- .../crates/hir-def/src/nameres/collector.rs | 96 +++++++++---------- 1 file changed, 47 insertions(+), 49 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs index 185cc0596b6cc..29f94ac2dca13 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs @@ -36,7 +36,7 @@ use crate::{ item_scope::{GlobId, ImportId, ImportOrExternCrate, PerNsGlobImports}, item_tree::{ self, FieldsShape, ImportAlias, ImportKind, ItemTree, ItemTreeAstId, Macro2, MacroCall, - MacroRules, Mod, ModItemId, ModKind, TreeId, UseTreeKind, + MacroRules, Mod, ModItemId, ModKind, TreeId, }, macro_call_as_call_id, nameres::{ @@ -140,8 +140,6 @@ struct ImportSource { id: UseId, is_prelude: bool, kind: ImportKind, - tree: TreeId, - item: FileAstId, } #[derive(Debug, Eq, PartialEq)] @@ -155,7 +153,6 @@ struct Import { impl Import { fn from_use( tree: &ItemTree, - tree_id: TreeId, item: FileAstId, id: UseId, is_prelude: bool, @@ -168,7 +165,7 @@ impl Import { path, alias, visibility: visibility.clone(), - source: ImportSource { use_tree: idx, id, is_prelude, kind, tree: tree_id, item }, + source: ImportSource { use_tree: idx, id, is_prelude, kind }, }); }); } @@ -183,15 +180,15 @@ struct ImportDirective { } #[derive(Clone, Debug, Eq, PartialEq)] -struct MacroDirective { +struct MacroDirective<'db> { module_id: LocalModuleId, depth: usize, - kind: MacroDirectiveKind, + kind: MacroDirectiveKind<'db>, container: ItemContainerId, } #[derive(Clone, Debug, Eq, PartialEq)] -enum MacroDirectiveKind { +enum MacroDirectiveKind<'db> { FnLike { ast_id: AstIdWithPath, expand_to: ExpandTo, @@ -210,28 +207,29 @@ enum MacroDirectiveKind { attr: Attr, mod_item: ModItemId, /* is this needed? */ tree: TreeId, + item_tree: &'db ItemTree, }, } /// Walks the tree of module recursively -struct DefCollector<'a> { - db: &'a dyn DefDatabase, +struct DefCollector<'db> { + db: &'db dyn DefDatabase, def_map: DefMap, local_def_map: LocalDefMap, /// Set only in case of blocks. - crate_local_def_map: Option<&'a LocalDefMap>, + crate_local_def_map: Option<&'db LocalDefMap>, // The dependencies of the current crate, including optional deps like `test`. deps: FxHashMap, glob_imports: FxHashMap>, unresolved_imports: Vec, indeterminate_imports: Vec<(ImportDirective, PerNs)>, - unresolved_macros: Vec, + unresolved_macros: Vec>, // We'd like to avoid emitting a diagnostics avalanche when some `extern crate` doesn't // resolve. When we emit diagnostics for unresolved imports, we only do so if the import // doesn't start with an unresolved crate's name. unresolved_extern_crates: FxHashSet, mod_dirs: FxHashMap, - cfg_options: &'a CfgOptions, + cfg_options: &'db CfgOptions, /// List of procedural macros defined by this crate. This is read from the dynamic library /// built by the build system, and is the list of proc-macros we can actually expand. It is /// empty when proc-macro support is disabled (in which case we still do name resolution for @@ -249,7 +247,7 @@ struct DefCollector<'a> { skip_attrs: FxHashMap>, AttrId>, } -impl DefCollector<'_> { +impl<'db> DefCollector<'db> { fn seed_with_top_level(&mut self) { let _p = tracing::info_span!("seed_with_top_level").entered(); @@ -461,7 +459,7 @@ impl DefCollector<'_> { self.unresolved_macros.iter().enumerate().find_map(|(idx, directive)| match &directive .kind { - MacroDirectiveKind::Attr { ast_id, mod_item, attr, tree } => { + MacroDirectiveKind::Attr { ast_id, mod_item, attr, tree, item_tree } => { self.def_map.diagnostics.push(DefDiagnostic::unresolved_macro_call( directive.module_id, MacroCallKind::Attr { @@ -474,14 +472,20 @@ impl DefCollector<'_> { self.skip_attrs.insert(ast_id.ast_id.with_value(mod_item.ast_id()), attr.id); - Some((idx, directive, *mod_item, *tree)) + Some((idx, directive, *mod_item, *tree, *item_tree)) } _ => None, }); match unresolved_attr { - Some((pos, &MacroDirective { module_id, depth, container, .. }, mod_item, tree_id)) => { - let item_tree = &tree_id.item_tree(self.db); + Some(( + pos, + &MacroDirective { module_id, depth, container, .. }, + mod_item, + tree_id, + item_tree, + )) => { + // FIXME: Remove this clone let mod_dir = self.mod_dirs[&module_id].clone(); ModCollector { def_collector: self, @@ -862,8 +866,6 @@ impl DefCollector<'_> { kind: kind @ (ImportKind::Plain | ImportKind::TypeOnly), id, use_tree, - tree, - item, .. } => { let name = match &import.alias { @@ -896,13 +898,11 @@ impl DefCollector<'_> { let Some(ImportOrExternCrate::ExternCrate(_)) = def.import else { return false; }; - let item_tree = tree.item_tree(self.db); - let use_kind = item_tree[item].use_tree.kind(); - let UseTreeKind::Single { path, .. } = use_kind else { + if kind == ImportKind::Glob { return false; - }; - matches!(path.kind, PathKind::Plain | PathKind::SELF) - && path.segments().len() < 2 + } + matches!(import.path.kind, PathKind::Plain | PathKind::SELF) + && import.path.segments().len() < 2 }; if is_extern_crate_reimport_without_prefix() { def.vis = vis; @@ -1256,7 +1256,7 @@ impl DefCollector<'_> { fn resolve_macros(&mut self) -> ReachedFixedPoint { let mut macros = mem::take(&mut self.unresolved_macros); let mut resolved = Vec::new(); - let mut push_resolved = |directive: &MacroDirective, call_id| { + let mut push_resolved = |directive: &MacroDirective<'_>, call_id| { resolved.push((directive.module_id, directive.depth, directive.container, call_id)); }; @@ -1269,7 +1269,7 @@ impl DefCollector<'_> { let mut eager_callback_buffer = vec![]; let mut res = ReachedFixedPoint::Yes; // Retain unresolved macros after this round of resolution. - let mut retain = |directive: &MacroDirective| { + let mut retain = |directive: &MacroDirective<'db>| { let subns = match &directive.kind { MacroDirectiveKind::FnLike { .. } => MacroSubNs::Bang, MacroDirectiveKind::Attr { .. } | MacroDirectiveKind::Derive { .. } => { @@ -1364,7 +1364,13 @@ impl DefCollector<'_> { return Resolved::Yes; } } - MacroDirectiveKind::Attr { ast_id: file_ast_id, mod_item, attr, tree } => { + MacroDirectiveKind::Attr { + ast_id: file_ast_id, + mod_item, + attr, + tree, + item_tree, + } => { let &AstIdWithPath { ast_id, ref path } = file_ast_id; let file_id = ast_id.file_id; @@ -1375,7 +1381,6 @@ impl DefCollector<'_> { .skip_attrs .insert(InFile::new(file_id, mod_item.ast_id()), attr.id); - let item_tree = tree.item_tree(self.db); ModCollector { def_collector: collector, macro_depth: directive.depth, @@ -1646,8 +1651,7 @@ impl DefCollector<'_> { import: Import { ref path, - source: - ImportSource { use_tree, id, is_prelude: _, kind: _, tree: _, item: _ }, + source: ImportSource { use_tree, id, is_prelude: _, kind: _ }, .. }, .. @@ -1671,12 +1675,12 @@ impl DefCollector<'_> { } /// Walks a single module, populating defs, imports and macros -struct ModCollector<'a, 'b> { - def_collector: &'a mut DefCollector<'b>, +struct ModCollector<'a, 'db> { + def_collector: &'a mut DefCollector<'db>, macro_depth: usize, module_id: LocalModuleId, tree_id: TreeId, - item_tree: &'a ItemTree, + item_tree: &'db ItemTree, mod_dir: ModDir, } @@ -1753,20 +1757,13 @@ impl ModCollector<'_, '_> { UseLoc { container: module, id: InFile::new(self.file_id(), item_tree_id) } .intern(db); let is_prelude = attrs.by_key(sym::prelude_import).exists(); - Import::from_use( - self.item_tree, - self.tree_id, - item_tree_id, - id, - is_prelude, - |import| { - self.def_collector.unresolved_imports.push(ImportDirective { - module_id: self.module_id, - import, - status: PartialResolvedImport::Unresolved, - }); - }, - ) + Import::from_use(self.item_tree, item_tree_id, id, is_prelude, |import| { + self.def_collector.unresolved_imports.push(ImportDirective { + module_id: self.module_id, + import, + status: PartialResolvedImport::Unresolved, + }); + }) } ModItemId::ExternCrate(item_tree_id) => { let item_tree::ExternCrate { name, visibility, alias } = @@ -2268,6 +2265,7 @@ impl ModCollector<'_, '_> { attr: attr.clone(), mod_item, tree: self.tree_id, + item_tree: self.item_tree, }, container, }); From 4b61ff72371b1724ee89f70a20a3be4a6037f463 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 12 Jun 2025 13:10:15 +0200 Subject: [PATCH 36/56] Generate annotations for macro defined items if their name is in the input --- .../crates/ide/src/annotations.rs | 82 +++++++++++++++++-- .../crates/ide/src/navigation_target.rs | 2 +- 2 files changed, 76 insertions(+), 8 deletions(-) diff --git a/src/tools/rust-analyzer/crates/ide/src/annotations.rs b/src/tools/rust-analyzer/crates/ide/src/annotations.rs index 3d71da985b24b..05196ac98c03e 100644 --- a/src/tools/rust-analyzer/crates/ide/src/annotations.rs +++ b/src/tools/rust-analyzer/crates/ide/src/annotations.rs @@ -10,6 +10,7 @@ use crate::{ NavigationTarget, RunnableKind, annotations::fn_references::find_all_methods, goto_implementation::goto_implementation, + navigation_target, references::find_all_refs, runnables::{Runnable, runnables}, }; @@ -148,15 +149,32 @@ pub(crate) fn annotations( node: InFile, source_file_id: FileId, ) -> Option<(TextRange, Option)> { - if let Some(InRealFile { file_id, value }) = node.original_ast_node_rooted(db) { - if file_id.file_id(db) == source_file_id { - return Some(( - value.syntax().text_range(), - value.name().map(|name| name.syntax().text_range()), - )); + if let Some(name) = node.value.name().map(|name| name.syntax().text_range()) { + // if we have a name, try mapping that out of the macro expansion as we can put the + // annotation on that name token + // See `test_no_annotations_macro_struct_def` vs `test_annotations_macro_struct_def_call_site` + let res = navigation_target::orig_range_with_focus_r( + db, + node.file_id, + node.value.syntax().text_range(), + Some(name), + ); + if res.call_site.0.file_id == source_file_id { + if let Some(name_range) = res.call_site.1 { + return Some((res.call_site.0.range, Some(name_range))); + } } + }; + // otherwise try upmapping the entire node out of attributes + let InRealFile { file_id, value } = node.original_ast_node_rooted(db)?; + if file_id.file_id(db) == source_file_id { + Some(( + value.syntax().text_range(), + value.name().map(|name| name.syntax().text_range()), + )) + } else { + None } - None } }); @@ -913,6 +931,56 @@ m!(); ); } + #[test] + fn test_annotations_macro_struct_def_call_site() { + check( + r#" +//- /lib.rs +macro_rules! m { + ($name:ident) => { + struct $name {} + }; +} + +m! { + Name +}; +"#, + expect![[r#" + [ + Annotation { + range: 83..87, + kind: HasImpls { + pos: FilePositionWrapper { + file_id: FileId( + 0, + ), + offset: 83, + }, + data: Some( + [], + ), + }, + }, + Annotation { + range: 83..87, + kind: HasReferences { + pos: FilePositionWrapper { + file_id: FileId( + 0, + ), + offset: 83, + }, + data: Some( + [], + ), + }, + }, + ] + "#]], + ); + } + #[test] fn test_annotations_appear_above_whole_item_when_configured_to_do_so() { check_with_config( diff --git a/src/tools/rust-analyzer/crates/ide/src/navigation_target.rs b/src/tools/rust-analyzer/crates/ide/src/navigation_target.rs index 9334b73fc7b4f..4c7c597e684e6 100644 --- a/src/tools/rust-analyzer/crates/ide/src/navigation_target.rs +++ b/src/tools/rust-analyzer/crates/ide/src/navigation_target.rs @@ -867,7 +867,7 @@ pub(crate) fn orig_range_with_focus_r( } // def site name - // FIXME: This can be de improved + // FIXME: This can be improved Some((focus_range, _ctxt)) => { match value_range { // but overall node is in macro input From dd7f93ef77e95c8bb92be623d86a7f87bf2c1b85 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Fri, 13 Jun 2025 14:42:23 +0200 Subject: [PATCH 37/56] Bring back EMPTY item tree deduplication --- .../crates/hir-def/src/item_tree.rs | 49 +++++++++++++------ .../crates/hir-def/src/item_tree/lower.rs | 4 +- 2 files changed, 37 insertions(+), 16 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs index bf482d33e7392..f61b403b84efd 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs @@ -86,9 +86,10 @@ impl fmt::Debug for RawVisibilityId { } } -#[salsa_macros::tracked(returns(ref))] -pub(crate) fn file_item_tree_query(db: &dyn DefDatabase, file_id: HirFileId) -> ItemTree { +#[salsa_macros::tracked(returns(deref))] +pub(crate) fn file_item_tree_query(db: &dyn DefDatabase, file_id: HirFileId) -> Arc { let _p = tracing::info_span!("file_item_tree_query", ?file_id).entered(); + static EMPTY: OnceLock> = OnceLock::new(); let ctx = lower::Ctx::new(db, file_id); let syntax = db.parse_or_expand(file_id); @@ -116,16 +117,35 @@ pub(crate) fn file_item_tree_query(db: &dyn DefDatabase, file_id: HirFileId) -> }, } }; - - item_tree.shrink_to_fit(); - item_tree + 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: RawAttrs::EMPTY, + vis: ItemVisibilities { arena: ThinVec::new() }, + }) + }) + .clone() + } else { + item_tree.shrink_to_fit(); + Arc::new(item_tree) + } } -#[salsa_macros::tracked(returns(ref))] +#[salsa_macros::tracked(returns(deref))] pub(crate) fn block_item_tree_query(db: &dyn DefDatabase, block: BlockId) -> Arc { let _p = tracing::info_span!("block_item_tree_query", ?block).entered(); - // Blocks have a tendency to be empty due to macro calls that do not expand to items, - // so deduplicate this case via `Arc` to reduce the size of the query storage here. static EMPTY: OnceLock> = OnceLock::new(); let loc = block.lookup(db); @@ -133,11 +153,13 @@ pub(crate) fn block_item_tree_query(db: &dyn DefDatabase, block: BlockId) -> Arc let ctx = lower::Ctx::new(db, loc.ast_id.file_id); let mut item_tree = ctx.lower_block(&block); - if item_tree.small_data.is_empty() - && item_tree.big_data.is_empty() - && item_tree.top_level.is_empty() - && item_tree.attrs.is_empty() - && item_tree.top_attrs.is_empty() + 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(|| { @@ -163,7 +185,6 @@ pub struct ItemTree { top_attrs: RawAttrs, attrs: FxHashMap, RawAttrs>, vis: ItemVisibilities, - // FIXME: They values store the key, turn this into a FxHashSet instead? big_data: FxHashMap, BigModItem>, small_data: FxHashMap, SmallModItem>, } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs index fe1b8e3134254..f3273667158de 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs @@ -383,8 +383,8 @@ impl<'a> Ctx<'a> { }); match &vis { RawVisibility::Public => RawVisibilityId::PUB, - RawVisibility::Module(path, explicitiy) if path.segments().is_empty() => { - match (path.kind, explicitiy) { + RawVisibility::Module(path, explicitness) if path.segments().is_empty() => { + match (path.kind, explicitness) { (PathKind::SELF, VisibilityExplicitness::Explicit) => { RawVisibilityId::PRIV_EXPLICIT } From 2eea0f8c05b32f1c39641160a5d0ccfff5c6fa22 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Fri, 13 Jun 2025 15:34:03 +0200 Subject: [PATCH 38/56] Use `ThinVec` in `ItemScope` in a couple places --- .../crates/hir-def/src/item_scope.rs | 36 +++++++++---------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs index 5362c0588dbe9..8591874eb943e 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs @@ -13,6 +13,7 @@ use smallvec::{SmallVec, smallvec}; use span::Edition; use stdx::format_to; use syntax::ast; +use thin_vec::ThinVec; use crate::{ AdtId, BuiltinType, ConstId, ExternBlockId, ExternCrateId, FxIndexMap, HasModule, ImplId, @@ -155,22 +156,21 @@ pub struct ItemScope { /// The defs declared in this scope. Each def has a single scope where it is /// declared. - declarations: Vec, + declarations: ThinVec, - impls: Vec, - #[allow(clippy::box_collection)] - extern_blocks: Option>>, - unnamed_consts: Vec, + impls: ThinVec, + extern_blocks: ThinVec, + unnamed_consts: ThinVec, /// Traits imported via `use Trait as _;`. - unnamed_trait_imports: FxHashMap>, + unnamed_trait_imports: ThinVec<(TraitId, Item<()>)>, // the resolutions of the imports of this scope use_imports_types: FxHashMap, use_imports_values: FxHashMap, use_imports_macros: FxHashMap, - use_decls: Vec, - extern_crate_decls: Vec, + use_decls: ThinVec, + extern_crate_decls: ThinVec, /// Macros visible in current module in legacy textual scope /// /// For macros invoked by an unqualified identifier like `bar!()`, `legacy_macros` will be searched in first. @@ -183,7 +183,7 @@ pub struct ItemScope { /// Module scoped macros will be inserted into `items` instead of here. // FIXME: Macro shadowing in one module is not properly handled. Non-item place macros will // be all resolved to the last one defined if shadowing happens. - legacy_macros: FxHashMap>, + legacy_macros: FxHashMap>, /// The attribute macro invocations in this scope. attr_macros: FxHashMap, MacroCallId>, /// The macro invocations in this scope. @@ -198,7 +198,7 @@ struct DeriveMacroInvocation { attr_id: AttrId, /// The `#[derive]` call attr_call_id: MacroCallId, - derive_call_ids: SmallVec<[Option; 1]>, + derive_call_ids: SmallVec<[Option; 4]>, } pub(crate) static BUILTIN_SCOPE: LazyLock> = LazyLock::new(|| { @@ -322,7 +322,7 @@ impl ItemScope { } pub fn extern_blocks(&self) -> impl Iterator + '_ { - self.extern_blocks.iter().flat_map(|it| it.iter()).copied() + self.extern_blocks.iter().copied() } pub fn use_decls(&self) -> impl ExactSizeIterator + '_ { @@ -435,7 +435,7 @@ impl ItemScope { ModuleDefId::TraitId(t) => Some(t), _ => None, }) - .chain(self.unnamed_trait_imports.keys().copied()) + .chain(self.unnamed_trait_imports.iter().map(|&(t, _)| t)) } pub(crate) fn resolutions(&self) -> impl Iterator, PerNs)> + '_ { @@ -476,7 +476,7 @@ impl ItemScope { } pub(crate) fn define_extern_block(&mut self, extern_block: ExternBlockId) { - self.extern_blocks.get_or_insert_default().push(extern_block); + self.extern_blocks.push(extern_block); } pub(crate) fn define_extern_crate_decl(&mut self, extern_crate: ExternCrateId) { @@ -564,7 +564,7 @@ impl ItemScope { // FIXME: This is only used in collection, we should move the relevant parts of it out of ItemScope pub(crate) fn unnamed_trait_vis(&self, tr: TraitId) -> Option { - self.unnamed_trait_imports.get(&tr).map(|trait_| trait_.vis) + self.unnamed_trait_imports.iter().find(|&&(t, _)| t == tr).map(|(_, trait_)| trait_.vis) } pub(crate) fn push_unnamed_trait( @@ -573,7 +573,7 @@ impl ItemScope { vis: Visibility, import: Option, ) { - self.unnamed_trait_imports.insert(tr, Item { def: (), vis, import }); + self.unnamed_trait_imports.push((tr, Item { def: (), vis, import })); } pub(crate) fn push_res_with_import( @@ -725,7 +725,7 @@ impl ItemScope { .values_mut() .map(|def| &mut def.vis) .chain(self.values.values_mut().map(|def| &mut def.vis)) - .chain(self.unnamed_trait_imports.values_mut().map(|def| &mut def.vis)) + .chain(self.unnamed_trait_imports.iter_mut().map(|(_, def)| &mut def.vis)) .for_each(|vis| match vis { &mut Visibility::Module(_, visibility_explicitness) => { *vis = Visibility::Module(this_module, visibility_explicitness) @@ -817,9 +817,7 @@ impl ItemScope { macro_invocations, extern_blocks, } = self; - if let Some(it) = extern_blocks { - it.shrink_to_fit(); - } + extern_blocks.shrink_to_fit(); types.shrink_to_fit(); values.shrink_to_fit(); macros.shrink_to_fit(); From 6438b31117bf8c8ebea6701e178ec4194a0ffcdd Mon Sep 17 00:00:00 2001 From: Martin Pool Date: Fri, 13 Jun 2025 07:35:03 -0700 Subject: [PATCH 39/56] Fix link to the contribution guide --- src/tools/rust-analyzer/docs/book/src/troubleshooting.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/tools/rust-analyzer/docs/book/src/troubleshooting.md b/src/tools/rust-analyzer/docs/book/src/troubleshooting.md index 4092b9de990cc..1b2841421a471 100644 --- a/src/tools/rust-analyzer/docs/book/src/troubleshooting.md +++ b/src/tools/rust-analyzer/docs/book/src/troubleshooting.md @@ -46,5 +46,4 @@ It is especially useful when the `repo` doesn’t use external crates or the standard library. If you want to go as far as to modify the source code to debug the -problem, be sure to take a look at the [dev -docs](https://github.com/rust-lang/rust-analyzer/tree/master/docs/dev)! +problem, be sure to take a look at the [contribution guide](contributing/index.html)! From 1bdd12ddc19263a3f34557060f09707b7e05e55b Mon Sep 17 00:00:00 2001 From: Martin Pool Date: Fri, 13 Jun 2025 07:36:40 -0700 Subject: [PATCH 40/56] Make the URL a hyperlink --- src/tools/rust-analyzer/docs/book/src/contributing/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/rust-analyzer/docs/book/src/contributing/README.md b/src/tools/rust-analyzer/docs/book/src/contributing/README.md index 5f4a74eba28aa..beb94cdfc4162 100644 --- a/src/tools/rust-analyzer/docs/book/src/contributing/README.md +++ b/src/tools/rust-analyzer/docs/book/src/contributing/README.md @@ -13,7 +13,7 @@ To learn more about how rust-analyzer works, see [Architecture](architecture.md) It also explains the high-level layout of the source code. Do skim through that document. -We also publish rustdoc docs to pages: https://rust-lang.github.io/rust-analyzer/ide/. +We also publish rustdoc docs to . Note though, that the internal documentation is very incomplete. Various organizational and process issues are discussed in this document. From 82076c1571fb7aa7f72d96cc19feb5a7dbcf4efb Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Fri, 13 Jun 2025 17:15:28 +0200 Subject: [PATCH 41/56] Turn `BlockId` into a `#[salsa::tracked]` --- .../rust-analyzer/crates/hir-def/src/db.rs | 11 ++++------ .../crates/hir-def/src/expr_store/lower.rs | 4 ++-- .../src/expr_store/tests/body/block.rs | 4 ++-- .../rust-analyzer/crates/hir-def/src/lib.rs | 21 ++++++++++++++++++- 4 files changed, 28 insertions(+), 12 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/db.rs b/src/tools/rust-analyzer/crates/hir-def/src/db.rs index 27fe62c4f0d9d..f024f04efe03b 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/db.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/db.rs @@ -12,10 +12,10 @@ use thin_vec::ThinVec; use triomphe::Arc; use crate::{ - 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, + AttrDefId, 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, TraitAliasId, TraitAliasLoc, TraitId, TraitLoc, TypeAliasId, TypeAliasLoc, UnionId, UnionLoc, UseId, UseLoc, VariantId, attr::{Attrs, AttrsWithOwner}, @@ -96,9 +96,6 @@ pub trait InternDatabase: RootQueryDb { #[salsa::interned] fn intern_macro_rules(&self, loc: MacroRulesLoc) -> MacroRulesId; // // endregion: items - - #[salsa::interned] - fn intern_block(&self, loc: BlockLoc) -> BlockId; } #[query_group::query_group] diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs index 4ba31c1e20bfe..03683ec9203c1 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs @@ -11,7 +11,7 @@ use base_db::FxIndexSet; use cfg::CfgOptions; use either::Either; use hir_expand::{ - HirFileId, InFile, MacroDefId, + HirFileId, InFile, Intern, MacroDefId, mod_path::tool_path, name::{AsName, Name}, span_map::SpanMapRef, @@ -2148,7 +2148,7 @@ impl ExprCollector<'_> { ) -> ExprId { let block_id = self.expander.ast_id_map().ast_id_for_block(&block).map(|file_local_id| { let ast_id = self.expander.in_file(file_local_id); - self.db.intern_block(BlockLoc { ast_id, module: self.module }) + BlockLoc { ast_id, module: self.module }.intern(self.db) }); let (module, def_map) = diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/tests/body/block.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/tests/body/block.rs index 5f7b510bba4bb..5fe72778172f2 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/tests/body/block.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/tests/body/block.rs @@ -189,8 +189,8 @@ fn f() { } "#, expect![[r#" - BlockId(3c01) in BlockRelativeModuleId { block: Some(BlockId(3c00)), local_id: Idx::(1) } - BlockId(3c00) in BlockRelativeModuleId { block: None, local_id: Idx::(0) } + BlockIdLt { [salsa id]: Id(3c01) } in BlockRelativeModuleId { block: Some(BlockIdLt { [salsa id]: Id(3c00) }), local_id: Idx::(1) } + BlockIdLt { [salsa id]: Id(3c00) } in BlockRelativeModuleId { block: None, local_id: Idx::(0) } crate scope "#]], ); diff --git a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs index dcc18666a57d1..e7ab2b4d77d11 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs @@ -344,7 +344,26 @@ pub struct BlockLoc { /// The containing module. pub module: ModuleId, } -impl_intern!(BlockId, BlockLoc, intern_block, lookup_intern_block); +#[salsa_macros::tracked(debug)] +#[derive(PartialOrd, Ord)] +pub struct BlockIdLt<'db> { + pub loc: BlockLoc, +} +pub type BlockId = BlockIdLt<'static>; +impl hir_expand::Intern for BlockLoc { + type Database = dyn DefDatabase; + type ID = BlockId; + fn intern(self, db: &Self::Database) -> Self::ID { + unsafe { std::mem::transmute::, BlockId>(BlockIdLt::new(db, self)) } + } +} +impl hir_expand::Lookup for BlockId { + type Database = dyn DefDatabase; + type Data = BlockLoc; + fn lookup(&self, db: &Self::Database) -> Self::Data { + self.loc(db) + } +} /// A `ModuleId` that is always a crate's root module. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] From 71f666352104ec9cb2fc3ccd4926aa7b3341808f Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Fri, 13 Jun 2025 17:29:22 +0200 Subject: [PATCH 42/56] Remove `InternedCallableDefId` It's unnecessary --- .../crates/hir-ty/src/chalk_ext.rs | 12 +++++------ .../rust-analyzer/crates/hir-ty/src/db.rs | 7 ------- .../rust-analyzer/crates/hir-ty/src/lib.rs | 4 ++-- .../crates/hir-ty/src/mapping.rs | 20 ++++--------------- .../crates/hir-ty/src/mir/eval.rs | 4 ++-- .../crates/hir-ty/src/mir/lower/as_place.rs | 9 +++------ .../crates/hir/src/source_analyzer.rs | 5 ++--- 7 files changed, 19 insertions(+), 42 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_ext.rs b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_ext.rs index aabc4c4234dbc..836cc96233eb8 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_ext.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_ext.rs @@ -16,7 +16,8 @@ use crate::{ ClosureId, DynTy, FnPointer, ImplTraitId, InEnvironment, Interner, Lifetime, ProjectionTy, QuantifiedWhereClause, Substitution, TraitRef, Ty, TyBuilder, TyKind, TypeFlags, WhereClause, db::HirDatabase, from_assoc_type_id, from_chalk_trait_id, from_foreign_def_id, - from_placeholder_idx, generics::generics, to_chalk_trait_id, utils::ClosureSubst, + from_placeholder_idx, generics::generics, mapping::ToChalk, to_chalk_trait_id, + utils::ClosureSubst, }; pub trait TyExt { @@ -190,10 +191,9 @@ impl TyExt for Ty { fn as_generic_def(&self, db: &dyn HirDatabase) -> Option { match *self.kind(Interner) { TyKind::Adt(AdtId(adt), ..) => Some(adt.into()), - TyKind::FnDef(callable, ..) => Some(GenericDefId::from_callable( - db, - db.lookup_intern_callable_def(callable.into()), - )), + TyKind::FnDef(callable, ..) => { + Some(GenericDefId::from_callable(db, ToChalk::from_chalk(db, callable))) + } TyKind::AssociatedType(type_alias, ..) => Some(from_assoc_type_id(type_alias).into()), TyKind::Foreign(type_alias, ..) => Some(from_foreign_def_id(type_alias).into()), _ => None, @@ -202,7 +202,7 @@ impl TyExt for Ty { fn callable_def(&self, db: &dyn HirDatabase) -> Option { match self.kind(Interner) { - &TyKind::FnDef(def, ..) => Some(db.lookup_intern_callable_def(def.into())), + &TyKind::FnDef(def, ..) => Some(ToChalk::from_chalk(db, def)), _ => None, } } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/db.rs b/src/tools/rust-analyzer/crates/hir-ty/src/db.rs index 1e985dc604ee6..1029969992c67 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/db.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/db.rs @@ -236,9 +236,6 @@ pub trait HirDatabase: DefDatabase + std::fmt::Debug { fn trait_impls_in_deps(&self, krate: Crate) -> Arc<[Arc]>; // Interned IDs for Chalk integration - #[salsa::interned] - fn intern_callable_def(&self, callable_def: CallableDefId) -> InternedCallableDefId; - #[salsa::interned] fn intern_type_or_const_param_id( &self, @@ -347,7 +344,3 @@ impl_intern_key!(InternedClosureId, InternedClosure); #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct InternedCoroutine(pub DefWithBodyId, pub ExprId); impl_intern_key!(InternedCoroutineId, InternedCoroutine); - -// This exists just for Chalk, because Chalk just has a single `FnDefId` where -// we have different IDs for struct and enum variant constructors. -impl_intern_key!(InternedCallableDefId, CallableDefId); diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs index 128569d55dc9b..148f2a41e7db5 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs @@ -98,7 +98,7 @@ pub use lower::{ ValueTyDefId, associated_type_shorthand_candidates, diagnostics::*, }; pub use mapping::{ - from_assoc_type_id, from_chalk_trait_id, from_foreign_def_id, from_placeholder_idx, + ToChalk, from_assoc_type_id, from_chalk_trait_id, from_foreign_def_id, from_placeholder_idx, lt_from_placeholder_idx, lt_to_placeholder_idx, to_assoc_type_id, to_chalk_trait_id, to_foreign_def_id, to_placeholder_idx, }; @@ -542,7 +542,7 @@ impl CallableSig { } pub fn from_def(db: &dyn HirDatabase, def: FnDefId, substs: &Substitution) -> CallableSig { - let callable_def = db.lookup_intern_callable_def(def.into()); + let callable_def = ToChalk::from_chalk(db, def); let sig = db.callable_item_signature(callable_def); sig.substitute(Interner, substs) } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mapping.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mapping.rs index 2abc1ac62a99a..6936d8193eb02 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mapping.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mapping.rs @@ -16,7 +16,7 @@ use crate::{ PlaceholderIndex, chalk_db, db::HirDatabase, }; -pub(crate) trait ToChalk { +pub trait ToChalk { type Chalk; fn to_chalk(self, db: &dyn HirDatabase) -> Self::Chalk; fn from_chalk(db: &dyn HirDatabase, chalk: Self::Chalk) -> Self; @@ -44,12 +44,12 @@ impl ToChalk for hir_def::ImplId { impl ToChalk for CallableDefId { type Chalk = FnDefId; - fn to_chalk(self, db: &dyn HirDatabase) -> FnDefId { - db.intern_callable_def(self).into() + fn to_chalk(self, _db: &dyn HirDatabase) -> FnDefId { + chalk_ir::FnDefId(salsa::plumbing::AsId::as_id(&self)) } fn from_chalk(db: &dyn HirDatabase, fn_def_id: FnDefId) -> CallableDefId { - db.lookup_intern_callable_def(fn_def_id.into()) + salsa::plumbing::FromIdWithDb::from_id(fn_def_id.0, db.zalsa()) } } @@ -70,18 +70,6 @@ impl ToChalk for TypeAliasAsValue { } } -impl From for crate::db::InternedCallableDefId { - fn from(fn_def_id: FnDefId) -> Self { - Self::from_id(fn_def_id.0) - } -} - -impl From for FnDefId { - fn from(callable_def_id: crate::db::InternedCallableDefId) -> Self { - chalk_ir::FnDefId(callable_def_id.as_id()) - } -} - impl From for crate::db::InternedOpaqueTyId { fn from(id: OpaqueTyId) -> Self { FromId::from_id(id.0) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs index 8fb8d64779bd7..da6e4e5d8a15b 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs @@ -32,7 +32,7 @@ use triomphe::Arc; use crate::{ CallableDefId, ClosureId, ComplexMemoryMap, Const, ConstData, ConstScalar, FnDefId, Interner, - MemoryMap, Substitution, TraitEnvironment, Ty, TyBuilder, TyExt, TyKind, + MemoryMap, Substitution, ToChalk, TraitEnvironment, Ty, TyBuilder, TyExt, TyKind, consteval::{ConstEvalError, intern_const_scalar, try_const_usize}, db::{HirDatabase, InternedClosure}, display::{ClosureStyle, DisplayTarget, HirDisplay}, @@ -2930,7 +2930,7 @@ pub fn render_const_using_debug_impl( let a2 = evaluator.heap_allocate(evaluator.ptr_size() * 2, evaluator.ptr_size())?; evaluator.write_memory(a2, &data.addr.to_bytes())?; let debug_fmt_fn_ptr = evaluator.vtable_map.id(TyKind::FnDef( - db.intern_callable_def(debug_fmt_fn.into()).into(), + CallableDefId::FunctionId(debug_fmt_fn).to_chalk(db), Substitution::from1(Interner, c.data(Interner).ty.clone()), ) .intern(Interner)); diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/as_place.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/as_place.rs index c22bada7a903a..ad664693e29f7 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/as_place.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/as_place.rs @@ -297,11 +297,8 @@ impl MirLowerCtx<'_> { let result_ref = TyKind::Ref(mutability, error_lifetime(), result_ty).intern(Interner); let mut result: Place = self.temp(result_ref, current, span)?.into(); let index_fn_op = Operand::const_zst( - TyKind::FnDef( - self.db.intern_callable_def(CallableDefId::FunctionId(index_fn.0)).into(), - index_fn.1, - ) - .intern(Interner), + TyKind::FnDef(CallableDefId::FunctionId(index_fn.0).to_chalk(self.db), index_fn.1) + .intern(Interner), ); let Some(current) = self.lower_call( index_fn_op, @@ -357,7 +354,7 @@ impl MirLowerCtx<'_> { .ok_or(MirLowerError::LangItemNotFound(trait_lang_item))?; let deref_fn_op = Operand::const_zst( TyKind::FnDef( - self.db.intern_callable_def(CallableDefId::FunctionId(deref_fn)).into(), + CallableDefId::FunctionId(deref_fn).to_chalk(self.db), Substitution::from1(Interner, source_ty), ) .intern(Interner), diff --git a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs index ec2ccf8cba0be..09b61524d6092 100644 --- a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs +++ b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs @@ -37,7 +37,7 @@ use hir_expand::{ }; use hir_ty::{ Adjustment, AliasTy, InferenceResult, Interner, LifetimeElisionKind, ProjectionTy, - Substitution, TraitEnvironment, Ty, TyExt, TyKind, TyLoweringContext, + Substitution, ToChalk, TraitEnvironment, Ty, TyExt, TyKind, TyLoweringContext, diagnostics::{ InsideUnsafeBlock, record_literal_missing_fields, record_pattern_missing_fields, unsafe_operations, @@ -1169,8 +1169,7 @@ impl<'db> SourceAnalyzer<'db> { ) } TyKind::FnDef(fn_id, subst) => { - let fn_id = hir_ty::db::InternedCallableDefId::from(*fn_id); - let fn_id = db.lookup_intern_callable_def(fn_id); + let fn_id = ToChalk::from_chalk(db, *fn_id); let generic_def_id = match fn_id { CallableDefId::StructId(id) => id.into(), CallableDefId::FunctionId(id) => id.into(), From cea73e95a8ce35c47e703d6b8c23af33a92b30f4 Mon Sep 17 00:00:00 2001 From: Waffle Lapkin Date: Thu, 12 Jun 2025 14:03:18 +0200 Subject: [PATCH 43/56] remove `pref_align_of` intrinsic handling, rename `{min_=>}align_of{,_val}` --- .../crates/hir-ty/src/consteval/tests/intrinsics.rs | 10 +++++----- .../rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs | 12 ++++++++---- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests/intrinsics.rs b/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests/intrinsics.rs index ee375d60deb83..5e85978e2990d 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests/intrinsics.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests/intrinsics.rs @@ -112,16 +112,16 @@ fn size_of_val() { } #[test] -fn min_align_of_val() { +fn align_of_val() { check_number( r#" //- minicore: coerce_unsized #[rustc_intrinsic] - pub fn min_align_of_val(_: *const T) -> usize; + pub fn align_of_val(_: *const T) -> usize; struct X(i32, u8); - const GOAL: usize = min_align_of_val(&X(1, 2)); + const GOAL: usize = align_of_val(&X(1, 2)); "#, 4, ); @@ -129,11 +129,11 @@ fn min_align_of_val() { r#" //- minicore: coerce_unsized #[rustc_intrinsic] - pub fn min_align_of_val(_: *const T) -> usize; + pub fn align_of_val(_: *const T) -> usize; const GOAL: usize = { let x: &[i32] = &[1, 2, 3]; - min_align_of_val(x) + align_of_val(x) }; "#, 4, diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs index 512a275aa7594..8d428dd6d049e 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs @@ -761,7 +761,9 @@ impl Evaluator<'_> { let size = self.size_of_sized(ty, locals, "size_of arg")?; destination.write_from_bytes(self, &size.to_le_bytes()[0..destination.size]) } - "min_align_of" | "pref_align_of" => { + // FIXME: `min_align_of` was renamed to `align_of` in Rust 1.89 + // (https://github.com/rust-lang/rust/pull/142410) + "min_align_of" | "align_of" => { let Some(ty) = generic_args.as_slice(Interner).first().and_then(|it| it.ty(Interner)) else { @@ -793,17 +795,19 @@ impl Evaluator<'_> { destination.write_from_bytes(self, &size.to_le_bytes()) } } - "min_align_of_val" => { + // FIXME: `min_align_of_val` was renamed to `align_of_val` in Rust 1.89 + // (https://github.com/rust-lang/rust/pull/142410) + "min_align_of_val" | "align_of_val" => { let Some(ty) = generic_args.as_slice(Interner).first().and_then(|it| it.ty(Interner)) else { return Err(MirEvalError::InternalError( - "min_align_of_val generic arg is not provided".into(), + "align_of_val generic arg is not provided".into(), )); }; let [arg] = args else { return Err(MirEvalError::InternalError( - "min_align_of_val args are not provided".into(), + "align_of_val args are not provided".into(), )); }; if let Some((_, align)) = self.size_align_of(ty, locals)? { From 3f4a23e5a8994b49ab67321177c6d5683f8d6494 Mon Sep 17 00:00:00 2001 From: Tadeo Kondrak Date: Fri, 13 Jun 2025 17:51:10 -0600 Subject: [PATCH 44/56] Allow lifetime repeats in macros: $($x)'a* This works in rustc. This change isn't motivated by any real code. I just learned about it and decided to see why it doesn't work with rust-analyzer. --- .../hir-def/src/macro_expansion_tests/mbe.rs | 22 +++++++++++++++++++ .../macro_expansion_tests/mbe/meta_syntax.rs | 4 ++++ .../rust-analyzer/crates/mbe/src/benchmark.rs | 4 ++++ .../crates/mbe/src/expander/matcher.rs | 11 ++++++---- .../crates/mbe/src/expander/transcriber.rs | 4 ++++ .../rust-analyzer/crates/mbe/src/parser.rs | 19 ++++++++++++---- 6 files changed, 56 insertions(+), 8 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe.rs b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe.rs index eea50d16f5a00..ef93a2a790d5b 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe.rs @@ -2029,3 +2029,25 @@ fn f() { "#]], ); } + +#[test] +fn lifetime_repeat() { + check( + r#" +macro_rules! m { + ($($x:expr)'a*) => (stringify!($($x)'b*)); +} +fn f() { + let _ = m!(0 'a 1 'a 2); +} + "#, + expect![[r#" +macro_rules! m { + ($($x:expr)'a*) => (stringify!($($x)'b*)); +} +fn f() { + let _ = stringify!(0 'b1 'b2); +} + "#]], + ); +} diff --git a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe/meta_syntax.rs b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe/meta_syntax.rs index 2d289b7683389..2c94f0e8d0986 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe/meta_syntax.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe/meta_syntax.rs @@ -13,6 +13,8 @@ macro_rules! m { ($(x),*) => (); ($(x)_*) => (); ($(x)i*) => (); + ($(x)'a*) => (); + ($(x)'_*) => (); ($($i:ident)*) => ($_); ($($true:ident)*) => ($true); ($($false:ident)*) => ($false); @@ -28,6 +30,8 @@ macro_rules! m { ($(x),*) => (); ($(x)_*) => (); ($(x)i*) => (); + ($(x)'a*) => (); + ($(x)'_*) => (); ($($i:ident)*) => ($_); ($($true:ident)*) => ($true); ($($false:ident)*) => ($false); diff --git a/src/tools/rust-analyzer/crates/mbe/src/benchmark.rs b/src/tools/rust-analyzer/crates/mbe/src/benchmark.rs index db75dceae1cb9..04ac85ad43ddf 100644 --- a/src/tools/rust-analyzer/crates/mbe/src/benchmark.rs +++ b/src/tools/rust-analyzer/crates/mbe/src/benchmark.rs @@ -197,6 +197,10 @@ fn invocation_fixtures( builder.push(tt::Leaf::Punct(*it)) } } + Separator::Lifetime(punct, ident) => { + builder.push(tt::Leaf::Punct(*punct)); + builder.push(tt::Leaf::Ident(ident.clone())); + } }; } } diff --git a/src/tools/rust-analyzer/crates/mbe/src/expander/matcher.rs b/src/tools/rust-analyzer/crates/mbe/src/expander/matcher.rs index 940aaacb02ed5..a8d5965d480c2 100644 --- a/src/tools/rust-analyzer/crates/mbe/src/expander/matcher.rs +++ b/src/tools/rust-analyzer/crates/mbe/src/expander/matcher.rs @@ -823,7 +823,7 @@ fn match_meta_var<'t>( "expected token tree", ) }), - MetaVarKind::Lifetime => expect_lifetime(input).map_err(|()| { + MetaVarKind::Lifetime => expect_lifetime(input).map(drop).map_err(|()| { ExpandError::binding_error( span.unwrap_or(delim_span.close), "expected lifetime", @@ -963,6 +963,10 @@ fn expect_separator(iter: &mut TtIter<'_, S>, separator: &Separator) -> } Err(_) => false, }, + Separator::Lifetime(_punct, ident) => match expect_lifetime(&mut fork) { + Ok(lifetime) => lifetime.sym == ident.sym, + Err(_) => false, + }, }; if ok { *iter = fork; @@ -983,13 +987,12 @@ fn expect_tt(iter: &mut TtIter<'_, S>) -> Result<(), ()> { Ok(()) } -fn expect_lifetime(iter: &mut TtIter<'_, S>) -> Result<(), ()> { +fn expect_lifetime<'a, S: Copy>(iter: &mut TtIter<'a, S>) -> Result<&'a tt::Ident, ()> { let punct = iter.expect_single_punct()?; if punct.char != '\'' { return Err(()); } - iter.expect_ident_or_underscore()?; - Ok(()) + iter.expect_ident_or_underscore() } fn eat_char(iter: &mut TtIter<'_, S>, c: char) { diff --git a/src/tools/rust-analyzer/crates/mbe/src/expander/transcriber.rs b/src/tools/rust-analyzer/crates/mbe/src/expander/transcriber.rs index ec277ba72e90e..2c046df10f5e5 100644 --- a/src/tools/rust-analyzer/crates/mbe/src/expander/transcriber.rs +++ b/src/tools/rust-analyzer/crates/mbe/src/expander/transcriber.rs @@ -497,6 +497,10 @@ fn expand_repeat( builder.push(tt::Leaf::from(punct)); } } + Separator::Lifetime(punct, ident) => { + builder.push(tt::Leaf::from(*punct)); + builder.push(tt::Leaf::from(ident.clone())); + } }; } diff --git a/src/tools/rust-analyzer/crates/mbe/src/parser.rs b/src/tools/rust-analyzer/crates/mbe/src/parser.rs index fbc353d610348..711101260a072 100644 --- a/src/tools/rust-analyzer/crates/mbe/src/parser.rs +++ b/src/tools/rust-analyzer/crates/mbe/src/parser.rs @@ -155,6 +155,7 @@ pub(crate) enum Separator { Literal(tt::Literal), Ident(tt::Ident), Puncts(ArrayVec, MAX_GLUED_PUNCT_LEN>), + Lifetime(tt::Punct, tt::Ident), } // Note that when we compare a Separator, we just care about its textual value. @@ -170,6 +171,7 @@ impl PartialEq for Separator { let b_iter = b.iter().map(|b| b.char); a_iter.eq(b_iter) } + (Lifetime(_, a), Lifetime(_, b)) => a.sym == b.sym, _ => false, } } @@ -350,10 +352,19 @@ fn parse_repeat(src: &mut TtIter<'_, Span>) -> Result<(Option, Repeat _ => true, }; match tt { - tt::Leaf::Ident(_) | tt::Leaf::Literal(_) if has_sep => { - return Err(ParseError::InvalidRepeat); - } - tt::Leaf::Ident(ident) => separator = Separator::Ident(ident.clone()), + tt::Leaf::Ident(ident) => match separator { + Separator::Puncts(puncts) if puncts.is_empty() => { + separator = Separator::Ident(ident.clone()); + } + Separator::Puncts(puncts) => match puncts.as_slice() { + [tt::Punct { char: '\'', .. }] => { + separator = Separator::Lifetime(puncts[0], ident.clone()); + } + _ => return Err(ParseError::InvalidRepeat), + }, + _ => return Err(ParseError::InvalidRepeat), + }, + tt::Leaf::Literal(_) if has_sep => return Err(ParseError::InvalidRepeat), tt::Leaf::Literal(lit) => separator = Separator::Literal(lit.clone()), tt::Leaf::Punct(punct) => { let repeat_kind = match punct.char { From 6cf1a89dc56616bf1e440a19d020a44484fde2c3 Mon Sep 17 00:00:00 2001 From: Lucas Holten Date: Sun, 15 Jun 2025 02:41:35 +0200 Subject: [PATCH 45/56] Add config option to exclude imports from symbol search --- .../rust-analyzer/crates/hir/src/symbols.rs | 7 ++ .../crates/ide-db/src/symbol_index.rs | 39 ++++++++++- .../ide-db/src/test_data/test_doc_alias.txt | 7 ++ .../test_symbol_index_collection.txt | 31 ++++++++ .../test_symbols_exclude_imports.txt | 36 ++++++++++ .../test_data/test_symbols_with_imports.txt | 70 +++++++++++++++++++ .../crates/rust-analyzer/src/config.rs | 5 ++ .../rust-analyzer/src/handlers/request.rs | 3 + .../docs/book/src/configuration_generated.md | 7 ++ .../rust-analyzer/editors/code/package.json | 10 +++ 10 files changed, 214 insertions(+), 1 deletion(-) create mode 100644 src/tools/rust-analyzer/crates/ide-db/src/test_data/test_symbols_exclude_imports.txt create mode 100644 src/tools/rust-analyzer/crates/ide-db/src/test_data/test_symbols_with_imports.txt diff --git a/src/tools/rust-analyzer/crates/hir/src/symbols.rs b/src/tools/rust-analyzer/crates/hir/src/symbols.rs index a0815c3131b1f..4b295fe9ec18e 100644 --- a/src/tools/rust-analyzer/crates/hir/src/symbols.rs +++ b/src/tools/rust-analyzer/crates/hir/src/symbols.rs @@ -33,6 +33,7 @@ pub struct FileSymbol { /// Whether this symbol is a doc alias for the original symbol. pub is_alias: bool, pub is_assoc: bool, + pub is_import: bool, pub do_not_complete: Complete, } @@ -196,6 +197,7 @@ impl<'a> SymbolCollector<'a> { loc: dec_loc, is_alias: false, is_assoc: false, + is_import: true, do_not_complete: Complete::Yes, }); }; @@ -226,6 +228,7 @@ impl<'a> SymbolCollector<'a> { loc: dec_loc, is_alias: false, is_assoc: false, + is_import: false, do_not_complete: Complete::Yes, }); }; @@ -397,6 +400,7 @@ impl<'a> SymbolCollector<'a> { container_name: self.current_container_name.clone(), is_alias: true, is_assoc, + is_import: false, do_not_complete, }); } @@ -409,6 +413,7 @@ impl<'a> SymbolCollector<'a> { loc: dec_loc, is_alias: false, is_assoc, + is_import: false, do_not_complete, }); @@ -441,6 +446,7 @@ impl<'a> SymbolCollector<'a> { container_name: self.current_container_name.clone(), is_alias: true, is_assoc: false, + is_import: false, do_not_complete, }); } @@ -453,6 +459,7 @@ impl<'a> SymbolCollector<'a> { loc: dec_loc, is_alias: false, is_assoc: false, + is_import: false, do_not_complete, }); } diff --git a/src/tools/rust-analyzer/crates/ide-db/src/symbol_index.rs b/src/tools/rust-analyzer/crates/ide-db/src/symbol_index.rs index d1ba79e8c785e..c15cade84a502 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/symbol_index.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/symbol_index.rs @@ -50,6 +50,7 @@ pub struct Query { case_sensitive: bool, only_types: bool, libs: bool, + exclude_imports: bool, } impl Query { @@ -63,6 +64,7 @@ impl Query { mode: SearchMode::Fuzzy, assoc_mode: AssocSearchMode::Include, case_sensitive: false, + exclude_imports: false, } } @@ -94,6 +96,10 @@ impl Query { pub fn case_sensitive(&mut self) { self.case_sensitive = true; } + + pub fn exclude_imports(&mut self) { + self.exclude_imports = true; + } } #[query_group::query_group] @@ -362,6 +368,9 @@ impl Query { if ignore_underscore_prefixed && symbol_name.starts_with("__") { continue; } + if self.exclude_imports && symbol.is_import { + continue; + } if self.mode.check(&self.query, self.case_sensitive, symbol_name) { if let Some(b) = cb(symbol).break_value() { return Some(b); @@ -385,7 +394,8 @@ impl Query { mod tests { use expect_test::expect_file; - use test_fixture::WithFixture; + use salsa::Durability; + use test_fixture::{WORKSPACE, WithFixture}; use super::*; @@ -506,4 +516,31 @@ struct Duplicate; expect_file!["./test_data/test_doc_alias.txt"].assert_debug_eq(&symbols); } + + #[test] + fn test_exclude_imports() { + let (mut db, _) = RootDatabase::with_many_files( + r#" +//- /lib.rs +mod foo; +pub use foo::Foo; + +//- /foo.rs +pub struct Foo; +"#, + ); + + let mut local_roots = FxHashSet::default(); + local_roots.insert(WORKSPACE); + db.set_local_roots_with_durability(Arc::new(local_roots), Durability::HIGH); + + let mut query = Query::new("Foo".to_owned()); + let mut symbols = world_symbols(&db, query.clone()); + symbols.sort_by_key(|x| x.is_import); + expect_file!["./test_data/test_symbols_with_imports.txt"].assert_debug_eq(&symbols); + + query.exclude_imports(); + let symbols = world_symbols(&db, query); + expect_file!["./test_data/test_symbols_exclude_imports.txt"].assert_debug_eq(&symbols); + } } diff --git a/src/tools/rust-analyzer/crates/ide-db/src/test_data/test_doc_alias.txt b/src/tools/rust-analyzer/crates/ide-db/src/test_data/test_doc_alias.txt index 455a6805907cc..30d1df4f8e554 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/test_data/test_doc_alias.txt +++ b/src/tools/rust-analyzer/crates/ide-db/src/test_data/test_doc_alias.txt @@ -41,6 +41,7 @@ container_name: None, is_alias: false, is_assoc: false, + is_import: false, do_not_complete: Yes, }, FileSymbol { @@ -74,6 +75,7 @@ container_name: None, is_alias: false, is_assoc: false, + is_import: false, do_not_complete: Yes, }, FileSymbol { @@ -107,6 +109,7 @@ container_name: None, is_alias: true, is_assoc: false, + is_import: false, do_not_complete: Yes, }, FileSymbol { @@ -140,6 +143,7 @@ container_name: None, is_alias: true, is_assoc: false, + is_import: false, do_not_complete: Yes, }, FileSymbol { @@ -173,6 +177,7 @@ container_name: None, is_alias: true, is_assoc: false, + is_import: false, do_not_complete: Yes, }, FileSymbol { @@ -206,6 +211,7 @@ container_name: None, is_alias: true, is_assoc: false, + is_import: false, do_not_complete: Yes, }, FileSymbol { @@ -239,6 +245,7 @@ container_name: None, is_alias: true, is_assoc: false, + is_import: false, do_not_complete: Yes, }, ], diff --git a/src/tools/rust-analyzer/crates/ide-db/src/test_data/test_symbol_index_collection.txt b/src/tools/rust-analyzer/crates/ide-db/src/test_data/test_symbol_index_collection.txt index 5e5ae1d168e7e..de046e70c6737 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/test_data/test_symbol_index_collection.txt +++ b/src/tools/rust-analyzer/crates/ide-db/src/test_data/test_symbol_index_collection.txt @@ -39,6 +39,7 @@ container_name: None, is_alias: false, is_assoc: false, + is_import: false, do_not_complete: Yes, }, FileSymbol { @@ -70,6 +71,7 @@ container_name: None, is_alias: false, is_assoc: false, + is_import: false, do_not_complete: Yes, }, FileSymbol { @@ -101,6 +103,7 @@ container_name: None, is_alias: false, is_assoc: false, + is_import: false, do_not_complete: Yes, }, FileSymbol { @@ -134,6 +137,7 @@ container_name: None, is_alias: false, is_assoc: false, + is_import: false, do_not_complete: Yes, }, FileSymbol { @@ -167,6 +171,7 @@ container_name: None, is_alias: false, is_assoc: false, + is_import: true, do_not_complete: Yes, }, FileSymbol { @@ -200,6 +205,7 @@ container_name: None, is_alias: false, is_assoc: false, + is_import: false, do_not_complete: Yes, }, FileSymbol { @@ -231,6 +237,7 @@ container_name: None, is_alias: false, is_assoc: false, + is_import: false, do_not_complete: Yes, }, FileSymbol { @@ -264,6 +271,7 @@ container_name: None, is_alias: false, is_assoc: false, + is_import: false, do_not_complete: Yes, }, FileSymbol { @@ -297,6 +305,7 @@ container_name: None, is_alias: false, is_assoc: false, + is_import: false, do_not_complete: Yes, }, FileSymbol { @@ -332,6 +341,7 @@ ), is_alias: false, is_assoc: false, + is_import: false, do_not_complete: Yes, }, FileSymbol { @@ -367,6 +377,7 @@ ), is_alias: false, is_assoc: false, + is_import: false, do_not_complete: Yes, }, FileSymbol { @@ -400,6 +411,7 @@ container_name: None, is_alias: false, is_assoc: false, + is_import: false, do_not_complete: Yes, }, FileSymbol { @@ -433,6 +445,7 @@ container_name: None, is_alias: false, is_assoc: false, + is_import: false, do_not_complete: Yes, }, FileSymbol { @@ -464,6 +477,7 @@ container_name: None, is_alias: false, is_assoc: false, + is_import: false, do_not_complete: Yes, }, FileSymbol { @@ -497,6 +511,7 @@ container_name: None, is_alias: false, is_assoc: false, + is_import: true, do_not_complete: Yes, }, FileSymbol { @@ -530,6 +545,7 @@ container_name: None, is_alias: false, is_assoc: false, + is_import: false, do_not_complete: Yes, }, FileSymbol { @@ -565,6 +581,7 @@ container_name: None, is_alias: false, is_assoc: false, + is_import: false, do_not_complete: Yes, }, FileSymbol { @@ -600,6 +617,7 @@ container_name: None, is_alias: false, is_assoc: false, + is_import: false, do_not_complete: Yes, }, FileSymbol { @@ -633,6 +651,7 @@ container_name: None, is_alias: false, is_assoc: false, + is_import: false, do_not_complete: Yes, }, FileSymbol { @@ -666,6 +685,7 @@ ), is_alias: false, is_assoc: true, + is_import: false, do_not_complete: Yes, }, FileSymbol { @@ -699,6 +719,7 @@ ), is_alias: false, is_assoc: true, + is_import: false, do_not_complete: Yes, }, FileSymbol { @@ -732,6 +753,7 @@ container_name: None, is_alias: false, is_assoc: false, + is_import: false, do_not_complete: Yes, }, FileSymbol { @@ -763,6 +785,7 @@ container_name: None, is_alias: false, is_assoc: false, + is_import: false, do_not_complete: Yes, }, FileSymbol { @@ -796,6 +819,7 @@ container_name: None, is_alias: false, is_assoc: false, + is_import: true, do_not_complete: Yes, }, FileSymbol { @@ -829,6 +853,7 @@ ), is_alias: false, is_assoc: true, + is_import: false, do_not_complete: Yes, }, ], @@ -875,6 +900,7 @@ container_name: None, is_alias: false, is_assoc: false, + is_import: false, do_not_complete: Yes, }, ], @@ -919,6 +945,7 @@ container_name: None, is_alias: false, is_assoc: false, + is_import: true, do_not_complete: Yes, }, FileSymbol { @@ -952,6 +979,7 @@ container_name: None, is_alias: false, is_assoc: false, + is_import: true, do_not_complete: Yes, }, FileSymbol { @@ -985,6 +1013,7 @@ container_name: None, is_alias: false, is_assoc: false, + is_import: false, do_not_complete: Yes, }, FileSymbol { @@ -1018,6 +1047,7 @@ container_name: None, is_alias: false, is_assoc: false, + is_import: true, do_not_complete: Yes, }, FileSymbol { @@ -1051,6 +1081,7 @@ container_name: None, is_alias: false, is_assoc: false, + is_import: true, do_not_complete: Yes, }, ], diff --git a/src/tools/rust-analyzer/crates/ide-db/src/test_data/test_symbols_exclude_imports.txt b/src/tools/rust-analyzer/crates/ide-db/src/test_data/test_symbols_exclude_imports.txt new file mode 100644 index 0000000000000..22872b577f712 --- /dev/null +++ b/src/tools/rust-analyzer/crates/ide-db/src/test_data/test_symbols_exclude_imports.txt @@ -0,0 +1,36 @@ +[ + FileSymbol { + name: "Foo", + def: Adt( + Struct( + Struct { + id: StructId( + 3800, + ), + }, + ), + ), + loc: DeclarationLocation { + hir_file_id: FileId( + EditionedFileId( + Id(2001), + ), + ), + ptr: SyntaxNodePtr { + kind: STRUCT, + range: 0..15, + }, + name_ptr: AstPtr( + SyntaxNodePtr { + kind: NAME, + range: 11..14, + }, + ), + }, + container_name: None, + is_alias: false, + is_assoc: false, + is_import: false, + do_not_complete: Yes, + }, +] diff --git a/src/tools/rust-analyzer/crates/ide-db/src/test_data/test_symbols_with_imports.txt b/src/tools/rust-analyzer/crates/ide-db/src/test_data/test_symbols_with_imports.txt new file mode 100644 index 0000000000000..9f98bf87e2e8d --- /dev/null +++ b/src/tools/rust-analyzer/crates/ide-db/src/test_data/test_symbols_with_imports.txt @@ -0,0 +1,70 @@ +[ + FileSymbol { + name: "Foo", + def: Adt( + Struct( + Struct { + id: StructId( + 3800, + ), + }, + ), + ), + loc: DeclarationLocation { + hir_file_id: FileId( + EditionedFileId( + Id(2001), + ), + ), + ptr: SyntaxNodePtr { + kind: STRUCT, + range: 0..15, + }, + name_ptr: AstPtr( + SyntaxNodePtr { + kind: NAME, + range: 11..14, + }, + ), + }, + container_name: None, + is_alias: false, + is_assoc: false, + is_import: false, + do_not_complete: Yes, + }, + FileSymbol { + name: "Foo", + def: Adt( + Struct( + Struct { + id: StructId( + 3800, + ), + }, + ), + ), + loc: DeclarationLocation { + hir_file_id: FileId( + EditionedFileId( + Id(2000), + ), + ), + ptr: SyntaxNodePtr { + kind: USE_TREE, + range: 17..25, + }, + name_ptr: AstPtr( + SyntaxNodePtr { + kind: NAME_REF, + range: 22..25, + }, + ), + }, + container_name: None, + is_alias: false, + is_assoc: false, + is_import: true, + do_not_complete: Yes, + }, +] diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs index 5cbea9c2b3d98..762b63f54b097 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs @@ -760,6 +760,8 @@ config_data! { /// though Cargo might be the eventual consumer. vfs_extraIncludes: Vec = vec![], + /// Exclude imports from symbol search. + workspace_symbol_search_excludeImports: bool = false, /// Workspace symbol search kind. workspace_symbol_search_kind: WorkspaceSymbolSearchKindDef = WorkspaceSymbolSearchKindDef::OnlyTypes, /// Limits the number of items returned from a workspace symbol search (Defaults to 128). @@ -1352,6 +1354,8 @@ pub struct RunnablesConfig { /// Configuration for workspace symbol search requests. #[derive(Debug, Clone)] pub struct WorkspaceSymbolConfig { + /// Should imports be excluded. + pub search_exclude_imports: bool, /// In what scope should the symbol be searched in. pub search_scope: WorkspaceSymbolSearchScope, /// What kind of symbol is being searched for. @@ -2280,6 +2284,7 @@ impl Config { pub fn workspace_symbol(&self, source_root: Option) -> WorkspaceSymbolConfig { WorkspaceSymbolConfig { + search_exclude_imports: *self.workspace_symbol_search_excludeImports(source_root), search_scope: match self.workspace_symbol_search_scope(source_root) { WorkspaceSymbolSearchScopeDef::Workspace => WorkspaceSymbolSearchScope::Workspace, WorkspaceSymbolSearchScopeDef::WorkspaceAndDependencies => { diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs index 6d46ce68ed474..afd9eff52645d 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs @@ -658,6 +658,9 @@ pub(crate) fn handle_workspace_symbol( if libs { q.libs(); } + if config.search_exclude_imports { + q.exclude_imports(); + } q }; let mut res = exec_query(&snap, query, config.search_limit)?; diff --git a/src/tools/rust-analyzer/docs/book/src/configuration_generated.md b/src/tools/rust-analyzer/docs/book/src/configuration_generated.md index 0e07dadfb7c9b..4eb9cfc4e5bd0 100644 --- a/src/tools/rust-analyzer/docs/book/src/configuration_generated.md +++ b/src/tools/rust-analyzer/docs/book/src/configuration_generated.md @@ -1531,6 +1531,13 @@ buck2's `rust-project` will likely be useful: https://github.com/facebook/buck2/tree/main/integrations/rust-project. +## rust-analyzer.workspace.symbol.search.excludeImports {#workspace.symbol.search.excludeImports} + +Default: `false` + +Exclude imports from symbol search. + + ## rust-analyzer.workspace.symbol.search.kind {#workspace.symbol.search.kind} Default: `"only_types"` diff --git a/src/tools/rust-analyzer/editors/code/package.json b/src/tools/rust-analyzer/editors/code/package.json index c8c36cd85c8e7..dcdb4fe30ee80 100644 --- a/src/tools/rust-analyzer/editors/code/package.json +++ b/src/tools/rust-analyzer/editors/code/package.json @@ -2891,6 +2891,16 @@ } } }, + { + "title": "workspace", + "properties": { + "rust-analyzer.workspace.symbol.search.excludeImports": { + "markdownDescription": "Exclude imports from symbol search.", + "default": false, + "type": "boolean" + } + } + }, { "title": "workspace", "properties": { From 535b9744b651d424c60b195ba15bae3e9c79b61e Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Sat, 14 Jun 2025 17:07:31 +0200 Subject: [PATCH 46/56] Cleanup incremental tests --- .../hir-def/src/nameres/tests/incremental.rs | 387 +++++++++---- .../crates/hir-ty/src/tests/incremental.rs | 518 ++++++++++++++---- 2 files changed, 692 insertions(+), 213 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/incremental.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/incremental.rs index 7a4ea62f12ac1..858aa055edfc9 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/incremental.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/incremental.rs @@ -2,13 +2,13 @@ use base_db::{ CrateDisplayName, CrateGraphBuilder, CrateName, CrateOrigin, CrateWorkspaceData, DependencyBuilder, Env, RootQueryDb, SourceDatabase, }; +use expect_test::{Expect, expect}; use intern::Symbol; use span::Edition; use test_fixture::WithFixture; use triomphe::Arc; use crate::{ - AdtId, ModuleDefId, db::DefDatabase, nameres::{crate_def_map, tests::TestDB}, }; @@ -16,29 +16,29 @@ use crate::{ fn check_def_map_is_not_recomputed( #[rust_analyzer::rust_fixture] ra_fixture_initial: &str, #[rust_analyzer::rust_fixture] ra_fixture_change: &str, + expecta: Expect, + expectb: Expect, ) { let (mut db, pos) = TestDB::with_position(ra_fixture_initial); let krate = db.fetch_test_crate(); - { - let events = db.log_executed(|| { + execute_assert_events( + &db, + || { crate_def_map(&db, krate); - }); - assert!( - format!("{events:?}").contains("crate_local_def_map"), - "no crate def map computed:\n{events:#?}", - ) - } + }, + &[], + expecta, + ); db.set_file_text(pos.file_id.file_id(&db), ra_fixture_change); - { - let events = db.log_executed(|| { + execute_assert_events( + &db, + || { crate_def_map(&db, krate); - }); - assert!( - !format!("{events:?}").contains("crate_local_def_map"), - "crate def map invalidated:\n{events:#?}", - ) - } + }, + &[("crate_local_def_map", 0)], + expectb, + ); } #[test] @@ -104,15 +104,20 @@ pub const BAZ: u32 = 0; Arc::ptr_eq(&all_crates_before, &all_crates_after), "the all_crates list should not have been invalidated" ); - - let events = db.log_executed(|| { - for &krate in db.all_crates().iter() { - crate_def_map(&db, krate); - } - }); - let invalidated_def_maps = - events.iter().filter(|event| event.contains("crate_local_def_map")).count(); - assert_eq!(invalidated_def_maps, 1, "{events:#?}") + execute_assert_events( + &db, + || { + for &krate in db.all_crates().iter() { + crate_def_map(&db, krate); + } + }, + &[("crate_local_def_map", 1)], + expect![[r#" + [ + "crate_local_def_map", + ] + "#]], + ); } #[test] @@ -152,6 +157,34 @@ fn foo() -> i32 { 92 } #[cfg(never)] fn no() {} ", + expect![[r#" + [ + "crate_local_def_map", + "file_item_tree_query", + "ast_id_map_shim", + "parse_shim", + "real_span_map_shim", + "file_item_tree_query", + "ast_id_map_shim", + "parse_shim", + "real_span_map_shim", + "file_item_tree_query", + "ast_id_map_shim", + "parse_shim", + "real_span_map_shim", + "enum_variants_shim", + "enum_variants_with_diagnostics_shim", + ] + "#]], + expect![[r#" + [ + "parse_shim", + "ast_id_map_shim", + "file_item_tree_query", + "real_span_map_shim", + "enum_variants_with_diagnostics_shim", + ] + "#]], ); } @@ -183,6 +216,41 @@ m!(Y); pub struct S {} ", + expect![[r#" + [ + "crate_local_def_map", + "file_item_tree_query", + "ast_id_map_shim", + "parse_shim", + "real_span_map_shim", + "file_item_tree_query", + "ast_id_map_shim", + "parse_shim", + "real_span_map_shim", + "file_item_tree_query", + "ast_id_map_shim", + "parse_shim", + "real_span_map_shim", + "macro_def_shim", + "file_item_tree_query", + "ast_id_map_shim", + "parse_macro_expansion_shim", + "macro_arg_shim", + "decl_macro_expander_shim", + ] + "#]], + expect![[r#" + [ + "parse_shim", + "ast_id_map_shim", + "file_item_tree_query", + "real_span_map_shim", + "macro_arg_shim", + "parse_macro_expansion_shim", + "ast_id_map_shim", + "file_item_tree_query", + ] + "#]], ); } @@ -206,6 +274,49 @@ fn f() {} #[proc_macros::identity] fn f() { foo } ", + expect![[r#" + [ + "crate_local_def_map", + "file_item_tree_query", + "ast_id_map_shim", + "parse_shim", + "real_span_map_shim", + "file_item_tree_query", + "ast_id_map_shim", + "parse_shim", + "real_span_map_shim", + "file_item_tree_query", + "ast_id_map_shim", + "parse_shim", + "real_span_map_shim", + "crate_local_def_map", + "proc_macros_for_crate_shim", + "file_item_tree_query", + "ast_id_map_shim", + "parse_shim", + "real_span_map_shim", + "macro_def_shim", + "file_item_tree_query", + "ast_id_map_shim", + "parse_macro_expansion_shim", + "expand_proc_macro_shim", + "macro_arg_shim", + "proc_macro_span_shim", + ] + "#]], + expect![[r#" + [ + "parse_shim", + "ast_id_map_shim", + "file_item_tree_query", + "real_span_map_shim", + "macro_arg_shim", + "expand_proc_macro_shim", + "parse_macro_expansion_shim", + "ast_id_map_shim", + "file_item_tree_query", + ] + "#]], ); } @@ -287,6 +398,61 @@ m2!(X); #[derive(proc_macros::DeriveIdentity)] pub struct S {} ", + expect![[r#" + [ + "crate_local_def_map", + "file_item_tree_query", + "ast_id_map_shim", + "parse_shim", + "real_span_map_shim", + "file_item_tree_query", + "ast_id_map_shim", + "parse_shim", + "real_span_map_shim", + "file_item_tree_query", + "ast_id_map_shim", + "parse_shim", + "real_span_map_shim", + "macro_def_shim", + "file_item_tree_query", + "ast_id_map_shim", + "parse_macro_expansion_shim", + "macro_arg_shim", + "decl_macro_expander_shim", + "macro_def_shim", + "file_item_tree_query", + "ast_id_map_shim", + "parse_macro_expansion_shim", + "macro_arg_shim", + "decl_macro_expander_shim", + "crate_local_def_map", + "proc_macros_for_crate_shim", + "file_item_tree_query", + "ast_id_map_shim", + "parse_shim", + "real_span_map_shim", + "macro_def_shim", + "macro_def_shim", + "file_item_tree_query", + "ast_id_map_shim", + "parse_macro_expansion_shim", + "expand_proc_macro_shim", + "macro_arg_shim", + "proc_macro_span_shim", + ] + "#]], + expect![[r#" + [ + "parse_shim", + "ast_id_map_shim", + "file_item_tree_query", + "real_span_map_shim", + "macro_arg_shim", + "macro_arg_shim", + "decl_macro_expander_shim", + "macro_arg_shim", + ] + "#]], ); } @@ -341,19 +507,46 @@ m!(Z); "#, ); let krate = db.test_crate(); - { - let events = db.log_executed(|| { + execute_assert_events( + &db, + || { let crate_def_map = crate_def_map(&db, krate); let (_, module_data) = crate_def_map.modules.iter().last().unwrap(); assert_eq!(module_data.scope.resolutions().count(), 4); - }); - let n_recalculated_item_trees = - events.iter().filter(|it| it.contains("file_item_tree_query")).count(); - assert_eq!(n_recalculated_item_trees, 6); - let n_reparsed_macros = - events.iter().filter(|it| it.contains("parse_macro_expansion_shim")).count(); - assert_eq!(n_reparsed_macros, 3); - } + }, + &[("file_item_tree_query", 6), ("parse_macro_expansion_shim", 3)], + expect![[r#" + [ + "crate_local_def_map", + "file_item_tree_query", + "ast_id_map_shim", + "parse_shim", + "real_span_map_shim", + "file_item_tree_query", + "ast_id_map_shim", + "parse_shim", + "real_span_map_shim", + "file_item_tree_query", + "ast_id_map_shim", + "parse_shim", + "real_span_map_shim", + "macro_def_shim", + "file_item_tree_query", + "ast_id_map_shim", + "parse_macro_expansion_shim", + "macro_arg_shim", + "decl_macro_expander_shim", + "file_item_tree_query", + "ast_id_map_shim", + "parse_macro_expansion_shim", + "macro_arg_shim", + "file_item_tree_query", + "ast_id_map_shim", + "parse_macro_expansion_shim", + "macro_arg_shim", + ] + "#]], + ); let new_text = r#" m!(X); @@ -363,28 +556,31 @@ m!(Z); "#; db.set_file_text(pos.file_id.file_id(&db), new_text); - { - let events = db.log_executed(|| { + execute_assert_events( + &db, + || { let crate_def_map = crate_def_map(&db, krate); let (_, module_data) = crate_def_map.modules.iter().last().unwrap(); assert_eq!(module_data.scope.resolutions().count(), 4); - }); - let n_recalculated_item_trees = - events.iter().filter(|it| it.contains("file_item_tree_query")).count(); - assert_eq!(n_recalculated_item_trees, 1, "{events:#?}"); - let n_reparsed_macros = - events.iter().filter(|it| it.contains("parse_macro_expansion_shim")).count(); - assert_eq!(n_reparsed_macros, 0); - } + }, + &[("file_item_tree_query", 1), ("parse_macro_expansion_shim", 0)], + expect![[r#" + [ + "parse_shim", + "ast_id_map_shim", + "file_item_tree_query", + "real_span_map_shim", + "macro_arg_shim", + "macro_arg_shim", + "macro_arg_shim", + ] + "#]], + ); } #[test] fn item_tree_prevents_reparsing() { - // The `ItemTree` is used by both name resolution and the various queries in `adt.rs` and - // `data.rs`. After computing the `ItemTree` and deleting the parse tree, we should be able to - // run those other queries without triggering a reparse. - - let (db, pos) = TestDB::with_position( + let (mut db, pos) = TestDB::with_position( r#" pub struct S; pub union U {} @@ -399,53 +595,54 @@ pub static ST: u8 = 0; pub type Ty = (); "#, ); - let krate = db.test_crate(); - { - let events = db.log_executed(|| { - db.file_item_tree(pos.file_id.into()); - }); - let n_calculated_item_trees = - events.iter().filter(|it| it.contains("file_item_tree_query")).count(); - assert_eq!(n_calculated_item_trees, 1, "{events:#?}"); - let n_parsed_files = events.iter().filter(|it| it.contains("parse")).count(); - assert_eq!(n_parsed_files, 1, "{events:#?}"); - } - // FIXME(salsa-transition): bring this back - // base_db::ParseQuery.in_db(&db).purge(); + execute_assert_events( + &db, + || { + db.file_item_tree(pos.file_id.into()); + }, + &[("file_item_tree_query", 1), ("parse", 1)], + expect![[r#" + [ + "file_item_tree_query", + "ast_id_map_shim", + "parse_shim", + "real_span_map_shim", + ] + "#]], + ); - { - let events = db.log_executed(|| { - let crate_def_map = crate_def_map(&db, krate); - let (_, module_data) = crate_def_map.modules.iter().last().unwrap(); - assert_eq!(module_data.scope.resolutions().count(), 8); - assert_eq!(module_data.scope.impls().count(), 1); + let file_id = pos.file_id.file_id(&db); + let file_text = db.file_text(file_id).text(&db); + db.set_file_text(file_id, &format!("{file_text}\n")); - for imp in module_data.scope.impls() { - db.impl_signature(imp); - } + execute_assert_events( + &db, + || { + db.file_item_tree(pos.file_id.into()); + }, + &[("file_item_tree_query", 1), ("parse", 1)], + expect![[r#" + [ + "parse_shim", + "ast_id_map_shim", + "file_item_tree_query", + "real_span_map_shim", + ] + "#]], + ); +} - for (_, res) in module_data.scope.resolutions() { - match res.values.map(|it| it.def).or(res.types.map(|it| it.def)).unwrap() { - ModuleDefId::FunctionId(f) => _ = db.function_signature(f), - ModuleDefId::AdtId(adt) => match adt { - AdtId::StructId(it) => _ = db.struct_signature(it), - AdtId::UnionId(it) => _ = db.union_signature(it), - AdtId::EnumId(it) => _ = db.enum_signature(it), - }, - ModuleDefId::ConstId(it) => _ = db.const_signature(it), - ModuleDefId::StaticId(it) => _ = db.static_signature(it), - ModuleDefId::TraitId(it) => _ = db.trait_signature(it), - ModuleDefId::TraitAliasId(it) => _ = db.trait_alias_signature(it), - ModuleDefId::TypeAliasId(it) => _ = db.type_alias_signature(it), - ModuleDefId::EnumVariantId(_) - | ModuleDefId::ModuleId(_) - | ModuleDefId::MacroId(_) - | ModuleDefId::BuiltinType(_) => unreachable!(), - } - } - }); - let n_reparsed_files = events.iter().filter(|it| it.contains("parse(")).count(); - assert_eq!(n_reparsed_files, 0, "{events:?}"); +fn execute_assert_events( + db: &TestDB, + f: impl FnOnce(), + required: &[(&str, usize)], + expect: Expect, +) { + let events = db.log_executed(f); + for (event, count) in required { + let n = events.iter().filter(|it| it.contains(event)).count(); + assert_eq!(n, *count, "Expected {event} to be executed {count} times, but only got {n}"); } + expect.assert_debug_eq(&events); } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/incremental.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/incremental.rs index 74f6bbb03089f..b45d8babd4e0d 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/incremental.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/incremental.rs @@ -1,4 +1,5 @@ use base_db::SourceDatabase; +use expect_test::Expect; use hir_def::{DefWithBodyId, ModuleDefId}; use test_fixture::WithFixture; @@ -15,8 +16,9 @@ fn foo() -> i32 { $01 + 1 }", ); - { - let events = db.log_executed(|| { + execute_assert_events( + &db, + || { 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.local_id, &mut |def| { @@ -24,9 +26,31 @@ fn foo() -> i32 { db.infer(it.into()); } }); - }); - assert!(format!("{events:?}").contains("infer_shim")) - } + }, + &[("infer_shim", 1)], + expect_test::expect![[r#" + [ + "source_root_crates_shim", + "crate_local_def_map", + "file_item_tree_query", + "ast_id_map_shim", + "parse_shim", + "real_span_map_shim", + "infer_shim", + "function_signature_shim", + "function_signature_with_source_map_shim", + "attrs_shim", + "body_shim", + "body_with_source_map_shim", + "trait_environment_shim", + "return_type_impl_traits_shim", + "expr_scopes_shim", + "lang_item", + "crate_lang_items", + "lang_item", + ] + "#]], + ); let new_text = " fn foo() -> i32 { @@ -37,8 +61,9 @@ fn foo() -> i32 { db.set_file_text(pos.file_id.file_id(&db), new_text); - { - let events = db.log_executed(|| { + execute_assert_events( + &db, + || { 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.local_id, &mut |def| { @@ -46,9 +71,22 @@ fn foo() -> i32 { db.infer(it.into()); } }); - }); - assert!(!format!("{events:?}").contains("infer_shim"), "{events:#?}") - } + }, + &[("infer_shim", 0)], + expect_test::expect![[r#" + [ + "parse_shim", + "ast_id_map_shim", + "file_item_tree_query", + "real_span_map_shim", + "attrs_shim", + "function_signature_with_source_map_shim", + "function_signature_shim", + "body_with_source_map_shim", + "body_shim", + ] + "#]], + ); } #[test] @@ -66,8 +104,9 @@ fn baz() -> i32 { 1 + 1 }", ); - { - let events = db.log_executed(|| { + execute_assert_events( + &db, + || { 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.local_id, &mut |def| { @@ -75,9 +114,49 @@ fn baz() -> i32 { db.infer(it.into()); } }); - }); - assert!(format!("{events:?}").contains("infer_shim")) - } + }, + &[("infer_shim", 3)], + expect_test::expect![[r#" + [ + "source_root_crates_shim", + "crate_local_def_map", + "file_item_tree_query", + "ast_id_map_shim", + "parse_shim", + "real_span_map_shim", + "infer_shim", + "function_signature_shim", + "function_signature_with_source_map_shim", + "attrs_shim", + "body_shim", + "body_with_source_map_shim", + "trait_environment_shim", + "return_type_impl_traits_shim", + "expr_scopes_shim", + "lang_item", + "crate_lang_items", + "attrs_shim", + "attrs_shim", + "lang_item", + "infer_shim", + "function_signature_shim", + "function_signature_with_source_map_shim", + "body_shim", + "body_with_source_map_shim", + "trait_environment_shim", + "return_type_impl_traits_shim", + "expr_scopes_shim", + "infer_shim", + "function_signature_shim", + "function_signature_with_source_map_shim", + "body_shim", + "body_with_source_map_shim", + "trait_environment_shim", + "return_type_impl_traits_shim", + "expr_scopes_shim", + ] + "#]], + ); let new_text = " fn foo() -> f32 { @@ -93,8 +172,9 @@ fn baz() -> i32 { db.set_file_text(pos.file_id.file_id(&db), new_text); - { - let events = db.log_executed(|| { + execute_assert_events( + &db, + || { 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.local_id, &mut |def| { @@ -102,9 +182,34 @@ fn baz() -> i32 { db.infer(it.into()); } }); - }); - assert_eq!(format!("{events:?}").matches("infer_shim").count(), 1, "{events:#?}") - } + }, + &[("infer_shim", 1)], + expect_test::expect![[r#" + [ + "parse_shim", + "ast_id_map_shim", + "file_item_tree_query", + "real_span_map_shim", + "attrs_shim", + "function_signature_with_source_map_shim", + "function_signature_shim", + "body_with_source_map_shim", + "body_shim", + "attrs_shim", + "attrs_shim", + "function_signature_with_source_map_shim", + "function_signature_shim", + "body_with_source_map_shim", + "body_shim", + "infer_shim", + "expr_scopes_shim", + "function_signature_with_source_map_shim", + "function_signature_shim", + "body_with_source_map_shim", + "body_shim", + ] + "#]], + ); } #[test] @@ -121,14 +226,26 @@ fn bar() -> f32 { } $0", ); - { - let events = db.log_executed(|| { + execute_assert_events( + &db, + || { let module = db.module_for_file(pos.file_id.file_id(&db)); let _crate_def_map = module.def_map(&db); db.trait_impls_in_crate(module.krate()); - }); - assert!(format!("{events:?}").contains("trait_impls_in_crate_shim")) - } + }, + &[("trait_impls_in_crate_shim", 1)], + expect_test::expect![[r#" + [ + "source_root_crates_shim", + "crate_local_def_map", + "file_item_tree_query", + "ast_id_map_shim", + "parse_shim", + "real_span_map_shim", + "trait_impls_in_crate_shim", + ] + "#]], + ); let new_text = " fn foo() -> i32 { @@ -146,24 +263,25 @@ pub struct NewStruct { db.set_file_text(pos.file_id.file_id(&db), new_text); - { - let actual = db.log_executed(|| { + execute_assert_events( + &db, + || { let module = db.module_for_file(pos.file_id.file_id(&db)); let _crate_def_map = module.def_map(&db); db.trait_impls_in_crate(module.krate()); - }); - - let expected = vec![ - "parse_shim".to_owned(), - "ast_id_map_shim".to_owned(), - "file_item_tree_query".to_owned(), - "real_span_map_shim".to_owned(), - "crate_local_def_map".to_owned(), - "trait_impls_in_crate_shim".to_owned(), - ]; - - assert_eq!(expected, actual); - } + }, + &[("trait_impls_in_crate_shim", 1)], + expect_test::expect![[r#" + [ + "parse_shim", + "ast_id_map_shim", + "file_item_tree_query", + "real_span_map_shim", + "crate_local_def_map", + "trait_impls_in_crate_shim", + ] + "#]], + ); } #[test] @@ -180,14 +298,26 @@ fn bar() -> f32 { } $0", ); - { - let events = db.log_executed(|| { + execute_assert_events( + &db, + || { let module = db.module_for_file(pos.file_id.file_id(&db)); let _crate_def_map = module.def_map(&db); db.trait_impls_in_crate(module.krate()); - }); - assert!(format!("{events:?}").contains("trait_impls_in_crate_shim")) - } + }, + &[("trait_impls_in_crate_shim", 1)], + expect_test::expect![[r#" + [ + "source_root_crates_shim", + "crate_local_def_map", + "file_item_tree_query", + "ast_id_map_shim", + "parse_shim", + "real_span_map_shim", + "trait_impls_in_crate_shim", + ] + "#]], + ); let new_text = " fn foo() -> i32 { @@ -206,24 +336,25 @@ pub enum SomeEnum { db.set_file_text(pos.file_id.file_id(&db), new_text); - { - let actual = db.log_executed(|| { + execute_assert_events( + &db, + || { let module = db.module_for_file(pos.file_id.file_id(&db)); let _crate_def_map = module.def_map(&db); db.trait_impls_in_crate(module.krate()); - }); - - let expected = vec![ - "parse_shim".to_owned(), - "ast_id_map_shim".to_owned(), - "file_item_tree_query".to_owned(), - "real_span_map_shim".to_owned(), - "crate_local_def_map".to_owned(), - "trait_impls_in_crate_shim".to_owned(), - ]; - - assert_eq!(expected, actual); - } + }, + &[("trait_impls_in_crate_shim", 1)], + expect_test::expect![[r#" + [ + "parse_shim", + "ast_id_map_shim", + "file_item_tree_query", + "real_span_map_shim", + "crate_local_def_map", + "trait_impls_in_crate_shim", + ] + "#]], + ); } #[test] @@ -240,14 +371,26 @@ fn bar() -> f32 { } $0", ); - { - let events = db.log_executed(|| { + execute_assert_events( + &db, + || { let module = db.module_for_file(pos.file_id.file_id(&db)); let _crate_def_map = module.def_map(&db); db.trait_impls_in_crate(module.krate()); - }); - assert!(format!("{events:?}").contains("trait_impls_in_crate_shim")) - } + }, + &[("trait_impls_in_crate_shim", 1)], + expect_test::expect![[r#" + [ + "source_root_crates_shim", + "crate_local_def_map", + "file_item_tree_query", + "ast_id_map_shim", + "parse_shim", + "real_span_map_shim", + "trait_impls_in_crate_shim", + ] + "#]], + ); let new_text = " use std::collections::HashMap; @@ -263,24 +406,25 @@ fn bar() -> f32 { db.set_file_text(pos.file_id.file_id(&db), new_text); - { - let actual = db.log_executed(|| { + execute_assert_events( + &db, + || { let module = db.module_for_file(pos.file_id.file_id(&db)); let _crate_def_map = module.def_map(&db); db.trait_impls_in_crate(module.krate()); - }); - - let expected = vec![ - "parse_shim".to_owned(), - "ast_id_map_shim".to_owned(), - "file_item_tree_query".to_owned(), - "real_span_map_shim".to_owned(), - "crate_local_def_map".to_owned(), - "trait_impls_in_crate_shim".to_owned(), - ]; - - assert_eq!(expected, actual); - } + }, + &[("trait_impls_in_crate_shim", 1)], + expect_test::expect![[r#" + [ + "parse_shim", + "ast_id_map_shim", + "file_item_tree_query", + "real_span_map_shim", + "crate_local_def_map", + "trait_impls_in_crate_shim", + ] + "#]], + ); } #[test] @@ -301,14 +445,26 @@ pub struct SomeStruct { } $0", ); - { - let events = db.log_executed(|| { + execute_assert_events( + &db, + || { let module = db.module_for_file(pos.file_id.file_id(&db)); let _crate_def_map = module.def_map(&db); db.trait_impls_in_crate(module.krate()); - }); - assert!(format!("{events:?}").contains("trait_impls_in_crate_shim")) - } + }, + &[("trait_impls_in_crate_shim", 1)], + expect_test::expect![[r#" + [ + "source_root_crates_shim", + "crate_local_def_map", + "file_item_tree_query", + "ast_id_map_shim", + "parse_shim", + "real_span_map_shim", + "trait_impls_in_crate_shim", + ] + "#]], + ); let new_text = " fn foo() -> i32 { @@ -332,33 +488,34 @@ impl SomeStruct { db.set_file_text(pos.file_id.file_id(&db), new_text); - { - let actual = db.log_executed(|| { + execute_assert_events( + &db, + || { let module = db.module_for_file(pos.file_id.file_id(&db)); let _crate_def_map = module.def_map(&db); db.trait_impls_in_crate(module.krate()); - }); - - let expected = vec![ - "parse_shim".to_owned(), - "ast_id_map_shim".to_owned(), - "file_item_tree_query".to_owned(), - "real_span_map_shim".to_owned(), - "crate_local_def_map".to_owned(), - "trait_impls_in_crate_shim".to_owned(), - "attrs_shim".to_owned(), - "impl_trait_with_diagnostics_shim".to_owned(), - "impl_signature_shim".to_owned(), - "impl_signature_with_source_map_shim".to_owned(), - "impl_self_ty_with_diagnostics_shim".to_owned(), - "struct_signature_shim".to_owned(), - "struct_signature_with_source_map_shim".to_owned(), - "attrs_shim".to_owned(), - "type_for_adt_tracked".to_owned(), - ]; - - assert_eq!(expected, actual); - } + }, + &[("trait_impls_in_crate_shim", 1)], + expect_test::expect![[r#" + [ + "parse_shim", + "ast_id_map_shim", + "file_item_tree_query", + "real_span_map_shim", + "crate_local_def_map", + "trait_impls_in_crate_shim", + "attrs_shim", + "impl_trait_with_diagnostics_shim", + "impl_signature_shim", + "impl_signature_with_source_map_shim", + "impl_self_ty_with_diagnostics_shim", + "struct_signature_shim", + "struct_signature_with_source_map_shim", + "attrs_shim", + "type_for_adt_tracked", + ] + "#]], + ); } #[test] @@ -380,8 +537,9 @@ fn main() { }", ); - { - let events = db.log_executed(|| { + execute_assert_events( + &db, + || { let module = db.module_for_file(file_id.file_id(&db)); let crate_def_map = module.def_map(&db); let mut defs: Vec = vec![]; @@ -399,9 +557,73 @@ fn main() { for def in defs { let _inference_result = db.infer(def); } - }); - assert!(format!("{events:?}").contains("trait_solve_shim")) - } + }, + &[("trait_solve_shim", 2)], + expect_test::expect![[r#" + [ + "source_root_crates_shim", + "crate_local_def_map", + "file_item_tree_query", + "ast_id_map_shim", + "parse_shim", + "real_span_map_shim", + "trait_items_with_diagnostics_shim", + "body_shim", + "body_with_source_map_shim", + "attrs_shim", + "impl_items_with_diagnostics_shim", + "infer_shim", + "trait_signature_shim", + "trait_signature_with_source_map_shim", + "attrs_shim", + "function_signature_shim", + "function_signature_with_source_map_shim", + "attrs_shim", + "body_shim", + "body_with_source_map_shim", + "trait_environment_shim", + "lang_item", + "crate_lang_items", + "attrs_shim", + "attrs_shim", + "return_type_impl_traits_shim", + "infer_shim", + "function_signature_shim", + "function_signature_with_source_map_shim", + "trait_environment_shim", + "expr_scopes_shim", + "struct_signature_shim", + "struct_signature_with_source_map_shim", + "generic_predicates_shim", + "value_ty_shim", + "variant_fields_shim", + "variant_fields_with_source_map_shim", + "lang_item", + "inherent_impls_in_crate_shim", + "impl_signature_shim", + "impl_signature_with_source_map_shim", + "callable_item_signature_shim", + "adt_variance_shim", + "variances_of_shim", + "trait_solve_shim", + "trait_datum_shim", + "generic_predicates_shim", + "adt_datum_shim", + "trait_impls_in_deps_shim", + "trait_impls_in_crate_shim", + "impl_trait_with_diagnostics_shim", + "impl_self_ty_with_diagnostics_shim", + "type_for_adt_tracked", + "impl_datum_shim", + "generic_predicates_shim", + "program_clauses_for_chalk_env_shim", + "value_ty_shim", + "generic_predicates_shim", + "trait_solve_shim", + "lang_item", + ] + "#]], + ); let new_text = " //- /main.rs crate:main @@ -422,8 +644,9 @@ fn main() { db.set_file_text(file_id.file_id(&db), new_text); - { - let events = db.log_executed(|| { + execute_assert_events( + &db, + || { let module = db.module_for_file(file_id.file_id(&db)); let crate_def_map = module.def_map(&db); let mut defs: Vec = vec![]; @@ -442,7 +665,66 @@ fn main() { for def in defs { let _inference_result = db.infer(def); } - }); - assert!(!format!("{events:?}").contains("trait_solve_shim")) + }, + &[("trait_solve_shim", 0)], + expect_test::expect![[r#" + [ + "parse_shim", + "ast_id_map_shim", + "file_item_tree_query", + "real_span_map_shim", + "crate_local_def_map", + "trait_items_with_diagnostics_shim", + "body_with_source_map_shim", + "attrs_shim", + "body_shim", + "impl_items_with_diagnostics_shim", + "infer_shim", + "attrs_shim", + "trait_signature_with_source_map_shim", + "attrs_shim", + "function_signature_with_source_map_shim", + "function_signature_shim", + "body_with_source_map_shim", + "body_shim", + "trait_environment_shim", + "crate_lang_items", + "attrs_shim", + "attrs_shim", + "attrs_shim", + "return_type_impl_traits_shim", + "infer_shim", + "function_signature_with_source_map_shim", + "trait_environment_shim", + "expr_scopes_shim", + "struct_signature_with_source_map_shim", + "generic_predicates_shim", + "variant_fields_with_source_map_shim", + "inherent_impls_in_crate_shim", + "impl_signature_with_source_map_shim", + "impl_signature_shim", + "callable_item_signature_shim", + "generic_predicates_shim", + "trait_impls_in_crate_shim", + "impl_trait_with_diagnostics_shim", + "impl_self_ty_with_diagnostics_shim", + "generic_predicates_shim", + "generic_predicates_shim", + ] + "#]], + ); +} + +fn execute_assert_events( + db: &TestDB, + f: impl FnOnce(), + required: &[(&str, usize)], + expect: Expect, +) { + let events = db.log_executed(f); + for (event, count) in required { + let n = events.iter().filter(|it| it.contains(event)).count(); + assert_eq!(n, *count, "Expected {event} to be executed {count} times, but only got {n}"); } + expect.assert_debug_eq(&events); } From 0d5fde22b1645dcd851e284840da561d933d00e3 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Sun, 15 Jun 2025 08:43:22 +0200 Subject: [PATCH 47/56] Idiomatic salsa use for enum variants query --- src/tools/rust-analyzer/Cargo.toml | 4 +++- .../rust-analyzer/crates/hir-def/src/db.rs | 20 +++---------------- .../crates/hir-def/src/find_path.rs | 2 +- .../crates/hir-def/src/lang_item.rs | 2 +- .../rust-analyzer/crates/hir-def/src/lib.rs | 18 ++++++++++++++++- .../crates/hir-def/src/nameres/collector.rs | 5 ++--- .../hir-def/src/nameres/path_resolution.rs | 4 ++-- .../hir-def/src/nameres/tests/incremental.rs | 5 ++--- .../crates/hir-def/src/signatures.rs | 15 +++++++------- .../crates/hir-ty/src/chalk_db.rs | 4 ++-- .../crates/hir-ty/src/consteval.rs | 2 +- .../hir-ty/src/diagnostics/decl_check.rs | 2 +- .../crates/hir-ty/src/diagnostics/expr.rs | 2 +- .../hir-ty/src/diagnostics/match_check.rs | 2 +- .../diagnostics/match_check/pat_analysis.rs | 4 ++-- .../crates/hir-ty/src/display.rs | 4 ++-- .../rust-analyzer/crates/hir-ty/src/drop.rs | 4 ++-- .../rust-analyzer/crates/hir-ty/src/infer.rs | 4 ++-- .../crates/hir-ty/src/infer/cast.rs | 2 +- .../crates/hir-ty/src/infer/closure.rs | 2 +- .../crates/hir-ty/src/infer/path.rs | 2 +- .../crates/hir-ty/src/inhabitedness.rs | 2 +- .../crates/hir-ty/src/layout/adt.rs | 4 ++-- .../crates/hir-ty/src/mir/eval.rs | 8 ++++---- .../crates/hir-ty/src/mir/lower.rs | 6 +++--- .../crates/hir-ty/src/mir/pretty.rs | 5 +++-- .../rust-analyzer/crates/hir-ty/src/tests.rs | 2 +- .../rust-analyzer/crates/hir-ty/src/tls.rs | 2 +- .../rust-analyzer/crates/hir-ty/src/utils.rs | 6 +++--- .../crates/hir-ty/src/variance.rs | 2 +- src/tools/rust-analyzer/crates/hir/src/lib.rs | 8 ++++---- .../hir/src/semantics/child_by_source.rs | 2 +- .../crates/hir/src/source_analyzer.rs | 2 +- 33 files changed, 81 insertions(+), 77 deletions(-) diff --git a/src/tools/rust-analyzer/Cargo.toml b/src/tools/rust-analyzer/Cargo.toml index c5f061cad7d1d..c791d741b0267 100644 --- a/src/tools/rust-analyzer/Cargo.toml +++ b/src/tools/rust-analyzer/Cargo.toml @@ -134,7 +134,9 @@ pulldown-cmark-to-cmark = "10.0.4" pulldown-cmark = { version = "0.9.6", default-features = false } rayon = "1.10.0" rowan = "=0.15.15" -salsa = { version = "0.22.0", default-features = false, features = ["rayon","salsa_unstable"] } +# Ideally we'd not enable the macros feature but unfortunately the `tracked` attribute does not work +# on impls without it +salsa = { version = "0.22.0", default-features = true, features = ["rayon","salsa_unstable", "macros"] } salsa-macros = "0.22.0" semver = "1.0.26" serde = { version = "1.0.219" } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/db.rs b/src/tools/rust-analyzer/crates/hir-def/src/db.rs index f024f04efe03b..2fc79c3809f6f 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/db.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/db.rs @@ -8,7 +8,6 @@ use hir_expand::{ use intern::{Symbol, sym}; use la_arena::ArenaMap; use syntax::{AstPtr, ast}; -use thin_vec::ThinVec; use triomphe::Arc; use crate::{ @@ -32,9 +31,9 @@ use crate::{ diagnostics::DefDiagnostics, }, signatures::{ - ConstSignature, EnumSignature, EnumVariants, FunctionSignature, ImplSignature, - InactiveEnumVariantCode, StaticSignature, StructSignature, TraitAliasSignature, - TraitSignature, TypeAliasSignature, UnionSignature, VariantFields, + ConstSignature, EnumSignature, FunctionSignature, ImplSignature, StaticSignature, + StructSignature, TraitAliasSignature, TraitSignature, TypeAliasSignature, UnionSignature, + VariantFields, }, tt, visibility::{self, Visibility}, @@ -121,19 +120,6 @@ pub trait DefDatabase: InternDatabase + ExpandDatabase + SourceDatabase { id: VariantId, ) -> (Arc, Arc); - // FIXME: Should we make this transparent? The only unstable thing in `enum_variants_with_diagnostics()` - // is ast ids, and ast ids are pretty stable now. - #[salsa::tracked] - fn enum_variants(&self, id: EnumId) -> Arc { - self.enum_variants_with_diagnostics(id).0 - } - - #[salsa::invoke(EnumVariants::enum_variants_query)] - fn enum_variants_with_diagnostics( - &self, - id: EnumId, - ) -> (Arc, Option>>); - #[salsa::transparent] #[salsa::invoke(ImplItems::impl_items_query)] fn impl_items(&self, e: ImplId) -> Arc; diff --git a/src/tools/rust-analyzer/crates/hir-def/src/find_path.rs b/src/tools/rust-analyzer/crates/hir-def/src/find_path.rs index bb75621c7e070..6ebc0d8dfd9cb 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/find_path.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/find_path.rs @@ -137,7 +137,7 @@ fn find_path_inner(ctx: &FindPathCtx<'_>, item: ItemInNs, max_len: usize) -> Opt let loc = variant.lookup(ctx.db); if let Some(mut path) = find_path_inner(ctx, ItemInNs::Types(loc.parent.into()), max_len) { path.push_segment( - ctx.db.enum_variants(loc.parent).variants[loc.index as usize].1.clone(), + loc.parent.enum_variants(ctx.db).variants[loc.index as usize].1.clone(), ); return Some(path); } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs b/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs index 8f071cd953a9c..c0e30ac79562f 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs @@ -125,7 +125,7 @@ pub fn crate_lang_items(db: &dyn DefDatabase, krate: Crate) -> Option { lang_items.collect_lang_item(db, e, LangItemTarget::EnumId); - db.enum_variants(e).variants.iter().for_each(|&(id, _, _)| { + e.enum_variants(db).variants.iter().for_each(|&(id, _, _)| { lang_items.collect_lang_item(db, id, LangItemTarget::EnumVariant); }); } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs index e7ab2b4d77d11..be5bb57ade6d8 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs @@ -51,6 +51,7 @@ pub mod visibility; use intern::{Interned, sym}; pub use rustc_abi as layout; +use thin_vec::ThinVec; use triomphe::Arc; pub use crate::signatures::LocalFieldId; @@ -88,7 +89,7 @@ use crate::{ db::DefDatabase, hir::generics::{LocalLifetimeParamId, LocalTypeOrConstParamId}, nameres::{LocalDefMap, block_def_map, crate_def_map, crate_local_def_map}, - signatures::VariantFields, + signatures::{EnumVariants, InactiveEnumVariantCode, VariantFields}, }; type FxIndexMap = indexmap::IndexMap; @@ -253,6 +254,21 @@ impl_intern!(UnionId, UnionLoc, intern_union, lookup_intern_union); pub type EnumLoc = ItemLoc; impl_intern!(EnumId, EnumLoc, intern_enum, lookup_intern_enum); +impl EnumId { + #[inline] + pub fn enum_variants(self, db: &dyn DefDatabase) -> &EnumVariants { + &self.enum_variants_with_diagnostics(db).0 + } + + #[inline] + pub fn enum_variants_with_diagnostics( + self, + db: &dyn DefDatabase, + ) -> &(EnumVariants, Option>) { + EnumVariants::of(db, self) + } +} + type ConstLoc = AssocItemLoc; impl_intern!(ConstId, ConstLoc, intern_const, lookup_intern_const); diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs index 29f94ac2dca13..3a2faae366fd2 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs @@ -995,9 +995,8 @@ impl<'db> DefCollector<'db> { Some(ModuleDefId::AdtId(AdtId::EnumId(e))) => { cov_mark::hit!(glob_enum); // glob import from enum => just import all the variants - let resolutions = self - .db - .enum_variants(e) + let resolutions = e + .enum_variants(self.db) .variants .iter() .map(|&(variant, ref name, _)| { diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/path_resolution.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/path_resolution.rs index e0e32a777356c..ca39173d47716 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/path_resolution.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/path_resolution.rs @@ -528,8 +528,8 @@ impl DefMap { // enum variant cov_mark::hit!(can_import_enum_variant); - let res = db - .enum_variants(e) + let res = e + .enum_variants(db) .variants .iter() .find(|(_, name, _)| name == segment) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/incremental.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/incremental.rs index 858aa055edfc9..77e706caed7ad 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/incremental.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/incremental.rs @@ -172,8 +172,7 @@ fn no() {} "ast_id_map_shim", "parse_shim", "real_span_map_shim", - "enum_variants_shim", - "enum_variants_with_diagnostics_shim", + "of_", ] "#]], expect![[r#" @@ -182,7 +181,7 @@ fn no() {} "ast_id_map_shim", "file_item_tree_query", "real_span_map_shim", - "enum_variants_with_diagnostics_shim", + "of_", ] "#]], ); diff --git a/src/tools/rust-analyzer/crates/hir-def/src/signatures.rs b/src/tools/rust-analyzer/crates/hir-def/src/signatures.rs index b7d29f54d08ee..c808079011788 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/signatures.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/signatures.rs @@ -884,11 +884,13 @@ pub struct EnumVariants { pub variants: Box<[(EnumVariantId, Name, FieldsShape)]>, } +#[salsa::tracked] impl EnumVariants { - pub(crate) fn enum_variants_query( + #[salsa::tracked(returns(ref))] + pub(crate) fn of( db: &dyn DefDatabase, e: EnumId, - ) -> (Arc, Option>>) { + ) -> (EnumVariants, Option>) { let loc = e.lookup(db); let source = loc.source(db); let ast_id_map = db.ast_id_map(source.file_id); @@ -898,7 +900,7 @@ impl EnumVariants { let cfg_options = loc.container.krate.cfg_options(db); let mut index = 0; let Some(variants) = source.value.variant_list() else { - return (Arc::new(EnumVariants { variants: Box::default() }), None); + return (EnumVariants { variants: Box::default() }, None); }; let variants = variants .variants() @@ -926,12 +928,11 @@ impl EnumVariants { }) .collect(); - ( - Arc::new(EnumVariants { variants }), - diagnostics.is_empty().not().then(|| Arc::new(diagnostics)), - ) + (EnumVariants { variants }, diagnostics.is_empty().not().then_some(diagnostics)) } +} +impl EnumVariants { pub fn variant(&self, name: &Name) -> Option { self.variants.iter().find_map(|(v, n, _)| if n == name { Some(*v) } else { None }) } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs index f658e23665895..cf4392451375a 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs @@ -823,8 +823,8 @@ pub(crate) fn adt_datum_query( (rust_ir::AdtKind::Struct, vec![variant_id_to_fields(id.into())]) } hir_def::AdtId::EnumId(id) => { - let variants = db - .enum_variants(id) + let variants = id + .enum_variants(db) .variants .iter() .map(|&(variant_id, _, _)| variant_id_to_fields(variant_id.into())) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs b/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs index f903b06d65e77..24530a5f67ce8 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs @@ -286,7 +286,7 @@ pub(crate) fn const_eval_discriminant_variant( let value = match prev_idx { Some(prev_idx) => { 1 + db.const_eval_discriminant( - db.enum_variants(loc.parent).variants[prev_idx as usize].0, + loc.parent.enum_variants(db).variants[prev_idx as usize].0, )? } _ => 0, diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check.rs index fae129fddbfe5..1873f12fb7cb4 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check.rs @@ -395,7 +395,7 @@ impl<'a> DeclValidator<'a> { /// Check incorrect names for enum variants. fn validate_enum_variants(&mut self, enum_id: EnumId) { - let data = self.db.enum_variants(enum_id); + let data = enum_id.enum_variants(self.db); for (variant_id, _, _) in data.variants.iter() { self.validate_enum_variant_fields(*variant_id); diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs index 9eb7ffe1c719b..df2eb410b996e 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs @@ -642,7 +642,7 @@ fn missing_match_arms<'p>( } let non_empty_enum = match scrut_ty.as_adt() { - Some((AdtId::EnumId(e), _)) => !cx.db.enum_variants(e).variants.is_empty(), + Some((AdtId::EnumId(e), _)) => !e.enum_variants(cx.db).variants.is_empty(), _ => false, }; let display_target = DisplayTarget::from_crate(cx.db, krate); diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check.rs index 7df22a45cb4ef..916876d4ac956 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check.rs @@ -328,7 +328,7 @@ impl HirDisplay for Pat { write!( f, "{}", - f.db.enum_variants(loc.parent).variants[loc.index as usize] + loc.parent.enum_variants(f.db).variants[loc.index as usize] .1 .display(f.db, f.edition()) )?; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs index 0914b5aac5070..2873a3e09e7dc 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs @@ -50,7 +50,7 @@ impl EnumVariantContiguousIndex { } fn to_enum_variant_id(self, db: &dyn HirDatabase, eid: EnumId) -> EnumVariantId { - db.enum_variants(eid).variants[self.0].0 + eid.enum_variants(db).variants[self.0].0 } } @@ -458,7 +458,7 @@ impl PatCx for MatchCheckCtx<'_> { TyKind::Scalar(Scalar::Int(..) | Scalar::Uint(..)) => unhandled(), TyKind::Array(..) | TyKind::Slice(..) => unhandled(), &TyKind::Adt(AdtId(adt @ hir_def::AdtId::EnumId(enum_id)), ref subst) => { - let enum_data = cx.db.enum_variants(enum_id); + let enum_data = enum_id.enum_variants(cx.db); let is_declared_nonexhaustive = cx.is_foreign_non_exhaustive(adt); if enum_data.variants.is_empty() && !is_declared_nonexhaustive { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs index f210dd8799f90..da21f08a1e1da 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs @@ -914,7 +914,7 @@ fn render_const_scalar( write!( f, "{}", - f.db.enum_variants(loc.parent).variants[loc.index as usize] + loc.parent.enum_variants(f.db).variants[loc.index as usize] .1 .display(f.db, f.edition()) )?; @@ -1208,7 +1208,7 @@ impl HirDisplay for Ty { write!( f, "{}", - db.enum_variants(loc.parent).variants[loc.index as usize] + loc.parent.enum_variants(db).variants[loc.index as usize] .1 .display(db, f.edition()) )? diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/drop.rs b/src/tools/rust-analyzer/crates/hir-ty/src/drop.rs index b9b0f9828661b..5577be890da34 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/drop.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/drop.rs @@ -67,8 +67,8 @@ pub(crate) fn has_drop_glue(db: &dyn HirDatabase, ty: Ty, env: Arc DropGlue::None, - AdtId::EnumId(id) => db - .enum_variants(id) + AdtId::EnumId(id) => id + .enum_variants(db) .variants .iter() .map(|&(variant, _, _)| { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs index 14eb716075303..80478f19371bb 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs @@ -1673,7 +1673,7 @@ impl<'db> InferenceContext<'db> { // If we can resolve to an enum variant, it takes priority over associated type // of the same name. if let Some((AdtId::EnumId(id), _)) = ty.as_adt() { - let enum_data = self.db.enum_variants(id); + let enum_data = id.enum_variants(self.db); if let Some(variant) = enum_data.variant(current_segment.name) { return if remaining_segments.len() == 1 { (ty, Some(variant.into())) @@ -1792,7 +1792,7 @@ impl<'db> InferenceContext<'db> { let segment = path.segments().last().unwrap(); // this could be an enum variant or associated type if let Some((AdtId::EnumId(enum_id), _)) = ty.as_adt() { - let enum_data = self.db.enum_variants(enum_id); + let enum_data = enum_id.enum_variants(self.db); if let Some(variant) = enum_data.variant(segment) { return (ty, Some(variant.into())); } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/cast.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/cast.rs index 10d85792c9d60..8d345defdc105 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/cast.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/cast.rs @@ -43,7 +43,7 @@ impl CastTy { let (AdtId::EnumId(id), _) = t.as_adt()? else { return None; }; - let enum_data = table.db.enum_variants(id); + let enum_data = id.enum_variants(table.db); if enum_data.is_payload_free(table.db) { Some(Self::Int(Int::CEnum)) } else { None } } TyKind::Raw(m, ty) => Some(Self::Ptr(ty.clone(), *m)), diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs index bd57ca891620a..d1432cacf8d83 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs @@ -1360,7 +1360,7 @@ impl InferenceContext<'_> { if let Some(variant) = self.result.variant_resolution_for_pat(p) { let adt = variant.adt_id(self.db); let is_multivariant = match adt { - hir_def::AdtId::EnumId(e) => self.db.enum_variants(e).variants.len() != 1, + hir_def::AdtId::EnumId(e) => e.enum_variants(self.db).variants.len() != 1, _ => false, }; if is_multivariant { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs index 9d4bbe53464dc..c327c13b66419 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs @@ -397,7 +397,7 @@ impl InferenceContext<'_> { Some((AdtId::EnumId(e), subst)) => (e, subst), _ => return None, }; - let enum_data = self.db.enum_variants(enum_id); + let enum_data = enum_id.enum_variants(self.db); let variant = enum_data.variant(name)?; self.write_variant_resolution(id, variant.into()); Some((ValueNs::EnumVariantId(variant), subst.clone())) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/inhabitedness.rs b/src/tools/rust-analyzer/crates/hir-ty/src/inhabitedness.rs index 8be812d8d5e4b..79a99321f1010 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/inhabitedness.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/inhabitedness.rs @@ -113,7 +113,7 @@ impl UninhabitedFrom<'_> { AdtId::UnionId(_) => CONTINUE_OPAQUELY_INHABITED, AdtId::StructId(s) => self.visit_variant(s.into(), subst), AdtId::EnumId(e) => { - let enum_data = self.db.enum_variants(e); + let enum_data = e.enum_variants(self.db); for &(variant, _, _) in enum_data.variants.iter() { let variant_inhabitedness = self.visit_variant(variant.into(), subst); diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/layout/adt.rs b/src/tools/rust-analyzer/crates/hir-ty/src/layout/adt.rs index a886c33d157b0..dff986fec3c3c 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/layout/adt.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/layout/adt.rs @@ -56,7 +56,7 @@ pub fn layout_of_adt_query( (r, data.repr.unwrap_or_default(), false) } AdtId::EnumId(e) => { - let variants = db.enum_variants(e); + let variants = e.enum_variants(db); let r = variants .variants .iter() @@ -82,7 +82,7 @@ pub fn layout_of_adt_query( |min, max| repr_discr(dl, &repr, min, max).unwrap_or((Integer::I8, false)), variants.iter_enumerated().filter_map(|(id, _)| { let AdtId::EnumId(e) = def else { return None }; - let d = db.const_eval_discriminant(db.enum_variants(e).variants[id.0].0).ok()?; + let d = db.const_eval_discriminant(e.enum_variants(db).variants[id.0].0).ok()?; Some((id, d)) }), // FIXME: The current code for niche-filling relies on variant indices diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs index da6e4e5d8a15b..a8156ec375bcf 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs @@ -1631,7 +1631,7 @@ impl Evaluator<'_> { Variants::Empty => unreachable!(), Variants::Single { index } => { let r = - self.const_eval_discriminant(self.db.enum_variants(e).variants[index.0].0)?; + self.const_eval_discriminant(e.enum_variants(self.db).variants[index.0].0)?; Ok(r) } Variants::Multiple { tag, tag_encoding, variants, .. } => { @@ -1656,7 +1656,7 @@ impl Evaluator<'_> { .unwrap_or(*untagged_variant) .0; let result = - self.const_eval_discriminant(self.db.enum_variants(e).variants[idx].0)?; + self.const_eval_discriminant(e.enum_variants(self.db).variants[idx].0)?; Ok(result) } } @@ -2775,8 +2775,8 @@ impl Evaluator<'_> { let name = format!( "{}::{}", self.db.enum_signature(loc.parent).name.display(db, edition), - self.db - .enum_variants(loc.parent) + loc.parent + .enum_variants(self.db) .variant_name_by_id(variant) .unwrap() .display(db, edition), diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs index ef1f215500c24..71e038b92f085 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs @@ -1925,8 +1925,8 @@ impl<'ctx> MirLowerCtx<'ctx> { let name = format!( "{}::{}", self.db.enum_signature(loc.parent).name.display(db, edition), - self.db - .enum_variants(loc.parent) + loc.parent + .enum_variants(self.db) .variant_name_by_id(variant) .unwrap() .display(db, edition), @@ -2155,7 +2155,7 @@ pub fn mir_body_query(db: &dyn HirDatabase, def: DefWithBodyId) -> Result { let loc = it.lookup(db); - db.enum_variants(loc.parent).variants[loc.index as usize] + loc.parent.enum_variants(db).variants[loc.index as usize] .1 .display(db, edition) .to_string() diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/pretty.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/pretty.rs index 91dc2627d1847..8764e48b53840 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/pretty.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/pretty.rs @@ -68,7 +68,8 @@ impl MirBody { this, "enum {}::{} = ", db.enum_signature(loc.parent).name.display(db, edition), - db.enum_variants(loc.parent) + loc.parent + .enum_variants(db) .variant_name_by_id(id) .unwrap() .display(db, edition), @@ -335,7 +336,7 @@ impl<'a> MirPrettyCtx<'a> { w!( this, " as {}).{}", - this.db.enum_variants(loc.parent).variants[loc.index as usize] + loc.parent.enum_variants(this.db).variants[loc.index as usize] .1 .display(this.db, this.display_target.edition), name.display(this.db, this.display_target.edition) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests.rs index 48af7b2e32a2e..f2812570ed5a1 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/tests.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests.rs @@ -479,7 +479,7 @@ pub(crate) fn visit_module( visit_body(db, &body, cb); } ModuleDefId::AdtId(hir_def::AdtId::EnumId(it)) => { - db.enum_variants(it).variants.iter().for_each(|&(it, _, _)| { + it.enum_variants(db).variants.iter().for_each(|&(it, _, _)| { let body = db.body(it.into()); cb(it.into()); visit_body(db, &body, cb); diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tls.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tls.rs index f5911e2161d0c..f53409af2b30c 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/tls.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/tls.rs @@ -109,7 +109,7 @@ impl DebugContext<'_> { CallableDefId::StructId(s) => self.0.struct_signature(s).name.clone(), CallableDefId::EnumVariantId(e) => { let loc = e.lookup(self.0); - self.0.enum_variants(loc.parent).variants[loc.index as usize].1.clone() + loc.parent.enum_variants(self.0).variants[loc.index as usize].1.clone() } }; match def { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs b/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs index f797e60b05e71..867c7ea087857 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs @@ -355,7 +355,7 @@ pub(crate) fn detect_variant_from_bytes<'a>( let (var_id, var_layout) = match &layout.variants { hir_def::layout::Variants::Empty => unreachable!(), hir_def::layout::Variants::Single { index } => { - (db.enum_variants(e).variants[index.0].0, layout) + (e.enum_variants(db).variants[index.0].0, layout) } hir_def::layout::Variants::Multiple { tag, tag_encoding, variants, .. } => { let size = tag.size(target_data_layout).bytes_usize(); @@ -365,7 +365,7 @@ pub(crate) fn detect_variant_from_bytes<'a>( TagEncoding::Direct => { let (var_idx, layout) = variants.iter_enumerated().find_map(|(var_idx, v)| { - let def = db.enum_variants(e).variants[var_idx.0].0; + let def = e.enum_variants(db).variants[var_idx.0].0; (db.const_eval_discriminant(def) == Ok(tag)).then_some((def, v)) })?; (var_idx, layout) @@ -378,7 +378,7 @@ pub(crate) fn detect_variant_from_bytes<'a>( .filter(|x| x != untagged_variant) .nth(candidate_tag) .unwrap_or(*untagged_variant); - (db.enum_variants(e).variants[variant.0].0, &variants[variant]) + (e.enum_variants(db).variants[variant.0].0, &variants[variant]) } } } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/variance.rs b/src/tools/rust-analyzer/crates/hir-ty/src/variance.rs index 62478d4fd86c5..08a215fecf623 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/variance.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/variance.rs @@ -213,7 +213,7 @@ impl Context<'_> { AdtId::StructId(s) => add_constraints_from_variant(VariantId::StructId(s)), AdtId::UnionId(u) => add_constraints_from_variant(VariantId::UnionId(u)), AdtId::EnumId(e) => { - db.enum_variants(e).variants.iter().for_each(|&(variant, _, _)| { + e.enum_variants(db).variants.iter().for_each(|&(variant, _, _)| { add_constraints_from_variant(VariantId::EnumVariantId(variant)) }); } diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs index c746b88c5b117..597da0a3cbd85 100644 --- a/src/tools/rust-analyzer/crates/hir/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs @@ -688,7 +688,7 @@ 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 (variants, diagnostics) = db.enum_variants_with_diagnostics(e.id); + 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); if let Some(diagnostics) = &diagnostics { @@ -1504,11 +1504,11 @@ impl Enum { } pub fn variants(self, db: &dyn HirDatabase) -> Vec { - db.enum_variants(self.id).variants.iter().map(|&(id, _, _)| Variant { id }).collect() + self.id.enum_variants(db).variants.iter().map(|&(id, _, _)| Variant { id }).collect() } pub fn num_variants(self, db: &dyn HirDatabase) -> usize { - db.enum_variants(self.id).variants.len() + self.id.enum_variants(db).variants.len() } pub fn repr(self, db: &dyn HirDatabase) -> Option { @@ -1606,7 +1606,7 @@ impl Variant { pub fn name(self, db: &dyn HirDatabase) -> Name { let lookup = self.id.lookup(db); let enum_ = lookup.parent; - db.enum_variants(enum_).variants[lookup.index as usize].1.clone() + enum_.enum_variants(db).variants[lookup.index as usize].1.clone() } pub fn fields(self, db: &dyn HirDatabase) -> Vec { diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics/child_by_source.rs b/src/tools/rust-analyzer/crates/hir/src/semantics/child_by_source.rs index ea44451a8ee4a..0d0bbe367ecd1 100644 --- a/src/tools/rust-analyzer/crates/hir/src/semantics/child_by_source.rs +++ b/src/tools/rust-analyzer/crates/hir/src/semantics/child_by_source.rs @@ -205,7 +205,7 @@ impl ChildBySource for EnumId { let ast_id_map = db.ast_id_map(loc.id.file_id); - db.enum_variants(*self).variants.iter().for_each(|&(variant, _, _)| { + 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); diff --git a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs index 09b61524d6092..3273358b78e9d 100644 --- a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs +++ b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs @@ -829,7 +829,7 @@ impl<'db> SourceAnalyzer<'db> { handle_variants(id.into(), subst, &mut container)? } AdtId::EnumId(id) => { - let variants = db.enum_variants(id); + let variants = id.enum_variants(db); let variant = variants.variant(&field_name.as_name())?; container = Either::Left((variant, subst.clone())); (Either::Left(Variant { id: variant }), id.into(), subst.clone()) From 1b3c370c13682d4bdfb110a19abc6b92e1e35486 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Sun, 15 Jun 2025 09:16:45 +0200 Subject: [PATCH 48/56] Replace unnecessary use of `MacroDefId` with `MacroId` --- src/tools/rust-analyzer/crates/hir-def/src/nameres.rs | 6 +++--- .../rust-analyzer/crates/hir-def/src/nameres/collector.rs | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs index 610bb6b00b024..0837308d5b607 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs @@ -62,8 +62,8 @@ use std::ops::Deref; use base_db::Crate; use hir_expand::{ - EditionedFileId, ErasedAstId, HirFileId, InFile, MacroCallId, MacroDefId, mod_path::ModPath, - name::Name, proc_macro::ProcMacroKind, + EditionedFileId, ErasedAstId, HirFileId, InFile, MacroCallId, mod_path::ModPath, name::Name, + proc_macro::ProcMacroKind, }; use intern::Symbol; use itertools::Itertools; @@ -189,7 +189,7 @@ pub struct DefMap { #[derive(Clone, Debug, PartialEq, Eq)] struct DefMapCrateData { /// Side table for resolving derive helpers. - exported_derives: FxHashMap>, + exported_derives: FxHashMap>, fn_proc_macro_mapping: FxHashMap, /// Custom attributes registered with `#![register_attr]`. diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs index 3a2faae366fd2..508fcc2fa513f 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs @@ -609,7 +609,7 @@ impl<'db> DefCollector<'db> { self.define_proc_macro(def.name.clone(), proc_macro_id); let crate_data = Arc::get_mut(&mut self.def_map.data).unwrap(); if let ProcMacroKind::Derive { helpers } = def.kind { - crate_data.exported_derives.insert(self.db.macro_def(proc_macro_id.into()), helpers); + crate_data.exported_derives.insert(proc_macro_id.into(), helpers); } crate_data.fn_proc_macro_mapping.insert(fn_id, proc_macro_id); } @@ -1345,7 +1345,7 @@ impl<'db> DefCollector<'db> { // Record its helper attributes. if def_id.krate != self.def_map.krate { let def_map = crate_def_map(self.db, def_id.krate); - if let Some(helpers) = def_map.data.exported_derives.get(&def_id) { + if let Some(helpers) = def_map.data.exported_derives.get(¯o_id) { self.def_map .derive_helpers_in_scope .entry(ast_id.ast_id.map(|it| it.upcast())) @@ -2425,7 +2425,7 @@ impl ModCollector<'_, '_> { Arc::get_mut(&mut self.def_collector.def_map.data) .unwrap() .exported_derives - .insert(self.def_collector.db.macro_def(macro_id.into()), helpers); + .insert(macro_id.into(), helpers); } } } From 12f81939a81a60f6a8858e149c826409644f7102 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Sun, 15 Jun 2025 09:40:02 +0200 Subject: [PATCH 49/56] Idiomatic salsa use for impl items query --- .../rust-analyzer/crates/hir-def/src/db.rs | 13 +------------ .../crates/hir-def/src/lang_item.rs | 2 +- .../rust-analyzer/crates/hir-def/src/lib.rs | 17 ++++++++++++++++- .../crates/hir-def/src/nameres/assoc.rs | 16 ++++++---------- .../hir-def/src/nameres/tests/incremental.rs | 1 - .../rust-analyzer/crates/hir-ty/src/chalk_db.rs | 6 +++--- .../crates/hir-ty/src/method_resolution.rs | 8 ++++---- .../rust-analyzer/crates/hir-ty/src/tests.rs | 2 +- src/tools/rust-analyzer/crates/hir/src/lib.rs | 12 ++++++------ .../crates/hir/src/semantics/child_by_source.rs | 2 +- .../rust-analyzer/crates/hir/src/symbols.rs | 2 +- 11 files changed, 40 insertions(+), 41 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/db.rs b/src/tools/rust-analyzer/crates/hir-def/src/db.rs index 2fc79c3809f6f..05fba1f7a1b48 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/db.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/db.rs @@ -25,11 +25,7 @@ use crate::{ import_map::ImportMap, item_tree::{ItemTree, file_item_tree_query}, lang_item::{self, LangItem}, - nameres::{ - assoc::{ImplItems, TraitItems}, - crate_def_map, - diagnostics::DefDiagnostics, - }, + nameres::{assoc::TraitItems, crate_def_map, diagnostics::DefDiagnostics}, signatures::{ ConstSignature, EnumSignature, FunctionSignature, ImplSignature, StaticSignature, StructSignature, TraitAliasSignature, TraitSignature, TypeAliasSignature, UnionSignature, @@ -120,13 +116,6 @@ pub trait DefDatabase: InternDatabase + ExpandDatabase + SourceDatabase { id: VariantId, ) -> (Arc, Arc); - #[salsa::transparent] - #[salsa::invoke(ImplItems::impl_items_query)] - fn impl_items(&self, e: ImplId) -> Arc; - - #[salsa::invoke(ImplItems::impl_items_with_diagnostics_query)] - fn impl_items_with_diagnostics(&self, e: ImplId) -> (Arc, DefDiagnostics); - #[salsa::transparent] #[salsa::invoke(TraitItems::trait_items_query)] fn trait_items(&self, e: TraitId) -> Arc; diff --git a/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs b/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs index c0e30ac79562f..faff7d036a289 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs @@ -96,7 +96,7 @@ pub fn crate_lang_items(db: &dyn DefDatabase, krate: Crate) -> Option { lang_items.collect_lang_item(db, f, LangItemTarget::Function) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs index be5bb57ade6d8..ed602d5198790 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs @@ -88,7 +88,10 @@ use crate::{ builtin_type::BuiltinType, db::DefDatabase, hir::generics::{LocalLifetimeParamId, LocalTypeOrConstParamId}, - nameres::{LocalDefMap, block_def_map, crate_def_map, crate_local_def_map}, + nameres::{ + LocalDefMap, assoc::ImplItems, block_def_map, crate_def_map, crate_local_def_map, + diagnostics::DefDiagnostics, + }, signatures::{EnumVariants, InactiveEnumVariantCode, VariantFields}, }; @@ -287,6 +290,18 @@ impl_intern!(TypeAliasId, TypeAliasLoc, intern_type_alias, lookup_intern_type_al type ImplLoc = ItemLoc; impl_intern!(ImplId, ImplLoc, intern_impl, lookup_intern_impl); +impl ImplId { + #[inline] + pub fn impl_items(self, db: &dyn DefDatabase) -> &ImplItems { + &self.impl_items_with_diagnostics(db).0 + } + + #[inline] + pub fn impl_items_with_diagnostics(self, db: &dyn DefDatabase) -> &(ImplItems, DefDiagnostics) { + ImplItems::of(db, self) + } +} + type UseLoc = ItemLoc; impl_intern!(UseId, UseLoc, intern_use, lookup_intern_use); diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/assoc.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/assoc.rs index cf123d14f502a..7aaa918d1c92a 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/assoc.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/assoc.rs @@ -100,16 +100,10 @@ pub struct ImplItems { pub macro_calls: ThinVec<(AstId, MacroCallId)>, } +#[salsa::tracked] impl ImplItems { - #[inline] - pub(crate) fn impl_items_query(db: &dyn DefDatabase, id: ImplId) -> Arc { - db.impl_items_with_diagnostics(id).0 - } - - pub(crate) fn impl_items_with_diagnostics_query( - db: &dyn DefDatabase, - id: ImplId, - ) -> (Arc, DefDiagnostics) { + #[salsa::tracked(returns(ref))] + pub fn of(db: &dyn DefDatabase, id: ImplId) -> (ImplItems, DefDiagnostics) { let _p = tracing::info_span!("impl_items_with_diagnostics_query").entered(); let ItemLoc { container: module_id, id: ast_id } = id.lookup(db); @@ -118,9 +112,11 @@ impl ImplItems { let source = ast_id.with_value(collector.ast_id_map.get(ast_id.value)).to_node(db); let (items, macro_calls, diagnostics) = collector.collect(source.assoc_item_list()); - (Arc::new(ImplItems { items, macro_calls }), DefDiagnostics::new(diagnostics)) + (ImplItems { items, macro_calls }, DefDiagnostics::new(diagnostics)) } +} +impl ImplItems { pub fn macro_calls(&self) -> impl Iterator, MacroCallId)> + '_ { self.macro_calls.iter().copied() } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/incremental.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/incremental.rs index 77e706caed7ad..ba75dca3d3de1 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/incremental.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/incremental.rs @@ -431,7 +431,6 @@ pub struct S {} "parse_shim", "real_span_map_shim", "macro_def_shim", - "macro_def_shim", "file_item_tree_query", "ast_id_map_shim", "parse_macro_expansion_shim", diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs index cf4392451375a..79454428112ff 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs @@ -63,7 +63,7 @@ impl chalk_solve::RustIrDatabase for ChalkContext<'_> { ) -> Option> { let alias_id = from_assoc_type_id(assoc_type_id); let trait_sig = self.db.type_alias_signature(alias_id); - self.db.impl_items(hir_def::ImplId::from_chalk(self.db, impl_id)).items.iter().find_map( + hir_def::ImplId::from_chalk(self.db, impl_id).impl_items(self.db).items.iter().find_map( |(name, item)| match item { AssocItemId::TypeAliasId(alias) if &trait_sig.name == name => { Some(TypeAliasAsValue(*alias).to_chalk(self.db)) @@ -880,8 +880,8 @@ fn impl_def_datum(db: &dyn HirDatabase, krate: Crate, impl_id: hir_def::ImplId) let impl_datum_bound = rust_ir::ImplDatumBound { trait_ref, where_clauses }; let trait_data = db.trait_items(trait_); - let associated_ty_value_ids = db - .impl_items(impl_id) + let associated_ty_value_ids = impl_id + .impl_items(db) .items .iter() .filter_map(|(_, item)| match item { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs b/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs index 3b295d41e6e31..70c89275a5c58 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs @@ -790,7 +790,7 @@ fn find_matching_impl( mut impls: impl Iterator, mut table: InferenceTable<'_>, actual_trait_ref: TraitRef, -) -> Option<(Arc, Substitution)> { +) -> Option<(&ImplItems, Substitution)> { let db = table.db; impls.find_map(|impl_| { table.run_in_snapshot(|table| { @@ -811,7 +811,7 @@ fn find_matching_impl( let goal = crate::Goal::all(Interner, wcs); table.try_obligation(goal.clone())?; table.register_obligation(goal); - Some((db.impl_items(impl_), table.resolve_completely(impl_substs))) + Some((impl_.impl_items(db), table.resolve_completely(impl_substs))) }) }) } @@ -875,7 +875,7 @@ fn is_inherent_impl_coherent( _ => false, }; - let items = db.impl_items(impl_id); + let items = impl_id.impl_items(db); rustc_has_incoherent_inherent_impls && !items.items.is_empty() && items.items.iter().all(|&(_, assoc)| match assoc { @@ -1462,7 +1462,7 @@ fn iterate_inherent_methods( callback: &mut dyn FnMut(ReceiverAdjustments, AssocItemId, bool) -> ControlFlow<()>, ) -> ControlFlow<()> { for &impl_id in impls.for_self_ty(self_ty) { - for &(ref item_name, item) in table.db.impl_items(impl_id).items.iter() { + for &(ref item_name, item) in impl_id.impl_items(table.db).items.iter() { let visible = match is_valid_impl_method_candidate( table, self_ty, diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests.rs index f2812570ed5a1..9ca6ee476c653 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/tests.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests.rs @@ -437,7 +437,7 @@ pub(crate) fn visit_module( ) { visit_scope(db, crate_def_map, &crate_def_map[module_id].scope, cb); for impl_id in crate_def_map[module_id].scope.impls() { - let impl_data = db.impl_items(impl_id); + let impl_data = impl_id.impl_items(db); for &(_, item) in impl_data.items.iter() { match item { AssocItemId::FunctionId(it) => { diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs index 597da0a3cbd85..2614a276bcce4 100644 --- a/src/tools/rust-analyzer/crates/hir/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs @@ -760,7 +760,7 @@ impl Module { let ast_id_map = db.ast_id_map(file_id); - for diag in db.impl_items_with_diagnostics(impl_def.id).1.iter() { + for diag in impl_def.id.impl_items_with_diagnostics(db).1.iter() { emit_def_diagnostic(db, acc, diag, edition); } @@ -824,7 +824,7 @@ impl Module { AssocItemId::ConstId(id) => !db.const_signature(id).has_body(), AssocItemId::TypeAliasId(it) => db.type_alias_signature(it).ty.is_none(), }); - impl_assoc_items_scratch.extend(db.impl_items(impl_def.id).items.iter().cloned()); + impl_assoc_items_scratch.extend(impl_def.id.impl_items(db).items.iter().cloned()); let redundant = impl_assoc_items_scratch .iter() @@ -912,7 +912,7 @@ impl Module { &source_map, ); - for &(_, item) in db.impl_items(impl_def.id).items.iter() { + for &(_, item) in impl_def.id.impl_items(db).items.iter() { AssocItem::from(item).diagnostics(db, acc, style_lints); } } @@ -4413,7 +4413,7 @@ impl Impl { } pub fn items(self, db: &dyn HirDatabase) -> Vec { - db.impl_items(self.id).items.iter().map(|&(_, it)| it.into()).collect() + self.id.impl_items(db).items.iter().map(|&(_, it)| it.into()).collect() } pub fn is_negative(self, db: &dyn HirDatabase) -> bool { @@ -4462,7 +4462,7 @@ impl Impl { } fn all_macro_calls(&self, db: &dyn HirDatabase) -> Box<[(AstId, MacroCallId)]> { - db.impl_items(self.id).macro_calls.to_vec().into_boxed_slice() + self.id.impl_items(db).macro_calls.to_vec().into_boxed_slice() } } @@ -5271,7 +5271,7 @@ impl Type { let impls = db.inherent_impls_in_crate(krate); for impl_def in impls.for_self_ty(&self.ty) { - for &(_, item) in db.impl_items(*impl_def).items.iter() { + for &(_, item) in impl_def.impl_items(db).items.iter() { if callback(item) { return; } diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics/child_by_source.rs b/src/tools/rust-analyzer/crates/hir/src/semantics/child_by_source.rs index 0d0bbe367ecd1..fedd8239d031e 100644 --- a/src/tools/rust-analyzer/crates/hir/src/semantics/child_by_source.rs +++ b/src/tools/rust-analyzer/crates/hir/src/semantics/child_by_source.rs @@ -61,7 +61,7 @@ impl ChildBySource for TraitId { impl ChildBySource for ImplId { fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap, file_id: HirFileId) { - let data = db.impl_items(*self); + let data = self.impl_items(db); data.macro_calls().filter(|(ast_id, _)| ast_id.file_id == file_id).for_each( |(ast_id, call_id)| { let ptr = ast_id.to_ptr(db); diff --git a/src/tools/rust-analyzer/crates/hir/src/symbols.rs b/src/tools/rust-analyzer/crates/hir/src/symbols.rs index a0815c3131b1f..05f4a830da5e4 100644 --- a/src/tools/rust-analyzer/crates/hir/src/symbols.rs +++ b/src/tools/rust-analyzer/crates/hir/src/symbols.rs @@ -321,7 +321,7 @@ impl<'a> SymbolCollector<'a> { .to_smolstr(), ); self.with_container_name(impl_name, |s| { - for &(ref name, assoc_item_id) in &self.db.impl_items(impl_id).items { + for &(ref name, assoc_item_id) in &impl_id.impl_items(self.db).items { s.push_assoc_item(assoc_item_id, name, None) } }) From 2da8d5892fec1a3da2d58d62ad77ca5b1cf199c0 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Sun, 15 Jun 2025 09:43:42 +0200 Subject: [PATCH 50/56] Idiomatic salsa use for extern block abi query --- src/tools/rust-analyzer/crates/hir-def/src/db.rs | 5 +---- src/tools/rust-analyzer/crates/hir-def/src/lib.rs | 10 +++++++++- .../rust-analyzer/crates/hir-def/src/signatures.rs | 2 +- .../rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs | 6 ++---- .../crates/hir-ty/src/tests/incremental.rs | 4 ++-- src/tools/rust-analyzer/crates/hir-ty/src/utils.rs | 2 +- 6 files changed, 16 insertions(+), 13 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/db.rs b/src/tools/rust-analyzer/crates/hir-def/src/db.rs index 05fba1f7a1b48..f5ade8bc6f98d 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/db.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/db.rs @@ -5,7 +5,7 @@ use hir_expand::{ EditionedFileId, HirFileId, InFile, Lookup, MacroCallId, MacroDefId, MacroDefKind, db::ExpandDatabase, }; -use intern::{Symbol, sym}; +use intern::sym; use la_arena::ArenaMap; use syntax::{AstPtr, ast}; use triomphe::Arc; @@ -238,9 +238,6 @@ pub trait DefDatabase: InternDatabase + ExpandDatabase + SourceDatabase { e: TypeAliasId, ) -> (Arc, Arc); - #[salsa::invoke(crate::signatures::extern_block_abi_query)] - fn extern_block_abi(&self, extern_block: ExternBlockId) -> Option; - // endregion:data #[salsa::invoke(Body::body_with_source_map_query)] diff --git a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs index ed602d5198790..68f0a4b26eeee 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs @@ -49,7 +49,7 @@ pub mod find_path; pub mod import_map; pub mod visibility; -use intern::{Interned, sym}; +use intern::{Interned, Symbol, sym}; pub use rustc_abi as layout; use thin_vec::ThinVec; use triomphe::Arc; @@ -311,6 +311,14 @@ impl_intern!(ExternCrateId, ExternCrateLoc, intern_extern_crate, lookup_intern_e type ExternBlockLoc = ItemLoc; impl_intern!(ExternBlockId, ExternBlockLoc, intern_extern_block, lookup_intern_extern_block); +#[salsa::tracked] +impl ExternBlockId { + #[salsa::tracked] + pub fn abi(self, db: &dyn DefDatabase) -> Option { + signatures::extern_block_abi(db, self) + } +} + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct EnumVariantLoc { pub id: AstId, diff --git a/src/tools/rust-analyzer/crates/hir-def/src/signatures.rs b/src/tools/rust-analyzer/crates/hir-def/src/signatures.rs index c808079011788..377a545ebf4b5 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/signatures.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/signatures.rs @@ -965,7 +965,7 @@ impl EnumVariants { } } -pub(crate) fn extern_block_abi_query( +pub(crate) fn extern_block_abi( db: &dyn DefDatabase, extern_block: ExternBlockId, ) -> Option { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs index 8d428dd6d049e..6ebde0133444e 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs @@ -65,7 +65,7 @@ impl Evaluator<'_> { Some(abi) => *abi == sym::rust_dash_intrinsic, None => match def.lookup(self.db).container { hir_def::ItemContainerId::ExternBlockId(block) => { - self.db.extern_block_abi(block) == Some(sym::rust_dash_intrinsic) + block.abi(self.db) == Some(sym::rust_dash_intrinsic) } _ => false, }, @@ -84,9 +84,7 @@ impl Evaluator<'_> { ); } let is_extern_c = match def.lookup(self.db).container { - hir_def::ItemContainerId::ExternBlockId(block) => { - self.db.extern_block_abi(block) == Some(sym::C) - } + hir_def::ItemContainerId::ExternBlockId(block) => block.abi(self.db) == Some(sym::C), _ => false, }; if is_extern_c { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/incremental.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/incremental.rs index b45d8babd4e0d..905fd8a3bca09 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/incremental.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/incremental.rs @@ -571,7 +571,7 @@ fn main() { "body_shim", "body_with_source_map_shim", "attrs_shim", - "impl_items_with_diagnostics_shim", + "of_", "infer_shim", "trait_signature_shim", "trait_signature_with_source_map_shim", @@ -678,7 +678,7 @@ fn main() { "body_with_source_map_shim", "attrs_shim", "body_shim", - "impl_items_with_diagnostics_shim", + "of_", "infer_shim", "attrs_shim", "trait_signature_with_source_map_shim", diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs b/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs index 867c7ea087857..4c8e635eff986 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs @@ -293,7 +293,7 @@ pub fn is_fn_unsafe_to_call( let loc = func.lookup(db); match loc.container { hir_def::ItemContainerId::ExternBlockId(block) => { - let is_intrinsic_block = db.extern_block_abi(block) == Some(sym::rust_dash_intrinsic); + let is_intrinsic_block = block.abi(db) == Some(sym::rust_dash_intrinsic); if is_intrinsic_block { // legacy intrinsics // extern "rust-intrinsic" intrinsics are unsafe unless they have the rustc_safe_intrinsic attribute From 8c9c8ada40ac7f4c96f049eaaf4758ecd8a42136 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Sun, 15 Jun 2025 09:59:56 +0200 Subject: [PATCH 51/56] Unify assoc item visibility queries --- .../rust-analyzer/crates/hir-def/src/db.rs | 20 ++--- .../rust-analyzer/crates/hir-def/src/lib.rs | 2 +- .../crates/hir-def/src/visibility.rs | 87 ++++++++----------- .../crates/hir-ty/src/method_resolution.rs | 4 +- src/tools/rust-analyzer/crates/hir/src/lib.rs | 22 ++--- 5 files changed, 58 insertions(+), 77 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/db.rs b/src/tools/rust-analyzer/crates/hir-def/src/db.rs index f5ade8bc6f98d..c618e4bdce7d1 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/db.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/db.rs @@ -11,10 +11,10 @@ use syntax::{AstPtr, ast}; use triomphe::Arc; use crate::{ - AttrDefId, 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, + AssocItemId, AttrDefId, 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, TraitAliasId, TraitAliasLoc, TraitId, TraitLoc, TypeAliasId, TypeAliasLoc, UnionId, UnionLoc, UseId, UseLoc, VariantId, attr::{Attrs, AttrsWithOwner}, @@ -298,16 +298,8 @@ pub trait DefDatabase: InternDatabase + ExpandDatabase + SourceDatabase { #[salsa::invoke(visibility::field_visibilities_query)] fn field_visibilities(&self, var: VariantId) -> Arc>; - // FIXME: unify function_visibility and const_visibility? - - #[salsa::invoke(visibility::function_visibility_query)] - fn function_visibility(&self, def: FunctionId) -> Visibility; - - #[salsa::invoke(visibility::const_visibility_query)] - fn const_visibility(&self, def: ConstId) -> Visibility; - - #[salsa::invoke(visibility::type_alias_visibility_query)] - fn type_alias_visibility(&self, def: TypeAliasId) -> Visibility; + #[salsa::invoke(visibility::assoc_visibility_query)] + fn assoc_visibility(&self, def: AssocItemId) -> Visibility; // endregion:visibilities diff --git a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs index 68f0a4b26eeee..0cd7e894327c9 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs @@ -793,7 +793,7 @@ impl DefWithBodyId { } } -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, salsa_macros::Supertype)] pub enum AssocItemId { FunctionId(FunctionId), ConstId(ConstId), diff --git a/src/tools/rust-analyzer/crates/hir-def/src/visibility.rs b/src/tools/rust-analyzer/crates/hir-def/src/visibility.rs index 14d67ea804ff2..aea2ac550e3e0 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/visibility.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/visibility.rs @@ -8,12 +8,8 @@ use syntax::ast::{self, HasVisibility}; use triomphe::Arc; use crate::{ - ConstId, FunctionId, HasModule, ItemContainerId, LocalFieldId, LocalModuleId, ModuleId, - TraitId, TypeAliasId, VariantId, - db::DefDatabase, - nameres::DefMap, - resolver::{HasResolver, Resolver}, - src::HasSource, + AssocItemId, HasModule, ItemContainerId, LocalFieldId, LocalModuleId, ModuleId, TraitId, + VariantId, db::DefDatabase, nameres::DefMap, resolver::HasResolver, src::HasSource, }; pub use crate::item_tree::{RawVisibility, VisibilityExplicitness}; @@ -225,63 +221,56 @@ pub(crate) fn field_visibilities_query( pub fn visibility_from_ast( db: &dyn DefDatabase, - resolver: &Resolver<'_>, + has_resolver: impl HasResolver, ast_vis: InFile>, ) -> Visibility { let mut span_map = None; let raw_vis = crate::item_tree::visibility_from_ast(db, ast_vis.value, &mut |range| { span_map.get_or_insert_with(|| db.span_map(ast_vis.file_id)).span_for_range(range).ctx }); - Visibility::resolve(db, resolver, &raw_vis) -} - -fn trait_item_visibility( - db: &dyn DefDatabase, - resolver: &Resolver<'_>, - container: ItemContainerId, -) -> Option { - match container { - ItemContainerId::TraitId(trait_) => Some(trait_visibility(db, resolver, trait_)), - _ => None, + if raw_vis == RawVisibility::Public { + return Visibility::Public; } -} -/// Resolve visibility of a function. -pub(crate) fn function_visibility_query(db: &dyn DefDatabase, def: FunctionId) -> Visibility { - let loc = def.lookup(db); - let resolver = def.resolver(db); - trait_item_visibility(db, &resolver, loc.container).unwrap_or_else(|| { - let source = loc.source(db); - visibility_from_ast(db, &resolver, source.map(|src| src.visibility())) - }) + Visibility::resolve(db, &has_resolver.resolver(db), &raw_vis) } -/// Resolve visibility of a const. -pub(crate) fn const_visibility_query(db: &dyn DefDatabase, def: ConstId) -> Visibility { - let loc = def.lookup(db); - let resolver = def.resolver(db); - trait_item_visibility(db, &resolver, loc.container).unwrap_or_else(|| { - let source = loc.source(db); - visibility_from_ast(db, &resolver, source.map(|src| src.visibility())) - }) +/// Resolve visibility of a type alias. +pub(crate) fn assoc_visibility_query(db: &dyn DefDatabase, def: AssocItemId) -> Visibility { + match def { + AssocItemId::FunctionId(function_id) => { + let loc = function_id.lookup(db); + trait_item_visibility(db, loc.container).unwrap_or_else(|| { + let source = loc.source(db); + visibility_from_ast(db, function_id, source.map(|src| src.visibility())) + }) + } + AssocItemId::ConstId(const_id) => { + let loc = const_id.lookup(db); + trait_item_visibility(db, loc.container).unwrap_or_else(|| { + let source = loc.source(db); + visibility_from_ast(db, const_id, source.map(|src| src.visibility())) + }) + } + AssocItemId::TypeAliasId(type_alias_id) => { + let loc = type_alias_id.lookup(db); + trait_item_visibility(db, loc.container).unwrap_or_else(|| { + let source = loc.source(db); + visibility_from_ast(db, type_alias_id, source.map(|src| src.visibility())) + }) + } + } } -/// Resolve visibility of a type alias. -pub(crate) fn type_alias_visibility_query(db: &dyn DefDatabase, def: TypeAliasId) -> Visibility { - let loc = def.lookup(db); - let resolver = def.resolver(db); - trait_item_visibility(db, &resolver, loc.container).unwrap_or_else(|| { - let source = loc.source(db); - visibility_from_ast(db, &resolver, source.map(|src| src.visibility())) - }) +fn trait_item_visibility(db: &dyn DefDatabase, container: ItemContainerId) -> Option { + match container { + ItemContainerId::TraitId(trait_) => Some(trait_visibility(db, trait_)), + _ => None, + } } -pub(crate) fn trait_visibility( - db: &dyn DefDatabase, - resolver: &Resolver<'_>, - def: TraitId, -) -> Visibility { +fn trait_visibility(db: &dyn DefDatabase, def: TraitId) -> Visibility { let loc = def.lookup(db); let source = loc.source(db); - visibility_from_ast(db, resolver, source.map(|src| src.visibility())) + visibility_from_ast(db, def, source.map(|src| src.visibility())) } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs b/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs index 70c89275a5c58..25f1782bdd870 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs @@ -1550,7 +1550,7 @@ fn is_valid_impl_method_candidate( check_that!(name.is_none_or(|n| n == item_name)); if let Some(from_module) = visible_from_module { - if !db.const_visibility(c).is_visible_from(db, from_module) { + if !db.assoc_visibility(c.into()).is_visible_from(db, from_module) { cov_mark::hit!(const_candidate_not_visible); return IsValidCandidate::NotVisible; } @@ -1639,7 +1639,7 @@ fn is_valid_impl_fn_candidate( let data = db.function_signature(fn_id); if let Some(from_module) = visible_from_module { - if !db.function_visibility(fn_id).is_visible_from(db, from_module) { + if !db.assoc_visibility(fn_id.into()).is_visible_from(db, from_module) { cov_mark::hit!(autoderef_candidate_not_visible); return IsValidCandidate::NotVisible; } diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs index 2614a276bcce4..adae335627ba7 100644 --- a/src/tools/rust-analyzer/crates/hir/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs @@ -1431,7 +1431,7 @@ impl HasVisibility for Struct { fn visibility(&self, db: &dyn HirDatabase) -> Visibility { let loc = self.id.lookup(db); let source = loc.source(db); - visibility_from_ast(db, &self.id.resolver(db), source.map(|src| src.visibility())) + visibility_from_ast(db, self.id, source.map(|src| src.visibility())) } } @@ -1485,7 +1485,7 @@ impl HasVisibility for Union { fn visibility(&self, db: &dyn HirDatabase) -> Visibility { let loc = self.id.lookup(db); let source = loc.source(db); - visibility_from_ast(db, &self.id.resolver(db), source.map(|src| src.visibility())) + visibility_from_ast(db, self.id, source.map(|src| src.visibility())) } } @@ -1574,7 +1574,7 @@ impl HasVisibility for Enum { fn visibility(&self, db: &dyn HirDatabase) -> Visibility { let loc = self.id.lookup(db); let source = loc.source(db); - visibility_from_ast(db, &self.id.resolver(db), source.map(|src| src.visibility())) + visibility_from_ast(db, self.id, source.map(|src| src.visibility())) } } @@ -2632,7 +2632,7 @@ impl SelfParam { impl HasVisibility for Function { fn visibility(&self, db: &dyn HirDatabase) -> Visibility { - db.function_visibility(self.id) + db.assoc_visibility(self.id.into()) } } @@ -2692,7 +2692,7 @@ impl HasVisibility for ExternCrateDecl { fn visibility(&self, db: &dyn HirDatabase) -> Visibility { let loc = self.id.lookup(db); let source = loc.source(db); - visibility_from_ast(db, &self.id.resolver(db), source.map(|src| src.visibility())) + visibility_from_ast(db, self.id, source.map(|src| src.visibility())) } } @@ -2727,7 +2727,7 @@ impl Const { impl HasVisibility for Const { fn visibility(&self, db: &dyn HirDatabase) -> Visibility { - db.const_visibility(self.id) + db.assoc_visibility(self.id.into()) } } @@ -2813,7 +2813,7 @@ impl HasVisibility for Static { fn visibility(&self, db: &dyn HirDatabase) -> Visibility { let loc = self.id.lookup(db); let source = loc.source(db); - visibility_from_ast(db, &self.id.resolver(db), source.map(|src| src.visibility())) + visibility_from_ast(db, self.id, source.map(|src| src.visibility())) } } @@ -2915,7 +2915,7 @@ impl HasVisibility for Trait { fn visibility(&self, db: &dyn HirDatabase) -> Visibility { let loc = self.id.lookup(db); let source = loc.source(db); - visibility_from_ast(db, &self.id.resolver(db), source.map(|src| src.visibility())) + visibility_from_ast(db, self.id, source.map(|src| src.visibility())) } } @@ -2938,7 +2938,7 @@ impl HasVisibility for TraitAlias { fn visibility(&self, db: &dyn HirDatabase) -> Visibility { let loc = self.id.lookup(db); let source = loc.source(db); - visibility_from_ast(db, &self.id.resolver(db), source.map(|src| src.visibility())) + visibility_from_ast(db, self.id, source.map(|src| src.visibility())) } } @@ -2976,7 +2976,7 @@ impl TypeAlias { impl HasVisibility for TypeAlias { fn visibility(&self, db: &dyn HirDatabase) -> Visibility { - db.type_alias_visibility(self.id) + db.assoc_visibility(self.id.into()) } } @@ -3200,7 +3200,7 @@ impl HasVisibility for Macro { MacroId::Macro2Id(id) => { let loc = id.lookup(db); let source = loc.source(db); - visibility_from_ast(db, &id.resolver(db), source.map(|src| src.visibility())) + visibility_from_ast(db, id, source.map(|src| src.visibility())) } MacroId::MacroRulesId(_) => Visibility::Public, MacroId::ProcMacroId(_) => Visibility::Public, From ece523c3cc624f7ee846fa8e5110fdbd2552711a Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Sat, 14 Jun 2025 14:33:52 +0200 Subject: [PATCH 52/56] Optimize `pub(crate)` visibility resolution --- .../crates/hir-def/src/expr_store/pretty.rs | 1 + .../src/expr_store/tests/body/block.rs | 1 - .../crates/hir-def/src/find_path.rs | 1 + .../crates/hir-def/src/item_scope.rs | 22 ++------- .../crates/hir-def/src/item_tree.rs | 11 ++--- .../crates/hir-def/src/item_tree/pretty.rs | 1 + .../crates/hir-def/src/nameres/collector.rs | 3 +- .../hir-def/src/nameres/path_resolution.rs | 1 + .../crates/hir-def/src/resolver.rs | 1 + .../crates/hir-def/src/visibility.rs | 47 +++++++++++++++---- .../crates/hir-ty/src/display.rs | 1 + .../rust-analyzer/crates/hir/src/symbols.rs | 1 + 12 files changed, 55 insertions(+), 36 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/pretty.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/pretty.rs index 7b452721dfe2b..ae8a959164ca4 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/pretty.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/pretty.rs @@ -144,6 +144,7 @@ pub fn print_variant_body_hir(db: &dyn DefDatabase, owner: VariantId, edition: E w!(p, "{}", interned.display(db, p.edition)) } crate::item_tree::RawVisibility::Public => w!(p, "pub "), + crate::item_tree::RawVisibility::PubCrate => w!(p, "pub(crate) "), } if *is_unsafe { w!(p, "unsafe "); diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/tests/body/block.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/tests/body/block.rs index 5fe72778172f2..5a694c2092027 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/tests/body/block.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/tests/body/block.rs @@ -457,7 +457,6 @@ fn foo() { #[test] fn is_visible_from_same_def_map() { // Regression test for https://github.com/rust-lang/rust-analyzer/issues/9481 - cov_mark::check!(is_visible_from_same_block_def_map); check_at( r#" fn outer() { diff --git a/src/tools/rust-analyzer/crates/hir-def/src/find_path.rs b/src/tools/rust-analyzer/crates/hir-def/src/find_path.rs index 6ebc0d8dfd9cb..2820729d60c69 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/find_path.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/find_path.rs @@ -615,6 +615,7 @@ fn find_local_import_locations( cov_mark::hit!(discount_private_imports); false } + Visibility::PubCrate(_) => true, Visibility::Public => true, }; diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs index 8591874eb943e..efa4399468501 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs @@ -20,7 +20,7 @@ use crate::{ LocalModuleId, Lookup, MacroId, ModuleDefId, ModuleId, TraitId, UseId, db::DefDatabase, per_ns::{Item, MacrosItem, PerNs, TypesItem, ValuesItem}, - visibility::{Visibility, VisibilityExplicitness}, + visibility::Visibility, }; #[derive(Debug, Default)] @@ -720,33 +720,19 @@ impl ItemScope { } /// Marks everything that is not a procedural macro as private to `this_module`. - pub(crate) fn censor_non_proc_macros(&mut self, this_module: ModuleId) { + pub(crate) fn censor_non_proc_macros(&mut self, krate: Crate) { self.types .values_mut() .map(|def| &mut def.vis) .chain(self.values.values_mut().map(|def| &mut def.vis)) .chain(self.unnamed_trait_imports.iter_mut().map(|(_, def)| &mut def.vis)) - .for_each(|vis| match vis { - &mut Visibility::Module(_, visibility_explicitness) => { - *vis = Visibility::Module(this_module, visibility_explicitness) - } - Visibility::Public => { - *vis = Visibility::Module(this_module, VisibilityExplicitness::Implicit) - } - }); + .for_each(|vis| *vis = Visibility::PubCrate(krate)); for mac in self.macros.values_mut() { if matches!(mac.def, MacroId::ProcMacroId(_) if mac.import.is_none()) { continue; } - match mac.vis { - Visibility::Module(_, visibility_explicitness) => { - mac.vis = Visibility::Module(this_module, visibility_explicitness) - } - Visibility::Public => { - mac.vis = Visibility::Module(this_module, VisibilityExplicitness::Implicit) - } - } + mac.vis = Visibility::PubCrate(krate) } } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs index f61b403b84efd..bf14c0ecee12a 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs @@ -416,7 +416,7 @@ impl Index for ItemTree { static VIS_PUB: RawVisibility = RawVisibility::Public; static VIS_PRIV_IMPLICIT: OnceLock = OnceLock::new(); static VIS_PRIV_EXPLICIT: OnceLock = OnceLock::new(); - static VIS_PUB_CRATE: OnceLock = OnceLock::new(); + static VIS_PUB_CRATE: RawVisibility = RawVisibility::PubCrate; match index { RawVisibilityId::PRIV_IMPLICIT => VIS_PRIV_IMPLICIT.get_or_init(|| { @@ -432,12 +432,7 @@ impl Index for ItemTree { ) }), RawVisibilityId::PUB => &VIS_PUB, - RawVisibilityId::PUB_CRATE => VIS_PUB_CRATE.get_or_init(|| { - RawVisibility::Module( - Interned::new(ModPath::from_kind(PathKind::Crate)), - VisibilityExplicitness::Explicit, - ) - }), + RawVisibilityId::PUB_CRATE => &VIS_PUB_CRATE, _ => &self.vis.arena[index.0 as usize], } } @@ -555,6 +550,8 @@ pub enum RawVisibility { /// `pub(in module)`, `pub(crate)` or `pub(super)`. Also private, which is /// equivalent to `pub(self)`. Module(Interned, VisibilityExplicitness), + /// `pub(crate)`. + PubCrate, /// `pub`. Public, } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs index eb97081128eda..a8e816bd3ae9a 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs @@ -111,6 +111,7 @@ impl Printer<'_> { w!(self, "pub({}) ", path.display(self.db, self.edition)) } RawVisibility::Public => w!(self, "pub "), + RawVisibility::PubCrate => w!(self, "pub(crate) "), }; } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs index 508fcc2fa513f..78fdc275606eb 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs @@ -437,9 +437,8 @@ impl<'db> DefCollector<'db> { // Additionally, while the proc macro entry points must be `pub`, they are not publicly // exported in type/value namespace. This function reduces the visibility of all items // in the crate root that aren't proc macros. - let module_id = self.def_map.module_id(DefMap::ROOT); let root = &mut self.def_map.modules[DefMap::ROOT]; - root.scope.censor_non_proc_macros(module_id); + root.scope.censor_non_proc_macros(self.def_map.krate); } } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/path_resolution.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/path_resolution.rs index ca39173d47716..307acaf1fe75e 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/path_resolution.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/path_resolution.rs @@ -129,6 +129,7 @@ impl DefMap { } } RawVisibility::Public => Visibility::Public, + RawVisibility::PubCrate => Visibility::PubCrate(self.krate), }; // In block expressions, `self` normally refers to the containing non-block module, and diff --git a/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs b/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs index 491b6204bce2c..7b24f6cc74fc4 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs @@ -305,6 +305,7 @@ impl<'db> Resolver<'db> { }), ) } + RawVisibility::PubCrate => Some(Visibility::PubCrate(self.krate())), RawVisibility::Public => Some(Visibility::Public), } } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/visibility.rs b/src/tools/rust-analyzer/crates/hir-def/src/visibility.rs index aea2ac550e3e0..11efeed17b122 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/visibility.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/visibility.rs @@ -2,6 +2,7 @@ use std::iter; +use base_db::Crate; use hir_expand::{InFile, Lookup}; use la_arena::ArenaMap; use syntax::ast::{self, HasVisibility}; @@ -19,6 +20,8 @@ pub use crate::item_tree::{RawVisibility, VisibilityExplicitness}; pub enum Visibility { /// Visibility is restricted to a certain module. Module(ModuleId, VisibilityExplicitness), + /// Visibility is restricted to the crate. + PubCrate(Crate), /// Visibility is unrestricted. Public, } @@ -41,6 +44,7 @@ impl Visibility { pub fn is_visible_from(self, db: &dyn DefDatabase, from_module: ModuleId) -> bool { let to_module = match self { Visibility::Module(m, _) => m, + Visibility::PubCrate(krate) => return from_module.krate == krate, Visibility::Public => return true, }; // if they're not in the same crate, it can't be visible @@ -59,6 +63,7 @@ impl Visibility { ) -> bool { let to_module = match self { Visibility::Module(m, _) => m, + Visibility::PubCrate(krate) => return def_map.krate() == krate, Visibility::Public => return true, }; // if they're not in the same crate, it can't be visible @@ -132,26 +137,41 @@ impl Visibility { pub(crate) fn max(self, other: Visibility, def_map: &DefMap) -> Option { match (self, other) { (_, Visibility::Public) | (Visibility::Public, _) => Some(Visibility::Public), + (Visibility::PubCrate(krate), Visibility::PubCrate(krateb)) => { + if krate == krateb { + Some(Visibility::PubCrate(krate)) + } else { + None + } + } + (Visibility::Module(mod_, _), Visibility::PubCrate(krate)) + | (Visibility::PubCrate(krate), Visibility::Module(mod_, _)) => { + if mod_.krate == krate { + Some(Visibility::PubCrate(krate)) + } else { + None + } + } (Visibility::Module(mod_a, expl_a), Visibility::Module(mod_b, expl_b)) => { - if mod_a.krate != mod_b.krate { + if mod_a.krate != def_map.krate() || mod_b.krate != def_map.krate() { return None; } let def_block = def_map.block_id(); - if (mod_a.containing_block(), mod_b.containing_block()) != (def_block, def_block) { + if mod_a.containing_block() != def_block || mod_b.containing_block() != def_block { return None; } let mut a_ancestors = iter::successors(Some(mod_a.local_id), |&m| def_map[m].parent); - let mut b_ancestors = - iter::successors(Some(mod_b.local_id), |&m| def_map[m].parent); if a_ancestors.any(|m| m == mod_b.local_id) { // B is above A return Some(Visibility::Module(mod_b, expl_b)); } + let mut b_ancestors = + iter::successors(Some(mod_b.local_id), |&m| def_map[m].parent); if b_ancestors.any(|m| m == mod_a.local_id) { // A is above B return Some(Visibility::Module(mod_a, expl_a)); @@ -169,26 +189,37 @@ impl Visibility { pub(crate) fn min(self, other: Visibility, def_map: &DefMap) -> Option { match (self, other) { (vis, Visibility::Public) | (Visibility::Public, vis) => Some(vis), + (Visibility::PubCrate(krate), Visibility::PubCrate(krateb)) => { + if krate == krateb { + Some(Visibility::PubCrate(krate)) + } else { + None + } + } + (Visibility::Module(mod_, exp), Visibility::PubCrate(krate)) + | (Visibility::PubCrate(krate), Visibility::Module(mod_, exp)) => { + if mod_.krate == krate { Some(Visibility::Module(mod_, exp)) } else { None } + } (Visibility::Module(mod_a, expl_a), Visibility::Module(mod_b, expl_b)) => { - if mod_a.krate != mod_b.krate { + if mod_a.krate != def_map.krate() || mod_b.krate != def_map.krate() { return None; } let def_block = def_map.block_id(); - if (mod_a.containing_block(), mod_b.containing_block()) != (def_block, def_block) { + if mod_a.containing_block() != def_block || mod_b.containing_block() != def_block { return None; } let mut a_ancestors = iter::successors(Some(mod_a.local_id), |&m| def_map[m].parent); - let mut b_ancestors = - iter::successors(Some(mod_b.local_id), |&m| def_map[m].parent); if a_ancestors.any(|m| m == mod_b.local_id) { // B is above A return Some(Visibility::Module(mod_a, expl_a)); } + let mut b_ancestors = + iter::successors(Some(mod_b.local_id), |&m| def_map[m].parent); if b_ancestors.any(|m| m == mod_a.local_id) { // A is above B return Some(Visibility::Module(mod_b, expl_b)); diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs index da21f08a1e1da..1aa7e0fcf88bf 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs @@ -2082,6 +2082,7 @@ pub fn write_visibility( ) -> Result<(), HirDisplayError> { match vis { Visibility::Public => write!(f, "pub "), + Visibility::PubCrate(_) => write!(f, "pub(crate) "), Visibility::Module(vis_id, _) => { let def_map = module_id.def_map(f.db); let root_module_id = def_map.module_id(DefMap::ROOT); diff --git a/src/tools/rust-analyzer/crates/hir/src/symbols.rs b/src/tools/rust-analyzer/crates/hir/src/symbols.rs index 05f4a830da5e4..d80b704f5306c 100644 --- a/src/tools/rust-analyzer/crates/hir/src/symbols.rs +++ b/src/tools/rust-analyzer/crates/hir/src/symbols.rs @@ -164,6 +164,7 @@ impl<'a> SymbolCollector<'a> { let is_explicit_import = |vis| match vis { Visibility::Public => true, + Visibility::PubCrate(_) => true, Visibility::Module(_, VisibilityExplicitness::Explicit) => true, Visibility::Module(_, VisibilityExplicitness::Implicit) => false, }; From 6ff82fbba606b58a58a24daa82ee6f6c320c9170 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Sat, 14 Jun 2025 15:33:48 +0200 Subject: [PATCH 53/56] Optimize private visibility resolution --- .../crates/hir-def/src/expr_store/pretty.rs | 3 +- .../src/expr_store/tests/body/block.rs | 1 - .../crates/hir-def/src/find_path.rs | 1 - .../crates/hir-def/src/item_tree.rs | 22 ++++----- .../crates/hir-def/src/item_tree/pretty.rs | 3 +- .../crates/hir-def/src/item_tree/tests.rs | 2 +- .../rust-analyzer/crates/hir-def/src/lib.rs | 4 ++ .../hir-def/src/nameres/path_resolution.rs | 36 ++++++++------ .../crates/hir-def/src/resolver.rs | 3 ++ .../crates/hir-def/src/visibility.rs | 47 +++++++++++++++++-- 10 files changed, 83 insertions(+), 39 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/pretty.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/pretty.rs index ae8a959164ca4..56c7655f9ea6a 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/pretty.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/pretty.rs @@ -141,10 +141,11 @@ pub fn print_variant_body_hir(db: &dyn DefDatabase, owner: VariantId, edition: E let FieldData { name, type_ref, visibility, is_unsafe } = data; match visibility { crate::item_tree::RawVisibility::Module(interned, _visibility_explicitness) => { - w!(p, "{}", interned.display(db, p.edition)) + w!(p, "pub(in {})", interned.display(db, p.edition)) } crate::item_tree::RawVisibility::Public => w!(p, "pub "), crate::item_tree::RawVisibility::PubCrate => w!(p, "pub(crate) "), + crate::item_tree::RawVisibility::PubSelf(_) => w!(p, "pub(self) "), } if *is_unsafe { w!(p, "unsafe "); diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/tests/body/block.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/tests/body/block.rs index 5a694c2092027..bb0b70bc5bf2f 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/tests/body/block.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/tests/body/block.rs @@ -397,7 +397,6 @@ fn main() { fn underscore_import() { // This used to panic, because the default (private) visibility inside block expressions would // point into the containing `DefMap`, which visibilities should never be able to do. - cov_mark::check!(adjust_vis_in_block_def_map); check_at( r#" mod m { diff --git a/src/tools/rust-analyzer/crates/hir-def/src/find_path.rs b/src/tools/rust-analyzer/crates/hir-def/src/find_path.rs index 2820729d60c69..dccfff002f23d 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/find_path.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/find_path.rs @@ -1287,7 +1287,6 @@ $0 #[test] fn explicit_private_imports_crate() { - cov_mark::check!(explicit_private_imports); check_found_path( r#" //- /main.rs diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs index bf14c0ecee12a..c633339857492 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs @@ -414,23 +414,15 @@ impl Index for ItemTree { type Output = RawVisibility; fn index(&self, index: RawVisibilityId) -> &Self::Output { static VIS_PUB: RawVisibility = RawVisibility::Public; - static VIS_PRIV_IMPLICIT: OnceLock = OnceLock::new(); - static VIS_PRIV_EXPLICIT: OnceLock = OnceLock::new(); + static VIS_PRIV_IMPLICIT: RawVisibility = + RawVisibility::PubSelf(VisibilityExplicitness::Implicit); + static VIS_PRIV_EXPLICIT: RawVisibility = + RawVisibility::PubSelf(VisibilityExplicitness::Explicit); static VIS_PUB_CRATE: RawVisibility = RawVisibility::PubCrate; match index { - RawVisibilityId::PRIV_IMPLICIT => VIS_PRIV_IMPLICIT.get_or_init(|| { - RawVisibility::Module( - Interned::new(ModPath::from_kind(PathKind::SELF)), - VisibilityExplicitness::Implicit, - ) - }), - RawVisibilityId::PRIV_EXPLICIT => VIS_PRIV_EXPLICIT.get_or_init(|| { - RawVisibility::Module( - Interned::new(ModPath::from_kind(PathKind::SELF)), - VisibilityExplicitness::Explicit, - ) - }), + RawVisibilityId::PRIV_IMPLICIT => &VIS_PRIV_IMPLICIT, + RawVisibilityId::PRIV_EXPLICIT => &VIS_PRIV_EXPLICIT, RawVisibilityId::PUB => &VIS_PUB, RawVisibilityId::PUB_CRATE => &VIS_PUB_CRATE, _ => &self.vis.arena[index.0 as usize], @@ -550,6 +542,8 @@ pub enum RawVisibility { /// `pub(in module)`, `pub(crate)` or `pub(super)`. Also private, which is /// equivalent to `pub(self)`. Module(Interned, VisibilityExplicitness), + /// `pub(self)`. + PubSelf(VisibilityExplicitness), /// `pub(crate)`. PubCrate, /// `pub`. diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs index a8e816bd3ae9a..696174cb072bf 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs @@ -108,10 +108,11 @@ impl Printer<'_> { fn print_visibility(&mut self, vis: RawVisibilityId) { match &self.tree[vis] { RawVisibility::Module(path, _expl) => { - w!(self, "pub({}) ", path.display(self.db, self.edition)) + w!(self, "pub(in {}) ", path.display(self.db, self.edition)) } RawVisibility::Public => w!(self, "pub "), RawVisibility::PubCrate => w!(self, "pub(crate) "), + RawVisibility::PubSelf(_) => w!(self, "pub(self) "), }; } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/tests.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/tests.rs index e39efd31c6c19..5923b3ea4913d 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/tests.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/tests.rs @@ -39,7 +39,7 @@ use a::{c, d::{e}}; pub(self) extern crate self as renamed; // AstId: ExternCrate[7E1C, 0] - pub(super) extern crate bli; + pub(in super) extern crate bli; // AstId: Use[0000, 0] pub use crate::path::{nested, items as renamed, Trait as _}; diff --git a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs index 0cd7e894327c9..a542214d3031c 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs @@ -149,6 +149,7 @@ impl HasModule for ItemLoc { #[derive(Debug)] pub struct AssocItemLoc { + // FIXME: Store this as an erased `salsa::Id` to save space pub container: ItemContainerId, pub id: AstId, } @@ -577,6 +578,7 @@ pub type LocalModuleId = Idx; #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct FieldId { + // FIXME: Store this as an erased `salsa::Id` to save space pub parent: VariantId, pub local_id: LocalFieldId, } @@ -592,6 +594,7 @@ pub struct TupleFieldId { #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct TypeOrConstParamId { + // FIXME: Store this as an erased `salsa::Id` to save space pub parent: GenericDefId, pub local_id: LocalTypeOrConstParamId, } @@ -650,6 +653,7 @@ impl From for TypeOrConstParamId { #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct LifetimeParamId { + // FIXME: Store this as an erased `salsa::Id` to save space pub parent: GenericDefId, pub local_id: LocalLifetimeParamId, } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/path_resolution.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/path_resolution.rs index 307acaf1fe75e..e8235b1c96fe0 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/path_resolution.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/path_resolution.rs @@ -106,7 +106,7 @@ impl DefMap { visibility: &RawVisibility, within_impl: bool, ) -> Option { - let mut vis = match visibility { + let vis = match visibility { RawVisibility::Module(path, explicitness) => { let (result, remaining) = self.resolve_path( local_def_map, @@ -120,30 +120,36 @@ impl DefMap { return None; } let types = result.take_types()?; - match types { + let mut vis = match types { ModuleDefId::ModuleId(m) => Visibility::Module(m, *explicitness), // error: visibility needs to refer to module _ => { return None; } + }; + + // In block expressions, `self` normally refers to the containing non-block module, and + // `super` to its parent (etc.). However, visibilities must only refer to a module in the + // DefMap they're written in, so we restrict them when that happens. + if let Visibility::Module(m, mv) = vis { + // ...unless we're resolving visibility for an associated item in an impl. + if self.block_id() != m.block && !within_impl { + vis = Visibility::Module(self.module_id(Self::ROOT), mv); + tracing::debug!( + "visibility {:?} points outside DefMap, adjusting to {:?}", + m, + vis + ); + } } + vis + } + RawVisibility::PubSelf(explicitness) => { + Visibility::Module(self.module_id(original_module), *explicitness) } RawVisibility::Public => Visibility::Public, RawVisibility::PubCrate => Visibility::PubCrate(self.krate), }; - - // In block expressions, `self` normally refers to the containing non-block module, and - // `super` to its parent (etc.). However, visibilities must only refer to a module in the - // DefMap they're written in, so we restrict them when that happens. - if let Visibility::Module(m, mv) = vis { - // ...unless we're resolving visibility for an associated item in an impl. - if self.block_id() != m.block && !within_impl { - cov_mark::hit!(adjust_vis_in_block_def_map); - vis = Visibility::Module(self.module_id(Self::ROOT), mv); - tracing::debug!("visibility {:?} points outside DefMap, adjusting to {:?}", m, vis); - } - } - Some(vis) } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs b/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs index 7b24f6cc74fc4..6f321980af43d 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs @@ -305,6 +305,9 @@ impl<'db> Resolver<'db> { }), ) } + RawVisibility::PubSelf(explicitness) => { + Some(Visibility::Module(self.module(), *explicitness)) + } RawVisibility::PubCrate => Some(Visibility::PubCrate(self.krate())), RawVisibility::Public => Some(Visibility::Public), } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/visibility.rs b/src/tools/rust-analyzer/crates/hir-def/src/visibility.rs index 11efeed17b122..2514e88864f3f 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/visibility.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/visibility.rs @@ -47,6 +47,10 @@ impl Visibility { Visibility::PubCrate(krate) => return from_module.krate == krate, Visibility::Public => return true, }; + if from_module == to_module { + // if the modules are the same, visibility is trivially satisfied + return true; + } // if they're not in the same crate, it can't be visible if from_module.krate != to_module.krate { return false; @@ -70,6 +74,11 @@ impl Visibility { if def_map.krate() != to_module.krate { return false; } + + if from_module == to_module.local_id && def_map.block_id() == to_module.block { + // if the modules are the same, visibility is trivially satisfied + return true; + } Self::is_visible_from_def_map_(db, def_map, to_module, from_module) } @@ -93,9 +102,7 @@ impl Visibility { // `to_module` is not a block, so there is no parent def map to use. (None, _) => (), // `to_module` is at `def_map`'s block, no need to move further. - (Some(a), Some(b)) if a == b => { - cov_mark::hit!(is_visible_from_same_block_def_map); - } + (Some(a), Some(b)) if a == b => {} _ => { if let Some(parent) = to_module.def_map(db).parent() { to_module = parent; @@ -153,7 +160,22 @@ impl Visibility { } } (Visibility::Module(mod_a, expl_a), Visibility::Module(mod_b, expl_b)) => { - if mod_a.krate != def_map.krate() || mod_b.krate != def_map.krate() { + if mod_a == mod_b { + // Most module visibilities are `pub(self)`, and assuming no errors + // this will be the common and thus fast path. + return Some(Visibility::Module( + mod_a, + match (expl_a, expl_b) { + (VisibilityExplicitness::Explicit, _) + | (_, VisibilityExplicitness::Explicit) => { + VisibilityExplicitness::Explicit + } + _ => VisibilityExplicitness::Implicit, + }, + )); + } + + if mod_a.krate() != def_map.krate() || mod_b.krate() != def_map.krate() { return None; } @@ -201,7 +223,22 @@ impl Visibility { if mod_.krate == krate { Some(Visibility::Module(mod_, exp)) } else { None } } (Visibility::Module(mod_a, expl_a), Visibility::Module(mod_b, expl_b)) => { - if mod_a.krate != def_map.krate() || mod_b.krate != def_map.krate() { + if mod_a == mod_b { + // Most module visibilities are `pub(self)`, and assuming no errors + // this will be the common and thus fast path. + return Some(Visibility::Module( + mod_a, + match (expl_a, expl_b) { + (VisibilityExplicitness::Explicit, _) + | (_, VisibilityExplicitness::Explicit) => { + VisibilityExplicitness::Explicit + } + _ => VisibilityExplicitness::Implicit, + }, + )); + } + + if mod_a.krate() != def_map.krate() || mod_b.krate() != def_map.krate() { return None; } From 0339a97ad22dc185f71f5fd0267201f1525ca1ab Mon Sep 17 00:00:00 2001 From: Tadeo Kondrak Date: Sun, 15 Jun 2025 17:42:06 +0200 Subject: [PATCH 54/56] Fix spacing for LIFETIME_IDENT near keywords and literals in test output --- .../crates/hir-def/src/macro_expansion_tests/mbe.rs | 2 +- .../src/macro_expansion_tests/mbe/regression.rs | 2 +- .../crates/hir-def/src/macro_expansion_tests/mod.rs | 12 ++++++++++-- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe.rs b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe.rs index ef93a2a790d5b..c6d901ec93bc4 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe.rs @@ -2046,7 +2046,7 @@ macro_rules! m { ($($x:expr)'a*) => (stringify!($($x)'b*)); } fn f() { - let _ = stringify!(0 'b1 'b2); + let _ = stringify!(0 'b 1 'b 2); } "#]], ); diff --git a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe/regression.rs b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe/regression.rs index 2cc3ca8c7523b..e2022c7967d86 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe/regression.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe/regression.rs @@ -784,7 +784,7 @@ macro_rules! delegate_impl { } } } -impl <> Data for &'amut G where G: Data {} +impl <> Data for &'a mut G where G: Data {} "#]], ); } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mod.rs b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mod.rs index b5321560918e0..15b31c1e7edc1 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mod.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mod.rs @@ -308,8 +308,16 @@ fn pretty_print_macro_expansion( { " " } - (IDENT, _) if curr_kind.is_keyword(Edition::CURRENT) => " ", - (_, IDENT) if prev_kind.is_keyword(Edition::CURRENT) => " ", + (IDENT | LIFETIME_IDENT, _) + if curr_kind.is_keyword(Edition::CURRENT) || curr_kind.is_literal() => + { + " " + } + (_, IDENT | LIFETIME_IDENT) + if prev_kind.is_keyword(Edition::CURRENT) || prev_kind.is_literal() => + { + " " + } (T![>], IDENT) => " ", (T![>], _) if curr_kind.is_keyword(Edition::CURRENT) => " ", (T![->], _) | (_, T![->]) => " ", From 68d841e7d6731482dd822a3238082690f0587b4c Mon Sep 17 00:00:00 2001 From: Tadeo Kondrak Date: Sun, 15 Jun 2025 18:23:18 +0200 Subject: [PATCH 55/56] Use is_any_identifier in pretty_print_macro_expansion --- .../hir-def/src/macro_expansion_tests/mod.rs | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mod.rs b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mod.rs index 15b31c1e7edc1..1c69b37f164f0 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mod.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mod.rs @@ -302,19 +302,12 @@ fn pretty_print_macro_expansion( (_, T!['{']) => " ", (T![;] | T!['{'] | T!['}'], _) => "\n", (_, T!['}']) => "\n", - (IDENT | LIFETIME_IDENT, IDENT | LIFETIME_IDENT) => " ", - _ if prev_kind.is_keyword(Edition::CURRENT) - && curr_kind.is_keyword(Edition::CURRENT) => - { - " " - } - (IDENT | LIFETIME_IDENT, _) - if curr_kind.is_keyword(Edition::CURRENT) || curr_kind.is_literal() => - { - " " - } - (_, IDENT | LIFETIME_IDENT) - if prev_kind.is_keyword(Edition::CURRENT) || prev_kind.is_literal() => + _ if (prev_kind.is_any_identifier() + || prev_kind == LIFETIME_IDENT + || prev_kind.is_literal()) + && (curr_kind.is_any_identifier() + || curr_kind == LIFETIME_IDENT + || curr_kind.is_literal()) => { " " } From 6a9c5d7ae01ab04235ce53489938ce1dd5838fe9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Tue, 17 Jun 2025 19:00:01 +0300 Subject: [PATCH 56/56] Try to downgrade object --- src/tools/rust-analyzer/Cargo.lock | 13 ++----------- src/tools/rust-analyzer/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 12 deletions(-) diff --git a/src/tools/rust-analyzer/Cargo.lock b/src/tools/rust-analyzer/Cargo.lock index c2b4e21483e7a..2c7b46416412d 100644 --- a/src/tools/rust-analyzer/Cargo.lock +++ b/src/tools/rust-analyzer/Cargo.lock @@ -60,7 +60,7 @@ dependencies = [ "cfg-if", "libc", "miniz_oxide", - "object 0.36.7", + "object", "rustc-demangle", "windows-targets 0.52.6", ] @@ -1400,15 +1400,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "object" -version = "0.37.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03fd943161069e1768b4b3d050890ba48730e590f57e56d4aa04e7e090e61b4a" -dependencies = [ - "memchr", -] - [[package]] name = "once_cell" version = "1.21.3" @@ -1573,7 +1564,7 @@ dependencies = [ "libc", "libloading", "memmap2", - "object 0.37.1", + "object", "paths", "proc-macro-test", "ra-ap-rustc_lexer", diff --git a/src/tools/rust-analyzer/Cargo.toml b/src/tools/rust-analyzer/Cargo.toml index c791d741b0267..449c75859cf9c 100644 --- a/src/tools/rust-analyzer/Cargo.toml +++ b/src/tools/rust-analyzer/Cargo.toml @@ -122,7 +122,7 @@ libloading = "0.8.8" memmap2 = "0.9.5" nohash-hasher = "0.2.0" oorandom = "11.1.5" -object = { version = "0.37.1", default-features = false, features = [ +object = { version = "0.36.7", default-features = false, features = [ "std", "read_core", "elf",