Skip to content

Commit c3e0b29

Browse files
committed
Point at fn bound that introduced lifetime obligation
``` error[E0597]: `c` does not live long enough --> $DIR/without-precise-captures-we-are-powerless.rs:19:20 | LL | fn simple<'a>(x: &'a i32) { | -- lifetime `'a` defined here ... LL | let c = async move || { println!("{}", *x); }; | - binding `c` declared here LL | outlives::<'a>(c()); | ---------------^--- | | | | | borrowed value does not live long enough | argument requires that `c` is borrowed for `'a` LL | outlives::<'a>(call_once(c)); LL | } | - `c` dropped here while still borrowed | note: requirement that `c` is borrowed for `'a` introduced here --> $DIR/without-precise-captures-we-are-powerless.rs:7:33 | LL | fn outlives<'a>(_: impl Sized + 'a) {} | ^^ ``` When encountering a `ConstraintCategory::Predicate` in a funtion call, point at the `Span` for that `Predicate` to explain where the lifetime obligation originates from.
1 parent 8d72d3e commit c3e0b29

15 files changed

+170
-24
lines changed

compiler/rustc_borrowck/src/borrowck_errors.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -426,7 +426,7 @@ impl<'infcx, 'tcx> crate::MirBorrowckCtxt<'_, 'infcx, 'tcx> {
426426
}
427427

428428
pub(crate) fn path_does_not_live_long_enough(&self, span: Span, path: &str) -> Diag<'infcx> {
429-
struct_span_code_err!(self.dcx(), span, E0597, "{} does not live long enough", path,)
429+
struct_span_code_err!(self.dcx(), span, E0597, "{} does not live long enough", path)
430430
}
431431

432432
pub(crate) fn cannot_return_reference_to_local(

compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3031,6 +3031,15 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
30313031

30323032
let mut err = self.path_does_not_live_long_enough(borrow_span, &name);
30333033

3034+
if let BorrowExplanation::MustBeValidFor { ref path, region_name, .. } = explanation {
3035+
for constraint in path {
3036+
if let ConstraintCategory::Predicate(pred) = constraint.category
3037+
&& !pred.is_dummy()
3038+
{
3039+
err.span_note(pred, format!("requirement that {name} is borrowed for `{region_name}` introduced here"));
3040+
}
3041+
}
3042+
}
30343043
if let Some(annotation) = self.annotate_argument_and_return_for_borrow(borrow) {
30353044
let region_name = annotation.emit(self, &mut err);
30363045

tests/ui/async-await/async-closures/without-precise-captures-we-are-powerless.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,4 +44,18 @@ fn through_field_and_ref_move<'a>(x: &S<'a>) {
4444
outlives::<'a>(call_once(c)); //~ ERROR explicit lifetime required in the type of `x`
4545
}
4646

47+
struct T;
48+
impl T {
49+
fn outlives<'a>(&'a self, _: impl Sized + 'a) {}
50+
}
51+
fn through_method<'a>(x: &'a i32) {
52+
let c = async || { println!("{}", *x); }; //~ ERROR `x` does not live long enough
53+
T.outlives::<'a>(c());
54+
T.outlives::<'a>(call_once(c));
55+
56+
let c = async move || { println!("{}", *x); };
57+
T.outlives::<'a>(c()); //~ ERROR `c` does not live long enough
58+
T.outlives::<'a>(call_once(c));
59+
}
60+
4761
fn main() {}

tests/ui/async-await/async-closures/without-precise-captures-we-are-powerless.stderr

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,12 @@ LL | outlives::<'a>(c());
2828
LL | outlives::<'a>(call_once(c));
2929
LL | }
3030
| - `c` dropped here while still borrowed
31+
|
32+
note: requirement that `c` is borrowed for `'a` introduced here
33+
--> $DIR/without-precise-captures-we-are-powerless.rs:7:33
34+
|
35+
LL | fn outlives<'a>(_: impl Sized + 'a) {}
36+
| ^^
3137

3238
error[E0597]: `x` does not live long enough
3339
--> $DIR/without-precise-captures-we-are-powerless.rs:26:13
@@ -73,6 +79,12 @@ LL | outlives::<'a>(c());
7379
LL | outlives::<'a>(call_once(c));
7480
LL | }
7581
| - `c` dropped here while still borrowed
82+
|
83+
note: requirement that `c` is borrowed for `'a` introduced here
84+
--> $DIR/without-precise-captures-we-are-powerless.rs:7:33
85+
|
86+
LL | fn outlives<'a>(_: impl Sized + 'a) {}
87+
| ^^
7688

7789
error[E0505]: cannot move out of `c` because it is borrowed
7890
--> $DIR/without-precise-captures-we-are-powerless.rs:32:30
@@ -129,6 +141,12 @@ LL | outlives::<'a>(c());
129141
LL | outlives::<'a>(call_once(c));
130142
LL | }
131143
| - `c` dropped here while still borrowed
144+
|
145+
note: requirement that `c` is borrowed for `'a` introduced here
146+
--> $DIR/without-precise-captures-we-are-powerless.rs:7:33
147+
|
148+
LL | fn outlives<'a>(_: impl Sized + 'a) {}
149+
| ^^
132150

133151
error[E0621]: explicit lifetime required in the type of `x`
134152
--> $DIR/without-precise-captures-we-are-powerless.rs:44:5
@@ -141,7 +159,44 @@ help: add explicit lifetime `'a` to the type of `x`
141159
LL | fn through_field_and_ref_move<'a>(x: &'a S<'a>) {
142160
| ++
143161

144-
error: aborting due to 10 previous errors
162+
error[E0597]: `x` does not live long enough
163+
--> $DIR/without-precise-captures-we-are-powerless.rs:52:13
164+
|
165+
LL | fn through_method<'a>(x: &'a i32) {
166+
| -- lifetime `'a` defined here
167+
LL | let c = async || { println!("{}", *x); };
168+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough
169+
LL | T.outlives::<'a>(c());
170+
LL | T.outlives::<'a>(call_once(c));
171+
| ------------------------------ argument requires that `x` is borrowed for `'a`
172+
...
173+
LL | }
174+
| - `x` dropped here while still borrowed
175+
176+
error[E0597]: `c` does not live long enough
177+
--> $DIR/without-precise-captures-we-are-powerless.rs:57:22
178+
|
179+
LL | fn through_method<'a>(x: &'a i32) {
180+
| -- lifetime `'a` defined here
181+
...
182+
LL | let c = async move || { println!("{}", *x); };
183+
| - binding `c` declared here
184+
LL | T.outlives::<'a>(c());
185+
| -----------------^---
186+
| | |
187+
| | borrowed value does not live long enough
188+
| argument requires that `c` is borrowed for `'a`
189+
LL | T.outlives::<'a>(call_once(c));
190+
LL | }
191+
| - `c` dropped here while still borrowed
192+
|
193+
note: requirement that `c` is borrowed for `'a` introduced here
194+
--> $DIR/without-precise-captures-we-are-powerless.rs:49:47
195+
|
196+
LL | fn outlives<'a>(&'a self, _: impl Sized + 'a) {}
197+
| ^^
198+
199+
error: aborting due to 12 previous errors
145200

146201
Some errors have detailed explanations: E0505, E0597, E0621.
147202
For more information about an error, try `rustc --explain E0505`.

tests/ui/borrowck/implementation-not-general-enough-ice-133252.stderr

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,12 @@ LL | force_send(async_load(&not_static));
2222
...
2323
LL | }
2424
| - `not_static` dropped here while still borrowed
25+
|
26+
note: requirement that `not_static` is borrowed for `'1` introduced here
27+
--> $DIR/implementation-not-general-enough-ice-133252.rs:16:18
28+
|
29+
LL | fn force_send<T: Send>(_: T) {}
30+
| ^^^^
2531

2632
error: aborting due to 2 previous errors
2733

tests/ui/impl-trait/precise-capturing/migration-note.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ fn needs_static() {
3232
//~| NOTE borrowed value does not live long enoug
3333

3434
fn needs_static(_: impl Sized + 'static) {}
35+
//~^ NOTE requirement that `x` is borrowed for `'static` introduced here
3536
needs_static(a);
3637
//~^ NOTE argument requires that `x` is borrowed for `'static`
3738
}
@@ -79,6 +80,7 @@ fn needs_static_mut() {
7980
//~| NOTE borrowed value does not live long enough
8081

8182
fn needs_static(_: impl Sized + 'static) {}
83+
//~^ NOTE requirement that `x` is borrowed for `'static` introduced here
8284
needs_static(a);
8385
//~^ NOTE argument requires that `x` is borrowed for `'static`
8486
}

tests/ui/impl-trait/precise-capturing/migration-note.stderr

Lines changed: 32 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0597]: `x` does not live long enough
2-
--> $DIR/migration-note.rs:182:17
2+
--> $DIR/migration-note.rs:184:17
33
|
44
LL | let x = vec![0];
55
| - binding `x` declared here
@@ -50,6 +50,11 @@ LL |
5050
LL | }
5151
| - `x` dropped here while still borrowed
5252
|
53+
note: requirement that `x` is borrowed for `'static` introduced here
54+
--> $DIR/migration-note.rs:34:37
55+
|
56+
LL | fn needs_static(_: impl Sized + 'static) {}
57+
| ^^^^^^^
5358
note: this call may capture more lifetimes than intended, because Rust 2024 has adjusted the `impl Trait` lifetime capture rules
5459
--> $DIR/migration-note.rs:29:13
5560
|
@@ -61,7 +66,7 @@ LL | fn display_len<T>(x: &Vec<T>) -> impl Display + use<T> {
6166
| ++++++++
6267

6368
error[E0505]: cannot move out of `x` because it is borrowed
64-
--> $DIR/migration-note.rs:48:8
69+
--> $DIR/migration-note.rs:49:8
6570
|
6671
LL | let x = vec![1];
6772
| - binding `x` declared here
@@ -76,7 +81,7 @@ LL | }
7681
| - borrow might be used here, when `a` is dropped and runs the destructor for type `impl std::fmt::Display`
7782
|
7883
note: this call may capture more lifetimes than intended, because Rust 2024 has adjusted the `impl Trait` lifetime capture rules
79-
--> $DIR/migration-note.rs:43:13
84+
--> $DIR/migration-note.rs:44:13
8085
|
8186
LL | let a = display_len(&x);
8287
| ^^^^^^^^^^^^^^^
@@ -90,7 +95,7 @@ LL | let a = display_len(&x.clone());
9095
| ++++++++
9196

9297
error[E0499]: cannot borrow `x` as mutable more than once at a time
93-
--> $DIR/migration-note.rs:66:5
98+
--> $DIR/migration-note.rs:67:5
9499
|
95100
LL | let a = display_len_mut(&mut x);
96101
| ------ first mutable borrow occurs here
@@ -102,7 +107,7 @@ LL | println!("{a}");
102107
| - first borrow later used here
103108
|
104109
note: this call may capture more lifetimes than intended, because Rust 2024 has adjusted the `impl Trait` lifetime capture rules
105-
--> $DIR/migration-note.rs:63:13
110+
--> $DIR/migration-note.rs:64:13
106111
|
107112
LL | let a = display_len_mut(&mut x);
108113
| ^^^^^^^^^^^^^^^^^^^^^^^
@@ -112,7 +117,7 @@ LL | fn display_len_mut<T>(x: &mut Vec<T>) -> impl Display + use<T> {
112117
| ++++++++
113118

114119
error[E0597]: `x` does not live long enough
115-
--> $DIR/migration-note.rs:76:29
120+
--> $DIR/migration-note.rs:77:29
116121
|
117122
LL | let mut x = vec![1];
118123
| ----- binding `x` declared here
@@ -126,8 +131,13 @@ LL |
126131
LL | }
127132
| - `x` dropped here while still borrowed
128133
|
134+
note: requirement that `x` is borrowed for `'static` introduced here
135+
--> $DIR/migration-note.rs:82:37
136+
|
137+
LL | fn needs_static(_: impl Sized + 'static) {}
138+
| ^^^^^^^
129139
note: this call may capture more lifetimes than intended, because Rust 2024 has adjusted the `impl Trait` lifetime capture rules
130-
--> $DIR/migration-note.rs:76:13
140+
--> $DIR/migration-note.rs:77:13
131141
|
132142
LL | let a = display_len_mut(&mut x);
133143
| ^^^^^^^^^^^^^^^^^^^^^^^
@@ -137,7 +147,7 @@ LL | fn display_len_mut<T>(x: &mut Vec<T>) -> impl Display + use<T> {
137147
| ++++++++
138148

139149
error[E0505]: cannot move out of `x` because it is borrowed
140-
--> $DIR/migration-note.rs:95:8
150+
--> $DIR/migration-note.rs:97:8
141151
|
142152
LL | let mut x = vec![1];
143153
| ----- binding `x` declared here
@@ -152,7 +162,7 @@ LL | }
152162
| - borrow might be used here, when `a` is dropped and runs the destructor for type `impl std::fmt::Display`
153163
|
154164
note: this call may capture more lifetimes than intended, because Rust 2024 has adjusted the `impl Trait` lifetime capture rules
155-
--> $DIR/migration-note.rs:90:13
165+
--> $DIR/migration-note.rs:92:13
156166
|
157167
LL | let a = display_len_mut(&mut x);
158168
| ^^^^^^^^^^^^^^^^^^^^^^^
@@ -166,7 +176,7 @@ LL | let a = display_len_mut(&mut x.clone());
166176
| ++++++++
167177

168178
error[E0506]: cannot assign to `s.f` because it is borrowed
169-
--> $DIR/migration-note.rs:115:5
179+
--> $DIR/migration-note.rs:117:5
170180
|
171181
LL | let a = display_field(&s.f);
172182
| ---- `s.f` is borrowed here
@@ -178,7 +188,7 @@ LL | println!("{a}");
178188
| - borrow later used here
179189
|
180190
note: this call may capture more lifetimes than intended, because Rust 2024 has adjusted the `impl Trait` lifetime capture rules
181-
--> $DIR/migration-note.rs:112:13
191+
--> $DIR/migration-note.rs:114:13
182192
|
183193
LL | let a = display_field(&s.f);
184194
| ^^^^^^^^^^^^^^^^^^^
@@ -188,7 +198,7 @@ LL | fn display_field<T: Copy + Display>(t: &T) -> impl Display + use<T> {
188198
| ++++++++
189199

190200
error[E0506]: cannot assign to `s.f` because it is borrowed
191-
--> $DIR/migration-note.rs:131:5
201+
--> $DIR/migration-note.rs:133:5
192202
|
193203
LL | let a = display_field(&mut s.f);
194204
| -------- `s.f` is borrowed here
@@ -200,7 +210,7 @@ LL | println!("{a}");
200210
| - borrow later used here
201211
|
202212
note: this call may capture more lifetimes than intended, because Rust 2024 has adjusted the `impl Trait` lifetime capture rules
203-
--> $DIR/migration-note.rs:128:13
213+
--> $DIR/migration-note.rs:130:13
204214
|
205215
LL | let a = display_field(&mut s.f);
206216
| ^^^^^^^^^^^^^^^^^^^^^^^
@@ -210,7 +220,7 @@ LL | fn display_field<T: Copy + Display>(t: &T) -> impl Display + use<T> {
210220
| ++++++++
211221

212222
error[E0503]: cannot use `s.f` because it was mutably borrowed
213-
--> $DIR/migration-note.rs:143:5
223+
--> $DIR/migration-note.rs:145:5
214224
|
215225
LL | let a = display_field(&mut s.f);
216226
| -------- `s.f` is borrowed here
@@ -222,7 +232,7 @@ LL | println!("{a}");
222232
| - borrow later used here
223233
|
224234
note: this call may capture more lifetimes than intended, because Rust 2024 has adjusted the `impl Trait` lifetime capture rules
225-
--> $DIR/migration-note.rs:140:13
235+
--> $DIR/migration-note.rs:142:13
226236
|
227237
LL | let a = display_field(&mut s.f);
228238
| ^^^^^^^^^^^^^^^^^^^^^^^
@@ -232,7 +242,7 @@ LL | fn display_field<T: Copy + Display>(t: &T) -> impl Display + use<T> {
232242
| ++++++++
233243

234244
error[E0597]: `z.f` does not live long enough
235-
--> $DIR/migration-note.rs:159:25
245+
--> $DIR/migration-note.rs:161:25
236246
|
237247
LL | let z = Z { f: vec![1] };
238248
| - binding `z` declared here
@@ -248,7 +258,7 @@ LL | }
248258
|
249259
= note: values in a scope are dropped in the opposite order they are defined
250260
note: this call may capture more lifetimes than intended, because Rust 2024 has adjusted the `impl Trait` lifetime capture rules
251-
--> $DIR/migration-note.rs:159:13
261+
--> $DIR/migration-note.rs:161:13
252262
|
253263
LL | x = display_len(&z.f);
254264
| ^^^^^^^^^^^^^^^^^
@@ -258,7 +268,7 @@ LL | fn display_len<T>(x: &Vec<T>) -> impl Display + use<T> {
258268
| ++++++++
259269

260270
error[E0716]: temporary value dropped while borrowed
261-
--> $DIR/migration-note.rs:170:40
271+
--> $DIR/migration-note.rs:172:40
262272
|
263273
LL | let x = { let x = display_len(&mut vec![0]); x };
264274
| ^^^^^^^ - - borrow later used here
@@ -268,7 +278,7 @@ LL | let x = { let x = display_len(&mut vec![0]); x };
268278
|
269279
= note: consider using a `let` binding to create a longer lived value
270280
note: this call may capture more lifetimes than intended, because Rust 2024 has adjusted the `impl Trait` lifetime capture rules
271-
--> $DIR/migration-note.rs:170:23
281+
--> $DIR/migration-note.rs:172:23
272282
|
273283
LL | let x = { let x = display_len(&mut vec![0]); x };
274284
| ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -279,7 +289,7 @@ LL | fn display_len<T>(x: &Vec<T>) -> impl Display + use<T> {
279289
| ++++++++
280290

281291
error[E0505]: cannot move out of `x` because it is borrowed
282-
--> $DIR/migration-note.rs:198:10
292+
--> $DIR/migration-note.rs:200:10
283293
|
284294
LL | let x = String::new();
285295
| - binding `x` declared here
@@ -294,12 +304,12 @@ LL | }
294304
| - borrow might be used here, when `y` is dropped and runs the destructor for type `impl Sized`
295305
|
296306
note: this call may capture more lifetimes than intended, because Rust 2024 has adjusted the `impl Trait` lifetime capture rules
297-
--> $DIR/migration-note.rs:195:13
307+
--> $DIR/migration-note.rs:197:13
298308
|
299309
LL | let y = capture_apit(&x);
300310
| ^^^^^^^^^^^^^^^^
301311
note: you could use a `use<...>` bound to explicitly specify captures, but argument-position `impl Trait`s are not nameable
302-
--> $DIR/migration-note.rs:189:21
312+
--> $DIR/migration-note.rs:191:21
303313
|
304314
LL | fn capture_apit(x: &impl Sized) -> impl Sized {}
305315
| ^^^^^^^^^^

tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,12 @@ LL | cell_x.set(cell_a.get()); // forces 'a: 'x, implies 'a = 'static ->
6969
LL | })
7070
LL | }
7171
| - `a` dropped here while still borrowed
72+
|
73+
note: requirement that `a` is borrowed for `'static` introduced here
74+
--> $DIR/propagate-approximated-shorter-to-static-comparing-against-free.rs:13:8
75+
|
76+
LL | F: for<'x> FnOnce(Cell<&'a u32>, Cell<&'x u32>),
77+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
7278

7379
error: aborting due to 2 previous errors
7480

tests/ui/nll/closure-requirements/propagate-multiple-requirements.stderr

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,12 @@ LL | z = &local_arr;
1313
...
1414
LL | }
1515
| - `local_arr` dropped here while still borrowed
16+
|
17+
note: requirement that `local_arr` is borrowed for `'static` introduced here
18+
--> $DIR/propagate-multiple-requirements.rs:4:21
19+
|
20+
LL | fn once<S, T, U, F: FnOnce(S, T) -> U>(f: F, s: S, t: T) -> U {
21+
| ^^^^^^^^^^^^^^^^^
1622

1723
error: aborting due to 1 previous error
1824

0 commit comments

Comments
 (0)