Handle regions equivalent to 'static in non_local_bounds
`non_local_bounds` would only find non local bounds that strictly bound a given region, but it's possible that a local region is equated to 'static when showing a type referencing a locally bound lifetime, such as `dyn Any + 'a` in the tests added, is well-formed. In this case we should return 'static.
This commit is contained in:
parent
f836ae4e66
commit
2d5e80b8cb
7 changed files with 185 additions and 15 deletions
|
|
@ -133,7 +133,8 @@ impl UniversalRegionRelations<'_> {
|
|||
assert!(self.universal_regions.is_universal_region(fr0));
|
||||
|
||||
let mut external_parents = vec![];
|
||||
let mut queue = vec![fr0];
|
||||
|
||||
let mut queue = vec![relation.minimal_scc_representative(fr0)];
|
||||
|
||||
// Keep expanding `fr` into its parents until we reach
|
||||
// non-local regions.
|
||||
|
|
|
|||
|
|
@ -354,6 +354,20 @@ impl<T: Eq + Hash + Copy> TransitiveRelation<T> {
|
|||
.collect()
|
||||
}
|
||||
|
||||
/// Given an element A, elements B with the lowest index such that `A R B`
|
||||
/// and `B R A`, or `A` if no such element exists.
|
||||
pub fn minimal_scc_representative(&self, a: T) -> T {
|
||||
match self.index(a) {
|
||||
Some(a_i) => self.with_closure(|closure| {
|
||||
closure
|
||||
.iter(a_i.0)
|
||||
.find(|i| closure.contains(*i, a_i.0))
|
||||
.map_or(a, |i| self.elements[i])
|
||||
}),
|
||||
None => a,
|
||||
}
|
||||
}
|
||||
|
||||
fn with_closure<OP, R>(&self, op: OP) -> R
|
||||
where
|
||||
OP: FnOnce(&BitMatrix<usize, usize>) -> R,
|
||||
|
|
|
|||
|
|
@ -1,14 +0,0 @@
|
|||
//@ known-bug: #122704
|
||||
use std::any::Any;
|
||||
|
||||
pub struct Foo {
|
||||
bar: Box<dyn for<'a> Fn(&'a usize) -> Box<dyn Any + 'a>>,
|
||||
}
|
||||
|
||||
impl Foo {
|
||||
pub fn ack<I>(&mut self, f: impl for<'a> Fn(&'a usize) -> Box<I>) {
|
||||
self.bar = Box::new(|baz| Box::new(f(baz)));
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
22
tests/ui/borrowck/unconstrained-closure-lifetime-generic.rs
Normal file
22
tests/ui/borrowck/unconstrained-closure-lifetime-generic.rs
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
// Regression test for #122704
|
||||
use std::any::Any;
|
||||
|
||||
pub struct Foo {
|
||||
bar: Box<dyn for<'a> Fn(&'a usize) -> Box<dyn Any + 'a>>,
|
||||
}
|
||||
|
||||
impl Foo {
|
||||
pub fn ack<I>(&mut self, f: impl for<'a> Fn(&'a usize) -> Box<I>) {
|
||||
self.bar = Box::new(|baz| Box::new(f(baz)));
|
||||
//~^ ERROR the parameter type `impl for<'a> Fn(&'a usize) -> Box<I>` may not live long enough
|
||||
//~| ERROR the parameter type `impl for<'a> Fn(&'a usize) -> Box<I>` may not live long enough
|
||||
//~| ERROR the parameter type `impl for<'a> Fn(&'a usize) -> Box<I>` may not live long enough
|
||||
//~| ERROR the parameter type `impl for<'a> Fn(&'a usize) -> Box<I>` may not live long enough
|
||||
//~| ERROR the parameter type `I` may not live long enough
|
||||
//~| ERROR the parameter type `I` may not live long enough
|
||||
//~| ERROR the parameter type `I` may not live long enough
|
||||
//~| ERROR `f` does not live long enough
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
119
tests/ui/borrowck/unconstrained-closure-lifetime-generic.stderr
Normal file
119
tests/ui/borrowck/unconstrained-closure-lifetime-generic.stderr
Normal file
|
|
@ -0,0 +1,119 @@
|
|||
error[E0310]: the parameter type `impl for<'a> Fn(&'a usize) -> Box<I>` may not live long enough
|
||||
--> $DIR/unconstrained-closure-lifetime-generic.rs:10:9
|
||||
|
|
||||
LL | self.bar = Box::new(|baz| Box::new(f(baz)));
|
||||
| ^^^^^^^^
|
||||
| |
|
||||
| the parameter type `impl for<'a> Fn(&'a usize) -> Box<I>` must be valid for the static lifetime...
|
||||
| ...so that the type `impl for<'a> Fn(&'a usize) -> Box<I>` will meet its required lifetime bounds
|
||||
|
|
||||
help: consider adding an explicit lifetime bound
|
||||
|
|
||||
LL | pub fn ack<I>(&mut self, f: impl for<'a> Fn(&'a usize) -> Box<I> + 'static) {
|
||||
| +++++++++
|
||||
|
||||
error[E0310]: the parameter type `impl for<'a> Fn(&'a usize) -> Box<I>` may not live long enough
|
||||
--> $DIR/unconstrained-closure-lifetime-generic.rs:10:9
|
||||
|
|
||||
LL | self.bar = Box::new(|baz| Box::new(f(baz)));
|
||||
| ^^^^^^^^
|
||||
| |
|
||||
| the parameter type `impl for<'a> Fn(&'a usize) -> Box<I>` must be valid for the static lifetime...
|
||||
| ...so that the type `impl for<'a> Fn(&'a usize) -> Box<I>` will meet its required lifetime bounds
|
||||
|
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
help: consider adding an explicit lifetime bound
|
||||
|
|
||||
LL | pub fn ack<I>(&mut self, f: impl for<'a> Fn(&'a usize) -> Box<I> + 'static) {
|
||||
| +++++++++
|
||||
|
||||
error[E0310]: the parameter type `impl for<'a> Fn(&'a usize) -> Box<I>` may not live long enough
|
||||
--> $DIR/unconstrained-closure-lifetime-generic.rs:10:20
|
||||
|
|
||||
LL | self.bar = Box::new(|baz| Box::new(f(baz)));
|
||||
| ^^^^^^^^
|
||||
| |
|
||||
| the parameter type `impl for<'a> Fn(&'a usize) -> Box<I>` must be valid for the static lifetime...
|
||||
| ...so that the type `impl for<'a> Fn(&'a usize) -> Box<I>` will meet its required lifetime bounds
|
||||
|
|
||||
help: consider adding an explicit lifetime bound
|
||||
|
|
||||
LL | pub fn ack<I>(&mut self, f: impl for<'a> Fn(&'a usize) -> Box<I> + 'static) {
|
||||
| +++++++++
|
||||
|
||||
error[E0310]: the parameter type `impl for<'a> Fn(&'a usize) -> Box<I>` may not live long enough
|
||||
--> $DIR/unconstrained-closure-lifetime-generic.rs:10:20
|
||||
|
|
||||
LL | self.bar = Box::new(|baz| Box::new(f(baz)));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| the parameter type `impl for<'a> Fn(&'a usize) -> Box<I>` must be valid for the static lifetime...
|
||||
| ...so that the type `impl for<'a> Fn(&'a usize) -> Box<I>` will meet its required lifetime bounds
|
||||
|
|
||||
help: consider adding an explicit lifetime bound
|
||||
|
|
||||
LL | pub fn ack<I>(&mut self, f: impl for<'a> Fn(&'a usize) -> Box<I> + 'static) {
|
||||
| +++++++++
|
||||
|
||||
error[E0310]: the parameter type `I` may not live long enough
|
||||
--> $DIR/unconstrained-closure-lifetime-generic.rs:10:35
|
||||
|
|
||||
LL | self.bar = Box::new(|baz| Box::new(f(baz)));
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| the parameter type `I` must be valid for the static lifetime...
|
||||
| ...so that the type `I` will meet its required lifetime bounds
|
||||
|
|
||||
help: consider adding an explicit lifetime bound
|
||||
|
|
||||
LL | pub fn ack<I: 'static>(&mut self, f: impl for<'a> Fn(&'a usize) -> Box<I>) {
|
||||
| +++++++++
|
||||
|
||||
error[E0310]: the parameter type `I` may not live long enough
|
||||
--> $DIR/unconstrained-closure-lifetime-generic.rs:10:35
|
||||
|
|
||||
LL | self.bar = Box::new(|baz| Box::new(f(baz)));
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| the parameter type `I` must be valid for the static lifetime...
|
||||
| ...so that the type `I` will meet its required lifetime bounds
|
||||
|
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
help: consider adding an explicit lifetime bound
|
||||
|
|
||||
LL | pub fn ack<I: 'static>(&mut self, f: impl for<'a> Fn(&'a usize) -> Box<I>) {
|
||||
| +++++++++
|
||||
|
||||
error[E0311]: the parameter type `I` may not live long enough
|
||||
--> $DIR/unconstrained-closure-lifetime-generic.rs:10:35
|
||||
|
|
||||
LL | pub fn ack<I>(&mut self, f: impl for<'a> Fn(&'a usize) -> Box<I>) {
|
||||
| --------- the parameter type `I` must be valid for the anonymous lifetime defined here...
|
||||
LL | self.bar = Box::new(|baz| Box::new(f(baz)));
|
||||
| ^^^^^^^^^^^^^^^^ ...so that the type `I` will meet its required lifetime bounds
|
||||
|
|
||||
help: consider adding an explicit lifetime bound
|
||||
|
|
||||
LL | pub fn ack<'a, I: 'a>(&'a mut self, f: impl for<'a> Fn(&'a usize) -> Box<I>) {
|
||||
| +++ ++++ ++
|
||||
|
||||
error[E0597]: `f` does not live long enough
|
||||
--> $DIR/unconstrained-closure-lifetime-generic.rs:10:44
|
||||
|
|
||||
LL | pub fn ack<I>(&mut self, f: impl for<'a> Fn(&'a usize) -> Box<I>) {
|
||||
| - binding `f` declared here
|
||||
LL | self.bar = Box::new(|baz| Box::new(f(baz)));
|
||||
| -------- ----- ^ borrowed value does not live long enough
|
||||
| | |
|
||||
| | value captured here
|
||||
| coercion requires that `f` is borrowed for `'static`
|
||||
...
|
||||
LL | }
|
||||
| - `f` dropped here while still borrowed
|
||||
|
|
||||
= note: due to object lifetime defaults, `Box<dyn for<'a> Fn(&'a usize) -> Box<(dyn Any + 'a)>>` actually means `Box<(dyn for<'a> Fn(&'a usize) -> Box<(dyn Any + 'a)> + 'static)>`
|
||||
|
||||
error: aborting due to 8 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0310, E0311, E0597.
|
||||
For more information about an error, try `rustc --explain E0310`.
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
// Regression test for #139004
|
||||
use std::any::Any;
|
||||
|
||||
type B = Box<dyn for<'a> Fn(&(dyn Any + 'a)) -> Box<dyn Any + 'a>>;
|
||||
|
||||
fn foo<E>() -> B {
|
||||
Box::new(|e| Box::new(e.is::<E>()))
|
||||
//~^ ERROR the parameter type `E` may not live long enough
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
error[E0310]: the parameter type `E` may not live long enough
|
||||
--> $DIR/unconstrained-closure-lifetime-trait-object.rs:7:29
|
||||
|
|
||||
LL | Box::new(|e| Box::new(e.is::<E>()))
|
||||
| ^^
|
||||
| |
|
||||
| the parameter type `E` must be valid for the static lifetime...
|
||||
| ...so that the type `E` will meet its required lifetime bounds
|
||||
|
|
||||
help: consider adding an explicit lifetime bound
|
||||
|
|
||||
LL | fn foo<E: 'static>() -> B {
|
||||
| +++++++++
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0310`.
|
||||
Loading…
Add table
Add a link
Reference in a new issue