@@ -140,6 +140,31 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>)
140
140
} )
141
141
. filter ( |( variant_pat, _) | is_variant_missing ( & top_lvl_pats, variant_pat) ) ;
142
142
( ( Box :: new ( missing_pats) as Box < dyn Iterator < Item = _ > > ) . peekable ( ) , is_non_exhaustive)
143
+ } else if let Some ( ( enum_def, len) ) = resolve_array_of_enum_def ( & ctx. sema , & expr) {
144
+ let is_non_exhaustive = enum_def. is_non_exhaustive ( ctx. db ( ) , module. krate ( ) ) ;
145
+ let variants = enum_def. variants ( ctx. db ( ) ) ;
146
+
147
+ if len. pow ( variants. len ( ) as u32 ) > 256 {
148
+ return None ;
149
+ }
150
+
151
+ let variants_of_enums = vec ! [ variants. clone( ) ; len] ;
152
+
153
+ let missing_pats = variants_of_enums
154
+ . into_iter ( )
155
+ . multi_cartesian_product ( )
156
+ . inspect ( |_| cov_mark:: hit!( add_missing_match_arms_lazy_computation) )
157
+ . map ( |variants| {
158
+ let is_hidden = variants
159
+ . iter ( )
160
+ . any ( |variant| variant. should_be_hidden ( ctx. db ( ) , module. krate ( ) ) ) ;
161
+ let patterns = variants. into_iter ( ) . filter_map ( |variant| {
162
+ build_pat ( ctx. db ( ) , module, variant. clone ( ) , ctx. config . prefer_no_std )
163
+ } ) ;
164
+ ( ast:: Pat :: from ( make:: slice_pat ( patterns) ) , is_hidden)
165
+ } )
166
+ . filter ( |( variant_pat, _) | is_variant_missing ( & top_lvl_pats, variant_pat) ) ;
167
+ ( ( Box :: new ( missing_pats) as Box < dyn Iterator < Item = _ > > ) . peekable ( ) , is_non_exhaustive)
143
168
} else {
144
169
return None ;
145
170
} ;
@@ -266,6 +291,9 @@ fn is_variant_missing(existing_pats: &[Pat], var: &Pat) -> bool {
266
291
fn does_pat_match_variant ( pat : & Pat , var : & Pat ) -> bool {
267
292
match ( pat, var) {
268
293
( Pat :: WildcardPat ( _) , _) => true ,
294
+ ( Pat :: SlicePat ( spat) , Pat :: SlicePat ( svar) ) => {
295
+ spat. pats ( ) . zip ( svar. pats ( ) ) . all ( |( p, v) | does_pat_match_variant ( & p, & v) )
296
+ }
269
297
( Pat :: TuplePat ( tpat) , Pat :: TuplePat ( tvar) ) => {
270
298
tpat. fields ( ) . zip ( tvar. fields ( ) ) . all ( |( p, v) | does_pat_match_variant ( & p, & v) )
271
299
}
@@ -280,7 +308,7 @@ enum ExtendedEnum {
280
308
Enum ( hir:: Enum ) ,
281
309
}
282
310
283
- #[ derive( Eq , PartialEq , Clone , Copy ) ]
311
+ #[ derive( Eq , PartialEq , Clone , Copy , Debug ) ]
284
312
enum ExtendedVariant {
285
313
True ,
286
314
False ,
@@ -340,15 +368,30 @@ fn resolve_tuple_of_enum_def(
340
368
. tuple_fields ( sema. db )
341
369
. iter ( )
342
370
. map ( |ty| {
343
- ty. autoderef ( sema. db ) . find_map ( |ty| match ty. as_adt ( ) {
344
- Some ( Adt :: Enum ( e) ) => Some ( lift_enum ( e) ) ,
345
- // For now we only handle expansion for a tuple of enums. Here
346
- // we map non-enum items to None and rely on `collect` to
347
- // convert Vec<Option<hir::Enum>> into Option<Vec<hir::Enum>>.
348
- _ => ty. is_bool ( ) . then_some ( ExtendedEnum :: Bool ) ,
371
+ ty. autoderef ( sema. db ) . find_map ( |ty| {
372
+ match ty. as_adt ( ) {
373
+ Some ( Adt :: Enum ( e) ) => Some ( lift_enum ( e) ) ,
374
+ // For now we only handle expansion for a tuple of enums. Here
375
+ // we map non-enum items to None and rely on `collect` to
376
+ // convert Vec<Option<hir::Enum>> into Option<Vec<hir::Enum>>.
377
+ _ => ty. is_bool ( ) . then_some ( ExtendedEnum :: Bool ) ,
378
+ }
349
379
} )
350
380
} )
351
- . collect ( )
381
+ . collect :: < Option < Vec < ExtendedEnum > > > ( )
382
+ . and_then ( |list| if list. is_empty ( ) { None } else { Some ( list) } )
383
+ }
384
+
385
+ fn resolve_array_of_enum_def (
386
+ sema : & Semantics < ' _ , RootDatabase > ,
387
+ expr : & ast:: Expr ,
388
+ ) -> Option < ( ExtendedEnum , usize ) > {
389
+ sema. type_of_expr ( expr) ?. adjusted ( ) . as_array ( sema. db ) . and_then ( |( ty, len) | {
390
+ ty. autoderef ( sema. db ) . find_map ( |ty| match ty. as_adt ( ) {
391
+ Some ( Adt :: Enum ( e) ) => Some ( ( lift_enum ( e) , len) ) ,
392
+ _ => ty. is_bool ( ) . then_some ( ( ExtendedEnum :: Bool , len) ) ,
393
+ } )
394
+ } )
352
395
}
353
396
354
397
fn build_pat (
@@ -377,7 +420,6 @@ fn build_pat(
377
420
}
378
421
ast:: StructKind :: Unit => make:: path_pat ( path) ,
379
422
} ;
380
-
381
423
Some ( pat)
382
424
}
383
425
ExtendedVariant :: True => Some ( ast:: Pat :: from ( make:: literal_pat ( "true" ) ) ) ,
@@ -573,6 +615,86 @@ fn foo(a: bool) {
573
615
)
574
616
}
575
617
618
+ #[ test]
619
+ fn fill_boolean_array ( ) {
620
+ check_assist (
621
+ add_missing_match_arms,
622
+ r#"
623
+ fn foo(a: bool) {
624
+ match [a]$0 {
625
+ }
626
+ }
627
+ "# ,
628
+ r#"
629
+ fn foo(a: bool) {
630
+ match [a] {
631
+ $0[true] => todo!(),
632
+ [false] => todo!(),
633
+ }
634
+ }
635
+ "# ,
636
+ ) ;
637
+
638
+ check_assist (
639
+ add_missing_match_arms,
640
+ r#"
641
+ fn foo(a: bool) {
642
+ match [a,]$0 {
643
+ }
644
+ }
645
+ "# ,
646
+ r#"
647
+ fn foo(a: bool) {
648
+ match [a,] {
649
+ $0[true] => todo!(),
650
+ [false] => todo!(),
651
+ }
652
+ }
653
+ "# ,
654
+ ) ;
655
+
656
+ check_assist (
657
+ add_missing_match_arms,
658
+ r#"
659
+ fn foo(a: bool) {
660
+ match [a, a]$0 {
661
+ [true, true] => todo!(),
662
+ }
663
+ }
664
+ "# ,
665
+ r#"
666
+ fn foo(a: bool) {
667
+ match [a, a] {
668
+ [true, true] => todo!(),
669
+ $0[true, false] => todo!(),
670
+ [false, true] => todo!(),
671
+ [false, false] => todo!(),
672
+ }
673
+ }
674
+ "# ,
675
+ ) ;
676
+
677
+ check_assist (
678
+ add_missing_match_arms,
679
+ r#"
680
+ fn foo(a: bool) {
681
+ match [a, a]$0 {
682
+ }
683
+ }
684
+ "# ,
685
+ r#"
686
+ fn foo(a: bool) {
687
+ match [a, a] {
688
+ $0[true, true] => todo!(),
689
+ [true, false] => todo!(),
690
+ [false, true] => todo!(),
691
+ [false, false] => todo!(),
692
+ }
693
+ }
694
+ "# ,
695
+ )
696
+ }
697
+
576
698
#[ test]
577
699
fn partial_fill_boolean_tuple ( ) {
578
700
check_assist (
0 commit comments