diff options
| author | Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> | 2018-01-25 16:44:45 +0100 |
|---|---|---|
| committer | Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> | 2018-03-08 08:34:10 +0100 |
| commit | 9857eaa4dfc1a103369b423b12cac1993a8d9e96 (patch) | |
| tree | 8dce236499fc6728f2b07e1a4c0c73bc0bdaaa29 | |
| parent | 3b8d2e0016884fdc56e3e2208235606d999990a8 (diff) | |
| download | rust-9857eaa4dfc1a103369b423b12cac1993a8d9e96.tar.gz rust-9857eaa4dfc1a103369b423b12cac1993a8d9e96.zip | |
Nuke ConstInt and Const*size
33 files changed, 159 insertions, 1101 deletions
diff --git a/src/librustc/ich/impls_const_math.rs b/src/librustc/ich/impls_const_math.rs index 6790c2ac7de..5f3ff461c0c 100644 --- a/src/librustc/ich/impls_const_math.rs +++ b/src/librustc/ich/impls_const_math.rs @@ -16,33 +16,6 @@ impl_stable_hash_for!(struct ::rustc_const_math::ConstFloat { bits }); -impl_stable_hash_for!(enum ::rustc_const_math::ConstInt { - I8(val), - I16(val), - I32(val), - I64(val), - I128(val), - Isize(val), - U8(val), - U16(val), - U32(val), - U64(val), - U128(val), - Usize(val) -}); - -impl_stable_hash_for!(enum ::rustc_const_math::ConstIsize { - Is16(i16), - Is32(i32), - Is64(i64) -}); - -impl_stable_hash_for!(enum ::rustc_const_math::ConstUsize { - Us16(i16), - Us32(i32), - Us64(i64) -}); - impl_stable_hash_for!(enum ::rustc_const_math::ConstMathErr { NotInRange, CmpBetweenUnequalTypes, diff --git a/src/librustc/middle/const_val.rs b/src/librustc/middle/const_val.rs index a40147aa2a1..06d4540a455 100644 --- a/src/librustc/middle/const_val.rs +++ b/src/librustc/middle/const_val.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -pub use rustc_const_math::ConstInt; - use hir::def_id::DefId; use ty::{self, TyCtxt, layout}; use ty::subst::Substs; @@ -56,18 +54,6 @@ impl<'tcx> ConstVal<'tcx> { None => bug!("expected constant u64, got {:#?}", self), } } - pub fn unwrap_usize<'a, 'gcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> ConstUsize { - match *self { - ConstVal::Value(Value::ByVal(PrimVal::Bytes(b))) => { - assert_eq!(b as u64 as u128, b); - match ConstUsize::new(b as u64, tcx.sess.target.usize_ty) { - Ok(val) => val, - Err(e) => bug!("{:#?} is not a usize {:?}", self, e), - } - }, - _ => bug!("expected constant u64, got {:#?}", self), - } - } } #[derive(Clone, Debug)] diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 24f4a74b3ac..e39765699f9 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -15,7 +15,7 @@ use graphviz::IntoCow; use middle::const_val::ConstVal; use middle::region; -use rustc_const_math::{ConstUsize, ConstMathErr}; +use rustc_const_math::ConstMathErr; use rustc_data_structures::sync::{Lrc}; use rustc_data_structures::indexed_vec::{IndexVec, Idx}; use rustc_data_structures::control_flow_graph::dominators::{Dominators, dominators}; @@ -1563,7 +1563,7 @@ pub enum Rvalue<'tcx> { Use(Operand<'tcx>), /// [x; 32] - Repeat(Operand<'tcx>, ConstUsize), + Repeat(Operand<'tcx>, u64), /// &x or &mut x Ref(Region<'tcx>, BorrowKind, Place<'tcx>), diff --git a/src/librustc/mir/tcx.rs b/src/librustc/mir/tcx.rs index 067c1742040..7d232ac20bf 100644 --- a/src/librustc/mir/tcx.rs +++ b/src/librustc/mir/tcx.rs @@ -149,7 +149,7 @@ impl<'tcx> Rvalue<'tcx> { match *self { Rvalue::Use(ref operand) => operand.ty(local_decls, tcx), Rvalue::Repeat(ref operand, count) => { - tcx.mk_array_const_usize(operand.ty(local_decls, tcx), count) + tcx.mk_array(operand.ty(local_decls, tcx), count) } Rvalue::Ref(reg, bk, ref place) => { let place_ty = place.ty(local_decls, tcx).to_ty(tcx); diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs index 54d3ed38d65..650af8dc4d9 100644 --- a/src/librustc/mir/visit.rs +++ b/src/librustc/mir/visit.rs @@ -12,7 +12,6 @@ use hir::def_id::DefId; use ty::subst::Substs; use ty::{ClosureSubsts, Region, Ty, GeneratorInterior}; use mir::*; -use rustc_const_math::ConstUsize; use syntax_pos::Span; // # The MIR Visitor @@ -243,12 +242,6 @@ macro_rules! make_mir_visitor { self.super_generator_interior(interior); } - fn visit_const_usize(&mut self, - const_usize: & $($mutability)* ConstUsize, - _: Location) { - self.super_const_usize(const_usize); - } - fn visit_local_decl(&mut self, local: Local, local_decl: & $($mutability)* LocalDecl<'tcx>) { @@ -529,10 +522,8 @@ macro_rules! make_mir_visitor { self.visit_operand(operand, location); } - Rvalue::Repeat(ref $($mutability)* value, - ref $($mutability)* length) => { + Rvalue::Repeat(ref $($mutability)* value, _) => { self.visit_operand(value, location); - self.visit_const_usize(length, location); } Rvalue::Ref(ref $($mutability)* r, bk, ref $($mutability)* path) => { @@ -789,9 +780,6 @@ macro_rules! make_mir_visitor { _substs: & $($mutability)* ClosureSubsts<'tcx>) { } - fn super_const_usize(&mut self, _const_usize: & $($mutability)* ConstUsize) { - } - // Convenience methods fn visit_location(&mut self, mir: & $($mutability)* Mir<'tcx>, location: Location) { diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index a4e5f725837..8c508c2f17c 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -54,7 +54,6 @@ use rustc_data_structures::stable_hasher::{HashStable, hash_stable_hashmap, StableHasher, StableHasherResult, StableVec}; use arena::{TypedArena, DroplessArena}; -use rustc_const_math::ConstUsize; use rustc_data_structures::indexed_vec::IndexVec; use rustc_data_structures::sync::Lrc; use std::any::Any; @@ -2096,13 +2095,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } pub fn mk_array(self, ty: Ty<'tcx>, n: u64) -> Ty<'tcx> { - let n = ConstUsize::new(n, self.sess.target.usize_ty).unwrap(); - self.mk_array_const_usize(ty, n) - } - - pub fn mk_array_const_usize(self, ty: Ty<'tcx>, n: ConstUsize) -> Ty<'tcx> { self.mk_ty(TyArray(ty, self.mk_const(ty::Const { - val: ConstVal::Value(Value::ByVal(PrimVal::Bytes(n.as_u64().into()))), + val: ConstVal::Value(Value::ByVal(PrimVal::Bytes(n.into()))), ty: self.types.usize }))) } diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index 79f01a32cd9..b02f221bb81 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -1537,7 +1537,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { if variants[i].iter().any(|f| f.abi == Abi::Uninhabited) { continue; } - let x = discr.to_u128_unchecked() as i128; + let x = discr.val as i128; if x < min { min = x; } if x > max { max = x; } } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 2c7ec5155a6..cb09687a657 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -32,7 +32,7 @@ use session::CrateDisambiguator; use traits; use ty; use ty::subst::{Subst, Substs}; -use ty::util::IntTypeExt; +use ty::util::{IntTypeExt, Discr}; use ty::walk::TypeWalker; use util::common::ErrorReported; use util::nodemap::{NodeSet, DefIdMap, FxHashMap, FxHashSet}; @@ -53,7 +53,6 @@ use syntax::attr; use syntax::ext::hygiene::{Mark, SyntaxContext}; use syntax::symbol::{Symbol, InternedString}; use syntax_pos::{DUMMY_SP, Span}; -use rustc_const_math::ConstInt; use rustc_data_structures::accumulate_vec::IntoIter as AccIntoIter; use rustc_data_structures::stable_hasher::{StableHasher, StableHasherResult, @@ -1826,13 +1825,13 @@ impl<'a, 'gcx, 'tcx> AdtDef { #[inline] pub fn discriminants(&'a self, tcx: TyCtxt<'a, 'gcx, 'tcx>) - -> impl Iterator<Item=ConstInt> + 'a { + -> impl Iterator<Item=Discr<'tcx>> + 'a { let param_env = ParamEnv::empty(traits::Reveal::UserFacing); let repr_type = self.repr.discr_type(); let initial = repr_type.initial_discriminant(tcx.global_tcx()); - let mut prev_discr = None::<ConstInt>; + let mut prev_discr = None::<Discr<'tcx>>; self.variants.iter().map(move |v| { - let mut discr = prev_discr.map_or(initial, |d| d.wrap_incr()); + let mut discr = prev_discr.map_or(initial, |d| d.wrap_incr(tcx)); if let VariantDiscr::Explicit(expr_did) = v.discr { let substs = Substs::identity_for_item(tcx.global_tcx(), expr_did); let instance = ty::Instance::new(expr_did, substs); @@ -1846,12 +1845,9 @@ impl<'a, 'gcx, 'tcx> AdtDef { .. }) => { trace!("discriminants: {} ({:?})", b, repr_type); - use syntax::attr::IntType; - discr = match repr_type { - IntType::SignedInt(int_type) => ConstInt::new_signed( - b as i128, int_type, tcx.sess.target.isize_ty).unwrap(), - IntType::UnsignedInt(uint_type) => ConstInt::new_unsigned( - b, uint_type, tcx.sess.target.usize_ty).unwrap(), + discr = Discr { + val: b, + ty: repr_type.to_ty(tcx), }; } _ => { @@ -1877,7 +1873,7 @@ impl<'a, 'gcx, 'tcx> AdtDef { pub fn discriminant_for_variant(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, variant_index: usize) - -> ConstInt { + -> Discr<'tcx> { let param_env = ParamEnv::empty(traits::Reveal::UserFacing); let repr_type = self.repr.discr_type(); let mut explicit_value = repr_type.initial_discriminant(tcx.global_tcx()); @@ -1901,12 +1897,9 @@ impl<'a, 'gcx, 'tcx> AdtDef { .. }) => { trace!("discriminants: {} ({:?})", b, repr_type); - use syntax::attr::IntType; - explicit_value = match repr_type { - IntType::SignedInt(int_type) => ConstInt::new_signed( - b as i128, int_type, tcx.sess.target.isize_ty).unwrap(), - IntType::UnsignedInt(uint_type) => ConstInt::new_unsigned( - b, uint_type, tcx.sess.target.usize_ty).unwrap(), + explicit_value = Discr { + val: b, + ty: repr_type.to_ty(tcx), }; break; } @@ -1925,18 +1918,7 @@ impl<'a, 'gcx, 'tcx> AdtDef { } } } - let discr = explicit_value.to_u128_unchecked() - .wrapping_add((variant_index - explicit_index) as u128); - match repr_type { - attr::UnsignedInt(ty) => { - ConstInt::new_unsigned_truncating(discr, ty, - tcx.sess.target.usize_ty) - } - attr::SignedInt(ty) => { - ConstInt::new_signed_truncating(discr as i128, ty, - tcx.sess.target.isize_ty) - } - } + explicit_value.checked_add(tcx, (variant_index - explicit_index) as u128).0 } pub fn destructor(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Option<Destructor> { diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index cdf619a1dfa..e65a3b620c3 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -26,57 +26,95 @@ use util::common::ErrorReported; use middle::lang_items; use mir::interpret::{Value, PrimVal}; -use rustc_const_math::{ConstInt, ConstIsize, ConstUsize}; use rustc_data_structures::stable_hasher::{StableHasher, StableHasherResult, HashStable}; use rustc_data_structures::fx::FxHashMap; -use std::cmp; +use std::{cmp, fmt}; use std::hash::Hash; use std::intrinsics; -use syntax::ast::{self, Name}; +use syntax::ast::{self, Name, UintTy, IntTy}; use syntax::attr::{self, SignedInt, UnsignedInt}; use syntax_pos::{Span, DUMMY_SP}; -type Disr = ConstInt; - -pub trait IntTypeExt { - fn to_ty<'a, 'gcx, 'tcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx>; - fn disr_incr<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, val: Option<Disr>) - -> Option<Disr>; - fn assert_ty_matches(&self, val: Disr); - fn initial_discriminant<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Disr; +#[derive(Copy, Clone, Debug)] +pub struct Discr<'tcx> { + pub val: u128, + pub ty: Ty<'tcx> } +impl<'tcx> fmt::Display for Discr<'tcx> { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + if self.ty.is_signed() { + write!(fmt, "{}", self.val as i128) + } else { + write!(fmt, "{}", self.val) + } + } +} -macro_rules! typed_literal { - ($tcx:expr, $ty:expr, $lit:expr) => { - match $ty { - SignedInt(ast::IntTy::I8) => ConstInt::I8($lit), - SignedInt(ast::IntTy::I16) => ConstInt::I16($lit), - SignedInt(ast::IntTy::I32) => ConstInt::I32($lit), - SignedInt(ast::IntTy::I64) => ConstInt::I64($lit), - SignedInt(ast::IntTy::I128) => ConstInt::I128($lit), - SignedInt(ast::IntTy::Isize) => match $tcx.sess.target.isize_ty { - ast::IntTy::I16 => ConstInt::Isize(ConstIsize::Is16($lit)), - ast::IntTy::I32 => ConstInt::Isize(ConstIsize::Is32($lit)), - ast::IntTy::I64 => ConstInt::Isize(ConstIsize::Is64($lit)), - _ => bug!(), - }, - UnsignedInt(ast::UintTy::U8) => ConstInt::U8($lit), - UnsignedInt(ast::UintTy::U16) => ConstInt::U16($lit), - UnsignedInt(ast::UintTy::U32) => ConstInt::U32($lit), - UnsignedInt(ast::UintTy::U64) => ConstInt::U64($lit), - UnsignedInt(ast::UintTy::U128) => ConstInt::U128($lit), - UnsignedInt(ast::UintTy::Usize) => match $tcx.sess.target.usize_ty { - ast::UintTy::U16 => ConstInt::Usize(ConstUsize::Us16($lit)), - ast::UintTy::U32 => ConstInt::Usize(ConstUsize::Us32($lit)), - ast::UintTy::U64 => ConstInt::Usize(ConstUsize::Us64($lit)), - _ => bug!(), - }, +impl<'tcx> Discr<'tcx> { + /// Adds 1 to the value and wraps around if the maximum for the type is reached + pub fn wrap_incr<'a, 'gcx>(self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Self { + self.checked_add(tcx, 1).0 + } + pub fn checked_add<'a, 'gcx>(self, tcx: TyCtxt<'a, 'gcx, 'tcx>, n: u128) -> (Self, bool) { + let ty = match self.ty.sty { + TyInt(IntTy::Isize) => tcx.mk_mach_int(tcx.sess.target.isize_ty), + TyUint(UintTy::Usize) => tcx.mk_mach_uint(tcx.sess.target.usize_ty), + _ => self.ty, + }; + let (min, max) = match ty.sty { + TyInt(IntTy::I8) => (i8::min_value() as i128 as u128, i8::max_value() as u128), + TyInt(IntTy::I16) => (i16::min_value() as i128 as u128, i16::max_value() as u128), + TyInt(IntTy::I32) => (i32::min_value() as i128 as u128, i32::max_value() as u128), + TyInt(IntTy::I64) => (i64::min_value() as i128 as u128, i64::max_value() as u128), + TyInt(IntTy::I128) => (i128::min_value() as i128 as u128, i128::max_value() as u128), + TyInt(IntTy::Isize) => unreachable!(), + TyUint(UintTy::U8) => (u8::min_value() as u128, u8::max_value() as u128), + TyUint(UintTy::U16) => (u16::min_value() as u128, u16::max_value() as u128), + TyUint(UintTy::U32) => (u32::min_value() as u128, u32::max_value() as u128), + TyUint(UintTy::U64) => (u64::min_value() as u128, u64::max_value() as u128), + TyUint(UintTy::U128) => (u128::min_value() as u128, u128::max_value()), + TyUint(UintTy::Usize) => unreachable!(), + _ => bug!("not a valid discriminant type: {}", ty) + }; + if ty.is_signed() { + let val = self.val as i128; + let n = n as i128; + let max = max as i128; + let min = min as i128; + let oflo = val > max - n; + let val = if oflo { + min + (n - (max - val)) + } else { + val + n + }; + (Self { + val: val as u128, + ty: self.ty, + }, oflo) + } else { + let oflo = self.val > max - n; + let val = if oflo { + min + (n - (max - self.val)) + } else { + self.val + n + }; + (Self { + val, + ty: self.ty, + }, oflo) } } } +pub trait IntTypeExt { + fn to_ty<'a, 'gcx, 'tcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx>; + fn disr_incr<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, val: Option<Discr<'tcx>>) + -> Option<Discr<'tcx>>; + fn initial_discriminant<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Discr<'tcx>; +} + impl IntTypeExt for attr::IntType { fn to_ty<'a, 'gcx, 'tcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> { match *self { @@ -95,33 +133,26 @@ impl IntTypeExt for attr::IntType { } } - fn initial_discriminant<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Disr { - typed_literal!(tcx, *self, 0) - } - - fn assert_ty_matches(&self, val: Disr) { - match (*self, val) { - (SignedInt(ast::IntTy::I8), ConstInt::I8(_)) => {}, - (SignedInt(ast::IntTy::I16), ConstInt::I16(_)) => {}, - (SignedInt(ast::IntTy::I32), ConstInt::I32(_)) => {}, - (SignedInt(ast::IntTy::I64), ConstInt::I64(_)) => {}, - (SignedInt(ast::IntTy::I128), ConstInt::I128(_)) => {}, - (SignedInt(ast::IntTy::Isize), ConstInt::Isize(_)) => {}, - (UnsignedInt(ast::UintTy::U8), ConstInt::U8(_)) => {}, - (UnsignedInt(ast::UintTy::U16), ConstInt::U16(_)) => {}, - (UnsignedInt(ast::UintTy::U32), ConstInt::U32(_)) => {}, - (UnsignedInt(ast::UintTy::U64), ConstInt::U64(_)) => {}, - (UnsignedInt(ast::UintTy::U128), ConstInt::U128(_)) => {}, - (UnsignedInt(ast::UintTy::Usize), ConstInt::Usize(_)) => {}, - _ => bug!("disr type mismatch: {:?} vs {:?}", self, val), + fn initial_discriminant<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Discr<'tcx> { + Discr { + val: 0, + ty: self.to_ty(tcx) } } - fn disr_incr<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, val: Option<Disr>) - -> Option<Disr> { + fn disr_incr<'a, 'tcx>( + &self, + tcx: TyCtxt<'a, 'tcx, 'tcx>, + val: Option<Discr<'tcx>>, + ) -> Option<Discr<'tcx>> { if let Some(val) = val { - self.assert_ty_matches(val); - (val + typed_literal!(tcx, *self, 1)).ok() + assert_eq!(self.to_ty(tcx), val.ty); + let (new, oflo) = val.checked_add(tcx, 1); + if oflo { + None + } else { + Some(new) + } } else { Some(self.initial_discriminant(tcx)) } @@ -682,15 +713,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { }) } - pub fn const_usize(&self, val: u16) -> ConstInt { - match self.sess.target.usize_ty { - ast::UintTy::U16 => ConstInt::Usize(ConstUsize::Us16(val as u16)), - ast::UintTy::U32 => ConstInt::Usize(ConstUsize::Us32(val as u32)), - ast::UintTy::U64 => ConstInt::Usize(ConstUsize::Us64(val as u64)), - _ => bug!(), - } - } - /// Return whether the node pointed to by def_id is a static item, and its mutability pub fn is_static(&self, def_id: DefId) -> Option<hir::Mutability> { if let Some(node) = self.hir.get_if_local(def_id) { diff --git a/src/librustc_const_math/int.rs b/src/librustc_const_math/int.rs deleted file mode 100644 index 4ec27d7ade5..00000000000 --- a/src/librustc_const_math/int.rs +++ /dev/null @@ -1,590 +0,0 @@ -// Copyright 2015 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 std::cmp::Ordering; -use syntax::attr::IntType; -use syntax::ast::{IntTy, UintTy}; - -use super::isize::*; -use super::usize::*; -use super::err::*; - -#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable, Hash, Eq, PartialEq)] -pub enum ConstInt { - I8(i8), - I16(i16), - I32(i32), - I64(i64), - I128(i128), - Isize(ConstIsize), - U8(u8), - U16(u16), - U32(u32), - U64(u64), - U128(u128), - Usize(ConstUsize), -} -pub use self::ConstInt::*; - - -macro_rules! bounds { - ($ct: ty, $($t:ident $min:ident $max:ident)*) => { - $( - pub const $min: $ct = $t::min_value() as $ct; - pub const $max: $ct = $t::max_value() as $ct; - )* - }; - ($ct: ty: $min_val: expr, $($t:ident $min:ident $max:ident)*) => { - $( - pub const $min: $ct = $min_val; - pub const $max: $ct = $t::max_value() as $ct; - )* - } -} - -mod ubounds { - #![allow(dead_code)] - bounds!{u128: 0, - i8 I8MIN I8MAX i16 I16MIN I16MAX i32 I32MIN I32MAX i64 I64MIN I64MAX i128 I128MIN I128MAX - u8 U8MIN U8MAX u16 U16MIN U16MAX u32 U32MIN U32MAX u64 U64MIN U64MAX u128 U128MIN U128MAX - // do not add constants for isize/usize, because these are guaranteed to be wrong for - // arbitrary host/target combinations - } -} - -mod ibounds { - #![allow(dead_code)] - bounds!(i128, u64 U64MIN U64MAX); - - pub const U128MIN: i128 = 0; - pub const U128MAX: i128 = i128::max_value(); - - bounds!{i128, - i8 I8MIN I8MAX i16 I16MIN I16MAX i32 I32MIN I32MAX i64 I64MIN I64MAX i128 I128MIN I128MAX - u8 U8MIN U8MAX u16 U16MIN U16MAX u32 U32MIN U32MAX - // do not add constants for isize/usize, because these are guaranteed to be wrong for - // arbitrary host/target combinations - } -} - -impl ConstInt { - /// Creates a new unsigned ConstInt with matching type while also checking that overflow does - /// not happen. - pub fn new_unsigned(val: u128, ty: UintTy, usize_ty: UintTy) -> Option<ConstInt> { - match ty { - UintTy::U8 if val <= ubounds::U8MAX => Some(U8(val as u8)), - UintTy::U16 if val <= ubounds::U16MAX => Some(U16(val as u16)), - UintTy::U32 if val <= ubounds::U32MAX => Some(U32(val as u32)), - UintTy::U64 if val <= ubounds::U64MAX => Some(U64(val as u64)), - UintTy::Usize if val <= ubounds::U64MAX => ConstUsize::new(val as u64, usize_ty).ok() - .map(Usize), - UintTy::U128 => Some(U128(val)), - _ => None - } - } - - /// Creates a new signed ConstInt with matching type while also checking that overflow does - /// not happen. - pub fn new_signed(val: i128, ty: IntTy, isize_ty: IntTy) -> Option<ConstInt> { - match ty { - IntTy::I8 if val <= ibounds::I8MAX => Some(I8(val as i8)), - IntTy::I16 if val <= ibounds::I16MAX => Some(I16(val as i16)), - IntTy::I32 if val <= ibounds::I32MAX => Some(I32(val as i32)), - IntTy::I64 if val <= ibounds::I64MAX => Some(I64(val as i64)), - IntTy::Isize if val <= ibounds::I64MAX => ConstIsize::new(val as i64, isize_ty).ok() - .map(Isize), - IntTy::I128 => Some(I128(val)), - _ => None - } - } - - /// Creates a new unsigned ConstInt with matching type. - pub fn new_unsigned_truncating(val: u128, ty: UintTy, usize_ty: UintTy) -> ConstInt { - match ty { - UintTy::U8 => U8(val as u8), - UintTy::U16 => U16(val as u16), - UintTy::U32 => U32(val as u32), - UintTy::U64 => U64(val as u64), - UintTy::Usize => Usize(ConstUsize::new_truncating(val, usize_ty)), - UintTy::U128 => U128(val) - } - } - - /// Creates a new signed ConstInt with matching type. - pub fn new_signed_truncating(val: i128, ty: IntTy, isize_ty: IntTy) -> ConstInt { - match ty { - IntTy::I8 => I8(val as i8), - IntTy::I16 => I16(val as i16), - IntTy::I32 => I32(val as i32), - IntTy::I64 => I64(val as i64), - IntTy::Isize => Isize(ConstIsize::new_truncating(val, isize_ty)), - IntTy::I128 => I128(val) - } - } - - /// Description of the type, not the value - pub fn description(&self) -> &'static str { - match *self { - I8(_) => "i8", - I16(_) => "i16", - I32(_) => "i32", - I64(_) => "i64", - I128(_) => "i128", - Isize(_) => "isize", - U8(_) => "u8", - U16(_) => "u16", - U32(_) => "u32", - U64(_) => "u64", - U128(_) => "u128", - Usize(_) => "usize", - } - } - - /// Erases the type and returns a u128. - /// This is not the same as `-5i8 as u128` but as `-5i8 as i128 as u128` - pub fn to_u128_unchecked(self) -> u128 { - match self { - I8(i) => i as i128 as u128, - I16(i) => i as i128 as u128, - I32(i) => i as i128 as u128, - I64(i) => i as i128 as u128, - I128(i) => i as i128 as u128, - Isize(Is16(i)) => i as i128 as u128, - Isize(Is32(i)) => i as i128 as u128, - Isize(Is64(i)) => i as i128 as u128, - U8(i) => i as u128, - U16(i) => i as u128, - U32(i) => i as u128, - U64(i) => i as u128, - U128(i) => i as u128, - Usize(Us16(i)) => i as u128, - Usize(Us32(i)) => i as u128, - Usize(Us64(i)) => i as u128, - } - } - - /// Converts the value to a `u32` if it's in the range 0...std::u32::MAX - pub fn to_u32(&self) -> Option<u32> { - self.to_u128().and_then(|v| if v <= u32::max_value() as u128 { - Some(v as u32) - } else { - None - }) - } - - /// Converts the value to a `u64` if it's in the range 0...std::u64::MAX - pub fn to_u64(&self) -> Option<u64> { - self.to_u128().and_then(|v| if v <= u64::max_value() as u128 { - Some(v as u64) - } else { - None - }) - } - - /// Converts the value to a `u128` if it's in the range 0...std::u128::MAX - pub fn to_u128(&self) -> Option<u128> { - match *self { - I8(v) if v >= 0 => Some(v as u128), - I16(v) if v >= 0 => Some(v as u128), - I32(v) if v >= 0 => Some(v as u128), - I64(v) if v >= 0 => Some(v as u128), - I128(v) if v >= 0 => Some(v as u128), - Isize(Is16(v)) if v >= 0 => Some(v as u128), - Isize(Is32(v)) if v >= 0 => Some(v as u128), - Isize(Is64(v)) if v >= 0 => Some(v as u128), - U8(v) => Some(v as u128), - U16(v) => Some(v as u128), - U32(v) => Some(v as u128), - U64(v) => Some(v as u128), - U128(v) => Some(v as u128), - Usize(Us16(v)) => Some(v as u128), - Usize(Us32(v)) => Some(v as u128), - Usize(Us64(v)) => Some(v as u128), - _ => None, - } - } - - pub fn is_negative(&self) -> bool { - match *self { - I8(v) => v < 0, - I16(v) => v < 0, - I32(v) => v < 0, - I64(v) => v < 0, - I128(v) => v < 0, - Isize(Is16(v)) => v < 0, - Isize(Is32(v)) => v < 0, - Isize(Is64(v)) => v < 0, - _ => false, - } - } - - /// Compares the values if they are of the same type - pub fn try_cmp(self, rhs: Self) -> Result<::std::cmp::Ordering, ConstMathErr> { - match (self, rhs) { - (I8(a), I8(b)) => Ok(a.cmp(&b)), - (I16(a), I16(b)) => Ok(a.cmp(&b)), - (I32(a), I32(b)) => Ok(a.cmp(&b)), - (I64(a), I64(b)) => Ok(a.cmp(&b)), - (I128(a), I128(b)) => Ok(a.cmp(&b)), - (Isize(Is16(a)), Isize(Is16(b))) => Ok(a.cmp(&b)), - (Isize(Is32(a)), Isize(Is32(b))) => Ok(a.cmp(&b)), - (Isize(Is64(a)), Isize(Is64(b))) => Ok(a.cmp(&b)), - (U8(a), U8(b)) => Ok(a.cmp(&b)), - (U16(a), U16(b)) => Ok(a.cmp(&b)), - (U32(a), U32(b)) => Ok(a.cmp(&b)), - (U64(a), U64(b)) => Ok(a.cmp(&b)), - (U128(a), U128(b)) => Ok(a.cmp(&b)), - (Usize(Us16(a)), Usize(Us16(b))) => Ok(a.cmp(&b)), - (Usize(Us32(a)), Usize(Us32(b))) => Ok(a.cmp(&b)), - (Usize(Us64(a)), Usize(Us64(b))) => Ok(a.cmp(&b)), - _ => Err(CmpBetweenUnequalTypes), - } - } - - /// Adds 1 to the value and wraps around if the maximum for the type is reached - pub fn wrap_incr(self) -> Self { - macro_rules! add1 { - ($e:expr) => { ($e).wrapping_add(1) } - } - match self { - ConstInt::I8(i) => ConstInt::I8(add1!(i)), - ConstInt::I16(i) => ConstInt::I16(add1!(i)), - ConstInt::I32(i) => ConstInt::I32(add1!(i)), - ConstInt::I64(i) => ConstInt::I64(add1!(i)), - ConstInt::I128(i) => ConstInt::I128(add1!(i)), - ConstInt::Isize(ConstIsize::Is16(i)) => ConstInt::Isize(ConstIsize::Is16(add1!(i))), - ConstInt::Isize(ConstIsize::Is32(i)) => ConstInt::Isize(ConstIsize::Is32(add1!(i))), - ConstInt::Isize(ConstIsize::Is64(i)) => ConstInt::Isize(ConstIsize::Is64(add1!(i))), - ConstInt::U8(i) => ConstInt::U8(add1!(i)), - ConstInt::U16(i) => ConstInt::U16(add1!(i)), - ConstInt::U32(i) => ConstInt::U32(add1!(i)), - ConstInt::U64(i) => ConstInt::U64(add1!(i)), - ConstInt::U128(i) => ConstInt::U128(add1!(i)), - ConstInt::Usize(ConstUsize::Us16(i)) => ConstInt::Usize(ConstUsize::Us16(add1!(i))), - ConstInt::Usize(ConstUsize::Us32(i)) => ConstInt::Usize(ConstUsize::Us32(add1!(i))), - ConstInt::Usize(ConstUsize::Us64(i)) => ConstInt::Usize(ConstUsize::Us64(add1!(i))), - } - } - - pub fn int_type(self) -> IntType { - match self { - ConstInt::I8(_) => IntType::SignedInt(IntTy::I8), - ConstInt::I16(_) => IntType::SignedInt(IntTy::I16), - ConstInt::I32(_) => IntType::SignedInt(IntTy::I32), - ConstInt::I64(_) => IntType::SignedInt(IntTy::I64), - ConstInt::I128(_) => IntType::SignedInt(IntTy::I128), - ConstInt::Isize(_) => IntType::SignedInt(IntTy::Isize), - ConstInt::U8(_) => IntType::UnsignedInt(UintTy::U8), - ConstInt::U16(_) => IntType::UnsignedInt(UintTy::U16), - ConstInt::U32(_) => IntType::UnsignedInt(UintTy::U32), - ConstInt::U64(_) => IntType::UnsignedInt(UintTy::U64), - ConstInt::U128(_) => IntType::UnsignedInt(UintTy::U128), - ConstInt::Usize(_) => IntType::UnsignedInt(UintTy::Usize), - } - } -} - -impl ::std::cmp::PartialOrd for ConstInt { - fn partial_cmp(&self, other: &Self) -> Option<Ordering> { - self.try_cmp(*other).ok() - } -} - -impl ::std::cmp::Ord for ConstInt { - fn cmp(&self, other: &Self) -> Ordering { - self.try_cmp(*other).unwrap() - } -} - -impl ::std::fmt::Display for ConstInt { - fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> { - match *self { - I8(i) => write!(fmt, "{}i8", i), - I16(i) => write!(fmt, "{}i16", i), - I32(i) => write!(fmt, "{}i32", i), - I64(i) => write!(fmt, "{}i64", i), - I128(i) => write!(fmt, "{}i128", i), - Isize(i) => write!(fmt, "{}isize", i), - U8(i) => write!(fmt, "{}u8", i), - U16(i) => write!(fmt, "{}u16", i), - U32(i) => write!(fmt, "{}u32", i), - U64(i) => write!(fmt, "{}u64", i), - U128(i) => write!(fmt, "{}u128", i), - Usize(i) => write!(fmt, "{}usize", i), - } - } -} - -macro_rules! overflowing { - ($e:expr, $err:expr) => {{ - if $e.1 { - return Err(Overflow($err)); - } else { - $e.0 - } - }} -} - -macro_rules! impl_binop { - ($op:ident, $func:ident, $checked_func:ident) => { - impl ::std::ops::$op for ConstInt { - type Output = Result<Self, ConstMathErr>; - fn $func(self, rhs: Self) -> Result<Self, ConstMathErr> { - match (self, rhs) { - (I8(a), I8(b)) => a.$checked_func(b).map(I8), - (I16(a), I16(b)) => a.$checked_func(b).map(I16), - (I32(a), I32(b)) => a.$checked_func(b).map(I32), - (I64(a), I64(b)) => a.$checked_func(b).map(I64), - (I128(a), I128(b)) => a.$checked_func(b).map(I128), - (Isize(Is16(a)), Isize(Is16(b))) => a.$checked_func(b).map(Is16).map(Isize), - (Isize(Is32(a)), Isize(Is32(b))) => a.$checked_func(b).map(Is32).map(Isize), - (Isize(Is64(a)), Isize(Is64(b))) => a.$checked_func(b).map(Is64).map(Isize), - (U8(a), U8(b)) => a.$checked_func(b).map(U8), - (U16(a), U16(b)) => a.$checked_func(b).map(U16), - (U32(a), U32(b)) => a.$checked_func(b).map(U32), - (U64(a), U64(b)) => a.$checked_func(b).map(U64), - (U128(a), U128(b)) => a.$checked_func(b).map(U128), - (Usize(Us16(a)), Usize(Us16(b))) => a.$checked_func(b).map(Us16).map(Usize), - (Usize(Us32(a)), Usize(Us32(b))) => a.$checked_func(b).map(Us32).map(Usize), - (Usize(Us64(a)), Usize(Us64(b))) => a.$checked_func(b).map(Us64).map(Usize), - _ => return Err(UnequalTypes(Op::$op)), - }.ok_or(Overflow(Op::$op)) - } - } - } -} - -macro_rules! derive_binop { - ($op:ident, $func:ident) => { - impl ::std::ops::$op for ConstInt { - type Output = Result<Self, ConstMathErr>; - fn $func(self, rhs: Self) -> Result<Self, ConstMathErr> { - match (self, rhs) { - (I8(a), I8(b)) => Ok(I8(a.$func(b))), - (I16(a), I16(b)) => Ok(I16(a.$func(b))), - (I32(a), I32(b)) => Ok(I32(a.$func(b))), - (I64(a), I64(b)) => Ok(I64(a.$func(b))), - (I128(a), I128(b)) => Ok(I128(a.$func(b))), - (Isize(Is16(a)), Isize(Is16(b))) => Ok(Isize(Is16(a.$func(b)))), - (Isize(Is32(a)), Isize(Is32(b))) => Ok(Isize(Is32(a.$func(b)))), - (Isize(Is64(a)), Isize(Is64(b))) => Ok(Isize(Is64(a.$func(b)))), - (U8(a), U8(b)) => Ok(U8(a.$func(b))), - (U16(a), U16(b)) => Ok(U16(a.$func(b))), - (U32(a), U32(b)) => Ok(U32(a.$func(b))), - (U64(a), U64(b)) => Ok(U64(a.$func(b))), - (U128(a), U128(b)) => Ok(U128(a.$func(b))), - (Usize(Us16(a)), Usize(Us16(b))) => Ok(Usize(Us16(a.$func(b)))), - (Usize(Us32(a)), Usize(Us32(b))) => Ok(Usize(Us32(a.$func(b)))), - (Usize(Us64(a)), Usize(Us64(b))) => Ok(Usize(Us64(a.$func(b)))), - _ => Err(UnequalTypes(Op::$op)), - } - } - } - } -} - -impl_binop!(Add, add, checked_add); -impl_binop!(Sub, sub, checked_sub); -impl_binop!(Mul, mul, checked_mul); -derive_binop!(BitAnd, bitand); -derive_binop!(BitOr, bitor); -derive_binop!(BitXor, bitxor); - -const I128_MIN: i128 = ::std::i128::MIN; - -fn check_division( - lhs: ConstInt, - rhs: ConstInt, - op: Op, - zerr: ConstMathErr, -) -> Result<(), ConstMathErr> { - match (lhs, rhs) { - (I8(_), I8(0)) => Err(zerr), - (I16(_), I16(0)) => Err(zerr), - (I32(_), I32(0)) => Err(zerr), - (I64(_), I64(0)) => Err(zerr), - (I128(_), I128(0)) => Err(zerr), - (Isize(_), Isize(Is16(0))) => Err(zerr), - (Isize(_), Isize(Is32(0))) => Err(zerr), - (Isize(_), Isize(Is64(0))) => Err(zerr), - - (U8(_), U8(0)) => Err(zerr), - (U16(_), U16(0)) => Err(zerr), - (U32(_), U32(0)) => Err(zerr), - (U64(_), U64(0)) => Err(zerr), - (U128(_), U128(0)) => Err(zerr), - (Usize(_), Usize(Us16(0))) => Err(zerr), - (Usize(_), Usize(Us32(0))) => Err(zerr), - (Usize(_), Usize(Us64(0))) => Err(zerr), - - (I8(::std::i8::MIN), I8(-1)) => Err(Overflow(op)), - (I16(::std::i16::MIN), I16(-1)) => Err(Overflow(op)), - (I32(::std::i32::MIN), I32(-1)) => Err(Overflow(op)), - (I64(::std::i64::MIN), I64(-1)) => Err(Overflow(op)), - (I128(I128_MIN), I128(-1)) => Err(Overflow(op)), - (Isize(Is16(::std::i16::MIN)), Isize(Is16(-1))) => Err(Overflow(op)), - (Isize(Is32(::std::i32::MIN)), Isize(Is32(-1))) => Err(Overflow(op)), - (Isize(Is64(::std::i64::MIN)), Isize(Is64(-1))) => Err(Overflow(op)), - - _ => Ok(()), - } -} - -impl ::std::ops::Div for ConstInt { - type Output = Result<Self, ConstMathErr>; - fn div(self, rhs: Self) -> Result<Self, ConstMathErr> { - let (lhs, rhs) = (self, rhs); - check_division(lhs, rhs, Op::Div, DivisionByZero)?; - match (lhs, rhs) { - (I8(a), I8(b)) => Ok(I8(a/b)), - (I16(a), I16(b)) => Ok(I16(a/b)), - (I32(a), I32(b)) => Ok(I32(a/b)), - (I64(a), I64(b)) => Ok(I64(a/b)), - (I128(a), I128(b)) => Ok(I128(a/b)), - (Isize(Is16(a)), Isize(Is16(b))) => Ok(Isize(Is16(a/b))), - (Isize(Is32(a)), Isize(Is32(b))) => Ok(Isize(Is32(a/b))), - (Isize(Is64(a)), Isize(Is64(b))) => Ok(Isize(Is64(a/b))), - - (U8(a), U8(b)) => Ok(U8(a/b)), - (U16(a), U16(b)) => Ok(U16(a/b)), - (U32(a), U32(b)) => Ok(U32(a/b)), - (U64(a), U64(b)) => Ok(U64(a/b)), - (U128(a), U128(b)) => Ok(U128(a/b)), - (Usize(Us16(a)), Usize(Us16(b))) => Ok(Usize(Us16(a/b))), - (Usize(Us32(a)), Usize(Us32(b))) => Ok(Usize(Us32(a/b))), - (Usize(Us64(a)), Usize(Us64(b))) => Ok(Usize(Us64(a/b))), - - _ => Err(UnequalTypes(Op::Div)), - } - } -} - -impl ::std::ops::Rem for ConstInt { - type Output = Result<Self, ConstMathErr>; - fn rem(self, rhs: Self) -> Result<Self, ConstMathErr> { - let (lhs, rhs) = (self, rhs); - // should INT_MIN%-1 be zero or an error? - check_division(lhs, rhs, Op::Rem, RemainderByZero)?; - match (lhs, rhs) { - (I8(a), I8(b)) => Ok(I8(a%b)), - (I16(a), I16(b)) => Ok(I16(a%b)), - (I32(a), I32(b)) => Ok(I32(a%b)), - (I64(a), I64(b)) => Ok(I64(a%b)), - (I128(a), I128(b)) => Ok(I128(a%b)), - (Isize(Is16(a)), Isize(Is16(b))) => Ok(Isize(Is16(a%b))), - (Isize(Is32(a)), Isize(Is32(b))) => Ok(Isize(Is32(a%b))), - (Isize(Is64(a)), Isize(Is64(b))) => Ok(Isize(Is64(a%b))), - - (U8(a), U8(b)) => Ok(U8(a%b)), - (U16(a), U16(b)) => Ok(U16(a%b)), - (U32(a), U32(b)) => Ok(U32(a%b)), - (U64(a), U64(b)) => Ok(U64(a%b)), - (U128(a), U128(b)) => Ok(U128(a%b)), - (Usize(Us16(a)), Usize(Us16(b))) => Ok(Usize(Us16(a%b))), - (Usize(Us32(a)), Usize(Us32(b))) => Ok(Usize(Us32(a%b))), - (Usize(Us64(a)), Usize(Us64(b))) => Ok(Usize(Us64(a%b))), - - _ => Err(UnequalTypes(Op::Rem)), - } - } -} - -impl ::std::ops::Shl<ConstInt> for ConstInt { - type Output = Result<Self, ConstMathErr>; - fn shl(self, rhs: Self) -> Result<Self, ConstMathErr> { - let b = rhs.to_u32().ok_or(ShiftNegative)?; - match self { - I8(a) => Ok(I8(overflowing!(a.overflowing_shl(b), Op::Shl))), - I16(a) => Ok(I16(overflowing!(a.overflowing_shl(b), Op::Shl))), - I32(a) => Ok(I32(overflowing!(a.overflowing_shl(b), Op::Shl))), - I64(a) => Ok(I64(overflowing!(a.overflowing_shl(b), Op::Shl))), - I128(a) => Ok(I128(overflowing!(a.overflowing_shl(b), Op::Shl))), - Isize(Is16(a)) => Ok(Isize(Is16(overflowing!(a.overflowing_shl(b), Op::Shl)))), - Isize(Is32(a)) => Ok(Isize(Is32(overflowing!(a.overflowing_shl(b), Op::Shl)))), - Isize(Is64(a)) => Ok(Isize(Is64(overflowing!(a.overflowing_shl(b), Op::Shl)))), - U8(a) => Ok(U8(overflowing!(a.overflowing_shl(b), Op::Shl))), - U16(a) => Ok(U16(overflowing!(a.overflowing_shl(b), Op::Shl))), - U32(a) => Ok(U32(overflowing!(a.overflowing_shl(b), Op::Shl))), - U64(a) => Ok(U64(overflowing!(a.overflowing_shl(b), Op::Shl))), - U128(a) => Ok(U128(overflowing!(a.overflowing_shl(b), Op::Shl))), - Usize(Us16(a)) => Ok(Usize(Us16(overflowing!(a.overflowing_shl(b), Op::Shl)))), - Usize(Us32(a)) => Ok(Usize(Us32(overflowing!(a.overflowing_shl(b), Op::Shl)))), - Usize(Us64(a)) => Ok(Usize(Us64(overflowing!(a.overflowing_shl(b), Op::Shl)))), - } - } -} - -impl ::std::ops::Shr<ConstInt> for ConstInt { - type Output = Result<Self, ConstMathErr>; - fn shr(self, rhs: Self) -> Result<Self, ConstMathErr> { - let b = rhs.to_u32().ok_or(ShiftNegative)?; - match self { - I8(a) => Ok(I8(overflowing!(a.overflowing_shr(b), Op::Shr))), - I16(a) => Ok(I16(overflowing!(a.overflowing_shr(b), Op::Shr))), - I32(a) => Ok(I32(overflowing!(a.overflowing_shr(b), Op::Shr))), - I64(a) => Ok(I64(overflowing!(a.overflowing_shr(b), Op::Shr))), - I128(a) => Ok(I128(overflowing!(a.overflowing_shr(b), Op::Shr))), - Isize(Is16(a)) => Ok(Isize(Is16(overflowing!(a.overflowing_shr(b), Op::Shr)))), - Isize(Is32(a)) => Ok(Isize(Is32(overflowing!(a.overflowing_shr(b), Op::Shr)))), - Isize(Is64(a)) => Ok(Isize(Is64(overflowing!(a.overflowing_shr(b), Op::Shr)))), - U8(a) => Ok(U8(overflowing!(a.overflowing_shr(b), Op::Shr))), - U16(a) => Ok(U16(overflowing!(a.overflowing_shr(b), Op::Shr))), - U32(a) => Ok(U32(overflowing!(a.overflowing_shr(b), Op::Shr))), - U64(a) => Ok(U64(overflowing!(a.overflowing_shr(b), Op::Shr))), - U128(a) => Ok(U128(overflowing!(a.overflowing_shr(b), Op::Shr))), - Usize(Us16(a)) => Ok(Usize(Us16(overflowing!(a.overflowing_shr(b), Op::Shr)))), - Usize(Us32(a)) => Ok(Usize(Us32(overflowing!(a.overflowing_shr(b), Op::Shr)))), - Usize(Us64(a)) => Ok(Usize(Us64(overflowing!(a.overflowing_shr(b), Op::Shr)))), - } - } -} - -impl ::std::ops::Neg for ConstInt { - type Output = Result<Self, ConstMathErr>; - fn neg(self) -> Result<Self, ConstMathErr> { - match self { - I8(a) => Ok(I8(overflowing!(a.overflowing_neg(), Op::Neg))), - I16(a) => Ok(I16(overflowing!(a.overflowing_neg(), Op::Neg))), - I32(a) => Ok(I32(overflowing!(a.overflowing_neg(), Op::Neg))), - I64(a) => Ok(I64(overflowing!(a.overflowing_neg(), Op::Neg))), - I128(a) => Ok(I128(overflowing!(a.overflowing_neg(), Op::Neg))), - Isize(Is16(a)) => Ok(Isize(Is16(overflowing!(a.overflowing_neg(), Op::Neg)))), - Isize(Is32(a)) => Ok(Isize(Is32(overflowing!(a.overflowing_neg(), Op::Neg)))), - Isize(Is64(a)) => Ok(Isize(Is64(overflowing!(a.overflowing_neg(), Op::Neg)))), - a@U8(0) | a@U16(0) | a@U32(0) | a@U64(0) | a@U128(0) | - a@Usize(Us16(0)) | a@Usize(Us32(0)) | a@Usize(Us64(0)) => Ok(a), - U8(_) | U16(_) | U32(_) | U64(_) | U128(_) | Usize(_) => Err(UnsignedNegation), - } - } -} - -impl ::std::ops::Not for ConstInt { - type Output = Result<Self, ConstMathErr>; - fn not(self) -> Result<Self, ConstMathErr> { - match self { - I8(a) => Ok(I8(!a)), - I16(a) => Ok(I16(!a)), - I32(a) => Ok(I32(!a)), - I64(a) => Ok(I64(!a)), - I128(a) => Ok(I128(!a)), - Isize(Is16(a)) => Ok(Isize(Is16(!a))), - Isize(Is32(a)) => Ok(Isize(Is32(!a))), - Isize(Is64(a)) => Ok(Isize(Is64(!a))), - U8(a) => Ok(U8(!a)), - U16(a) => Ok(U16(!a)), - U32(a) => Ok(U32(!a)), - U64(a) => Ok(U64(!a)), - U128(a) => Ok(U128(!a)), - Usize(Us16(a)) => Ok(Usize(Us16(!a))), - Usize(Us32(a)) => Ok(Usize(Us32(!a))), - Usize(Us64(a)) => Ok(Usize(Us64(!a))), - } - } -} diff --git a/src/librustc_const_math/isize.rs b/src/librustc_const_math/isize.rs deleted file mode 100644 index 18acc782775..00000000000 --- a/src/librustc_const_math/isize.rs +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright 2015 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 syntax::ast; -use super::err::*; - -/// Depending on the target only one variant is ever used in a compilation. -/// Anything else is an error. This invariant is checked at several locations -#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable, Hash, Eq, PartialEq)] -pub enum ConstIsize { - Is16(i16), - Is32(i32), - Is64(i64), -} -pub use self::ConstIsize::*; - -impl ::std::fmt::Display for ConstIsize { - fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> { - write!(fmt, "{}", self.as_i64()) - } -} - -impl ConstIsize { - pub fn as_i64(self) -> i64 { - match self { - Is16(i) => i as i64, - Is32(i) => i as i64, - Is64(i) => i, - } - } - pub fn new(i: i64, isize_ty: ast::IntTy) -> Result<Self, ConstMathErr> { - match isize_ty { - ast::IntTy::I16 if i as i16 as i64 == i => Ok(Is16(i as i16)), - ast::IntTy::I16 => Err(LitOutOfRange(ast::IntTy::Isize)), - ast::IntTy::I32 if i as i32 as i64 == i => Ok(Is32(i as i32)), - ast::IntTy::I32 => Err(LitOutOfRange(ast::IntTy::Isize)), - ast::IntTy::I64 => Ok(Is64(i)), - _ => unreachable!(), - } - } - pub fn new_truncating(i: i128, isize_ty: ast::IntTy) -> Self { - match isize_ty { - ast::IntTy::I16 => Is16(i as i16), - ast::IntTy::I32 => Is32(i as i32), - ast::IntTy::I64 => Is64(i as i64), - _ => unreachable!(), - } - } -} diff --git a/src/librustc_const_math/lib.rs b/src/librustc_const_math/lib.rs index 2d98bc48d28..5555e727a95 100644 --- a/src/librustc_const_math/lib.rs +++ b/src/librustc_const_math/lib.rs @@ -29,13 +29,7 @@ extern crate syntax; extern crate serialize as rustc_serialize; // used by deriving mod float; -mod int; -mod usize; -mod isize; mod err; pub use float::*; -pub use int::*; -pub use usize::*; -pub use isize::*; pub use err::{ConstMathErr, Op}; diff --git a/src/librustc_const_math/usize.rs b/src/librustc_const_math/usize.rs deleted file mode 100644 index 56995f08f05..00000000000 --- a/src/librustc_const_math/usize.rs +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright 2015 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 syntax::ast; -use super::err::*; - -/// Depending on the target only one variant is ever used in a compilation. -/// Anything else is an error. This invariant is checked at several locations -#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable, Hash, Eq, PartialEq)] -pub enum ConstUsize { - Us16(u16), - Us32(u32), - Us64(u64), -} -pub use self::ConstUsize::*; - -impl ::std::fmt::Display for ConstUsize { - fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> { - write!(fmt, "{}", self.as_u64()) - } -} - -impl ConstUsize { - pub fn as_u64(self) -> u64 { - match self { - Us16(i) => i as u64, - Us32(i) => i as u64, - Us64(i) => i, - } - } - pub fn new(i: u64, usize_ty: ast::UintTy) -> Result<Self, ConstMathErr> { - match usize_ty { - ast::UintTy::U16 if i as u16 as u64 == i => Ok(Us16(i as u16)), - ast::UintTy::U16 => Err(ULitOutOfRange(ast::UintTy::Usize)), - ast::UintTy::U32 if i as u32 as u64 == i => Ok(Us32(i as u32)), - ast::UintTy::U32 => Err(ULitOutOfRange(ast::UintTy::Usize)), - ast::UintTy::U64 => Ok(Us64(i)), - _ => unreachable!(), - } - } - pub fn new_truncating(i: u128, usize_ty: ast::UintTy) -> Self { - match usize_ty { - ast::UintTy::U16 => Us16(i as u16), - ast::UintTy::U32 => Us32(i as u32), - ast::UintTy::U64 => Us64(i as u64), - _ => unreachable!(), - } - } -} diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index 35aa5adf76d..059fd9111b6 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -1316,7 +1316,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { self.check_aggregate_rvalue(mir, rvalue, ak, ops, location) } - Rvalue::Repeat(operand, const_usize) => if const_usize.as_u64() > 1 { + Rvalue::Repeat(operand, len) => if *len > 1 { let operand_ty = operand.ty(mir, tcx); let trait_ref = ty::TraitRef { diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs index ca6e7c2c415..e2cc58b1fb0 100644 --- a/src/librustc_mir/build/expr/as_rvalue.rs +++ b/src/librustc_mir/build/expr/as_rvalue.rs @@ -10,8 +10,6 @@ //! See docs in build/expr/mod.rs -use std; - use rustc_const_math::{ConstMathErr, Op}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::indexed_vec::Idx; @@ -19,7 +17,6 @@ use rustc_data_structures::indexed_vec::Idx; use build::{BlockAnd, BlockAndExtension, Builder}; use build::expr::category::{Category, RvalueFunc}; use hair::*; -use rustc_const_math::{ConstInt, ConstIsize}; use rustc::middle::const_val::ConstVal; use rustc::middle::region; use rustc::ty::{self, Ty}; @@ -385,31 +382,11 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { // Helper to get a `-1` value of the appropriate type fn neg_1_literal(&mut self, span: Span, ty: Ty<'tcx>) -> Operand<'tcx> { - let literal = match ty.sty { - ty::TyInt(ity) => { - let val = match ity { - ast::IntTy::I8 => ConstInt::I8(-1), - ast::IntTy::I16 => ConstInt::I16(-1), - ast::IntTy::I32 => ConstInt::I32(-1), - ast::IntTy::I64 => ConstInt::I64(-1), - ast::IntTy::I128 => ConstInt::I128(-1), - ast::IntTy::Isize => { - let int_ty = self.hir.tcx().sess.target.isize_ty; - let val = ConstIsize::new(-1, int_ty).unwrap(); - ConstInt::Isize(val) - } - }; - - Literal::Value { - value: self.hir.tcx().mk_const(ty::Const { - val: ConstVal::Value(Value::ByVal(PrimVal::Bytes(val.to_u128_unchecked()))), - ty - }) - } - } - _ => { - span_bug!(span, "Invalid type for neg_1_literal: `{:?}`", ty) - } + let literal = Literal::Value { + value: self.hir.tcx().mk_const(ty::Const { + val: ConstVal::Value(Value::ByVal(PrimVal::Bytes(-1i128 as u128))), + ty + }) }; self.literal_operand(span, ty, literal) @@ -419,30 +396,22 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { fn minval_literal(&mut self, span: Span, ty: Ty<'tcx>) -> Operand<'tcx> { let literal = match ty.sty { ty::TyInt(ity) => { + let ity = match ity { + ast::IntTy::Isize => self.hir.tcx().sess.target.isize_ty, + other => other, + }; let val = match ity { - ast::IntTy::I8 => ConstInt::I8(i8::min_value()), - ast::IntTy::I16 => ConstInt::I16(i16::min_value()), - ast::IntTy::I32 => ConstInt::I32(i32::min_value()), - ast::IntTy::I64 => ConstInt::I64(i64::min_value()), - ast::IntTy::I128 => ConstInt::I128(i128::min_value()), - ast::IntTy::Isize => { - let int_ty = self.hir.tcx().sess.target.isize_ty; - let min = match int_ty { - ast::IntTy::I16 => std::i16::MIN as i64, - ast::IntTy::I32 => std::i32::MIN as i64, - ast::IntTy::I64 => std::i64::MIN, - _ => unreachable!() - }; - let val = ConstIsize::new(min, int_ty).unwrap(); - ConstInt::Isize(val) - } + ast::IntTy::I8 => i8::min_value() as i128, + ast::IntTy::I16 => i16::min_value() as i128, + ast::IntTy::I32 => i32::min_value() as i128, + ast::IntTy::I64 => i64::min_value() as i128, + ast::IntTy::I128 => i128::min_value() as i128, + ast::IntTy::Isize => unreachable!(), }; Literal::Value { value: self.hir.tcx().mk_const(ty::Const { - val: ConstVal::Value(Value::ByVal(PrimVal::Bytes( - val.to_u128_unchecked() - ))), + val: ConstVal::Value(Value::ByVal(PrimVal::Bytes(val as u128))), ty }) } diff --git a/src/librustc_mir/build/matches/test.rs b/src/librustc_mir/build/matches/test.rs index 4a5d9e22881..09579eaecb2 100644 --- a/src/librustc_mir/build/matches/test.rs +++ b/src/librustc_mir/build/matches/test.rs @@ -197,7 +197,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let tcx = self.hir.tcx(); for (idx, discr) in adt_def.discriminants(tcx).enumerate() { target_blocks.place_back() <- if variants.contains(idx) { - values.push(discr.to_u128_unchecked()); + values.push(discr.val); *(targets.place_back() <- self.cfg.start_new_block()) } else { if otherwise_block.is_none() { diff --git a/src/librustc_mir/const_eval/pattern.rs b/src/librustc_mir/const_eval/pattern.rs index c1618d8e8a9..0b8a96332b0 100644 --- a/src/librustc_mir/const_eval/pattern.rs +++ b/src/librustc_mir/const_eval/pattern.rs @@ -799,7 +799,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { ).unwrap(); let variant_index = adt_def .discriminants(self.tcx) - .position(|var| var.to_u128_unchecked() == discr) + .position(|var| var.val == discr) .unwrap(); PatternKind::Variant { adt_def, diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index db44d870acb..6b5a5c59842 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -523,10 +523,10 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, promoted: None }; let count = match cx.tcx.at(c.span).const_eval(cx.param_env.and(global_id)) { - Ok(cv) => cv.val.unwrap_usize(cx.tcx), + Ok(cv) => cv.val.unwrap_u64(), Err(e) => { e.report(cx.tcx, cx.tcx.def_span(def_id), "array length"); - ConstUsize::new(0, cx.tcx.sess.target.usize_ty).unwrap() + 0 }, }; diff --git a/src/librustc_mir/hair/cx/mod.rs b/src/librustc_mir/hair/cx/mod.rs index 24bf9445d45..0b59ce9e117 100644 --- a/src/librustc_mir/hair/cx/mod.rs +++ b/src/librustc_mir/hair/cx/mod.rs @@ -29,7 +29,7 @@ use syntax::ast::{self, LitKind}; use syntax::attr; use syntax::symbol::Symbol; use rustc::hir; -use rustc_const_math::{ConstInt, ConstUsize}; +use rustc_const_math::ConstFloat; use rustc_data_structures::sync::Lrc; use rustc::mir::interpret::{Value, PrimVal}; @@ -115,16 +115,11 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> { } pub fn usize_literal(&mut self, value: u64) -> Literal<'tcx> { - match ConstUsize::new(value, self.tcx.sess.target.usize_ty) { - Ok(val) => { - Literal::Value { - value: self.tcx.mk_const(ty::Const { - val: ConstVal::Value(Value::ByVal(PrimVal::Bytes(val.as_u64() as u128))), - ty: self.tcx.types.usize - }) - } - } - Err(_) => bug!("usize literal out of range for target"), + Literal::Value { + value: self.tcx.mk_const(ty::Const { + val: ConstVal::Value(Value::ByVal(PrimVal::Bytes(value as u128))), + ty: self.tcx.types.usize + }) } } diff --git a/src/librustc_mir/hair/mod.rs b/src/librustc_mir/hair/mod.rs index 329365c4415..a7cfa94f696 100644 --- a/src/librustc_mir/hair/mod.rs +++ b/src/librustc_mir/hair/mod.rs @@ -14,7 +14,6 @@ //! unit-tested and separated from the Rust source and compiler data //! structures. -use rustc_const_math::ConstUsize; use rustc::mir::{BinOp, BorrowKind, Field, Literal, UnOp}; use rustc::hir::def_id::DefId; use rustc::middle::region; @@ -246,7 +245,7 @@ pub enum ExprKind<'tcx> { }, Repeat { value: ExprRef<'tcx>, - count: ConstUsize, + count: u64, }, Array { fields: Vec<ExprRef<'tcx>>, diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index eaa1bcb96a9..08152019003 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -760,7 +760,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M if let ty::TyAdt(adt_def, _) = ty.sty { trace!("Read discriminant {}, valid discriminants {:?}", discr_val, adt_def.discriminants(self.tcx).collect::<Vec<_>>()); if adt_def.discriminants(self.tcx).all(|v| { - discr_val != v.to_u128_unchecked() + discr_val != v.val }) { return err!(InvalidDiscriminant); @@ -916,7 +916,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M layout::Variants::Tagged { .. } => { let discr_val = dest_ty.ty_adt_def().unwrap() .discriminant_for_variant(self.tcx, variant_index) - .to_u128_unchecked(); + .val; let (discr_dest, discr) = self.place_field(dest, mir::Field::new(0), layout)?; self.write_primval(discr_dest, PrimVal::Bytes(discr_val), discr.ty)?; diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index ae790971ec8..9aff7fa2a2c 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -16,7 +16,6 @@ use rustc::mir::*; use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::subst::{Kind, Subst, Substs}; use rustc::ty::maps::Providers; -use rustc_const_math::ConstUsize; use rustc::mir::interpret::{Value, PrimVal}; use rustc_data_structures::indexed_vec::{IndexVec, Idx}; @@ -508,13 +507,7 @@ impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> { ty: self.tcx.types.usize, literal: Literal::Value { value: self.tcx.mk_const(ty::Const { - val: { - let value = ConstUsize::new( - value, - self.tcx.sess.target.usize_ty, - ).unwrap().as_u64(); - ConstVal::Value(Value::ByVal(PrimVal::Bytes(value.into()))) - }, + val: ConstVal::Value(Value::ByVal(PrimVal::Bytes(value.into()))), ty: self.tcx.types.usize, }) } diff --git a/src/librustc_mir/util/elaborate_drops.rs b/src/librustc_mir/util/elaborate_drops.rs index fbdeb3334ab..458dd488409 100644 --- a/src/librustc_mir/util/elaborate_drops.rs +++ b/src/librustc_mir/util/elaborate_drops.rs @@ -426,7 +426,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D> variant_path, &adt.variants[variant_index], substs); - values.push(discr.to_u128().unwrap()); + values.push(discr.val); if let Unwind::To(unwind) = unwind { // We can't use the half-ladder from the original // drop ladder, because this breaks the diff --git a/src/librustc_passes/mir_stats.rs b/src/librustc_passes/mir_stats.rs index e4705674e22..4a4ce63cc1d 100644 --- a/src/librustc_passes/mir_stats.rs +++ b/src/librustc_passes/mir_stats.rs @@ -12,7 +12,6 @@ // pieces of MIR. The resulting numbers are good approximations but not // completely accurate (some things might be counted twice, others missed). -use rustc_const_math::{ConstUsize}; use rustc::mir::{AggregateKind, AssertMessage, BasicBlock, BasicBlockData}; use rustc::mir::{Constant, Literal, Location, Local, LocalDecl}; use rustc::mir::{Place, PlaceElem, PlaceProjection}; @@ -265,13 +264,6 @@ impl<'a, 'tcx> mir_visit::Visitor<'tcx> for StatCollector<'a, 'tcx> { self.super_const(constant); } - fn visit_const_usize(&mut self, - const_usize: &ConstUsize, - _: Location) { - self.record("ConstUsize", const_usize); - self.super_const_usize(const_usize); - } - fn visit_local_decl(&mut self, local: Local, local_decl: &LocalDecl<'tcx>) { diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index 314b8c59df5..bae9fe8bd1b 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -334,14 +334,6 @@ pub fn cast_shift_expr_rhs( cast_shift_rhs(op, lhs, rhs, |a, b| cx.trunc(a, b), |a, b| cx.zext(a, b)) } -pub fn cast_shift_const_rhs(op: hir::BinOp_, lhs: ValueRef, rhs: ValueRef) -> ValueRef { - cast_shift_rhs(op, - lhs, - rhs, - |a, b| unsafe { llvm::LLVMConstTrunc(a, b.to_ref()) }, - |a, b| unsafe { llvm::LLVMConstZExt(a, b.to_ref()) }) -} - fn cast_shift_rhs<F, G>(op: hir::BinOp_, lhs: ValueRef, rhs: ValueRef, diff --git a/src/librustc_trans/debuginfo/metadata.rs b/src/librustc_trans/debuginfo/metadata.rs index 0fe425fb7ea..d20b51ca0fd 100644 --- a/src/librustc_trans/debuginfo/metadata.rs +++ b/src/librustc_trans/debuginfo/metadata.rs @@ -1378,7 +1378,7 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, DIB(cx), name.as_ptr(), // FIXME: what if enumeration has i128 discriminant? - discr.to_u128_unchecked() as u64) + discr.val as u64) } }) .collect(); diff --git a/src/librustc_trans/mir/constant.rs b/src/librustc_trans/mir/constant.rs index 1d04e30eb3e..954abf4c5d7 100644 --- a/src/librustc_trans/mir/constant.rs +++ b/src/librustc_trans/mir/constant.rs @@ -9,7 +9,6 @@ // except according to those terms. use llvm::{self, ValueRef}; -use rustc_const_math::{ConstInt, ConstMathErr}; use rustc::middle::const_val::{ConstVal, ConstEvalErr}; use rustc_mir::interpret::{read_target_uint, const_val_field}; use rustc::hir::def_id::DefId; @@ -17,13 +16,11 @@ use rustc::traits; use rustc::mir; use rustc_data_structures::indexed_vec::Idx; use rustc::mir::interpret::{Allocation, GlobalId, MemoryPointer, PrimVal, Value as MiriValue}; -use rustc::ty::{self, Ty, TyCtxt}; +use rustc::ty::{self, Ty}; use rustc::ty::layout::{self, HasDataLayout, LayoutOf, Scalar}; -use base; use builder::Builder; use common::{CodegenCx}; use common::{C_bytes, C_struct, C_uint_big, C_undef, C_usize}; -use common::const_to_opt_u128; use consts; use type_of::LayoutLlvmExt; use type_::Type; @@ -31,110 +28,6 @@ use type_::Type; use super::super::callee; use super::FunctionCx; -fn to_const_int(value: ValueRef, t: Ty, tcx: TyCtxt) -> Option<ConstInt> { - match t.sty { - ty::TyInt(int_type) => const_to_opt_u128(value, true) - .and_then(|input| ConstInt::new_signed(input as i128, int_type, - tcx.sess.target.isize_ty)), - ty::TyUint(uint_type) => const_to_opt_u128(value, false) - .and_then(|input| ConstInt::new_unsigned(input, uint_type, - tcx.sess.target.usize_ty)), - _ => None - - } -} - -pub fn const_scalar_binop(op: mir::BinOp, - lhs: ValueRef, - rhs: ValueRef, - input_ty: Ty) -> ValueRef { - assert!(!input_ty.is_simd()); - let is_float = input_ty.is_fp(); - let signed = input_ty.is_signed(); - - unsafe { - match op { - mir::BinOp::Add if is_float => llvm::LLVMConstFAdd(lhs, rhs), - mir::BinOp::Add => llvm::LLVMConstAdd(lhs, rhs), - - mir::BinOp::Sub if is_float => llvm::LLVMConstFSub(lhs, rhs), - mir::BinOp::Sub => llvm::LLVMConstSub(lhs, rhs), - - mir::BinOp::Mul if is_float => llvm::LLVMConstFMul(lhs, rhs), - mir::BinOp::Mul => llvm::LLVMConstMul(lhs, rhs), - - mir::BinOp::Div if is_float => llvm::LLVMConstFDiv(lhs, rhs), - mir::BinOp::Div if signed => llvm::LLVMConstSDiv(lhs, rhs), - mir::BinOp::Div => llvm::LLVMConstUDiv(lhs, rhs), - - mir::BinOp::Rem if is_float => llvm::LLVMConstFRem(lhs, rhs), - mir::BinOp::Rem if signed => llvm::LLVMConstSRem(lhs, rhs), - mir::BinOp::Rem => llvm::LLVMConstURem(lhs, rhs), - - mir::BinOp::BitXor => llvm::LLVMConstXor(lhs, rhs), - mir::BinOp::BitAnd => llvm::LLVMConstAnd(lhs, rhs), - mir::BinOp::BitOr => llvm::LLVMConstOr(lhs, rhs), - mir::BinOp::Shl => { - let rhs = base::cast_shift_const_rhs(op.to_hir_binop(), lhs, rhs); - llvm::LLVMConstShl(lhs, rhs) - } - mir::BinOp::Shr => { - let rhs = base::cast_shift_const_rhs(op.to_hir_binop(), lhs, rhs); - if signed { llvm::LLVMConstAShr(lhs, rhs) } - else { llvm::LLVMConstLShr(lhs, rhs) } - } - mir::BinOp::Eq | mir::BinOp::Ne | - mir::BinOp::Lt | mir::BinOp::Le | - mir::BinOp::Gt | mir::BinOp::Ge => { - if is_float { - let cmp = base::bin_op_to_fcmp_predicate(op.to_hir_binop()); - llvm::LLVMConstFCmp(cmp, lhs, rhs) - } else { - let cmp = base::bin_op_to_icmp_predicate(op.to_hir_binop(), - signed); - llvm::LLVMConstICmp(cmp, lhs, rhs) - } - } - mir::BinOp::Offset => unreachable!("BinOp::Offset in const-eval!") - } - } -} - -pub fn const_scalar_checked_binop<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - op: mir::BinOp, - lllhs: ValueRef, - llrhs: ValueRef, - input_ty: Ty<'tcx>) - -> Option<(ValueRef, bool)> { - if let (Some(lhs), Some(rhs)) = (to_const_int(lllhs, input_ty, tcx), - to_const_int(llrhs, input_ty, tcx)) { - let result = match op { - mir::BinOp::Add => lhs + rhs, - mir::BinOp::Sub => lhs - rhs, - mir::BinOp::Mul => lhs * rhs, - mir::BinOp::Shl => lhs << rhs, - mir::BinOp::Shr => lhs >> rhs, - _ => { - bug!("Operator `{:?}` is not a checkable operator", op) - } - }; - - let of = match result { - Ok(_) => false, - Err(ConstMathErr::Overflow(_)) | - Err(ConstMathErr::ShiftNegative) => true, - Err(err) => { - bug!("Operator `{:?}` on `{:?}` and `{:?}` errored: {}", - op, lhs, rhs, err.description()); - } - }; - - Some((const_scalar_binop(op, lllhs, llrhs, input_ty), of)) - } else { - None - } -} - pub fn primval_to_llvm(cx: &CodegenCx, cv: PrimVal, scalar: &Scalar, diff --git a/src/librustc_trans/mir/place.rs b/src/librustc_trans/mir/place.rs index 99770476e12..b340d91b027 100644 --- a/src/librustc_trans/mir/place.rs +++ b/src/librustc_trans/mir/place.rs @@ -328,7 +328,7 @@ impl<'a, 'tcx> PlaceRef<'tcx> { let ptr = self.project_field(bx, 0); let to = self.layout.ty.ty_adt_def().unwrap() .discriminant_for_variant(bx.tcx(), variant_index) - .to_u128_unchecked() as u64; + .val as u64; bx.store(C_int(ptr.layout.llvm_type(bx.cx), to as i64), ptr.llval, ptr.align); } diff --git a/src/librustc_trans/mir/rvalue.rs b/src/librustc_trans/mir/rvalue.rs index b0cb7de824e..fa0514952d2 100644 --- a/src/librustc_trans/mir/rvalue.rs +++ b/src/librustc_trans/mir/rvalue.rs @@ -30,7 +30,6 @@ use type_of::LayoutLlvmExt; use value::Value; use super::{FunctionCx, LocalRef}; -use super::constant::const_scalar_checked_binop; use super::operand::{OperandRef, OperandValue}; use super::place::PlaceRef; @@ -122,7 +121,6 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { } } - let count = count.as_u64(); let count = C_usize(bx.cx, count); let end = dest.project_index(&bx, count).llval; @@ -645,14 +643,6 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { return OperandValue::Pair(val, C_bool(bx.cx, false)); } - // First try performing the operation on constants, which - // will only succeed if both operands are constant. - // This is necessary to determine when an overflow Assert - // will always panic at runtime, and produce a warning. - if let Some((val, of)) = const_scalar_checked_binop(bx.tcx(), op, lhs, rhs, input_ty) { - return OperandValue::Pair(val, C_bool(bx.cx, of)); - } - let (val, of) = match op { // These are checked using intrinsics mir::BinOp::Add | mir::BinOp::Sub | mir::BinOp::Mul => { diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 56f2b30190f..4e1fd987d90 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -100,7 +100,8 @@ use rustc::ty::{self, Ty, TyCtxt, Visibility, ToPredicate}; use rustc::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability}; use rustc::ty::fold::TypeFoldable; use rustc::ty::maps::Providers; -use rustc::ty::util::{Representability, IntTypeExt}; +use rustc::ty::util::{Representability, IntTypeExt, Discr}; +use rustc::ty::layout::LayoutOf; use errors::{DiagnosticBuilder, DiagnosticId}; use require_c_abi_if_variadic; @@ -133,7 +134,6 @@ use rustc::hir::itemlikevisit::ItemLikeVisitor; use rustc::hir::map::Node; use rustc::hir::{self, PatKind}; use rustc::middle::lang_items; -use rustc_const_math::ConstInt; mod autoderef; pub mod dropck; @@ -1632,10 +1632,10 @@ pub fn check_enum<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } } - let mut disr_vals: Vec<ConstInt> = Vec::new(); + let mut disr_vals: Vec<Discr<'tcx>> = Vec::new(); for (discr, v) in def.discriminants(tcx).zip(vs) { // Check for duplicate discriminant values - if let Some(i) = disr_vals.iter().position(|&x| x == discr) { + if let Some(i) = disr_vals.iter().position(|&x| x.val == discr.val) { let variant_i_node_id = tcx.hir.as_local_node_id(def.variants[i].did).unwrap(); let variant_i = tcx.hir.expect_variant(variant_i_node_id); let i_span = match variant_i.node.disr_expr { diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index bb41acc5410..b040bd014e3 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -39,8 +39,7 @@ use rustc::ty::maps::Providers; use rustc::ty::util::IntTypeExt; use rustc::util::nodemap::{FxHashSet, FxHashMap}; use rustc::mir::interpret::{GlobalId, Value, PrimVal}; - -use rustc_const_math::ConstInt; +use rustc::ty::util::Discr; use syntax::{abi, ast}; use syntax::ast::MetaItemKind; @@ -516,11 +515,11 @@ fn convert_enum_variant_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let def = tcx.adt_def(def_id); let repr_type = def.repr.discr_type(); let initial = repr_type.initial_discriminant(tcx); - let mut prev_discr = None::<ConstInt>; + let mut prev_discr = None::<Discr<'tcx>>; // fill the discriminant values and field types for variant in variants { - let wrapped_discr = prev_discr.map_or(initial, |d| d.wrap_incr()); + let wrapped_discr = prev_discr.map_or(initial, |d| d.wrap_incr(tcx)); prev_discr = Some(if let Some(e) = variant.node.disr_expr { let expr_did = tcx.hir.local_def_id(e.node_id); let substs = Substs::identity_for_item(tcx, expr_did); @@ -535,19 +534,17 @@ fn convert_enum_variant_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // so we need to report the real error if let Err(ref err) = result { err.report(tcx, variant.span, "enum discriminant"); -} + } match result { + // FIXME: just use `to_raw_bits` here? Ok(&ty::Const { val: ConstVal::Value(Value::ByVal(PrimVal::Bytes(b))), .. }) => { - use syntax::attr::IntType; - Some(match repr_type { - IntType::SignedInt(int_type) => ConstInt::new_signed( - b as i128, int_type, tcx.sess.target.isize_ty).unwrap(), - IntType::UnsignedInt(uint_type) => ConstInt::new_unsigned( - b, uint_type, tcx.sess.target.usize_ty).unwrap(), + Some(Discr { + val: b, + ty: initial.ty, }) } _ => None diff --git a/src/test/compile-fail/issue-27592.rs b/src/test/compile-fail/issue-27592.rs index 731d4fb2bf6..bc295941147 100644 --- a/src/test/compile-fail/issue-27592.rs +++ b/src/test/compile-fail/issue-27592.rs @@ -26,4 +26,5 @@ fn main() { write(|| format_args!("{}", String::from("Hello world"))); //~^ ERROR borrowed value does not live long enough //~| ERROR borrowed value does not live long enough + //~| ERROR borrowed value does not live long enough } diff --git a/src/test/ui/issue-15524.rs b/src/test/ui/issue-15524.rs index 85214bd8633..7e696c97595 100644 --- a/src/test/ui/issue-15524.rs +++ b/src/test/ui/issue-15524.rs @@ -13,13 +13,13 @@ const N: isize = 1; enum Foo { A = 1, B = 1, - //~^ ERROR discriminant value `1isize` already exists + //~^ ERROR discriminant value `1` already exists C = 0, D, - //~^ ERROR discriminant value `1isize` already exists + //~^ ERROR discriminant value `1` already exists E = N, - //~^ ERROR discriminant value `1isize` already exists + //~^ ERROR discriminant value `1` already exists } |
