Skip to content

Commit 0cb2ee2

Browse files
committed
Auto merge of #32877 - oli-obk:const_err_multi, r=arielb1
don't report errors in constants at every use site partially fixes #32842 r? @arielb1 cc @retep998 I chose this way of implementing it, because the alternative (checking if the error span is inside the constant's expressions's span) would get confusing when combined with expression generating macros. A next step would be to re-enable the re-reporting of errors if the original erroneous constant is in another crate.
2 parents adb0923 + d38a58d commit 0cb2ee2

File tree

6 files changed

+54
-7
lines changed

6 files changed

+54
-7
lines changed

src/librustc_const_eval/eval.rs

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -364,7 +364,7 @@ pub struct ConstEvalErr {
364364
pub kind: ErrKind,
365365
}
366366

367-
#[derive(Clone, PartialEq)]
367+
#[derive(Clone)]
368368
pub enum ErrKind {
369369
CannotCast,
370370
CannotCastTo(&'static str),
@@ -414,6 +414,7 @@ pub enum ErrKind {
414414
/// Expected, Got
415415
TypeMismatch(String, ConstInt),
416416
BadType(ConstVal),
417+
ErroneousReferencedConstant(Box<ConstEvalErr>),
417418
}
418419

419420
impl From<ConstMathErr> for ErrKind {
@@ -480,6 +481,7 @@ impl ConstEvalErr {
480481
expected, got.description()).into_cow()
481482
},
482483
BadType(ref i) => format!("value of wrong type: {:?}", i).into_cow(),
484+
ErroneousReferencedConstant(_) => "could not evaluate referenced constant".into_cow(),
483485
}
484486
}
485487
}
@@ -696,6 +698,8 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &TyCtxt<'tcx>,
696698

697699
let val = match eval_const_expr_partial(tcx, &base, base_hint, fn_args) {
698700
Ok(val) => val,
701+
Err(ConstEvalErr { kind: ErroneousReferencedConstant(
702+
box ConstEvalErr { kind: TypeMismatch(_, val), .. }), .. }) |
699703
Err(ConstEvalErr { kind: TypeMismatch(_, val), .. }) => {
700704
// Something like `5i8 as usize` doesn't need a type hint for the base
701705
// instead take the type hint from the inner value
@@ -737,19 +741,31 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &TyCtxt<'tcx>,
737741
} else {
738742
None
739743
};
740-
if let Some((e, ty)) = lookup_const_by_id(tcx, def_id, substs) {
744+
if let Some((expr, ty)) = lookup_const_by_id(tcx, def_id, substs) {
741745
let item_hint = match ty {
742746
Some(ty) => ty_hint.checked_or(ty),
743747
None => ty_hint,
744748
};
745-
eval_const_expr_partial(tcx, e, item_hint, None)?
749+
match eval_const_expr_partial(tcx, expr, item_hint, None) {
750+
Ok(val) => val,
751+
Err(err) => {
752+
debug!("bad reference: {:?}, {:?}", err.description(), err.span);
753+
signal!(e, ErroneousReferencedConstant(box err))
754+
},
755+
}
746756
} else {
747757
signal!(e, NonConstPath);
748758
}
749759
},
750760
Def::Variant(enum_def, variant_def) => {
751761
if let Some(const_expr) = lookup_variant_by_id(tcx, enum_def, variant_def) {
752-
eval_const_expr_partial(tcx, const_expr, ty_hint, None)?
762+
match eval_const_expr_partial(tcx, const_expr, ty_hint, None) {
763+
Ok(val) => val,
764+
Err(err) => {
765+
debug!("bad reference: {:?}, {:?}", err.description(), err.span);
766+
signal!(e, ErroneousReferencedConstant(box err))
767+
},
768+
}
753769
} else {
754770
signal!(e, UnimplementedConstVal("enum variants"));
755771
}

src/librustc_const_eval/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929
#![feature(slice_patterns)]
3030
#![feature(iter_arith)]
3131
#![feature(question_mark)]
32+
#![feature(box_patterns)]
33+
#![feature(box_syntax)]
3234

3335
#[macro_use] extern crate syntax;
3436
#[macro_use] extern crate log;

src/librustc_passes/consts.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ use rustc::ty::cast::{CastKind};
2929
use rustc_const_eval::{ConstEvalErr, lookup_const_fn_by_id, compare_lit_exprs};
3030
use rustc_const_eval::{eval_const_expr_partial, lookup_const_by_id};
3131
use rustc_const_eval::ErrKind::{IndexOpFeatureGated, UnimplementedConstVal};
32+
use rustc_const_eval::ErrKind::ErroneousReferencedConstant;
3233
use rustc_const_eval::EvalHint::ExprTypeChecked;
3334
use rustc::hir::def::Def;
3435
use rustc::hir::def_id::DefId;
@@ -114,6 +115,7 @@ impl<'a, 'tcx> CheckCrateVisitor<'a, 'tcx> {
114115
match err.kind {
115116
UnimplementedConstVal(_) => {},
116117
IndexOpFeatureGated => {},
118+
ErroneousReferencedConstant(_) => {},
117119
_ => self.tcx.sess.add_lint(CONST_ERR, expr.id, expr.span,
118120
format!("constant evaluation error: {}. This will \
119121
become a HARD ERROR in the future",

src/librustc_typeck/astconv.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,9 @@
5050
5151
use middle::astconv_util::{prim_ty_to_ty, prohibit_type_params, prohibit_projection};
5252
use middle::const_val::ConstVal;
53-
use rustc_const_eval::eval_const_expr_partial;
53+
use rustc_const_eval::{eval_const_expr_partial, ConstEvalErr};
5454
use rustc_const_eval::EvalHint::UncheckedExprHint;
55+
use rustc_const_eval::ErrKind::ErroneousReferencedConstant;
5556
use hir::def::{self, Def};
5657
use hir::def_id::DefId;
5758
use middle::resolve_lifetime as rl;
@@ -1693,7 +1694,10 @@ pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx>,
16931694
"expected usize value for array length, got {}", val.description());
16941695
this.tcx().types.err
16951696
},
1696-
Err(ref r) => {
1697+
// array length errors happen before the global constant check
1698+
// so we need to report the real error
1699+
Err(ConstEvalErr { kind: ErroneousReferencedConstant(box r), ..}) |
1700+
Err(r) => {
16971701
let mut err = struct_span_err!(tcx.sess, r.span, E0250,
16981702
"array length constant evaluation error: {}",
16991703
r.description());

src/librustc_typeck/collect.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,8 @@ use middle::lang_items::SizedTraitLangItem;
6868
use middle::resolve_lifetime;
6969
use middle::const_val::ConstVal;
7070
use rustc_const_eval::EvalHint::UncheckedExprHint;
71-
use rustc_const_eval::eval_const_expr_partial;
71+
use rustc_const_eval::{eval_const_expr_partial, ConstEvalErr};
72+
use rustc_const_eval::ErrKind::ErroneousReferencedConstant;
7273
use rustc::ty::subst::{Substs, FnSpace, ParamSpace, SelfSpace, TypeSpace, VecPerParamSpace};
7374
use rustc::ty::{ToPredicate, ImplContainer, ImplOrTraitItemContainer, TraitContainer};
7475
use rustc::ty::{self, ToPolyTraitRef, Ty, TyCtxt, TypeScheme};
@@ -1062,6 +1063,9 @@ fn convert_enum_def<'tcx>(tcx: &TyCtxt<'tcx>,
10621063
print_err(tcx, e.span, ty_hint, cv);
10631064
None
10641065
},
1066+
// enum variant evaluation happens before the global constant check
1067+
// so we need to report the real error
1068+
Err(ConstEvalErr { kind: ErroneousReferencedConstant(box err), ..}) |
10651069
Err(err) => {
10661070
let mut diag = struct_span_err!(tcx.sess, err.span, E0080,
10671071
"constant evaluation error: {}",
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![deny(const_err)]
12+
13+
pub const A: i8 = -std::i8::MIN; //~ ERROR attempted to negate with overflow
14+
pub const B: i8 = A;
15+
pub const C: u8 = A as u8;
16+
pub const D: i8 = 50 - A;
17+
18+
fn main() {
19+
}

0 commit comments

Comments
 (0)