]>
Commit | Line | Data |
---|---|---|
3dfed10e | 1 | use rustc_ast as ast; |
923072b8 FG |
2 | use rustc_middle::mir::interpret::{LitToConstError, LitToConstInput}; |
3 | use rustc_middle::ty::{self, ParamEnv, ScalarInt, TyCtxt}; | |
487cf647 | 4 | use rustc_span::DUMMY_SP; |
a1dfa0c6 | 5 | |
923072b8 | 6 | pub(crate) fn lit_to_const<'tcx>( |
dc9dc135 | 7 | tcx: TyCtxt<'tcx>, |
dfeec247 | 8 | lit_input: LitToConstInput<'tcx>, |
5099ac24 | 9 | ) -> Result<ty::Const<'tcx>, LitToConstError> { |
dfeec247 | 10 | let LitToConstInput { lit, ty, neg } = lit_input; |
a1dfa0c6 XL |
11 | |
12 | let trunc = |n| { | |
dc9dc135 | 13 | let param_ty = ParamEnv::reveal_all().and(ty); |
487cf647 FG |
14 | let width = tcx |
15 | .layout_of(param_ty) | |
16 | .map_err(|_| { | |
17 | LitToConstError::Reported(tcx.sess.delay_span_bug( | |
18 | DUMMY_SP, | |
19 | format!("couldn't compute width of literal: {:?}", lit_input.lit), | |
20 | )) | |
21 | })? | |
22 | .size; | |
a1dfa0c6 | 23 | trace!("trunc {} with size {} and shift {}", n, width.bits(), 128 - width.bits()); |
29967ef6 | 24 | let result = width.truncate(n); |
a1dfa0c6 | 25 | trace!("trunc result: {}", result); |
923072b8 FG |
26 | |
27 | Ok(ScalarInt::try_from_uint(result, width) | |
28 | .unwrap_or_else(|| bug!("expected to create ScalarInt from uint {:?}", result))) | |
a1dfa0c6 XL |
29 | }; |
30 | ||
923072b8 | 31 | let valtree = match (lit, &ty.kind()) { |
1b1a35ee | 32 | (ast::LitKind::Str(s, _), ty::Ref(_, inner_ty, _)) if inner_ty.is_str() => { |
923072b8 FG |
33 | let str_bytes = s.as_str().as_bytes(); |
34 | ty::ValTree::from_raw_bytes(tcx, str_bytes) | |
dfeec247 | 35 | } |
1b1a35ee XL |
36 | (ast::LitKind::ByteStr(data), ty::Ref(_, inner_ty, _)) |
37 | if matches!(inner_ty.kind(), ty::Slice(_)) => | |
38 | { | |
923072b8 FG |
39 | let bytes = data as &[u8]; |
40 | ty::ValTree::from_raw_bytes(tcx, bytes) | |
dfeec247 | 41 | } |
1b1a35ee | 42 | (ast::LitKind::ByteStr(data), ty::Ref(_, inner_ty, _)) if inner_ty.is_array() => { |
923072b8 FG |
43 | let bytes = data as &[u8]; |
44 | ty::ValTree::from_raw_bytes(tcx, bytes) | |
a1dfa0c6 | 45 | } |
5869c6ff | 46 | (ast::LitKind::Byte(n), ty::Uint(ty::UintTy::U8)) => { |
923072b8 | 47 | ty::ValTree::from_scalar_int((*n).into()) |
dfeec247 XL |
48 | } |
49 | (ast::LitKind::Int(n, _), ty::Uint(_)) | (ast::LitKind::Int(n, _), ty::Int(_)) => { | |
923072b8 FG |
50 | let scalar_int = |
51 | trunc(if neg { (*n as i128).overflowing_neg().0 as u128 } else { *n })?; | |
52 | ty::ValTree::from_scalar_int(scalar_int) | |
a2a8927a | 53 | } |
923072b8 FG |
54 | (ast::LitKind::Bool(b), ty::Bool) => ty::ValTree::from_scalar_int((*b).into()), |
55 | (ast::LitKind::Char(c), ty::Char) => ty::ValTree::from_scalar_int((*c).into()), | |
487cf647 FG |
56 | (ast::LitKind::Err, _) => { |
57 | return Err(LitToConstError::Reported( | |
58 | tcx.sess.delay_span_bug(DUMMY_SP, "encountered LitKind::Err during mir build"), | |
59 | )); | |
60 | } | |
dfeec247 | 61 | _ => return Err(LitToConstError::TypeError), |
a1dfa0c6 | 62 | }; |
a1dfa0c6 | 63 | |
487cf647 | 64 | Ok(tcx.mk_const(valtree, ty)) |
a1dfa0c6 | 65 | } |