Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/librustc/dep_graph/dep_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -530,6 +530,7 @@ define_dep_nodes!( <'tcx>
[] UsedTraitImports(DefId),
[] HasTypeckTables(DefId),
[] ConstEval { param_env: ParamEnvAnd<'tcx, GlobalId<'tcx>> },
[] ConstEvalRaw { param_env: ParamEnvAnd<'tcx, GlobalId<'tcx>> },
[] CheckMatch(DefId),
[] SymbolName(DefId),
[] InstanceSymbolName { instance: Instance<'tcx> },
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/hir/map/blocks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ pub struct FnLikeNode<'a> { node: Node<'a> }

/// MaybeFnLike wraps a method that indicates if an object
/// corresponds to some FnLikeNode.
pub trait MaybeFnLike { fn is_fn_like(&self) -> bool; }
trait MaybeFnLike { fn is_fn_like(&self) -> bool; }

impl MaybeFnLike for ast::Item {
fn is_fn_like(&self) -> bool {
Expand Down
12 changes: 4 additions & 8 deletions src/librustc/ich/impls_ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -483,10 +483,9 @@ impl_stable_hash_for!(struct ty::Const<'tcx> {
val
});

impl_stable_hash_for!(struct ::mir::interpret::ConstEvalErr<'tcx> {
span,
stacktrace,
error
impl_stable_hash_for!(enum mir::interpret::ErrorHandled {
Reported,
TooGeneric
});

impl_stable_hash_for!(struct ::mir::interpret::FrameInfo {
Expand All @@ -503,8 +502,6 @@ impl_stable_hash_for!(struct ty::GenericPredicates<'tcx> {
predicates
});

impl_stable_hash_for!(struct ::mir::interpret::EvalError<'tcx> { kind });

impl<'a, 'gcx, O: HashStable<StableHashingContext<'a>>> HashStable<StableHashingContext<'a>>
for ::mir::interpret::EvalErrorKind<'gcx, O> {
fn hash_stable<W: StableHasherResult>(&self,
Expand Down Expand Up @@ -543,14 +540,14 @@ for ::mir::interpret::EvalErrorKind<'gcx, O> {
UnimplementedTraitSelection |
TypeckError |
TooGeneric |
CheckMatchError |
DerefFunctionPointer |
ExecuteMemory |
OverflowNeg |
RemainderByZero |
DivisionByZero |
GeneratorResumedAfterReturn |
GeneratorResumedAfterPanic |
ReferencedConstant |
InfiniteLoop => {}
ReadUndefBytes(offset) => offset.hash_stable(hcx, hasher),
InvalidDiscriminant(val) => val.hash_stable(hcx, hasher),
Expand All @@ -560,7 +557,6 @@ for ::mir::interpret::EvalErrorKind<'gcx, O> {
line.hash_stable(hcx, hasher);
col.hash_stable(hcx, hasher);
},
ReferencedConstant(ref err) => err.hash_stable(hcx, hasher),
MachineError(ref err) => err.hash_stable(hcx, hasher),
FunctionAbiMismatch(a, b) => {
a.hash_stable(hcx, hasher);
Expand Down
68 changes: 44 additions & 24 deletions src/librustc/mir/interpret/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@ use std::{fmt, env};

use mir;
use ty::{Ty, layout};
use ty::layout::{Size, Align};
use rustc_data_structures::sync::Lrc;
use ty::layout::{Size, Align, LayoutError};
use rustc_target::spec::abi::Abi;

use super::{
Expand All @@ -30,7 +29,26 @@ use syntax_pos::Span;
use syntax::ast;
use syntax::symbol::Symbol;

pub type ConstEvalResult<'tcx> = Result<&'tcx ty::Const<'tcx>, Lrc<ConstEvalErr<'tcx>>>;
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum ErrorHandled {
/// Already reported a lint or an error for this evaluation
Reported,
/// Don't emit an error, the evaluation failed because the MIR was generic
/// and the substs didn't fully monomorphize it.
TooGeneric,
}

impl ErrorHandled {
pub fn assert_reported(self) {
match self {
ErrorHandled::Reported => {},
ErrorHandled::TooGeneric => bug!("MIR interpretation failed without reporting an error \
even though it was fully monomorphized"),
}
}
}

pub type ConstEvalResult<'tcx> = Result<&'tcx ty::Const<'tcx>, ErrorHandled>;

#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
pub struct ConstEvalErr<'tcx> {
Expand All @@ -50,33 +68,41 @@ impl<'a, 'gcx, 'tcx> ConstEvalErr<'tcx> {
pub fn struct_error(&self,
tcx: TyCtxtAt<'a, 'gcx, 'tcx>,
message: &str)
-> Option<DiagnosticBuilder<'tcx>>
-> Result<DiagnosticBuilder<'tcx>, ErrorHandled>
{
self.struct_generic(tcx, message, None)
}

pub fn report_as_error(&self,
tcx: TyCtxtAt<'a, 'gcx, 'tcx>,
message: &str
) {
) -> ErrorHandled {
let err = self.struct_error(tcx, message);
if let Some(mut err) = err {
err.emit();
match err {
Ok(mut err) => {
err.emit();
ErrorHandled::Reported
},
Err(err) => err,
}
}

pub fn report_as_lint(&self,
tcx: TyCtxtAt<'a, 'gcx, 'tcx>,
message: &str,
lint_root: ast::NodeId,
) {
) -> ErrorHandled {
let lint = self.struct_generic(
tcx,
message,
Some(lint_root),
);
if let Some(mut lint) = lint {
lint.emit();
match lint {
Ok(mut lint) => {
lint.emit();
ErrorHandled::Reported
},
Err(err) => err,
}
}

Expand All @@ -85,15 +111,12 @@ impl<'a, 'gcx, 'tcx> ConstEvalErr<'tcx> {
tcx: TyCtxtAt<'a, 'gcx, 'tcx>,
message: &str,
lint_root: Option<ast::NodeId>,
) -> Option<DiagnosticBuilder<'tcx>> {
) -> Result<DiagnosticBuilder<'tcx>, ErrorHandled> {
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();
},
EvalErrorKind::Layout(LayoutError::Unknown(_)) |
EvalErrorKind::TooGeneric => return Err(ErrorHandled::TooGeneric),
EvalErrorKind::Layout(LayoutError::SizeOverflow(_)) |
EvalErrorKind::TypeckError => return Err(ErrorHandled::Reported),
_ => {},
}
trace!("reporting const eval failure at {:?}", self.span);
Expand All @@ -117,7 +140,7 @@ impl<'a, 'gcx, 'tcx> ConstEvalErr<'tcx> {
for FrameInfo { span, location, .. } in &self.stacktrace {
err.span_label(*span, format!("inside call to `{}`", location));
}
Some(err)
Ok(err)
}
}

Expand Down Expand Up @@ -279,10 +302,9 @@ pub enum EvalErrorKind<'tcx, O> {
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(Lrc<ConstEvalErr<'tcx>>),
ReferencedConstant,
GeneratorResumedAfterReturn,
GeneratorResumedAfterPanic,
InfiniteLoop,
Expand Down Expand Up @@ -407,9 +429,7 @@ impl<'tcx, O> EvalErrorKind<'tcx, O> {
"encountered constants with type errors, stopping evaluation",
TooGeneric =>
"encountered overly generic constant",
CheckMatchError =>
"match checking failed",
ReferencedConstant(_) =>
ReferencedConstant =>
"referenced constant has errors",
Overflow(mir::BinOp::Add) => "attempt to add with overflow",
Overflow(mir::BinOp::Sub) => "attempt to subtract with overflow",
Expand Down
12 changes: 6 additions & 6 deletions src/librustc/mir/interpret/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ mod value;

pub use self::error::{
EvalError, EvalResult, EvalErrorKind, AssertMessage, ConstEvalErr, struct_error,
FrameInfo, ConstEvalResult,
FrameInfo, ConstEvalResult, ErrorHandled,
};

pub use self::value::{Scalar, ConstValue};
Expand Down Expand Up @@ -176,33 +176,33 @@ impl<'tcx, Tag> Pointer<Tag> {
Pointer { alloc_id, offset, tag }
}

pub fn wrapping_signed_offset<C: HasDataLayout>(self, i: i64, cx: C) -> Self {
pub fn wrapping_signed_offset(self, i: i64, cx: impl HasDataLayout) -> Self {
Pointer::new_with_tag(
self.alloc_id,
Size::from_bytes(cx.data_layout().wrapping_signed_offset(self.offset.bytes(), i)),
self.tag,
)
}

pub fn overflowing_signed_offset<C: HasDataLayout>(self, i: i128, cx: C) -> (Self, bool) {
pub fn overflowing_signed_offset(self, i: i128, cx: impl HasDataLayout) -> (Self, bool) {
let (res, over) = cx.data_layout().overflowing_signed_offset(self.offset.bytes(), i);
(Pointer::new_with_tag(self.alloc_id, Size::from_bytes(res), self.tag), over)
}

pub fn signed_offset<C: HasDataLayout>(self, i: i64, cx: C) -> EvalResult<'tcx, Self> {
pub fn signed_offset(self, i: i64, cx: impl HasDataLayout) -> EvalResult<'tcx, Self> {
Ok(Pointer::new_with_tag(
self.alloc_id,
Size::from_bytes(cx.data_layout().signed_offset(self.offset.bytes(), i)?),
self.tag,
))
}

pub fn overflowing_offset<C: HasDataLayout>(self, i: Size, cx: C) -> (Self, bool) {
pub fn overflowing_offset(self, i: Size, cx: impl HasDataLayout) -> (Self, bool) {
let (res, over) = cx.data_layout().overflowing_offset(self.offset.bytes(), i.bytes());
(Pointer::new_with_tag(self.alloc_id, Size::from_bytes(res), self.tag), over)
}

pub fn offset<C: HasDataLayout>(self, i: Size, cx: C) -> EvalResult<'tcx, Self> {
pub fn offset(self, i: Size, cx: impl HasDataLayout) -> EvalResult<'tcx, Self> {
Ok(Pointer::new_with_tag(
self.alloc_id,
Size::from_bytes(cx.data_layout().offset(self.offset.bytes(), i.bytes())?),
Expand Down
16 changes: 4 additions & 12 deletions src/librustc/traits/error_reporting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -880,18 +880,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
self.tcx.report_object_safety_error(span, did, violations)
}

ConstEvalFailure(ref err) => {
match err.struct_error(
self.tcx.at(span),
"could not evaluate constant expression",
) {
Some(err) => err,
None => {
self.tcx.sess.delay_span_bug(span,
&format!("constant in type had an ignored error: {:?}", err));
return;
}
}
// already reported in the query
ConstEvalFailure(_) => {
self.tcx.sess.delay_span_bug(span, "constant in type had an ignored error");
return;
}

Overflow => {
Expand Down
14 changes: 4 additions & 10 deletions src/librustc/traits/fulfill.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,13 @@
// except according to those terms.

use infer::InferCtxt;
use mir::interpret::GlobalId;
use mir::interpret::{GlobalId, ErrorHandled};
use ty::{self, Ty, TypeFoldable, ToPolyTraitRef, ToPredicate};
use ty::error::ExpectedFound;
use rustc_data_structures::obligation_forest::{Error, ForestObligation, ObligationForest};
use rustc_data_structures::obligation_forest::{ObligationProcessor, ProcessResult};
use std::marker::PhantomData;
use hir::def_id::DefId;
use mir::interpret::ConstEvalErr;
use mir::interpret::EvalErrorKind;

use super::CodeAmbiguity;
use super::CodeProjectionError;
Expand Down Expand Up @@ -495,13 +493,9 @@ impl<'a, 'b, 'gcx, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'gcx,
CodeSelectionError(ConstEvalFailure(err)))
}
} else {
ProcessResult::Error(
CodeSelectionError(ConstEvalFailure(ConstEvalErr {
span: obligation.cause.span,
error: EvalErrorKind::TooGeneric.into(),
stacktrace: vec![],
}.into()))
)
ProcessResult::Error(CodeSelectionError(
ConstEvalFailure(ErrorHandled::TooGeneric)
))
}
},
None => {
Expand Down
4 changes: 2 additions & 2 deletions src/librustc/traits/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ use hir::def_id::DefId;
use infer::SuppressRegionErrors;
use infer::outlives::env::OutlivesEnvironment;
use middle::region;
use mir::interpret::ConstEvalErr;
use mir::interpret::ErrorHandled;
use ty::subst::Substs;
use ty::{self, AdtKind, List, Ty, TyCtxt, GenericParamDefKind, ToPredicate};
use ty::error::{ExpectedFound, TypeError};
Expand Down Expand Up @@ -438,7 +438,7 @@ pub enum SelectionError<'tcx> {
ty::PolyTraitRef<'tcx>,
ty::error::TypeError<'tcx>),
TraitNotObjectSafe(DefId),
ConstEvalFailure(Lrc<ConstEvalErr<'tcx>>),
ConstEvalFailure(ErrorHandled),
Overflow,
}

Expand Down
4 changes: 1 addition & 3 deletions src/librustc/traits/structural_impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,9 +172,7 @@ impl<'a, 'tcx> Lift<'tcx> for traits::SelectionError<'a> {
)
}
super::TraitNotObjectSafe(def_id) => Some(super::TraitNotObjectSafe(def_id)),
super::ConstEvalFailure(ref err) => tcx.lift(&**err).map(|err| super::ConstEvalFailure(
err.into(),
)),
super::ConstEvalFailure(err) => Some(super::ConstEvalFailure(err)),
super::Overflow => Some(super::Overflow),
}
}
Expand Down
12 changes: 6 additions & 6 deletions src/librustc/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem, FnOnceTraitLangIte
use middle::privacy::AccessLevels;
use middle::resolve_lifetime::ObjectLifetimeDefault;
use mir::Mir;
use mir::interpret::GlobalId;
use mir::interpret::{GlobalId, ErrorHandled};
use mir::GeneratorLayout;
use session::CrateDisambiguator;
use traits::{self, Reveal};
Expand Down Expand Up @@ -2191,18 +2191,18 @@ impl<'a, 'gcx, 'tcx> AdtDef {
None
}
}
Err(err) => {
err.report_as_error(
tcx.at(tcx.def_span(expr_did)),
"could not evaluate enum discriminant",
);
Err(ErrorHandled::Reported) => {
if !expr_did.is_local() {
span_bug!(tcx.def_span(expr_did),
"variant discriminant evaluation succeeded \
in its crate but failed locally");
}
None
}
Err(ErrorHandled::TooGeneric) => span_bug!(
tcx.def_span(expr_did),
"enum discriminant depends on generic arguments",
),
}
}

Expand Down
Loading