Skip to content

Commit 8e7299d

Browse files
committed
Support as casts in abstract consts
1 parent dda4a88 commit 8e7299d

File tree

7 files changed

+66
-14
lines changed

7 files changed

+66
-14
lines changed

compiler/rustc_middle/src/mir/abstract_const.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! A subset of a mir body used for const evaluatability checking.
2-
use crate::mir;
3-
use crate::ty;
2+
use crate::mir::{self, CastKind};
3+
use crate::ty::{self, Ty};
44

55
rustc_index::newtype_index! {
66
/// An index into an `AbstractConst`.
@@ -17,6 +17,7 @@ pub enum Node<'tcx> {
1717
Binop(mir::BinOp, NodeId, NodeId),
1818
UnaryOp(mir::UnOp, NodeId),
1919
FunctionCall(NodeId, &'tcx [NodeId]),
20+
Cast(CastKind, NodeId, Ty<'tcx>),
2021
}
2122

2223
#[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)]

compiler/rustc_privacy/src/lib.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -156,9 +156,10 @@ where
156156
let leaf = leaf.subst(tcx, ct.substs);
157157
self.visit_const(leaf)
158158
}
159-
ACNode::Binop(..) | ACNode::UnaryOp(..) | ACNode::FunctionCall(_, _) => {
160-
ControlFlow::CONTINUE
161-
}
159+
ACNode::Binop(..)
160+
| ACNode::UnaryOp(..)
161+
| ACNode::FunctionCall(_, _)
162+
| ACNode::Cast(_, _, _) => ControlFlow::CONTINUE,
162163
})
163164
}
164165

compiler/rustc_trait_selection/src/traits/const_evaluatable.rs

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -97,9 +97,10 @@ pub fn is_const_evaluatable<'cx, 'tcx>(
9797

9898
ControlFlow::CONTINUE
9999
}
100-
Node::Binop(_, _, _) | Node::UnaryOp(_, _) | Node::FunctionCall(_, _) => {
101-
ControlFlow::CONTINUE
102-
}
100+
Node::Binop(_, _, _)
101+
| Node::UnaryOp(_, _)
102+
| Node::FunctionCall(_, _)
103+
| Node::Cast(_, _, _) => ControlFlow::CONTINUE,
103104
});
104105

105106
match failure_kind {
@@ -304,6 +305,9 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
304305
self.nodes[func].used = true;
305306
nodes.iter().for_each(|&n| self.nodes[n].used = true);
306307
}
308+
Node::Cast(_, operand, _) => {
309+
self.nodes[operand].used = true;
310+
}
307311
}
308312

309313
// Nodes start as unused.
@@ -408,6 +412,12 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
408412
self.locals[local] = self.add_node(Node::UnaryOp(op, operand), span);
409413
Ok(())
410414
}
415+
Rvalue::Cast(cast_kind, ref operand, ty) => {
416+
let operand = self.operand_to_node(span, operand)?;
417+
self.locals[local] =
418+
self.add_node(Node::Cast(cast_kind, operand, ty), span);
419+
Ok(())
420+
}
411421
_ => self.error(Some(span), "unsupported rvalue")?,
412422
}
413423
}
@@ -594,6 +604,7 @@ where
594604
recurse(tcx, ct.subtree(func), f)?;
595605
args.iter().try_for_each(|&arg| recurse(tcx, ct.subtree(arg), f))
596606
}
607+
Node::Cast(_, operand, _) => recurse(tcx, ct.subtree(operand), f),
597608
}
598609
}
599610

@@ -676,6 +687,11 @@ pub(super) fn try_unify<'tcx>(
676687
&& iter::zip(a_args, b_args)
677688
.all(|(&an, &bn)| try_unify(tcx, a.subtree(an), b.subtree(bn)))
678689
}
690+
(Node::Cast(a_cast_kind, a_operand, a_ty), Node::Cast(b_cast_kind, b_operand, b_ty))
691+
if (a_ty == b_ty) && (a_cast_kind == b_cast_kind) =>
692+
{
693+
try_unify(tcx, a.subtree(a_operand), b.subtree(b_operand))
694+
}
679695
_ => false,
680696
}
681697
}

compiler/rustc_trait_selection/src/traits/object_safety.rs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -838,9 +838,10 @@ fn contains_illegal_self_type_reference<'tcx, T: TypeFoldable<'tcx>>(
838838
let leaf = leaf.subst(self.tcx, ct.substs);
839839
self.visit_const(leaf)
840840
}
841-
Node::Binop(..) | Node::UnaryOp(..) | Node::FunctionCall(_, _) => {
842-
ControlFlow::CONTINUE
843-
}
841+
Node::Binop(..)
842+
| Node::UnaryOp(..)
843+
| Node::FunctionCall(_, _)
844+
| Node::Cast(_, _, _) => ControlFlow::CONTINUE,
844845
})
845846
} else {
846847
ControlFlow::CONTINUE
@@ -859,9 +860,10 @@ fn contains_illegal_self_type_reference<'tcx, T: TypeFoldable<'tcx>>(
859860
let leaf = leaf.subst(self.tcx, ct.substs);
860861
self.visit_const(leaf)
861862
}
862-
Node::Binop(..) | Node::UnaryOp(..) | Node::FunctionCall(_, _) => {
863-
ControlFlow::CONTINUE
864-
}
863+
Node::Binop(..)
864+
| Node::UnaryOp(..)
865+
| Node::FunctionCall(_, _)
866+
| Node::Cast(_, _, _) => ControlFlow::CONTINUE,
865867
})
866868
} else {
867869
ControlFlow::CONTINUE
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#![feature(const_evaluatable_checked, const_generics)]
2+
#![allow(incomplete_features)]
3+
4+
trait Evaluatable<const N: u128> {}
5+
impl<const N: u128> Evaluatable<N> for () {}
6+
7+
struct Foo<const N: u8>([u8; N as usize])
8+
//~^ Error: unconstrained generic constant
9+
//~| help: try adding a `where` bound using this expression: `where [(); N as usize]:`
10+
where
11+
(): Evaluatable<{N as u128}>;
12+
13+
fn main() {}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
error: unconstrained generic constant
2+
--> $DIR/abstract-const-as-cast-2.rs:7:25
3+
|
4+
LL | struct Foo<const N: u8>([u8; N as usize])
5+
| ^^^^^^^^^^^^^^^^
6+
|
7+
= help: try adding a `where` bound using this expression: `where [(); N as usize]:`
8+
9+
error: aborting due to previous error
10+
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// check-pass
2+
#![feature(const_evaluatable_checked, const_generics)]
3+
#![allow(incomplete_features)]
4+
5+
struct Foo<const N: u8>([u8; N as usize])
6+
where
7+
[(); N as usize]:;
8+
9+
fn main() {}

0 commit comments

Comments
 (0)