Skip to content

Commit 7b50a5f

Browse files
committed
Extract generics module
1 parent 9b8b6f9 commit 7b50a5f

File tree

15 files changed

+333
-323
lines changed

15 files changed

+333
-323
lines changed

src/tools/rust-analyzer/crates/hir-ty/src/builder.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@ use hir_def::{
1414
use smallvec::SmallVec;
1515

1616
use crate::{
17-
consteval::unknown_const_as_generic, db::HirDatabase, error_lifetime,
18-
infer::unify::InferenceTable, primitive, to_assoc_type_id, to_chalk_trait_id, utils::generics,
19-
Binders, BoundVar, CallableSig, GenericArg, GenericArgData, Interner, ProjectionTy,
20-
Substitution, TraitRef, Ty, TyDefId, TyExt, TyKind,
17+
consteval::unknown_const_as_generic, db::HirDatabase, error_lifetime, generics::generics,
18+
infer::unify::InferenceTable, primitive, to_assoc_type_id, to_chalk_trait_id, Binders,
19+
BoundVar, CallableSig, GenericArg, GenericArgData, Interner, ProjectionTy, Substitution,
20+
TraitRef, Ty, TyDefId, TyExt, TyKind,
2121
};
2222

2323
#[derive(Debug, Clone, PartialEq, Eq)]

src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,14 @@ use hir_expand::name::name;
2020
use crate::{
2121
db::{HirDatabase, InternedCoroutine},
2222
display::HirDisplay,
23-
from_assoc_type_id, from_chalk_trait_id, from_foreign_def_id, make_binders,
24-
make_single_type_binders,
23+
from_assoc_type_id, from_chalk_trait_id, from_foreign_def_id,
24+
generics::generics,
25+
make_binders, make_single_type_binders,
2526
mapping::{from_chalk, ToChalk, TypeAliasAsValue},
2627
method_resolution::{TraitImpls, TyFingerprint, ALL_FLOAT_FPS, ALL_INT_FPS},
2728
to_assoc_type_id, to_chalk_trait_id,
2829
traits::ChalkContext,
29-
utils::{generics, ClosureSubst},
30+
utils::ClosureSubst,
3031
wrap_empty_binders, AliasEq, AliasTy, BoundVar, CallableDefId, DebruijnIndex, FnDefId,
3132
Interner, ProjectionTy, ProjectionTyExt, QuantifiedWhereClause, Substitution, TraitRef,
3233
TraitRefExt, Ty, TyBuilder, TyExt, TyKind, WhereClause,

src/tools/rust-analyzer/crates/hir-ty/src/chalk_ext.rs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,10 @@ use hir_def::{
1212
};
1313

1414
use crate::{
15-
db::HirDatabase,
16-
from_assoc_type_id, from_chalk_trait_id, from_foreign_def_id, from_placeholder_idx,
17-
to_chalk_trait_id,
18-
utils::{generics, ClosureSubst},
19-
AdtId, AliasEq, AliasTy, Binders, CallableDefId, CallableSig, Canonical, CanonicalVarKinds,
20-
ClosureId, DynTy, FnPointer, ImplTraitId, InEnvironment, Interner, Lifetime, ProjectionTy,
15+
db::HirDatabase, from_assoc_type_id, from_chalk_trait_id, from_foreign_def_id,
16+
from_placeholder_idx, generics::generics, to_chalk_trait_id, utils::ClosureSubst, AdtId,
17+
AliasEq, AliasTy, Binders, CallableDefId, CallableSig, Canonical, CanonicalVarKinds, ClosureId,
18+
DynTy, FnPointer, ImplTraitId, InEnvironment, Interner, Lifetime, ProjectionTy,
2119
QuantifiedWhereClause, Substitution, TraitRef, Ty, TyBuilder, TyKind, TypeFlags, WhereClause,
2220
};
2321

src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,9 @@ use stdx::never;
1515
use triomphe::Arc;
1616

1717
use crate::{
18-
db::HirDatabase, infer::InferenceContext, lower::ParamLoweringMode,
19-
mir::monomorphize_mir_body_bad, to_placeholder_idx, utils::Generics, Const, ConstData,
20-
ConstScalar, ConstValue, GenericArg, Interner, MemoryMap, Substitution, TraitEnvironment, Ty,
21-
TyBuilder,
18+
db::HirDatabase, generics::Generics, infer::InferenceContext, lower::ParamLoweringMode,
19+
mir::monomorphize_mir_body_bad, to_placeholder_idx, Const, ConstData, ConstScalar, ConstValue,
20+
GenericArg, Interner, MemoryMap, Substitution, TraitEnvironment, Ty, TyBuilder,
2221
};
2322

2423
use super::mir::{interpret_mir, lower_to_mir, pad16, MirEvalError, MirLowerError};

src/tools/rust-analyzer/crates/hir-ty/src/display.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,13 @@ use crate::{
3636
consteval::try_const_usize,
3737
db::{HirDatabase, InternedClosure},
3838
from_assoc_type_id, from_foreign_def_id, from_placeholder_idx,
39+
generics::generics,
3940
layout::Layout,
4041
lt_from_placeholder_idx,
4142
mapping::from_chalk,
4243
mir::pad16,
4344
primitive, to_assoc_type_id,
44-
utils::{self, detect_variant_from_bytes, generics, ClosureSubst},
45+
utils::{self, detect_variant_from_bytes, ClosureSubst},
4546
AdtId, AliasEq, AliasTy, Binders, CallableDefId, CallableSig, ConcreteConst, Const,
4647
ConstScalar, ConstValue, DomainGoal, FnAbi, GenericArg, ImplTraitId, Interner, Lifetime,
4748
LifetimeData, LifetimeOutlives, MemoryMap, Mutability, OpaqueTy, ProjectionTy, ProjectionTyExt,
Lines changed: 286 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,286 @@
1+
use chalk_ir::{cast::Cast as _, BoundVar, DebruijnIndex};
2+
use hir_def::{
3+
db::DefDatabase,
4+
generics::{
5+
GenericParamDataRef, GenericParams, LifetimeParamData, TypeOrConstParamData,
6+
TypeParamProvenance,
7+
},
8+
ConstParamId, GenericDefId, GenericParamId, ItemContainerId, LifetimeParamId, Lookup,
9+
TypeOrConstParamId, TypeParamId,
10+
};
11+
use intern::Interned;
12+
13+
use crate::{db::HirDatabase, Interner, Substitution};
14+
15+
pub(crate) fn generics(db: &dyn DefDatabase, def: GenericDefId) -> Generics {
16+
let parent_generics = parent_generic_def(db, def).map(|def| Box::new(generics(db, def)));
17+
Generics { def, params: db.generic_params(def), parent_generics }
18+
}
19+
#[derive(Clone, Debug)]
20+
pub(crate) struct Generics {
21+
def: GenericDefId,
22+
pub(crate) params: Interned<GenericParams>,
23+
parent_generics: Option<Box<Generics>>,
24+
}
25+
26+
impl Generics {
27+
pub(crate) fn iter_id(&self) -> impl Iterator<Item = GenericParamId> + '_ {
28+
self.iter().map(|(id, _)| id)
29+
}
30+
31+
pub(crate) fn def(&self) -> GenericDefId {
32+
self.def
33+
}
34+
35+
/// Iterator over types and const params of self, then parent.
36+
pub(crate) fn iter<'a>(
37+
&'a self,
38+
) -> impl DoubleEndedIterator<Item = (GenericParamId, GenericParamDataRef<'a>)> + 'a {
39+
let from_toc_id = |it: &'a Generics| {
40+
move |(local_id, p): (_, &'a TypeOrConstParamData)| {
41+
let id = TypeOrConstParamId { parent: it.def, local_id };
42+
match p {
43+
TypeOrConstParamData::TypeParamData(p) => (
44+
GenericParamId::TypeParamId(TypeParamId::from_unchecked(id)),
45+
GenericParamDataRef::TypeParamData(p),
46+
),
47+
TypeOrConstParamData::ConstParamData(p) => (
48+
GenericParamId::ConstParamId(ConstParamId::from_unchecked(id)),
49+
GenericParamDataRef::ConstParamData(p),
50+
),
51+
}
52+
}
53+
};
54+
55+
let from_lt_id = |it: &'a Generics| {
56+
move |(local_id, p): (_, &'a LifetimeParamData)| {
57+
(
58+
GenericParamId::LifetimeParamId(LifetimeParamId { parent: it.def, local_id }),
59+
GenericParamDataRef::LifetimeParamData(p),
60+
)
61+
}
62+
};
63+
64+
let lt_iter = self.params.iter_lt().map(from_lt_id(self));
65+
self.params
66+
.iter_type_or_consts()
67+
.map(from_toc_id(self))
68+
.chain(lt_iter)
69+
.chain(self.iter_parent())
70+
}
71+
72+
/// Iterate over types and const params without parent params.
73+
pub(crate) fn iter_self<'a>(
74+
&'a self,
75+
) -> impl DoubleEndedIterator<Item = (GenericParamId, GenericParamDataRef<'a>)> + 'a {
76+
let from_toc_id = |it: &'a Generics| {
77+
move |(local_id, p): (_, &'a TypeOrConstParamData)| {
78+
let id = TypeOrConstParamId { parent: it.def, local_id };
79+
match p {
80+
TypeOrConstParamData::TypeParamData(p) => (
81+
GenericParamId::TypeParamId(TypeParamId::from_unchecked(id)),
82+
GenericParamDataRef::TypeParamData(p),
83+
),
84+
TypeOrConstParamData::ConstParamData(p) => (
85+
GenericParamId::ConstParamId(ConstParamId::from_unchecked(id)),
86+
GenericParamDataRef::ConstParamData(p),
87+
),
88+
}
89+
}
90+
};
91+
92+
let from_lt_id = |it: &'a Generics| {
93+
move |(local_id, p): (_, &'a LifetimeParamData)| {
94+
(
95+
GenericParamId::LifetimeParamId(LifetimeParamId { parent: it.def, local_id }),
96+
GenericParamDataRef::LifetimeParamData(p),
97+
)
98+
}
99+
};
100+
101+
self.params
102+
.iter_type_or_consts()
103+
.map(from_toc_id(self))
104+
.chain(self.params.iter_lt().map(from_lt_id(self)))
105+
}
106+
107+
/// Iterator over types and const params of parent.
108+
pub(crate) fn iter_parent(
109+
&self,
110+
) -> impl DoubleEndedIterator<Item = (GenericParamId, GenericParamDataRef<'_>)> + '_ {
111+
self.parent_generics().into_iter().flat_map(|it| {
112+
let from_toc_id = move |(local_id, p)| {
113+
let p: &_ = p;
114+
let id = TypeOrConstParamId { parent: it.def, local_id };
115+
match p {
116+
TypeOrConstParamData::TypeParamData(p) => (
117+
GenericParamId::TypeParamId(TypeParamId::from_unchecked(id)),
118+
GenericParamDataRef::TypeParamData(p),
119+
),
120+
TypeOrConstParamData::ConstParamData(p) => (
121+
GenericParamId::ConstParamId(ConstParamId::from_unchecked(id)),
122+
GenericParamDataRef::ConstParamData(p),
123+
),
124+
}
125+
};
126+
127+
let from_lt_id = move |(local_id, p): (_, _)| {
128+
(
129+
GenericParamId::LifetimeParamId(LifetimeParamId { parent: it.def, local_id }),
130+
GenericParamDataRef::LifetimeParamData(p),
131+
)
132+
};
133+
let lt_iter = it.params.iter_lt().map(from_lt_id);
134+
it.params.iter_type_or_consts().map(from_toc_id).chain(lt_iter)
135+
})
136+
}
137+
138+
/// Returns total number of generic parameters in scope, including those from parent.
139+
pub(crate) fn len(&self) -> usize {
140+
let parent = self.parent_generics().map_or(0, Generics::len);
141+
let child = self.params.len();
142+
parent + child
143+
}
144+
145+
/// Returns numbers of generic parameters excluding those from parent.
146+
pub(crate) fn len_self(&self) -> usize {
147+
self.params.len()
148+
}
149+
150+
/// Returns number of generic parameter excluding those from parent
151+
fn len_type_and_const_params(&self) -> usize {
152+
self.params.type_or_consts.len()
153+
}
154+
155+
/// (parent total, self param, type params, const params, impl trait list, lifetimes)
156+
pub(crate) fn provenance_split(&self) -> (usize, usize, usize, usize, usize, usize) {
157+
let mut self_params = 0;
158+
let mut type_params = 0;
159+
let mut impl_trait_params = 0;
160+
let mut const_params = 0;
161+
let mut lifetime_params = 0;
162+
self.params.iter_type_or_consts().for_each(|(_, data)| match data {
163+
TypeOrConstParamData::TypeParamData(p) => match p.provenance {
164+
TypeParamProvenance::TypeParamList => type_params += 1,
165+
TypeParamProvenance::TraitSelf => self_params += 1,
166+
TypeParamProvenance::ArgumentImplTrait => impl_trait_params += 1,
167+
},
168+
TypeOrConstParamData::ConstParamData(_) => const_params += 1,
169+
});
170+
171+
self.params.iter_lt().for_each(|(_, _)| lifetime_params += 1);
172+
173+
let parent_len = self.parent_generics().map_or(0, Generics::len);
174+
(parent_len, self_params, type_params, const_params, impl_trait_params, lifetime_params)
175+
}
176+
177+
pub(crate) fn type_or_const_param_idx(&self, param: TypeOrConstParamId) -> Option<usize> {
178+
Some(self.find_type_or_const_param(param)?.0)
179+
}
180+
181+
fn find_type_or_const_param(
182+
&self,
183+
param: TypeOrConstParamId,
184+
) -> Option<(usize, &TypeOrConstParamData)> {
185+
if param.parent == self.def {
186+
let idx = param.local_id.into_raw().into_u32() as usize;
187+
if idx >= self.params.type_or_consts.len() {
188+
return None;
189+
}
190+
Some((idx, &self.params.type_or_consts[param.local_id]))
191+
} else {
192+
self.parent_generics()
193+
.and_then(|g| g.find_type_or_const_param(param))
194+
// Remember that parent parameters come after parameters for self.
195+
.map(|(idx, data)| (self.len_self() + idx, data))
196+
}
197+
}
198+
199+
pub(crate) fn lifetime_idx(&self, lifetime: LifetimeParamId) -> Option<usize> {
200+
Some(self.find_lifetime(lifetime)?.0)
201+
}
202+
203+
fn find_lifetime(&self, lifetime: LifetimeParamId) -> Option<(usize, &LifetimeParamData)> {
204+
if lifetime.parent == self.def {
205+
let idx = lifetime.local_id.into_raw().into_u32() as usize;
206+
if idx >= self.params.lifetimes.len() {
207+
return None;
208+
}
209+
Some((
210+
self.len_type_and_const_params() + idx,
211+
&self.params.lifetimes[lifetime.local_id],
212+
))
213+
} else {
214+
self.parent_generics()
215+
.and_then(|g| g.find_lifetime(lifetime))
216+
.map(|(idx, data)| (self.len_self() + idx, data))
217+
}
218+
}
219+
220+
pub(crate) fn parent_generics(&self) -> Option<&Generics> {
221+
self.parent_generics.as_deref()
222+
}
223+
224+
pub(crate) fn parent_or_self(&self) -> &Generics {
225+
self.parent_generics.as_deref().unwrap_or(self)
226+
}
227+
228+
/// Returns a Substitution that replaces each parameter by a bound variable.
229+
pub(crate) fn bound_vars_subst(
230+
&self,
231+
db: &dyn HirDatabase,
232+
debruijn: DebruijnIndex,
233+
) -> Substitution {
234+
Substitution::from_iter(
235+
Interner,
236+
self.iter_id().enumerate().map(|(idx, id)| match id {
237+
GenericParamId::ConstParamId(id) => BoundVar::new(debruijn, idx)
238+
.to_const(Interner, db.const_param_ty(id))
239+
.cast(Interner),
240+
GenericParamId::TypeParamId(_) => {
241+
BoundVar::new(debruijn, idx).to_ty(Interner).cast(Interner)
242+
}
243+
GenericParamId::LifetimeParamId(_) => {
244+
BoundVar::new(debruijn, idx).to_lifetime(Interner).cast(Interner)
245+
}
246+
}),
247+
)
248+
}
249+
250+
/// Returns a Substitution that replaces each parameter by itself (i.e. `Ty::Param`).
251+
pub(crate) fn placeholder_subst(&self, db: &dyn HirDatabase) -> Substitution {
252+
Substitution::from_iter(
253+
Interner,
254+
self.iter_id().map(|id| match id {
255+
GenericParamId::TypeParamId(id) => {
256+
crate::to_placeholder_idx(db, id.into()).to_ty(Interner).cast(Interner)
257+
}
258+
GenericParamId::ConstParamId(id) => crate::to_placeholder_idx(db, id.into())
259+
.to_const(Interner, db.const_param_ty(id))
260+
.cast(Interner),
261+
GenericParamId::LifetimeParamId(id) => {
262+
crate::lt_to_placeholder_idx(db, id).to_lifetime(Interner).cast(Interner)
263+
}
264+
}),
265+
)
266+
}
267+
}
268+
269+
fn parent_generic_def(db: &dyn DefDatabase, def: GenericDefId) -> Option<GenericDefId> {
270+
let container = match def {
271+
GenericDefId::FunctionId(it) => it.lookup(db).container,
272+
GenericDefId::TypeAliasId(it) => it.lookup(db).container,
273+
GenericDefId::ConstId(it) => it.lookup(db).container,
274+
GenericDefId::EnumVariantId(it) => return Some(it.lookup(db).parent.into()),
275+
GenericDefId::AdtId(_)
276+
| GenericDefId::TraitId(_)
277+
| GenericDefId::ImplId(_)
278+
| GenericDefId::TraitAliasId(_) => return None,
279+
};
280+
281+
match container {
282+
ItemContainerId::ImplId(it) => Some(it.into()),
283+
ItemContainerId::TraitId(it) => Some(it.into()),
284+
ItemContainerId::ModuleId(_) | ItemContainerId::ExternBlockId(_) => None,
285+
}
286+
}

src/tools/rust-analyzer/crates/hir-ty/src/infer.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,12 @@ use triomphe::Arc;
5656
use crate::{
5757
db::HirDatabase,
5858
error_lifetime, fold_tys,
59+
generics::Generics,
5960
infer::{coerce::CoerceMany, unify::InferenceTable},
6061
lower::ImplTraitLoweringMode,
6162
to_assoc_type_id,
6263
traits::FnTrait,
63-
utils::{Generics, InTypeConstIdMetadata, UnevaluatedConstEvaluatorFolder},
64+
utils::{InTypeConstIdMetadata, UnevaluatedConstEvaluatorFolder},
6465
AliasEq, AliasTy, Binders, ClosureId, Const, DomainGoal, GenericArg, Goal, ImplTraitId,
6566
ImplTraitIdx, InEnvironment, Interner, Lifetime, OpaqueTyId, ProjectionTy, Substitution,
6667
TraitEnvironment, Ty, TyBuilder, TyExt,
@@ -633,7 +634,7 @@ impl<'a> InferenceContext<'a> {
633634
}
634635

635636
pub(crate) fn generics(&self) -> Option<Generics> {
636-
Some(crate::utils::generics(self.db.upcast(), self.resolver.generic_def()?))
637+
Some(crate::generics::generics(self.db.upcast(), self.resolver.generic_def()?))
637638
}
638639

639640
// FIXME: This function should be private in module. It is currently only used in the consteval, since we need
@@ -1263,7 +1264,7 @@ impl<'a> InferenceContext<'a> {
12631264
forbid_unresolved_segments((ty, Some(var.into())), unresolved)
12641265
}
12651266
TypeNs::SelfType(impl_id) => {
1266-
let generics = crate::utils::generics(self.db.upcast(), impl_id.into());
1267+
let generics = crate::generics::generics(self.db.upcast(), impl_id.into());
12671268
let substs = generics.placeholder_subst(self.db);
12681269
let mut ty = self.db.impl_self_ty(impl_id).substitute(Interner, &substs);
12691270

0 commit comments

Comments
 (0)