Skip to content

Commit 5c0d135

Browse files
committed
Refactor the const eval diagnostic API
1 parent 4a9c58c commit 5c0d135

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+352
-349
lines changed

src/librustc/ich/impls_ty.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -510,6 +510,7 @@ impl_stable_hash_for!(struct ::middle::const_val::ConstEvalErr<'tcx> {
510510

511511
impl_stable_hash_for!(struct ::middle::const_val::FrameInfo {
512512
span,
513+
lint_root,
513514
location
514515
});
515516

src/librustc/lint/context.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -655,6 +655,9 @@ impl<'a, 'tcx> LateContext<'a, 'tcx> {
655655
f(self);
656656
self.param_env = old_param_env;
657657
}
658+
pub fn current_lint_root(&self) -> ast::NodeId {
659+
self.last_ast_node_with_lint_attrs
660+
}
658661
}
659662

660663
impl<'a, 'tcx> LayoutOf for &'a LateContext<'a, 'tcx> {

src/librustc/middle/const_val.rs

Lines changed: 68 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,15 @@
99
// except according to those terms.
1010

1111
use hir::def_id::DefId;
12-
use ty::{self, TyCtxt, layout};
12+
use ty::{self, layout};
1313
use ty::subst::Substs;
14+
use ty::maps::TyCtxtAt;
1415
use mir::interpret::ConstValue;
1516
use errors::DiagnosticBuilder;
1617

1718
use graphviz::IntoCow;
1819
use syntax_pos::Span;
20+
use syntax::ast;
1921

2022
use std::borrow::Cow;
2123
use rustc_data_structures::sync::Lrc;
@@ -52,6 +54,7 @@ pub enum ErrKind<'tcx> {
5254
pub struct FrameInfo {
5355
pub span: Span,
5456
pub location: String,
57+
pub lint_root: Option<ast::NodeId>,
5558
}
5659

5760
#[derive(Clone, Debug)]
@@ -100,64 +103,86 @@ impl<'a, 'gcx, 'tcx> ConstEvalErr<'tcx> {
100103
}
101104

102105
pub fn struct_error(&self,
103-
tcx: TyCtxt<'a, 'gcx, 'tcx>,
104-
primary_span: Span,
105-
primary_kind: &str)
106-
-> DiagnosticBuilder<'gcx>
106+
tcx: TyCtxtAt<'a, 'gcx, 'tcx>,
107+
message: &str)
108+
-> Option<DiagnosticBuilder<'tcx>>
107109
{
108-
let mut diag = struct_error(tcx, self.span, "constant evaluation error");
109-
self.note(tcx, primary_span, primary_kind, &mut diag);
110-
diag
110+
self.struct_generic(tcx, message, None, true)
111111
}
112112

113-
pub fn note(&self,
114-
_tcx: TyCtxt<'a, 'gcx, 'tcx>,
115-
primary_span: Span,
116-
primary_kind: &str,
117-
diag: &mut DiagnosticBuilder)
118-
{
119-
match self.description() {
120-
ConstEvalErrDescription::Simple(message) => {
121-
diag.span_label(self.span, message);
122-
}
123-
ConstEvalErrDescription::Backtrace(miri, frames) => {
124-
diag.span_label(self.span, format!("{}", miri));
125-
for frame in frames {
126-
diag.span_label(frame.span, format!("inside call to `{}`", frame.location));
127-
}
128-
}
113+
pub fn report_as_error(&self,
114+
tcx: TyCtxtAt<'a, 'gcx, 'tcx>,
115+
message: &str
116+
) {
117+
let err = self.struct_generic(tcx, message, None, true);
118+
if let Some(mut err) = err {
119+
err.emit();
129120
}
121+
}
130122

131-
if !primary_span.contains(self.span) {
132-
diag.span_note(primary_span,
133-
&format!("for {} here", primary_kind));
123+
pub fn report_as_lint(&self,
124+
tcx: TyCtxtAt<'a, 'gcx, 'tcx>,
125+
message: &str,
126+
lint_root: ast::NodeId,
127+
) {
128+
let lint = self.struct_generic(
129+
tcx,
130+
message,
131+
Some(lint_root),
132+
false,
133+
);
134+
if let Some(mut lint) = lint {
135+
lint.emit();
134136
}
135137
}
136138

137-
pub fn report(&self,
138-
tcx: TyCtxt<'a, 'gcx, 'tcx>,
139-
primary_span: Span,
140-
primary_kind: &str)
141-
{
142-
match *self.kind {
143-
ErrKind::TypeckError | ErrKind::CheckMatchError => return,
144-
ErrKind::Miri(ref miri, _) => {
139+
fn struct_generic(
140+
&self,
141+
tcx: TyCtxtAt<'a, 'gcx, 'tcx>,
142+
message: &str,
143+
lint_root: Option<ast::NodeId>,
144+
as_err: bool,
145+
) -> Option<DiagnosticBuilder<'tcx>> {
146+
let (msg, frames): (_, &[_]) = match *self.kind {
147+
ErrKind::TypeckError | ErrKind::CheckMatchError => return None,
148+
ErrKind::Miri(ref miri, ref frames) => {
145149
match miri.kind {
146150
::mir::interpret::EvalErrorKind::TypeckError |
147-
::mir::interpret::EvalErrorKind::Layout(_) => return,
148-
_ => {},
151+
::mir::interpret::EvalErrorKind::Layout(_) => return None,
152+
_ => (miri.to_string(), frames),
149153
}
150154
}
151-
_ => {}
155+
_ => (self.description().into_oneline().to_string(), &[]),
156+
};
157+
trace!("reporting const eval failure at {:?}", self.span);
158+
let mut err = if as_err {
159+
struct_error(tcx, message)
160+
} else {
161+
let node_id = frames
162+
.iter()
163+
.rev()
164+
.filter_map(|frame| frame.lint_root)
165+
.next()
166+
.or(lint_root)
167+
.expect("some part of a failing const eval must be local");
168+
tcx.struct_span_lint_node(
169+
::rustc::lint::builtin::CONST_ERR,
170+
node_id,
171+
tcx.span,
172+
message,
173+
)
174+
};
175+
err.span_label(self.span, msg);
176+
for FrameInfo { span, location, .. } in frames {
177+
err.span_label(*span, format!("inside call to `{}`", location));
152178
}
153-
self.struct_error(tcx, primary_span, primary_kind).emit();
179+
Some(err)
154180
}
155181
}
156182

157183
pub fn struct_error<'a, 'gcx, 'tcx>(
158-
tcx: TyCtxt<'a, 'gcx, 'tcx>,
159-
span: Span,
184+
tcx: TyCtxtAt<'a, 'gcx, 'tcx>,
160185
msg: &str,
161-
) -> DiagnosticBuilder<'gcx> {
162-
struct_span_err!(tcx.sess, span, E0080, "{}", msg)
186+
) -> DiagnosticBuilder<'tcx> {
187+
struct_span_err!(tcx.sess, tcx.span, E0080, "{}", msg)
163188
}

src/librustc/mir/interpret/error.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,42 @@ pub struct EvalError<'tcx> {
1616
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();
42+
}
43+
if let Some(line) = symbol.lineno() {
44+
write!(trace_text, ":{}\n", line).unwrap();
45+
} else {
46+
write!(trace_text, "\n").unwrap();
47+
}
48+
}
49+
}
50+
error!("{}", trace_text);
51+
}
52+
}
53+
}
54+
1955
impl<'tcx> From<EvalErrorKind<'tcx, u64>> for EvalError<'tcx> {
2056
fn from(kind: EvalErrorKind<'tcx, u64>) -> Self {
2157
let backtrace = match env::var("MIRI_BACKTRACE") {

src/librustc/traits/error_reporting.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -827,10 +827,13 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
827827
}
828828

829829
ConstEvalFailure(ref err) => {
830-
if let ::middle::const_val::ErrKind::TypeckError = *err.kind {
831-
return;
830+
match err.struct_error(
831+
self.tcx.at(span),
832+
"could not evaluate constant expression",
833+
) {
834+
Some(err) => err,
835+
None => return,
832836
}
833-
err.struct_error(self.tcx, span, "constant expression")
834837
}
835838

836839
Overflow => {

src/librustc/ty/mod.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2075,15 +2075,17 @@ impl<'a, 'gcx, 'tcx> AdtDef {
20752075
} else {
20762076
info!("invalid enum discriminant: {:#?}", val);
20772077
::middle::const_val::struct_error(
2078-
tcx,
2079-
tcx.def_span(expr_did),
2078+
tcx.at(tcx.def_span(expr_did)),
20802079
"constant evaluation of enum discriminant resulted in non-integer",
20812080
).emit();
20822081
None
20832082
}
20842083
}
20852084
Err(err) => {
2086-
err.report(tcx, tcx.def_span(expr_did), "enum discriminant");
2085+
err.report_as_error(
2086+
tcx.at(tcx.def_span(expr_did)),
2087+
"could not evaluate enum discriminant",
2088+
);
20872089
if !expr_did.is_local() {
20882090
span_bug!(tcx.def_span(expr_did),
20892091
"variant discriminant evaluation succeeded \

src/librustc_codegen_llvm/mir/constant.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,10 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
217217
Ok((llval, constant.ty))
218218
})
219219
.unwrap_or_else(|e| {
220-
e.report(bx.tcx(), constant.span, "shuffle_indices");
220+
e.report_as_error(
221+
bx.tcx().at(constant.span),
222+
"could not evaluate shuffle_indices at compile time",
223+
);
221224
// We've errored, so we don't have to produce working code.
222225
let ty = self.monomorphize(&constant.ty);
223226
let llty = bx.cx.layout_of(ty).llvm_type(bx.cx);

src/librustc_codegen_llvm/mir/operand.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -416,7 +416,10 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
416416
// FIXME: generate a panic here
417417
},
418418
mir::Literal::Value { .. } => {
419-
err.report(bx.tcx(), constant.span, "const operand");
419+
err.report_as_error(
420+
bx.tcx().at(constant.span),
421+
"could not evaluate constant operand",
422+
);
420423
},
421424
}
422425
// We've errored, so we don't have to produce working code.

src/librustc_lint/builtin.rs

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1501,24 +1501,11 @@ fn check_const(cx: &LateContext, body_id: hir::BodyId, what: &str) {
15011501
};
15021502
if let Err(err) = cx.tcx.const_eval(param_env.and(cid)) {
15031503
let span = cx.tcx.def_span(def_id);
1504-
let mut diag = cx.struct_span_lint(
1505-
CONST_ERR,
1506-
span,
1504+
err.report_as_lint(
1505+
cx.tcx.at(span),
15071506
&format!("this {} cannot be used", what),
1507+
cx.current_lint_root(),
15081508
);
1509-
use rustc::middle::const_val::ConstEvalErrDescription;
1510-
match err.description() {
1511-
ConstEvalErrDescription::Simple(message) => {
1512-
diag.span_label(span, message);
1513-
}
1514-
ConstEvalErrDescription::Backtrace(miri, frames) => {
1515-
diag.span_label(span, format!("{}", miri));
1516-
for frame in frames {
1517-
diag.span_label(frame.span, format!("inside call to `{}`", frame.location));
1518-
}
1519-
}
1520-
}
1521-
diag.emit()
15221509
}
15231510
}
15241511

src/librustc_mir/hair/cx/expr.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -523,7 +523,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
523523
let count = match cx.tcx.at(span).const_eval(cx.param_env.and(global_id)) {
524524
Ok(cv) => cv.unwrap_usize(cx.tcx),
525525
Err(e) => {
526-
e.report(cx.tcx, cx.tcx.def_span(def_id), "array length");
526+
e.report_as_error(cx.tcx.at(span), "could not evaluate array length");
527527
0
528528
},
529529
};

src/librustc_mir/hair/pattern/check_match.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -141,13 +141,13 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
141141
PatternError::FloatBug => {
142142
// FIXME(#31407) this is only necessary because float parsing is buggy
143143
::rustc::middle::const_val::struct_error(
144-
self.tcx, pat_span,
144+
self.tcx.at(pat_span),
145145
"could not evaluate float literal (see issue #31407)",
146146
).emit();
147147
}
148148
PatternError::NonConstPath(span) => {
149149
::rustc::middle::const_val::struct_error(
150-
self.tcx, span,
150+
self.tcx.at(span),
151151
"runtime values cannot be referenced in patterns",
152152
).emit();
153153
}

src/librustc_mir/hair/pattern/mod.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -695,7 +695,10 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
695695
return self.const_to_pat(instance, value, id, span)
696696
},
697697
Err(err) => {
698-
err.report(self.tcx, span, "pattern");
698+
err.report_as_error(
699+
self.tcx.at(span),
700+
"could not evaluate constant pattern",
701+
);
699702
PatternKind::Wild
700703
},
701704
}

0 commit comments

Comments
 (0)