diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-30 03:57:31 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-30 03:57:31 +0000 |
commit | dc0db358abe19481e475e10c32149b53370f1a1c (patch) | |
tree | ab8ce99c4b255ce46f99ef402c27916055b899ee /src/tools/rust-analyzer/crates/hir-def/src/lib.rs | |
parent | Releasing progress-linux version 1.71.1+dfsg1-2~progress7.99u1. (diff) | |
download | rustc-dc0db358abe19481e475e10c32149b53370f1a1c.tar.xz rustc-dc0db358abe19481e475e10c32149b53370f1a1c.zip |
Merging upstream version 1.72.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/tools/rust-analyzer/crates/hir-def/src/lib.rs')
-rw-r--r-- | src/tools/rust-analyzer/crates/hir-def/src/lib.rs | 407 |
1 files changed, 333 insertions, 74 deletions
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs index 8c2e93f09..9d8b57a0d 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs @@ -18,24 +18,23 @@ pub mod db; pub mod attr; pub mod path; -pub mod type_ref; pub mod builtin_type; -pub mod builtin_attr; pub mod per_ns; pub mod item_scope; +pub mod lower; +pub mod expander; + pub mod dyn_map; -pub mod keys; pub mod item_tree; -pub mod adt; pub mod data; pub mod generics; pub mod lang_item; -pub mod layout; -pub mod expr; +pub mod hir; +pub use self::hir::type_ref; pub mod body; pub mod resolver; @@ -49,6 +48,9 @@ pub mod visibility; pub mod find_path; pub mod import_map; +pub use rustc_abi as layout; +use triomphe::Arc; + #[cfg(test)] mod test_db; #[cfg(test)] @@ -57,7 +59,7 @@ mod pretty; use std::{ hash::{Hash, Hasher}, - sync::Arc, + panic::{RefUnwindSafe, UnwindSafe}, }; use base_db::{impl_intern_key, salsa, CrateId, ProcMacroKind}; @@ -67,11 +69,12 @@ use hir_expand::{ builtin_attr_macro::BuiltinAttrExpander, builtin_derive_macro::BuiltinDeriveExpander, builtin_fn_macro::{BuiltinFnLikeExpander, EagerExpander}, - eager::{expand_eager_macro, ErrorEmitted, ErrorSink}, + db::ExpandDatabase, + eager::expand_eager_macro_input, hygiene::Hygiene, proc_macro::ProcMacroExpander, - AstId, ExpandError, ExpandTo, HirFileId, InFile, MacroCallId, MacroCallKind, MacroDefId, - MacroDefKind, UnresolvedMacro, + AstId, ExpandError, ExpandResult, ExpandTo, HirFileId, InFile, MacroCallId, MacroCallKind, + MacroDefId, MacroDefKind, UnresolvedMacro, }; use item_tree::ExternBlock; use la_arena::Idx; @@ -82,14 +85,54 @@ use syntax::ast; use ::tt::token_id as tt; use crate::{ - adt::VariantData, builtin_type::BuiltinType, + data::adt::VariantData, item_tree::{ - Const, Enum, Function, Impl, ItemTreeId, ItemTreeNode, MacroDef, MacroRules, ModItem, - Static, Struct, Trait, TraitAlias, TypeAlias, Union, + Const, Enum, Function, Impl, ItemTreeId, ItemTreeNode, MacroDef, MacroRules, Static, + Struct, Trait, TraitAlias, TypeAlias, Union, }, }; +/// A `ModuleId` that is always a crate's root module. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct CrateRootModuleId { + krate: CrateId, +} + +impl CrateRootModuleId { + pub fn def_map(&self, db: &dyn db::DefDatabase) -> Arc<DefMap> { + db.crate_def_map(self.krate) + } + + pub fn krate(self) -> CrateId { + self.krate + } +} + +impl From<CrateRootModuleId> for ModuleId { + fn from(CrateRootModuleId { krate }: CrateRootModuleId) -> Self { + ModuleId { krate, block: None, local_id: DefMap::ROOT } + } +} + +impl From<CrateRootModuleId> for ModuleDefId { + fn from(value: CrateRootModuleId) -> Self { + ModuleDefId::ModuleId(value.into()) + } +} + +impl TryFrom<ModuleId> for CrateRootModuleId { + type Error = (); + + fn try_from(ModuleId { krate, block, local_id }: ModuleId) -> Result<Self, Self::Error> { + if block.is_none() && local_id == DefMap::ROOT { + Ok(CrateRootModuleId { krate }) + } else { + Err(()) + } + } +} + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct ModuleId { krate: CrateId, @@ -104,13 +147,7 @@ pub struct ModuleId { impl ModuleId { pub fn def_map(&self, db: &dyn db::DefDatabase) -> Arc<DefMap> { match self.block { - Some(block) => { - db.block_def_map(block).unwrap_or_else(|| { - // NOTE: This should be unreachable - all `ModuleId`s come from their `DefMap`s, - // so the `DefMap` here must exist. - unreachable!("no `block_def_map` for `ModuleId` {:?}", self); - }) - } + Some(block) => db.block_def_map(block), None => db.crate_def_map(self.krate), } } @@ -236,7 +273,7 @@ pub struct EnumVariantId { pub local_id: LocalEnumVariantId, } -pub type LocalEnumVariantId = Idx<adt::EnumVariantData>; +pub type LocalEnumVariantId = Idx<data::adt::EnumVariantData>; #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct FieldId { @@ -244,7 +281,7 @@ pub struct FieldId { pub local_id: LocalFieldId, } -pub type LocalFieldId = Idx<adt::FieldData>; +pub type LocalFieldId = Idx<data::adt::FieldData>; #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct ConstId(salsa::InternId); @@ -317,8 +354,7 @@ impl_intern!(MacroRulesId, MacroRulesLoc, intern_macro_rules, lookup_intern_macr pub struct ProcMacroId(salsa::InternId); #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct ProcMacroLoc { - // FIXME: this should be a crate? or just a crate-root module - pub container: ModuleId, + pub container: CrateRootModuleId, pub id: ItemTreeId<Function>, pub expander: ProcMacroExpander, pub kind: ProcMacroKind, @@ -478,16 +514,228 @@ impl_from!( for ModuleDefId ); +/// Id of the anonymous const block expression and patterns. This is very similar to `ClosureId` and +/// shouldn't be a `DefWithBodyId` since its type inference is dependent on its parent. +#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] +pub struct ConstBlockId(salsa::InternId); +impl_intern!(ConstBlockId, ConstBlockLoc, intern_anonymous_const, lookup_intern_anonymous_const); + +#[derive(Debug, Hash, PartialEq, Eq, Clone)] +pub struct ConstBlockLoc { + /// The parent of the anonymous const block. + pub parent: DefWithBodyId, + /// The root expression of this const block in the parent body. + pub root: hir::ExprId, +} + +#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] +pub enum TypeOwnerId { + FunctionId(FunctionId), + StaticId(StaticId), + ConstId(ConstId), + InTypeConstId(InTypeConstId), + AdtId(AdtId), + TraitId(TraitId), + TraitAliasId(TraitAliasId), + TypeAliasId(TypeAliasId), + ImplId(ImplId), + EnumVariantId(EnumVariantId), + // FIXME(const-generic-body): ModuleId should not be a type owner. This needs to be fixed to make `TypeOwnerId` actually + // useful for assigning ids to in type consts. + ModuleId(ModuleId), +} + +impl TypeOwnerId { + fn as_generic_def_id(self) -> Option<GenericDefId> { + Some(match self { + TypeOwnerId::FunctionId(x) => GenericDefId::FunctionId(x), + TypeOwnerId::ConstId(x) => GenericDefId::ConstId(x), + TypeOwnerId::AdtId(x) => GenericDefId::AdtId(x), + TypeOwnerId::TraitId(x) => GenericDefId::TraitId(x), + TypeOwnerId::TraitAliasId(x) => GenericDefId::TraitAliasId(x), + TypeOwnerId::TypeAliasId(x) => GenericDefId::TypeAliasId(x), + TypeOwnerId::ImplId(x) => GenericDefId::ImplId(x), + TypeOwnerId::EnumVariantId(x) => GenericDefId::EnumVariantId(x), + TypeOwnerId::InTypeConstId(_) | TypeOwnerId::ModuleId(_) | TypeOwnerId::StaticId(_) => { + return None + } + }) + } +} + +impl_from!( + FunctionId, + StaticId, + ConstId, + InTypeConstId, + AdtId, + TraitId, + TraitAliasId, + TypeAliasId, + ImplId, + EnumVariantId, + ModuleId + for TypeOwnerId +); + +// Every `DefWithBodyId` is a type owner, since bodies can contain type (e.g. `{ let x: Type = _; }`) +impl From<DefWithBodyId> for TypeOwnerId { + fn from(value: DefWithBodyId) -> Self { + match value { + DefWithBodyId::FunctionId(x) => x.into(), + DefWithBodyId::StaticId(x) => x.into(), + DefWithBodyId::ConstId(x) => x.into(), + DefWithBodyId::InTypeConstId(x) => x.into(), + DefWithBodyId::VariantId(x) => x.into(), + } + } +} + +impl From<GenericDefId> for TypeOwnerId { + fn from(value: GenericDefId) -> Self { + match value { + GenericDefId::FunctionId(x) => x.into(), + GenericDefId::AdtId(x) => x.into(), + GenericDefId::TraitId(x) => x.into(), + GenericDefId::TraitAliasId(x) => x.into(), + GenericDefId::TypeAliasId(x) => x.into(), + GenericDefId::ImplId(x) => x.into(), + GenericDefId::EnumVariantId(x) => x.into(), + GenericDefId::ConstId(x) => x.into(), + } + } +} + +// FIXME: This should not be a thing +/// A thing that we want to store in interned ids, but we don't know its type in `hir-def`. This is +/// currently only used in `InTypeConstId` for storing the type (which has type `Ty` defined in +/// the `hir-ty` crate) of the constant in its id, which is a temporary hack so we may want +/// to remove this after removing that. +pub trait OpaqueInternableThing: + std::any::Any + std::fmt::Debug + Sync + Send + UnwindSafe + RefUnwindSafe +{ + fn as_any(&self) -> &dyn std::any::Any; + fn box_any(&self) -> Box<dyn std::any::Any>; + fn dyn_hash(&self, state: &mut dyn Hasher); + fn dyn_eq(&self, other: &dyn OpaqueInternableThing) -> bool; + fn dyn_clone(&self) -> Box<dyn OpaqueInternableThing>; +} + +impl Hash for dyn OpaqueInternableThing { + fn hash<H: Hasher>(&self, state: &mut H) { + self.dyn_hash(state); + } +} + +impl PartialEq for dyn OpaqueInternableThing { + fn eq(&self, other: &Self) -> bool { + self.dyn_eq(other) + } +} + +impl Eq for dyn OpaqueInternableThing {} + +impl Clone for Box<dyn OpaqueInternableThing> { + fn clone(&self) -> Self { + self.dyn_clone() + } +} + +// FIXME(const-generic-body): Use an stable id for in type consts. +// +// The current id uses `AstId<ast::ConstArg>` which will be changed by every change in the code. Ideally +// we should use an id which is relative to the type owner, so that every change will only invalidate the +// id if it happens inside of the type owner. +// +// The solution probably is to have some query on `TypeOwnerId` to traverse its constant children and store +// their `AstId` in a list (vector or arena), and use the index of that list in the id here. That query probably +// needs name resolution, and might go far and handles the whole path lowering or type lowering for a `TypeOwnerId`. +// +// Whatever path the solution takes, it should answer 3 questions at the same time: +// * Is the id stable enough? +// * How to find a constant id using an ast node / position in the source code? This is needed when we want to +// provide ide functionalities inside an in type const (which we currently don't support) e.g. go to definition +// for a local defined there. A complex id might have some trouble in this reverse mapping. +// * How to find the return type of a constant using its id? We have this data when we are doing type lowering +// and the name of the struct that contains this constant is resolved, so a query that only traverses the +// type owner by its syntax tree might have a hard time here. + +/// A constant in a type as a substitution for const generics (like `Foo<{ 2 + 2 }>`) or as an array +/// length (like `[u8; 2 + 2]`). These constants are body owner and are a variant of `DefWithBodyId`. These +/// are not called `AnonymousConstId` to prevent confusion with [`ConstBlockId`]. +#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] +pub struct InTypeConstId(salsa::InternId); +impl_intern!(InTypeConstId, InTypeConstLoc, intern_in_type_const, lookup_intern_in_type_const); + +#[derive(Debug, Hash, Eq, Clone)] +pub struct InTypeConstLoc { + pub id: AstId<ast::ConstArg>, + /// The thing this const arg appears in + pub owner: TypeOwnerId, + pub thing: Box<dyn OpaqueInternableThing>, +} + +impl PartialEq for InTypeConstLoc { + fn eq(&self, other: &Self) -> bool { + self.id == other.id && self.owner == other.owner && &*self.thing == &*other.thing + } +} + +impl InTypeConstId { + pub fn source(&self, db: &dyn db::DefDatabase) -> ast::ConstArg { + let src = self.lookup(db).id; + let file_id = src.file_id; + let root = &db.parse_or_expand(file_id); + db.ast_id_map(file_id).get(src.value).to_node(root) + } +} + +/// A constant, which might appears as a const item, an annonymous const block in expressions +/// or patterns, or as a constant in types with const generics. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub enum GeneralConstId { + ConstId(ConstId), + ConstBlockId(ConstBlockId), + InTypeConstId(InTypeConstId), +} + +impl_from!(ConstId, ConstBlockId, InTypeConstId for GeneralConstId); + +impl GeneralConstId { + pub fn generic_def(self, db: &dyn db::DefDatabase) -> Option<GenericDefId> { + match self { + GeneralConstId::ConstId(it) => Some(it.into()), + GeneralConstId::ConstBlockId(it) => it.lookup(db).parent.as_generic_def_id(), + GeneralConstId::InTypeConstId(it) => it.lookup(db).owner.as_generic_def_id(), + } + } + + pub fn name(self, db: &dyn db::DefDatabase) -> String { + match self { + GeneralConstId::ConstId(const_id) => db + .const_data(const_id) + .name + .as_ref() + .and_then(|x| x.as_str()) + .unwrap_or("_") + .to_owned(), + GeneralConstId::ConstBlockId(id) => format!("{{anonymous const {id:?}}}"), + GeneralConstId::InTypeConstId(id) => format!("{{in type const {id:?}}}"), + } + } +} + /// The defs which have a body. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub enum DefWithBodyId { FunctionId(FunctionId), StaticId(StaticId), ConstId(ConstId), + InTypeConstId(InTypeConstId), VariantId(EnumVariantId), } -impl_from!(FunctionId, ConstId, StaticId for DefWithBodyId); +impl_from!(FunctionId, ConstId, StaticId, InTypeConstId for DefWithBodyId); impl From<EnumVariantId> for DefWithBodyId { fn from(id: EnumVariantId) -> Self { @@ -502,6 +750,9 @@ impl DefWithBodyId { DefWithBodyId::StaticId(_) => None, DefWithBodyId::ConstId(c) => Some(c.into()), DefWithBodyId::VariantId(c) => Some(c.into()), + // FIXME: stable rust doesn't allow generics in constants, but we should + // use `TypeOwnerId::as_generic_def_id` when it does. + DefWithBodyId::InTypeConstId(_) => None, } } } @@ -691,29 +942,37 @@ impl HasModule for MacroId { match self { MacroId::MacroRulesId(it) => it.lookup(db).container, MacroId::Macro2Id(it) => it.lookup(db).container, - MacroId::ProcMacroId(it) => it.lookup(db).container, + MacroId::ProcMacroId(it) => it.lookup(db).container.into(), } } } -impl HasModule for DefWithBodyId { +impl HasModule for TypeOwnerId { fn module(&self, db: &dyn db::DefDatabase) -> ModuleId { match self { - DefWithBodyId::FunctionId(it) => it.lookup(db).module(db), - DefWithBodyId::StaticId(it) => it.lookup(db).module(db), - DefWithBodyId::ConstId(it) => it.lookup(db).module(db), - DefWithBodyId::VariantId(it) => it.parent.lookup(db).container, + TypeOwnerId::FunctionId(x) => x.lookup(db).module(db), + TypeOwnerId::StaticId(x) => x.lookup(db).module(db), + TypeOwnerId::ConstId(x) => x.lookup(db).module(db), + TypeOwnerId::InTypeConstId(x) => x.lookup(db).owner.module(db), + TypeOwnerId::AdtId(x) => x.module(db), + TypeOwnerId::TraitId(x) => x.lookup(db).container, + TypeOwnerId::TraitAliasId(x) => x.lookup(db).container, + TypeOwnerId::TypeAliasId(x) => x.lookup(db).module(db), + TypeOwnerId::ImplId(x) => x.lookup(db).container, + TypeOwnerId::EnumVariantId(x) => x.parent.lookup(db).container, + TypeOwnerId::ModuleId(x) => *x, } } } -impl DefWithBodyId { - pub fn as_mod_item(self, db: &dyn db::DefDatabase) -> ModItem { +impl HasModule for DefWithBodyId { + fn module(&self, db: &dyn db::DefDatabase) -> ModuleId { match self { - DefWithBodyId::FunctionId(it) => it.lookup(db).id.value.into(), - DefWithBodyId::StaticId(it) => it.lookup(db).id.value.into(), - DefWithBodyId::ConstId(it) => it.lookup(db).id.value.into(), - DefWithBodyId::VariantId(it) => it.parent.lookup(db).id.value.into(), + DefWithBodyId::FunctionId(it) => it.lookup(db).module(db), + DefWithBodyId::StaticId(it) => it.lookup(db).module(db), + DefWithBodyId::ConstId(it) => it.lookup(db).module(db), + DefWithBodyId::VariantId(it) => it.parent.lookup(db).container, + DefWithBodyId::InTypeConstId(it) => it.lookup(db).owner.module(db), } } } @@ -799,52 +1058,43 @@ impl AttrDefId { pub trait AsMacroCall { fn as_call_id( &self, - db: &dyn db::DefDatabase, + db: &dyn ExpandDatabase, krate: CrateId, resolver: impl Fn(path::ModPath) -> Option<MacroDefId>, ) -> Option<MacroCallId> { - self.as_call_id_with_errors(db, krate, resolver, &mut |_| ()).ok()?.ok() + self.as_call_id_with_errors(db, krate, resolver).ok()?.value } fn as_call_id_with_errors( &self, - db: &dyn db::DefDatabase, + db: &dyn ExpandDatabase, krate: CrateId, resolver: impl Fn(path::ModPath) -> Option<MacroDefId>, - error_sink: &mut dyn FnMut(ExpandError), - ) -> Result<Result<MacroCallId, ErrorEmitted>, UnresolvedMacro>; + ) -> Result<ExpandResult<Option<MacroCallId>>, UnresolvedMacro>; } impl AsMacroCall for InFile<&ast::MacroCall> { fn as_call_id_with_errors( &self, - db: &dyn db::DefDatabase, + db: &dyn ExpandDatabase, krate: CrateId, resolver: impl Fn(path::ModPath) -> Option<MacroDefId>, - mut error_sink: &mut dyn FnMut(ExpandError), - ) -> Result<Result<MacroCallId, ErrorEmitted>, UnresolvedMacro> { + ) -> Result<ExpandResult<Option<MacroCallId>>, UnresolvedMacro> { let expands_to = hir_expand::ExpandTo::from_call_site(self.value); let ast_id = AstId::new(self.file_id, db.ast_id_map(self.file_id).ast_id(self.value)); - let h = Hygiene::new(db.upcast(), self.file_id); - let path = - self.value.path().and_then(|path| path::ModPath::from_src(db.upcast(), path, &h)); - - let path = match error_sink - .option(path, || ExpandError::Other("malformed macro invocation".into())) - { - Ok(path) => path, - Err(error) => { - return Ok(Err(error)); - } + let h = Hygiene::new(db, self.file_id); + let path = self.value.path().and_then(|path| path::ModPath::from_src(db, path, &h)); + + let Some(path) = path else { + return Ok(ExpandResult::only_err(ExpandError::other("malformed macro invocation"))); }; - macro_call_as_call_id( + macro_call_as_call_id_( db, &AstIdWithPath::new(ast_id.file_id, ast_id.value, path), expands_to, krate, resolver, - error_sink, ) } } @@ -863,26 +1113,37 @@ impl<T: ast::AstNode> AstIdWithPath<T> { } fn macro_call_as_call_id( - db: &dyn db::DefDatabase, + db: &dyn ExpandDatabase, call: &AstIdWithPath<ast::MacroCall>, expand_to: ExpandTo, krate: CrateId, resolver: impl Fn(path::ModPath) -> Option<MacroDefId>, - error_sink: &mut dyn FnMut(ExpandError), -) -> Result<Result<MacroCallId, ErrorEmitted>, UnresolvedMacro> { +) -> Result<Option<MacroCallId>, UnresolvedMacro> { + macro_call_as_call_id_(db, call, expand_to, krate, resolver).map(|res| res.value) +} + +fn macro_call_as_call_id_( + db: &dyn ExpandDatabase, + call: &AstIdWithPath<ast::MacroCall>, + expand_to: ExpandTo, + krate: CrateId, + resolver: impl Fn(path::ModPath) -> Option<MacroDefId>, +) -> Result<ExpandResult<Option<MacroCallId>>, UnresolvedMacro> { let def = resolver(call.path.clone()).ok_or_else(|| UnresolvedMacro { path: call.path.clone() })?; let res = if let MacroDefKind::BuiltInEager(..) = def.kind { - let macro_call = InFile::new(call.ast_id.file_id, call.ast_id.to_node(db.upcast())); - - expand_eager_macro(db.upcast(), krate, macro_call, def, &resolver, error_sink)? + let macro_call = InFile::new(call.ast_id.file_id, call.ast_id.to_node(db)); + expand_eager_macro_input(db, krate, macro_call, def, &resolver)? } else { - Ok(def.as_lazy_macro( - db.upcast(), - krate, - MacroCallKind::FnLike { ast_id: call.ast_id, expand_to }, - )) + ExpandResult { + value: Some(def.as_lazy_macro( + db, + krate, + MacroCallKind::FnLike { ast_id: call.ast_id, expand_to }, + )), + err: None, + } }; Ok(res) } @@ -986,16 +1247,15 @@ fn attr_macro_as_call_id( macro_attr: &Attr, krate: CrateId, def: MacroDefId, - is_derive: bool, ) -> MacroCallId { let arg = match macro_attr.input.as_deref() { - Some(AttrInput::TokenTree(tt, map)) => ( + Some(AttrInput::TokenTree(tt)) => ( { - let mut tt = tt.clone(); + let mut tt = tt.0.clone(); tt.delimiter = tt::Delimiter::UNSPECIFIED; tt }, - map.clone(), + tt.1.clone(), ), _ => (tt::Subtree::empty(), Default::default()), }; @@ -1007,7 +1267,6 @@ fn attr_macro_as_call_id( ast_id: item_attr.ast_id, attr_args: Arc::new(arg), invoc_attr_index: macro_attr.id, - is_derive, }, ) } |