From 889d84a1bec26d3e4d872fa9df2b624cfb3e329c Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 26 Jun 2025 12:55:55 +0200 Subject: [PATCH] Salsa idiomize `VariantFields` query --- crates/hir-def/src/db.rs | 12 --- crates/hir-def/src/expr_store.rs | 18 +++- crates/hir-def/src/expr_store/lower.rs | 2 +- crates/hir-def/src/expr_store/pretty.rs | 2 +- crates/hir-def/src/lib.rs | 52 ++++++++++- crates/hir-def/src/signatures.rs | 88 +++++++++++-------- crates/hir-def/src/visibility.rs | 2 +- crates/hir-ty/src/chalk_db.rs | 2 +- crates/hir-ty/src/diagnostics/decl_check.rs | 4 +- crates/hir-ty/src/diagnostics/expr.rs | 4 +- crates/hir-ty/src/diagnostics/match_check.rs | 8 +- .../diagnostics/match_check/pat_analysis.rs | 6 +- crates/hir-ty/src/display.rs | 4 +- crates/hir-ty/src/infer/cast.rs | 2 +- crates/hir-ty/src/infer/closure.rs | 10 +-- crates/hir-ty/src/infer/expr.rs | 6 +- crates/hir-ty/src/infer/pat.rs | 6 +- crates/hir-ty/src/infer/unify.rs | 2 +- crates/hir-ty/src/inhabitedness.rs | 2 +- crates/hir-ty/src/layout.rs | 2 +- crates/hir-ty/src/layout/adt.rs | 6 +- crates/hir-ty/src/lower.rs | 6 +- crates/hir-ty/src/mir/eval.rs | 9 +- crates/hir-ty/src/mir/eval/shim/simd.rs | 2 +- crates/hir-ty/src/mir/lower.rs | 7 +- .../hir-ty/src/mir/lower/pattern_matching.rs | 4 +- crates/hir-ty/src/mir/pretty.rs | 2 +- crates/hir-ty/src/tests/incremental.rs | 5 +- crates/hir/src/diagnostics.rs | 2 +- crates/hir/src/display.rs | 2 +- crates/hir/src/lib.rs | 39 ++++---- crates/hir/src/semantics/child_by_source.rs | 2 +- crates/hir/src/source_analyzer.rs | 12 +-- 33 files changed, 201 insertions(+), 131 deletions(-) diff --git a/crates/hir-def/src/db.rs b/crates/hir-def/src/db.rs index e472072e32..c67bb2422a 100644 --- a/crates/hir-def/src/db.rs +++ b/crates/hir-def/src/db.rs @@ -29,7 +29,6 @@ use crate::{ signatures::{ ConstSignature, EnumSignature, FunctionSignature, ImplSignature, StaticSignature, StructSignature, TraitAliasSignature, TraitSignature, TypeAliasSignature, UnionSignature, - VariantFields, }, tt, visibility::{self, Visibility}, @@ -113,17 +112,6 @@ pub trait DefDatabase: InternDatabase + ExpandDatabase + SourceDatabase { // region:data - #[salsa::invoke(VariantFields::query)] - fn variant_fields_with_source_map( - &self, - id: VariantId, - ) -> (Arc, Arc); - - #[salsa::tracked] - fn variant_fields(&self, id: VariantId) -> Arc { - self.variant_fields_with_source_map(id).0 - } - #[salsa::tracked] fn trait_signature(&self, trait_: TraitId) -> Arc { self.trait_signature_with_source_map(trait_).0 diff --git a/crates/hir-def/src/expr_store.rs b/crates/hir-def/src/expr_store.rs index f617c3225a..85bd193223 100644 --- a/crates/hir-def/src/expr_store.rs +++ b/crates/hir-def/src/expr_store.rs @@ -9,7 +9,10 @@ pub mod scope; #[cfg(test)] mod tests; -use std::ops::{Deref, Index}; +use std::{ + ops::{Deref, Index}, + sync::LazyLock, +}; use cfg::{CfgExpr, CfgOptions}; use either::Either; @@ -19,6 +22,7 @@ use rustc_hash::FxHashMap; use smallvec::SmallVec; use span::{Edition, SyntaxContext}; use syntax::{AstPtr, SyntaxNodePtr, ast}; +use triomphe::Arc; use tt::TextRange; use crate::{ @@ -220,6 +224,12 @@ impl ExpressionStoreBuilder { } impl ExpressionStore { + pub fn empty_singleton() -> Arc { + static EMPTY: LazyLock> = + LazyLock::new(|| Arc::new(ExpressionStoreBuilder::default().finish())); + EMPTY.clone() + } + /// Returns an iterator over all block expressions in this store that define inner items. pub fn blocks<'a>( &'a self, @@ -636,6 +646,12 @@ impl Index for ExpressionStore { // FIXME: Change `node_` prefix to something more reasonable. // Perhaps `expr_syntax` and `expr_id`? impl ExpressionStoreSourceMap { + pub fn empty_singleton() -> Arc { + static EMPTY: LazyLock> = + LazyLock::new(|| Arc::new(ExpressionStoreSourceMap::default())); + EMPTY.clone() + } + pub fn expr_or_pat_syntax(&self, id: ExprOrPatId) -> Result { match id { ExprOrPatId::ExprId(id) => self.expr_syntax(id), diff --git a/crates/hir-def/src/expr_store/lower.rs b/crates/hir-def/src/expr_store/lower.rs index d15c855aa6..c0e51b338b 100644 --- a/crates/hir-def/src/expr_store/lower.rs +++ b/crates/hir-def/src/expr_store/lower.rs @@ -2250,7 +2250,7 @@ impl ExprCollector<'_> { Some(ModuleDefId::ConstId(_)) => (None, Pat::Path(name.into())), Some(ModuleDefId::EnumVariantId(variant)) // FIXME: This can cause a cycle if the user is writing invalid code - if self.db.variant_fields(variant.into()).shape != FieldsShape::Record => + if variant.fields(self.db).shape != FieldsShape::Record => { (None, Pat::Path(name.into())) } diff --git a/crates/hir-def/src/expr_store/pretty.rs b/crates/hir-def/src/expr_store/pretty.rs index 56c7655f9e..87bcd33ed7 100644 --- a/crates/hir-def/src/expr_store/pretty.rs +++ b/crates/hir-def/src/expr_store/pretty.rs @@ -121,7 +121,7 @@ pub fn print_variant_body_hir(db: &dyn DefDatabase, owner: VariantId, edition: E VariantId::UnionId(it) => format!("union {}", item_name(db, it, "")), }; - let fields = db.variant_fields(owner); + let fields = owner.fields(db); let mut p = Printer { db, diff --git a/crates/hir-def/src/lib.rs b/crates/hir-def/src/lib.rs index eb74c97a7d..8117b0206b 100644 --- a/crates/hir-def/src/lib.rs +++ b/crates/hir-def/src/lib.rs @@ -87,6 +87,7 @@ use crate::{ attr::Attrs, builtin_type::BuiltinType, db::DefDatabase, + expr_store::ExpressionStoreSourceMap, hir::generics::{LocalLifetimeParamId, LocalTypeOrConstParamId}, nameres::{ LocalDefMap, @@ -254,9 +255,35 @@ impl_intern!(FunctionId, FunctionLoc, intern_function, lookup_intern_function); type StructLoc = ItemLoc; impl_intern!(StructId, StructLoc, intern_struct, lookup_intern_struct); +impl StructId { + pub fn fields(self, db: &dyn DefDatabase) -> &VariantFields { + &VariantFields::query(db, self.into()).0 + } + + pub fn fields_with_source_map( + self, + db: &dyn DefDatabase, + ) -> &(VariantFields, Arc) { + VariantFields::query(db, self.into()) + } +} + pub type UnionLoc = ItemLoc; impl_intern!(UnionId, UnionLoc, intern_union, lookup_intern_union); +impl UnionId { + pub fn fields(self, db: &dyn DefDatabase) -> &VariantFields { + &VariantFields::query(db, self.into()).0 + } + + pub fn fields_with_source_map( + self, + db: &dyn DefDatabase, + ) -> &(VariantFields, Arc) { + VariantFields::query(db, self.into()) + } +} + pub type EnumLoc = ItemLoc; impl_intern!(EnumId, EnumLoc, intern_enum, lookup_intern_enum); @@ -337,6 +364,20 @@ pub struct EnumVariantLoc { } impl_intern!(EnumVariantId, EnumVariantLoc, intern_enum_variant, lookup_intern_enum_variant); impl_loc!(EnumVariantLoc, id: Variant, parent: EnumId); + +impl EnumVariantId { + pub fn fields(self, db: &dyn DefDatabase) -> &VariantFields { + &VariantFields::query(db, self.into()).0 + } + + pub fn fields_with_source_map( + self, + db: &dyn DefDatabase, + ) -> &(VariantFields, Arc) { + VariantFields::query(db, self.into()) + } +} + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct Macro2Loc { pub container: ModuleId, @@ -1024,8 +1065,15 @@ pub enum VariantId { impl_from!(EnumVariantId, StructId, UnionId for VariantId); impl VariantId { - pub fn variant_data(self, db: &dyn DefDatabase) -> Arc { - db.variant_fields(self) + pub fn fields(self, db: &dyn DefDatabase) -> &VariantFields { + &VariantFields::query(db, self).0 + } + + pub fn fields_with_source_map( + self, + db: &dyn DefDatabase, + ) -> &(VariantFields, Arc) { + VariantFields::query(db, self) } pub fn file_id(self, db: &dyn DefDatabase) -> HirFileId { diff --git a/crates/hir-def/src/signatures.rs b/crates/hir-def/src/signatures.rs index 377a545ebf..6e924d93a2 100644 --- a/crates/hir-def/src/signatures.rs +++ b/crates/hir-def/src/signatures.rs @@ -1,6 +1,6 @@ //! Item signature IR definitions -use std::ops::Not as _; +use std::{cell::LazyCell, ops::Not as _}; use bitflags::bitflags; use cfg::{CfgExpr, CfgOptions}; @@ -731,29 +731,26 @@ pub struct VariantFields { pub store: Arc, pub shape: FieldsShape, } + +#[salsa::tracked] impl VariantFields { - #[inline] + #[salsa::tracked(returns(ref))] pub(crate) fn query( db: &dyn DefDatabase, id: VariantId, - ) -> (Arc, Arc) { - let (shape, (fields, store, source_map)) = match id { + ) -> (Self, Arc) { + let (shape, result) = match id { VariantId::EnumVariantId(id) => { let loc = id.lookup(db); let parent = loc.parent.lookup(db); 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 enum_vis = Some(source.value.parent_enum().visibility()); let fields = lower_field_list( db, parent.container, source.map(|src| src.field_list()), - Some(override_visibility), + enum_vis, ); (shape, fields) } @@ -777,10 +774,23 @@ impl VariantFields { (FieldsShape::Record, fields) } }; - - (Arc::new(VariantFields { fields, store: Arc::new(store), shape }), Arc::new(source_map)) + match result { + Some((fields, store, source_map)) => { + (VariantFields { fields, store: Arc::new(store), shape }, Arc::new(source_map)) + } + None => ( + VariantFields { + fields: Arena::default(), + store: ExpressionStore::empty_singleton(), + shape, + }, + ExpressionStoreSourceMap::empty_singleton(), + ), + } } +} +impl VariantFields { pub fn len(&self) -> usize { self.fields.len() } @@ -798,31 +808,24 @@ fn lower_field_list( db: &dyn DefDatabase, module: ModuleId, fields: InFile>, - override_visibility: Option, -) -> (Arena, ExpressionStore, ExpressionStoreSourceMap) { + override_visibility: Option>, +) -> Option<(Arena, ExpressionStore, ExpressionStoreSourceMap)> { let file_id = fields.file_id; - match fields.value { - Some(ast::FieldList::RecordFieldList(fields)) => lower_fields( + match fields.value? { + 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( + 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, - ), } } @@ -831,22 +834,34 @@ fn lower_fields( module: ModuleId, fields: InFile, Field)>>, mut field_name: impl FnMut(usize, &Field) -> Name, - override_visibility: Option, -) -> (Arena, ExpressionStore, ExpressionStoreSourceMap) { - let mut arena = Arena::new(); + override_visibility: Option>, +) -> Option<(Arena, ExpressionStore, ExpressionStoreSourceMap)> { let cfg_options = module.krate.cfg_options(db); let mut col = ExprCollector::new(db, module, fields.file_id); + let override_visibility = override_visibility.map(|vis| { + LazyCell::new(|| { + let span_map = db.span_map(fields.file_id); + visibility_from_ast(db, vis, &mut |range| span_map.span_for_range(range).ctx) + }) + }); + + let mut arena = Arena::new(); let mut idx = 0; + let mut has_fields = false; for (ty, field) in fields.value { + has_fields = true; 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 visibility = override_visibility.as_ref().map_or_else( + || { + visibility_from_ast(db, field.visibility(), &mut |range| { + col.span_map().span_for_range(range).ctx + }) + }, + |it| RawVisibility::clone(it), + ); let is_unsafe = field .syntax() .children_with_tokens() @@ -867,9 +882,12 @@ fn lower_fields( } } } + if !has_fields { + return None; + } let store = col.store.finish(); arena.shrink_to_fit(); - (arena, store, col.source_map) + Some((arena, store, col.source_map)) } #[derive(Debug, PartialEq, Eq)] @@ -948,7 +966,7 @@ impl EnumVariants { 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()); + let variant = v.fields(db); if !variant.fields().is_empty() { return false; } diff --git a/crates/hir-def/src/visibility.rs b/crates/hir-def/src/visibility.rs index 2514e88864..b5eb84c25f 100644 --- a/crates/hir-def/src/visibility.rs +++ b/crates/hir-def/src/visibility.rs @@ -273,7 +273,7 @@ pub(crate) fn field_visibilities_query( db: &dyn DefDatabase, variant_id: VariantId, ) -> Arc> { - let variant_fields = db.variant_fields(variant_id); + let variant_fields = variant_id.fields(db); let fields = variant_fields.fields(); if fields.is_empty() { return Arc::default(); diff --git a/crates/hir-ty/src/chalk_db.rs b/crates/hir-ty/src/chalk_db.rs index 04a4635da4..26b635298a 100644 --- a/crates/hir-ty/src/chalk_db.rs +++ b/crates/hir-ty/src/chalk_db.rs @@ -801,7 +801,7 @@ pub(crate) fn adt_datum_query( // this slows down rust-analyzer by quite a bit unfortunately, so enabling this is currently not worth it let _variant_id_to_fields = |id: VariantId| { - let variant_data = &id.variant_data(db); + let variant_data = &id.fields(db); let fields = if variant_data.fields().is_empty() { vec![] } else { diff --git a/crates/hir-ty/src/diagnostics/decl_check.rs b/crates/hir-ty/src/diagnostics/decl_check.rs index 1873f12fb7..9c0f8f4008 100644 --- a/crates/hir-ty/src/diagnostics/decl_check.rs +++ b/crates/hir-ty/src/diagnostics/decl_check.rs @@ -307,7 +307,7 @@ impl<'a> DeclValidator<'a> { /// Check incorrect names for struct fields. fn validate_struct_fields(&mut self, struct_id: StructId) { - let data = self.db.variant_fields(struct_id.into()); + let data = struct_id.fields(self.db); if data.shape != FieldsShape::Record { return; }; @@ -468,7 +468,7 @@ impl<'a> DeclValidator<'a> { /// Check incorrect names for fields of enum variant. fn validate_enum_variant_fields(&mut self, variant_id: EnumVariantId) { - let variant_data = self.db.variant_fields(variant_id.into()); + let variant_data = variant_id.fields(self.db); if variant_data.shape != FieldsShape::Record { return; }; diff --git a/crates/hir-ty/src/diagnostics/expr.rs b/crates/hir-ty/src/diagnostics/expr.rs index 6e95daca05..5d56957be6 100644 --- a/crates/hir-ty/src/diagnostics/expr.rs +++ b/crates/hir-ty/src/diagnostics/expr.rs @@ -558,7 +558,7 @@ pub fn record_literal_missing_fields( return None; } - let variant_data = variant_def.variant_data(db); + let variant_data = variant_def.fields(db); let specified_fields: FxHashSet<_> = fields.iter().map(|f| &f.name).collect(); let missed_fields: Vec = variant_data @@ -588,7 +588,7 @@ pub fn record_pattern_missing_fields( return None; } - let variant_data = variant_def.variant_data(db); + let variant_data = variant_def.fields(db); let specified_fields: FxHashSet<_> = fields.iter().map(|f| &f.name).collect(); let missed_fields: Vec = variant_data diff --git a/crates/hir-ty/src/diagnostics/match_check.rs b/crates/hir-ty/src/diagnostics/match_check.rs index 916876d4ac..0bce32a677 100644 --- a/crates/hir-ty/src/diagnostics/match_check.rs +++ b/crates/hir-ty/src/diagnostics/match_check.rs @@ -169,13 +169,13 @@ impl<'a> PatCtxt<'a> { } hir_def::hir::Pat::TupleStruct { ref args, ellipsis, .. } if variant.is_some() => { - let expected_len = variant.unwrap().variant_data(self.db).fields().len(); + let expected_len = variant.unwrap().fields(self.db).fields().len(); let subpatterns = self.lower_tuple_subpats(args, expected_len, ellipsis); self.lower_variant_or_leaf(pat, ty, subpatterns) } hir_def::hir::Pat::Record { ref args, .. } if variant.is_some() => { - let variant_data = variant.unwrap().variant_data(self.db); + let variant_data = variant.unwrap().fields(self.db); let subpatterns = args .iter() .map(|field| { @@ -345,7 +345,7 @@ impl HirDisplay for Pat { )?, }; - let variant_data = variant.variant_data(f.db); + let variant_data = variant.fields(f.db); if variant_data.shape == FieldsShape::Record { write!(f, " {{ ")?; @@ -377,7 +377,7 @@ impl HirDisplay for Pat { } let num_fields = - variant.map_or(subpatterns.len(), |v| v.variant_data(f.db).fields().len()); + variant.map_or(subpatterns.len(), |v| v.fields(f.db).fields().len()); if num_fields != 0 || variant.is_none() { write!(f, "(")?; let subpats = (0..num_fields).map(|i| { diff --git a/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs b/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs index 2873a3e09e..b79c8c2ab1 100644 --- a/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs +++ b/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs @@ -146,7 +146,7 @@ impl<'db> MatchCheckCtx<'db> { let (_, substs) = ty.as_adt().unwrap(); let field_tys = self.db.field_types(variant); - let fields_len = variant.variant_data(self.db).fields().len() as u32; + let fields_len = variant.fields(self.db).fields().len() as u32; (0..fields_len).map(|idx| LocalFieldId::from_raw(idx.into())).map(move |fid| { let ty = field_tys[fid].clone().substitute(Interner, substs); @@ -229,7 +229,7 @@ impl<'db> MatchCheckCtx<'db> { } }; let variant = Self::variant_id_for_adt(self.db, &ctor, adt).unwrap(); - arity = variant.variant_data(self.db).fields().len(); + arity = variant.fields(self.db).fields().len(); } _ => { never!("pattern has unexpected type: pat: {:?}, ty: {:?}", pat, &pat.ty); @@ -349,7 +349,7 @@ impl PatCx for MatchCheckCtx<'_> { 1 } else { let variant = Self::variant_id_for_adt(self.db, ctor, adt).unwrap(); - variant.variant_data(self.db).fields().len() + variant.fields(self.db).fields().len() } } _ => { diff --git a/crates/hir-ty/src/display.rs b/crates/hir-ty/src/display.rs index 41f495b238..507bab2920 100644 --- a/crates/hir-ty/src/display.rs +++ b/crates/hir-ty/src/display.rs @@ -888,7 +888,7 @@ fn render_const_scalar( write!(f, "{}", data.name.display(f.db, f.edition()))?; let field_types = f.db.field_types(s.into()); render_variant_after_name( - &f.db.variant_fields(s.into()), + s.fields(f.db), f, &field_types, f.db.trait_environment(adt.0.into()), @@ -920,7 +920,7 @@ fn render_const_scalar( )?; let field_types = f.db.field_types(var_id.into()); render_variant_after_name( - &f.db.variant_fields(var_id.into()), + var_id.fields(f.db), f, &field_types, f.db.trait_environment(adt.0.into()), diff --git a/crates/hir-ty/src/infer/cast.rs b/crates/hir-ty/src/infer/cast.rs index 8d345defdc..4e95eca3f9 100644 --- a/crates/hir-ty/src/infer/cast.rs +++ b/crates/hir-ty/src/infer/cast.rs @@ -382,7 +382,7 @@ fn pointer_kind(ty: &Ty, table: &mut InferenceTable<'_>) -> Result {} ProjectionElem::Field(Either::Left(f)) => { - let variant_data = f.parent.variant_data(db); + let variant_data = f.parent.fields(db); match variant_data.shape { FieldsShape::Record => { result.push('_'); @@ -720,7 +720,7 @@ impl CapturedItem { // In source code autoderef kicks in. ProjectionElem::Deref => {} ProjectionElem::Field(Either::Left(f)) => { - let variant_data = f.parent.variant_data(db); + let variant_data = f.parent.fields(db); match variant_data.shape { FieldsShape::Record => format_to!( result, @@ -782,7 +782,7 @@ impl CapturedItem { if field_need_paren { result = format!("({result})"); } - let variant_data = f.parent.variant_data(db); + let variant_data = f.parent.fields(db); let field = match variant_data.shape { FieldsShape::Record => { variant_data.fields()[f.local_id].name.as_str().to_owned() @@ -1559,7 +1559,7 @@ impl InferenceContext<'_> { self.consume_place(place) } VariantId::StructId(s) => { - let vd = &*self.db.variant_fields(s.into()); + let vd = s.fields(self.db); for field_pat in args.iter() { let arg = field_pat.pat; let Some(local_id) = vd.field(&field_pat.name) else { @@ -1611,7 +1611,7 @@ impl InferenceContext<'_> { self.consume_place(place) } VariantId::StructId(s) => { - let vd = &*self.db.variant_fields(s.into()); + let vd = s.fields(self.db); let (al, ar) = args.split_at(ellipsis.map_or(args.len(), |it| it as usize)); let fields = vd.fields().iter(); diff --git a/crates/hir-ty/src/infer/expr.rs b/crates/hir-ty/src/infer/expr.rs index a8392bb14c..d40d52c134 100644 --- a/crates/hir-ty/src/infer/expr.rs +++ b/crates/hir-ty/src/infer/expr.rs @@ -542,7 +542,7 @@ impl InferenceContext<'_> { _ if fields.is_empty() => {} Some(def) => { let field_types = self.db.field_types(def); - let variant_data = def.variant_data(self.db); + let variant_data = def.fields(self.db); let visibilities = self.db.field_visibilities(def); for field in fields.iter() { let field_def = { @@ -1566,12 +1566,12 @@ impl InferenceContext<'_> { }); } &TyKind::Adt(AdtId(hir_def::AdtId::StructId(s)), ref parameters) => { - let local_id = self.db.variant_fields(s.into()).field(name)?; + let local_id = s.fields(self.db).field(name)?; let field = FieldId { parent: s.into(), local_id }; (field, parameters.clone()) } &TyKind::Adt(AdtId(hir_def::AdtId::UnionId(u)), ref parameters) => { - let local_id = self.db.variant_fields(u.into()).field(name)?; + let local_id = u.fields(self.db).field(name)?; let field = FieldId { parent: u.into(), local_id }; (field, parameters.clone()) } diff --git a/crates/hir-ty/src/infer/pat.rs b/crates/hir-ty/src/infer/pat.rs index 4bc3e167eb..99d3b5c7a8 100644 --- a/crates/hir-ty/src/infer/pat.rs +++ b/crates/hir-ty/src/infer/pat.rs @@ -38,7 +38,7 @@ impl InferenceContext<'_> { decl: Option, ) -> Ty { let (ty, def) = self.resolve_variant(id.into(), path, true); - let var_data = def.map(|it| it.variant_data(self.db)); + let var_data = def.map(|it| it.fields(self.db)); if let Some(variant) = def { self.write_variant_resolution(id.into(), variant); } @@ -60,7 +60,7 @@ impl InferenceContext<'_> { _ if subs.is_empty() => {} Some(def) => { let field_types = self.db.field_types(def); - let variant_data = def.variant_data(self.db); + let variant_data = def.fields(self.db); let visibilities = self.db.field_visibilities(def); let (pre, post) = match ellipsis { @@ -129,7 +129,7 @@ impl InferenceContext<'_> { _ if subs.len() == 0 => {} Some(def) => { let field_types = self.db.field_types(def); - let variant_data = def.variant_data(self.db); + let variant_data = def.fields(self.db); let visibilities = self.db.field_visibilities(def); let substs = ty.as_adt().map(TupleExt::tail); diff --git a/crates/hir-ty/src/infer/unify.rs b/crates/hir-ty/src/infer/unify.rs index ce8a790ef6..c07755535f 100644 --- a/crates/hir-ty/src/infer/unify.rs +++ b/crates/hir-ty/src/infer/unify.rs @@ -1001,7 +1001,7 @@ impl<'a> InferenceTable<'a> { // Must use a loop here and not recursion because otherwise users will conduct completely // artificial examples of structs that have themselves as the tail field and complain r-a crashes. while let Some((AdtId::StructId(id), subst)) = ty.as_adt() { - let struct_data = self.db.variant_fields(id.into()); + let struct_data = id.fields(self.db); if let Some((last_field, _)) = struct_data.fields().iter().next_back() { let last_field_ty = self.db.field_types(id.into())[last_field] .clone() diff --git a/crates/hir-ty/src/inhabitedness.rs b/crates/hir-ty/src/inhabitedness.rs index 79a99321f1..b16b6a1178 100644 --- a/crates/hir-ty/src/inhabitedness.rs +++ b/crates/hir-ty/src/inhabitedness.rs @@ -132,7 +132,7 @@ impl UninhabitedFrom<'_> { variant: VariantId, subst: &Substitution, ) -> ControlFlow { - let variant_data = self.db.variant_fields(variant); + let variant_data = variant.fields(self.db); let fields = variant_data.fields(); if fields.is_empty() { return CONTINUE_OPAQUELY_INHABITED; diff --git a/crates/hir-ty/src/layout.rs b/crates/hir-ty/src/layout.rs index c58bd1b773..3fa2bfbd1b 100644 --- a/crates/hir-ty/src/layout.rs +++ b/crates/hir-ty/src/layout.rs @@ -375,7 +375,7 @@ pub(crate) fn layout_of_ty_cycle_result( fn struct_tail_erasing_lifetimes(db: &dyn HirDatabase, pointee: Ty) -> Ty { match pointee.kind(Interner) { &TyKind::Adt(AdtId(hir_def::AdtId::StructId(i)), ref subst) => { - let data = db.variant_fields(i.into()); + let data = i.fields(db); let mut it = data.fields().iter().rev(); match it.next() { Some((f, _)) => { diff --git a/crates/hir-ty/src/layout/adt.rs b/crates/hir-ty/src/layout/adt.rs index dff986fec3..236f316366 100644 --- a/crates/hir-ty/src/layout/adt.rs +++ b/crates/hir-ty/src/layout/adt.rs @@ -42,7 +42,7 @@ pub fn layout_of_adt_query( AdtId::StructId(s) => { let sig = db.struct_signature(s); let mut r = SmallVec::<[_; 1]>::new(); - r.push(handle_variant(s.into(), &db.variant_fields(s.into()))?); + r.push(handle_variant(s.into(), s.fields(db))?); ( r, sig.repr.unwrap_or_default(), @@ -52,7 +52,7 @@ pub fn layout_of_adt_query( AdtId::UnionId(id) => { let data = db.union_signature(id); let mut r = SmallVec::new(); - r.push(handle_variant(id.into(), &db.variant_fields(id.into()))?); + r.push(handle_variant(id.into(), id.fields(db))?); (r, data.repr.unwrap_or_default(), false) } AdtId::EnumId(e) => { @@ -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(), v.fields(db))) .collect::, _>>()?; (r, db.enum_signature(e).repr.unwrap_or_default(), false) } diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs index 3c73330224..91a7803f76 100644 --- a/crates/hir-ty/src/lower.rs +++ b/crates/hir-ty/src/lower.rs @@ -883,7 +883,7 @@ pub(crate) fn field_types_with_diagnostics_query( db: &dyn HirDatabase, variant_id: VariantId, ) -> (Arc>>, Diagnostics) { - let var_data = db.variant_fields(variant_id); + let var_data = variant_id.fields(db); let fields = var_data.fields(); if fields.is_empty() { return (Arc::new(ArenaMap::default()), None); @@ -1435,7 +1435,7 @@ fn fn_sig_for_struct_constructor(db: &dyn HirDatabase, def: StructId) -> PolyFnS /// Build the type of a tuple struct constructor. fn type_for_struct_constructor(db: &dyn HirDatabase, def: StructId) -> Option> { - let struct_data = db.variant_fields(def.into()); + let struct_data = def.fields(db); match struct_data.shape { FieldsShape::Record => None, FieldsShape::Unit => Some(type_for_adt(db, def.into())), @@ -1468,7 +1468,7 @@ fn type_for_enum_variant_constructor( def: EnumVariantId, ) -> Option> { let e = def.lookup(db).parent; - match db.variant_fields(def.into()).shape { + match def.fields(db).shape { FieldsShape::Record => None, FieldsShape::Unit => Some(type_for_adt(db, e.into())), FieldsShape::Tuple => { diff --git a/crates/hir-ty/src/mir/eval.rs b/crates/hir-ty/src/mir/eval.rs index 3b75d4cf12..9c2a9eb5c5 100644 --- a/crates/hir-ty/src/mir/eval.rs +++ b/crates/hir-ty/src/mir/eval.rs @@ -1749,8 +1749,7 @@ impl Evaluator<'_> { AdtId::UnionId(_) => not_supported!("unsizing unions"), AdtId::EnumId(_) => not_supported!("unsizing enums"), }; - let Some((last_field, _)) = - self.db.variant_fields(id.into()).fields().iter().next_back() + let Some((last_field, _)) = id.fields(self.db).fields().iter().next_back() else { not_supported!("unsizing struct without field"); }; @@ -2232,7 +2231,7 @@ impl Evaluator<'_> { } chalk_ir::TyKind::Adt(adt, subst) => match adt.0 { AdtId::StructId(s) => { - let data = this.db.variant_fields(s.into()); + let data = s.fields(this.db); let layout = this.layout(ty)?; let field_types = this.db.field_types(s.into()); for (f, _) in data.fields().iter() { @@ -2261,7 +2260,7 @@ impl Evaluator<'_> { bytes, e, ) { - let data = &this.db.variant_fields(v.into()); + let data = v.fields(this.db); let field_types = this.db.field_types(v.into()); for (f, _) in data.fields().iter() { let offset = @@ -2838,7 +2837,7 @@ impl Evaluator<'_> { return Ok(()); } let layout = self.layout_adt(id.0, subst.clone())?; - let variant_fields = self.db.variant_fields(s.into()); + let variant_fields = s.fields(self.db); match variant_fields.shape { FieldsShape::Record | FieldsShape::Tuple => { let field_types = self.db.field_types(s.into()); diff --git a/crates/hir-ty/src/mir/eval/shim/simd.rs b/crates/hir-ty/src/mir/eval/shim/simd.rs index 984648cfec..bc331a23d9 100644 --- a/crates/hir-ty/src/mir/eval/shim/simd.rs +++ b/crates/hir-ty/src/mir/eval/shim/simd.rs @@ -31,7 +31,7 @@ impl Evaluator<'_> { Some(len) => len, _ => { if let AdtId::StructId(id) = id.0 { - let struct_data = self.db.variant_fields(id.into()); + let struct_data = id.fields(self.db); let fields = struct_data.fields(); let Some((first_field, _)) = fields.iter().next() else { not_supported!("simd type with no field"); diff --git a/crates/hir-ty/src/mir/lower.rs b/crates/hir-ty/src/mir/lower.rs index 71e038b92f..845d6b8eae 100644 --- a/crates/hir-ty/src/mir/lower.rs +++ b/crates/hir-ty/src/mir/lower.rs @@ -503,7 +503,7 @@ impl<'ctx> MirLowerCtx<'ctx> { Ok(Some(current)) } ValueNs::EnumVariantId(variant_id) => { - let variant_fields = &self.db.variant_fields(variant_id.into()); + let variant_fields = variant_id.fields(self.db); if variant_fields.shape == FieldsShape::Unit { let ty = self.infer.type_of_expr[expr_id].clone(); current = self.lower_enum_variant( @@ -856,7 +856,7 @@ impl<'ctx> MirLowerCtx<'ctx> { TyKind::Adt(_, s) => s.clone(), _ => not_supported!("Non ADT record literal"), }; - let variant_fields = self.db.variant_fields(variant_id); + let variant_fields = variant_id.fields(self.db); match variant_id { VariantId::EnumVariantId(_) | VariantId::StructId(_) => { let mut operands = vec![None; variant_fields.fields().len()]; @@ -1176,8 +1176,7 @@ impl<'ctx> MirLowerCtx<'ctx> { place, Rvalue::Aggregate( AggregateKind::Adt(st.into(), subst.clone()), - self.db - .variant_fields(st.into()) + st.fields(self.db) .fields() .iter() .map(|it| { diff --git a/crates/hir-ty/src/mir/lower/pattern_matching.rs b/crates/hir-ty/src/mir/lower/pattern_matching.rs index b3c1f6f387..61c0685c48 100644 --- a/crates/hir-ty/src/mir/lower/pattern_matching.rs +++ b/crates/hir-ty/src/mir/lower/pattern_matching.rs @@ -609,7 +609,7 @@ impl MirLowerCtx<'_> { } self.pattern_matching_variant_fields( shape, - &self.db.variant_fields(v.into()), + v.fields(self.db), variant, current, current_else, @@ -619,7 +619,7 @@ impl MirLowerCtx<'_> { } VariantId::StructId(s) => self.pattern_matching_variant_fields( shape, - &self.db.variant_fields(s.into()), + s.fields(self.db), variant, current, current_else, diff --git a/crates/hir-ty/src/mir/pretty.rs b/crates/hir-ty/src/mir/pretty.rs index 8764e48b53..78a69cf450 100644 --- a/crates/hir-ty/src/mir/pretty.rs +++ b/crates/hir-ty/src/mir/pretty.rs @@ -326,7 +326,7 @@ impl<'a> MirPrettyCtx<'a> { w!(this, ")"); } ProjectionElem::Field(Either::Left(field)) => { - let variant_fields = this.db.variant_fields(field.parent); + let variant_fields = field.parent.fields(this.db); let name = &variant_fields.fields()[field.local_id].name; match field.parent { hir_def::VariantId::EnumVariantId(e) => { diff --git a/crates/hir-ty/src/tests/incremental.rs b/crates/hir-ty/src/tests/incremental.rs index 903b1fb6ab..0262390651 100644 --- a/crates/hir-ty/src/tests/incremental.rs +++ b/crates/hir-ty/src/tests/incremental.rs @@ -596,8 +596,7 @@ fn main() { "struct_signature_with_source_map_shim", "generic_predicates_shim", "value_ty_shim", - "variant_fields_shim", - "variant_fields_with_source_map_shim", + "query_", "lang_item", "inherent_impls_in_crate_shim", "impl_signature_shim", @@ -697,7 +696,7 @@ fn main() { "function_signature_with_source_map_shim", "expr_scopes_shim", "struct_signature_with_source_map_shim", - "variant_fields_with_source_map_shim", + "query_", "inherent_impls_in_crate_shim", "impl_signature_with_source_map_shim", "impl_signature_shim", diff --git a/crates/hir/src/diagnostics.rs b/crates/hir/src/diagnostics.rs index 074bde91fb..aba2e032b3 100644 --- a/crates/hir/src/diagnostics.rs +++ b/crates/hir/src/diagnostics.rs @@ -490,7 +490,7 @@ impl<'db> AnyDiagnostic<'db> { ) -> Option> { match diagnostic { BodyValidationDiagnostic::RecordMissingFields { record, variant, missed_fields } => { - let variant_data = variant.variant_data(db); + let variant_data = variant.fields(db); let missed_fields = missed_fields .into_iter() .map(|idx| variant_data.fields()[idx].name.clone()) diff --git a/crates/hir/src/display.rs b/crates/hir/src/display.rs index 18bab7cbf9..2960ebedf3 100644 --- a/crates/hir/src/display.rs +++ b/crates/hir/src/display.rs @@ -404,7 +404,7 @@ impl HirDisplay for TupleField { impl HirDisplay for Variant { fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> { write!(f, "{}", self.name(f.db).display(f.db, f.edition()))?; - let data = f.db.variant_fields(self.id.into()); + let data = self.id.fields(f.db); match data.shape { FieldsShape::Unit => {} FieldsShape::Tuple => { diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 5ebb5628ad..6607d6c31e 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -668,25 +668,25 @@ impl Module { Adt::Struct(s) => { let source_map = db.struct_signature_with_source_map(s.id).1; expr_store_diagnostics(db, acc, &source_map); - let source_map = db.variant_fields_with_source_map(s.id.into()).1; - expr_store_diagnostics(db, acc, &source_map); + let source_map = &s.id.fields_with_source_map(db).1; + expr_store_diagnostics(db, acc, source_map); push_ty_diagnostics( db, acc, db.field_types_with_diagnostics(s.id.into()).1, - &source_map, + source_map, ); } Adt::Union(u) => { let source_map = db.union_signature_with_source_map(u.id).1; expr_store_diagnostics(db, acc, &source_map); - let source_map = db.variant_fields_with_source_map(u.id.into()).1; - expr_store_diagnostics(db, acc, &source_map); + let source_map = &u.id.fields_with_source_map(db).1; + expr_store_diagnostics(db, acc, source_map); push_ty_diagnostics( db, acc, db.field_types_with_diagnostics(u.id.into()).1, - &source_map, + source_map, ); } Adt::Enum(e) => { @@ -711,14 +711,14 @@ impl Module { } } for &(v, _, _) in &variants.variants { - let source_map = db.variant_fields_with_source_map(v.into()).1; + let source_map = &v.fields_with_source_map(db).1; push_ty_diagnostics( db, acc, db.field_types_with_diagnostics(v.into()).1, - &source_map, + source_map, ); - expr_store_diagnostics(db, acc, &source_map); + expr_store_diagnostics(db, acc, source_map); } } } @@ -1311,7 +1311,7 @@ impl AstNode for FieldSource { impl Field { pub fn name(&self, db: &dyn HirDatabase) -> Name { - db.variant_fields(self.parent.into()).fields()[self.id].name.clone() + VariantId::from(self.parent).fields(db).fields()[self.id].name.clone() } pub fn index(&self) -> usize { @@ -1380,7 +1380,7 @@ impl Field { impl HasVisibility for Field { fn visibility(&self, db: &dyn HirDatabase) -> Visibility { - let variant_data = db.variant_fields(self.parent.into()); + let variant_data = VariantId::from(self.parent).fields(db); let visibility = &variant_data.fields()[self.id].visibility; let parent_id: hir_def::VariantId = self.parent.into(); // FIXME: RawVisibility::Public doesn't need to construct a resolver @@ -1403,7 +1403,8 @@ impl Struct { } pub fn fields(self, db: &dyn HirDatabase) -> Vec { - db.variant_fields(self.id.into()) + self.id + .fields(db) .fields() .iter() .map(|(id, _)| Field { parent: self.into(), id }) @@ -1434,8 +1435,8 @@ impl Struct { } } - fn variant_fields(self, db: &dyn HirDatabase) -> Arc { - db.variant_fields(self.id.into()) + fn variant_fields(self, db: &dyn HirDatabase) -> &VariantFields { + self.id.fields(db) } pub fn is_unstable(self, db: &dyn HirDatabase) -> bool { @@ -1478,7 +1479,7 @@ impl Union { } pub fn kind(self, db: &dyn HirDatabase) -> StructKind { - match db.variant_fields(self.id.into()).shape { + match self.id.fields(db).shape { hir_def::item_tree::FieldsShape::Record => StructKind::Record, hir_def::item_tree::FieldsShape::Tuple => StructKind::Tuple, hir_def::item_tree::FieldsShape::Unit => StructKind::Unit, @@ -1486,7 +1487,8 @@ impl Union { } pub fn fields(self, db: &dyn HirDatabase) -> Vec { - db.variant_fields(self.id.into()) + self.id + .fields(db) .fields() .iter() .map(|(id, _)| Field { parent: self.into(), id }) @@ -1626,7 +1628,8 @@ impl Variant { } pub fn fields(self, db: &dyn HirDatabase) -> Vec { - db.variant_fields(self.id.into()) + self.id + .fields(db) .fields() .iter() .map(|(id, _)| Field { parent: self.into(), id }) @@ -1634,7 +1637,7 @@ impl Variant { } pub fn kind(self, db: &dyn HirDatabase) -> StructKind { - match db.variant_fields(self.id.into()).shape { + match self.id.fields(db).shape { hir_def::item_tree::FieldsShape::Record => StructKind::Record, hir_def::item_tree::FieldsShape::Tuple => StructKind::Tuple, hir_def::item_tree::FieldsShape::Unit => StructKind::Unit, diff --git a/crates/hir/src/semantics/child_by_source.rs b/crates/hir/src/semantics/child_by_source.rs index 188d0b9273..e7db93d375 100644 --- a/crates/hir/src/semantics/child_by_source.rs +++ b/crates/hir/src/semantics/child_by_source.rs @@ -191,7 +191,7 @@ impl ChildBySource for VariantId { Either::Right(source) => res[keys::RECORD_FIELD].insert(AstPtr::new(&source), id), } } - let (_, sm) = db.variant_fields_with_source_map(*self); + let (_, sm) = self.fields_with_source_map(db); sm.expansions().for_each(|(ast, &exp_id)| res[keys::MACRO_CALL].insert(ast.value, exp_id)); } } diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs index ae72cc6f5a..f18ca7cb20 100644 --- a/crates/hir/src/source_analyzer.rs +++ b/crates/hir/src/source_analyzer.rs @@ -156,14 +156,14 @@ impl<'db> SourceAnalyzer<'db> { InFile { file_id, .. }: InFile<&SyntaxNode>, _offset: Option, ) -> SourceAnalyzer<'db> { - let (fields, source_map) = db.variant_fields_with_source_map(def); + let (fields, source_map) = def.fields_with_source_map(db); let resolver = def.resolver(db); SourceAnalyzer { resolver, body_or_sig: Some(BodyOrSig::VariantFields { def, store: fields.store.clone(), - source_map, + source_map: source_map.clone(), }), file_id, } @@ -713,7 +713,7 @@ impl<'db> SourceAnalyzer<'db> { }; let (adt, subst) = self.infer()?.type_of_expr_or_pat(expr_id)?.as_adt()?; let variant = self.infer()?.variant_resolution_for_expr_or_pat(expr_id)?; - let variant_data = variant.variant_data(db); + let variant_data = variant.fields(db); let field = FieldId { parent: variant, local_id: variant_data.field(&local_name)? }; let field_ty = db.field_types(variant).get(field.local_id)?.clone().substitute(Interner, subst); @@ -734,7 +734,7 @@ impl<'db> SourceAnalyzer<'db> { let record_pat = ast::RecordPat::cast(field.syntax().parent().and_then(|p| p.parent())?)?; let pat_id = self.pat_id(&record_pat.into())?; let variant = self.infer()?.variant_resolution_for_pat(pat_id.as_pat()?)?; - let variant_data = variant.variant_data(db); + let variant_data = variant.fields(db); let field = FieldId { parent: variant, local_id: variant_data.field(&field_name)? }; let (adt, subst) = self.infer()?.type_of_pat.get(pat_id.as_pat()?)?.as_adt()?; let field_ty = @@ -803,8 +803,8 @@ impl<'db> SourceAnalyzer<'db> { }; container = Either::Right(db.normalize_projection(projection, trait_env.clone())); } - let handle_variants = |variant, subst: &Substitution, container: &mut _| { - let fields = db.variant_fields(variant); + let handle_variants = |variant: VariantId, subst: &Substitution, container: &mut _| { + let fields = variant.fields(db); let field = fields.field(&field_name.as_name())?; let field_types = db.field_types(variant); *container = Either::Right(field_types[field].clone().substitute(Interner, subst));