rustc_traits/
normalize_projection_ty.rs1use 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,
16 normalize_canonicalized_free_alias,
17 normalize_canonicalized_inherent_projection,
18 ..*p
19 };
20}
21
22fn normalize_canonicalized_projection<'tcx>(
23 tcx: TyCtxt<'tcx>,
24 goal: CanonicalAliasGoal<'tcx>,
25) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, NormalizationResult<'tcx>>>, NoSolution> {
26 debug!("normalize_canonicalized_projection(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 normalized_term = traits::normalize_projection_term(
36 selcx,
37 param_env,
38 goal.into(),
39 cause,
40 0,
41 &mut obligations,
42 );
43 ocx.register_obligations(obligations);
44 let errors = ocx.try_evaluate_obligations();
49 if !errors.is_empty() {
50 if !tcx.sess.opts.actually_rustdoc {
55 for error in &errors {
56 if let ScrubbedTraitError::Cycle(cycle) = &error {
57 ocx.infcx.err_ctxt().report_overflow_obligation_cycle(cycle);
58 }
59 }
60 }
61 return Err(NoSolution);
62 }
63
64 Ok(NormalizationResult { normalized_term })
65 },
66 )
67}
68
69fn normalize_canonicalized_free_alias<'tcx>(
70 tcx: TyCtxt<'tcx>,
71 goal: CanonicalAliasGoal<'tcx>,
72) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, NormalizationResult<'tcx>>>, NoSolution> {
73 debug!("normalize_canonicalized_free_alias(goal={:#?})", goal);
74
75 tcx.infer_ctxt().enter_canonical_trait_query(
76 &goal,
77 |ocx, ParamEnvAnd { param_env, value: goal }| {
78 let obligations = tcx.predicates_of(goal.def_id).instantiate_own(tcx, goal.args).map(
79 |(predicate, span)| {
80 traits::Obligation::new(
81 tcx,
82 ObligationCause::dummy_with_span(span),
83 param_env,
84 predicate,
85 )
86 },
87 );
88 ocx.register_obligations(obligations);
89 let normalized_term = if goal.kind(tcx).is_type() {
90 tcx.type_of(goal.def_id).instantiate(tcx, goal.args).into()
91 } else {
92 tcx.const_of_item(goal.def_id).instantiate(tcx, goal.args).into()
93 };
94 Ok(NormalizationResult { normalized_term })
95 },
96 )
97}
98
99fn normalize_canonicalized_inherent_projection<'tcx>(
100 tcx: TyCtxt<'tcx>,
101 goal: CanonicalAliasGoal<'tcx>,
102) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, NormalizationResult<'tcx>>>, NoSolution> {
103 debug!("normalize_canonicalized_inherent_projection(goal={:#?})", goal);
104
105 tcx.infer_ctxt().enter_canonical_trait_query(
106 &goal,
107 |ocx, ParamEnvAnd { param_env, value: goal }| {
108 let selcx = &mut SelectionContext::new(ocx.infcx);
109 let cause = ObligationCause::dummy();
110 let mut obligations = PredicateObligations::new();
111 let normalized_term = traits::normalize_inherent_projection(
112 selcx,
113 param_env,
114 goal.into(),
115 cause,
116 0,
117 &mut obligations,
118 );
119 ocx.register_obligations(obligations);
120
121 Ok(NormalizationResult { normalized_term })
122 },
123 )
124}