diff options
Diffstat (limited to '')
-rw-r--r-- | compiler/rustc_traits/src/type_op.rs | 229 |
1 files changed, 71 insertions, 158 deletions
diff --git a/compiler/rustc_traits/src/type_op.rs b/compiler/rustc_traits/src/type_op.rs index bca7458ed..7f964afde 100644 --- a/compiler/rustc_traits/src/type_op.rs +++ b/compiler/rustc_traits/src/type_op.rs @@ -1,26 +1,21 @@ use rustc_hir as hir; -use rustc_hir::def_id::DefId; -use rustc_infer::infer::at::ToTrace; use rustc_infer::infer::canonical::{Canonical, QueryResponse}; -use rustc_infer::infer::{DefiningAnchor, InferCtxt, TyCtxtInferExt}; -use rustc_infer::traits::{ObligationCauseCode, TraitEngineExt as _}; +use rustc_infer::infer::{DefiningAnchor, TyCtxtInferExt}; +use rustc_infer::traits::ObligationCauseCode; use rustc_middle::ty::query::Providers; -use rustc_middle::ty::{ - self, EarlyBinder, FnSig, Lift, PolyFnSig, Ty, TyCtxt, TypeFoldable, Variance, -}; -use rustc_middle::ty::{GenericArg, UserSelfTy, UserSubsts}; -use rustc_middle::ty::{ParamEnv, ParamEnvAnd, Predicate, ToPredicate}; +use rustc_middle::ty::{self, FnSig, Lift, PolyFnSig, Ty, TyCtxt, TypeFoldable}; +use rustc_middle::ty::{ParamEnvAnd, Predicate, ToPredicate}; +use rustc_middle::ty::{UserSelfTy, UserSubsts}; use rustc_span::{Span, DUMMY_SP}; use rustc_trait_selection::infer::InferCtxtBuilderExt; -use rustc_trait_selection::infer::InferCtxtExt; -use rustc_trait_selection::traits::query::normalize::AtExt; +use rustc_trait_selection::traits::query::normalize::QueryNormalizeExt; use rustc_trait_selection::traits::query::type_op::ascribe_user_type::AscribeUserType; use rustc_trait_selection::traits::query::type_op::eq::Eq; use rustc_trait_selection::traits::query::type_op::normalize::Normalize; use rustc_trait_selection::traits::query::type_op::prove_predicate::ProvePredicate; use rustc_trait_selection::traits::query::type_op::subtype::Subtype; use rustc_trait_selection::traits::query::{Fallible, NoSolution}; -use rustc_trait_selection::traits::{Normalized, Obligation, ObligationCause, TraitEngine}; +use rustc_trait_selection::traits::{Normalized, Obligation, ObligationCause, ObligationCtxt}; use std::fmt; use std::iter::zip; @@ -42,17 +37,16 @@ fn type_op_ascribe_user_type<'tcx>( tcx: TyCtxt<'tcx>, canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, AscribeUserType<'tcx>>>, ) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, ()>>, NoSolution> { - tcx.infer_ctxt().enter_canonical_trait_query(&canonicalized, |infcx, fulfill_cx, key| { - type_op_ascribe_user_type_with_span(infcx, fulfill_cx, key, None) + tcx.infer_ctxt().enter_canonical_trait_query(&canonicalized, |ocx, key| { + type_op_ascribe_user_type_with_span(ocx, key, None) }) } /// The core of the `type_op_ascribe_user_type` query: for diagnostics purposes in NLL HRTB errors, /// this query can be re-run to better track the span of the obligation cause, and improve the error /// message. Do not call directly unless you're in that very specific context. -pub fn type_op_ascribe_user_type_with_span<'a, 'tcx: 'a>( - infcx: &'a InferCtxt<'tcx>, - fulfill_cx: &'a mut dyn TraitEngine<'tcx>, +pub fn type_op_ascribe_user_type_with_span<'tcx>( + ocx: &ObligationCtxt<'_, 'tcx>, key: ParamEnvAnd<'tcx, AscribeUserType<'tcx>>, span: Option<Span>, ) -> Result<(), NoSolution> { @@ -61,157 +55,81 @@ pub fn type_op_ascribe_user_type_with_span<'a, 'tcx: 'a>( "type_op_ascribe_user_type: mir_ty={:?} def_id={:?} user_substs={:?}", mir_ty, def_id, user_substs ); + let span = span.unwrap_or(DUMMY_SP); - let mut cx = AscribeUserTypeCx { infcx, param_env, span: span.unwrap_or(DUMMY_SP), fulfill_cx }; - cx.relate_mir_and_user_ty(mir_ty, def_id, user_substs)?; - Ok(()) -} + let UserSubsts { user_self_ty, substs } = user_substs; + let tcx = ocx.infcx.tcx; + let cause = ObligationCause::dummy_with_span(span); -struct AscribeUserTypeCx<'me, 'tcx> { - infcx: &'me InferCtxt<'tcx>, - param_env: ParamEnv<'tcx>, - span: Span, - fulfill_cx: &'me mut dyn TraitEngine<'tcx>, -} + let ty = tcx.bound_type_of(def_id).subst(tcx, substs); + let ty = ocx.normalize(&cause, param_env, ty); + debug!("relate_type_and_user_type: ty of def-id is {:?}", ty); -impl<'me, 'tcx> AscribeUserTypeCx<'me, 'tcx> { - fn normalize<T>(&mut self, value: T) -> T - where - T: TypeFoldable<'tcx>, - { - self.normalize_with_cause(value, ObligationCause::misc(self.span, hir::CRATE_HIR_ID)) - } + ocx.eq(&cause, param_env, mir_ty, ty)?; - fn normalize_with_cause<T>(&mut self, value: T, cause: ObligationCause<'tcx>) -> T - where - T: TypeFoldable<'tcx>, - { - self.infcx - .partially_normalize_associated_types_in(cause, self.param_env, value) - .into_value_registering_obligations(self.infcx, self.fulfill_cx) - } + // Prove the predicates coming along with `def_id`. + // + // Also, normalize the `instantiated_predicates` + // because otherwise we wind up with duplicate "type + // outlives" error messages. + let instantiated_predicates = tcx.predicates_of(def_id).instantiate(tcx, substs); - fn relate<T>(&mut self, a: T, variance: Variance, b: T) -> Result<(), NoSolution> - where - T: ToTrace<'tcx>, + debug!(?instantiated_predicates); + for (instantiated_predicate, predicate_span) in + zip(instantiated_predicates.predicates, instantiated_predicates.spans) { - self.infcx - .at(&ObligationCause::dummy_with_span(self.span), self.param_env) - .relate(a, variance, b)? - .into_value_registering_obligations(self.infcx, self.fulfill_cx); - Ok(()) - } - - fn prove_predicate(&mut self, predicate: Predicate<'tcx>, cause: ObligationCause<'tcx>) { - self.fulfill_cx.register_predicate_obligation( - self.infcx, - Obligation::new(cause, self.param_env, predicate), + let span = if span == DUMMY_SP { predicate_span } else { span }; + let cause = ObligationCause::new( + span, + hir::CRATE_HIR_ID, + ObligationCauseCode::AscribeUserTypeProvePredicate(predicate_span), ); - } + let instantiated_predicate = + ocx.normalize(&cause.clone(), param_env, instantiated_predicate); - fn tcx(&self) -> TyCtxt<'tcx> { - self.infcx.tcx + ocx.register_obligation(Obligation::new(tcx, cause, param_env, instantiated_predicate)); } - fn subst<T>(&self, value: T, substs: &[GenericArg<'tcx>]) -> T - where - T: TypeFoldable<'tcx>, - { - EarlyBinder(value).subst(self.tcx(), substs) - } + if let Some(UserSelfTy { impl_def_id, self_ty }) = user_self_ty { + let impl_self_ty = tcx.bound_type_of(impl_def_id).subst(tcx, substs); + let impl_self_ty = ocx.normalize(&cause, param_env, impl_self_ty); - #[instrument(level = "debug", skip(self))] - fn relate_mir_and_user_ty( - &mut self, - mir_ty: Ty<'tcx>, - def_id: DefId, - user_substs: UserSubsts<'tcx>, - ) -> Result<(), NoSolution> { - let UserSubsts { user_self_ty, substs } = user_substs; - let tcx = self.tcx(); + ocx.eq(&cause, param_env, self_ty, impl_self_ty)?; - let ty = tcx.type_of(def_id); - let ty = self.subst(ty, substs); - let ty = self.normalize(ty); - debug!("relate_type_and_user_type: ty of def-id is {:?}", ty); - - self.relate(mir_ty, Variance::Invariant, ty)?; - - // Prove the predicates coming along with `def_id`. - // - // Also, normalize the `instantiated_predicates` - // because otherwise we wind up with duplicate "type - // outlives" error messages. - let instantiated_predicates = - self.tcx().predicates_of(def_id).instantiate(self.tcx(), substs); - - let cause = ObligationCause::dummy_with_span(self.span); - - debug!(?instantiated_predicates); - for (instantiated_predicate, predicate_span) in - zip(instantiated_predicates.predicates, instantiated_predicates.spans) - { - let span = if self.span == DUMMY_SP { predicate_span } else { self.span }; - let cause = ObligationCause::new( - span, - hir::CRATE_HIR_ID, - ObligationCauseCode::AscribeUserTypeProvePredicate(predicate_span), - ); - let instantiated_predicate = - self.normalize_with_cause(instantiated_predicate, cause.clone()); - self.prove_predicate(instantiated_predicate, cause); - } - - if let Some(UserSelfTy { impl_def_id, self_ty }) = user_self_ty { - let impl_self_ty = self.tcx().type_of(impl_def_id); - let impl_self_ty = self.subst(impl_self_ty, &substs); - let impl_self_ty = self.normalize(impl_self_ty); - - self.relate(self_ty, Variance::Invariant, impl_self_ty)?; - - self.prove_predicate( - ty::Binder::dummy(ty::PredicateKind::WellFormed(impl_self_ty.into())) - .to_predicate(self.tcx()), - cause.clone(), - ); - } - - // In addition to proving the predicates, we have to - // prove that `ty` is well-formed -- this is because - // the WF of `ty` is predicated on the substs being - // well-formed, and we haven't proven *that*. We don't - // want to prove the WF of types from `substs` directly because they - // haven't been normalized. - // - // FIXME(nmatsakis): Well, perhaps we should normalize - // them? This would only be relevant if some input - // type were ill-formed but did not appear in `ty`, - // which...could happen with normalization... - self.prove_predicate( - ty::Binder::dummy(ty::PredicateKind::WellFormed(ty.into())).to_predicate(self.tcx()), - cause, - ); - Ok(()) + let predicate: Predicate<'tcx> = + ty::Binder::dummy(ty::PredicateKind::WellFormed(impl_self_ty.into())).to_predicate(tcx); + ocx.register_obligation(Obligation::new(tcx, cause.clone(), param_env, predicate)); } + + // In addition to proving the predicates, we have to + // prove that `ty` is well-formed -- this is because + // the WF of `ty` is predicated on the substs being + // well-formed, and we haven't proven *that*. We don't + // want to prove the WF of types from `substs` directly because they + // haven't been normalized. + // + // FIXME(nmatsakis): Well, perhaps we should normalize + // them? This would only be relevant if some input + // type were ill-formed but did not appear in `ty`, + // which...could happen with normalization... + let predicate: Predicate<'tcx> = + ty::Binder::dummy(ty::PredicateKind::WellFormed(ty.into())).to_predicate(tcx); + ocx.register_obligation(Obligation::new(tcx, cause, param_env, predicate)); + Ok(()) } fn type_op_eq<'tcx>( tcx: TyCtxt<'tcx>, canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Eq<'tcx>>>, ) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, ()>>, NoSolution> { - tcx.infer_ctxt().enter_canonical_trait_query(&canonicalized, |infcx, fulfill_cx, key| { + tcx.infer_ctxt().enter_canonical_trait_query(&canonicalized, |ocx, key| { let (param_env, Eq { a, b }) = key.into_parts(); - infcx - .at(&ObligationCause::dummy(), param_env) - .eq(a, b)? - .into_value_registering_obligations(infcx, fulfill_cx); - Ok(()) + Ok(ocx.eq(&ObligationCause::dummy(), param_env, a, b)?) }) } fn type_op_normalize<'tcx, T>( - infcx: &InferCtxt<'tcx>, - fulfill_cx: &mut dyn TraitEngine<'tcx>, + ocx: &ObligationCtxt<'_, 'tcx>, key: ParamEnvAnd<'tcx, Normalize<T>>, ) -> Fallible<T> where @@ -219,8 +137,8 @@ where { let (param_env, Normalize { value }) = key.into_parts(); let Normalized { value, obligations } = - infcx.at(&ObligationCause::dummy(), param_env).normalize(value)?; - fulfill_cx.register_predicate_obligations(infcx, obligations); + ocx.infcx.at(&ObligationCause::dummy(), param_env).query_normalize(value)?; + ocx.register_obligations(obligations); Ok(value) } @@ -256,13 +174,9 @@ fn type_op_subtype<'tcx>( tcx: TyCtxt<'tcx>, canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Subtype<'tcx>>>, ) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, ()>>, NoSolution> { - tcx.infer_ctxt().enter_canonical_trait_query(&canonicalized, |infcx, fulfill_cx, key| { + tcx.infer_ctxt().enter_canonical_trait_query(&canonicalized, |ocx, key| { let (param_env, Subtype { sub, sup }) = key.into_parts(); - infcx - .at(&ObligationCause::dummy(), param_env) - .sup(sup, sub)? - .into_value_registering_obligations(infcx, fulfill_cx); - Ok(()) + Ok(ocx.sup(&ObligationCause::dummy(), param_env, sup, sub)?) }) } @@ -274,8 +188,8 @@ fn type_op_prove_predicate<'tcx>( // impl-trait/issue-99642.rs tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bubble).enter_canonical_trait_query( &canonicalized, - |infcx, fulfill_cx, key| { - type_op_prove_predicate_with_cause(infcx, fulfill_cx, key, ObligationCause::dummy()); + |ocx, key| { + type_op_prove_predicate_with_cause(ocx, key, ObligationCause::dummy()); Ok(()) }, ) @@ -284,12 +198,11 @@ fn type_op_prove_predicate<'tcx>( /// The core of the `type_op_prove_predicate` query: for diagnostics purposes in NLL HRTB errors, /// this query can be re-run to better track the span of the obligation cause, and improve the error /// message. Do not call directly unless you're in that very specific context. -pub fn type_op_prove_predicate_with_cause<'a, 'tcx: 'a>( - infcx: &'a InferCtxt<'tcx>, - fulfill_cx: &'a mut dyn TraitEngine<'tcx>, +pub fn type_op_prove_predicate_with_cause<'tcx>( + ocx: &ObligationCtxt<'_, 'tcx>, key: ParamEnvAnd<'tcx, ProvePredicate<'tcx>>, cause: ObligationCause<'tcx>, ) { let (param_env, ProvePredicate { predicate }) = key.into_parts(); - fulfill_cx.register_predicate_obligation(infcx, Obligation::new(cause, param_env, predicate)); + ocx.register_obligation(Obligation::new(ocx.infcx.tcx, cause, param_env, predicate)); } |