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