fn show_substructure(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<Expr> {
    // build fmt.debug_struct(<name>).field(<fieldname>, &<fieldval>)....build()
    // or fmt.debug_tuple(<name>).field(&<fieldval>)....build()
    // based on the "shape".
    let (ident, is_struct) = match *substr.fields {
        Struct(vdata, _) => (substr.type_ident, vdata.is_struct()),
        EnumMatching(_, v, _) => (v.node.name, v.node.data.is_struct()),
        EnumNonMatchingCollapsed(..) |
        StaticStruct(..) |
        StaticEnum(..) => cx.span_bug(span, "nonsensical .fields in `#[derive(Debug)]`"),
    };

    // We want to make sure we have the expn_id set so that we can use unstable methods
    let span = Span { expn_id: cx.backtrace(), ..span };
    let name = cx.expr_lit(span,
                           ast::LitKind::Str(ident.name.as_str(), ast::StrStyle::Cooked));
    let builder = token::str_to_ident("builder");
    let builder_expr = cx.expr_ident(span, builder.clone());

    let fmt = substr.nonself_args[0].clone();

    let mut stmts = match *substr.fields {
        Struct(_, ref fields) |
        EnumMatching(_, _, ref fields) => {
            let mut stmts = vec![];
            if !is_struct {
                // tuple struct/"normal" variant
                let expr =
                    cx.expr_method_call(span, fmt, token::str_to_ident("debug_tuple"), vec![name]);
                stmts.push(cx.stmt_let(DUMMY_SP, true, builder, expr));

                for field in fields {
                    // Use double indirection to make sure this works for unsized types
                    let field = cx.expr_addr_of(field.span, field.self_.clone());
                    let field = cx.expr_addr_of(field.span, field);

                    let expr = cx.expr_method_call(span,
                                                   builder_expr.clone(),
                                                   token::str_to_ident("field"),
                                                   vec![field]);

                    // Use `let _ = expr;` to avoid triggering the
                    // unused_results lint.
                    stmts.push(stmt_let_undescore(cx, span, expr));
                }
            } else {
                // normal struct/struct variant
                let expr =
                    cx.expr_method_call(span, fmt, token::str_to_ident("debug_struct"), vec![name]);
                stmts.push(cx.stmt_let(DUMMY_SP, true, builder, expr));

                for field in fields {
                    let name = cx.expr_lit(field.span,
                                           ast::LitKind::Str(field.name.unwrap().name.as_str(),
                                                             ast::StrStyle::Cooked));

                    // Use double indirection to make sure this works for unsized types
                    let field = cx.expr_addr_of(field.span, field.self_.clone());
                    let field = cx.expr_addr_of(field.span, field);
                    let expr = cx.expr_method_call(span,
                                                   builder_expr.clone(),
                                                   token::str_to_ident("field"),
                                                   vec![name, field]);
                    stmts.push(stmt_let_undescore(cx, span, expr));
                }
            }
            stmts
        }
        _ => unreachable!(),
    };

    let expr = cx.expr_method_call(span, builder_expr, token::str_to_ident("finish"), vec![]);

    stmts.push(cx.stmt_expr(expr));
    let block = cx.block(span, stmts);
    cx.expr_block(block)
}
/// We use the debug builders to do the heavy lifting here
We use the debug builders to do the heavy lifting here
We use the debug builders to do the heavy lifting here
fn show_substructure(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<Expr> {
    // build fmt.debug_struct(<name>).field(<fieldname>, &<fieldval>)....build()
    // or fmt.debug_tuple(<name>).field(&<fieldval>)....build()
    // based on the "shape".
    let (ident, is_struct) = match *substr.fields {
        Struct(vdata, _) => (substr.type_ident, vdata.is_struct()),
        EnumMatching(_, v, _) => (v.node.name, v.node.data.is_struct()),
        EnumNonMatchingCollapsed(..) |
        StaticStruct(..) |
        StaticEnum(..) => cx.span_bug(span, "nonsensical .fields in `#[derive(Debug)]`"),
    };
    // We want to make sure we have the expn_id set so that we can use unstable methods
    let span = Span { expn_id: cx.backtrace(), ..span };
    let name = cx.expr_lit(span,
                           ast::LitKind::Str(ident.name.as_str(), ast::StrStyle::Cooked));
    let builder = token::str_to_ident("builder");
    let builder_expr = cx.expr_ident(span, builder.clone());
    let fmt = substr.nonself_args[0].clone();
    let mut stmts = match *substr.fields {
        Struct(_, ref fields) |
        EnumMatching(_, _, ref fields) => {
            let mut stmts = vec![];
            if !is_struct {
                // tuple struct/"normal" variant
                let expr =
                    cx.expr_method_call(span, fmt, token::str_to_ident("debug_tuple"), vec![name]);
                stmts.push(cx.stmt_let(DUMMY_SP, true, builder, expr));
                for field in fields {
                    // Use double indirection to make sure this works for unsized types
                    let field = cx.expr_addr_of(field.span, field.self_.clone());
                    let field = cx.expr_addr_of(field.span, field);
                    let expr = cx.expr_method_call(span,
                                                   builder_expr.clone(),
                                                   token::str_to_ident("field"),
                                                   vec![field]);
                    // Use `let _ = expr;` to avoid triggering the
                    // unused_results lint.
                    stmts.push(stmt_let_undescore(cx, span, expr));
                }
            } else {
                // normal struct/struct variant
                let expr =
                    cx.expr_method_call(span, fmt, token::str_to_ident("debug_struct"), vec![name]);
                stmts.push(cx.stmt_let(DUMMY_SP, true, builder, expr));
                for field in fields {
                    let name = cx.expr_lit(field.span,
                                           ast::LitKind::Str(field.name.unwrap().name.as_str(),
                                                             ast::StrStyle::Cooked));
                    // Use double indirection to make sure this works for unsized types
                    let field = cx.expr_addr_of(field.span, field.self_.clone());
                    let field = cx.expr_addr_of(field.span, field);
                    let expr = cx.expr_method_call(span,
                                                   builder_expr.clone(),
                                                   token::str_to_ident("field"),
                                                   vec![name, field]);
                    stmts.push(stmt_let_undescore(cx, span, expr));
                }
            }
            stmts
        }
        _ => unreachable!(),
    };
    let expr = cx.expr_method_call(span, builder_expr, token::str_to_ident("finish"), vec![]);
    stmts.push(cx.stmt_expr(expr));
    let block = cx.block(span, stmts);
    cx.expr_block(block)
}
fn show_substructure ( cx : & mut ExtCtxt , span : Span , substr : & Substructure ) -> P < Expr > { // build fmt.debug_struct(<name>).field(<fieldname>, &<fieldval>)....build() // or fmt.debug_tuple(<name>).field(&<fieldval>)....build() // based on the "shape". let ( ident , is_struct ) = match * substr . fields { Struct ( vdata , _ ) => ( substr . type_ident , vdata . is_struct ( ) ) , EnumMatching ( _ , v , _ ) => ( v . node . name , v . node . data . is_struct ( ) ) , EnumNonMatchingCollapsed ( .. ) | StaticStruct ( .. ) | StaticEnum ( .. ) => cx . span_bug ( span , " " ) , } ; // We want to make sure we have the expn_id set so that we can use unstable methods let span = Span { expn_id : cx . backtrace ( ) , .. span } ; let name = cx . expr_lit ( span , ast :: LitKind :: Str ( ident . name . as_str ( ) , ast :: StrStyle :: Cooked ) ) ; let builder = token :: str_to_ident ( " " ) ; let builder_expr = cx . expr_ident ( span , builder . clone ( ) ) ; let fmt = substr . nonself_args [ 0 ] . clone ( ) ; let mut stmts = match * substr . fields { Struct ( _ , ref fields ) | EnumMatching ( _ , _ , ref fields ) => { let mut stmts = vec ! [ ] ; if ! is_struct { // tuple struct/"normal" variant let expr = cx . expr_method_call ( span , fmt , token :: str_to_ident ( " " ) , vec ! [ name ] ) ; stmts . push ( cx . stmt_let ( DUMMY_SP , true , builder , expr ) ) ; for field in fields { // Use double indirection to make sure this works for unsized types let field = cx . expr_addr_of ( field . span , field . self_ . clone ( ) ) ; let field = cx . expr_addr_of ( field . span , field ) ; let expr = cx . expr_method_call ( span , builder_expr . clone ( ) , token :: str_to_ident ( " " ) , vec ! [ field ] ) ; // Use `let _ = expr;` to avoid triggering the // unused_results lint. stmts . push ( stmt_let_undescore ( cx , span , expr ) ) ; } } else { // normal struct/struct variant let expr = cx . expr_method_call ( span , fmt , token :: str_to_ident ( " " ) , vec ! [ name ] ) ; stmts . push ( cx . stmt_let ( DUMMY_SP , true , builder , expr ) ) ; for field in fields { let name = cx . expr_lit ( field . span , ast :: LitKind :: Str ( field . name . unwrap ( ) . name . as_str ( ) , ast :: StrStyle :: Cooked ) ) ; // Use double indirection to make sure this works for unsized types let field = cx . expr_addr_of ( field . span , field . self_ . clone ( ) ) ; let field = cx . expr_addr_of ( field . span , field ) ; let expr = cx . expr_method_call ( span , builder_expr . clone ( ) , token :: str_to_ident ( " " ) , vec ! [ name field ] ) ; stmts . push ( stmt_let_undescore ( cx , span , expr ) ) ; } } stmts } _ => unreachable ! ( ) , } ; let expr = cx . expr_method_call ( span , builder_expr , token :: str_to_ident ( " " ) , vec ! [ ] ) ; stmts . push ( cx . stmt_expr ( expr ) ) ; let block = cx . block ( span , stmts ) ; cx . expr_block ( block ) }
We use the debug builders to do the heavy lifting here
We use the debug builders to do the heavy lifting here
cx
&mut ExtCtxt
span
Span
substr
&Substructure
cx
&mut ExtCtxt
span
Span
substr
&Substructure