Skip to content

Commit 47cb871

Browse files
committed
review
1 parent 6ad140c commit 47cb871

File tree

2 files changed

+45
-35
lines changed

2 files changed

+45
-35
lines changed

compiler/rustc_trait_selection/src/traits/const_evaluatable.rs

+36-32
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,13 @@ impl AbstractConst<'tcx> {
223223
}
224224
}
225225

226+
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
227+
struct WorkNode<'tcx> {
228+
node: Node<'tcx>,
229+
span: Span,
230+
used: bool,
231+
}
232+
226233
struct AbstractConstBuilder<'a, 'tcx> {
227234
tcx: TyCtxt<'tcx>,
228235
body: &'a mir::Body<'tcx>,
@@ -232,7 +239,7 @@ struct AbstractConstBuilder<'a, 'tcx> {
232239
/// so we store this here. Note that we also consider nodes as used
233240
/// if they are mentioned in an assert, so some used nodes are never
234241
/// actually reachable by walking the [`AbstractConst`].
235-
nodes: IndexVec<NodeId, (Node<'tcx>, bool)>,
242+
nodes: IndexVec<NodeId, WorkNode<'tcx>>,
236243
locals: IndexVec<mir::Local, NodeId>,
237244
/// We only allow field accesses if they access
238245
/// the result of a checked operation.
@@ -279,25 +286,25 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
279286
Ok(Some(builder))
280287
}
281288

282-
fn add_node(&mut self, n: Node<'tcx>) -> NodeId {
289+
fn add_node(&mut self, node: Node<'tcx>, span: Span) -> NodeId {
283290
// Mark used nodes.
284-
match n {
291+
match node {
285292
Node::Leaf(_) => (),
286293
Node::Binop(_, lhs, rhs) => {
287-
self.nodes[lhs].1 = true;
288-
self.nodes[rhs].1 = true;
294+
self.nodes[lhs].used = true;
295+
self.nodes[rhs].used = true;
289296
}
290297
Node::UnaryOp(_, input) => {
291-
self.nodes[input].1 = true;
298+
self.nodes[input].used = true;
292299
}
293300
Node::FunctionCall(func, nodes) => {
294-
self.nodes[func].1 = true;
295-
nodes.iter().for_each(|&n| self.nodes[n].1 = true);
301+
self.nodes[func].used = true;
302+
nodes.iter().for_each(|&n| self.nodes[n].used = true);
296303
}
297304
}
298305

299306
// Nodes start as unused.
300-
self.nodes.push((n, false))
307+
self.nodes.push(WorkNode { node, span, used: false })
301308
}
302309

303310
fn place_to_local(
@@ -337,7 +344,7 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
337344
let local = self.place_to_local(span, p)?;
338345
Ok(self.locals[local])
339346
}
340-
mir::Operand::Constant(ct) => Ok(self.add_node(Node::Leaf(ct.literal))),
347+
mir::Operand::Constant(ct) => Ok(self.add_node(Node::Leaf(ct.literal), span)),
341348
}
342349
}
343350

@@ -362,38 +369,38 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
362369

363370
fn build_statement(&mut self, stmt: &mir::Statement<'tcx>) -> Result<(), ErrorReported> {
364371
debug!("AbstractConstBuilder: stmt={:?}", stmt);
372+
let span = stmt.source_info.span;
365373
match stmt.kind {
366374
StatementKind::Assign(box (ref place, ref rvalue)) => {
367-
let local = self.place_to_local(stmt.source_info.span, place)?;
375+
let local = self.place_to_local(span, place)?;
368376
match *rvalue {
369377
Rvalue::Use(ref operand) => {
370-
self.locals[local] =
371-
self.operand_to_node(stmt.source_info.span, operand)?;
378+
self.locals[local] = self.operand_to_node(span, operand)?;
372379
Ok(())
373380
}
374381
Rvalue::BinaryOp(op, ref lhs, ref rhs) if Self::check_binop(op) => {
375-
let lhs = self.operand_to_node(stmt.source_info.span, lhs)?;
376-
let rhs = self.operand_to_node(stmt.source_info.span, rhs)?;
377-
self.locals[local] = self.add_node(Node::Binop(op, lhs, rhs));
382+
let lhs = self.operand_to_node(span, lhs)?;
383+
let rhs = self.operand_to_node(span, rhs)?;
384+
self.locals[local] = self.add_node(Node::Binop(op, lhs, rhs), span);
378385
if op.is_checkable() {
379386
bug!("unexpected unchecked checkable binary operation");
380387
} else {
381388
Ok(())
382389
}
383390
}
384391
Rvalue::CheckedBinaryOp(op, ref lhs, ref rhs) if Self::check_binop(op) => {
385-
let lhs = self.operand_to_node(stmt.source_info.span, lhs)?;
386-
let rhs = self.operand_to_node(stmt.source_info.span, rhs)?;
387-
self.locals[local] = self.add_node(Node::Binop(op, lhs, rhs));
392+
let lhs = self.operand_to_node(span, lhs)?;
393+
let rhs = self.operand_to_node(span, rhs)?;
394+
self.locals[local] = self.add_node(Node::Binop(op, lhs, rhs), span);
388395
self.checked_op_locals.insert(local);
389396
Ok(())
390397
}
391398
Rvalue::UnaryOp(op, ref operand) if Self::check_unop(op) => {
392-
let operand = self.operand_to_node(stmt.source_info.span, operand)?;
393-
self.locals[local] = self.add_node(Node::UnaryOp(op, operand));
399+
let operand = self.operand_to_node(span, operand)?;
400+
self.locals[local] = self.add_node(Node::UnaryOp(op, operand), span);
394401
Ok(())
395402
}
396-
_ => self.error(Some(stmt.source_info.span), "unsupported rvalue")?,
403+
_ => self.error(Some(span), "unsupported rvalue")?,
397404
}
398405
}
399406
// These are not actually relevant for us here, so we can ignore them.
@@ -441,7 +448,7 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
441448
.map(|arg| self.operand_to_node(terminator.source_info.span, arg))
442449
.collect::<Result<Vec<NodeId>, _>>()?,
443450
);
444-
self.locals[local] = self.add_node(Node::FunctionCall(func, args));
451+
self.locals[local] = self.add_node(Node::FunctionCall(func, args), fn_span);
445452
Ok(Some(target))
446453
}
447454
TerminatorKind::Assert { ref cond, expected: false, target, .. } => {
@@ -458,7 +465,7 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
458465
//
459466
// This is needed because division does not use `CheckedBinop` but instead
460467
// adds an explicit assert for `divisor != 0`.
461-
self.nodes[self.locals[p]].1 = true;
468+
self.nodes[self.locals[p]].used = true;
462469
return Ok(Some(target));
463470
} else if let &[mir::ProjectionElem::Field(ONE_FIELD, _)] = p.projection.as_ref() {
464471
// Only allow asserts checking the result of a checked operation.
@@ -487,16 +494,13 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
487494
if let Some(next) = self.build_terminator(block.terminator())? {
488495
block = &self.body.basic_blocks()[next];
489496
} else {
490-
assert_eq!(self.locals[mir::Local::from_usize(0)], self.nodes.last().unwrap());
491-
self.nodes[self.locals[mir::Local::from_usize(0)]].1 = true;
492-
if !self.nodes.iter().all(|n| n.1) {
493-
self.error(None, "unused node")?;
497+
assert_eq!(self.locals[mir::RETURN_PLACE], self.nodes.last().unwrap());
498+
self.nodes[self.locals[mir::RETURN_PLACE]].used = true;
499+
if let Some(&unused) = self.nodes.iter().find(|n| !n.used) {
500+
self.error(Some(unused.span), "dead code")?;
494501
}
495502

496-
return Ok(self
497-
.tcx
498-
.arena
499-
.alloc_from_iter(self.nodes.into_iter().map(|(n, _used)| n)));
503+
return Ok(self.tcx.arena.alloc_from_iter(self.nodes.into_iter().map(|n| n.node)));
500504
}
501505
}
502506
}

src/test/ui/const-generics/const_evaluatable_checked/unused_expr.stderr

+9-3
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,29 @@ error: overly complex generic constant
22
--> $DIR/unused_expr.rs:4:34
33
|
44
LL | fn add<const N: usize>() -> [u8; { N + 1; 5 }] {
5-
| ^^^^^^^^^^^^ unused node
5+
| ^^-----^^^^^
6+
| |
7+
| dead code
68
|
79
= help: consider moving this anonymous constant into a `const` function
810

911
error: overly complex generic constant
1012
--> $DIR/unused_expr.rs:9:34
1113
|
1214
LL | fn div<const N: usize>() -> [u8; { N / 1; 5 }] {
13-
| ^^^^^^^^^^^^ unused node
15+
| ^^-----^^^^^
16+
| |
17+
| dead code
1418
|
1519
= help: consider moving this anonymous constant into a `const` function
1620

1721
error: overly complex generic constant
1822
--> $DIR/unused_expr.rs:16:38
1923
|
2024
LL | fn fn_call<const N: usize>() -> [u8; { foo(N); 5 }] {
21-
| ^^^^^^^^^^^^^ unused node
25+
| ^^------^^^^^
26+
| |
27+
| dead code
2228
|
2329
= help: consider moving this anonymous constant into a `const` function
2430

0 commit comments

Comments
 (0)