From 6cc449ad241c1cc54f5a789affffed2642422cec Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 15 Mar 2016 12:33:13 +0100 Subject: [PATCH 1/2] rename `rustc_const_eval` to `rustc_const_math` --- mk/crates.mk | 2 +- src/librustc/Cargo.toml | 2 +- src/librustc/lib.rs | 2 +- src/librustc/middle/const_eval.rs | 2 +- src/librustc/mir/repr.rs | 2 +- src/librustc/mir/visit.rs | 2 +- src/librustc/ty/mod.rs | 2 +- src/librustc/ty/util.rs | 2 +- src/{librustc_const_eval => librustc_const_math}/Cargo.toml | 4 ++-- src/{librustc_const_eval => librustc_const_math}/err.rs | 0 src/{librustc_const_eval => librustc_const_math}/int.rs | 0 src/{librustc_const_eval => librustc_const_math}/is.rs | 0 src/{librustc_const_eval => librustc_const_math}/lib.rs | 2 +- src/{librustc_const_eval => librustc_const_math}/us.rs | 0 src/librustc_metadata/Cargo.toml | 2 +- src/librustc_metadata/decoder.rs | 2 +- src/librustc_metadata/lib.rs | 2 +- src/librustc_mir/Cargo.toml | 2 +- src/librustc_mir/build/scope.rs | 2 +- src/librustc_mir/hair/cx/expr.rs | 2 +- src/librustc_mir/hair/cx/mod.rs | 2 +- src/librustc_mir/lib.rs | 2 +- src/librustc_trans/Cargo.toml | 2 +- src/librustc_trans/consts.rs | 2 +- src/librustc_trans/lib.rs | 2 +- src/librustc_trans/mir/constant.rs | 2 +- src/librustc_trans/mir/rvalue.rs | 2 +- src/librustc_typeck/Cargo.toml | 2 +- src/librustc_typeck/astconv.rs | 2 +- src/librustc_typeck/collect.rs | 2 +- src/librustc_typeck/lib.rs | 2 +- src/test/auxiliary/dummy_mir_pass.rs | 4 ++-- 32 files changed, 30 insertions(+), 30 deletions(-) rename src/{librustc_const_eval => librustc_const_math}/Cargo.toml (82%) rename src/{librustc_const_eval => librustc_const_math}/err.rs (100%) rename src/{librustc_const_eval => librustc_const_math}/int.rs (100%) rename src/{librustc_const_eval => librustc_const_math}/is.rs (100%) rename src/{librustc_const_eval => librustc_const_math}/lib.rs (97%) rename src/{librustc_const_eval => librustc_const_math}/us.rs (100%) diff --git a/mk/crates.mk b/mk/crates.mk index ba959d2778e78..1b614595e2a8e 100644 --- a/mk/crates.mk +++ b/mk/crates.mk @@ -92,7 +92,7 @@ DEPS_test := std getopts term native:rust_test_helpers DEPS_syntax := std term serialize log arena libc rustc_bitflags rustc_unicode DEPS_syntax_ext := syntax fmt_macros -DEPS_rustc_const_eval := std syntax +DEPS_rustc_const_math := std syntax log serialize DEPS_rustc := syntax fmt_macros flate arena serialize getopts rbml rustc_front\ log graphviz rustc_back rustc_data_structures\ diff --git a/src/librustc/Cargo.toml b/src/librustc/Cargo.toml index d2dc5f1ed93e0..cdbe8696a90d4 100644 --- a/src/librustc/Cargo.toml +++ b/src/librustc/Cargo.toml @@ -18,7 +18,7 @@ log = { path = "../liblog" } rbml = { path = "../librbml" } rustc_back = { path = "../librustc_back" } rustc_bitflags = { path = "../librustc_bitflags" } -rustc_const_eval = { path = "../librustc_const_eval" } +rustc_const_math = { path = "../librustc_const_math" } rustc_data_structures = { path = "../librustc_data_structures" } rustc_front = { path = "../librustc_front" } serialize = { path = "../libserialize" } diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 6b5f889fcfb85..1728bec5a8d3f 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -55,7 +55,7 @@ extern crate rustc_front; extern crate rustc_data_structures; extern crate serialize; extern crate collections; -extern crate rustc_const_eval; +extern crate rustc_const_math; #[macro_use] extern crate log; #[macro_use] extern crate syntax; #[macro_use] #[no_link] extern crate rustc_bitflags; diff --git a/src/librustc/middle/const_eval.rs b/src/librustc/middle/const_eval.rs index fca2904979c64..f685e4c0e18df 100644 --- a/src/librustc/middle/const_eval.rs +++ b/src/librustc/middle/const_eval.rs @@ -46,7 +46,7 @@ use std::hash; use std::mem::transmute; use std::rc::Rc; -use rustc_const_eval::*; +use rustc_const_math::*; macro_rules! math { ($e:expr, $op:expr) => { diff --git a/src/librustc/mir/repr.rs b/src/librustc/mir/repr.rs index b90738107834d..d3b1a8d6c1333 100644 --- a/src/librustc/mir/repr.rs +++ b/src/librustc/mir/repr.rs @@ -10,7 +10,7 @@ use graphviz::IntoCow; use middle::const_eval::ConstVal; -use rustc_const_eval::{ConstUsize, ConstInt}; +use rustc_const_math::{ConstUsize, ConstInt}; use middle::def_id::DefId; use ty::subst::Substs; use ty::{self, AdtDef, ClosureSubsts, FnOutput, Region, Ty}; diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs index 856902bea3c3c..d11eea811cd75 100644 --- a/src/librustc/mir/visit.rs +++ b/src/librustc/mir/visit.rs @@ -13,7 +13,7 @@ use middle::def_id::DefId; use ty::subst::Substs; use ty::{ClosureSubsts, FnOutput, Region, Ty}; use mir::repr::*; -use rustc_const_eval::ConstUsize; +use rustc_const_math::ConstUsize; use rustc_data_structures::tuple_slice::TupleSlice; use syntax::codemap::Span; diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index d080724fac9a9..5c754fc12d7d8 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -50,7 +50,7 @@ use syntax::attr::{self, AttrMetaMethods}; use syntax::codemap::{DUMMY_SP, Span}; use syntax::parse::token::InternedString; -use rustc_const_eval::ConstInt; +use rustc_const_math::ConstInt; use rustc_front::hir; use rustc_front::hir::{ItemImpl, ItemTrait, PatKind}; diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index b870dc47ec76a..970c807b36f7d 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -22,7 +22,7 @@ use ty::{self, Ty, TyCtxt, TypeAndMut, TypeFlags, TypeFoldable}; use ty::{Disr, ParameterEnvironment}; use ty::TypeVariants::*; -use rustc_const_eval::{ConstInt, ConstIsize, ConstUsize}; +use rustc_const_math::{ConstInt, ConstIsize, ConstUsize}; use std::cmp; use std::hash::{Hash, SipHasher, Hasher}; diff --git a/src/librustc_const_eval/Cargo.toml b/src/librustc_const_math/Cargo.toml similarity index 82% rename from src/librustc_const_eval/Cargo.toml rename to src/librustc_const_math/Cargo.toml index f885e9a94d522..10aadabe22ed7 100644 --- a/src/librustc_const_eval/Cargo.toml +++ b/src/librustc_const_math/Cargo.toml @@ -1,10 +1,10 @@ [package] authors = ["The Rust Project Developers"] -name = "rustc_const_eval" +name = "rustc_const_math" version = "0.0.0" [lib] -name = "rustc_const_eval" +name = "rustc_const_math" path = "lib.rs" crate-type = ["dylib"] diff --git a/src/librustc_const_eval/err.rs b/src/librustc_const_math/err.rs similarity index 100% rename from src/librustc_const_eval/err.rs rename to src/librustc_const_math/err.rs diff --git a/src/librustc_const_eval/int.rs b/src/librustc_const_math/int.rs similarity index 100% rename from src/librustc_const_eval/int.rs rename to src/librustc_const_math/int.rs diff --git a/src/librustc_const_eval/is.rs b/src/librustc_const_math/is.rs similarity index 100% rename from src/librustc_const_eval/is.rs rename to src/librustc_const_math/is.rs diff --git a/src/librustc_const_eval/lib.rs b/src/librustc_const_math/lib.rs similarity index 97% rename from src/librustc_const_eval/lib.rs rename to src/librustc_const_math/lib.rs index 80b8c75104a8d..9f66aac6e3899 100644 --- a/src/librustc_const_eval/lib.rs +++ b/src/librustc_const_math/lib.rs @@ -14,7 +14,7 @@ //! //! This API is completely unstable and subject to change. -#![crate_name = "rustc_const_eval"] +#![crate_name = "rustc_const_math"] #![unstable(feature = "rustc_private", issue = "27812")] #![crate_type = "dylib"] #![crate_type = "rlib"] diff --git a/src/librustc_const_eval/us.rs b/src/librustc_const_math/us.rs similarity index 100% rename from src/librustc_const_eval/us.rs rename to src/librustc_const_math/us.rs diff --git a/src/librustc_metadata/Cargo.toml b/src/librustc_metadata/Cargo.toml index e8b5a7efdd96b..65c2c2d1480a8 100644 --- a/src/librustc_metadata/Cargo.toml +++ b/src/librustc_metadata/Cargo.toml @@ -15,7 +15,7 @@ rbml = { path = "../librbml" } rustc = { path = "../librustc" } rustc_back = { path = "../librustc_back" } rustc_bitflags = { path = "../librustc_bitflags" } -rustc_const_eval = { path = "../librustc_const_eval" } +rustc_const_math = { path = "../librustc_const_math" } rustc_front = { path = "../librustc_front" } rustc_llvm = { path = "../librustc_llvm" } serialize = { path = "../libserialize" } diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index e6f516ccd33bd..b9ebd3c3afabf 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -36,7 +36,7 @@ use rustc::ty::subst; use rustc::ty::{ImplContainer, TraitContainer}; use rustc::ty::{self, Ty, TyCtxt, TypeFoldable, VariantKind}; -use rustc_const_eval::ConstInt; +use rustc_const_math::ConstInt; use rustc::mir; use rustc::mir::visit::MutVisitor; diff --git a/src/librustc_metadata/lib.rs b/src/librustc_metadata/lib.rs index a6c612f5397b4..674106dd82ad8 100644 --- a/src/librustc_metadata/lib.rs +++ b/src/librustc_metadata/lib.rs @@ -37,7 +37,7 @@ extern crate rustc; extern crate rustc_back; extern crate rustc_front; extern crate rustc_llvm; -extern crate rustc_const_eval; +extern crate rustc_const_math; pub use rustc::middle; diff --git a/src/librustc_mir/Cargo.toml b/src/librustc_mir/Cargo.toml index 99237c9fa5f47..35c29e2cf2d2f 100644 --- a/src/librustc_mir/Cargo.toml +++ b/src/librustc_mir/Cargo.toml @@ -13,7 +13,7 @@ graphviz = { path = "../libgraphviz" } log = { path = "../liblog" } rustc = { path = "../librustc" } rustc_back = { path = "../librustc_back" } -rustc_const_eval = { path = "../librustc_const_eval" } +rustc_const_math = { path = "../librustc_const_math" } rustc_data_structures = { path = "../librustc_data_structures" } rustc_front = { path = "../librustc_front" } syntax = { path = "../libsyntax" } diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir/build/scope.rs index bac7b310dc701..ffaf02bbfee6c 100644 --- a/src/librustc_mir/build/scope.rs +++ b/src/librustc_mir/build/scope.rs @@ -95,7 +95,7 @@ use rustc::mir::repr::*; use syntax::codemap::{Span, DUMMY_SP}; use syntax::parse::token::intern_and_get_ident; use rustc::middle::const_eval::ConstVal; -use rustc_const_eval::ConstInt; +use rustc_const_math::ConstInt; pub struct Scope<'tcx> { /// the scope-id within the scope_datas diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index aa55ee3e3f729..231acbfb4884a 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -10,7 +10,7 @@ use hair::*; use rustc_data_structures::fnv::FnvHashMap; -use rustc_const_eval::ConstInt; +use rustc_const_math::ConstInt; use hair::cx::Cx; use hair::cx::block; use hair::cx::to_ref::ToRef; diff --git a/src/librustc_mir/hair/cx/mod.rs b/src/librustc_mir/hair/cx/mod.rs index 30467a981d914..9bd94e432bf17 100644 --- a/src/librustc_mir/hair/cx/mod.rs +++ b/src/librustc_mir/hair/cx/mod.rs @@ -26,7 +26,7 @@ use rustc::ty::{self, Ty, TyCtxt}; use syntax::codemap::Span; use syntax::parse::token; use rustc_front::hir; -use rustc_const_eval::{ConstInt, ConstUsize}; +use rustc_const_math::{ConstInt, ConstUsize}; #[derive(Copy, Clone)] pub struct Cx<'a, 'tcx: 'a> { diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs index 67bac196f4806..3b55f62717c41 100644 --- a/src/librustc_mir/lib.rs +++ b/src/librustc_mir/lib.rs @@ -32,7 +32,7 @@ extern crate rustc_data_structures; extern crate rustc_front; extern crate rustc_back; extern crate syntax; -extern crate rustc_const_eval; +extern crate rustc_const_math; pub mod build; pub mod graphviz; diff --git a/src/librustc_trans/Cargo.toml b/src/librustc_trans/Cargo.toml index b7faafeba9aa1..e884442f03b01 100644 --- a/src/librustc_trans/Cargo.toml +++ b/src/librustc_trans/Cargo.toml @@ -16,7 +16,7 @@ graphviz = { path = "../libgraphviz" } log = { path = "../liblog" } rustc = { path = "../librustc" } rustc_back = { path = "../librustc_back" } -rustc_const_eval = { path = "../librustc_const_eval" } +rustc_const_math = { path = "../librustc_const_math" } rustc_data_structures = { path = "../librustc_data_structures" } rustc_front = { path = "../librustc_front" } rustc_llvm = { path = "../librustc_llvm" } diff --git a/src/librustc_trans/consts.rs b/src/librustc_trans/consts.rs index 8302fc0158c6a..b2edcbd9b9e87 100644 --- a/src/librustc_trans/consts.rs +++ b/src/librustc_trans/consts.rs @@ -38,7 +38,7 @@ use rustc::ty::adjustment::{AdjustUnsafeFnPointer, AdjustMutToConstPointer}; use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::cast::{CastTy,IntTy}; use util::nodemap::NodeMap; -use rustc_const_eval::{ConstInt, ConstMathErr, ConstUsize, ConstIsize}; +use rustc_const_math::{ConstInt, ConstMathErr, ConstUsize, ConstIsize}; use rustc_front::hir; diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs index 103de7e42af39..c85008181a447 100644 --- a/src/librustc_trans/lib.rs +++ b/src/librustc_trans/lib.rs @@ -51,7 +51,7 @@ pub extern crate rustc_llvm as llvm; extern crate rustc_mir; extern crate rustc_platform_intrinsics as intrinsics; extern crate serialize; -extern crate rustc_const_eval; +extern crate rustc_const_math; #[macro_use] extern crate log; #[macro_use] extern crate syntax; diff --git a/src/librustc_trans/mir/constant.rs b/src/librustc_trans/mir/constant.rs index be1c3f3b56b2c..cdb54eadbddcc 100644 --- a/src/librustc_trans/mir/constant.rs +++ b/src/librustc_trans/mir/constant.rs @@ -11,7 +11,7 @@ use llvm::ValueRef; use rustc::ty::{Ty, TypeFoldable}; use rustc::middle::const_eval::{self, ConstVal}; -use rustc_const_eval::ConstInt::*; +use rustc_const_math::ConstInt::*; use rustc::mir::repr as mir; use abi; use common::{self, BlockAndBuilder, C_bool, C_bytes, C_floating_f64, C_integral, diff --git a/src/librustc_trans/mir/rvalue.rs b/src/librustc_trans/mir/rvalue.rs index 47fa618ebad83..b90be5e0ab626 100644 --- a/src/librustc_trans/mir/rvalue.rs +++ b/src/librustc_trans/mir/rvalue.rs @@ -12,7 +12,7 @@ use llvm::ValueRef; use rustc::ty::{self, Ty}; use rustc::ty::cast::{CastTy, IntTy}; use middle::const_eval::ConstVal; -use rustc_const_eval::ConstInt; +use rustc_const_math::ConstInt; use rustc::mir::repr as mir; use asm; diff --git a/src/librustc_typeck/Cargo.toml b/src/librustc_typeck/Cargo.toml index 1c907972863b6..6e1bca87a821a 100644 --- a/src/librustc_typeck/Cargo.toml +++ b/src/librustc_typeck/Cargo.toml @@ -15,6 +15,6 @@ arena = { path = "../libarena" } fmt_macros = { path = "../libfmt_macros" } rustc = { path = "../librustc" } rustc_back = { path = "../librustc_back" } -rustc_const_eval = { path = "../librustc_const_eval" } +rustc_const_math = { path = "../librustc_const_math" } rustc_front = { path = "../librustc_front" } rustc_platform_intrinsics = { path = "../librustc_platform_intrinsics" } diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index af40b845767d8..bd2e0092a89ba 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -65,7 +65,7 @@ use rscope::{self, UnelidableRscope, RegionScope, ElidableRscope, use util::common::{ErrorReported, FN_OUTPUT_NAME}; use util::nodemap::FnvHashSet; -use rustc_const_eval::ConstInt; +use rustc_const_math::ConstInt; use syntax::{abi, ast}; use syntax::codemap::{Span, Pos}; diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 0b447b2009b58..743a2bb221139 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -81,7 +81,7 @@ use util::common::{ErrorReported, MemoizationMap}; use util::nodemap::{FnvHashMap, FnvHashSet}; use write_ty_to_tcx; -use rustc_const_eval::ConstInt; +use rustc_const_math::ConstInt; use std::cell::RefCell; use std::collections::HashSet; diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 9b0fdd8a2e327..9c08f57b8331e 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -92,7 +92,7 @@ extern crate rustc; extern crate rustc_platform_intrinsics as intrinsics; extern crate rustc_front; extern crate rustc_back; -extern crate rustc_const_eval; +extern crate rustc_const_math; pub use rustc::dep_graph; pub use rustc::front; diff --git a/src/test/auxiliary/dummy_mir_pass.rs b/src/test/auxiliary/dummy_mir_pass.rs index 3e1b46522a98d..edf1c2c3a398e 100644 --- a/src/test/auxiliary/dummy_mir_pass.rs +++ b/src/test/auxiliary/dummy_mir_pass.rs @@ -16,7 +16,7 @@ #[macro_use] extern crate rustc; extern crate rustc_front; extern crate rustc_plugin; -extern crate rustc_const_eval; +extern crate rustc_const_math; extern crate syntax; use rustc::mir::transform::{self, MirPass}; @@ -24,7 +24,7 @@ use rustc::mir::repr::{Mir, Literal}; use rustc::mir::visit::MutVisitor; use rustc::ty; use rustc::middle::const_eval::ConstVal; -use rustc_const_eval::ConstInt; +use rustc_const_math::ConstInt; use rustc_plugin::Registry; use syntax::ast::NodeId; From 3eac64747f520ec29195c9040348e028f22058aa Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Wed, 30 Mar 2016 13:43:36 +0200 Subject: [PATCH 2/2] move `const_eval` and `check_match` out of `librustc` --- mk/crates.mk | 23 +- src/librustc/diagnostics.rs | 521 ----------------- src/librustc/lib.rs | 3 +- src/librustc/middle/const_val.rs | 101 ++++ src/librustc/mir/repr.rs | 4 +- src/librustc/mir/visit.rs | 2 +- src/librustc/ty/util.rs | 37 -- src/librustc_const_eval/Cargo.toml | 19 + .../check_match.rs | 56 +- src/librustc_const_eval/diagnostics.rs | 545 ++++++++++++++++++ .../eval.rs} | 155 ++--- src/librustc_const_eval/lib.rs | 53 ++ src/librustc_const_math/int.rs | 4 +- src/librustc_driver/Cargo.toml | 1 + src/librustc_driver/driver.rs | 3 +- src/librustc_driver/lib.rs | 2 + src/librustc_lint/Cargo.toml | 1 + src/librustc_lint/lib.rs | 1 + src/librustc_lint/types.rs | 5 +- src/librustc_mir/Cargo.toml | 1 + src/librustc_mir/build/matches/mod.rs | 2 +- src/librustc_mir/build/matches/test.rs | 2 +- src/librustc_mir/build/scope.rs | 2 +- src/librustc_mir/hair/cx/expr.rs | 3 +- src/librustc_mir/hair/cx/mod.rs | 3 +- src/librustc_mir/hair/cx/pattern.rs | 2 +- src/librustc_mir/hair/mod.rs | 2 +- src/librustc_mir/lib.rs | 1 + src/librustc_mir/transform/simplify_cfg.rs | 2 +- src/librustc_passes/Cargo.toml | 1 + src/librustc_passes/consts.rs | 15 +- src/librustc_passes/lib.rs | 1 + src/librustc_trans/Cargo.toml | 1 + src/librustc_trans/_match.rs | 13 +- src/librustc_trans/consts.rs | 13 +- src/librustc_trans/lib.rs | 1 + src/librustc_trans/mir/constant.rs | 5 +- src/librustc_trans/mir/rvalue.rs | 2 +- src/librustc_trans/tvec.rs | 5 +- src/librustc_typeck/Cargo.toml | 1 + src/librustc_typeck/astconv.rs | 7 +- src/librustc_typeck/check/mod.rs | 3 +- src/librustc_typeck/collect.rs | 7 +- src/librustc_typeck/lib.rs | 1 + src/librustdoc/Cargo.toml | 1 + src/librustdoc/clean/inline.rs | 8 +- src/librustdoc/lib.rs | 1 + src/test/auxiliary/dummy_mir_pass.rs | 2 +- 48 files changed, 890 insertions(+), 754 deletions(-) create mode 100644 src/librustc/middle/const_val.rs create mode 100644 src/librustc_const_eval/Cargo.toml rename src/{librustc/middle => librustc_const_eval}/check_match.rs (97%) create mode 100644 src/librustc_const_eval/diagnostics.rs rename src/{librustc/middle/const_eval.rs => librustc_const_eval/eval.rs} (93%) create mode 100644 src/librustc_const_eval/lib.rs diff --git a/mk/crates.mk b/mk/crates.mk index 1b614595e2a8e..8c80335e772bb 100644 --- a/mk/crates.mk +++ b/mk/crates.mk @@ -58,7 +58,7 @@ RUSTC_CRATES := rustc rustc_typeck rustc_mir rustc_borrowck rustc_resolve rustc_ rustc_trans rustc_back rustc_llvm rustc_privacy rustc_lint \ rustc_data_structures rustc_front rustc_platform_intrinsics \ rustc_plugin rustc_metadata rustc_passes rustc_save_analysis \ - rustc_const_eval + rustc_const_eval rustc_const_math HOST_CRATES := syntax syntax_ext $(RUSTC_CRATES) rustdoc fmt_macros \ flate arena graphviz rbml log serialize TOOLS := compiletest rustdoc rustc rustbook error_index_generator @@ -93,35 +93,38 @@ DEPS_syntax := std term serialize log arena libc rustc_bitflags rustc_unicode DEPS_syntax_ext := syntax fmt_macros DEPS_rustc_const_math := std syntax log serialize +DEPS_rustc_const_eval := rustc_const_math rustc syntax log serialize rustc_front \ + rustc_back graphviz DEPS_rustc := syntax fmt_macros flate arena serialize getopts rbml rustc_front\ log graphviz rustc_back rustc_data_structures\ - rustc_const_eval + rustc_const_math DEPS_rustc_back := std syntax rustc_front flate log libc DEPS_rustc_borrowck := rustc rustc_front rustc_mir log graphviz syntax DEPS_rustc_data_structures := std log serialize DEPS_rustc_driver := arena flate getopts graphviz libc rustc rustc_back rustc_borrowck \ rustc_typeck rustc_mir rustc_resolve log syntax serialize rustc_llvm \ rustc_trans rustc_privacy rustc_lint rustc_front rustc_plugin \ - rustc_metadata syntax_ext rustc_passes rustc_save_analysis + rustc_metadata syntax_ext rustc_passes rustc_save_analysis rustc_const_eval DEPS_rustc_front := std syntax log serialize -DEPS_rustc_lint := rustc log syntax +DEPS_rustc_lint := rustc log syntax rustc_const_eval DEPS_rustc_llvm := native:rustllvm libc std rustc_bitflags -DEPS_rustc_metadata := rustc rustc_front syntax rbml rustc_const_eval -DEPS_rustc_passes := syntax rustc core rustc_front -DEPS_rustc_mir := rustc rustc_front syntax rustc_const_eval +DEPS_rustc_metadata := rustc rustc_front syntax rbml rustc_const_math +DEPS_rustc_passes := syntax rustc core rustc_front rustc_const_eval +DEPS_rustc_mir := rustc rustc_front syntax rustc_const_math rustc_const_eval DEPS_rustc_resolve := arena rustc rustc_front log syntax DEPS_rustc_platform_intrinsics := std DEPS_rustc_plugin := rustc rustc_metadata syntax rustc_mir DEPS_rustc_privacy := rustc rustc_front log syntax DEPS_rustc_trans := arena flate getopts graphviz libc rustc rustc_back rustc_mir \ log syntax serialize rustc_llvm rustc_front rustc_platform_intrinsics \ - rustc_const_eval + rustc_const_math rustc_const_eval DEPS_rustc_save_analysis := rustc log syntax rustc_front -DEPS_rustc_typeck := rustc syntax rustc_front rustc_platform_intrinsics rustc_const_eval +DEPS_rustc_typeck := rustc syntax rustc_front rustc_platform_intrinsics rustc_const_math \ + rustc_const_eval DEPS_rustdoc := rustc rustc_driver native:hoedown serialize getopts \ - test rustc_lint rustc_front + test rustc_lint rustc_front rustc_const_eval TOOL_DEPS_compiletest := test getopts log diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs index 9348c05d44461..117b1119c0a99 100644 --- a/src/librustc/diagnostics.rs +++ b/src/librustc/diagnostics.rs @@ -14,273 +14,6 @@ // Each message should start and end with a new line, and be wrapped to 80 characters. // In vim you can `:set tw=80` and use `gq` to wrap paragraphs. Use `:set tw=0` to disable. register_long_diagnostics! { - -E0001: r##" -This error suggests that the expression arm corresponding to the noted pattern -will never be reached as for all possible values of the expression being -matched, one of the preceding patterns will match. - -This means that perhaps some of the preceding patterns are too general, this -one is too specific or the ordering is incorrect. - -For example, the following `match` block has too many arms: - -```compile_fail -match foo { - Some(bar) => {/* ... */} - None => {/* ... */} - _ => {/* ... */} // All possible cases have already been handled -} -``` - -`match` blocks have their patterns matched in order, so, for example, putting -a wildcard arm above a more specific arm will make the latter arm irrelevant. - -Ensure the ordering of the match arm is correct and remove any superfluous -arms. -"##, - -E0002: r##" -This error indicates that an empty match expression is invalid because the type -it is matching on is non-empty (there exist values of this type). In safe code -it is impossible to create an instance of an empty type, so empty match -expressions are almost never desired. This error is typically fixed by adding -one or more cases to the match expression. - -An example of an empty type is `enum Empty { }`. So, the following will work: - -``` -enum Empty {} - -fn foo(x: Empty) { - match x { - // empty - } -} -``` - -However, this won't: - -```compile_fail -enum Empty {} - -fn foo(x: Option) { - match x { - // empty - } -} -``` -"##, - -E0003: r##" -Not-a-Number (NaN) values cannot be compared for equality and hence can never -match the input to a match expression. So, the following will not compile: - -```compile_fail -const NAN: f32 = 0.0 / 0.0; - -let number = 0.1f32; - -match number { - NAN => { /* ... */ }, - _ => {} -} -``` - -To match against NaN values, you should instead use the `is_nan()` method in a -guard, like so: - -``` -let number = 0.1f32; - -match number { - x if x.is_nan() => { /* ... */ } - _ => {} -} -``` -"##, - -E0004: r##" -This error indicates that the compiler cannot guarantee a matching pattern for -one or more possible inputs to a match expression. Guaranteed matches are -required in order to assign values to match expressions, or alternatively, -determine the flow of execution. Erroneous code example: - -```compile_fail -enum Terminator { - HastaLaVistaBaby, - TalkToMyHand, -} - -let x = Terminator::HastaLaVistaBaby; - -match x { // error: non-exhaustive patterns: `HastaLaVistaBaby` not covered - Terminator::TalkToMyHand => {} -} -``` - -If you encounter this error you must alter your patterns so that every possible -value of the input type is matched. For types with a small number of variants -(like enums) you should probably cover all cases explicitly. Alternatively, the -underscore `_` wildcard pattern can be added after all other patterns to match -"anything else". Example: - -``` -enum Terminator { - HastaLaVistaBaby, - TalkToMyHand, -} - -let x = Terminator::HastaLaVistaBaby; - -match x { - Terminator::TalkToMyHand => {} - Terminator::HastaLaVistaBaby => {} -} - -// or: - -match x { - Terminator::TalkToMyHand => {} - _ => {} -} -``` -"##, - -E0005: r##" -Patterns used to bind names must be irrefutable, that is, they must guarantee -that a name will be extracted in all cases. Erroneous code example: - -```compile_fail -let x = Some(1); -let Some(y) = x; -// error: refutable pattern in local binding: `None` not covered -``` - -If you encounter this error you probably need to use a `match` or `if let` to -deal with the possibility of failure. Example: - -```compile_fail -let x = Some(1); - -match x { - Some(y) => { - // do something - }, - None => {} -} - -// or: - -if let Some(y) = x { - // do something -} -``` -"##, - -E0007: r##" -This error indicates that the bindings in a match arm would require a value to -be moved into more than one location, thus violating unique ownership. Code -like the following is invalid as it requires the entire `Option` to be -moved into a variable called `op_string` while simultaneously requiring the -inner `String` to be moved into a variable called `s`. - -```compile_fail -let x = Some("s".to_string()); - -match x { - op_string @ Some(s) => {}, - None => {}, -} -``` - -See also the error E0303. -"##, - -E0008: r##" -Names bound in match arms retain their type in pattern guards. As such, if a -name is bound by move in a pattern, it should also be moved to wherever it is -referenced in the pattern guard code. Doing so however would prevent the name -from being available in the body of the match arm. Consider the following: - -```compile_fail -match Some("hi".to_string()) { - Some(s) if s.len() == 0 => {}, // use s. - _ => {}, -} -``` - -The variable `s` has type `String`, and its use in the guard is as a variable of -type `String`. The guard code effectively executes in a separate scope to the -body of the arm, so the value would be moved into this anonymous scope and -therefore become unavailable in the body of the arm. Although this example seems -innocuous, the problem is most clear when considering functions that take their -argument by value. - -```compile_fail -match Some("hi".to_string()) { - Some(s) if { drop(s); false } => (), - Some(s) => {}, // use s. - _ => {}, -} -``` - -The value would be dropped in the guard then become unavailable not only in the -body of that arm but also in all subsequent arms! The solution is to bind by -reference when using guards or refactor the entire expression, perhaps by -putting the condition inside the body of the arm. -"##, - -E0009: r##" -In a pattern, all values that don't implement the `Copy` trait have to be bound -the same way. The goal here is to avoid binding simultaneously by-move and -by-ref. - -This limitation may be removed in a future version of Rust. - -Erroneous code example: - -```compile_fail -struct X { x: (), } - -let x = Some((X { x: () }, X { x: () })); -match x { - Some((y, ref z)) => {}, - None => panic!() -} -``` - -You have two solutions: - -Solution #1: Bind the pattern's values the same way. - -``` -struct X { x: (), } - -let x = Some((X { x: () }, X { x: () })); -match x { - Some((ref y, ref z)) => {}, - // or Some((y, z)) => {} - None => panic!() -} -``` - -Solution #2: Implement the `Copy` trait for the `X` structure. - -However, please keep in mind that the first solution should be preferred. - -``` -#[derive(Clone, Copy)] -struct X { x: (), } - -let x = Some((X { x: () }, X { x: () })); -match x { - Some((y, ref z)) => {}, - None => panic!() -} -``` -"##, - E0020: r##" This error indicates that an attempt was made to divide by zero (or take the remainder of a zero divisor) in a static or constant expression. Erroneous @@ -762,128 +495,6 @@ attributes: See also https://doc.rust-lang.org/book/no-stdlib.html "##, -E0158: r##" -`const` and `static` mean different things. A `const` is a compile-time -constant, an alias for a literal value. This property means you can match it -directly within a pattern. - -The `static` keyword, on the other hand, guarantees a fixed location in memory. -This does not always mean that the value is constant. For example, a global -mutex can be declared `static` as well. - -If you want to match against a `static`, consider using a guard instead: - -``` -static FORTY_TWO: i32 = 42; - -match Some(42) { - Some(x) if x == FORTY_TWO => {} - _ => {} -} -``` -"##, - -E0162: r##" -An if-let pattern attempts to match the pattern, and enters the body if the -match was successful. If the match is irrefutable (when it cannot fail to -match), use a regular `let`-binding instead. For instance: - -```compile_fail -struct Irrefutable(i32); -let irr = Irrefutable(0); - -// This fails to compile because the match is irrefutable. -if let Irrefutable(x) = irr { - // This body will always be executed. - foo(x); -} -``` - -Try this instead: - -```ignore -struct Irrefutable(i32); -let irr = Irrefutable(0); - -let Irrefutable(x) = irr; -foo(x); -``` -"##, - -E0165: r##" -A while-let pattern attempts to match the pattern, and enters the body if the -match was successful. If the match is irrefutable (when it cannot fail to -match), use a regular `let`-binding inside a `loop` instead. For instance: - -```compile_fail -struct Irrefutable(i32); -let irr = Irrefutable(0); - -// This fails to compile because the match is irrefutable. -while let Irrefutable(x) = irr { - ... -} - -Try this instead: - -``` -struct Irrefutable(i32); -let irr = Irrefutable(0); - -loop { - let Irrefutable(x) = irr; - ... -} -``` -"##, - -E0170: r##" -Enum variants are qualified by default. For example, given this type: - -``` -enum Method { - GET, - POST, -} -``` - -You would match it using: - -``` -enum Method { - GET, - POST, -} - -let m = Method::GET; - -match m { - Method::GET => {}, - Method::POST => {}, -} -``` - -If you don't qualify the names, the code will bind new variables named "GET" and -"POST" instead. This behavior is likely not what you want, so `rustc` warns when -that happens. - -Qualified names are good practice, and most code works well with them. But if -you prefer them unqualified, you can import the variants into scope: - -```ignore -use Method::*; -enum Method { GET, POST } -``` - -If you want others to be able to import variants from your module directly, use -`pub use`: - -```ignore -pub use Method::*; -enum Method { GET, POST } -``` -"##, - E0229: r##" An associated type binding was done outside of the type parameter declaration and `where` clause. Erroneous code example: @@ -1573,135 +1184,6 @@ that the value provided is a positive integer between quotes, like so: ``` "##, -E0297: r##" -Patterns used to bind names must be irrefutable. That is, they must guarantee -that a name will be extracted in all cases. Instead of pattern matching the -loop variable, consider using a `match` or `if let` inside the loop body. For -instance: - -```compile_fail -let xs : Vec> = vec!(Some(1), None); - -// This fails because `None` is not covered. -for Some(x) in xs { - // ... -} -``` - -Match inside the loop instead: - -``` -let xs : Vec> = vec!(Some(1), None); - -for item in xs { - match item { - Some(x) => {}, - None => {}, - } -} -``` - -Or use `if let`: - -``` -let xs : Vec> = vec!(Some(1), None); - -for item in xs { - if let Some(x) = item { - // ... - } -} -``` -"##, - -E0301: r##" -Mutable borrows are not allowed in pattern guards, because matching cannot have -side effects. Side effects could alter the matched object or the environment -on which the match depends in such a way, that the match would not be -exhaustive. For instance, the following would not match any arm if mutable -borrows were allowed: - -```compile_fail -match Some(()) { - None => { }, - option if option.take().is_none() => { - /* impossible, option is `Some` */ - }, - Some(_) => { } // When the previous match failed, the option became `None`. -} -``` -"##, - -E0302: r##" -Assignments are not allowed in pattern guards, because matching cannot have -side effects. Side effects could alter the matched object or the environment -on which the match depends in such a way, that the match would not be -exhaustive. For instance, the following would not match any arm if assignments -were allowed: - -```compile_fail -match Some(()) { - None => { }, - option if { option = None; false } { }, - Some(_) => { } // When the previous match failed, the option became `None`. -} -``` -"##, - -E0303: r##" -In certain cases it is possible for sub-bindings to violate memory safety. -Updates to the borrow checker in a future version of Rust may remove this -restriction, but for now patterns must be rewritten without sub-bindings. - -```ignore -// Before. -match Some("hi".to_string()) { - ref op_string_ref @ Some(s) => {}, - None => {}, -} - -// After. -match Some("hi".to_string()) { - Some(ref s) => { - let op_string_ref = &Some(s); - // ... - }, - None => {}, -} -``` - -The `op_string_ref` binding has type `&Option<&String>` in both cases. - -See also https://github.com/rust-lang/rust/issues/14587 -"##, - -E0306: r##" -In an array literal `[x; N]`, `N` is the number of elements in the array. This -must be an unsigned integer. Erroneous code example: - -```compile_fail -let x = [0i32; true]; // error: expected positive integer for repeat count, - // found boolean -``` - -Working example: - -``` -let x = [0i32; 2]; -``` -"##, - -E0307: r##" -The length of an array is part of its type. For this reason, this length must -be a compile-time constant. Erroneous code example: - -```compile_fail - let len = 10; - let x = [0i32; len]; // error: expected constant integer for repeat count, - // found variable -``` -"##, - E0308: r##" This error occurs when the compiler was unable to infer the concrete type of a variable. It can occur for several cases, the most common of which is a @@ -1991,8 +1473,6 @@ register_diagnostics! { E0280, // requirement is not satisfied E0284, // cannot resolve type // E0285, // overflow evaluation builtin bounds - E0298, // mismatched types between arms - E0299, // mismatched types between arms // E0300, // unexpanded macro // E0304, // expected signed integer constant // E0305, // expected constant @@ -2003,7 +1483,6 @@ register_diagnostics! { E0315, // cannot invoke closure outside of its lifetime E0316, // nested quantification of lifetimes E0453, // overruled by outer forbid - E0471, // constant evaluation error: .. E0473, // dereference of reference outside its lifetime E0474, // captured variable `..` does not outlive the enclosing closure E0475, // index of slice outside its lifetime diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 1728bec5a8d3f..03a08231c7433 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -91,8 +91,7 @@ pub mod lint; pub mod middle { pub mod astconv_util; pub mod expr_use_visitor; // STAGE0: increase glitch immunity - pub mod check_match; - pub mod const_eval; + pub mod const_val; pub mod const_qualif; pub mod cstore; pub mod dataflow; diff --git a/src/librustc/middle/const_val.rs b/src/librustc/middle/const_val.rs new file mode 100644 index 0000000000000..a939389c460ea --- /dev/null +++ b/src/librustc/middle/const_val.rs @@ -0,0 +1,101 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use syntax::parse::token::InternedString; +use syntax::ast; +use std::rc::Rc; +use middle::def_id::DefId; +use std::hash; +use std::mem::transmute; +use rustc_const_math::*; +use self::ConstVal::*; + +#[derive(Clone, Debug, RustcEncodable, RustcDecodable)] +pub enum ConstVal { + Float(f64), + Integral(ConstInt), + Str(InternedString), + ByteStr(Rc>), + Bool(bool), + Struct(ast::NodeId), + Tuple(ast::NodeId), + Function(DefId), + Array(ast::NodeId, u64), + Repeat(ast::NodeId, u64), + Char(char), + /// A value that only occurs in case `eval_const_expr` reported an error. You should never + /// handle this case. Its sole purpose is to allow more errors to be reported instead of + /// causing a fatal error. + Dummy, +} + +impl hash::Hash for ConstVal { + fn hash(&self, state: &mut H) { + match *self { + Float(a) => unsafe { transmute::<_,u64>(a) }.hash(state), + Integral(a) => a.hash(state), + Str(ref a) => a.hash(state), + ByteStr(ref a) => a.hash(state), + Bool(a) => a.hash(state), + Struct(a) => a.hash(state), + Tuple(a) => a.hash(state), + Function(a) => a.hash(state), + Array(a, n) => { a.hash(state); n.hash(state) }, + Repeat(a, n) => { a.hash(state); n.hash(state) }, + Char(c) => c.hash(state), + Dummy => ().hash(state), + } + } +} + +/// Note that equality for `ConstVal` means that the it is the same +/// constant, not that the rust values are equal. In particular, `NaN +/// == NaN` (at least if it's the same NaN; distinct encodings for NaN +/// are considering unequal). +impl PartialEq for ConstVal { + fn eq(&self, other: &ConstVal) -> bool { + match (self, other) { + (&Float(a), &Float(b)) => unsafe{transmute::<_,u64>(a) == transmute::<_,u64>(b)}, + (&Integral(a), &Integral(b)) => a == b, + (&Str(ref a), &Str(ref b)) => a == b, + (&ByteStr(ref a), &ByteStr(ref b)) => a == b, + (&Bool(a), &Bool(b)) => a == b, + (&Struct(a), &Struct(b)) => a == b, + (&Tuple(a), &Tuple(b)) => a == b, + (&Function(a), &Function(b)) => a == b, + (&Array(a, an), &Array(b, bn)) => (a == b) && (an == bn), + (&Repeat(a, an), &Repeat(b, bn)) => (a == b) && (an == bn), + (&Char(a), &Char(b)) => a == b, + (&Dummy, &Dummy) => true, // FIXME: should this be false? + _ => false, + } + } +} + +impl Eq for ConstVal { } + +impl ConstVal { + pub fn description(&self) -> &'static str { + match *self { + Float(_) => "float", + Integral(i) => i.description(), + Str(_) => "string literal", + ByteStr(_) => "byte string literal", + Bool(_) => "boolean", + Struct(_) => "struct", + Tuple(_) => "tuple", + Function(_) => "function definition", + Array(..) => "array", + Repeat(..) => "repeat", + Char(..) => "char", + Dummy => "dummy value", + } + } +} diff --git a/src/librustc/mir/repr.rs b/src/librustc/mir/repr.rs index d3b1a8d6c1333..bc10d0c90ef06 100644 --- a/src/librustc/mir/repr.rs +++ b/src/librustc/mir/repr.rs @@ -9,7 +9,7 @@ // except according to those terms. use graphviz::IntoCow; -use middle::const_eval::ConstVal; +use middle::const_val::ConstVal; use rustc_const_math::{ConstUsize, ConstInt}; use middle::def_id::DefId; use ty::subst::Substs; @@ -999,7 +999,7 @@ impl<'tcx> Debug for Literal<'tcx> { /// Write a `ConstVal` in a way closer to the original source code than the `Debug` output. fn fmt_const_val(fmt: &mut W, const_val: &ConstVal) -> fmt::Result { - use middle::const_eval::ConstVal::*; + use middle::const_val::ConstVal::*; match *const_val { Float(f) => write!(fmt, "{:?}", f), Integral(n) => write!(fmt, "{}", n), diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs index d11eea811cd75..403c749fe4bcb 100644 --- a/src/librustc/mir/visit.rs +++ b/src/librustc/mir/visit.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use middle::const_eval::ConstVal; +use middle::const_val::ConstVal; use middle::def_id::DefId; use ty::subst::Substs; use ty::{ClosureSubsts, FnOutput, Region, Ty}; diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index 970c807b36f7d..a3aa3f31cd1f2 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -11,8 +11,6 @@ //! misc. type-system utilities too small to deserve their own file use back::svh::Svh; -use middle::const_eval::{self, ConstVal, ErrKind}; -use middle::const_eval::EvalHint::UncheckedExprHint; use middle::def_id::DefId; use ty::subst; use infer; @@ -269,41 +267,6 @@ impl<'tcx> TyCtxt<'tcx> { (a, b) } - /// Returns the repeat count for a repeating vector expression. - pub fn eval_repeat_count(&self, count_expr: &hir::Expr) -> usize { - let hint = UncheckedExprHint(self.types.usize); - match const_eval::eval_const_expr_partial(self, count_expr, hint, None) { - Ok(ConstVal::Integral(ConstInt::Usize(count))) => { - let val = count.as_u64(self.sess.target.uint_type); - assert_eq!(val as usize as u64, val); - val as usize - }, - Ok(const_val) => { - span_err!(self.sess, count_expr.span, E0306, - "expected positive integer for repeat count, found {}", - const_val.description()); - 0 - } - Err(err) => { - let err_msg = match count_expr.node { - hir::ExprPath(None, hir::Path { - global: false, - ref segments, - .. - }) if segments.len() == 1 => - format!("found variable"), - _ => match err.kind { - ErrKind::MiscCatchAll => format!("but found {}", err.description()), - _ => format!("but {}", err.description()) - } - }; - span_err!(self.sess, count_expr.span, E0307, - "expected constant integer for repeat count, {}", err_msg); - 0 - } - } - } - /// Given a set of predicates that apply to an object type, returns /// the region bounds that the (erased) `Self` type must /// outlive. Precisely *because* the `Self` type is erased, the diff --git a/src/librustc_const_eval/Cargo.toml b/src/librustc_const_eval/Cargo.toml new file mode 100644 index 0000000000000..f38c60cd1fae3 --- /dev/null +++ b/src/librustc_const_eval/Cargo.toml @@ -0,0 +1,19 @@ +[package] +authors = ["The Rust Project Developers"] +name = "rustc_const_eval" +version = "0.0.0" + +[lib] +name = "rustc_const_eval" +path = "lib.rs" +crate-type = ["dylib"] + +[dependencies] +log = { path = "../liblog" } +serialize = { path = "../libserialize" } +rustc = { path = "../librustc" } +rustc_front = { path = "../librustc_front" } +rustc_back = { path = "../librustc_back" } +rustc_const_math = { path = "../librustc_const_math" } +syntax = { path = "../libsyntax" } +graphviz = { path = "../libgraphviz" } diff --git a/src/librustc/middle/check_match.rs b/src/librustc_const_eval/check_match.rs similarity index 97% rename from src/librustc/middle/check_match.rs rename to src/librustc_const_eval/check_match.rs index 79e4b7c0901bd..f00df1f671f8c 100644 --- a/src/librustc/middle/check_match.rs +++ b/src/librustc_const_eval/check_match.rs @@ -1,4 +1,4 @@ -// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT +// 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. // @@ -12,22 +12,22 @@ pub use self::Constructor::*; use self::Usefulness::*; use self::WitnessPreference::*; -use dep_graph::DepNode; -use middle::const_eval::{compare_const_vals, ConstVal}; -use middle::const_eval::{eval_const_expr, eval_const_expr_partial}; -use middle::const_eval::{const_expr_to_pat, lookup_const_by_id}; -use middle::const_eval::EvalHint::ExprTypeChecked; -use middle::def::*; -use middle::def_id::{DefId}; -use middle::expr_use_visitor::{ConsumeMode, Delegate, ExprUseVisitor}; -use middle::expr_use_visitor::{LoanCause, MutateMode}; -use middle::expr_use_visitor as euv; -use infer; -use middle::mem_categorization::{cmt}; -use middle::pat_util::*; -use traits::ProjectionMode; -use ty::*; -use ty; +use rustc::dep_graph::DepNode; +use rustc::middle::const_val::ConstVal; +use ::{eval_const_expr, eval_const_expr_partial, compare_const_vals}; +use ::{const_expr_to_pat, lookup_const_by_id}; +use ::EvalHint::ExprTypeChecked; +use rustc::middle::def::*; +use rustc::middle::def_id::{DefId}; +use rustc::middle::expr_use_visitor::{ConsumeMode, Delegate, ExprUseVisitor}; +use rustc::middle::expr_use_visitor::{LoanCause, MutateMode}; +use rustc::middle::expr_use_visitor as euv; +use rustc::infer; +use rustc::middle::mem_categorization::{cmt}; +use rustc::middle::pat_util::*; +use rustc::traits::ProjectionMode; +use rustc::ty::*; +use rustc::ty; use std::cmp::Ordering; use std::fmt; use std::iter::{FromIterator, IntoIterator, repeat}; @@ -44,7 +44,7 @@ use syntax::codemap::{Span, Spanned, DUMMY_SP}; use rustc_front::fold::{Folder, noop_fold_pat}; use rustc_front::print::pprust::pat_to_string; use syntax::ptr::P; -use util::nodemap::FnvHashMap; +use rustc::util::nodemap::FnvHashMap; pub const DUMMY_WILD_PAT: &'static Pat = &Pat { id: DUMMY_NODE_ID, @@ -546,7 +546,7 @@ fn construct_witness<'a,'tcx>(cx: &MatchCheckCtxt<'a,'tcx>, ctor: &Constructor, ty::TyTuple(_) => PatKind::Tup(pats.collect()), ty::TyEnum(adt, _) | ty::TyStruct(adt, _) => { - let v = adt.variant_of_ctor(ctor); + let v = ctor.variant_for_adt(adt); match v.kind() { VariantKind::Struct => { let field_pats: hir::HirVec<_> = v.fields.iter() @@ -617,13 +617,13 @@ fn construct_witness<'a,'tcx>(cx: &MatchCheckCtxt<'a,'tcx>, ctor: &Constructor, }) } -impl<'tcx, 'container> ty::AdtDefData<'tcx, 'container> { - fn variant_of_ctor(&self, - ctor: &Constructor) - -> &VariantDefData<'tcx, 'container> { - match ctor { - &Variant(vid) => self.variant_with_id(vid), - _ => self.struct_variant() +impl Constructor { + fn variant_for_adt<'tcx, 'container, 'a>(&self, + adt: &'a ty::AdtDefData<'tcx, 'container>) + -> &'a VariantDefData<'tcx, 'container> { + match self { + &Variant(vid) => adt.variant_with_id(vid), + _ => adt.struct_variant() } } } @@ -843,7 +843,7 @@ pub fn constructor_arity(_cx: &MatchCheckCtxt, ctor: &Constructor, ty: Ty) -> us _ => 1 }, ty::TyEnum(adt, _) | ty::TyStruct(adt, _) => { - adt.variant_of_ctor(ctor).fields.len() + ctor.variant_for_adt(adt).fields.len() } ty::TyArray(_, n) => n, _ => 0 @@ -924,7 +924,7 @@ pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat], PatKind::Struct(_, ref pattern_fields, _) => { let def = cx.tcx.def_map.borrow().get(&pat_id).unwrap().full_def(); let adt = cx.tcx.node_id_to_type(pat_id).ty_adt_def().unwrap(); - let variant = adt.variant_of_ctor(constructor); + let variant = constructor.variant_for_adt(adt); let def_variant = adt.variant_of_def(def); if variant.did == def_variant.did { Some(variant.fields.iter().map(|sf| { diff --git a/src/librustc_const_eval/diagnostics.rs b/src/librustc_const_eval/diagnostics.rs new file mode 100644 index 0000000000000..4f5176f6b0be5 --- /dev/null +++ b/src/librustc_const_eval/diagnostics.rs @@ -0,0 +1,545 @@ +// Copyright 2014 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![allow(non_snake_case)] + +// Error messages for EXXXX errors. +// Each message should start and end with a new line, and be wrapped to 80 characters. +// In vim you can `:set tw=80` and use `gq` to wrap paragraphs. Use `:set tw=0` to disable. +register_long_diagnostics! { + +E0001: r##" +This error suggests that the expression arm corresponding to the noted pattern +will never be reached as for all possible values of the expression being +matched, one of the preceding patterns will match. + +This means that perhaps some of the preceding patterns are too general, this +one is too specific or the ordering is incorrect. + +For example, the following `match` block has too many arms: + +```compile_fail +match foo { + Some(bar) => {/* ... */} + None => {/* ... */} + _ => {/* ... */} // All possible cases have already been handled +} +``` + +`match` blocks have their patterns matched in order, so, for example, putting +a wildcard arm above a more specific arm will make the latter arm irrelevant. + +Ensure the ordering of the match arm is correct and remove any superfluous +arms. +"##, + +E0002: r##" +This error indicates that an empty match expression is invalid because the type +it is matching on is non-empty (there exist values of this type). In safe code +it is impossible to create an instance of an empty type, so empty match +expressions are almost never desired. This error is typically fixed by adding +one or more cases to the match expression. + +An example of an empty type is `enum Empty { }`. So, the following will work: + +``` +enum Empty {} + +fn foo(x: Empty) { + match x { + // empty + } +} +``` + +However, this won't: + +```compile_fail +enum Empty {} + +fn foo(x: Option) { + match x { + // empty + } +} +``` +"##, + + +E0003: r##" +Not-a-Number (NaN) values cannot be compared for equality and hence can never +match the input to a match expression. So, the following will not compile: + +```compile_fail +const NAN: f32 = 0.0 / 0.0; + +let number = 0.1f32; + +match number { + NAN => { /* ... */ }, + _ => {} +} +``` + +To match against NaN values, you should instead use the `is_nan()` method in a +guard, like so: + +``` +let number = 0.1f32; + +match number { + x if x.is_nan() => { /* ... */ } + _ => {} +} +``` +"##, + + +E0004: r##" +This error indicates that the compiler cannot guarantee a matching pattern for +one or more possible inputs to a match expression. Guaranteed matches are +required in order to assign values to match expressions, or alternatively, +determine the flow of execution. Erroneous code example: + +```compile_fail +enum Terminator { + HastaLaVistaBaby, + TalkToMyHand, +} + +let x = Terminator::HastaLaVistaBaby; + +match x { // error: non-exhaustive patterns: `HastaLaVistaBaby` not covered + Terminator::TalkToMyHand => {} +} +``` + +If you encounter this error you must alter your patterns so that every possible +value of the input type is matched. For types with a small number of variants +(like enums) you should probably cover all cases explicitly. Alternatively, the +underscore `_` wildcard pattern can be added after all other patterns to match +"anything else". Example: + +``` +enum Terminator { + HastaLaVistaBaby, + TalkToMyHand, +} + +let x = Terminator::HastaLaVistaBaby; + +match x { + Terminator::TalkToMyHand => {} + Terminator::HastaLaVistaBaby => {} +} + +// or: + +match x { + Terminator::TalkToMyHand => {} + _ => {} +} +``` +"##, + +E0005: r##" +Patterns used to bind names must be irrefutable, that is, they must guarantee +that a name will be extracted in all cases. Erroneous code example: + +```compile_fail +let x = Some(1); +let Some(y) = x; +// error: refutable pattern in local binding: `None` not covered +``` + +If you encounter this error you probably need to use a `match` or `if let` to +deal with the possibility of failure. Example: + +```compile_fail +let x = Some(1); + +match x { + Some(y) => { + // do something + }, + None => {} +} + +// or: + +if let Some(y) = x { + // do something +} +``` +"##, + +E0007: r##" +This error indicates that the bindings in a match arm would require a value to +be moved into more than one location, thus violating unique ownership. Code +like the following is invalid as it requires the entire `Option` to be +moved into a variable called `op_string` while simultaneously requiring the +inner `String` to be moved into a variable called `s`. + +```compile_fail +let x = Some("s".to_string()); + +match x { + op_string @ Some(s) => {}, + None => {}, +} +``` + +See also the error E0303. +"##, + +E0008: r##" +Names bound in match arms retain their type in pattern guards. As such, if a +name is bound by move in a pattern, it should also be moved to wherever it is +referenced in the pattern guard code. Doing so however would prevent the name +from being available in the body of the match arm. Consider the following: + +```compile_fail +match Some("hi".to_string()) { + Some(s) if s.len() == 0 => {}, // use s. + _ => {}, +} +``` + +The variable `s` has type `String`, and its use in the guard is as a variable of +type `String`. The guard code effectively executes in a separate scope to the +body of the arm, so the value would be moved into this anonymous scope and +therefore become unavailable in the body of the arm. Although this example seems +innocuous, the problem is most clear when considering functions that take their +argument by value. + +```compile_fail +match Some("hi".to_string()) { + Some(s) if { drop(s); false } => (), + Some(s) => {}, // use s. + _ => {}, +} +``` + +The value would be dropped in the guard then become unavailable not only in the +body of that arm but also in all subsequent arms! The solution is to bind by +reference when using guards or refactor the entire expression, perhaps by +putting the condition inside the body of the arm. +"##, + +E0009: r##" +In a pattern, all values that don't implement the `Copy` trait have to be bound +the same way. The goal here is to avoid binding simultaneously by-move and +by-ref. + +This limitation may be removed in a future version of Rust. + +Erroneous code example: + +```compile_fail +struct X { x: (), } + +let x = Some((X { x: () }, X { x: () })); +match x { + Some((y, ref z)) => {}, + None => panic!() +} +``` + +You have two solutions: + +Solution #1: Bind the pattern's values the same way. + +``` +struct X { x: (), } + +let x = Some((X { x: () }, X { x: () })); +match x { + Some((ref y, ref z)) => {}, + // or Some((y, z)) => {} + None => panic!() +} +``` + +Solution #2: Implement the `Copy` trait for the `X` structure. + +However, please keep in mind that the first solution should be preferred. + +``` +#[derive(Clone, Copy)] +struct X { x: (), } + +let x = Some((X { x: () }, X { x: () })); +match x { + Some((y, ref z)) => {}, + None => panic!() +} +``` +"##, + +E0158: r##" +`const` and `static` mean different things. A `const` is a compile-time +constant, an alias for a literal value. This property means you can match it +directly within a pattern. + +The `static` keyword, on the other hand, guarantees a fixed location in memory. +This does not always mean that the value is constant. For example, a global +mutex can be declared `static` as well. + +If you want to match against a `static`, consider using a guard instead: + +``` +static FORTY_TWO: i32 = 42; + +match Some(42) { + Some(x) if x == FORTY_TWO => {} + _ => {} +} +``` +"##, + +E0162: r##" +An if-let pattern attempts to match the pattern, and enters the body if the +match was successful. If the match is irrefutable (when it cannot fail to +match), use a regular `let`-binding instead. For instance: + +```compile_fail +struct Irrefutable(i32); +let irr = Irrefutable(0); + +// This fails to compile because the match is irrefutable. +if let Irrefutable(x) = irr { + // This body will always be executed. + foo(x); +} +``` + +Try this instead: + +```ignore +struct Irrefutable(i32); +let irr = Irrefutable(0); + +let Irrefutable(x) = irr; +foo(x); +``` +"##, + +E0165: r##" +A while-let pattern attempts to match the pattern, and enters the body if the +match was successful. If the match is irrefutable (when it cannot fail to +match), use a regular `let`-binding inside a `loop` instead. For instance: + +```compile_fail +struct Irrefutable(i32); +let irr = Irrefutable(0); + +// This fails to compile because the match is irrefutable. +while let Irrefutable(x) = irr { + ... +} + +Try this instead: + +``` +struct Irrefutable(i32); +let irr = Irrefutable(0); + +loop { + let Irrefutable(x) = irr; + ... +} +``` +"##, + +E0170: r##" +Enum variants are qualified by default. For example, given this type: + +``` +enum Method { + GET, + POST, +} +``` + +You would match it using: + +``` +enum Method { + GET, + POST, +} + +let m = Method::GET; + +match m { + Method::GET => {}, + Method::POST => {}, +} +``` + +If you don't qualify the names, the code will bind new variables named "GET" and +"POST" instead. This behavior is likely not what you want, so `rustc` warns when +that happens. + +Qualified names are good practice, and most code works well with them. But if +you prefer them unqualified, you can import the variants into scope: + +```ignore +use Method::*; +enum Method { GET, POST } +``` + +If you want others to be able to import variants from your module directly, use +`pub use`: + +```ignore +pub use Method::*; +enum Method { GET, POST } +``` +"##, + + +E0297: r##" +Patterns used to bind names must be irrefutable. That is, they must guarantee +that a name will be extracted in all cases. Instead of pattern matching the +loop variable, consider using a `match` or `if let` inside the loop body. For +instance: + +```compile_fail +let xs : Vec> = vec!(Some(1), None); + +// This fails because `None` is not covered. +for Some(x) in xs { + // ... +} +``` + +Match inside the loop instead: + +``` +let xs : Vec> = vec!(Some(1), None); + +for item in xs { + match item { + Some(x) => {}, + None => {}, + } +} +``` + +Or use `if let`: + +``` +let xs : Vec> = vec!(Some(1), None); + +for item in xs { + if let Some(x) = item { + // ... + } +} +``` +"##, + +E0301: r##" +Mutable borrows are not allowed in pattern guards, because matching cannot have +side effects. Side effects could alter the matched object or the environment +on which the match depends in such a way, that the match would not be +exhaustive. For instance, the following would not match any arm if mutable +borrows were allowed: + +```compile_fail +match Some(()) { + None => { }, + option if option.take().is_none() => { + /* impossible, option is `Some` */ + }, + Some(_) => { } // When the previous match failed, the option became `None`. +} +``` +"##, + +E0302: r##" +Assignments are not allowed in pattern guards, because matching cannot have +side effects. Side effects could alter the matched object or the environment +on which the match depends in such a way, that the match would not be +exhaustive. For instance, the following would not match any arm if assignments +were allowed: + +```compile_fail +match Some(()) { + None => { }, + option if { option = None; false } { }, + Some(_) => { } // When the previous match failed, the option became `None`. +} +``` +"##, + +E0303: r##" +In certain cases it is possible for sub-bindings to violate memory safety. +Updates to the borrow checker in a future version of Rust may remove this +restriction, but for now patterns must be rewritten without sub-bindings. + +```ignore +// Before. +match Some("hi".to_string()) { + ref op_string_ref @ Some(s) => {}, + None => {}, +} + +// After. +match Some("hi".to_string()) { + Some(ref s) => { + let op_string_ref = &Some(s); + // ... + }, + None => {}, +} +``` + +The `op_string_ref` binding has type `&Option<&String>` in both cases. + +See also https://github.com/rust-lang/rust/issues/14587 +"##, + +E0306: r##" +In an array literal `[x; N]`, `N` is the number of elements in the array. This +must be an unsigned integer. Erroneous code example: + +```compile_fail +let x = [0i32; true]; // error: expected positive integer for repeat count, + // found boolean +``` + +Working example: + +``` +let x = [0i32; 2]; +``` +"##, + +E0307: r##" +The length of an array is part of its type. For this reason, this length must +be a compile-time constant. Erroneous code example: + +```compile_fail + let len = 10; + let x = [0i32; len]; // error: expected constant integer for repeat count, + // found variable +``` +"##, + +} + + +register_diagnostics! { +E0298, // mismatched types between arms +E0299, // mismatched types between arms +E0471, // constant evaluation error: .. +} diff --git a/src/librustc/middle/const_eval.rs b/src/librustc_const_eval/eval.rs similarity index 93% rename from src/librustc/middle/const_eval.rs rename to src/librustc_const_eval/eval.rs index f685e4c0e18df..a36d0b3fcff22 100644 --- a/src/librustc/middle/const_eval.rs +++ b/src/librustc_const_eval/eval.rs @@ -1,4 +1,4 @@ -// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT +// 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. // @@ -10,23 +10,24 @@ //#![allow(non_camel_case_types)] -use self::ConstVal::*; +use rustc::middle::const_val::ConstVal::*; +use rustc::middle::const_val::ConstVal; use self::ErrKind::*; use self::EvalHint::*; -use front::map as ast_map; -use front::map::blocks::FnLikeNode; -use lint; -use middle::cstore::{self, CrateStore, InlinedItem}; -use {infer, traits}; -use middle::def::Def; -use middle::def_id::DefId; -use middle::pat_util::def_to_path; -use ty::{self, subst, Ty, TyCtxt}; -use ty::util::IntTypeExt; -use traits::ProjectionMode; -use middle::astconv_util::ast_ty_to_prim_ty; -use util::nodemap::NodeMap; +use rustc::front::map as ast_map; +use rustc::front::map::blocks::FnLikeNode; +use rustc::middle::cstore::{self, CrateStore, InlinedItem}; +use rustc::{infer, traits}; +use rustc::middle::def::Def; +use rustc::middle::def_id::DefId; +use rustc::middle::pat_util::def_to_path; +use rustc::ty::{self, Ty, TyCtxt, subst}; +use rustc::ty::util::IntTypeExt; +use rustc::traits::ProjectionMode; +use rustc::middle::astconv_util::ast_ty_to_prim_ty; +use rustc::util::nodemap::NodeMap; +use rustc::lint; use graphviz::IntoCow; use syntax::ast; @@ -34,7 +35,6 @@ use rustc_front::hir::{Expr, PatKind}; use rustc_front::hir; use rustc_front::intravisit::FnKind; use syntax::codemap::Span; -use syntax::parse::token::InternedString; use syntax::ptr::P; use syntax::codemap; use syntax::attr::IntType; @@ -42,9 +42,6 @@ use syntax::attr::IntType; use std::borrow::Cow; use std::cmp::Ordering; use std::collections::hash_map::Entry::Vacant; -use std::hash; -use std::mem::transmute; -use std::rc::Rc; use rustc_const_math::*; @@ -241,89 +238,6 @@ pub fn lookup_const_fn_by_id<'tcx>(tcx: &TyCtxt<'tcx>, def_id: DefId) } } -#[derive(Clone, Debug, RustcEncodable, RustcDecodable)] -pub enum ConstVal { - Float(f64), - Integral(ConstInt), - Str(InternedString), - ByteStr(Rc>), - Bool(bool), - Struct(ast::NodeId), - Tuple(ast::NodeId), - Function(DefId), - Array(ast::NodeId, u64), - Repeat(ast::NodeId, u64), - Char(char), - /// A value that only occurs in case `eval_const_expr` reported an error. You should never - /// handle this case. Its sole purpose is to allow more errors to be reported instead of - /// causing a fatal error. - Dummy, -} - -impl hash::Hash for ConstVal { - fn hash(&self, state: &mut H) { - match *self { - Float(a) => unsafe { transmute::<_,u64>(a) }.hash(state), - Integral(a) => a.hash(state), - Str(ref a) => a.hash(state), - ByteStr(ref a) => a.hash(state), - Bool(a) => a.hash(state), - Struct(a) => a.hash(state), - Tuple(a) => a.hash(state), - Function(a) => a.hash(state), - Array(a, n) => { a.hash(state); n.hash(state) }, - Repeat(a, n) => { a.hash(state); n.hash(state) }, - Char(c) => c.hash(state), - Dummy => ().hash(state), - } - } -} - -/// Note that equality for `ConstVal` means that the it is the same -/// constant, not that the rust values are equal. In particular, `NaN -/// == NaN` (at least if it's the same NaN; distinct encodings for NaN -/// are considering unequal). -impl PartialEq for ConstVal { - fn eq(&self, other: &ConstVal) -> bool { - match (self, other) { - (&Float(a), &Float(b)) => unsafe{transmute::<_,u64>(a) == transmute::<_,u64>(b)}, - (&Integral(a), &Integral(b)) => a == b, - (&Str(ref a), &Str(ref b)) => a == b, - (&ByteStr(ref a), &ByteStr(ref b)) => a == b, - (&Bool(a), &Bool(b)) => a == b, - (&Struct(a), &Struct(b)) => a == b, - (&Tuple(a), &Tuple(b)) => a == b, - (&Function(a), &Function(b)) => a == b, - (&Array(a, an), &Array(b, bn)) => (a == b) && (an == bn), - (&Repeat(a, an), &Repeat(b, bn)) => (a == b) && (an == bn), - (&Char(a), &Char(b)) => a == b, - (&Dummy, &Dummy) => true, // FIXME: should this be false? - _ => false, - } - } -} - -impl Eq for ConstVal { } - -impl ConstVal { - pub fn description(&self) -> &'static str { - match *self { - Float(_) => "float", - Integral(i) => i.description(), - Str(_) => "string literal", - ByteStr(_) => "byte string literal", - Bool(_) => "boolean", - Struct(_) => "struct", - Tuple(_) => "tuple", - Function(_) => "function definition", - Array(..) => "array", - Repeat(..) => "repeat", - Char(..) => "char", - Dummy => "dummy value", - } - } -} - pub fn const_expr_to_pat(tcx: &ty::TyCtxt, expr: &Expr, pat_id: ast::NodeId, span: Span) -> Result, DefId> { let pat_ty = tcx.expr_ty(expr); @@ -352,7 +266,6 @@ pub fn const_expr_to_pat(tcx: &ty::TyCtxt, expr: &Expr, pat_id: ast::NodeId, spa } _ => { } } - let pat = match expr.node { hir::ExprTup(ref exprs) => PatKind::Tup(try!(exprs.iter() @@ -1275,3 +1188,39 @@ pub fn compare_lit_exprs<'tcx>(tcx: &TyCtxt<'tcx>, }; compare_const_vals(&a, &b) } + + +/// Returns the repeat count for a repeating vector expression. +pub fn eval_repeat_count(tcx: &TyCtxt, count_expr: &hir::Expr) -> usize { + let hint = UncheckedExprHint(tcx.types.usize); + match eval_const_expr_partial(tcx, count_expr, hint, None) { + Ok(Integral(Usize(count))) => { + let val = count.as_u64(tcx.sess.target.uint_type); + assert_eq!(val as usize as u64, val); + val as usize + }, + Ok(const_val) => { + span_err!(tcx.sess, count_expr.span, E0306, + "expected positive integer for repeat count, found {}", + const_val.description()); + 0 + } + Err(err) => { + let err_msg = match count_expr.node { + hir::ExprPath(None, hir::Path { + global: false, + ref segments, + .. + }) if segments.len() == 1 => + format!("found variable"), + _ => match err.kind { + MiscCatchAll => format!("but found {}", err.description()), + _ => format!("but {}", err.description()) + } + }; + span_err!(tcx.sess, count_expr.span, E0307, + "expected constant integer for repeat count, {}", err_msg); + 0 + } + } +} diff --git a/src/librustc_const_eval/lib.rs b/src/librustc_const_eval/lib.rs new file mode 100644 index 0000000000000..558ae71756b8b --- /dev/null +++ b/src/librustc_const_eval/lib.rs @@ -0,0 +1,53 @@ +// Copyright 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! constant evaluation on the HIR and code to validate patterns/matches +//! +//! # Note +//! +//! This API is completely unstable and subject to change. + +#![crate_name = "rustc_const_eval"] +#![unstable(feature = "rustc_private", issue = "27812")] +#![crate_type = "dylib"] +#![crate_type = "rlib"] +#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", + html_favicon_url = "https://doc.rust-lang.org/favicon.ico", + html_root_url = "https://doc.rust-lang.org/nightly/")] + + +#![feature(rustc_private)] +#![feature(staged_api)] +#![feature(rustc_diagnostic_macros)] +#![feature(slice_patterns)] +#![feature(iter_arith)] +#![feature(question_mark)] + +#[macro_use] extern crate syntax; +#[macro_use] extern crate log; +extern crate rustc; +extern crate rustc_front; +extern crate rustc_back; +extern crate rustc_const_math; +extern crate graphviz; + +extern crate serialize as rustc_serialize; // used by deriving + +// NB: This module needs to be declared first so diagnostics are +// registered before they are used. +pub mod diagnostics; + +mod eval; +pub mod check_match; + +pub use eval::*; + +// Build the diagnostics array at the end so that the metadata includes error use sites. +__build_diagnostic_array! { librustc_const_eval, DIAGNOSTICS } diff --git a/src/librustc_const_math/int.rs b/src/librustc_const_math/int.rs index 7576a984bec7a..658d4d9a6d2fa 100644 --- a/src/librustc_const_math/int.rs +++ b/src/librustc_const_math/int.rs @@ -326,7 +326,7 @@ macro_rules! impl_binop { impl ::std::ops::$op for ConstInt { type Output = Result; fn $func(self, rhs: Self) -> Result { - match try!(self.infer(rhs)) { + match self.infer(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), @@ -353,7 +353,7 @@ macro_rules! derive_binop { impl ::std::ops::$op for ConstInt { type Output = Result; fn $func(self, rhs: Self) -> Result { - match try!(self.infer(rhs)) { + match self.infer(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))), diff --git a/src/librustc_driver/Cargo.toml b/src/librustc_driver/Cargo.toml index c8c517934443d..803b919058da6 100644 --- a/src/librustc_driver/Cargo.toml +++ b/src/librustc_driver/Cargo.toml @@ -17,6 +17,7 @@ log = { path = "../liblog" } rustc = { path = "../librustc" } rustc_back = { path = "../librustc_back" } rustc_borrowck = { path = "../librustc_borrowck" } +rustc_const_eval = { path = "../librustc_const_eval" } rustc_front = { path = "../librustc_front" } rustc_lint = { path = "../librustc_lint" } rustc_llvm = { path = "../librustc_llvm" } diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 468dc7b12c162..61f8c9bcc4f4d 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -38,6 +38,7 @@ use rustc_plugin as plugin; use rustc_front::hir; use rustc_front::lowering::{lower_crate, LoweringContext}; use rustc_passes::{no_asm, loops, consts, const_fn, rvalues, static_recursion}; +use rustc_const_eval::check_match; use super::Compilation; use serialize::json; @@ -851,7 +852,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session, time(time_passes, "match checking", - || middle::check_match::check_crate(tcx)); + || check_match::check_crate(tcx)); // this must run before MIR dump, because // "not all control paths return a value" is reported here. diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 057a34c27b1c7..516c55e1020ea 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -40,6 +40,7 @@ extern crate libc; extern crate rustc; extern crate rustc_back; extern crate rustc_borrowck; +extern crate rustc_const_eval; extern crate rustc_passes; extern crate rustc_front; extern crate rustc_lint; @@ -1090,6 +1091,7 @@ pub fn diagnostics_registry() -> diagnostics::registry::Registry { all_errors.extend_from_slice(&rustc_resolve::DIAGNOSTICS); all_errors.extend_from_slice(&rustc_privacy::DIAGNOSTICS); all_errors.extend_from_slice(&rustc_trans::DIAGNOSTICS); + all_errors.extend_from_slice(&rustc_const_eval::DIAGNOSTICS); Registry::new(&all_errors) } diff --git a/src/librustc_lint/Cargo.toml b/src/librustc_lint/Cargo.toml index 33443957d1b3b..4821a72327978 100644 --- a/src/librustc_lint/Cargo.toml +++ b/src/librustc_lint/Cargo.toml @@ -12,5 +12,6 @@ crate-type = ["dylib"] log = { path = "../liblog" } rustc = { path = "../librustc" } rustc_back = { path = "../librustc_back" } +rustc_const_eval = { path = "../librustc_const_eval" } rustc_front = { path = "../librustc_front" } syntax = { path = "../libsyntax" } diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs index 9ed21117cebca..6e3a961cacae7 100644 --- a/src/librustc_lint/lib.rs +++ b/src/librustc_lint/lib.rs @@ -46,6 +46,7 @@ extern crate rustc; extern crate log; extern crate rustc_front; extern crate rustc_back; +extern crate rustc_const_eval; pub use rustc::lint as lint; pub use rustc::middle as middle; diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index 6322f59257310..80733bccf8ec3 100644 --- a/src/librustc_lint/types.rs +++ b/src/librustc_lint/types.rs @@ -14,8 +14,9 @@ use middle::def_id::DefId; use rustc::infer; use rustc::ty::subst::Substs; use rustc::ty::{self, Ty, TyCtxt}; -use middle::const_eval::{eval_const_expr_partial, ConstVal}; -use middle::const_eval::EvalHint::ExprTypeChecked; +use middle::const_val::ConstVal; +use rustc_const_eval::eval_const_expr_partial; +use rustc_const_eval::EvalHint::ExprTypeChecked; use util::nodemap::{FnvHashSet}; use lint::{LateContext, LintContext, LintArray}; use lint::{LintPass, LateLintPass}; diff --git a/src/librustc_mir/Cargo.toml b/src/librustc_mir/Cargo.toml index 35c29e2cf2d2f..f136618b1c9e2 100644 --- a/src/librustc_mir/Cargo.toml +++ b/src/librustc_mir/Cargo.toml @@ -13,6 +13,7 @@ graphviz = { path = "../libgraphviz" } log = { path = "../liblog" } rustc = { path = "../librustc" } rustc_back = { path = "../librustc_back" } +rustc_const_eval = { path = "../librustc_const_eval" } rustc_const_math = { path = "../librustc_const_math" } rustc_data_structures = { path = "../librustc_data_structures" } rustc_front = { path = "../librustc_front" } diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs index 581e8e35ee89f..685631970146f 100644 --- a/src/librustc_mir/build/matches/mod.rs +++ b/src/librustc_mir/build/matches/mod.rs @@ -15,7 +15,7 @@ use build::{BlockAnd, BlockAndExtension, Builder}; use rustc_data_structures::fnv::FnvHashMap; -use rustc::middle::const_eval::ConstVal; +use rustc::middle::const_val::ConstVal; use rustc::ty::{AdtDef, Ty}; use rustc::mir::repr::*; use hair::*; diff --git a/src/librustc_mir/build/matches/test.rs b/src/librustc_mir/build/matches/test.rs index 5a1c3739ef5f0..dc70cf4ffb93a 100644 --- a/src/librustc_mir/build/matches/test.rs +++ b/src/librustc_mir/build/matches/test.rs @@ -19,7 +19,7 @@ use build::Builder; use build::matches::{Candidate, MatchPair, Test, TestKind}; use hair::*; use rustc_data_structures::fnv::FnvHashMap; -use rustc::middle::const_eval::ConstVal; +use rustc::middle::const_val::ConstVal; use rustc::ty::{self, Ty}; use rustc::mir::repr::*; use syntax::codemap::Span; diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir/build/scope.rs index ffaf02bbfee6c..e3093eab22bc0 100644 --- a/src/librustc_mir/build/scope.rs +++ b/src/librustc_mir/build/scope.rs @@ -94,7 +94,7 @@ use rustc::ty::{self, Ty, TyCtxt}; use rustc::mir::repr::*; use syntax::codemap::{Span, DUMMY_SP}; use syntax::parse::token::intern_and_get_ident; -use rustc::middle::const_eval::ConstVal; +use rustc::middle::const_val::ConstVal; use rustc_const_math::ConstInt; pub struct Scope<'tcx> { diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index 231acbfb4884a..451cdea35a7f6 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -16,7 +16,8 @@ use hair::cx::block; use hair::cx::to_ref::ToRef; use rustc::front::map; use rustc::middle::def::Def; -use rustc::middle::const_eval::{self, ConstVal}; +use rustc::middle::const_val::ConstVal; +use rustc_const_eval as const_eval; use rustc::middle::region::CodeExtent; use rustc::middle::pat_util; use rustc::ty::{self, VariantDef, Ty}; diff --git a/src/librustc_mir/hair/cx/mod.rs b/src/librustc_mir/hair/cx/mod.rs index 9bd94e432bf17..e4a8363051b78 100644 --- a/src/librustc_mir/hair/cx/mod.rs +++ b/src/librustc_mir/hair/cx/mod.rs @@ -18,7 +18,8 @@ use hair::*; use rustc::mir::repr::*; -use rustc::middle::const_eval::{self, ConstVal}; +use rustc::middle::const_val::ConstVal; +use rustc_const_eval as const_eval; use rustc::middle::def_id::DefId; use rustc::infer::InferCtxt; use rustc::ty::subst::{Subst, Substs}; diff --git a/src/librustc_mir/hair/cx/pattern.rs b/src/librustc_mir/hair/cx/pattern.rs index 0cb849555f24b..c6132a71eefd5 100644 --- a/src/librustc_mir/hair/cx/pattern.rs +++ b/src/librustc_mir/hair/cx/pattern.rs @@ -11,7 +11,7 @@ use hair::*; use hair::cx::Cx; use rustc_data_structures::fnv::FnvHashMap; -use rustc::middle::const_eval; +use rustc_const_eval as const_eval; use rustc::middle::def::Def; use rustc::middle::pat_util::{pat_is_resolved_const, pat_is_binding}; use rustc::ty::{self, Ty}; diff --git a/src/librustc_mir/hair/mod.rs b/src/librustc_mir/hair/mod.rs index 79c8356bb557a..affc187298715 100644 --- a/src/librustc_mir/hair/mod.rs +++ b/src/librustc_mir/hair/mod.rs @@ -16,7 +16,7 @@ use rustc::mir::repr::{BinOp, BorrowKind, Field, Literal, Mutability, UnOp, TypedConstVal}; -use rustc::middle::const_eval::ConstVal; +use rustc::middle::const_val::ConstVal; use rustc::middle::def_id::DefId; use rustc::middle::region::CodeExtent; use rustc::ty::subst::Substs; diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs index 3b55f62717c41..e024fa94fb772 100644 --- a/src/librustc_mir/lib.rs +++ b/src/librustc_mir/lib.rs @@ -33,6 +33,7 @@ extern crate rustc_front; extern crate rustc_back; extern crate syntax; extern crate rustc_const_math; +extern crate rustc_const_eval; pub mod build; pub mod graphviz; diff --git a/src/librustc_mir/transform/simplify_cfg.rs b/src/librustc_mir/transform/simplify_cfg.rs index cbde292cb995b..00b8f5c093043 100644 --- a/src/librustc_mir/transform/simplify_cfg.rs +++ b/src/librustc_mir/transform/simplify_cfg.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use rustc::middle::const_eval::ConstVal; +use rustc::middle::const_val::ConstVal; use rustc::ty::TyCtxt; use rustc::mir::repr::*; use rustc::mir::transform::{MirPass, Pass}; diff --git a/src/librustc_passes/Cargo.toml b/src/librustc_passes/Cargo.toml index 7cc6510fa1fd1..02303aa7130ea 100644 --- a/src/librustc_passes/Cargo.toml +++ b/src/librustc_passes/Cargo.toml @@ -11,5 +11,6 @@ crate-type = ["dylib"] [dependencies] log = { path = "../liblog" } rustc = { path = "../librustc" } +rustc_const_eval = { path = "../librustc_const_eval" } rustc_front = { path = "../librustc_front" } syntax = { path = "../libsyntax" } diff --git a/src/librustc_passes/consts.rs b/src/librustc_passes/consts.rs index 571d5bd9bc5a3..a33b8caee2e12 100644 --- a/src/librustc_passes/consts.rs +++ b/src/librustc_passes/consts.rs @@ -26,9 +26,10 @@ use rustc::dep_graph::DepNode; use rustc::ty::cast::{CastKind}; -use rustc::middle::const_eval::{self, ConstEvalErr}; -use rustc::middle::const_eval::ErrKind::IndexOpFeatureGated; -use rustc::middle::const_eval::EvalHint::ExprTypeChecked; +use rustc_const_eval::{ConstEvalErr, lookup_const_fn_by_id, compare_lit_exprs}; +use rustc_const_eval::{eval_const_expr_partial, lookup_const_by_id}; +use rustc_const_eval::ErrKind::IndexOpFeatureGated; +use rustc_const_eval::EvalHint::ExprTypeChecked; use rustc::middle::def::Def; use rustc::middle::def_id::DefId; use rustc::middle::expr_use_visitor as euv; @@ -169,7 +170,7 @@ impl<'a, 'tcx> CheckCrateVisitor<'a, 'tcx> { def_id: DefId, ret_ty: Ty<'tcx>) -> bool { - if let Some(fn_like) = const_eval::lookup_const_fn_by_id(self.tcx, def_id) { + if let Some(fn_like) = lookup_const_fn_by_id(self.tcx, def_id) { if // we are in a static/const initializer self.mode != Mode::Var && @@ -335,7 +336,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CheckCrateVisitor<'a, 'tcx> { self.global_expr(Mode::Const, &start); self.global_expr(Mode::Const, &end); - match const_eval::compare_lit_exprs(self.tcx, start, end) { + match compare_lit_exprs(self.tcx, start, end) { Some(Ordering::Less) | Some(Ordering::Equal) => {} Some(Ordering::Greater) => { @@ -431,7 +432,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CheckCrateVisitor<'a, 'tcx> { match node_ty.sty { ty::TyUint(_) | ty::TyInt(_) if div_or_rem => { if !self.qualif.intersects(ConstQualif::NOT_CONST) { - match const_eval::eval_const_expr_partial( + match eval_const_expr_partial( self.tcx, ex, ExprTypeChecked, None) { Ok(_) => {} Err(ConstEvalErr { kind: IndexOpFeatureGated, ..}) => {}, @@ -611,7 +612,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, Some(Def::Const(did)) | Some(Def::AssociatedConst(did)) => { let substs = Some(v.tcx.node_id_item_substs(e.id).substs); - if let Some((expr, _)) = const_eval::lookup_const_by_id(v.tcx, did, substs) { + if let Some((expr, _)) = lookup_const_by_id(v.tcx, did, substs) { let inner = v.global_expr(Mode::Const, expr); v.add_qualif(inner); } diff --git a/src/librustc_passes/lib.rs b/src/librustc_passes/lib.rs index 91bfb19aa9d60..6d217040316c9 100644 --- a/src/librustc_passes/lib.rs +++ b/src/librustc_passes/lib.rs @@ -30,6 +30,7 @@ extern crate core; extern crate rustc; extern crate rustc_front; +extern crate rustc_const_eval; #[macro_use] extern crate log; #[macro_use] extern crate syntax; diff --git a/src/librustc_trans/Cargo.toml b/src/librustc_trans/Cargo.toml index e884442f03b01..b798afe25edb7 100644 --- a/src/librustc_trans/Cargo.toml +++ b/src/librustc_trans/Cargo.toml @@ -16,6 +16,7 @@ graphviz = { path = "../libgraphviz" } log = { path = "../liblog" } rustc = { path = "../librustc" } rustc_back = { path = "../librustc_back" } +rustc_const_eval = { path = "../librustc_const_eval" } rustc_const_math = { path = "../librustc_const_math" } rustc_data_structures = { path = "../librustc_data_structures" } rustc_front = { path = "../librustc_front" } diff --git a/src/librustc_trans/_match.rs b/src/librustc_trans/_match.rs index 008323ee5bf31..f545ba2cbe056 100644 --- a/src/librustc_trans/_match.rs +++ b/src/librustc_trans/_match.rs @@ -189,9 +189,8 @@ use self::Opt::*; use self::FailureHandler::*; use llvm::{ValueRef, BasicBlockRef}; -use middle::check_match::StaticInliner; -use middle::check_match; -use middle::const_eval; +use rustc_const_eval::check_match::{self, StaticInliner}; +use rustc_const_eval::{compare_lit_exprs, eval_const_expr}; use middle::def::{Def, DefMap}; use middle::def_id::DefId; use middle::expr_use_visitor as euv; @@ -241,7 +240,7 @@ struct ConstantExpr<'a>(&'a hir::Expr); impl<'a> ConstantExpr<'a> { fn eq(self, other: ConstantExpr<'a>, tcx: &TyCtxt) -> bool { - match const_eval::compare_lit_exprs(tcx, self.0, other.0) { + match compare_lit_exprs(tcx, self.0, other.0) { Some(result) => result == Ordering::Equal, None => panic!("compare_list_exprs: type mismatch"), } @@ -611,11 +610,11 @@ fn enter_opt<'a, 'p, 'blk, 'tcx>( let ctor = match opt { &ConstantValue(ConstantExpr(expr), _) => check_match::ConstantValue( - const_eval::eval_const_expr(bcx.tcx(), &expr) + eval_const_expr(bcx.tcx(), &expr) ), &ConstantRange(ConstantExpr(lo), ConstantExpr(hi), _) => check_match::ConstantRange( - const_eval::eval_const_expr(bcx.tcx(), &lo), - const_eval::eval_const_expr(bcx.tcx(), &hi) + eval_const_expr(bcx.tcx(), &lo), + eval_const_expr(bcx.tcx(), &hi) ), &SliceLengthEqual(n, _) => check_match::Slice(n), diff --git a/src/librustc_trans/consts.rs b/src/librustc_trans/consts.rs index b2edcbd9b9e87..555c12807baf2 100644 --- a/src/librustc_trans/consts.rs +++ b/src/librustc_trans/consts.rs @@ -13,7 +13,8 @@ use llvm; use llvm::{ConstFCmp, ConstICmp, SetLinkage, SetUnnamedAddr}; use llvm::{InternalLinkage, ValueRef, Bool, True}; use middle::const_qualif::ConstQualif; -use middle::const_eval::{self, ConstEvalErr}; +use rustc_const_eval::{ConstEvalErr, lookup_const_fn_by_id, lookup_const_by_id, ErrKind}; +use rustc_const_eval::eval_repeat_count; use middle::def::Def; use middle::def_id::DefId; use rustc::front::map as hir_map; @@ -197,7 +198,7 @@ fn const_fn_call<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, arg_vals: &[ValueRef], param_substs: &'tcx Substs<'tcx>, trueconst: TrueConst) -> Result { - let fn_like = const_eval::lookup_const_fn_by_id(ccx.tcx(), def_id); + let fn_like = lookup_const_fn_by_id(ccx.tcx(), def_id); let fn_like = fn_like.expect("lookup_const_fn_by_id failed in const_fn_call"); let body = match fn_like.body().expr { @@ -228,7 +229,7 @@ pub fn get_const_expr<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, let substs = monomorphize::apply_param_substs(ccx.tcx(), param_substs, &substs.erase_regions()); - match const_eval::lookup_const_by_id(ccx.tcx(), def_id, Some(substs)) { + match lookup_const_by_id(ccx.tcx(), def_id, Some(substs)) { Some((ref expr, _ty)) => expr, None => { ccx.sess().span_bug(ref_expr.span, "constant item not found") @@ -534,12 +535,12 @@ fn const_err(cx: &CrateContext, Ok(()) }, (Err(err), TrueConst::Yes) => { - let err = ConstEvalErr{ span: e.span, kind: const_eval::ErrKind::Math(err) }; + let err = ConstEvalErr{ span: e.span, kind: ErrKind::Math(err) }; cx.tcx().sess.span_err(e.span, &err.description()); Err(Compiletime(err)) }, (Err(err), TrueConst::No) => { - let err = ConstEvalErr{ span: e.span, kind: const_eval::ErrKind::Math(err) }; + let err = ConstEvalErr{ span: e.span, kind: ErrKind::Math(err) }; cx.tcx().sess.span_warn(e.span, &err.description()); Err(Runtime(err)) }, @@ -883,7 +884,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, hir::ExprRepeat(ref elem, ref count) => { let unit_ty = ety.sequence_element_type(cx.tcx()); let llunitty = type_of::type_of(cx, unit_ty); - let n = cx.tcx().eval_repeat_count(count); + let n = eval_repeat_count(cx.tcx(), count); let unit_val = const_expr(cx, &elem, param_substs, fn_args, trueconst)?.0; let vs = vec![unit_val; n]; if val_ty(unit_val) != llunitty { diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs index c85008181a447..e968793553887 100644 --- a/src/librustc_trans/lib.rs +++ b/src/librustc_trans/lib.rs @@ -52,6 +52,7 @@ extern crate rustc_mir; extern crate rustc_platform_intrinsics as intrinsics; extern crate serialize; extern crate rustc_const_math; +extern crate rustc_const_eval; #[macro_use] extern crate log; #[macro_use] extern crate syntax; diff --git a/src/librustc_trans/mir/constant.rs b/src/librustc_trans/mir/constant.rs index cdb54eadbddcc..2e154c40875f1 100644 --- a/src/librustc_trans/mir/constant.rs +++ b/src/librustc_trans/mir/constant.rs @@ -10,8 +10,9 @@ use llvm::ValueRef; use rustc::ty::{Ty, TypeFoldable}; -use rustc::middle::const_eval::{self, ConstVal}; +use rustc::middle::const_val::ConstVal; use rustc_const_math::ConstInt::*; +use rustc_const_eval::lookup_const_by_id; use rustc::mir::repr as mir; use abi; use common::{self, BlockAndBuilder, C_bool, C_bytes, C_floating_f64, C_integral, @@ -114,7 +115,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { } let substs = Some(bcx.monomorphize(substs)); - let expr = const_eval::lookup_const_by_id(bcx.tcx(), def_id, substs) + let expr = lookup_const_by_id(bcx.tcx(), def_id, substs) .expect("def was const, but lookup_const_by_id failed").0; // FIXME: this is falling back to translating from HIR. This is not easy to fix, // because we would have somehow adapt const_eval to work on MIR rather than HIR. diff --git a/src/librustc_trans/mir/rvalue.rs b/src/librustc_trans/mir/rvalue.rs index b90be5e0ab626..1396883120b86 100644 --- a/src/librustc_trans/mir/rvalue.rs +++ b/src/librustc_trans/mir/rvalue.rs @@ -11,7 +11,7 @@ use llvm::ValueRef; use rustc::ty::{self, Ty}; use rustc::ty::cast::{CastTy, IntTy}; -use middle::const_eval::ConstVal; +use middle::const_val::ConstVal; use rustc_const_math::ConstInt; use rustc::mir::repr as mir; diff --git a/src/librustc_trans/tvec.rs b/src/librustc_trans/tvec.rs index c42bad0bc0bd1..56ba1b0242609 100644 --- a/src/librustc_trans/tvec.rs +++ b/src/librustc_trans/tvec.rs @@ -30,6 +30,7 @@ use value::Value; use rustc::ty::{self, Ty}; use rustc_front::hir; +use rustc_const_eval::eval_repeat_count; use syntax::ast; use syntax::parse::token::InternedString; @@ -218,7 +219,7 @@ fn write_content<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, return expr::trans_into(bcx, &element, Ignore); } SaveIn(lldest) => { - match bcx.tcx().eval_repeat_count(&count_expr) { + match eval_repeat_count(bcx.tcx(), &count_expr) { 0 => expr::trans_into(bcx, &element, Ignore), 1 => expr::trans_into(bcx, &element, SaveIn(lldest)), count => { @@ -270,7 +271,7 @@ fn elements_required(bcx: Block, content_expr: &hir::Expr) -> usize { }, hir::ExprVec(ref es) => es.len(), hir::ExprRepeat(_, ref count_expr) => { - bcx.tcx().eval_repeat_count(&count_expr) + eval_repeat_count(bcx.tcx(), &count_expr) } _ => bcx.tcx().sess.span_bug(content_expr.span, "unexpected vec content") diff --git a/src/librustc_typeck/Cargo.toml b/src/librustc_typeck/Cargo.toml index 6e1bca87a821a..6f46686feb5c8 100644 --- a/src/librustc_typeck/Cargo.toml +++ b/src/librustc_typeck/Cargo.toml @@ -15,6 +15,7 @@ arena = { path = "../libarena" } fmt_macros = { path = "../libfmt_macros" } rustc = { path = "../librustc" } rustc_back = { path = "../librustc_back" } +rustc_const_eval = { path = "../librustc_const_eval" } rustc_const_math = { path = "../librustc_const_math" } rustc_front = { path = "../librustc_front" } rustc_platform_intrinsics = { path = "../librustc_platform_intrinsics" } diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index bd2e0092a89ba..b7d00716f0223 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -49,8 +49,9 @@ //! an rptr (`&r.T`) use the region `r` that appears in the rptr. use middle::astconv_util::{prim_ty_to_ty, prohibit_type_params, prohibit_projection}; -use middle::const_eval::{self, ConstVal}; -use middle::const_eval::EvalHint::UncheckedExprHint; +use middle::const_val::ConstVal; +use rustc_const_eval::eval_const_expr_partial; +use rustc_const_eval::EvalHint::UncheckedExprHint; use middle::def::{self, Def}; use middle::def_id::DefId; use middle::resolve_lifetime as rl; @@ -1681,7 +1682,7 @@ pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx>, } hir::TyFixedLengthVec(ref ty, ref e) => { let hint = UncheckedExprHint(tcx.types.usize); - match const_eval::eval_const_expr_partial(tcx, &e, hint, None) { + match eval_const_expr_partial(tcx, &e, hint, None) { Ok(ConstVal::Integral(ConstInt::Usize(i))) => { let i = i.as_u64(tcx.sess.target.uint_type); assert_eq!(i as usize as u64, i); diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 107497a2aa367..d90ba03abd40e 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -130,6 +130,7 @@ use rustc_front::hir; use rustc_front::hir::{Visibility, PatKind}; use rustc_front::print::pprust; use rustc_back::slice; +use rustc_const_eval::eval_repeat_count; mod assoc; pub mod dropck; @@ -3592,7 +3593,7 @@ fn check_expr_with_expectation_and_lvalue_pref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, } hir::ExprRepeat(ref element, ref count_expr) => { check_expr_has_type(fcx, &count_expr, tcx.types.usize); - let count = fcx.tcx().eval_repeat_count(&count_expr); + let count = eval_repeat_count(fcx.tcx(), &count_expr); let uty = match expected { ExpectHasType(uty) => { diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 743a2bb221139..a9ef0fce88091 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -66,8 +66,9 @@ use constrained_type_params as ctp; use coherence; use middle::lang_items::SizedTraitLangItem; use middle::resolve_lifetime; -use middle::const_eval::{self, ConstVal}; -use middle::const_eval::EvalHint::UncheckedExprHint; +use middle::const_val::ConstVal; +use rustc_const_eval::EvalHint::UncheckedExprHint; +use rustc_const_eval::eval_const_expr_partial; use rustc::ty::subst::{Substs, FnSpace, ParamSpace, SelfSpace, TypeSpace, VecPerParamSpace}; use rustc::ty::{ToPredicate, ImplContainer, ImplOrTraitItemContainer, TraitContainer}; use rustc::ty::{self, ToPolyTraitRef, Ty, TyCtxt, TypeScheme}; @@ -1045,7 +1046,7 @@ fn convert_enum_def<'tcx>(tcx: &TyCtxt<'tcx>, let ty_hint = repr_ty.to_ty(tcx); let hint = UncheckedExprHint(ty_hint); - match const_eval::eval_const_expr_partial(tcx, e, hint, None) { + match eval_const_expr_partial(tcx, e, hint, None) { Ok(ConstVal::Integral(i)) => { // FIXME: eval_const_expr_partial should return an error if the hint is wrong match (repr_ty, i) { diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 9c08f57b8331e..c3ba91823434a 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -93,6 +93,7 @@ extern crate rustc_platform_intrinsics as intrinsics; extern crate rustc_front; extern crate rustc_back; extern crate rustc_const_math; +extern crate rustc_const_eval; pub use rustc::dep_graph; pub use rustc::front; diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml index 6b0ad30f4509c..3950131129ca7 100644 --- a/src/librustdoc/Cargo.toml +++ b/src/librustdoc/Cargo.toml @@ -14,6 +14,7 @@ arena = { path = "../libarena" } getopts = { path = "../libgetopts" } rustc = { path = "../librustc" } rustc_back = { path = "../librustc_back" } +rustc_const_eval = { path = "../librustc_const_eval" } rustc_driver = { path = "../librustc_driver" } rustc_front = { path = "../librustc_front" } rustc_lint = { path = "../librustc_lint" } diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 702c6dd8211cb..3e4ba47ce4cd2 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -22,7 +22,8 @@ use rustc::middle::def_id::DefId; use rustc::ty::{self, TyCtxt}; use rustc::ty::subst; use rustc::middle::stability; -use rustc::middle::const_eval; + +use rustc_const_eval::lookup_const_by_id; use core::DocContext; use doctree; @@ -336,7 +337,7 @@ pub fn build_impl(cx: &DocContext, let did = assoc_const.def_id; let type_scheme = tcx.lookup_item_type(did); let default = if assoc_const.has_value { - Some(const_eval::lookup_const_by_id(tcx, did, None) + Some(lookup_const_by_id(tcx, did, None) .unwrap().0.span.to_src(cx)) } else { None @@ -483,10 +484,9 @@ fn build_module(cx: &DocContext, tcx: &TyCtxt, fn build_const(cx: &DocContext, tcx: &TyCtxt, did: DefId) -> clean::Constant { - use rustc::middle::const_eval; use rustc_front::print::pprust; - let (expr, ty) = const_eval::lookup_const_by_id(tcx, did, None).unwrap_or_else(|| { + let (expr, ty) = lookup_const_by_id(tcx, did, None).unwrap_or_else(|| { panic!("expected lookup_const_by_id to succeed for {:?}", did); }); debug!("converting constant expr {:?} to snippet", expr); diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 90cb78f46a67c..a35fe20b6b6f4 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -35,6 +35,7 @@ extern crate arena; extern crate getopts; extern crate libc; extern crate rustc; +extern crate rustc_const_eval; extern crate rustc_trans; extern crate rustc_driver; extern crate rustc_resolve; diff --git a/src/test/auxiliary/dummy_mir_pass.rs b/src/test/auxiliary/dummy_mir_pass.rs index edf1c2c3a398e..fc1ef4d41a855 100644 --- a/src/test/auxiliary/dummy_mir_pass.rs +++ b/src/test/auxiliary/dummy_mir_pass.rs @@ -23,7 +23,7 @@ use rustc::mir::transform::{self, MirPass}; use rustc::mir::repr::{Mir, Literal}; use rustc::mir::visit::MutVisitor; use rustc::ty; -use rustc::middle::const_eval::ConstVal; +use rustc::middle::const_val::ConstVal; use rustc_const_math::ConstInt; use rustc_plugin::Registry;