Skip to content

Commit 73464a9

Browse files
committed
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.
1 parent e5fefc3 commit 73464a9

7 files changed

+185
-15
lines changed

compiler/rustc_borrowck/src/type_check/free_region_relations.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,8 @@ impl UniversalRegionRelations<'_> {
133133
assert!(self.universal_regions.is_universal_region(fr0));
134134

135135
let mut external_parents = vec![];
136-
let mut queue = vec![fr0];
136+
137+
let mut queue = vec![relation.scc_representative(fr0)];
137138

138139
// Keep expanding `fr` into its parents until we reach
139140
// non-local regions.

compiler/rustc_data_structures/src/transitive_relation.rs

+14
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,20 @@ impl<T: Eq + Hash + Copy> TransitiveRelation<T> {
354354
.collect()
355355
}
356356

357+
/// Given an element A, elements B with the lowest index such that `A R B`
358+
/// and `B R A`, or `A` if no such element exists.
359+
pub fn scc_representative(&self, a: T) -> T {
360+
match self.index(a) {
361+
Some(a_i) => self.with_closure(|closure| {
362+
closure
363+
.iter(a_i.0)
364+
.find(|i| closure.contains(*i, a_i.0))
365+
.map_or(a, |i| self.elements[i])
366+
}),
367+
None => a,
368+
}
369+
}
370+
357371
fn with_closure<OP, R>(&self, op: OP) -> R
358372
where
359373
OP: FnOnce(&BitMatrix<usize, usize>) -> R,

tests/crashes/122704.rs

-14
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Regression test for #122704
2+
use std::any::Any;
3+
4+
pub struct Foo {
5+
bar: Box<dyn for<'a> Fn(&'a usize) -> Box<dyn Any + 'a>>,
6+
}
7+
8+
impl Foo {
9+
pub fn ack<I>(&mut self, f: impl for<'a> Fn(&'a usize) -> Box<I>) {
10+
self.bar = Box::new(|baz| Box::new(f(baz)));
11+
//~^ ERROR the parameter type `impl for<'a> Fn(&'a usize) -> Box<I>` may not live long enough
12+
//~| ERROR the parameter type `impl for<'a> Fn(&'a usize) -> Box<I>` may not live long enough
13+
//~| ERROR the parameter type `impl for<'a> Fn(&'a usize) -> Box<I>` may not live long enough
14+
//~| ERROR the parameter type `impl for<'a> Fn(&'a usize) -> Box<I>` may not live long enough
15+
//~| ERROR the parameter type `I` may not live long enough
16+
//~| ERROR the parameter type `I` may not live long enough
17+
//~| ERROR the parameter type `I` may not live long enough
18+
//~| ERROR `f` does not live long enough
19+
}
20+
}
21+
22+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
error[E0310]: the parameter type `impl for<'a> Fn(&'a usize) -> Box<I>` may not live long enough
2+
--> $DIR/unconstrained-closure-lifetime-generic.rs:10:9
3+
|
4+
LL | self.bar = Box::new(|baz| Box::new(f(baz)));
5+
| ^^^^^^^^
6+
| |
7+
| the parameter type `impl for<'a> Fn(&'a usize) -> Box<I>` must be valid for the static lifetime...
8+
| ...so that the type `impl for<'a> Fn(&'a usize) -> Box<I>` will meet its required lifetime bounds
9+
|
10+
help: consider adding an explicit lifetime bound
11+
|
12+
LL | pub fn ack<I>(&mut self, f: impl for<'a> Fn(&'a usize) -> Box<I> + 'static) {
13+
| +++++++++
14+
15+
error[E0310]: the parameter type `impl for<'a> Fn(&'a usize) -> Box<I>` may not live long enough
16+
--> $DIR/unconstrained-closure-lifetime-generic.rs:10:9
17+
|
18+
LL | self.bar = Box::new(|baz| Box::new(f(baz)));
19+
| ^^^^^^^^
20+
| |
21+
| the parameter type `impl for<'a> Fn(&'a usize) -> Box<I>` must be valid for the static lifetime...
22+
| ...so that the type `impl for<'a> Fn(&'a usize) -> Box<I>` will meet its required lifetime bounds
23+
|
24+
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
25+
help: consider adding an explicit lifetime bound
26+
|
27+
LL | pub fn ack<I>(&mut self, f: impl for<'a> Fn(&'a usize) -> Box<I> + 'static) {
28+
| +++++++++
29+
30+
error[E0310]: the parameter type `impl for<'a> Fn(&'a usize) -> Box<I>` may not live long enough
31+
--> $DIR/unconstrained-closure-lifetime-generic.rs:10:20
32+
|
33+
LL | self.bar = Box::new(|baz| Box::new(f(baz)));
34+
| ^^^^^^^^
35+
| |
36+
| the parameter type `impl for<'a> Fn(&'a usize) -> Box<I>` must be valid for the static lifetime...
37+
| ...so that the type `impl for<'a> Fn(&'a usize) -> Box<I>` will meet its required lifetime bounds
38+
|
39+
help: consider adding an explicit lifetime bound
40+
|
41+
LL | pub fn ack<I>(&mut self, f: impl for<'a> Fn(&'a usize) -> Box<I> + 'static) {
42+
| +++++++++
43+
44+
error[E0310]: the parameter type `impl for<'a> Fn(&'a usize) -> Box<I>` may not live long enough
45+
--> $DIR/unconstrained-closure-lifetime-generic.rs:10:20
46+
|
47+
LL | self.bar = Box::new(|baz| Box::new(f(baz)));
48+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
49+
| |
50+
| the parameter type `impl for<'a> Fn(&'a usize) -> Box<I>` must be valid for the static lifetime...
51+
| ...so that the type `impl for<'a> Fn(&'a usize) -> Box<I>` will meet its required lifetime bounds
52+
|
53+
help: consider adding an explicit lifetime bound
54+
|
55+
LL | pub fn ack<I>(&mut self, f: impl for<'a> Fn(&'a usize) -> Box<I> + 'static) {
56+
| +++++++++
57+
58+
error[E0310]: the parameter type `I` may not live long enough
59+
--> $DIR/unconstrained-closure-lifetime-generic.rs:10:35
60+
|
61+
LL | self.bar = Box::new(|baz| Box::new(f(baz)));
62+
| ^^^^^^^^^^^^^^^^
63+
| |
64+
| the parameter type `I` must be valid for the static lifetime...
65+
| ...so that the type `I` will meet its required lifetime bounds
66+
|
67+
help: consider adding an explicit lifetime bound
68+
|
69+
LL | pub fn ack<I: 'static>(&mut self, f: impl for<'a> Fn(&'a usize) -> Box<I>) {
70+
| +++++++++
71+
72+
error[E0310]: the parameter type `I` may not live long enough
73+
--> $DIR/unconstrained-closure-lifetime-generic.rs:10:35
74+
|
75+
LL | self.bar = Box::new(|baz| Box::new(f(baz)));
76+
| ^^^^^^^^^^^^^^^^
77+
| |
78+
| the parameter type `I` must be valid for the static lifetime...
79+
| ...so that the type `I` will meet its required lifetime bounds
80+
|
81+
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
82+
help: consider adding an explicit lifetime bound
83+
|
84+
LL | pub fn ack<I: 'static>(&mut self, f: impl for<'a> Fn(&'a usize) -> Box<I>) {
85+
| +++++++++
86+
87+
error[E0311]: the parameter type `I` may not live long enough
88+
--> $DIR/unconstrained-closure-lifetime-generic.rs:10:35
89+
|
90+
LL | pub fn ack<I>(&mut self, f: impl for<'a> Fn(&'a usize) -> Box<I>) {
91+
| --------- the parameter type `I` must be valid for the anonymous lifetime defined here...
92+
LL | self.bar = Box::new(|baz| Box::new(f(baz)));
93+
| ^^^^^^^^^^^^^^^^ ...so that the type `I` will meet its required lifetime bounds
94+
|
95+
help: consider adding an explicit lifetime bound
96+
|
97+
LL | pub fn ack<'a, I: 'a>(&'a mut self, f: impl for<'a> Fn(&'a usize) -> Box<I>) {
98+
| +++ ++++ ++
99+
100+
error[E0597]: `f` does not live long enough
101+
--> $DIR/unconstrained-closure-lifetime-generic.rs:10:44
102+
|
103+
LL | pub fn ack<I>(&mut self, f: impl for<'a> Fn(&'a usize) -> Box<I>) {
104+
| - binding `f` declared here
105+
LL | self.bar = Box::new(|baz| Box::new(f(baz)));
106+
| -------- ----- ^ borrowed value does not live long enough
107+
| | |
108+
| | value captured here
109+
| coercion requires that `f` is borrowed for `'static`
110+
...
111+
LL | }
112+
| - `f` dropped here while still borrowed
113+
|
114+
= 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)>`
115+
116+
error: aborting due to 8 previous errors
117+
118+
Some errors have detailed explanations: E0310, E0311, E0597.
119+
For more information about an error, try `rustc --explain E0310`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// Regression test for #139004
2+
use std::any::Any;
3+
4+
type B = Box<dyn for<'a> Fn(&(dyn Any + 'a)) -> Box<dyn Any + 'a>>;
5+
6+
fn foo<E>() -> B {
7+
Box::new(|e| Box::new(e.is::<E>()))
8+
//~^ ERROR the parameter type `E` may not live long enough
9+
}
10+
11+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
error[E0310]: the parameter type `E` may not live long enough
2+
--> $DIR/unconstrained-closure-lifetime-trait-object.rs:7:29
3+
|
4+
LL | Box::new(|e| Box::new(e.is::<E>()))
5+
| ^^
6+
| |
7+
| the parameter type `E` must be valid for the static lifetime...
8+
| ...so that the type `E` will meet its required lifetime bounds
9+
|
10+
help: consider adding an explicit lifetime bound
11+
|
12+
LL | fn foo<E: 'static>() -> B {
13+
| +++++++++
14+
15+
error: aborting due to 1 previous error
16+
17+
For more information about this error, try `rustc --explain E0310`.

0 commit comments

Comments
 (0)