@@ -7,6 +7,8 @@ use rustc_data_structures::sync::Lrc;
77use rustc_hir:: def:: { DefKind , Res } ;
88use rustc_hir:: { BinOp , BinOpKind , Block , Expr , ExprKind , HirId , Item , ItemKind , Node , QPath , UnOp } ;
99use rustc_lint:: LateContext ;
10+ use rustc_middle:: mir;
11+ use rustc_middle:: mir:: interpret:: Scalar ;
1012use rustc_middle:: ty:: subst:: { Subst , SubstsRef } ;
1113use rustc_middle:: ty:: { self , EarlyBinder , FloatTy , ScalarInt , Ty , TyCtxt } ;
1214use rustc_middle:: { bug, span_bug} ;
@@ -422,13 +424,13 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
422424 let result = self
423425 . lcx
424426 . tcx
425- . const_eval_resolve_for_typeck (
427+ . const_eval_resolve (
426428 self . param_env ,
427429 ty:: Unevaluated :: new ( ty:: WithOptConstParam :: unknown ( def_id) , substs) ,
428430 None ,
429431 )
430432 . 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) ) ) ?;
432434 let result = miri_to_const ( self . lcx . tcx , result) ;
433435 if result. is_some ( ) {
434436 self . needed_resolution = true ;
@@ -579,69 +581,90 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
579581 }
580582}
581583
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 ( ) {
584586 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 (
589602 int. try_into ( ) . expect ( "invalid f32 bit representation" ) ,
590603 ) ) ) ,
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 (
592605 int. try_into ( ) . expect ( "invalid f64 bit representation" ) ,
593606 ) ) ) ,
594- ( ty:: ValTree :: Leaf ( int ) , ty :: RawPtr ( type_and_mut) ) => {
607+ ty:: RawPtr ( type_and_mut) => {
595608 if let ty:: Uint ( _) = type_and_mut. ty . kind ( ) {
596609 return Some ( Constant :: RawPtr ( int. assert_bits ( int. size ( ) ) ) ) ;
597610 }
598611 None
599612 } ,
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- } ,
641613 // FIXME: implement other conversions.
642614 _ => None ,
643615 }
644616 } ,
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.
645668 _ => None ,
646669 }
647670}
0 commit comments