Skip to content

Commit e65790b

Browse files
committed
Auto merge of rust-lang#117967 - adetaylor:fix-lifetime-elision-bug, r=<try>
Fix lifetime elision ```rust struct Concrete(u32); impl Concrete { fn m(self: &Box<Self>) -> &u32 { &self.0 } } ``` resulted in a confusing error. ```rust impl Concrete { fn n(self: &Box<&Self>) -> &u32 { &self.0 } } ``` resulted in no error or warning, despite apparent ambiguity over the elided lifetime. Fixes rust-lang#117715
2 parents ae9d24d + c46b820 commit e65790b

13 files changed

+445
-17
lines changed

compiler/rustc_resolve/src/late.rs

+18-10
Original file line numberDiff line numberDiff line change
@@ -2105,13 +2105,17 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
21052105
// Handle `self` specially.
21062106
if index == 0 && has_self {
21072107
let self_lifetime = self.find_lifetime_for_self(ty);
2108-
if let Set1::One(lifetime) = self_lifetime {
2108+
elision_lifetime = match self_lifetime {
21092109
// We found `self` elision.
2110-
elision_lifetime = Elision::Self_(lifetime);
2111-
} else {
2110+
Set1::One(lifetime) => Elision::Self_(lifetime),
2111+
// `self` itself had ambiguous lifetimes, e.g.
2112+
// &Box<&Self>. In this case we won't consider
2113+
// taking an alternative parameter lifetime; just avoid elision
2114+
// entirely.
2115+
Set1::Many => Elision::Err,
21122116
// We do not have `self` elision: disregard the `Elision::Param` that we may
21132117
// have found.
2114-
elision_lifetime = Elision::None;
2118+
Set1::Empty => Elision::None,
21152119
}
21162120
}
21172121
debug!("(resolving function / closure) recorded parameter");
@@ -2135,6 +2139,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
21352139
r: &'r Resolver<'a, 'tcx>,
21362140
impl_self: Option<Res>,
21372141
lifetime: Set1<LifetimeRes>,
2142+
self_found: bool,
21382143
}
21392144

21402145
impl SelfVisitor<'_, '_, '_> {
@@ -2158,9 +2163,11 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
21582163
impl<'a> Visitor<'a> for SelfVisitor<'_, '_, '_> {
21592164
fn visit_ty(&mut self, ty: &'a Ty) {
21602165
trace!("SelfVisitor considering ty={:?}", ty);
2161-
if let TyKind::Ref(lt, ref mt) = ty.kind
2162-
&& self.is_self_ty(&mt.ty)
2163-
{
2166+
if self.is_self_ty(ty) {
2167+
trace!("SelfVisitor found Self");
2168+
self.self_found = true;
2169+
}
2170+
if let TyKind::Ref(lt, _) = ty.kind {
21642171
let lt_id = if let Some(lt) = lt {
21652172
lt.id
21662173
} else {
@@ -2201,10 +2208,11 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
22012208
Res::Def(DefKind::Struct | DefKind::Union | DefKind::Enum, _,) | Res::PrimTy(_)
22022209
)
22032210
});
2204-
let mut visitor = SelfVisitor { r: self.r, impl_self, lifetime: Set1::Empty };
2211+
let mut visitor =
2212+
SelfVisitor { r: self.r, impl_self, lifetime: Set1::Empty, self_found: false };
22052213
visitor.visit_ty(ty);
2206-
trace!("SelfVisitor found={:?}", visitor.lifetime);
2207-
visitor.lifetime
2214+
trace!("SelfVisitor found={:?}, self_found={:?}", visitor.lifetime, visitor.self_found);
2215+
if visitor.self_found { visitor.lifetime } else { Set1::Empty }
22082216
}
22092217

22102218
/// Searches the current set of local scopes for labels. Returns the `NodeId` of the resolved

tests/ui/self/elision/multiple-ref-self-async.rs

+10-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
// check-pass
21
// edition:2018
32

43
#![feature(arbitrary_self_types)]
@@ -21,23 +20,33 @@ impl Struct {
2120
// Test using multiple `&Self`:
2221

2322
async fn wrap_ref_Self_ref_Self(self: Wrap<&Self, &Self>, f: &u8) -> &u8 {
23+
//~^ ERROR missing lifetime specifier
2424
f
25+
//~^ ERROR lifetime may not live long enough
2526
}
2627

2728
async fn box_wrap_ref_Self_ref_Self(self: Box<Wrap<&Self, &Self>>, f: &u32) -> &u32 {
29+
//~^ ERROR missing lifetime specifier
2830
f
31+
//~^ ERROR lifetime may not live long enough
2932
}
3033

3134
async fn pin_wrap_ref_Self_ref_Self(self: Pin<Wrap<&Self, &Self>>, f: &u32) -> &u32 {
35+
//~^ ERROR missing lifetime specifier
3236
f
37+
//~^ ERROR lifetime may not live long enough
3338
}
3439

3540
async fn box_box_wrap_ref_Self_ref_Self(self: Box<Box<Wrap<&Self, &Self>>>, f: &u32) -> &u32 {
41+
//~^ ERROR missing lifetime specifier
3642
f
43+
//~^ ERROR lifetime may not live long enough
3744
}
3845

3946
async fn box_pin_wrap_ref_Self_ref_Self(self: Box<Pin<Wrap<&Self, &Self>>>, f: &u32) -> &u32 {
47+
//~^ ERROR missing lifetime specifier
4048
f
49+
//~^ ERROR lifetime may not live long enough
4150
}
4251
}
4352

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
error[E0106]: missing lifetime specifier
2+
--> $DIR/multiple-ref-self-async.rs:22:74
3+
|
4+
LL | async fn wrap_ref_Self_ref_Self(self: Wrap<&Self, &Self>, f: &u8) -> &u8 {
5+
| ------------------ --- ^ expected named lifetime parameter
6+
|
7+
= help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from one of `self`'s 2 lifetimes or `f`
8+
help: consider introducing a named lifetime parameter
9+
|
10+
LL | async fn wrap_ref_Self_ref_Self<'a>(self: Wrap<&'a Self, &'a Self>, f: &'a u8) -> &'a u8 {
11+
| ++++ ++ ++ ++ ++
12+
13+
error[E0106]: missing lifetime specifier
14+
--> $DIR/multiple-ref-self-async.rs:28:84
15+
|
16+
LL | async fn box_wrap_ref_Self_ref_Self(self: Box<Wrap<&Self, &Self>>, f: &u32) -> &u32 {
17+
| ----------------------- ---- ^ expected named lifetime parameter
18+
|
19+
= help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from one of `self`'s 2 lifetimes or `f`
20+
help: consider introducing a named lifetime parameter
21+
|
22+
LL | async fn box_wrap_ref_Self_ref_Self<'a>(self: Box<Wrap<&'a Self, &'a Self>>, f: &'a u32) -> &'a u32 {
23+
| ++++ ++ ++ ++ ++
24+
25+
error[E0106]: missing lifetime specifier
26+
--> $DIR/multiple-ref-self-async.rs:34:84
27+
|
28+
LL | async fn pin_wrap_ref_Self_ref_Self(self: Pin<Wrap<&Self, &Self>>, f: &u32) -> &u32 {
29+
| ----------------------- ---- ^ expected named lifetime parameter
30+
|
31+
= help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from one of `self`'s 2 lifetimes or `f`
32+
help: consider introducing a named lifetime parameter
33+
|
34+
LL | async fn pin_wrap_ref_Self_ref_Self<'a>(self: Pin<Wrap<&'a Self, &'a Self>>, f: &'a u32) -> &'a u32 {
35+
| ++++ ++ ++ ++ ++
36+
37+
error[E0106]: missing lifetime specifier
38+
--> $DIR/multiple-ref-self-async.rs:40:93
39+
|
40+
LL | async fn box_box_wrap_ref_Self_ref_Self(self: Box<Box<Wrap<&Self, &Self>>>, f: &u32) -> &u32 {
41+
| ---------------------------- ---- ^ expected named lifetime parameter
42+
|
43+
= help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from one of `self`'s 2 lifetimes or `f`
44+
help: consider introducing a named lifetime parameter
45+
|
46+
LL | async fn box_box_wrap_ref_Self_ref_Self<'a>(self: Box<Box<Wrap<&'a Self, &'a Self>>>, f: &'a u32) -> &'a u32 {
47+
| ++++ ++ ++ ++ ++
48+
49+
error[E0106]: missing lifetime specifier
50+
--> $DIR/multiple-ref-self-async.rs:46:93
51+
|
52+
LL | async fn box_pin_wrap_ref_Self_ref_Self(self: Box<Pin<Wrap<&Self, &Self>>>, f: &u32) -> &u32 {
53+
| ---------------------------- ---- ^ expected named lifetime parameter
54+
|
55+
= help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from one of `self`'s 2 lifetimes or `f`
56+
help: consider introducing a named lifetime parameter
57+
|
58+
LL | async fn box_pin_wrap_ref_Self_ref_Self<'a>(self: Box<Pin<Wrap<&'a Self, &'a Self>>>, f: &'a u32) -> &'a u32 {
59+
| ++++ ++ ++ ++ ++
60+
61+
error: lifetime may not live long enough
62+
--> $DIR/multiple-ref-self-async.rs:24:9
63+
|
64+
LL | async fn wrap_ref_Self_ref_Self(self: Wrap<&Self, &Self>, f: &u8) -> &u8 {
65+
| - let's call the lifetime of this reference `'1`
66+
LL |
67+
LL | f
68+
| ^ returning this value requires that `'1` must outlive `'static`
69+
70+
error: lifetime may not live long enough
71+
--> $DIR/multiple-ref-self-async.rs:30:9
72+
|
73+
LL | async fn box_wrap_ref_Self_ref_Self(self: Box<Wrap<&Self, &Self>>, f: &u32) -> &u32 {
74+
| - let's call the lifetime of this reference `'1`
75+
LL |
76+
LL | f
77+
| ^ returning this value requires that `'1` must outlive `'static`
78+
79+
error: lifetime may not live long enough
80+
--> $DIR/multiple-ref-self-async.rs:36:9
81+
|
82+
LL | async fn pin_wrap_ref_Self_ref_Self(self: Pin<Wrap<&Self, &Self>>, f: &u32) -> &u32 {
83+
| - let's call the lifetime of this reference `'1`
84+
LL |
85+
LL | f
86+
| ^ returning this value requires that `'1` must outlive `'static`
87+
88+
error: lifetime may not live long enough
89+
--> $DIR/multiple-ref-self-async.rs:42:9
90+
|
91+
LL | async fn box_box_wrap_ref_Self_ref_Self(self: Box<Box<Wrap<&Self, &Self>>>, f: &u32) -> &u32 {
92+
| - let's call the lifetime of this reference `'1`
93+
LL |
94+
LL | f
95+
| ^ returning this value requires that `'1` must outlive `'static`
96+
97+
error: lifetime may not live long enough
98+
--> $DIR/multiple-ref-self-async.rs:48:9
99+
|
100+
LL | async fn box_pin_wrap_ref_Self_ref_Self(self: Box<Pin<Wrap<&Self, &Self>>>, f: &u32) -> &u32 {
101+
| - let's call the lifetime of this reference `'1`
102+
LL |
103+
LL | f
104+
| ^ returning this value requires that `'1` must outlive `'static`
105+
106+
error: aborting due to 10 previous errors
107+
108+
For more information about this error, try `rustc --explain E0106`.

tests/ui/self/elision/multiple-ref-self.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
// check-pass
2-
31
#![feature(arbitrary_self_types)]
42
#![allow(non_snake_case)]
53

@@ -20,22 +18,27 @@ impl Struct {
2018
// Test using multiple `&Self`:
2119

2220
fn wrap_ref_Self_ref_Self(self: Wrap<&Self, &Self>, f: &u8) -> &u8 {
21+
//~^ ERROR missing lifetime specifier
2322
f
2423
}
2524

2625
fn box_wrap_ref_Self_ref_Self(self: Box<Wrap<&Self, &Self>>, f: &u32) -> &u32 {
26+
//~^ ERROR missing lifetime specifier
2727
f
2828
}
2929

3030
fn pin_wrap_ref_Self_ref_Self(self: Pin<Wrap<&Self, &Self>>, f: &u32) -> &u32 {
31+
//~^ ERROR missing lifetime specifier
3132
f
3233
}
3334

3435
fn box_box_wrap_ref_Self_ref_Self(self: Box<Box<Wrap<&Self, &Self>>>, f: &u32) -> &u32 {
36+
//~^ ERROR missing lifetime specifier
3537
f
3638
}
3739

3840
fn box_pin_wrap_ref_Self_ref_Self(self: Box<Pin<Wrap<&Self, &Self>>>, f: &u32) -> &u32 {
41+
//~^ ERROR missing lifetime specifier
3942
f
4043
}
4144
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
error[E0106]: missing lifetime specifier
2+
--> $DIR/multiple-ref-self.rs:20:68
3+
|
4+
LL | fn wrap_ref_Self_ref_Self(self: Wrap<&Self, &Self>, f: &u8) -> &u8 {
5+
| ------------------ --- ^ expected named lifetime parameter
6+
|
7+
= help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from one of `self`'s 2 lifetimes or `f`
8+
help: consider introducing a named lifetime parameter
9+
|
10+
LL | fn wrap_ref_Self_ref_Self<'a>(self: Wrap<&'a Self, &'a Self>, f: &'a u8) -> &'a u8 {
11+
| ++++ ++ ++ ++ ++
12+
13+
error[E0106]: missing lifetime specifier
14+
--> $DIR/multiple-ref-self.rs:25:78
15+
|
16+
LL | fn box_wrap_ref_Self_ref_Self(self: Box<Wrap<&Self, &Self>>, f: &u32) -> &u32 {
17+
| ----------------------- ---- ^ expected named lifetime parameter
18+
|
19+
= help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from one of `self`'s 2 lifetimes or `f`
20+
help: consider introducing a named lifetime parameter
21+
|
22+
LL | fn box_wrap_ref_Self_ref_Self<'a>(self: Box<Wrap<&'a Self, &'a Self>>, f: &'a u32) -> &'a u32 {
23+
| ++++ ++ ++ ++ ++
24+
25+
error[E0106]: missing lifetime specifier
26+
--> $DIR/multiple-ref-self.rs:30:78
27+
|
28+
LL | fn pin_wrap_ref_Self_ref_Self(self: Pin<Wrap<&Self, &Self>>, f: &u32) -> &u32 {
29+
| ----------------------- ---- ^ expected named lifetime parameter
30+
|
31+
= help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from one of `self`'s 2 lifetimes or `f`
32+
help: consider introducing a named lifetime parameter
33+
|
34+
LL | fn pin_wrap_ref_Self_ref_Self<'a>(self: Pin<Wrap<&'a Self, &'a Self>>, f: &'a u32) -> &'a u32 {
35+
| ++++ ++ ++ ++ ++
36+
37+
error[E0106]: missing lifetime specifier
38+
--> $DIR/multiple-ref-self.rs:35:87
39+
|
40+
LL | fn box_box_wrap_ref_Self_ref_Self(self: Box<Box<Wrap<&Self, &Self>>>, f: &u32) -> &u32 {
41+
| ---------------------------- ---- ^ expected named lifetime parameter
42+
|
43+
= help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from one of `self`'s 2 lifetimes or `f`
44+
help: consider introducing a named lifetime parameter
45+
|
46+
LL | fn box_box_wrap_ref_Self_ref_Self<'a>(self: Box<Box<Wrap<&'a Self, &'a Self>>>, f: &'a u32) -> &'a u32 {
47+
| ++++ ++ ++ ++ ++
48+
49+
error[E0106]: missing lifetime specifier
50+
--> $DIR/multiple-ref-self.rs:40:87
51+
|
52+
LL | fn box_pin_wrap_ref_Self_ref_Self(self: Box<Pin<Wrap<&Self, &Self>>>, f: &u32) -> &u32 {
53+
| ---------------------------- ---- ^ expected named lifetime parameter
54+
|
55+
= help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from one of `self`'s 2 lifetimes or `f`
56+
help: consider introducing a named lifetime parameter
57+
|
58+
LL | fn box_pin_wrap_ref_Self_ref_Self<'a>(self: Box<Pin<Wrap<&'a Self, &'a Self>>>, f: &'a u32) -> &'a u32 {
59+
| ++++ ++ ++ ++ ++
60+
61+
error: aborting due to 5 previous errors
62+
63+
For more information about this error, try `rustc --explain E0106`.

tests/ui/self/elision/ref-assoc-async.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
// edition:2018
2-
// check-pass
32

43
#![allow(non_snake_case)]
54

@@ -18,22 +17,27 @@ impl Trait for Struct {
1817
impl Struct {
1918
async fn ref_AssocType(self: &<Struct as Trait>::AssocType, f: &u32) -> &u32 {
2019
f
20+
//~^ ERROR lifetime may not live long enough
2121
}
2222

2323
async fn box_ref_AssocType(self: Box<&<Struct as Trait>::AssocType>, f: &u32) -> &u32 {
2424
f
25+
//~^ ERROR lifetime may not live long enough
2526
}
2627

2728
async fn pin_ref_AssocType(self: Pin<&<Struct as Trait>::AssocType>, f: &u32) -> &u32 {
2829
f
30+
//~^ ERROR lifetime may not live long enough
2931
}
3032

3133
async fn box_box_ref_AssocType(self: Box<Box<&<Struct as Trait>::AssocType>>, f: &u32) -> &u32 {
3234
f
35+
//~^ ERROR lifetime may not live long enough
3336
}
3437

3538
async fn box_pin_ref_AssocType(self: Box<Pin<&<Struct as Trait>::AssocType>>, f: &u32) -> &u32 {
3639
f
40+
//~^ ERROR lifetime may not live long enough
3741
}
3842
}
3943

0 commit comments

Comments
 (0)