Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-def/src/generics.rs')
| -rw-r--r-- | crates/hir-def/src/generics.rs | 191 |
1 files changed, 27 insertions, 164 deletions
diff --git a/crates/hir-def/src/generics.rs b/crates/hir-def/src/generics.rs index 349d327aaa..1d2c7c3a55 100644 --- a/crates/hir-def/src/generics.rs +++ b/crates/hir-def/src/generics.rs @@ -3,31 +3,27 @@ //! generic parameters. See also the `Generics` type and the `generics_of` query //! in rustc. -use base_db::FileId; use either::Either; use hir_expand::{ name::{AsName, Name}, - ExpandResult, HirFileId, InFile, + ExpandResult, }; use intern::Interned; -use la_arena::{Arena, ArenaMap, Idx}; +use la_arena::{Arena, Idx}; use once_cell::unsync::Lazy; use stdx::impl_from; use syntax::ast::{self, HasGenericParams, HasName, HasTypeBounds}; use triomphe::Arc; use crate::{ - child_by_source::ChildBySource, db::DefDatabase, - dyn_map::{keys, DynMap}, expander::Expander, - item_tree::ItemTree, + item_tree::{GenericsItemTreeNode, ItemTree}, lower::LowerCtx, nameres::{DefMap, MacroSubNs}, - src::{HasChildSource, HasSource}, type_ref::{ConstRef, LifetimeRef, TypeBound, TypeRef}, - AdtId, ConstParamId, GenericDefId, HasModule, LifetimeParamId, LocalLifetimeParamId, - LocalTypeOrConstParamId, Lookup, TypeOrConstParamId, TypeParamId, + AdtId, ConstParamId, GenericDefId, HasModule, ItemTreeLoc, LocalTypeOrConstParamId, Lookup, + TypeOrConstParamId, TypeParamId, }; /// Data about a generic type parameter (to a function, struct, impl, ...). @@ -264,7 +260,7 @@ impl GenericParamsCollector { self.add_where_predicate_from_bound( lower_ctx, bound, - lifetimes.as_ref(), + lifetimes.as_deref(), target.clone(), ); } @@ -275,14 +271,14 @@ impl GenericParamsCollector { &mut self, lower_ctx: &LowerCtx<'_>, bound: ast::TypeBound, - hrtb_lifetimes: Option<&Box<[Name]>>, + hrtb_lifetimes: Option<&[Name]>, target: Either<TypeRef, LifetimeRef>, ) { let bound = TypeBound::from_ast(lower_ctx, bound); let predicate = match (target, bound) { (Either::Left(type_ref), bound) => match hrtb_lifetimes { Some(hrtb_lifetimes) => WherePredicate::ForLifetime { - lifetimes: hrtb_lifetimes.clone(), + lifetimes: hrtb_lifetimes.to_vec().into_boxed_slice(), target: WherePredicateTypeTarget::TypeRef(Interned::new(type_ref)), bound: Interned::new(bound), }, @@ -418,13 +414,18 @@ impl GenericParams { }) } }; - macro_rules! id_to_generics { - ($id:ident) => {{ - let id = $id.lookup(db).id; - let tree = id.item_tree(db); - let item = &tree[id.value]; - enabled_params(&item.generic_params, &tree) - }}; + fn id_to_generics<Id: GenericsItemTreeNode>( + db: &dyn DefDatabase, + id: impl for<'db> Lookup< + Database<'db> = dyn DefDatabase + 'db, + Data = impl ItemTreeLoc<Id = Id>, + >, + enabled_params: impl Fn(&Interned<GenericParams>, &ItemTree) -> Interned<GenericParams>, + ) -> Interned<GenericParams> { + let id = id.lookup(db).item_tree_id(); + let tree = id.item_tree(db); + let item = &tree[id.value]; + enabled_params(item.generic_params(), &tree) } match def { @@ -457,13 +458,13 @@ impl GenericParams { Interned::new(generic_params.finish()) } } - GenericDefId::AdtId(AdtId::StructId(id)) => id_to_generics!(id), - GenericDefId::AdtId(AdtId::EnumId(id)) => id_to_generics!(id), - GenericDefId::AdtId(AdtId::UnionId(id)) => id_to_generics!(id), - GenericDefId::TraitId(id) => id_to_generics!(id), - GenericDefId::TraitAliasId(id) => id_to_generics!(id), - GenericDefId::TypeAliasId(id) => id_to_generics!(id), - GenericDefId::ImplId(id) => id_to_generics!(id), + GenericDefId::AdtId(AdtId::StructId(id)) => id_to_generics(db, id, enabled_params), + GenericDefId::AdtId(AdtId::EnumId(id)) => id_to_generics(db, id, enabled_params), + GenericDefId::AdtId(AdtId::UnionId(id)) => id_to_generics(db, id, enabled_params), + GenericDefId::TraitId(id) => id_to_generics(db, id, enabled_params), + GenericDefId::TraitAliasId(id) => id_to_generics(db, id, enabled_params), + GenericDefId::TypeAliasId(id) => id_to_generics(db, id, enabled_params), + GenericDefId::ImplId(id) => id_to_generics(db, id, enabled_params), GenericDefId::EnumVariantId(_) | GenericDefId::ConstId(_) => { Interned::new(GenericParams { type_or_consts: Default::default(), @@ -507,141 +508,3 @@ impl GenericParams { }) } } - -fn file_id_and_params_of( - def: GenericDefId, - db: &dyn DefDatabase, -) -> (HirFileId, Option<ast::GenericParamList>) { - match def { - GenericDefId::FunctionId(it) => { - let src = it.lookup(db).source(db); - (src.file_id, src.value.generic_param_list()) - } - GenericDefId::AdtId(AdtId::StructId(it)) => { - let src = it.lookup(db).source(db); - (src.file_id, src.value.generic_param_list()) - } - GenericDefId::AdtId(AdtId::UnionId(it)) => { - let src = it.lookup(db).source(db); - (src.file_id, src.value.generic_param_list()) - } - GenericDefId::AdtId(AdtId::EnumId(it)) => { - let src = it.lookup(db).source(db); - (src.file_id, src.value.generic_param_list()) - } - GenericDefId::TraitId(it) => { - let src = it.lookup(db).source(db); - (src.file_id, src.value.generic_param_list()) - } - GenericDefId::TraitAliasId(it) => { - let src = it.lookup(db).source(db); - (src.file_id, src.value.generic_param_list()) - } - GenericDefId::TypeAliasId(it) => { - let src = it.lookup(db).source(db); - (src.file_id, src.value.generic_param_list()) - } - GenericDefId::ImplId(it) => { - let src = it.lookup(db).source(db); - (src.file_id, src.value.generic_param_list()) - } - // We won't be using this ID anyway - GenericDefId::EnumVariantId(_) | GenericDefId::ConstId(_) => (FileId::BOGUS.into(), None), - } -} - -impl HasChildSource<LocalTypeOrConstParamId> for GenericDefId { - type Value = Either<ast::TypeOrConstParam, ast::TraitOrAlias>; - fn child_source( - &self, - db: &dyn DefDatabase, - ) -> InFile<ArenaMap<LocalTypeOrConstParamId, Self::Value>> { - let generic_params = db.generic_params(*self); - let mut idx_iter = generic_params.type_or_consts.iter().map(|(idx, _)| idx); - - let (file_id, generic_params_list) = file_id_and_params_of(*self, db); - - let mut params = ArenaMap::default(); - - // For traits and trait aliases the first type index is `Self`, we need to add it before - // the other params. - match *self { - GenericDefId::TraitId(id) => { - let trait_ref = id.lookup(db).source(db).value; - let idx = idx_iter.next().unwrap(); - params.insert(idx, Either::Right(ast::TraitOrAlias::Trait(trait_ref))); - } - GenericDefId::TraitAliasId(id) => { - let alias = id.lookup(db).source(db).value; - let idx = idx_iter.next().unwrap(); - params.insert(idx, Either::Right(ast::TraitOrAlias::TraitAlias(alias))); - } - _ => {} - } - - if let Some(generic_params_list) = generic_params_list { - for (idx, ast_param) in idx_iter.zip(generic_params_list.type_or_const_params()) { - params.insert(idx, Either::Left(ast_param)); - } - } - - InFile::new(file_id, params) - } -} - -impl HasChildSource<LocalLifetimeParamId> for GenericDefId { - type Value = ast::LifetimeParam; - fn child_source( - &self, - db: &dyn DefDatabase, - ) -> InFile<ArenaMap<LocalLifetimeParamId, Self::Value>> { - let generic_params = db.generic_params(*self); - let idx_iter = generic_params.lifetimes.iter().map(|(idx, _)| idx); - - let (file_id, generic_params_list) = file_id_and_params_of(*self, db); - - let mut params = ArenaMap::default(); - - if let Some(generic_params_list) = generic_params_list { - for (idx, ast_param) in idx_iter.zip(generic_params_list.lifetime_params()) { - params.insert(idx, ast_param); - } - } - - InFile::new(file_id, params) - } -} - -impl ChildBySource for GenericDefId { - fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap, file_id: HirFileId) { - let (gfile_id, generic_params_list) = file_id_and_params_of(*self, db); - if gfile_id != file_id { - return; - } - - let generic_params = db.generic_params(*self); - let mut toc_idx_iter = generic_params.type_or_consts.iter().map(|(idx, _)| idx); - let lts_idx_iter = generic_params.lifetimes.iter().map(|(idx, _)| idx); - - // For traits the first type index is `Self`, skip it. - if let GenericDefId::TraitId(_) = *self { - toc_idx_iter.next().unwrap(); // advance_by(1); - } - - if let Some(generic_params_list) = generic_params_list { - for (local_id, ast_param) in - toc_idx_iter.zip(generic_params_list.type_or_const_params()) - { - let id = TypeOrConstParamId { parent: *self, local_id }; - match ast_param { - ast::TypeOrConstParam::Type(a) => res[keys::TYPE_PARAM].insert(a, id), - ast::TypeOrConstParam::Const(a) => res[keys::CONST_PARAM].insert(a, id), - } - } - for (local_id, ast_param) in lts_idx_iter.zip(generic_params_list.lifetime_params()) { - let id = LifetimeParamId { parent: *self, local_id }; - res[keys::LIFETIME_PARAM].insert(ast_param, id); - } - } - } -} |