1use std::borrow::Cow;
2
3use rustc_data_structures::intern::Interned;
4use rustc_error_messages::MultiSpan;
5use rustc_macros::HashStable;
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 UnevaluatedConst<'tcx> = ir::UnevaluatedConst<TyCtxt<'tcx>>;
25
26#[cfg(target_pointer_width = "64")]
27const _: [(); 24] = [(); ::std::mem::size_of::<ConstKind<'_>>()];rustc_data_structures::static_assert_size!(ConstKind<'_>, 24);
28
29#[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_receiver_is_total_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, '__ctx>
::rustc_data_structures::stable_hasher::HashStable<::rustc_middle::ich::StableHashingContext<'__ctx>>
for Const<'tcx> {
#[inline]
fn hash_stable(&self,
__hcx: &mut ::rustc_middle::ich::StableHashingContext<'__ctx>,
__hasher:
&mut ::rustc_data_structures::stable_hasher::StableHasher) {
match *self {
Const(ref __binding_0) => {
{ __binding_0.hash_stable(__hcx, __hasher); }
}
}
}
}
};HashStable)]
30#[rustc_pass_by_value]
31pub struct Const<'tcx>(pub(super) Interned<'tcx, WithCachedTypeInfo<ConstKind<'tcx>>>);
32
33impl<'tcx> rustc_type_ir::inherent::IntoKind for Const<'tcx> {
34 type Kind = ConstKind<'tcx>;
35
36 fn kind(self) -> ConstKind<'tcx> {
37 self.kind()
38 }
39}
40
41impl<'tcx> rustc_type_ir::Flags for Const<'tcx> {
42 fn flags(&self) -> TypeFlags {
43 self.0.flags
44 }
45
46 fn outer_exclusive_binder(&self) -> rustc_type_ir::DebruijnIndex {
47 self.0.outer_exclusive_binder
48 }
49}
50
51impl<'tcx> Const<'tcx> {
52 #[inline]
53 pub fn kind(self) -> ConstKind<'tcx> {
54 let a: &ConstKind<'tcx> = self.0.0;
55 *a
56 }
57
58 #[inline]
60 pub fn flags(self) -> TypeFlags {
61 self.0.flags
62 }
63
64 #[inline]
66 pub fn outer_exclusive_binder(self) -> ty::DebruijnIndex {
67 self.0.outer_exclusive_binder
68 }
69
70 #[inline]
71 pub fn new(tcx: TyCtxt<'tcx>, kind: ty::ConstKind<'tcx>) -> Const<'tcx> {
72 tcx.mk_ct_from_kind(kind)
73 }
74
75 #[inline]
76 pub fn new_param(tcx: TyCtxt<'tcx>, param: ty::ParamConst) -> Const<'tcx> {
77 Const::new(tcx, ty::ConstKind::Param(param))
78 }
79
80 #[inline]
81 pub fn new_var(tcx: TyCtxt<'tcx>, infer: ty::ConstVid) -> Const<'tcx> {
82 Const::new(tcx, ty::ConstKind::Infer(ty::InferConst::Var(infer)))
83 }
84
85 #[inline]
86 pub fn new_fresh(tcx: TyCtxt<'tcx>, fresh: u32) -> Const<'tcx> {
87 Const::new(tcx, ty::ConstKind::Infer(ty::InferConst::Fresh(fresh)))
88 }
89
90 #[inline]
91 pub fn new_infer(tcx: TyCtxt<'tcx>, infer: ty::InferConst) -> Const<'tcx> {
92 Const::new(tcx, ty::ConstKind::Infer(infer))
93 }
94
95 #[inline]
96 pub fn new_bound(
97 tcx: TyCtxt<'tcx>,
98 debruijn: ty::DebruijnIndex,
99 bound_const: ty::BoundConst<'tcx>,
100 ) -> Const<'tcx> {
101 Const::new(tcx, ty::ConstKind::Bound(ty::BoundVarIndexKind::Bound(debruijn), bound_const))
102 }
103
104 #[inline]
105 pub fn new_canonical_bound(tcx: TyCtxt<'tcx>, var: ty::BoundVar) -> Const<'tcx> {
106 Const::new(
107 tcx,
108 ty::ConstKind::Bound(ty::BoundVarIndexKind::Canonical, ty::BoundConst::new(var)),
109 )
110 }
111
112 #[inline]
113 pub fn new_placeholder(
114 tcx: TyCtxt<'tcx>,
115 placeholder: ty::PlaceholderConst<'tcx>,
116 ) -> Const<'tcx> {
117 Const::new(tcx, ty::ConstKind::Placeholder(placeholder))
118 }
119
120 #[inline]
121 pub fn new_unevaluated(tcx: TyCtxt<'tcx>, uv: ty::UnevaluatedConst<'tcx>) -> Const<'tcx> {
122 tcx.debug_assert_args_compatible(uv.def, uv.args);
123 Const::new(tcx, ty::ConstKind::Unevaluated(uv))
124 }
125
126 #[inline]
127 pub fn new_value(tcx: TyCtxt<'tcx>, valtree: ty::ValTree<'tcx>, ty: Ty<'tcx>) -> Const<'tcx> {
128 Const::new(tcx, ty::ConstKind::Value(ty::Value { ty, valtree }))
129 }
130
131 #[inline]
132 pub fn new_expr(tcx: TyCtxt<'tcx>, expr: ty::Expr<'tcx>) -> Const<'tcx> {
133 Const::new(tcx, ty::ConstKind::Expr(expr))
134 }
135
136 #[inline]
137 pub fn new_error(tcx: TyCtxt<'tcx>, e: ty::ErrorGuaranteed) -> Const<'tcx> {
138 Const::new(tcx, ty::ConstKind::Error(e))
139 }
140
141 #[track_caller]
143 pub fn new_misc_error(tcx: TyCtxt<'tcx>) -> Const<'tcx> {
144 Const::new_error_with_message(
145 tcx,
146 DUMMY_SP,
147 "ty::ConstKind::Error constructed but no error reported",
148 )
149 }
150
151 #[track_caller]
153 pub fn new_error_with_message<S: Into<MultiSpan>>(
154 tcx: TyCtxt<'tcx>,
155 span: S,
156 msg: impl Into<Cow<'static, str>>,
157 ) -> Const<'tcx> {
158 let reported = tcx.dcx().span_delayed_bug(span, msg);
159 Const::new_error(tcx, reported)
160 }
161
162 pub fn is_trivially_wf(self) -> bool {
163 match self.kind() {
164 ty::ConstKind::Param(_) | ty::ConstKind::Placeholder(_) | ty::ConstKind::Bound(..) => {
165 true
166 }
167 ty::ConstKind::Infer(_)
168 | ty::ConstKind::Unevaluated(..)
169 | ty::ConstKind::Value(_)
170 | ty::ConstKind::Error(_)
171 | ty::ConstKind::Expr(_) => false,
172 }
173 }
174}
175
176impl<'tcx> rustc_type_ir::inherent::Const<TyCtxt<'tcx>> for Const<'tcx> {
177 fn new_infer(tcx: TyCtxt<'tcx>, infer: ty::InferConst) -> Self {
178 Const::new_infer(tcx, infer)
179 }
180
181 fn new_var(tcx: TyCtxt<'tcx>, vid: ty::ConstVid) -> Self {
182 Const::new_var(tcx, vid)
183 }
184
185 fn new_bound(
186 interner: TyCtxt<'tcx>,
187 debruijn: ty::DebruijnIndex,
188 bound_const: ty::BoundConst<'tcx>,
189 ) -> Self {
190 Const::new_bound(interner, debruijn, bound_const)
191 }
192
193 fn new_anon_bound(tcx: TyCtxt<'tcx>, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self {
194 Const::new_bound(tcx, debruijn, ty::BoundConst::new(var))
195 }
196
197 fn new_canonical_bound(tcx: TyCtxt<'tcx>, var: rustc_type_ir::BoundVar) -> Self {
198 Const::new_canonical_bound(tcx, var)
199 }
200
201 fn new_placeholder(tcx: TyCtxt<'tcx>, placeholder: ty::PlaceholderConst<'tcx>) -> Self {
202 Const::new_placeholder(tcx, placeholder)
203 }
204
205 fn new_unevaluated(interner: TyCtxt<'tcx>, uv: ty::UnevaluatedConst<'tcx>) -> Self {
206 Const::new_unevaluated(interner, uv)
207 }
208
209 fn new_expr(interner: TyCtxt<'tcx>, expr: ty::Expr<'tcx>) -> Self {
210 Const::new_expr(interner, expr)
211 }
212
213 fn new_error(interner: TyCtxt<'tcx>, guar: ErrorGuaranteed) -> Self {
214 Const::new_error(interner, guar)
215 }
216}
217
218impl<'tcx> Const<'tcx> {
219 #[inline]
221 pub fn from_bits(
222 tcx: TyCtxt<'tcx>,
223 bits: u128,
224 typing_env: ty::TypingEnv<'tcx>,
225 ty: Ty<'tcx>,
226 ) -> Self {
227 let size = tcx
228 .layout_of(typing_env.as_query_input(ty))
229 .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:?}"))
230 .size;
231 ty::Const::new_value(
232 tcx,
233 ty::ValTree::from_scalar_int(tcx, ScalarInt::try_from_uint(bits, size).unwrap()),
234 ty,
235 )
236 }
237
238 #[inline]
239 pub fn zero_sized(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Self {
241 ty::Const::new_value(tcx, ty::ValTree::zst(tcx), ty)
242 }
243
244 #[inline]
245 pub fn from_bool(tcx: TyCtxt<'tcx>, v: bool) -> Self {
247 Self::from_bits(tcx, v as u128, ty::TypingEnv::fully_monomorphized(), tcx.types.bool)
248 }
249
250 #[inline]
251 pub fn from_target_usize(tcx: TyCtxt<'tcx>, n: u64) -> Self {
253 Self::from_bits(tcx, n as u128, ty::TypingEnv::fully_monomorphized(), tcx.types.usize)
254 }
255
256 pub fn to_value(self) -> ty::Value<'tcx> {
258 match self.kind() {
259 ty::ConstKind::Value(cv) => cv,
260 _ => crate::util::bug::bug_fmt(format_args!("expected ConstKind::Value, got {0:?}",
self.kind()))bug!("expected ConstKind::Value, got {:?}", self.kind()),
261 }
262 }
263
264 pub fn try_to_value(self) -> Option<ty::Value<'tcx>> {
268 match self.kind() {
269 ty::ConstKind::Value(cv) => Some(cv),
270 _ => None,
271 }
272 }
273
274 #[inline]
279 pub fn to_leaf(self) -> ScalarInt {
280 self.to_value().to_leaf()
281 }
282
283 #[inline]
288 pub fn to_branch(self) -> &'tcx [ty::Const<'tcx>] {
289 self.to_value().to_branch()
290 }
291
292 pub fn try_to_leaf(self) -> Option<ScalarInt> {
296 self.try_to_value()?.try_to_leaf()
297 }
298
299 pub fn try_to_scalar(self) -> Option<Scalar> {
303 self.try_to_leaf().map(Scalar::Int)
304 }
305
306 pub fn try_to_branch(self) -> Option<&'tcx [ty::Const<'tcx>]> {
310 self.try_to_value()?.try_to_branch()
311 }
312
313 #[inline]
318 pub fn try_to_target_usize(self, tcx: TyCtxt<'tcx>) -> Option<u64> {
319 self.try_to_value()?.try_to_target_usize(tcx)
320 }
321
322 pub fn is_ct_infer(self) -> bool {
323 #[allow(non_exhaustive_omitted_patterns)] match self.kind() {
ty::ConstKind::Infer(_) => true,
_ => false,
}matches!(self.kind(), ty::ConstKind::Infer(_))
324 }
325
326 pub fn walk(self) -> TypeWalker<TyCtxt<'tcx>> {
337 TypeWalker::new(self.into())
338 }
339}