@@ -607,6 +607,8 @@ impl<'a> Context<'a> {
607
607
let mut lets = ~[ ] ;
608
608
let mut locals = ~[ ] ;
609
609
let mut names = vec:: from_fn ( self . name_positions . len ( ) , |_| None ) ;
610
+ let mut pats = ~[ ] ;
611
+ let mut heads = ~[ ] ;
610
612
611
613
// First, declare all of our methods that are statics
612
614
for & method in self . method_statics . iter ( ) {
@@ -653,8 +655,8 @@ impl<'a> Context<'a> {
653
655
if self . arg_types [ i] . is_none ( ) { continue } // error already generated
654
656
655
657
let name = self . ecx . ident_of ( format ! ( "__arg{}" , i) ) ;
656
- let e = self . ecx . expr_addr_of ( e. span , e ) ;
657
- lets . push ( self . ecx . stmt_let ( e. span , false , name , e) ) ;
658
+ pats . push ( self . ecx . pat_ident ( e. span , name ) ) ;
659
+ heads . push ( self . ecx . expr_addr_of ( e. span , e) ) ;
658
660
locals. push ( self . format_arg ( e. span , Exact ( i) ,
659
661
self . ecx . expr_ident ( e. span , name) ) ) ;
660
662
}
@@ -664,8 +666,8 @@ impl<'a> Context<'a> {
664
666
}
665
667
666
668
let lname = self . ecx . ident_of ( format ! ( "__arg{}" , * name) ) ;
667
- let e = self . ecx . expr_addr_of ( e. span , e ) ;
668
- lets . push ( self . ecx . stmt_let ( e. span , false , lname , e) ) ;
669
+ pats . push ( self . ecx . pat_ident ( e. span , lname ) ) ;
670
+ heads . push ( self . ecx . expr_addr_of ( e. span , e) ) ;
669
671
names[ * self . name_positions . get ( name) ] =
670
672
Some ( self . format_arg ( e. span ,
671
673
Named ( ( * name) . clone ( ) ) ,
@@ -706,8 +708,40 @@ impl<'a> Context<'a> {
706
708
let res = self . ecx . expr_ident ( self . fmtsp , resname) ;
707
709
let result = self . ecx . expr_call ( extra. span , extra, ~[
708
710
self . ecx . expr_addr_of ( extra. span , res) ] ) ;
709
- self . ecx . expr_block ( self . ecx . block ( self . fmtsp , lets,
710
- Some ( result) ) )
711
+ let body = self . ecx . expr_block ( self . ecx . block ( self . fmtsp , lets,
712
+ Some ( result) ) ) ;
713
+
714
+ // Constructs an AST equivalent to:
715
+ //
716
+ // match (&arg0, &arg1) {
717
+ // (tmp0, tmp1) => body
718
+ // }
719
+ //
720
+ // It was:
721
+ //
722
+ // let tmp0 = &arg0;
723
+ // let tmp1 = &arg1;
724
+ // body
725
+ //
726
+ // Because of #11585 the new temporary lifetime rule, the enclosing
727
+ // statements for these temporaries become the let's themselves.
728
+ // If one or more of them are RefCell's, RefCell borrow() will also
729
+ // end there; they don't last long enough for body to use them. The
730
+ // match expression solves the scope problem.
731
+ //
732
+ // Note, it may also very well be transformed to:
733
+ //
734
+ // match arg0 {
735
+ // ref tmp0 => {
736
+ // match arg1 => {
737
+ // ref tmp1 => body } } }
738
+ //
739
+ // But the nested match expression is proved to perform not as well
740
+ // as series of let's; the first approach does.
741
+ let pat = self . ecx . pat ( self . fmtsp , ast:: PatTup ( pats) ) ;
742
+ let arm = self . ecx . arm ( self . fmtsp , ~[ pat] , body) ;
743
+ let head = self . ecx . expr ( self . fmtsp , ast:: ExprTup ( heads) ) ;
744
+ self . ecx . expr_match ( self . fmtsp , head, ~[ arm] )
711
745
}
712
746
713
747
fn format_arg ( & self , sp : Span , argno : Position , arg : @ast:: Expr )
0 commit comments