1 use rustc_infer::infer::canonical::{Canonical, QueryResponse};
2 use rustc_infer::infer::TyCtxtInferExt;
3 use rustc_middle::query::Providers;
4 use rustc_middle::ty::{ParamEnvAnd, TyCtxt};
5 use rustc_trait_selection::infer::InferCtxtBuilderExt;
6 use rustc_trait_selection::traits::query::{
7 normalize::NormalizationResult, CanonicalProjectionGoal, NoSolution,
8 };
9 use rustc_trait_selection::traits::{self, ObligationCause, SelectionContext};
10 use std::sync::atomic::Ordering;
11
provide(p: &mut Providers)12 pub(crate) fn provide(p: &mut Providers) {
13 *p = Providers {
14 normalize_projection_ty,
15 normalize_weak_ty,
16 normalize_inherent_projection_ty,
17 ..*p
18 };
19 }
20
normalize_projection_ty<'tcx>( tcx: TyCtxt<'tcx>, goal: CanonicalProjectionGoal<'tcx>, ) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, NormalizationResult<'tcx>>>, NoSolution>21 fn normalize_projection_ty<'tcx>(
22 tcx: TyCtxt<'tcx>,
23 goal: CanonicalProjectionGoal<'tcx>,
24 ) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, NormalizationResult<'tcx>>>, NoSolution> {
25 debug!("normalize_provider(goal={:#?})", goal);
26
27 tcx.sess.perf_stats.normalize_projection_ty.fetch_add(1, Ordering::Relaxed);
28 tcx.infer_ctxt().enter_canonical_trait_query(
29 &goal,
30 |ocx, ParamEnvAnd { param_env, value: goal }| {
31 let selcx = &mut SelectionContext::new(ocx.infcx);
32 let cause = ObligationCause::dummy();
33 let mut obligations = vec![];
34 let answer = traits::normalize_projection_type(
35 selcx,
36 param_env,
37 goal,
38 cause,
39 0,
40 &mut obligations,
41 );
42 ocx.register_obligations(obligations);
43 // FIXME(associated_const_equality): All users of normalize_projection_ty expected
44 // a type, but there is the possibility it could've been a const now. Maybe change
45 // it to a Term later?
46 Ok(NormalizationResult { normalized_ty: answer.ty().unwrap() })
47 },
48 )
49 }
50
normalize_weak_ty<'tcx>( tcx: TyCtxt<'tcx>, goal: CanonicalProjectionGoal<'tcx>, ) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, NormalizationResult<'tcx>>>, NoSolution>51 fn normalize_weak_ty<'tcx>(
52 tcx: TyCtxt<'tcx>,
53 goal: CanonicalProjectionGoal<'tcx>,
54 ) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, NormalizationResult<'tcx>>>, NoSolution> {
55 debug!("normalize_provider(goal={:#?})", goal);
56
57 tcx.sess.perf_stats.normalize_projection_ty.fetch_add(1, Ordering::Relaxed);
58 tcx.infer_ctxt().enter_canonical_trait_query(
59 &goal,
60 |ocx, ParamEnvAnd { param_env, value: goal }| {
61 let obligations = tcx.predicates_of(goal.def_id).instantiate_own(tcx, goal.substs).map(
62 |(predicate, span)| {
63 traits::Obligation::new(
64 tcx,
65 ObligationCause::dummy_with_span(span),
66 param_env,
67 predicate,
68 )
69 },
70 );
71 ocx.register_obligations(obligations);
72 let normalized_ty = tcx.type_of(goal.def_id).subst(tcx, goal.substs);
73 Ok(NormalizationResult { normalized_ty })
74 },
75 )
76 }
77
normalize_inherent_projection_ty<'tcx>( tcx: TyCtxt<'tcx>, goal: CanonicalProjectionGoal<'tcx>, ) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, NormalizationResult<'tcx>>>, NoSolution>78 fn normalize_inherent_projection_ty<'tcx>(
79 tcx: TyCtxt<'tcx>,
80 goal: CanonicalProjectionGoal<'tcx>,
81 ) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, NormalizationResult<'tcx>>>, NoSolution> {
82 debug!("normalize_provider(goal={:#?})", goal);
83
84 tcx.infer_ctxt().enter_canonical_trait_query(
85 &goal,
86 |ocx, ParamEnvAnd { param_env, value: goal }| {
87 let selcx = &mut SelectionContext::new(ocx.infcx);
88 let cause = ObligationCause::dummy();
89 let mut obligations = vec![];
90 let answer = traits::normalize_inherent_projection(
91 selcx,
92 param_env,
93 goal,
94 cause,
95 0,
96 &mut obligations,
97 );
98 ocx.register_obligations(obligations);
99
100 Ok(NormalizationResult { normalized_ty: answer })
101 },
102 )
103 }
104