Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Eagerly drop higher-ranked type outlives obligations if satisfied by param env #98034

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 56 additions & 0 deletions compiler/rustc_infer/src/infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1049,6 +1049,62 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
})
}

// Attempts to satisfy a type outlives predicate that is instantiated with
// a placeholder by using a higher-ranked type outlives caller bound.
pub fn type_outlives_predicate_from_param_env(
&self,
cause: &traits::ObligationCause<'tcx>,
param_env: ty::ParamEnv<'tcx>,
ty: Ty<'tcx>,
region: ty::Region<'tcx>,
) -> Option<Vec<traits::PredicateObligation<'tcx>>> {
if ty.is_ty_infer() {
return None;
}

for caller_bound in param_env.caller_bounds() {
let ty::PredicateKind::TypeOutlives(bound_outlives) =
caller_bound.kind().skip_binder() else { continue };

// Only use WC bounds that are themselves of the form `for<'a> TY: 'a`
if !bound_outlives.1.is_late_bound() {
continue;
}

let satisfies = self.commit_if_ok::<_, (), _>(|_| {
let ty::OutlivesPredicate(wc_ty, wc_region) = self
.replace_bound_vars_with_fresh_vars(
cause.span,
LateBoundRegionConversionTime::HigherRankedType,
caller_bound.kind().rebind(bound_outlives),
);

let mut r = self.at(cause, param_env).eq(wc_region, region).map_err(|_| ())?;

// Specifically use two snapshots here, so we can make sure _not_
// to constrain the regions of `Ty` here. We probably should just
// use some custom `replace_bound_vars_with_fresh_vars` that doesn't
// replace `wc_region` with an infer variable, but eagerly replaces
// it with `region` instead.
self.commit_if_ok::<_, (), _>(|snapshot| {
let t = self.at(cause, param_env).eq(wc_ty, ty).map_err(|_| ())?;
r.obligations.extend(t.into_obligations());
if self.region_constraints_added_in_snapshot(snapshot).is_none() {
Ok(r.obligations)
} else {
Err(())
}
})
});

if let Ok(obligations) = satisfies {
return Some(obligations);
}
}

None
}

/// Number of type variables created so far.
pub fn num_ty_vars(&self) -> usize {
self.inner.borrow_mut().type_variables().num_vars()
Expand Down
14 changes: 9 additions & 5 deletions compiler/rustc_trait_selection/src/traits/fulfill.rs
Original file line number Diff line number Diff line change
Expand Up @@ -432,13 +432,17 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> {
}
}

ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(t_a, r_b)) => {
ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(t_a, r_a)) => {
if self.register_region_obligations {
self.selcx.infcx().register_region_obligation_with_cause(
t_a,
r_b,
if let Some(obligations) = infcx.type_outlives_predicate_from_param_env(
&obligation.cause,
);
obligation.param_env,
t_a,
r_a,
) {
return ProcessResult::Changed(mk_pending(obligations));
}
infcx.register_region_obligation_with_cause(t_a, r_a, &obligation.cause);
}
ProcessResult::Changed(vec![])
}
Expand Down
5 changes: 2 additions & 3 deletions src/test/ui/generic-associated-types/issue-86483.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
// Regression test of #86483.
// check-pass

#![feature(generic_associated_types)]

pub trait IceIce<T> //~ ERROR: the parameter type `T` may not live long enough
pub trait IceIce<T>
where
for<'a> T: 'a,
{
type Ice<'v>: IntoIterator<Item = &'v T>;
//~^ ERROR: the parameter type `T` may not live long enough
//~| ERROR: the parameter type `T` may not live long enough
}

fn main() {}
50 changes: 0 additions & 50 deletions src/test/ui/generic-associated-types/issue-86483.stderr

This file was deleted.

2 changes: 1 addition & 1 deletion src/test/ui/generic-associated-types/issue-88360.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ where
{
fn copy(&self) -> Self::Gat<'_> where T: Copy {
*self.test()
//~^ mismatched types
//~^ ERROR mismatched types
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
// check-pass

// Regression test for #88586: a higher-ranked outlives bound on Self in a trait
// definition caused an ICE when debug_assertions were enabled.
//
// FIXME: The error output in the absence of the ICE is unhelpful; this should be improved.

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

Expand Down

This file was deleted.

11 changes: 11 additions & 0 deletions src/test/ui/hrtb/issue-97607.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// check-pass

fn test<T, F, U>(f: F) -> Box<dyn Fn(T) -> U + 'static>
where
F: 'static + Fn(T) -> U,
for<'a> U: 'a, // < This is the problematic line -- remove it, and it passes.
{
Box::new(move |t| f(t))
}

fn main() {}