Skip to main content

rustc_type_ir/
unnormalized.rs

1use std::marker::PhantomData;
2
3use derive_where::derive_where;
4
5use crate::inherent::*;
6use crate::upcast::Upcast;
7use crate::{
8    Binder, BoundConstness, ClauseKind, HostEffectPredicate, Interner, PredicatePolarity,
9    TraitPredicate, TraitRef,
10};
11
12/// A wrapper for values that need normalization.
13///
14/// FIXME(#155345): This is very WIP. The plan is to replace the `skip_norm_wip`
15/// spread throughout the codebase with proper normalization. This is the first
16/// step toward switching to eager normalization with the next solver. See the
17/// normalization refactor plan [here].
18///
19/// We're in a weird intermediate state as the change is too big to land in a
20/// single PR. While this work is in progress, just use `Unnormalized::new_wip`
21/// and `Unnormalized::skip_norm_wip` as needed.
22///
23/// The interner type parameter exists to constraint generic for certain impl,
24/// e.g., `Unnormalized<I, I::Clause>`.
25///
26/// [here]: https://rust-lang.zulipchat.com/#narrow/channel/364551-t-types.2Ftrait-system-refactor/topic/Eager.20normalization.2C.20ahoy.21/with/582996293
27#[automatically_derived]
impl<I: Interner, T> ::core::fmt::Debug for Unnormalized<I, T> where
    T: ::core::fmt::Debug {
    fn fmt(&self, __f: &mut ::core::fmt::Formatter<'_>)
        -> ::core::fmt::Result {
        match self {
            Unnormalized { value: ref __field_value, _tcx: ref __field__tcx }
                => {
                let mut __builder =
                    ::core::fmt::Formatter::debug_struct(__f, "Unnormalized");
                ::core::fmt::DebugStruct::field(&mut __builder, "value",
                    __field_value);
                ::core::fmt::DebugStruct::finish_non_exhaustive(&mut __builder)
            }
        }
    }
}#[derive_where(Clone, Copy, PartialOrd, PartialEq, Debug; T)]
28pub struct Unnormalized<I: Interner, T> {
29    value: T,
30    #[derive_where(skip(Debug))]
31    _tcx: PhantomData<fn() -> I>,
32}
33
34impl<I: Interner, T> Unnormalized<I, T> {
35    /// Should only be used in limited situations where you produce an potentially
36    /// unnormalized value, like in (Early)Binder/GenericPredicates instantiation.
37    pub fn new(value: T) -> Unnormalized<I, T> {
38        Unnormalized { value, _tcx: PhantomData }
39    }
40
41    /// FIXME: This is going to be eventually removed once we migrate the relevant
42    /// APIs to return `Unnormalized`.
43    pub fn new_wip(value: T) -> Unnormalized<I, T> {
44        Unnormalized { value, _tcx: PhantomData }
45    }
46
47    /// Intentionally skip normalization.
48    /// You probably should perform normalization in most cases.
49    pub fn skip_normalization(self) -> T {
50        self.value
51    }
52
53    /// FIXME: This is going to be eventually removed.
54    /// If you meet this in codebase, try using one of the normalization routines
55    /// to consume the `Unnormalized` wrapper. Or use `skip_normalization` when normalization
56    /// is really unnecessary.
57    pub fn skip_norm_wip(self) -> T {
58        self.value
59    }
60
61    pub fn map<F, U>(self, f: F) -> Unnormalized<I, U>
62    where
63        F: FnOnce(T) -> U,
64    {
65        Unnormalized { value: f(self.value), _tcx: PhantomData }
66    }
67
68    pub fn as_ref(&self) -> Unnormalized<I, &T> {
69        Unnormalized { value: &self.value, _tcx: PhantomData }
70    }
71
72    pub fn map_ref<U, F>(&self, f: F) -> Unnormalized<I, U>
73    where
74        F: FnOnce(&T) -> U,
75    {
76        Unnormalized { value: f(&self.value), _tcx: PhantomData }
77    }
78}
79
80impl<I: Interner, T, U> Unnormalized<I, (T, U)> {
81    pub fn unzip(self) -> (Unnormalized<I, T>, Unnormalized<I, U>) {
82        (Unnormalized::new(self.value.0), Unnormalized::new(self.value.1))
83    }
84}
85
86impl<I: Interner, T> Unnormalized<I, Binder<I, T>> {
87    pub fn skip_binder(self) -> T {
88        self.value.skip_binder()
89    }
90}
91
92impl<I: Interner> Unnormalized<I, I::Clause> {
93    pub fn as_trait_clause(self) -> Option<Unnormalized<I, Binder<I, TraitPredicate<I>>>> {
94        self.value.as_trait_clause().map(|v| Unnormalized::new(v))
95    }
96
97    pub fn kind(self) -> Unnormalized<I, Binder<I, ClauseKind<I>>> {
98        self.map(|v| v.kind())
99    }
100}
101
102impl<I: Interner> Unnormalized<I, Binder<I, TraitPredicate<I>>> {
103    pub fn self_ty(self) -> Unnormalized<I, Binder<I, I::Ty>> {
104        self.map(|pred| pred.self_ty())
105    }
106
107    pub fn def_id(self) -> I::TraitId {
108        self.value.skip_binder().def_id()
109    }
110
111    #[inline]
112    pub fn polarity(self) -> PredicatePolarity {
113        self.value.skip_binder().polarity
114    }
115}
116
117impl<I: Interner> Unnormalized<I, Binder<I, TraitRef<I>>> {
118    pub fn self_ty(&self) -> Unnormalized<I, Binder<I, I::Ty>> {
119        self.map_ref(|tr| tr.self_ty())
120    }
121
122    pub fn def_id(&self) -> I::TraitId {
123        self.value.skip_binder().def_id
124    }
125
126    pub fn to_host_effect_clause(
127        self,
128        cx: I,
129        constness: BoundConstness,
130    ) -> Unnormalized<I, I::Clause> {
131        let inner = self
132            .value
133            .map_bound(|trait_ref| {
134                ClauseKind::HostEffect(HostEffectPredicate { trait_ref, constness })
135            })
136            .upcast(cx);
137        Unnormalized::new(inner)
138    }
139}