-
-
Notifications
You must be signed in to change notification settings - Fork 14.7k
Open
Labels
A-borrow-checkerArea: The borrow checkerArea: The borrow checkerA-closuresArea: Closures (`|…| { … }`)Area: Closures (`|…| { … }`)A-higher-rankedArea: Higher-ranked things (e.g., lifetimes, types, trait bounds aka HRTBs)Area: Higher-ranked things (e.g., lifetimes, types, trait bounds aka HRTBs)A-lifetimesArea: Lifetimes / regionsArea: Lifetimes / regionsC-bugCategory: This is a bug.Category: This is a bug.T-typesRelevant to the types team, which will review and decide on the PR/issue.Relevant to the types team, which will review and decide on the PR/issue.
Description
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:
rust/compiler/rustc_borrowck/src/region_infer/mod.rs
Lines 712 to 736 in 13e2aba
| 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.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
A-borrow-checkerArea: The borrow checkerArea: The borrow checkerA-closuresArea: Closures (`|…| { … }`)Area: Closures (`|…| { … }`)A-higher-rankedArea: Higher-ranked things (e.g., lifetimes, types, trait bounds aka HRTBs)Area: Higher-ranked things (e.g., lifetimes, types, trait bounds aka HRTBs)A-lifetimesArea: Lifetimes / regionsArea: Lifetimes / regionsC-bugCategory: This is a bug.Category: This is a bug.T-typesRelevant to the types team, which will review and decide on the PR/issue.Relevant to the types team, which will review and decide on the PR/issue.
Type
Fields
Give feedbackNo fields configured for issues without a type.