11//! Wrappers over [`make`] constructors
2- use itertools:: Itertools ;
3-
42use crate :: {
53 ast:: { self , make, HasGenericParams , HasName , HasTypeBounds , HasVisibility } ,
64 syntax_editor:: SyntaxMappingBuilder ,
@@ -62,13 +60,12 @@ impl SyntaxFactory {
6260
6361 pub fn block_expr (
6462 & self ,
65- stmts : impl IntoIterator < Item = ast:: Stmt > ,
63+ statements : impl IntoIterator < Item = ast:: Stmt > ,
6664 tail_expr : Option < ast:: Expr > ,
6765 ) -> ast:: BlockExpr {
68- let stmts = stmts. into_iter ( ) . collect_vec ( ) ;
69- let mut input = stmts. iter ( ) . map ( |it| it. syntax ( ) . clone ( ) ) . collect_vec ( ) ;
66+ let ( statements, mut input) = iterator_input ( statements) ;
7067
71- let ast = make:: block_expr ( stmts , tail_expr. clone ( ) ) . clone_for_update ( ) ;
68+ let ast = make:: block_expr ( statements , tail_expr. clone ( ) ) . clone_for_update ( ) ;
7269
7370 if let Some ( mut mapping) = self . mappings ( ) {
7471 let stmt_list = ast. stmt_list ( ) . unwrap ( ) ;
@@ -257,14 +254,15 @@ impl SyntaxFactory {
257254
258255 pub fn turbofish_generic_arg_list (
259256 & self ,
260- args : impl IntoIterator < Item = ast:: GenericArg > + Clone ,
257+ generic_args : impl IntoIterator < Item = ast:: GenericArg > ,
261258 ) -> ast:: GenericArgList {
262- let ast = make:: turbofish_generic_arg_list ( args. clone ( ) ) . clone_for_update ( ) ;
259+ let ( generic_args, input) = iterator_input ( generic_args) ;
260+ let ast = make:: turbofish_generic_arg_list ( generic_args. clone ( ) ) . clone_for_update ( ) ;
263261
264262 if let Some ( mut mapping) = self . mappings ( ) {
265263 let mut builder = SyntaxMappingBuilder :: new ( ast. syntax ( ) . clone ( ) ) ;
266264 builder. map_children (
267- args . into_iter ( ) . map ( |arg| arg . syntax ( ) . clone ( ) ) ,
265+ input . into_iter ( ) ,
268266 ast. generic_args ( ) . map ( |arg| arg. syntax ( ) . clone ( ) ) ,
269267 ) ;
270268 builder. finish ( & mut mapping) ;
@@ -277,8 +275,7 @@ impl SyntaxFactory {
277275 & self ,
278276 fields : impl IntoIterator < Item = ast:: RecordField > ,
279277 ) -> ast:: RecordFieldList {
280- let fields: Vec < ast:: RecordField > = fields. into_iter ( ) . collect ( ) ;
281- let input: Vec < _ > = fields. iter ( ) . map ( |it| it. syntax ( ) . clone ( ) ) . collect ( ) ;
278+ let ( fields, input) = iterator_input ( fields) ;
282279 let ast = make:: record_field_list ( fields) . clone_for_update ( ) ;
283280
284281 if let Some ( mut mapping) = self . mappings ( ) {
@@ -323,8 +320,7 @@ impl SyntaxFactory {
323320 & self ,
324321 fields : impl IntoIterator < Item = ast:: TupleField > ,
325322 ) -> ast:: TupleFieldList {
326- let fields: Vec < ast:: TupleField > = fields. into_iter ( ) . collect ( ) ;
327- let input: Vec < _ > = fields. iter ( ) . map ( |it| it. syntax ( ) . clone ( ) ) . collect ( ) ;
323+ let ( fields, input) = iterator_input ( fields) ;
328324 let ast = make:: tuple_field_list ( fields) . clone_for_update ( ) ;
329325
330326 if let Some ( mut mapping) = self . mappings ( ) {
@@ -419,8 +415,7 @@ impl SyntaxFactory {
419415 & self ,
420416 variants : impl IntoIterator < Item = ast:: Variant > ,
421417 ) -> ast:: VariantList {
422- let variants: Vec < ast:: Variant > = variants. into_iter ( ) . collect ( ) ;
423- let input: Vec < _ > = variants. iter ( ) . map ( |it| it. syntax ( ) . clone ( ) ) . collect ( ) ;
418+ let ( variants, input) = iterator_input ( variants) ;
424419 let ast = make:: variant_list ( variants) . clone_for_update ( ) ;
425420
426421 if let Some ( mut mapping) = self . mappings ( ) {
@@ -481,7 +476,7 @@ impl SyntaxFactory {
481476 pub fn token_tree (
482477 & self ,
483478 delimiter : SyntaxKind ,
484- tt : Vec < NodeOrToken < ast:: TokenTree , SyntaxToken > > ,
479+ tt : impl IntoIterator < Item = NodeOrToken < ast:: TokenTree , SyntaxToken > > ,
485480 ) -> ast:: TokenTree {
486481 let tt: Vec < _ > = tt. into_iter ( ) . collect ( ) ;
487482 let input: Vec < _ > = tt. iter ( ) . cloned ( ) . filter_map ( only_nodes) . collect ( ) ;
@@ -512,3 +507,20 @@ impl SyntaxFactory {
512507 make:: tokens:: whitespace ( text)
513508 }
514509}
510+
511+ // We need to collect `input` here instead of taking `impl IntoIterator + Clone`,
512+ // because if we took `impl IntoIterator + Clone`, that could be something like an
513+ // `Iterator::map` with a closure that also makes use of a `SyntaxFactory` constructor.
514+ //
515+ // In that case, the iterator would be evaluated inside of the call to `map_children`,
516+ // and the inner constructor would try to take a mutable borrow of the mappings `RefCell`,
517+ // which would panic since it's already being mutably borrowed in the outer constructor.
518+ fn iterator_input < N : AstNode > ( input : impl IntoIterator < Item = N > ) -> ( Vec < N > , Vec < SyntaxNode > ) {
519+ input
520+ . into_iter ( )
521+ . map ( |it| {
522+ let syntax = it. syntax ( ) . clone ( ) ;
523+ ( it, syntax)
524+ } )
525+ . collect ( )
526+ }
0 commit comments