Skip to content

Commit 8f91999

Browse files
committed
fix: consider_late_bound field in Generics for RPITs
1 parent 1686871 commit 8f91999

14 files changed

Lines changed: 261 additions & 89 deletions

File tree

crates/hir-def/src/hir/generics.rs

Lines changed: 11 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,12 @@ pub enum LifetimeBoundType {
4343
LateBound,
4444
}
4545

46+
impl LifetimeParamData {
47+
pub fn is_late_bound(&self) -> bool {
48+
self.bound_type == LifetimeBoundType::LateBound
49+
}
50+
}
51+
4652
/// Data about a generic const parameter (to a function, struct, impl, ...).
4753
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
4854
pub struct ConstParamData {
@@ -306,10 +312,7 @@ impl GenericParams {
306312

307313
#[inline]
308314
pub fn len_late_bound_lifetimes(&self) -> usize {
309-
self.lifetimes
310-
.iter()
311-
.filter(|(_, p)| !p.is_opaque_captured && p.bound_type == LifetimeBoundType::LateBound)
312-
.count()
315+
self.lifetimes.iter().filter(|(_, p)| p.bound_type == LifetimeBoundType::LateBound).count()
313316
}
314317

315318
#[inline]
@@ -345,16 +348,14 @@ impl GenericParams {
345348
pub fn iter_lt(
346349
&self,
347350
) -> impl DoubleEndedIterator<Item = (LocalLifetimeParamId, &LifetimeParamData)> {
348-
self.iter_early_bound_lt().chain(self.iter_late_bound_lt())
351+
self.lifetimes.iter()
349352
}
350353

351354
#[inline]
352355
pub fn iter_early_bound_lt(
353356
&self,
354357
) -> impl DoubleEndedIterator<Item = (LocalLifetimeParamId, &LifetimeParamData)> {
355-
self.lifetimes
356-
.iter()
357-
.filter(|(_, p)| p.is_opaque_captured || p.bound_type == LifetimeBoundType::EarlyBound)
358+
self.lifetimes.iter().filter(|(_, p)| p.bound_type == LifetimeBoundType::EarlyBound)
358359
}
359360

360361
#[inline]
@@ -412,24 +413,18 @@ impl GenericParams {
412413
pub fn late_bound_lifetime_idx(
413414
&self,
414415
lifetime_param_id: &LocalLifetimeParamId,
415-
is_opaque_lowering: bool,
416416
) -> Option<usize> {
417417
self.iter_late_bound_lt().position(|(id, data)| {
418-
!(is_opaque_lowering && data.is_opaque_captured)
419-
&& data.bound_type == LifetimeBoundType::LateBound
420-
&& id == *lifetime_param_id
418+
data.bound_type == LifetimeBoundType::LateBound && id == *lifetime_param_id
421419
})
422420
}
423421

424422
pub fn early_bound_lifetime_idx(
425423
&self,
426424
lifetime_param_id: &LocalLifetimeParamId,
427-
is_opaque_lowering: bool,
428425
) -> Option<usize> {
429426
self.iter_early_bound_lt().position(|(id, data)| {
430-
((is_opaque_lowering && data.is_opaque_captured)
431-
|| data.bound_type == LifetimeBoundType::EarlyBound)
432-
&& id == *lifetime_param_id
427+
data.bound_type == LifetimeBoundType::EarlyBound && id == *lifetime_param_id
433428
})
434429
}
435430
}

crates/hir-ty/src/builtin_derive.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,14 +69,16 @@ pub(crate) fn generics_of<'db>(
6969
| BuiltinDeriveImplTrait::Ord
7070
| BuiltinDeriveImplTrait::PartialOrd
7171
| BuiltinDeriveImplTrait::Eq
72-
| BuiltinDeriveImplTrait::PartialEq => Generics::from_generic_def(db, loc.adt.into()),
72+
| BuiltinDeriveImplTrait::PartialEq => {
73+
Generics::from_generic_def(db, loc.adt.into(), false)
74+
}
7375
BuiltinDeriveImplTrait::CoerceUnsized | BuiltinDeriveImplTrait::DispatchFromDyn => {
7476
let trait_id = loc
7577
.trait_
7678
.get_id(interner.lang_items())
7779
.expect("we don't pass the impl to the solver if we can't resolve the trait");
78-
let additional_param = coerce_pointee_new_type_param(trait_id).into();
79-
Generics::from_generic_def_plus_one(db, loc.adt.into(), additional_param)
80+
let additional_param = coerce_pointee_new_type_param(trait_id);
81+
Generics::from_generic_def_plus_one(db, loc.adt.into(), additional_param, false)
8082
}
8183
}
8284
}

crates/hir-ty/src/generics.rs

Lines changed: 75 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,16 @@ impl<'db> SingleGenerics<'db> {
8383
.map(move |(local_id, data)| (LifetimeParamId { parent, local_id }, data))
8484
}
8585

86+
fn iter_late_bound_lifetimes(
87+
&self,
88+
consider_late_bound: bool,
89+
) -> impl Iterator<Item = (LifetimeParamId, &'db LifetimeParamData)> {
90+
let parent = self.def;
91+
self.params.iter_late_bound_lt().filter_map(move |(local_id, data)| {
92+
consider_late_bound.then_some((LifetimeParamId { parent, local_id }, data))
93+
})
94+
}
95+
8696
pub(crate) fn iter_type_or_consts(
8797
&self,
8898
) -> impl Iterator<Item = (TypeOrConstParamId, &'db TypeOrConstParamData)> {
@@ -118,23 +128,33 @@ impl<'db> SingleGenerics<'db> {
118128
(trait_self, iter)
119129
}
120130

121-
pub(crate) fn iter(&self) -> impl Iterator<Item = (GenericParamId, GenericParamDataRef<'db>)> {
122-
let lifetimes = self.iter_lifetimes().map(|(id, data)| {
131+
pub(crate) fn iter(
132+
&self,
133+
consider_late_bound: bool,
134+
) -> impl Iterator<Item = (GenericParamId, GenericParamDataRef<'db>)> {
135+
let lifetime_map = |(id, data)| {
123136
(GenericParamId::LifetimeParamId(id), GenericParamDataRef::LifetimeParamData(data))
124-
});
137+
};
138+
let lifetimes = self.iter_lifetimes().map(lifetime_map);
139+
let late_bound_lifetimes =
140+
self.iter_late_bound_lifetimes(consider_late_bound).map(lifetime_map);
141+
125142
let (trait_self, type_and_consts) = self.trait_self_and_others();
126-
trait_self.into_iter().chain(lifetimes).chain(type_and_consts)
143+
trait_self.into_iter().chain(lifetimes).chain(type_and_consts).chain(late_bound_lifetimes)
127144
}
128145

129146
pub(crate) fn iter_with_idx(
130147
&self,
131148
) -> impl Iterator<Item = (u32, GenericParamId, GenericParamDataRef<'db>)> {
132-
std::iter::zip(self.preceding_params_len.., self.iter())
149+
std::iter::zip(self.preceding_params_len.., self.iter(false))
133150
.map(|(index, (id, data))| (index, id, data))
134151
}
135152

136-
pub(crate) fn iter_id(&self) -> impl Iterator<Item = GenericParamId> {
137-
self.iter().map(|(id, _)| id)
153+
pub(crate) fn iter_id(
154+
&self,
155+
consider_late_bound: bool,
156+
) -> impl Iterator<Item = GenericParamId> {
157+
self.iter(consider_late_bound).map(|(id, _)| id)
138158
}
139159

140160
pub(crate) fn iter_late_bound(
@@ -149,6 +169,18 @@ impl<'db> SingleGenerics<'db> {
149169
)
150170
})
151171
}
172+
173+
pub(crate) fn type_or_const_param(&self, param_id: TypeParamId) -> GenericParamDataRef<'db> {
174+
let data = &self.params[param_id.local_id()];
175+
match data {
176+
TypeOrConstParamData::TypeParamData(type_param_data) => {
177+
GenericParamDataRef::TypeParamData(type_param_data)
178+
}
179+
TypeOrConstParamData::ConstParamData(const_param_data) => {
180+
GenericParamDataRef::ConstParamData(const_param_data)
181+
}
182+
}
183+
}
152184
}
153185

154186
impl<'db> Generics<'db> {
@@ -182,7 +214,7 @@ impl<'db> Generics<'db> {
182214
pub(crate) fn iter_self(
183215
&self,
184216
) -> impl Iterator<Item = (GenericParamId, GenericParamDataRef<'db>)> {
185-
self.owner().iter()
217+
self.owner().iter(false)
186218
}
187219

188220
pub(crate) fn iter_self_with_idx(
@@ -198,7 +230,7 @@ impl<'db> Generics<'db> {
198230
}
199231

200232
pub(crate) fn iter_parent_id(&self) -> impl Iterator<Item = GenericParamId> {
201-
self.parent().into_iter().flat_map(|parent| parent.iter_id())
233+
self.parent().into_iter().flat_map(move |parent| parent.iter_id(false))
202234
}
203235

204236
pub(crate) fn iter_self_type_or_consts(
@@ -208,13 +240,18 @@ impl<'db> Generics<'db> {
208240
}
209241

210242
/// Iterate over the parent params followed by self params.
211-
#[cfg(test)]
212-
pub(crate) fn iter(&self) -> impl Iterator<Item = (GenericParamId, GenericParamDataRef<'_>)> {
213-
self.iter_owners().flat_map(|owner| owner.iter())
243+
pub(crate) fn iter(
244+
&self,
245+
consider_late_bound: bool,
246+
) -> impl Iterator<Item = (GenericParamId, GenericParamDataRef<'db>)> {
247+
self.iter_owners().flat_map(move |owner| owner.iter(consider_late_bound))
214248
}
215249

216-
pub(crate) fn iter_id(&self) -> impl Iterator<Item = GenericParamId> {
217-
self.iter_owners().flat_map(|owner| owner.iter_id())
250+
pub(crate) fn iter_id(
251+
&self,
252+
consider_late_bound: bool,
253+
) -> impl Iterator<Item = GenericParamId> {
254+
self.iter_owners().flat_map(move |owner| owner.iter_id(consider_late_bound))
218255
}
219256

220257
/// Returns total number of generic parameters in scope, including those from parent.
@@ -298,16 +335,19 @@ impl<'db> Generics<'db> {
298335
pub(crate) fn lifetime_param_idx(
299336
&self,
300337
param: LifetimeParamId,
301-
is_opaque_lowering: bool,
338+
is_lowering_impl_trait_bounds: bool,
302339
) -> (u32, bool) {
303340
let owner = self.find_owner(param.parent);
304-
if let Some(late_bound_idx) =
305-
owner.params.late_bound_lifetime_idx(&param.local_id, is_opaque_lowering)
306-
{
341+
if is_lowering_impl_trait_bounds {
342+
let idx = self.opaque_lifetime_idx(param);
343+
return (owner.preceding_params_len + (idx as u32), false);
344+
}
345+
346+
if let Some(late_bound_idx) = owner.params.late_bound_lifetime_idx(&param.local_id) {
307347
return (late_bound_idx as u32, true);
308348
}
309349
let has_trait_self = matches!(owner.def, GenericDefId::TraitId(_));
310-
match owner.params.early_bound_lifetime_idx(&param.local_id, is_opaque_lowering) {
350+
match owner.params.early_bound_lifetime_idx(&param.local_id) {
311351
Some(idx) => {
312352
(owner.preceding_params_len + u32::from(has_trait_self) + (idx as u32), false)
313353
}
@@ -326,6 +366,22 @@ impl<'db> Generics<'db> {
326366
});
327367
Generics { chain }
328368
}
369+
370+
pub(crate) fn type_or_const_param(&self, param_id: TypeParamId) -> GenericParamDataRef<'db> {
371+
self.find_owner(param_id.parent()).type_or_const_param(param_id)
372+
}
373+
374+
fn opaque_lifetime_idx(&self, param: LifetimeParamId) -> usize {
375+
self.find_owner(param.parent)
376+
.iter_id(true)
377+
.position(|id| {
378+
let GenericParamId::LifetimeParamId(id) = id else {
379+
return false;
380+
};
381+
param == id
382+
})
383+
.unwrap()
384+
}
329385
}
330386

331387
pub(crate) struct ProvenanceSplit {

crates/hir-ty/src/infer/op.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -333,7 +333,7 @@ impl<'a, 'db> InferenceContext<'a, 'db> {
333333
let args = GenericArgs::for_item(
334334
self.interner(),
335335
trait_did.into(),
336-
|param_idx, param_id, _| match param_id {
336+
|param_idx, (param_id, _), _| match param_id {
337337
GenericParamId::LifetimeParamId(_) | GenericParamId::ConstParamId(_) => {
338338
unreachable!("did not expect operand trait to have lifetime/const args")
339339
}

crates/hir-ty/src/lower.rs

Lines changed: 53 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ use crate::{
6767
FnSigKind, FxIndexMap, GenericArg, GenericArgs, ParamConst, ParamEnv, Pattern, PolyFnSig,
6868
Predicate, Region, StoredClauses, StoredEarlyBinder, StoredGenericArg, StoredGenericArgs,
6969
StoredPolyFnSig, StoredTraitRef, StoredTy, TraitPredicate, TraitRef, Ty, Tys, Unnormalized,
70-
abi::Safety, util::BottomUpFolder,
70+
abi::Safety, mk_param, util::BottomUpFolder,
7171
},
7272
};
7373

@@ -220,6 +220,7 @@ pub struct TyLoweringContext<'db, 'a> {
220220
forbid_params_after_reason: ForbidParamsAfterReason,
221221
pub(crate) defined_anon_consts: ThinVec<AnonConstId>,
222222
infer_vars: Option<&'a mut dyn TyLoweringInferVarsCtx<'db>>,
223+
is_lowering_impl_trait_bounds: bool,
223224
bound_vars: Vec<BoundVarKinds<'db>>, // FIXME: HRTB and other for lifetime doesn't change it now
224225
lifetime_lowering_mode: LifetimeLoweringMode,
225226
}
@@ -259,6 +260,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
259260
forbid_params_after_reason: ForbidParamsAfterReason::AnonConst,
260261
defined_anon_consts: ThinVec::new(),
261262
infer_vars: None,
263+
is_lowering_impl_trait_bounds: false,
262264
bound_vars,
263265
lifetime_lowering_mode,
264266
}
@@ -585,8 +587,41 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
585587
});
586588
self.impl_trait_mode.opaque_type_data[idx] = actual_opaque_type_data;
587589

588-
let args =
589-
GenericArgs::identity_for_item(self.interner, opaque_ty_id.into());
590+
let mut late_bound_index = 0;
591+
let args = GenericArgs::for_item(
592+
self.interner,
593+
opaque_ty_id.into(),
594+
|index, param @ (id, data), _| {
595+
if let GenericParamDataRef::LifetimeParamData(lt) = data
596+
&& lt.is_late_bound()
597+
{
598+
let GenericParamId::LifetimeParamId(id) = id else {
599+
unreachable!()
600+
};
601+
let bound_region_kind =
602+
BoundRegionKind::Named(id.parent.into());
603+
let region = match self.lifetime_lowering_mode {
604+
LifetimeLoweringMode::Bound => Region::new_bound(
605+
interner,
606+
self.in_binders,
607+
BoundRegion {
608+
var: BoundVar::from_u32(late_bound_index),
609+
kind: bound_region_kind,
610+
},
611+
),
612+
LifetimeLoweringMode::LateParam => Region::new_late_param(
613+
interner,
614+
self.generic_def.into(),
615+
bound_region_kind,
616+
),
617+
};
618+
late_bound_index += 1;
619+
return region.into();
620+
}
621+
622+
mk_param(interner, index - late_bound_index, param)
623+
},
624+
);
590625
Ty::new_alias(
591626
self.interner,
592627
AliasTy::new_from_args(
@@ -819,7 +854,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
819854
Binder::bind_with_vars(
820855
rustc_type_ir::PredicateKind::Clause(
821856
rustc_type_ir::ClauseKind::Trait(TraitPredicate {
822-
trait_ref,
857+
trait_ref: trait_ref,
823858
polarity: rustc_type_ir::PredicatePolarity::Positive,
824859
}),
825860
),
@@ -1145,6 +1180,8 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
11451180
self.interner,
11461181
AliasTy::new_from_args(interner, rustc_type_ir::Opaque { def_id: def_id.into() }, args),
11471182
);
1183+
let prev_is_lowering_impl_trait_bounds =
1184+
mem::replace(&mut self.is_lowering_impl_trait_bounds, true);
11481185
let (predicates, assoc_ty_bounds_start) =
11491186
self.with_shifted_in(DebruijnIndex::from_u32(1), |ctx| {
11501187
let mut predicates = Vec::new();
@@ -1166,14 +1203,18 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
11661203
trait_id.into(),
11671204
GenericArgs::new_from_slice(&[self_ty.into()]),
11681205
);
1206+
let binder = BoundVarKinds::new_from_slice(ctx.bound_vars.last().unwrap());
11691207
Clause(Predicate::new(
11701208
interner,
1171-
Binder::dummy(rustc_type_ir::PredicateKind::Clause(
1172-
rustc_type_ir::ClauseKind::Trait(TraitPredicate {
1173-
trait_ref,
1174-
polarity: rustc_type_ir::PredicatePolarity::Positive,
1175-
}),
1176-
)),
1209+
Binder::bind_with_vars(
1210+
rustc_type_ir::PredicateKind::Clause(
1211+
rustc_type_ir::ClauseKind::Trait(TraitPredicate {
1212+
trait_ref,
1213+
polarity: rustc_type_ir::PredicatePolarity::Positive,
1214+
}),
1215+
),
1216+
binder,
1217+
),
11771218
))
11781219
});
11791220
predicates.extend(sized_clause);
@@ -1184,6 +1225,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
11841225
(predicates, assoc_ty_bounds_start)
11851226
});
11861227

1228+
self.is_lowering_impl_trait_bounds = prev_is_lowering_impl_trait_bounds;
11871229
ImplTrait {
11881230
predicates: Clauses::new_from_slice(&predicates).store(),
11891231
assoc_ty_bounds_start,
@@ -1195,10 +1237,8 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
11951237
Some(resolution) => match resolution {
11961238
LifetimeNs::Static => Region::new_static(self.interner),
11971239
LifetimeNs::LifetimeParam(id) => {
1198-
let is_opaque_lowering =
1199-
self.impl_trait_mode.mode == ImplTraitLoweringMode::Opaque;
12001240
let (idx, is_late_bound) =
1201-
self.generics().lifetime_param_idx(id, is_opaque_lowering);
1241+
self.generics().lifetime_param_idx(id, self.is_lowering_impl_trait_bounds);
12021242
self.region_param(id, idx, is_late_bound)
12031243
}
12041244
},

0 commit comments

Comments
 (0)