@@ -7,6 +7,8 @@ use rustc_data_structures::sync::Lrc;
7
7
use rustc_hir:: def:: { DefKind , Res } ;
8
8
use rustc_hir:: { BinOp , BinOpKind , Block , Expr , ExprKind , HirId , Item , ItemKind , Node , QPath , UnOp } ;
9
9
use rustc_lint:: LateContext ;
10
+ use rustc_middle:: mir;
11
+ use rustc_middle:: mir:: interpret:: Scalar ;
10
12
use rustc_middle:: ty:: subst:: { Subst , SubstsRef } ;
11
13
use rustc_middle:: ty:: { self , EarlyBinder , FloatTy , ScalarInt , Ty , TyCtxt } ;
12
14
use rustc_middle:: { bug, span_bug} ;
@@ -422,13 +424,13 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
422
424
let result = self
423
425
. lcx
424
426
. tcx
425
- . const_eval_resolve_for_typeck (
427
+ . const_eval_resolve (
426
428
self . param_env ,
427
429
ty:: Unevaluated :: new ( ty:: WithOptConstParam :: unknown ( def_id) , substs) ,
428
430
None ,
429
431
)
430
432
. ok ( )
431
- . and_then ( |val| val . map ( |val| rustc_middle:: ty :: Const :: from_value ( self . lcx . tcx , val, ty) ) ) ?;
433
+ . and_then ( |val| Some ( rustc_middle:: mir :: ConstantKind :: from_value ( val, ty) ) ) ?;
432
434
let result = miri_to_const ( self . lcx . tcx , result) ;
433
435
if result. is_some ( ) {
434
436
self . needed_resolution = true ;
@@ -579,69 +581,90 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
579
581
}
580
582
}
581
583
582
- pub fn miri_to_const < ' tcx > ( tcx : TyCtxt < ' tcx > , result : ty:: Const < ' tcx > ) -> Option < Constant > {
583
- match result . kind ( ) {
584
+ fn try_const_to_constant < ' tcx > ( tcx : TyCtxt < ' tcx > , c : ty:: Const < ' tcx > ) -> Option < Constant > {
585
+ match c . kind ( ) {
584
586
ty:: ConstKind :: Value ( valtree) => {
585
- match ( valtree, result. ty ( ) . kind ( ) ) {
586
- ( ty:: ValTree :: Leaf ( int) , ty:: Bool ) => Some ( Constant :: Bool ( int == ScalarInt :: TRUE ) ) ,
587
- ( ty:: ValTree :: Leaf ( int) , ty:: Uint ( _) | ty:: Int ( _) ) => Some ( Constant :: Int ( int. assert_bits ( int. size ( ) ) ) ) ,
588
- ( ty:: ValTree :: Leaf ( int) , ty:: Float ( FloatTy :: F32 ) ) => Some ( Constant :: F32 ( f32:: from_bits (
587
+ let const_val = tcx. valtree_to_const_val ( ( c. ty ( ) , valtree) ) ;
588
+ miri_to_const ( tcx, mir:: ConstantKind :: from_value ( const_val, c. ty ( ) ) )
589
+ } ,
590
+ _ => None ,
591
+ }
592
+ }
593
+
594
+ pub fn miri_to_const < ' tcx > ( tcx : TyCtxt < ' tcx > , result : mir:: ConstantKind < ' tcx > ) -> Option < Constant > {
595
+ use rustc_middle:: mir:: interpret:: ConstValue ;
596
+ match result {
597
+ mir:: ConstantKind :: Val ( ConstValue :: Scalar ( Scalar :: Int ( int) ) , _) => {
598
+ match result. ty ( ) . kind ( ) {
599
+ ty:: Bool => Some ( Constant :: Bool ( int == ScalarInt :: TRUE ) ) ,
600
+ ty:: Uint ( _) | ty:: Int ( _) => Some ( Constant :: Int ( int. assert_bits ( int. size ( ) ) ) ) ,
601
+ ty:: Float ( FloatTy :: F32 ) => Some ( Constant :: F32 ( f32:: from_bits (
589
602
int. try_into ( ) . expect ( "invalid f32 bit representation" ) ,
590
603
) ) ) ,
591
- ( ty:: ValTree :: Leaf ( int ) , ty :: Float ( FloatTy :: F64 ) ) => Some ( Constant :: F64 ( f64:: from_bits (
604
+ ty:: Float ( FloatTy :: F64 ) => Some ( Constant :: F64 ( f64:: from_bits (
592
605
int. try_into ( ) . expect ( "invalid f64 bit representation" ) ,
593
606
) ) ) ,
594
- ( ty:: ValTree :: Leaf ( int ) , ty :: RawPtr ( type_and_mut) ) => {
607
+ ty:: RawPtr ( type_and_mut) => {
595
608
if let ty:: Uint ( _) = type_and_mut. ty . kind ( ) {
596
609
return Some ( Constant :: RawPtr ( int. assert_bits ( int. size ( ) ) ) ) ;
597
610
}
598
611
None
599
612
} ,
600
- ( ty:: ValTree :: Branch ( _) , ty:: Ref ( _, inner_ty, _) ) if * inner_ty == tcx. types . str_ => valtree
601
- . try_to_raw_bytes ( tcx, result. ty ( ) )
602
- . and_then ( |bytes| String :: from_utf8 ( bytes. to_owned ( ) ) . ok ( ) . map ( Constant :: Str ) ) ,
603
- ( ty:: ValTree :: Branch ( _) , ty:: Array ( arr_ty, len) ) => match arr_ty. kind ( ) {
604
- ty:: Float ( float_ty) => {
605
- let chunk_size = match float_ty {
606
- FloatTy :: F32 => 4 ,
607
- FloatTy :: F64 => 8 ,
608
- } ;
609
-
610
- match miri_to_const ( tcx, * len) {
611
- Some ( Constant :: Int ( _) ) => valtree. try_to_raw_bytes ( tcx, result. ty ( ) ) . and_then ( |bytes| {
612
- bytes
613
- . to_owned ( )
614
- . chunks ( chunk_size)
615
- . map ( |chunk| match float_ty {
616
- FloatTy :: F32 => {
617
- let float = f32:: from_le_bytes (
618
- chunk
619
- . try_into ( )
620
- . expect ( & format ! ( "expected to construct f32 from {:?}" , chunk) ) ,
621
- ) ;
622
- Some ( Constant :: F32 ( float) )
623
- } ,
624
- FloatTy :: F64 => {
625
- let float = f64:: from_le_bytes (
626
- chunk
627
- . try_into ( )
628
- . expect ( & format ! ( "expected to construct f64 from {:?}" , chunk) ) ,
629
- ) ;
630
- Some ( Constant :: F64 ( float) )
631
- } ,
632
- } )
633
- . collect :: < Option < Vec < Constant > > > ( )
634
- . map ( Constant :: Vec )
635
- } ) ,
636
- _ => None ,
637
- }
638
- } ,
639
- _ => None ,
640
- } ,
641
613
// FIXME: implement other conversions.
642
614
_ => None ,
643
615
}
644
616
} ,
617
+ mir:: ConstantKind :: Val ( ConstValue :: Slice { data, start, end } , _) => match result. ty ( ) . kind ( ) {
618
+ ty:: Ref ( _, tam, _) => match tam. kind ( ) {
619
+ ty:: Str => String :: from_utf8 (
620
+ data. inner ( )
621
+ . inspect_with_uninit_and_ptr_outside_interpreter ( start..end)
622
+ . to_owned ( ) ,
623
+ )
624
+ . ok ( )
625
+ . map ( Constant :: Str ) ,
626
+ _ => None ,
627
+ } ,
628
+ _ => None ,
629
+ } ,
630
+ mir:: ConstantKind :: Val ( ConstValue :: ByRef { alloc, offset : _ } , _) => match result. ty ( ) . kind ( ) {
631
+ ty:: Array ( sub_type, len) => match sub_type. kind ( ) {
632
+ ty:: Float ( FloatTy :: F32 ) => match try_const_to_constant ( tcx, * len) {
633
+ Some ( Constant :: Int ( len) ) => alloc
634
+ . inner ( )
635
+ . inspect_with_uninit_and_ptr_outside_interpreter ( 0 ..( 4 * len as usize ) )
636
+ . to_owned ( )
637
+ . chunks ( 4 )
638
+ . map ( |chunk| {
639
+ Some ( Constant :: F32 ( f32:: from_le_bytes (
640
+ chunk. try_into ( ) . expect ( "this shouldn't happen" ) ,
641
+ ) ) )
642
+ } )
643
+ . collect :: < Option < Vec < Constant > > > ( )
644
+ . map ( Constant :: Vec ) ,
645
+ _ => None ,
646
+ } ,
647
+ ty:: Float ( FloatTy :: F64 ) => match try_const_to_constant ( tcx, * len) {
648
+ Some ( Constant :: Int ( len) ) => alloc
649
+ . inner ( )
650
+ . inspect_with_uninit_and_ptr_outside_interpreter ( 0 ..( 8 * len as usize ) )
651
+ . to_owned ( )
652
+ . chunks ( 8 )
653
+ . map ( |chunk| {
654
+ Some ( Constant :: F64 ( f64:: from_le_bytes (
655
+ chunk. try_into ( ) . expect ( "this shouldn't happen" ) ,
656
+ ) ) )
657
+ } )
658
+ . collect :: < Option < Vec < Constant > > > ( )
659
+ . map ( Constant :: Vec ) ,
660
+ _ => None ,
661
+ } ,
662
+ // FIXME: implement other array type conversions.
663
+ _ => None ,
664
+ } ,
665
+ _ => None ,
666
+ } ,
667
+ // FIXME: implement other conversions.
645
668
_ => None ,
646
669
}
647
670
}
0 commit comments