11use std:: iter:: { self , Peekable } ;
2+ use std:: ops:: Deref ;
3+ use std:: rc:: Rc ;
24
35use either:: Either ;
46use hir:: { sym, Adt , Crate , HasAttrs , ImportPathConfig , ModuleDef , Semantics } ;
@@ -76,6 +78,11 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>)
7678
7779 let cfg = ctx. config . import_path_config ( ) ;
7880
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+
7986 let module = ctx. sema . scope ( expr. syntax ( ) ) ?. module ( ) ;
8087 let ( mut missing_pats, is_non_exhaustive, has_hidden_variants) : (
8188 Peekable < Box < dyn Iterator < Item = ( ast:: Pat , bool ) > > > ,
@@ -92,8 +99,9 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>)
9299 let missing_pats = variants
93100 . into_iter ( )
94101 . filter_map ( |variant| {
102+ let make = make_weak. upgrade ( ) ?;
95103 Some ( (
96- build_pat ( ctx, module, variant, cfg) ?,
104+ build_pat ( ctx, make , module, variant, cfg) ?,
97105 variant. should_be_hidden ( ctx. db ( ) , module. krate ( ) ) ,
98106 ) )
99107 } )
@@ -140,14 +148,17 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>)
140148 . into_iter ( )
141149 . multi_cartesian_product ( )
142150 . inspect ( |_| cov_mark:: hit!( add_missing_match_arms_lazy_computation) )
143- . map ( |variants| {
151+ . filter_map ( |variants| {
144152 let is_hidden = variants
145153 . iter ( )
146154 . 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+ } ) ;
149158
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) )
151162 } )
152163 . filter ( |( variant_pat, _) | is_variant_missing ( & top_lvl_pats, variant_pat) ) ;
153164 (
@@ -172,13 +183,17 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>)
172183 . into_iter ( )
173184 . multi_cartesian_product ( )
174185 . inspect ( |_| cov_mark:: hit!( add_missing_match_arms_lazy_computation) )
175- . map ( |variants| {
186+ . filter_map ( |variants| {
176187 let is_hidden = variants
177188 . iter ( )
178189 . 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) )
182197 } )
183198 . filter ( |( variant_pat, _) | is_variant_missing ( & top_lvl_pats, variant_pat) ) ;
184199 (
@@ -203,8 +218,6 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>)
203218 "Fill match arms" ,
204219 ctx. sema . original_range ( match_expr. syntax ( ) ) . range ,
205220 |builder| {
206- let make = SyntaxFactory :: new ( ) ;
207-
208221 // having any hidden variants means that we need a catch-all arm
209222 needs_catch_all_arm |= has_hidden_variants;
210223
@@ -243,7 +256,7 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>)
243256
244257 if needs_catch_all_arm && !has_catch_all_arm {
245258 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 ( ) ) ;
247260 arms. push ( arm) ;
248261 }
249262
@@ -290,7 +303,7 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>)
290303 }
291304 }
292305
293- editor. add_mappings ( make. finish_with_mappings ( ) ) ;
306+ editor. add_mappings ( Rc :: into_inner ( make) . unwrap ( ) . finish_with_mappings ( ) ) ;
294307 builder. add_file_edits ( ctx. file_id ( ) , editor) ;
295308 } ,
296309 )
@@ -445,6 +458,7 @@ fn resolve_array_of_enum_def(
445458
446459fn build_pat (
447460 ctx : & AssistContext < ' _ > ,
461+ make : impl Deref < Target = SyntaxFactory > ,
448462 module : hir:: Module ,
449463 var : ExtendedVariant ,
450464 cfg : ImportPathConfig ,
@@ -455,31 +469,32 @@ fn build_pat(
455469 let edition = module. krate ( ) . edition ( db) ;
456470 let path = mod_path_to_ast ( & module. find_path ( db, ModuleDef :: from ( var) , cfg) ?, edition) ;
457471 let fields = var. fields ( db) ;
458- let pat = match var. kind ( db) {
472+ let pat: ast :: Pat = match var. kind ( db) {
459473 hir:: StructKind :: Tuple => {
460474 let mut name_generator = suggest_name:: NameGenerator :: new ( ) ;
461475 let pats = fields. into_iter ( ) . map ( |f| {
462476 let name = name_generator. for_type ( & f. ty ( db) , db, edition) ;
463477 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 ( ) ,
466480 }
467481 } ) ;
468- make:: tuple_struct_pat ( path, pats) . into ( )
482+ make. tuple_struct_pat ( path, pats) . into ( )
469483 }
470484 hir:: StructKind :: Record => {
471- let pats = fields
485+ let fields = fields
472486 . 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 ( )
476491 }
477- hir:: StructKind :: Unit => make:: path_pat ( path) ,
492+ hir:: StructKind :: Unit => make. path_pat ( path) ,
478493 } ;
479494 Some ( pat)
480495 }
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" ) ) ) ,
483498 }
484499}
485500
0 commit comments