hir_ty/next_solver/
generics.rs

1//! Things related to generics in the next-trait-solver.
2
3use hir_def::{
4    ConstParamId, GenericDefId, GenericParamId, LifetimeParamId, TypeOrConstParamId, TypeParamId,
5    hir::generics::{GenericParams, TypeOrConstParamData},
6};
7
8use crate::{db::HirDatabase, generics::parent_generic_def};
9
10use super::SolverDefId;
11
12use super::DbInterner;
13
14pub(crate) fn generics(db: &dyn HirDatabase, def: SolverDefId) -> Generics {
15    let mk_lt = |parent, index, local_id| {
16        let id = GenericParamId::LifetimeParamId(LifetimeParamId { parent, local_id });
17        GenericParamDef { index, id }
18    };
19    let mk_ty = |parent, index, local_id, p: &TypeOrConstParamData| {
20        let id = TypeOrConstParamId { parent, local_id };
21        let id = match p {
22            TypeOrConstParamData::TypeParamData(_) => {
23                GenericParamId::TypeParamId(TypeParamId::from_unchecked(id))
24            }
25            TypeOrConstParamData::ConstParamData(_) => {
26                GenericParamId::ConstParamId(ConstParamId::from_unchecked(id))
27            }
28        };
29        GenericParamDef { index, id }
30    };
31    let own_params_for_generic_params = |parent, params: &GenericParams| {
32        let mut result = Vec::with_capacity(params.len());
33        let mut type_and_consts = params.iter_type_or_consts();
34        let mut index = 0;
35        if let Some(self_param) = params.trait_self_param() {
36            result.push(mk_ty(parent, 0, self_param, &params[self_param]));
37            type_and_consts.next();
38            index += 1;
39        }
40        result.extend(params.iter_lt().map(|(local_id, _data)| {
41            let lt = mk_lt(parent, index, local_id);
42            index += 1;
43            lt
44        }));
45        result.extend(type_and_consts.map(|(local_id, data)| {
46            let ty = mk_ty(parent, index, local_id, data);
47            index += 1;
48            ty
49        }));
50        result
51    };
52
53    let (parent, own_params) = match (def.try_into(), def) {
54        (Ok(def), _) => (
55            parent_generic_def(db, def),
56            own_params_for_generic_params(def, &db.generic_params(def)),
57        ),
58        (_, SolverDefId::InternedOpaqueTyId(id)) => {
59            match db.lookup_intern_impl_trait_id(id) {
60                crate::ImplTraitId::ReturnTypeImplTrait(function_id, _) => {
61                    // The opaque type itself does not have generics - only the parent function
62                    (Some(GenericDefId::FunctionId(function_id)), vec![])
63                }
64                crate::ImplTraitId::TypeAliasImplTrait(type_alias_id, _) => {
65                    (Some(type_alias_id.into()), Vec::new())
66                }
67            }
68        }
69        _ => panic!("No generics for {def:?}"),
70    };
71    let parent_generics = parent.map(|def| Box::new(generics(db, def.into())));
72
73    Generics {
74        parent,
75        parent_count: parent_generics.map_or(0, |g| g.parent_count + g.own_params.len()),
76        own_params,
77    }
78}
79
80#[derive(Debug)]
81pub struct Generics {
82    pub parent: Option<GenericDefId>,
83    pub parent_count: usize,
84    pub own_params: Vec<GenericParamDef>,
85}
86
87#[derive(Debug)]
88pub struct GenericParamDef {
89    index: u32,
90    pub(crate) id: GenericParamId,
91}
92
93impl GenericParamDef {
94    /// Returns the index of the param on the self generics only
95    /// (i.e. not including parent generics)
96    pub fn index(&self) -> u32 {
97        self.index
98    }
99}
100
101impl<'db> rustc_type_ir::inherent::GenericsOf<DbInterner<'db>> for Generics {
102    fn count(&self) -> usize {
103        self.parent_count + self.own_params.len()
104    }
105}