@@ -11,15 +11,16 @@ use std::mem;
1111use std:: sync:: Arc ;
1212
1313use rustc_abi:: VariantIdx ;
14- use rustc_ast:: LitKind ;
1514use rustc_data_structures:: fx:: FxIndexMap ;
1615use rustc_data_structures:: stack:: ensure_sufficient_stack;
1716use rustc_hir:: { BindingMode , ByRef , LetStmt , LocalSource , Node } ;
18- use rustc_middle:: bug;
1917use rustc_middle:: middle:: region;
2018use rustc_middle:: mir:: { self , * } ;
2119use rustc_middle:: thir:: { self , * } ;
22- use rustc_middle:: ty:: { self , CanonicalUserTypeAnnotation , Ty } ;
20+ use rustc_middle:: ty:: {
21+ self , CanonicalUserTypeAnnotation , Ty , TypeVisitableExt , ValTree , ValTreeKind ,
22+ } ;
23+ use rustc_middle:: { bug, span_bug} ;
2324use rustc_pattern_analysis:: rustc:: { DeconstructedPat , RustcPatCtxt } ;
2425use rustc_span:: { BytePos , Pos , Span , Symbol , sym} ;
2526use tracing:: { debug, instrument} ;
@@ -2870,7 +2871,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
28702871 pub ( crate ) fn static_pattern_match (
28712872 & self ,
28722873 cx : & RustcPatCtxt < ' _ , ' tcx > ,
2873- value : ExprId ,
2874+ constant : ConstOperand < ' tcx > ,
28742875 arms : & [ ArmId ] ,
28752876 built_match_tree : & BuiltMatchTree < ' tcx > ,
28762877 ) -> Option < BasicBlock > {
@@ -2889,56 +2890,81 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
28892890 . or_else ( || branch. sub_branches . last ( ) )
28902891 . unwrap ( ) ;
28912892
2892- match self . static_pattern_match_help ( value , & pat. pat ) {
2893+ match self . static_pattern_match_help ( constant , & pat. pat ) {
28932894 true => return Some ( sub_branch. success_block ) ,
28942895 false => continue ,
28952896 }
28962897 }
2897- } else if self . static_pattern_match_help ( value , & pat) {
2898+ } else if self . static_pattern_match_help ( constant , & pat) {
28982899 return Some ( branch. sub_branches [ 0 ] . success_block ) ;
28992900 }
29002901 }
29012902
29022903 None
29032904 }
29042905
2905- fn static_pattern_match_help ( & self , value : ExprId , pat : & DeconstructedPat < ' _ , ' tcx > ) -> bool {
2906- use rustc_middle:: thir:: ExprKind ;
2906+ fn static_pattern_match_help (
2907+ & self ,
2908+ constant : ConstOperand < ' tcx > ,
2909+ pat : & DeconstructedPat < ' _ , ' tcx > ,
2910+ ) -> bool {
29072911 use rustc_pattern_analysis:: constructor:: { IntRange , MaybeInfiniteInt } ;
29082912 use rustc_pattern_analysis:: rustc:: Constructor ;
29092913
2910- match pat. ctor ( ) {
2911- Constructor :: Variant ( variant_index) => match & self . thir [ value] . kind {
2912- ExprKind :: Adt ( value_adt) => {
2913- return * variant_index == value_adt. variant_index ;
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) ;
29142927 }
2915- other => todo ! ( "{other:?}" ) ,
2916- } ,
2917- Constructor :: IntRange ( int_range) => match & self . thir [ value] . kind {
2918- ExprKind :: Literal { lit, neg } => match & lit. node {
2919- LitKind :: Int ( n, _) => {
2920- let n = if pat. ty ( ) . is_signed ( ) {
2921- let size = pat. ty ( ) . primitive_size ( self . tcx ) ;
2922- MaybeInfiniteInt :: new_finite_int (
2923- if * neg {
2924- size. truncate ( ( n. get ( ) as i128 ) . overflowing_neg ( ) . 0 as u128 )
2925- } else {
2926- n. get ( )
2927- } ,
2928- size. bits ( ) ,
2929- )
2930- } else {
2931- MaybeInfiniteInt :: new_finite_uint ( n. get ( ) )
2932- } ;
2933-
2934- return IntRange :: from_singleton ( n) . is_subrange ( int_range) ;
2935- }
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+ } ;
2946+ assert ! ( !ty. has_param( ) ) ;
29362947
2937- other => todo ! ( "{other:?}" ) ,
2938- } ,
2948+ 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+ }
29392954 other => todo ! ( "{other:?}" ) ,
29402955 } ,
2941- Constructor :: Wildcard => return true ,
2956+ Constructor :: IntRange ( int_range) => {
2957+ let size = pat. ty ( ) . primitive_size ( self . tcx ) ;
2958+ let actual_int = valtree. unwrap_leaf ( ) . to_bits ( size) ;
2959+ let actual_int = if pat. ty ( ) . is_signed ( ) {
2960+ MaybeInfiniteInt :: new_finite_int ( actual_int, size. bits ( ) )
2961+ } else {
2962+ MaybeInfiniteInt :: new_finite_uint ( actual_int)
2963+ } ;
2964+ IntRange :: from_singleton ( actual_int) . is_subrange ( int_range)
2965+ }
2966+ Constructor :: Wildcard => true ,
2967+ // FIXME error out before static_pattern_match gets run and replace this with bug!()
29422968 _ => false ,
29432969 }
29442970 }
0 commit comments