Skip to content

Commit 78d4886

Browse files
committed
Properly report transitive errors
1 parent 9cb47de commit 78d4886

25 files changed

+270
-104
lines changed

src/librustc/ich/impls_ty.rs

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -526,19 +526,14 @@ for ::middle::const_val::ErrKind<'gcx> {
526526
match *self {
527527
NonConstPath |
528528
TypeckError |
529+
CouldNotResolve |
529530
CheckMatchError => {
530531
// nothing to do
531532
}
532-
UnimplementedConstVal(s) => {
533-
s.hash_stable(hcx, hasher);
534-
}
535533
IndexOutOfBounds { len, index } => {
536534
len.hash_stable(hcx, hasher);
537535
index.hash_stable(hcx, hasher);
538536
}
539-
LayoutError(ref layout_error) => {
540-
layout_error.hash_stable(hcx, hasher);
541-
}
542537
Miri(ref err, ref trace) => {
543538
err.hash_stable(hcx, hasher);
544539
trace.hash_stable(hcx, hasher);
@@ -609,8 +604,8 @@ for ::mir::interpret::EvalErrorKind<'gcx, O> {
609604
RemainderByZero |
610605
DivisionByZero |
611606
GeneratorResumedAfterReturn |
612-
GeneratorResumedAfterPanic |
613-
ReferencedConstant => {}
607+
GeneratorResumedAfterPanic => {}
608+
ReferencedConstant(ref err) => err.hash_stable(hcx, hasher),
614609
MachineError(ref err) => err.hash_stable(hcx, hasher),
615610
FunctionPointerTyMismatch(a, b) => {
616611
a.hash_stable(hcx, hasher);

src/librustc/middle/const_val.rs

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
// except according to those terms.
1010

1111
use hir::def_id::DefId;
12-
use ty::{self, layout};
12+
use ty;
1313
use ty::subst::Substs;
1414
use ty::maps::TyCtxtAt;
1515
use mir::interpret::ConstValue;
@@ -30,27 +30,25 @@ pub enum ConstVal<'tcx> {
3030
Value(ConstValue<'tcx>),
3131
}
3232

33-
#[derive(Clone, Debug)]
33+
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
3434
pub struct ConstEvalErr<'tcx> {
3535
pub span: Span,
3636
pub kind: Lrc<ErrKind<'tcx>>,
3737
}
3838

39-
#[derive(Clone, Debug)]
39+
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
4040
pub enum ErrKind<'tcx> {
4141

4242
NonConstPath,
43-
UnimplementedConstVal(&'static str),
43+
CouldNotResolve,
4444
IndexOutOfBounds { len: u64, index: u64 },
4545

46-
LayoutError(layout::LayoutError<'tcx>),
47-
4846
TypeckError,
4947
CheckMatchError,
5048
Miri(::mir::interpret::EvalError<'tcx>, Vec<FrameInfo>),
5149
}
5250

53-
#[derive(Clone, Debug)]
51+
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
5452
pub struct FrameInfo {
5553
pub span: Span,
5654
pub location: String,
@@ -87,15 +85,12 @@ impl<'a, 'gcx, 'tcx> ConstEvalErr<'tcx> {
8785

8886
match *self.kind {
8987
NonConstPath => simple!("non-constant path in constant expression"),
90-
UnimplementedConstVal(what) =>
91-
simple!("unimplemented constant expression: {}", what),
88+
CouldNotResolve => simple!("could not resolve"),
9289
IndexOutOfBounds { len, index } => {
9390
simple!("index out of bounds: the len is {} but the index is {}",
9491
len, index)
9592
}
9693

97-
LayoutError(ref err) => Simple(err.to_string().into_cow()),
98-
9994
TypeckError => simple!("type-checking failed"),
10095
CheckMatchError => simple!("match-checking failed"),
10196
Miri(ref err, ref trace) => Backtrace(err, trace),
@@ -149,6 +144,10 @@ impl<'a, 'gcx, 'tcx> ConstEvalErr<'tcx> {
149144
match miri.kind {
150145
::mir::interpret::EvalErrorKind::TypeckError |
151146
::mir::interpret::EvalErrorKind::Layout(_) => return None,
147+
::mir::interpret::EvalErrorKind::ReferencedConstant(ref inner) => {
148+
inner.struct_generic(tcx, "referenced constant", lint_root, as_err)?.emit();
149+
(miri.to_string(), frames)
150+
},
152151
_ => (miri.to_string(), frames),
153152
}
154153
}

src/librustc/mir/interpret/error.rs

Lines changed: 37 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use std::{fmt, env};
22

33
use mir;
4+
use middle::const_val::ConstEvalErr;
45
use ty::{FnSig, Ty, layout};
56
use ty::layout::{Size, Align};
67

@@ -10,57 +11,50 @@ use super::{
1011

1112
use backtrace::Backtrace;
1213

13-
#[derive(Debug, Clone)]
14+
#[derive(Debug, Clone, RustcEncodable, RustcDecodable)]
1415
pub struct EvalError<'tcx> {
1516
pub kind: EvalErrorKind<'tcx, u64>,
16-
pub backtrace: Option<Backtrace>,
1717
}
1818

19-
impl<'tcx> EvalError<'tcx> {
20-
pub fn print_backtrace(&mut self) {
21-
if let Some(ref mut backtrace) = self.backtrace {
22-
use std::fmt::Write;
23-
let mut trace_text = "\n\nAn error occurred in miri:\n".to_string();
24-
backtrace.resolve();
25-
write!(trace_text, "backtrace frames: {}\n", backtrace.frames().len()).unwrap();
26-
'frames: for (i, frame) in backtrace.frames().iter().enumerate() {
27-
if frame.symbols().is_empty() {
28-
write!(trace_text, "{}: no symbols\n", i).unwrap();
29-
}
30-
for symbol in frame.symbols() {
31-
write!(trace_text, "{}: ", i).unwrap();
32-
if let Some(name) = symbol.name() {
33-
write!(trace_text, "{}\n", name).unwrap();
34-
} else {
35-
write!(trace_text, "<unknown>\n").unwrap();
36-
}
37-
write!(trace_text, "\tat ").unwrap();
38-
if let Some(file_path) = symbol.filename() {
39-
write!(trace_text, "{}", file_path.display()).unwrap();
40-
} else {
41-
write!(trace_text, "<unknown_file>").unwrap();
19+
impl<'tcx> From<EvalErrorKind<'tcx, u64>> for EvalError<'tcx> {
20+
fn from(kind: EvalErrorKind<'tcx, u64>) -> Self {
21+
match env::var("MIRI_BACKTRACE") {
22+
Ok(ref val) if !val.is_empty() => {
23+
let backtrace = Backtrace::new();
24+
25+
use std::fmt::Write;
26+
let mut trace_text = "\n\nAn error occurred in miri:\n".to_string();
27+
write!(trace_text, "backtrace frames: {}\n", backtrace.frames().len()).unwrap();
28+
'frames: for (i, frame) in backtrace.frames().iter().enumerate() {
29+
if frame.symbols().is_empty() {
30+
write!(trace_text, "{}: no symbols\n", i).unwrap();
4231
}
43-
if let Some(line) = symbol.lineno() {
44-
write!(trace_text, ":{}\n", line).unwrap();
45-
} else {
46-
write!(trace_text, "\n").unwrap();
32+
for symbol in frame.symbols() {
33+
write!(trace_text, "{}: ", i).unwrap();
34+
if let Some(name) = symbol.name() {
35+
write!(trace_text, "{}\n", name).unwrap();
36+
} else {
37+
write!(trace_text, "<unknown>\n").unwrap();
38+
}
39+
write!(trace_text, "\tat ").unwrap();
40+
if let Some(file_path) = symbol.filename() {
41+
write!(trace_text, "{}", file_path.display()).unwrap();
42+
} else {
43+
write!(trace_text, "<unknown_file>").unwrap();
44+
}
45+
if let Some(line) = symbol.lineno() {
46+
write!(trace_text, ":{}\n", line).unwrap();
47+
} else {
48+
write!(trace_text, "\n").unwrap();
49+
}
4750
}
4851
}
49-
}
50-
error!("{}", trace_text);
52+
error!("{}", trace_text);
53+
},
54+
_ => {},
5155
}
52-
}
53-
}
54-
55-
impl<'tcx> From<EvalErrorKind<'tcx, u64>> for EvalError<'tcx> {
56-
fn from(kind: EvalErrorKind<'tcx, u64>) -> Self {
57-
let backtrace = match env::var("MIRI_BACKTRACE") {
58-
Ok(ref val) if !val.is_empty() => Some(Backtrace::new_unresolved()),
59-
_ => None
60-
};
6156
EvalError {
6257
kind,
63-
backtrace,
6458
}
6559
}
6660
}
@@ -158,7 +152,7 @@ pub enum EvalErrorKind<'tcx, O> {
158152
TypeckError,
159153
/// Cannot compute this constant because it depends on another one
160154
/// which already produced an error
161-
ReferencedConstant,
155+
ReferencedConstant(ConstEvalErr<'tcx>),
162156
GeneratorResumedAfterReturn,
163157
GeneratorResumedAfterPanic,
164158
}
@@ -274,7 +268,7 @@ impl<'tcx, O> EvalErrorKind<'tcx, O> {
274268
"there were unresolved type arguments during trait selection",
275269
TypeckError =>
276270
"encountered constants with type errors, stopping evaluation",
277-
ReferencedConstant =>
271+
ReferencedConstant(_) =>
278272
"referenced constant has errors",
279273
Overflow(mir::BinOp::Add) => "attempt to add with overflow",
280274
Overflow(mir::BinOp::Sub) => "attempt to subtract with overflow",

src/librustc/traits/fulfill.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -534,8 +534,7 @@ fn process_predicate<'a, 'gcx, 'tcx>(
534534
} else {
535535
Err(CodeSelectionError(ConstEvalFailure(ConstEvalErr {
536536
span: obligation.cause.span,
537-
kind: ErrKind::UnimplementedConstVal("could not resolve")
538-
.into(),
537+
kind: ErrKind::CouldNotResolve.into(),
539538
})))
540539
}
541540
},

src/librustc/ty/structural_impls.rs

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -476,7 +476,6 @@ impl<'a, 'tcx> Lift<'tcx> for interpret::EvalError<'a> {
476476
fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
477477
Some(interpret::EvalError {
478478
kind: tcx.lift(&self.kind)?,
479-
backtrace: self.backtrace.clone(),
480479
})
481480
}
482481
}
@@ -578,7 +577,7 @@ impl<'a, 'tcx, O: Lift<'tcx>> Lift<'tcx> for interpret::EvalErrorKind<'a, O> {
578577
PathNotFound(ref v) => PathNotFound(v.clone()),
579578
UnimplementedTraitSelection => UnimplementedTraitSelection,
580579
TypeckError => TypeckError,
581-
ReferencedConstant => ReferencedConstant,
580+
ReferencedConstant(ref err) => ReferencedConstant(tcx.lift(err)?),
582581
OverflowNeg => OverflowNeg,
583582
Overflow(op) => Overflow(op),
584583
DivisionByZero => DivisionByZero,
@@ -596,13 +595,9 @@ impl<'a, 'tcx> Lift<'tcx> for const_val::ErrKind<'a> {
596595

597596
Some(match *self {
598597
NonConstPath => NonConstPath,
599-
UnimplementedConstVal(s) => UnimplementedConstVal(s),
598+
CouldNotResolve => CouldNotResolve,
600599
IndexOutOfBounds { len, index } => IndexOutOfBounds { len, index },
601600

602-
LayoutError(ref e) => {
603-
return tcx.lift(e).map(LayoutError)
604-
}
605-
606601
TypeckError => TypeckError,
607602
CheckMatchError => CheckMatchError,
608603
Miri(ref e, ref frames) => return tcx.lift(e).map(|e| Miri(e, frames.clone())),

src/librustc_mir/interpret/const_eval.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -564,8 +564,7 @@ pub fn const_eval_provider<'a, 'tcx>(
564564
val = ecx.try_read_by_ref(val, miri_ty)?;
565565
}
566566
Ok(value_to_const_value(&ecx, val, miri_ty))
567-
}).map_err(|mut err| {
568-
err.print_backtrace();
567+
}).map_err(|err| {
569568
let (trace, span) = ecx.generate_stacktrace(None);
570569
let err = ErrKind::Miri(err, trace);
571570
let err = ConstEvalErr {

src/librustc_mir/interpret/eval_context.rs

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use std::fmt::Write;
33
use rustc::hir::def_id::DefId;
44
use rustc::hir::def::Def;
55
use rustc::hir::map::definitions::DefPathData;
6-
use rustc::middle::const_val::{ConstVal, ErrKind};
6+
use rustc::middle::const_val::ConstVal;
77
use rustc::mir;
88
use rustc::ty::layout::{self, Size, Align, HasDataLayout, IntegerExt, LayoutOf, TyLayout};
99
use rustc::ty::subst::{Subst, Substs};
@@ -1056,15 +1056,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
10561056
} else {
10571057
self.param_env
10581058
};
1059-
self.tcx.const_eval(param_env.and(gid)).map_err(|err| match *err.kind {
1060-
ErrKind::Miri(ref err, _) => match err.kind {
1061-
EvalErrorKind::TypeckError |
1062-
EvalErrorKind::Layout(_) => EvalErrorKind::TypeckError.into(),
1063-
_ => EvalErrorKind::ReferencedConstant.into(),
1064-
},
1065-
ErrKind::TypeckError => EvalErrorKind::TypeckError.into(),
1066-
ref other => bug!("const eval returned {:?}", other),
1067-
})
1059+
self.tcx.const_eval(param_env.and(gid)).map_err(|err| EvalErrorKind::ReferencedConstant(err).into())
10681060
}
10691061

10701062
pub fn force_allocation(&mut self, place: Place) -> EvalResult<'tcx, Place> {

src/librustc_mir/interpret/memory.rs

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use rustc::ty::ParamEnv;
77
use rustc::ty::maps::TyCtxtAt;
88
use rustc::ty::layout::{self, Align, TargetDataLayout, Size};
99
use syntax::ast::Mutability;
10-
use rustc::middle::const_val::{ConstVal, ErrKind};
10+
use rustc::middle::const_val::ConstVal;
1111

1212
use rustc_data_structures::fx::{FxHashSet, FxHashMap};
1313
use rustc::mir::interpret::{Pointer, AllocId, Allocation, AccessKind, Value,
@@ -285,16 +285,10 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
285285
instance,
286286
promoted: None,
287287
};
288-
self.tcx.const_eval(ParamEnv::reveal_all().and(gid)).map_err(|err| {
289-
match *err.kind {
290-
ErrKind::Miri(ref err, _) => match err.kind {
291-
EvalErrorKind::TypeckError |
292-
EvalErrorKind::Layout(_) => EvalErrorKind::TypeckError.into(),
293-
_ => EvalErrorKind::ReferencedConstant.into(),
294-
},
295-
ErrKind::TypeckError => EvalErrorKind::TypeckError.into(),
296-
ref other => bug!("const eval returned {:?}", other),
297-
}
288+
self.tcx.const_eval(ParamEnv::reveal_all().and(gid)).map_err(|_| {
289+
// no need to report anything, the const_eval call takes care of that for statics
290+
assert!(self.tcx.is_static(def_id).is_some());
291+
EvalErrorKind::TypeckError.into()
298292
}).map(|val| {
299293
let const_val = match val.val {
300294
ConstVal::Value(val) => val,

src/librustc_mir/monomorphize/collector.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1201,7 +1201,7 @@ fn collect_neighbours<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
12011201
use rustc::middle::const_val::ErrKind;
12021202
use rustc::mir::interpret::EvalErrorKind;
12031203
if let ErrKind::Miri(ref miri, ..) = *err.kind {
1204-
if let EvalErrorKind::ReferencedConstant = miri.kind {
1204+
if let EvalErrorKind::ReferencedConstant(_) = miri.kind {
12051205
err.report_as_error(
12061206
tcx.at(mir.promoted[i].span),
12071207
"erroneous constant used",

src/test/compile-fail/const-err-multi.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,13 @@ pub const A: i8 = -std::i8::MIN;
1717
//~| ERROR this constant cannot be used
1818
pub const B: i8 = A;
1919
//~^ ERROR const_err
20+
//~| ERROR const_err
2021
pub const C: u8 = A as u8;
2122
//~^ ERROR const_err
23+
//~| ERROR const_err
2224
pub const D: i8 = 50 - A;
2325
//~^ ERROR const_err
26+
//~| ERROR const_err
2427

2528
fn main() {
2629
let _ = (A, B, C, D);

0 commit comments

Comments
 (0)