• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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