From 6cc449ad241c1cc54f5a789affffed2642422cec Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 15 Mar 2016 12:33:13 +0100 Subject: [PATCH 1/6] 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/6] 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; From 99501e6177b2614708dd30fe06109415015b1158 Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Wed, 30 Mar 2016 09:35:38 -0400 Subject: [PATCH 3/6] Remove no longer necessary coercions to fn pointer types. Originally added in 8fe9e4dff6d9d0fdd940835ae377edcb3754f8c1. Everything appears to build fine without the coercions, so they can presumably be removed. --- src/libstd/collections/hash/map.rs | 8 -------- src/libstd/collections/hash/set.rs | 4 ---- 2 files changed, 12 deletions(-) diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index 7ab5c90b0abde..1d21d2d18e4f3 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -837,8 +837,6 @@ impl HashMap #[stable(feature = "rust1", since = "1.0.0")] pub fn keys<'a>(&'a self) -> Keys<'a, K, V> { fn first((a, _): (A, B)) -> A { a } - let first: fn((&'a K,&'a V)) -> &'a K = first; // coerce to fn ptr - Keys { inner: self.iter().map(first) } } @@ -862,8 +860,6 @@ impl HashMap #[stable(feature = "rust1", since = "1.0.0")] pub fn values<'a>(&'a self) -> Values<'a, K, V> { fn second((_, b): (A, B)) -> B { b } - let second: fn((&'a K,&'a V)) -> &'a V = second; // coerce to fn ptr - Values { inner: self.iter().map(second) } } @@ -997,8 +993,6 @@ impl HashMap #[stable(feature = "drain", since = "1.6.0")] pub fn drain(&mut self) -> Drain { fn last_two((_, b, c): (A, B, C)) -> (B, C) { (b, c) } - let last_two: fn((SafeHash, K, V)) -> (K, V) = last_two; // coerce to fn pointer - Drain { inner: self.table.drain().map(last_two), } @@ -1404,8 +1398,6 @@ impl IntoIterator for HashMap /// ``` fn into_iter(self) -> IntoIter { fn last_two((_, b, c): (A, B, C)) -> (B, C) { (b, c) } - let last_two: fn((SafeHash, K, V)) -> (K, V) = last_two; - IntoIter { inner: self.table.into_iter().map(last_two) } diff --git a/src/libstd/collections/hash/set.rs b/src/libstd/collections/hash/set.rs index fdde1773a4518..24dfcb1a9b7ba 100644 --- a/src/libstd/collections/hash/set.rs +++ b/src/libstd/collections/hash/set.rs @@ -415,8 +415,6 @@ impl HashSet #[stable(feature = "drain", since = "1.6.0")] pub fn drain(&mut self) -> Drain { fn first((a, _): (A, B)) -> A { a } - let first: fn((T, ())) -> T = first; // coerce to fn pointer - Drain { iter: self.map.drain().map(first) } } @@ -892,8 +890,6 @@ impl IntoIterator for HashSet /// ``` fn into_iter(self) -> IntoIter { fn first((a, _): (A, B)) -> A { a } - let first: fn((T, ())) -> T = first; - IntoIter { iter: self.map.into_iter().map(first) } } } From b1b37384cd6cf45525962a4535188e944493ad9a Mon Sep 17 00:00:00 2001 From: Valentin Lorentz Date: Wed, 30 Mar 2016 19:34:53 +0200 Subject: [PATCH 4/6] =?UTF-8?q?Book:=20Fix=20phrasing:=20=E2=80=9Can=20ass?= =?UTF-8?q?ociated=20type=E2=80=9D=20=E2=86=92=20=E2=80=9Ca=20trait=20with?= =?UTF-8?q?=20an=20associated=20type=E2=80=9D.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/doc/book/associated-types.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/book/associated-types.md b/src/doc/book/associated-types.md index a0676a33996fc..cb54ac2419ecd 100644 --- a/src/doc/book/associated-types.md +++ b/src/doc/book/associated-types.md @@ -131,7 +131,7 @@ declarations. ## Trait objects with associated types There’s one more bit of syntax we should talk about: trait objects. If you -try to create a trait object from an associated type, like this: +try to create a trait object from a trait with an associated type, like this: ```rust,ignore # trait Graph { From 2646663b5a9b9bd021e58eb9cd8bcc63b7925c95 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Fri, 25 Mar 2016 18:17:04 +0100 Subject: [PATCH 5/6] Put in `-Z continue-parse-after-error` This works by adding a boolean flag, `continue_after_error`, to `syntax::errors::Handler` that can be imperatively set to `true` or `false` via a new `fn set_continue_after_error`. The flag starts off true (since we generally try to recover from compiler errors, and `Handler` is shared across all phases). Then, during the `phase_1_parse_input`, we consult the setting of the `-Z continue-parse-after-error` debug flag to determine whether we should leave the flag set to `true` or should change it to `false`. ---- (We might consider adding a debugflag to do such aborts in other places where we are currently attempting recovery, such as resolve, but I think the parser is the really important case to handle in the face of #31994 and the parser bugs of varying degrees that were injected by parse error recovery.) --- src/librustc/session/config.rs | 6 ++++++ src/librustc_driver/driver.rs | 4 ++++ src/libsyntax/errors/mod.rs | 9 +++++++++ 3 files changed, 19 insertions(+) diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 17f70b2d8dc66..ac0c18ea2b15f 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -138,6 +138,7 @@ pub struct Options { pub no_trans: bool, pub error_format: ErrorOutputType, pub treat_err_as_bug: bool, + pub continue_parse_after_error: bool, pub mir_opt_level: usize, /// if true, build up the dep-graph @@ -259,6 +260,7 @@ pub fn basic_options() -> Options { parse_only: false, no_trans: false, treat_err_as_bug: false, + continue_parse_after_error: false, mir_opt_level: 1, build_dep_graph: false, dump_dep_graph: false, @@ -633,6 +635,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "run all passes except translation; no output"), treat_err_as_bug: bool = (false, parse_bool, "treat all errors that occur as bugs"), + continue_parse_after_error: bool = (false, parse_bool, + "attempt to recover from parse errors (experimental)"), incr_comp: bool = (false, parse_bool, "enable incremental compilation (experimental)"), dump_dep_graph: bool = (false, parse_bool, @@ -1045,6 +1049,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { let parse_only = debugging_opts.parse_only; let no_trans = debugging_opts.no_trans; let treat_err_as_bug = debugging_opts.treat_err_as_bug; + let continue_parse_after_error = debugging_opts.continue_parse_after_error; let mir_opt_level = debugging_opts.mir_opt_level.unwrap_or(1); let incremental_compilation = debugging_opts.incr_comp; let dump_dep_graph = debugging_opts.dump_dep_graph; @@ -1228,6 +1233,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { parse_only: parse_only, no_trans: no_trans, treat_err_as_bug: treat_err_as_bug, + continue_parse_after_error: continue_parse_after_error, mir_opt_level: mir_opt_level, build_dep_graph: incremental_compilation || dump_dep_graph, dump_dep_graph: dump_dep_graph, diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 55b873c06630a..55c46ae38713b 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -427,6 +427,8 @@ pub fn phase_1_parse_input<'a>(sess: &'a Session, // memory, but they do not restore the initial state. syntax::ext::mtwt::reset_tables(); token::reset_ident_interner(); + let continue_after_error = sess.opts.continue_parse_after_error; + sess.diagnostic().set_continue_after_error(continue_after_error); let krate = time(sess.time_passes(), "parsing", || { match *input { @@ -442,6 +444,8 @@ pub fn phase_1_parse_input<'a>(sess: &'a Session, } })?; + sess.diagnostic().set_continue_after_error(true); + if sess.opts.debugging_opts.ast_json_noexpand { println!("{}", json::as_json(&krate)); } diff --git a/src/libsyntax/errors/mod.rs b/src/libsyntax/errors/mod.rs index 9e1cb60f54f67..c8c12d5a88334 100644 --- a/src/libsyntax/errors/mod.rs +++ b/src/libsyntax/errors/mod.rs @@ -370,6 +370,7 @@ pub struct Handler { emit: RefCell>, pub can_emit_warnings: bool, treat_err_as_bug: bool, + continue_after_error: Cell, delayed_span_bug: RefCell>, } @@ -392,10 +393,15 @@ impl Handler { emit: RefCell::new(e), can_emit_warnings: can_emit_warnings, treat_err_as_bug: treat_err_as_bug, + continue_after_error: Cell::new(true), delayed_span_bug: RefCell::new(None), } } + pub fn set_continue_after_error(&self, continue_after_error: bool) { + self.continue_after_error.set(continue_after_error); + } + pub fn struct_dummy<'a>(&'a self) -> DiagnosticBuilder<'a> { DiagnosticBuilder::new(&self.emit, Level::Cancelled, "") } @@ -612,6 +618,7 @@ impl Handler { lvl: Level) { if lvl == Warning && !self.can_emit_warnings { return } self.emit.borrow_mut().emit(msp, msg, None, lvl); + if !self.continue_after_error.get() { self.abort_if_errors(); } } pub fn emit_with_code(&self, msp: Option<&MultiSpan>, @@ -620,10 +627,12 @@ impl Handler { lvl: Level) { if lvl == Warning && !self.can_emit_warnings { return } self.emit.borrow_mut().emit(msp, msg, Some(code), lvl); + if !self.continue_after_error.get() { self.abort_if_errors(); } } pub fn custom_emit(&self, rsp: RenderSpan, msg: &str, lvl: Level) { if lvl == Warning && !self.can_emit_warnings { return } self.emit.borrow_mut().custom_emit(&rsp, msg, lvl); + if !self.continue_after_error.get() { self.abort_if_errors(); } } } From e1d8ad3fb0a1fc764bd2b117141ee94ef78460e6 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Sat, 26 Mar 2016 01:36:03 +0100 Subject: [PATCH 6/6] fix compile-fail and parse-fail tests by blindly opting back into parser recovery (so that expected errors match up) I'm opting into parser recovery in all these cases out of expediency, not because the error messages you get with recovery enabled are actually all that usable in all cases listed. --- src/test/compile-fail/issue-12560-2.rs | 2 ++ src/test/compile-fail/issue-28433.rs | 2 ++ src/test/compile-fail/issue-30715.rs | 2 ++ src/test/compile-fail/macro-incomplete-parse.rs | 2 ++ src/test/compile-fail/parse-error-correct.rs | 2 ++ src/test/compile-fail/parser-recovery-1.rs | 2 ++ src/test/compile-fail/parser-recovery-2.rs | 2 ++ src/test/compile-fail/self_type_keyword.rs | 2 ++ src/test/parse-fail/ascii-only-character-escape.rs | 2 +- src/test/parse-fail/bad-char-literals.rs | 2 +- src/test/parse-fail/bad-lit-suffixes.rs | 2 +- src/test/parse-fail/byte-literals.rs | 2 +- src/test/parse-fail/byte-string-literals.rs | 2 +- src/test/parse-fail/issue-10412.rs | 2 +- src/test/parse-fail/issue-23620-invalid-escapes.rs | 2 ++ src/test/parse-fail/lex-bad-binary-literal.rs | 2 ++ src/test/parse-fail/lex-bad-char-literals-1.rs | 2 +- src/test/parse-fail/lex-bad-numeric-literals.rs | 2 +- src/test/parse-fail/lex-bare-cr-string-literal-doc-comment.rs | 2 +- src/test/parse-fail/new-unicode-escapes-4.rs | 2 +- src/test/parse-fail/no-unsafe-self.rs | 2 +- 21 files changed, 31 insertions(+), 11 deletions(-) diff --git a/src/test/compile-fail/issue-12560-2.rs b/src/test/compile-fail/issue-12560-2.rs index 13829d73aadaa..9cbe2ebffe694 100644 --- a/src/test/compile-fail/issue-12560-2.rs +++ b/src/test/compile-fail/issue-12560-2.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// compile-flags: -Z continue-parse-after-error + // For style and consistency reasons, non-parametrized enum variants must // be used simply as `ident` instead of `ident ()`. // This test-case covers enum matching. diff --git a/src/test/compile-fail/issue-28433.rs b/src/test/compile-fail/issue-28433.rs index 3ca2213087d1f..018a40e28ef32 100644 --- a/src/test/compile-fail/issue-28433.rs +++ b/src/test/compile-fail/issue-28433.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// compile-flags: -Z continue-parse-after-error + enum bird { pub duck, //~^ ERROR: expected identifier, found keyword `pub` diff --git a/src/test/compile-fail/issue-30715.rs b/src/test/compile-fail/issue-30715.rs index 67f619b4de4f4..5cacf8f53c62e 100644 --- a/src/test/compile-fail/issue-30715.rs +++ b/src/test/compile-fail/issue-30715.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// compile-flags: -Z continue-parse-after-error + macro_rules! parallel { ( // If future has `pred`/`moelarry` fragments (where "pred" is diff --git a/src/test/compile-fail/macro-incomplete-parse.rs b/src/test/compile-fail/macro-incomplete-parse.rs index 364a7e9cf6d75..0d5f9079649c4 100644 --- a/src/test/compile-fail/macro-incomplete-parse.rs +++ b/src/test/compile-fail/macro-incomplete-parse.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// compile-flags: -Z continue-parse-after-error + macro_rules! ignored_item { () => { fn foo() {} diff --git a/src/test/compile-fail/parse-error-correct.rs b/src/test/compile-fail/parse-error-correct.rs index 7715ed41841cf..17b58a9f7c298 100644 --- a/src/test/compile-fail/parse-error-correct.rs +++ b/src/test/compile-fail/parse-error-correct.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// compile-flags: -Z continue-parse-after-error + // Test that the parser is error correcting missing idents. Despite a parsing // error (or two), we still run type checking (and don't get extra errors there). diff --git a/src/test/compile-fail/parser-recovery-1.rs b/src/test/compile-fail/parser-recovery-1.rs index 674418dcca6ad..85b6246123833 100644 --- a/src/test/compile-fail/parser-recovery-1.rs +++ b/src/test/compile-fail/parser-recovery-1.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// compile-flags: -Z continue-parse-after-error + // Test that we can recover from missing braces in the parser. trait Foo { diff --git a/src/test/compile-fail/parser-recovery-2.rs b/src/test/compile-fail/parser-recovery-2.rs index f1eb696f6ff84..109da6251e37d 100644 --- a/src/test/compile-fail/parser-recovery-2.rs +++ b/src/test/compile-fail/parser-recovery-2.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// compile-flags: -Z continue-parse-after-error + // Test that we can recover from mismatched braces in the parser. trait Foo { diff --git a/src/test/compile-fail/self_type_keyword.rs b/src/test/compile-fail/self_type_keyword.rs index e28197e81faf9..6296673787407 100644 --- a/src/test/compile-fail/self_type_keyword.rs +++ b/src/test/compile-fail/self_type_keyword.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// compile-flags: -Z continue-parse-after-error + struct Self; //~^ ERROR expected identifier, found keyword `Self` diff --git a/src/test/parse-fail/ascii-only-character-escape.rs b/src/test/parse-fail/ascii-only-character-escape.rs index 2094b63ab3688..a8c40225c3021 100644 --- a/src/test/parse-fail/ascii-only-character-escape.rs +++ b/src/test/parse-fail/ascii-only-character-escape.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags: -Z parse-only +// compile-flags: -Z parse-only -Z continue-parse-after-error fn main() { let x = "\x80"; //~ ERROR may only be used diff --git a/src/test/parse-fail/bad-char-literals.rs b/src/test/parse-fail/bad-char-literals.rs index fe8ed8bb9a52f..96311d6de176c 100644 --- a/src/test/parse-fail/bad-char-literals.rs +++ b/src/test/parse-fail/bad-char-literals.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags: -Z parse-only +// compile-flags: -Z parse-only -Z continue-parse-after-error // ignore-tidy-cr // ignore-tidy-tab diff --git a/src/test/parse-fail/bad-lit-suffixes.rs b/src/test/parse-fail/bad-lit-suffixes.rs index d5985fcebeb26..0811a6470247e 100644 --- a/src/test/parse-fail/bad-lit-suffixes.rs +++ b/src/test/parse-fail/bad-lit-suffixes.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags: -Z parse-only +// compile-flags: -Z parse-only -Z continue-parse-after-error extern diff --git a/src/test/parse-fail/byte-literals.rs b/src/test/parse-fail/byte-literals.rs index 3321f2450c188..3ecd7780afd84 100644 --- a/src/test/parse-fail/byte-literals.rs +++ b/src/test/parse-fail/byte-literals.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags: -Z parse-only +// compile-flags: -Z parse-only -Z continue-parse-after-error // ignore-tidy-tab diff --git a/src/test/parse-fail/byte-string-literals.rs b/src/test/parse-fail/byte-string-literals.rs index 22f123416f26e..4eba9e91ca5f4 100644 --- a/src/test/parse-fail/byte-string-literals.rs +++ b/src/test/parse-fail/byte-string-literals.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags: -Z parse-only +// compile-flags: -Z parse-only -Z continue-parse-after-error // ignore-tidy-tab diff --git a/src/test/parse-fail/issue-10412.rs b/src/test/parse-fail/issue-10412.rs index 0b9456bc080d9..b75e7b12bbdc9 100644 --- a/src/test/parse-fail/issue-10412.rs +++ b/src/test/parse-fail/issue-10412.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags: -Z parse-only +// compile-flags: -Z parse-only -Z continue-parse-after-error trait Serializable<'self, T> { //~ ERROR no longer a special lifetime diff --git a/src/test/parse-fail/issue-23620-invalid-escapes.rs b/src/test/parse-fail/issue-23620-invalid-escapes.rs index d2f78ef897b35..821149d1d0087 100644 --- a/src/test/parse-fail/issue-23620-invalid-escapes.rs +++ b/src/test/parse-fail/issue-23620-invalid-escapes.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// compile-flags: -Z parse-only -Z continue-parse-after-error + fn main() { let _ = b"\u{a66e}"; //~^ ERROR unicode escape sequences cannot be used as a byte or in a byte string diff --git a/src/test/parse-fail/lex-bad-binary-literal.rs b/src/test/parse-fail/lex-bad-binary-literal.rs index e92000c54ba34..caacb12d0082d 100644 --- a/src/test/parse-fail/lex-bad-binary-literal.rs +++ b/src/test/parse-fail/lex-bad-binary-literal.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// compile-flags: -Z parse-only -Z continue-parse-after-error + fn main() { 0b121; //~ ERROR invalid digit for a base 2 literal 0b10_10301; //~ ERROR invalid digit for a base 2 literal diff --git a/src/test/parse-fail/lex-bad-char-literals-1.rs b/src/test/parse-fail/lex-bad-char-literals-1.rs index 7e22a11ca970d..006e3e68d8f2d 100644 --- a/src/test/parse-fail/lex-bad-char-literals-1.rs +++ b/src/test/parse-fail/lex-bad-char-literals-1.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags: -Z parse-only +// compile-flags: -Z parse-only -Z continue-parse-after-error static c3: char = '\x1' //~ ERROR: numeric character escape is too short ; diff --git a/src/test/parse-fail/lex-bad-numeric-literals.rs b/src/test/parse-fail/lex-bad-numeric-literals.rs index cf171b694c377..bb97b037a0028 100644 --- a/src/test/parse-fail/lex-bad-numeric-literals.rs +++ b/src/test/parse-fail/lex-bad-numeric-literals.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags: -Z parse-only +// compile-flags: -Z parse-only -Z continue-parse-after-error fn main() { 0o1.0; //~ ERROR: octal float literal is not supported diff --git a/src/test/parse-fail/lex-bare-cr-string-literal-doc-comment.rs b/src/test/parse-fail/lex-bare-cr-string-literal-doc-comment.rs index aa48144650fed..f894305754319 100644 --- a/src/test/parse-fail/lex-bare-cr-string-literal-doc-comment.rs +++ b/src/test/parse-fail/lex-bare-cr-string-literal-doc-comment.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags: -Z parse-only +// compile-flags: -Z parse-only -Z continue-parse-after-error // ignore-tidy-cr diff --git a/src/test/parse-fail/new-unicode-escapes-4.rs b/src/test/parse-fail/new-unicode-escapes-4.rs index fe125da1755bd..5615ac8df017d 100644 --- a/src/test/parse-fail/new-unicode-escapes-4.rs +++ b/src/test/parse-fail/new-unicode-escapes-4.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags: -Z parse-only +// compile-flags: -Z parse-only -Z continue-parse-after-error pub fn main() { let s = "\u{lol}"; diff --git a/src/test/parse-fail/no-unsafe-self.rs b/src/test/parse-fail/no-unsafe-self.rs index 1cc0e62f5b2d5..cbdf50a7521ac 100644 --- a/src/test/parse-fail/no-unsafe-self.rs +++ b/src/test/parse-fail/no-unsafe-self.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags: -Z parse-only +// compile-flags: -Z parse-only -Z continue-parse-after-error trait A { fn foo(*mut self); //~ ERROR cannot pass self by raw pointer