Skip to content

Commit 16d2a92

Browse files
committed
Improve the diagnostic message
1 parent 8937faa commit 16d2a92

File tree

10 files changed

+61
-72
lines changed

10 files changed

+61
-72
lines changed

src/librustc/mir/mod.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,9 @@ pub struct Mir<'tcx> {
153153
/// `||` expression into `&` or `|` respectively. This is problematic because if we ever stop
154154
/// this conversion from happening and use short circuiting, we will cause the following code
155155
/// to change the value of `x`: `let mut x = 42; false && { x = 55; true };`
156-
pub control_flow_destroyed: bool,
156+
///
157+
/// List of places where control flow was destroyed. Used for error reporting.
158+
pub control_flow_destroyed: Vec<(Span, String)>,
157159

158160
/// A span representing this MIR, for error reporting
159161
pub span: Span,
@@ -173,7 +175,7 @@ impl<'tcx> Mir<'tcx> {
173175
arg_count: usize,
174176
upvar_decls: Vec<UpvarDecl>,
175177
span: Span,
176-
control_flow_destroyed: bool,
178+
control_flow_destroyed: Vec<(Span, String)>,
177179
) -> Self {
178180
// We need `arg_count` locals, and one for the return place
179181
assert!(

src/librustc/ty/structural_impls.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ CloneTypeFoldableAndLiftImpls! {
3535
usize,
3636
::ty::layout::VariantIdx,
3737
u64,
38+
String,
3839
::middle::region::Scope,
3940
::syntax::ast::FloatTy,
4041
::syntax::ast::NodeId,

src/librustc_mir/hair/cx/expr.rs

Lines changed: 6 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ use rustc::hir;
2323
use rustc::hir::def_id::LocalDefId;
2424
use rustc::mir::{BorrowKind};
2525
use syntax_pos::Span;
26-
use syntax::errors::Applicability;
2726

2827
impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
2928
type Output = Expr<'tcx>;
@@ -373,37 +372,21 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
373372
// FIXME(eddyb) use logical ops in constants when
374373
// they can handle that kind of control-flow.
375374
(hir::BinOpKind::And, hir::Constness::Const) => {
376-
cx.control_flow_destroyed = true;
377-
cx.tcx.sess.struct_span_warn(
375+
cx.control_flow_destroyed.push((
378376
op.span,
379-
"boolean short circuiting operators in constants do \
380-
not actually short circuit. Thus new const eval features \
381-
are not accessible in constants."
382-
).span_suggestion_with_applicability(
383-
op.span,
384-
"use a bit operator instead",
385-
"&".into(),
386-
Applicability::MachineApplicable,
387-
).emit();
377+
"`&&` operator".into(),
378+
));
388379
ExprKind::Binary {
389380
op: BinOp::BitAnd,
390381
lhs: lhs.to_ref(),
391382
rhs: rhs.to_ref(),
392383
}
393384
}
394385
(hir::BinOpKind::Or, hir::Constness::Const) => {
395-
cx.control_flow_destroyed = true;
396-
cx.tcx.sess.struct_span_warn(
397-
op.span,
398-
"boolean short circuiting operators in constants do \
399-
not actually short circuit. Thus new const eval features \
400-
are not accessible in constants."
401-
).span_suggestion_with_applicability(
386+
cx.control_flow_destroyed.push((
402387
op.span,
403-
"use a bit operator instead",
404-
"|".into(),
405-
Applicability::MachineApplicable,
406-
).emit();
388+
"`||` operator".into(),
389+
));
407390
ExprKind::Binary {
408391
op: BinOp::BitOr,
409392
lhs: lhs.to_ref(),

src/librustc_mir/hair/cx/mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ pub struct Cx<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
5858
check_overflow: bool,
5959

6060
/// See field with the same name on `Mir`
61-
control_flow_destroyed: bool,
61+
control_flow_destroyed: Vec<(Span, String)>,
6262
}
6363

6464
impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
@@ -99,11 +99,11 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
9999
constness,
100100
body_owner_kind,
101101
check_overflow,
102-
control_flow_destroyed: false,
102+
control_flow_destroyed: Vec::new(),
103103
}
104104
}
105105

106-
pub fn control_flow_destroyed(&self) -> bool {
106+
pub fn control_flow_destroyed(self) -> Vec<(Span, String)> {
107107
self.control_flow_destroyed
108108
}
109109
}

src/librustc_mir/shim.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ fn build_drop_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
220220
sig.inputs().len(),
221221
vec![],
222222
span,
223-
true,
223+
vec![],
224224
);
225225

226226
if let Some(..) = ty {
@@ -389,7 +389,7 @@ impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> {
389389
self.sig.inputs().len(),
390390
vec![],
391391
self.span,
392-
true,
392+
vec![],
393393
)
394394
}
395395

@@ -838,7 +838,7 @@ fn build_call_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
838838
sig.inputs().len(),
839839
vec![],
840840
span,
841-
true,
841+
vec![],
842842
);
843843
if let Abi::RustCall = sig.abi {
844844
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>,
916916
sig.inputs().len(),
917917
vec![],
918918
span,
919-
true,
919+
vec![],
920920
)
921921
}

src/librustc_mir/transform/promote_consts.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -413,7 +413,7 @@ pub fn promote_candidates<'a, 'tcx>(mir: &mut Mir<'tcx>,
413413
0,
414414
vec![],
415415
mir.span,
416-
false,
416+
vec![],
417417
),
418418
tcx,
419419
source: mir,

src/librustc_mir/transform/qualify_consts.rs

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1335,17 +1335,32 @@ impl MirPass for QualifyAndPromoteConstants {
13351335
// Do the actual promotion, now that we know what's viable.
13361336
promote_consts::promote_candidates(mir, tcx, temps, candidates);
13371337
} else {
1338-
if mir.control_flow_destroyed {
1339-
for local in mir.vars_iter() {
1338+
if !mir.control_flow_destroyed.is_empty() {
1339+
let mut locals = mir.vars_iter();
1340+
if let Some(local) = locals.next() {
13401341
let span = mir.local_decls[local].source_info.span;
1341-
tcx.sess.span_err(
1342+
let mut error = tcx.sess.struct_span_err(
13421343
span,
13431344
&format!(
1344-
"short circuiting operators do not actually short circuit in {}. \
1345-
Thus new features like let bindings are not permitted",
1345+
"new features like let bindings are not permitted in {} \
1346+
which also use short circuiting operators",
13461347
mode,
13471348
),
13481349
);
1350+
for (span, kind) in mir.control_flow_destroyed.iter() {
1351+
error.span_note(
1352+
*span,
1353+
&format!("use of {} here", kind),
1354+
);
1355+
}
1356+
for local in locals {
1357+
let span = mir.local_decls[local].source_info.span;
1358+
error.span_note(
1359+
span,
1360+
"more locals defined here",
1361+
);
1362+
}
1363+
error.emit();
13491364
}
13501365
}
13511366
let promoted_temps = if mode == Mode::Const {

src/test/run-pass/ctfe/issue-37550.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
#![allow(dead_code)]
1313
#![allow(unused_variables)]
1414

15-
#![feature(const_fn)]
15+
#![feature(const_fn, const_let)]
1616

1717
const fn x() {
1818
let t = true;

src/test/ui/consts/const_short_circuit.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
#![feature(underscore_const_names, const_let)]
22

3-
const _: bool = false && false; //~ WARN boolean short circuiting operators in constants
4-
const _: bool = true && false; //~ WARN boolean short circuiting operators in constants
3+
const _: bool = false && false;
4+
const _: bool = true && false;
55
const _: bool = {
6-
let mut x = true && false; //~ WARN boolean short circuiting operators in constants
7-
//~^ ERROR short circuiting operators do not actually short circuit in constant
6+
let mut x = true && false;
7+
//~^ ERROR new features like let bindings are not permitted
88
x
99
};
1010
const _: bool = {
11-
let x = true && false; //~ WARN boolean short circuiting operators in constants
12-
//~^ ERROR short circuiting operators do not actually short circuit in constant
11+
let x = true && false;
12+
//~^ ERROR new features like let bindings are not permitted
1313
x
1414
};
1515

Lines changed: 15 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,26 @@
1-
warning: boolean short circuiting operators in constants do not actually short circuit. Thus new const eval features are not accessible in constants.
2-
--> $DIR/const_short_circuit.rs:3:23
3-
|
4-
LL | const _: bool = false && false; //~ WARN boolean short circuiting operators in constants
5-
| ^^ help: use a bit operator instead: `&`
6-
7-
warning: boolean short circuiting operators in constants do not actually short circuit. Thus new const eval features are not accessible in constants.
8-
--> $DIR/const_short_circuit.rs:4:22
9-
|
10-
LL | const _: bool = true && false; //~ WARN boolean short circuiting operators in constants
11-
| ^^ help: use a bit operator instead: `&`
12-
13-
warning: boolean short circuiting operators in constants do not actually short circuit. Thus new const eval features are not accessible in constants.
14-
--> $DIR/const_short_circuit.rs:6:22
15-
|
16-
LL | let mut x = true && false; //~ WARN boolean short circuiting operators in constants
17-
| ^^ help: use a bit operator instead: `&`
18-
19-
error: short circuiting operators do not actually short circuit in constant. Thus new features like let bindings are not permitted
1+
error: new features like let bindings are not permitted in constant which also use short circuiting operators
202
--> $DIR/const_short_circuit.rs:6:9
213
|
22-
LL | let mut x = true && false; //~ WARN boolean short circuiting operators in constants
4+
LL | let mut x = true && false;
235
| ^^^^^
24-
25-
warning: boolean short circuiting operators in constants do not actually short circuit. Thus new const eval features are not accessible in constants.
26-
--> $DIR/const_short_circuit.rs:11:18
276
|
28-
LL | let x = true && false; //~ WARN boolean short circuiting operators in constants
29-
| ^^ help: use a bit operator instead: `&`
7+
note: use of `&&` operator here
8+
--> $DIR/const_short_circuit.rs:6:22
9+
|
10+
LL | let mut x = true && false;
11+
| ^^
3012

31-
error: short circuiting operators do not actually short circuit in constant. Thus new features like let bindings are not permitted
13+
error: new features like let bindings are not permitted in constant which also use short circuiting operators
3214
--> $DIR/const_short_circuit.rs:11:9
3315
|
34-
LL | let x = true && false; //~ WARN boolean short circuiting operators in constants
16+
LL | let x = true && false;
3517
| ^
18+
|
19+
note: use of `&&` operator here
20+
--> $DIR/const_short_circuit.rs:11:18
21+
|
22+
LL | let x = true && false;
23+
| ^^
3624

3725
error: aborting due to 2 previous errors
3826

0 commit comments

Comments
 (0)