Don't arbitrarily choose one upper bound for hidden captured region

This commit is contained in:
Michael Goulet 2024-08-06 15:43:28 -04:00
parent 60d146580c
commit c656ce7aeb
6 changed files with 68 additions and 36 deletions

View File

@ -225,21 +225,26 @@ impl<'tcx> RegionInferenceContext<'tcx> {
// Find something that we can name
let upper_bound = self.approx_universal_upper_bound(vid);
let upper_bound = &self.definitions[upper_bound];
match upper_bound.external_name {
Some(reg) => reg,
None => {
// Nothing exact found, so we pick the first one that we find.
let scc = self.constraint_sccs.scc(vid);
for vid in self.rev_scc_graph.as_ref().unwrap().upper_bounds(scc) {
match self.definitions[vid].external_name {
None => {}
Some(region) if region.is_static() => {}
Some(region) => return region,
}
}
region
}
if let Some(universal_region) = self.definitions[upper_bound].external_name {
return universal_region;
}
// Nothing exact found, so we pick a named upper bound, if there's only one.
// If there's >1 universal region, then we probably are dealing w/ an intersection
// region which cannot be mapped back to a universal.
// FIXME: We could probably compute the LUB if there is one.
let scc = self.constraint_sccs.scc(vid);
let upper_bounds: Vec<_> = self
.rev_scc_graph
.as_ref()
.unwrap()
.upper_bounds(scc)
.filter_map(|vid| self.definitions[vid].external_name)
.filter(|r| !r.is_static())
.collect();
match &upper_bounds[..] {
[universal_region] => *universal_region,
_ => region,
}
}
_ => region,

View File

@ -0,0 +1,29 @@
#![feature(precise_capturing)]
use std::future::Future;
use std::pin::Pin;
trait MyTrait {
fn foo<'a, 'b>(&'a self, x: &'b i32) -> impl Future<Output = i32>;
}
trait ErasedMyTrait {
fn foo<'life0, 'life1, 'dynosaur>(&'life0 self, x: &'life1 i32)
-> Pin<Box<dyn Future<Output = i32> + 'dynosaur>>
where
'life0: 'dynosaur,
'life1: 'dynosaur;
}
struct DynMyTrait<T: ErasedMyTrait> {
ptr: T,
}
impl<T: ErasedMyTrait> MyTrait for DynMyTrait<T> {
fn foo<'a, 'b>(&'a self, x: &'b i32) -> impl Future<Output = i32> {
self.ptr.foo(x)
//~^ ERROR hidden type for `impl Future<Output = i32>` captures lifetime that does not appear in bounds
}
}
fn main() {}

View File

@ -0,0 +1,13 @@
error[E0700]: hidden type for `impl Future<Output = i32>` captures lifetime that does not appear in bounds
--> $DIR/cannot-capture-intersection.rs:24:9
|
LL | fn foo<'a, 'b>(&'a self, x: &'b i32) -> impl Future<Output = i32> {
| ------------------------- opaque type defined here
LL | self.ptr.foo(x)
| ^^^^^^^^^^^^^^^
|
= note: hidden type `Pin<Box<dyn Future<Output = i32>>>` captures lifetime `'_`
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0700`.

View File

@ -2,17 +2,12 @@ error[E0700]: hidden type for `impl Trait<'d, 'e>` captures lifetime that does n
--> $DIR/ordinary-bounds-unrelated.rs:28:33
|
LL | fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'d, 'e>
| -- ------------------ opaque type defined here
| |
| hidden type `Ordinary<'b>` captures the lifetime `'b` as defined here
| ------------------ opaque type defined here
...
LL | if condition() { a } else { b }
| ^
|
help: to declare that `impl Trait<'d, 'e>` captures `'b`, you can add an explicit `'b` lifetime bound
|
LL | fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'d, 'e> + 'b
| ++++
= note: hidden type `Ordinary<'_>` captures lifetime `'_`
error: aborting due to 1 previous error

View File

@ -2,17 +2,12 @@ error[E0700]: hidden type for `impl Trait<'a, 'b>` captures lifetime that does n
--> $DIR/ordinary-bounds-unsuited.rs:31:33
|
LL | fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b>
| -- ------------------ opaque type defined here
| |
| hidden type `Ordinary<'b>` captures the lifetime `'b` as defined here
| ------------------ opaque type defined here
...
LL | if condition() { a } else { b }
| ^
|
help: to declare that `impl Trait<'a, 'b>` captures `'b`, you can add an explicit `'b` lifetime bound
|
LL | fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b> + 'b
| ++++
= note: hidden type `Ordinary<'_>` captures lifetime `'_`
error: aborting due to 1 previous error

View File

@ -2,18 +2,13 @@ error[E0700]: hidden type for `impl Iterator<Item = i32>` captures lifetime that
--> $DIR/explicit-lifetime-suggestion-in-proper-span-issue-121267.rs:7:5
|
LL | fn bar(src: &crate::Foo) -> impl Iterator<Item = i32> {
| ---------- ------------------------- opaque type defined here
| |
| hidden type `FilterMap<std::slice::Iter<'static, i32>, {closure@$DIR/explicit-lifetime-suggestion-in-proper-span-issue-121267.rs:9:21: 9:24}>` captures the anonymous lifetime defined here
| ------------------------- opaque type defined here
LL | / [0].into_iter()
LL | |
LL | | .filter_map(|_| foo(src))
| |_________________________________^
|
help: to declare that `impl Iterator<Item = i32>` captures `'_`, you can introduce a named lifetime parameter `'a`
|
LL | fn bar<'a>(src: &'a crate::Foo<'a>) -> impl Iterator<Item = i32> + 'a {
| ++++ ++ ++++ ++++
= note: hidden type `FilterMap<std::slice::Iter<'static, i32>, {closure@$DIR/explicit-lifetime-suggestion-in-proper-span-issue-121267.rs:9:21: 9:24}>` captures lifetime `'_`
error: aborting due to 1 previous error