rustc_trait_selection/traits/query/type_op/
normalize.rs1use std::fmt;
2
3use rustc_middle::traits::ObligationCause;
4use rustc_middle::traits::query::NoSolution;
5pub use rustc_middle::traits::query::type_op::{DeeplyNormalize, Normalize};
6use rustc_middle::ty::fold::TypeFoldable;
7use rustc_middle::ty::{self, Lift, ParamEnvAnd, Ty, TyCtxt, TypeVisitableExt};
8use rustc_span::Span;
9
10use crate::infer::canonical::{CanonicalQueryInput, CanonicalQueryResponse};
11use crate::traits::ObligationCtxt;
12
13impl<'tcx, T> super::QueryTypeOp<'tcx> for Normalize<T>
14where
15 T: Normalizable<'tcx> + 'tcx,
16{
17 type QueryResponse = T;
18
19 fn try_fast_path(_tcx: TyCtxt<'tcx>, key: &ParamEnvAnd<'tcx, Self>) -> Option<T> {
20 if !key.value.value.has_aliases() { Some(key.value.value) } else { None }
21 }
22
23 fn perform_query(
24 tcx: TyCtxt<'tcx>,
25 canonicalized: CanonicalQueryInput<'tcx, ParamEnvAnd<'tcx, Self>>,
26 ) -> Result<CanonicalQueryResponse<'tcx, Self::QueryResponse>, NoSolution> {
27 T::type_op_method(tcx, canonicalized)
28 }
29
30 fn perform_locally_with_next_solver(
31 _ocx: &ObligationCtxt<'_, 'tcx>,
32 key: ParamEnvAnd<'tcx, Self>,
33 _span: Span,
34 ) -> Result<Self::QueryResponse, NoSolution> {
35 Ok(key.value.value)
36 }
37}
38
39impl<'tcx, T> super::QueryTypeOp<'tcx> for DeeplyNormalize<T>
40where
41 T: Normalizable<'tcx> + 'tcx,
42{
43 type QueryResponse = T;
44
45 fn try_fast_path(_tcx: TyCtxt<'tcx>, key: &ParamEnvAnd<'tcx, Self>) -> Option<T> {
46 if !key.value.value.has_aliases() { Some(key.value.value) } else { None }
47 }
48
49 fn perform_query(
50 tcx: TyCtxt<'tcx>,
51 canonicalized: CanonicalQueryInput<'tcx, ParamEnvAnd<'tcx, Self>>,
52 ) -> Result<CanonicalQueryResponse<'tcx, Self::QueryResponse>, NoSolution> {
53 T::type_op_method(
54 tcx,
55 CanonicalQueryInput {
56 typing_mode: canonicalized.typing_mode,
57 canonical: canonicalized.canonical.unchecked_map(
58 |ty::ParamEnvAnd { param_env, value }| ty::ParamEnvAnd {
59 param_env,
60 value: Normalize { value: value.value },
61 },
62 ),
63 },
64 )
65 }
66
67 fn perform_locally_with_next_solver(
68 ocx: &ObligationCtxt<'_, 'tcx>,
69 key: ParamEnvAnd<'tcx, Self>,
70 span: Span,
71 ) -> Result<Self::QueryResponse, NoSolution> {
72 ocx.deeply_normalize(
73 &ObligationCause::dummy_with_span(span),
74 key.param_env,
75 key.value.value,
76 )
77 .map_err(|_| NoSolution)
78 }
79}
80
81pub trait Normalizable<'tcx>:
82 fmt::Debug + TypeFoldable<TyCtxt<'tcx>> + Lift<TyCtxt<'tcx>> + Copy
83{
84 fn type_op_method(
85 tcx: TyCtxt<'tcx>,
86 canonicalized: CanonicalQueryInput<'tcx, ParamEnvAnd<'tcx, Normalize<Self>>>,
87 ) -> Result<CanonicalQueryResponse<'tcx, Self>, NoSolution>;
88}
89
90impl<'tcx> Normalizable<'tcx> for Ty<'tcx> {
91 fn type_op_method(
92 tcx: TyCtxt<'tcx>,
93 canonicalized: CanonicalQueryInput<'tcx, ParamEnvAnd<'tcx, Normalize<Self>>>,
94 ) -> Result<CanonicalQueryResponse<'tcx, Self>, NoSolution> {
95 tcx.type_op_normalize_ty(canonicalized)
96 }
97}
98
99impl<'tcx> Normalizable<'tcx> for ty::Clause<'tcx> {
100 fn type_op_method(
101 tcx: TyCtxt<'tcx>,
102 canonicalized: CanonicalQueryInput<'tcx, ParamEnvAnd<'tcx, Normalize<Self>>>,
103 ) -> Result<CanonicalQueryResponse<'tcx, Self>, NoSolution> {
104 tcx.type_op_normalize_clause(canonicalized)
105 }
106}
107
108impl<'tcx> Normalizable<'tcx> for ty::PolyFnSig<'tcx> {
109 fn type_op_method(
110 tcx: TyCtxt<'tcx>,
111 canonicalized: CanonicalQueryInput<'tcx, ParamEnvAnd<'tcx, Normalize<Self>>>,
112 ) -> Result<CanonicalQueryResponse<'tcx, Self>, NoSolution> {
113 tcx.type_op_normalize_poly_fn_sig(canonicalized)
114 }
115}
116
117impl<'tcx> Normalizable<'tcx> for ty::FnSig<'tcx> {
118 fn type_op_method(
119 tcx: TyCtxt<'tcx>,
120 canonicalized: CanonicalQueryInput<'tcx, ParamEnvAnd<'tcx, Normalize<Self>>>,
121 ) -> Result<CanonicalQueryResponse<'tcx, Self>, NoSolution> {
122 tcx.type_op_normalize_fn_sig(canonicalized)
123 }
124}
125
126impl<'tcx> Normalizable<'tcx> for ty::PolyTypeOutlivesPredicate<'tcx> {
129 fn type_op_method(
130 _tcx: TyCtxt<'tcx>,
131 _canonicalized: CanonicalQueryInput<'tcx, ParamEnvAnd<'tcx, Normalize<Self>>>,
132 ) -> Result<CanonicalQueryResponse<'tcx, Self>, NoSolution> {
133 unreachable!("we never normalize PolyTypeOutlivesPredicate")
134 }
135}