Skip to content

Commit 8d1ad7b

Browse files
committed
wf: escaping bound var check to function
1 parent 4b3b731 commit 8d1ad7b

File tree

1 file changed

+25
-15
lines changed
  • compiler/rustc_trait_selection/src/traits

1 file changed

+25
-15
lines changed

compiler/rustc_trait_selection/src/traits/wf.rs

+25-15
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,20 @@ pub fn predicate_obligations<'tcx>(
168168
wf.normalize(infcx)
169169
}
170170

171+
/// Whether we should emit nested obligations containing `value`.
172+
/// This is a hack to deal with higher ranked types as we require implications
173+
/// in binders for a more correct implementation.
174+
///
175+
/// `WF(for<'a> fn(&'a T))` would otherwise emit a `T: 'a` bound for `&'a T`
176+
/// which would require `T: 'static`. What we actually want here is the type
177+
/// `for<'a> where { T: 'a } fn(&'a T)`, at which point the `T: 'a` bound is
178+
/// trivially implied from the `param_env`.
179+
///
180+
/// This means that we WF bounds aren't always sufficiently checked for now.
181+
fn emit_obligations_for<'tcx, T: TypeVisitable<'tcx>>(value: T) -> bool {
182+
!value.has_escaping_bound_vars()
183+
}
184+
171185
struct WfPredicates<'tcx> {
172186
tcx: TyCtxt<'tcx>,
173187
param_env: ty::ParamEnv<'tcx>,
@@ -280,7 +294,7 @@ impl<'tcx> WfPredicates<'tcx> {
280294
let param_env = self.param_env;
281295
let mut obligations = Vec::with_capacity(self.out.len());
282296
for mut obligation in self.out {
283-
assert!(!obligation.has_escaping_bound_vars());
297+
assert!(emit_obligations_for(obligation.predicate));
284298
let mut selcx = traits::SelectionContext::new(infcx);
285299
// Don't normalize the whole obligation, the param env is either
286300
// already normalized, or we're currently normalizing the
@@ -373,7 +387,7 @@ impl<'tcx> WfPredicates<'tcx> {
373387
.filter(|(_, arg)| {
374388
matches!(arg.unpack(), GenericArgKind::Type(..) | GenericArgKind::Const(..))
375389
})
376-
.filter(|(_, arg)| !arg.has_escaping_bound_vars())
390+
.filter(|&(_, arg)| emit_obligations_for(arg))
377391
.map(|(i, arg)| {
378392
let mut cause = traits::ObligationCause::misc(self.span, self.body_id);
379393
// The first subst is the self ty - use the correct span for it.
@@ -433,7 +447,7 @@ impl<'tcx> WfPredicates<'tcx> {
433447
.filter(|arg| {
434448
matches!(arg.unpack(), GenericArgKind::Type(..) | GenericArgKind::Const(..))
435449
})
436-
.filter(|arg| !arg.has_escaping_bound_vars())
450+
.filter(|&arg| emit_obligations_for(arg))
437451
.map(|arg| {
438452
traits::Obligation::with_depth(
439453
cause.clone(),
@@ -446,7 +460,7 @@ impl<'tcx> WfPredicates<'tcx> {
446460
}
447461

448462
fn require_sized(&mut self, subty: Ty<'tcx>, cause: traits::ObligationCauseCode<'tcx>) {
449-
if !subty.has_escaping_bound_vars() {
463+
if emit_obligations_for(subty) {
450464
let cause = self.cause(cause);
451465
let trait_ref = ty::TraitRef {
452466
def_id: self.tcx.require_lang_item(LangItem::Sized, None),
@@ -582,7 +596,7 @@ impl<'tcx> WfPredicates<'tcx> {
582596

583597
ty::Ref(r, rty, _) => {
584598
// WfReference
585-
if !r.has_escaping_bound_vars() && !rty.has_escaping_bound_vars() {
599+
if emit_obligations_for(r) && emit_obligations_for(rty) {
586600
let cause = self.cause(traits::ReferenceOutlivesReferent(ty));
587601
self.out.push(traits::Obligation::with_depth(
588602
cause,
@@ -755,7 +769,7 @@ impl<'tcx> WfPredicates<'tcx> {
755769
}
756770
traits::Obligation::with_depth(cause, self.recursion_depth, self.param_env, pred)
757771
})
758-
.filter(|pred| !pred.has_escaping_bound_vars())
772+
.filter(|obl| emit_obligations_for(obl.predicate))
759773
.collect()
760774
}
761775

@@ -812,7 +826,7 @@ impl<'tcx> WfPredicates<'tcx> {
812826
//
813827
// Note: in fact we only permit builtin traits, not `Bar<'d>`, I
814828
// am looking forward to the future here.
815-
if !data.has_escaping_bound_vars() && !region.has_escaping_bound_vars() {
829+
if emit_obligations_for(data) && emit_obligations_for(region) {
816830
let implicit_bounds = object_region_bounds(self.tcx, data);
817831

818832
let explicit_bound = region;
@@ -876,12 +890,12 @@ pub fn object_region_bounds<'tcx>(
876890
/// Requires that trait definitions have been processed so that we can
877891
/// elaborate predicates and walk supertraits.
878892
#[instrument(skip(tcx, predicates), level = "debug", ret)]
879-
pub(crate) fn required_region_bounds<'tcx>(
893+
fn required_region_bounds<'tcx>(
880894
tcx: TyCtxt<'tcx>,
881895
erased_self_ty: Ty<'tcx>,
882896
predicates: impl Iterator<Item = ty::Predicate<'tcx>>,
883897
) -> Vec<ty::Region<'tcx>> {
884-
assert!(!erased_self_ty.has_escaping_bound_vars());
898+
assert!(emit_obligations_for(erased_self_ty));
885899

886900
traits::elaborate_predicates(tcx, predicates)
887901
.filter_map(|obligation| {
@@ -898,7 +912,7 @@ pub(crate) fn required_region_bounds<'tcx>(
898912
| ty::PredicateKind::ConstEvaluatable(..)
899913
| ty::PredicateKind::ConstEquate(..)
900914
| ty::PredicateKind::TypeWellFormedFromEnv(..) => None,
901-
ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ref t, ref r)) => {
915+
ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(t, r)) => {
902916
// Search for a bound of the form `erased_self_ty
903917
// : 'a`, but be wary of something like `for<'a>
904918
// erased_self_ty : 'a` (we interpret a
@@ -908,11 +922,7 @@ pub(crate) fn required_region_bounds<'tcx>(
908922
// it's kind of a moot point since you could never
909923
// construct such an object, but this seems
910924
// correct even if that code changes).
911-
if t == &erased_self_ty && !r.has_escaping_bound_vars() {
912-
Some(*r)
913-
} else {
914-
None
915-
}
925+
if t == erased_self_ty && emit_obligations_for(r) { Some(r) } else { None }
916926
}
917927
}
918928
})

0 commit comments

Comments
 (0)