Skip to main content

rustc_type_ir/sty/
consts.rs

1use std::fmt;
2
3use derive_where::derive_where;
4use rustc_ast_ir::visit::VisitorResult;
5#[cfg(feature = "nightly")]
6use rustc_macros::StableHash_NoContext;
7use rustc_type_ir_macros::{GenericTypeVisitable, Lift_Generic};
8
9use crate::inherent::*;
10use crate::intern::Interned;
11use crate::relate::{Relate, RelateResult, TypeRelation};
12use crate::{
13    AliasConst, BoundConst, BoundVar, BoundVarIndexKind, ConstKind, ConstVid, DebruijnIndex,
14    FallibleTypeFolder, Flags, InferConst, Interner, IsRigid, PlaceholderConst, TypeFlags,
15    TypeFoldable, TypeFolder, TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitor,
16};
17
18#[automatically_derived]
impl<I: Interner> ::core::clone::Clone for Const<I> where I: Interner {
    #[inline]
    fn clone(&self) -> Self { *self }
}
#[automatically_derived]
impl<I: Interner> ::core::marker::Copy for Const<I> where I: Interner { }
#[automatically_derived]
impl<I: Interner> ::core::cmp::PartialEq for Const<I> where I: Interner {
    #[inline]
    fn eq(&self, __other: &Self) -> ::core::primitive::bool {
        match (self, __other) {
            (Const(ref __field_0), Const(ref __other_field_0)) =>
                true &&
                    ::core::cmp::PartialEq::eq(__field_0, __other_field_0),
        }
    }
}
const _: () =
    {
        trait DeriveWhereAssertEq {
            fn assert(&self);
        }
        impl<I: Interner> DeriveWhereAssertEq for Const<I> where I: Interner {
            fn assert(&self) {
                struct __AssertEq<__T: ::core::cmp::Eq +
                    ?::core::marker::Sized>(::core::marker::PhantomData<__T>);
                let _: __AssertEq<I::InternedConstKind>;
            }
        }
    };
#[automatically_derived]
impl<I: Interner> ::core::cmp::Eq for Const<I> where I: Interner { }
#[automatically_derived]
impl<I: Interner> ::core::hash::Hash for Const<I> where I: Interner {
    fn hash<__H: ::core::hash::Hasher>(&self, __state: &mut __H) {
        match self {
            Const(ref __field_0) => {
                ::core::hash::Hash::hash(__field_0, __state);
            }
        }
    }
}#[derive_where(Clone, Copy, PartialEq, Eq, Hash; I: Interner)]
19#[cfg_attr(feature = "nightly", derive(const _: () =
    {
        impl<I: Interner> ::rustc_data_structures::stable_hash::StableHash for
            Const<I> where
            I::InternedConstKind: ::rustc_data_structures::stable_hash::StableHash
            {
            #[inline]
            fn stable_hash<__Hcx: ::rustc_data_structures::stable_hash::StableHashCtxt>(&self,
                __hcx: &mut __Hcx,
                __hasher:
                    &mut ::rustc_data_structures::stable_hash::StableHasher) {
                match *self {
                    Const(ref __binding_0) => {
                        { __binding_0.stable_hash(__hcx, __hasher); }
                    }
                }
            }
        }
    };StableHash_NoContext))]
20#[cfg_attr(feature = "nightly", rustc_pass_by_value)]
21#[derive(const _: () =
    {
        unsafe impl<I: Interner, __V>
            ::rustc_type_ir::GenericTypeVisitable<__V> for Const<I> where
            I::InternedConstKind: ::rustc_type_ir::GenericTypeVisitable<__V> {
            fn generic_visit_with(&self, __visitor: &mut __V) {
                match *self {
                    Const(ref __binding_0) => {
                        {
                            ::rustc_type_ir::GenericTypeVisitable::<__V>::generic_visit_with(__binding_0,
                                __visitor);
                        }
                    }
                }
            }
        }
    };GenericTypeVisitable, const _: () =
    {
        impl<I: Interner, J> ::rustc_type_ir::lift::Lift<J> for Const<I> where
            J: Interner, I: ::rustc_type_ir::LiftInto<J> {
            type Lifted = Const<J>;
            fn lift_to_interner(self, interner: J) -> Self::Lifted {
                match self {
                    Const(__binding_0) => {
                        Const(__binding_0.lift_to_interner(interner))
                    }
                }
            }
        }
    };Lift_Generic)]
22pub struct Const<I: Interner>(pub I::InternedConstKind);
23
24impl<I: Interner> fmt::Debug for Const<I> {
25    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
26        // If this is a value, we spend some effort to make it look nice.
27        if let ConstKind::Value(cv) = self.kind() {
28            f.write_fmt(format_args!("{0}", cv))write!(f, "{}", cv)
29        } else {
30            // Fall back to something verbose.
31            f.write_fmt(format_args!("{0:?}", self.kind()))write!(f, "{:?}", self.kind())
32        }
33    }
34}
35
36impl<I: Interner> Const<I> {
37    #[inline]
38    pub fn kind(self) -> ConstKind<I> {
39        *self.0.get()
40    }
41
42    #[inline]
43    pub fn new(interner: I, kind: ConstKind<I>) -> Self {
44        interner.mk_ct_from_kind(kind)
45    }
46
47    #[inline]
48    pub fn new_var(interner: I, infer: ConstVid) -> Self {
49        Self::new(interner, ConstKind::Infer(InferConst::Var(infer)))
50    }
51
52    #[inline]
53    pub fn new_infer(interner: I, infer: InferConst) -> Self {
54        Self::new(interner, ConstKind::Infer(infer))
55    }
56
57    #[inline]
58    pub fn new_bound(interner: I, debruijn: DebruijnIndex, bound_const: BoundConst<I>) -> Self {
59        Self::new(interner, ConstKind::Bound(BoundVarIndexKind::Bound(debruijn), bound_const))
60    }
61
62    #[inline]
63    pub fn new_anon_bound(interner: I, debruijn: DebruijnIndex, var: BoundVar) -> Self {
64        Self::new_bound(interner, debruijn, BoundConst::new(var))
65    }
66
67    #[inline]
68    pub fn new_canonical_bound(interner: I, var: BoundVar) -> Self {
69        Self::new(interner, ConstKind::Bound(BoundVarIndexKind::Canonical, BoundConst::new(var)))
70    }
71
72    #[inline]
73    pub fn new_placeholder(interner: I, placeholder: PlaceholderConst<I>) -> Self {
74        Self::new(interner, ConstKind::Placeholder(placeholder))
75    }
76
77    #[inline]
78    pub fn new_alias(interner: I, is_rigid: IsRigid, alias_const: AliasConst<I>) -> Self {
79        Self::new(interner, ConstKind::Alias(is_rigid, alias_const))
80    }
81
82    #[inline]
83    pub fn new_expr(interner: I, expr: I::ExprConst) -> Self {
84        Const::new(interner, ConstKind::Expr(expr))
85    }
86
87    #[inline]
88    pub fn new_error(interner: I, e: I::ErrorGuaranteed) -> Self {
89        Const::new(interner, ConstKind::Error(e))
90    }
91
92    #[inline]
93    pub fn is_ct_var(self) -> bool {
94        #[allow(non_exhaustive_omitted_patterns)] match self.kind() {
    ConstKind::Infer(InferConst::Var(_)) => true,
    _ => false,
}matches!(self.kind(), ConstKind::Infer(InferConst::Var(_)))
95    }
96
97    #[inline]
98    pub fn is_ct_error(self) -> bool {
99        #[allow(non_exhaustive_omitted_patterns)] match self.kind() {
    ConstKind::Error(_) => true,
    _ => false,
}matches!(self.kind(), ConstKind::Error(_))
100    }
101
102    #[inline]
103    pub fn new_param(interner: I, param: I::ParamConst) -> Self {
104        Self::new(interner, ConstKind::Param(param))
105    }
106
107    #[inline]
108    pub fn new_fresh(interner: I, fresh: u32) -> Self {
109        Self::new(interner, ConstKind::Infer(InferConst::Fresh(fresh)))
110    }
111
112    #[track_caller]
113    pub fn new_misc_error(interner: I) -> Self {
114        Self::new_error_with_message(
115            interner,
116            I::Span::dummy(),
117            "ty::ConstKind::Error constructed but no error reported",
118        )
119    }
120
121    #[track_caller]
122    pub fn new_error_with_message(interner: I, span: I::Span, msg: impl ToString) -> Self {
123        let reported = interner.span_delayed_bug(span, msg);
124        Self::new_error(interner, reported)
125    }
126
127    pub fn is_trivially_wf(self) -> bool {
128        match self.kind() {
129            ConstKind::Param(_) | ConstKind::Placeholder(_) | ConstKind::Bound(..) => true,
130            ConstKind::Infer(_)
131            | ConstKind::Alias(..)
132            | ConstKind::Value(_)
133            | ConstKind::Error(_)
134            | ConstKind::Expr(_) => false,
135        }
136    }
137
138    pub fn is_ct_infer(self) -> bool {
139        #[allow(non_exhaustive_omitted_patterns)] match self.kind() {
    ConstKind::Infer(_) => true,
    _ => false,
}matches!(self.kind(), ConstKind::Infer(_))
140    }
141
142    pub fn ct_vid(self) -> Option<ConstVid> {
143        match self.kind() {
144            ConstKind::Infer(InferConst::Var(vid)) => Some(vid),
145            _ => None,
146        }
147    }
148}
149
150impl<I: Interner> Flags for Const<I> {
151    fn flags(&self) -> TypeFlags {
152        self.0.get().flags
153    }
154
155    fn outer_exclusive_binder(&self) -> DebruijnIndex {
156        self.0.get().outer_exclusive_binder
157    }
158}
159
160impl<I: Interner> IntoKind for Const<I> {
161    type Kind = ConstKind<I>;
162
163    fn kind(self) -> Self::Kind {
164        *self.0.get()
165    }
166}
167
168impl<I: Interner> TypeFoldable<I> for Const<I> {
169    fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
170        folder.try_fold_const(self)
171    }
172
173    fn fold_with<F: TypeFolder<I>>(self, folder: &mut F) -> Self {
174        folder.fold_const(self)
175    }
176}
177
178impl<I: Interner> TypeVisitable<I> for Const<I> {
179    fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
180        visitor.visit_const(*self)
181    }
182}
183
184impl<I: Interner> TypeSuperFoldable<I> for Const<I> {
185    fn try_super_fold_with<F: FallibleTypeFolder<I>>(
186        self,
187        folder: &mut F,
188    ) -> Result<Self, F::Error> {
189        let kind = match self.kind() {
190            ConstKind::Alias(is_rigid, alias_const) => {
191                ConstKind::Alias(is_rigid, alias_const.try_fold_with(folder)?)
192            }
193            ConstKind::Value(v) => ConstKind::Value(v.try_fold_with(folder)?),
194            ConstKind::Expr(e) => ConstKind::Expr(e.try_fold_with(folder)?),
195
196            ConstKind::Param(_)
197            | ConstKind::Infer(_)
198            | ConstKind::Bound(..)
199            | ConstKind::Placeholder(_)
200            | ConstKind::Error(_) => return Ok(self),
201        };
202        if kind != self.kind() { Ok(Self::new(folder.cx(), kind)) } else { Ok(self) }
203    }
204
205    fn super_fold_with<F: TypeFolder<I>>(self, folder: &mut F) -> Self {
206        let kind = match self.kind() {
207            ConstKind::Alias(is_rigid, alias_const) => {
208                ConstKind::Alias(is_rigid, alias_const.fold_with(folder))
209            }
210            ConstKind::Value(v) => ConstKind::Value(v.fold_with(folder)),
211            ConstKind::Expr(e) => ConstKind::Expr(e.fold_with(folder)),
212
213            ConstKind::Param(_)
214            | ConstKind::Infer(_)
215            | ConstKind::Bound(..)
216            | ConstKind::Placeholder(_)
217            | ConstKind::Error(_) => return self,
218        };
219        if kind != self.kind() { Self::new(folder.cx(), kind) } else { self }
220    }
221}
222
223impl<I: Interner> TypeSuperVisitable<I> for Const<I> {
224    fn super_visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
225        match self.kind() {
226            ConstKind::Alias(_, alias_const) => alias_const.visit_with(visitor),
227            ConstKind::Value(v) => v.visit_with(visitor),
228            ConstKind::Expr(e) => e.visit_with(visitor),
229            ConstKind::Error(e) => e.visit_with(visitor),
230
231            ConstKind::Param(_)
232            | ConstKind::Infer(_)
233            | ConstKind::Bound(..)
234            | ConstKind::Placeholder(_) => V::Result::output(),
235        }
236    }
237}
238
239impl<I: Interner> Relate<I> for Const<I> {
240    fn relate<R: TypeRelation<I>>(relation: &mut R, a: Self, b: Self) -> RelateResult<I, Self> {
241        relation.consts(a, b)
242    }
243}