Skip to main content

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