Move lit_to_const to pattern and remove the now-empty eval module
This commit is contained in:
parent
b38e8af5eb
commit
57f9e0e468
3 changed files with 98 additions and 119 deletions
|
|
@ -1,114 +0,0 @@
|
|||
// Copyright 2012-2016 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use rustc::middle::const_val::ConstVal;
|
||||
|
||||
use rustc::hir::def_id::DefId;
|
||||
use rustc::ty::{self, Ty, TyCtxt};
|
||||
use rustc::ty::subst::Substs;
|
||||
|
||||
use syntax::ast;
|
||||
|
||||
use rustc_const_math::*;
|
||||
|
||||
pub fn lit_to_const<'a, 'tcx>(lit: &'tcx ast::LitKind,
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
ty: Ty<'tcx>,
|
||||
neg: bool)
|
||||
-> Result<ConstVal<'tcx>, ()> {
|
||||
use syntax::ast::*;
|
||||
|
||||
use rustc::mir::interpret::*;
|
||||
let lit = match *lit {
|
||||
LitKind::Str(ref s, _) => {
|
||||
let s = s.as_str();
|
||||
let id = tcx.allocate_cached(s.as_bytes());
|
||||
let ptr = MemoryPointer::new(id, 0);
|
||||
Value::ByValPair(
|
||||
PrimVal::Ptr(ptr),
|
||||
PrimVal::from_u128(s.len() as u128),
|
||||
)
|
||||
},
|
||||
LitKind::ByteStr(ref data) => {
|
||||
let id = tcx.allocate_cached(data);
|
||||
let ptr = MemoryPointer::new(id, 0);
|
||||
Value::ByVal(PrimVal::Ptr(ptr))
|
||||
},
|
||||
LitKind::Byte(n) => Value::ByVal(PrimVal::Bytes(n as u128)),
|
||||
LitKind::Int(n, _) => {
|
||||
enum Int {
|
||||
Signed(IntTy),
|
||||
Unsigned(UintTy),
|
||||
}
|
||||
let ty = match ty.sty {
|
||||
ty::TyInt(IntTy::Isize) => Int::Signed(tcx.sess.target.isize_ty),
|
||||
ty::TyInt(other) => Int::Signed(other),
|
||||
ty::TyUint(UintTy::Usize) => Int::Unsigned(tcx.sess.target.usize_ty),
|
||||
ty::TyUint(other) => Int::Unsigned(other),
|
||||
_ => bug!(),
|
||||
};
|
||||
let n = match ty {
|
||||
// FIXME(oli-obk): are these casts correct?
|
||||
Int::Signed(IntTy::I8) if neg =>
|
||||
(n as i128 as i8).overflowing_neg().0 as i128 as u128,
|
||||
Int::Signed(IntTy::I16) if neg =>
|
||||
(n as i128 as i16).overflowing_neg().0 as i128 as u128,
|
||||
Int::Signed(IntTy::I32) if neg =>
|
||||
(n as i128 as i32).overflowing_neg().0 as i128 as u128,
|
||||
Int::Signed(IntTy::I64) if neg =>
|
||||
(n as i128 as i64).overflowing_neg().0 as i128 as u128,
|
||||
Int::Signed(IntTy::I128) if neg =>
|
||||
(n as i128).overflowing_neg().0 as u128,
|
||||
Int::Signed(IntTy::I8) => n as i128 as i8 as i128 as u128,
|
||||
Int::Signed(IntTy::I16) => n as i128 as i16 as i128 as u128,
|
||||
Int::Signed(IntTy::I32) => n as i128 as i32 as i128 as u128,
|
||||
Int::Signed(IntTy::I64) => n as i128 as i64 as i128 as u128,
|
||||
Int::Signed(IntTy::I128) => n,
|
||||
Int::Unsigned(UintTy::U8) => n as u8 as u128,
|
||||
Int::Unsigned(UintTy::U16) => n as u16 as u128,
|
||||
Int::Unsigned(UintTy::U32) => n as u32 as u128,
|
||||
Int::Unsigned(UintTy::U64) => n as u64 as u128,
|
||||
Int::Unsigned(UintTy::U128) => n,
|
||||
_ => bug!(),
|
||||
};
|
||||
Value::ByVal(PrimVal::Bytes(n))
|
||||
},
|
||||
LitKind::Float(n, fty) => {
|
||||
let n = n.as_str();
|
||||
let mut f = parse_float(&n, fty)?;
|
||||
if neg {
|
||||
f = -f;
|
||||
}
|
||||
let bits = f.bits;
|
||||
Value::ByVal(PrimVal::Bytes(bits))
|
||||
}
|
||||
LitKind::FloatUnsuffixed(n) => {
|
||||
let fty = match ty.sty {
|
||||
ty::TyFloat(fty) => fty,
|
||||
_ => bug!()
|
||||
};
|
||||
let n = n.as_str();
|
||||
let mut f = parse_float(&n, fty)?;
|
||||
if neg {
|
||||
f = -f;
|
||||
}
|
||||
let bits = f.bits;
|
||||
Value::ByVal(PrimVal::Bytes(bits))
|
||||
}
|
||||
LitKind::Bool(b) => Value::ByVal(PrimVal::Bytes(b as u128)),
|
||||
LitKind::Char(c) => Value::ByVal(PrimVal::Bytes(c as u128)),
|
||||
};
|
||||
Ok(ConstVal::Value(lit))
|
||||
}
|
||||
|
||||
fn parse_float<'tcx>(num: &str, fty: ast::FloatTy)
|
||||
-> Result<ConstFloat, ()> {
|
||||
ConstFloat::from_str(num, fty).map_err(|_| ())
|
||||
}
|
||||
|
|
@ -10,10 +10,7 @@
|
|||
|
||||
//! constant evaluation on the HIR and code to validate patterns/matches
|
||||
|
||||
mod eval;
|
||||
mod _match;
|
||||
pub mod check_match;
|
||||
pub mod pattern;
|
||||
pub mod check;
|
||||
|
||||
pub use self::eval::*;
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ use rustc::hir::def::{Def, CtorKind};
|
|||
use rustc::hir::pat_util::EnumerateAndAdjustIterator;
|
||||
|
||||
use rustc_data_structures::indexed_vec::Idx;
|
||||
use rustc_const_math::ConstFloat;
|
||||
|
||||
use std::cmp::Ordering;
|
||||
use std::fmt;
|
||||
|
|
@ -716,7 +717,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
|
|||
match expr.node {
|
||||
hir::ExprLit(ref lit) => {
|
||||
let ty = self.tables.expr_ty(expr);
|
||||
match super::eval::lit_to_const(&lit.node, self.tcx, ty, false) {
|
||||
match lit_to_const(&lit.node, self.tcx, ty, false) {
|
||||
Ok(val) => {
|
||||
let instance = ty::Instance::new(
|
||||
self.tables.local_id_root.expect("literal outside any scope"),
|
||||
|
|
@ -738,7 +739,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
|
|||
hir::ExprLit(ref lit) => lit,
|
||||
_ => span_bug!(expr.span, "not a literal: {:?}", expr),
|
||||
};
|
||||
match super::eval::lit_to_const(&lit.node, self.tcx, ty, true) {
|
||||
match lit_to_const(&lit.node, self.tcx, ty, true) {
|
||||
Ok(val) => {
|
||||
let instance = ty::Instance::new(
|
||||
self.tables.local_id_root.expect("literal outside any scope"),
|
||||
|
|
@ -1089,3 +1090,98 @@ pub fn compare_const_vals(a: &ConstVal, b: &ConstVal, ty: Ty) -> Option<Ordering
|
|||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn lit_to_const<'a, 'tcx>(lit: &'tcx ast::LitKind,
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
ty: Ty<'tcx>,
|
||||
neg: bool)
|
||||
-> Result<ConstVal<'tcx>, ()> {
|
||||
use syntax::ast::*;
|
||||
|
||||
use rustc::mir::interpret::*;
|
||||
let lit = match *lit {
|
||||
LitKind::Str(ref s, _) => {
|
||||
let s = s.as_str();
|
||||
let id = tcx.allocate_cached(s.as_bytes());
|
||||
let ptr = MemoryPointer::new(id, 0);
|
||||
Value::ByValPair(
|
||||
PrimVal::Ptr(ptr),
|
||||
PrimVal::from_u128(s.len() as u128),
|
||||
)
|
||||
},
|
||||
LitKind::ByteStr(ref data) => {
|
||||
let id = tcx.allocate_cached(data);
|
||||
let ptr = MemoryPointer::new(id, 0);
|
||||
Value::ByVal(PrimVal::Ptr(ptr))
|
||||
},
|
||||
LitKind::Byte(n) => Value::ByVal(PrimVal::Bytes(n as u128)),
|
||||
LitKind::Int(n, _) => {
|
||||
enum Int {
|
||||
Signed(IntTy),
|
||||
Unsigned(UintTy),
|
||||
}
|
||||
let ty = match ty.sty {
|
||||
ty::TyInt(IntTy::Isize) => Int::Signed(tcx.sess.target.isize_ty),
|
||||
ty::TyInt(other) => Int::Signed(other),
|
||||
ty::TyUint(UintTy::Usize) => Int::Unsigned(tcx.sess.target.usize_ty),
|
||||
ty::TyUint(other) => Int::Unsigned(other),
|
||||
_ => bug!(),
|
||||
};
|
||||
let n = match ty {
|
||||
// FIXME(oli-obk): are these casts correct?
|
||||
Int::Signed(IntTy::I8) if neg =>
|
||||
(n as i128 as i8).overflowing_neg().0 as i128 as u128,
|
||||
Int::Signed(IntTy::I16) if neg =>
|
||||
(n as i128 as i16).overflowing_neg().0 as i128 as u128,
|
||||
Int::Signed(IntTy::I32) if neg =>
|
||||
(n as i128 as i32).overflowing_neg().0 as i128 as u128,
|
||||
Int::Signed(IntTy::I64) if neg =>
|
||||
(n as i128 as i64).overflowing_neg().0 as i128 as u128,
|
||||
Int::Signed(IntTy::I128) if neg =>
|
||||
(n as i128).overflowing_neg().0 as u128,
|
||||
Int::Signed(IntTy::I8) => n as i128 as i8 as i128 as u128,
|
||||
Int::Signed(IntTy::I16) => n as i128 as i16 as i128 as u128,
|
||||
Int::Signed(IntTy::I32) => n as i128 as i32 as i128 as u128,
|
||||
Int::Signed(IntTy::I64) => n as i128 as i64 as i128 as u128,
|
||||
Int::Signed(IntTy::I128) => n,
|
||||
Int::Unsigned(UintTy::U8) => n as u8 as u128,
|
||||
Int::Unsigned(UintTy::U16) => n as u16 as u128,
|
||||
Int::Unsigned(UintTy::U32) => n as u32 as u128,
|
||||
Int::Unsigned(UintTy::U64) => n as u64 as u128,
|
||||
Int::Unsigned(UintTy::U128) => n,
|
||||
_ => bug!(),
|
||||
};
|
||||
Value::ByVal(PrimVal::Bytes(n))
|
||||
},
|
||||
LitKind::Float(n, fty) => {
|
||||
let n = n.as_str();
|
||||
let mut f = parse_float(&n, fty)?;
|
||||
if neg {
|
||||
f = -f;
|
||||
}
|
||||
let bits = f.bits;
|
||||
Value::ByVal(PrimVal::Bytes(bits))
|
||||
}
|
||||
LitKind::FloatUnsuffixed(n) => {
|
||||
let fty = match ty.sty {
|
||||
ty::TyFloat(fty) => fty,
|
||||
_ => bug!()
|
||||
};
|
||||
let n = n.as_str();
|
||||
let mut f = parse_float(&n, fty)?;
|
||||
if neg {
|
||||
f = -f;
|
||||
}
|
||||
let bits = f.bits;
|
||||
Value::ByVal(PrimVal::Bytes(bits))
|
||||
}
|
||||
LitKind::Bool(b) => Value::ByVal(PrimVal::Bytes(b as u128)),
|
||||
LitKind::Char(c) => Value::ByVal(PrimVal::Bytes(c as u128)),
|
||||
};
|
||||
Ok(ConstVal::Value(lit))
|
||||
}
|
||||
|
||||
fn parse_float<'tcx>(num: &str, fty: ast::FloatTy)
|
||||
-> Result<ConstFloat, ()> {
|
||||
ConstFloat::from_str(num, fty).map_err(|_| ())
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue