hir_ty/next_solver/
generics.rs1use hir_def::{
4 GenericDefId, GenericParamId, TypeParamId,
5 hir::generics::{GenericParamDataRef, LifetimeParamData},
6};
7
8use crate::db::HirDatabase;
9
10use super::{Ctor, DbInterner, SolverDefId};
11
12pub(crate) fn generics<'db>(interner: DbInterner<'db>, def: SolverDefId<'db>) -> Generics<'db> {
13 let db = interner.db;
14 let (def, consider_late_bound) = match (def.try_into(), def) {
15 (Ok(def), _) => (def, false),
16 (_, SolverDefId::InternedOpaqueTyId(id)) => match id.loc(db) {
17 crate::ImplTraitId::ReturnTypeImplTrait(function_id, _) => (function_id.into(), true),
18 crate::ImplTraitId::TypeAliasImplTrait(type_alias_id, _) => {
19 (type_alias_id.into(), true)
20 }
21 },
22 (_, SolverDefId::BuiltinDeriveImplId(id)) => {
23 return crate::builtin_derive::generics_of(interner, id);
24 }
25 (_, SolverDefId::EnumVariantId(id) | SolverDefId::Ctor(Ctor::Enum(id))) => {
26 (id.loc(db).parent.into(), false)
27 }
28 (_, SolverDefId::Ctor(Ctor::Struct(id))) => (id.into(), false),
29 (_, SolverDefId::AnonConstId(id)) => {
30 let loc = id.loc(db);
31 let generic_def = loc.owner.generic_def(db);
32 return if loc.allow_using_generic_params {
33 Generics::from_generic_def(db, generic_def, false)
34 } else {
35 #[expect(
36 deprecated,
37 reason = "`Generics` only exposes an iterator over `GenericParamId`, \
38 so you cannot exploit the erroneous `crate::generics::Generics`"
39 )]
40 Generics {
41 generics: crate::generics::Generics::empty(generic_def),
42 additional_param: None,
43 consider_late_bound: false,
44 }
45 };
46 }
47 _ => panic!("No generics for {def:?}"),
48 };
49
50 Generics::from_generic_def(db, def, consider_late_bound)
51}
52
53#[derive(Debug)]
54pub struct Generics<'db> {
55 generics: crate::generics::Generics<'db>,
56 additional_param: Option<GenericParamId>,
58 consider_late_bound: bool,
59}
60
61impl<'db> Generics<'db> {
62 pub(crate) fn from_generic_def(
63 db: &'db dyn HirDatabase,
64 def: GenericDefId,
65 consider_late_bound: bool,
66 ) -> Generics<'db> {
67 Generics {
68 generics: crate::generics::generics(db, def),
69 additional_param: None,
70 consider_late_bound,
71 }
72 }
73
74 pub(crate) fn from_generic_def_plus_one(
75 db: &'db dyn HirDatabase,
76 def: GenericDefId,
77 additional_param: TypeParamId,
78 consider_late_bound: bool,
79 ) -> Generics<'db> {
80 Generics {
81 generics: crate::generics::generics(db, def),
82 additional_param: Some(additional_param.into()),
83 consider_late_bound,
84 }
85 }
86
87 pub(super) fn iter(
88 &self,
89 ) -> impl Iterator<Item = (GenericParamId, Option<&LifetimeParamData>)> {
90 self.generics
91 .iter(self.consider_late_bound)
92 .map(|(id, data)| {
93 if let GenericParamDataRef::LifetimeParamData(lt_param) = data {
94 (id, Some(lt_param))
95 } else {
96 (id, None)
97 }
98 })
99 .chain(self.additional_param.zip(None))
100 }
101}
102
103impl<'db> rustc_type_ir::inherent::GenericsOf<DbInterner<'db>> for Generics<'db> {
104 fn count(&self) -> usize {
105 self.generics.len(self.consider_late_bound) + usize::from(self.additional_param.is_some())
106 }
107}