diff --git a/crates/hir-def/src/attr.rs b/crates/hir-def/src/attr.rs index 005d5830ea..119b4fc610 100644 --- a/crates/hir-def/src/attr.rs +++ b/crates/hir-def/src/attr.rs @@ -76,7 +76,6 @@ impl Attrs { 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 { VariantId::EnumVariantId(it) => { diff --git a/crates/hir-def/src/data.rs b/crates/hir-def/src/data.rs deleted file mode 100644 index e1fe13f9af..0000000000 --- a/crates/hir-def/src/data.rs +++ /dev/null @@ -1,605 +0,0 @@ -//! Contains basic data about various HIR declarations. - -pub mod adt; - -use base_db::Crate; -use hir_expand::name::Name; -use intern::{Symbol, sym}; -use la_arena::{Idx, RawIdx}; -use triomphe::Arc; - -use crate::{ - ConstId, ExternCrateId, FunctionId, HasModule, ImplId, ItemContainerId, ItemLoc, Lookup, - Macro2Id, MacroRulesId, ProcMacroId, StaticId, TraitAliasId, TraitId, TypeAliasId, - db::DefDatabase, - item_tree::{self, FnFlags, ModItem, StaticFlags}, - nameres::proc_macro::{ProcMacroKind, parse_macro_name_and_helper_attrs}, - path::ImportAlias, - type_ref::{TraitRef, TypeBound, TypeRefId, TypesMap}, - visibility::RawVisibility, -}; - -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct FunctionData { - pub name: Name, - pub params: Box<[TypeRefId]>, - pub ret_type: TypeRefId, - pub visibility: RawVisibility, - pub abi: Option, - pub legacy_const_generics_indices: Option>>, - pub types_map: Arc, - pub flags: FnFlags, -} - -impl FunctionData { - pub(crate) fn fn_data_query(db: &dyn DefDatabase, func: FunctionId) -> Arc { - let loc = func.lookup(db); - let krate = loc.container.module(db).krate; - let item_tree = loc.id.item_tree(db); - let func = &item_tree[loc.id.value]; - let visibility = if let ItemContainerId::TraitId(trait_id) = loc.container { - trait_vis(db, trait_id) - } else { - item_tree[func.visibility].clone() - }; - - let cfg_options = krate.cfg_options(db); - let attr_owner = |idx| { - item_tree::AttrOwner::Param(loc.id.value, Idx::from_raw(RawIdx::from(idx as u32))) - }; - - let mut flags = func.flags; - if flags.contains(FnFlags::HAS_SELF_PARAM) { - // If there's a self param in the syntax, but it is cfg'd out, remove the flag. - let is_cfgd_out = - !item_tree.attrs(db, krate, attr_owner(0usize)).is_cfg_enabled(cfg_options); - if is_cfgd_out { - cov_mark::hit!(cfgd_out_self_param); - flags.remove(FnFlags::HAS_SELF_PARAM); - } - } - if flags.contains(FnFlags::IS_VARARGS) { - if let Some((_, param)) = func.params.iter().enumerate().rev().find(|&(idx, _)| { - item_tree.attrs(db, krate, attr_owner(idx)).is_cfg_enabled(cfg_options) - }) { - if param.type_ref.is_some() { - flags.remove(FnFlags::IS_VARARGS); - } - } else { - flags.remove(FnFlags::IS_VARARGS); - } - } - - let attrs = item_tree.attrs(db, krate, ModItem::from(loc.id.value).into()); - if attrs.by_key(&sym::rustc_allow_incoherent_impl).exists() { - flags |= FnFlags::RUSTC_ALLOW_INCOHERENT_IMPL; - } - if flags.contains(FnFlags::HAS_UNSAFE_KW) - && attrs.by_key(&sym::rustc_deprecated_safe_2024).exists() - { - flags.remove(FnFlags::HAS_UNSAFE_KW); - flags.insert(FnFlags::DEPRECATED_SAFE_2024); - } - - if attrs.by_key(&sym::target_feature).exists() { - flags.insert(FnFlags::HAS_TARGET_FEATURE); - } - - Arc::new(FunctionData { - name: func.name.clone(), - params: func - .params - .iter() - .enumerate() - .filter(|&(idx, _)| { - item_tree.attrs(db, krate, attr_owner(idx)).is_cfg_enabled(cfg_options) - }) - .filter_map(|(_, param)| param.type_ref) - .collect(), - ret_type: func.ret_type, - visibility, - abi: func.abi.clone(), - legacy_const_generics_indices: attrs.rustc_legacy_const_generics(), - types_map: func.types_map.clone(), - flags, - }) - } - - #[inline] - pub fn has_body(&self) -> bool { - self.flags.contains(FnFlags::HAS_BODY) - } - - /// True if the first param is `self`. This is relevant to decide whether this - /// can be called as a method. - #[inline] - pub fn has_self_param(&self) -> bool { - self.flags.contains(FnFlags::HAS_SELF_PARAM) - } - - #[inline] - pub fn is_default(&self) -> bool { - self.flags.contains(FnFlags::HAS_DEFAULT_KW) - } - - #[inline] - pub fn is_const(&self) -> bool { - self.flags.contains(FnFlags::HAS_CONST_KW) - } - - #[inline] - pub fn is_async(&self) -> bool { - self.flags.contains(FnFlags::HAS_ASYNC_KW) - } - - #[inline] - pub fn is_unsafe(&self) -> bool { - self.flags.contains(FnFlags::HAS_UNSAFE_KW) - } - - #[inline] - pub fn is_deprecated_safe_2024(&self) -> bool { - self.flags.contains(FnFlags::DEPRECATED_SAFE_2024) - } - - #[inline] - pub fn is_safe(&self) -> bool { - self.flags.contains(FnFlags::HAS_SAFE_KW) - } - - #[inline] - pub fn is_varargs(&self) -> bool { - self.flags.contains(FnFlags::IS_VARARGS) - } - - #[inline] - pub fn has_target_feature(&self) -> bool { - self.flags.contains(FnFlags::HAS_TARGET_FEATURE) - } - - #[inline] - pub fn rustc_allow_incoherent_impl(&self) -> bool { - self.flags.contains(FnFlags::RUSTC_ALLOW_INCOHERENT_IMPL) - } -} - -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct TypeAliasData { - pub name: Name, - pub type_ref: Option, - pub visibility: RawVisibility, - pub flags: TypeAliasFlags, - /// Bounds restricting the type alias itself (eg. `type Ty: Bound;` in a trait or impl). - pub bounds: Box<[TypeBound]>, - pub types_map: Arc, -} - -bitflags::bitflags! { - #[derive(Debug, Clone, PartialEq, Eq)] - pub struct TypeAliasFlags: u8 { - const IS_EXTERN = 1 << 0; - const RUSTC_HAS_INCOHERENT_INHERENT_IMPLS = 1 << 1; - const RUSTC_ALLOW_INCOHERENT_IMPL = 1 << 2; - } -} - -impl TypeAliasData { - #[inline] - pub fn is_extern(&self) -> bool { - self.flags.contains(TypeAliasFlags::IS_EXTERN) - } - - #[inline] - pub fn rustc_has_incoherent_inherent_impls(&self) -> bool { - self.flags.contains(TypeAliasFlags::RUSTC_HAS_INCOHERENT_INHERENT_IMPLS) - } - - #[inline] - pub fn rustc_allow_incoherent_impl(&self) -> bool { - self.flags.contains(TypeAliasFlags::RUSTC_ALLOW_INCOHERENT_IMPL) - } - - pub(crate) fn type_alias_data_query( - db: &dyn DefDatabase, - typ: TypeAliasId, - ) -> Arc { - let loc = typ.lookup(db); - let item_tree = loc.id.item_tree(db); - let typ = &item_tree[loc.id.value]; - let visibility = if let ItemContainerId::TraitId(trait_id) = loc.container { - trait_vis(db, trait_id) - } else { - item_tree[typ.visibility].clone() - }; - - let attrs = item_tree.attrs( - db, - loc.container.module(db).krate(), - ModItem::from(loc.id.value).into(), - ); - - let mut flags = TypeAliasFlags::empty(); - - if matches!(loc.container, ItemContainerId::ExternBlockId(_)) { - flags |= TypeAliasFlags::IS_EXTERN; - } - if attrs.by_key(&sym::rustc_has_incoherent_inherent_impls).exists() { - flags |= TypeAliasFlags::RUSTC_HAS_INCOHERENT_INHERENT_IMPLS; - } - if attrs.by_key(&sym::rustc_allow_incoherent_impl).exists() { - flags |= TypeAliasFlags::RUSTC_ALLOW_INCOHERENT_IMPL; - } - - Arc::new(TypeAliasData { - name: typ.name.clone(), - type_ref: typ.type_ref, - visibility, - flags, - bounds: typ.bounds.clone(), - types_map: typ.types_map.clone(), - }) - } -} - -bitflags::bitflags! { - #[derive(Debug, Clone, Copy, Eq, PartialEq, Default)] - pub struct TraitFlags: u16 { - const IS_AUTO = 1 << 0; - const IS_UNSAFE = 1 << 1; - const IS_FUNDAMENTAL = 1 << 2; - const RUSTC_HAS_INCOHERENT_INHERENT_IMPLS = 1 << 3; - const SKIP_ARRAY_DURING_METHOD_DISPATCH = 1 << 4; - const SKIP_BOXED_SLICE_DURING_METHOD_DISPATCH = 1 << 5; - const RUSTC_PAREN_SUGAR = 1 << 6; - } -} - -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct TraitData { - pub name: Name, - pub flags: TraitFlags, - pub visibility: RawVisibility, -} - -impl TraitData { - #[inline] - pub(crate) fn trait_data_query(db: &dyn DefDatabase, tr: TraitId) -> Arc { - let ItemLoc { container: module_id, id: tree_id } = tr.lookup(db); - let item_tree = tree_id.item_tree(db); - let tr_def = &item_tree[tree_id.value]; - let name = tr_def.name.clone(); - let visibility = item_tree[tr_def.visibility].clone(); - let attrs = item_tree.attrs(db, module_id.krate(), ModItem::from(tree_id.value).into()); - - let mut flags = TraitFlags::empty(); - - if tr_def.is_auto { - flags |= TraitFlags::IS_AUTO; - } - if tr_def.is_unsafe { - flags |= TraitFlags::IS_UNSAFE; - } - if attrs.by_key(&sym::fundamental).exists() { - flags |= TraitFlags::IS_FUNDAMENTAL; - } - if attrs.by_key(&sym::rustc_has_incoherent_inherent_impls).exists() { - flags |= TraitFlags::RUSTC_HAS_INCOHERENT_INHERENT_IMPLS; - } - if attrs.by_key(&sym::rustc_paren_sugar).exists() { - flags |= TraitFlags::RUSTC_PAREN_SUGAR; - } - - 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 { - flags |= TraitFlags::SKIP_ARRAY_DURING_METHOD_DISPATCH; - } - if skip_boxed_slice_during_method_dispatch { - flags |= TraitFlags::SKIP_BOXED_SLICE_DURING_METHOD_DISPATCH; - } - - Arc::new(TraitData { name, visibility, flags }) - } -} - -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct TraitAliasData { - pub name: Name, - pub visibility: RawVisibility, -} - -impl TraitAliasData { - pub(crate) fn trait_alias_query(db: &dyn DefDatabase, id: TraitAliasId) -> Arc { - let loc = id.lookup(db); - let item_tree = loc.id.item_tree(db); - let alias = &item_tree[loc.id.value]; - let visibility = item_tree[alias.visibility].clone(); - - Arc::new(TraitAliasData { name: alias.name.clone(), visibility }) - } -} - -#[derive(Debug, PartialEq, Eq)] -pub struct ImplData { - pub target_trait: Option, - pub self_ty: TypeRefId, - pub is_negative: bool, - pub is_unsafe: bool, - pub types_map: Arc, -} - -impl ImplData { - #[inline] - pub(crate) fn impl_data_query(db: &dyn DefDatabase, id: ImplId) -> Arc { - let _p = tracing::info_span!("impl_data_query").entered(); - let ItemLoc { id: tree_id, .. } = id.lookup(db); - - let item_tree = tree_id.item_tree(db); - let impl_def = &item_tree[tree_id.value]; - let target_trait = impl_def.target_trait; - let self_ty = impl_def.self_ty; - let is_negative = impl_def.is_negative; - let is_unsafe = impl_def.is_unsafe; - - Arc::new(ImplData { - target_trait, - self_ty, - is_negative, - is_unsafe, - types_map: impl_def.types_map.clone(), - }) - } -} - -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct Macro2Data { - pub name: Name, - pub visibility: RawVisibility, - // It's a bit wasteful as currently this is only for builtin `Default` derive macro, but macro2 - // are rarely used in practice so I think it's okay for now. - /// Derive helpers, if this is a derive rustc_builtin_macro - pub helpers: Option>, -} - -impl Macro2Data { - pub(crate) fn macro2_data_query(db: &dyn DefDatabase, makro: Macro2Id) -> Arc { - let loc = makro.lookup(db); - let item_tree = loc.id.item_tree(db); - let makro = &item_tree[loc.id.value]; - let attrs = item_tree.attrs(db, loc.container.krate(), ModItem::from(loc.id.value).into()); - - let helpers = attrs - .by_key(&sym::rustc_builtin_macro) - .tt_values() - .next() - .and_then(parse_macro_name_and_helper_attrs) - .map(|(_, helpers)| helpers); - - Arc::new(Macro2Data { - name: makro.name.clone(), - visibility: item_tree[makro.visibility].clone(), - helpers, - }) - } -} -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct MacroRulesData { - pub name: Name, - pub macro_export: bool, -} - -impl MacroRulesData { - pub(crate) fn macro_rules_data_query( - db: &dyn DefDatabase, - makro: MacroRulesId, - ) -> Arc { - let loc = makro.lookup(db); - let item_tree = loc.id.item_tree(db); - let makro = &item_tree[loc.id.value]; - let attrs = item_tree.attrs(db, loc.container.krate(), ModItem::from(loc.id.value).into()); - - let macro_export = attrs.by_key(&sym::macro_export).exists(); - - Arc::new(MacroRulesData { name: makro.name.clone(), macro_export }) - } -} - -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct ProcMacroData { - pub name: Name, - /// Derive helpers, if this is a derive - pub helpers: Option>, -} - -impl ProcMacroData { - pub(crate) fn proc_macro_data_query( - db: &dyn DefDatabase, - makro: ProcMacroId, - ) -> Arc { - let loc = makro.lookup(db); - let item_tree = loc.id.item_tree(db); - let makro = &item_tree[loc.id.value]; - let attrs = item_tree.attrs(db, loc.container.krate(), ModItem::from(loc.id.value).into()); - - let (name, helpers) = if let Some(def) = attrs.parse_proc_macro_decl(&makro.name) { - ( - def.name, - match def.kind { - ProcMacroKind::Derive { helpers } => Some(helpers), - ProcMacroKind::Bang | ProcMacroKind::Attr => None, - }, - ) - } else { - // eeeh... - stdx::never!("proc macro declaration is not a proc macro"); - (makro.name.clone(), None) - }; - - Arc::new(ProcMacroData { name, helpers }) - } -} - -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct ExternCrateDeclData { - pub name: Name, - pub alias: Option, - pub visibility: RawVisibility, - pub crate_id: Option, -} - -impl ExternCrateDeclData { - pub(crate) fn extern_crate_decl_data_query( - db: &dyn DefDatabase, - extern_crate: ExternCrateId, - ) -> Arc { - let loc = extern_crate.lookup(db); - let item_tree = loc.id.item_tree(db); - let extern_crate = &item_tree[loc.id.value]; - - let name = extern_crate.name.clone(); - let krate = loc.container.krate(); - let crate_id = if name == sym::self_.clone() { - Some(krate) - } else { - krate.data(db).dependencies.iter().find_map(|dep| { - if dep.name.symbol() == name.symbol() { Some(dep.crate_id) } else { None } - }) - }; - - Arc::new(Self { - name, - visibility: item_tree[extern_crate.visibility].clone(), - alias: extern_crate.alias.clone(), - crate_id, - }) - } -} - -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct ConstData { - /// `None` for `const _: () = ();` - pub name: Option, - pub type_ref: TypeRefId, - pub visibility: RawVisibility, - pub types_map: Arc, - pub flags: ConstFlags, -} - -bitflags::bitflags! { - #[derive(Debug, Clone, Copy, PartialEq, Eq)] - pub struct ConstFlags: u8 { - const RUSTC_ALLOW_INCOHERENT_IMPL = 1 << 0; - const HAS_BODY = 1 << 1; - } -} - -impl ConstData { - pub(crate) fn const_data_query(db: &dyn DefDatabase, konst: ConstId) -> Arc { - let loc = konst.lookup(db); - let item_tree = loc.id.item_tree(db); - let konst = &item_tree[loc.id.value]; - let visibility = if let ItemContainerId::TraitId(trait_id) = loc.container { - trait_vis(db, trait_id) - } else { - item_tree[konst.visibility].clone() - }; - let attrs = item_tree.attrs( - db, - loc.container.module(db).krate(), - ModItem::from(loc.id.value).into(), - ); - - let mut flags = ConstFlags::empty(); - if attrs.by_key(&sym::rustc_allow_incoherent_impl).exists() { - flags |= ConstFlags::RUSTC_ALLOW_INCOHERENT_IMPL; - } - if konst.has_body { - flags |= ConstFlags::HAS_BODY; - } - - Arc::new(ConstData { - name: konst.name.clone(), - type_ref: konst.type_ref, - visibility, - flags, - types_map: konst.types_map.clone(), - }) - } - - #[inline] - pub fn rustc_allow_incoherent_impl(&self) -> bool { - self.flags.contains(ConstFlags::RUSTC_ALLOW_INCOHERENT_IMPL) - } - - #[inline] - pub fn has_body(&self) -> bool { - self.flags.contains(ConstFlags::HAS_BODY) - } -} - -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct StaticData { - pub name: Name, - pub type_ref: TypeRefId, - pub visibility: RawVisibility, - pub types_map: Arc, - pub flags: StaticFlags, -} - -impl StaticData { - pub(crate) fn static_data_query(db: &dyn DefDatabase, konst: StaticId) -> Arc { - let loc = konst.lookup(db); - let item_tree = loc.id.item_tree(db); - let statik = &item_tree[loc.id.value]; - - let mut flags = statik.flags; - if matches!(loc.container, ItemContainerId::ExternBlockId(_)) { - flags |= StaticFlags::IS_EXTERN; - } - - Arc::new(StaticData { - name: statik.name.clone(), - type_ref: statik.type_ref, - visibility: item_tree[statik.visibility].clone(), - flags, - types_map: statik.types_map.clone(), - }) - } - - #[inline] - pub fn is_extern(&self) -> bool { - self.flags.contains(StaticFlags::IS_EXTERN) - } - - #[inline] - pub fn mutable(&self) -> bool { - self.flags.contains(StaticFlags::MUTABLE) - } - - #[inline] - pub fn has_safe_kw(&self) -> bool { - self.flags.contains(StaticFlags::HAS_SAFE_KW) - } - - #[inline] - pub fn has_unsafe_kw(&self) -> bool { - self.flags.contains(StaticFlags::HAS_UNSAFE_KW) - } -} - -fn trait_vis(db: &dyn DefDatabase, trait_id: TraitId) -> RawVisibility { - 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]; - item_tree[tr_def.visibility].clone() -} diff --git a/crates/hir-def/src/data/adt.rs b/crates/hir-def/src/data/adt.rs deleted file mode 100644 index a54d7663cc..0000000000 --- a/crates/hir-def/src/data/adt.rs +++ /dev/null @@ -1,412 +0,0 @@ -//! Defines hir-level representation of structs, enums and unions - -use base_db::Crate; -use bitflags::bitflags; -use cfg::CfgOptions; - -use hir_expand::name::Name; -use intern::sym; -use la_arena::Arena; -use rustc_abi::{IntegerType, ReprOptions}; -use triomphe::Arc; - -use crate::{ - EnumId, EnumVariantId, LocalFieldId, LocalModuleId, Lookup, StructId, UnionId, VariantId, - db::DefDatabase, - hir::Expr, - item_tree::{ - AttrOwner, Field, FieldParent, FieldsShape, ItemTree, ModItem, RawVisibilityId, TreeId, - }, - lang_item::LangItem, - nameres::diagnostics::{DefDiagnostic, DefDiagnostics}, - type_ref::{TypeRefId, TypesMap}, - visibility::RawVisibility, -}; - -/// Note that we use `StructData` for unions as well! -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct StructData { - pub name: Name, - pub repr: Option, - pub visibility: RawVisibility, - pub flags: StructFlags, -} - -bitflags! { - #[derive(Debug, Copy, Clone, PartialEq, Eq)] - pub struct StructFlags: u8 { - const NO_FLAGS = 0; - /// Indicates whether the struct is `PhantomData`. - const IS_PHANTOM_DATA = 1 << 2; - /// Indicates whether the struct has a `#[fundamental]` attribute. - const IS_FUNDAMENTAL = 1 << 3; - // FIXME: should this be a flag? - /// Indicates whether the struct has a `#[rustc_has_incoherent_inherent_impls]` attribute. - const IS_RUSTC_HAS_INCOHERENT_INHERENT_IMPL = 1 << 4; - /// Indicates whether this struct is `Box`. - const IS_BOX = 1 << 5; - /// Indicates whether this struct is `ManuallyDrop`. - const IS_MANUALLY_DROP = 1 << 6; - /// Indicates whether this struct is `UnsafeCell`. - const IS_UNSAFE_CELL = 1 << 7; - } -} - -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct EnumData { - pub name: Name, - pub repr: Option, - pub visibility: RawVisibility, - pub rustc_has_incoherent_inherent_impls: bool, -} - -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct EnumVariants { - pub variants: Box<[(EnumVariantId, Name)]>, -} - -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct EnumVariantData { - pub name: Name, -} - -#[derive(Debug, Clone, PartialEq, Eq)] -pub enum VariantData { - Record { fields: Arena, types_map: Arc }, - Tuple { fields: Arena, types_map: Arc }, - Unit, -} - -impl VariantData { - #[inline] - pub(crate) fn variant_data_query(db: &dyn DefDatabase, id: VariantId) -> Arc { - db.variant_data_with_diagnostics(id).0 - } - - pub(crate) fn variant_data_with_diagnostics_query( - db: &dyn DefDatabase, - id: VariantId, - ) -> (Arc, DefDiagnostics) { - let (shape, types_map, (fields, diagnostics)) = 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 krate = parent.container.krate; - let variant = &item_tree[loc.id.value]; - ( - variant.shape, - variant.types_map.clone(), - lower_fields( - db, - krate, - parent.container.local_id, - loc.id.tree_id(), - &item_tree, - krate.cfg_options(db), - FieldParent::EnumVariant(loc.id.value), - &variant.fields, - Some(item_tree[parent.id.value].visibility), - ), - ) - } - VariantId::StructId(id) => { - let loc = id.lookup(db); - let item_tree = loc.id.item_tree(db); - let krate = loc.container.krate; - let strukt = &item_tree[loc.id.value]; - ( - strukt.shape, - strukt.types_map.clone(), - lower_fields( - db, - krate, - loc.container.local_id, - loc.id.tree_id(), - &item_tree, - krate.cfg_options(db), - FieldParent::Struct(loc.id.value), - &strukt.fields, - None, - ), - ) - } - VariantId::UnionId(id) => { - let loc = id.lookup(db); - let item_tree = loc.id.item_tree(db); - let krate = loc.container.krate; - let union = &item_tree[loc.id.value]; - ( - FieldsShape::Record, - union.types_map.clone(), - lower_fields( - db, - krate, - loc.container.local_id, - loc.id.tree_id(), - &item_tree, - krate.cfg_options(db), - FieldParent::Union(loc.id.value), - &union.fields, - None, - ), - ) - } - }; - - ( - Arc::new(match shape { - FieldsShape::Record => VariantData::Record { fields, types_map }, - FieldsShape::Tuple => VariantData::Tuple { fields, types_map }, - FieldsShape::Unit => VariantData::Unit, - }), - DefDiagnostics::new(diagnostics), - ) - } -} - -/// A single field of an enum variant or struct -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct FieldData { - pub name: Name, - pub type_ref: TypeRefId, - pub visibility: RawVisibility, - pub is_unsafe: bool, -} - -fn repr_from_value( - db: &dyn DefDatabase, - krate: Crate, - item_tree: &ItemTree, - of: AttrOwner, -) -> Option { - item_tree.attrs(db, krate, of).repr() -} - -impl StructData { - #[inline] - pub(crate) fn struct_data_query(db: &dyn DefDatabase, id: StructId) -> Arc { - let loc = id.lookup(db); - let krate = loc.container.krate; - let item_tree = loc.id.item_tree(db); - let repr = repr_from_value(db, krate, &item_tree, ModItem::from(loc.id.value).into()); - let attrs = item_tree.attrs(db, krate, ModItem::from(loc.id.value).into()); - - let mut flags = StructFlags::NO_FLAGS; - if attrs.by_key(&sym::rustc_has_incoherent_inherent_impls).exists() { - flags |= StructFlags::IS_RUSTC_HAS_INCOHERENT_INHERENT_IMPL; - } - if attrs.by_key(&sym::fundamental).exists() { - flags |= StructFlags::IS_FUNDAMENTAL; - } - if let Some(lang) = attrs.lang_item() { - 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, - _ => (), - } - } - - let strukt = &item_tree[loc.id.value]; - Arc::new(StructData { - name: strukt.name.clone(), - repr, - visibility: item_tree[strukt.visibility].clone(), - flags, - }) - } - - #[inline] - pub(crate) fn union_data_query(db: &dyn DefDatabase, id: UnionId) -> Arc { - let loc = id.lookup(db); - let krate = loc.container.krate; - let item_tree = loc.id.item_tree(db); - let repr = repr_from_value(db, krate, &item_tree, ModItem::from(loc.id.value).into()); - let attrs = item_tree.attrs(db, krate, ModItem::from(loc.id.value).into()); - let mut flags = StructFlags::NO_FLAGS; - - if attrs.by_key(&sym::rustc_has_incoherent_inherent_impls).exists() { - flags |= StructFlags::IS_RUSTC_HAS_INCOHERENT_INHERENT_IMPL; - } - if attrs.by_key(&sym::fundamental).exists() { - flags |= StructFlags::IS_FUNDAMENTAL; - } - - let union = &item_tree[loc.id.value]; - - Arc::new(StructData { - name: union.name.clone(), - repr, - visibility: item_tree[union.visibility].clone(), - flags, - }) - } -} - -impl EnumVariants { - pub(crate) fn enum_variants_query(db: &dyn DefDatabase, e: EnumId) -> Arc { - let loc = e.lookup(db); - let item_tree = loc.id.item_tree(db); - - Arc::new(EnumVariants { - variants: loc.container.def_map(db).enum_definitions[&e] - .iter() - .map(|&id| (id, item_tree[id.lookup(db).id.value].name.clone())) - .collect(), - }) - } - - pub fn variant(&self, name: &Name) -> Option { - let &(id, _) = self.variants.iter().find(|(_id, n)| n == name)?; - Some(id) - } - - // [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, _)| { - // The condition check order is slightly modified from rustc - // to improve performance by early returning with relatively fast checks - let variant = &db.variant_data(v.into()); - if !variant.fields().is_empty() { - return false; - } - // The outer if condition is whether this variant has const ctor or not - if !matches!(variant.kind(), StructKind::Unit) { - let body = db.body(v.into()); - // A variant with explicit discriminant - if body.exprs[body.body_expr] != Expr::Missing { - return false; - } - } - true - }) - } -} - -impl EnumData { - pub(crate) fn enum_data_query(db: &dyn DefDatabase, e: EnumId) -> Arc { - let loc = e.lookup(db); - let krate = loc.container.krate; - let item_tree = loc.id.item_tree(db); - let repr = repr_from_value(db, krate, &item_tree, ModItem::from(loc.id.value).into()); - let attrs = item_tree.attrs(db, loc.container.krate, ModItem::from(loc.id.value).into()); - - let rustc_has_incoherent_inherent_impls = - attrs.by_key(&sym::rustc_has_incoherent_inherent_impls).exists(); - - let enum_ = &item_tree[loc.id.value]; - - Arc::new(EnumData { - name: enum_.name.clone(), - repr, - visibility: item_tree[enum_.visibility].clone(), - rustc_has_incoherent_inherent_impls, - }) - } - - pub fn variant_body_type(&self) -> IntegerType { - match self.repr { - Some(ReprOptions { int: Some(builtin), .. }) => builtin, - _ => IntegerType::Pointer(true), - } - } -} - -impl EnumVariantData { - #[inline] - pub(crate) fn enum_variant_data_query( - db: &dyn DefDatabase, - e: EnumVariantId, - ) -> Arc { - let loc = e.lookup(db); - let item_tree = loc.id.item_tree(db); - let variant = &item_tree[loc.id.value]; - - Arc::new(EnumVariantData { name: variant.name.clone() }) - } -} - -impl VariantData { - pub fn fields(&self) -> &Arena { - const EMPTY: &Arena = &Arena::new(); - match self { - VariantData::Record { fields, .. } | VariantData::Tuple { fields, .. } => fields, - _ => EMPTY, - } - } - - pub fn types_map(&self) -> &TypesMap { - match self { - VariantData::Record { types_map, .. } | VariantData::Tuple { types_map, .. } => { - types_map - } - VariantData::Unit => TypesMap::EMPTY, - } - } - - // FIXME: Linear lookup - pub fn field(&self, name: &Name) -> Option { - self.fields().iter().find_map(|(id, data)| if &data.name == name { Some(id) } else { None }) - } - - pub fn kind(&self) -> StructKind { - match self { - VariantData::Record { .. } => StructKind::Record, - VariantData::Tuple { .. } => StructKind::Tuple, - VariantData::Unit => StructKind::Unit, - } - } -} - -#[derive(Debug, Copy, Clone, PartialEq, Eq)] -pub enum StructKind { - Tuple, - Record, - Unit, -} - -fn lower_fields( - db: &dyn DefDatabase, - krate: Crate, - container: LocalModuleId, - tree_id: TreeId, - item_tree: &ItemTree, - cfg_options: &CfgOptions, - parent: FieldParent, - fields: &[Field], - override_visibility: Option, -) -> (Arena, Vec) { - let mut diagnostics = Vec::new(); - let mut arena = Arena::new(); - for (idx, field) in fields.iter().enumerate() { - let attr_owner = AttrOwner::make_field_indexed(parent, idx); - let attrs = item_tree.attrs(db, krate, attr_owner); - if attrs.is_cfg_enabled(cfg_options) { - arena.alloc(lower_field(item_tree, field, override_visibility)); - } else { - diagnostics.push(DefDiagnostic::unconfigured_code( - container, - tree_id, - attr_owner, - attrs.cfg().unwrap(), - cfg_options.clone(), - )) - } - } - (arena, diagnostics) -} - -fn lower_field( - item_tree: &ItemTree, - field: &Field, - override_visibility: Option, -) -> FieldData { - FieldData { - name: field.name.clone(), - type_ref: field.type_ref, - visibility: item_tree[override_visibility.unwrap_or(field.visibility)].clone(), - is_unsafe: field.is_unsafe, - } -} diff --git a/crates/hir-def/src/db.rs b/crates/hir-def/src/db.rs index 58688d5f41..94f899a226 100644 --- a/crates/hir-def/src/db.rs +++ b/crates/hir-def/src/db.rs @@ -6,34 +6,35 @@ use intern::sym; use la_arena::ArenaMap; use span::{EditionedFileId, MacroCallId}; use syntax::{AstPtr, ast}; +use thin_vec::ThinVec; use triomphe::Arc; use crate::{ - AttrDefId, BlockId, BlockLoc, ConstBlockId, ConstBlockLoc, ConstId, ConstLoc, DefWithBodyId, - EnumId, EnumLoc, EnumVariantId, EnumVariantLoc, ExternBlockId, ExternBlockLoc, ExternCrateId, - ExternCrateLoc, FunctionId, FunctionLoc, GenericDefId, ImplId, ImplLoc, InTypeConstId, - InTypeConstLoc, LocalFieldId, Macro2Id, Macro2Loc, MacroId, MacroRulesId, MacroRulesLoc, - MacroRulesLocFlags, ProcMacroId, ProcMacroLoc, StaticId, StaticLoc, StructId, StructLoc, - TraitAliasId, TraitAliasLoc, TraitId, TraitLoc, TypeAliasId, TypeAliasLoc, UnionId, UnionLoc, - UseId, UseLoc, VariantId, + 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, + StaticLoc, StructId, StructLoc, TraitAliasId, TraitAliasLoc, TraitId, TraitLoc, TypeAliasId, + TypeAliasLoc, UnionId, UnionLoc, UseId, UseLoc, VariantId, attr::{Attrs, AttrsWithOwner}, - data::{ - ConstData, ExternCrateDeclData, FunctionData, ImplData, Macro2Data, MacroRulesData, - ProcMacroData, StaticData, TraitAliasData, TraitData, TypeAliasData, - adt::{EnumData, EnumVariantData, EnumVariants, StructData, VariantData}, + expr_store::{ + Body, BodySourceMap, ExpressionStore, ExpressionStoreSourceMap, scope::ExprScopes, }, - expr_store::{Body, BodySourceMap, scope::ExprScopes}, - generics::GenericParams, + hir::generics::GenericParams, import_map::ImportMap, - item_tree::{AttrOwner, ItemTree, ItemTreeSourceMaps}, + item_tree::{AttrOwner, ItemTree}, lang_item::{self, LangItem, LangItemTarget, LangItems}, nameres::{ DefMap, LocalDefMap, assoc::{ImplItems, TraitItems}, diagnostics::DefDiagnostics, }, + signatures::{ + ConstSignature, EnumSignature, EnumVariants, FunctionSignature, ImplSignature, + InactiveEnumVariantCode, StaticSignature, StructSignature, TraitAliasSignature, + TraitSignature, TypeAliasSignature, UnionSignature, VariantFields, + }, tt, - type_ref::TypesSourceMap, visibility::{self, Visibility}, }; @@ -96,11 +97,6 @@ pub trait InternDatabase: RootQueryDb { #[salsa::interned] fn intern_block(&self, loc: BlockLoc) -> BlockId; - #[salsa::interned] - fn intern_anonymous_const(&self, id: ConstBlockLoc) -> ConstBlockId; - - #[salsa::interned] - fn intern_in_type_const(&self, id: InTypeConstLoc) -> InTypeConstId; } #[query_group::query_group] @@ -122,18 +118,6 @@ pub trait DefDatabase: #[salsa::invoke_actual(ItemTree::block_item_tree_query)] fn block_item_tree(&self, block_id: BlockId) -> Arc; - #[salsa::invoke(ItemTree::file_item_tree_with_source_map_query)] - fn file_item_tree_with_source_map( - &self, - file_id: HirFileId, - ) -> (Arc, Arc); - - #[salsa::invoke_actual(ItemTree::block_item_tree_with_source_map_query)] - fn block_item_tree_with_source_map( - &self, - block_id: BlockId, - ) -> (Arc, Arc); - #[salsa::invoke_actual(DefMap::crate_local_def_map_query)] fn crate_local_def_map(&self, krate: Crate) -> (Arc, Arc); @@ -150,30 +134,22 @@ pub trait DefDatabase: // region:data - #[salsa::transparent] - #[salsa::invoke_actual(VariantData::variant_data_query)] - fn variant_data(&self, id: VariantId) -> Arc; + #[salsa::invoke_actual(VariantFields::query)] + fn variant_fields_with_source_map( + &self, + id: VariantId, + ) -> (Arc, Arc); - #[salsa::invoke_actual(VariantData::variant_data_with_diagnostics_query)] - fn variant_data_with_diagnostics(&self, id: VariantId) -> (Arc, DefDiagnostics); - - #[salsa::invoke_actual(StructData::struct_data_query)] - fn struct_data(&self, id: StructId) -> Arc; - - #[salsa::invoke_actual(StructData::union_data_query)] - fn union_data(&self, id: UnionId) -> Arc; - - #[salsa::invoke_actual(EnumData::enum_data_query)] - fn enum_data(&self, e: EnumId) -> Arc; + #[salsa::tracked] + fn enum_variants(&self, id: EnumId) -> Arc { + self.enum_variants_with_diagnostics(id).0 + } #[salsa::invoke_actual(EnumVariants::enum_variants_query)] - fn enum_variants(&self, e: EnumId) -> Arc; - - #[salsa::invoke_actual(EnumVariantData::enum_variant_data_query)] - fn enum_variant_data(&self, id: EnumVariantId) -> Arc; - - #[salsa::invoke_actual(ImplData::impl_data_query)] - fn impl_data(&self, e: ImplId) -> Arc; + fn enum_variants_with_diagnostics( + &self, + id: EnumId, + ) -> (Arc, Option>>); #[salsa::transparent] #[salsa::invoke_actual(ImplItems::impl_items_query)] @@ -182,9 +158,6 @@ pub trait DefDatabase: #[salsa::invoke_actual(ImplItems::impl_items_with_diagnostics_query)] fn impl_items_with_diagnostics(&self, e: ImplId) -> (Arc, DefDiagnostics); - #[salsa::invoke_actual(TraitData::trait_data_query)] - fn trait_data(&self, e: TraitId) -> Arc; - #[salsa::transparent] #[salsa::invoke_actual(TraitItems::trait_items_query)] fn trait_items(&self, e: TraitId) -> Arc; @@ -192,32 +165,120 @@ pub trait DefDatabase: #[salsa::invoke_actual(TraitItems::trait_items_with_diagnostics_query)] fn trait_items_with_diagnostics(&self, tr: TraitId) -> (Arc, DefDiagnostics); - #[salsa::invoke_actual(TraitAliasData::trait_alias_query)] - fn trait_alias_data(&self, e: TraitAliasId) -> Arc; + #[salsa::tracked] + fn variant_fields(&self, id: VariantId) -> Arc { + self.variant_fields_with_source_map(id).0 + } - #[salsa::invoke_actual(TypeAliasData::type_alias_data_query)] - fn type_alias_data(&self, e: TypeAliasId) -> Arc; + #[salsa::tracked] + fn trait_signature(&self, trait_: TraitId) -> Arc { + self.trait_signature_with_source_map(trait_).0 + } - #[salsa::invoke_actual(FunctionData::fn_data_query)] - fn function_data(&self, func: FunctionId) -> Arc; + #[salsa::tracked] + fn impl_signature(&self, impl_: ImplId) -> Arc { + self.impl_signature_with_source_map(impl_).0 + } - #[salsa::invoke_actual(ConstData::const_data_query)] - fn const_data(&self, konst: ConstId) -> Arc; + #[salsa::tracked] + fn struct_signature(&self, struct_: StructId) -> Arc { + self.struct_signature_with_source_map(struct_).0 + } - #[salsa::invoke_actual(StaticData::static_data_query)] - fn static_data(&self, statik: StaticId) -> Arc; + #[salsa::tracked] + fn union_signature(&self, union_: UnionId) -> Arc { + self.union_signature_with_source_map(union_).0 + } - #[salsa::invoke_actual(Macro2Data::macro2_data_query)] - fn macro2_data(&self, makro: Macro2Id) -> Arc; + #[salsa::tracked] + fn enum_signature(&self, e: EnumId) -> Arc { + self.enum_signature_with_source_map(e).0 + } - #[salsa::invoke_actual(MacroRulesData::macro_rules_data_query)] - fn macro_rules_data(&self, makro: MacroRulesId) -> Arc; + #[salsa::tracked] + fn const_signature(&self, e: ConstId) -> Arc { + self.const_signature_with_source_map(e).0 + } - #[salsa::invoke_actual(ProcMacroData::proc_macro_data_query)] - fn proc_macro_data(&self, makro: ProcMacroId) -> Arc; + #[salsa::tracked] + fn static_signature(&self, e: StaticId) -> Arc { + self.static_signature_with_source_map(e).0 + } - #[salsa::invoke_actual(ExternCrateDeclData::extern_crate_decl_data_query)] - fn extern_crate_decl_data(&self, extern_crate: ExternCrateId) -> Arc; + #[salsa::tracked] + fn function_signature(&self, e: FunctionId) -> Arc { + self.function_signature_with_source_map(e).0 + } + + #[salsa::tracked] + fn trait_alias_signature(&self, e: TraitAliasId) -> Arc { + self.trait_alias_signature_with_source_map(e).0 + } + + #[salsa::tracked] + fn type_alias_signature(&self, e: TypeAliasId) -> Arc { + self.type_alias_signature_with_source_map(e).0 + } + + #[salsa::invoke_actual(TraitSignature::query)] + fn trait_signature_with_source_map( + &self, + trait_: TraitId, + ) -> (Arc, Arc); + + #[salsa::invoke_actual(ImplSignature::query)] + fn impl_signature_with_source_map( + &self, + impl_: ImplId, + ) -> (Arc, Arc); + + #[salsa::invoke_actual(StructSignature::query)] + fn struct_signature_with_source_map( + &self, + struct_: StructId, + ) -> (Arc, Arc); + + #[salsa::invoke_actual(UnionSignature::query)] + fn union_signature_with_source_map( + &self, + union_: UnionId, + ) -> (Arc, Arc); + + #[salsa::invoke_actual(EnumSignature::query)] + fn enum_signature_with_source_map( + &self, + e: EnumId, + ) -> (Arc, Arc); + + #[salsa::invoke_actual(ConstSignature::query)] + fn const_signature_with_source_map( + &self, + e: ConstId, + ) -> (Arc, Arc); + + #[salsa::invoke_actual(StaticSignature::query)] + fn static_signature_with_source_map( + &self, + e: StaticId, + ) -> (Arc, Arc); + + #[salsa::invoke_actual(FunctionSignature::query)] + fn function_signature_with_source_map( + &self, + e: FunctionId, + ) -> (Arc, Arc); + + #[salsa::invoke_actual(TraitAliasSignature::query)] + fn trait_alias_signature_with_source_map( + &self, + e: TraitAliasId, + ) -> (Arc, Arc); + + #[salsa::invoke_actual(TypeAliasSignature::query)] + fn type_alias_signature_with_source_map( + &self, + e: TypeAliasId, + ) -> (Arc, Arc); // endregion:data @@ -231,15 +292,23 @@ pub trait DefDatabase: #[salsa::invoke_actual(ExprScopes::expr_scopes_query)] fn expr_scopes(&self, def: DefWithBodyId) -> Arc; - #[salsa::invoke_actual(GenericParams::generic_params_query)] + #[salsa::transparent] + #[salsa::invoke(GenericParams::new)] fn generic_params(&self, def: GenericDefId) -> Arc; - /// If this returns `None` for the source map, that means it is the same as with the item tree. - #[salsa::invoke_actual(GenericParams::generic_params_with_source_map_query)] - fn generic_params_with_source_map( + #[salsa::transparent] + #[salsa::invoke(GenericParams::generic_params_and_store)] + fn generic_params_and_store( &self, def: GenericDefId, - ) -> (Arc, Option>); + ) -> (Arc, Arc); + + #[salsa::transparent] + #[salsa::invoke(GenericParams::generic_params_and_store_and_source_map)] + fn generic_params_and_store_and_source_map( + &self, + def: GenericDefId, + ) -> (Arc, Arc, Arc); // region:attrs @@ -270,16 +339,20 @@ pub trait DefDatabase: // region:visibilities - #[salsa::invoke(visibility::field_visibilities_query)] + #[salsa::invoke_actual(visibility::field_visibilities_query)] fn field_visibilities(&self, var: VariantId) -> Arc>; // FIXME: unify function_visibility and const_visibility? + #[salsa::invoke_actual(visibility::function_visibility_query)] fn function_visibility(&self, def: FunctionId) -> Visibility; #[salsa::invoke_actual(visibility::const_visibility_query)] fn const_visibility(&self, def: ConstId) -> Visibility; + #[salsa::invoke_actual(visibility::type_alias_visibility_query)] + fn type_alias_visibility(&self, def: TypeAliasId) -> Visibility; + // endregion:visibilities #[salsa::invoke_actual(LangItems::crate_lang_items_query)] diff --git a/crates/hir-def/src/expander.rs b/crates/hir-def/src/expander.rs deleted file mode 100644 index 7c182a4aba..0000000000 --- a/crates/hir-def/src/expander.rs +++ /dev/null @@ -1,236 +0,0 @@ -//! Macro expansion utilities. - -use std::cell::OnceCell; - -use base_db::Crate; -use cfg::CfgOptions; -use drop_bomb::DropBomb; -use hir_expand::{ - ExpandError, ExpandErrorKind, ExpandResult, HirFileId, InFile, Lookup, MacroCallId, - attrs::RawAttrs, mod_path::ModPath, span_map::SpanMap, -}; -use span::{Edition, SyntaxContext}; -use syntax::{Parse, ast}; - -use crate::type_ref::{TypesMap, TypesSourceMap}; -use crate::{ - AsMacroCall, MacroId, ModuleId, UnresolvedMacro, attr::Attrs, db::DefDatabase, lower::LowerCtx, - path::Path, -}; - -#[derive(Debug)] -pub struct Expander { - span_map: OnceCell, - current_file_id: HirFileId, - pub(crate) module: ModuleId, - /// `recursion_depth == usize::MAX` indicates that the recursion limit has been reached. - recursion_depth: u32, - recursion_limit: usize, -} - -impl Expander { - pub fn new(db: &dyn DefDatabase, current_file_id: HirFileId, module: ModuleId) -> Expander { - let recursion_limit = module.def_map(db).recursion_limit() as usize; - let recursion_limit = if cfg!(test) { - // Without this, `body::tests::your_stack_belongs_to_me` stack-overflows in debug - std::cmp::min(32, recursion_limit) - } else { - recursion_limit - }; - Expander { - current_file_id, - module, - recursion_depth: 0, - recursion_limit, - span_map: OnceCell::new(), - } - } - - pub(crate) fn span_map(&self, db: &dyn DefDatabase) -> &SpanMap { - self.span_map.get_or_init(|| db.span_map(self.current_file_id)) - } - - pub fn krate(&self) -> Crate { - self.module.krate - } - - pub fn syntax_context(&self) -> SyntaxContext { - // FIXME: - SyntaxContext::root(Edition::CURRENT_FIXME) - } - - pub fn enter_expand( - &mut self, - db: &dyn DefDatabase, - macro_call: ast::MacroCall, - resolver: impl Fn(&ModPath) -> Option, - ) -> Result)>>, UnresolvedMacro> { - // FIXME: within_limit should support this, instead of us having to extract the error - let mut unresolved_macro_err = None; - - let result = self.within_limit(db, |this| { - let macro_call = this.in_file(¯o_call); - match macro_call.as_call_id_with_errors(db.upcast(), this.module.krate(), |path| { - resolver(path).map(|it| db.macro_def(it)) - }) { - Ok(call_id) => call_id, - Err(resolve_err) => { - unresolved_macro_err = Some(resolve_err); - ExpandResult { value: None, err: None } - } - } - }); - - if let Some(err) = unresolved_macro_err { Err(err) } else { Ok(result) } - } - - pub fn enter_expand_id( - &mut self, - db: &dyn DefDatabase, - call_id: MacroCallId, - ) -> ExpandResult)>> { - self.within_limit(db, |_this| ExpandResult::ok(Some(call_id))) - } - - pub fn exit(&mut self, mut mark: Mark) { - self.span_map = mark.span_map; - self.current_file_id = mark.file_id; - if self.recursion_depth == u32::MAX { - // Recursion limit has been reached somewhere in the macro expansion tree. Reset the - // depth only when we get out of the tree. - if !self.current_file_id.is_macro() { - self.recursion_depth = 0; - } - } else { - self.recursion_depth -= 1; - } - mark.bomb.defuse(); - } - - pub fn ctx<'a>( - &self, - db: &'a dyn DefDatabase, - types_map: &'a mut TypesMap, - types_source_map: &'a mut TypesSourceMap, - ) -> LowerCtx<'a> { - LowerCtx::with_span_map_cell( - db, - self.current_file_id, - self.span_map.clone(), - types_map, - types_source_map, - ) - } - - pub(crate) fn in_file(&self, value: T) -> InFile { - InFile { file_id: self.current_file_id, value } - } - - pub(crate) fn parse_attrs(&self, db: &dyn DefDatabase, owner: &dyn ast::HasAttrs) -> Attrs { - Attrs::filter( - db, - self.krate(), - RawAttrs::new( - db.upcast(), - owner, - self.span_map.get_or_init(|| db.span_map(self.current_file_id)).as_ref(), - ), - ) - } - - pub(crate) fn cfg_options<'db>(&self, db: &'db dyn DefDatabase) -> &'db CfgOptions { - self.module.krate.cfg_options(db) - } - - pub fn current_file_id(&self) -> HirFileId { - self.current_file_id - } - - pub(crate) fn parse_path( - &mut self, - db: &dyn DefDatabase, - path: ast::Path, - types_map: &mut TypesMap, - types_source_map: &mut TypesSourceMap, - ) -> Option { - let mut ctx = LowerCtx::with_span_map_cell( - db, - self.current_file_id, - self.span_map.clone(), - types_map, - types_source_map, - ); - Path::from_src(&mut ctx, path) - } - - fn within_limit( - &mut self, - db: &dyn DefDatabase, - op: F, - ) -> ExpandResult)>> - where - F: FnOnce(&mut Self) -> ExpandResult>, - { - if self.recursion_depth == u32::MAX { - // Recursion limit has been reached somewhere in the macro expansion tree. We should - // stop expanding other macro calls in this tree, or else this may result in - // exponential number of macro expansions, leading to a hang. - // - // The overflow error should have been reported when it occurred (see the next branch), - // so don't return overflow error here to avoid diagnostics duplication. - cov_mark::hit!(overflow_but_not_me); - return ExpandResult::ok(None); - } - - let ExpandResult { value, err } = op(self); - let Some(call_id) = value else { - return ExpandResult { value: None, err }; - }; - if self.recursion_depth as usize > self.recursion_limit { - self.recursion_depth = u32::MAX; - cov_mark::hit!(your_stack_belongs_to_me); - return ExpandResult::only_err(ExpandError::new( - db.macro_arg_considering_derives(call_id, &call_id.lookup(db.upcast()).kind).2, - ExpandErrorKind::RecursionOverflow, - )); - } - - let macro_file = call_id.as_macro_file(); - let res = db.parse_macro_expansion(macro_file); - - let err = err.or(res.err); - ExpandResult { - value: match &err { - // If proc-macro is disabled or unresolved, we want to expand to a missing expression - // instead of an empty tree which might end up in an empty block. - Some(e) if matches!(e.kind(), ExpandErrorKind::MissingProcMacroExpander(_)) => None, - _ => (|| { - let parse = res.value.0.cast::()?; - - self.recursion_depth += 1; - let old_span_map = OnceCell::new(); - if let Some(prev) = self.span_map.take() { - _ = old_span_map.set(prev); - }; - _ = self.span_map.set(SpanMap::ExpansionSpanMap(res.value.1)); - let old_file_id = - std::mem::replace(&mut self.current_file_id, macro_file.into()); - let mark = Mark { - file_id: old_file_id, - span_map: old_span_map, - bomb: DropBomb::new("expansion mark dropped"), - }; - Some((mark, parse)) - })(), - }, - err, - } - } -} - -#[derive(Debug)] -pub struct Mark { - file_id: HirFileId, - span_map: OnceCell, - bomb: DropBomb, -} diff --git a/crates/hir-def/src/expr_store.rs b/crates/hir-def/src/expr_store.rs index c9a7566c8d..05c220d223 100644 --- a/crates/hir-def/src/expr_store.rs +++ b/crates/hir-def/src/expr_store.rs @@ -1,10 +1,11 @@ //! Defines `ExpressionStore`: a lowered representation of functions, statics and //! consts. -mod body; -mod lower; -mod pretty; +pub mod body; +mod expander; +pub mod lower; +pub mod path; +pub(crate) mod pretty; pub mod scope; - #[cfg(test)] mod tests; @@ -12,7 +13,7 @@ use std::ops::{Deref, Index}; use cfg::{CfgExpr, CfgOptions}; use either::Either; -use hir_expand::{ExpandError, InFile, name::Name}; +use hir_expand::{ExpandError, InFile, mod_path::ModPath, name::Name}; use la_arena::{Arena, ArenaMap}; use rustc_hash::FxHashMap; use smallvec::SmallVec; @@ -22,18 +23,19 @@ use triomphe::Arc; use tt::TextRange; use crate::{ - BlockId, DefWithBodyId, Lookup, SyntheticSyntax, + BlockId, SyntheticSyntax, db::DefDatabase, + expr_store::path::Path, hir::{ Array, AsmOperand, Binding, BindingId, Expr, ExprId, ExprOrPatId, Label, LabelId, Pat, PatId, RecordFieldPat, Statement, }, nameres::DefMap, - path::{ModPath, Path}, - type_ref::{TypeRef, TypeRefId, TypesMap, TypesSourceMap}, + type_ref::{PathId, TypeRef, TypeRefId}, }; pub use self::body::{Body, BodySourceMap}; +pub use self::lower::hir_segment_to_ast_segment; /// A wrapper around [`span::SyntaxContextId`] that is intended only for comparisons. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] @@ -80,16 +82,19 @@ pub type ExprOrPatSource = InFile; pub type SelfParamPtr = AstPtr; pub type MacroCallPtr = AstPtr; +pub type TypePtr = AstPtr; +pub type TypeSource = InFile; + #[derive(Debug, Eq, PartialEq)] pub struct ExpressionStore { pub exprs: Arena, pub pats: Arena, pub bindings: Arena, pub labels: Arena