Rollup merge of #41310 - eddyb:demand-const-eval, r=nikomatsakis
[on-demand] Turn monomorphic_const_eval into a proper query, not just a cache. The error definitions and reporting logic, alongside with `eval_length` were moved to `librustc`. Both local and cross-crate constant evaluation is on-demand now, but the latter is only used for `enum` discriminants, to replace the manual insertion into the cache which was done when decoding variants. r? @nikomatsakis
This commit is contained in:
commit
24e8158213
38 changed files with 436 additions and 453 deletions
4
src/Cargo.lock
generated
4
src/Cargo.lock
generated
|
@ -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",
|
||||
|
@ -762,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",
|
||||
|
@ -783,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",
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -8,17 +8,28 @@
|
|||
// 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 hir::def_id::DefId;
|
||||
use ty::subst::Substs;
|
||||
use rustc_const_math::*;
|
||||
|
||||
use self::ConstVal::*;
|
||||
pub use rustc_const_math::ConstInt;
|
||||
|
||||
use hir;
|
||||
use hir::def::Def;
|
||||
use hir::def_id::DefId;
|
||||
use ty::{self, TyCtxt};
|
||||
use ty::subst::Substs;
|
||||
use util::common::ErrorReported;
|
||||
use rustc_const_math::*;
|
||||
|
||||
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<ConstVal<'tcx>, ConstEvalErr<'tcx>>;
|
||||
|
||||
#[derive(Clone, Debug, Hash, RustcEncodable, RustcDecodable, Eq, PartialEq)]
|
||||
pub enum ConstVal<'tcx> {
|
||||
|
@ -61,3 +72,181 @@ 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<ConstEvalErr<'tcx>>),
|
||||
|
||||
TypeckError
|
||||
}
|
||||
|
||||
impl<'tcx> From<ConstMathErr> 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();
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the value of the length-valued expression
|
||||
pub fn eval_length(tcx: TyCtxt,
|
||||
count: hir::BodyId,
|
||||
reason: &str)
|
||||
-> Result<usize, ErrorReported>
|
||||
{
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<ConstVal<'tcx>, ()>,
|
||||
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<AccessLevels>,
|
||||
|
|
|
@ -1690,7 +1690,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;
|
||||
}
|
||||
|
@ -1703,6 +1703,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<Destructor> {
|
||||
queries::adt_destructor::get(tcx, DUMMY_SP, self.did)
|
||||
}
|
||||
|
|
|
@ -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" }
|
||||
|
|
|
@ -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,6 +106,22 @@ impl<'a, 'tcx> Visitor<'tcx> for MatchVisitor<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
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(ref err) => {
|
||||
err.report(self.tcx, pat_span, "pattern");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> MatchVisitor<'a, 'tcx> {
|
||||
fn check_patterns(&self, has_guard: bool, pats: &[P<Pat>]) {
|
||||
check_legality_of_move_bindings(self, has_guard, pats);
|
||||
|
@ -116,20 +130,6 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
fn report_inlining_errors(&self, patcx: PatternContext, pat_span: Span) {
|
||||
for error in patcx.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");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn check_match(
|
||||
&self,
|
||||
scrut: &hir::Expr,
|
||||
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
"##,
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
@ -18,22 +18,20 @@ 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;
|
||||
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 +156,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>,
|
||||
|
@ -226,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,
|
||||
|
@ -251,107 +183,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<ConstEvalErr<'tcx>>),
|
||||
|
||||
TypeckError
|
||||
}
|
||||
|
||||
impl<'tcx> From<ConstMathErr> 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<ConstVal<'tcx>, ConstEvalErr<'tcx>>;
|
||||
pub type CastResult<'tcx> = Result<ConstVal<'tcx>, ErrKind<'tcx>>;
|
||||
type CastResult<'tcx> = Result<ConstVal<'tcx>, ErrKind<'tcx>>;
|
||||
|
||||
fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>,
|
||||
e: &Expr) -> EvalResult<'tcx> {
|
||||
|
@ -947,14 +779,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);
|
||||
}
|
||||
};
|
||||
|
@ -962,35 +794,23 @@ impl<'a, 'tcx> ConstContext<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/// 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<usize, ErrorReported>
|
||||
{
|
||||
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 = build_const_eval_err(
|
||||
tcx, &err, 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)
|
||||
}
|
||||
}
|
||||
pub fn provide(providers: &mut Providers) {
|
||||
*providers = Providers {
|
||||
monomorphic_const_eval,
|
||||
..*providers
|
||||
};
|
||||
}
|
||||
|
||||
fn monomorphic_const_eval<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
def_id: DefId)
|
||||
-> EvalResult<'tcx> {
|
||||
let cx = ConstContext::with_tables(tcx, tcx.item_tables(def_id));
|
||||
|
||||
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)
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)]
|
||||
|
|
|
@ -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,10 +895,13 @@ 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);
|
||||
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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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<DefIndex>) {
|
||||
fn get_variant(&self, item: &Entry, index: DefIndex) -> ty::VariantDef {
|
||||
let data = match item.kind {
|
||||
EntryKind::Variant(data) |
|
||||
EntryKind::Struct(data, _) |
|
||||
|
@ -523,12 +519,7 @@ impl<'a, 'tcx> CrateMetadata {
|
|||
_ => bug!(),
|
||||
};
|
||||
|
||||
if let ty::VariantDiscr::Explicit(def_id) = data.discr {
|
||||
let result = data.evaluated_discr.map_or(Err(()), Ok);
|
||||
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| {
|
||||
|
@ -541,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,
|
||||
|
@ -560,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),
|
||||
|
|
|
@ -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<ast::Attribute> {
|
||||
// NOTE: This must use lazy_seq_from_slice(), not lazy_seq() because
|
||||
// we really on the HashStable specialization for [Attribute]
|
||||
|
|
|
@ -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<VariantData<'tcx>>),
|
||||
Struct(Lazy<VariantData<'tcx>>, ReprOptions),
|
||||
Union(Lazy<VariantData<'tcx>>, ReprOptions),
|
||||
Variant(Lazy<VariantData>),
|
||||
Struct(Lazy<VariantData>, ReprOptions),
|
||||
Union(Lazy<VariantData>, ReprOptions),
|
||||
Fn(Lazy<FnData>),
|
||||
ForeignFn(Lazy<FnData>),
|
||||
Mod(Lazy<ModData>),
|
||||
|
@ -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<ConstVal<'tcx>>,
|
||||
|
||||
/// If this is a struct's only variant, this
|
||||
/// is the index of the "struct ctor" item.
|
||||
pub struct_ctor: Option<DefIndex>,
|
||||
}
|
||||
|
||||
impl_stable_hash_for!(struct VariantData<'tcx> {
|
||||
impl_stable_hash_for!(struct VariantData {
|
||||
ctor_kind,
|
||||
discr,
|
||||
evaluated_discr,
|
||||
struct_ctor
|
||||
});
|
||||
|
||||
|
|
|
@ -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, fatal_const_eval_err};
|
||||
use rustc::ty::{self, AdtKind, VariantDef, Ty};
|
||||
use rustc::ty::cast::CastKind as TyCastKind;
|
||||
use rustc::hir;
|
||||
|
@ -592,12 +591,12 @@ 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) => fatal_const_eval_err(tcx, &s, c.span, "expression")
|
||||
Err(s) => cx.fatal_const_eval_err(&s, c.span, "expression")
|
||||
};
|
||||
|
||||
ExprKind::Repeat {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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" }
|
||||
|
|
|
@ -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<D: PartialOrd>(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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use rustc::middle::const_val::ConstVal;
|
||||
use rustc::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<ConstInt> for Disr {
|
||||
fn from(i: ConstInt) -> Disr {
|
||||
// FIXME: what if discr has 128 bit discr?
|
||||
Disr(i.to_u128_unchecked() as u64)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<usize> 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)
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
|
@ -68,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;
|
||||
|
@ -119,7 +117,6 @@ mod consts;
|
|||
mod context;
|
||||
mod debuginfo;
|
||||
mod declare;
|
||||
mod disr;
|
||||
mod glue;
|
||||
mod intrinsic;
|
||||
mod machine;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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};
|
||||
|
@ -23,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};
|
||||
|
@ -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
|
||||
|
@ -429,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 {
|
||||
|
@ -988,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];
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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) => {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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" }
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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, report_const_eval_err};
|
||||
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;
|
||||
|
@ -587,17 +585,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<ConstVal<'tcx>, ()> {
|
||||
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]) {
|
||||
|
@ -611,9 +598,13 @@ 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, || {
|
||||
evaluate_disr_expr(tcx, e)
|
||||
});
|
||||
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
|
||||
if let Err(ref err) = result {
|
||||
err.report(tcx, variant.span, "enum discriminant");
|
||||
}
|
||||
|
||||
match result {
|
||||
Ok(ConstVal::Integral(x)) => Some(x),
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -15,7 +15,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" }
|
||||
|
|
|
@ -1718,7 +1718,7 @@ impl Clean<Type> 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())
|
||||
},
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)]
|
||||
|
|
Loading…
Add table
Reference in a new issue