Skip to content

Commit e176496

Browse files
Satisfy higher-ranked type outlives predicates with ones in the param-env
1 parent 37a4225 commit e176496

File tree

8 files changed

+64
-70
lines changed

8 files changed

+64
-70
lines changed

compiler/rustc_infer/src/infer/mod.rs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1049,6 +1049,45 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
10491049
})
10501050
}
10511051

1052+
// Attempts to satisfy a type outlives predicate that is instantiated with
1053+
// a placeholder by using a higher-ranked type outlives caller bound.
1054+
pub fn type_outlives_predicate_from_param_env(
1055+
&self,
1056+
cause: &traits::ObligationCause<'tcx>,
1057+
param_env: ty::ParamEnv<'tcx>,
1058+
ty: Ty<'tcx>,
1059+
region: ty::Region<'tcx>,
1060+
) -> Option<Vec<traits::PredicateObligation<'tcx>>> {
1061+
// Only attempt to satisfy placeholder-replaced higher-ranked outlives
1062+
if !region.is_placeholder() {
1063+
return None;
1064+
}
1065+
1066+
for caller_bound in param_env.caller_bounds() {
1067+
// Only use WC bounds that are themselves of the form `for<'a> TY: 'a`
1068+
if let ty::PredicateKind::TypeOutlives(bound_outlives) =
1069+
caller_bound.kind().skip_binder()
1070+
&& bound_outlives.1.is_late_bound()
1071+
{
1072+
if let Ok(obligations) = self.commit_if_ok::<_, TypeError<'_>, _>(|_| {
1073+
let ty::OutlivesPredicate(wc_ty, wc_region) = self.replace_bound_vars_with_fresh_vars(
1074+
cause.span,
1075+
LateBoundRegionConversionTime::HigherRankedType,
1076+
caller_bound.kind().rebind(bound_outlives),
1077+
);
1078+
let t = self.at(cause, param_env).sub(wc_ty, ty)?;
1079+
let mut r = self.at(cause, param_env).eq(wc_region, region)?;
1080+
r.obligations.extend(t.into_obligations());
1081+
Ok(r.obligations)
1082+
}) {
1083+
return Some(obligations);
1084+
}
1085+
}
1086+
}
1087+
1088+
None
1089+
}
1090+
10521091
/// Number of type variables created so far.
10531092
pub fn num_ty_vars(&self) -> usize {
10541093
self.inner.borrow_mut().type_variables().num_vars()

compiler/rustc_trait_selection/src/traits/fulfill.rs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -432,13 +432,17 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> {
432432
}
433433
}
434434

435-
ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(t_a, r_b)) => {
435+
ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(t_a, r_a)) => {
436436
if self.register_region_obligations {
437-
self.selcx.infcx().register_region_obligation_with_cause(
438-
t_a,
439-
r_b,
437+
if let Some(obligations) = infcx.type_outlives_predicate_from_param_env(
440438
&obligation.cause,
441-
);
439+
obligation.param_env,
440+
t_a,
441+
r_a,
442+
) {
443+
return ProcessResult::Changed(mk_pending(obligations));
444+
}
445+
infcx.register_region_obligation_with_cause(t_a, r_a, &obligation.cause);
442446
}
443447
ProcessResult::Changed(vec![])
444448
}

src/test/ui/generic-associated-types/issue-86483.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,12 @@
22

33
#![feature(generic_associated_types)]
44

5-
pub trait IceIce<T> //~ ERROR: the parameter type `T` may not live long enough
5+
pub trait IceIce<T>
66
where
77
for<'a> T: 'a,
88
{
99
type Ice<'v>: IntoIterator<Item = &'v T>;
1010
//~^ ERROR: the parameter type `T` may not live long enough
11-
//~| ERROR: the parameter type `T` may not live long enough
1211
}
1312

1413
fn main() {}
Lines changed: 1 addition & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,3 @@
1-
error[E0311]: the parameter type `T` may not live long enough
2-
--> $DIR/issue-86483.rs:5:1
3-
|
4-
LL | / pub trait IceIce<T>
5-
LL | | where
6-
LL | | for<'a> T: 'a,
7-
LL | | {
8-
... |
9-
LL | |
10-
LL | | }
11-
| |_^
12-
|
13-
= note: ...so that the type `T` will meet its required lifetime bounds...
14-
note: ...that is required by this bound
15-
--> $DIR/issue-86483.rs:7:16
16-
|
17-
LL | for<'a> T: 'a,
18-
| ^^
19-
help: consider adding an explicit lifetime bound...
20-
|
21-
LL | for<'a> T: 'a + 'a,
22-
| ++++
23-
24-
error[E0311]: the parameter type `T` may not live long enough
25-
--> $DIR/issue-86483.rs:9:5
26-
|
27-
LL | type Ice<'v>: IntoIterator<Item = &'v T>;
28-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds...
29-
|
30-
note: ...that is required by this bound
31-
--> $DIR/issue-86483.rs:7:16
32-
|
33-
LL | for<'a> T: 'a,
34-
| ^^
35-
help: consider adding an explicit lifetime bound...
36-
|
37-
LL | for<'a> T: 'a + 'a,
38-
| ++++
39-
401
error[E0309]: the parameter type `T` may not live long enough
412
--> $DIR/issue-86483.rs:9:32
423
|
@@ -45,6 +6,6 @@ LL | type Ice<'v>: IntoIterator<Item = &'v T>;
456
| |
467
| ...so that the reference type `&'v T` does not outlive the data it points at
478

48-
error: aborting due to 3 previous errors
9+
error: aborting due to previous error
4910

5011
For more information about this error, try `rustc --explain E0309`.

src/test/ui/generic-associated-types/issue-88360.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ where
1313
{
1414
fn copy(&self) -> Self::Gat<'_> where T: Copy {
1515
*self.test()
16-
//~^ mismatched types
16+
//~^ ERROR mismatched types
1717
}
1818
}
1919

src/test/ui/higher-rank-trait-bounds/issue-88586-hr-self-outlives-in-trait-def.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
1+
// check-pass
2+
13
// Regression test for #88586: a higher-ranked outlives bound on Self in a trait
24
// definition caused an ICE when debug_assertions were enabled.
3-
//
4-
// FIXME: The error output in the absence of the ICE is unhelpful; this should be improved.
55

66
trait A where for<'a> Self: 'a
7-
//~^ ERROR the parameter type `Self` may not live long enough
87
{
98
}
109

src/test/ui/higher-rank-trait-bounds/issue-88586-hr-self-outlives-in-trait-def.stderr

Lines changed: 0 additions & 19 deletions
This file was deleted.

src/test/ui/hrtb/issue-97607.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// check-pass
2+
3+
fn test<T, F, U>(f: F) -> Box<dyn Fn(T) -> U + 'static>
4+
where
5+
F: 'static + Fn(T) -> U,
6+
for<'a> U: 'a, // < This is the problematic line -- remove it, and it passes.
7+
{
8+
Box::new(move |t| f(t))
9+
}
10+
11+
fn main() {}

0 commit comments

Comments
 (0)