@@ -75,14 +75,18 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>)
7575 . collect ( ) ;
7676
7777 let module = ctx. sema . scope ( expr. syntax ( ) ) ?. module ( ) ;
78- let ( mut missing_pats, is_non_exhaustive) : (
78+ let ( mut missing_pats, is_non_exhaustive, has_hidden_variants ) : (
7979 Peekable < Box < dyn Iterator < Item = ( ast:: Pat , bool ) > > > ,
8080 bool ,
81+ bool ,
8182 ) = if let Some ( enum_def) = resolve_enum_def ( & ctx. sema , & expr) {
8283 let is_non_exhaustive = enum_def. is_non_exhaustive ( ctx. db ( ) , module. krate ( ) ) ;
8384
8485 let variants = enum_def. variants ( ctx. db ( ) ) ;
8586
87+ let has_hidden_variants =
88+ variants. iter ( ) . any ( |variant| variant. should_be_hidden ( ctx. db ( ) , module. krate ( ) ) ) ;
89+
8690 let missing_pats = variants
8791 . into_iter ( )
8892 . filter_map ( |variant| {
@@ -101,7 +105,7 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>)
101105 } else {
102106 Box :: new ( missing_pats)
103107 } ;
104- ( missing_pats. peekable ( ) , is_non_exhaustive)
108+ ( missing_pats. peekable ( ) , is_non_exhaustive, has_hidden_variants )
105109 } else if let Some ( enum_defs) = resolve_tuple_of_enum_def ( & ctx. sema , & expr) {
106110 let is_non_exhaustive =
107111 enum_defs. iter ( ) . any ( |enum_def| enum_def. is_non_exhaustive ( ctx. db ( ) , module. krate ( ) ) ) ;
@@ -124,6 +128,12 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>)
124128 if n_arms > 256 {
125129 return None ;
126130 }
131+
132+ let has_hidden_variants = variants_of_enums
133+ . iter ( )
134+ . flatten ( )
135+ . any ( |variant| variant. should_be_hidden ( ctx. db ( ) , module. krate ( ) ) ) ;
136+
127137 let missing_pats = variants_of_enums
128138 . into_iter ( )
129139 . multi_cartesian_product ( )
@@ -139,7 +149,11 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>)
139149 ( ast:: Pat :: from ( make:: tuple_pat ( patterns) ) , is_hidden)
140150 } )
141151 . filter ( |( variant_pat, _) | is_variant_missing ( & top_lvl_pats, variant_pat) ) ;
142- ( ( Box :: new ( missing_pats) as Box < dyn Iterator < Item = _ > > ) . peekable ( ) , is_non_exhaustive)
152+ (
153+ ( Box :: new ( missing_pats) as Box < dyn Iterator < Item = _ > > ) . peekable ( ) ,
154+ is_non_exhaustive,
155+ has_hidden_variants,
156+ )
143157 } else if let Some ( ( enum_def, len) ) = resolve_array_of_enum_def ( & ctx. sema , & expr) {
144158 let is_non_exhaustive = enum_def. is_non_exhaustive ( ctx. db ( ) , module. krate ( ) ) ;
145159 let variants = enum_def. variants ( ctx. db ( ) ) ;
@@ -148,6 +162,9 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>)
148162 return None ;
149163 }
150164
165+ let has_hidden_variants =
166+ variants. iter ( ) . any ( |variant| variant. should_be_hidden ( ctx. db ( ) , module. krate ( ) ) ) ;
167+
151168 let variants_of_enums = vec ! [ variants; len] ;
152169
153170 let missing_pats = variants_of_enums
@@ -164,14 +181,20 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>)
164181 ( ast:: Pat :: from ( make:: slice_pat ( patterns) ) , is_hidden)
165182 } )
166183 . 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)
184+ (
185+ ( Box :: new ( missing_pats) as Box < dyn Iterator < Item = _ > > ) . peekable ( ) ,
186+ is_non_exhaustive,
187+ has_hidden_variants,
188+ )
168189 } else {
169190 return None ;
170191 } ;
171192
172193 let mut needs_catch_all_arm = is_non_exhaustive && !has_catch_all_arm;
173194
174- if !needs_catch_all_arm && missing_pats. peek ( ) . is_none ( ) {
195+ if !needs_catch_all_arm
196+ && ( ( has_hidden_variants && has_catch_all_arm) || missing_pats. peek ( ) . is_none ( ) )
197+ {
175198 return None ;
176199 }
177200
@@ -181,11 +204,17 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>)
181204 target_range,
182205 |builder| {
183206 let new_match_arm_list = match_arm_list. clone_for_update ( ) ;
184- let missing_arms = missing_pats
185- . map ( |( pat, hidden) | {
186- ( make:: match_arm ( iter:: once ( pat) , None , make:: ext:: expr_todo ( ) ) , hidden)
207+
208+ // having any hidden variants means that we need a catch-all arm
209+ needs_catch_all_arm |= has_hidden_variants;
210+
211+ let missing_arms = missing_pats. filter_map ( |( pat, hidden) | {
212+ // filter out hidden patterns because they're handled by the catch-all arm
213+ ( !hidden) . then ( || {
214+ make:: match_arm ( iter:: once ( pat) , None , make:: ext:: expr_todo ( ) )
215+ . clone_for_update ( )
187216 } )
188- . map ( | ( it , hidden ) | ( it . clone_for_update ( ) , hidden ) ) ;
217+ } ) ;
189218
190219 let catch_all_arm = new_match_arm_list
191220 . arms ( )
@@ -204,15 +233,13 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>)
204233 cov_mark:: hit!( add_missing_match_arms_empty_expr) ;
205234 }
206235 }
236+
207237 let mut first_new_arm = None ;
208- for ( arm, hidden) in missing_arms {
209- if hidden {
210- needs_catch_all_arm = !has_catch_all_arm;
211- } else {
212- first_new_arm. get_or_insert_with ( || arm. clone ( ) ) ;
213- new_match_arm_list. add_arm ( arm) ;
214- }
238+ for arm in missing_arms {
239+ first_new_arm. get_or_insert_with ( || arm. clone ( ) ) ;
240+ new_match_arm_list. add_arm ( arm) ;
215241 }
242+
216243 if needs_catch_all_arm && !has_catch_all_arm {
217244 cov_mark:: hit!( added_wildcard_pattern) ;
218245 let arm = make:: match_arm (
@@ -1621,10 +1648,9 @@ pub enum E { #[doc(hidden)] A, }
16211648 ) ;
16221649 }
16231650
1624- // FIXME: I don't think the assist should be applicable in this case
16251651 #[ test]
16261652 fn does_not_fill_wildcard_with_wildcard ( ) {
1627- check_assist (
1653+ check_assist_not_applicable (
16281654 add_missing_match_arms,
16291655 r#"
16301656//- /main.rs crate:main deps:e
@@ -1635,13 +1661,6 @@ fn foo(t: ::e::E) {
16351661}
16361662//- /e.rs crate:e
16371663pub enum E { #[doc(hidden)] A, }
1638- "# ,
1639- r#"
1640- fn foo(t: ::e::E) {
1641- match t {
1642- _ => todo!(),
1643- }
1644- }
16451664"# ,
16461665 ) ;
16471666 }
@@ -1777,7 +1796,7 @@ fn foo(t: ::e::E, b: bool) {
17771796
17781797 #[ test]
17791798 fn does_not_fill_wildcard_with_partial_wildcard_and_wildcard ( ) {
1780- check_assist (
1799+ check_assist_not_applicable (
17811800 add_missing_match_arms,
17821801 r#"
17831802//- /main.rs crate:main deps:e
@@ -1789,14 +1808,6 @@ fn foo(t: ::e::E, b: bool) {
17891808}
17901809//- /e.rs crate:e
17911810pub enum E { #[doc(hidden)] A, }"# ,
1792- r#"
1793- fn foo(t: ::e::E, b: bool) {
1794- match t {
1795- _ if b => todo!(),
1796- _ => todo!(),
1797- }
1798- }
1799- "# ,
18001811 ) ;
18011812 }
18021813
0 commit comments