@@ -27,6 +27,7 @@ use tracing::{debug, instrument};
27
27
28
28
use crate :: builder:: ForGuard :: { self , OutsideGuard , RefWithinGuard } ;
29
29
use crate :: builder:: expr:: as_place:: PlaceBuilder ;
30
+ use crate :: builder:: interpret:: ErrorHandled ;
30
31
use crate :: builder:: matches:: user_ty:: ProjectedUserTypesNode ;
31
32
use crate :: builder:: scope:: DropKind ;
32
33
use crate :: builder:: {
@@ -2903,6 +2904,40 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
2903
2904
None
2904
2905
}
2905
2906
2907
+ /// Based on `FunctionCx::eval_unevaluated_mir_constant_to_valtree`.
2908
+ fn eval_unevaluated_mir_constant_to_valtree (
2909
+ & self ,
2910
+ constant : ConstOperand < ' tcx > ,
2911
+ ) -> Result < ( ty:: ValTree < ' tcx > , Ty < ' tcx > ) , ErrorHandled > {
2912
+ assert ! ( !constant. const_. ty( ) . has_param( ) ) ;
2913
+ let ( uv, ty) = match constant. const_ {
2914
+ mir:: Const :: Unevaluated ( uv, ty) => ( uv. shrink ( ) , ty) ,
2915
+ mir:: Const :: Ty ( _, c) => match c. kind ( ) {
2916
+ // A constant that came from a const generic but was then used as an argument to
2917
+ // old-style simd_shuffle (passing as argument instead of as a generic param).
2918
+ ty:: ConstKind :: Value ( cv) => return Ok ( ( cv. valtree , cv. ty ) ) ,
2919
+ other => span_bug ! ( constant. span, "{other:#?}" ) ,
2920
+ } ,
2921
+ mir:: Const :: Val ( mir:: ConstValue :: Scalar ( mir:: interpret:: Scalar :: Int ( val) ) , ty) => {
2922
+ return Ok ( ( ValTree :: from_scalar_int ( self . tcx , val) , ty) ) ;
2923
+ }
2924
+ // We should never encounter `Const::Val` unless MIR opts (like const prop) evaluate
2925
+ // a constant and write that value back into `Operand`s. This could happen, but is
2926
+ // unlikely. Also: all users of `simd_shuffle` are on unstable and already need to take
2927
+ // a lot of care around intrinsics. For an issue to happen here, it would require a
2928
+ // macro expanding to a `simd_shuffle` call without wrapping the constant argument in a
2929
+ // `const {}` block, but the user pass through arbitrary expressions.
2930
+ // FIXME(oli-obk): replace the magic const generic argument of `simd_shuffle` with a
2931
+ // real const generic, and get rid of this entire function.
2932
+ other => span_bug ! ( constant. span, "{other:#?}" ) ,
2933
+ } ;
2934
+
2935
+ match self . tcx . const_eval_resolve_for_typeck ( self . typing_env ( ) , uv, constant. span ) ? {
2936
+ Ok ( valtree) => Ok ( ( valtree, ty) ) ,
2937
+ Err ( ty) => bug ! ( "could not convert {ty:?} to a valtree" ) ,
2938
+ }
2939
+ }
2940
+
2906
2941
fn static_pattern_match_help (
2907
2942
& self ,
2908
2943
constant : ConstOperand < ' tcx > ,
@@ -2911,48 +2946,21 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
2911
2946
use rustc_pattern_analysis:: constructor:: { IntRange , MaybeInfiniteInt } ;
2912
2947
use rustc_pattern_analysis:: rustc:: Constructor ;
2913
2948
2914
- // Based on eval_unevaluated_mir_constant_to_valtree
2915
- let ( valtree, ty) = ' a: {
2916
- assert ! ( !constant. const_. ty( ) . has_param( ) ) ;
2917
- let ( uv, ty) = match constant. const_ {
2918
- mir:: Const :: Unevaluated ( uv, ty) => ( uv. shrink ( ) , ty) ,
2919
- mir:: Const :: Ty ( _, c) => match c. kind ( ) {
2920
- // A constant that came from a const generic but was then used as an argument to
2921
- // old-style simd_shuffle (passing as argument instead of as a generic param).
2922
- ty:: ConstKind :: Value ( cv) => break ' a ( cv. valtree , cv. ty ) ,
2923
- other => span_bug ! ( constant. span, "{other:#?}" ) ,
2924
- } ,
2925
- mir:: Const :: Val ( mir:: ConstValue :: Scalar ( mir:: interpret:: Scalar :: Int ( val) ) , ty) => {
2926
- break ' a ( ValTree :: from_scalar_int ( self . tcx , val) , ty) ;
2927
- }
2928
- // We should never encounter `Const::Val` unless MIR opts (like const prop) evaluate
2929
- // a constant and write that value back into `Operand`s. This could happen, but is
2930
- // unlikely. Also: all users of `simd_shuffle` are on unstable and already need to take
2931
- // a lot of care around intrinsics. For an issue to happen here, it would require a
2932
- // macro expanding to a `simd_shuffle` call without wrapping the constant argument in a
2933
- // `const {}` block, but the user pass through arbitrary expressions.
2934
- // FIXME(oli-obk): replace the magic const generic argument of `simd_shuffle` with a
2935
- // real const generic, and get rid of this entire function.
2936
- other => span_bug ! ( constant. span, "{other:#?}" ) ,
2937
- } ;
2938
- (
2939
- self . tcx
2940
- . const_eval_resolve_for_typeck ( self . typing_env ( ) , uv, constant. span )
2941
- . unwrap ( )
2942
- . unwrap ( ) ,
2943
- ty,
2944
- )
2945
- } ;
2949
+ let ( valtree, ty) = self . eval_unevaluated_mir_constant_to_valtree ( constant) . unwrap ( ) ;
2946
2950
assert ! ( !ty. has_param( ) ) ;
2947
2951
2948
2952
match pat. ctor ( ) {
2949
- Constructor :: Variant ( variant_index) => match * valtree {
2950
- ValTreeKind :: Branch ( box [ actual_variant_idx] ) => {
2951
- * variant_index
2952
- == VariantIdx :: from_u32 ( actual_variant_idx. unwrap_leaf ( ) . to_u32 ( ) )
2953
- }
2954
- other => todo ! ( "{other:?}" ) ,
2955
- } ,
2953
+ Constructor :: Variant ( variant_index) => {
2954
+ let ValTreeKind :: Branch ( box [ actual_variant_idx] ) = * valtree else {
2955
+ bug ! ( "malformed valtree for an enum" )
2956
+ } ;
2957
+
2958
+ let ValTreeKind :: Leaf ( actual_variant_idx) = * * * actual_variant_idx else {
2959
+ bug ! ( "malformed valtree for an enum" )
2960
+ } ;
2961
+
2962
+ * variant_index == VariantIdx :: from_u32 ( actual_variant_idx. to_u32 ( ) )
2963
+ }
2956
2964
Constructor :: IntRange ( int_range) => {
2957
2965
let size = pat. ty ( ) . primitive_size ( self . tcx ) ;
2958
2966
let actual_int = valtree. unwrap_leaf ( ) . to_bits ( size) ;
0 commit comments