Unnamed repository; edit this file 'description' to name the repository.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
//! Things related to generics in the next-trait-solver.

use hir_def::{GenericDefId, GenericParamId};

use crate::db::HirDatabase;

use super::SolverDefId;

use super::DbInterner;

pub(crate) fn generics(interner: DbInterner<'_>, def: SolverDefId) -> Generics<'_> {
    let db = interner.db;
    let def = match (def.try_into(), def) {
        (Ok(def), _) => def,
        (_, SolverDefId::InternedOpaqueTyId(id)) => match db.lookup_intern_impl_trait_id(id) {
            crate::ImplTraitId::ReturnTypeImplTrait(function_id, _) => function_id.into(),
            crate::ImplTraitId::TypeAliasImplTrait(type_alias_id, _) => type_alias_id.into(),
        },
        (_, SolverDefId::BuiltinDeriveImplId(id)) => {
            return crate::builtin_derive::generics_of(interner, id);
        }
        _ => panic!("No generics for {def:?}"),
    };

    Generics::from_generic_def(db, def)
}

#[derive(Debug)]
pub struct Generics<'db> {
    generics: crate::generics::Generics<'db>,
    /// This is used for builtin derives, specifically `CoercePointee`.
    additional_param: Option<GenericParamId>,
}

impl<'db> Generics<'db> {
    pub(crate) fn from_generic_def(db: &'db dyn HirDatabase, def: GenericDefId) -> Generics<'db> {
        Generics { generics: crate::generics::generics(db, def), additional_param: None }
    }

    pub(crate) fn from_generic_def_plus_one(
        db: &'db dyn HirDatabase,
        def: GenericDefId,
        additional_param: GenericParamId,
    ) -> Generics<'db> {
        Generics {
            generics: crate::generics::generics(db, def),
            additional_param: Some(additional_param),
        }
    }

    pub(super) fn iter_id(&self) -> impl Iterator<Item = GenericParamId> {
        self.generics.iter_id().chain(self.additional_param)
    }
}

impl<'db> rustc_type_ir::inherent::GenericsOf<DbInterner<'db>> for Generics<'db> {
    fn count(&self) -> usize {
        self.generics.len() + usize::from(self.additional_param.is_some())
    }
}