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