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 let ConstKind::Value(cv) = self.kind() {
28 f.write_fmt(format_args!("{0}", cv))write!(f, "{}", cv)
29 } else {
30 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}