Improve the diagnostic message
This commit is contained in:
parent
8937faa837
commit
16d2a92b3d
@ -153,7 +153,9 @@ pub struct Mir<'tcx> {
|
||||
/// `||` expression into `&` or `|` respectively. This is problematic because if we ever stop
|
||||
/// this conversion from happening and use short circuiting, we will cause the following code
|
||||
/// to change the value of `x`: `let mut x = 42; false && { x = 55; true };`
|
||||
pub control_flow_destroyed: bool,
|
||||
///
|
||||
/// List of places where control flow was destroyed. Used for error reporting.
|
||||
pub control_flow_destroyed: Vec<(Span, String)>,
|
||||
|
||||
/// A span representing this MIR, for error reporting
|
||||
pub span: Span,
|
||||
@ -173,7 +175,7 @@ pub fn new(
|
||||
arg_count: usize,
|
||||
upvar_decls: Vec<UpvarDecl>,
|
||||
span: Span,
|
||||
control_flow_destroyed: bool,
|
||||
control_flow_destroyed: Vec<(Span, String)>,
|
||||
) -> Self {
|
||||
// We need `arg_count` locals, and one for the return place
|
||||
assert!(
|
||||
|
@ -35,6 +35,7 @@
|
||||
usize,
|
||||
::ty::layout::VariantIdx,
|
||||
u64,
|
||||
String,
|
||||
::middle::region::Scope,
|
||||
::syntax::ast::FloatTy,
|
||||
::syntax::ast::NodeId,
|
||||
|
@ -23,7 +23,6 @@
|
||||
use rustc::hir::def_id::LocalDefId;
|
||||
use rustc::mir::{BorrowKind};
|
||||
use syntax_pos::Span;
|
||||
use syntax::errors::Applicability;
|
||||
|
||||
impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
|
||||
type Output = Expr<'tcx>;
|
||||
@ -373,18 +372,10 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
||||
// FIXME(eddyb) use logical ops in constants when
|
||||
// they can handle that kind of control-flow.
|
||||
(hir::BinOpKind::And, hir::Constness::Const) => {
|
||||
cx.control_flow_destroyed = true;
|
||||
cx.tcx.sess.struct_span_warn(
|
||||
cx.control_flow_destroyed.push((
|
||||
op.span,
|
||||
"boolean short circuiting operators in constants do \
|
||||
not actually short circuit. Thus new const eval features \
|
||||
are not accessible in constants."
|
||||
).span_suggestion_with_applicability(
|
||||
op.span,
|
||||
"use a bit operator instead",
|
||||
"&".into(),
|
||||
Applicability::MachineApplicable,
|
||||
).emit();
|
||||
"`&&` operator".into(),
|
||||
));
|
||||
ExprKind::Binary {
|
||||
op: BinOp::BitAnd,
|
||||
lhs: lhs.to_ref(),
|
||||
@ -392,18 +383,10 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
||||
}
|
||||
}
|
||||
(hir::BinOpKind::Or, hir::Constness::Const) => {
|
||||
cx.control_flow_destroyed = true;
|
||||
cx.tcx.sess.struct_span_warn(
|
||||
cx.control_flow_destroyed.push((
|
||||
op.span,
|
||||
"boolean short circuiting operators in constants do \
|
||||
not actually short circuit. Thus new const eval features \
|
||||
are not accessible in constants."
|
||||
).span_suggestion_with_applicability(
|
||||
op.span,
|
||||
"use a bit operator instead",
|
||||
"|".into(),
|
||||
Applicability::MachineApplicable,
|
||||
).emit();
|
||||
"`||` operator".into(),
|
||||
));
|
||||
ExprKind::Binary {
|
||||
op: BinOp::BitOr,
|
||||
lhs: lhs.to_ref(),
|
||||
|
@ -58,7 +58,7 @@ pub struct Cx<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
|
||||
check_overflow: bool,
|
||||
|
||||
/// See field with the same name on `Mir`
|
||||
control_flow_destroyed: bool,
|
||||
control_flow_destroyed: Vec<(Span, String)>,
|
||||
}
|
||||
|
||||
impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
|
||||
@ -99,11 +99,11 @@ pub fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
|
||||
constness,
|
||||
body_owner_kind,
|
||||
check_overflow,
|
||||
control_flow_destroyed: false,
|
||||
control_flow_destroyed: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn control_flow_destroyed(&self) -> bool {
|
||||
pub fn control_flow_destroyed(self) -> Vec<(Span, String)> {
|
||||
self.control_flow_destroyed
|
||||
}
|
||||
}
|
||||
|
@ -220,7 +220,7 @@ fn build_drop_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
sig.inputs().len(),
|
||||
vec![],
|
||||
span,
|
||||
true,
|
||||
vec![],
|
||||
);
|
||||
|
||||
if let Some(..) = ty {
|
||||
@ -389,7 +389,7 @@ fn into_mir(self) -> Mir<'tcx> {
|
||||
self.sig.inputs().len(),
|
||||
vec![],
|
||||
self.span,
|
||||
true,
|
||||
vec![],
|
||||
)
|
||||
}
|
||||
|
||||
@ -838,7 +838,7 @@ fn build_call_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
sig.inputs().len(),
|
||||
vec![],
|
||||
span,
|
||||
true,
|
||||
vec![],
|
||||
);
|
||||
if let Abi::RustCall = sig.abi {
|
||||
mir.spread_arg = Some(Local::new(sig.inputs().len()));
|
||||
@ -916,6 +916,6 @@ pub fn build_adt_ctor<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a, 'gcx, 'tcx>,
|
||||
sig.inputs().len(),
|
||||
vec![],
|
||||
span,
|
||||
true,
|
||||
vec![],
|
||||
)
|
||||
}
|
||||
|
@ -413,7 +413,7 @@ pub fn promote_candidates<'a, 'tcx>(mir: &mut Mir<'tcx>,
|
||||
0,
|
||||
vec![],
|
||||
mir.span,
|
||||
false,
|
||||
vec![],
|
||||
),
|
||||
tcx,
|
||||
source: mir,
|
||||
|
@ -1335,17 +1335,32 @@ fn run_pass<'a, 'tcx>(&self,
|
||||
// Do the actual promotion, now that we know what's viable.
|
||||
promote_consts::promote_candidates(mir, tcx, temps, candidates);
|
||||
} else {
|
||||
if mir.control_flow_destroyed {
|
||||
for local in mir.vars_iter() {
|
||||
if !mir.control_flow_destroyed.is_empty() {
|
||||
let mut locals = mir.vars_iter();
|
||||
if let Some(local) = locals.next() {
|
||||
let span = mir.local_decls[local].source_info.span;
|
||||
tcx.sess.span_err(
|
||||
let mut error = tcx.sess.struct_span_err(
|
||||
span,
|
||||
&format!(
|
||||
"short circuiting operators do not actually short circuit in {}. \
|
||||
Thus new features like let bindings are not permitted",
|
||||
"new features like let bindings are not permitted in {} \
|
||||
which also use short circuiting operators",
|
||||
mode,
|
||||
),
|
||||
);
|
||||
for (span, kind) in mir.control_flow_destroyed.iter() {
|
||||
error.span_note(
|
||||
*span,
|
||||
&format!("use of {} here", kind),
|
||||
);
|
||||
}
|
||||
for local in locals {
|
||||
let span = mir.local_decls[local].source_info.span;
|
||||
error.span_note(
|
||||
span,
|
||||
"more locals defined here",
|
||||
);
|
||||
}
|
||||
error.emit();
|
||||
}
|
||||
}
|
||||
let promoted_temps = if mode == Mode::Const {
|
||||
|
@ -12,7 +12,7 @@
|
||||
#![allow(dead_code)]
|
||||
#![allow(unused_variables)]
|
||||
|
||||
#![feature(const_fn)]
|
||||
#![feature(const_fn, const_let)]
|
||||
|
||||
const fn x() {
|
||||
let t = true;
|
||||
|
@ -1,15 +1,15 @@
|
||||
#![feature(underscore_const_names, const_let)]
|
||||
|
||||
const _: bool = false && false; //~ WARN boolean short circuiting operators in constants
|
||||
const _: bool = true && false; //~ WARN boolean short circuiting operators in constants
|
||||
const _: bool = false && false;
|
||||
const _: bool = true && false;
|
||||
const _: bool = {
|
||||
let mut x = true && false; //~ WARN boolean short circuiting operators in constants
|
||||
//~^ ERROR short circuiting operators do not actually short circuit in constant
|
||||
let mut x = true && false;
|
||||
//~^ ERROR new features like let bindings are not permitted
|
||||
x
|
||||
};
|
||||
const _: bool = {
|
||||
let x = true && false; //~ WARN boolean short circuiting operators in constants
|
||||
//~^ ERROR short circuiting operators do not actually short circuit in constant
|
||||
let x = true && false;
|
||||
//~^ ERROR new features like let bindings are not permitted
|
||||
x
|
||||
};
|
||||
|
||||
|
@ -1,38 +1,26 @@
|
||||
warning: boolean short circuiting operators in constants do not actually short circuit. Thus new const eval features are not accessible in constants.
|
||||
--> $DIR/const_short_circuit.rs:3:23
|
||||
|
|
||||
LL | const _: bool = false && false; //~ WARN boolean short circuiting operators in constants
|
||||
| ^^ help: use a bit operator instead: `&`
|
||||
|
||||
warning: boolean short circuiting operators in constants do not actually short circuit. Thus new const eval features are not accessible in constants.
|
||||
--> $DIR/const_short_circuit.rs:4:22
|
||||
|
|
||||
LL | const _: bool = true && false; //~ WARN boolean short circuiting operators in constants
|
||||
| ^^ help: use a bit operator instead: `&`
|
||||
|
||||
warning: boolean short circuiting operators in constants do not actually short circuit. Thus new const eval features are not accessible in constants.
|
||||
--> $DIR/const_short_circuit.rs:6:22
|
||||
|
|
||||
LL | let mut x = true && false; //~ WARN boolean short circuiting operators in constants
|
||||
| ^^ help: use a bit operator instead: `&`
|
||||
|
||||
error: short circuiting operators do not actually short circuit in constant. Thus new features like let bindings are not permitted
|
||||
error: new features like let bindings are not permitted in constant which also use short circuiting operators
|
||||
--> $DIR/const_short_circuit.rs:6:9
|
||||
|
|
||||
LL | let mut x = true && false; //~ WARN boolean short circuiting operators in constants
|
||||
LL | let mut x = true && false;
|
||||
| ^^^^^
|
||||
|
||||
warning: boolean short circuiting operators in constants do not actually short circuit. Thus new const eval features are not accessible in constants.
|
||||
--> $DIR/const_short_circuit.rs:11:18
|
||||
|
|
||||
LL | let x = true && false; //~ WARN boolean short circuiting operators in constants
|
||||
| ^^ help: use a bit operator instead: `&`
|
||||
note: use of `&&` operator here
|
||||
--> $DIR/const_short_circuit.rs:6:22
|
||||
|
|
||||
LL | let mut x = true && false;
|
||||
| ^^
|
||||
|
||||
error: short circuiting operators do not actually short circuit in constant. Thus new features like let bindings are not permitted
|
||||
error: new features like let bindings are not permitted in constant which also use short circuiting operators
|
||||
--> $DIR/const_short_circuit.rs:11:9
|
||||
|
|
||||
LL | let x = true && false; //~ WARN boolean short circuiting operators in constants
|
||||
LL | let x = true && false;
|
||||
| ^
|
||||
|
|
||||
note: use of `&&` operator here
|
||||
--> $DIR/const_short_circuit.rs:11:18
|
||||
|
|
||||
LL | let x = true && false;
|
||||
| ^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user