| use rustc_infer::infer::canonical::{Canonical, QueryResponse}; |
| use rustc_infer::infer::TyCtxtInferExt; |
| use rustc_middle::query::Providers; |
| use rustc_middle::ty::{ParamEnvAnd, TyCtxt}; |
| use rustc_trait_selection::error_reporting::InferCtxtErrorExt; |
| use rustc_trait_selection::infer::InferCtxtBuilderExt; |
| use rustc_trait_selection::traits::query::normalize::NormalizationResult; |
| use rustc_trait_selection::traits::query::{CanonicalAliasGoal, NoSolution}; |
| use rustc_trait_selection::traits::{self, ObligationCause, ScrubbedTraitError, SelectionContext}; |
| use tracing::debug; |
| |
| pub(crate) fn provide(p: &mut Providers) { |
| *p = Providers { |
| normalize_canonicalized_projection_ty, |
| normalize_canonicalized_weak_ty, |
| normalize_canonicalized_inherent_projection_ty, |
| ..*p |
| }; |
| } |
| |
| fn normalize_canonicalized_projection_ty<'tcx>( |
| tcx: TyCtxt<'tcx>, |
| goal: CanonicalAliasGoal<'tcx>, |
| ) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, NormalizationResult<'tcx>>>, NoSolution> { |
| debug!("normalize_canonicalized_projection_ty(goal={:#?})", goal); |
| |
| tcx.infer_ctxt().enter_canonical_trait_query( |
| &goal, |
| |ocx, ParamEnvAnd { param_env, value: goal }| { |
| debug_assert!(!ocx.infcx.next_trait_solver()); |
| let selcx = &mut SelectionContext::new(ocx.infcx); |
| let cause = ObligationCause::dummy(); |
| let mut obligations = vec![]; |
| let answer = |
| traits::normalize_projection_ty(selcx, param_env, goal, cause, 0, &mut obligations); |
| ocx.register_obligations(obligations); |
| // #112047: With projections and opaques, we are able to create opaques that |
| // are recursive (given some generic parameters of the opaque's type variables). |
| // In that case, we may only realize a cycle error when calling |
| // `normalize_erasing_regions` in mono. |
| let errors = ocx.select_where_possible(); |
| if !errors.is_empty() { |
| // Rustdoc may attempt to normalize type alias types which are not |
| // well-formed. Rustdoc also normalizes types that are just not |
| // well-formed, since we don't do as much HIR analysis (checking |
| // that impl vars are constrained by the signature, for example). |
| if !tcx.sess.opts.actually_rustdoc { |
| for error in &errors { |
| if let ScrubbedTraitError::Cycle(cycle) = &error { |
| ocx.infcx.err_ctxt().report_overflow_obligation_cycle(cycle); |
| } |
| } |
| } |
| return Err(NoSolution); |
| } |
| |
| // FIXME(associated_const_equality): All users of normalize_canonicalized_projection_ty |
| // expected a type, but there is the possibility it could've been a const now. |
| // Maybe change it to a Term later? |
| Ok(NormalizationResult { normalized_ty: answer.expect_type() }) |
| }, |
| ) |
| } |
| |
| fn normalize_canonicalized_weak_ty<'tcx>( |
| tcx: TyCtxt<'tcx>, |
| goal: CanonicalAliasGoal<'tcx>, |
| ) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, NormalizationResult<'tcx>>>, NoSolution> { |
| debug!("normalize_canonicalized_weak_ty(goal={:#?})", goal); |
| |
| tcx.infer_ctxt().enter_canonical_trait_query( |
| &goal, |
| |ocx, ParamEnvAnd { param_env, value: goal }| { |
| let obligations = tcx.predicates_of(goal.def_id).instantiate_own(tcx, goal.args).map( |
| |(predicate, span)| { |
| traits::Obligation::new( |
| tcx, |
| ObligationCause::dummy_with_span(span), |
| param_env, |
| predicate, |
| ) |
| }, |
| ); |
| ocx.register_obligations(obligations); |
| let normalized_ty = tcx.type_of(goal.def_id).instantiate(tcx, goal.args); |
| Ok(NormalizationResult { normalized_ty }) |
| }, |
| ) |
| } |
| |
| fn normalize_canonicalized_inherent_projection_ty<'tcx>( |
| tcx: TyCtxt<'tcx>, |
| goal: CanonicalAliasGoal<'tcx>, |
| ) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, NormalizationResult<'tcx>>>, NoSolution> { |
| debug!("normalize_canonicalized_inherent_projection_ty(goal={:#?})", goal); |
| |
| tcx.infer_ctxt().enter_canonical_trait_query( |
| &goal, |
| |ocx, ParamEnvAnd { param_env, value: goal }| { |
| let selcx = &mut SelectionContext::new(ocx.infcx); |
| let cause = ObligationCause::dummy(); |
| let mut obligations = vec![]; |
| let answer = traits::normalize_inherent_projection( |
| selcx, |
| param_env, |
| goal, |
| cause, |
| 0, |
| &mut obligations, |
| ); |
| ocx.register_obligations(obligations); |
| |
| Ok(NormalizationResult { normalized_ty: answer }) |
| }, |
| ) |
| } |