Skip to content

Commit 835fc8a

Browse files
committed
Be more conservative about discarding bounds
1 parent fdad385 commit 835fc8a

File tree

1 file changed

+37
-2
lines changed
  • compiler/rustc_trait_selection/src/traits/select

1 file changed

+37
-2
lines changed

compiler/rustc_trait_selection/src/traits/select/mod.rs

+37-2
Original file line numberDiff line numberDiff line change
@@ -733,12 +733,47 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
733733
.caller_bounds()
734734
.iter()
735735
.filter(|bound| match bound.kind().skip_binder() {
736-
ty::PredicateKind::RegionOutlives(_) | ty::PredicateKind::TypeOutlives(_) => {
737-
false
736+
predicate @ ty::PredicateKind::RegionOutlives(_) => {
737+
// A bound involving early-bound regions
738+
// (e.g. `fn foo<'a, 'b>() where 'a: 'b or
739+
// `fn bar<'a>() where 'a: 'static
740+
//)
741+
// cannot affect the evaluation of a predicate with no
742+
// free regions. Such a predicate only gives us information
743+
// about some specific caller-chosen lifetime, and does not
744+
// give us any information about any bound regions within
745+
// our predicate (e.g. `for<'a> T: MyTrait<'a>`). Since
746+
// we checked above that our predicate does not include any
747+
// free regions (which includes early-bound regions), we know
748+
// that it's safe to discard a predicate involving only
749+
// early-bound regions.
750+
//
751+
// If a `RegionOutLives` predicate has any late-bound regions,
752+
// we choose to keep it. This might be overly conservative,
753+
// but should be safe in all cases.
754+
predicate.has_late_bound_regions()
738755
}
756+
// If we have a predicate like `T: 'static`, then we need to keep
757+
// it, since it could legitimately affect the evaluation of our predicate.
758+
// For exmaple, we could be evaluating `T: MyTrait`, and find
759+
// `impl<T: 'static> MyTrait for T {}`.
760+
//
761+
// We also keep any `TypeOutlives` predicates involving any late-bound
762+
// regions. This is probably overly conservative, but ensures that we don't
763+
// run into any weird situations with impossible-to-satisfiy predicates
764+
// (e.g. `for<'a> &'a u8: 'static).
765+
predicate @ ty::PredicateKind::TypeOutlives(outlives) => {
766+
*outlives.1 == ty::ReStatic || predicate.has_late_bound_regions()
767+
}
768+
// We assume that all other bounds can potentially affect
769+
// the evaluation of our predicates, so we keep them
739770
_ => true,
740771
})
741772
.collect();
773+
774+
// Replace the `ParamEnv` with a new one, which differs
775+
// only be the removal of some of the caller bounds. This will
776+
// allow us to use the global cache in more cases.
742777
obligation.param_env = ty::ParamEnv::new(
743778
self.tcx().intern_predicates(&new_bounds),
744779
obligation.param_env.reveal(),

0 commit comments

Comments
 (0)