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_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, '__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]
59 pub fn new(tcx: TyCtxt<'tcx>, kind: ty::ConstKind<'tcx>) -> Const<'tcx> {
60 tcx.mk_ct_from_kind(kind)
61 }
62
63 #[inline]
64 pub fn new_param(tcx: TyCtxt<'tcx>, param: ty::ParamConst) -> Const<'tcx> {
65 Const::new(tcx, ty::ConstKind::Param(param))
66 }
67
68 #[inline]
69 pub fn new_var(tcx: TyCtxt<'tcx>, infer: ty::ConstVid) -> Const<'tcx> {
70 Const::new(tcx, ty::ConstKind::Infer(ty::InferConst::Var(infer)))
71 }
72
73 #[inline]
74 pub fn new_fresh(tcx: TyCtxt<'tcx>, fresh: u32) -> Const<'tcx> {
75 Const::new(tcx, ty::ConstKind::Infer(ty::InferConst::Fresh(fresh)))
76 }
77
78 #[inline]
79 pub fn new_infer(tcx: TyCtxt<'tcx>, infer: ty::InferConst) -> Const<'tcx> {
80 Const::new(tcx, ty::ConstKind::Infer(infer))
81 }
82
83 #[inline]
84 pub fn new_bound(
85 tcx: TyCtxt<'tcx>,
86 debruijn: ty::DebruijnIndex,
87 bound_const: ty::BoundConst<'tcx>,
88 ) -> Const<'tcx> {
89 Const::new(tcx, ty::ConstKind::Bound(ty::BoundVarIndexKind::Bound(debruijn), bound_const))
90 }
91
92 #[inline]
93 pub fn new_canonical_bound(tcx: TyCtxt<'tcx>, var: ty::BoundVar) -> Const<'tcx> {
94 Const::new(
95 tcx,
96 ty::ConstKind::Bound(ty::BoundVarIndexKind::Canonical, ty::BoundConst::new(var)),
97 )
98 }
99
100 #[inline]
101 pub fn new_placeholder(
102 tcx: TyCtxt<'tcx>,
103 placeholder: ty::PlaceholderConst<'tcx>,
104 ) -> Const<'tcx> {
105 Const::new(tcx, ty::ConstKind::Placeholder(placeholder))
106 }
107
108 #[inline]
109 pub fn new_unevaluated(tcx: TyCtxt<'tcx>, uv: ty::UnevaluatedConst<'tcx>) -> Const<'tcx> {
110 tcx.debug_assert_args_compatible(uv.def, uv.args);
111 Const::new(tcx, ty::ConstKind::Unevaluated(uv))
112 }
113
114 #[inline]
115 pub fn new_value(tcx: TyCtxt<'tcx>, valtree: ty::ValTree<'tcx>, ty: Ty<'tcx>) -> Const<'tcx> {
116 Const::new(tcx, ty::ConstKind::Value(ty::Value { ty, valtree }))
117 }
118
119 #[inline]
120 pub fn new_expr(tcx: TyCtxt<'tcx>, expr: ty::Expr<'tcx>) -> Const<'tcx> {
121 Const::new(tcx, ty::ConstKind::Expr(expr))
122 }
123
124 #[inline]
125 pub fn new_error(tcx: TyCtxt<'tcx>, e: ty::ErrorGuaranteed) -> Const<'tcx> {
126 Const::new(tcx, ty::ConstKind::Error(e))
127 }
128
129 #[track_caller]
131 pub fn new_misc_error(tcx: TyCtxt<'tcx>) -> Const<'tcx> {
132 Const::new_error_with_message(
133 tcx,
134 DUMMY_SP,
135 "ty::ConstKind::Error constructed but no error reported",
136 )
137 }
138
139 #[track_caller]
141 pub fn new_error_with_message<S: Into<MultiSpan>>(
142 tcx: TyCtxt<'tcx>,
143 span: S,
144 msg: impl Into<Cow<'static, str>>,
145 ) -> Const<'tcx> {
146 let reported = tcx.dcx().span_delayed_bug(span, msg);
147 Const::new_error(tcx, reported)
148 }
149
150 pub fn is_trivially_wf(self) -> bool {
151 match self.kind() {
152 ty::ConstKind::Param(_) | ty::ConstKind::Placeholder(_) | ty::ConstKind::Bound(..) => {
153 true
154 }
155 ty::ConstKind::Infer(_)
156 | ty::ConstKind::Unevaluated(..)
157 | ty::ConstKind::Value(_)
158 | ty::ConstKind::Error(_)
159 | ty::ConstKind::Expr(_) => false,
160 }
161 }
162}
163
164impl<'tcx> rustc_type_ir::inherent::Const<TyCtxt<'tcx>> for Const<'tcx> {
165 fn new_infer(tcx: TyCtxt<'tcx>, infer: ty::InferConst) -> Self {
166 Const::new_infer(tcx, infer)
167 }
168
169 fn new_var(tcx: TyCtxt<'tcx>, vid: ty::ConstVid) -> Self {
170 Const::new_var(tcx, vid)
171 }
172
173 fn new_bound(
174 interner: TyCtxt<'tcx>,
175 debruijn: ty::DebruijnIndex,
176 bound_const: ty::BoundConst<'tcx>,
177 ) -> Self {
178 Const::new_bound(interner, debruijn, bound_const)
179 }
180
181 fn new_anon_bound(tcx: TyCtxt<'tcx>, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self {
182 Const::new_bound(tcx, debruijn, ty::BoundConst::new(var))
183 }
184
185 fn new_canonical_bound(tcx: TyCtxt<'tcx>, var: rustc_type_ir::BoundVar) -> Self {
186 Const::new_canonical_bound(tcx, var)
187 }
188
189 fn new_placeholder(tcx: TyCtxt<'tcx>, placeholder: ty::PlaceholderConst<'tcx>) -> Self {
190 Const::new_placeholder(tcx, placeholder)
191 }
192
193 fn new_unevaluated(interner: TyCtxt<'tcx>, uv: ty::UnevaluatedConst<'tcx>) -> Self {
194 Const::new_unevaluated(interner, uv)
195 }
196
197 fn new_expr(interner: TyCtxt<'tcx>, expr: ty::Expr<'tcx>) -> Self {
198 Const::new_expr(interner, expr)
199 }
200
201 fn new_error(interner: TyCtxt<'tcx>, guar: ErrorGuaranteed) -> Self {
202 Const::new_error(interner, guar)
203 }
204}
205
206impl<'tcx> Const<'tcx> {
207 #[inline]
209 pub fn from_bits(
210 tcx: TyCtxt<'tcx>,
211 bits: u128,
212 typing_env: ty::TypingEnv<'tcx>,
213 ty: Ty<'tcx>,
214 ) -> Self {
215 let size = tcx
216 .layout_of(typing_env.as_query_input(ty))
217 .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:?}"))
218 .size;
219 ty::Const::new_value(
220 tcx,
221 ty::ValTree::from_scalar_int(tcx, ScalarInt::try_from_uint(bits, size).unwrap()),
222 ty,
223 )
224 }
225
226 #[inline]
227 pub fn zero_sized(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Self {
229 ty::Const::new_value(tcx, ty::ValTree::zst(tcx), ty)
230 }
231
232 #[inline]
233 pub fn from_bool(tcx: TyCtxt<'tcx>, v: bool) -> Self {
235 Self::from_bits(tcx, v as u128, ty::TypingEnv::fully_monomorphized(), tcx.types.bool)
236 }
237
238 #[inline]
239 pub fn from_target_usize(tcx: TyCtxt<'tcx>, n: u64) -> Self {
241 Self::from_bits(tcx, n as u128, ty::TypingEnv::fully_monomorphized(), tcx.types.usize)
242 }
243
244 pub fn to_value(self) -> ty::Value<'tcx> {
246 match self.kind() {
247 ty::ConstKind::Value(cv) => cv,
248 _ => crate::util::bug::bug_fmt(format_args!("expected ConstKind::Value, got {0:?}",
self.kind()))bug!("expected ConstKind::Value, got {:?}", self.kind()),
249 }
250 }
251
252 pub fn try_to_value(self) -> Option<ty::Value<'tcx>> {
256 match self.kind() {
257 ty::ConstKind::Value(cv) => Some(cv),
258 _ => None,
259 }
260 }
261
262 #[inline]
267 pub fn to_leaf(self) -> ScalarInt {
268 self.to_value().to_leaf()
269 }
270
271 #[inline]
276 pub fn to_branch(self) -> &'tcx [ty::Const<'tcx>] {
277 self.to_value().to_branch()
278 }
279
280 pub fn try_to_leaf(self) -> Option<ScalarInt> {
284 self.try_to_value()?.try_to_leaf()
285 }
286
287 pub fn try_to_scalar(self) -> Option<Scalar> {
291 self.try_to_leaf().map(Scalar::Int)
292 }
293
294 pub fn try_to_branch(self) -> Option<&'tcx [ty::Const<'tcx>]> {
298 self.try_to_value()?.try_to_branch()
299 }
300
301 #[inline]
306 pub fn try_to_target_usize(self, tcx: TyCtxt<'tcx>) -> Option<u64> {
307 self.try_to_value()?.try_to_target_usize(tcx)
308 }
309
310 pub fn is_ct_infer(self) -> bool {
311 #[allow(non_exhaustive_omitted_patterns)] match self.kind() {
ty::ConstKind::Infer(_) => true,
_ => false,
}matches!(self.kind(), ty::ConstKind::Infer(_))
312 }
313
314 pub fn ct_vid(self) -> Option<ty::ConstVid> {
315 match self.kind() {
316 ConstKind::Infer(ty::InferConst::Var(vid)) => Some(vid),
317 _ => None,
318 }
319 }
320
321 pub fn walk(self) -> TypeWalker<TyCtxt<'tcx>> {
332 TypeWalker::new(self.into())
333 }
334}