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::walk::TypeWalker;
13use crate::{
14 AliasConst, BoundConst, BoundVar, BoundVarIndexKind, ConstKind, ConstVid, DebruijnIndex,
15 FallibleTypeFolder, Flags, InferConst, Interner, IsRigid, PlaceholderConst, TypeFlags,
16 TypeFoldable, TypeFolder, TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitor,
17 ValTreeKind,
18};
19
20#[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)]
21#[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))]
22#[cfg_attr(feature = "nightly", rustc_pass_by_value)]
23#[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)]
24pub struct Const<I: Interner>(pub I::InternedConstKind);
25
26impl<I: Interner> fmt::Debug for Const<I> {
27 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
28 if let ConstKind::Value(cv) = self.kind() {
30 f.write_fmt(format_args!("{0}", cv))write!(f, "{}", cv)
31 } else {
32 f.write_fmt(format_args!("{0:?}", self.kind()))write!(f, "{:?}", self.kind())
34 }
35 }
36}
37
38impl<I: Interner> Const<I> {
39 #[inline]
40 pub fn kind(self) -> ConstKind<I> {
41 *self.0.get()
42 }
43
44 #[inline]
45 pub fn new(interner: I, kind: ConstKind<I>) -> Self {
46 interner.mk_ct_from_kind(kind)
47 }
48
49 #[inline]
50 pub fn new_var(interner: I, infer: ConstVid) -> Self {
51 Self::new(interner, ConstKind::Infer(InferConst::Var(infer)))
52 }
53
54 #[inline]
55 pub fn new_infer(interner: I, infer: InferConst) -> Self {
56 Self::new(interner, ConstKind::Infer(infer))
57 }
58
59 #[inline]
60 pub fn new_bound(interner: I, debruijn: DebruijnIndex, bound_const: BoundConst<I>) -> Self {
61 Self::new(interner, ConstKind::Bound(BoundVarIndexKind::Bound(debruijn), bound_const))
62 }
63
64 #[inline]
65 pub fn new_anon_bound(interner: I, debruijn: DebruijnIndex, var: BoundVar) -> Self {
66 Self::new_bound(interner, debruijn, BoundConst::new(var))
67 }
68
69 #[inline]
70 pub fn new_canonical_bound(interner: I, var: BoundVar) -> Self {
71 Self::new(interner, ConstKind::Bound(BoundVarIndexKind::Canonical, BoundConst::new(var)))
72 }
73
74 #[inline]
75 pub fn new_placeholder(interner: I, placeholder: PlaceholderConst<I>) -> Self {
76 Self::new(interner, ConstKind::Placeholder(placeholder))
77 }
78
79 #[inline]
80 pub fn new_alias(interner: I, is_rigid: IsRigid, alias_const: AliasConst<I>) -> Self {
81 Self::new(interner, ConstKind::Alias(is_rigid, alias_const))
82 }
83
84 #[inline]
85 pub fn new_expr(interner: I, expr: I::ExprConst) -> Self {
86 Const::new(interner, ConstKind::Expr(expr))
87 }
88
89 #[inline]
90 pub fn new_error(interner: I, e: I::ErrorGuaranteed) -> Self {
91 Const::new(interner, ConstKind::Error(e))
92 }
93
94 #[inline]
95 pub fn is_ct_var(self) -> bool {
96 #[allow(non_exhaustive_omitted_patterns)] match self.kind() {
ConstKind::Infer(InferConst::Var(_)) => true,
_ => false,
}matches!(self.kind(), ConstKind::Infer(InferConst::Var(_)))
97 }
98
99 #[inline]
100 pub fn is_ct_error(self) -> bool {
101 #[allow(non_exhaustive_omitted_patterns)] match self.kind() {
ConstKind::Error(_) => true,
_ => false,
}matches!(self.kind(), ConstKind::Error(_))
102 }
103
104 #[inline]
105 pub fn new_param(interner: I, param: I::ParamConst) -> Self {
106 Self::new(interner, ConstKind::Param(param))
107 }
108
109 #[inline]
110 pub fn new_fresh(interner: I, fresh: u32) -> Self {
111 Self::new(interner, ConstKind::Infer(InferConst::Fresh(fresh)))
112 }
113
114 #[track_caller]
115 pub fn new_misc_error(interner: I) -> Self {
116 Self::new_error_with_message(
117 interner,
118 I::Span::dummy(),
119 "ty::ConstKind::Error constructed but no error reported",
120 )
121 }
122
123 #[track_caller]
124 pub fn new_error_with_message(interner: I, span: I::Span, msg: impl ToString) -> Self {
125 let reported = interner.span_delayed_bug(span, msg);
126 Self::new_error(interner, reported)
127 }
128
129 pub fn is_trivially_wf(self) -> bool {
130 match self.kind() {
131 ConstKind::Param(_) | ConstKind::Placeholder(_) | ConstKind::Bound(..) => true,
132 ConstKind::Infer(_)
133 | ConstKind::Alias(..)
134 | ConstKind::Value(_)
135 | ConstKind::Error(_)
136 | ConstKind::Expr(_) => false,
137 }
138 }
139
140 pub fn is_ct_infer(self) -> bool {
141 #[allow(non_exhaustive_omitted_patterns)] match self.kind() {
ConstKind::Infer(_) => true,
_ => false,
}matches!(self.kind(), ConstKind::Infer(_))
142 }
143
144 pub fn ct_vid(self) -> Option<ConstVid> {
145 match self.kind() {
146 ConstKind::Infer(InferConst::Var(vid)) => Some(vid),
147 _ => None,
148 }
149 }
150
151 #[inline]
152 pub fn new_value(interner: I, valtree: I::ValTree, ty: I::Ty) -> Self {
153 Self::new(interner, ConstKind::Value(I::ValueConst::new(ty, valtree)))
154 }
155
156 #[inline]
158 pub fn zero_sized(interner: I, ty: I::Ty) -> Self {
159 Self::new_value(interner, interner.const_zst(), ty)
160 }
161
162 pub fn to_value(self) -> I::ValueConst {
164 match self.kind() {
165 ConstKind::Value(cv) => cv,
166 _ => {
::core::panicking::panic_fmt(format_args!("expected ConstKind::Value, got {0:?}",
self.kind()));
}panic!("expected ConstKind::Value, got {:?}", self.kind()),
167 }
168 }
169
170 pub fn try_to_value(self) -> Option<I::ValueConst> {
174 match self.kind() {
175 ConstKind::Value(cv) => Some(cv),
176 _ => None,
177 }
178 }
179
180 #[inline]
185 pub fn to_leaf(self) -> I::ScalarInt {
186 self.to_value().valtree().kind().to_leaf()
187 }
188
189 #[inline]
194 pub fn to_branch(self) -> I::Consts {
195 self.to_value().valtree().kind().to_branch()
196 }
197
198 pub fn try_to_leaf(self) -> Option<I::ScalarInt> {
202 self.try_to_value()?.valtree().kind().try_to_leaf()
203 }
204 pub fn try_to_branch(self) -> Option<I::Consts> {
208 self.try_to_value()?.valtree().kind().try_to_branch()
209 }
210
211 pub fn try_to_scalar(self) -> Option<I::Scalar> {
215 self.try_to_leaf().map(|x| x.to_scalar())
216 }
217
218 #[inline]
220 pub fn from_bits(interner: I, bits: u128, typing_env: I::TypingEnv, ty: I::Ty) -> Self {
221 let size = typing_env.layout_size(interner, ty);
222 let scalar_int = I::ScalarInt::try_from_uint(bits, size).unwrap();
223 let valtree = interner.intern_valtree(ValTreeKind::Leaf(scalar_int));
224 Self::new_value(interner, valtree, ty)
225 }
226
227 #[inline]
228 pub fn from_bool(interner: I, v: bool) -> Self {
230 let bool_ty = I::Ty::new_bool(interner);
231 Self::from_bits(interner, v as u128, I::TypingEnv::fully_monomorphized(), bool_ty)
232 }
233
234 #[inline]
235 pub fn from_target_usize(interner: I, n: u64) -> Self {
237 let usize_ty = I::Ty::new_usize(interner);
238 Self::from_bits(interner, n as u128, I::TypingEnv::fully_monomorphized(), usize_ty)
239 }
240
241 #[inline]
246 pub fn try_to_target_usize(self, interner: I) -> Option<u64> {
247 self.try_to_value()?.try_to_target_usize(interner)
248 }
249
250 pub fn walk(self) -> TypeWalker<I> {
261 TypeWalker::new(self.into())
262 }
263}
264
265impl<I: Interner> Flags for Const<I> {
266 fn flags(&self) -> TypeFlags {
267 self.0.get().flags
268 }
269
270 fn outer_exclusive_binder(&self) -> DebruijnIndex {
271 self.0.get().outer_exclusive_binder
272 }
273}
274
275impl<I: Interner> IntoKind for Const<I> {
276 type Kind = ConstKind<I>;
277
278 fn kind(self) -> Self::Kind {
279 *self.0.get()
280 }
281}
282
283impl<I: Interner> TypeFoldable<I> for Const<I> {
284 fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
285 folder.try_fold_const(self)
286 }
287
288 fn fold_with<F: TypeFolder<I>>(self, folder: &mut F) -> Self {
289 folder.fold_const(self)
290 }
291}
292
293impl<I: Interner> TypeVisitable<I> for Const<I> {
294 fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
295 visitor.visit_const(*self)
296 }
297}
298
299impl<I: Interner> TypeSuperFoldable<I> for Const<I> {
300 fn try_super_fold_with<F: FallibleTypeFolder<I>>(
301 self,
302 folder: &mut F,
303 ) -> Result<Self, F::Error> {
304 let kind = match self.kind() {
305 ConstKind::Alias(is_rigid, alias_const) => {
306 ConstKind::Alias(is_rigid, alias_const.try_fold_with(folder)?)
307 }
308 ConstKind::Value(v) => ConstKind::Value(v.try_fold_with(folder)?),
309 ConstKind::Expr(e) => ConstKind::Expr(e.try_fold_with(folder)?),
310
311 ConstKind::Param(_)
312 | ConstKind::Infer(_)
313 | ConstKind::Bound(..)
314 | ConstKind::Placeholder(_)
315 | ConstKind::Error(_) => return Ok(self),
316 };
317 if kind != self.kind() { Ok(Self::new(folder.cx(), kind)) } else { Ok(self) }
318 }
319
320 fn super_fold_with<F: TypeFolder<I>>(self, folder: &mut F) -> Self {
321 let kind = match self.kind() {
322 ConstKind::Alias(is_rigid, alias_const) => {
323 ConstKind::Alias(is_rigid, alias_const.fold_with(folder))
324 }
325 ConstKind::Value(v) => ConstKind::Value(v.fold_with(folder)),
326 ConstKind::Expr(e) => ConstKind::Expr(e.fold_with(folder)),
327
328 ConstKind::Param(_)
329 | ConstKind::Infer(_)
330 | ConstKind::Bound(..)
331 | ConstKind::Placeholder(_)
332 | ConstKind::Error(_) => return self,
333 };
334 if kind != self.kind() { Self::new(folder.cx(), kind) } else { self }
335 }
336}
337
338impl<I: Interner> TypeSuperVisitable<I> for Const<I> {
339 fn super_visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
340 match self.kind() {
341 ConstKind::Alias(_, alias_const) => alias_const.visit_with(visitor),
342 ConstKind::Value(v) => v.visit_with(visitor),
343 ConstKind::Expr(e) => e.visit_with(visitor),
344 ConstKind::Error(e) => e.visit_with(visitor),
345
346 ConstKind::Param(_)
347 | ConstKind::Infer(_)
348 | ConstKind::Bound(..)
349 | ConstKind::Placeholder(_) => V::Result::output(),
350 }
351 }
352}
353
354impl<I: Interner> Relate<I> for Const<I> {
355 fn relate<R: TypeRelation<I>>(relation: &mut R, a: Self, b: Self) -> RelateResult<I, Self> {
356 relation.consts(a, b)
357 }
358}