diff options
Diffstat (limited to 'compiler/rustc_trait_selection/src/traits/wf.rs')
-rw-r--r-- | compiler/rustc_trait_selection/src/traits/wf.rs | 111 |
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() |