@@ -140,6 +140,31 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>)
140140 } )
141141 . filter ( |( variant_pat, _) | is_variant_missing ( & top_lvl_pats, variant_pat) ) ;
142142 ( ( 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)
143168 } else {
144169 return None ;
145170 } ;
@@ -266,6 +291,9 @@ fn is_variant_missing(existing_pats: &[Pat], var: &Pat) -> bool {
266291fn does_pat_match_variant ( pat : & Pat , var : & Pat ) -> bool {
267292 match ( pat, var) {
268293 ( 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+ }
269297 ( Pat :: TuplePat ( tpat) , Pat :: TuplePat ( tvar) ) => {
270298 tpat. fields ( ) . zip ( tvar. fields ( ) ) . all ( |( p, v) | does_pat_match_variant ( & p, & v) )
271299 }
@@ -280,7 +308,7 @@ enum ExtendedEnum {
280308 Enum ( hir:: Enum ) ,
281309}
282310
283- #[ derive( Eq , PartialEq , Clone , Copy ) ]
311+ #[ derive( Eq , PartialEq , Clone , Copy , Debug ) ]
284312enum ExtendedVariant {
285313 True ,
286314 False ,
@@ -340,15 +368,30 @@ fn resolve_tuple_of_enum_def(
340368 . tuple_fields ( sema. db )
341369 . iter ( )
342370 . 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+ }
349379 } )
350380 } )
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+ } )
352395}
353396
354397fn build_pat (
@@ -377,7 +420,6 @@ fn build_pat(
377420 }
378421 ast:: StructKind :: Unit => make:: path_pat ( path) ,
379422 } ;
380-
381423 Some ( pat)
382424 }
383425 ExtendedVariant :: True => Some ( ast:: Pat :: from ( make:: literal_pat ( "true" ) ) ) ,
@@ -573,6 +615,86 @@ fn foo(a: bool) {
573615 )
574616 }
575617
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+
576698 #[ test]
577699 fn partial_fill_boolean_tuple ( ) {
578700 check_assist (
0 commit comments