1use std::borrow::Cow;
2
3use rustc_data_structures::intern::Interned;
4use rustc_error_messages::MultiSpan;
5use rustc_macros::StableHash;
6use rustc_type_ir::walk::TypeWalker;
7use rustc_type_ir::{self as ir, TypeFlags, WithCachedTypeInfo};
8
9use crate::mir::interpret::Scalar;
10use crate::ty::{self, Ty, TyCtxt};
11
12mod int;
13mod kind;
14mod lit;
15mod valtree;
16
17pub use int::*;
18pub use kind::*;
19pub use lit::*;
20use rustc_span::{DUMMY_SP, ErrorGuaranteed};
21pub use valtree::*;
22
23pub type ConstKind<'tcx> = ir::ConstKind<TyCtxt<'tcx>>;
24pub type AliasConst<'tcx> = ir::AliasConst<TyCtxt<'tcx>>;
25pub type AliasConstKind<'tcx> = ir::AliasConstKind<TyCtxt<'tcx>>;
26
27#[cfg(target_pointer_width = "64")]
28const _: [(); 32] = [(); ::std::mem::size_of::<ConstKind<'_>>()];rustc_data_structures::static_assert_size!(ConstKind<'_>, 32);
29
30#[derive(#[automatically_derived]
impl<'tcx> ::core::marker::Copy for Const<'tcx> { }Copy, #[automatically_derived]
impl<'tcx> ::core::clone::Clone for Const<'tcx> {
#[inline]
fn clone(&self) -> Const<'tcx> {
let _:
::core::clone::AssertParamIsClone<Interned<'tcx,
WithCachedTypeInfo<ConstKind<'tcx>>>>;
*self
}
}Clone, #[automatically_derived]
impl<'tcx> ::core::cmp::PartialEq for Const<'tcx> {
#[inline]
fn eq(&self, other: &Const<'tcx>) -> bool { self.0 == other.0 }
}PartialEq, #[automatically_derived]
impl<'tcx> ::core::cmp::Eq for Const<'tcx> {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _:
::core::cmp::AssertParamIsEq<Interned<'tcx,
WithCachedTypeInfo<ConstKind<'tcx>>>>;
}
}Eq, #[automatically_derived]
impl<'tcx> ::core::hash::Hash for Const<'tcx> {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
::core::hash::Hash::hash(&self.0, state)
}
}Hash, const _: () =
{
impl<'tcx> ::rustc_data_structures::stable_hash::StableHash for
Const<'tcx> {
#[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)]
31#[rustc_pass_by_value]
32pub struct Const<'tcx>(pub(super) Interned<'tcx, WithCachedTypeInfo<ConstKind<'tcx>>>);
33
34impl<'tcx> rustc_type_ir::inherent::IntoKind for Const<'tcx> {
35 type Kind = ConstKind<'tcx>;
36
37 fn kind(self) -> ConstKind<'tcx> {
38 self.kind()
39 }
40}
41
42impl<'tcx> rustc_type_ir::Flags for Const<'tcx> {
43 fn flags(&self) -> TypeFlags {
44 self.0.flags
45 }
46
47 fn outer_exclusive_binder(&self) -> rustc_type_ir::DebruijnIndex {
48 self.0.outer_exclusive_binder
49 }
50}
51
52impl<'tcx> Const<'tcx> {
53 #[inline]
54 pub fn kind(self) -> ConstKind<'tcx> {
55 let a: &ConstKind<'tcx> = self.0.0;
56 *a
57 }
58
59 #[inline]
60 pub fn new(tcx: TyCtxt<'tcx>, kind: ty::ConstKind<'tcx>) -> Const<'tcx> {
61 tcx.mk_ct_from_kind(kind)
62 }
63
64 #[inline]
65 pub fn new_param(tcx: TyCtxt<'tcx>, param: ty::ParamConst) -> Const<'tcx> {
66 Const::new(tcx, ty::ConstKind::Param(param))
67 }
68
69 #[inline]
70 pub fn new_var(tcx: TyCtxt<'tcx>, infer: ty::ConstVid) -> Const<'tcx> {
71 Const::new(tcx, ty::ConstKind::Infer(ty::InferConst::Var(infer)))
72 }
73
74 #[inline]
75 pub fn new_fresh(tcx: TyCtxt<'tcx>, fresh: u32) -> Const<'tcx> {
76 Const::new(tcx, ty::ConstKind::Infer(ty::InferConst::Fresh(fresh)))
77 }
78
79 #[inline]
80 pub fn new_infer(tcx: TyCtxt<'tcx>, infer: ty::InferConst) -> Const<'tcx> {
81 Const::new(tcx, ty::ConstKind::Infer(infer))
82 }
83
84 #[inline]
85 pub fn new_bound(
86 tcx: TyCtxt<'tcx>,
87 debruijn: ty::DebruijnIndex,
88 bound_const: ty::BoundConst<'tcx>,
89 ) -> Const<'tcx> {
90 Const::new(tcx, ty::ConstKind::Bound(ty::BoundVarIndexKind::Bound(debruijn), bound_const))
91 }
92
93 #[inline]
94 pub fn new_canonical_bound(tcx: TyCtxt<'tcx>, var: ty::BoundVar) -> Const<'tcx> {
95 Const::new(
96 tcx,
97 ty::ConstKind::Bound(ty::BoundVarIndexKind::Canonical, ty::BoundConst::new(var)),
98 )
99 }
100
101 #[inline]
102 pub fn new_placeholder(
103 tcx: TyCtxt<'tcx>,
104 placeholder: ty::PlaceholderConst<'tcx>,
105 ) -> Const<'tcx> {
106 Const::new(tcx, ty::ConstKind::Placeholder(placeholder))
107 }
108
109 #[inline]
110 pub fn new_alias(
111 tcx: TyCtxt<'tcx>,
112 is_rigid: ty::IsRigid,
113 alias_const: ty::AliasConst<'tcx>,
114 ) -> Const<'tcx> {
115 Const::new(tcx, ty::ConstKind::Alias(is_rigid, alias_const))
116 }
117
118 #[inline]
119 pub fn new_value(tcx: TyCtxt<'tcx>, valtree: ty::ValTree<'tcx>, ty: Ty<'tcx>) -> Const<'tcx> {
120 Const::new(tcx, ty::ConstKind::Value(ty::Value { ty, valtree }))
121 }
122
123 #[inline]
124 pub fn new_expr(tcx: TyCtxt<'tcx>, expr: ty::Expr<'tcx>) -> Const<'tcx> {
125 Const::new(tcx, ty::ConstKind::Expr(expr))
126 }
127
128 #[inline]
129 pub fn new_error(tcx: TyCtxt<'tcx>, e: ty::ErrorGuaranteed) -> Const<'tcx> {
130 Const::new(tcx, ty::ConstKind::Error(e))
131 }
132
133 #[track_caller]
135 pub fn new_misc_error(tcx: TyCtxt<'tcx>) -> Const<'tcx> {
136 Const::new_error_with_message(
137 tcx,
138 DUMMY_SP,
139 "ty::ConstKind::Error constructed but no error reported",
140 )
141 }
142
143 #[track_caller]
145 pub fn new_error_with_message<S: Into<MultiSpan>>(
146 tcx: TyCtxt<'tcx>,
147 span: S,
148 msg: impl Into<Cow<'static, str>>,
149 ) -> Const<'tcx> {
150 let reported = tcx.dcx().span_delayed_bug(span, msg);
151 Const::new_error(tcx, reported)
152 }
153
154 pub fn is_trivially_wf(self) -> bool {
155 match self.kind() {
156 ty::ConstKind::Param(_) | ty::ConstKind::Placeholder(_) | ty::ConstKind::Bound(..) => {
157 true
158 }
159 ty::ConstKind::Infer(_)
160 | ty::ConstKind::Alias(..)
161 | ty::ConstKind::Value(_)
162 | ty::ConstKind::Error(_)
163 | ty::ConstKind::Expr(_) => false,
164 }
165 }
166}
167
168impl<'tcx> rustc_type_ir::inherent::Const<TyCtxt<'tcx>> for Const<'tcx> {
169 fn new_infer(tcx: TyCtxt<'tcx>, infer: ty::InferConst) -> Self {
170 Const::new_infer(tcx, infer)
171 }
172
173 fn new_var(tcx: TyCtxt<'tcx>, vid: ty::ConstVid) -> Self {
174 Const::new_var(tcx, vid)
175 }
176
177 fn new_bound(
178 interner: TyCtxt<'tcx>,
179 debruijn: ty::DebruijnIndex,
180 bound_const: ty::BoundConst<'tcx>,
181 ) -> Self {
182 Const::new_bound(interner, debruijn, bound_const)
183 }
184
185 fn new_anon_bound(tcx: TyCtxt<'tcx>, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self {
186 Const::new_bound(tcx, debruijn, ty::BoundConst::new(var))
187 }
188
189 fn new_canonical_bound(tcx: TyCtxt<'tcx>, var: rustc_type_ir::BoundVar) -> Self {
190 Const::new_canonical_bound(tcx, var)
191 }
192
193 fn new_placeholder(tcx: TyCtxt<'tcx>, placeholder: ty::PlaceholderConst<'tcx>) -> Self {
194 Const::new_placeholder(tcx, placeholder)
195 }
196
197 fn new_alias(
198 interner: TyCtxt<'tcx>,
199 is_rigid: ty::IsRigid,
200 alias_const: ty::AliasConst<'tcx>,
201 ) -> Self {
202 Const::new_alias(interner, is_rigid, alias_const)
203 }
204
205 fn new_expr(interner: TyCtxt<'tcx>, expr: ty::Expr<'tcx>) -> Self {
206 Const::new_expr(interner, expr)
207 }
208
209 fn new_error(interner: TyCtxt<'tcx>, guar: ErrorGuaranteed) -> Self {
210 Const::new_error(interner, guar)
211 }
212}
213
214impl<'tcx> Const<'tcx> {
215 #[inline]
217 pub fn from_bits(
218 tcx: TyCtxt<'tcx>,
219 bits: u128,
220 typing_env: ty::TypingEnv<'tcx>,
221 ty: Ty<'tcx>,
222 ) -> Self {
223 let size = tcx
224 .layout_of(typing_env.as_query_input(ty))
225 .unwrap_or_else(|e| {
::core::panicking::panic_fmt(format_args!("could not compute layout for {0:?}: {1:?}",
ty, e));
}panic!("could not compute layout for {ty:?}: {e:?}"))
226 .size;
227 ty::Const::new_value(
228 tcx,
229 ty::ValTree::from_scalar_int(tcx, ScalarInt::try_from_uint(bits, size).unwrap()),
230 ty,
231 )
232 }
233
234 #[inline]
235 pub fn zero_sized(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Self {
237 ty::Const::new_value(tcx, ty::ValTree::zst(tcx), ty)
238 }
239
240 #[inline]
241 pub fn from_bool(tcx: TyCtxt<'tcx>, v: bool) -> Self {
243 Self::from_bits(tcx, v as u128, ty::TypingEnv::fully_monomorphized(), tcx.types.bool)
244 }
245
246 #[inline]
247 pub fn from_target_usize(tcx: TyCtxt<'tcx>, n: u64) -> Self {
249 Self::from_bits(tcx, n as u128, ty::TypingEnv::fully_monomorphized(), tcx.types.usize)
250 }
251
252 pub fn to_value(self) -> ty::Value<'tcx> {
254 match self.kind() {
255 ty::ConstKind::Value(cv) => cv,
256 _ => crate::util::bug::bug_fmt(format_args!("expected ConstKind::Value, got {0:?}",
self.kind()))bug!("expected ConstKind::Value, got {:?}", self.kind()),
257 }
258 }
259
260 pub fn try_to_value(self) -> Option<ty::Value<'tcx>> {
264 match self.kind() {
265 ty::ConstKind::Value(cv) => Some(cv),
266 _ => None,
267 }
268 }
269
270 #[inline]
275 pub fn to_leaf(self) -> ScalarInt {
276 self.to_value().to_leaf()
277 }
278
279 #[inline]
284 pub fn to_branch(self) -> &'tcx [ty::Const<'tcx>] {
285 self.to_value().to_branch()
286 }
287
288 pub fn try_to_leaf(self) -> Option<ScalarInt> {
292 self.try_to_value()?.try_to_leaf()
293 }
294
295 pub fn try_to_scalar(self) -> Option<Scalar> {
299 self.try_to_leaf().map(Scalar::Int)
300 }
301
302 pub fn try_to_branch(self) -> Option<&'tcx [ty::Const<'tcx>]> {
306 self.try_to_value()?.try_to_branch()
307 }
308
309 #[inline]
314 pub fn try_to_target_usize(self, tcx: TyCtxt<'tcx>) -> Option<u64> {
315 self.try_to_value()?.try_to_target_usize(tcx)
316 }
317
318 pub fn is_ct_infer(self) -> bool {
319 #[allow(non_exhaustive_omitted_patterns)] match self.kind() {
ty::ConstKind::Infer(_) => true,
_ => false,
}matches!(self.kind(), ty::ConstKind::Infer(_))
320 }
321
322 pub fn ct_vid(self) -> Option<ty::ConstVid> {
323 match self.kind() {
324 ConstKind::Infer(ty::InferConst::Var(vid)) => Some(vid),
325 _ => None,
326 }
327 }
328
329 pub fn walk(self) -> TypeWalker<TyCtxt<'tcx>> {
340 TypeWalker::new(self.into())
341 }
342}