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