rustc_trait_selection/traits/query/type_op/
normalize.rs

1use 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
126/// This impl is not needed, since we never normalize type outlives predicates
127/// in the old solver, but is required by trait bounds to be happy.
128impl<'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}