Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit d1294e0

Browse files
committed
allow unary operations and ignore StorageLive/Dead stmts
1 parent 5a27782 commit d1294e0

File tree

2 files changed

+37
-4
lines changed

2 files changed

+37
-4
lines changed

compiler/rustc_trait_selection/src/traits/const_evaluatable.rs

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,7 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
174174
}
175175
}
176176

177+
/// We do not allow all binary operations in abstract consts, so filter disallowed ones.
177178
fn check_binop(op: mir::BinOp) -> bool {
178179
use mir::BinOp::*;
179180
match op {
@@ -183,6 +184,15 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
183184
}
184185
}
185186

187+
/// While we currently allow all unary operations, we still want to explicitly guard against
188+
/// future changes here.
189+
fn check_unop(op: mir::UnOp) -> bool {
190+
use mir::UnOp::*;
191+
match op {
192+
Not | Neg => true,
193+
}
194+
}
195+
186196
fn build_statement(&mut self, stmt: &mir::Statement<'tcx>) -> Option<()> {
187197
debug!("AbstractConstBuilder: stmt={:?}", stmt);
188198
match stmt.kind {
@@ -191,28 +201,37 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
191201
match *rvalue {
192202
Rvalue::Use(ref operand) => {
193203
self.locals[local] = self.operand_to_node(operand)?;
204+
Some(())
194205
}
195206
Rvalue::BinaryOp(op, ref lhs, ref rhs) if Self::check_binop(op) => {
196207
let lhs = self.operand_to_node(lhs)?;
197208
let rhs = self.operand_to_node(rhs)?;
198209
self.locals[local] = self.nodes.push(Node::Binop(op, lhs, rhs));
199210
if op.is_checkable() {
200211
bug!("unexpected unchecked checkable binary operation");
212+
} else {
213+
Some(())
201214
}
202215
}
203216
Rvalue::CheckedBinaryOp(op, ref lhs, ref rhs) if Self::check_binop(op) => {
204217
let lhs = self.operand_to_node(lhs)?;
205218
let rhs = self.operand_to_node(rhs)?;
206219
self.locals[local] = self.nodes.push(Node::Binop(op, lhs, rhs));
207220
self.checked_op_locals.insert(local);
221+
Some(())
208222
}
209-
_ => return None,
223+
Rvalue::UnaryOp(op, ref operand) if Self::check_unop(op) => {
224+
let operand = self.operand_to_node(operand)?;
225+
self.locals[local] = self.nodes.push(Node::UnaryOp(op, operand));
226+
Some(())
227+
}
228+
_ => None,
210229
}
211230
}
212-
_ => return None,
231+
// These are not actually relevant for us here, so we can ignore them.
232+
StatementKind::StorageLive(_) | StatementKind::StorageDead(_) => Some(()),
233+
_ => None,
213234
}
214-
215-
Some(())
216235
}
217236

218237
fn build_terminator(
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// run-pass
2+
#![feature(const_generics, const_evaluatable_checked)]
3+
#![allow(incomplete_features)]
4+
5+
struct Foo<const B: bool>;
6+
7+
fn test<const N: usize>() -> Foo<{ !(N > 10) }> where Foo<{ !(N > 10) }>: Sized {
8+
Foo
9+
}
10+
11+
fn main() {
12+
let _: Foo<false> = test::<12>();
13+
let _: Foo<true> = test::<9>();
14+
}

0 commit comments

Comments
 (0)