rustc_traits/
normalize_projection_ty.rs
1use rustc_infer::infer::TyCtxtInferExt;
2use rustc_infer::infer::canonical::{Canonical, QueryResponse};
3use rustc_infer::traits::PredicateObligations;
4use rustc_middle::query::Providers;
5use rustc_middle::ty::{ParamEnvAnd, TyCtxt};
6use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
7use rustc_trait_selection::infer::InferCtxtBuilderExt;
8use rustc_trait_selection::traits::query::normalize::NormalizationResult;
9use rustc_trait_selection::traits::query::{CanonicalAliasGoal, NoSolution};
10use rustc_trait_selection::traits::{self, ObligationCause, ScrubbedTraitError, SelectionContext};
11use tracing::debug;
12
13pub(crate) fn provide(p: &mut Providers) {
14 *p = Providers {
15 normalize_canonicalized_projection_ty,
16 normalize_canonicalized_weak_ty,
17 normalize_canonicalized_inherent_projection_ty,
18 ..*p
19 };
20}
21
22fn normalize_canonicalized_projection_ty<'tcx>(
23 tcx: TyCtxt<'tcx>,
24 goal: CanonicalAliasGoal<'tcx>,
25) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, NormalizationResult<'tcx>>>, NoSolution> {
26 debug!("normalize_canonicalized_projection_ty(goal={:#?})", goal);
27
28 tcx.infer_ctxt().enter_canonical_trait_query(
29 &goal,
30 |ocx, ParamEnvAnd { param_env, value: goal }| {
31 debug_assert!(!ocx.infcx.next_trait_solver());
32 let selcx = &mut SelectionContext::new(ocx.infcx);
33 let cause = ObligationCause::dummy();
34 let mut obligations = PredicateObligations::new();
35 let answer =
36 traits::normalize_projection_ty(selcx, param_env, goal, cause, 0, &mut obligations);
37 ocx.register_obligations(obligations);
38 let errors = ocx.select_where_possible();
43 if !errors.is_empty() {
44 if !tcx.sess.opts.actually_rustdoc {
49 for error in &errors {
50 if let ScrubbedTraitError::Cycle(cycle) = &error {
51 ocx.infcx.err_ctxt().report_overflow_obligation_cycle(cycle);
52 }
53 }
54 }
55 return Err(NoSolution);
56 }
57
58 Ok(NormalizationResult { normalized_ty: answer.expect_type() })
62 },
63 )
64}
65
66fn normalize_canonicalized_weak_ty<'tcx>(
67 tcx: TyCtxt<'tcx>,
68 goal: CanonicalAliasGoal<'tcx>,
69) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, NormalizationResult<'tcx>>>, NoSolution> {
70 debug!("normalize_canonicalized_weak_ty(goal={:#?})", goal);
71
72 tcx.infer_ctxt().enter_canonical_trait_query(
73 &goal,
74 |ocx, ParamEnvAnd { param_env, value: goal }| {
75 let obligations = tcx.predicates_of(goal.def_id).instantiate_own(tcx, goal.args).map(
76 |(predicate, span)| {
77 traits::Obligation::new(
78 tcx,
79 ObligationCause::dummy_with_span(span),
80 param_env,
81 predicate,
82 )
83 },
84 );
85 ocx.register_obligations(obligations);
86 let normalized_ty = tcx.type_of(goal.def_id).instantiate(tcx, goal.args);
87 Ok(NormalizationResult { normalized_ty })
88 },
89 )
90}
91
92fn normalize_canonicalized_inherent_projection_ty<'tcx>(
93 tcx: TyCtxt<'tcx>,
94 goal: CanonicalAliasGoal<'tcx>,
95) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, NormalizationResult<'tcx>>>, NoSolution> {
96 debug!("normalize_canonicalized_inherent_projection_ty(goal={:#?})", goal);
97
98 tcx.infer_ctxt().enter_canonical_trait_query(
99 &goal,
100 |ocx, ParamEnvAnd { param_env, value: goal }| {
101 let selcx = &mut SelectionContext::new(ocx.infcx);
102 let cause = ObligationCause::dummy();
103 let mut obligations = PredicateObligations::new();
104 let answer = traits::normalize_inherent_projection(
105 selcx,
106 param_env,
107 goal,
108 cause,
109 0,
110 &mut obligations,
111 );
112 ocx.register_obligations(obligations);
113
114 Ok(NormalizationResult { normalized_ty: answer })
115 },
116 )
117}