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 | 130 |
1 files changed, 61 insertions, 69 deletions
diff --git a/crates/hir-def/src/signatures.rs b/crates/hir-def/src/signatures.rs index c9e8955ad6..ebbf87cad6 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, - attrs::AttrFlags, + attr::Attrs, db::DefDatabase, expr_store::{ ExpressionStore, ExpressionStoreSourceMap, @@ -48,13 +48,12 @@ 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. @@ -76,19 +75,16 @@ 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 = AttrFlags::query(db, id.into()); + let attrs = db.attrs(id.into()); let mut flags = StructFlags::empty(); - if attrs.contains(AttrFlags::RUSTC_HAS_INCOHERENT_INHERENT_IMPLS) { + if attrs.by_key(sym::rustc_has_incoherent_inherent_impls).exists() { flags |= StructFlags::RUSTC_HAS_INCOHERENT_INHERENT_IMPLS; } - if attrs.contains(AttrFlags::FUNDAMENTAL) { + if attrs.by_key(sym::fundamental).exists() { flags |= StructFlags::FUNDAMENTAL; } - if attrs.contains(AttrFlags::HAS_REPR) { - flags |= StructFlags::HAS_REPR; - } - if let Some(lang) = attrs.lang_item_with_attrs(db, id.into()) { + if let Some(lang) = attrs.lang_item() { match lang { LangItem::PhantomData => flags |= StructFlags::IS_PHANTOM_DATA, LangItem::OwnedBox => flags |= StructFlags::IS_BOX, @@ -98,6 +94,7 @@ impl StructSignature { _ => (), } } + let repr = attrs.repr(); let shape = adt_shape(source.kind()); let (store, generic_params, source_map) = lower_generic_params( @@ -115,19 +112,11 @@ 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] @@ -145,22 +134,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 = AttrFlags::query(db, id.into()); + let attrs = db.attrs(id.into()); let mut flags = StructFlags::empty(); - if attrs.contains(AttrFlags::RUSTC_HAS_INCOHERENT_INHERENT_IMPLS) { + if attrs.by_key(sym::rustc_has_incoherent_inherent_impls).exists() { flags |= StructFlags::RUSTC_HAS_INCOHERENT_INHERENT_IMPLS; } - if attrs.contains(AttrFlags::FUNDAMENTAL) { + if attrs.by_key(sym::fundamental).exists() { flags |= StructFlags::FUNDAMENTAL; } - if attrs.contains(AttrFlags::HAS_REPR) { - flags |= StructFlags::HAS_REPR; - } + + let repr = attrs.repr(); let InFile { file_id, value: source } = loc.source(db); let (store, generic_params, source_map) = lower_generic_params( @@ -176,6 +165,7 @@ impl UnionSignature { generic_params, store, flags, + repr, name: as_name_opt(source.name()), }), Arc::new(source_map), @@ -196,17 +186,20 @@ 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 = AttrFlags::query(db, id.into()); + let attrs = db.attrs(id.into()); let mut flags = EnumFlags::empty(); - if attrs.contains(AttrFlags::RUSTC_HAS_INCOHERENT_INHERENT_IMPLS) { + if attrs.by_key(sym::rustc_has_incoherent_inherent_impls).exists() { 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, @@ -222,14 +215,15 @@ impl EnumSignature { generic_params, store, flags, + repr, name: as_name_opt(source.name()), }), Arc::new(source_map), ) } - pub fn variant_body_type(db: &dyn DefDatabase, id: EnumId) -> IntegerType { - match AttrFlags::repr(db, id.into()) { + pub fn variant_body_type(&self) -> IntegerType { + match self.repr { Some(ReprOptions { int: Some(builtin), .. }) => builtin, _ => IntegerType::Pointer(true), } @@ -257,9 +251,9 @@ impl ConstSignature { let loc = id.lookup(db); let module = loc.container.module(db); - let attrs = AttrFlags::query(db, id.into()); + let attrs = db.attrs(id.into()); let mut flags = ConstFlags::empty(); - if attrs.contains(AttrFlags::RUSTC_ALLOW_INCOHERENT_IMPL) { + if attrs.by_key(sym::rustc_allow_incoherent_impl).exists() { flags |= ConstFlags::RUSTC_ALLOW_INCOHERENT_IMPL; } let source = loc.source(db); @@ -312,9 +306,9 @@ impl StaticSignature { let loc = id.lookup(db); let module = loc.container.module(db); - let attrs = AttrFlags::query(db, id.into()); + let attrs = db.attrs(id.into()); let mut flags = StaticFlags::empty(); - if attrs.contains(AttrFlags::RUSTC_ALLOW_INCOHERENT_IMPL) { + if attrs.by_key(sym::rustc_allow_incoherent_impl).exists() { flags |= StaticFlags::RUSTC_ALLOW_INCOHERENT_IMPL; } @@ -439,7 +433,7 @@ impl TraitSignature { let loc = id.lookup(db); let mut flags = TraitFlags::empty(); - let attrs = AttrFlags::query(db, id.into()); + let attrs = db.attrs(id.into()); let source = loc.source(db); if source.value.auto_token().is_some() { flags.insert(TraitFlags::AUTO); @@ -450,23 +444,34 @@ impl TraitSignature { if source.value.eq_token().is_some() { flags.insert(TraitFlags::ALIAS); } - if attrs.contains(AttrFlags::FUNDAMENTAL) { + if attrs.by_key(sym::fundamental).exists() { flags |= TraitFlags::FUNDAMENTAL; } - if attrs.contains(AttrFlags::RUSTC_HAS_INCOHERENT_INHERENT_IMPLS) { + if attrs.by_key(sym::rustc_has_incoherent_inherent_impls).exists() { flags |= TraitFlags::RUSTC_HAS_INCOHERENT_INHERENT_IMPLS; } - if attrs.contains(AttrFlags::RUSTC_PAREN_SUGAR) { + if attrs.by_key(sym::rustc_paren_sugar).exists() { flags |= TraitFlags::RUSTC_PAREN_SUGAR; } - if attrs.contains(AttrFlags::RUSTC_COINDUCTIVE) { + if attrs.by_key(sym::rustc_coinductive).exists() { 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 attrs.contains(AttrFlags::RUSTC_SKIP_ARRAY_DURING_METHOD_DISPATCH) { + if skip_array_during_method_dispatch { flags |= TraitFlags::SKIP_ARRAY_DURING_METHOD_DISPATCH; } - if attrs.contains(AttrFlags::RUSTC_SKIP_BOXED_SLICE_DURING_METHOD_DISPATCH) { + if skip_boxed_slice_during_method_dispatch { flags |= TraitFlags::SKIP_BOXED_SLICE_DURING_METHOD_DISPATCH; } @@ -498,8 +503,7 @@ bitflags! { const HAS_TARGET_FEATURE = 1 << 9; const DEPRECATED_SAFE_2024 = 1 << 10; const EXPLICIT_SAFE = 1 << 11; - const HAS_LEGACY_CONST_GENERICS = 1 << 12; - const RUSTC_INTRINSIC = 1 << 13; + const RUSTC_INTRINSIC = 1 << 12; } } @@ -512,6 +516,8 @@ 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 { @@ -523,26 +529,23 @@ impl FunctionSignature { let module = loc.container.module(db); let mut flags = FnFlags::empty(); - let attrs = AttrFlags::query(db, id.into()); - if attrs.contains(AttrFlags::RUSTC_ALLOW_INCOHERENT_IMPL) { + let attrs = db.attrs(id.into()); + if attrs.by_key(sym::rustc_allow_incoherent_impl).exists() { flags.insert(FnFlags::RUSTC_ALLOW_INCOHERENT_IMPL); } - if attrs.contains(AttrFlags::HAS_TARGET_FEATURE) { + if attrs.by_key(sym::target_feature).exists() { flags.insert(FnFlags::HAS_TARGET_FEATURE); } - - if attrs.contains(AttrFlags::RUSTC_INTRINSIC) { + if attrs.by_key(sym::rustc_intrinsic).exists() { flags.insert(FnFlags::RUSTC_INTRINSIC); } - if attrs.contains(AttrFlags::HAS_LEGACY_CONST_GENERICS) { - flags.insert(FnFlags::HAS_LEGACY_CONST_GENERICS); - } + let legacy_const_generics_indices = attrs.rustc_legacy_const_generics(); let source = loc.source(db); if source.value.unsafe_token().is_some() { - if attrs.contains(AttrFlags::RUSTC_DEPRECATED_SAFE_2024) { + if attrs.by_key(sym::rustc_deprecated_safe_2024).exists() { flags.insert(FnFlags::DEPRECATED_SAFE_2024); } else { flags.insert(FnFlags::UNSAFE); @@ -584,6 +587,7 @@ impl FunctionSignature { ret_type, abi, flags, + legacy_const_generics_indices, name, }), Arc::new(source_map), @@ -632,19 +636,6 @@ 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) @@ -688,11 +679,11 @@ impl TypeAliasSignature { let loc = id.lookup(db); let mut flags = TypeAliasFlags::empty(); - let attrs = AttrFlags::query(db, id.into()); - if attrs.contains(AttrFlags::RUSTC_HAS_INCOHERENT_INHERENT_IMPLS) { + 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); } - if attrs.contains(AttrFlags::RUSTC_ALLOW_INCOHERENT_IMPL) { + if attrs.by_key(sym::rustc_allow_incoherent_impl).exists() { flags.insert(TypeAliasFlags::RUSTC_ALLOW_INCOHERENT_IMPL); } if matches!(loc.container, ItemContainerId::ExternBlockId(_)) { @@ -875,7 +866,7 @@ fn lower_fields<Field: ast::HasAttrs + ast::HasVisibility>( let mut has_fields = false; for (ty, field) in fields.value { has_fields = true; - match AttrFlags::is_cfg_enabled_for(&field, cfg_options) { + 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); @@ -937,6 +928,7 @@ 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); @@ -948,7 +940,7 @@ impl EnumVariants { .variants() .filter_map(|variant| { let ast_id = ast_id_map.ast_id(&variant); - match AttrFlags::is_cfg_enabled_for(&variant, cfg_options) { + 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 } |