Skip to content

Commit 3075f03

Browse files
committed
Resolve lifetimes using the regular logic for RPIT.
1 parent 44c10e4 commit 3075f03

11 files changed

+238
-62
lines changed

compiler/rustc_hir_analysis/src/collect/lifetimes.rs

+36-37
Original file line numberDiff line numberDiff line change
@@ -452,7 +452,9 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
452452
intravisit::walk_item(this, item)
453453
});
454454
}
455-
hir::ItemKind::OpaqueTy(hir::OpaqueTy { .. }) => {
455+
hir::ItemKind::OpaqueTy(hir::OpaqueTy {
456+
origin: hir::OpaqueTyOrigin::TyAlias, ..
457+
}) => {
456458
// Opaque types are visited when we visit the
457459
// `TyKind::OpaqueDef`, so that they have the lifetimes from
458460
// their parent opaque_ty in scope.
@@ -478,6 +480,37 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
478480
});
479481
}
480482
}
483+
hir::ItemKind::OpaqueTy(hir::OpaqueTy {
484+
origin: hir::OpaqueTyOrigin::FnReturn(_) | hir::OpaqueTyOrigin::AsyncFn(_),
485+
generics,
486+
..
487+
}) => {
488+
// We want to start our early-bound indices at the end of the parent scope,
489+
// not including any parent `impl Trait`s.
490+
let mut lifetimes = FxIndexMap::default();
491+
debug!(?generics.params);
492+
for param in generics.params {
493+
match param.kind {
494+
GenericParamKind::Lifetime { .. } => {
495+
let (def_id, reg) = Region::early(self.tcx.hir(), &param);
496+
lifetimes.insert(def_id, reg);
497+
}
498+
GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => {}
499+
}
500+
}
501+
502+
let scope = Scope::Binder {
503+
hir_id: item.hir_id(),
504+
lifetimes,
505+
s: self.scope,
506+
scope_type: BinderScopeType::Normal,
507+
where_bound_origin: None,
508+
};
509+
self.with(scope, |this| {
510+
let scope = Scope::TraitRefBoundary { s: this.scope };
511+
this.with(scope, |this| intravisit::walk_item(this, item))
512+
});
513+
}
481514
hir::ItemKind::TyAlias(_, ref generics)
482515
| hir::ItemKind::Enum(_, ref generics)
483516
| hir::ItemKind::Struct(_, ref generics)
@@ -604,7 +637,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
604637
// ^ ^ this gets resolved in the scope of
605638
// the opaque_ty generics
606639
let opaque_ty = self.tcx.hir().item(item_id);
607-
let (generics, bounds) = match opaque_ty.kind {
640+
match opaque_ty.kind {
608641
hir::ItemKind::OpaqueTy(hir::OpaqueTy {
609642
origin: hir::OpaqueTyOrigin::TyAlias,
610643
..
@@ -625,10 +658,8 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
625658
}
626659
hir::ItemKind::OpaqueTy(hir::OpaqueTy {
627660
origin: hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..),
628-
ref generics,
629-
bounds,
630661
..
631-
}) => (generics, bounds),
662+
}) => {}
632663
ref i => bug!("`impl Trait` pointed to non-opaque type?? {:#?}", i),
633664
};
634665

@@ -681,38 +712,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
681712
self.uninsert_lifetime_on_error(lifetime, def.unwrap());
682713
}
683714
}
684-
685-
// We want to start our early-bound indices at the end of the parent scope,
686-
// not including any parent `impl Trait`s.
687-
let mut lifetimes = FxIndexMap::default();
688-
debug!(?generics.params);
689-
for param in generics.params {
690-
match param.kind {
691-
GenericParamKind::Lifetime { .. } => {
692-
let (def_id, reg) = Region::early(self.tcx.hir(), &param);
693-
lifetimes.insert(def_id, reg);
694-
}
695-
GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => {}
696-
}
697-
}
698-
self.record_late_bound_vars(ty.hir_id, vec![]);
699-
700-
let scope = Scope::Binder {
701-
hir_id: ty.hir_id,
702-
lifetimes,
703-
s: self.scope,
704-
scope_type: BinderScopeType::Normal,
705-
where_bound_origin: None,
706-
};
707-
self.with(scope, |this| {
708-
let scope = Scope::TraitRefBoundary { s: this.scope };
709-
this.with(scope, |this| {
710-
this.visit_generics(generics);
711-
for bound in bounds {
712-
this.visit_param_bound(bound);
713-
}
714-
})
715-
});
716715
}
717716
_ => intravisit::walk_ty(self, ty),
718717
}

src/test/ui/impl-trait/impl-fn-hrtb-bounds.rs

+3
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,19 @@ use std::fmt::Debug;
44
fn a() -> impl Fn(&u8) -> (impl Debug + '_) {
55
//~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet
66
|x| x
7+
//~^ ERROR lifetime may not live long enough
78
}
89

910
fn b() -> impl for<'a> Fn(&'a u8) -> (impl Debug + 'a) {
1011
//~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet
1112
|x| x
13+
//~^ ERROR lifetime may not live long enough
1214
}
1315

1416
fn c() -> impl for<'a> Fn(&'a u8) -> (impl Debug + '_) {
1517
//~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet
1618
|x| x
19+
//~^ ERROR lifetime may not live long enough
1720
}
1821

1922
fn d() -> impl Fn() -> (impl Debug + '_) {

src/test/ui/impl-trait/impl-fn-hrtb-bounds.stderr

+33-6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0106]: missing lifetime specifier
2-
--> $DIR/impl-fn-hrtb-bounds.rs:19:38
2+
--> $DIR/impl-fn-hrtb-bounds.rs:22:38
33
|
44
LL | fn d() -> impl Fn() -> (impl Debug + '_) {
55
| ^^ expected named lifetime parameter
@@ -22,30 +22,57 @@ note: lifetime declared here
2222
LL | fn a() -> impl Fn(&u8) -> (impl Debug + '_) {
2323
| ^
2424

25+
error: lifetime may not live long enough
26+
--> $DIR/impl-fn-hrtb-bounds.rs:6:9
27+
|
28+
LL | |x| x
29+
| -- ^ returning this value requires that `'1` must outlive `'2`
30+
| ||
31+
| |return type of closure is impl Debug + '2
32+
| has type `&'1 u8`
33+
2534
error: higher kinded lifetime bounds on nested opaque types are not supported yet
26-
--> $DIR/impl-fn-hrtb-bounds.rs:9:52
35+
--> $DIR/impl-fn-hrtb-bounds.rs:10:52
2736
|
2837
LL | fn b() -> impl for<'a> Fn(&'a u8) -> (impl Debug + 'a) {
2938
| ^^
3039
|
3140
note: lifetime declared here
32-
--> $DIR/impl-fn-hrtb-bounds.rs:9:20
41+
--> $DIR/impl-fn-hrtb-bounds.rs:10:20
3342
|
3443
LL | fn b() -> impl for<'a> Fn(&'a u8) -> (impl Debug + 'a) {
3544
| ^^
3645

46+
error: lifetime may not live long enough
47+
--> $DIR/impl-fn-hrtb-bounds.rs:12:9
48+
|
49+
LL | |x| x
50+
| -- ^ returning this value requires that `'1` must outlive `'2`
51+
| ||
52+
| |return type of closure is impl Debug + '2
53+
| has type `&'1 u8`
54+
3755
error: higher kinded lifetime bounds on nested opaque types are not supported yet
38-
--> $DIR/impl-fn-hrtb-bounds.rs:14:52
56+
--> $DIR/impl-fn-hrtb-bounds.rs:16:52
3957
|
4058
LL | fn c() -> impl for<'a> Fn(&'a u8) -> (impl Debug + '_) {
4159
| ^^
4260
|
4361
note: lifetime declared here
44-
--> $DIR/impl-fn-hrtb-bounds.rs:14:20
62+
--> $DIR/impl-fn-hrtb-bounds.rs:16:20
4563
|
4664
LL | fn c() -> impl for<'a> Fn(&'a u8) -> (impl Debug + '_) {
4765
| ^^
4866

49-
error: aborting due to 4 previous errors
67+
error: lifetime may not live long enough
68+
--> $DIR/impl-fn-hrtb-bounds.rs:18:9
69+
|
70+
LL | |x| x
71+
| -- ^ returning this value requires that `'1` must outlive `'2`
72+
| ||
73+
| |return type of closure is impl Debug + '2
74+
| has type `&'1 u8`
75+
76+
error: aborting due to 7 previous errors
5077

5178
For more information about this error, try `rustc --explain E0106`.

src/test/ui/impl-trait/impl-fn-parsing-ambiguities.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@ use std::fmt::Debug;
33

44
fn a() -> impl Fn(&u8) -> impl Debug + '_ {
55
//~^ ERROR ambiguous `+` in a type
6-
//~^^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet
6+
//~| ERROR higher kinded lifetime bounds on nested opaque types are not supported yet
77
|x| x
8+
//~^ ERROR lifetime may not live long enough
89
}
910

1011
fn b() -> impl Fn() -> impl Debug + Send {

src/test/ui/impl-trait/impl-fn-parsing-ambiguities.stderr

+11-2
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ LL | fn a() -> impl Fn(&u8) -> impl Debug + '_ {
55
| ^^^^^^^^^^^^^^^ help: use parentheses to disambiguate: `(impl Debug + '_)`
66

77
error: ambiguous `+` in a type
8-
--> $DIR/impl-fn-parsing-ambiguities.rs:10:24
8+
--> $DIR/impl-fn-parsing-ambiguities.rs:11:24
99
|
1010
LL | fn b() -> impl Fn() -> impl Debug + Send {
1111
| ^^^^^^^^^^^^^^^^^ help: use parentheses to disambiguate: `(impl Debug + Send)`
@@ -22,5 +22,14 @@ note: lifetime declared here
2222
LL | fn a() -> impl Fn(&u8) -> impl Debug + '_ {
2323
| ^
2424

25-
error: aborting due to 3 previous errors
25+
error: lifetime may not live long enough
26+
--> $DIR/impl-fn-parsing-ambiguities.rs:7:9
27+
|
28+
LL | |x| x
29+
| -- ^ returning this value requires that `'1` must outlive `'2`
30+
| ||
31+
| |return type of closure is impl Debug + '2
32+
| has type `&'1 u8`
33+
34+
error: aborting due to 4 previous errors
2635

src/test/ui/impl-trait/issues/issue-67830.rs

+2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ struct A;
2121
fn test() -> impl for<'a> MyFn<&'a A, Output=impl Iterator + 'a> {
2222
//~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet
2323
Wrap(|a| Some(a).into_iter())
24+
//~^ ERROR implementation of `FnOnce` is not general enough
25+
//~| ERROR implementation of `FnOnce` is not general enough
2426
}
2527

2628
fn main() {}

src/test/ui/impl-trait/issues/issue-67830.stderr

+19-1
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,23 @@ note: lifetime declared here
1010
LL | fn test() -> impl for<'a> MyFn<&'a A, Output=impl Iterator + 'a> {
1111
| ^^
1212

13-
error: aborting due to previous error
13+
error: implementation of `FnOnce` is not general enough
14+
--> $DIR/issue-67830.rs:23:5
15+
|
16+
LL | Wrap(|a| Some(a).into_iter())
17+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough
18+
|
19+
= note: closure with signature `fn(&'2 A) -> std::option::IntoIter<&A>` must implement `FnOnce<(&'1 A,)>`, for any lifetime `'1`...
20+
= note: ...but it actually implements `FnOnce<(&'2 A,)>`, for some specific lifetime `'2`
21+
22+
error: implementation of `FnOnce` is not general enough
23+
--> $DIR/issue-67830.rs:23:5
24+
|
25+
LL | Wrap(|a| Some(a).into_iter())
26+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough
27+
|
28+
= note: closure with signature `fn(&'2 A) -> std::option::IntoIter<&A>` must implement `FnOnce<(&'1 A,)>`, for any lifetime `'1`...
29+
= note: ...but it actually implements `FnOnce<(&'2 A,)>`, for some specific lifetime `'2`
30+
31+
error: aborting due to 3 previous errors
1432

src/test/ui/impl-trait/issues/issue-88236-2.rs

+5
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,16 @@ fn make_impl() -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {}
1818
fn make_weird_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {
1919
//~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet
2020
&()
21+
//~^ ERROR implementation of `Hrtb` is not general enough
22+
//~| ERROR implementation of `Hrtb` is not general enough
2123
}
2224

2325
fn make_bad_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {
2426
//~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet
2527
x
28+
//~^ ERROR implementation of `Hrtb` is not general enough
29+
//~| ERROR implementation of `Hrtb` is not general enough
30+
//~| ERROR lifetime may not live long enough
2631
}
2732

2833
fn main() {}

src/test/ui/impl-trait/issues/issue-88236-2.stderr

+57-3
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,71 @@ note: lifetime declared here
2222
LL | fn make_weird_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {
2323
| ^^
2424

25+
error: implementation of `Hrtb` is not general enough
26+
--> $DIR/issue-88236-2.rs:20:5
27+
|
28+
LL | &()
29+
| ^^^ implementation of `Hrtb` is not general enough
30+
|
31+
= note: `Hrtb<'0>` would have to be implemented for the type `&()`, for any lifetime `'0`...
32+
= note: ...but `Hrtb<'1>` is actually implemented for the type `&'1 ()`, for some specific lifetime `'1`
33+
34+
error: implementation of `Hrtb` is not general enough
35+
--> $DIR/issue-88236-2.rs:20:5
36+
|
37+
LL | &()
38+
| ^^^ implementation of `Hrtb` is not general enough
39+
|
40+
= note: `Hrtb<'0>` would have to be implemented for the type `&()`, for any lifetime `'0`...
41+
= note: ...but `Hrtb<'1>` is actually implemented for the type `&'1 ()`, for some specific lifetime `'1`
42+
2543
error: higher kinded lifetime bounds on nested opaque types are not supported yet
26-
--> $DIR/issue-88236-2.rs:23:78
44+
--> $DIR/issue-88236-2.rs:25:78
2745
|
2846
LL | fn make_bad_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {
2947
| ^^
3048
|
3149
note: lifetime declared here
32-
--> $DIR/issue-88236-2.rs:23:45
50+
--> $DIR/issue-88236-2.rs:25:45
3351
|
3452
LL | fn make_bad_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {
3553
| ^^
3654

37-
error: aborting due to 3 previous errors
55+
error: lifetime may not live long enough
56+
--> $DIR/issue-88236-2.rs:27:5
57+
|
58+
LL | fn make_bad_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {
59+
| -- lifetime `'b` defined here
60+
LL |
61+
LL | x
62+
| ^ returning this value requires that `'b` must outlive `'static`
63+
|
64+
help: to declare that `impl for<'a> Hrtb<'a, Assoc = impl Send + 'static>` captures data from argument `x`, you can add an explicit `'b` lifetime bound
65+
|
66+
LL | fn make_bad_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> + 'b {
67+
| ++++
68+
help: to declare that `impl Send + 'a` captures data from argument `x`, you can add an explicit `'b` lifetime bound
69+
|
70+
LL | fn make_bad_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a + 'b> {
71+
| ++++
72+
73+
error: implementation of `Hrtb` is not general enough
74+
--> $DIR/issue-88236-2.rs:27:5
75+
|
76+
LL | x
77+
| ^ implementation of `Hrtb` is not general enough
78+
|
79+
= note: `Hrtb<'0>` would have to be implemented for the type `&()`, for any lifetime `'0`...
80+
= note: ...but `Hrtb<'1>` is actually implemented for the type `&'1 ()`, for some specific lifetime `'1`
81+
82+
error: implementation of `Hrtb` is not general enough
83+
--> $DIR/issue-88236-2.rs:27:5
84+
|
85+
LL | x
86+
| ^ implementation of `Hrtb` is not general enough
87+
|
88+
= note: `Hrtb<'0>` would have to be implemented for the type `&()`, for any lifetime `'0`...
89+
= note: ...but `Hrtb<'1>` is actually implemented for the type `&'1 ()`, for some specific lifetime `'1`
90+
91+
error: aborting due to 8 previous errors
3892

0 commit comments

Comments
 (0)