2 use rustc_middle
::mir
::interpret
::{LitToConstError, LitToConstInput}
;
3 use rustc_middle
::ty
::{self, ParamEnv, ScalarInt, TyCtxt}
;
4 use rustc_span
::DUMMY_SP
;
6 use crate::build
::parse_float_into_scalar
;
8 pub(crate) fn lit_to_const
<'tcx
>(
10 lit_input
: LitToConstInput
<'tcx
>,
11 ) -> Result
<ty
::Const
<'tcx
>, LitToConstError
> {
12 let LitToConstInput { lit, ty, neg }
= lit_input
;
15 let param_ty
= ParamEnv
::reveal_all().and(ty
);
19 LitToConstError
::Reported(tcx
.sess
.span_delayed_bug(
21 format
!("couldn't compute width of literal: {:?}", lit_input
.lit
),
25 trace
!("trunc {} with size {} and shift {}", n
, width
.bits(), 128 - width
.bits());
26 let result
= width
.truncate(n
);
27 trace
!("trunc result: {}", result
);
29 Ok(ScalarInt
::try_from_uint(result
, width
)
30 .unwrap_or_else(|| bug
!("expected to create ScalarInt from uint {:?}", result
)))
33 let valtree
= match (lit
, &ty
.kind()) {
34 (ast
::LitKind
::Str(s
, _
), ty
::Ref(_
, inner_ty
, _
)) if inner_ty
.is_str() => {
35 let str_bytes
= s
.as_str().as_bytes();
36 ty
::ValTree
::from_raw_bytes(tcx
, str_bytes
)
38 (ast
::LitKind
::ByteStr(data
, _
), ty
::Ref(_
, inner_ty
, _
))
39 if matches
!(inner_ty
.kind(), ty
::Slice(_
)) =>
41 let bytes
= data
as &[u8];
42 ty
::ValTree
::from_raw_bytes(tcx
, bytes
)
44 (ast
::LitKind
::ByteStr(data
, _
), ty
::Ref(_
, inner_ty
, _
)) if inner_ty
.is_array() => {
45 let bytes
= data
as &[u8];
46 ty
::ValTree
::from_raw_bytes(tcx
, bytes
)
48 (ast
::LitKind
::Byte(n
), ty
::Uint(ty
::UintTy
::U8
)) => {
49 ty
::ValTree
::from_scalar_int((*n
).into())
51 (ast
::LitKind
::CStr(data
, _
), ty
::Ref(_
, inner_ty
, _
)) if matches
!(inner_ty
.kind(), ty
::Adt(def
, _
) if Some(def
.did()) == tcx
.lang_items().c_str()) =>
53 let bytes
= data
as &[u8];
54 ty
::ValTree
::from_raw_bytes(tcx
, bytes
)
56 (ast
::LitKind
::Int(n
, _
), ty
::Uint(_
)) | (ast
::LitKind
::Int(n
, _
), ty
::Int(_
)) => {
58 trunc(if neg { (*n as i128).overflowing_neg().0 as u128 }
else { *n }
)?
;
59 ty
::ValTree
::from_scalar_int(scalar_int
)
61 (ast
::LitKind
::Bool(b
), ty
::Bool
) => ty
::ValTree
::from_scalar_int((*b
).into()),
62 (ast
::LitKind
::Float(n
, _
), ty
::Float(fty
)) => {
63 let bits
= parse_float_into_scalar(*n
, *fty
, neg
)
65 LitToConstError
::Reported(tcx
.sess
.span_delayed_bug(
67 format
!("couldn't parse float literal: {:?}", lit_input
.lit
),
71 ty
::ValTree
::from_scalar_int(bits
)
73 (ast
::LitKind
::Char(c
), ty
::Char
) => ty
::ValTree
::from_scalar_int((*c
).into()),
74 (ast
::LitKind
::Err
, _
) => {
75 return Err(LitToConstError
::Reported(
76 tcx
.sess
.span_delayed_bug(DUMMY_SP
, "encountered LitKind::Err during mir build"),
79 _
=> return Err(LitToConstError
::TypeError
),
82 Ok(ty
::Const
::new_value(tcx
, valtree
, ty
))