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