mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-29 11:37:39 +00:00
check constants even if they are unused in the current crate
This commit is contained in:
parent
a09f386e8d
commit
913a2b4b05
@ -343,10 +343,15 @@ pub fn eval_const_expr(tcx: &TyCtxt, e: &Expr) -> ConstVal {
|
|||||||
match eval_const_expr_partial(tcx, e, ExprTypeChecked, None) {
|
match eval_const_expr_partial(tcx, e, ExprTypeChecked, None) {
|
||||||
Ok(r) => r,
|
Ok(r) => r,
|
||||||
// non-const path still needs to be a fatal error, because enums are funky
|
// non-const path still needs to be a fatal error, because enums are funky
|
||||||
Err(ref s) if s.kind == NonConstPath => tcx.sess.span_fatal(s.span, &s.description()),
|
|
||||||
Err(s) => {
|
Err(s) => {
|
||||||
tcx.sess.span_err(s.span, &s.description());
|
match s.kind {
|
||||||
Dummy
|
NonConstPath |
|
||||||
|
UnimplementedConstVal(_) => tcx.sess.span_fatal(s.span, &s.description()),
|
||||||
|
_ => {
|
||||||
|
tcx.sess.span_err(s.span, &s.description());
|
||||||
|
Dummy
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -607,6 +612,7 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &TyCtxt<'tcx>,
|
|||||||
const_val => signal!(e, NotOn(const_val)),
|
const_val => signal!(e, NotOn(const_val)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
hir::ExprUnary(hir::UnDeref, _) => signal!(e, UnimplementedConstVal("deref operation")),
|
||||||
hir::ExprBinary(op, ref a, ref b) => {
|
hir::ExprBinary(op, ref a, ref b) => {
|
||||||
let b_ty = match op.node {
|
let b_ty = match op.node {
|
||||||
hir::BiShl | hir::BiShr => ty_hint.erase_hint(),
|
hir::BiShl | hir::BiShr => ty_hint.erase_hint(),
|
||||||
@ -745,7 +751,7 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &TyCtxt<'tcx>,
|
|||||||
if let Some(const_expr) = lookup_variant_by_id(tcx, enum_def, variant_def) {
|
if let Some(const_expr) = lookup_variant_by_id(tcx, enum_def, variant_def) {
|
||||||
eval_const_expr_partial(tcx, const_expr, ty_hint, None)?
|
eval_const_expr_partial(tcx, const_expr, ty_hint, None)?
|
||||||
} else {
|
} else {
|
||||||
signal!(e, NonConstPath);
|
signal!(e, UnimplementedConstVal("enum variants"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Def::Struct(..) => {
|
Def::Struct(..) => {
|
||||||
@ -768,6 +774,7 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &TyCtxt<'tcx>,
|
|||||||
let callee_val = eval_const_expr_partial(tcx, callee, sub_ty_hint, fn_args)?;
|
let callee_val = eval_const_expr_partial(tcx, callee, sub_ty_hint, fn_args)?;
|
||||||
let did = match callee_val {
|
let did = match callee_val {
|
||||||
Function(did) => did,
|
Function(did) => did,
|
||||||
|
Struct(_) => signal!(e, UnimplementedConstVal("tuple struct constructors")),
|
||||||
callee => signal!(e, CallOn(callee)),
|
callee => signal!(e, CallOn(callee)),
|
||||||
};
|
};
|
||||||
let (decl, result) = if let Some(fn_like) = lookup_const_fn_by_id(tcx, did) {
|
let (decl, result) = if let Some(fn_like) = lookup_const_fn_by_id(tcx, did) {
|
||||||
@ -798,7 +805,7 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &TyCtxt<'tcx>,
|
|||||||
hir::ExprBlock(ref block) => {
|
hir::ExprBlock(ref block) => {
|
||||||
match block.expr {
|
match block.expr {
|
||||||
Some(ref expr) => eval_const_expr_partial(tcx, &expr, ty_hint, fn_args)?,
|
Some(ref expr) => eval_const_expr_partial(tcx, &expr, ty_hint, fn_args)?,
|
||||||
None => bug!(),
|
None => signal!(e, UnimplementedConstVal("empty block")),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hir::ExprType(ref e, _) => eval_const_expr_partial(tcx, &e, ty_hint, fn_args)?,
|
hir::ExprType(ref e, _) => eval_const_expr_partial(tcx, &e, ty_hint, fn_args)?,
|
||||||
@ -840,7 +847,8 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &TyCtxt<'tcx>,
|
|||||||
},
|
},
|
||||||
|
|
||||||
Str(ref s) if idx as usize >= s.len() => signal!(e, IndexOutOfBounds),
|
Str(ref s) if idx as usize >= s.len() => signal!(e, IndexOutOfBounds),
|
||||||
Str(_) => bug!("unimplemented"), // FIXME: return a const char
|
// FIXME: return a const char
|
||||||
|
Str(_) => signal!(e, UnimplementedConstVal("indexing into str")),
|
||||||
_ => signal!(e, IndexedNonVec),
|
_ => signal!(e, IndexedNonVec),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -894,6 +902,7 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &TyCtxt<'tcx>,
|
|||||||
signal!(base, ExpectedConstStruct);
|
signal!(base, ExpectedConstStruct);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
hir::ExprAddrOf(..) => signal!(e, UnimplementedConstVal("address operator")),
|
||||||
_ => signal!(e, MiscCatchAll)
|
_ => signal!(e, MiscCatchAll)
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1073,6 +1082,7 @@ fn cast_const_int<'tcx>(tcx: &TyCtxt<'tcx>, val: ConstInt, ty: ty::Ty) -> CastRe
|
|||||||
Ok(Float(val as f64))
|
Ok(Float(val as f64))
|
||||||
},
|
},
|
||||||
ty::TyFloat(ast::FloatTy::F32) => Ok(Float(val.to_u64().unwrap() as f32 as f64)),
|
ty::TyFloat(ast::FloatTy::F32) => Ok(Float(val.to_u64().unwrap() as f32 as f64)),
|
||||||
|
ty::TyRawPtr(_) => Err(ErrKind::UnimplementedConstVal("casting an address to a raw ptr")),
|
||||||
_ => Err(CannotCast),
|
_ => Err(CannotCast),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1094,6 +1104,7 @@ fn cast_const<'tcx>(tcx: &TyCtxt<'tcx>, val: ConstVal, ty: ty::Ty) -> CastResult
|
|||||||
Bool(b) => cast_const_int(tcx, Infer(b as u64), ty),
|
Bool(b) => cast_const_int(tcx, Infer(b as u64), ty),
|
||||||
Float(f) => cast_const_float(tcx, f, ty),
|
Float(f) => cast_const_float(tcx, f, ty),
|
||||||
Char(c) => cast_const_int(tcx, Infer(c as u64), ty),
|
Char(c) => cast_const_int(tcx, Infer(c as u64), ty),
|
||||||
|
Function(_) => Err(UnimplementedConstVal("casting fn pointers")),
|
||||||
_ => Err(CannotCast),
|
_ => Err(CannotCast),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,7 @@ use rustc::dep_graph::DepNode;
|
|||||||
use rustc::ty::cast::{CastKind};
|
use rustc::ty::cast::{CastKind};
|
||||||
use rustc_const_eval::{ConstEvalErr, lookup_const_fn_by_id, compare_lit_exprs};
|
use rustc_const_eval::{ConstEvalErr, lookup_const_fn_by_id, compare_lit_exprs};
|
||||||
use rustc_const_eval::{eval_const_expr_partial, lookup_const_by_id};
|
use rustc_const_eval::{eval_const_expr_partial, lookup_const_by_id};
|
||||||
use rustc_const_eval::ErrKind::IndexOpFeatureGated;
|
use rustc_const_eval::ErrKind::{IndexOpFeatureGated, UnimplementedConstVal};
|
||||||
use rustc_const_eval::EvalHint::ExprTypeChecked;
|
use rustc_const_eval::EvalHint::ExprTypeChecked;
|
||||||
use rustc::middle::def::Def;
|
use rustc::middle::def::Def;
|
||||||
use rustc::middle::def_id::DefId;
|
use rustc::middle::def_id::DefId;
|
||||||
@ -110,6 +110,16 @@ impl<'a, 'tcx> CheckCrateVisitor<'a, 'tcx> {
|
|||||||
entry.insert(ConstQualif::empty());
|
entry.insert(ConstQualif::empty());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if let Err(err) = eval_const_expr_partial(self.tcx, expr, ExprTypeChecked, None) {
|
||||||
|
match err.kind {
|
||||||
|
UnimplementedConstVal(_) => {},
|
||||||
|
IndexOpFeatureGated => {},
|
||||||
|
_ => self.tcx.sess.add_lint(CONST_ERR, expr.id, expr.span,
|
||||||
|
format!("constant evaluation error: {}. This will \
|
||||||
|
become a HARD ERROR in the future",
|
||||||
|
err.description())),
|
||||||
|
}
|
||||||
|
}
|
||||||
self.with_mode(mode, |this| {
|
self.with_mode(mode, |this| {
|
||||||
this.with_euv(None, |euv| euv.consume_expr(expr));
|
this.with_euv(None, |euv| euv.consume_expr(expr));
|
||||||
this.visit_expr(expr);
|
this.visit_expr(expr);
|
||||||
@ -435,6 +445,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CheckCrateVisitor<'a, 'tcx> {
|
|||||||
match eval_const_expr_partial(
|
match eval_const_expr_partial(
|
||||||
self.tcx, ex, ExprTypeChecked, None) {
|
self.tcx, ex, ExprTypeChecked, None) {
|
||||||
Ok(_) => {}
|
Ok(_) => {}
|
||||||
|
Err(ConstEvalErr { kind: UnimplementedConstVal(_), ..}) |
|
||||||
Err(ConstEvalErr { kind: IndexOpFeatureGated, ..}) => {},
|
Err(ConstEvalErr { kind: IndexOpFeatureGated, ..}) => {},
|
||||||
Err(msg) => {
|
Err(msg) => {
|
||||||
self.tcx.sess.add_lint(CONST_ERR, ex.id,
|
self.tcx.sess.add_lint(CONST_ERR, ex.id,
|
||||||
|
22
src/test/compile-fail/const-err-early.rs
Normal file
22
src/test/compile-fail/const-err-early.rs
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
|
||||||
|
// file at the top-level directory of this distribution and at
|
||||||
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
#![feature(const_indexing)]
|
||||||
|
#![deny(const_err)]
|
||||||
|
|
||||||
|
pub const A: i8 = -std::i8::MIN; //~ ERROR attempted to negate with overflow
|
||||||
|
pub const B: u8 = 200u8 + 200u8; //~ ERROR attempted to add with overflow
|
||||||
|
pub const C: u8 = 200u8 * 4; //~ ERROR attempted to multiply with overflow
|
||||||
|
pub const D: u8 = 42u8 - (42u8 + 1); //~ ERROR attempted to subtract with overflow
|
||||||
|
pub const E: u8 = [5u8][1]; //~ ERROR index out of bounds
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let _e = [6u8][1];
|
||||||
|
}
|
@ -10,15 +10,11 @@
|
|||||||
|
|
||||||
#![feature(rustc_attrs)]
|
#![feature(rustc_attrs)]
|
||||||
#![allow(exceeding_bitshifts)]
|
#![allow(exceeding_bitshifts)]
|
||||||
#![deny(const_err)]
|
|
||||||
|
|
||||||
fn black_box<T>(_: T) {
|
fn black_box<T>(_: T) {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
const BLA: u8 = 200u8 + 200u8;
|
|
||||||
//~^ ERROR attempted to add with overflow
|
|
||||||
|
|
||||||
#[rustc_no_mir] // FIXME #29769 MIR overflow checking is TBD.
|
#[rustc_no_mir] // FIXME #29769 MIR overflow checking is TBD.
|
||||||
fn main() {
|
fn main() {
|
||||||
let a = -std::i8::MIN;
|
let a = -std::i8::MIN;
|
||||||
@ -30,7 +26,8 @@ fn main() {
|
|||||||
//~^ WARN attempted to multiply with overflow
|
//~^ WARN attempted to multiply with overflow
|
||||||
let d = 42u8 - (42u8 + 1);
|
let d = 42u8 - (42u8 + 1);
|
||||||
//~^ WARN attempted to subtract with overflow
|
//~^ WARN attempted to subtract with overflow
|
||||||
let _e = BLA;
|
let _e = [5u8][1];
|
||||||
|
//~^ ERROR const index-expr is out of bounds
|
||||||
black_box(a);
|
black_box(a);
|
||||||
black_box(b);
|
black_box(b);
|
||||||
black_box(c);
|
black_box(c);
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
struct S(i32);
|
struct S(i32);
|
||||||
|
|
||||||
const CONSTANT: S = S(0);
|
const CONSTANT: S = S(0);
|
||||||
//~^ ERROR: constant evaluation error: call on struct [E0080]
|
//~^ ERROR: unimplemented constant expression: tuple struct constructors [E0080]
|
||||||
|
|
||||||
enum E {
|
enum E {
|
||||||
V = CONSTANT,
|
V = CONSTANT,
|
||||||
|
@ -17,12 +17,12 @@ enum Cake {
|
|||||||
use Cake::*;
|
use Cake::*;
|
||||||
|
|
||||||
const BOO: (Cake, Cake) = (Marmor, BlackForest);
|
const BOO: (Cake, Cake) = (Marmor, BlackForest);
|
||||||
//~^ ERROR: constant evaluation error: non-constant path in constant expression [E0471]
|
//~^ ERROR: constant evaluation error: unimplemented constant expression: enum variants [E0471]
|
||||||
const FOO: Cake = BOO.1;
|
const FOO: Cake = BOO.1;
|
||||||
|
|
||||||
const fn foo() -> Cake {
|
const fn foo() -> Cake {
|
||||||
Marmor //~ ERROR: constant evaluation error: non-constant path in constant expression [E0471]
|
Marmor //~ ERROR: constant evaluation error: unimplemented constant expression: enum variants
|
||||||
//~^ ERROR: non-constant path in constant expression
|
//~^ ERROR: unimplemented constant expression: enum variants
|
||||||
}
|
}
|
||||||
|
|
||||||
const WORKS: Cake = Marmor;
|
const WORKS: Cake = Marmor;
|
||||||
|
@ -17,7 +17,8 @@ impl std::ops::Neg for S {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const _MAX: usize = -1;
|
const _MAX: usize = -1;
|
||||||
//~^ ERROR unary negation of unsigned integer
|
//~^ WARN unary negation of unsigned integer
|
||||||
|
//~| ERROR unary negation of unsigned integer
|
||||||
//~| HELP use a cast or the `!` operator
|
//~| HELP use a cast or the `!` operator
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
@ -15,5 +15,5 @@ enum State { ST_NULL, ST_WHITESPACE }
|
|||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
[State::ST_NULL; (State::ST_WHITESPACE as usize)];
|
[State::ST_NULL; (State::ST_WHITESPACE as usize)];
|
||||||
//~^ ERROR expected constant integer for repeat count, but non-constant path
|
//~^ ERROR expected constant integer for repeat count, but unimplemented constant expression
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user