Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-def/src/signatures.rs')
| -rw-r--r-- | crates/hir-def/src/signatures.rs | 141 |
1 files changed, 74 insertions, 67 deletions
diff --git a/crates/hir-def/src/signatures.rs b/crates/hir-def/src/signatures.rs index ebbf87cad6..e8ccf56059 100644 --- a/crates/hir-def/src/signatures.rs +++ b/crates/hir-def/src/signatures.rs @@ -21,7 +21,7 @@ use triomphe::Arc; use crate::{ ConstId, EnumId, EnumVariantId, EnumVariantLoc, ExternBlockId, FunctionId, HasModule, ImplId, ItemContainerId, ModuleId, StaticId, StructId, TraitId, TypeAliasId, UnionId, VariantId, - attr::Attrs, + attrs::AttrFlags, db::DefDatabase, expr_store::{ ExpressionStore, ExpressionStoreSourceMap, @@ -31,7 +31,6 @@ use crate::{ }, hir::{ExprId, PatId, generics::GenericParams}, item_tree::{FieldsShape, RawVisibility, visibility_from_ast}, - lang_item::LangItem, src::HasSource, type_ref::{TraitRef, TypeBound, TypeRefId}, }; @@ -48,12 +47,13 @@ pub struct StructSignature { pub store: Arc<ExpressionStore>, pub flags: StructFlags, pub shape: FieldsShape, - pub repr: Option<ReprOptions>, } bitflags! { #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub struct StructFlags: u8 { + /// Indicates whether this struct has `#[repr]`. + const HAS_REPR = 1 << 0; /// Indicates whether the struct has a `#[rustc_has_incoherent_inherent_impls]` attribute. const RUSTC_HAS_INCOHERENT_INHERENT_IMPLS = 1 << 1; /// Indicates whether the struct has a `#[fundamental]` attribute. @@ -75,26 +75,28 @@ impl StructSignature { pub fn query(db: &dyn DefDatabase, id: StructId) -> (Arc<Self>, Arc<ExpressionStoreSourceMap>) { let loc = id.lookup(db); let InFile { file_id, value: source } = loc.source(db); - let attrs = db.attrs(id.into()); + let attrs = AttrFlags::query(db, id.into()); let mut flags = StructFlags::empty(); - if attrs.by_key(sym::rustc_has_incoherent_inherent_impls).exists() { + if attrs.contains(AttrFlags::RUSTC_HAS_INCOHERENT_INHERENT_IMPLS) { flags |= StructFlags::RUSTC_HAS_INCOHERENT_INHERENT_IMPLS; } - if attrs.by_key(sym::fundamental).exists() { + if attrs.contains(AttrFlags::FUNDAMENTAL) { flags |= StructFlags::FUNDAMENTAL; } - if let Some(lang) = attrs.lang_item() { + if attrs.contains(AttrFlags::HAS_REPR) { + flags |= StructFlags::HAS_REPR; + } + if let Some(lang) = attrs.lang_item_with_attrs(db, id.into()) { match lang { - LangItem::PhantomData => flags |= StructFlags::IS_PHANTOM_DATA, - LangItem::OwnedBox => flags |= StructFlags::IS_BOX, - LangItem::ManuallyDrop => flags |= StructFlags::IS_MANUALLY_DROP, - LangItem::UnsafeCell => flags |= StructFlags::IS_UNSAFE_CELL, - LangItem::UnsafePinned => flags |= StructFlags::IS_UNSAFE_PINNED, + _ if lang == sym::phantom_data => flags |= StructFlags::IS_PHANTOM_DATA, + _ if lang == sym::owned_box => flags |= StructFlags::IS_BOX, + _ if lang == sym::manually_drop => flags |= StructFlags::IS_MANUALLY_DROP, + _ if lang == sym::unsafe_cell => flags |= StructFlags::IS_UNSAFE_CELL, + _ if lang == sym::unsafe_pinned => flags |= StructFlags::IS_UNSAFE_PINNED, _ => (), } } - let repr = attrs.repr(); let shape = adt_shape(source.kind()); let (store, generic_params, source_map) = lower_generic_params( @@ -112,11 +114,19 @@ impl StructSignature { flags, shape, name: as_name_opt(source.name()), - repr, }), Arc::new(source_map), ) } + + #[inline] + pub fn repr(&self, db: &dyn DefDatabase, id: StructId) -> Option<ReprOptions> { + if self.flags.contains(StructFlags::HAS_REPR) { + AttrFlags::repr(db, id.into()) + } else { + None + } + } } #[inline] @@ -134,22 +144,22 @@ pub struct UnionSignature { pub generic_params: Arc<GenericParams>, pub store: Arc<ExpressionStore>, pub flags: StructFlags, - pub repr: Option<ReprOptions>, } impl UnionSignature { pub fn query(db: &dyn DefDatabase, id: UnionId) -> (Arc<Self>, Arc<ExpressionStoreSourceMap>) { let loc = id.lookup(db); - let attrs = db.attrs(id.into()); + let attrs = AttrFlags::query(db, id.into()); let mut flags = StructFlags::empty(); - if attrs.by_key(sym::rustc_has_incoherent_inherent_impls).exists() { + if attrs.contains(AttrFlags::RUSTC_HAS_INCOHERENT_INHERENT_IMPLS) { flags |= StructFlags::RUSTC_HAS_INCOHERENT_INHERENT_IMPLS; } - if attrs.by_key(sym::fundamental).exists() { + if attrs.contains(AttrFlags::FUNDAMENTAL) { flags |= StructFlags::FUNDAMENTAL; } - - let repr = attrs.repr(); + if attrs.contains(AttrFlags::HAS_REPR) { + flags |= StructFlags::HAS_REPR; + } let InFile { file_id, value: source } = loc.source(db); let (store, generic_params, source_map) = lower_generic_params( @@ -165,7 +175,6 @@ impl UnionSignature { generic_params, store, flags, - repr, name: as_name_opt(source.name()), }), Arc::new(source_map), @@ -186,20 +195,17 @@ pub struct EnumSignature { pub generic_params: Arc<GenericParams>, pub store: Arc<ExpressionStore>, pub flags: EnumFlags, - pub repr: Option<ReprOptions>, } impl EnumSignature { pub fn query(db: &dyn DefDatabase, id: EnumId) -> (Arc<Self>, Arc<ExpressionStoreSourceMap>) { let loc = id.lookup(db); - let attrs = db.attrs(id.into()); + let attrs = AttrFlags::query(db, id.into()); let mut flags = EnumFlags::empty(); - if attrs.by_key(sym::rustc_has_incoherent_inherent_impls).exists() { + if attrs.contains(AttrFlags::RUSTC_HAS_INCOHERENT_INHERENT_IMPLS) { flags |= EnumFlags::RUSTC_HAS_INCOHERENT_INHERENT_IMPLS; } - let repr = attrs.repr(); - let InFile { file_id, value: source } = loc.source(db); let (store, generic_params, source_map) = lower_generic_params( db, @@ -215,15 +221,14 @@ impl EnumSignature { generic_params, store, flags, - repr, name: as_name_opt(source.name()), }), Arc::new(source_map), ) } - pub fn variant_body_type(&self) -> IntegerType { - match self.repr { + pub fn variant_body_type(db: &dyn DefDatabase, id: EnumId) -> IntegerType { + match AttrFlags::repr(db, id.into()) { Some(ReprOptions { int: Some(builtin), .. }) => builtin, _ => IntegerType::Pointer(true), } @@ -251,9 +256,9 @@ impl ConstSignature { let loc = id.lookup(db); let module = loc.container.module(db); - let attrs = db.attrs(id.into()); + let attrs = AttrFlags::query(db, id.into()); let mut flags = ConstFlags::empty(); - if attrs.by_key(sym::rustc_allow_incoherent_impl).exists() { + if attrs.contains(AttrFlags::RUSTC_ALLOW_INCOHERENT_IMPL) { flags |= ConstFlags::RUSTC_ALLOW_INCOHERENT_IMPL; } let source = loc.source(db); @@ -306,9 +311,9 @@ impl StaticSignature { let loc = id.lookup(db); let module = loc.container.module(db); - let attrs = db.attrs(id.into()); + let attrs = AttrFlags::query(db, id.into()); let mut flags = StaticFlags::empty(); - if attrs.by_key(sym::rustc_allow_incoherent_impl).exists() { + if attrs.contains(AttrFlags::RUSTC_ALLOW_INCOHERENT_IMPL) { flags |= StaticFlags::RUSTC_ALLOW_INCOHERENT_IMPL; } @@ -433,7 +438,7 @@ impl TraitSignature { let loc = id.lookup(db); let mut flags = TraitFlags::empty(); - let attrs = db.attrs(id.into()); + let attrs = AttrFlags::query(db, id.into()); let source = loc.source(db); if source.value.auto_token().is_some() { flags.insert(TraitFlags::AUTO); @@ -444,34 +449,23 @@ impl TraitSignature { if source.value.eq_token().is_some() { flags.insert(TraitFlags::ALIAS); } - if attrs.by_key(sym::fundamental).exists() { + if attrs.contains(AttrFlags::FUNDAMENTAL) { flags |= TraitFlags::FUNDAMENTAL; } - if attrs.by_key(sym::rustc_has_incoherent_inherent_impls).exists() { + if attrs.contains(AttrFlags::RUSTC_HAS_INCOHERENT_INHERENT_IMPLS) { flags |= TraitFlags::RUSTC_HAS_INCOHERENT_INHERENT_IMPLS; } - if attrs.by_key(sym::rustc_paren_sugar).exists() { + if attrs.contains(AttrFlags::RUSTC_PAREN_SUGAR) { flags |= TraitFlags::RUSTC_PAREN_SUGAR; } - if attrs.by_key(sym::rustc_coinductive).exists() { + if attrs.contains(AttrFlags::RUSTC_COINDUCTIVE) { flags |= TraitFlags::COINDUCTIVE; } - let mut skip_array_during_method_dispatch = - attrs.by_key(sym::rustc_skip_array_during_method_dispatch).exists(); - let mut skip_boxed_slice_during_method_dispatch = false; - for tt in attrs.by_key(sym::rustc_skip_during_method_dispatch).tt_values() { - for tt in tt.iter() { - if let tt::iter::TtElement::Leaf(tt::Leaf::Ident(ident)) = tt { - skip_array_during_method_dispatch |= ident.sym == sym::array; - skip_boxed_slice_during_method_dispatch |= ident.sym == sym::boxed_slice; - } - } - } - if skip_array_during_method_dispatch { + if attrs.contains(AttrFlags::RUSTC_SKIP_ARRAY_DURING_METHOD_DISPATCH) { flags |= TraitFlags::SKIP_ARRAY_DURING_METHOD_DISPATCH; } - if skip_boxed_slice_during_method_dispatch { + if attrs.contains(AttrFlags::RUSTC_SKIP_BOXED_SLICE_DURING_METHOD_DISPATCH) { flags |= TraitFlags::SKIP_BOXED_SLICE_DURING_METHOD_DISPATCH; } @@ -503,7 +497,8 @@ bitflags! { const HAS_TARGET_FEATURE = 1 << 9; const DEPRECATED_SAFE_2024 = 1 << 10; const EXPLICIT_SAFE = 1 << 11; - const RUSTC_INTRINSIC = 1 << 12; + const HAS_LEGACY_CONST_GENERICS = 1 << 12; + const RUSTC_INTRINSIC = 1 << 13; } } @@ -516,8 +511,6 @@ pub struct FunctionSignature { pub ret_type: Option<TypeRefId>, pub abi: Option<Symbol>, pub flags: FnFlags, - // FIXME: we should put this behind a fn flags + query to avoid bloating the struct - pub legacy_const_generics_indices: Option<Box<Box<[u32]>>>, } impl FunctionSignature { @@ -529,23 +522,26 @@ impl FunctionSignature { let module = loc.container.module(db); let mut flags = FnFlags::empty(); - let attrs = db.attrs(id.into()); - if attrs.by_key(sym::rustc_allow_incoherent_impl).exists() { + let attrs = AttrFlags::query(db, id.into()); + if attrs.contains(AttrFlags::RUSTC_ALLOW_INCOHERENT_IMPL) { flags.insert(FnFlags::RUSTC_ALLOW_INCOHERENT_IMPL); } - if attrs.by_key(sym::target_feature).exists() { + if attrs.contains(AttrFlags::HAS_TARGET_FEATURE) { flags.insert(FnFlags::HAS_TARGET_FEATURE); } - if attrs.by_key(sym::rustc_intrinsic).exists() { + + if attrs.contains(AttrFlags::RUSTC_INTRINSIC) { flags.insert(FnFlags::RUSTC_INTRINSIC); } - let legacy_const_generics_indices = attrs.rustc_legacy_const_generics(); + if attrs.contains(AttrFlags::HAS_LEGACY_CONST_GENERICS) { + flags.insert(FnFlags::HAS_LEGACY_CONST_GENERICS); + } let source = loc.source(db); if source.value.unsafe_token().is_some() { - if attrs.by_key(sym::rustc_deprecated_safe_2024).exists() { + if attrs.contains(AttrFlags::RUSTC_DEPRECATED_SAFE_2024) { flags.insert(FnFlags::DEPRECATED_SAFE_2024); } else { flags.insert(FnFlags::UNSAFE); @@ -587,7 +583,6 @@ impl FunctionSignature { ret_type, abi, flags, - legacy_const_generics_indices, name, }), Arc::new(source_map), @@ -636,6 +631,19 @@ impl FunctionSignature { self.flags.contains(FnFlags::HAS_TARGET_FEATURE) } + #[inline] + pub fn legacy_const_generics_indices<'db>( + &self, + db: &'db dyn DefDatabase, + id: FunctionId, + ) -> Option<&'db [u32]> { + if !self.flags.contains(FnFlags::HAS_LEGACY_CONST_GENERICS) { + return None; + } + + AttrFlags::legacy_const_generic_indices(db, id).as_deref() + } + pub fn is_intrinsic(db: &dyn DefDatabase, id: FunctionId) -> bool { let data = db.function_signature(id); data.flags.contains(FnFlags::RUSTC_INTRINSIC) @@ -679,11 +687,11 @@ impl TypeAliasSignature { let loc = id.lookup(db); let mut flags = TypeAliasFlags::empty(); - let attrs = db.attrs(id.into()); - if attrs.by_key(sym::rustc_has_incoherent_inherent_impls).exists() { + let attrs = AttrFlags::query(db, id.into()); + if attrs.contains(AttrFlags::RUSTC_HAS_INCOHERENT_INHERENT_IMPLS) { flags.insert(TypeAliasFlags::RUSTC_HAS_INCOHERENT_INHERENT_IMPL); } - if attrs.by_key(sym::rustc_allow_incoherent_impl).exists() { + if attrs.contains(AttrFlags::RUSTC_ALLOW_INCOHERENT_IMPL) { flags.insert(TypeAliasFlags::RUSTC_ALLOW_INCOHERENT_IMPL); } if matches!(loc.container, ItemContainerId::ExternBlockId(_)) { @@ -866,7 +874,7 @@ fn lower_fields<Field: ast::HasAttrs + ast::HasVisibility>( 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) { + match AttrFlags::is_cfg_enabled_for(&field, cfg_options) { Ok(()) => { let type_ref = col.lower_type_ref_opt(ty, &mut ExprCollector::impl_trait_error_allocator); @@ -928,7 +936,6 @@ impl EnumVariants { let loc = e.lookup(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); @@ -940,7 +947,7 @@ impl EnumVariants { .variants() .filter_map(|variant| { let ast_id = ast_id_map.ast_id(&variant); - match Attrs::is_cfg_enabled_for(db, &variant, span_map.as_ref(), cfg_options) { + match AttrFlags::is_cfg_enabled_for(&variant, cfg_options) { Ok(()) => { let enum_variant = EnumVariantLoc { id: source.with_value(ast_id), parent: e, index } |