1
- use core:: ops:: ControlFlow ;
2
1
use std:: borrow:: Cow ;
3
2
4
- use rustc_ast:: visit:: Visitor ;
5
3
use rustc_ast:: * ;
6
4
use rustc_data_structures:: fx:: FxIndexMap ;
7
5
use rustc_hir as hir;
@@ -476,77 +474,32 @@ fn expand_format_args<'hir>(
476
474
return hir:: ExprKind :: Call ( new, new_args) ;
477
475
}
478
476
479
- // If the args array contains exactly all the original arguments once,
480
- // in order, we can use a simple array instead of a `match` construction.
481
- // However, if there's a yield point in any argument except the first one,
482
- // we don't do this, because an Argument cannot be kept across yield points.
483
- //
484
- // This is an optimization, speeding up compilation about 1-2% in some cases.
485
- // See https://github.com/rust-lang/rust/pull/106770#issuecomment-1380790609
486
- let use_simple_array = argmap. len ( ) == arguments. len ( )
487
- && argmap. iter ( ) . enumerate ( ) . all ( |( i, ( & ( j, _) , _) ) | i == j)
488
- && arguments. iter ( ) . skip ( 1 ) . all ( |arg| !may_contain_yield_point ( & arg. expr ) ) ;
489
-
490
- let args = if arguments. is_empty ( ) {
477
+ let ( let_statements, args) = if arguments. is_empty ( ) {
491
478
// Generate:
492
- // &<core::fmt::Argument>::none()
493
- //
494
- // Note:
495
- // `none()` just returns `[]`. We use `none()` rather than `[]` to limit the lifetime.
496
- //
497
- // This makes sure that this still fails to compile, even when the argument is inlined:
498
- //
499
- // ```
500
- // let f = format_args!("{}", "a");
501
- // println!("{f}"); // error E0716
502
- // ```
503
- //
504
- // Cases where keeping the object around is allowed, such as `format_args!("a")`,
505
- // are handled above by the `allow_const` case.
506
- let none_fn = ctx. arena . alloc ( ctx. expr_lang_item_type_relative (
507
- macsp,
508
- hir:: LangItem :: FormatArgument ,
509
- sym:: none,
510
- ) ) ;
511
- let none = ctx. expr_call ( macsp, none_fn, & [ ] ) ;
512
- ctx. expr ( macsp, hir:: ExprKind :: AddrOf ( hir:: BorrowKind :: Ref , hir:: Mutability :: Not , none) )
513
- } else if use_simple_array {
514
- // Generate:
515
- // &[
516
- // <core::fmt::Argument>::new_display(&arg0),
517
- // <core::fmt::Argument>::new_lower_hex(&arg1),
518
- // <core::fmt::Argument>::new_debug(&arg2),
519
- // …
520
- // ]
521
- let elements = ctx. arena . alloc_from_iter ( arguments. iter ( ) . zip ( argmap) . map (
522
- |( arg, ( ( _, ty) , placeholder_span) ) | {
523
- let placeholder_span =
524
- placeholder_span. unwrap_or ( arg. expr . span ) . with_ctxt ( macsp. ctxt ( ) ) ;
525
- let arg_span = match arg. kind {
526
- FormatArgumentKind :: Captured ( _) => placeholder_span,
527
- _ => arg. expr . span . with_ctxt ( macsp. ctxt ( ) ) ,
528
- } ;
529
- let arg = ctx. lower_expr ( & arg. expr ) ;
530
- let ref_arg = ctx. arena . alloc ( ctx. expr (
531
- arg_span,
532
- hir:: ExprKind :: AddrOf ( hir:: BorrowKind :: Ref , hir:: Mutability :: Not , arg) ,
533
- ) ) ;
534
- make_argument ( ctx, placeholder_span, ref_arg, ty)
535
- } ,
536
- ) ) ;
537
- ctx. expr_array_ref ( macsp, elements)
479
+ // []
480
+ ( None , ctx. arena . alloc ( ctx. expr ( macsp, hir:: ExprKind :: Array ( & [ ] ) ) ) )
538
481
} else {
539
482
// Generate:
540
- // &match (&arg0, &arg1, &…) {
541
- // args => [
542
- // <core::fmt::Argument>::new_display(args.0),
543
- // <core::fmt::Argument>::new_lower_hex(args.1),
544
- // <core::fmt::Argument>::new_debug(args.0),
545
- // …
546
- // ]
547
- // }
483
+ // super let args = (&arg0, &arg1, &…);
548
484
let args_ident = Ident :: new ( sym:: args, macsp) ;
549
485
let ( args_pat, args_hir_id) = ctx. pat_ident ( macsp, args_ident) ;
486
+ let elements = ctx. arena . alloc_from_iter ( arguments. iter ( ) . map ( |arg| {
487
+ let arg_expr = ctx. lower_expr ( & arg. expr ) ;
488
+ ctx. expr (
489
+ arg. expr . span . with_ctxt ( macsp. ctxt ( ) ) ,
490
+ hir:: ExprKind :: AddrOf ( hir:: BorrowKind :: Ref , hir:: Mutability :: Not , arg_expr) ,
491
+ )
492
+ } ) ) ;
493
+ let args_tuple = ctx. arena . alloc ( ctx. expr ( macsp, hir:: ExprKind :: Tup ( elements) ) ) ;
494
+ let let_statement_1 = ctx. stmt_super_let_pat ( macsp, args_pat, Some ( args_tuple) ) ;
495
+
496
+ // Generate:
497
+ // super let args = [
498
+ // <core::fmt::Argument>::new_display(args.0),
499
+ // <core::fmt::Argument>::new_lower_hex(args.1),
500
+ // <core::fmt::Argument>::new_debug(args.0),
501
+ // …
502
+ // ];
550
503
let args = ctx. arena . alloc_from_iter ( argmap. iter ( ) . map (
551
504
|( & ( arg_index, ty) , & placeholder_span) | {
552
505
let arg = & arguments[ arg_index] ;
@@ -567,29 +520,21 @@ fn expand_format_args<'hir>(
567
520
make_argument ( ctx, placeholder_span, arg, ty)
568
521
} ,
569
522
) ) ;
570
- let elements = ctx. arena . alloc_from_iter ( arguments. iter ( ) . map ( |arg| {
571
- let arg_expr = ctx. lower_expr ( & arg. expr ) ;
572
- ctx. expr (
573
- arg. expr . span . with_ctxt ( macsp. ctxt ( ) ) ,
574
- hir:: ExprKind :: AddrOf ( hir:: BorrowKind :: Ref , hir:: Mutability :: Not , arg_expr) ,
575
- )
576
- } ) ) ;
577
- let args_tuple = ctx. arena . alloc ( ctx. expr ( macsp, hir:: ExprKind :: Tup ( elements) ) ) ;
578
- let array = ctx. arena . alloc ( ctx. expr ( macsp, hir:: ExprKind :: Array ( args) ) ) ;
579
- let match_arms = ctx. arena . alloc_from_iter ( [ ctx. arm ( args_pat, array) ] ) ;
580
- let match_expr = ctx. arena . alloc ( ctx. expr_match (
581
- macsp,
582
- args_tuple,
583
- match_arms,
584
- hir:: MatchSource :: FormatArgs ,
585
- ) ) ;
586
- ctx. expr (
587
- macsp,
588
- hir:: ExprKind :: AddrOf ( hir:: BorrowKind :: Ref , hir:: Mutability :: Not , match_expr) ,
523
+ let args = ctx. arena . alloc ( ctx. expr ( macsp, hir:: ExprKind :: Array ( args) ) ) ;
524
+ let ( args_pat, args_hir_id) = ctx. pat_ident ( macsp, args_ident) ;
525
+ let let_statement_2 = ctx. stmt_super_let_pat ( macsp, args_pat, Some ( args) ) ;
526
+ (
527
+ Some ( [ let_statement_1, let_statement_2] ) ,
528
+ ctx. arena . alloc ( ctx. expr_ident_mut ( macsp, args_ident, args_hir_id) ) ,
589
529
)
590
530
} ;
591
531
592
- if let Some ( format_options) = format_options {
532
+ // Generate:
533
+ // &args
534
+ let args =
535
+ ctx. expr ( macsp, hir:: ExprKind :: AddrOf ( hir:: BorrowKind :: Ref , hir:: Mutability :: Not , args) ) ;
536
+
537
+ let call = if let Some ( format_options) = format_options {
593
538
// Generate:
594
539
// <core::fmt::Arguments>::new_v1_formatted(
595
540
// lit_pieces,
@@ -632,35 +577,21 @@ fn expand_format_args<'hir>(
632
577
) ) ;
633
578
let new_args = ctx. arena . alloc_from_iter ( [ lit_pieces, args] ) ;
634
579
hir:: ExprKind :: Call ( new_v1, new_args)
635
- }
636
- }
637
-
638
- fn may_contain_yield_point ( e : & ast:: Expr ) -> bool {
639
- struct MayContainYieldPoint ;
640
-
641
- impl Visitor < ' _ > for MayContainYieldPoint {
642
- type Result = ControlFlow < ( ) > ;
643
-
644
- fn visit_expr ( & mut self , e : & ast:: Expr ) -> ControlFlow < ( ) > {
645
- if let ast:: ExprKind :: Await ( _, _) | ast:: ExprKind :: Yield ( _) = e. kind {
646
- ControlFlow :: Break ( ( ) )
647
- } else {
648
- visit:: walk_expr ( self , e)
649
- }
650
- }
651
-
652
- fn visit_mac_call ( & mut self , _: & ast:: MacCall ) -> ControlFlow < ( ) > {
653
- // Macros should be expanded at this point.
654
- unreachable ! ( "unexpanded macro in ast lowering" ) ;
655
- }
580
+ } ;
656
581
657
- fn visit_item ( & mut self , _: & ast:: Item ) -> ControlFlow < ( ) > {
658
- // Do not recurse into nested items.
659
- ControlFlow :: Continue ( ( ) )
660
- }
582
+ if let Some ( let_statements) = let_statements {
583
+ // Generate:
584
+ // {
585
+ // super let …
586
+ // super let …
587
+ // <core::fmt::Arguments>::new_…(…)
588
+ // }
589
+ let call = ctx. arena . alloc ( ctx. expr ( macsp, call) ) ;
590
+ let block = ctx. block_all ( macsp, ctx. arena . alloc_from_iter ( let_statements) , Some ( call) ) ;
591
+ hir:: ExprKind :: Block ( block, None )
592
+ } else {
593
+ call
661
594
}
662
-
663
- MayContainYieldPoint . visit_expr ( e) . is_break ( )
664
595
}
665
596
666
597
fn for_all_argument_indexes ( template : & mut [ FormatArgsPiece ] , mut f : impl FnMut ( & mut usize ) ) {
0 commit comments