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