@@ -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}
0 commit comments