From 8854164d0cda3c90f6c3c774d8acf891599e4da3 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Thu, 13 Apr 2017 16:40:03 +0300 Subject: [PATCH 1/3] rustc_const_eval: move ConstEvalErr to the rustc crate. --- src/Cargo.lock | 2 - src/librustc/diagnostics.rs | 19 +++ src/librustc/middle/const_val.rs | 164 ++++++++++++++++++++++- src/librustc/ty/maps.rs | 4 +- src/librustc_const_eval/Cargo.toml | 1 - src/librustc_const_eval/check_match.rs | 32 ++--- src/librustc_const_eval/diagnostics.rs | 19 --- src/librustc_const_eval/eval.rs | 176 +------------------------ src/librustc_const_eval/lib.rs | 1 - src/librustc_const_eval/pattern.rs | 4 +- src/librustc_metadata/decoder.rs | 3 +- src/librustc_mir/hair/cx/expr.rs | 4 +- src/librustc_mir/hair/cx/mod.rs | 17 ++- src/librustc_passes/consts.rs | 9 +- src/librustc_trans/Cargo.toml | 1 - src/librustc_trans/consts.rs | 2 +- src/librustc_trans/lib.rs | 1 - src/librustc_trans/mir/block.rs | 5 +- src/librustc_trans/mir/constant.rs | 7 +- src/librustc_trans/trans_item.rs | 5 +- src/librustc_typeck/collect.rs | 21 ++- 21 files changed, 242 insertions(+), 255 deletions(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index 1fa256197ce52..c4b5366d4a324 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -503,7 +503,6 @@ name = "rustc_const_eval" version = "0.0.0" dependencies = [ "arena 0.0.0", - "graphviz 0.0.0", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", "rustc_back 0.0.0", @@ -731,7 +730,6 @@ dependencies = [ "rustc 0.0.0", "rustc_back 0.0.0", "rustc_bitflags 0.0.0", - "rustc_const_eval 0.0.0", "rustc_const_math 0.0.0", "rustc_data_structures 0.0.0", "rustc_errors 0.0.0", diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs index 5a0fbf8efb707..8a391f9cde3a3 100644 --- a/src/librustc/diagnostics.rs +++ b/src/librustc/diagnostics.rs @@ -327,6 +327,25 @@ struct ListNode { This works because `Box` is a pointer, so its size is well-known. "##, +E0080: r##" +This error indicates that the compiler was unable to sensibly evaluate an +constant expression that had to be evaluated. Attempting to divide by 0 +or causing integer overflow are two ways to induce this error. For example: + +```compile_fail,E0080 +enum Enum { + X = (1 << 500), + Y = (1 / 0) +} +``` + +Ensure that the expressions given can be evaluated as the desired integer type. +See the FFI section of the Reference for more information about using a custom +integer type: + +https://doc.rust-lang.org/reference.html#ffi-attributes +"##, + E0106: r##" This error indicates that a lifetime is missing from a type. If it is an error inside a function signature, the problem may be with failing to adhere to the diff --git a/src/librustc/middle/const_val.rs b/src/librustc/middle/const_val.rs index d81f89827d938..9315f7f58081a 100644 --- a/src/librustc/middle/const_val.rs +++ b/src/librustc/middle/const_val.rs @@ -8,17 +8,25 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use syntax::symbol::InternedString; -use syntax::ast; -use std::rc::Rc; +use self::ConstVal::*; +pub use rustc_const_math::ConstInt; + use hir::def_id::DefId; +use ty::TyCtxt; use ty::subst::Substs; use rustc_const_math::*; -use self::ConstVal::*; -pub use rustc_const_math::ConstInt; +use graphviz::IntoCow; +use errors::DiagnosticBuilder; +use syntax::symbol::InternedString; +use syntax::ast; +use syntax_pos::Span; +use std::borrow::Cow; use std::collections::BTreeMap; +use std::rc::Rc; + +pub type EvalResult<'tcx> = Result, ConstEvalErr<'tcx>>; #[derive(Clone, Debug, Hash, RustcEncodable, RustcDecodable, Eq, PartialEq)] pub enum ConstVal<'tcx> { @@ -61,3 +69,149 @@ impl<'tcx> ConstVal<'tcx> { } } } + +#[derive(Clone, Debug)] +pub struct ConstEvalErr<'tcx> { + pub span: Span, + pub kind: ErrKind<'tcx>, +} + +#[derive(Clone, Debug)] +pub enum ErrKind<'tcx> { + CannotCast, + MissingStructField, + NegateOn(ConstVal<'tcx>), + NotOn(ConstVal<'tcx>), + CallOn(ConstVal<'tcx>), + + NonConstPath, + UnimplementedConstVal(&'static str), + ExpectedConstTuple, + ExpectedConstStruct, + IndexedNonVec, + IndexNotUsize, + IndexOutOfBounds { len: u64, index: u64 }, + + MiscBinaryOp, + MiscCatchAll, + + IndexOpFeatureGated, + Math(ConstMathErr), + + ErroneousReferencedConstant(Box>), + + TypeckError +} + +impl<'tcx> From for ErrKind<'tcx> { + fn from(err: ConstMathErr) -> ErrKind<'tcx> { + match err { + ConstMathErr::UnsignedNegation => ErrKind::TypeckError, + _ => ErrKind::Math(err) + } + } +} + +#[derive(Clone, Debug)] +pub enum ConstEvalErrDescription<'a> { + Simple(Cow<'a, str>), +} + +impl<'a> ConstEvalErrDescription<'a> { + /// Return a one-line description of the error, for lints and such + pub fn into_oneline(self) -> Cow<'a, str> { + match self { + ConstEvalErrDescription::Simple(simple) => simple, + } + } +} + +impl<'a, 'gcx, 'tcx> ConstEvalErr<'tcx> { + pub fn description(&self) -> ConstEvalErrDescription { + use self::ErrKind::*; + use self::ConstEvalErrDescription::*; + + macro_rules! simple { + ($msg:expr) => ({ Simple($msg.into_cow()) }); + ($fmt:expr, $($arg:tt)+) => ({ + Simple(format!($fmt, $($arg)+).into_cow()) + }) + } + + match self.kind { + CannotCast => simple!("can't cast this type"), + NegateOn(ref const_val) => simple!("negate on {}", const_val.description()), + NotOn(ref const_val) => simple!("not on {}", const_val.description()), + CallOn(ref const_val) => simple!("call on {}", const_val.description()), + + MissingStructField => simple!("nonexistent struct field"), + NonConstPath => simple!("non-constant path in constant expression"), + UnimplementedConstVal(what) => + simple!("unimplemented constant expression: {}", what), + ExpectedConstTuple => simple!("expected constant tuple"), + ExpectedConstStruct => simple!("expected constant struct"), + IndexedNonVec => simple!("indexing is only supported for arrays"), + IndexNotUsize => simple!("indices must be of type `usize`"), + IndexOutOfBounds { len, index } => { + simple!("index out of bounds: the len is {} but the index is {}", + len, index) + } + + MiscBinaryOp => simple!("bad operands for binary"), + MiscCatchAll => simple!("unsupported constant expr"), + IndexOpFeatureGated => simple!("the index operation on const values is unstable"), + Math(ref err) => Simple(err.description().into_cow()), + + ErroneousReferencedConstant(_) => simple!("could not evaluate referenced constant"), + + TypeckError => simple!("type-checking failed"), + } + } + + pub fn struct_error(&self, + tcx: TyCtxt<'a, 'gcx, 'tcx>, + primary_span: Span, + primary_kind: &str) + -> DiagnosticBuilder<'gcx> + { + let mut err = self; + while let &ConstEvalErr { + kind: ErrKind::ErroneousReferencedConstant(box ref i_err), .. + } = err { + err = i_err; + } + + let mut diag = struct_span_err!(tcx.sess, err.span, E0080, "constant evaluation error"); + err.note(tcx, primary_span, primary_kind, &mut diag); + diag + } + + pub fn note(&self, + _tcx: TyCtxt<'a, 'gcx, 'tcx>, + primary_span: Span, + primary_kind: &str, + diag: &mut DiagnosticBuilder) + { + match self.description() { + ConstEvalErrDescription::Simple(message) => { + diag.span_label(self.span, &message); + } + } + + if !primary_span.contains(self.span) { + diag.span_note(primary_span, + &format!("for {} here", primary_kind)); + } + } + + pub fn report(&self, + tcx: TyCtxt<'a, 'gcx, 'tcx>, + primary_span: Span, + primary_kind: &str) + { + if let ErrKind::TypeckError = self.kind { + return; + } + self.struct_error(tcx, primary_span, primary_kind).emit(); + } +} diff --git a/src/librustc/ty/maps.rs b/src/librustc/ty/maps.rs index 868ccad8a3a90..e9eb5e97582bf 100644 --- a/src/librustc/ty/maps.rs +++ b/src/librustc/ty/maps.rs @@ -10,7 +10,7 @@ use dep_graph::{DepGraph, DepNode, DepTrackingMap, DepTrackingMapConfig}; use hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; -use middle::const_val::ConstVal; +use middle::const_val; use middle::privacy::AccessLevels; use mir; use session::CompileResult; @@ -443,7 +443,7 @@ define_maps! { <'tcx> /// Results of evaluating monomorphic constants embedded in /// other items, such as enum variant explicit discriminants. - pub monomorphic_const_eval: MonomorphicConstEval(DefId) -> Result, ()>, + pub monomorphic_const_eval: MonomorphicConstEval(DefId) -> const_val::EvalResult<'tcx>, /// Performs the privacy check and computes "access levels". pub privacy_access_levels: PrivacyAccessLevels(CrateNum) -> Rc, diff --git a/src/librustc_const_eval/Cargo.toml b/src/librustc_const_eval/Cargo.toml index 907410f74dca4..bbc6148082494 100644 --- a/src/librustc_const_eval/Cargo.toml +++ b/src/librustc_const_eval/Cargo.toml @@ -17,5 +17,4 @@ rustc_const_math = { path = "../librustc_const_math" } rustc_data_structures = { path = "../librustc_data_structures" } rustc_errors = { path = "../librustc_errors" } syntax = { path = "../libsyntax" } -graphviz = { path = "../libgraphviz" } syntax_pos = { path = "../libsyntax_pos" } diff --git a/src/librustc_const_eval/check_match.rs b/src/librustc_const_eval/check_match.rs index 9d55281d019d9..f1ab6a00aa2ef 100644 --- a/src/librustc_const_eval/check_match.rs +++ b/src/librustc_const_eval/check_match.rs @@ -14,8 +14,6 @@ use _match::WitnessPreference::*; use pattern::{Pattern, PatternContext, PatternError, PatternKind}; -use eval::report_const_eval_err; - use rustc::dep_graph::DepNode; use rustc::middle::expr_use_visitor::{ConsumeMode, Delegate, ExprUseVisitor}; @@ -108,27 +106,29 @@ impl<'a, 'tcx> Visitor<'tcx> for MatchVisitor<'a, 'tcx> { } } -impl<'a, 'tcx> MatchVisitor<'a, 'tcx> { - fn check_patterns(&self, has_guard: bool, pats: &[P]) { - check_legality_of_move_bindings(self, has_guard, pats); - for pat in pats { - check_legality_of_bindings_in_at_patterns(self, pat); - } - } - - fn report_inlining_errors(&self, patcx: PatternContext, pat_span: Span) { - for error in patcx.errors { - match error { +impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> { + fn report_inlining_errors(&self, pat_span: Span) { + for error in &self.errors { + match *error { PatternError::StaticInPattern(span) => { span_err!(self.tcx.sess, span, E0158, "statics cannot be referenced in patterns"); } - PatternError::ConstEval(err) => { - report_const_eval_err(self.tcx, &err, pat_span, "pattern"); + PatternError::ConstEval(ref err) => { + err.report(self.tcx, pat_span, "pattern"); } } } } +} + +impl<'a, 'tcx> MatchVisitor<'a, 'tcx> { + fn check_patterns(&self, has_guard: bool, pats: &[P]) { + check_legality_of_move_bindings(self, has_guard, pats); + for pat in pats { + check_legality_of_bindings_in_at_patterns(self, pat); + } + } fn check_match( &self, @@ -161,7 +161,7 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> { let mut patcx = PatternContext::new(self.tcx, self.tables); let pattern = expand_pattern(cx, patcx.lower_pattern(&pat)); if !patcx.errors.is_empty() { - self.report_inlining_errors(patcx, pat.span); + patcx.report_inlining_errors(pat.span); have_errors = true; } (pattern, &**pat) diff --git a/src/librustc_const_eval/diagnostics.rs b/src/librustc_const_eval/diagnostics.rs index 60eef8dd3bc5f..04fc3e68c8ccd 100644 --- a/src/librustc_const_eval/diagnostics.rs +++ b/src/librustc_const_eval/diagnostics.rs @@ -557,25 +557,6 @@ The `op_string_ref` binding has type `&Option<&String>` in both cases. See also https://github.com/rust-lang/rust/issues/14587 "##, -E0080: r##" -This error indicates that the compiler was unable to sensibly evaluate an -constant expression that had to be evaluated. Attempting to divide by 0 -or causing integer overflow are two ways to induce this error. For example: - -```compile_fail,E0080 -enum Enum { - X = (1 << 500), - Y = (1 / 0) -} -``` - -Ensure that the expressions given can be evaluated as the desired integer type. -See the FFI section of the Reference for more information about using a custom -integer type: - -https://doc.rust-lang.org/reference.html#ffi-attributes -"##, - } diff --git a/src/librustc_const_eval/eval.rs b/src/librustc_const_eval/eval.rs index 54f5cff16ed6c..b928bae620b6c 100644 --- a/src/librustc_const_eval/eval.rs +++ b/src/librustc_const_eval/eval.rs @@ -9,8 +9,8 @@ // except according to those terms. use rustc::middle::const_val::ConstVal::*; -use rustc::middle::const_val::ConstVal; -use self::ErrKind::*; +use rustc::middle::const_val::ErrKind::*; +use rustc::middle::const_val::{ConstVal, ConstEvalErr, EvalResult, ErrKind}; use rustc::hir::map as hir_map; use rustc::hir::map::blocks::FnLikeNode; @@ -24,16 +24,13 @@ use rustc::traits::Reveal; use rustc::util::common::ErrorReported; use rustc::util::nodemap::DefIdMap; -use graphviz::IntoCow; use syntax::ast; use rustc::hir::{self, Expr}; use syntax_pos::{Span, DUMMY_SP}; -use std::borrow::Cow; use std::cmp::Ordering; use rustc_const_math::*; -use rustc_errors::DiagnosticBuilder; macro_rules! signal { ($e:expr, $exn:expr) => { @@ -158,66 +155,6 @@ fn lookup_const_fn_by_id<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) } } -fn build_const_eval_err<'a, 'tcx>( - tcx: TyCtxt<'a, 'tcx, 'tcx>, - err: &ConstEvalErr, - primary_span: Span, - primary_kind: &str) - -> DiagnosticBuilder<'tcx> -{ - let mut err = err; - while let &ConstEvalErr { kind: ErroneousReferencedConstant(box ref i_err), .. } = err { - err = i_err; - } - - let mut diag = struct_span_err!(tcx.sess, err.span, E0080, "constant evaluation error"); - note_const_eval_err(tcx, err, primary_span, primary_kind, &mut diag); - diag -} - -pub fn report_const_eval_err<'a, 'tcx>( - tcx: TyCtxt<'a, 'tcx, 'tcx>, - err: &ConstEvalErr, - primary_span: Span, - primary_kind: &str) -{ - if let TypeckError = err.kind { - return; - } - build_const_eval_err(tcx, err, primary_span, primary_kind).emit(); -} - -pub fn fatal_const_eval_err<'a, 'tcx>( - tcx: TyCtxt<'a, 'tcx, 'tcx>, - err: &ConstEvalErr, - primary_span: Span, - primary_kind: &str) - -> ! -{ - report_const_eval_err(tcx, err, primary_span, primary_kind); - tcx.sess.abort_if_errors(); - unreachable!() -} - -pub fn note_const_eval_err<'a, 'tcx>( - _tcx: TyCtxt<'a, 'tcx, 'tcx>, - err: &ConstEvalErr, - primary_span: Span, - primary_kind: &str, - diag: &mut DiagnosticBuilder) -{ - match err.description() { - ConstEvalErrDescription::Simple(message) => { - diag.span_label(err.span, &message); - } - } - - if !primary_span.contains(err.span) { - diag.span_note(primary_span, - &format!("for {} here", primary_kind)); - } -} - pub struct ConstContext<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx>, tables: &'a ty::TypeckTables<'tcx>, @@ -251,107 +188,7 @@ impl<'a, 'tcx> ConstContext<'a, 'tcx> { } } -#[derive(Clone, Debug)] -pub struct ConstEvalErr<'tcx> { - pub span: Span, - pub kind: ErrKind<'tcx>, -} - -#[derive(Clone, Debug)] -pub enum ErrKind<'tcx> { - CannotCast, - MissingStructField, - NegateOn(ConstVal<'tcx>), - NotOn(ConstVal<'tcx>), - CallOn(ConstVal<'tcx>), - - NonConstPath, - UnimplementedConstVal(&'static str), - ExpectedConstTuple, - ExpectedConstStruct, - IndexedNonVec, - IndexNotUsize, - IndexOutOfBounds { len: u64, index: u64 }, - - MiscBinaryOp, - MiscCatchAll, - - IndexOpFeatureGated, - Math(ConstMathErr), - - ErroneousReferencedConstant(Box>), - - TypeckError -} - -impl<'tcx> From for ErrKind<'tcx> { - fn from(err: ConstMathErr) -> ErrKind<'tcx> { - match err { - ConstMathErr::UnsignedNegation => TypeckError, - _ => Math(err) - } - } -} - -#[derive(Clone, Debug)] -pub enum ConstEvalErrDescription<'a> { - Simple(Cow<'a, str>), -} - -impl<'a> ConstEvalErrDescription<'a> { - /// Return a one-line description of the error, for lints and such - pub fn into_oneline(self) -> Cow<'a, str> { - match self { - ConstEvalErrDescription::Simple(simple) => simple, - } - } -} - -impl<'tcx> ConstEvalErr<'tcx> { - pub fn description(&self) -> ConstEvalErrDescription { - use self::ErrKind::*; - use self::ConstEvalErrDescription::*; - - macro_rules! simple { - ($msg:expr) => ({ Simple($msg.into_cow()) }); - ($fmt:expr, $($arg:tt)+) => ({ - Simple(format!($fmt, $($arg)+).into_cow()) - }) - } - - match self.kind { - CannotCast => simple!("can't cast this type"), - NegateOn(ref const_val) => simple!("negate on {}", const_val.description()), - NotOn(ref const_val) => simple!("not on {}", const_val.description()), - CallOn(ref const_val) => simple!("call on {}", const_val.description()), - - MissingStructField => simple!("nonexistent struct field"), - NonConstPath => simple!("non-constant path in constant expression"), - UnimplementedConstVal(what) => - simple!("unimplemented constant expression: {}", what), - ExpectedConstTuple => simple!("expected constant tuple"), - ExpectedConstStruct => simple!("expected constant struct"), - IndexedNonVec => simple!("indexing is only supported for arrays"), - IndexNotUsize => simple!("indices must be of type `usize`"), - IndexOutOfBounds { len, index } => { - simple!("index out of bounds: the len is {} but the index is {}", - len, index) - } - - MiscBinaryOp => simple!("bad operands for binary"), - MiscCatchAll => simple!("unsupported constant expr"), - IndexOpFeatureGated => simple!("the index operation on const values is unstable"), - Math(ref err) => Simple(err.description().into_cow()), - - ErroneousReferencedConstant(_) => simple!("could not evaluate referenced constant"), - - TypeckError => simple!("type-checking failed"), - } - } -} - -pub type EvalResult<'tcx> = Result, ConstEvalErr<'tcx>>; -pub type CastResult<'tcx> = Result, ErrKind<'tcx>>; +type CastResult<'tcx> = Result, ErrKind<'tcx>>; fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>, e: &Expr) -> EvalResult<'tcx> { @@ -947,14 +784,14 @@ impl<'a, 'tcx> ConstContext<'a, 'tcx> { let a = match self.eval(a) { Ok(a) => a, Err(e) => { - report_const_eval_err(tcx, &e, a.span, "expression"); + e.report(tcx, a.span, "expression"); return Err(ErrorReported); } }; let b = match self.eval(b) { Ok(b) => b, Err(e) => { - report_const_eval_err(tcx, &e, b.span, "expression"); + e.report(tcx, b.span, "expression"); return Err(ErrorReported); } }; @@ -979,8 +816,7 @@ pub fn eval_length<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, Ok(_) | Err(ConstEvalErr { kind: TypeckError, .. }) => Err(ErrorReported), Err(err) => { - let mut diag = build_const_eval_err( - tcx, &err, count_expr.span, reason); + let mut diag = err.struct_error(tcx, count_expr.span, reason); if let hir::ExprPath(hir::QPath::Resolved(None, ref path)) = count_expr.node { if let Def::Local(..) = path.def { diff --git a/src/librustc_const_eval/lib.rs b/src/librustc_const_eval/lib.rs index 4434a901f9412..fa3161a860498 100644 --- a/src/librustc_const_eval/lib.rs +++ b/src/librustc_const_eval/lib.rs @@ -40,7 +40,6 @@ extern crate rustc_back; extern crate rustc_const_math; extern crate rustc_data_structures; extern crate rustc_errors; -extern crate graphviz; extern crate syntax_pos; // NB: This module needs to be declared first so diagnostics are diff --git a/src/librustc_const_eval/pattern.rs b/src/librustc_const_eval/pattern.rs index bd67dd2e6b25d..f20fa27dc2251 100644 --- a/src/librustc_const_eval/pattern.rs +++ b/src/librustc_const_eval/pattern.rs @@ -11,7 +11,7 @@ use eval; use rustc::lint; -use rustc::middle::const_val::ConstVal; +use rustc::middle::const_val::{ConstEvalErr, ConstVal}; use rustc::mir::{Field, BorrowKind, Mutability}; use rustc::ty::{self, TyCtxt, AdtDef, Ty, TypeVariants, Region}; use rustc::ty::subst::{Substs, Kind}; @@ -29,7 +29,7 @@ use syntax_pos::Span; #[derive(Clone, Debug)] pub enum PatternError<'tcx> { StaticInPattern(Span), - ConstEval(eval::ConstEvalErr<'tcx>), + ConstEval(ConstEvalErr<'tcx>), } #[derive(Copy, Clone, Debug)] diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 3498be9dfdf32..d2512ff602a84 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -524,7 +524,8 @@ impl<'a, 'tcx> CrateMetadata { }; if let ty::VariantDiscr::Explicit(def_id) = data.discr { - let result = data.evaluated_discr.map_or(Err(()), Ok); + // The original crate wouldn't have compiled if this is missing. + let result = Ok(data.evaluated_discr.unwrap()); tcx.maps.monomorphic_const_eval.borrow_mut().insert(def_id, result); } diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index d9b8d04ad386f..595748c8c6fdc 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -17,7 +17,7 @@ use hair::cx::to_ref::ToRef; use rustc::hir::map; use rustc::hir::def::{Def, CtorKind}; use rustc::middle::const_val::ConstVal; -use rustc_const_eval::{ConstContext, fatal_const_eval_err}; +use rustc_const_eval::ConstContext; use rustc::ty::{self, AdtKind, VariantDef, Ty}; use rustc::ty::cast::CastKind as TyCastKind; use rustc::hir; @@ -597,7 +597,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, let count = match ConstContext::new(tcx, count).eval(c) { Ok(ConstVal::Integral(ConstInt::Usize(u))) => u, Ok(other) => bug!("constant evaluation of repeat count yielded {:?}", other), - Err(s) => fatal_const_eval_err(tcx, &s, c.span, "expression") + Err(s) => cx.fatal_const_eval_err(&s, c.span, "expression") }; ExprKind::Repeat { diff --git a/src/librustc_mir/hair/cx/mod.rs b/src/librustc_mir/hair/cx/mod.rs index 3eef5d83b8ba0..5f9fb8e1b120f 100644 --- a/src/librustc_mir/hair/cx/mod.rs +++ b/src/librustc_mir/hair/cx/mod.rs @@ -17,8 +17,8 @@ use hair::*; use rustc::mir::transform::MirSource; -use rustc::middle::const_val::ConstVal; -use rustc_const_eval::{ConstContext, fatal_const_eval_err}; +use rustc::middle::const_val::{ConstEvalErr, ConstVal}; +use rustc_const_eval::ConstContext; use rustc_data_structures::indexed_vec::Idx; use rustc::hir::def_id::DefId; use rustc::hir::map::blocks::FnLikeNode; @@ -115,10 +115,21 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> { let tcx = self.tcx.global_tcx(); match ConstContext::with_tables(tcx, self.tables()).eval(e) { Ok(value) => Literal::Value { value: value }, - Err(s) => fatal_const_eval_err(tcx, &s, e.span, "expression") + Err(s) => self.fatal_const_eval_err(&s, e.span, "expression") } } + pub fn fatal_const_eval_err(&self, + err: &ConstEvalErr<'tcx>, + primary_span: Span, + primary_kind: &str) + -> ! + { + err.report(self.tcx, primary_span, primary_kind); + self.tcx.sess.abort_if_errors(); + unreachable!() + } + pub fn trait_method(&mut self, trait_def_id: DefId, method_name: &str, diff --git a/src/librustc_passes/consts.rs b/src/librustc_passes/consts.rs index 930a13e36bdca..44d3026d80c3e 100644 --- a/src/librustc_passes/consts.rs +++ b/src/librustc_passes/consts.rs @@ -26,10 +26,11 @@ use rustc::dep_graph::DepNode; use rustc::ty::cast::CastKind; -use rustc_const_eval::{ConstEvalErr, ConstContext}; -use rustc_const_eval::ErrKind::{IndexOpFeatureGated, UnimplementedConstVal, MiscCatchAll, Math}; -use rustc_const_eval::ErrKind::{ErroneousReferencedConstant, MiscBinaryOp, NonConstPath}; -use rustc_const_eval::ErrKind::{TypeckError}; +use rustc_const_eval::ConstContext; +use rustc::middle::const_val::ConstEvalErr; +use rustc::middle::const_val::ErrKind::{IndexOpFeatureGated, UnimplementedConstVal, MiscCatchAll}; +use rustc::middle::const_val::ErrKind::{ErroneousReferencedConstant, MiscBinaryOp, NonConstPath}; +use rustc::middle::const_val::ErrKind::{TypeckError, Math}; use rustc_const_math::{ConstMathErr, Op}; use rustc::hir::def::{Def, CtorKind}; use rustc::hir::def_id::DefId; diff --git a/src/librustc_trans/Cargo.toml b/src/librustc_trans/Cargo.toml index 07dcb2fc29dc6..af477f5a15217 100644 --- a/src/librustc_trans/Cargo.toml +++ b/src/librustc_trans/Cargo.toml @@ -15,7 +15,6 @@ log = "0.3" 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_data_structures = { path = "../librustc_data_structures" } rustc_errors = { path = "../librustc_errors" } diff --git a/src/librustc_trans/consts.rs b/src/librustc_trans/consts.rs index 6b6fa538dc03b..7a53a03344fcb 100644 --- a/src/librustc_trans/consts.rs +++ b/src/librustc_trans/consts.rs @@ -13,9 +13,9 @@ use back::symbol_names; use llvm; use llvm::{SetUnnamedAddr}; use llvm::{ValueRef, True}; -use rustc_const_eval::ConstEvalErr; use rustc::hir::def_id::DefId; use rustc::hir::map as hir_map; +use rustc::middle::const_val::ConstEvalErr; use {debuginfo, machine}; use base; use trans_item::TransItem; diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs index abda358bc4f87..c5383fceb8787 100644 --- a/src/librustc_trans/lib.rs +++ b/src/librustc_trans/lib.rs @@ -51,7 +51,6 @@ extern crate rustc_incremental; pub extern crate rustc_llvm as llvm; extern crate rustc_platform_intrinsics as intrinsics; extern crate rustc_const_math; -extern crate rustc_const_eval; #[macro_use] #[no_link] extern crate rustc_bitflags; diff --git a/src/librustc_trans/mir/block.rs b/src/librustc_trans/mir/block.rs index caec4789eddce..0976859e27f44 100644 --- a/src/librustc_trans/mir/block.rs +++ b/src/librustc_trans/mir/block.rs @@ -9,9 +9,8 @@ // except according to those terms. use llvm::{self, ValueRef, BasicBlockRef}; -use rustc_const_eval::{ErrKind, ConstEvalErr, note_const_eval_err}; use rustc::middle::lang_items; -use rustc::middle::const_val::ConstInt; +use rustc::middle::const_val::{ConstEvalErr, ConstInt, ErrKind}; use rustc::ty::{self, TypeFoldable}; use rustc::ty::layout::{self, LayoutTyper}; use rustc::mir; @@ -363,7 +362,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> { let err = ConstEvalErr{ span: span, kind: err }; let mut diag = bcx.tcx().sess.struct_span_warn( span, "this expression will panic at run-time"); - note_const_eval_err(bcx.tcx(), &err, span, "expression", &mut diag); + err.note(bcx.tcx(), span, "expression", &mut diag); diag.emit(); } } diff --git a/src/librustc_trans/mir/constant.rs b/src/librustc_trans/mir/constant.rs index 4d5b691c86ebb..37d2b1952f494 100644 --- a/src/librustc_trans/mir/constant.rs +++ b/src/librustc_trans/mir/constant.rs @@ -9,8 +9,7 @@ // except according to those terms. use llvm::{self, ValueRef}; -use rustc::middle::const_val::ConstVal; -use rustc_const_eval::{ErrKind, ConstEvalErr, report_const_eval_err}; +use rustc::middle::const_val::{ConstEvalErr, ConstVal, ErrKind}; use rustc_const_math::ConstInt::*; use rustc_const_math::ConstFloat::*; use rustc_const_math::{ConstInt, ConstMathErr}; @@ -327,8 +326,8 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> { } }; - let err = ConstEvalErr{ span: span, kind: err }; - report_const_eval_err(tcx, &err, span, "expression"); + let err = ConstEvalErr { span: span, kind: err }; + err.report(tcx, span, "expression"); failure = Err(err); } target diff --git a/src/librustc_trans/trans_item.rs b/src/librustc_trans/trans_item.rs index f5556bb8382f6..4d908f3c94fa5 100644 --- a/src/librustc_trans/trans_item.rs +++ b/src/librustc_trans/trans_item.rs @@ -28,7 +28,6 @@ use rustc::hir; use rustc::hir::def_id::DefId; use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; use rustc::ty::subst::Substs; -use rustc_const_eval::fatal_const_eval_err; use syntax::ast::{self, NodeId}; use syntax::attr; use type_of; @@ -82,9 +81,7 @@ impl<'a, 'tcx> TransItem<'tcx> { match consts::trans_static(&ccx, m, item.id, &item.attrs) { Ok(_) => { /* Cool, everything's alright. */ }, Err(err) => { - // FIXME: shouldn't this be a `span_err`? - fatal_const_eval_err( - ccx.tcx(), &err, item.span, "static"); + err.report(ccx.tcx(), item.span, "static"); } }; } else { diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 649353d52f6aa..4c7979ea3765c 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -59,7 +59,7 @@ use constrained_type_params as ctp; use middle::lang_items::SizedTraitLangItem; use middle::const_val::ConstVal; use middle::resolve_lifetime as rl; -use rustc_const_eval::{ConstContext, report_const_eval_err}; +use rustc_const_eval::ConstContext; use rustc::ty::subst::Substs; use rustc::ty::{ToPredicate, ReprOptions}; use rustc::ty::{self, AdtKind, ToPolyTraitRef, Ty, TyCtxt}; @@ -587,17 +587,6 @@ fn convert_variant_ctor<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, tcx.item_predicates(def_id); } -fn evaluate_disr_expr<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - body: hir::BodyId) - -> Result, ()> { - let e = &tcx.hir.body(body).value; - ConstContext::new(tcx, body).eval(e).map_err(|err| { - // enum variant evaluation happens before the global constant check - // so we need to report the real error - report_const_eval_err(tcx, &err, e.span, "enum discriminant"); - }) -} - fn convert_enum_variant_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId, variants: &[hir::Variant]) { @@ -612,9 +601,15 @@ fn convert_enum_variant_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, prev_discr = Some(if let Some(e) = variant.node.disr_expr { let expr_did = tcx.hir.local_def_id(e.node_id); let result = tcx.maps.monomorphic_const_eval.memoize(expr_did, || { - evaluate_disr_expr(tcx, e) + ConstContext::new(tcx, e).eval(&tcx.hir.body(e).value) }); + // enum variant evaluation happens before the global constant check + // so we need to report the real error + if let Err(ref err) = result { + err.report(tcx, variant.span, "enum discriminant"); + } + match result { Ok(ConstVal::Integral(x)) => Some(x), _ => None From 63064ec190fef7947c3eabfcdfeaeb293c9a91dd Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Fri, 14 Apr 2017 19:00:08 +0300 Subject: [PATCH 2/3] rustc: expose monomorphic const_eval through on-demand. --- src/Cargo.lock | 2 -- src/librustc/middle/const_val.rs | 37 +++++++++++++++++++++++- src/librustc_const_eval/eval.rs | 49 ++++++++++---------------------- src/librustc_driver/driver.rs | 3 +- src/librustc_mir/hair/cx/expr.rs | 5 ++-- src/librustc_typeck/Cargo.toml | 1 - src/librustc_typeck/astconv.rs | 4 +-- src/librustc_typeck/check/mod.rs | 4 +-- src/librustc_typeck/collect.rs | 6 +--- src/librustc_typeck/lib.rs | 1 - src/librustdoc/Cargo.toml | 1 - src/librustdoc/clean/mod.rs | 2 +- src/librustdoc/lib.rs | 1 - 13 files changed, 61 insertions(+), 55 deletions(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index c4b5366d4a324..62b853480394f 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -760,7 +760,6 @@ dependencies = [ "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", "rustc_back 0.0.0", - "rustc_const_eval 0.0.0", "rustc_const_math 0.0.0", "rustc_data_structures 0.0.0", "rustc_errors 0.0.0", @@ -781,7 +780,6 @@ dependencies = [ "pulldown-cmark 0.0.14 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", "rustc_back 0.0.0", - "rustc_const_eval 0.0.0", "rustc_data_structures 0.0.0", "rustc_driver 0.0.0", "rustc_errors 0.0.0", diff --git a/src/librustc/middle/const_val.rs b/src/librustc/middle/const_val.rs index 9315f7f58081a..b4c5af9401944 100644 --- a/src/librustc/middle/const_val.rs +++ b/src/librustc/middle/const_val.rs @@ -11,9 +11,12 @@ use self::ConstVal::*; pub use rustc_const_math::ConstInt; +use hir; +use hir::def::Def; use hir::def_id::DefId; -use ty::TyCtxt; +use ty::{self, TyCtxt}; use ty::subst::Substs; +use util::common::ErrorReported; use rustc_const_math::*; use graphviz::IntoCow; @@ -215,3 +218,35 @@ impl<'a, 'gcx, 'tcx> ConstEvalErr<'tcx> { self.struct_error(tcx, primary_span, primary_kind).emit(); } } + +/// Returns the value of the length-valued expression +pub fn eval_length(tcx: TyCtxt, + count: hir::BodyId, + reason: &str) + -> Result +{ + let count_expr = &tcx.hir.body(count).value; + let count_def_id = tcx.hir.body_owner_def_id(count); + match ty::queries::monomorphic_const_eval::get(tcx, count_expr.span, count_def_id) { + Ok(Integral(Usize(count))) => { + let val = count.as_u64(tcx.sess.target.uint_type); + assert_eq!(val as usize as u64, val); + Ok(val as usize) + }, + Ok(_) | + Err(ConstEvalErr { kind: ErrKind::TypeckError, .. }) => Err(ErrorReported), + Err(err) => { + let mut diag = err.struct_error(tcx, count_expr.span, reason); + + if let hir::ExprPath(hir::QPath::Resolved(None, ref path)) = count_expr.node { + if let Def::Local(..) = path.def { + diag.note(&format!("`{}` is a variable", + tcx.hir.node_to_pretty_string(count_expr.id))); + } + } + + diag.emit(); + Err(ErrorReported) + } + } +} diff --git a/src/librustc_const_eval/eval.rs b/src/librustc_const_eval/eval.rs index b928bae620b6c..bf8085be31c44 100644 --- a/src/librustc_const_eval/eval.rs +++ b/src/librustc_const_eval/eval.rs @@ -18,6 +18,7 @@ use rustc::traits; use rustc::hir::def::Def; use rustc::hir::def_id::DefId; use rustc::ty::{self, Ty, TyCtxt}; +use rustc::ty::maps::Providers; use rustc::ty::util::IntTypeExt; use rustc::ty::subst::{Substs, Subst}; use rustc::traits::Reveal; @@ -163,12 +164,6 @@ pub struct ConstContext<'a, 'tcx: 'a> { } impl<'a, 'tcx> ConstContext<'a, 'tcx> { - pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, body: hir::BodyId) -> Self { - let def_id = tcx.hir.body_owner_def_id(body); - ty::queries::mir_const_qualif::get(tcx, DUMMY_SP, def_id); - ConstContext::with_tables(tcx, tcx.item_tables(def_id)) - } - pub fn with_tables(tcx: TyCtxt<'a, 'tcx, 'tcx>, tables: &'a ty::TypeckTables<'tcx>) -> Self { ConstContext { tcx: tcx, @@ -799,34 +794,20 @@ impl<'a, 'tcx> ConstContext<'a, 'tcx> { } } +pub fn provide(providers: &mut Providers) { + *providers = Providers { + monomorphic_const_eval, + ..*providers + }; +} -/// Returns the value of the length-valued expression -pub fn eval_length<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - count: hir::BodyId, - reason: &str) - -> Result -{ - let count_expr = &tcx.hir.body(count).value; - match ConstContext::new(tcx, count).eval(count_expr) { - Ok(Integral(Usize(count))) => { - let val = count.as_u64(tcx.sess.target.uint_type); - assert_eq!(val as usize as u64, val); - Ok(val as usize) - }, - Ok(_) | - Err(ConstEvalErr { kind: TypeckError, .. }) => Err(ErrorReported), - Err(err) => { - let mut diag = err.struct_error(tcx, count_expr.span, reason); - - if let hir::ExprPath(hir::QPath::Resolved(None, ref path)) = count_expr.node { - if let Def::Local(..) = path.def { - diag.note(&format!("`{}` is a variable", - tcx.hir.node_to_pretty_string(count_expr.id))); - } - } +fn monomorphic_const_eval<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + def_id: DefId) + -> EvalResult<'tcx> { + ty::queries::mir_const_qualif::get(tcx, DUMMY_SP, def_id); + let cx = ConstContext::with_tables(tcx, tcx.item_tables(def_id)); - diag.emit(); - Err(ErrorReported) - } - } + let id = tcx.hir.as_local_node_id(def_id).unwrap(); + let body = tcx.hir.body_owned_by(id); + cx.eval(&tcx.hir.body(body).value) } diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 48d9719e76c4d..c856ea505ffe8 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -37,7 +37,7 @@ use rustc_plugin::registry::Registry; use rustc_plugin as plugin; use rustc_passes::{ast_validation, no_asm, loops, consts, static_recursion, hir_stats, mir_stats}; -use rustc_const_eval::check_match; +use rustc_const_eval::{self, check_match}; use super::Compilation; use serialize::json; @@ -895,6 +895,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session, typeck::provide(&mut local_providers); ty::provide(&mut local_providers); reachable::provide(&mut local_providers); + rustc_const_eval::provide(&mut local_providers); let mut extern_providers = ty::maps::Providers::default(); cstore::provide(&mut extern_providers); diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index 595748c8c6fdc..b7de50efe3442 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -17,7 +17,6 @@ use hair::cx::to_ref::ToRef; use rustc::hir::map; use rustc::hir::def::{Def, CtorKind}; use rustc::middle::const_val::ConstVal; -use rustc_const_eval::ConstContext; use rustc::ty::{self, AdtKind, VariantDef, Ty}; use rustc::ty::cast::CastKind as TyCastKind; use rustc::hir; @@ -592,9 +591,9 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, // Now comes the rote stuff: hir::ExprRepeat(ref v, count) => { - let tcx = cx.tcx.global_tcx(); let c = &cx.tcx.hir.body(count).value; - let count = match ConstContext::new(tcx, count).eval(c) { + let def_id = cx.tcx.hir.body_owner_def_id(count); + let count = match ty::queries::monomorphic_const_eval::get(cx.tcx, c.span, def_id) { Ok(ConstVal::Integral(ConstInt::Usize(u))) => u, Ok(other) => bug!("constant evaluation of repeat count yielded {:?}", other), Err(s) => cx.fatal_const_eval_err(&s, c.span, "expression") diff --git a/src/librustc_typeck/Cargo.toml b/src/librustc_typeck/Cargo.toml index 07998aa4a30ea..194d37dcb81c2 100644 --- a/src/librustc_typeck/Cargo.toml +++ b/src/librustc_typeck/Cargo.toml @@ -16,7 +16,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_data_structures = { path = "../librustc_data_structures" } rustc_platform_intrinsics = { path = "../librustc_platform_intrinsics" } diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 66c4a81a5c0f2..9426d601dfcce 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -12,7 +12,7 @@ //! representation. The main routine here is `ast_ty_to_ty()`: each use //! is parameterized by an instance of `AstConv`. -use rustc_const_eval::eval_length; +use rustc::middle::const_val::eval_length; use rustc_data_structures::accumulate_vec::AccumulateVec; use hir; use hir::def::Def; @@ -1208,7 +1208,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { self.associated_path_def_to_ty(ast_ty.id, ast_ty.span, ty, def, segment).0 } hir::TyArray(ref ty, length) => { - if let Ok(length) = eval_length(tcx.global_tcx(), length, "array length") { + if let Ok(length) = eval_length(tcx, length, "array length") { tcx.mk_array(self.ast_ty_to_ty(&ty), length) } else { self.tcx().types.err diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 5e7325275b819..d2c9fd119d72b 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -126,7 +126,7 @@ use rustc::hir::itemlikevisit::ItemLikeVisitor; use rustc::hir::{self, PatKind}; use rustc::middle::lang_items; use rustc_back::slice; -use rustc_const_eval::eval_length; +use rustc::middle::const_val::eval_length; use rustc_const_math::ConstInt; mod assoc; @@ -3634,7 +3634,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { tcx.mk_array(element_ty, args.len()) } hir::ExprRepeat(ref element, count) => { - let count = eval_length(self.tcx.global_tcx(), count, "repeat count") + let count = eval_length(self.tcx, count, "repeat count") .unwrap_or(0); let uty = match expected { diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 4c7979ea3765c..73e3de0cc76dd 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -59,14 +59,12 @@ use constrained_type_params as ctp; use middle::lang_items::SizedTraitLangItem; use middle::const_val::ConstVal; use middle::resolve_lifetime as rl; -use rustc_const_eval::ConstContext; use rustc::ty::subst::Substs; use rustc::ty::{ToPredicate, ReprOptions}; use rustc::ty::{self, AdtKind, ToPolyTraitRef, Ty, TyCtxt}; use rustc::ty::maps::Providers; use rustc::ty::util::IntTypeExt; use rustc::dep_graph::DepNode; -use util::common::MemoizationMap; use util::nodemap::{NodeMap, FxHashMap}; use rustc_const_math::ConstInt; @@ -600,9 +598,7 @@ fn convert_enum_variant_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let wrapped_discr = prev_discr.map_or(initial, |d| d.wrap_incr()); prev_discr = Some(if let Some(e) = variant.node.disr_expr { let expr_did = tcx.hir.local_def_id(e.node_id); - let result = tcx.maps.monomorphic_const_eval.memoize(expr_did, || { - ConstContext::new(tcx, e).eval(&tcx.hir.body(e).value) - }); + let result = ty::queries::monomorphic_const_eval::get(tcx, variant.span, expr_did); // enum variant evaluation happens before the global constant check // so we need to report the real error diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 12db76bf91c34..e9d52c5eb98d9 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -94,7 +94,6 @@ extern crate fmt_macros; extern crate rustc_platform_intrinsics as intrinsics; extern crate rustc_back; extern crate rustc_const_math; -extern crate rustc_const_eval; extern crate rustc_data_structures; extern crate rustc_errors as errors; diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml index 52f5d99838dc7..e81acf7bdba82 100644 --- a/src/librustdoc/Cargo.toml +++ b/src/librustdoc/Cargo.toml @@ -14,7 +14,6 @@ env_logger = { version = "0.4", default-features = false } log = "0.3" rustc = { path = "../librustc" } rustc_back = { path = "../librustc_back" } -rustc_const_eval = { path = "../librustc_const_eval" } rustc_data_structures = { path = "../librustc_data_structures" } rustc_driver = { path = "../librustc_driver" } rustc_errors = { path = "../librustc_errors" } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 3d233463bba3a..47e1d0b7edb2a 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1715,7 +1715,7 @@ impl Clean for hir::Ty { } TySlice(ref ty) => Vector(box ty.clean(cx)), TyArray(ref ty, length) => { - use rustc_const_eval::eval_length; + use rustc::middle::const_val::eval_length; let n = eval_length(cx.tcx, length, "array length").unwrap(); FixedVector(box ty.clean(cx), n.to_string()) }, diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 447d60018d912..d5b997001bb9d 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -33,7 +33,6 @@ extern crate getopts; extern crate env_logger; extern crate libc; extern crate rustc; -extern crate rustc_const_eval; extern crate rustc_data_structures; extern crate rustc_trans; extern crate rustc_driver; From 6dc21b71cfd8e5246e7953cf64ea5ee6a19ceb3d Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Sat, 15 Apr 2017 04:14:44 +0300 Subject: [PATCH 3/3] rustc: use monomorphic const_eval for cross-crate enum discriminants. --- src/librustc/ty/mod.rs | 47 ++++++++++- src/librustc_const_eval/eval.rs | 11 ++- src/librustc_driver/driver.rs | 2 + .../persist/dirty_clean.rs | 11 +++ src/librustc_metadata/decoder.rs | 24 ++---- src/librustc_metadata/encoder.rs | 46 +++++++++-- src/librustc_metadata/schema.rs | 13 ++- src/librustc_trans/adt.rs | 20 ++--- src/librustc_trans/disr.rs | 82 ------------------- src/librustc_trans/lib.rs | 2 - src/librustc_trans/mir/constant.rs | 13 +-- src/librustc_trans/mir/rvalue.rs | 6 +- src/librustc_trans/mir/statement.rs | 3 +- src/test/incremental/hashes/enum_defs.rs | 8 +- 14 files changed, 139 insertions(+), 149 deletions(-) delete mode 100644 src/librustc_trans/disr.rs diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 09eacb40aef7e..0b5434f50e830 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -1660,7 +1660,7 @@ impl<'a, 'gcx, 'tcx> AdtDef { self.variants.iter().map(move |v| { let mut discr = prev_discr.map_or(initial, |d| d.wrap_incr()); if let VariantDiscr::Explicit(expr_did) = v.discr { - match tcx.maps.monomorphic_const_eval.borrow()[&expr_did] { + match queries::monomorphic_const_eval::get(tcx, DUMMY_SP, expr_did) { Ok(ConstVal::Integral(v)) => { discr = v; } @@ -1673,6 +1673,51 @@ impl<'a, 'gcx, 'tcx> AdtDef { }) } + /// Compute the discriminant value used by a specific variant. + /// Unlike `discriminants`, this is (amortized) constant-time, + /// only doing at most one query for evaluating an explicit + /// discriminant (the last one before the requested variant), + /// assuming there are no constant-evaluation errors there. + pub fn discriminant_for_variant(&self, + tcx: TyCtxt<'a, 'gcx, 'tcx>, + variant_index: usize) + -> ConstInt { + let repr_type = self.repr.discr_type(); + let mut explicit_value = repr_type.initial_discriminant(tcx.global_tcx()); + let mut explicit_index = variant_index; + loop { + match self.variants[explicit_index].discr { + ty::VariantDiscr::Relative(0) => break, + ty::VariantDiscr::Relative(distance) => { + explicit_index -= distance; + } + ty::VariantDiscr::Explicit(expr_did) => { + match queries::monomorphic_const_eval::get(tcx, DUMMY_SP, expr_did) { + Ok(ConstVal::Integral(v)) => { + explicit_value = v; + break; + } + _ => { + explicit_index -= 1; + } + } + } + } + } + let discr = explicit_value.to_u128_unchecked() + .wrapping_add((variant_index - explicit_index) as u128); + match repr_type { + attr::UnsignedInt(ty) => { + ConstInt::new_unsigned_truncating(discr, ty, + tcx.sess.target.uint_type) + } + attr::SignedInt(ty) => { + ConstInt::new_signed_truncating(discr as i128, ty, + tcx.sess.target.int_type) + } + } + } + pub fn destructor(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Option { queries::adt_destructor::get(tcx, DUMMY_SP, self.did) } diff --git a/src/librustc_const_eval/eval.rs b/src/librustc_const_eval/eval.rs index bf8085be31c44..9c5a669bef0d9 100644 --- a/src/librustc_const_eval/eval.rs +++ b/src/librustc_const_eval/eval.rs @@ -804,10 +804,13 @@ pub fn provide(providers: &mut Providers) { fn monomorphic_const_eval<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> EvalResult<'tcx> { - ty::queries::mir_const_qualif::get(tcx, DUMMY_SP, def_id); let cx = ConstContext::with_tables(tcx, tcx.item_tables(def_id)); - let id = tcx.hir.as_local_node_id(def_id).unwrap(); - let body = tcx.hir.body_owned_by(id); - cx.eval(&tcx.hir.body(body).value) + let body = if let Some(id) = tcx.hir.as_local_node_id(def_id) { + ty::queries::mir_const_qualif::get(tcx, DUMMY_SP, def_id); + tcx.hir.body(tcx.hir.body_owned_by(id)) + } else { + tcx.sess.cstore.maybe_get_item_body(tcx, def_id).unwrap() + }; + cx.eval(&body.value) } diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index c856ea505ffe8..7632b40ab4f9e 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -900,6 +900,8 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session, let mut extern_providers = ty::maps::Providers::default(); cstore::provide(&mut extern_providers); ty::provide_extern(&mut extern_providers); + // FIXME(eddyb) get rid of this once we replace const_eval with miri. + rustc_const_eval::provide(&mut extern_providers); TyCtxt::create_and_enter(sess, local_providers, diff --git a/src/librustc_incremental/persist/dirty_clean.rs b/src/librustc_incremental/persist/dirty_clean.rs index af5c1f05bd1fc..b73b3e161f9b5 100644 --- a/src/librustc_incremental/persist/dirty_clean.rs +++ b/src/librustc_incremental/persist/dirty_clean.rs @@ -266,6 +266,17 @@ impl<'a, 'tcx, 'm> intravisit::Visitor<'tcx> for DirtyCleanMetadataVisitor<'a, ' intravisit::walk_item(self, item); } + fn visit_variant(&mut self, + variant: &'tcx hir::Variant, + generics: &'tcx hir::Generics, + parent_id: ast::NodeId) { + if let Some(e) = variant.node.disr_expr { + self.check_item(e.node_id, variant.span); + } + + intravisit::walk_variant(self, variant, generics, parent_id); + } + fn visit_variant_data(&mut self, variant_data: &'tcx hir::VariantData, _: ast::Name, diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index d2512ff602a84..fac6079529e30 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -511,11 +511,7 @@ impl<'a, 'tcx> CrateMetadata { def } - fn get_variant(&self, - item: &Entry<'tcx>, - index: DefIndex, - tcx: TyCtxt<'a, 'tcx, 'tcx>) - -> (ty::VariantDef, Option) { + fn get_variant(&self, item: &Entry, index: DefIndex) -> ty::VariantDef { let data = match item.kind { EntryKind::Variant(data) | EntryKind::Struct(data, _) | @@ -523,13 +519,7 @@ impl<'a, 'tcx> CrateMetadata { _ => bug!(), }; - if let ty::VariantDiscr::Explicit(def_id) = data.discr { - // The original crate wouldn't have compiled if this is missing. - let result = Ok(data.evaluated_discr.unwrap()); - tcx.maps.monomorphic_const_eval.borrow_mut().insert(def_id, result); - } - - (ty::VariantDef { + ty::VariantDef { did: self.local_def_id(data.struct_ctor.unwrap_or(index)), name: self.item_name(index), fields: item.children.decode(self).map(|index| { @@ -542,7 +532,7 @@ impl<'a, 'tcx> CrateMetadata { }).collect(), discr: data.discr, ctor_kind: data.ctor_kind, - }, data.struct_ctor) + } } pub fn get_adt_def(&self, @@ -561,15 +551,11 @@ impl<'a, 'tcx> CrateMetadata { item.children .decode(self) .map(|index| { - let (variant, struct_ctor) = - self.get_variant(&self.entry(index), index, tcx); - assert_eq!(struct_ctor, None); - variant + self.get_variant(&self.entry(index), index) }) .collect() } else { - let (variant, _struct_ctor) = self.get_variant(&item, item_id, tcx); - vec![variant] + vec![self.get_variant(&item, item_id)] }; let (kind, repr) = match item.kind { EntryKind::Enum(repr) => (ty::AdtKind::Enum, repr), diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 0e204695e8f22..ce9f0a73fe2b8 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -269,12 +269,6 @@ impl<'a, 'b: 'a, 'tcx: 'b> EntryBuilder<'a, 'b, 'tcx> { let data = VariantData { ctor_kind: variant.ctor_kind, discr: variant.discr, - evaluated_discr: match variant.discr { - ty::VariantDiscr::Explicit(def_id) => { - ty::queries::monomorphic_const_eval::get(tcx, DUMMY_SP, def_id).ok() - } - ty::VariantDiscr::Relative(_) => None - }, struct_ctor: None, }; @@ -408,7 +402,6 @@ impl<'a, 'b: 'a, 'tcx: 'b> EntryBuilder<'a, 'b, 'tcx> { let data = VariantData { ctor_kind: variant.ctor_kind, discr: variant.discr, - evaluated_discr: None, struct_ctor: Some(def_id.index), }; @@ -697,7 +690,6 @@ impl<'a, 'b: 'a, 'tcx: 'b> EntryBuilder<'a, 'b, 'tcx> { EntryKind::Struct(self.lazy(&VariantData { ctor_kind: variant.ctor_kind, discr: variant.discr, - evaluated_discr: None, struct_ctor: struct_ctor, }), repr_options) } @@ -708,7 +700,6 @@ impl<'a, 'b: 'a, 'tcx: 'b> EntryBuilder<'a, 'b, 'tcx> { EntryKind::Union(self.lazy(&VariantData { ctor_kind: variant.ctor_kind, discr: variant.discr, - evaluated_discr: None, struct_ctor: None, }), repr_options) } @@ -1037,6 +1028,17 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for EncodeVisitor<'a, 'b, 'tcx> { EntryBuilder::encode_info_for_foreign_item, (def_id, ni)); } + fn visit_variant(&mut self, + v: &'tcx hir::Variant, + g: &'tcx hir::Generics, + id: ast::NodeId) { + intravisit::walk_variant(self, v, g, id); + + if let Some(discr) = v.node.disr_expr { + let def_id = self.index.tcx.hir.body_owner_def_id(discr); + self.index.record(def_id, EntryBuilder::encode_info_for_embedded_const, def_id); + } + } fn visit_generics(&mut self, generics: &'tcx hir::Generics) { intravisit::walk_generics(self, generics); self.index.encode_info_for_generics(generics); @@ -1160,6 +1162,32 @@ impl<'a, 'b: 'a, 'tcx: 'b> EntryBuilder<'a, 'b, 'tcx> { } } + fn encode_info_for_embedded_const(&mut self, def_id: DefId) -> Entry<'tcx> { + debug!("EntryBuilder::encode_info_for_embedded_const({:?})", def_id); + let tcx = self.tcx; + let id = tcx.hir.as_local_node_id(def_id).unwrap(); + let body = tcx.hir.body_owned_by(id); + + Entry { + kind: EntryKind::Const(ty::queries::mir_const_qualif::get(tcx, DUMMY_SP, def_id)), + visibility: self.lazy(&ty::Visibility::Public), + span: self.lazy(&tcx.def_span(def_id)), + attributes: LazySeq::empty(), + children: LazySeq::empty(), + stability: None, + deprecation: None, + + ty: Some(self.encode_item_type(def_id)), + inherent_impls: LazySeq::empty(), + variances: LazySeq::empty(), + generics: Some(self.encode_generics(def_id)), + predicates: Some(self.encode_predicates(def_id)), + + ast: Some(self.encode_body(body)), + mir: self.encode_mir(def_id), + } + } + fn encode_attributes(&mut self, attrs: &[ast::Attribute]) -> LazySeq { // NOTE: This must use lazy_seq_from_slice(), not lazy_seq() because // we really on the HashStable specialization for [Attribute] diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index 6cd35f1335ed7..2f2e0e125aea5 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -15,7 +15,6 @@ use rustc::hir; use rustc::hir::def::{self, CtorKind}; use rustc::hir::def_id::{DefIndex, DefId}; use rustc::ich::StableHashingContext; -use rustc::middle::const_val::ConstVal; use rustc::middle::cstore::{DepKind, LinkagePreference, NativeLibrary}; use rustc::middle::lang_items; use rustc::mir; @@ -271,9 +270,9 @@ pub enum EntryKind<'tcx> { Type, Enum(ReprOptions), Field, - Variant(Lazy>), - Struct(Lazy>, ReprOptions), - Union(Lazy>, ReprOptions), + Variant(Lazy), + Struct(Lazy, ReprOptions), + Union(Lazy, ReprOptions), Fn(Lazy), ForeignFn(Lazy), Mod(Lazy), @@ -374,20 +373,18 @@ pub struct FnData { impl_stable_hash_for!(struct FnData { constness, arg_names }); #[derive(RustcEncodable, RustcDecodable)] -pub struct VariantData<'tcx> { +pub struct VariantData { pub ctor_kind: CtorKind, pub discr: ty::VariantDiscr, - pub evaluated_discr: Option>, /// If this is a struct's only variant, this /// is the index of the "struct ctor" item. pub struct_ctor: Option, } -impl_stable_hash_for!(struct VariantData<'tcx> { +impl_stable_hash_for!(struct VariantData { ctor_kind, discr, - evaluated_discr, struct_ctor }); diff --git a/src/librustc_trans/adt.rs b/src/librustc_trans/adt.rs index 0fe180253b5b8..87ca410dece0d 100644 --- a/src/librustc_trans/adt.rs +++ b/src/librustc_trans/adt.rs @@ -41,8 +41,6 @@ //! used unboxed and any field can have pointers (including mutable) //! taken to it, implementing them for Rust seems difficult. -use super::Disr; - use std; use llvm::{ValueRef, True, IntEQ, IntNE}; @@ -347,31 +345,31 @@ fn load_discr(bcx: &Builder, ity: layout::Integer, ptr: ValueRef, /// Set the discriminant for a new value of the given case of the given /// representation. -pub fn trans_set_discr<'a, 'tcx>(bcx: &Builder<'a, 'tcx>, t: Ty<'tcx>, val: ValueRef, to: Disr) { +pub fn trans_set_discr<'a, 'tcx>(bcx: &Builder<'a, 'tcx>, t: Ty<'tcx>, val: ValueRef, to: u64) { let l = bcx.ccx.layout_of(t); match *l { layout::CEnum{ discr, min, max, .. } => { - assert_discr_in_range(Disr(min), Disr(max), to); - bcx.store(C_integral(Type::from_integer(bcx.ccx, discr), to.0, true), + assert_discr_in_range(min, max, to); + bcx.store(C_integral(Type::from_integer(bcx.ccx, discr), to, true), val, None); } layout::General{ discr, .. } => { - bcx.store(C_integral(Type::from_integer(bcx.ccx, discr), to.0, true), + bcx.store(C_integral(Type::from_integer(bcx.ccx, discr), to, true), bcx.struct_gep(val, 0), None); } layout::Univariant { .. } | layout::UntaggedUnion { .. } | layout::Vector { .. } => { - assert_eq!(to, Disr(0)); + assert_eq!(to, 0); } layout::RawNullablePointer { nndiscr, .. } => { - if to.0 != nndiscr { + if to != nndiscr { let llptrty = val_ty(val).element_type(); bcx.store(C_null(llptrty), val, None); } } layout::StructWrappedNullablePointer { nndiscr, ref discrfield, ref nonnull, .. } => { - if to.0 != nndiscr { + if to != nndiscr { if target_sets_discr_via_memset(bcx) { // Issue #34427: As workaround for LLVM bug on // ARM, use memset of 0 on whole struct rather @@ -397,7 +395,7 @@ fn target_sets_discr_via_memset<'a, 'tcx>(bcx: &Builder<'a, 'tcx>) -> bool { bcx.sess().target.target.arch == "arm" || bcx.sess().target.target.arch == "aarch64" } -pub fn assert_discr_in_range(min: Disr, max: Disr, discr: Disr) { +pub fn assert_discr_in_range(min: D, max: D, discr: D) { if min <= max { assert!(min <= discr && discr <= max) } else { @@ -415,7 +413,7 @@ fn roundup(x: u64, a: u32) -> u64 { let a = a as u64; ((x + (a - 1)) / a) * a } /// (Not to be confused with `common::const_get_elt`, which operates on /// raw LLVM-level structs and arrays.) pub fn const_get_field<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>, - val: ValueRef, _discr: Disr, + val: ValueRef, ix: usize) -> ValueRef { let l = ccx.layout_of(t); match *l { diff --git a/src/librustc_trans/disr.rs b/src/librustc_trans/disr.rs deleted file mode 100644 index a940faac83877..0000000000000 --- a/src/librustc_trans/disr.rs +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use rustc::middle::const_val::ConstVal; -use rustc::ty::{self, TyCtxt}; -use rustc_const_math::ConstInt; - -#[derive(Debug, Eq, PartialEq, Copy, Clone)] -pub struct Disr(pub u64); - -impl Disr { - pub fn for_variant(tcx: TyCtxt, - def: &ty::AdtDef, - variant_index: usize) -> Self { - let mut explicit_index = variant_index; - let mut explicit_value = Disr(0); - loop { - match def.variants[explicit_index].discr { - ty::VariantDiscr::Relative(0) => break, - ty::VariantDiscr::Relative(distance) => { - explicit_index -= distance; - } - ty::VariantDiscr::Explicit(expr_did) => { - match tcx.maps.monomorphic_const_eval.borrow()[&expr_did] { - Ok(ConstVal::Integral(v)) => { - explicit_value = Disr::from(v); - break; - } - _ => { - explicit_index -= 1; - } - } - } - } - } - let distance = variant_index - explicit_index; - explicit_value.wrapping_add(Disr::from(distance)) - } - - pub fn wrapping_add(self, other: Self) -> Self { - Disr(self.0.wrapping_add(other.0)) - } -} - -impl ::std::ops::BitAnd for Disr { - type Output = Disr; - fn bitand(self, other: Self) -> Self { - Disr(self.0 & other.0) - } -} - -impl From for Disr { - fn from(i: ConstInt) -> Disr { - // FIXME: what if discr has 128 bit discr? - Disr(i.to_u128_unchecked() as u64) - } -} - -impl From for Disr { - fn from(i: usize) -> Disr { - Disr(i as u64) - } -} - -impl PartialOrd for Disr { - fn partial_cmp(&self, other: &Disr) -> Option<::std::cmp::Ordering> { - self.0.partial_cmp(&other.0) - } -} - -impl Ord for Disr { - fn cmp(&self, other: &Disr) -> ::std::cmp::Ordering { - self.0.cmp(&other.0) - } -} diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs index c5383fceb8787..be214a0f6143c 100644 --- a/src/librustc_trans/lib.rs +++ b/src/librustc_trans/lib.rs @@ -67,7 +67,6 @@ pub use rustc::lint; pub use rustc::util; pub use base::trans_crate; -pub use disr::Disr; pub mod back { pub use rustc::hir::svh; @@ -118,7 +117,6 @@ mod consts; mod context; mod debuginfo; mod declare; -mod disr; mod glue; mod intrinsic; mod machine; diff --git a/src/librustc_trans/mir/constant.rs b/src/librustc_trans/mir/constant.rs index 37d2b1952f494..8bce0cf85c08b 100644 --- a/src/librustc_trans/mir/constant.rs +++ b/src/librustc_trans/mir/constant.rs @@ -22,7 +22,7 @@ use rustc::ty::layout::{self, LayoutTyper}; use rustc::ty::cast::{CastTy, IntTy}; use rustc::ty::subst::{Kind, Substs, Subst}; use rustc_data_structures::indexed_vec::{Idx, IndexVec}; -use {abi, adt, base, Disr, machine}; +use {abi, adt, base, machine}; use callee; use builder::Builder; use common::{self, CrateContext, const_get_elt, val_ty}; @@ -428,7 +428,7 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> { } mir::ProjectionElem::Field(ref field, _) => { let llprojected = adt::const_get_field(self.ccx, tr_base.ty, base.llval, - Disr(0), field.index()); + field.index()); let llextra = if is_sized { ptr::null_mut() } else { @@ -987,13 +987,14 @@ fn trans_const<'a, 'tcx>( layout::CEnum { discr: d, min, max, .. } => { let discr = match *kind { mir::AggregateKind::Adt(adt_def, _, _, _) => { - Disr::for_variant(ccx.tcx(), adt_def, variant_index) + adt_def.discriminant_for_variant(ccx.tcx(), variant_index) + .to_u128_unchecked() as u64 }, - _ => Disr(0), + _ => 0, }; assert_eq!(vals.len(), 0); - adt::assert_discr_in_range(Disr(min), Disr(max), discr); - C_integral(Type::from_integer(ccx, d), discr.0, true) + adt::assert_discr_in_range(min, max, discr); + C_integral(Type::from_integer(ccx, d), discr, true) } layout::General { discr: d, ref variants, .. } => { let variant = &variants[variant_index]; diff --git a/src/librustc_trans/mir/rvalue.rs b/src/librustc_trans/mir/rvalue.rs index aa41720d717a7..98e9008f829f6 100644 --- a/src/librustc_trans/mir/rvalue.rs +++ b/src/librustc_trans/mir/rvalue.rs @@ -28,7 +28,6 @@ use type_::Type; use type_of; use tvec; use value::Value; -use Disr; use super::MirContext; use super::constant::const_scalar_checked_binop; @@ -107,9 +106,10 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> { mir::Rvalue::Aggregate(ref kind, ref operands) => { match *kind { mir::AggregateKind::Adt(adt_def, variant_index, substs, active_field_index) => { - let disr = Disr::for_variant(bcx.tcx(), adt_def, variant_index); + let discr = adt_def.discriminant_for_variant(bcx.tcx(), variant_index) + .to_u128_unchecked() as u64; let dest_ty = dest.ty.to_ty(bcx.tcx()); - adt::trans_set_discr(&bcx, dest_ty, dest.llval, disr); + adt::trans_set_discr(&bcx, dest_ty, dest.llval, discr); for (i, operand) in operands.iter().enumerate() { let op = self.trans_operand(&bcx, operand); // Do not generate stores and GEPis for zero-sized fields. diff --git a/src/librustc_trans/mir/statement.rs b/src/librustc_trans/mir/statement.rs index 29a0648c8f8f8..52c2afca4748b 100644 --- a/src/librustc_trans/mir/statement.rs +++ b/src/librustc_trans/mir/statement.rs @@ -18,7 +18,6 @@ use builder::Builder; use super::MirContext; use super::LocalRef; use super::super::adt; -use super::super::disr::Disr; impl<'a, 'tcx> MirContext<'a, 'tcx> { pub fn trans_statement(&mut self, @@ -65,7 +64,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> { adt::trans_set_discr(&bcx, ty, lvalue_transed.llval, - Disr::from(variant_index)); + variant_index as u64); bcx } mir::StatementKind::StorageLive(ref lvalue) => { diff --git a/src/test/incremental/hashes/enum_defs.rs b/src/test/incremental/hashes/enum_defs.rs index 37c6ef58f5e56..0f734683b60e5 100644 --- a/src/test/incremental/hashes/enum_defs.rs +++ b/src/test/incremental/hashes/enum_defs.rs @@ -27,6 +27,7 @@ #![allow(warnings)] #![feature(rustc_attrs)] +#![feature(stmt_expr_attributes)] #![crate_type="rlib"] @@ -125,9 +126,12 @@ enum EnumChangeValueCStyleVariant0 { enum EnumChangeValueCStyleVariant0 { Variant1, - #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] - Variant2 = 22, + Variant2 = + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] + 22, } #[cfg(cfail1)]