@@ -9,11 +9,12 @@ use rustc_hir::def::{DefKind, Res};
99use rustc_hir:: { BinOp , BinOpKind , Block , ConstBlock , Expr , ExprKind , HirId , Item , ItemKind , Node , QPath , UnOp } ;
1010use rustc_lexer:: tokenize;
1111use rustc_lint:: LateContext ;
12- use rustc_middle:: mir:: interpret:: Scalar ;
12+ use rustc_middle:: mir:: interpret:: { alloc_range , Scalar } ;
1313use rustc_middle:: ty:: { self , EarlyBinder , FloatTy , GenericArgsRef , List , ScalarInt , Ty , TyCtxt } ;
1414use rustc_middle:: { bug, mir, span_bug} ;
1515use rustc_span:: symbol:: { Ident , Symbol } ;
1616use rustc_span:: SyntaxContext ;
17+ use rustc_target:: abi:: Size ;
1718use std:: cmp:: Ordering :: { self , Equal } ;
1819use std:: hash:: { Hash , Hasher } ;
1920use std:: iter;
@@ -403,7 +404,7 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
403404 && adt_def. is_struct ( )
404405 && let Some ( desired_field) = field_of_struct ( * adt_def, self . lcx , * constant, field)
405406 {
406- miri_to_const ( self . lcx , desired_field)
407+ mir_to_const ( self . lcx , desired_field)
407408 }
408409 else {
409410 result
@@ -483,7 +484,7 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
483484 . const_eval_resolve ( self . param_env , mir:: UnevaluatedConst :: new ( def_id, args) , None )
484485 . ok ( )
485486 . map ( |val| rustc_middle:: mir:: Const :: from_value ( val, ty) ) ?;
486- let result = miri_to_const ( self . lcx , result) ?;
487+ let result = mir_to_const ( self . lcx , result) ?;
487488 self . source = ConstantSource :: Constant ;
488489 Some ( result)
489490 } ,
@@ -655,10 +656,14 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
655656 }
656657}
657658
658- pub fn miri_to_const < ' tcx > ( lcx : & LateContext < ' tcx > , result : mir:: Const < ' tcx > ) -> Option < Constant < ' tcx > > {
659+ pub fn mir_to_const < ' tcx > ( lcx : & LateContext < ' tcx > , result : mir:: Const < ' tcx > ) -> Option < Constant < ' tcx > > {
659660 use rustc_middle:: mir:: ConstValue ;
660- match result {
661- mir:: Const :: Val ( ConstValue :: Scalar ( Scalar :: Int ( int) ) , _) => match result. ty ( ) . kind ( ) {
661+ let mir:: Const :: Val ( val, _) = result else {
662+ // We only work on evaluated consts.
663+ return None ;
664+ } ;
665+ match ( val, result. ty ( ) . kind ( ) ) {
666+ ( ConstValue :: Scalar ( Scalar :: Int ( int) ) , _) => match result. ty ( ) . kind ( ) {
662667 ty:: Adt ( adt_def, _) if adt_def. is_struct ( ) => Some ( Constant :: Adt ( result) ) ,
663668 ty:: Bool => Some ( Constant :: Bool ( int == ScalarInt :: TRUE ) ) ,
664669 ty:: Uint ( _) | ty:: Int ( _) => Some ( Constant :: Int ( int. assert_bits ( int. size ( ) ) ) ) ,
@@ -671,42 +676,28 @@ pub fn miri_to_const<'tcx>(lcx: &LateContext<'tcx>, result: mir::Const<'tcx>) ->
671676 ty:: RawPtr ( _) => Some ( Constant :: RawPtr ( int. assert_bits ( int. size ( ) ) ) ) ,
672677 _ => None ,
673678 } ,
674- mir:: Const :: Val ( cv, _) if matches ! ( result. ty( ) . kind( ) , ty:: Ref ( _, inner_ty, _) if matches!( inner_ty. kind( ) , ty:: Str ) ) =>
675- {
676- let data = cv. try_get_slice_bytes_for_diagnostics ( lcx. tcx ) ?;
679+ ( _, ty:: Ref ( _, inner_ty, _) ) if matches ! ( inner_ty. kind( ) , ty:: Str ) => {
680+ let data = val. try_get_slice_bytes_for_diagnostics ( lcx. tcx ) ?;
677681 String :: from_utf8 ( data. to_owned ( ) ) . ok ( ) . map ( Constant :: Str )
678682 } ,
679- mir:: Const :: Val ( ConstValue :: Indirect { alloc_id, offset : _ } , _) => {
680- let alloc = lcx. tcx . global_alloc ( alloc_id) . unwrap_memory ( ) ;
681- match result. ty ( ) . kind ( ) {
682- ty:: Adt ( adt_def, _) if adt_def. is_struct ( ) => Some ( Constant :: Adt ( result) ) ,
683- ty:: Array ( sub_type, len) => match sub_type. kind ( ) {
684- ty:: Float ( FloatTy :: F32 ) => match len. try_to_target_usize ( lcx. tcx ) {
685- Some ( len) => alloc
686- . inner ( )
687- . inspect_with_uninit_and_ptr_outside_interpreter ( 0 ..( 4 * usize:: try_from ( len) . unwrap ( ) ) )
688- . to_owned ( )
689- . array_chunks :: < 4 > ( )
690- . map ( |& chunk| Some ( Constant :: F32 ( f32:: from_le_bytes ( chunk) ) ) )
691- . collect :: < Option < Vec < Constant < ' tcx > > > > ( )
692- . map ( Constant :: Vec ) ,
693- _ => None ,
694- } ,
695- ty:: Float ( FloatTy :: F64 ) => match len. try_to_target_usize ( lcx. tcx ) {
696- Some ( len) => alloc
697- . inner ( )
698- . inspect_with_uninit_and_ptr_outside_interpreter ( 0 ..( 8 * usize:: try_from ( len) . unwrap ( ) ) )
699- . to_owned ( )
700- . array_chunks :: < 8 > ( )
701- . map ( |& chunk| Some ( Constant :: F64 ( f64:: from_le_bytes ( chunk) ) ) )
702- . collect :: < Option < Vec < Constant < ' tcx > > > > ( )
703- . map ( Constant :: Vec ) ,
704- _ => None ,
705- } ,
706- _ => None ,
707- } ,
708- _ => None ,
683+ ( _, ty:: Adt ( adt_def, _) ) if adt_def. is_struct ( ) => Some ( Constant :: Adt ( result) ) ,
684+ ( ConstValue :: Indirect { alloc_id, offset } , ty:: Array ( sub_type, len) ) => {
685+ let alloc = lcx. tcx . global_alloc ( alloc_id) . unwrap_memory ( ) . inner ( ) ;
686+ let len = len. try_to_target_usize ( lcx. tcx ) ?;
687+ let ty:: Float ( flt) = sub_type. kind ( ) else {
688+ return None ;
689+ } ;
690+ let size = Size :: from_bits ( flt. bit_width ( ) ) ;
691+ let mut res = Vec :: new ( ) ;
692+ for idx in 0 ..len {
693+ let range = alloc_range ( offset + size * idx, size) ;
694+ let val = alloc. read_scalar ( & lcx. tcx , range, /* read_provenance */ false ) . ok ( ) ?;
695+ res. push ( match flt {
696+ FloatTy :: F32 => Constant :: F32 ( f32:: from_bits ( val. to_u32 ( ) . ok ( ) ?) ) ,
697+ FloatTy :: F64 => Constant :: F64 ( f64:: from_bits ( val. to_u64 ( ) . ok ( ) ?) ) ,
698+ } ) ;
709699 }
700+ Some ( Constant :: Vec ( res) )
710701 } ,
711702 _ => None ,
712703 }
0 commit comments