fn into_expr(self) -> P<ast::Expr> {
        let mut locals = Vec::with_capacity(
            (0..self.args.len()).map(|i| self.arg_unique_types[i].len()).sum()
        );
        let mut counts = Vec::with_capacity(self.count_args.len());
        let mut pats = Vec::with_capacity(self.args.len());
        let mut heads = Vec::with_capacity(self.args.len());

        let names_pos: Vec<_> = (0..self.args.len())
            .map(|i| self.ecx.ident_of(&format!("arg{}", i)).gensym())
            .collect();

        // First, build up the static array which will become our precompiled
        // format "string"
        let pieces = self.ecx.expr_vec_slice(self.fmtsp, self.str_pieces);

        // Before consuming the expressions, we have to remember spans for
        // count arguments as they are now generated separate from other
        // arguments, hence have no access to the `P<ast::Expr>`'s.
        let spans_pos: Vec<_> = self.args.iter().map(|e| e.span.clone()).collect();

        // Right now there is a bug such that for the expression:
        //      foo(bar(&1))
        // the lifetime of `1` doesn't outlast the call to `bar`, so it's not
        // valid for the call to `foo`. To work around this all arguments to the
        // format! string are shoved into locals. Furthermore, we shove the address
        // of each variable because we don't want to move out of the arguments
        // passed to this function.
        for (i, e) in self.args.into_iter().enumerate() {
            let name = names_pos[i];
            let span =
                DUMMY_SP.with_ctxt(e.span.ctxt().apply_mark(self.ecx.current_expansion.mark));
            pats.push(self.ecx.pat_ident(span, name));
            for ref arg_ty in self.arg_unique_types[i].iter() {
                locals.push(Context::format_arg(self.ecx, self.macsp, e.span, arg_ty, name));
            }
            heads.push(self.ecx.expr_addr_of(e.span, e));
        }
        for pos in self.count_args {
            let index = match pos {
                Exact(i) => i,
                _ => panic!("should never happen"),
            };
            let name = names_pos[index];
            let span = spans_pos[index];
            counts.push(Context::format_arg(self.ecx, self.macsp, span, &Count, name));
        }

        // Now create a vector containing all the arguments
        let args = locals.into_iter().chain(counts.into_iter());

        let args_array = self.ecx.expr_vec(self.fmtsp, args.collect());

        // Constructs an AST equivalent to:
        //
        //      match (&arg0, &arg1) {
        //          (tmp0, tmp1) => args_array
        //      }
        //
        // It was:
        //
        //      let tmp0 = &arg0;
        //      let tmp1 = &arg1;
        //      args_array
        //
        // Because of #11585 the new temporary lifetime rule, the enclosing
        // statements for these temporaries become the let's themselves.
        // If one or more of them are RefCell's, RefCell borrow() will also
        // end there; they don't last long enough for args_array to use them.
        // The match expression solves the scope problem.
        //
        // Note, it may also very well be transformed to:
        //
        //      match arg0 {
        //          ref tmp0 => {
        //              match arg1 => {
        //                  ref tmp1 => args_array } } }
        //
        // But the nested match expression is proved to perform not as well
        // as series of let's; the first approach does.
        let pat = self.ecx.pat_tuple(self.fmtsp, pats);
        let arm = self.ecx.arm(self.fmtsp, vec![pat], args_array);
        let head = self.ecx.expr(self.fmtsp, ast::ExprKind::Tup(heads));
        let result = self.ecx.expr_match(self.fmtsp, head, vec![arm]);

        let args_slice = self.ecx.expr_addr_of(self.fmtsp, result);

        // Now create the fmt::Arguments struct with all our locals we created.
        let (fn_name, fn_args) = if self.all_pieces_simple {
            ("new_v1", vec![pieces, args_slice])
        } else {
            // Build up the static array which will store our precompiled
            // nonstandard placeholders, if there are any.
            let fmt = self.ecx.expr_vec_slice(self.macsp, self.pieces);

            ("new_v1_formatted", vec![pieces, args_slice, fmt])
        };

        let path = self.ecx.std_path(&["fmt", "Arguments", fn_name]);
        self.ecx.expr_call_global(self.macsp, path, fn_args)
    }
/// Actually builds the expression which the format_args! block will be
/// expanded to
Actually builds the expression which the format_args. block will be
expanded to
Actually builds the expression which the format_args . block will be expanded to
fn into_expr(self) -> P<ast::Expr> {
        let mut locals = Vec::with_capacity(
            (0..self.args.len()).map(|i| self.arg_unique_types[i].len()).sum()
        );
        let mut counts = Vec::with_capacity(self.count_args.len());
        let mut pats = Vec::with_capacity(self.args.len());
        let mut heads = Vec::with_capacity(self.args.len());
        let names_pos: Vec<_> = (0..self.args.len())
            .map(|i| self.ecx.ident_of(&format!("arg{}", i)).gensym())
            .collect();
        // First, build up the static array which will become our precompiled
        // format "string"
        let pieces = self.ecx.expr_vec_slice(self.fmtsp, self.str_pieces);
        // Before consuming the expressions, we have to remember spans for
        // count arguments as they are now generated separate from other
        // arguments, hence have no access to the `P<ast::Expr>`'s.
        let spans_pos: Vec<_> = self.args.iter().map(|e| e.span.clone()).collect();
        // Right now there is a bug such that for the expression:
        //      foo(bar(&1))
        // the lifetime of `1` doesn't outlast the call to `bar`, so it's not
        // valid for the call to `foo`. To work around this all arguments to the
        // format! string are shoved into locals. Furthermore, we shove the address
        // of each variable because we don't want to move out of the arguments
        // passed to this function.
        for (i, e) in self.args.into_iter().enumerate() {
            let name = names_pos[i];
            let span =
                DUMMY_SP.with_ctxt(e.span.ctxt().apply_mark(self.ecx.current_expansion.mark));
            pats.push(self.ecx.pat_ident(span, name));
            for ref arg_ty in self.arg_unique_types[i].iter() {
                locals.push(Context::format_arg(self.ecx, self.macsp, e.span, arg_ty, name));
            }
            heads.push(self.ecx.expr_addr_of(e.span, e));
        }
        for pos in self.count_args {
            let index = match pos {
                Exact(i) => i,
                _ => panic!("should never happen"),
            };
            let name = names_pos[index];
            let span = spans_pos[index];
            counts.push(Context::format_arg(self.ecx, self.macsp, span, &Count, name));
        }
        // Now create a vector containing all the arguments
        let args = locals.into_iter().chain(counts.into_iter());
        let args_array = self.ecx.expr_vec(self.fmtsp, args.collect());
        // Constructs an AST equivalent to:
        //
        //      match (&arg0, &arg1) {
        //          (tmp0, tmp1) => args_array
        //      }
        //
        // It was:
        //
        //      let tmp0 = &arg0;
        //      let tmp1 = &arg1;
        //      args_array
        //
        // Because of #11585 the new temporary lifetime rule, the enclosing
        // statements for these temporaries become the let's themselves.
        // If one or more of them are RefCell's, RefCell borrow() will also
        // end there; they don't last long enough for args_array to use them.
        // The match expression solves the scope problem.
        //
        // Note, it may also very well be transformed to:
        //
        //      match arg0 {
        //          ref tmp0 => {
        //              match arg1 => {
        //                  ref tmp1 => args_array } } }
        //
        // But the nested match expression is proved to perform not as well
        // as series of let's; the first approach does.
        let pat = self.ecx.pat_tuple(self.fmtsp, pats);
        let arm = self.ecx.arm(self.fmtsp, vec![pat], args_array);
        let head = self.ecx.expr(self.fmtsp, ast::ExprKind::Tup(heads));
        let result = self.ecx.expr_match(self.fmtsp, head, vec![arm]);
        let args_slice = self.ecx.expr_addr_of(self.fmtsp, result);
        // Now create the fmt::Arguments struct with all our locals we created.
        let (fn_name, fn_args) = if self.all_pieces_simple {
            ("new_v1", vec![pieces, args_slice])
        } else {
            // Build up the static array which will store our precompiled
            // nonstandard placeholders, if there are any.
            let fmt = self.ecx.expr_vec_slice(self.macsp, self.pieces);
            ("new_v1_formatted", vec![pieces, args_slice, fmt])
        };
        let path = self.ecx.std_path(&["fmt", "Arguments", fn_name]);
        self.ecx.expr_call_global(self.macsp, path, fn_args)
    }
fn into_expr ( self ) -> P < ast :: Expr > { let mut locals = Vec :: with_capacity ( ( 0 .. self . args . len ( ) ) . map ( | i | self . arg_unique_types [ i ] . len ( ) ) . sum ( ) ) ; let mut counts = Vec :: with_capacity ( self . count_args . len ( ) ) ; let mut pats = Vec :: with_capacity ( self . args . len ( ) ) ; let mut heads = Vec :: with_capacity ( self . args . len ( ) ) ; let names_pos : Vec < _ > = ( 0 .. self . args . len ( ) ) . map ( | i | self . ecx . ident_of ( & format ! ( " " i ) ) . gensym ( ) ) . collect ( ) ; // First, build up the static array which will become our precompiled // format "string" let pieces = self . ecx . expr_vec_slice ( self . fmtsp , self . str_pieces ) ; // Before consuming the expressions, we have to remember spans for // count arguments as they are now generated separate from other // arguments, hence have no access to the `P<ast::Expr>`'s. let spans_pos : Vec < _ > = self . args . iter ( ) . map ( | e | e . span . clone ( ) ) . collect ( ) ; // Right now there is a bug such that for the expression: //      foo(bar(&1)) // the lifetime of `1` doesn't outlast the call to `bar`, so it's not // valid for the call to `foo`. To work around this all arguments to the // format! string are shoved into locals. Furthermore, we shove the address // of each variable because we don't want to move out of the arguments // passed to this function. for ( i , e ) in self . args . into_iter ( ) . enumerate ( ) { let name = names_pos [ i ] ; let span = DUMMY_SP . with_ctxt ( e . span . ctxt ( ) . apply_mark ( self . ecx . current_expansion . mark ) ) ; pats . push ( self . ecx . pat_ident ( span , name ) ) ; for ref arg_ty in self . arg_unique_types [ i ] . iter ( ) { locals . push ( Context :: format_arg ( self . ecx , self . macsp , e . span , arg_ty , name ) ) ; } heads . push ( self . ecx . expr_addr_of ( e . span , e ) ) ; } for pos in self . count_args { let index = match pos { Exact ( i ) => i , _ => panic ! ( " " ) , } ; let name = names_pos [ index ] ; let span = spans_pos [ index ] ; counts . push ( Context :: format_arg ( self . ecx , self . macsp , span , & Count , name ) ) ; } // Now create a vector containing all the arguments let args = locals . into_iter ( ) . chain ( counts . into_iter ( ) ) ; let args_array = self . ecx . expr_vec ( self . fmtsp , args . collect ( ) ) ; // Constructs an AST equivalent to: // //      match (&arg0, &arg1) { //          (tmp0, tmp1) => args_array //      } // // It was: // //      let tmp0 = &arg0; //      let tmp1 = &arg1; //      args_array // // Because of #11585 the new temporary lifetime rule, the enclosing // statements for these temporaries become the let's themselves. // If one or more of them are RefCell's, RefCell borrow() will also // end there; they don't last long enough for args_array to use them. // The match expression solves the scope problem. // // Note, it may also very well be transformed to: // //      match arg0 { //          ref tmp0 => { //              match arg1 => { //                  ref tmp1 => args_array } } } // // But the nested match expression is proved to perform not as well // as series of let's; the first approach does. let pat = self . ecx . pat_tuple ( self . fmtsp , pats ) ; let arm = self . ecx . arm ( self . fmtsp , vec ! [ pat ] , args_array ) ; let head = self . ecx . expr ( self . fmtsp , ast :: ExprKind :: Tup ( heads ) ) ; let result = self . ecx . expr_match ( self . fmtsp , head , vec ! [ arm ] ) ; let args_slice = self . ecx . expr_addr_of ( self . fmtsp , result ) ; // Now create the fmt::Arguments struct with all our locals we created. let ( fn_name , fn_args ) = if self . all_pieces_simple { ( " " , vec ! [ pieces args_slice ] ) } else { // Build up the static array which will store our precompiled // nonstandard placeholders, if there are any. let fmt = self . ecx . expr_vec_slice ( self . macsp , self . pieces ) ; ( " " , vec ! [ pieces args_slice fmt ] ) } ; let path = self . ecx . std_path ( & [ " " , " " , fn_name ] ) ; self . ecx . expr_call_global ( self . macsp , path , fn_args ) }
Actually builds the expression which the format_args!
Actually builds the expression which the format_args!
self
self