Skip to content

Commit

Permalink
best_blame_constraint: add a special case to recover object lifetim…
Browse files Browse the repository at this point in the history
…e default notes
  • Loading branch information
dianne committed Dec 14, 2024
1 parent 59512d7 commit ff793a7
Show file tree
Hide file tree
Showing 6 changed files with 51 additions and 38 deletions.
22 changes: 21 additions & 1 deletion compiler/rustc_borrowck/src/region_infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1940,7 +1940,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
target_test: impl Fn(RegionVid) -> bool,
) -> (BlameConstraint<'tcx>, Vec<OutlivesConstraint<'tcx>>) {
// Find all paths
let (path, _) =
let (path, target_region) =
self.find_constraint_paths_between_regions(from_region, target_test).unwrap();
debug!(
"path={:#?}",
Expand Down Expand Up @@ -2060,6 +2060,26 @@ impl<'tcx> RegionInferenceContext<'tcx> {
}
}

Some(_)
if target_region == self.universal_regions().fr_static
&& let Some(old_best) = path.iter().min_by_key(|p| p.category)
&& matches!(old_best.category, ConstraintCategory::Cast {
is_implicit_coercion: true,
unsize_to: Some(_)
}) =>
{
// FIXME(dianne): This is a hack in order to emit the subdiagnostic
// `BorrowExplanation::add_object_lifetime_default_note` more often, e.g. on
// `tests/ui/traits/trait-object-lifetime-default-note.rs`. The subdiagnostic
// depends on a coercion being blamed, so we fall back to an earlier version of this
// function's blaming logic to keep the test result the same. A proper fix will
// require rewriting the subdiagnostic not to rely on a coercion being blamed.
// For examples of where notes are missing, see #131008 and
// `tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs`.
// As part of fixing those, this case should be removed.
*old_best
}

Some(i) => path[i],

None => {
Expand Down
42 changes: 19 additions & 23 deletions tests/ui/dropck/dropck_trait_cycle_checked.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,87 +2,83 @@ error[E0597]: `o2` does not live long enough
--> $DIR/dropck_trait_cycle_checked.rs:111:13
|
LL | let (o1, o2, o3): (Box<dyn Obj>, Box<dyn Obj>, Box<dyn Obj>) = (O::new(), O::new(), O::new());
| -- binding `o2` declared here
| -- binding `o2` declared here -------- coercion requires that `o2` is borrowed for `'static`
LL | o1.set0(&o2);
| ^^^ borrowed value does not live long enough
...
LL | o3.set0(&o1);
| ------------ argument requires that `o2` is borrowed for `'static`
LL | o3.set1(&o2);
LL | }
| - `o2` dropped here while still borrowed
|
= note: due to object lifetime defaults, `Box<dyn Obj<'_>>` actually means `Box<(dyn Obj<'_> + 'static)>`

error[E0597]: `o3` does not live long enough
--> $DIR/dropck_trait_cycle_checked.rs:112:13
|
LL | let (o1, o2, o3): (Box<dyn Obj>, Box<dyn Obj>, Box<dyn Obj>) = (O::new(), O::new(), O::new());
| -- binding `o3` declared here
| -- binding `o3` declared here -------- coercion requires that `o3` is borrowed for `'static`
LL | o1.set0(&o2);
LL | o1.set1(&o3);
| ^^^ borrowed value does not live long enough
...
LL | o3.set0(&o1);
| ------------ argument requires that `o3` is borrowed for `'static`
LL | o3.set1(&o2);
LL | }
| - `o3` dropped here while still borrowed
|
= note: due to object lifetime defaults, `Box<dyn Obj<'_>>` actually means `Box<(dyn Obj<'_> + 'static)>`

error[E0597]: `o2` does not live long enough
--> $DIR/dropck_trait_cycle_checked.rs:113:13
|
LL | let (o1, o2, o3): (Box<dyn Obj>, Box<dyn Obj>, Box<dyn Obj>) = (O::new(), O::new(), O::new());
| -- binding `o2` declared here
LL | o1.set0(&o2);
| ------------ argument requires that `o2` is borrowed for `'static`
LL | o1.set1(&o3);
| -- binding `o2` declared here -------- coercion requires that `o2` is borrowed for `'static`
...
LL | o2.set0(&o2);
| ^^^ borrowed value does not live long enough
...
LL | }
| - `o2` dropped here while still borrowed
|
= note: due to object lifetime defaults, `Box<dyn Obj<'_>>` actually means `Box<(dyn Obj<'_> + 'static)>`

error[E0597]: `o3` does not live long enough
--> $DIR/dropck_trait_cycle_checked.rs:114:13
|
LL | let (o1, o2, o3): (Box<dyn Obj>, Box<dyn Obj>, Box<dyn Obj>) = (O::new(), O::new(), O::new());
| -- binding `o3` declared here
LL | o1.set0(&o2);
| ------------ argument requires that `o3` is borrowed for `'static`
| -- binding `o3` declared here -------- coercion requires that `o3` is borrowed for `'static`
...
LL | o2.set1(&o3);
| ^^^ borrowed value does not live long enough
...
LL | }
| - `o3` dropped here while still borrowed
|
= note: due to object lifetime defaults, `Box<dyn Obj<'_>>` actually means `Box<(dyn Obj<'_> + 'static)>`

error[E0597]: `o1` does not live long enough
--> $DIR/dropck_trait_cycle_checked.rs:115:13
|
LL | let (o1, o2, o3): (Box<dyn Obj>, Box<dyn Obj>, Box<dyn Obj>) = (O::new(), O::new(), O::new());
| -- binding `o1` declared here
LL | o1.set0(&o2);
LL | o1.set1(&o3);
| ------------ argument requires that `o1` is borrowed for `'static`
| -- binding `o1` declared here -------- coercion requires that `o1` is borrowed for `'static`
...
LL | o3.set0(&o1);
| ^^^ borrowed value does not live long enough
LL | o3.set1(&o2);
LL | }
| - `o1` dropped here while still borrowed
|
= note: due to object lifetime defaults, `Box<dyn Obj<'_>>` actually means `Box<(dyn Obj<'_> + 'static)>`

error[E0597]: `o2` does not live long enough
--> $DIR/dropck_trait_cycle_checked.rs:116:13
|
LL | let (o1, o2, o3): (Box<dyn Obj>, Box<dyn Obj>, Box<dyn Obj>) = (O::new(), O::new(), O::new());
| -- binding `o2` declared here
LL | o1.set0(&o2);
LL | o1.set1(&o3);
| ------------ argument requires that `o2` is borrowed for `'static`
| -- binding `o2` declared here -------- coercion requires that `o2` is borrowed for `'static`
...
LL | o3.set1(&o2);
| ^^^ borrowed value does not live long enough
LL | }
| - `o2` dropped here while still borrowed
|
= note: due to object lifetime defaults, `Box<dyn Obj<'_>>` actually means `Box<(dyn Obj<'_> + 'static)>`

error: aborting due to 6 previous errors

Expand Down
2 changes: 1 addition & 1 deletion tests/ui/nll/issue-54779-anon-static-lifetime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ impl DebugWith<dyn DebugContext> for Foo {
fmt: &mut std::fmt::Formatter<'_>,
) -> std::fmt::Result {
let Foo { bar } = self;
bar.debug_with(cx); //~ ERROR borrowed data escapes outside of method [E0521]
bar.debug_with(cx); //~ lifetime may not live long enough
Ok(())
}
}
Expand Down
14 changes: 4 additions & 10 deletions tests/ui/nll/issue-54779-anon-static-lifetime.stderr
Original file line number Diff line number Diff line change
@@ -1,17 +1,11 @@
error[E0521]: borrowed data escapes outside of method
--> $DIR/issue-54779-anon-static-lifetime.rs:32:9
error: lifetime may not live long enough
--> $DIR/issue-54779-anon-static-lifetime.rs:32:24
|
LL | cx: &dyn DebugContext,
| -- - let's call the lifetime of this reference `'1`
| |
| `cx` is a reference that is only valid in the method body
| - let's call the lifetime of this reference `'1`
...
LL | bar.debug_with(cx);
| ^^^^^^^^^^^^^^^^^^
| |
| `cx` escapes the method body here
| argument requires that `'1` must outlive `'static`
| ^^ coercion requires that `'1` must outlive `'static`

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0521`.
3 changes: 2 additions & 1 deletion tests/ui/traits/trait-object-lifetime-default-note.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ fn main() {
let local = 0; //~ NOTE binding `local` declared here
let r = &local; //~ ERROR `local` does not live long enough
//~| NOTE borrowed value does not live long enough
//~| NOTE due to object lifetime defaults, `Box<dyn A>` actually means `Box<(dyn A + 'static)>`
require_box(Box::new(r));
//~^ NOTE argument requires that `local` is borrowed for `'static`
//~^ NOTE coercion requires that `local` is borrowed for `'static`

let _ = 0;
} //~ NOTE `local` dropped here while still borrowed
Expand Down
6 changes: 4 additions & 2 deletions tests/ui/traits/trait-object-lifetime-default-note.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@ LL | let local = 0;
| ----- binding `local` declared here
LL | let r = &local;
| ^^^^^^ borrowed value does not live long enough
LL |
...
LL | require_box(Box::new(r));
| ------------------------ argument requires that `local` is borrowed for `'static`
| ----------- coercion requires that `local` is borrowed for `'static`
...
LL | }
| - `local` dropped here while still borrowed
|
= note: due to object lifetime defaults, `Box<dyn A>` actually means `Box<(dyn A + 'static)>`

error: aborting due to 1 previous error

Expand Down

0 comments on commit ff793a7

Please sign in to comment.