summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_trait_selection/src/traits/wf.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_trait_selection/src/traits/wf.rs')
-rw-r--r--compiler/rustc_trait_selection/src/traits/wf.rs111
1 files changed, 67 insertions, 44 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs
index 086ab32b5..d81722ce2 100644
--- a/compiler/rustc_trait_selection/src/traits/wf.rs
+++ b/compiler/rustc_trait_selection/src/traits/wf.rs
@@ -77,12 +77,19 @@ pub fn unnormalized_obligations<'tcx>(
param_env: ty::ParamEnv<'tcx>,
arg: GenericArg<'tcx>,
) -> Option<Vec<traits::PredicateObligation<'tcx>>> {
+ debug_assert_eq!(arg, infcx.resolve_vars_if_possible(arg));
+
+ // However, if `arg` IS an unresolved inference variable, returns `None`,
+ // because we are not able to make any progress at all. This is to prevent
+ // "livelock" where we say "$0 is WF if $0 is WF".
+ if arg.is_non_region_infer() {
+ return None;
+ }
+
if let ty::GenericArgKind::Lifetime(..) = arg.unpack() {
return Some(vec![]);
}
- debug_assert_eq!(arg, infcx.resolve_vars_if_possible(arg));
-
let mut wf = WfPredicates {
infcx,
param_env,
@@ -142,29 +149,32 @@ pub fn predicate_obligations<'tcx>(
// It's ok to skip the binder here because wf code is prepared for it
match predicate.kind().skip_binder() {
- ty::PredicateKind::Clause(ty::Clause::Trait(t)) => {
+ ty::PredicateKind::Clause(ty::ClauseKind::Trait(t)) => {
wf.compute_trait_pred(&t, Elaborate::None);
}
- ty::PredicateKind::Clause(ty::Clause::RegionOutlives(..)) => {}
- ty::PredicateKind::Clause(ty::Clause::TypeOutlives(ty::OutlivesPredicate(ty, _reg))) => {
+ ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(..)) => {}
+ ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(
+ ty,
+ _reg,
+ ))) => {
wf.compute(ty.into());
}
- ty::PredicateKind::Clause(ty::Clause::Projection(t)) => {
+ ty::PredicateKind::Clause(ty::ClauseKind::Projection(t)) => {
wf.compute_projection(t.projection_ty);
wf.compute(match t.term.unpack() {
ty::TermKind::Ty(ty) => ty.into(),
ty::TermKind::Const(c) => c.into(),
})
}
- ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(ct, ty)) => {
+ ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ty)) => {
wf.compute(ct.into());
wf.compute(ty.into());
}
- ty::PredicateKind::WellFormed(arg) => {
+ ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) => {
wf.compute(arg);
}
- ty::PredicateKind::ConstEvaluatable(ct) => {
+ ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(ct)) => {
wf.compute(ct.into());
}
@@ -174,8 +184,7 @@ pub fn predicate_obligations<'tcx>(
| ty::PredicateKind::Coerce(..)
| ty::PredicateKind::ConstEquate(..)
| ty::PredicateKind::Ambiguous
- | ty::PredicateKind::AliasRelate(..)
- | ty::PredicateKind::TypeWellFormedFromEnv(..) => {
+ | ty::PredicateKind::AliasRelate(..) => {
bug!("We should only wf check where clauses, unexpected predicate: {predicate:?}")
}
}
@@ -247,7 +256,7 @@ fn extend_cause_with_original_assoc_item_obligation<'tcx>(
// It is fine to skip the binder as we don't care about regions here.
match pred.kind().skip_binder() {
- ty::PredicateKind::Clause(ty::Clause::Projection(proj)) => {
+ ty::PredicateKind::Clause(ty::ClauseKind::Projection(proj)) => {
// The obligation comes not from the current `impl` nor the `trait` being implemented,
// but rather from a "second order" obligation, where an associated type has a
// projection coming from another associated type. See
@@ -264,7 +273,7 @@ fn extend_cause_with_original_assoc_item_obligation<'tcx>(
cause.span = impl_item_span;
}
}
- ty::PredicateKind::Clause(ty::Clause::Trait(pred)) => {
+ ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => {
// An associated item obligation born out of the `trait` failed to be met. An example
// can be seen in `ui/associated-types/point-at-type-on-obligation-failure-2.rs`.
debug!("extended_cause_with_original_assoc_item_obligation trait proj {:?}", pred);
@@ -293,6 +302,16 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
}
fn normalize(self, infcx: &InferCtxt<'tcx>) -> Vec<traits::PredicateObligation<'tcx>> {
+ // Do not normalize `wf` obligations with the new solver.
+ //
+ // The current deep normalization routine with the new solver does not
+ // handle ambiguity and the new solver correctly deals with unnnormalized goals.
+ // If the user relies on normalized types, e.g. for `fn implied_outlives_bounds`,
+ // it is their responsibility to normalize while avoiding ambiguity.
+ if infcx.next_trait_solver() {
+ return self.out;
+ }
+
let cause = self.cause(traits::WellFormed(None));
let param_env = self.param_env;
let mut obligations = Vec::with_capacity(self.out.len());
@@ -386,7 +405,9 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
cause,
depth,
param_env,
- ty::Binder::dummy(ty::PredicateKind::WellFormed(arg)),
+ ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(
+ arg,
+ ))),
)
}),
);
@@ -478,7 +499,9 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
cause.clone(),
depth,
param_env,
- ty::Binder::dummy(ty::PredicateKind::WellFormed(arg)),
+ ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(
+ arg,
+ ))),
)
}),
);
@@ -521,8 +544,9 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
let obligations = self.nominal_obligations(uv.def, uv.substs);
self.out.extend(obligations);
- let predicate =
- ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(ct));
+ let predicate = ty::Binder::dummy(ty::PredicateKind::Clause(
+ ty::ClauseKind::ConstEvaluatable(ct),
+ ));
let cause = self.cause(traits::WellFormed(None));
self.out.push(traits::Obligation::with_depth(
self.tcx(),
@@ -541,7 +565,9 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
cause,
self.recursion_depth,
self.param_env,
- ty::Binder::dummy(ty::PredicateKind::WellFormed(ct.into())),
+ ty::Binder::dummy(ty::PredicateKind::Clause(
+ ty::ClauseKind::WellFormed(ct.into()),
+ )),
));
}
ty::ConstKind::Expr(_) => {
@@ -552,8 +578,9 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
// the future we may allow directly lowering to `ConstKind::Expr` in which case
// we would not be proving bounds we should.
- let predicate =
- ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(ct));
+ let predicate = ty::Binder::dummy(ty::PredicateKind::Clause(
+ ty::ClauseKind::ConstEvaluatable(ct),
+ ));
let cause = self.cause(traits::WellFormed(None));
self.out.push(traits::Obligation::with_depth(
self.tcx(),
@@ -654,9 +681,9 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
cause,
depth,
param_env,
- ty::Binder::dummy(ty::PredicateKind::Clause(ty::Clause::TypeOutlives(
- ty::OutlivesPredicate(rty, r),
- ))),
+ ty::Binder::dummy(ty::PredicateKind::Clause(
+ ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(rty, r)),
+ )),
));
}
}
@@ -731,6 +758,11 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
}
}
+ ty::Alias(ty::Weak, ty::AliasTy { def_id, substs, .. }) => {
+ let obligations = self.nominal_obligations(def_id, substs);
+ self.out.extend(obligations);
+ }
+
ty::Dynamic(data, r, _) => {
// WfObject
//
@@ -779,7 +811,9 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
cause,
self.recursion_depth,
param_env,
- ty::Binder::dummy(ty::PredicateKind::WellFormed(ty.into())),
+ ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(
+ ty.into(),
+ ))),
));
}
}
@@ -918,7 +952,7 @@ pub fn object_region_bounds<'tcx>(
// Since we don't actually *know* the self type for an object,
// this "open(err)" serves as a kind of dummy standin -- basically
// a placeholder type.
- let open_ty = tcx.mk_fresh_ty(0);
+ let open_ty = Ty::new_fresh(tcx, 0);
let predicates = existential_predicates.iter().filter_map(|predicate| {
if let ty::ExistentialPredicate::Projection(_) = predicate.skip_binder() {
@@ -951,7 +985,7 @@ pub fn object_region_bounds<'tcx>(
pub(crate) fn required_region_bounds<'tcx>(
tcx: TyCtxt<'tcx>,
erased_self_ty: Ty<'tcx>,
- predicates: impl Iterator<Item = ty::Predicate<'tcx>>,
+ predicates: impl Iterator<Item = ty::Clause<'tcx>>,
) -> Vec<ty::Region<'tcx>> {
assert!(!erased_self_ty.has_escaping_bound_vars());
@@ -959,24 +993,7 @@ pub(crate) fn required_region_bounds<'tcx>(
.filter_map(|pred| {
debug!(?pred);
match pred.kind().skip_binder() {
- ty::PredicateKind::Clause(ty::Clause::Projection(..))
- | ty::PredicateKind::Clause(ty::Clause::Trait(..))
- | ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..))
- | ty::PredicateKind::Subtype(..)
- | ty::PredicateKind::Coerce(..)
- | ty::PredicateKind::WellFormed(..)
- | ty::PredicateKind::ObjectSafe(..)
- | ty::PredicateKind::ClosureKind(..)
- | ty::PredicateKind::Clause(ty::Clause::RegionOutlives(..))
- | ty::PredicateKind::ConstEvaluatable(..)
- | ty::PredicateKind::ConstEquate(..)
- | ty::PredicateKind::Ambiguous
- | ty::PredicateKind::AliasRelate(..)
- | ty::PredicateKind::TypeWellFormedFromEnv(..) => None,
- ty::PredicateKind::Clause(ty::Clause::TypeOutlives(ty::OutlivesPredicate(
- ref t,
- ref r,
- ))) => {
+ ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(ref t, ref r)) => {
// Search for a bound of the form `erased_self_ty
// : 'a`, but be wary of something like `for<'a>
// erased_self_ty : 'a` (we interpret a
@@ -992,6 +1009,12 @@ pub(crate) fn required_region_bounds<'tcx>(
None
}
}
+ ty::ClauseKind::Trait(_)
+ | ty::ClauseKind::RegionOutlives(_)
+ | ty::ClauseKind::Projection(_)
+ | ty::ClauseKind::ConstArgHasType(_, _)
+ | ty::ClauseKind::WellFormed(_)
+ | ty::ClauseKind::ConstEvaluatable(_) => None,
}
})
.collect()