I tried this code (credit to @lcnr):
struct Arg<'a: 'c, 'b: 'c, 'c, T> {
field: *mut (&'a (), &'b (), &'c (), T),
}
impl<'a, 'b, 'c, T> Arg<'a, 'b, 'c, T> {
fn constrain(self)
where
T: 'a,
{
}
}
fn takes_closure<'a, 'b, T>(_: impl for<'c> FnOnce(Arg<'a, 'b, 'c, T>)) {}
fn error<'a, 'b, T: 'a>() {
takes_closure::<'a, 'b, T>(|arg| arg.constrain());
}
fn main() {}
This should compile fine, but instead this error is reported:
error[E0309]: the parameter type `T` may not live long enough
--> src/lib.rs:19:38
|
18 | fn error<'a, 'b, T: 'a>() {
| -- the parameter type `T` must be valid for the lifetime `'b` as defined here...
19 | takes_closure::<'a, 'b, T>(|arg| arg.constrain());
| ^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
|
help: consider adding an explicit lifetime bound
|
18 | fn error<'a, 'b, T: 'a + 'b>() {
| ++++
For more information about this error, try `rustc --explain E0309`.
So what's happening here is that during the type test T: 'a we have to propagate some requirements so we can prove the type test. This happens here:
|
let mut found_outlived_universal_region = false; |
|
for ur in self.scc_values.universal_regions_outlived_by(r_scc) { |
|
found_outlived_universal_region = true; |
|
debug!("universal_region_outlived_by ur={:?}", ur); |
|
let non_local_ub = self.universal_region_relations.non_local_upper_bounds(ur); |
|
debug!(?non_local_ub); |
|
|
|
// This is slightly too conservative. To show T: '1, given `'2: '1` |
|
// and `'3: '1` we only need to prove that T: '2 *or* T: '3, but to |
|
// avoid potential non-determinism we approximate this by requiring |
|
// T: '1 and T: '2. |
|
for upper_bound in non_local_ub { |
|
debug_assert!(self.universal_regions().is_universal_region(upper_bound)); |
|
debug_assert!(!self.universal_regions().is_local_free_region(upper_bound)); |
|
|
|
let requirement = ClosureOutlivesRequirement { |
|
subject, |
|
outlived_free_region: upper_bound, |
|
blame_span, |
|
category: ConstraintCategory::Boring, |
|
}; |
|
debug!(?requirement, "adding closure requirement"); |
|
propagated_outlives_requirements.push(requirement); |
|
} |
|
} |
We loop over lower_bound_universal_regions of 'a, these are ['a, 'c].
Then for each of these regions we loop over their non_local_upper_bounds and propagate T: 'ub. Nothing special happens with 'abut it does with 'c. Its non_local_upper_bounds are ['a, 'b] and we thus propagate T: 'a and T: 'b, propagating T: 'b is incorrect and results in the above error.
I tried this code (credit to @lcnr):
This should compile fine, but instead this error is reported:
So what's happening here is that during the type test
T: 'awe have to propagate some requirements so we can prove the type test. This happens here:rust/compiler/rustc_borrowck/src/region_infer/mod.rs
Lines 712 to 736 in 13e2aba
We loop over
lower_bound_universal_regionsof'a, these are['a, 'c].Then for each of these regions we loop over their
non_local_upper_boundsand propagateT: 'ub. Nothing special happens with'abut it does with'c. Itsnon_local_upper_boundsare['a, 'b]and we thus propagateT: 'aandT: 'b, propagatingT: 'bis incorrect and results in the above error.