Skip to content

Commit 68a7f1b

Browse files
committed
syntax: turn the match-call generated by format_args inside-out.
1 parent 17b3c11 commit 68a7f1b

File tree

1 file changed

+41
-39
lines changed

1 file changed

+41
-39
lines changed

src/libsyntax/ext/format.rs

Lines changed: 41 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -559,9 +559,43 @@ impl<'a, 'b> Context<'a, 'b> {
559559
// Now create a vector containing all the arguments
560560
let args = locals.into_iter().chain(names.into_iter().map(|a| a.unwrap()));
561561

562-
// Now create the fmt::Arguments struct with all our locals we created.
563-
let args_slice = self.ecx.expr_vec_slice(self.fmtsp, args.collect());
562+
let args_array = self.ecx.expr_vec(self.fmtsp, args.collect());
563+
564+
// Constructs an AST equivalent to:
565+
//
566+
// match (&arg0, &arg1) {
567+
// (tmp0, tmp1) => args_array
568+
// }
569+
//
570+
// It was:
571+
//
572+
// let tmp0 = &arg0;
573+
// let tmp1 = &arg1;
574+
// args_array
575+
//
576+
// Because of #11585 the new temporary lifetime rule, the enclosing
577+
// statements for these temporaries become the let's themselves.
578+
// If one or more of them are RefCell's, RefCell borrow() will also
579+
// end there; they don't last long enough for args_array to use them.
580+
// The match expression solves the scope problem.
581+
//
582+
// Note, it may also very well be transformed to:
583+
//
584+
// match arg0 {
585+
// ref tmp0 => {
586+
// match arg1 => {
587+
// ref tmp1 => args_array } } }
588+
//
589+
// But the nested match expression is proved to perform not as well
590+
// as series of let's; the first approach does.
591+
let pat = self.ecx.pat_tuple(self.fmtsp, pats);
592+
let arm = self.ecx.arm(self.fmtsp, vec!(pat), args_array);
593+
let head = self.ecx.expr(self.fmtsp, ast::ExprTup(heads));
594+
let result = self.ecx.expr_match(self.fmtsp, head, vec!(arm));
595+
596+
let args_slice = self.ecx.expr_addr_of(self.fmtsp, result);
564597

598+
// Now create the fmt::Arguments struct with all our locals we created.
565599
let (fn_name, fn_args) = if self.all_pieces_simple {
566600
("new", vec![pieces, args_slice])
567601
} else {
@@ -582,58 +616,26 @@ impl<'a, 'b> Context<'a, 'b> {
582616
("with_placeholders", vec![pieces, fmt, args_slice])
583617
};
584618

585-
let result = self.ecx.expr_call_global(self.fmtsp, vec!(
619+
let body = self.ecx.expr_call_global(self.fmtsp, vec!(
586620
self.ecx.ident_of("std"),
587621
self.ecx.ident_of("fmt"),
588622
self.ecx.ident_of("Arguments"),
589623
self.ecx.ident_of(fn_name)), fn_args);
590624

591-
let body = match invocation {
625+
match invocation {
592626
Call(e) => {
593627
let span = e.span;
594628
self.ecx.expr_call(span, e, vec![
595-
self.ecx.expr_addr_of(span, result)
629+
self.ecx.expr_addr_of(span, body)
596630
])
597631
}
598632
MethodCall(e, m) => {
599633
let span = e.span;
600634
self.ecx.expr_method_call(span, e, m, vec![
601-
self.ecx.expr_addr_of(span, result)
635+
self.ecx.expr_addr_of(span, body)
602636
])
603637
}
604-
};
605-
606-
// Constructs an AST equivalent to:
607-
//
608-
// match (&arg0, &arg1) {
609-
// (tmp0, tmp1) => body
610-
// }
611-
//
612-
// It was:
613-
//
614-
// let tmp0 = &arg0;
615-
// let tmp1 = &arg1;
616-
// body
617-
//
618-
// Because of #11585 the new temporary lifetime rule, the enclosing
619-
// statements for these temporaries become the let's themselves.
620-
// If one or more of them are RefCell's, RefCell borrow() will also
621-
// end there; they don't last long enough for body to use them. The
622-
// match expression solves the scope problem.
623-
//
624-
// Note, it may also very well be transformed to:
625-
//
626-
// match arg0 {
627-
// ref tmp0 => {
628-
// match arg1 => {
629-
// ref tmp1 => body } } }
630-
//
631-
// But the nested match expression is proved to perform not as well
632-
// as series of let's; the first approach does.
633-
let pat = self.ecx.pat_tuple(self.fmtsp, pats);
634-
let arm = self.ecx.arm(self.fmtsp, vec!(pat), body);
635-
let head = self.ecx.expr(self.fmtsp, ast::ExprTup(heads));
636-
self.ecx.expr_match(self.fmtsp, head, vec!(arm))
638+
}
637639
}
638640

639641
fn format_arg(ecx: &ExtCtxt, sp: Span,

0 commit comments

Comments
 (0)