1
1
use std:: iter:: { self , Peekable } ;
2
+ use std:: ops:: Deref ;
3
+ use std:: rc:: Rc ;
2
4
3
5
use either:: Either ;
4
6
use hir:: { sym, Adt , Crate , HasAttrs , ImportPathConfig , ModuleDef , Semantics } ;
@@ -76,6 +78,11 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>)
76
78
77
79
let cfg = ctx. config . import_path_config ( ) ;
78
80
81
+ // As `make` is borrowed by the closure that builds `missing_pats`, this is needed
82
+ // to satisfy the borrow checker.
83
+ let make = Rc :: new ( SyntaxFactory :: new ( ) ) ;
84
+ let make_weak = Rc :: downgrade ( & make) ;
85
+
79
86
let module = ctx. sema . scope ( expr. syntax ( ) ) ?. module ( ) ;
80
87
let ( mut missing_pats, is_non_exhaustive, has_hidden_variants) : (
81
88
Peekable < Box < dyn Iterator < Item = ( ast:: Pat , bool ) > > > ,
@@ -92,8 +99,9 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>)
92
99
let missing_pats = variants
93
100
. into_iter ( )
94
101
. filter_map ( |variant| {
102
+ let make = make_weak. upgrade ( ) ?;
95
103
Some ( (
96
- build_pat ( ctx, module, variant, cfg) ?,
104
+ build_pat ( ctx, make , module, variant, cfg) ?,
97
105
variant. should_be_hidden ( ctx. db ( ) , module. krate ( ) ) ,
98
106
) )
99
107
} )
@@ -140,14 +148,17 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>)
140
148
. into_iter ( )
141
149
. multi_cartesian_product ( )
142
150
. inspect ( |_| cov_mark:: hit!( add_missing_match_arms_lazy_computation) )
143
- . map ( |variants| {
151
+ . filter_map ( |variants| {
144
152
let is_hidden = variants
145
153
. iter ( )
146
154
. any ( |variant| variant. should_be_hidden ( ctx. db ( ) , module. krate ( ) ) ) ;
147
- let patterns =
148
- variants. into_iter ( ) . filter_map ( |variant| build_pat ( ctx, module, variant, cfg) ) ;
155
+ let patterns = variants. into_iter ( ) . filter_map ( |variant| {
156
+ make_weak. upgrade ( ) . and_then ( |make| build_pat ( ctx, make, module, variant, cfg) )
157
+ } ) ;
149
158
150
- ( ast:: Pat :: from ( make:: tuple_pat ( patterns) ) , is_hidden)
159
+ make_weak
160
+ . upgrade ( )
161
+ . map ( |make| ( ast:: Pat :: from ( make. tuple_pat ( patterns) ) , is_hidden) )
151
162
} )
152
163
. filter ( |( variant_pat, _) | is_variant_missing ( & top_lvl_pats, variant_pat) ) ;
153
164
(
@@ -172,13 +183,17 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>)
172
183
. into_iter ( )
173
184
. multi_cartesian_product ( )
174
185
. inspect ( |_| cov_mark:: hit!( add_missing_match_arms_lazy_computation) )
175
- . map ( |variants| {
186
+ . filter_map ( |variants| {
176
187
let is_hidden = variants
177
188
. iter ( )
178
189
. any ( |variant| variant. should_be_hidden ( ctx. db ( ) , module. krate ( ) ) ) ;
179
- let patterns =
180
- variants. into_iter ( ) . filter_map ( |variant| build_pat ( ctx, module, variant, cfg) ) ;
181
- ( ast:: Pat :: from ( make:: slice_pat ( patterns) ) , is_hidden)
190
+ let patterns = variants. into_iter ( ) . filter_map ( |variant| {
191
+ make_weak. upgrade ( ) . and_then ( |make| build_pat ( ctx, make, module, variant, cfg) )
192
+ } ) ;
193
+
194
+ make_weak
195
+ . upgrade ( )
196
+ . map ( |make| ( ast:: Pat :: from ( make. slice_pat ( patterns) ) , is_hidden) )
182
197
} )
183
198
. filter ( |( variant_pat, _) | is_variant_missing ( & top_lvl_pats, variant_pat) ) ;
184
199
(
@@ -203,8 +218,6 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>)
203
218
"Fill match arms" ,
204
219
ctx. sema . original_range ( match_expr. syntax ( ) ) . range ,
205
220
|builder| {
206
- let make = SyntaxFactory :: new ( ) ;
207
-
208
221
// having any hidden variants means that we need a catch-all arm
209
222
needs_catch_all_arm |= has_hidden_variants;
210
223
@@ -243,7 +256,7 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>)
243
256
244
257
if needs_catch_all_arm && !has_catch_all_arm {
245
258
cov_mark:: hit!( added_wildcard_pattern) ;
246
- let arm = make. match_arm ( make:: wildcard_pat ( ) . into ( ) , None , make:: ext:: expr_todo ( ) ) ;
259
+ let arm = make. match_arm ( make. wildcard_pat ( ) . into ( ) , None , make:: ext:: expr_todo ( ) ) ;
247
260
arms. push ( arm) ;
248
261
}
249
262
@@ -290,7 +303,7 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>)
290
303
}
291
304
}
292
305
293
- editor. add_mappings ( make. finish_with_mappings ( ) ) ;
306
+ editor. add_mappings ( Rc :: into_inner ( make) . unwrap ( ) . finish_with_mappings ( ) ) ;
294
307
builder. add_file_edits ( ctx. file_id ( ) , editor) ;
295
308
} ,
296
309
)
@@ -445,6 +458,7 @@ fn resolve_array_of_enum_def(
445
458
446
459
fn build_pat (
447
460
ctx : & AssistContext < ' _ > ,
461
+ make : impl Deref < Target = SyntaxFactory > ,
448
462
module : hir:: Module ,
449
463
var : ExtendedVariant ,
450
464
cfg : ImportPathConfig ,
@@ -455,31 +469,32 @@ fn build_pat(
455
469
let edition = module. krate ( ) . edition ( db) ;
456
470
let path = mod_path_to_ast ( & module. find_path ( db, ModuleDef :: from ( var) , cfg) ?, edition) ;
457
471
let fields = var. fields ( db) ;
458
- let pat = match var. kind ( db) {
472
+ let pat: ast :: Pat = match var. kind ( db) {
459
473
hir:: StructKind :: Tuple => {
460
474
let mut name_generator = suggest_name:: NameGenerator :: new ( ) ;
461
475
let pats = fields. into_iter ( ) . map ( |f| {
462
476
let name = name_generator. for_type ( & f. ty ( db) , db, edition) ;
463
477
match name {
464
- Some ( name) => make:: ext:: simple_ident_pat ( make:: name ( & name) ) . into ( ) ,
465
- None => make:: wildcard_pat ( ) . into ( ) ,
478
+ Some ( name) => make:: ext:: simple_ident_pat ( make. name ( & name) ) . into ( ) ,
479
+ None => make. wildcard_pat ( ) . into ( ) ,
466
480
}
467
481
} ) ;
468
- make:: tuple_struct_pat ( path, pats) . into ( )
482
+ make. tuple_struct_pat ( path, pats) . into ( )
469
483
}
470
484
hir:: StructKind :: Record => {
471
- let pats = fields
485
+ let fields = fields
472
486
. into_iter ( )
473
- . map ( |f| make:: name ( f. name ( db) . as_str ( ) ) )
474
- . map ( |name| make:: ext:: simple_ident_pat ( name) . into ( ) ) ;
475
- make:: record_pat ( path, pats) . into ( )
487
+ . map ( |f| make. name_ref ( f. name ( db) . as_str ( ) ) )
488
+ . map ( |name_ref| make. record_pat_field_shorthand ( name_ref) ) ;
489
+ let fields = make. record_pat_field_list ( fields, None ) ;
490
+ make. record_pat_with_fields ( path, fields) . into ( )
476
491
}
477
- hir:: StructKind :: Unit => make:: path_pat ( path) ,
492
+ hir:: StructKind :: Unit => make. path_pat ( path) ,
478
493
} ;
479
494
Some ( pat)
480
495
}
481
- ExtendedVariant :: True => Some ( ast:: Pat :: from ( make:: literal_pat ( "true" ) ) ) ,
482
- ExtendedVariant :: False => Some ( ast:: Pat :: from ( make:: literal_pat ( "false" ) ) ) ,
496
+ ExtendedVariant :: True => Some ( ast:: Pat :: from ( make. literal_pat ( "true" ) ) ) ,
497
+ ExtendedVariant :: False => Some ( ast:: Pat :: from ( make. literal_pat ( "false" ) ) ) ,
483
498
}
484
499
}
485
500
0 commit comments