2 use rustc::ty::{self, Ty, TyCtxt, ParamEnv};
3 use syntax_pos::symbol::Symbol;
4 use rustc::mir::interpret::{ConstValue, Scalar};
7 crate enum LitToConstError {
12 crate fn lit_to_const<'a, 'gcx, 'tcx>(
13 lit: &'tcx ast::LitKind,
14 tcx: TyCtxt<'a, 'gcx, 'tcx>,
17 ) -> Result<ty::Const<'tcx>, LitToConstError> {
21 let param_ty = ParamEnv::reveal_all().and(tcx.lift_to_global(&ty).unwrap());
22 let width = tcx.layout_of(param_ty).map_err(|_| LitToConstError::Reported)?.size;
23 trace!("trunc {} with size {} and shift {}", n, width.bits(), 128 - width.bits());
24 let shift = 128 - width.bits();
25 let result = (n << shift) >> shift;
26 trace!("trunc result: {}", result);
27 Ok(ConstValue::Scalar(Scalar::Bits {
29 size: width.bytes() as u8,
33 use rustc::mir::interpret::*;
34 let lit = match *lit {
35 LitKind::Str(ref s, _) => {
37 let id = tcx.allocate_bytes(s.as_bytes());
38 ConstValue::new_slice(Scalar::Ptr(id.into()), s.len() as u64, &tcx)
40 LitKind::Err(ref s) => {
42 let id = tcx.allocate_bytes(s.as_bytes());
44 val: ConstValue::new_slice(Scalar::Ptr(id.into()), s.len() as u64, &tcx),
48 LitKind::ByteStr(ref data) => {
49 let id = tcx.allocate_bytes(data);
50 ConstValue::Scalar(Scalar::Ptr(id.into()))
52 LitKind::Byte(n) => ConstValue::Scalar(Scalar::Bits {
56 LitKind::Int(n, _) if neg => {
58 let n = n.overflowing_neg().0;
61 LitKind::Int(n, _) => trunc(n)?,
62 LitKind::Float(n, fty) => {
63 parse_float(n, fty, neg).map_err(|_| LitToConstError::UnparseableFloat)?
65 LitKind::FloatUnsuffixed(n) => {
66 let fty = match ty.sty {
67 ty::Float(fty) => fty,
70 parse_float(n, fty, neg).map_err(|_| LitToConstError::UnparseableFloat)?
72 LitKind::Bool(b) => ConstValue::Scalar(Scalar::from_bool(b)),
73 LitKind::Char(c) => ConstValue::Scalar(Scalar::from_char(c)),
75 Ok(ty::Const { val: lit, ty })
82 ) -> Result<ConstValue<'tcx>, ()> {
83 let num = num.as_str();
84 use rustc_apfloat::ieee::{Single, Double};
85 use rustc_apfloat::Float;
86 let (bits, size) = match fty {
87 ast::FloatTy::F32 => {
88 num.parse::<f32>().map_err(|_| ())?;
89 let mut f = num.parse::<Single>().unwrap_or_else(|e| {
90 panic!("apfloat::ieee::Single failed to parse `{}`: {:?}", num, e)
97 ast::FloatTy::F64 => {
98 num.parse::<f64>().map_err(|_| ())?;
99 let mut f = num.parse::<Double>().unwrap_or_else(|e| {
100 panic!("apfloat::ieee::Single failed to parse `{}`: {:?}", num, e)
109 Ok(ConstValue::Scalar(Scalar::Bits { bits, size }))