Don't arbitrarily choose one upper bound for hidden captured region
This commit is contained in:
parent
60d146580c
commit
c656ce7aeb
@ -225,21 +225,26 @@ pub(crate) fn name_regions<T>(&self, tcx: TyCtxt<'tcx>, ty: T) -> T
|
||||
|
||||
// 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,
|
||||
|
29
tests/ui/impl-trait/in-trait/cannot-capture-intersection.rs
Normal file
29
tests/ui/impl-trait/in-trait/cannot-capture-intersection.rs
Normal 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() {}
|
@ -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`.
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user