@@ -92,7 +92,7 @@ pub fn is_const_evaluatable<'cx, 'tcx>(
92
92
93
93
ControlFlow :: CONTINUE
94
94
}
95
- Node :: Cast ( _, _ , ty) => {
95
+ Node :: Cast ( _, ty) => {
96
96
let ty = ty. subst ( tcx, ct. substs ) ;
97
97
if ty. has_infer_types_or_consts ( ) {
98
98
failure_kind = FailureKind :: MentionsInfer ;
@@ -292,7 +292,7 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
292
292
stmts. iter ( ) . for_each ( |& id| self . nodes [ id] . used = true ) ;
293
293
opt_expr. map ( |e| self . nodes [ e] . used = true ) ;
294
294
}
295
- Node :: Cast ( _ , operand, _) => {
295
+ Node :: Cast ( operand, _) => {
296
296
self . nodes [ operand] . used = true ;
297
297
}
298
298
}
@@ -335,6 +335,7 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
335
335
}
336
336
}
337
337
338
+ // FIXME I dont even think we can get unused nodes anymore with thir abstract const
338
339
if let Some ( & unused) = self . nodes . iter ( ) . find ( |n| !n. used ) {
339
340
self . error ( Some ( unused. span ) , "dead code" ) ?;
340
341
}
@@ -352,6 +353,8 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
352
353
& ExprKind :: PlaceTypeAscription { source, .. } |
353
354
& ExprKind :: ValueTypeAscription { source, .. } => self . recurse_build ( source) ?,
354
355
356
+ // subtle: associated consts are literals this arm handles
357
+ // `<T as Trait>::ASSOC` as well as `12`
355
358
& ExprKind :: Literal { literal, .. }
356
359
| & ExprKind :: StaticRef { literal, .. } => self . add_node ( Node :: Leaf ( literal) , node. span ) ,
357
360
@@ -375,14 +378,6 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
375
378
let arg = self . recurse_build ( arg) ?;
376
379
self . add_node ( Node :: UnaryOp ( op, arg) , node. span )
377
380
} ,
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) ?,
386
381
ExprKind :: Block { body } => {
387
382
let mut stmts = Vec :: with_capacity ( body. stmts . len ( ) ) ;
388
383
for & id in body. stmts . iter ( ) {
@@ -398,26 +393,34 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
398
393
let opt_expr = body. expr . map ( |e| self . recurse_build ( e) ) . transpose ( ) ?;
399
394
self . add_node ( Node :: Block ( stmts, opt_expr) , node. span )
400
395
}
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
+ } ,
402
405
// never can arise even without panic/fail to terminate
403
406
& ExprKind :: NeverToAny { source } => todo ! ( ) ,
404
- // i think this is a dummy usage of the expr to allow coercions
405
- & ExprKind :: Use { source } => todo ! ( ) ,
406
407
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 { .. }
421
424
| ExprKind :: VarRef { .. } //
422
425
| ExprKind :: UpvarRef { .. } // we dont permit let stmts so...
423
426
| ExprKind :: Closure { .. }
@@ -433,6 +436,9 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
433
436
| ExprKind :: Pointer { .. } // dont know if this is correct
434
437
| ExprKind :: ThreadLocalRef ( _)
435
438
| ExprKind :: LlvmInlineAsm { .. }
439
+ | ExprKind :: Return { .. }
440
+ | ExprKind :: Box { .. } // allocations not allowed in constants
441
+ | ExprKind :: AssignOp { .. }
436
442
| ExprKind :: InlineAsm { .. }
437
443
| ExprKind :: Yield { .. } => return self . error ( Some ( node. span ) , "unsupported operation in generic constant" ) . map ( |never| never) ,
438
444
} )
@@ -521,7 +527,7 @@ where
521
527
}
522
528
ControlFlow :: CONTINUE
523
529
}
524
- Node :: Cast ( _ , operand, _) => recurse ( tcx, ct. subtree ( operand) , f) ,
530
+ Node :: Cast ( operand, _) => recurse ( tcx, ct. subtree ( operand) , f) ,
525
531
}
526
532
}
527
533
@@ -604,11 +610,27 @@ pub(super) fn try_unify<'tcx>(
604
610
&& iter:: zip ( a_args, b_args)
605
611
. all ( |( & an, & bn) | try_unify ( tcx, a. subtree ( an) , b. subtree ( bn) ) )
606
612
}
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) =>
609
615
{
610
616
try_unify ( tcx, a. subtree ( a_operand) , b. subtree ( b_operand) )
611
617
}
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 ,
613
635
}
614
636
}
0 commit comments