Add a fallback for stacktrace printing for older Windows versions.
Some time ago we switched stack inspection functions of dbghelp.dll to their newer alternatives that also capture inlined context.
Unfortunately, said new alternatives are not present in older dbghelp.dll versions.
In particular Windows 7 at the time of writing has dbghelp.dll version 6.1.7601 from 2010, that lacks StackWalkEx and friends.
Tested on my Windows 7 - both msvc and gnu versions produce a readable stacktrace.
Fixes #50138
- [`Take::set_limit`]
- [`hint::unreachable_unchecked`]
- [`os::unix::process::parent_id`]
-- [`process::id`]
- [`ptr::swap_nonoverlapping`]
- [`slice::rsplit_mut`]
- [`slice::rsplit`]
use core::fmt;
use core::cmp::Ordering;
use core::intrinsics::abort;
-use core::mem::{self, align_of_val, size_of_val, uninitialized};
+use core::mem::{self, align_of_val, size_of_val};
use core::ops::Deref;
use core::ops::CoerceUnsized;
use core::ptr::{self, NonNull};
/// necessarily) at _exactly_ `MAX_REFCOUNT + 1` references.
const MAX_REFCOUNT: usize = (isize::MAX) as usize;
+/// A sentinel value that is used for the pointer of `Weak::new()`.
+const WEAK_EMPTY: usize = 1;
+
/// A thread-safe reference-counting pointer. 'Arc' stands for 'Atomically
/// Reference Counted'.
///
/// [`None`]: ../../std/option/enum.Option.html#variant.None
#[stable(feature = "arc_weak", since = "1.4.0")]
pub struct Weak<T: ?Sized> {
+ // This is a `NonNull` to allow optimizing the size of this type in enums,
+ // but it is actually not truly "non-null". A `Weak::new()` will set this
+ // to a sentinel value, instead of needing to allocate some space in the
+ // heap.
ptr: NonNull<ArcInner<T>>,
}
}
impl<T> Weak<T> {
- /// Constructs a new `Weak<T>`, allocating memory for `T` without initializing
- /// it. Calling [`upgrade`] on the return value always gives [`None`].
+ /// Constructs a new `Weak<T>`, without allocating any memory.
+ /// Calling [`upgrade`] on the return value always gives [`None`].
///
/// [`upgrade`]: struct.Weak.html#method.upgrade
/// [`None`]: ../../std/option/enum.Option.html#variant.None
pub fn new() -> Weak<T> {
unsafe {
Weak {
- ptr: Box::into_raw_non_null(box ArcInner {
- strong: atomic::AtomicUsize::new(0),
- weak: atomic::AtomicUsize::new(1),
- data: uninitialized(),
- }),
+ ptr: NonNull::new_unchecked(WEAK_EMPTY as *mut _),
}
}
}
pub fn upgrade(&self) -> Option<Arc<T>> {
// We use a CAS loop to increment the strong count instead of a
// fetch_add because once the count hits 0 it must never be above 0.
- let inner = self.inner();
+ let inner = if self.ptr.as_ptr() as *const u8 as usize == WEAK_EMPTY {
+ return None;
+ } else {
+ unsafe { self.ptr.as_ref() }
+ };
// Relaxed load because any write of 0 that we can observe
// leaves the field in a permanently zero state (so a
// Relaxed is valid for the same reason it is on Arc's Clone impl
match inner.strong.compare_exchange_weak(n, n + 1, Relaxed, Relaxed) {
- Ok(_) => return Some(Arc { ptr: self.ptr, phantom: PhantomData }),
+ Ok(_) => return Some(Arc {
+ // null checked above
+ ptr: self.ptr,
+ phantom: PhantomData,
+ }),
Err(old) => n = old,
}
}
}
-
- #[inline]
- fn inner(&self) -> &ArcInner<T> {
- // See comments above for why this is "safe"
- unsafe { self.ptr.as_ref() }
- }
}
#[stable(feature = "arc_weak", since = "1.4.0")]
/// ```
#[inline]
fn clone(&self) -> Weak<T> {
+ let inner = if self.ptr.as_ptr() as *const u8 as usize == WEAK_EMPTY {
+ return Weak { ptr: self.ptr };
+ } else {
+ unsafe { self.ptr.as_ref() }
+ };
// See comments in Arc::clone() for why this is relaxed. This can use a
// fetch_add (ignoring the lock) because the weak count is only locked
// where are *no other* weak pointers in existence. (So we can't be
// running this code in that case).
- let old_size = self.inner().weak.fetch_add(1, Relaxed);
+ let old_size = inner.weak.fetch_add(1, Relaxed);
// See comments in Arc::clone() for why we do this (for mem::forget).
if old_size > MAX_REFCOUNT {
#[stable(feature = "downgraded_weak", since = "1.10.0")]
impl<T> Default for Weak<T> {
- /// Constructs a new `Weak<T>`, allocating memory for `T` without initializing
- /// it. Calling [`upgrade`] on the return value always gives [`None`].
+ /// Constructs a new `Weak<T>`, without allocating memory.
+ /// Calling [`upgrade`] on the return value always gives [`None`].
///
/// [`upgrade`]: struct.Weak.html#method.upgrade
/// [`None`]: ../../std/option/enum.Option.html#variant.None
// weak count can only be locked if there was precisely one weak ref,
// meaning that drop could only subsequently run ON that remaining weak
// ref, which can only happen after the lock is released.
- if self.inner().weak.fetch_sub(1, Release) == 1 {
+ let inner = if self.ptr.as_ptr() as *const u8 as usize == WEAK_EMPTY {
+ return;
+ } else {
+ unsafe { self.ptr.as_ref() }
+ };
+
+ if inner.weak.fetch_sub(1, Release) == 1 {
atomic::fence(Acquire);
unsafe {
Global.dealloc(self.ptr.cast(), Layout::for_value(self.ptr.as_ref()))
/// [`split_at_mut`]: #method.split_at_mut
#[stable(feature = "copy_from_slice", since = "1.9.0")]
pub fn copy_from_slice(&mut self, src: &[T]) where T: Copy {
- assert!(self.len() == src.len(),
- "destination and source slices have different lengths");
+ assert_eq!(self.len(), src.len(),
+ "destination and source slices have different lengths");
unsafe {
ptr::copy_nonoverlapping(
src.as_ptr(), self.as_mut_ptr(), self.len());
//! user of the `DepNode` API of having to know how to compute the expected
//! fingerprint for a given set of node parameters.
-use mir::interpret::{GlobalId, ConstValue};
+use mir::interpret::GlobalId;
use hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX};
use hir::map::DefPathHash;
use hir::{HirId, ItemLocalId};
CanonicalPredicateGoal, CanonicalTypeOpProvePredicateGoal, CanonicalTypeOpNormalizeGoal,
};
use ty::{TyCtxt, FnSig, Instance, InstanceDef,
- ParamEnv, ParamEnvAnd, Predicate, PolyFnSig, PolyTraitRef, Ty};
+ ParamEnv, ParamEnvAnd, Predicate, PolyFnSig, PolyTraitRef, Ty, self};
use ty::subst::Substs;
// erase!() just makes tokens go away. It's used to specify which macro argument
// queries). Making them anonymous avoids hashing the result, which
// may save a bit of time.
[anon] EraseRegionsTy { ty: Ty<'tcx> },
- [anon] ConstValueToAllocation { val: ConstValue<'tcx>, ty: Ty<'tcx> },
+ [anon] ConstValueToAllocation { val: &'tcx ty::Const<'tcx> },
[input] Freevars(DefId),
[input] MaybeUnusedTraitImport(DefId),
});
impl<'a, 'gcx> HashStable<StableHashingContext<'a>>
-for ::middle::const_val::ConstVal<'gcx> {
+for ::mir::interpret::ConstValue<'gcx> {
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a>,
hasher: &mut StableHasher<W>) {
- use middle::const_val::ConstVal::*;
+ use mir::interpret::ConstValue::*;
mem::discriminant(self).hash_stable(hcx, hasher);
def_id.hash_stable(hcx, hasher);
substs.hash_stable(hcx, hasher);
}
- Value(ref value) => {
- value.hash_stable(hcx, hasher);
- }
- }
- }
-}
-
-impl<'a, 'gcx> HashStable<StableHashingContext<'a>>
-for ::mir::interpret::ConstValue<'gcx> {
- fn hash_stable<W: StableHasherResult>(&self,
- hcx: &mut StableHashingContext<'a>,
- hasher: &mut StableHasher<W>) {
- use mir::interpret::ConstValue::*;
-
- mem::discriminant(self).hash_stable(hcx, hasher);
-
- match *self {
Scalar(val) => {
val.hash_stable(hcx, hasher);
}
val
});
-impl_stable_hash_for!(struct ::middle::const_val::ConstEvalErr<'tcx> {
+impl_stable_hash_for!(struct ::mir::interpret::ConstEvalErr<'tcx> {
span,
- kind
+ stacktrace,
+ error
});
-impl_stable_hash_for!(struct ::middle::const_val::FrameInfo {
+impl_stable_hash_for!(struct ::mir::interpret::FrameInfo {
span,
lint_root,
location
});
-impl<'a, 'gcx> HashStable<StableHashingContext<'a>>
-for ::middle::const_val::ErrKind<'gcx> {
- fn hash_stable<W: StableHasherResult>(&self,
- hcx: &mut StableHashingContext<'a>,
- hasher: &mut StableHasher<W>) {
- use middle::const_val::ErrKind::*;
-
- mem::discriminant(self).hash_stable(hcx, hasher);
-
- match *self {
- TypeckError |
- CouldNotResolve |
- CheckMatchError => {
- // nothing to do
- }
- Miri(ref err, ref trace) => {
- err.hash_stable(hcx, hasher);
- trace.hash_stable(hcx, hasher);
- },
- }
- }
-}
-
impl_stable_hash_for!(struct ty::ClosureSubsts<'tcx> { substs });
impl_stable_hash_for!(struct ty::GeneratorSubsts<'tcx> { substs });
ReadFromReturnPointer |
UnimplementedTraitSelection |
TypeckError |
+ TooGeneric |
+ CheckMatchError |
DerefFunctionPointer |
ExecuteMemory |
OverflowNeg |
pub mod allocator;
pub mod borrowck;
pub mod expr_use_visitor;
- pub mod const_val;
pub mod cstore;
pub mod dataflow;
pub mod dead;
+++ /dev/null
-// Copyright 2012-2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <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 hir::def_id::DefId;
-use ty;
-use ty::subst::Substs;
-use ty::query::TyCtxtAt;
-use mir::interpret::ConstValue;
-use errors::DiagnosticBuilder;
-
-use graphviz::IntoCow;
-use syntax_pos::Span;
-use syntax::ast;
-
-use std::borrow::Cow;
-use rustc_data_structures::sync::Lrc;
-
-pub type EvalResult<'tcx> = Result<&'tcx ty::Const<'tcx>, ConstEvalErr<'tcx>>;
-
-#[derive(Copy, Clone, Debug, Hash, RustcEncodable, RustcDecodable, Eq, PartialEq, Ord, PartialOrd)]
-pub enum ConstVal<'tcx> {
- Unevaluated(DefId, &'tcx Substs<'tcx>),
- Value(ConstValue<'tcx>),
-}
-
-#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
-pub struct ConstEvalErr<'tcx> {
- pub span: Span,
- pub kind: Lrc<ErrKind<'tcx>>,
-}
-
-#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
-pub enum ErrKind<'tcx> {
-
- CouldNotResolve,
- TypeckError,
- CheckMatchError,
- Miri(::mir::interpret::EvalError<'tcx>, Vec<FrameInfo>),
-}
-
-#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
-pub struct FrameInfo {
- pub span: Span,
- pub location: String,
- pub lint_root: Option<ast::NodeId>,
-}
-
-#[derive(Clone, Debug)]
-pub enum ConstEvalErrDescription<'a, 'tcx: 'a> {
- Simple(Cow<'a, str>),
- Backtrace(&'a ::mir::interpret::EvalError<'tcx>, &'a [FrameInfo]),
-}
-
-impl<'a, 'tcx> ConstEvalErrDescription<'a, 'tcx> {
- /// 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,
- ConstEvalErrDescription::Backtrace(miri, _) => format!("{}", miri).into_cow(),
- }
- }
-}
-
-impl<'a, 'gcx, 'tcx> ConstEvalErr<'tcx> {
- pub fn description(&'a self) -> ConstEvalErrDescription<'a, 'tcx> {
- 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 {
- CouldNotResolve => simple!("could not resolve"),
- TypeckError => simple!("type-checking failed"),
- CheckMatchError => simple!("match-checking failed"),
- Miri(ref err, ref trace) => Backtrace(err, trace),
- }
- }
-
- pub fn struct_error(&self,
- tcx: TyCtxtAt<'a, 'gcx, 'tcx>,
- message: &str)
- -> Option<DiagnosticBuilder<'tcx>>
- {
- self.struct_generic(tcx, message, None, true)
- }
-
- pub fn report_as_error(&self,
- tcx: TyCtxtAt<'a, 'gcx, 'tcx>,
- message: &str
- ) {
- let err = self.struct_generic(tcx, message, None, true);
- if let Some(mut err) = err {
- err.emit();
- }
- }
-
- pub fn report_as_lint(&self,
- tcx: TyCtxtAt<'a, 'gcx, 'tcx>,
- message: &str,
- lint_root: ast::NodeId,
- ) {
- let lint = self.struct_generic(
- tcx,
- message,
- Some(lint_root),
- false,
- );
- if let Some(mut lint) = lint {
- lint.emit();
- }
- }
-
- fn struct_generic(
- &self,
- tcx: TyCtxtAt<'a, 'gcx, 'tcx>,
- message: &str,
- lint_root: Option<ast::NodeId>,
- as_err: bool,
- ) -> Option<DiagnosticBuilder<'tcx>> {
- let (msg, frames): (_, &[_]) = match *self.kind {
- ErrKind::TypeckError | ErrKind::CheckMatchError => return None,
- ErrKind::Miri(ref miri, ref frames) => {
- match miri.kind {
- ::mir::interpret::EvalErrorKind::TypeckError |
- ::mir::interpret::EvalErrorKind::Layout(_) => return None,
- ::mir::interpret::EvalErrorKind::ReferencedConstant(ref inner) => {
- inner.struct_generic(tcx, "referenced constant", lint_root, as_err)?.emit();
- (miri.to_string(), frames)
- },
- _ => (miri.to_string(), frames),
- }
- }
- _ => (self.description().into_oneline().to_string(), &[]),
- };
- trace!("reporting const eval failure at {:?}", self.span);
- let mut err = if as_err {
- struct_error(tcx, message)
- } else {
- let node_id = frames
- .iter()
- .rev()
- .filter_map(|frame| frame.lint_root)
- .next()
- .or(lint_root)
- .expect("some part of a failing const eval must be local");
- tcx.struct_span_lint_node(
- ::rustc::lint::builtin::CONST_ERR,
- node_id,
- tcx.span,
- message,
- )
- };
- err.span_label(self.span, msg);
- for FrameInfo { span, location, .. } in frames {
- err.span_label(*span, format!("inside call to `{}`", location));
- }
- Some(err)
- }
-}
-
-pub fn struct_error<'a, 'gcx, 'tcx>(
- tcx: TyCtxtAt<'a, 'gcx, 'tcx>,
- msg: &str,
-) -> DiagnosticBuilder<'tcx> {
- struct_span_err!(tcx.sess, tcx.span, E0080, "{}", msg)
-}
use std::{fmt, env};
use mir;
-use middle::const_val::ConstEvalErr;
use ty::{FnSig, Ty, layout};
use ty::layout::{Size, Align};
+use rustc_data_structures::sync::Lrc;
use super::{
Pointer, Lock, AccessKind
use backtrace::Backtrace;
+use ty;
+use ty::query::TyCtxtAt;
+use errors::DiagnosticBuilder;
+
+use syntax_pos::Span;
+use syntax::ast;
+
+pub type ConstEvalResult<'tcx> = Result<&'tcx ty::Const<'tcx>, Lrc<ConstEvalErr<'tcx>>>;
+
+#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
+pub struct ConstEvalErr<'tcx> {
+ pub span: Span,
+ pub error: ::mir::interpret::EvalError<'tcx>,
+ pub stacktrace: Vec<FrameInfo>,
+}
+
+#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
+pub struct FrameInfo {
+ pub span: Span,
+ pub location: String,
+ pub lint_root: Option<ast::NodeId>,
+}
+
+impl<'a, 'gcx, 'tcx> ConstEvalErr<'tcx> {
+ pub fn struct_error(&self,
+ tcx: TyCtxtAt<'a, 'gcx, 'tcx>,
+ message: &str)
+ -> Option<DiagnosticBuilder<'tcx>>
+ {
+ self.struct_generic(tcx, message, None)
+ }
+
+ pub fn report_as_error(&self,
+ tcx: TyCtxtAt<'a, 'gcx, 'tcx>,
+ message: &str
+ ) {
+ let err = self.struct_generic(tcx, message, None);
+ if let Some(mut err) = err {
+ err.emit();
+ }
+ }
+
+ pub fn report_as_lint(&self,
+ tcx: TyCtxtAt<'a, 'gcx, 'tcx>,
+ message: &str,
+ lint_root: ast::NodeId,
+ ) {
+ let lint = self.struct_generic(
+ tcx,
+ message,
+ Some(lint_root),
+ );
+ if let Some(mut lint) = lint {
+ lint.emit();
+ }
+ }
+
+ fn struct_generic(
+ &self,
+ tcx: TyCtxtAt<'a, 'gcx, 'tcx>,
+ message: &str,
+ lint_root: Option<ast::NodeId>,
+ ) -> Option<DiagnosticBuilder<'tcx>> {
+ match self.error.kind {
+ ::mir::interpret::EvalErrorKind::TypeckError |
+ ::mir::interpret::EvalErrorKind::TooGeneric |
+ ::mir::interpret::EvalErrorKind::CheckMatchError |
+ ::mir::interpret::EvalErrorKind::Layout(_) => return None,
+ ::mir::interpret::EvalErrorKind::ReferencedConstant(ref inner) => {
+ inner.struct_generic(tcx, "referenced constant has errors", lint_root)?.emit();
+ },
+ _ => {},
+ }
+ trace!("reporting const eval failure at {:?}", self.span);
+ let mut err = if let Some(lint_root) = lint_root {
+ let node_id = self.stacktrace
+ .iter()
+ .rev()
+ .filter_map(|frame| frame.lint_root)
+ .next()
+ .unwrap_or(lint_root);
+ tcx.struct_span_lint_node(
+ ::rustc::lint::builtin::CONST_ERR,
+ node_id,
+ tcx.span,
+ message,
+ )
+ } else {
+ struct_error(tcx, message)
+ };
+ err.span_label(self.span, self.error.to_string());
+ for FrameInfo { span, location, .. } in &self.stacktrace {
+ err.span_label(*span, format!("inside call to `{}`", location));
+ }
+ Some(err)
+ }
+}
+
+pub fn struct_error<'a, 'gcx, 'tcx>(
+ tcx: TyCtxtAt<'a, 'gcx, 'tcx>,
+ msg: &str,
+) -> DiagnosticBuilder<'tcx> {
+ struct_span_err!(tcx.sess, tcx.span, E0080, "{}", msg)
+}
+
#[derive(Debug, Clone, RustcEncodable, RustcDecodable)]
pub struct EvalError<'tcx> {
pub kind: EvalErrorKind<'tcx, u64>,
UnimplementedTraitSelection,
/// Abort in case type errors are reached
TypeckError,
+ /// Resolution can fail if we are in a too generic context
+ TooGeneric,
+ CheckMatchError,
/// Cannot compute this constant because it depends on another one
/// which already produced an error
- ReferencedConstant(ConstEvalErr<'tcx>),
+ ReferencedConstant(Lrc<ConstEvalErr<'tcx>>),
GeneratorResumedAfterReturn,
GeneratorResumedAfterPanic,
}
"there were unresolved type arguments during trait selection",
TypeckError =>
"encountered constants with type errors, stopping evaluation",
+ TooGeneric =>
+ "encountered overly generic constant",
+ CheckMatchError =>
+ "match checking failed",
ReferencedConstant(_) =>
"referenced constant has errors",
Overflow(mir::BinOp::Add) => "attempt to add with overflow",
mod error;
mod value;
-pub use self::error::{EvalError, EvalResult, EvalErrorKind, AssertMessage};
+pub use self::error::{
+ EvalError, EvalResult, EvalErrorKind, AssertMessage, ConstEvalErr, struct_error,
+ FrameInfo, ConstEvalResult,
+};
pub use self::value::{Scalar, Value, ConstValue};
use ty::layout::{Align, HasDataLayout, Size};
use ty;
+use ty::subst::Substs;
+use hir::def_id::DefId;
use super::{EvalResult, Pointer, PointerArithmetic, Allocation};
/// Represents a constant value in Rust. ByVal and ScalarPair are optimizations which
/// matches Value's optimizations for easy conversions between these two types
-#[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord, RustcEncodable, RustcDecodable, Hash)]
+#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, RustcEncodable, RustcDecodable, Hash)]
pub enum ConstValue<'tcx> {
+ /// Never returned from the `const_eval` query, but the HIR contains these frequently in order
+ /// to allow HIR creation to happen for everything before needing to be able to run constant
+ /// evaluation
+ Unevaluated(DefId, &'tcx Substs<'tcx>),
/// Used only for types with layout::abi::Scalar ABI and ZSTs which use Scalar::undef()
Scalar(Scalar),
/// Used only for types with layout::abi::ScalarPair
#[inline]
pub fn to_byval_value(&self) -> Option<Value> {
match *self {
+ ConstValue::Unevaluated(..) |
ConstValue::ByRef(..) => None,
ConstValue::ScalarPair(a, b) => Some(Value::ScalarPair(a, b)),
ConstValue::Scalar(val) => Some(Value::Scalar(val)),
#[inline]
pub fn to_scalar(&self) -> Option<Scalar> {
match *self {
- ConstValue::ByRef(..) => None,
+ ConstValue::Unevaluated(..) |
+ ConstValue::ByRef(..) |
ConstValue::ScalarPair(..) => None,
ConstValue::Scalar(val) => Some(val),
}
}
}
-/// Write a `ConstVal` in a way closer to the original source code than the `Debug` output.
+/// Write a `ConstValue` in a way closer to the original source code than the `Debug` output.
pub fn fmt_const_val<W: Write>(fmt: &mut W, const_val: &ty::Const) -> fmt::Result {
- use middle::const_val::ConstVal;
- match const_val.val {
- ConstVal::Unevaluated(..) => write!(fmt, "{:?}", const_val),
- ConstVal::Value(val) => {
- if let Some(value) = val.to_byval_value() {
- print_miri_value(value, const_val.ty, fmt)
- } else {
- write!(fmt, "{:?}:{}", val, const_val.ty)
- }
- }
+ if let Some(value) = const_val.to_byval_value() {
+ print_miri_value(value, const_val.ty, fmt)
+ } else {
+ write!(fmt, "{:?}:{}", const_val.val, const_val.ty)
}
}
use rustc_data_structures::obligation_forest::{ObligationProcessor, ProcessResult};
use std::marker::PhantomData;
use hir::def_id::DefId;
-use middle::const_val::{ConstEvalErr, ErrKind};
+use mir::interpret::ConstEvalErr;
+use mir::interpret::EvalErrorKind;
use super::CodeAmbiguity;
use super::CodeProjectionError;
ProcessResult::Error(
CodeSelectionError(ConstEvalFailure(ConstEvalErr {
span: obligation.cause.span,
- kind: ErrKind::CouldNotResolve.into(),
- }))
+ error: EvalErrorKind::TooGeneric.into(),
+ stacktrace: vec![],
+ }.into()))
)
}
},
use hir::def_id::DefId;
use infer::outlives::env::OutlivesEnvironment;
use middle::region;
-use middle::const_val::ConstEvalErr;
+use mir::interpret::ConstEvalErr;
use ty::subst::Substs;
use ty::{self, AdtKind, Slice, Ty, TyCtxt, GenericParamDefKind, ToPredicate};
use ty::error::{ExpectedFound, TypeError};
ty::PolyTraitRef<'tcx>,
ty::error::TypeError<'tcx>),
TraitNotObjectSafe(DefId),
- ConstEvalFailure(ConstEvalErr<'tcx>),
+ ConstEvalFailure(Lrc<ConstEvalErr<'tcx>>),
Overflow,
}
use hir::def_id::DefId;
use infer::{InferCtxt, InferOk};
use infer::type_variable::TypeVariableOrigin;
-use middle::const_val::ConstVal;
+use mir::interpret::ConstValue;
use mir::interpret::{GlobalId};
use rustc_data_structures::snapshot_map::{Snapshot, SnapshotMap};
use syntax::ast::Ident;
}
fn fold_const(&mut self, constant: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
- if let ConstVal::Unevaluated(def_id, substs) = constant.val {
+ if let ConstValue::Unevaluated(def_id, substs) = constant.val {
let tcx = self.selcx.tcx().global_tcx();
if let Some(param_env) = self.tcx().lift_to_global(&self.param_env) {
if substs.needs_infer() || substs.has_skol() {
use infer::{InferCtxt, InferOk};
use infer::at::At;
-use middle::const_val::ConstVal;
-use mir::interpret::GlobalId;
+use mir::interpret::{GlobalId, ConstValue};
use traits::{Obligation, ObligationCause, PredicateObligation, Reveal};
use traits::project::Normalized;
use ty::{self, Ty, TyCtxt};
}
fn fold_const(&mut self, constant: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
- if let ConstVal::Unevaluated(def_id, substs) = constant.val {
+ if let ConstValue::Unevaluated(def_id, substs) = constant.val {
let tcx = self.infcx.tcx.global_tcx();
if let Some(param_env) = self.tcx().lift_to_global(&self.param_env) {
if substs.needs_infer() || substs.has_skol() {
})
}
super::TraitNotObjectSafe(def_id) => Some(super::TraitNotObjectSafe(def_id)),
- super::ConstEvalFailure(ref err) => tcx.lift(err).map(super::ConstEvalFailure),
+ super::ConstEvalFailure(ref err) => tcx.lift(&**err).map(|err| super::ConstEvalFailure(
+ err.into(),
+ )),
super::Overflow => bug!(), // FIXME: ape ConstEvalFailure?
}
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use middle::const_val::ConstVal;
+use mir::interpret::ConstValue;
use ty::subst::Substs;
use ty::{self, Ty, TypeFlags, TypeFoldable};
fn add_const(&mut self, constant: &ty::Const) {
self.add_ty(constant.ty);
- match constant.val {
- ConstVal::Value(_) => {}
- ConstVal::Unevaluated(_, substs) => {
- self.add_flags(TypeFlags::HAS_PROJECTION);
- self.add_substs(substs);
- }
+ if let ConstValue::Unevaluated(_, substs) = constant.val {
+ self.add_flags(TypeFlags::HAS_PROJECTION);
+ self.add_substs(substs);
}
}
//! These methods return true to indicate that the visitor has found what it is looking for
//! and does not need to visit anything else.
-use middle::const_val::ConstVal;
+use mir::interpret::ConstValue;
use hir::def_id::DefId;
use ty::{self, Binder, Ty, TyCtxt, TypeFlags};
}
fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> bool {
- if let ConstVal::Unevaluated(..) = c.val {
+ if let ConstValue::Unevaluated(..) = c.val {
let projection_flags = TypeFlags::HAS_NORMALIZABLE_PROJECTION |
TypeFlags::HAS_PROJECTION;
if projection_flags.intersects(self.flags) {
})
} else {
info!("invalid enum discriminant: {:#?}", val);
- ::middle::const_val::struct_error(
+ ::mir::interpret::struct_error(
tcx.at(tcx.def_span(expr_did)),
"constant evaluation of enum discriminant resulted in non-integer",
).emit();
use dep_graph::SerializedDepNodeIndex;
use dep_graph::DepNode;
use hir::def_id::{CrateNum, DefId, DefIndex};
-use mir::interpret::{GlobalId, ConstValue};
+use mir::interpret::GlobalId;
use traits::query::{
CanonicalPredicateGoal, CanonicalProjectionGoal, CanonicalTyGoal, CanonicalTypeOpEqGoal,
CanonicalTypeOpNormalizeGoal, CanonicalTypeOpProvePredicateGoal, CanonicalTypeOpSubtypeGoal,
}
impl<'tcx> QueryDescription<'tcx> for queries::const_value_to_allocation<'tcx> {
- fn describe(_tcx: TyCtxt, (val, ty): (ConstValue<'tcx>, Ty<'tcx>)) -> String {
- format!("converting value `{:?}` ({}) to an allocation", val, ty)
+ fn describe(_tcx: TyCtxt, val: &'tcx ty::Const<'tcx>) -> String {
+ format!("converting value `{:?}` to an allocation", val)
}
}
}
}
-impl<'tcx> Key for (mir::interpret::ConstValue<'tcx>, Ty<'tcx>) {
+impl<'tcx> Key for &'tcx ty::Const<'tcx> {
fn query_crate(&self) -> CrateNum {
LOCAL_CRATE
}
use middle::stability::{self, DeprecationEntry};
use middle::lang_items::{LanguageItems, LangItem};
use middle::exported_symbols::{SymbolExportLevel, ExportedSymbol};
-use middle::const_val::EvalResult;
+use mir::interpret::ConstEvalResult;
use mir::mono::{CodegenUnit, Stats};
use mir;
-use mir::interpret::{GlobalId, Allocation, ConstValue};
+use mir::interpret::{GlobalId, Allocation};
use session::{CompileResult, CrateDisambiguator};
use session::config::OutputFilenames;
use traits::{self, Vtable};
/// Results of evaluating const items or constants embedded in
/// other items (such as enum variant explicit discriminants).
[] fn const_eval: const_eval_dep_node(ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>)
- -> EvalResult<'tcx>,
+ -> ConstEvalResult<'tcx>,
/// Converts a constant value to an constant allocation
[] fn const_value_to_allocation: const_value_to_allocation(
- (ConstValue<'tcx>, Ty<'tcx>)
+ &'tcx ty::Const<'tcx>
) -> &'tcx Allocation,
[] fn check_match: CheckMatch(DefId)
}
fn const_value_to_allocation<'tcx>(
- (val, ty): (ConstValue<'tcx>, Ty<'tcx>)
+ val: &'tcx ty::Const<'tcx>,
) -> DepConstructor<'tcx> {
- DepConstructor::ConstValueToAllocation { val, ty }
+ DepConstructor::ConstValueToAllocation { val }
}
fn type_param_predicates<'tcx>((item_id, param_id): (DefId, DefId)) -> DepConstructor<'tcx> {
//! type equality, etc.
use hir::def_id::DefId;
-use middle::const_val::ConstVal;
+use mir::interpret::ConstValue;
use ty::subst::{Kind, UnpackedKind, Substs};
use ty::{self, Ty, TyCtxt, TypeFoldable};
use ty::error::{ExpectedFound, TypeError};
return Ok(s);
}
match x.val {
- ConstVal::Unevaluated(def_id, substs) => {
+ ConstValue::Unevaluated(def_id, substs) => {
// FIXME(eddyb) get the right param_env.
let param_env = ty::ParamEnv::empty();
match tcx.lift_to_global(&substs) {
//! hand, though we've recently added some macros (e.g.,
//! `BraceStructLiftImpl!`) to help with the tedium.
-use middle::const_val::{self, ConstVal, ConstEvalErr};
+use mir::interpret::{ConstValue, ConstEvalErr};
use ty::{self, Lift, Ty, TyCtxt};
use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
use rustc_data_structures::accumulate_vec::AccumulateVec;
use rustc_data_structures::indexed_vec::{IndexVec, Idx};
-use rustc_data_structures::sync::Lrc;
use mir::interpret;
use std::rc::Rc;
impl<'a, 'tcx> Lift<'tcx> for ConstEvalErr<'a> {
type Lifted = ConstEvalErr<'tcx>;
fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
- tcx.lift(&*self.kind).map(|kind| {
+ tcx.lift(&self.error).map(|error| {
ConstEvalErr {
span: self.span,
- kind: Lrc::new(kind),
+ stacktrace: self.stacktrace.clone(),
+ error,
}
})
}
PathNotFound(ref v) => PathNotFound(v.clone()),
UnimplementedTraitSelection => UnimplementedTraitSelection,
TypeckError => TypeckError,
- ReferencedConstant(ref err) => ReferencedConstant(tcx.lift(err)?),
+ TooGeneric => TooGeneric,
+ CheckMatchError => CheckMatchError,
+ ReferencedConstant(ref err) => ReferencedConstant(tcx.lift(&**err)?.into()),
OverflowNeg => OverflowNeg,
Overflow(op) => Overflow(op),
DivisionByZero => DivisionByZero,
}
}
-impl<'a, 'tcx> Lift<'tcx> for const_val::ErrKind<'a> {
- type Lifted = const_val::ErrKind<'tcx>;
- fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
- use middle::const_val::ErrKind::*;
-
- Some(match *self {
- CouldNotResolve => CouldNotResolve,
- TypeckError => TypeckError,
- CheckMatchError => CheckMatchError,
- Miri(ref e, ref frames) => return tcx.lift(e).map(|e| Miri(e, frames.clone())),
- })
- }
-}
-
impl<'a, 'tcx> Lift<'tcx> for ty::layout::LayoutError<'a> {
type Lifted = ty::layout::LayoutError<'tcx>;
fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
}
}
-impl<'tcx> TypeFoldable<'tcx> for ConstVal<'tcx> {
+impl<'tcx> TypeFoldable<'tcx> for ConstValue<'tcx> {
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
match *self {
- ConstVal::Value(v) => ConstVal::Value(v),
- ConstVal::Unevaluated(def_id, substs) => {
- ConstVal::Unevaluated(def_id, substs.fold_with(folder))
+ ConstValue::Scalar(v) => ConstValue::Scalar(v),
+ ConstValue::ScalarPair(a, b) => ConstValue::ScalarPair(a, b),
+ ConstValue::ByRef(alloc, offset) => ConstValue::ByRef(alloc, offset),
+ ConstValue::Unevaluated(def_id, substs) => {
+ ConstValue::Unevaluated(def_id, substs.fold_with(folder))
}
}
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
match *self {
- ConstVal::Value(_) => false,
- ConstVal::Unevaluated(_, substs) => substs.visit_with(visitor),
+ ConstValue::Scalar(_) |
+ ConstValue::ScalarPair(_, _) |
+ ConstValue::ByRef(_, _) => false,
+ ConstValue::Unevaluated(_, substs) => substs.visit_with(visitor),
}
}
}
use hir::def_id::DefId;
-use middle::const_val::ConstVal;
+use mir::interpret::ConstValue;
use middle::region;
use polonius_engine::Atom;
use rustc_data_structures::indexed_vec::Idx;
use ty::{self, AdtDef, TypeFlags, Ty, TyCtxt, TypeFoldable};
use ty::{Slice, TyS, ParamEnvAnd, ParamEnv};
use util::captures::Captures;
-use mir::interpret::{Scalar, Pointer, Value, ConstValue};
+use mir::interpret::{Scalar, Pointer, Value};
use std::iter;
use std::cmp::Ordering;
pub struct Const<'tcx> {
pub ty: Ty<'tcx>,
- pub val: ConstVal<'tcx>,
+ pub val: ConstValue<'tcx>,
}
impl<'tcx> Const<'tcx> {
ty: Ty<'tcx>,
) -> &'tcx Self {
tcx.mk_const(Const {
- val: ConstVal::Unevaluated(def_id, substs),
+ val: ConstValue::Unevaluated(def_id, substs),
ty,
})
}
#[inline]
- pub fn from_const_val(
+ pub fn from_const_value(
tcx: TyCtxt<'_, '_, 'tcx>,
- val: ConstVal<'tcx>,
+ val: ConstValue<'tcx>,
ty: Ty<'tcx>,
) -> &'tcx Self {
tcx.mk_const(Const {
})
}
- #[inline]
- pub fn from_const_value(
- tcx: TyCtxt<'_, '_, 'tcx>,
- val: ConstValue<'tcx>,
- ty: Ty<'tcx>,
- ) -> &'tcx Self {
- Self::from_const_val(tcx, ConstVal::Value(val), ty)
- }
-
#[inline]
pub fn from_byval_value(
tcx: TyCtxt<'_, '_, 'tcx>,
}
let ty = tcx.lift_to_global(&ty).unwrap();
let size = tcx.layout_of(ty).ok()?.size;
- match self.val {
- ConstVal::Value(val) => val.to_bits(size),
- _ => None,
- }
+ self.val.to_bits(size)
}
#[inline]
pub fn to_ptr(&self) -> Option<Pointer> {
- match self.val {
- ConstVal::Value(val) => val.to_ptr(),
- _ => None,
- }
+ self.val.to_ptr()
}
#[inline]
pub fn to_byval_value(&self) -> Option<Value> {
- match self.val {
- ConstVal::Value(val) => val.to_byval_value(),
- _ => None,
- }
+ self.val.to_byval_value()
}
#[inline]
pub fn to_scalar(&self) -> Option<Scalar> {
- match self.val {
- ConstVal::Value(val) => val.to_scalar(),
- _ => None,
- }
+ self.val.to_scalar()
}
#[inline]
assert_eq!(self.ty, ty.value);
let ty = tcx.lift_to_global(&ty).unwrap();
let size = tcx.layout_of(ty).ok()?.size;
- match self.val {
- ConstVal::Value(val) => val.to_bits(size),
- _ => None,
- }
+ self.val.to_bits(size)
}
#[inline]
//! An iterator over the type substructure.
//! WARNING: this does not keep track of the region depth.
-use middle::const_val::ConstVal;
+use mir::interpret::ConstValue;
use ty::{self, Ty};
use rustc_data_structures::small_vec::SmallVec;
use rustc_data_structures::accumulate_vec::IntoIter as AccIntoIter;
}
fn push_const<'tcx>(stack: &mut TypeWalkerStack<'tcx>, constant: &'tcx ty::Const<'tcx>) {
- match constant.val {
- ConstVal::Value(_) => {}
- ConstVal::Unevaluated(_, substs) => {
- stack.extend(substs.types().rev());
- }
+ if let ConstValue::Unevaluated(_, substs) = constant.val {
+ stack.extend(substs.types().rev());
}
stack.push(constant.ty);
}
// except according to those terms.
use hir::def_id::DefId;
-use middle::const_val::ConstVal;
+use mir::interpret::ConstValue;
use infer::InferCtxt;
use ty::subst::Substs;
use traits;
/// into `self.out`.
fn compute_const(&mut self, constant: &'tcx ty::Const<'tcx>) {
self.require_sized(constant.ty, traits::ConstSized);
- match constant.val {
- ConstVal::Value(_) => {}
- ConstVal::Unevaluated(def_id, substs) => {
- let obligations = self.nominal_obligations(def_id, substs);
- self.out.extend(obligations);
-
- let predicate = ty::Predicate::ConstEvaluatable(def_id, substs);
- let cause = self.cause(traits::MiscObligation);
- self.out.push(traits::Obligation::new(cause,
- self.param_env,
- predicate));
- }
+ if let ConstValue::Unevaluated(def_id, substs) = constant.val {
+ let obligations = self.nominal_obligations(def_id, substs);
+ self.out.extend(obligations);
+
+ let predicate = ty::Predicate::ConstEvaluatable(def_id, substs);
+ let cause = self.cause(traits::MiscObligation);
+ self.out.push(traits::Obligation::new(cause,
+ self.param_env,
+ predicate));
}
}
use hir::def_id::DefId;
use hir::map::definitions::DefPathData;
-use middle::const_val::ConstVal;
+use mir::interpret::ConstValue;
use middle::region::{self, BlockRemainder};
use ty::subst::{self, Subst};
use ty::{BrAnon, BrEnv, BrFresh, BrNamed};
TyArray(ty, sz) => {
print!(f, cx, write("["), print(ty), write("; "))?;
match sz.val {
- ConstVal::Value(..) => ty::tls::with(|tcx| {
- write!(f, "{}", sz.unwrap_usize(tcx))
- })?,
- ConstVal::Unevaluated(_def_id, _substs) => {
+ ConstValue::Unevaluated(_def_id, _substs) => {
write!(f, "_")?;
}
+ _ => ty::tls::with(|tcx| {
+ write!(f, "{}", sz.unwrap_usize(tcx))
+ })?,
}
write!(f, "]")
}
fn fetch_wasm_section(tcx: TyCtxt, id: DefId) -> (String, Vec<u8>) {
use rustc::mir::interpret::GlobalId;
- use rustc::middle::const_val::ConstVal;
info!("loading wasm section {:?}", id);
};
let param_env = ty::ParamEnv::reveal_all();
let val = tcx.const_eval(param_env.and(cid)).unwrap();
-
- let const_val = match val.val {
- ConstVal::Value(val) => val,
- ConstVal::Unevaluated(..) => bug!("should be evaluated"),
- };
-
- let alloc = tcx.const_value_to_allocation((const_val, val.ty));
+ let alloc = tcx.const_value_to_allocation(val);
(section.to_string(), alloc.bytes.clone())
}
// except according to those terms.
use llvm::{self, ValueRef};
-use rustc::middle::const_val::{ConstVal, ConstEvalErr};
+use rustc::mir::interpret::ConstEvalErr;
use rustc_mir::interpret::{read_target_uint, const_val_field};
use rustc::hir::def_id::DefId;
use rustc::mir;
use rustc_data_structures::indexed_vec::Idx;
+use rustc_data_structures::sync::Lrc;
use rustc::mir::interpret::{GlobalId, Pointer, Scalar, Allocation, ConstValue, AllocType};
use rustc::ty::{self, Ty};
use rustc::ty::layout::{self, HasDataLayout, LayoutOf, Size};
pub fn codegen_static_initializer<'a, 'tcx>(
cx: &CodegenCx<'a, 'tcx>,
def_id: DefId)
- -> Result<ValueRef, ConstEvalErr<'tcx>>
+ -> Result<ValueRef, Lrc<ConstEvalErr<'tcx>>>
{
let instance = ty::Instance::mono(cx.tcx, def_id);
let cid = GlobalId {
let static_ = cx.tcx.const_eval(param_env.and(cid))?;
let alloc = match static_.val {
- ConstVal::Value(ConstValue::ByRef(alloc, n)) if n.bytes() == 0 => alloc,
+ ConstValue::ByRef(alloc, n) if n.bytes() == 0 => alloc,
_ => bug!("static const eval returned {:#?}", static_),
};
Ok(const_alloc_to_llvm(cx, alloc))
}
impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
- fn const_to_const_value(
+ fn fully_evaluate(
&mut self,
bx: &Builder<'a, 'tcx>,
constant: &'tcx ty::Const<'tcx>,
- ) -> Result<ConstValue<'tcx>, ConstEvalErr<'tcx>> {
+ ) -> Result<&'tcx ty::Const<'tcx>, Lrc<ConstEvalErr<'tcx>>> {
match constant.val {
- ConstVal::Unevaluated(def_id, ref substs) => {
+ ConstValue::Unevaluated(def_id, ref substs) => {
let tcx = bx.tcx();
let param_env = ty::ParamEnv::reveal_all();
let instance = ty::Instance::resolve(tcx, param_env, def_id, substs).unwrap();
instance,
promoted: None,
};
- let c = tcx.const_eval(param_env.and(cid))?;
- self.const_to_const_value(bx, c)
+ tcx.const_eval(param_env.and(cid))
},
- ConstVal::Value(val) => Ok(val),
+ _ => Ok(constant),
}
}
- pub fn mir_constant_to_const_value(
+ pub fn eval_mir_constant(
&mut self,
bx: &Builder<'a, 'tcx>,
constant: &mir::Constant<'tcx>,
- ) -> Result<ConstValue<'tcx>, ConstEvalErr<'tcx>> {
+ ) -> Result<&'tcx ty::Const<'tcx>, Lrc<ConstEvalErr<'tcx>>> {
match constant.literal {
mir::Literal::Promoted { index } => {
let param_env = ty::ParamEnv::reveal_all();
mir::Literal::Value { value } => {
Ok(self.monomorphize(&value))
}
- }.and_then(|c| self.const_to_const_value(bx, c))
+ }.and_then(|c| self.fully_evaluate(bx, c))
}
/// process constant containing SIMD shuffle indices
bx: &Builder<'a, 'tcx>,
constant: &mir::Constant<'tcx>,
) -> (ValueRef, Ty<'tcx>) {
- self.mir_constant_to_const_value(bx, constant)
+ self.eval_mir_constant(bx, constant)
.and_then(|c| {
- let field_ty = constant.ty.builtin_index().unwrap();
- let fields = match constant.ty.sty {
+ let field_ty = c.ty.builtin_index().unwrap();
+ let fields = match c.ty.sty {
ty::TyArray(_, n) => n.unwrap_usize(bx.tcx()),
ref other => bug!("invalid simd shuffle type: {}", other),
};
- let values: Result<Vec<ValueRef>, _> = (0..fields).map(|field| {
+ let values: Result<Vec<ValueRef>, Lrc<_>> = (0..fields).map(|field| {
let field = const_val_field(
bx.tcx(),
ty::ParamEnv::reveal_all(),
None,
mir::Field::new(field as usize),
c,
- constant.ty,
)?;
if let Some(prim) = field.to_scalar() {
let layout = bx.cx.layout_of(field_ty);
}
}).collect();
let llval = C_struct(bx.cx, &values?, false);
- Ok((llval, constant.ty))
+ Ok((llval, c.ty))
})
.unwrap_or_else(|e| {
e.report_as_error(
// except according to those terms.
use llvm::{ValueRef, LLVMConstInBoundsGEP};
-use rustc::middle::const_val::ConstEvalErr;
+use rustc::mir::interpret::ConstEvalErr;
use rustc::mir;
use rustc::mir::interpret::ConstValue;
use rustc::ty;
use rustc::ty::layout::{self, Align, LayoutOf, TyLayout};
use rustc_data_structures::indexed_vec::Idx;
+use rustc_data_structures::sync::Lrc;
use base;
use common::{self, CodegenCx, C_null, C_undef, C_usize};
}
pub fn from_const(bx: &Builder<'a, 'tcx>,
- val: ConstValue<'tcx>,
- ty: ty::Ty<'tcx>)
- -> Result<OperandRef<'tcx>, ConstEvalErr<'tcx>> {
- let layout = bx.cx.layout_of(ty);
+ val: &'tcx ty::Const<'tcx>)
+ -> Result<OperandRef<'tcx>, Lrc<ConstEvalErr<'tcx>>> {
+ let layout = bx.cx.layout_of(val.ty);
if layout.is_zst() {
return Ok(OperandRef::new_zst(bx.cx, layout));
}
- let val = match val {
+ let val = match val.val {
+ ConstValue::Unevaluated(..) => bug!(),
ConstValue::Scalar(x) => {
let scalar = match layout.abi {
layout::Abi::Scalar(ref x) => x,
mir::Operand::Constant(ref constant) => {
let ty = self.monomorphize(&constant.ty);
- self.mir_constant_to_const_value(bx, constant)
- .and_then(|c| OperandRef::from_const(bx, c, ty))
+ self.eval_mir_constant(bx, constant)
+ .and_then(|c| OperandRef::from_const(bx, c))
.unwrap_or_else(|err| {
match constant.literal {
mir::Literal::Promoted { .. } => {
use self::Usefulness::*;
use self::WitnessPreference::*;
-use rustc::middle::const_val::ConstVal;
-
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::indexed_vec::Idx;
for row in patterns {
match *row.kind {
- PatternKind::Constant {
- value: const_val @ &ty::Const {
- val: ConstVal::Value(..),
- ..
- }
- } => {
- if let Some(ptr) = const_val.to_ptr() {
- let is_array_ptr = const_val.ty
+ PatternKind::Constant { value } => {
+ if let Some(ptr) = value.to_ptr() {
+ let is_array_ptr = value.ty
.builtin_deref(true)
.and_then(|t| t.ty.builtin_index())
.map_or(false, |t| t == cx.tcx.types.u8);
suffix: &[Pattern<'tcx>]
) -> Result<bool, ErrorReported> {
let data: &[u8] = match *ctor {
- ConstantValue(&ty::Const { val: ConstVal::Value(const_val), ty }) => {
- let val = match const_val {
- ConstValue::ByRef(..) => bug!("unexpected ConstValue::ByRef"),
+ ConstantValue(const_val) => {
+ let val = match const_val.val {
+ ConstValue::Unevaluated(..) |
+ ConstValue::ByRef(..) => bug!("unexpected ConstValue: {:?}", const_val),
ConstValue::Scalar(val) | ConstValue::ScalarPair(val, _) => val,
};
if let Ok(ptr) = val.to_ptr() {
- let is_array_ptr = ty
+ let is_array_ptr = const_val.ty
.builtin_deref(true)
.and_then(|t| t.ty.builtin_index())
.map_or(false, |t| t == tcx.types.u8);
}
PatternError::FloatBug => {
// FIXME(#31407) this is only necessary because float parsing is buggy
- ::rustc::middle::const_val::struct_error(
+ ::rustc::mir::interpret::struct_error(
self.tcx.at(pat_span),
"could not evaluate float literal (see issue #31407)",
).emit();
}
PatternError::NonConstPath(span) => {
- ::rustc::middle::const_val::struct_error(
+ ::rustc::mir::interpret::struct_error(
self.tcx.at(span),
"runtime values cannot be referenced in patterns",
).emit();
use interpret::{const_val_field, const_variant_index, self};
-use rustc::middle::const_val::ConstVal;
use rustc::mir::{fmt_const_val, Field, BorrowKind, Mutability};
use rustc::mir::interpret::{Scalar, GlobalId, ConstValue, Value};
use rustc::ty::{self, TyCtxt, AdtDef, Ty, Region};
},
}
-fn print_const_val(value: &ty::Const, f: &mut fmt::Formatter) -> fmt::Result {
- match value.val {
- ConstVal::Value(..) => fmt_const_val(f, value),
- ConstVal::Unevaluated(..) => bug!("{:?} not printable in a pattern", value)
- }
-}
-
impl<'tcx> fmt::Display for Pattern<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self.kind {
write!(f, "{}", subpattern)
}
PatternKind::Constant { value } => {
- print_const_val(value, f)
+ fmt_const_val(f, value)
}
PatternKind::Range { lo, hi, end } => {
- print_const_val(lo, f)?;
+ fmt_const_val(f, lo)?;
match end {
RangeEnd::Included => write!(f, "...")?,
RangeEnd::Excluded => write!(f, "..")?,
}
- print_const_val(hi, f)
+ fmt_const_val(f, hi)
}
PatternKind::Slice { ref prefix, ref slice, ref suffix } |
PatternKind::Array { ref prefix, ref slice, ref suffix } => {
debug!("const_to_pat: cv={:#?}", cv);
let adt_subpattern = |i, variant_opt| {
let field = Field::new(i);
- let val = match cv.val {
- ConstVal::Value(miri) => const_val_field(
- self.tcx, self.param_env, instance,
- variant_opt, field, miri, cv.ty,
- ).expect("field access failed"),
- _ => bug!("{:#?} is not a valid adt", cv),
- };
+ let val = const_val_field(
+ self.tcx, self.param_env, instance,
+ variant_opt, field, cv,
+ ).expect("field access failed");
self.const_to_pat(instance, val, id, span)
};
let adt_subpatterns = |n, variant_opt| {
PatternKind::Wild
},
ty::TyAdt(adt_def, substs) if adt_def.is_enum() => {
- match cv.val {
- ConstVal::Value(val) => {
- let variant_index = const_variant_index(
- self.tcx, self.param_env, instance, val, cv.ty
- ).expect("const_variant_index failed");
- let subpatterns = adt_subpatterns(
- adt_def.variants[variant_index].fields.len(),
- Some(variant_index),
- );
- PatternKind::Variant {
- adt_def,
- substs,
- variant_index,
- subpatterns,
- }
- },
- ConstVal::Unevaluated(..) =>
- span_bug!(span, "{:#?} is not a valid enum constant", cv),
+ let variant_index = const_variant_index(
+ self.tcx, self.param_env, instance, cv
+ ).expect("const_variant_index failed");
+ let subpatterns = adt_subpatterns(
+ adt_def.variants[variant_index].fields.len(),
+ Some(variant_index),
+ );
+ PatternKind::Variant {
+ adt_def,
+ substs,
+ variant_index,
+ subpatterns,
}
},
ty::TyAdt(adt_def, _) => {
use rustc::hir;
-use rustc::middle::const_val::{ConstEvalErr, ErrKind};
-use rustc::middle::const_val::ErrKind::{TypeckError, CheckMatchError};
+use rustc::mir::interpret::{ConstEvalErr};
use rustc::mir;
use rustc::ty::{self, TyCtxt, Ty, Instance};
use rustc::ty::layout::{self, LayoutOf, Primitive};
use std::fmt;
use std::error::Error;
-use rustc_data_structures::sync::Lrc;
pub fn mk_borrowck_eval_cx<'a, 'mir, 'tcx>(
tcx: TyCtxt<'a, 'tcx, 'tcx>,
let (frames, span) = ecx.generate_stacktrace(None);
let err = ConstEvalErr {
span,
- kind: ErrKind::Miri(err, frames).into(),
+ error: err,
+ stacktrace: frames,
};
err.report_as_error(
ecx.tcx,
instance: ty::Instance<'tcx>,
variant: Option<usize>,
field: mir::Field,
- value: ConstValue<'tcx>,
- ty: Ty<'tcx>,
-) -> ::rustc::middle::const_val::EvalResult<'tcx> {
- trace!("const_val_field: {:?}, {:?}, {:?}, {:?}", instance, field, value, ty);
+ value: &'tcx ty::Const<'tcx>,
+) -> ::rustc::mir::interpret::ConstEvalResult<'tcx> {
+ trace!("const_val_field: {:?}, {:?}, {:?}", instance, field, value);
let mut ecx = mk_eval_cx(tcx, instance, param_env).unwrap();
let result = (|| {
- let value = ecx.const_value_to_value(value, ty)?;
+ let ty = value.ty;
+ let value = ecx.const_to_value(value.val)?;
let layout = ecx.layout_of(ty)?;
let (ptr, align) = match value {
Value::ByRef(ptr, align) => (ptr, align),
})();
result.map_err(|err| {
let (trace, span) = ecx.generate_stacktrace(None);
- let err = ErrKind::Miri(err, trace);
ConstEvalErr {
- kind: err.into(),
+ error: err,
+ stacktrace: trace,
span,
- }
+ }.into()
})
}
tcx: TyCtxt<'a, 'tcx, 'tcx>,
param_env: ty::ParamEnv<'tcx>,
instance: ty::Instance<'tcx>,
- val: ConstValue<'tcx>,
- ty: Ty<'tcx>,
+ val: &'tcx ty::Const<'tcx>,
) -> EvalResult<'tcx, usize> {
- trace!("const_variant_index: {:?}, {:?}, {:?}", instance, val, ty);
+ trace!("const_variant_index: {:?}, {:?}", instance, val);
let mut ecx = mk_eval_cx(tcx, instance, param_env).unwrap();
- let value = ecx.const_value_to_value(val, ty)?;
+ let value = ecx.const_to_value(val.val)?;
let (ptr, align) = match value {
Value::ScalarPair(..) | Value::Scalar(_) => {
- let layout = ecx.layout_of(ty)?;
+ let layout = ecx.layout_of(val.ty)?;
let ptr = ecx.memory.allocate(layout.size, layout.align, Some(MemoryKind::Stack))?.into();
- ecx.write_value_to_ptr(value, ptr, layout.align, ty)?;
+ ecx.write_value_to_ptr(value, ptr, layout.align, val.ty)?;
(ptr, layout.align)
},
Value::ByRef(ptr, align) => (ptr, align),
};
let place = Place::from_scalar_ptr(ptr, align);
- ecx.read_discriminant_as_variant_index(place, ty)
+ ecx.read_discriminant_as_variant_index(place, val.ty)
}
pub fn const_value_to_allocation_provider<'a, 'tcx>(
tcx: TyCtxt<'a, 'tcx, 'tcx>,
- (val, ty): (ConstValue<'tcx>, Ty<'tcx>),
+ val: &'tcx ty::Const<'tcx>,
) -> &'tcx Allocation {
- match val {
+ match val.val {
ConstValue::ByRef(alloc, offset) => {
assert_eq!(offset.bytes(), 0);
return alloc;
ty::ParamEnv::reveal_all(),
CompileTimeEvaluator,
());
- let value = ecx.const_value_to_value(val, ty)?;
- let layout = ecx.layout_of(ty)?;
+ let value = ecx.const_to_value(val.val)?;
+ let layout = ecx.layout_of(val.ty)?;
let ptr = ecx.memory.allocate(layout.size, layout.align, Some(MemoryKind::Stack))?;
- ecx.write_value_to_ptr(value, ptr.into(), layout.align, ty)?;
+ ecx.write_value_to_ptr(value, ptr.into(), layout.align, val.ty)?;
let alloc = ecx.memory.get(ptr.alloc_id)?;
Ok(tcx.intern_const_alloc(alloc.clone()))
};
- result().expect("unable to convert ConstVal to Allocation")
+ result().expect("unable to convert ConstValue to Allocation")
}
pub fn const_eval_provider<'a, 'tcx>(
tcx: TyCtxt<'a, 'tcx, 'tcx>,
key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>,
-) -> ::rustc::middle::const_val::EvalResult<'tcx> {
+) -> ::rustc::mir::interpret::ConstEvalResult<'tcx> {
trace!("const eval: {:?}", key);
let cid = key.value;
let def_id = cid.instance.def.def_id();
// Do match-check before building MIR
if tcx.check_match(def_id).is_err() {
return Err(ConstEvalErr {
- kind: Lrc::new(CheckMatchError),
+ error: EvalErrorKind::CheckMatchError.into(),
+ stacktrace: vec![],
span,
- });
+ }.into());
}
if let hir::BodyOwnerKind::Const = tcx.hir.body_owner_kind(id) {
// Do not continue into miri if typeck errors occurred; it will fail horribly
if tables.tainted_by_errors {
return Err(ConstEvalErr {
- kind: Lrc::new(TypeckError),
+ error: EvalErrorKind::CheckMatchError.into(),
+ stacktrace: vec![],
span,
- });
+ }.into());
}
};
Ok(value_to_const_value(&ecx, val, miri_ty))
}).map_err(|err| {
let (trace, span) = ecx.generate_stacktrace(None);
- let err = ErrKind::Miri(err, trace);
let err = ConstEvalErr {
- kind: err.into(),
+ error: err,
+ stacktrace: trace,
span,
};
if tcx.is_static(def_id).is_some() {
err.report_as_error(ecx.tcx, "could not evaluate static initializer");
}
- err
+ err.into()
})
}
use rustc::hir::def_id::DefId;
use rustc::hir::def::Def;
use rustc::hir::map::definitions::DefPathData;
-use rustc::middle::const_val::ConstVal;
use rustc::mir;
use rustc::ty::layout::{self, Size, Align, HasDataLayout, IntegerExt, LayoutOf, TyLayout};
use rustc::ty::subst::{Subst, Substs};
use rustc::ty::{self, Ty, TyCtxt, TypeAndMut};
use rustc::ty::query::TyCtxtAt;
use rustc_data_structures::indexed_vec::{IndexVec, Idx};
-use rustc::middle::const_val::FrameInfo;
+use rustc::mir::interpret::FrameInfo;
use syntax::codemap::{self, Span};
use syntax::ast::Mutability;
use rustc::mir::interpret::{
Ok(Scalar::Ptr(ptr).to_value_with_len(s.len() as u64, self.tcx.tcx))
}
- pub fn const_value_to_value(
+ pub fn const_to_value(
&mut self,
val: ConstValue<'tcx>,
- _ty: Ty<'tcx>,
) -> EvalResult<'tcx, Value> {
match val {
+ ConstValue::Unevaluated(def_id, substs) => {
+ let instance = self.resolve(def_id, substs)?;
+ self.read_global_as_value(GlobalId {
+ instance,
+ promoted: None,
+ })
+ }
ConstValue::ByRef(alloc, offset) => {
// FIXME: Allocate new AllocId for all constants inside
let id = self.memory.allocate_value(alloc.clone(), Some(MemoryKind::Stack))?;
}
}
- pub(super) fn const_to_value(
- &mut self,
- const_val: &ConstVal<'tcx>,
- ty: Ty<'tcx>
- ) -> EvalResult<'tcx, Value> {
- match *const_val {
- ConstVal::Unevaluated(def_id, substs) => {
- let instance = self.resolve(def_id, substs)?;
- self.read_global_as_value(GlobalId {
- instance,
- promoted: None,
- }, ty)
- }
- ConstVal::Value(val) => self.const_value_to_value(val, ty)
- }
- }
-
pub(super) fn resolve(&self, def_id: DefId, substs: &'tcx Substs<'tcx>) -> EvalResult<'tcx, ty::Instance<'tcx>> {
trace!("resolve: {:?}, {:#?}", def_id, substs);
trace!("substs: {:#?}", self.substs());
self.param_env,
def_id,
substs,
- ).ok_or_else(|| EvalErrorKind::TypeckError.into()) // turn error prop into a panic to expose associated type in const issue
+ ).ok_or_else(|| EvalErrorKind::TooGeneric.into())
}
pub(super) fn type_is_sized(&self, ty: Ty<'tcx>) -> bool {
self.param_env,
def_id,
substs,
- ).ok_or_else(|| EvalErrorKind::TypeckError.into());
+ ).ok_or_else(|| EvalErrorKind::TooGeneric.into());
let fn_ptr = self.memory.create_fn_alloc(instance?);
let valty = ValTy {
value: Value::Scalar(fn_ptr.into()),
use rustc::mir::Literal;
let mir::Constant { ref literal, .. } = **constant;
let value = match *literal {
- Literal::Value { ref value } => self.const_to_value(&value.val, ty)?,
+ Literal::Value { ref value } => self.const_to_value(value.val)?,
Literal::Promoted { index } => {
let instance = self.frame().instance;
self.read_global_as_value(GlobalId {
instance,
promoted: Some(index),
- }, ty)?
+ })?
}
};
Ok(())
}
- pub fn read_global_as_value(&mut self, gid: GlobalId<'tcx>, ty: Ty<'tcx>) -> EvalResult<'tcx, Value> {
- if self.tcx.is_static(gid.instance.def_id()).is_some() {
- let alloc_id = self
- .tcx
- .alloc_map
- .lock()
- .intern_static(gid.instance.def_id());
- let layout = self.layout_of(ty)?;
- return Ok(Value::ByRef(Scalar::Ptr(alloc_id.into()), layout.align))
- }
+ pub fn read_global_as_value(&mut self, gid: GlobalId<'tcx>) -> EvalResult<'tcx, Value> {
let cv = self.const_eval(gid)?;
- self.const_to_value(&cv.val, ty)
+ self.const_to_value(cv.val)
}
pub fn const_eval(&self, gid: GlobalId<'tcx>) -> EvalResult<'tcx, &'tcx ty::Const<'tcx>> {
use rustc::ty::query::TyCtxtAt;
use rustc::ty::layout::{self, Align, TargetDataLayout, Size};
use syntax::ast::Mutability;
-use rustc::middle::const_val::ConstVal;
use rustc_data_structures::fx::{FxHashSet, FxHashMap};
use rustc::mir::interpret::{Pointer, AllocId, Allocation, AccessKind, Value,
instance,
promoted: None,
};
- self.tcx.const_eval(ParamEnv::reveal_all().and(gid)).map_err(|_| {
+ self.tcx.const_eval(ParamEnv::reveal_all().and(gid)).map_err(|err| {
// no need to report anything, the const_eval call takes care of that for statics
assert!(self.tcx.is_static(def_id).is_some());
- EvalErrorKind::TypeckError.into()
+ EvalErrorKind::ReferencedConstant(err).into()
}).map(|val| {
- let const_val = match val.val {
- ConstVal::Value(val) => val,
- ConstVal::Unevaluated(..) => bug!("should be evaluated"),
- };
- self.tcx.const_value_to_allocation((const_val, val.ty))
+ self.tcx.const_value_to_allocation(val)
})
}
// These ops can have an RHS with a different numeric type.
if right_kind.is_int() && (bin_op == Shl || bin_op == Shr) {
let signed = left_layout.abi.is_signed();
+ let mut oflo = (r as u32 as u128) != r;
let mut r = r as u32;
let size = left_layout.size.bits() as u32;
- let oflo = r >= size;
+ oflo |= r >= size;
if oflo {
r %= size;
}
use rustc::hir::map as hir_map;
use rustc::hir::def_id::DefId;
-use rustc::middle::const_val::ConstVal;
use rustc::mir::interpret::{AllocId, ConstValue};
use rustc::middle::lang_items::{ExchangeMallocFnLangItem, StartFnLangItem};
use rustc::ty::subst::Substs;
match tcx.const_eval(param_env.and(cid)) {
Ok(val) => collect_const(tcx, val, instance.substs, output),
Err(err) => {
- use rustc::middle::const_val::ErrKind;
use rustc::mir::interpret::EvalErrorKind;
- if let ErrKind::Miri(ref miri, ..) = *err.kind {
- if let EvalErrorKind::ReferencedConstant(_) = miri.kind {
- err.report_as_error(
- tcx.at(mir.promoted[i].span),
- "erroneous constant used",
- );
- }
+ if let EvalErrorKind::ReferencedConstant(_) = err.error.kind {
+ err.report_as_error(
+ tcx.at(mir.promoted[i].span),
+ "erroneous constant used",
+ );
}
},
}
debug!("visiting const {:?}", *constant);
let val = match constant.val {
- ConstVal::Unevaluated(def_id, substs) => {
+ ConstValue::Unevaluated(def_id, substs) => {
let param_env = ty::ParamEnv::reveal_all();
let substs = tcx.subst_and_normalize_erasing_regions(
param_substs,
_ => constant.val,
};
match val {
- ConstVal::Unevaluated(..) => bug!("const eval yielded unevaluated const"),
- ConstVal::Value(ConstValue::ScalarPair(Scalar::Ptr(a), Scalar::Ptr(b))) => {
+ ConstValue::Unevaluated(..) => bug!("const eval yielded unevaluated const"),
+ ConstValue::ScalarPair(Scalar::Ptr(a), Scalar::Ptr(b)) => {
collect_miri(tcx, a.alloc_id, output);
collect_miri(tcx, b.alloc_id, output);
}
- ConstVal::Value(ConstValue::ScalarPair(_, Scalar::Ptr(ptr))) |
- ConstVal::Value(ConstValue::ScalarPair(Scalar::Ptr(ptr), _)) |
- ConstVal::Value(ConstValue::Scalar(Scalar::Ptr(ptr))) =>
+ ConstValue::ScalarPair(_, Scalar::Ptr(ptr)) |
+ ConstValue::ScalarPair(Scalar::Ptr(ptr), _) |
+ ConstValue::Scalar(Scalar::Ptr(ptr)) =>
collect_miri(tcx, ptr.alloc_id, output),
- ConstVal::Value(ConstValue::ByRef(alloc, _offset)) => {
+ ConstValue::ByRef(alloc, _offset) => {
for &id in alloc.relocations.values() {
collect_miri(tcx, id, output);
}
use rustc::mir::{NullOp, StatementKind, Statement, BasicBlock, LocalKind};
use rustc::mir::{TerminatorKind, ClearCrossCrate, SourceInfo, BinOp, ProjectionElem};
use rustc::mir::visit::{Visitor, PlaceContext};
-use rustc::middle::const_val::{ConstVal, ConstEvalErr, ErrKind};
+use rustc::mir::interpret::ConstEvalErr;
use rustc::ty::{TyCtxt, self, Instance};
use rustc::mir::interpret::{Value, Scalar, GlobalId, EvalResult};
use interpret::EvalContext;
return;
}
match tcx.describe_def(source.def_id) {
- // skip statics because they'll be evaluated by miri anyway
+ // skip statics/consts because they'll be evaluated by miri anyway
+ Some(Def::Const(..)) |
Some(Def::Static(..)) => return,
+ // we still run on associated constants, because they might not get evaluated
+ // within the current crate
_ => {},
}
trace!("ConstProp starting for {:?}", source.def_id);
let (frames, span) = self.ecx.generate_stacktrace(None);
let err = ConstEvalErr {
span,
- kind: ErrKind::Miri(err, frames).into(),
+ error: err,
+ stacktrace: frames,
};
err.report_as_lint(
self.ecx.tcx,
r
}
- fn const_eval(&mut self, cid: GlobalId<'tcx>, source_info: SourceInfo) -> Option<Const<'tcx>> {
- let value = match self.tcx.const_eval(self.param_env.and(cid)) {
- Ok(val) => val,
- Err(err) => {
- err.report_as_error(
- self.tcx.at(err.span),
- "constant evaluation error",
- );
- return None;
- },
- };
- let val = match value.val {
- ConstVal::Value(v) => {
- self.use_ecx(source_info, |this| this.ecx.const_value_to_value(v, value.ty))?
- },
- _ => bug!("eval produced: {:?}", value),
- };
- let val = (val, value.ty, source_info.span);
- trace!("evaluated {:?} to {:?}", cid, val);
- Some(val)
- }
-
fn eval_constant(
&mut self,
c: &Constant<'tcx>,
source_info: SourceInfo,
) -> Option<Const<'tcx>> {
match c.literal {
- Literal::Value { value } => match value.val {
- ConstVal::Value(v) => {
- let v = self.use_ecx(source_info, |this| {
- this.ecx.const_value_to_value(v, value.ty)
- })?;
- Some((v, value.ty, c.span))
- },
- ConstVal::Unevaluated(did, substs) => {
- let instance = Instance::resolve(
- self.tcx,
- self.param_env,
- did,
- substs,
- )?;
- let cid = GlobalId {
- instance,
- promoted: None,
- };
- self.const_eval(cid, source_info)
- },
+ Literal::Value { value } => {
+ self.ecx.tcx.span = source_info.span;
+ match self.ecx.const_to_value(value.val) {
+ Ok(val) => Some((val, value.ty, c.span)),
+ Err(error) => {
+ let (stacktrace, span) = self.ecx.generate_stacktrace(None);
+ let err = ConstEvalErr {
+ span,
+ error,
+ stacktrace,
+ };
+ err.report_as_error(
+ self.tcx.at(source_info.span),
+ "could not evaluate constant",
+ );
+ None
+ },
+ }
},
// evaluate the promoted and replace the constant with the evaluated result
Literal::Promoted { index } => {
use rustc_data_structures::fx::FxHashSet;
use rustc::hir;
use rustc::hir::def_id::DefId;
-use rustc::middle::const_val::ConstVal;
+use rustc::mir::interpret::ConstValue;
use rustc::traits::{self, TraitEngine};
use rustc::ty::{self, TyCtxt, Ty, TypeFoldable};
use rustc::ty::cast::CastTy;
}
Operand::Constant(ref constant) => {
if let Literal::Value {
- value: &ty::Const { val: ConstVal::Unevaluated(def_id, _), ty, .. }
+ value: &ty::Const { val: ConstValue::Unevaluated(def_id, _), ty, .. }
} = constant.literal {
// Don't peek inside trait associated constants.
if self.tcx.trait_of_item(def_id).is_some() {
vec!["-s".to_string(),
"ERROR_ON_UNDEFINED_SYMBOLS=1".to_string(),
"-s".to_string(),
- "ABORTING_MALLOC=0".to_string()]);
+ "ABORTING_MALLOC=0".to_string(),
+ "-s".to_string(),
+ "WASM=0".to_string()]);
let opts = TargetOptions {
dynamic_linking: false,
"supposed to be part of a block tail expression, but the \
expression is empty");
});
- fcx.suggest_mismatched_types_on_tail(&mut db, expr,
- expected, found,
- cause.span, blk_id);
+ fcx.suggest_mismatched_types_on_tail(
+ &mut db,
+ expr,
+ expected,
+ found,
+ cause.span,
+ blk_id,
+ );
}
_ => {
db = fcx.report_mismatched_types(cause, expected, found, err);
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use std::iter;
-
use check::FnCtxt;
use rustc::infer::InferOk;
use rustc::traits::ObligationCause;
}
}
- if let Some((sp, msg, suggestion)) = self.check_ref(expr, checked_ty, expected) {
- err.span_suggestion(sp, msg, suggestion);
- } else if !self.check_for_cast(&mut err, expr, expr_ty, expected) {
- let methods = self.get_conversion_methods(expr.span, expected, checked_ty);
- if let Ok(expr_text) = self.tcx.sess.codemap().span_to_snippet(expr.span) {
- let suggestions = iter::repeat(expr_text).zip(methods.iter())
- .map(|(receiver, method)| format!("{}.{}()", receiver, method.ident))
- .collect::<Vec<_>>();
- if !suggestions.is_empty() {
- err.span_suggestions(expr.span,
- "try using a conversion method",
- suggestions);
- }
- }
- }
+ self.suggest_ref_or_into(&mut err, expr, expected, expr_ty);
+
(expected, Some(err))
}
- fn get_conversion_methods(&self, span: Span, expected: Ty<'tcx>, checked_ty: Ty<'tcx>)
+ pub fn get_conversion_methods(&self, span: Span, expected: Ty<'tcx>, checked_ty: Ty<'tcx>)
-> Vec<AssociatedItem> {
let mut methods = self.probe_for_return_type(span,
probe::Mode::MethodCall,
/// In addition of this check, it also checks between references mutability state. If the
/// expected is mutable but the provided isn't, maybe we could just say "Hey, try with
/// `&mut`!".
- fn check_ref(&self,
+ pub fn check_ref(&self,
expr: &hir::Expr,
checked_ty: Ty<'tcx>,
expected: Ty<'tcx>)
-> Option<(Span, &'static str, String)> {
- let sp = expr.span;
+ let cm = self.sess().codemap();
+ // Use the callsite's span if this is a macro call. #41858
+ let sp = cm.call_span_if_macro(expr.span);
+ if !cm.span_to_filename(sp).is_real() {
+ return None;
+ }
+
match (&expected.sty, &checked_ty.sty) {
(&ty::TyRef(_, exp, _), &ty::TyRef(_, check, _)) => match (&exp.sty, &check.sty) {
(&ty::TyStr, &ty::TyArray(arr, _)) |
(&ty::TyStr, &ty::TySlice(arr)) if arr == self.tcx.types.u8 => {
if let hir::ExprLit(_) = expr.node {
- let sp = self.sess().codemap().call_span_if_macro(expr.span);
- if let Ok(src) = self.tcx.sess.codemap().span_to_snippet(sp) {
+ if let Ok(src) = cm.span_to_snippet(sp) {
return Some((sp,
"consider removing the leading `b`",
src[1..].to_string()));
(&ty::TyArray(arr, _), &ty::TyStr) |
(&ty::TySlice(arr), &ty::TyStr) if arr == self.tcx.types.u8 => {
if let hir::ExprLit(_) = expr.node {
- let sp = self.sess().codemap().call_span_if_macro(expr.span);
- if let Ok(src) = self.tcx.sess.codemap().span_to_snippet(sp) {
+ if let Ok(src) = cm.span_to_snippet(sp) {
return Some((sp,
"consider adding a leading `b`",
format!("b{}", src)));
checked_ty),
};
if self.can_coerce(ref_ty, expected) {
- // Use the callsite's span if this is a macro call. #41858
- let sp = self.sess().codemap().call_span_if_macro(expr.span);
- if let Ok(src) = self.tcx.sess.codemap().span_to_snippet(sp) {
+ if let Ok(src) = cm.span_to_snippet(sp) {
let sugg_expr = match expr.node { // parenthesize if needed (Issue #46756)
hir::ExprCast(_, _) | hir::ExprBinary(_, _, _) => format!("({})", src),
_ => src,
// a macro; if so, it's hard to extract the text and make a good
// suggestion, so don't bother.)
if self.infcx.can_sub(self.param_env, checked, &expected).is_ok() &&
- expr.span.ctxt().outer().expn_info().is_none() {
+ sp.ctxt().outer().expn_info().is_none() {
match expr.node {
// Maybe remove `&`?
hir::ExprAddrOf(_, ref expr) => {
- if let Ok(code) = self.tcx.sess.codemap().span_to_snippet(expr.span) {
+ if !cm.span_to_filename(expr.span).is_real() {
+ return None;
+ }
+ if let Ok(code) = cm.span_to_snippet(expr.span) {
return Some((sp, "consider removing the borrow", code));
}
}
_ => {
if !self.infcx.type_moves_by_default(self.param_env,
checked,
- expr.span) {
- let sp = self.sess().codemap().call_span_if_macro(expr.span);
- if let Ok(code) = self.tcx.sess.codemap().span_to_snippet(sp) {
+ sp) {
+ let sp = cm.call_span_if_macro(sp);
+ if let Ok(code) = cm.span_to_snippet(sp) {
return Some((sp,
"consider dereferencing the borrow",
format!("*{}", code)));
None
}
- fn check_for_cast(&self,
+ pub fn check_for_cast(&self,
err: &mut DiagnosticBuilder<'tcx>,
expr: &hir::Expr,
checked_ty: Ty<'tcx>,
use std::collections::hash_map::Entry;
use std::cmp;
use std::fmt::Display;
+use std::iter;
use std::mem::replace;
use std::ops::{self, Deref};
use rustc_target::spec::abi::Abi;
cause_span: Span,
blk_id: ast::NodeId) {
self.suggest_missing_semicolon(err, expression, expected, cause_span);
-
if let Some((fn_decl, can_suggest)) = self.get_fn_decl(blk_id) {
self.suggest_missing_return_type(err, &fn_decl, expected, found, can_suggest);
}
+ self.suggest_ref_or_into(err, expression, expected, found);
+ }
+
+ pub fn suggest_ref_or_into(
+ &self,
+ err: &mut DiagnosticBuilder<'tcx>,
+ expr: &hir::Expr,
+ expected: Ty<'tcx>,
+ found: Ty<'tcx>,
+ ) {
+ if let Some((sp, msg, suggestion)) = self.check_ref(expr, found, expected) {
+ err.span_suggestion(sp, msg, suggestion);
+ } else if !self.check_for_cast(err, expr, found, expected) {
+ let methods = self.get_conversion_methods(expr.span, expected, found);
+ if let Ok(expr_text) = self.sess().codemap().span_to_snippet(expr.span) {
+ let suggestions = iter::repeat(expr_text).zip(methods.iter())
+ .map(|(receiver, method)| format!("{}.{}()", receiver, method.ident))
+ .collect::<Vec<_>>();
+ if !suggestions.is_empty() {
+ err.span_suggestions(expr.span, "try using a conversion method", suggestions);
+ }
+ }
+ }
}
/// A common error is to forget to add a semicolon at the end of a block:
use syntax::symbol::{Symbol, InternedString};
use syntax_pos::{self, DUMMY_SP, Pos, FileName};
-use rustc::middle::const_val::ConstVal;
+use rustc::mir::interpret::ConstValue;
use rustc::middle::privacy::AccessLevels;
use rustc::middle::resolve_lifetime as rl;
use rustc::ty::fold::TypeFolder;
ty::TySlice(ty) => Slice(box ty.clean(cx)),
ty::TyArray(ty, n) => {
let mut n = cx.tcx.lift(&n).unwrap();
- if let ConstVal::Unevaluated(def_id, substs) = n.val {
+ if let ConstValue::Unevaluated(def_id, substs) = n.val {
let param_env = cx.tcx.param_env(def_id);
let cid = GlobalId {
instance: ty::Instance::new(def_id, substs),
fn print_const(cx: &DocContext, n: &ty::Const) -> String {
match n.val {
- ConstVal::Unevaluated(def_id, _) => {
+ ConstValue::Unevaluated(def_id, _) => {
if let Some(node_id) = cx.tcx.hir.as_local_node_id(def_id) {
print_const_expr(cx, cx.tcx.hir.body_owned_by(node_id))
} else {
inline::print_inlined_const(cx, def_id)
}
},
- ConstVal::Value(..) => {
+ _ => {
let mut s = String::new();
::rustc::mir::fmt_const_val(&mut s, n).unwrap();
// array lengths are obviously usize
var res = buildHrefAndPath(obj);
obj.displayPath = pathSplitter(res[0]);
obj.fullPath = obj.displayPath + obj.name;
- if (obj.ty === TY_KEYWORD) {
- // To be sure than it isn't considered as duplicate with items.
- obj.fullPath += '|k';
- }
+ // To be sure than it some items aren't considered as duplicate.
+ obj.fullPath += '|' + obj.ty;
obj.href = res[1];
out.push(obj);
if (out.length >= MAX_RESULTS) {
let mut m = thread.inner.lock.lock().unwrap();
match thread.inner.state.compare_exchange(EMPTY, PARKED, SeqCst, SeqCst) {
Ok(_) => {}
- Err(NOTIFIED) => return, // notified after we locked
+ Err(NOTIFIED) => {
+ thread.inner.state.store(EMPTY, SeqCst);
+ return;
+ } // should consume this notification, so prohibit spurious wakeups in next park.
Err(_) => panic!("inconsistent park state"),
}
loop {
let m = thread.inner.lock.lock().unwrap();
match thread.inner.state.compare_exchange(EMPTY, PARKED, SeqCst, SeqCst) {
Ok(_) => {}
- Err(NOTIFIED) => return, // notified after we locked
+ Err(NOTIFIED) => {
+ thread.inner.state.store(EMPTY, SeqCst);
+ return;
+ } // should consume this notification, so prohibit spurious wakeups in next park.
Err(_) => panic!("inconsistent park_timeout state"),
}
#![deny(const_err)]
pub const A: i8 = -std::i8::MIN; //~ ERROR const_err
-//~^ ERROR this constant cannot be used
-//~| ERROR this expression will panic at runtime
pub const B: u8 = 200u8 + 200u8; //~ ERROR const_err
-//~^ ERROR this constant cannot be used
pub const C: u8 = 200u8 * 4; //~ ERROR const_err
-//~^ ERROR this constant cannot be used
pub const D: u8 = 42u8 - (42u8 + 1); //~ ERROR const_err
-//~^ ERROR this constant cannot be used
pub const E: u8 = [5u8][1]; //~ ERROR const_err
-//~| ERROR this constant cannot be used
fn main() {
let _a = A;
#![deny(const_err)]
pub const A: i8 = -std::i8::MIN;
-//~^ ERROR E0080
-//~| ERROR attempt to negate with overflow
-//~| ERROR this expression will panic at runtime
-//~| ERROR this constant cannot be used
+//~^ ERROR this constant cannot be used
pub const B: i8 = A;
//~^ ERROR const_err
//~| ERROR const_err
// Make sure that the two uses get two errors.
const FOO: u8 = [5u8][1];
//~^ ERROR constant evaluation error
-//~| ERROR constant evaluation error
//~| index out of bounds: the len is 1 but the index is 1
fn main() {
black_box((FOO, FOO));
+ //~^ ERROR referenced constant has errors
+ //~| ERROR could not evaluate constant
}
//~^ ERROR this constant cannot be used
(
i8::MIN - 1,
- //~^ ERROR attempt to subtract with overflow
);
const VALS_I16: (i16,) =
//~^ ERROR this constant cannot be used
(
i16::MIN - 1,
- //~^ ERROR attempt to subtract with overflow
);
const VALS_I32: (i32,) =
//~^ ERROR this constant cannot be used
(
i32::MIN - 1,
- //~^ ERROR attempt to subtract with overflow
);
const VALS_I64: (i64,) =
//~^ ERROR this constant cannot be used
(
i64::MIN - 1,
- //~^ ERROR attempt to subtract with overflow
);
const VALS_U8: (u8,) =
//~^ ERROR this constant cannot be used
(
u8::MIN - 1,
- //~^ ERROR attempt to subtract with overflow
);
const VALS_U16: (u16,) = (
//~^ ERROR this constant cannot be used
u16::MIN - 1,
- //~^ ERROR attempt to subtract with overflow
);
const VALS_U32: (u32,) = (
//~^ ERROR this constant cannot be used
u32::MIN - 1,
- //~^ ERROR attempt to subtract with overflow
);
const VALS_U64: (u64,) =
//~^ ERROR this constant cannot be used
(
u64::MIN - 1,
- //~^ ERROR attempt to subtract with overflow
);
fn main() {
//~^ ERROR this constant cannot be used
(
i8::MAX + 1,
- //~^ ERROR attempt to add with overflow
);
const VALS_I16: (i16,) =
//~^ ERROR this constant cannot be used
(
i16::MAX + 1,
- //~^ ERROR attempt to add with overflow
);
const VALS_I32: (i32,) =
//~^ ERROR this constant cannot be used
(
i32::MAX + 1,
- //~^ ERROR attempt to add with overflow
);
const VALS_I64: (i64,) =
//~^ ERROR this constant cannot be used
(
i64::MAX + 1,
- //~^ ERROR attempt to add with overflow
);
const VALS_U8: (u8,) =
//~^ ERROR this constant cannot be used
(
u8::MAX + 1,
- //~^ ERROR attempt to add with overflow
);
const VALS_U16: (u16,) = (
//~^ ERROR this constant cannot be used
u16::MAX + 1,
- //~^ ERROR attempt to add with overflow
);
const VALS_U32: (u32,) = (
//~^ ERROR this constant cannot be used
u32::MAX + 1,
- //~^ ERROR attempt to add with overflow
);
const VALS_U64: (u64,) =
//~^ ERROR this constant cannot be used
(
u64::MAX + 1,
- //~^ ERROR attempt to add with overflow
);
fn main() {
//~^ ERROR this constant cannot be used
(
i8::MIN * 2,
- //~^ ERROR attempt to multiply with overflow
);
const VALS_I16: (i16,) =
//~^ ERROR this constant cannot be used
(
i16::MIN * 2,
- //~^ ERROR attempt to multiply with overflow
);
const VALS_I32: (i32,) =
//~^ ERROR this constant cannot be used
(
i32::MIN * 2,
- //~^ ERROR attempt to multiply with overflow
);
const VALS_I64: (i64,) =
//~^ ERROR this constant cannot be used
(
i64::MIN * 2,
- //~^ ERROR attempt to multiply with overflow
);
const VALS_U8: (u8,) =
//~^ ERROR this constant cannot be used
(
u8::MAX * 2,
- //~^ ERROR attempt to multiply with overflow
);
const VALS_U16: (u16,) = (
//~^ ERROR this constant cannot be used
u16::MAX * 2,
- //~^ ERROR attempt to multiply with overflow
);
const VALS_U32: (u32,) = (
//~^ ERROR this constant cannot be used
u32::MAX * 2,
- //~^ ERROR attempt to multiply with overflow
);
const VALS_U64: (u64,) =
//~^ ERROR this constant cannot be used
(
u64::MAX * 2,
- //~^ ERROR attempt to multiply with overflow
);
fn main() {
--- /dev/null
+// Copyright 2018 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.
+
+// ignore-order
+
+const QUERY = 'panic';
+
+const EXPECTED = {
+ 'others': [
+ { 'path': 'std', 'name': 'panic', ty: 14 }, // 15 is for macros
+ { 'path': 'std', 'name': 'panic', ty: 0 }, // 0 is for modules
+ ],
+};
-warning: attempt to subtract with overflow
- --> $DIR/conditional_array_execution.rs:15:19
+warning: this constant cannot be used
+ --> $DIR/conditional_array_execution.rs:15:1
|
LL | const FOO: u32 = [X - Y, Y - X][(X < Y) as usize];
- | ^^^^^
+ | ^^^^^^^^^^^^^^^^^^-----^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | attempt to subtract with overflow
|
note: lint level defined here
--> $DIR/conditional_array_execution.rs:11:9
LL | #![warn(const_err)]
| ^^^^^^^^^
-warning: this constant cannot be used
- --> $DIR/conditional_array_execution.rs:15:1
- |
-LL | const FOO: u32 = [X - Y, Y - X][(X < Y) as usize];
- | ^^^^^^^^^^^^^^^^^^-----^^^^^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | attempt to subtract with overflow
-
-warning: referenced constant
- --> $DIR/conditional_array_execution.rs:20:20
+warning: referenced constant has errors
+ --> $DIR/conditional_array_execution.rs:19:20
|
LL | const FOO: u32 = [X - Y, Y - X][(X < Y) as usize];
| ----- attempt to subtract with overflow
| ^^^
warning: this expression will panic at runtime
- --> $DIR/conditional_array_execution.rs:20:20
+ --> $DIR/conditional_array_execution.rs:19:20
|
LL | println!("{}", FOO);
| ^^^ referenced constant has errors
-error[E0080]: referenced constant
- --> $DIR/conditional_array_execution.rs:20:5
+error[E0080]: referenced constant has errors
+ --> $DIR/conditional_array_execution.rs:19:5
|
LL | const FOO: u32 = [X - Y, Y - X][(X < Y) as usize];
| ----- attempt to subtract with overflow
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
error[E0080]: erroneous constant used
- --> $DIR/conditional_array_execution.rs:20:5
+ --> $DIR/conditional_array_execution.rs:19:5
|
LL | println!("{}", FOO);
| ^^^^^^^^^^^^^^^---^^
|
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
-error[E0080]: referenced constant
- --> $DIR/conditional_array_execution.rs:20:20
+error[E0080]: referenced constant has errors
+ --> $DIR/conditional_array_execution.rs:19:20
|
LL | const FOO: u32 = [X - Y, Y - X][(X < Y) as usize];
| ----- attempt to subtract with overflow
| ^^^
error[E0080]: erroneous constant used
- --> $DIR/conditional_array_execution.rs:20:20
+ --> $DIR/conditional_array_execution.rs:19:20
|
LL | println!("{}", FOO);
| ^^^ referenced constant has errors
const X: u32 = 5;
const Y: u32 = 6;
const FOO: u32 = [X - Y, Y - X][(X < Y) as usize];
-//~^ WARN attempt to subtract with overflow
-//~| WARN this constant cannot be used
+//~^ WARN this constant cannot be used
fn main() {
println!("{}", FOO);
-warning: attempt to subtract with overflow
- --> $DIR/conditional_array_execution.rs:15:19
+warning: this constant cannot be used
+ --> $DIR/conditional_array_execution.rs:15:1
|
LL | const FOO: u32 = [X - Y, Y - X][(X < Y) as usize];
- | ^^^^^
+ | ^^^^^^^^^^^^^^^^^^-----^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | attempt to subtract with overflow
|
note: lint level defined here
--> $DIR/conditional_array_execution.rs:11:9
LL | #![warn(const_err)]
| ^^^^^^^^^
-warning: this constant cannot be used
- --> $DIR/conditional_array_execution.rs:15:1
- |
-LL | const FOO: u32 = [X - Y, Y - X][(X < Y) as usize];
- | ^^^^^^^^^^^^^^^^^^-----^^^^^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | attempt to subtract with overflow
-
-warning: referenced constant
- --> $DIR/conditional_array_execution.rs:20:20
+warning: referenced constant has errors
+ --> $DIR/conditional_array_execution.rs:19:20
|
LL | const FOO: u32 = [X - Y, Y - X][(X < Y) as usize];
| ----- attempt to subtract with overflow
| ^^^
warning: this expression will panic at runtime
- --> $DIR/conditional_array_execution.rs:20:20
+ --> $DIR/conditional_array_execution.rs:19:20
|
LL | println!("{}", FOO);
| ^^^ referenced constant has errors
-error[E0080]: referenced constant
- --> $DIR/conditional_array_execution.rs:20:20
+error[E0080]: referenced constant has errors
+ --> $DIR/conditional_array_execution.rs:19:20
|
LL | const FOO: u32 = [X - Y, Y - X][(X < Y) as usize];
| ----- attempt to subtract with overflow
| ^^^
error[E0080]: erroneous constant used
- --> $DIR/conditional_array_execution.rs:20:20
+ --> $DIR/conditional_array_execution.rs:19:20
|
LL | println!("{}", FOO);
| ^^^ referenced constant has errors
-warning: attempt to subtract with overflow
- --> $DIR/issue-43197.rs:20:20
- |
-LL | const X: u32 = 0-1;
- | ^^^
- |
-note: lint level defined here
- --> $DIR/issue-43197.rs:11:9
- |
-LL | #![warn(const_err)]
- | ^^^^^^^^^
-
warning: this constant cannot be used
--> $DIR/issue-43197.rs:20:5
|
| ^^^^^^^^^^^^^^^---^
| |
| attempt to subtract with overflow
-
-warning: attempt to subtract with overflow
- --> $DIR/issue-43197.rs:23:24
|
-LL | const Y: u32 = foo(0-1);
- | ^^^
+note: lint level defined here
+ --> $DIR/issue-43197.rs:11:9
+ |
+LL | #![warn(const_err)]
+ | ^^^^^^^^^
warning: this constant cannot be used
- --> $DIR/issue-43197.rs:23:5
+ --> $DIR/issue-43197.rs:22:5
|
LL | const Y: u32 = foo(0-1);
| ^^^^^^^^^^^^^^^^^^^---^^
| |
| attempt to subtract with overflow
-warning: referenced constant
- --> $DIR/issue-43197.rs:26:23
+warning: referenced constant has errors
+ --> $DIR/issue-43197.rs:24:23
|
LL | const X: u32 = 0-1;
| --- attempt to subtract with overflow
| ^
warning: this expression will panic at runtime
- --> $DIR/issue-43197.rs:26:23
+ --> $DIR/issue-43197.rs:24:23
|
LL | println!("{} {}", X, Y);
| ^ referenced constant has errors
-warning: referenced constant
- --> $DIR/issue-43197.rs:26:26
+warning: referenced constant has errors
+ --> $DIR/issue-43197.rs:24:26
|
LL | const Y: u32 = foo(0-1);
| --- attempt to subtract with overflow
-...
+LL | //~^ WARN this constant cannot be used
LL | println!("{} {}", X, Y);
| ^
warning: this expression will panic at runtime
- --> $DIR/issue-43197.rs:26:26
+ --> $DIR/issue-43197.rs:24:26
|
LL | println!("{} {}", X, Y);
| ^ referenced constant has errors
-error[E0080]: referenced constant
- --> $DIR/issue-43197.rs:26:5
+error[E0080]: referenced constant has errors
+ --> $DIR/issue-43197.rs:24:5
|
LL | const X: u32 = 0-1;
| --- attempt to subtract with overflow
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
error[E0080]: erroneous constant used
- --> $DIR/issue-43197.rs:26:5
+ --> $DIR/issue-43197.rs:24:5
|
LL | println!("{} {}", X, Y);
| ^^^^^^^^^^^^^^^^^^-^^^^^
|
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
-error[E0080]: referenced constant
- --> $DIR/issue-43197.rs:26:26
+error[E0080]: referenced constant has errors
+ --> $DIR/issue-43197.rs:24:26
|
LL | const Y: u32 = foo(0-1);
| --- attempt to subtract with overflow
-...
+LL | //~^ WARN this constant cannot be used
LL | println!("{} {}", X, Y);
| ^
error[E0080]: erroneous constant used
- --> $DIR/issue-43197.rs:26:26
+ --> $DIR/issue-43197.rs:24:26
|
LL | println!("{} {}", X, Y);
| ^ referenced constant has errors
-error[E0080]: referenced constant
- --> $DIR/issue-43197.rs:26:23
+error[E0080]: referenced constant has errors
+ --> $DIR/issue-43197.rs:24:23
|
LL | const X: u32 = 0-1;
| --- attempt to subtract with overflow
| ^
error[E0080]: erroneous constant used
- --> $DIR/issue-43197.rs:26:23
+ --> $DIR/issue-43197.rs:24:23
|
LL | println!("{} {}", X, Y);
| ^ referenced constant has errors
fn main() {
const X: u32 = 0-1;
- //~^ WARN attempt to subtract with overflow
- //~| WARN this constant cannot be used
+ //~^ WARN this constant cannot be used
const Y: u32 = foo(0-1);
- //~^ WARN attempt to subtract with overflow
- //~| WARN this constant cannot be used
+ //~^ WARN this constant cannot be used
println!("{} {}", X, Y);
//~^ WARN this expression will panic at runtime
//~| WARN this expression will panic at runtime
-warning: attempt to subtract with overflow
- --> $DIR/issue-43197.rs:20:20
- |
-LL | const X: u32 = 0-1;
- | ^^^
- |
-note: lint level defined here
- --> $DIR/issue-43197.rs:11:9
- |
-LL | #![warn(const_err)]
- | ^^^^^^^^^
-
warning: this constant cannot be used
--> $DIR/issue-43197.rs:20:5
|
| ^^^^^^^^^^^^^^^---^
| |
| attempt to subtract with overflow
-
-warning: attempt to subtract with overflow
- --> $DIR/issue-43197.rs:23:24
|
-LL | const Y: u32 = foo(0-1);
- | ^^^
+note: lint level defined here
+ --> $DIR/issue-43197.rs:11:9
+ |
+LL | #![warn(const_err)]
+ | ^^^^^^^^^
warning: this constant cannot be used
- --> $DIR/issue-43197.rs:23:5
+ --> $DIR/issue-43197.rs:22:5
|
LL | const Y: u32 = foo(0-1);
| ^^^^^^^^^^^^^^^^^^^---^^
| |
| attempt to subtract with overflow
-warning: referenced constant
- --> $DIR/issue-43197.rs:26:23
+warning: referenced constant has errors
+ --> $DIR/issue-43197.rs:24:23
|
LL | const X: u32 = 0-1;
| --- attempt to subtract with overflow
| ^
warning: this expression will panic at runtime
- --> $DIR/issue-43197.rs:26:23
+ --> $DIR/issue-43197.rs:24:23
|
LL | println!("{} {}", X, Y);
| ^ referenced constant has errors
-warning: referenced constant
- --> $DIR/issue-43197.rs:26:26
+warning: referenced constant has errors
+ --> $DIR/issue-43197.rs:24:26
|
LL | const Y: u32 = foo(0-1);
| --- attempt to subtract with overflow
-...
+LL | //~^ WARN this constant cannot be used
LL | println!("{} {}", X, Y);
| ^
warning: this expression will panic at runtime
- --> $DIR/issue-43197.rs:26:26
+ --> $DIR/issue-43197.rs:24:26
|
LL | println!("{} {}", X, Y);
| ^ referenced constant has errors
-error[E0080]: referenced constant
- --> $DIR/issue-43197.rs:26:26
+error[E0080]: referenced constant has errors
+ --> $DIR/issue-43197.rs:24:26
|
LL | const Y: u32 = foo(0-1);
| --- attempt to subtract with overflow
-...
+LL | //~^ WARN this constant cannot be used
LL | println!("{} {}", X, Y);
| ^
error[E0080]: erroneous constant used
- --> $DIR/issue-43197.rs:26:26
+ --> $DIR/issue-43197.rs:24:26
|
LL | println!("{} {}", X, Y);
| ^ referenced constant has errors
-error[E0080]: referenced constant
- --> $DIR/issue-43197.rs:26:23
+error[E0080]: referenced constant has errors
+ --> $DIR/issue-43197.rs:24:23
|
LL | const X: u32 = 0-1;
| --- attempt to subtract with overflow
| ^
error[E0080]: erroneous constant used
- --> $DIR/issue-43197.rs:26:23
+ --> $DIR/issue-43197.rs:24:23
|
LL | println!("{} {}", X, Y);
| ^ referenced constant has errors
-error[E0080]: referenced constant
+error[E0080]: referenced constant has errors
--> $DIR/issue-44578.rs:35:5
|
LL | const AMT: usize = [A::AMT][(A::AMT > B::AMT) as usize];
|
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
-error[E0080]: referenced constant
+error[E0080]: referenced constant has errors
--> $DIR/issue-44578.rs:35:20
|
LL | const AMT: usize = [A::AMT][(A::AMT > B::AMT) as usize];
-error[E0080]: referenced constant
+error[E0080]: referenced constant has errors
--> $DIR/issue-44578.rs:35:20
|
LL | const AMT: usize = [A::AMT][(A::AMT > B::AMT) as usize];
-error[E0080]: referenced constant
+error[E0080]: referenced constant has errors
--> $DIR/issue-50814-2.rs:26:5
|
LL | const BAR: usize = [5, 6, 7][T::BOO];
-error[E0080]: referenced constant
+error[E0080]: referenced constant has errors
--> $DIR/issue-50814.rs:27:5
|
LL | const MAX: u8 = A::MAX + B::MAX;
#![crate_type = "lib"]
pub const Z: u32 = 0 - 1;
-//~^ WARN attempt to subtract with overflow
-//~| WARN this constant cannot be used
+//~^ WARN this constant cannot be used
pub type Foo = [i32; 0 - 1];
//~^ WARN attempt to subtract with overflow
-warning: attempt to subtract with overflow
- --> $DIR/pub_const_err.rs:16:20
+warning: this constant cannot be used
+ --> $DIR/pub_const_err.rs:16:1
|
LL | pub const Z: u32 = 0 - 1;
- | ^^^^^
+ | ^^^^^^^^^^^^^^^^^^^-----^
+ | |
+ | attempt to subtract with overflow
|
note: lint level defined here
--> $DIR/pub_const_err.rs:12:9
LL | #![warn(const_err)]
| ^^^^^^^^^
-warning: this constant cannot be used
- --> $DIR/pub_const_err.rs:16:1
- |
-LL | pub const Z: u32 = 0 - 1;
- | ^^^^^^^^^^^^^^^^^^^-----^
- | |
- | attempt to subtract with overflow
-
warning: attempt to subtract with overflow
- --> $DIR/pub_const_err.rs:20:22
+ --> $DIR/pub_const_err.rs:19:22
|
LL | pub type Foo = [i32; 0 - 1];
| ^^^^^
warning: this array length cannot be used
- --> $DIR/pub_const_err.rs:20:22
+ --> $DIR/pub_const_err.rs:19:22
|
LL | pub type Foo = [i32; 0 - 1];
| ^^^^^ attempt to subtract with overflow
#![warn(const_err)]
pub const Z: u32 = 0 - 1;
-//~^ WARN attempt to subtract with overflow
-//~| WARN this constant cannot be used
+//~^ WARN this constant cannot be used
pub type Foo = [i32; 0 - 1];
//~^ WARN attempt to subtract with overflow
-warning: attempt to subtract with overflow
- --> $DIR/pub_const_err_bin.rs:14:20
+warning: this constant cannot be used
+ --> $DIR/pub_const_err_bin.rs:14:1
|
LL | pub const Z: u32 = 0 - 1;
- | ^^^^^
+ | ^^^^^^^^^^^^^^^^^^^-----^
+ | |
+ | attempt to subtract with overflow
|
note: lint level defined here
--> $DIR/pub_const_err_bin.rs:12:9
LL | #![warn(const_err)]
| ^^^^^^^^^
-warning: this constant cannot be used
- --> $DIR/pub_const_err_bin.rs:14:1
- |
-LL | pub const Z: u32 = 0 - 1;
- | ^^^^^^^^^^^^^^^^^^^-----^
- | |
- | attempt to subtract with overflow
-
warning: attempt to subtract with overflow
- --> $DIR/pub_const_err_bin.rs:18:22
+ --> $DIR/pub_const_err_bin.rs:17:22
|
LL | pub type Foo = [i32; 0 - 1];
| ^^^^^
warning: this array length cannot be used
- --> $DIR/pub_const_err_bin.rs:18:22
+ --> $DIR/pub_const_err_bin.rs:17:22
|
LL | pub type Foo = [i32; 0 - 1];
| ^^^^^ attempt to subtract with overflow
--- /dev/null
+// Copyright 2018 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.
+
+enum Foo {
+ // test that we detect overflows for non-u32 discriminants
+ X = 1 << ((u32::max_value() as u64) + 1), //~ ERROR E0080
+ Y = 42,
+}
+
+
+fn main() {
+}
--- /dev/null
+error[E0080]: could not evaluate enum discriminant
+ --> $DIR/shift_overflow.rs:13:9
+ |
+LL | X = 1 << ((u32::max_value() as u64) + 1), //~ ERROR E0080
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attempt to shift left with overflow
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0080`.
const ONE: usize = 1;
const TWO: usize = 2;
const LEN: usize = ONE - TWO;
-//~^ ERROR E0080
-//~| ERROR attempt to subtract with overflow
fn main() {
let a: [i8; LEN] = unimplemented!();
//~^ ERROR E0080
//~| ERROR E0080
+//~| ERROR E0080
+//~| ERROR E0080
}
-error: attempt to subtract with overflow
- --> $DIR/const-len-underflow-separate-spans.rs:17:20
+error[E0080]: referenced constant has errors
+ --> $DIR/const-len-underflow-separate-spans.rs:20:17
|
LL | const LEN: usize = ONE - TWO;
- | ^^^^^^^^^
- |
- = note: #[deny(const_err)] on by default
+ | --------- attempt to subtract with overflow
+...
+LL | let a: [i8; LEN] = unimplemented!();
+ | ^^^
-error[E0080]: constant evaluation error
- --> $DIR/const-len-underflow-separate-spans.rs:17:20
+error[E0080]: could not evaluate constant
+ --> $DIR/const-len-underflow-separate-spans.rs:20:17
|
-LL | const LEN: usize = ONE - TWO;
- | ^^^^^^^^^ attempt to subtract with overflow
+LL | let a: [i8; LEN] = unimplemented!();
+ | ^^^ referenced constant has errors
-error[E0080]: referenced constant
- --> $DIR/const-len-underflow-separate-spans.rs:22:12
+error[E0080]: referenced constant has errors
+ --> $DIR/const-len-underflow-separate-spans.rs:20:12
|
LL | const LEN: usize = ONE - TWO;
| --------- attempt to subtract with overflow
| ^^^^^^^^^
error[E0080]: could not evaluate constant expression
- --> $DIR/const-len-underflow-separate-spans.rs:22:12
+ --> $DIR/const-len-underflow-separate-spans.rs:20:12
|
LL | let a: [i8; LEN] = unimplemented!();
| ^^^^^---^
| - expected `()` because of default return type
...
LL | let u: &str = if true { s[..2] } else { s };
- | ^^^^^^ expected &str, found str
+ | ^^^^^^
+ | |
+ | expected &str, found str
+ | help: consider borrowing here: `&s[..2]`
|
= note: expected type `&str`
found type `str`