1 use crate::middle::resolve_bound_vars as rbv;
2 use crate::mir::interpret::{AllocId, ConstValue, LitToConstInput, Scalar};
3 use crate::ty::{self, InternalSubsts, ParamEnv, ParamEnvAnd, Ty, TyCtxt, TypeVisitableExt};
4 use rustc_data_structures::intern::Interned;
5 use rustc_error_messages::MultiSpan;
6 use rustc_hir as hir;
7 use rustc_hir::def::{DefKind, Res};
8 use rustc_hir::def_id::LocalDefId;
9 use rustc_macros::HashStable;
10
11 mod int;
12 mod kind;
13 mod valtree;
14
15 pub use int::*;
16 pub use kind::*;
17 use rustc_span::ErrorGuaranteed;
18 use rustc_span::DUMMY_SP;
19 use rustc_target::abi::Size;
20 pub use valtree::*;
21
22 use super::sty::ConstKind;
23
24 /// Use this rather than `ConstData`, whenever possible.
25 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable)]
26 #[rustc_pass_by_value]
27 pub struct Const<'tcx>(pub(super) Interned<'tcx, ConstData<'tcx>>);
28
29 /// Typed constant value.
30 #[derive(PartialEq, Eq, PartialOrd, Ord, Hash, HashStable, TyEncodable, TyDecodable)]
31 pub struct ConstData<'tcx> {
32 pub ty: Ty<'tcx>,
33 pub kind: ConstKind<'tcx>,
34 }
35
36 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
37 static_assert_size!(ConstData<'_>, 40);
38
39 enum EvalMode {
40 Typeck,
41 Mir,
42 }
43
44 enum EvalResult<'tcx> {
45 ValTree(ty::ValTree<'tcx>),
46 ConstVal(ConstValue<'tcx>),
47 }
48
49 impl<'tcx> Const<'tcx> {
50 #[inline]
ty(self) -> Ty<'tcx>51 pub fn ty(self) -> Ty<'tcx> {
52 self.0.ty
53 }
54
55 #[inline]
kind(self) -> ConstKind<'tcx>56 pub fn kind(self) -> ConstKind<'tcx> {
57 self.0.kind.clone()
58 }
59
60 #[inline]
new(tcx: TyCtxt<'tcx>, kind: ty::ConstKind<'tcx>, ty: Ty<'tcx>) -> Const<'tcx>61 pub fn new(tcx: TyCtxt<'tcx>, kind: ty::ConstKind<'tcx>, ty: Ty<'tcx>) -> Const<'tcx> {
62 tcx.mk_ct_from_kind(kind, ty)
63 }
64
65 #[inline]
new_param(tcx: TyCtxt<'tcx>, param: ty::ParamConst, ty: Ty<'tcx>) -> Const<'tcx>66 pub fn new_param(tcx: TyCtxt<'tcx>, param: ty::ParamConst, ty: Ty<'tcx>) -> Const<'tcx> {
67 Const::new(tcx, ty::ConstKind::Param(param), ty)
68 }
69
70 #[inline]
new_var(tcx: TyCtxt<'tcx>, infer: ty::ConstVid<'tcx>, ty: Ty<'tcx>) -> Const<'tcx>71 pub fn new_var(tcx: TyCtxt<'tcx>, infer: ty::ConstVid<'tcx>, ty: Ty<'tcx>) -> Const<'tcx> {
72 Const::new(tcx, ty::ConstKind::Infer(ty::InferConst::Var(infer)), ty)
73 }
74
75 #[inline]
new_fresh(tcx: TyCtxt<'tcx>, fresh: u32, ty: Ty<'tcx>) -> Const<'tcx>76 pub fn new_fresh(tcx: TyCtxt<'tcx>, fresh: u32, ty: Ty<'tcx>) -> Const<'tcx> {
77 Const::new(tcx, ty::ConstKind::Infer(ty::InferConst::Fresh(fresh)), ty)
78 }
79
80 #[inline]
new_infer(tcx: TyCtxt<'tcx>, infer: ty::InferConst<'tcx>, ty: Ty<'tcx>) -> Const<'tcx>81 pub fn new_infer(tcx: TyCtxt<'tcx>, infer: ty::InferConst<'tcx>, ty: Ty<'tcx>) -> Const<'tcx> {
82 Const::new(tcx, ty::ConstKind::Infer(infer), ty)
83 }
84
85 #[inline]
new_bound( tcx: TyCtxt<'tcx>, debruijn: ty::DebruijnIndex, var: ty::BoundVar, ty: Ty<'tcx>, ) -> Const<'tcx>86 pub fn new_bound(
87 tcx: TyCtxt<'tcx>,
88 debruijn: ty::DebruijnIndex,
89 var: ty::BoundVar,
90 ty: Ty<'tcx>,
91 ) -> Const<'tcx> {
92 Const::new(tcx, ty::ConstKind::Bound(debruijn, var), ty)
93 }
94
95 #[inline]
new_placeholder( tcx: TyCtxt<'tcx>, placeholder: ty::PlaceholderConst<'tcx>, ty: Ty<'tcx>, ) -> Const<'tcx>96 pub fn new_placeholder(
97 tcx: TyCtxt<'tcx>,
98 placeholder: ty::PlaceholderConst<'tcx>,
99 ty: Ty<'tcx>,
100 ) -> Const<'tcx> {
101 Const::new(tcx, ty::ConstKind::Placeholder(placeholder), ty)
102 }
103
104 #[inline]
new_unevaluated( tcx: TyCtxt<'tcx>, uv: ty::UnevaluatedConst<'tcx>, ty: Ty<'tcx>, ) -> Const<'tcx>105 pub fn new_unevaluated(
106 tcx: TyCtxt<'tcx>,
107 uv: ty::UnevaluatedConst<'tcx>,
108 ty: Ty<'tcx>,
109 ) -> Const<'tcx> {
110 Const::new(tcx, ty::ConstKind::Unevaluated(uv), ty)
111 }
112
113 #[inline]
new_value(tcx: TyCtxt<'tcx>, val: ty::ValTree<'tcx>, ty: Ty<'tcx>) -> Const<'tcx>114 pub fn new_value(tcx: TyCtxt<'tcx>, val: ty::ValTree<'tcx>, ty: Ty<'tcx>) -> Const<'tcx> {
115 Const::new(tcx, ty::ConstKind::Value(val), ty)
116 }
117
118 #[inline]
new_expr(tcx: TyCtxt<'tcx>, expr: ty::Expr<'tcx>, ty: Ty<'tcx>) -> Const<'tcx>119 pub fn new_expr(tcx: TyCtxt<'tcx>, expr: ty::Expr<'tcx>, ty: Ty<'tcx>) -> Const<'tcx> {
120 Const::new(tcx, ty::ConstKind::Expr(expr), ty)
121 }
122
123 #[inline]
new_error(tcx: TyCtxt<'tcx>, e: ty::ErrorGuaranteed, ty: Ty<'tcx>) -> Const<'tcx>124 pub fn new_error(tcx: TyCtxt<'tcx>, e: ty::ErrorGuaranteed, ty: Ty<'tcx>) -> Const<'tcx> {
125 Const::new(tcx, ty::ConstKind::Error(e), ty)
126 }
127
128 /// Like [Ty::new_error] but for constants.
129 #[track_caller]
new_misc_error(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Const<'tcx>130 pub fn new_misc_error(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Const<'tcx> {
131 Const::new_error_with_message(
132 tcx,
133 ty,
134 DUMMY_SP,
135 "ty::ConstKind::Error constructed but no error reported",
136 )
137 }
138
139 /// Like [Ty::new_error_with_message] but for constants.
140 #[track_caller]
new_error_with_message<S: Into<MultiSpan>>( tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, span: S, msg: &'static str, ) -> Const<'tcx>141 pub fn new_error_with_message<S: Into<MultiSpan>>(
142 tcx: TyCtxt<'tcx>,
143 ty: Ty<'tcx>,
144 span: S,
145 msg: &'static str,
146 ) -> Const<'tcx> {
147 let reported = tcx.sess.delay_span_bug(span, msg);
148 Const::new_error(tcx, reported, ty)
149 }
150
151 /// Literals and const generic parameters are eagerly converted to a constant, everything else
152 /// becomes `Unevaluated`.
153 #[instrument(skip(tcx), level = "debug")]
from_anon_const(tcx: TyCtxt<'tcx>, def: LocalDefId) -> Self154 pub fn from_anon_const(tcx: TyCtxt<'tcx>, def: LocalDefId) -> Self {
155 let body_id = match tcx.hir().get_by_def_id(def) {
156 hir::Node::AnonConst(ac) => ac.body,
157 _ => span_bug!(
158 tcx.def_span(def.to_def_id()),
159 "from_anon_const can only process anonymous constants"
160 ),
161 };
162
163 let expr = &tcx.hir().body(body_id).value;
164 debug!(?expr);
165
166 let ty = tcx.type_of(def).no_bound_vars().expect("const parameter types cannot be generic");
167
168 match Self::try_eval_lit_or_param(tcx, ty, expr) {
169 Some(v) => v,
170 None => ty::Const::new_unevaluated(
171 tcx,
172 ty::UnevaluatedConst {
173 def: def.to_def_id(),
174 substs: InternalSubsts::identity_for_item(tcx, def.to_def_id()),
175 },
176 ty,
177 ),
178 }
179 }
180
181 #[instrument(skip(tcx), level = "debug")]
try_eval_lit_or_param( tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, expr: &'tcx hir::Expr<'tcx>, ) -> Option<Self>182 fn try_eval_lit_or_param(
183 tcx: TyCtxt<'tcx>,
184 ty: Ty<'tcx>,
185 expr: &'tcx hir::Expr<'tcx>,
186 ) -> Option<Self> {
187 // Unwrap a block, so that e.g. `{ P }` is recognised as a parameter. Const arguments
188 // currently have to be wrapped in curly brackets, so it's necessary to special-case.
189 let expr = match &expr.kind {
190 hir::ExprKind::Block(block, _) if block.stmts.is_empty() && block.expr.is_some() => {
191 block.expr.as_ref().unwrap()
192 }
193 _ => expr,
194 };
195
196 let lit_input = match expr.kind {
197 hir::ExprKind::Lit(ref lit) => Some(LitToConstInput { lit: &lit.node, ty, neg: false }),
198 hir::ExprKind::Unary(hir::UnOp::Neg, ref expr) => match expr.kind {
199 hir::ExprKind::Lit(ref lit) => {
200 Some(LitToConstInput { lit: &lit.node, ty, neg: true })
201 }
202 _ => None,
203 },
204 _ => None,
205 };
206
207 if let Some(lit_input) = lit_input {
208 // If an error occurred, ignore that it's a literal and leave reporting the error up to
209 // mir.
210 match tcx.at(expr.span).lit_to_const(lit_input) {
211 Ok(c) => return Some(c),
212 Err(e) => {
213 tcx.sess.delay_span_bug(
214 expr.span,
215 format!("Const::from_anon_const: couldn't lit_to_const {:?}", e),
216 );
217 }
218 }
219 }
220
221 match expr.kind {
222 hir::ExprKind::Path(hir::QPath::Resolved(
223 _,
224 &hir::Path { res: Res::Def(DefKind::ConstParam, def_id), .. },
225 )) => {
226 // Use the type from the param's definition, since we can resolve it,
227 // not the expected parameter type from WithOptConstParam.
228 let param_ty = tcx.type_of(def_id).subst_identity();
229 match tcx.named_bound_var(expr.hir_id) {
230 Some(rbv::ResolvedArg::EarlyBound(_)) => {
231 // Find the name and index of the const parameter by indexing the generics of
232 // the parent item and construct a `ParamConst`.
233 let item_def_id = tcx.parent(def_id);
234 let generics = tcx.generics_of(item_def_id);
235 let index = generics.param_def_id_to_index[&def_id];
236 let name = tcx.item_name(def_id);
237 Some(ty::Const::new_param(tcx, ty::ParamConst::new(index, name), param_ty))
238 }
239 Some(rbv::ResolvedArg::LateBound(debruijn, index, _)) => {
240 Some(ty::Const::new_bound(
241 tcx,
242 debruijn,
243 ty::BoundVar::from_u32(index),
244 param_ty,
245 ))
246 }
247 Some(rbv::ResolvedArg::Error(guar)) => {
248 Some(ty::Const::new_error(tcx, guar, param_ty))
249 }
250 arg => bug!("unexpected bound var resolution for {:?}: {arg:?}", expr.hir_id),
251 }
252 }
253 _ => None,
254 }
255 }
256
257 /// Panics if self.kind != ty::ConstKind::Value
to_valtree(self) -> ty::ValTree<'tcx>258 pub fn to_valtree(self) -> ty::ValTree<'tcx> {
259 match self.kind() {
260 ty::ConstKind::Value(valtree) => valtree,
261 _ => bug!("expected ConstKind::Value, got {:?}", self.kind()),
262 }
263 }
264
265 #[inline]
266 /// Creates a constant with the given integer value and interns it.
from_bits(tcx: TyCtxt<'tcx>, bits: u128, ty: ParamEnvAnd<'tcx, Ty<'tcx>>) -> Self267 pub fn from_bits(tcx: TyCtxt<'tcx>, bits: u128, ty: ParamEnvAnd<'tcx, Ty<'tcx>>) -> Self {
268 let size = tcx
269 .layout_of(ty)
270 .unwrap_or_else(|e| panic!("could not compute layout for {:?}: {:?}", ty, e))
271 .size;
272 ty::Const::new_value(
273 tcx,
274 ty::ValTree::from_scalar_int(ScalarInt::try_from_uint(bits, size).unwrap()),
275 ty.value,
276 )
277 }
278
279 #[inline]
280 /// Creates an interned zst constant.
zero_sized(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Self281 pub fn zero_sized(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Self {
282 ty::Const::new_value(tcx, ty::ValTree::zst(), ty)
283 }
284
285 #[inline]
286 /// Creates an interned bool constant.
from_bool(tcx: TyCtxt<'tcx>, v: bool) -> Self287 pub fn from_bool(tcx: TyCtxt<'tcx>, v: bool) -> Self {
288 Self::from_bits(tcx, v as u128, ParamEnv::empty().and(tcx.types.bool))
289 }
290
291 #[inline]
292 /// Creates an interned usize constant.
from_target_usize(tcx: TyCtxt<'tcx>, n: u64) -> Self293 pub fn from_target_usize(tcx: TyCtxt<'tcx>, n: u64) -> Self {
294 Self::from_bits(tcx, n as u128, ParamEnv::empty().and(tcx.types.usize))
295 }
296
297 #[inline]
298 /// Attempts to evaluate the given constant to bits. Can fail to evaluate in the presence of
299 /// generics (or erroneous code) or if the value can't be represented as bits (e.g. because it
300 /// contains const generic parameters or pointers).
try_eval_bits( self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ty: Ty<'tcx>, ) -> Option<u128>301 pub fn try_eval_bits(
302 self,
303 tcx: TyCtxt<'tcx>,
304 param_env: ParamEnv<'tcx>,
305 ty: Ty<'tcx>,
306 ) -> Option<u128> {
307 assert_eq!(self.ty(), ty);
308 let size = tcx.layout_of(param_env.with_reveal_all_normalized(tcx).and(ty)).ok()?.size;
309 // if `ty` does not depend on generic parameters, use an empty param_env
310 self.eval(tcx, param_env).try_to_bits(size)
311 }
312
313 #[inline]
try_eval_bool(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Option<bool>314 pub fn try_eval_bool(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Option<bool> {
315 self.eval(tcx, param_env).try_to_bool()
316 }
317
318 #[inline]
try_eval_target_usize( self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ) -> Option<u64>319 pub fn try_eval_target_usize(
320 self,
321 tcx: TyCtxt<'tcx>,
322 param_env: ParamEnv<'tcx>,
323 ) -> Option<u64> {
324 self.eval(tcx, param_env).try_to_target_usize(tcx)
325 }
326
327 #[inline]
328 /// Tries to evaluate the constant if it is `Unevaluated`. If that doesn't succeed, return the
329 /// unevaluated constant.
eval(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Const<'tcx>330 pub fn eval(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Const<'tcx> {
331 if let Some(val) = self.try_eval_for_typeck(tcx, param_env) {
332 match val {
333 Ok(val) => ty::Const::new_value(tcx, val, self.ty()),
334 Err(guar) => ty::Const::new_error(tcx, guar, self.ty()),
335 }
336 } else {
337 // Either the constant isn't evaluatable or ValTree creation failed.
338 self
339 }
340 }
341
342 #[inline]
343 /// Panics if the value cannot be evaluated or doesn't contain a valid integer of the given type.
eval_bits(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ty: Ty<'tcx>) -> u128344 pub fn eval_bits(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ty: Ty<'tcx>) -> u128 {
345 self.try_eval_bits(tcx, param_env, ty)
346 .unwrap_or_else(|| bug!("expected bits of {:#?}, got {:#?}", ty, self))
347 }
348
349 #[inline]
350 /// Panics if the value cannot be evaluated or doesn't contain a valid `usize`.
eval_target_usize(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> u64351 pub fn eval_target_usize(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> u64 {
352 self.try_eval_target_usize(tcx, param_env)
353 .unwrap_or_else(|| bug!("expected usize, got {:#?}", self))
354 }
355
356 #[inline]
357 /// Tries to evaluate the constant if it is `Unevaluated`. If that isn't possible or necessary
358 /// return `None`.
359 // FIXME(@lcnr): Completely rework the evaluation/normalization system for `ty::Const` once valtrees are merged.
try_eval_for_mir( self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ) -> Option<Result<ConstValue<'tcx>, ErrorGuaranteed>>360 pub fn try_eval_for_mir(
361 self,
362 tcx: TyCtxt<'tcx>,
363 param_env: ParamEnv<'tcx>,
364 ) -> Option<Result<ConstValue<'tcx>, ErrorGuaranteed>> {
365 match self.try_eval_inner(tcx, param_env, EvalMode::Mir) {
366 Some(Ok(EvalResult::ValTree(_))) => unreachable!(),
367 Some(Ok(EvalResult::ConstVal(v))) => Some(Ok(v)),
368 Some(Err(e)) => Some(Err(e)),
369 None => None,
370 }
371 }
372
373 #[inline]
374 /// Tries to evaluate the constant if it is `Unevaluated`. If that isn't possible or necessary
375 /// return `None`.
376 // FIXME(@lcnr): Completely rework the evaluation/normalization system for `ty::Const` once valtrees are merged.
try_eval_for_typeck( self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ) -> Option<Result<ty::ValTree<'tcx>, ErrorGuaranteed>>377 pub fn try_eval_for_typeck(
378 self,
379 tcx: TyCtxt<'tcx>,
380 param_env: ParamEnv<'tcx>,
381 ) -> Option<Result<ty::ValTree<'tcx>, ErrorGuaranteed>> {
382 match self.try_eval_inner(tcx, param_env, EvalMode::Typeck) {
383 Some(Ok(EvalResult::ValTree(v))) => Some(Ok(v)),
384 Some(Ok(EvalResult::ConstVal(_))) => unreachable!(),
385 Some(Err(e)) => Some(Err(e)),
386 None => None,
387 }
388 }
389
390 #[inline]
try_eval_inner( self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, eval_mode: EvalMode, ) -> Option<Result<EvalResult<'tcx>, ErrorGuaranteed>>391 fn try_eval_inner(
392 self,
393 tcx: TyCtxt<'tcx>,
394 param_env: ParamEnv<'tcx>,
395 eval_mode: EvalMode,
396 ) -> Option<Result<EvalResult<'tcx>, ErrorGuaranteed>> {
397 assert!(!self.has_escaping_bound_vars(), "escaping vars in {self:?}");
398 if let ConstKind::Unevaluated(unevaluated) = self.kind() {
399 use crate::mir::interpret::ErrorHandled;
400
401 // HACK(eddyb) this erases lifetimes even though `const_eval_resolve`
402 // also does later, but we want to do it before checking for
403 // inference variables.
404 // Note that we erase regions *before* calling `with_reveal_all_normalized`,
405 // so that we don't try to invoke this query with
406 // any region variables.
407
408 // HACK(eddyb) when the query key would contain inference variables,
409 // attempt using identity substs and `ParamEnv` instead, that will succeed
410 // when the expression doesn't depend on any parameters.
411 // FIXME(eddyb, skinny121) pass `InferCtxt` into here when it's available, so that
412 // we can call `infcx.const_eval_resolve` which handles inference variables.
413 let param_env_and = if (param_env, unevaluated).has_non_region_infer() {
414 tcx.param_env(unevaluated.def).and(ty::UnevaluatedConst {
415 def: unevaluated.def,
416 substs: InternalSubsts::identity_for_item(tcx, unevaluated.def),
417 })
418 } else {
419 tcx.erase_regions(param_env)
420 .with_reveal_all_normalized(tcx)
421 .and(tcx.erase_regions(unevaluated))
422 };
423
424 // FIXME(eddyb) maybe the `const_eval_*` methods should take
425 // `ty::ParamEnvAnd` instead of having them separate.
426 let (param_env, unevaluated) = param_env_and.into_parts();
427 // try to resolve e.g. associated constants to their definition on an impl, and then
428 // evaluate the const.
429 match eval_mode {
430 EvalMode::Typeck => {
431 match tcx.const_eval_resolve_for_typeck(param_env, unevaluated, None) {
432 // NOTE(eddyb) `val` contains no lifetimes/types/consts,
433 // and we use the original type, so nothing from `substs`
434 // (which may be identity substs, see above),
435 // can leak through `val` into the const we return.
436 Ok(val) => Some(Ok(EvalResult::ValTree(val?))),
437 Err(ErrorHandled::TooGeneric) => None,
438 Err(ErrorHandled::Reported(e)) => Some(Err(e.into())),
439 }
440 }
441 EvalMode::Mir => {
442 match tcx.const_eval_resolve(param_env, unevaluated.expand(), None) {
443 // NOTE(eddyb) `val` contains no lifetimes/types/consts,
444 // and we use the original type, so nothing from `substs`
445 // (which may be identity substs, see above),
446 // can leak through `val` into the const we return.
447 Ok(val) => Some(Ok(EvalResult::ConstVal(val))),
448 Err(ErrorHandled::TooGeneric) => None,
449 Err(ErrorHandled::Reported(e)) => Some(Err(e.into())),
450 }
451 }
452 }
453 } else {
454 None
455 }
456 }
457
458 #[inline]
try_to_value(self) -> Option<ty::ValTree<'tcx>>459 pub fn try_to_value(self) -> Option<ty::ValTree<'tcx>> {
460 if let ConstKind::Value(val) = self.kind() { Some(val) } else { None }
461 }
462
463 #[inline]
try_to_scalar(self) -> Option<Scalar<AllocId>>464 pub fn try_to_scalar(self) -> Option<Scalar<AllocId>> {
465 self.try_to_value()?.try_to_scalar()
466 }
467
468 #[inline]
try_to_scalar_int(self) -> Option<ScalarInt>469 pub fn try_to_scalar_int(self) -> Option<ScalarInt> {
470 self.try_to_value()?.try_to_scalar_int()
471 }
472
473 #[inline]
try_to_bits(self, size: Size) -> Option<u128>474 pub fn try_to_bits(self, size: Size) -> Option<u128> {
475 self.try_to_scalar_int()?.to_bits(size).ok()
476 }
477
478 #[inline]
try_to_bool(self) -> Option<bool>479 pub fn try_to_bool(self) -> Option<bool> {
480 self.try_to_scalar_int()?.try_into().ok()
481 }
482
483 #[inline]
try_to_target_usize(self, tcx: TyCtxt<'tcx>) -> Option<u64>484 pub fn try_to_target_usize(self, tcx: TyCtxt<'tcx>) -> Option<u64> {
485 self.try_to_value()?.try_to_target_usize(tcx)
486 }
487
is_ct_infer(self) -> bool488 pub fn is_ct_infer(self) -> bool {
489 matches!(self.kind(), ty::ConstKind::Infer(_))
490 }
491 }
492
const_param_default(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Const<'_>>493 pub fn const_param_default(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Const<'_>> {
494 let default_def_id = match tcx.hir().get_by_def_id(def_id) {
495 hir::Node::GenericParam(hir::GenericParam {
496 kind: hir::GenericParamKind::Const { default: Some(ac), .. },
497 ..
498 }) => ac.def_id,
499 _ => span_bug!(
500 tcx.def_span(def_id),
501 "`const_param_default` expected a generic parameter with a constant"
502 ),
503 };
504 ty::EarlyBinder::bind(Const::from_anon_const(tcx, default_def_id))
505 }
506