Skip to content

Commit 9b29138

Browse files
committed
as casts and block exprs
1 parent 2987f4b commit 9b29138

File tree

4 files changed

+57
-35
lines changed

4 files changed

+57
-35
lines changed

compiler/rustc_middle/src/mir/abstract_const.rs

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

55
rustc_index::newtype_index! {
@@ -18,7 +18,7 @@ pub enum Node<'tcx> {
1818
UnaryOp(mir::UnOp, NodeId),
1919
FunctionCall(NodeId, &'tcx [NodeId]),
2020
Block(&'tcx [NodeId], Option<NodeId>),
21-
Cast(CastKind, NodeId, Ty<'tcx>),
21+
Cast(NodeId, Ty<'tcx>),
2222
}
2323

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

compiler/rustc_privacy/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ where
158158
let leaf = leaf.subst(tcx, ct.substs);
159159
self.visit_const(leaf)
160160
}
161-
ACNode::Cast(_, _, ty) => self.visit_ty(ty),
161+
ACNode::Cast(_, ty) => self.visit_ty(ty),
162162
ACNode::Block(_, _)
163163
| ACNode::Binop(..)
164164
| ACNode::UnaryOp(..)

compiler/rustc_trait_selection/src/traits/const_evaluatable.rs

Lines changed: 53 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ pub fn is_const_evaluatable<'cx, 'tcx>(
9292

9393
ControlFlow::CONTINUE
9494
}
95-
Node::Cast(_, _, ty) => {
95+
Node::Cast(_, ty) => {
9696
let ty = ty.subst(tcx, ct.substs);
9797
if ty.has_infer_types_or_consts() {
9898
failure_kind = FailureKind::MentionsInfer;
@@ -292,7 +292,7 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
292292
stmts.iter().for_each(|&id| self.nodes[id].used = true);
293293
opt_expr.map(|e| self.nodes[e].used = true);
294294
}
295-
Node::Cast(_, operand, _) => {
295+
Node::Cast(operand, _) => {
296296
self.nodes[operand].used = true;
297297
}
298298
}
@@ -335,6 +335,7 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
335335
}
336336
}
337337

338+
// FIXME I dont even think we can get unused nodes anymore with thir abstract const
338339
if let Some(&unused) = self.nodes.iter().find(|n| !n.used) {
339340
self.error(Some(unused.span), "dead code")?;
340341
}
@@ -352,6 +353,8 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
352353
&ExprKind::PlaceTypeAscription { source, .. } |
353354
&ExprKind::ValueTypeAscription { source, .. } => self.recurse_build(source)?,
354355

356+
// subtle: associated consts are literals this arm handles
357+
// `<T as Trait>::ASSOC` as well as `12`
355358
&ExprKind::Literal { literal, .. }
356359
| &ExprKind::StaticRef { literal, .. } => self.add_node(Node::Leaf(literal), node.span),
357360

@@ -375,14 +378,6 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
375378
let arg = self.recurse_build(arg)?;
376379
self.add_node(Node::UnaryOp(op, arg), node.span)
377380
},
378-
// HACK: without this arm the following doesn't compile:
379-
// ```
380-
// fn foo<const N: usize>(_: [(); N + 1]) {
381-
// bar::<{ N + 1}>();
382-
// }
383-
// ```
384-
// we ought to properly handle this in `try_unify`
385-
ExprKind::Block { body: thir::Block { stmts: box [], expr: Some(e), .. }} => self.recurse_build(*e)?,
386381
ExprKind::Block { body } => {
387382
let mut stmts = Vec::with_capacity(body.stmts.len());
388383
for &id in body.stmts.iter() {
@@ -398,26 +393,34 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
398393
let opt_expr = body.expr.map(|e| self.recurse_build(e)).transpose()?;
399394
self.add_node(Node::Block(stmts, opt_expr), node.span)
400395
}
401-
&ExprKind::Cast { source } => todo!(),
396+
397+
// ExprKind::Use happens when a `hir::ExprKind::Cast` is a
398+
// "coercion cast" i.e. using a coercion or is a no-op.
399+
// this is important so that `N as usize as usize` doesnt unify with `N as usize`
400+
&ExprKind::Use { source}
401+
| &ExprKind::Cast { source } => {
402+
let arg = self.recurse_build(source)?;
403+
self.add_node(Node::Cast(arg, node.ty), node.span)
404+
},
402405
// never can arise even without panic/fail to terminate
403406
&ExprKind::NeverToAny { source } => todo!(),
404-
// i think this is a dummy usage of the expr to allow coercions
405-
&ExprKind::Use { source } => todo!(),
406407

407-
ExprKind::Return { .. }
408-
| ExprKind::Box { .. } // allocations not allowed in constants
409-
| ExprKind::AssignOp { .. }
410-
| ExprKind::AddressOf { .. } // FIXME(generic_const_exprs)
411-
| ExprKind::Borrow { .. } // FIXME(generic_const_exprs)
412-
| ExprKind::Deref { .. } // FIXME(generic_const_exprs)
413-
| ExprKind::Repeat { .. } // FIXME(generic_const_exprs)
414-
| ExprKind::Array { .. } // FIXME(generic_const_exprs)
415-
| ExprKind::Tuple { .. } // FIXME(generic_const_exprs)
416-
| ExprKind::Index { .. } // FIXME(generic_const_exprs)
417-
| ExprKind::Field { .. } // FIXME(generic_const_exprs)
418-
| ExprKind::ConstBlock { .. } // FIXME(generic_const_exprs)
419-
| ExprKind::Adt(_) // FIXME(generic_const_exprs) we *should* permit this but dont currently
420-
| ExprKind::Match { .. }
408+
// FIXME(generic_const_exprs) we want to support these
409+
ExprKind::AddressOf { .. }
410+
| ExprKind::Borrow { .. }
411+
| ExprKind::Deref { .. }
412+
| ExprKind::Repeat { .. }
413+
| ExprKind::Array { .. }
414+
| ExprKind::Tuple { .. }
415+
| ExprKind::Index { .. }
416+
| ExprKind::Field { .. }
417+
| ExprKind::ConstBlock { .. }
418+
| ExprKind::Adt(_) => return self.error(
419+
Some(node.span),
420+
"unsupported operation in generic constant, this may be supported in the future",
421+
).map(|never| never),
422+
423+
ExprKind::Match { .. }
421424
| ExprKind::VarRef { .. } //
422425
| ExprKind::UpvarRef { .. } // we dont permit let stmts so...
423426
| ExprKind::Closure { .. }
@@ -433,6 +436,9 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
433436
| ExprKind::Pointer { .. } // dont know if this is correct
434437
| ExprKind::ThreadLocalRef(_)
435438
| ExprKind::LlvmInlineAsm { .. }
439+
| ExprKind::Return { .. }
440+
| ExprKind::Box { .. } // allocations not allowed in constants
441+
| ExprKind::AssignOp { .. }
436442
| ExprKind::InlineAsm { .. }
437443
| ExprKind::Yield { .. } => return self.error(Some(node.span), "unsupported operation in generic constant").map(|never| never),
438444
})
@@ -521,7 +527,7 @@ where
521527
}
522528
ControlFlow::CONTINUE
523529
}
524-
Node::Cast(_, operand, _) => recurse(tcx, ct.subtree(operand), f),
530+
Node::Cast(operand, _) => recurse(tcx, ct.subtree(operand), f),
525531
}
526532
}
527533

@@ -604,11 +610,27 @@ pub(super) fn try_unify<'tcx>(
604610
&& iter::zip(a_args, b_args)
605611
.all(|(&an, &bn)| try_unify(tcx, a.subtree(an), b.subtree(bn)))
606612
}
607-
(Node::Cast(a_cast_kind, a_operand, a_ty), Node::Cast(b_cast_kind, b_operand, b_ty))
608-
if (a_ty == b_ty) && (a_cast_kind == b_cast_kind) =>
613+
(Node::Cast(a_operand, a_ty), Node::Cast(b_operand, b_ty))
614+
if (a_ty == b_ty) =>
609615
{
610616
try_unify(tcx, a.subtree(a_operand), b.subtree(b_operand))
611617
}
612-
_ => false,
618+
(Node::Block(a_stmts, a_opt_expr), Node::Block(b_stmts, b_opt_expr))
619+
if a_stmts.len() == b_stmts.len() => {
620+
a_stmts.iter().zip(b_stmts.iter()).all(|(&a_stmt, &b_stmt)| {
621+
try_unify(tcx, a.subtree(a_stmt), b.subtree(b_stmt))
622+
}) && match (a_opt_expr, b_opt_expr) {
623+
(Some(a_expr), Some(b_expr)) => try_unify(tcx, a.subtree(a_expr), b.subtree(b_expr)),
624+
(None, None) => true,
625+
_ => false,
626+
}
627+
}
628+
// use this over `_ => false` to make adding variants to `Node` less error prone
629+
(Node::Block(..), _)
630+
| (Node::Cast(..), _)
631+
| (Node::FunctionCall(..), _)
632+
| (Node::UnaryOp(..), _)
633+
| (Node::Binop(..), _)
634+
| (Node::Leaf(..), _) => false,
613635
}
614636
}

compiler/rustc_trait_selection/src/traits/object_safety.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -843,7 +843,7 @@ fn contains_illegal_self_type_reference<'tcx, T: TypeFoldable<'tcx>>(
843843
let leaf = leaf.subst(self.tcx, ct.substs);
844844
self.visit_const(leaf)
845845
}
846-
Node::Cast(_, _, ty) => self.visit_ty(ty),
846+
Node::Cast(_, ty) => self.visit_ty(ty),
847847
Node::Block(_, _)
848848
| Node::Binop(..)
849849
| Node::UnaryOp(..)

0 commit comments

Comments
 (0)