| //! 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() |
| } |
| } |