Skip to content

Commit 7966739

Browse files
committed
refactor constant evaluation error reporting
Refactor constant evaluation to use a single error reporting function that reports a type-error-like message. Also, unify all error codes with the "constant evaluation error" message to just E0080, and similarly for a few other duplicate codes. The old situation was a total mess, and now that we have *something* we can further iterate on the UX.
1 parent b7017d6 commit 7966739

Some content is hidden

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

55 files changed

+506
-376
lines changed

src/librustc_const_eval/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ serialize = { path = "../libserialize" }
1414
rustc = { path = "../librustc" }
1515
rustc_back = { path = "../librustc_back" }
1616
rustc_const_math = { path = "../librustc_const_math" }
17+
rustc_errors = { path = "../librustc_errors" }
1718
syntax = { path = "../libsyntax" }
1819
graphviz = { path = "../libgraphviz" }
1920
syntax_pos = { path = "../libsyntax_pos" }

src/librustc_const_eval/check_match.rs

+23-32
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use rustc::middle::const_val::ConstVal;
1717
use ::{eval_const_expr, eval_const_expr_partial, compare_const_vals};
1818
use ::{const_expr_to_pat, lookup_const_by_id};
1919
use ::EvalHint::ExprTypeChecked;
20+
use eval::report_const_eval_err;
2021
use rustc::hir::def::*;
2122
use rustc::hir::def_id::{DefId};
2223
use rustc::middle::expr_use_visitor::{ConsumeMode, Delegate, ExprUseVisitor};
@@ -42,6 +43,7 @@ use syntax_pos::{Span, DUMMY_SP};
4243
use rustc::hir::fold::{Folder, noop_fold_pat};
4344
use rustc::hir::print::pat_to_string;
4445
use syntax::ptr::P;
46+
use rustc::util::common::ErrorReported;
4547
use rustc::util::nodemap::FnvHashMap;
4648

4749
pub const DUMMY_WILD_PAT: &'static Pat = &Pat {
@@ -279,13 +281,7 @@ fn check_for_static_nan(cx: &MatchCheckCtxt, pat: &Pat) {
279281
Ok(_) => {}
280282

281283
Err(err) => {
282-
let mut diag = struct_span_err!(cx.tcx.sess, err.span, E0471,
283-
"constant evaluation error: {}",
284-
err.description());
285-
if !p.span.contains(err.span) {
286-
diag.span_note(p.span, "in pattern here");
287-
}
288-
diag.emit();
284+
report_const_eval_err(cx.tcx, &err, p.span, "pattern").emit();
289285
}
290286
}
291287
}
@@ -838,22 +834,19 @@ pub fn constructor_arity(_cx: &MatchCheckCtxt, ctor: &Constructor, ty: Ty) -> us
838834
}
839835
}
840836

841-
fn range_covered_by_constructor(ctor: &Constructor,
842-
from: &ConstVal, to: &ConstVal) -> Option<bool> {
837+
fn range_covered_by_constructor(tcx: TyCtxt, span: Span,
838+
ctor: &Constructor,
839+
from: &ConstVal, to: &ConstVal)
840+
-> Result<bool, ErrorReported> {
843841
let (c_from, c_to) = match *ctor {
844842
ConstantValue(ref value) => (value, value),
845843
ConstantRange(ref from, ref to) => (from, to),
846-
Single => return Some(true),
844+
Single => return Ok(true),
847845
_ => bug!()
848846
};
849-
let cmp_from = compare_const_vals(c_from, from);
850-
let cmp_to = compare_const_vals(c_to, to);
851-
match (cmp_from, cmp_to) {
852-
(Some(cmp_from), Some(cmp_to)) => {
853-
Some(cmp_from != Ordering::Less && cmp_to != Ordering::Greater)
854-
}
855-
_ => None
856-
}
847+
let cmp_from = compare_const_vals(tcx, span, c_from, from)?;
848+
let cmp_to = compare_const_vals(tcx, span, c_to, to)?;
849+
Ok(cmp_from != Ordering::Less && cmp_to != Ordering::Greater)
857850
}
858851

859852
fn wrap_pat<'a, 'b, 'tcx>(cx: &MatchCheckCtxt<'b, 'tcx>,
@@ -965,27 +958,25 @@ pub fn specialize<'a, 'b, 'tcx>(
965958
Some(vec![(pat, Some(mt.ty))])
966959
} else {
967960
let expr_value = eval_const_expr(cx.tcx, &expr);
968-
match range_covered_by_constructor(constructor, &expr_value, &expr_value) {
969-
Some(true) => Some(vec![]),
970-
Some(false) => None,
971-
None => {
972-
span_err!(cx.tcx.sess, pat_span, E0298, "mismatched types between arms");
973-
None
974-
}
961+
match range_covered_by_constructor(
962+
cx.tcx, expr.span, constructor, &expr_value, &expr_value
963+
) {
964+
Ok(true) => Some(vec![]),
965+
Ok(false) => None,
966+
Err(ErrorReported) => None,
975967
}
976968
}
977969
}
978970

979971
PatKind::Range(ref from, ref to) => {
980972
let from_value = eval_const_expr(cx.tcx, &from);
981973
let to_value = eval_const_expr(cx.tcx, &to);
982-
match range_covered_by_constructor(constructor, &from_value, &to_value) {
983-
Some(true) => Some(vec![]),
984-
Some(false) => None,
985-
None => {
986-
span_err!(cx.tcx.sess, pat_span, E0299, "mismatched types between arms");
987-
None
988-
}
974+
match range_covered_by_constructor(
975+
cx.tcx, pat_span, constructor, &from_value, &to_value
976+
) {
977+
Ok(true) => Some(vec![]),
978+
Ok(false) => None,
979+
Err(ErrorReported) => None,
989980
}
990981
}
991982

src/librustc_const_eval/diagnostics.rs

+22-20
Original file line numberDiff line numberDiff line change
@@ -551,44 +551,46 @@ The `op_string_ref` binding has type `&Option<&String>` in both cases.
551551
See also https://github.com/rust-lang/rust/issues/14587
552552
"##,
553553

554-
E0306: r##"
555-
In an array literal `[x; N]`, `N` is the number of elements in the array. This
556-
must be an unsigned integer. Erroneous code example:
554+
E0080: r##"
555+
This error indicates that the compiler was unable to sensibly evaluate an
556+
constant expression that had to be evaluated. Attempting to divide by 0
557+
or causing integer overflow are two ways to induce this error. For example:
557558
558559
```compile_fail
559-
let x = [0i32; true]; // error: expected positive integer for repeat count,
560-
// found boolean
560+
enum Enum {
561+
X = (1 << 500),
562+
Y = (1 / 0)
563+
}
561564
```
562565
563-
Working example:
566+
Ensure that the expressions given can be evaluated as the desired integer type.
567+
See the FFI section of the Reference for more information about using a custom
568+
integer type:
564569
565-
```
566-
let x = [0i32; 2];
567-
```
570+
https://doc.rust-lang.org/reference.html#ffi-attributes
568571
"##,
569572

570-
E0307: r##"
571-
The length of an array is part of its type. For this reason, this length must
572-
be a compile-time constant. Erroneous code example:
573+
574+
E0306: r##"
575+
In an array literal `[x; N]`, `N` is the number of elements in the array. This
576+
must be an unsigned integer. Erroneous code example:
573577
574578
```compile_fail
575-
let len = 10;
576-
let x = [0i32; len]; // error: expected constant integer for repeat count,
577-
// found variable
579+
let x = [0i32; true]; // error: expected positive integer for repeat count,
580+
// found boolean
578581
```
579582
580583
Working example:
581584
582585
```
583-
let x = [0i32; 10];
586+
let x = [0i32; 2];
584587
```
585588
"##,
586-
587589
}
588590

589591

590592
register_diagnostics! {
591-
E0298, // mismatched types between arms
592-
E0299, // mismatched types between arms
593-
E0471, // constant evaluation error: ..
593+
E0298, // cannot compare constants
594+
// E0299, // mismatched types between arms
595+
// E0471, // constant evaluation error (in pattern)
594596
}

0 commit comments

Comments
 (0)