Skip to main content

rustc_type_ir/
unnormalized.rs

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