Skip to content

Commit 720b694

Browse files
authored
Rollup merge of #78164 - Aaron1011:fix/async-region-name, r=tmandry
Prefer regions with an `external_name` in `approx_universal_upper_bound` Fixes #75785 When displaying a MIR borrowcheck error, we may need to find an upper bound for a region, which gives us a region to point to in the error message. However, a region might outlive multiple distinct universal regions, in which case the only upper bound is 'static To try to display a meaningful error message, we compute an 'approximate' upper bound by picking one of the universal regions. Currently, we pick the region with the lowest index - however, this caused us to produce a suboptimal error message in issue #75785 This PR `approx_universal_upper_bound` to prefer regions with an `external_name`. This causes us to prefer regions from function arguments/upvars, which seems to lead to a nicer error message in some cases.
2 parents eb4fc71 + 419d3ae commit 720b694

File tree

4 files changed

+46
-2
lines changed

4 files changed

+46
-2
lines changed

compiler/rustc_mir/src/borrow_check/region_infer/mod.rs

+17-1
Original file line numberDiff line numberDiff line change
@@ -1145,8 +1145,24 @@ impl<'tcx> RegionInferenceContext<'tcx> {
11451145
for ur in self.scc_values.universal_regions_outlived_by(r_scc) {
11461146
let new_lub = self.universal_region_relations.postdom_upper_bound(lub, ur);
11471147
debug!("approx_universal_upper_bound: ur={:?} lub={:?} new_lub={:?}", ur, lub, new_lub);
1148+
// The upper bound of two non-static regions is static: this
1149+
// means we know nothing about the relationship between these
1150+
// two regions. Pick a 'better' one to use when constructing
1151+
// a diagnostic
11481152
if ur != static_r && lub != static_r && new_lub == static_r {
1149-
lub = std::cmp::min(ur, lub);
1153+
// Prefer the region with an `external_name` - this
1154+
// indicates that the region is early-bound, so working with
1155+
// it can produce a nicer error.
1156+
if self.region_definition(ur).external_name.is_some() {
1157+
lub = ur;
1158+
} else if self.region_definition(lub).external_name.is_some() {
1159+
// Leave lub unchanged
1160+
} else {
1161+
// If we get here, we don't have any reason to prefer
1162+
// one region over the other. Just pick the
1163+
// one with the lower index for now.
1164+
lub = std::cmp::min(ur, lub);
1165+
}
11501166
} else {
11511167
lub = new_lub;
11521168
}

src/test/ui/async-await/issue-74072-lifetime-name-annotations.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error[E0506]: cannot assign to `*x` because it is borrowed
22
--> $DIR/issue-74072-lifetime-name-annotations.rs:9:5
33
|
44
LL | pub async fn async_fn(x: &mut i32) -> &i32 {
5-
| - let's call the lifetime of this reference `'1`
5+
| - let's call the lifetime of this reference `'1`
66
LL | let y = &*x;
77
| --- borrow of `*x` occurs here
88
LL | *x += 1;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// edition:2018
2+
//
3+
// Regression test for issue #75785
4+
// Tests that we don't point to a confusing named
5+
// region when emitting a diagnostic
6+
7+
pub async fn async_fn(x: &mut i32) -> (&i32, &i32) {
8+
let y = &*x;
9+
*x += 1; //~ ERROR cannot assign to
10+
(&32, y)
11+
}
12+
13+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error[E0506]: cannot assign to `*x` because it is borrowed
2+
--> $DIR/issue-75785-confusing-named-region.rs:9:5
3+
|
4+
LL | pub async fn async_fn(x: &mut i32) -> (&i32, &i32) {
5+
| - let's call the lifetime of this reference `'1`
6+
LL | let y = &*x;
7+
| --- borrow of `*x` occurs here
8+
LL | *x += 1;
9+
| ^^^^^^^ assignment to borrowed `*x` occurs here
10+
LL | (&32, y)
11+
| -------- returning this value requires that `*x` is borrowed for `'1`
12+
13+
error: aborting due to previous error
14+
15+
For more information about this error, try `rustc --explain E0506`.

0 commit comments

Comments
 (0)