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 | 106 |
1 files changed, 65 insertions, 41 deletions
diff --git a/crates/hir-def/src/signatures.rs b/crates/hir-def/src/signatures.rs index 6d704274f4..e58befae20 100644 --- a/crates/hir-def/src/signatures.rs +++ b/crates/hir-def/src/signatures.rs @@ -8,9 +8,9 @@ use hir_expand::{ InFile, Intern, Lookup, name::{AsName, Name}, }; -use intern::{Symbol, sym}; +use intern::sym; use la_arena::{Arena, Idx}; -use rustc_abi::{IntegerType, ReprOptions}; +use rustc_abi::{ExternAbi, IntegerType, ReprOptions}; use syntax::{ AstNode, NodeOrToken, SyntaxNodePtr, T, ast::{self, HasGenericParams, HasName, HasVisibility, IsString}, @@ -128,13 +128,11 @@ impl StructSignature { source_map, ) } -} -impl StructSignature { #[inline] pub fn repr(&self, db: &dyn DefDatabase, id: StructId) -> Option<ReprOptions> { if self.flags.contains(StructFlags::HAS_REPR) { - AttrFlags::repr(db, id.into()) + AttrFlags::repr_assume_has(db, id.into()) } else { None } @@ -202,6 +200,15 @@ impl UnionSignature { source_map, ) } + + #[inline] + pub fn repr(&self, db: &dyn DefDatabase, id: UnionId) -> Option<ReprOptions> { + if self.flags.contains(StructFlags::HAS_REPR) { + AttrFlags::repr_assume_has(db, id.into()) + } else { + None + } + } } bitflags! { @@ -211,6 +218,8 @@ bitflags! { const HAS_REPR = 1 << 0; /// Indicates whether the enum has a `#[rustc_has_incoherent_inherent_impls]` attribute. const RUSTC_HAS_INCOHERENT_INHERENT_IMPLS = 1 << 1; + /// Whether this enum has `#[fundamental]`. + const FUNDAMENTAL = 1 << 2; } } @@ -243,6 +252,9 @@ impl EnumSignature { if attrs.contains(AttrFlags::HAS_REPR) { flags |= EnumFlags::HAS_REPR; } + if attrs.contains(AttrFlags::FUNDAMENTAL) { + flags |= EnumFlags::FUNDAMENTAL; + } let InFile { file_id, value: source } = loc.source(db); let (store, generic_params, source_map) = lower_generic_params( @@ -276,7 +288,11 @@ impl EnumSignature { #[inline] pub fn repr(&self, db: &dyn DefDatabase, id: EnumId) -> Option<ReprOptions> { - if self.flags.contains(EnumFlags::HAS_REPR) { AttrFlags::repr(db, id.into()) } else { None } + if self.flags.contains(EnumFlags::HAS_REPR) { + AttrFlags::repr_assume_has(db, id.into()) + } else { + None + } } } bitflags::bitflags! { @@ -567,19 +583,20 @@ bitflags! { const DEFAULT = 1 << 2; const CONST = 1 << 3; const ASYNC = 1 << 4; - const UNSAFE = 1 << 5; - const HAS_VARARGS = 1 << 6; - const RUSTC_ALLOW_INCOHERENT_IMPL = 1 << 7; - const HAS_SELF_PARAM = 1 << 8; + const GEN = 1 << 5; + const UNSAFE = 1 << 6; + const HAS_VARARGS = 1 << 7; + const RUSTC_ALLOW_INCOHERENT_IMPL = 1 << 8; + const HAS_SELF_PARAM = 1 << 9; /// The `#[target_feature]` attribute is necessary to check safety (with RFC 2396), /// but keeping it for all functions will consume a lot of memory when there are /// only very few functions with it. So we only encode its existence here, and lookup /// it if needed. - 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 HAS_TARGET_FEATURE = 1 << 10; + const DEPRECATED_SAFE_2024 = 1 << 11; + const EXPLICIT_SAFE = 1 << 12; + const HAS_LEGACY_CONST_GENERICS = 1 << 13; + const RUSTC_INTRINSIC = 1 << 14; } } @@ -590,7 +607,7 @@ pub struct FunctionSignature { pub store: ExpressionStore, pub params: Box<[TypeRefId]>, pub ret_type: Option<TypeRefId>, - pub abi: Option<Symbol>, + pub abi: ExternAbi, pub flags: FnFlags, } @@ -638,6 +655,9 @@ impl FunctionSignature { if source.value.async_token().is_some() { flags.insert(FnFlags::ASYNC); } + if source.value.gen_token().is_some() { + flags.insert(FnFlags::GEN); + } if source.value.const_token().is_some() { flags.insert(FnFlags::CONST); } @@ -652,9 +672,23 @@ impl FunctionSignature { } 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())) - }); + let abi = source + .value + .abi() + .map(|abi| { + abi.abi_string() + .and_then(|abi| abi.text_without_quotes().parse().ok()) + .unwrap_or(ExternAbi::FALLBACK) + }) + .or_else(|| match loc.container { + ItemContainerId::ExternBlockId(extern_block) => { + Some(extern_block_abi(db, extern_block)) + } + ItemContainerId::ModuleId(_) + | ItemContainerId::ImplId(_) + | ItemContainerId::TraitId(_) => None, + }) + .unwrap_or(ExternAbi::Rust); let (store, source_map, generic_params, params, ret_type, self_param, variadic) = lower_function(db, module, source, id); if self_param { @@ -701,6 +735,10 @@ impl FunctionSignature { self.flags.contains(FnFlags::ASYNC) } + pub fn is_gen(&self) -> bool { + self.flags.contains(FnFlags::GEN) + } + pub fn is_unsafe(&self) -> bool { self.flags.contains(FnFlags::UNSAFE) } @@ -737,16 +775,6 @@ impl FunctionSignature { pub fn is_intrinsic(db: &dyn DefDatabase, id: FunctionId) -> bool { let data = FunctionSignature::of(db, id); data.flags.contains(FnFlags::RUSTC_INTRINSIC) - // Keep this around for a bit until extern "rustc-intrinsic" abis are no longer used - || match &data.abi { - Some(abi) => *abi == sym::rust_dash_intrinsic, - None => match id.lookup(db).container { - ItemContainerId::ExternBlockId(block) => { - block.abi(db) == Some(sym::rust_dash_intrinsic) - } - _ => false, - }, - } } } @@ -958,7 +986,7 @@ fn lower_fields<Field: ast::HasAttrs + ast::HasVisibility>( override_visibility: Option<Option<ast::Visibility>>, ) -> Option<(Arena<FieldData>, ExpressionStore, ExpressionStoreSourceMap)> { let cfg_options = module.krate(db).cfg_options(db); - let mut col = ExprCollector::signature(db, module, fields.file_id); + 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); @@ -1110,16 +1138,12 @@ impl EnumVariants { } } -pub(crate) fn extern_block_abi( - db: &dyn DefDatabase, - extern_block: ExternBlockId, -) -> Option<Symbol> { +#[salsa::tracked] +pub(crate) fn extern_block_abi(db: &dyn DefDatabase, extern_block: ExternBlockId) -> ExternAbi { 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, - } - }) + source + .value + .abi() + .and_then(|abi| abi.abi_string()?.text_without_quotes().parse().ok()) + .unwrap_or(ExternAbi::FALLBACK) } |