Skip to content

Commit 7febdbd

Browse files
committed
fix: early/late bound idx and opaque captured lifetimes
1 parent f96a4af commit 7febdbd

6 files changed

Lines changed: 73 additions & 16 deletions

File tree

crates/hir-def/src/expr_store/lower.rs

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -559,13 +559,15 @@ pub struct NamedLifetimeStore {
559559
lifetimes_in_where_clause: FxIndexSet<Name>,
560560
lifetimes_constraint_by_input: FxIndexSet<Name>,
561561
lifetimes_in_output: FxIndexSet<Name>,
562+
opaque_captured_lifetimes: FxIndexSet<Name>,
562563
}
563564

564565
#[derive(Debug)]
565566
enum LifetimeBoundScope {
566567
Argument,
567568
Return,
568569
WhereClause,
570+
ImplTrait(bool),
569571
}
570572

571573
impl NamedLifetimeStore {
@@ -574,13 +576,23 @@ impl NamedLifetimeStore {
574576
pub(crate) fn push_named_lifetime(&mut self, lifetime: Name) {
575577
match self.lifetime_bound_scope {
576578
Some(LifetimeBoundScope::Argument) => {
577-
self.lifetimes_constraint_by_input.insert(lifetime)
579+
self.lifetimes_constraint_by_input.insert(lifetime);
580+
}
581+
Some(LifetimeBoundScope::Return) => {
582+
self.lifetimes_in_output.insert(lifetime);
578583
}
579-
Some(LifetimeBoundScope::Return) => self.lifetimes_in_output.insert(lifetime),
580584
Some(LifetimeBoundScope::WhereClause) => {
581-
self.lifetimes_in_where_clause.insert(lifetime)
585+
self.lifetimes_in_where_clause.insert(lifetime);
586+
}
587+
Some(LifetimeBoundScope::ImplTrait(is_argument_scope)) => {
588+
if is_argument_scope {
589+
self.lifetimes_in_where_clause.insert(lifetime);
590+
} else {
591+
self.opaque_captured_lifetimes.insert(lifetime.clone());
592+
self.lifetimes_in_output.insert(lifetime);
593+
}
582594
}
583-
_ => false,
595+
_ => (),
584596
};
585597
}
586598
}
@@ -751,8 +763,16 @@ impl<'db> ExprCollector<'db> {
751763
TypeRef::Error
752764
} else {
753765
return self.with_outer_impl_trait_scope(true, |this| {
754-
let type_bounds =
755-
this.type_bounds_from_ast(inner.type_bound_list(), impl_trait_lower_fn);
766+
let is_argument_lt_bound_scope = this.is_argument_lt_bound_scope();
767+
let type_bounds = this.with_lifetime_bound_scope(
768+
LifetimeBoundScope::ImplTrait(is_argument_lt_bound_scope),
769+
|this| {
770+
this.type_bounds_from_ast(
771+
inner.type_bound_list(),
772+
impl_trait_lower_fn,
773+
)
774+
},
775+
);
756776
impl_trait_lower_fn(this, AstPtr::new(&node), type_bounds)
757777
});
758778
}

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ impl GenericParamsCollector {
143143
let param = LifetimeParamData {
144144
name: name.clone(),
145145
bound_type: LifetimeBoundType::EarlyBound,
146+
is_opaque_captured: false,
146147
};
147148
let _idx = self.lifetimes.alloc(param);
148149
ec.with_lifetime_bound_scope(LifetimeBoundScope::WhereClause, |ec| {
@@ -291,6 +292,10 @@ impl GenericParamsCollector {
291292
) {
292293
for (_param_id, lifetime) in self.lifetimes.iter_mut() {
293294
let lifetime_name = &lifetime.name;
295+
if named_lifetime_store.opaque_captured_lifetimes.contains(lifetime_name) {
296+
lifetime.is_opaque_captured = true;
297+
}
298+
294299
if named_lifetime_store.lifetimes_in_where_clause.contains(lifetime_name) {
295300
continue;
296301
}

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

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ pub struct TypeParamData {
3434
pub struct LifetimeParamData {
3535
pub name: Name,
3636
pub bound_type: LifetimeBoundType,
37+
pub is_opaque_captured: bool,
3738
}
3839

3940
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
@@ -348,7 +349,9 @@ impl GenericParams {
348349
pub fn iter_early_bound_lt(
349350
&self,
350351
) -> impl DoubleEndedIterator<Item = (LocalLifetimeParamId, &LifetimeParamData)> {
351-
self.lifetimes.iter().filter(|(_, p)| p.bound_type == LifetimeBoundType::EarlyBound)
352+
self.lifetimes
353+
.iter()
354+
.filter(|(_, p)| p.is_opaque_captured || p.bound_type == LifetimeBoundType::EarlyBound)
352355
}
353356

354357
#[inline]
@@ -411,4 +414,13 @@ impl GenericParams {
411414
data.bound_type == LifetimeBoundType::LateBound && id == *lifetime_param_id
412415
})
413416
}
417+
418+
pub fn early_bound_lifetime_idx(
419+
&self,
420+
lifetime_param_id: &LocalLifetimeParamId,
421+
) -> Option<usize> {
422+
self.iter_early_bound_lt().position(|(id, data)| {
423+
data.bound_type == LifetimeBoundType::EarlyBound && id == *lifetime_param_id
424+
})
425+
}
414426
}

crates/hir-ty/src/generics.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -301,12 +301,12 @@ impl<'db> Generics<'db> {
301301
return (late_bound_idx as u32, true);
302302
}
303303
let has_trait_self = matches!(owner.def, GenericDefId::TraitId(_));
304-
(
305-
owner.preceding_params_len
306-
+ u32::from(has_trait_self)
307-
+ param.local_id.into_raw().into_u32(),
308-
false,
309-
)
304+
match owner.params.early_bound_lifetime_idx(&param.local_id) {
305+
Some(idx) => {
306+
(owner.preceding_params_len + u32::from(has_trait_self) + (idx as u32), false)
307+
}
308+
_ => unreachable!(),
309+
}
310310
}
311311

312312
#[deprecated = "don't use this; it's easy to expose an erroneous `Generics` with this"]

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

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,7 @@ impl<'db> InferenceContext<'_, 'db> {
304304
};
305305

306306
// Now go through the argument patterns
307-
for (arg_pat, arg_ty) in args.iter().zip(bound_sig.skip_binder().inputs()) {
307+
for (arg_pat, arg_ty) in args.iter().zip(liberated_sig.inputs()) {
308308
self.infer_top_pat(*arg_pat, *arg_ty, PatOrigin::Param);
309309
}
310310

@@ -1148,8 +1148,9 @@ impl<'db> InferenceContext<'_, 'db> {
11481148
}
11491149

11501150
fn closure_sigs(&self, bound_sig: PolyFnSig<'db>) -> ClosureSignatures<'db> {
1151-
let liberated_sig = bound_sig.skip_binder();
1152-
// FIXME: When we lower HRTB we'll need to actually liberate regions here.
1151+
// TODO: def id needs to be changed?
1152+
let liberated_sig =
1153+
self.interner().liberate_late_bound_regions(self.owner.into(), bound_sig);
11531154
ClosureSignatures { bound_sig, liberated_sig }
11541155
}
11551156
}

crates/hir-ty/src/tests/simple.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4305,3 +4305,22 @@ enum Enum {
43054305
"#]],
43064306
);
43074307
}
4308+
4309+
#[test]
4310+
fn rpit_with_lifetimes() {
4311+
check_infer(
4312+
r#"
4313+
struct Event<'a> {};
4314+
struct Range<T> {}
4315+
trait Iterator {
4316+
type Item;
4317+
}
4318+
4319+
struct Vec<T> {}
4320+
4321+
fn foo<'e>(events: &'e mut dyn Iterator<Item = (Event<'e>, Range<usize>)>) -> impl Iterator<Item = Event<'e>> {
4322+
4323+
}"#,
4324+
expect![[r#""#]],
4325+
);
4326+
}

0 commit comments

Comments
 (0)