diff --git a/compiler/rustc_middle/src/mir/abstract_const.rs b/compiler/rustc_middle/src/mir/abstract_const.rs index 776a777b1bd..1ef10241143 100644 --- a/compiler/rustc_middle/src/mir/abstract_const.rs +++ b/compiler/rustc_middle/src/mir/abstract_const.rs @@ -1,6 +1,6 @@ //! A subset of a mir body used for const evaluatability checking. -use crate::mir; -use crate::ty; +use crate::mir::{self, CastKind}; +use crate::ty::{self, Ty}; rustc_index::newtype_index! { /// An index into an `AbstractConst`. @@ -17,6 +17,7 @@ pub enum Node<'tcx> { Binop(mir::BinOp, NodeId, NodeId), UnaryOp(mir::UnOp, NodeId), FunctionCall(NodeId, &'tcx [NodeId]), + Cast(CastKind, NodeId, Ty<'tcx>), } #[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)] diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index e64f12ef48f..05139b9404f 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -156,9 +156,10 @@ where let leaf = leaf.subst(tcx, ct.substs); self.visit_const(leaf) } - ACNode::Binop(..) | ACNode::UnaryOp(..) | ACNode::FunctionCall(_, _) => { - ControlFlow::CONTINUE - } + ACNode::Binop(..) + | ACNode::UnaryOp(..) + | ACNode::FunctionCall(_, _) + | ACNode::Cast(_, _, _) => ControlFlow::CONTINUE, }) } diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs index 8961cdaebf3..8954918b43c 100644 --- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs +++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs @@ -97,9 +97,10 @@ pub fn is_const_evaluatable<'cx, 'tcx>( ControlFlow::CONTINUE } - Node::Binop(_, _, _) | Node::UnaryOp(_, _) | Node::FunctionCall(_, _) => { - ControlFlow::CONTINUE - } + Node::Binop(_, _, _) + | Node::UnaryOp(_, _) + | Node::FunctionCall(_, _) + | Node::Cast(_, _, _) => ControlFlow::CONTINUE, }); match failure_kind { @@ -304,6 +305,9 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> { self.nodes[func].used = true; nodes.iter().for_each(|&n| self.nodes[n].used = true); } + Node::Cast(_, operand, _) => { + self.nodes[operand].used = true; + } } // Nodes start as unused. @@ -408,6 +412,12 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> { self.locals[local] = self.add_node(Node::UnaryOp(op, operand), span); Ok(()) } + Rvalue::Cast(cast_kind, ref operand, ty) => { + let operand = self.operand_to_node(span, operand)?; + self.locals[local] = + self.add_node(Node::Cast(cast_kind, operand, ty), span); + Ok(()) + } _ => self.error(Some(span), "unsupported rvalue")?, } } @@ -594,6 +604,7 @@ where recurse(tcx, ct.subtree(func), f)?; args.iter().try_for_each(|&arg| recurse(tcx, ct.subtree(arg), f)) } + Node::Cast(_, operand, _) => recurse(tcx, ct.subtree(operand), f), } } @@ -676,6 +687,11 @@ pub(super) fn try_unify<'tcx>( && iter::zip(a_args, b_args) .all(|(&an, &bn)| try_unify(tcx, a.subtree(an), b.subtree(bn))) } + (Node::Cast(a_cast_kind, a_operand, a_ty), Node::Cast(b_cast_kind, b_operand, b_ty)) + if (a_ty == b_ty) && (a_cast_kind == b_cast_kind) => + { + try_unify(tcx, a.subtree(a_operand), b.subtree(b_operand)) + } _ => false, } } diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs index d5e1bd3f9ea..ac63f2e25db 100644 --- a/compiler/rustc_trait_selection/src/traits/object_safety.rs +++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs @@ -838,9 +838,10 @@ fn contains_illegal_self_type_reference<'tcx, T: TypeFoldable<'tcx>>( let leaf = leaf.subst(self.tcx, ct.substs); self.visit_const(leaf) } - Node::Binop(..) | Node::UnaryOp(..) | Node::FunctionCall(_, _) => { - ControlFlow::CONTINUE - } + Node::Binop(..) + | Node::UnaryOp(..) + | Node::FunctionCall(_, _) + | Node::Cast(_, _, _) => ControlFlow::CONTINUE, }) } else { ControlFlow::CONTINUE @@ -859,9 +860,10 @@ fn contains_illegal_self_type_reference<'tcx, T: TypeFoldable<'tcx>>( let leaf = leaf.subst(self.tcx, ct.substs); self.visit_const(leaf) } - Node::Binop(..) | Node::UnaryOp(..) | Node::FunctionCall(_, _) => { - ControlFlow::CONTINUE - } + Node::Binop(..) + | Node::UnaryOp(..) + | Node::FunctionCall(_, _) + | Node::Cast(_, _, _) => ControlFlow::CONTINUE, }) } else { ControlFlow::CONTINUE diff --git a/src/test/ui/const-generics/const_evaluatable_checked/abstract-const-as-cast-2.rs b/src/test/ui/const-generics/const_evaluatable_checked/abstract-const-as-cast-2.rs new file mode 100644 index 00000000000..a8f5b89d229 --- /dev/null +++ b/src/test/ui/const-generics/const_evaluatable_checked/abstract-const-as-cast-2.rs @@ -0,0 +1,13 @@ +#![feature(const_evaluatable_checked, const_generics)] +#![allow(incomplete_features)] + +trait Evaluatable {} +impl Evaluatable for () {} + +struct Foo([u8; N as usize]) +//~^ Error: unconstrained generic constant +//~| help: try adding a `where` bound using this expression: `where [(); N as usize]:` +where + (): Evaluatable<{N as u128}>; + +fn main() {} diff --git a/src/test/ui/const-generics/const_evaluatable_checked/abstract-const-as-cast-2.stderr b/src/test/ui/const-generics/const_evaluatable_checked/abstract-const-as-cast-2.stderr new file mode 100644 index 00000000000..167e116f557 --- /dev/null +++ b/src/test/ui/const-generics/const_evaluatable_checked/abstract-const-as-cast-2.stderr @@ -0,0 +1,10 @@ +error: unconstrained generic constant + --> $DIR/abstract-const-as-cast-2.rs:7:25 + | +LL | struct Foo([u8; N as usize]) + | ^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); N as usize]:` + +error: aborting due to previous error + diff --git a/src/test/ui/const-generics/const_evaluatable_checked/abstract-const-as-cast.rs b/src/test/ui/const-generics/const_evaluatable_checked/abstract-const-as-cast.rs new file mode 100644 index 00000000000..33146d95536 --- /dev/null +++ b/src/test/ui/const-generics/const_evaluatable_checked/abstract-const-as-cast.rs @@ -0,0 +1,9 @@ +// check-pass +#![feature(const_evaluatable_checked, const_generics)] +#![allow(incomplete_features)] + +struct Foo([u8; N as usize]) +where + [(); N as usize]:; + +fn main() {}