Skip to content

Commit 86063b3

Browse files
committed
diagnostics :3
1 parent b563755 commit 86063b3

File tree

9 files changed

+69
-57
lines changed

9 files changed

+69
-57
lines changed

compiler/rustc_borrowck/src/diagnostics/opaque_types.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for FindOpaqueRegion<'_, 'tcx> {
244244

245245
// Find a path between the borrow region and our opaque capture.
246246
if let Some((path, _)) =
247-
self.regioncx.find_constraint_paths_between_regions(self.borrow_region, |r| {
247+
self.regioncx.find_constraint_path_between_regions(self.borrow_region, |r| {
248248
r == opaque_region_vid
249249
})
250250
{

compiler/rustc_borrowck/src/region_infer/mod.rs

Lines changed: 42 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1405,18 +1405,39 @@ impl<'tcx> RegionInferenceContext<'tcx> {
14051405
}
14061406

14071407
/// Walks the graph of constraints (where `'a: 'b` is considered
1408-
/// an edge `'a -> 'b`) to find all paths from `from_region` to
1409-
/// `to_region`. The paths are accumulated into the vector
1410-
/// `results`. The paths are stored as a series of
1411-
/// `ConstraintIndex` values -- in other words, a list of *edges*.
1408+
/// an edge `'a -> 'b`) to find a path from `from_region` to
1409+
/// `to_region`.
14121410
///
14131411
/// Returns: a series of constraints as well as the region `R`
14141412
/// that passed the target test.
14151413
#[instrument(skip(self, target_test), ret)]
1416-
pub(crate) fn find_constraint_paths_between_regions(
1414+
pub(crate) fn find_constraint_path_between_regions(
14171415
&self,
14181416
from_region: RegionVid,
14191417
target_test: impl Fn(RegionVid) -> bool,
1418+
) -> Option<(Vec<OutlivesConstraint<'tcx>>, RegionVid)> {
1419+
self.find_constraint_path_between_regions_inner(true, from_region, &target_test).or_else(
1420+
|| self.find_constraint_path_between_regions_inner(false, from_region, &target_test),
1421+
)
1422+
}
1423+
1424+
/// The constraints we get from equating the hidden type of each use of an opaque
1425+
/// with its final concrete type may end up getting preferred over other, potentially
1426+
/// longer constraint paths.
1427+
///
1428+
/// Given that we compute the final concrete type by relying on this existing constraint
1429+
/// path, this can easily end up hiding the actual reason for why we require these regions
1430+
/// to be equal.
1431+
///
1432+
/// To handle this, we first look at the path while ignoring these constraints and then
1433+
/// retry while considering them. This is not perfect, as the `from_region` may have already
1434+
/// been partially related to its argument region, so while we rely on a member constraint
1435+
/// to get a complete path, the most relevant step of that path already existed before then.
1436+
fn find_constraint_path_between_regions_inner(
1437+
&self,
1438+
ignore_opaque_type_constraints: bool,
1439+
from_region: RegionVid,
1440+
target_test: impl Fn(RegionVid) -> bool,
14201441
) -> Option<(Vec<OutlivesConstraint<'tcx>>, RegionVid)> {
14211442
let mut context = IndexVec::from_elem(Trace::NotVisited, &self.definitions);
14221443
context[from_region] = Trace::StartRegion;
@@ -1431,7 +1452,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
14311452

14321453
while let Some(r) = deque.pop_front() {
14331454
debug!(
1434-
"find_constraint_paths_between_regions: from_region={:?} r={:?} value={}",
1455+
"find_constraint_path_between_regions: from_region={:?} r={:?} value={}",
14351456
from_region,
14361457
r,
14371458
self.region_value_str(r),
@@ -1503,9 +1524,16 @@ impl<'tcx> RegionInferenceContext<'tcx> {
15031524
let edges = self.constraint_graph.outgoing_edges_from_graph(r, &self.constraints);
15041525
// This loop can be hot.
15051526
for constraint in edges {
1506-
if matches!(constraint.category, ConstraintCategory::IllegalUniverse) {
1507-
debug!("Ignoring illegal universe constraint: {constraint:?}");
1508-
continue;
1527+
match constraint.category {
1528+
ConstraintCategory::IllegalUniverse => {
1529+
debug!("Ignoring illegal universe constraint: {constraint:?}");
1530+
continue;
1531+
}
1532+
ConstraintCategory::OpaqueType if ignore_opaque_type_constraints => {
1533+
debug!("Ignoring member constraint: {constraint:?}");
1534+
continue;
1535+
}
1536+
_ => {}
15091537
}
15101538
debug_assert_eq!(constraint.sup, r);
15111539
handle_trace(constraint.sub, Trace::FromGraph(constraint));
@@ -1521,7 +1549,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
15211549
pub(crate) fn find_sub_region_live_at(&self, fr1: RegionVid, location: Location) -> RegionVid {
15221550
trace!(scc = ?self.constraint_sccs.scc(fr1));
15231551
trace!(universe = ?self.max_nameable_universe(self.constraint_sccs.scc(fr1)));
1524-
self.find_constraint_paths_between_regions(fr1, |r| {
1552+
self.find_constraint_path_between_regions(fr1, |r| {
15251553
// First look for some `r` such that `fr1: r` and `r` is live at `location`
15261554
trace!(?r, liveness_constraints=?self.liveness_constraints.pretty_print_live_points(r));
15271555
self.liveness_constraints.is_live_at(r, location)
@@ -1531,9 +1559,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
15311559
// `fr1: r` and `r` is a placeholder from some universe
15321560
// `fr1` cannot name. This would force `fr1` to be
15331561
// `'static`.
1534-
self.find_constraint_paths_between_regions(fr1, |r| {
1535-
self.cannot_name_placeholder(fr1, r)
1536-
})
1562+
self.find_constraint_path_between_regions(fr1, |r| self.cannot_name_placeholder(fr1, r))
15371563
})
15381564
.or_else(|| {
15391565
// If we fail to find THAT, it may be that `fr1` is a
@@ -1546,9 +1572,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
15461572
// must be able to name the universe of R2, because R2 will
15471573
// be at least `'empty(Universe(R2))`, and `R1` must be at
15481574
// larger than that.
1549-
self.find_constraint_paths_between_regions(fr1, |r| {
1550-
self.cannot_name_placeholder(r, fr1)
1551-
})
1575+
self.find_constraint_path_between_regions(fr1, |r| self.cannot_name_placeholder(r, fr1))
15521576
})
15531577
.map(|(_path, r)| r)
15541578
.unwrap()
@@ -1604,9 +1628,9 @@ impl<'tcx> RegionInferenceContext<'tcx> {
16041628
) -> (BlameConstraint<'tcx>, Vec<OutlivesConstraint<'tcx>>) {
16051629
// Find all paths
16061630
let (path, target_region) = self
1607-
.find_constraint_paths_between_regions(from_region, target_test)
1631+
.find_constraint_path_between_regions(from_region, target_test)
16081632
.or_else(|| {
1609-
self.find_constraint_paths_between_regions(from_region, |r| {
1633+
self.find_constraint_path_between_regions(from_region, |r| {
16101634
self.cannot_name_placeholder(from_region, r)
16111635
})
16121636
})

tests/ui/async-await/issue-76547.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ impl<'a> Future for ListFut<'a> {
1717
}
1818

1919
async fn fut(bufs: &mut [&mut [u8]]) {
20-
//~^ ERROR lifetime may not live long enough
2120
ListFut(bufs).await
21+
//~^ ERROR lifetime may not live long enough
2222
}
2323

2424
pub struct ListFut2<'a>(&'a mut [&'a mut [u8]]);
@@ -31,8 +31,8 @@ impl<'a> Future for ListFut2<'a> {
3131
}
3232

3333
async fn fut2(bufs: &mut [&mut [u8]]) -> i32 {
34-
//~^ ERROR lifetime may not live long enough
3534
ListFut2(bufs).await
35+
//~^ ERROR lifetime may not live long enough
3636
}
3737

3838
fn main() {}

tests/ui/async-await/issue-76547.stderr

Lines changed: 14 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,27 @@
11
error: lifetime may not live long enough
2-
--> $DIR/issue-76547.rs:19:38
2+
--> $DIR/issue-76547.rs:20:13
33
|
4-
LL | async fn fut(bufs: &mut [&mut [u8]]) {
5-
| ____________________-_____-___________^
6-
| | | |
7-
| | | let's call the lifetime of this reference `'2`
8-
| | let's call the lifetime of this reference `'1`
9-
LL | |
10-
LL | | ListFut(bufs).await
11-
LL | | }
12-
| |_^ opaque type requires that `'1` must outlive `'2`
4+
LL | async fn fut(bufs: &mut [&mut [u8]]) {
5+
| - - let's call the lifetime of this reference `'2`
6+
| |
7+
| let's call the lifetime of this reference `'1`
8+
LL | ListFut(bufs).await
9+
| ^^^^ this usage requires that `'1` must outlive `'2`
1310
|
1411
help: consider introducing a named lifetime parameter
1512
|
1613
LL | async fn fut<'a>(bufs: &'a mut [&'a mut [u8]]) {
1714
| ++++ ++ ++
1815

1916
error: lifetime may not live long enough
20-
--> $DIR/issue-76547.rs:33:46
17+
--> $DIR/issue-76547.rs:34:14
2118
|
22-
LL | async fn fut2(bufs: &mut [&mut [u8]]) -> i32 {
23-
| _____________________-_____-__________________^
24-
| | | |
25-
| | | let's call the lifetime of this reference `'2`
26-
| | let's call the lifetime of this reference `'1`
27-
LL | |
28-
LL | | ListFut2(bufs).await
29-
LL | | }
30-
| |_^ opaque type requires that `'1` must outlive `'2`
19+
LL | async fn fut2(bufs: &mut [&mut [u8]]) -> i32 {
20+
| - - let's call the lifetime of this reference `'2`
21+
| |
22+
| let's call the lifetime of this reference `'1`
23+
LL | ListFut2(bufs).await
24+
| ^^^^ this usage requires that `'1` must outlive `'2`
3125
|
3226
help: consider introducing a named lifetime parameter
3327
|

tests/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ LL | async fn async_ret_impl_trait3<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trai
99
LL | |
1010
LL | | (a, b)
1111
LL | | }
12-
| |_^ opaque type requires that `'a` must outlive `'b`
12+
| |_^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
1313
|
1414
= help: consider adding the following bound: `'a: 'b`
1515

tests/ui/impl-trait/wf-check-hidden-type.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ LL | fn boom<'a, 'b>() -> impl Extend<'a, 'b> {
66
| |
77
| lifetime `'a` defined here
88
LL | None::<&'_ &'_ ()>
9-
| ^^^^^^^^^^^^^^^^^^ opaque type requires that `'a` must outlive `'b`
9+
| ^^^^^^^^^^^^^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
1010
|
1111
= help: consider adding the following bound: `'a: 'b`
1212

tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ mod bav {
1818
impl Bar for i32 {}
1919

2020
fn use_it<'a>(val: Box<dyn ObjectTrait<Assoc = i32>>) -> impl OtherTrait<'a> {
21-
val.use_self() //~ ERROR `val` does not live long enough
21+
val.use_self() //~ ERROR cannot return value referencing function parameter `val`
2222
}
2323
}
2424

tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.stderr

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,11 @@
1-
error[E0597]: `val` does not live long enough
1+
error[E0515]: cannot return value referencing function parameter `val`
22
--> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:21:9
33
|
4-
LL | fn use_it<'a>(val: Box<dyn ObjectTrait<Assoc = i32>>) -> impl OtherTrait<'a> {
5-
| -- --- binding `val` declared here
6-
| |
7-
| lifetime `'a` defined here
84
LL | val.use_self()
9-
| ^^^-----------
5+
| ---^^^^^^^^^^^
106
| |
11-
| borrowed value does not live long enough
12-
| opaque type requires that `val` is borrowed for `'a`
13-
LL | }
14-
| - `val` dropped here while still borrowed
7+
| returns a value referencing data owned by the current function
8+
| `val` is borrowed here
159

1610
error[E0515]: cannot return value referencing function parameter `val`
1711
--> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:43:9
@@ -76,5 +70,5 @@ LL | val.use_self()
7670

7771
error: aborting due to 6 previous errors
7872

79-
Some errors have detailed explanations: E0515, E0521, E0597.
73+
Some errors have detailed explanations: E0515, E0521.
8074
For more information about an error, try `rustc --explain E0515`.

tests/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ LL | |
88
LL | | current: None,
99
LL | | remaining: self.0.iter(),
1010
LL | | }
11-
| |_________^ opaque type requires that `'1` must outlive `'static`
11+
| |_________^ returning this value requires that `'1` must outlive `'static`
1212
|
1313
help: to declare that `impl Iterator<Item = Box<(dyn Foo + 'static)>>` captures data from argument `self`, you can add an explicit `'_` lifetime bound
1414
|
@@ -63,7 +63,7 @@ LL | |
6363
LL | | current: None,
6464
LL | | remaining: self.0.iter(),
6565
LL | | }
66-
| |_________^ opaque type requires that `'a` must outlive `'static`
66+
| |_________^ returning this value requires that `'a` must outlive `'static`
6767
|
6868
help: to declare that `impl Iterator<Item = Box<(dyn Foo + 'static)>>` captures data from argument `self`, you can add an explicit `'a` lifetime bound
6969
|

0 commit comments

Comments
 (0)