@@ -11,15 +11,16 @@ use std::mem;
11
11
use std:: sync:: Arc ;
12
12
13
13
use rustc_abi:: VariantIdx ;
14
- use rustc_ast:: LitKind ;
15
14
use rustc_data_structures:: fx:: FxIndexMap ;
16
15
use rustc_data_structures:: stack:: ensure_sufficient_stack;
17
16
use rustc_hir:: { BindingMode , ByRef , LetStmt , LocalSource , Node } ;
18
- use rustc_middle:: bug;
19
17
use rustc_middle:: middle:: region;
20
18
use rustc_middle:: mir:: { self , * } ;
21
19
use 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} ;
23
24
use rustc_pattern_analysis:: rustc:: { DeconstructedPat , RustcPatCtxt } ;
24
25
use rustc_span:: { BytePos , Pos , Span , Symbol , sym} ;
25
26
use tracing:: { debug, instrument} ;
@@ -2871,7 +2872,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
2871
2872
pub ( crate ) fn static_pattern_match (
2872
2873
& self ,
2873
2874
cx : & RustcPatCtxt < ' _ , ' tcx > ,
2874
- value : ExprId ,
2875
+ constant : ConstOperand < ' tcx > ,
2875
2876
arms : & [ ArmId ] ,
2876
2877
built_match_tree : & BuiltMatchTree < ' tcx > ,
2877
2878
) -> Option < BasicBlock > {
@@ -2890,56 +2891,81 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
2890
2891
. or_else ( || branch. sub_branches . last ( ) )
2891
2892
. unwrap ( ) ;
2892
2893
2893
- match self . static_pattern_match_help ( value , & pat. pat ) {
2894
+ match self . static_pattern_match_help ( constant , & pat. pat ) {
2894
2895
true => return Some ( sub_branch. success_block ) ,
2895
2896
false => continue ,
2896
2897
}
2897
2898
}
2898
- } else if self . static_pattern_match_help ( value , & pat) {
2899
+ } else if self . static_pattern_match_help ( constant , & pat) {
2899
2900
return Some ( branch. sub_branches [ 0 ] . success_block ) ;
2900
2901
}
2901
2902
}
2902
2903
2903
2904
None
2904
2905
}
2905
2906
2906
- fn static_pattern_match_help ( & self , value : ExprId , pat : & DeconstructedPat < ' _ , ' tcx > ) -> bool {
2907
- use rustc_middle:: thir:: ExprKind ;
2907
+ fn static_pattern_match_help (
2908
+ & self ,
2909
+ constant : ConstOperand < ' tcx > ,
2910
+ pat : & DeconstructedPat < ' _ , ' tcx > ,
2911
+ ) -> bool {
2908
2912
use rustc_pattern_analysis:: constructor:: { IntRange , MaybeInfiniteInt } ;
2909
2913
use rustc_pattern_analysis:: rustc:: Constructor ;
2910
2914
2911
- match pat. ctor ( ) {
2912
- Constructor :: Variant ( variant_index) => match & self . thir [ value] . kind {
2913
- ExprKind :: Adt ( value_adt) => {
2914
- return * variant_index == value_adt. variant_index ;
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) ;
2915
2928
}
2916
- other => todo ! ( "{other:?}" ) ,
2917
- } ,
2918
- Constructor :: IntRange ( int_range) => match & self . thir [ value] . kind {
2919
- ExprKind :: Literal { lit, neg } => match & lit. node {
2920
- LitKind :: Int ( n, _) => {
2921
- let n = if pat. ty ( ) . is_signed ( ) {
2922
- let size = pat. ty ( ) . primitive_size ( self . tcx ) ;
2923
- MaybeInfiniteInt :: new_finite_int (
2924
- if * neg {
2925
- size. truncate ( ( n. get ( ) as i128 ) . overflowing_neg ( ) . 0 as u128 )
2926
- } else {
2927
- n. get ( )
2928
- } ,
2929
- size. bits ( ) ,
2930
- )
2931
- } else {
2932
- MaybeInfiniteInt :: new_finite_uint ( n. get ( ) )
2933
- } ;
2934
-
2935
- return IntRange :: from_singleton ( n) . is_subrange ( int_range) ;
2936
- }
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
+ } ;
2947
+ assert ! ( !ty. has_param( ) ) ;
2937
2948
2938
- other => todo ! ( "{other:?}" ) ,
2939
- } ,
2949
+ 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
+ }
2940
2955
other => todo ! ( "{other:?}" ) ,
2941
2956
} ,
2942
- Constructor :: Wildcard => return true ,
2957
+ Constructor :: IntRange ( int_range) => {
2958
+ let size = pat. ty ( ) . primitive_size ( self . tcx ) ;
2959
+ let actual_int = valtree. unwrap_leaf ( ) . to_bits ( size) ;
2960
+ let actual_int = if pat. ty ( ) . is_signed ( ) {
2961
+ MaybeInfiniteInt :: new_finite_int ( actual_int, size. bits ( ) )
2962
+ } else {
2963
+ MaybeInfiniteInt :: new_finite_uint ( actual_int)
2964
+ } ;
2965
+ IntRange :: from_singleton ( actual_int) . is_subrange ( int_range)
2966
+ }
2967
+ Constructor :: Wildcard => true ,
2968
+ // FIXME error out before static_pattern_match gets run and replace this with bug!()
2943
2969
_ => false ,
2944
2970
}
2945
2971
}
0 commit comments