1 #![allow(clippy::float_cmp)]
3 use crate::{clip, is_direct_expn_of, sext, unsext}
;
4 use if_chain
::if_chain
;
5 use rustc_ast
::ast
::{self, LitFloatType, LitKind}
;
6 use rustc_data_structures
::sync
::Lrc
;
7 use rustc_hir
::def
::{DefKind, Res}
;
8 use rustc_hir
::{BinOp, BinOpKind, Block, Expr, ExprKind, HirId, QPath, UnOp}
;
9 use rustc_lint
::LateContext
;
10 use rustc_middle
::mir
::interpret
::Scalar
;
11 use rustc_middle
::ty
::subst
::{Subst, SubstsRef}
;
12 use rustc_middle
::ty
::{self, FloatTy, ScalarInt, Ty, TyCtxt}
;
13 use rustc_middle
::{bug, span_bug}
;
14 use rustc_span
::symbol
::Symbol
;
15 use std
::cmp
::Ordering
::{self, Equal}
;
16 use std
::convert
::TryInto
;
17 use std
::hash
::{Hash, Hasher}
;
20 /// A `LitKind`-like enum to fold constant `Expr`s into.
21 #[derive(Debug, Clone)]
23 /// A `String` (e.g., "abc").
25 /// A binary string (e.g., `b"abc"`).
27 /// A single `char` (e.g., `'a'`).
29 /// An integer's bit representation.
35 /// `true` or `false`.
37 /// An array of constants.
39 /// Also an array, but with only one constant, repeated N times.
40 Repeat(Box
<Constant
>, u64),
41 /// A tuple of constants.
47 /// A literal with syntax error.
51 impl PartialEq
for Constant
{
52 fn eq(&self, other
: &Self) -> bool
{
54 (&Self::Str(ref ls
), &Self::Str(ref rs
)) => ls
== rs
,
55 (&Self::Binary(ref l
), &Self::Binary(ref r
)) => l
== r
,
56 (&Self::Char(l
), &Self::Char(r
)) => l
== r
,
57 (&Self::Int(l
), &Self::Int(r
)) => l
== r
,
58 (&Self::F64(l
), &Self::F64(r
)) => {
59 // We want `Fw32 == FwAny` and `FwAny == Fw64`, and by transitivity we must have
60 // `Fw32 == Fw64`, so don’t compare them.
61 // `to_bits` is required to catch non-matching 0.0, -0.0, and NaNs.
62 l
.to_bits() == r
.to_bits()
64 (&Self::F32(l
), &Self::F32(r
)) => {
65 // We want `Fw32 == FwAny` and `FwAny == Fw64`, and by transitivity we must have
66 // `Fw32 == Fw64`, so don’t compare them.
67 // `to_bits` is required to catch non-matching 0.0, -0.0, and NaNs.
68 f64::from(l
).to_bits() == f64::from(r
).to_bits()
70 (&Self::Bool(l
), &Self::Bool(r
)) => l
== r
,
71 (&Self::Vec(ref l
), &Self::Vec(ref r
)) | (&Self::Tuple(ref l
), &Self::Tuple(ref r
)) => l
== r
,
72 (&Self::Repeat(ref lv
, ref ls
), &Self::Repeat(ref rv
, ref rs
)) => ls
== rs
&& lv
== rv
,
73 (&Self::Ref(ref lb
), &Self::Ref(ref rb
)) => *lb
== *rb
,
74 // TODO: are there inter-type equalities?
80 impl Hash
for Constant
{
81 fn hash
<H
>(&self, state
: &mut H
)
85 std
::mem
::discriminant(self).hash(state
);
90 Self::Binary(ref b
) => {
100 f64::from(f
).to_bits().hash(state
);
103 f
.to_bits().hash(state
);
108 Self::Vec(ref v
) | Self::Tuple(ref v
) => {
111 Self::Repeat(ref c
, l
) => {
118 Self::Ref(ref r
) => {
121 Self::Err(ref s
) => {
129 pub fn partial_cmp(tcx
: TyCtxt
<'_
>, cmp_type
: Ty
<'_
>, left
: &Self, right
: &Self) -> Option
<Ordering
> {
130 match (left
, right
) {
131 (&Self::Str(ref ls
), &Self::Str(ref rs
)) => Some(ls
.cmp(rs
)),
132 (&Self::Char(ref l
), &Self::Char(ref r
)) => Some(l
.cmp(r
)),
133 (&Self::Int(l
), &Self::Int(r
)) => {
134 if let ty
::Int(int_ty
) = *cmp_type
.kind() {
135 Some(sext(tcx
, l
, int_ty
).cmp(&sext(tcx
, r
, int_ty
)))
140 (&Self::F64(l
), &Self::F64(r
)) => l
.partial_cmp(&r
),
141 (&Self::F32(l
), &Self::F32(r
)) => l
.partial_cmp(&r
),
142 (&Self::Bool(ref l
), &Self::Bool(ref r
)) => Some(l
.cmp(r
)),
143 (&Self::Tuple(ref l
), &Self::Tuple(ref r
)) | (&Self::Vec(ref l
), &Self::Vec(ref r
)) => iter
::zip(l
, r
)
144 .map(|(li
, ri
)| Self::partial_cmp(tcx
, cmp_type
, li
, ri
))
145 .find(|r
| r
.map_or(true, |o
| o
!= Ordering
::Equal
))
146 .unwrap_or_else(|| Some(l
.len().cmp(&r
.len()))),
147 (&Self::Repeat(ref lv
, ref ls
), &Self::Repeat(ref rv
, ref rs
)) => {
148 match Self::partial_cmp(tcx
, cmp_type
, lv
, rv
) {
149 Some(Equal
) => Some(ls
.cmp(rs
)),
153 (&Self::Ref(ref lb
), &Self::Ref(ref rb
)) => Self::partial_cmp(tcx
, cmp_type
, lb
, rb
),
154 // TODO: are there any useful inter-type orderings?
159 /// Returns the integer value or `None` if `self` or `val_type` is not integer type.
160 pub fn int_value(&self, cx
: &LateContext
<'_
>, val_type
: Ty
<'_
>) -> Option
<FullInt
> {
161 if let Constant
::Int(const_int
) = *self {
162 match *val_type
.kind() {
163 ty
::Int(ity
) => Some(FullInt
::S(sext(cx
.tcx
, const_int
, ity
))),
164 ty
::Uint(_
) => Some(FullInt
::U(const_int
)),
173 /// Parses a `LitKind` to a `Constant`.
174 pub fn lit_to_constant(lit
: &LitKind
, ty
: Option
<Ty
<'_
>>) -> Constant
{
176 LitKind
::Str(ref is
, _
) => Constant
::Str(is
.to_string()),
177 LitKind
::Byte(b
) => Constant
::Int(u128
::from(b
)),
178 LitKind
::ByteStr(ref s
) => Constant
::Binary(Lrc
::clone(s
)),
179 LitKind
::Char(c
) => Constant
::Char(c
),
180 LitKind
::Int(n
, _
) => Constant
::Int(n
),
181 LitKind
::Float(ref is
, LitFloatType
::Suffixed(fty
)) => match fty
{
182 ast
::FloatTy
::F32
=> Constant
::F32(is
.as_str().parse().unwrap()),
183 ast
::FloatTy
::F64
=> Constant
::F64(is
.as_str().parse().unwrap()),
185 LitKind
::Float(ref is
, LitFloatType
::Unsuffixed
) => match ty
.expect("type of float is known").kind() {
186 ty
::Float(FloatTy
::F32
) => Constant
::F32(is
.as_str().parse().unwrap()),
187 ty
::Float(FloatTy
::F64
) => Constant
::F64(is
.as_str().parse().unwrap()),
190 LitKind
::Bool(b
) => Constant
::Bool(b
),
191 LitKind
::Err(s
) => Constant
::Err(s
),
195 pub fn constant
<'tcx
>(
196 lcx
: &LateContext
<'tcx
>,
197 typeck_results
: &ty
::TypeckResults
<'tcx
>,
199 ) -> Option
<(Constant
, bool
)> {
200 let mut cx
= ConstEvalLateContext
{
203 param_env
: lcx
.param_env
,
204 needed_resolution
: false,
205 substs
: lcx
.tcx
.intern_substs(&[]),
207 cx
.expr(e
).map(|cst
| (cst
, cx
.needed_resolution
))
210 pub fn constant_simple
<'tcx
>(
211 lcx
: &LateContext
<'tcx
>,
212 typeck_results
: &ty
::TypeckResults
<'tcx
>,
214 ) -> Option
<Constant
> {
215 constant(lcx
, typeck_results
, e
).and_then(|(cst
, res
)| if res { None }
else { Some(cst) }
)
218 pub fn constant_full_int(
219 lcx
: &LateContext
<'tcx
>,
220 typeck_results
: &ty
::TypeckResults
<'tcx
>,
222 ) -> Option
<FullInt
> {
223 constant_simple(lcx
, typeck_results
, e
)?
.int_value(lcx
, typeck_results
.expr_ty(e
))
226 #[derive(Copy, Clone, Debug, Eq)]
232 impl PartialEq
for FullInt
{
234 fn eq(&self, other
: &Self) -> bool
{
235 self.cmp(other
) == Ordering
::Equal
239 impl PartialOrd
for FullInt
{
241 fn partial_cmp(&self, other
: &Self) -> Option
<Ordering
> {
242 Some(self.cmp(other
))
246 impl Ord
for FullInt
{
248 fn cmp(&self, other
: &Self) -> Ordering
{
251 fn cmp_s_u(s
: i128
, u
: u128
) -> Ordering
{
252 u128
::try_from(s
).map_or(Ordering
::Less
, |x
| x
.cmp(&u
))
255 match (*self, *other
) {
256 (S(s
), S(o
)) => s
.cmp(&o
),
257 (U(s
), U(o
)) => s
.cmp(&o
),
258 (S(s
), U(o
)) => cmp_s_u(s
, o
),
259 (U(s
), S(o
)) => cmp_s_u(o
, s
).reverse(),
264 /// Creates a `ConstEvalLateContext` from the given `LateContext` and `TypeckResults`.
265 pub fn constant_context
<'a
, 'tcx
>(
266 lcx
: &'a LateContext
<'tcx
>,
267 typeck_results
: &'a ty
::TypeckResults
<'tcx
>,
268 ) -> ConstEvalLateContext
<'a
, 'tcx
> {
269 ConstEvalLateContext
{
272 param_env
: lcx
.param_env
,
273 needed_resolution
: false,
274 substs
: lcx
.tcx
.intern_substs(&[]),
278 pub struct ConstEvalLateContext
<'a
, 'tcx
> {
279 lcx
: &'a LateContext
<'tcx
>,
280 typeck_results
: &'a ty
::TypeckResults
<'tcx
>,
281 param_env
: ty
::ParamEnv
<'tcx
>,
282 needed_resolution
: bool
,
283 substs
: SubstsRef
<'tcx
>,
286 impl<'a
, 'tcx
> ConstEvalLateContext
<'a
, 'tcx
> {
287 /// Simple constant folding: Insert an expression, get a constant or none.
288 pub fn expr(&mut self, e
: &Expr
<'_
>) -> Option
<Constant
> {
290 ExprKind
::Path(ref qpath
) => self.fetch_path(qpath
, e
.hir_id
, self.typeck_results
.expr_ty(e
)),
291 ExprKind
::Block(block
, _
) => self.block(block
),
292 ExprKind
::Lit(ref lit
) => {
293 if is_direct_expn_of(e
.span
, "cfg").is_some() {
296 Some(lit_to_constant(&lit
.node
, self.typeck_results
.expr_ty_opt(e
)))
299 ExprKind
::Array(vec
) => self.multi(vec
).map(Constant
::Vec
),
300 ExprKind
::Tup(tup
) => self.multi(tup
).map(Constant
::Tuple
),
301 ExprKind
::Repeat(value
, _
) => {
302 let n
= match self.typeck_results
.expr_ty(e
).kind() {
303 ty
::Array(_
, n
) => n
.try_eval_usize(self.lcx
.tcx
, self.lcx
.param_env
)?
,
304 _
=> span_bug
!(e
.span
, "typeck error"),
306 self.expr(value
).map(|v
| Constant
::Repeat(Box
::new(v
), n
))
308 ExprKind
::Unary(op
, operand
) => self.expr(operand
).and_then(|o
| match op
{
309 UnOp
::Not
=> self.constant_not(&o
, self.typeck_results
.expr_ty(e
)),
310 UnOp
::Neg
=> self.constant_negate(&o
, self.typeck_results
.expr_ty(e
)),
311 UnOp
::Deref
=> Some(if let Constant
::Ref(r
) = o { *r }
else { o }
),
313 ExprKind
::If(cond
, then
, ref otherwise
) => self.ifthenelse(cond
, then
, *otherwise
),
314 ExprKind
::Binary(op
, left
, right
) => self.binop(op
, left
, right
),
315 ExprKind
::Call(callee
, args
) => {
316 // We only handle a few const functions for now.
319 if let ExprKind
::Path(qpath
) = &callee
.kind
;
320 let res
= self.typeck_results
.qpath_res(qpath
, callee
.hir_id
);
321 if let Some(def_id
) = res
.opt_def_id();
322 let def_path
: Vec
<_
> = self.lcx
.get_def_path(def_id
).into_iter().map(Symbol
::as_str
).collect();
323 let def_path
: Vec
<&str> = def_path
.iter().take(4).map(|s
| &**s
).collect();
324 if let ["core", "num", int_impl
, "max_value"] = *def_path
;
326 let value
= match int_impl
{
327 "<impl i8>" => i8::MAX
as u128
,
328 "<impl i16>" => i16::MAX
as u128
,
329 "<impl i32>" => i32::MAX
as u128
,
330 "<impl i64>" => i64::MAX
as u128
,
331 "<impl i128>" => i128
::MAX
as u128
,
334 Some(Constant
::Int(value
))
341 ExprKind
::Index(arr
, index
) => self.index(arr
, index
),
342 ExprKind
::AddrOf(_
, _
, inner
) => self.expr(inner
).map(|r
| Constant
::Ref(Box
::new(r
))),
343 // TODO: add other expressions.
348 #[allow(clippy::cast_possible_wrap)]
349 fn constant_not(&self, o
: &Constant
, ty
: Ty
<'_
>) -> Option
<Constant
> {
350 use self::Constant
::{Bool, Int}
;
352 Bool(b
) => Some(Bool(!b
)),
356 ty
::Int(ity
) => Some(Int(unsext(self.lcx
.tcx
, value
as i128
, ity
))),
357 ty
::Uint(ity
) => Some(Int(clip(self.lcx
.tcx
, value
, ity
))),
365 fn constant_negate(&self, o
: &Constant
, ty
: Ty
<'_
>) -> Option
<Constant
> {
366 use self::Constant
::{Int, F32, F64}
;
369 let ity
= match *ty
.kind() {
374 let value
= sext(self.lcx
.tcx
, value
, ity
);
375 let value
= value
.checked_neg()?
;
377 Some(Int(unsext(self.lcx
.tcx
, value
, ity
)))
379 F32(f
) => Some(F32(-f
)),
380 F64(f
) => Some(F64(-f
)),
385 /// Create `Some(Vec![..])` of all constants, unless there is any
386 /// non-constant part.
387 fn multi(&mut self, vec
: &[Expr
<'_
>]) -> Option
<Vec
<Constant
>> {
388 vec
.iter().map(|elem
| self.expr(elem
)).collect
::<Option
<_
>>()
391 /// Lookup a possibly constant expression from an `ExprKind::Path`.
392 fn fetch_path(&mut self, qpath
: &QPath
<'_
>, id
: HirId
, ty
: Ty
<'tcx
>) -> Option
<Constant
> {
393 let res
= self.typeck_results
.qpath_res(qpath
, id
);
395 Res
::Def(DefKind
::Const
| DefKind
::AssocConst
, def_id
) => {
396 let substs
= self.typeck_results
.node_substs(id
);
397 let substs
= if self.substs
.is_empty() {
400 substs
.subst(self.lcx
.tcx
, self.substs
)
408 ty
::Unevaluated
::new(ty
::WithOptConstParam
::unknown(def_id
), substs
),
412 .map(|val
| rustc_middle
::ty
::Const
::from_value(self.lcx
.tcx
, val
, ty
))?
;
413 let result
= miri_to_const(result
);
414 if result
.is_some() {
415 self.needed_resolution
= true;
419 // FIXME: cover all usable cases.
424 fn index(&mut self, lhs
: &'_ Expr
<'_
>, index
: &'_ Expr
<'_
>) -> Option
<Constant
> {
425 let lhs
= self.expr(lhs
);
426 let index
= self.expr(index
);
429 (Some(Constant
::Vec(vec
)), Some(Constant
::Int(index
))) => match vec
.get(index
as usize) {
430 Some(Constant
::F32(x
)) => Some(Constant
::F32(*x
)),
431 Some(Constant
::F64(x
)) => Some(Constant
::F64(*x
)),
434 (Some(Constant
::Vec(vec
)), _
) => {
435 if !vec
.is_empty() && vec
.iter().all(|x
| *x
== vec
[0]) {
437 Some(Constant
::F32(x
)) => Some(Constant
::F32(*x
)),
438 Some(Constant
::F64(x
)) => Some(Constant
::F64(*x
)),
449 /// A block can only yield a constant if it only has one constant expression.
450 fn block(&mut self, block
: &Block
<'_
>) -> Option
<Constant
> {
451 if block
.stmts
.is_empty() {
452 block
.expr
.as_ref().and_then(|b
| self.expr(b
))
458 fn ifthenelse(&mut self, cond
: &Expr
<'_
>, then
: &Expr
<'_
>, otherwise
: Option
<&Expr
<'_
>>) -> Option
<Constant
> {
459 if let Some(Constant
::Bool(b
)) = self.expr(cond
) {
463 otherwise
.as_ref().and_then(|expr
| self.expr(expr
))
470 fn binop(&mut self, op
: BinOp
, left
: &Expr
<'_
>, right
: &Expr
<'_
>) -> Option
<Constant
> {
471 let l
= self.expr(left
)?
;
472 let r
= self.expr(right
);
474 (Constant
::Int(l
), Some(Constant
::Int(r
))) => match *self.typeck_results
.expr_ty_opt(left
)?
.kind() {
476 let l
= sext(self.lcx
.tcx
, l
, ity
);
477 let r
= sext(self.lcx
.tcx
, r
, ity
);
478 let zext
= |n
: i128
| Constant
::Int(unsext(self.lcx
.tcx
, n
, ity
));
480 BinOpKind
::Add
=> l
.checked_add(r
).map(zext
),
481 BinOpKind
::Sub
=> l
.checked_sub(r
).map(zext
),
482 BinOpKind
::Mul
=> l
.checked_mul(r
).map(zext
),
483 BinOpKind
::Div
if r
!= 0 => l
.checked_div(r
).map(zext
),
484 BinOpKind
::Rem
if r
!= 0 => l
.checked_rem(r
).map(zext
),
485 BinOpKind
::Shr
=> l
.checked_shr(r
.try_into().expect("invalid shift")).map(zext
),
486 BinOpKind
::Shl
=> l
.checked_shl(r
.try_into().expect("invalid shift")).map(zext
),
487 BinOpKind
::BitXor
=> Some(zext(l ^ r
)),
488 BinOpKind
::BitOr
=> Some(zext(l
| r
)),
489 BinOpKind
::BitAnd
=> Some(zext(l
& r
)),
490 BinOpKind
::Eq
=> Some(Constant
::Bool(l
== r
)),
491 BinOpKind
::Ne
=> Some(Constant
::Bool(l
!= r
)),
492 BinOpKind
::Lt
=> Some(Constant
::Bool(l
< r
)),
493 BinOpKind
::Le
=> Some(Constant
::Bool(l
<= r
)),
494 BinOpKind
::Ge
=> Some(Constant
::Bool(l
>= r
)),
495 BinOpKind
::Gt
=> Some(Constant
::Bool(l
> r
)),
499 ty
::Uint(_
) => match op
.node
{
500 BinOpKind
::Add
=> l
.checked_add(r
).map(Constant
::Int
),
501 BinOpKind
::Sub
=> l
.checked_sub(r
).map(Constant
::Int
),
502 BinOpKind
::Mul
=> l
.checked_mul(r
).map(Constant
::Int
),
503 BinOpKind
::Div
=> l
.checked_div(r
).map(Constant
::Int
),
504 BinOpKind
::Rem
=> l
.checked_rem(r
).map(Constant
::Int
),
505 BinOpKind
::Shr
=> l
.checked_shr(r
.try_into().expect("shift too large")).map(Constant
::Int
),
506 BinOpKind
::Shl
=> l
.checked_shl(r
.try_into().expect("shift too large")).map(Constant
::Int
),
507 BinOpKind
::BitXor
=> Some(Constant
::Int(l ^ r
)),
508 BinOpKind
::BitOr
=> Some(Constant
::Int(l
| r
)),
509 BinOpKind
::BitAnd
=> Some(Constant
::Int(l
& r
)),
510 BinOpKind
::Eq
=> Some(Constant
::Bool(l
== r
)),
511 BinOpKind
::Ne
=> Some(Constant
::Bool(l
!= r
)),
512 BinOpKind
::Lt
=> Some(Constant
::Bool(l
< r
)),
513 BinOpKind
::Le
=> Some(Constant
::Bool(l
<= r
)),
514 BinOpKind
::Ge
=> Some(Constant
::Bool(l
>= r
)),
515 BinOpKind
::Gt
=> Some(Constant
::Bool(l
> r
)),
520 (Constant
::F32(l
), Some(Constant
::F32(r
))) => match op
.node
{
521 BinOpKind
::Add
=> Some(Constant
::F32(l
+ r
)),
522 BinOpKind
::Sub
=> Some(Constant
::F32(l
- r
)),
523 BinOpKind
::Mul
=> Some(Constant
::F32(l
* r
)),
524 BinOpKind
::Div
=> Some(Constant
::F32(l
/ r
)),
525 BinOpKind
::Rem
=> Some(Constant
::F32(l
% r
)),
526 BinOpKind
::Eq
=> Some(Constant
::Bool(l
== r
)),
527 BinOpKind
::Ne
=> Some(Constant
::Bool(l
!= r
)),
528 BinOpKind
::Lt
=> Some(Constant
::Bool(l
< r
)),
529 BinOpKind
::Le
=> Some(Constant
::Bool(l
<= r
)),
530 BinOpKind
::Ge
=> Some(Constant
::Bool(l
>= r
)),
531 BinOpKind
::Gt
=> Some(Constant
::Bool(l
> r
)),
534 (Constant
::F64(l
), Some(Constant
::F64(r
))) => match op
.node
{
535 BinOpKind
::Add
=> Some(Constant
::F64(l
+ r
)),
536 BinOpKind
::Sub
=> Some(Constant
::F64(l
- r
)),
537 BinOpKind
::Mul
=> Some(Constant
::F64(l
* r
)),
538 BinOpKind
::Div
=> Some(Constant
::F64(l
/ r
)),
539 BinOpKind
::Rem
=> Some(Constant
::F64(l
% r
)),
540 BinOpKind
::Eq
=> Some(Constant
::Bool(l
== r
)),
541 BinOpKind
::Ne
=> Some(Constant
::Bool(l
!= r
)),
542 BinOpKind
::Lt
=> Some(Constant
::Bool(l
< r
)),
543 BinOpKind
::Le
=> Some(Constant
::Bool(l
<= r
)),
544 BinOpKind
::Ge
=> Some(Constant
::Bool(l
>= r
)),
545 BinOpKind
::Gt
=> Some(Constant
::Bool(l
> r
)),
548 (l
, r
) => match (op
.node
, l
, r
) {
549 (BinOpKind
::And
, Constant
::Bool(false), _
) => Some(Constant
::Bool(false)),
550 (BinOpKind
::Or
, Constant
::Bool(true), _
) => Some(Constant
::Bool(true)),
551 (BinOpKind
::And
, Constant
::Bool(true), Some(r
)) | (BinOpKind
::Or
, Constant
::Bool(false), Some(r
)) => {
554 (BinOpKind
::BitXor
, Constant
::Bool(l
), Some(Constant
::Bool(r
))) => Some(Constant
::Bool(l ^ r
)),
555 (BinOpKind
::BitAnd
, Constant
::Bool(l
), Some(Constant
::Bool(r
))) => Some(Constant
::Bool(l
& r
)),
556 (BinOpKind
::BitOr
, Constant
::Bool(l
), Some(Constant
::Bool(r
))) => Some(Constant
::Bool(l
| r
)),
563 pub fn miri_to_const(result
: &ty
::Const
<'_
>) -> Option
<Constant
> {
564 use rustc_middle
::mir
::interpret
::ConstValue
;
566 ty
::ConstKind
::Value(ConstValue
::Scalar(Scalar
::Int(int
))) => {
567 match result
.ty
.kind() {
568 ty
::Bool
=> Some(Constant
::Bool(int
== ScalarInt
::TRUE
)),
569 ty
::Uint(_
) | ty
::Int(_
) => Some(Constant
::Int(int
.assert_bits(int
.size()))),
570 ty
::Float(FloatTy
::F32
) => Some(Constant
::F32(f32::from_bits(
571 int
.try_into().expect("invalid f32 bit representation"),
573 ty
::Float(FloatTy
::F64
) => Some(Constant
::F64(f64::from_bits(
574 int
.try_into().expect("invalid f64 bit representation"),
576 ty
::RawPtr(type_and_mut
) => {
577 if let ty
::Uint(_
) = type_and_mut
.ty
.kind() {
578 return Some(Constant
::RawPtr(int
.assert_bits(int
.size())));
582 // FIXME: implement other conversions.
586 ty
::ConstKind
::Value(ConstValue
::Slice { data, start, end }
) => match result
.ty
.kind() {
587 ty
::Ref(_
, tam
, _
) => match tam
.kind() {
588 ty
::Str
=> String
::from_utf8(
589 data
.inspect_with_uninit_and_ptr_outside_interpreter(start
..end
)
598 ty
::ConstKind
::Value(ConstValue
::ByRef { alloc, offset: _ }
) => match result
.ty
.kind() {
599 ty
::Array(sub_type
, len
) => match sub_type
.kind() {
600 ty
::Float(FloatTy
::F32
) => match miri_to_const(len
) {
601 Some(Constant
::Int(len
)) => alloc
602 .inspect_with_uninit_and_ptr_outside_interpreter(0..(4 * len
as usize))
606 Some(Constant
::F32(f32::from_le_bytes(
607 chunk
.try_into().expect("this shouldn't happen"),
610 .collect
::<Option
<Vec
<Constant
>>>()
614 ty
::Float(FloatTy
::F64
) => match miri_to_const(len
) {
615 Some(Constant
::Int(len
)) => alloc
616 .inspect_with_uninit_and_ptr_outside_interpreter(0..(8 * len
as usize))
620 Some(Constant
::F64(f64::from_le_bytes(
621 chunk
.try_into().expect("this shouldn't happen"),
624 .collect
::<Option
<Vec
<Constant
>>>()
628 // FIXME: implement other array type conversions.
633 // FIXME: implement other conversions.