Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions compiler/rustc_borrowck/src/borrowck_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -426,7 +426,7 @@ impl<'infcx, 'tcx> crate::MirBorrowckCtxt<'_, 'infcx, 'tcx> {
}

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

pub(crate) fn cannot_return_reference_to_local(
Expand Down Expand Up @@ -480,7 +480,7 @@ impl<'infcx, 'tcx> crate::MirBorrowckCtxt<'_, 'infcx, 'tcx> {
}

pub(crate) fn temporary_value_borrowed_for_too_long(&self, span: Span) -> Diag<'infcx> {
struct_span_code_err!(self.dcx(), span, E0716, "temporary value dropped while borrowed",)
struct_span_code_err!(self.dcx(), span, E0716, "temporary value dropped while borrowed")
}
}

Expand Down
8 changes: 1 addition & 7 deletions compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2992,6 +2992,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
self.buffer_error(err);
}

#[tracing::instrument(level = "debug", skip(self, explanation))]
fn report_local_value_does_not_live_long_enough(
&self,
location: Location,
Expand All @@ -3001,13 +3002,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
borrow_spans: UseSpans<'tcx>,
explanation: BorrowExplanation<'tcx>,
) -> Diag<'infcx> {
debug!(
"report_local_value_does_not_live_long_enough(\
{:?}, {:?}, {:?}, {:?}, {:?}\
)",
location, name, borrow, drop_span, borrow_spans
);

let borrow_span = borrow_spans.var_or_use_path_span();
if let BorrowExplanation::MustBeValidFor {
category,
Expand Down
20 changes: 20 additions & 0 deletions compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,26 @@ impl<'tcx> BorrowExplanation<'tcx> {
{
self.add_object_lifetime_default_note(tcx, err, unsize_ty);
}

let mut preds = path
.iter()
.filter_map(|constraint| match constraint.category {
ConstraintCategory::Predicate(pred) if !pred.is_dummy() => Some(pred),
_ => None,
})
.collect::<Vec<Span>>();
preds.sort();
preds.dedup();
if !preds.is_empty() {
let s = if preds.len() == 1 { "" } else { "s" };
err.span_note(
preds,
format!(
"requirement{s} that the value outlives `{region_name}` introduced here"
),
);
}

self.add_lifetime_bound_suggestion_to_diagnostic(err, &category, span, region_name);
}
_ => {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,18 @@ fn through_field_and_ref_move<'a>(x: &S<'a>) {
outlives::<'a>(call_once(c)); //~ ERROR explicit lifetime required in the type of `x`
}

struct T;
impl T {
fn outlives<'a>(&'a self, _: impl Sized + 'a) {}
}
fn through_method<'a>(x: &'a i32) {
let c = async || { println!("{}", *x); }; //~ ERROR `x` does not live long enough
T.outlives::<'a>(c());
T.outlives::<'a>(call_once(c));

let c = async move || { println!("{}", *x); };
T.outlives::<'a>(c()); //~ ERROR `c` does not live long enough
T.outlives::<'a>(call_once(c));
}

fn main() {}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@ LL | outlives::<'a>(c());
LL | outlives::<'a>(call_once(c));
LL | }
| - `c` dropped here while still borrowed
|
note: requirement that the value outlives `'a` introduced here
--> $DIR/without-precise-captures-we-are-powerless.rs:7:33
|
LL | fn outlives<'a>(_: impl Sized + 'a) {}
| ^^

error[E0597]: `x` does not live long enough
--> $DIR/without-precise-captures-we-are-powerless.rs:26:13
Expand Down Expand Up @@ -73,6 +79,12 @@ LL | outlives::<'a>(c());
LL | outlives::<'a>(call_once(c));
LL | }
| - `c` dropped here while still borrowed
|
note: requirement that the value outlives `'a` introduced here
--> $DIR/without-precise-captures-we-are-powerless.rs:7:33
|
LL | fn outlives<'a>(_: impl Sized + 'a) {}
| ^^

error[E0505]: cannot move out of `c` because it is borrowed
--> $DIR/without-precise-captures-we-are-powerless.rs:32:30
Expand All @@ -89,6 +101,12 @@ LL | outlives::<'a>(c());
| argument requires that `c` is borrowed for `'a`
LL | outlives::<'a>(call_once(c));
| ^ move out of `c` occurs here
|
note: requirement that the value outlives `'a` introduced here
--> $DIR/without-precise-captures-we-are-powerless.rs:7:33
|
LL | fn outlives<'a>(_: impl Sized + 'a) {}
| ^^

error[E0597]: `x` does not live long enough
--> $DIR/without-precise-captures-we-are-powerless.rs:36:13
Expand Down Expand Up @@ -129,6 +147,12 @@ LL | outlives::<'a>(c());
LL | outlives::<'a>(call_once(c));
LL | }
| - `c` dropped here while still borrowed
|
note: requirement that the value outlives `'a` introduced here
--> $DIR/without-precise-captures-we-are-powerless.rs:7:33
|
LL | fn outlives<'a>(_: impl Sized + 'a) {}
| ^^

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

error: aborting due to 10 previous errors
error[E0597]: `x` does not live long enough
--> $DIR/without-precise-captures-we-are-powerless.rs:52:13
|
LL | fn through_method<'a>(x: &'a i32) {
| -- lifetime `'a` defined here
LL | let c = async || { println!("{}", *x); };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough
LL | T.outlives::<'a>(c());
LL | T.outlives::<'a>(call_once(c));
| ------------------------------ argument requires that `x` is borrowed for `'a`
...
LL | }
| - `x` dropped here while still borrowed

error[E0597]: `c` does not live long enough
--> $DIR/without-precise-captures-we-are-powerless.rs:57:22
|
LL | fn through_method<'a>(x: &'a i32) {
| -- lifetime `'a` defined here
...
LL | let c = async move || { println!("{}", *x); };
| - binding `c` declared here
LL | T.outlives::<'a>(c());
| -----------------^---
| | |
| | borrowed value does not live long enough
| argument requires that `c` is borrowed for `'a`
LL | T.outlives::<'a>(call_once(c));
LL | }
| - `c` dropped here while still borrowed
|
note: requirement that the value outlives `'a` introduced here
--> $DIR/without-precise-captures-we-are-powerless.rs:49:47
|
LL | fn outlives<'a>(&'a self, _: impl Sized + 'a) {}
| ^^

error: aborting due to 12 previous errors

Some errors have detailed explanations: E0505, E0597, E0621.
For more information about an error, try `rustc --explain E0505`.
12 changes: 12 additions & 0 deletions tests/ui/borrowck/fn-item-check-type-params.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@ LL | want(&String::new(), extend_lt);
| | |
| | creates a temporary value which is freed while still in use
| argument requires that borrow lasts for `'static`
|
note: requirement that the value outlives `'static` introduced here
--> $DIR/fn-item-check-type-params.rs:47:33
|
LL | fn want<I, O>(_: I, _: impl Fn(I) -> O) {}
| ^^^^^^^^^^

error[E0716]: temporary value dropped while borrowed
--> $DIR/fn-item-check-type-params.rs:54:26
Expand All @@ -36,6 +42,12 @@ LL | let val = extend_lt(&String::from("blah blah blah"));
| | |
| | creates a temporary value which is freed while still in use
| argument requires that borrow lasts for `'static`
|
note: requirement that the value outlives `'static` introduced here
--> $DIR/fn-item-check-type-params.rs:22:21
|
LL | (T, Option<U>): Displayable,
| ^^^^^^^^^^^

error: aborting due to 4 previous errors

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@ LL | force_send(async_load(&not_static));
...
LL | }
| - `not_static` dropped here while still borrowed
|
note: requirement that the value outlives `'1` introduced here
--> $DIR/implementation-not-general-enough-ice-133252.rs:16:18
|
LL | fn force_send<T: Send>(_: T) {}
| ^^^^

error: aborting due to 2 previous errors

Expand Down
3 changes: 3 additions & 0 deletions tests/ui/borrowck/issue-17545.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ LL | | ));
| | -- temporary value is freed at the end of this statement
| |______|
| argument requires that borrow lasts for `'a`
|
note: requirement that the value outlives `'a` introduced here
--> $SRC_DIR/core/src/ops/function.rs:LL:COL
Copy link
Contributor

@lcnr lcnr Sep 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how come this doesn't actually show the predicate which caused this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

because the span is in std, which don't get displayed when the sources aren't found (like when path remap is being used, which is done for all tests).


error: aborting due to 1 previous error

Expand Down
5 changes: 5 additions & 0 deletions tests/ui/generic-associated-types/bugs/hrtb-implied-1.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ note: due to a current limitation of the type system, this implies a `'static` l
|
LL | for<'a> I::Item<'a>: Debug,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
note: requirement that the value outlives `'static` introduced here
--> $DIR/hrtb-implied-1.rs:26:26
|
LL | for<'a> I::Item<'a>: Debug,
| ^^^^^

error: aborting due to 1 previous error

Expand Down
2 changes: 2 additions & 0 deletions tests/ui/impl-trait/precise-capturing/migration-note.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ fn needs_static() {
//~| NOTE borrowed value does not live long enoug

fn needs_static(_: impl Sized + 'static) {}
//~^ NOTE requirement that the value outlives `'static` introduced here
needs_static(a);
//~^ NOTE argument requires that `x` is borrowed for `'static`
}
Expand Down Expand Up @@ -79,6 +80,7 @@ fn needs_static_mut() {
//~| NOTE borrowed value does not live long enough

fn needs_static(_: impl Sized + 'static) {}
//~^ NOTE requirement that the value outlives `'static` introduced here
needs_static(a);
//~^ NOTE argument requires that `x` is borrowed for `'static`
}
Expand Down
Loading
Loading