Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/next_solver/generics.rs')
| -rw-r--r-- | crates/hir-ty/src/next_solver/generics.rs | 142 |
1 files changed, 142 insertions, 0 deletions
diff --git a/crates/hir-ty/src/next_solver/generics.rs b/crates/hir-ty/src/next_solver/generics.rs new file mode 100644 index 0000000000..5ec9a18a6c --- /dev/null +++ b/crates/hir-ty/src/next_solver/generics.rs @@ -0,0 +1,142 @@ +//! Things related to generics in the next-trait-solver. + +use hir_def::{ + ConstParamId, GenericDefId, GenericParamId, ItemContainerId, LifetimeParamId, Lookup, + TypeOrConstParamId, TypeParamId, + db::DefDatabase, + expr_store::ExpressionStore, + hir::generics::{ + GenericParamDataRef, GenericParams, LifetimeParamData, LocalLifetimeParamId, + LocalTypeOrConstParamId, TypeOrConstParamData, TypeParamData, TypeParamProvenance, + WherePredicate, + }, +}; +use hir_expand::name::Name; +use intern::{Symbol, sym}; +use la_arena::Arena; +use rustc_type_ir::inherent::Ty as _; +use triomphe::Arc; + +use crate::{db::HirDatabase, generics::parent_generic_def, next_solver::Ty}; + +use super::{Const, EarlyParamRegion, ErrorGuaranteed, ParamConst, Region, SolverDefId}; + +use super::{DbInterner, GenericArg}; + +pub(crate) fn generics(db: &dyn HirDatabase, def: SolverDefId) -> Generics { + let mk_lt = |parent, index, local_id, lt: &LifetimeParamData| { + let name = lt.name.symbol().clone(); + let id = GenericParamId::LifetimeParamId(LifetimeParamId { parent, local_id }); + GenericParamDef { name, index, id } + }; + let mk_ty = |parent, index, local_id, p: &TypeOrConstParamData| { + let name = p.name().map(|n| n.symbol().clone()).unwrap_or_else(|| sym::MISSING_NAME); + let id = TypeOrConstParamId { parent, local_id }; + let id = match p { + TypeOrConstParamData::TypeParamData(_) => { + GenericParamId::TypeParamId(TypeParamId::from_unchecked(id)) + } + TypeOrConstParamData::ConstParamData(_) => { + GenericParamId::ConstParamId(ConstParamId::from_unchecked(id)) + } + }; + GenericParamDef { name, index, id } + }; + let own_params_for_generic_params = |parent, params: &GenericParams| { + let mut result = Vec::with_capacity(params.len()); + let mut type_and_consts = params.iter_type_or_consts(); + let mut index = 0; + if let Some(self_param) = params.trait_self_param() { + result.push(mk_ty(parent, 0, self_param, ¶ms[self_param])); + type_and_consts.next(); + index += 1; + } + result.extend(params.iter_lt().map(|(local_id, data)| { + let lt = mk_lt(parent, index, local_id, data); + index += 1; + lt + })); + result.extend(type_and_consts.map(|(local_id, data)| { + let ty = mk_ty(parent, index, local_id, data); + index += 1; + ty + })); + result + }; + + let (parent, own_params) = match (def.try_into(), def) { + (Ok(def), _) => ( + parent_generic_def(db, def), + own_params_for_generic_params(def, &db.generic_params(def)), + ), + (_, SolverDefId::InternedOpaqueTyId(id)) => { + match db.lookup_intern_impl_trait_id(id) { + crate::ImplTraitId::ReturnTypeImplTrait(function_id, _) => { + // The opaque type itself does not have generics - only the parent function + (Some(GenericDefId::FunctionId(function_id)), vec![]) + } + crate::ImplTraitId::TypeAliasImplTrait(type_alias_id, _) => { + (Some(type_alias_id.into()), Vec::new()) + } + crate::ImplTraitId::AsyncBlockTypeImplTrait(def, _) => { + let param = TypeOrConstParamData::TypeParamData(TypeParamData { + name: None, + default: None, + provenance: TypeParamProvenance::TypeParamList, + }); + // Yes, there is a parent but we don't include it in the generics + // FIXME: It seems utterly sensitive to fake a generic param here. + // Also, what a horrible mess! + ( + None, + vec![mk_ty( + GenericDefId::FunctionId(salsa::plumbing::FromId::from_id(unsafe { + salsa::Id::from_index(salsa::Id::MAX_U32 - 1) + })), + 0, + LocalTypeOrConstParamId::from_raw(la_arena::RawIdx::from_u32(0)), + ¶m, + )], + ) + } + } + } + _ => panic!("No generics for {def:?}"), + }; + let parent_generics = parent.map(|def| Box::new(generics(db, def.into()))); + + Generics { + parent, + parent_count: parent_generics.map_or(0, |g| g.parent_count + g.own_params.len()), + own_params, + } +} + +#[derive(Debug)] +pub struct Generics { + pub parent: Option<GenericDefId>, + pub parent_count: usize, + pub own_params: Vec<GenericParamDef>, +} + +#[derive(Debug)] +pub struct GenericParamDef { + pub(crate) name: Symbol, + //def_id: GenericDefId, + index: u32, + pub(crate) id: GenericParamId, +} + +impl GenericParamDef { + /// Returns the index of the param on the self generics only + /// (i.e. not including parent generics) + pub fn index(&self) -> u32 { + self.index + } +} + +impl<'db> rustc_type_ir::inherent::GenericsOf<DbInterner<'db>> for Generics { + fn count(&self) -> usize { + self.parent_count + self.own_params.len() + } +} |