Skip to content

Commit 8854164

Browse files
committed
rustc_const_eval: move ConstEvalErr to the rustc crate.
1 parent d5cf1cb commit 8854164

File tree

21 files changed

+242
-255
lines changed

21 files changed

+242
-255
lines changed

src/Cargo.lock

-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/librustc/diagnostics.rs

+19
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,25 @@ struct ListNode {
327327
This works because `Box` is a pointer, so its size is well-known.
328328
"##,
329329

330+
E0080: r##"
331+
This error indicates that the compiler was unable to sensibly evaluate an
332+
constant expression that had to be evaluated. Attempting to divide by 0
333+
or causing integer overflow are two ways to induce this error. For example:
334+
335+
```compile_fail,E0080
336+
enum Enum {
337+
X = (1 << 500),
338+
Y = (1 / 0)
339+
}
340+
```
341+
342+
Ensure that the expressions given can be evaluated as the desired integer type.
343+
See the FFI section of the Reference for more information about using a custom
344+
integer type:
345+
346+
https://doc.rust-lang.org/reference.html#ffi-attributes
347+
"##,
348+
330349
E0106: r##"
331350
This error indicates that a lifetime is missing from a type. If it is an error
332351
inside a function signature, the problem may be with failing to adhere to the

src/librustc/middle/const_val.rs

+159-5
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,25 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
use syntax::symbol::InternedString;
12-
use syntax::ast;
13-
use std::rc::Rc;
11+
use self::ConstVal::*;
12+
pub use rustc_const_math::ConstInt;
13+
1414
use hir::def_id::DefId;
15+
use ty::TyCtxt;
1516
use ty::subst::Substs;
1617
use rustc_const_math::*;
1718

18-
use self::ConstVal::*;
19-
pub use rustc_const_math::ConstInt;
19+
use graphviz::IntoCow;
20+
use errors::DiagnosticBuilder;
21+
use syntax::symbol::InternedString;
22+
use syntax::ast;
23+
use syntax_pos::Span;
2024

25+
use std::borrow::Cow;
2126
use std::collections::BTreeMap;
27+
use std::rc::Rc;
28+
29+
pub type EvalResult<'tcx> = Result<ConstVal<'tcx>, ConstEvalErr<'tcx>>;
2230

2331
#[derive(Clone, Debug, Hash, RustcEncodable, RustcDecodable, Eq, PartialEq)]
2432
pub enum ConstVal<'tcx> {
@@ -61,3 +69,149 @@ impl<'tcx> ConstVal<'tcx> {
6169
}
6270
}
6371
}
72+
73+
#[derive(Clone, Debug)]
74+
pub struct ConstEvalErr<'tcx> {
75+
pub span: Span,
76+
pub kind: ErrKind<'tcx>,
77+
}
78+
79+
#[derive(Clone, Debug)]
80+
pub enum ErrKind<'tcx> {
81+
CannotCast,
82+
MissingStructField,
83+
NegateOn(ConstVal<'tcx>),
84+
NotOn(ConstVal<'tcx>),
85+
CallOn(ConstVal<'tcx>),
86+
87+
NonConstPath,
88+
UnimplementedConstVal(&'static str),
89+
ExpectedConstTuple,
90+
ExpectedConstStruct,
91+
IndexedNonVec,
92+
IndexNotUsize,
93+
IndexOutOfBounds { len: u64, index: u64 },
94+
95+
MiscBinaryOp,
96+
MiscCatchAll,
97+
98+
IndexOpFeatureGated,
99+
Math(ConstMathErr),
100+
101+
ErroneousReferencedConstant(Box<ConstEvalErr<'tcx>>),
102+
103+
TypeckError
104+
}
105+
106+
impl<'tcx> From<ConstMathErr> for ErrKind<'tcx> {
107+
fn from(err: ConstMathErr) -> ErrKind<'tcx> {
108+
match err {
109+
ConstMathErr::UnsignedNegation => ErrKind::TypeckError,
110+
_ => ErrKind::Math(err)
111+
}
112+
}
113+
}
114+
115+
#[derive(Clone, Debug)]
116+
pub enum ConstEvalErrDescription<'a> {
117+
Simple(Cow<'a, str>),
118+
}
119+
120+
impl<'a> ConstEvalErrDescription<'a> {
121+
/// Return a one-line description of the error, for lints and such
122+
pub fn into_oneline(self) -> Cow<'a, str> {
123+
match self {
124+
ConstEvalErrDescription::Simple(simple) => simple,
125+
}
126+
}
127+
}
128+
129+
impl<'a, 'gcx, 'tcx> ConstEvalErr<'tcx> {
130+
pub fn description(&self) -> ConstEvalErrDescription {
131+
use self::ErrKind::*;
132+
use self::ConstEvalErrDescription::*;
133+
134+
macro_rules! simple {
135+
($msg:expr) => ({ Simple($msg.into_cow()) });
136+
($fmt:expr, $($arg:tt)+) => ({
137+
Simple(format!($fmt, $($arg)+).into_cow())
138+
})
139+
}
140+
141+
match self.kind {
142+
CannotCast => simple!("can't cast this type"),
143+
NegateOn(ref const_val) => simple!("negate on {}", const_val.description()),
144+
NotOn(ref const_val) => simple!("not on {}", const_val.description()),
145+
CallOn(ref const_val) => simple!("call on {}", const_val.description()),
146+
147+
MissingStructField => simple!("nonexistent struct field"),
148+
NonConstPath => simple!("non-constant path in constant expression"),
149+
UnimplementedConstVal(what) =>
150+
simple!("unimplemented constant expression: {}", what),
151+
ExpectedConstTuple => simple!("expected constant tuple"),
152+
ExpectedConstStruct => simple!("expected constant struct"),
153+
IndexedNonVec => simple!("indexing is only supported for arrays"),
154+
IndexNotUsize => simple!("indices must be of type `usize`"),
155+
IndexOutOfBounds { len, index } => {
156+
simple!("index out of bounds: the len is {} but the index is {}",
157+
len, index)
158+
}
159+
160+
MiscBinaryOp => simple!("bad operands for binary"),
161+
MiscCatchAll => simple!("unsupported constant expr"),
162+
IndexOpFeatureGated => simple!("the index operation on const values is unstable"),
163+
Math(ref err) => Simple(err.description().into_cow()),
164+
165+
ErroneousReferencedConstant(_) => simple!("could not evaluate referenced constant"),
166+
167+
TypeckError => simple!("type-checking failed"),
168+
}
169+
}
170+
171+
pub fn struct_error(&self,
172+
tcx: TyCtxt<'a, 'gcx, 'tcx>,
173+
primary_span: Span,
174+
primary_kind: &str)
175+
-> DiagnosticBuilder<'gcx>
176+
{
177+
let mut err = self;
178+
while let &ConstEvalErr {
179+
kind: ErrKind::ErroneousReferencedConstant(box ref i_err), ..
180+
} = err {
181+
err = i_err;
182+
}
183+
184+
let mut diag = struct_span_err!(tcx.sess, err.span, E0080, "constant evaluation error");
185+
err.note(tcx, primary_span, primary_kind, &mut diag);
186+
diag
187+
}
188+
189+
pub fn note(&self,
190+
_tcx: TyCtxt<'a, 'gcx, 'tcx>,
191+
primary_span: Span,
192+
primary_kind: &str,
193+
diag: &mut DiagnosticBuilder)
194+
{
195+
match self.description() {
196+
ConstEvalErrDescription::Simple(message) => {
197+
diag.span_label(self.span, &message);
198+
}
199+
}
200+
201+
if !primary_span.contains(self.span) {
202+
diag.span_note(primary_span,
203+
&format!("for {} here", primary_kind));
204+
}
205+
}
206+
207+
pub fn report(&self,
208+
tcx: TyCtxt<'a, 'gcx, 'tcx>,
209+
primary_span: Span,
210+
primary_kind: &str)
211+
{
212+
if let ErrKind::TypeckError = self.kind {
213+
return;
214+
}
215+
self.struct_error(tcx, primary_span, primary_kind).emit();
216+
}
217+
}

src/librustc/ty/maps.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
use dep_graph::{DepGraph, DepNode, DepTrackingMap, DepTrackingMapConfig};
1212
use hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
13-
use middle::const_val::ConstVal;
13+
use middle::const_val;
1414
use middle::privacy::AccessLevels;
1515
use mir;
1616
use session::CompileResult;
@@ -443,7 +443,7 @@ define_maps! { <'tcx>
443443

444444
/// Results of evaluating monomorphic constants embedded in
445445
/// other items, such as enum variant explicit discriminants.
446-
pub monomorphic_const_eval: MonomorphicConstEval(DefId) -> Result<ConstVal<'tcx>, ()>,
446+
pub monomorphic_const_eval: MonomorphicConstEval(DefId) -> const_val::EvalResult<'tcx>,
447447

448448
/// Performs the privacy check and computes "access levels".
449449
pub privacy_access_levels: PrivacyAccessLevels(CrateNum) -> Rc<AccessLevels>,

src/librustc_const_eval/Cargo.toml

-1
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,4 @@ rustc_const_math = { path = "../librustc_const_math" }
1717
rustc_data_structures = { path = "../librustc_data_structures" }
1818
rustc_errors = { path = "../librustc_errors" }
1919
syntax = { path = "../libsyntax" }
20-
graphviz = { path = "../libgraphviz" }
2120
syntax_pos = { path = "../libsyntax_pos" }

src/librustc_const_eval/check_match.rs

+16-16
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,6 @@ use _match::WitnessPreference::*;
1414

1515
use pattern::{Pattern, PatternContext, PatternError, PatternKind};
1616

17-
use eval::report_const_eval_err;
18-
1917
use rustc::dep_graph::DepNode;
2018

2119
use rustc::middle::expr_use_visitor::{ConsumeMode, Delegate, ExprUseVisitor};
@@ -108,27 +106,29 @@ impl<'a, 'tcx> Visitor<'tcx> for MatchVisitor<'a, 'tcx> {
108106
}
109107
}
110108

111-
impl<'a, 'tcx> MatchVisitor<'a, 'tcx> {
112-
fn check_patterns(&self, has_guard: bool, pats: &[P<Pat>]) {
113-
check_legality_of_move_bindings(self, has_guard, pats);
114-
for pat in pats {
115-
check_legality_of_bindings_in_at_patterns(self, pat);
116-
}
117-
}
118-
119-
fn report_inlining_errors(&self, patcx: PatternContext, pat_span: Span) {
120-
for error in patcx.errors {
121-
match error {
109+
impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> {
110+
fn report_inlining_errors(&self, pat_span: Span) {
111+
for error in &self.errors {
112+
match *error {
122113
PatternError::StaticInPattern(span) => {
123114
span_err!(self.tcx.sess, span, E0158,
124115
"statics cannot be referenced in patterns");
125116
}
126-
PatternError::ConstEval(err) => {
127-
report_const_eval_err(self.tcx, &err, pat_span, "pattern");
117+
PatternError::ConstEval(ref err) => {
118+
err.report(self.tcx, pat_span, "pattern");
128119
}
129120
}
130121
}
131122
}
123+
}
124+
125+
impl<'a, 'tcx> MatchVisitor<'a, 'tcx> {
126+
fn check_patterns(&self, has_guard: bool, pats: &[P<Pat>]) {
127+
check_legality_of_move_bindings(self, has_guard, pats);
128+
for pat in pats {
129+
check_legality_of_bindings_in_at_patterns(self, pat);
130+
}
131+
}
132132

133133
fn check_match(
134134
&self,
@@ -161,7 +161,7 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> {
161161
let mut patcx = PatternContext::new(self.tcx, self.tables);
162162
let pattern = expand_pattern(cx, patcx.lower_pattern(&pat));
163163
if !patcx.errors.is_empty() {
164-
self.report_inlining_errors(patcx, pat.span);
164+
patcx.report_inlining_errors(pat.span);
165165
have_errors = true;
166166
}
167167
(pattern, &**pat)

src/librustc_const_eval/diagnostics.rs

-19
Original file line numberDiff line numberDiff line change
@@ -557,25 +557,6 @@ The `op_string_ref` binding has type `&Option<&String>` in both cases.
557557
See also https://github.com/rust-lang/rust/issues/14587
558558
"##,
559559

560-
E0080: r##"
561-
This error indicates that the compiler was unable to sensibly evaluate an
562-
constant expression that had to be evaluated. Attempting to divide by 0
563-
or causing integer overflow are two ways to induce this error. For example:
564-
565-
```compile_fail,E0080
566-
enum Enum {
567-
X = (1 << 500),
568-
Y = (1 / 0)
569-
}
570-
```
571-
572-
Ensure that the expressions given can be evaluated as the desired integer type.
573-
See the FFI section of the Reference for more information about using a custom
574-
integer type:
575-
576-
https://doc.rust-lang.org/reference.html#ffi-attributes
577-
"##,
578-
579560
}
580561

581562

0 commit comments

Comments
 (0)