@@ -9,11 +9,12 @@ use rustc_hir::def::{DefKind, Res};
9
9
use rustc_hir:: { BinOp , BinOpKind , Block , ConstBlock , Expr , ExprKind , HirId , Item , ItemKind , Node , QPath , UnOp } ;
10
10
use rustc_lexer:: tokenize;
11
11
use rustc_lint:: LateContext ;
12
- use rustc_middle:: mir:: interpret:: Scalar ;
12
+ use rustc_middle:: mir:: interpret:: { alloc_range , Scalar } ;
13
13
use rustc_middle:: ty:: { self , EarlyBinder , FloatTy , GenericArgsRef , List , ScalarInt , Ty , TyCtxt } ;
14
14
use rustc_middle:: { bug, mir, span_bug} ;
15
15
use rustc_span:: symbol:: { Ident , Symbol } ;
16
16
use rustc_span:: SyntaxContext ;
17
+ use rustc_target:: abi:: Size ;
17
18
use std:: cmp:: Ordering :: { self , Equal } ;
18
19
use std:: hash:: { Hash , Hasher } ;
19
20
use std:: iter;
@@ -403,7 +404,7 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
403
404
&& adt_def. is_struct ( )
404
405
&& let Some ( desired_field) = field_of_struct ( * adt_def, self . lcx , * constant, field)
405
406
{
406
- miri_to_const ( self . lcx , desired_field)
407
+ mir_to_const ( self . lcx , desired_field)
407
408
}
408
409
else {
409
410
result
@@ -483,7 +484,7 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
483
484
. const_eval_resolve ( self . param_env , mir:: UnevaluatedConst :: new ( def_id, args) , None )
484
485
. ok ( )
485
486
. 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) ?;
487
488
self . source = ConstantSource :: Constant ;
488
489
Some ( result)
489
490
} ,
@@ -655,10 +656,14 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
655
656
}
656
657
}
657
658
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 > > {
659
660
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 ( ) {
662
667
ty:: Adt ( adt_def, _) if adt_def. is_struct ( ) => Some ( Constant :: Adt ( result) ) ,
663
668
ty:: Bool => Some ( Constant :: Bool ( int == ScalarInt :: TRUE ) ) ,
664
669
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>) ->
671
676
ty:: RawPtr ( _) => Some ( Constant :: RawPtr ( int. assert_bits ( int. size ( ) ) ) ) ,
672
677
_ => None ,
673
678
} ,
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 ) ?;
677
681
String :: from_utf8 ( data. to_owned ( ) ) . ok ( ) . map ( Constant :: Str )
678
682
} ,
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
+ } ) ;
709
699
}
700
+ Some ( Constant :: Vec ( res) )
710
701
} ,
711
702
_ => None ,
712
703
}
0 commit comments