diff options
Diffstat (limited to 'compiler/rustc_trait_selection/src/traits/wf.rs')
-rw-r--r-- | compiler/rustc_trait_selection/src/traits/wf.rs | 102 |
1 files changed, 67 insertions, 35 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index fc0a9f690..681fb753f 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -4,7 +4,7 @@ use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::lang_items::LangItem; use rustc_middle::ty::subst::{GenericArg, GenericArgKind, SubstsRef}; -use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, TypeVisitable}; +use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitable}; use rustc_span::Span; use std::iter; @@ -121,14 +121,14 @@ 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::Trait(t) => { + ty::PredicateKind::Clause(ty::Clause::Trait(t)) => { wf.compute_trait_pred(&t, Elaborate::None); } - ty::PredicateKind::RegionOutlives(..) => {} - ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ty, _reg)) => { + ty::PredicateKind::Clause(ty::Clause::RegionOutlives(..)) => {} + ty::PredicateKind::Clause(ty::Clause::TypeOutlives(ty::OutlivesPredicate(ty, _reg))) => { wf.compute(ty.into()); } - ty::PredicateKind::Projection(t) => { + ty::PredicateKind::Clause(ty::Clause::Projection(t)) => { wf.compute_projection(t.projection_ty); wf.compute(match t.term.unpack() { ty::TermKind::Ty(ty) => ty.into(), @@ -155,6 +155,7 @@ pub fn predicate_obligations<'tcx>( wf.compute(c1.into()); wf.compute(c2.into()); } + ty::PredicateKind::Ambiguous => {} ty::PredicateKind::TypeWellFormedFromEnv(..) => { bug!("TypeWellFormedFromEnv is only used for Chalk") } @@ -227,7 +228,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::Projection(proj) => { + ty::PredicateKind::Clause(ty::Clause::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 @@ -244,7 +245,7 @@ fn extend_cause_with_original_assoc_item_obligation<'tcx>( cause.span = impl_item_span; } } - ty::PredicateKind::Trait(pred) => { + ty::PredicateKind::Clause(ty::Clause::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); @@ -324,7 +325,7 @@ impl<'tcx> WfPredicates<'tcx> { extend_cause_with_original_assoc_item_obligation( tcx, trait_ref, item, &mut cause, predicate, ); - traits::Obligation::with_depth(cause, depth, param_env, predicate) + traits::Obligation::with_depth(tcx, cause, depth, param_env, predicate) }; if let Elaborate::All = elaborate { @@ -356,10 +357,11 @@ impl<'tcx> WfPredicates<'tcx> { } } traits::Obligation::with_depth( + tcx, cause, depth, param_env, - ty::Binder::dummy(ty::PredicateKind::WellFormed(arg)).to_predicate(tcx), + ty::Binder::dummy(ty::PredicateKind::WellFormed(arg)), ) }), ); @@ -407,10 +409,11 @@ impl<'tcx> WfPredicates<'tcx> { .filter(|arg| !arg.has_escaping_bound_vars()) .map(|arg| { traits::Obligation::with_depth( + tcx, cause.clone(), depth, param_env, - ty::Binder::dummy(ty::PredicateKind::WellFormed(arg)).to_predicate(tcx), + ty::Binder::dummy(ty::PredicateKind::WellFormed(arg)), ) }), ); @@ -419,15 +422,13 @@ impl<'tcx> WfPredicates<'tcx> { fn require_sized(&mut self, subty: Ty<'tcx>, cause: traits::ObligationCauseCode<'tcx>) { if !subty.has_escaping_bound_vars() { let cause = self.cause(cause); - let trait_ref = ty::TraitRef { - def_id: self.tcx.require_lang_item(LangItem::Sized, None), - substs: self.tcx.mk_substs_trait(subty, &[]), - }; + let trait_ref = self.tcx.at(cause.span).mk_trait_ref(LangItem::Sized, [subty]); self.out.push(traits::Obligation::with_depth( + self.tcx, cause, self.recursion_depth, self.param_env, - ty::Binder::dummy(trait_ref).without_const().to_predicate(self.tcx), + ty::Binder::dummy(trait_ref).without_const(), )); } } @@ -454,10 +455,10 @@ impl<'tcx> WfPredicates<'tcx> { self.out.extend(obligations); let predicate = - ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(ct)) - .to_predicate(self.tcx()); + ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(ct)); let cause = self.cause(traits::WellFormed(None)); self.out.push(traits::Obligation::with_depth( + self.tcx(), cause, self.recursion_depth, self.param_env, @@ -468,13 +469,33 @@ impl<'tcx> WfPredicates<'tcx> { let cause = self.cause(traits::WellFormed(None)); self.out.push(traits::Obligation::with_depth( + self.tcx(), cause, self.recursion_depth, self.param_env, - ty::Binder::dummy(ty::PredicateKind::WellFormed(ct.into())) - .to_predicate(self.tcx()), + ty::Binder::dummy(ty::PredicateKind::WellFormed(ct.into())), )); } + ty::ConstKind::Expr(_) => { + // FIXME(generic_const_exprs): this doesnt verify that given `Expr(N + 1)` the + // trait bound `typeof(N): Add<typeof(1)>` holds. This is currently unnecessary + // as `ConstKind::Expr` is only produced via normalization of `ConstKind::Unevaluated` + // which means that the `DefId` would have been typeck'd elsewhere. However in + // 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 cause = self.cause(traits::WellFormed(None)); + self.out.push(traits::Obligation::with_depth( + self.tcx(), + cause, + self.recursion_depth, + self.param_env, + predicate, + )); + } + ty::ConstKind::Error(_) | ty::ConstKind::Param(_) | ty::ConstKind::Bound(..) @@ -556,13 +577,13 @@ impl<'tcx> WfPredicates<'tcx> { if !r.has_escaping_bound_vars() && !rty.has_escaping_bound_vars() { let cause = self.cause(traits::ReferenceOutlivesReferent(ty)); self.out.push(traits::Obligation::with_depth( + self.tcx(), cause, depth, param_env, - ty::Binder::dummy(ty::PredicateKind::TypeOutlives( + ty::Binder::dummy(ty::PredicateKind::Clause(ty::Clause::TypeOutlives( ty::OutlivesPredicate(rty, r), - )) - .to_predicate(self.tcx()), + ))), )); } } @@ -631,7 +652,7 @@ impl<'tcx> WfPredicates<'tcx> { // All of the requirements on type parameters // have already been checked for `impl Trait` in // return position. We do need to check type-alias-impl-trait though. - if ty::is_impl_trait_defn(self.tcx, did).is_none() { + if self.tcx.is_type_alias_impl_trait(did) { let obligations = self.nominal_obligations(did, substs); self.out.extend(obligations); } @@ -656,11 +677,11 @@ impl<'tcx> WfPredicates<'tcx> { let tcx = self.tcx(); self.out.extend(component_traits.map(|did| { traits::Obligation::with_depth( + tcx, cause.clone(), depth, param_env, - ty::Binder::dummy(ty::PredicateKind::ObjectSafe(did)) - .to_predicate(tcx), + ty::Binder::dummy(ty::PredicateKind::ObjectSafe(did)), ) })); } @@ -681,11 +702,11 @@ impl<'tcx> WfPredicates<'tcx> { ty::Infer(_) => { let cause = self.cause(traits::WellFormed(None)); self.out.push(traits::Obligation::with_depth( + self.tcx(), cause, self.recursion_depth, param_env, - ty::Binder::dummy(ty::PredicateKind::WellFormed(ty.into())) - .to_predicate(self.tcx()), + ty::Binder::dummy(ty::PredicateKind::WellFormed(ty.into())), )); } } @@ -724,7 +745,13 @@ impl<'tcx> WfPredicates<'tcx> { if remap_constness { pred = pred.without_const(self.tcx); } - traits::Obligation::with_depth(cause, self.recursion_depth, self.param_env, pred) + traits::Obligation::with_depth( + self.tcx, + cause, + self.recursion_depth, + self.param_env, + pred, + ) }) .filter(|pred| !pred.has_escaping_bound_vars()) .collect() @@ -749,7 +776,7 @@ impl<'tcx> WfPredicates<'tcx> { fn from_object_ty( &mut self, ty: Ty<'tcx>, - data: &'tcx ty::List<ty::Binder<'tcx, ty::ExistentialPredicate<'tcx>>>, + data: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>, region: ty::Region<'tcx>, ) { // Imagine a type like this: @@ -794,10 +821,11 @@ impl<'tcx> WfPredicates<'tcx> { let outlives = ty::Binder::dummy(ty::OutlivesPredicate(explicit_bound, implicit_bound)); self.out.push(traits::Obligation::with_depth( + self.tcx, cause, self.recursion_depth, self.param_env, - outlives.to_predicate(self.tcx), + outlives, )); } } @@ -812,7 +840,7 @@ impl<'tcx> WfPredicates<'tcx> { /// `infer::required_region_bounds`, see that for more information. pub fn object_region_bounds<'tcx>( tcx: TyCtxt<'tcx>, - existential_predicates: &'tcx ty::List<ty::Binder<'tcx, ty::ExistentialPredicate<'tcx>>>, + existential_predicates: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>, ) -> Vec<ty::Region<'tcx>> { // Since we don't actually *know* the self type for an object, // this "open(err)" serves as a kind of dummy standin -- basically @@ -858,18 +886,22 @@ pub(crate) fn required_region_bounds<'tcx>( .filter_map(|obligation| { debug!(?obligation); match obligation.predicate.kind().skip_binder() { - ty::PredicateKind::Projection(..) - | ty::PredicateKind::Trait(..) + ty::PredicateKind::Clause(ty::Clause::Projection(..)) + | ty::PredicateKind::Clause(ty::Clause::Trait(..)) | ty::PredicateKind::Subtype(..) | ty::PredicateKind::Coerce(..) | ty::PredicateKind::WellFormed(..) | ty::PredicateKind::ObjectSafe(..) | ty::PredicateKind::ClosureKind(..) - | ty::PredicateKind::RegionOutlives(..) + | ty::PredicateKind::Clause(ty::Clause::RegionOutlives(..)) | ty::PredicateKind::ConstEvaluatable(..) | ty::PredicateKind::ConstEquate(..) + | ty::PredicateKind::Ambiguous | ty::PredicateKind::TypeWellFormedFromEnv(..) => None, - ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ref t, ref r)) => { + ty::PredicateKind::Clause(ty::Clause::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 |