Skip to content

Commit bd6ed22

Browse files
committed
Switch derive(Debug) to use the debug builders
1 parent 8121cf0 commit bd6ed22

File tree

5 files changed

+74
-64
lines changed

5 files changed

+74
-64
lines changed

src/libcore/fmt/builders.rs

+18
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
111
use prelude::*;
212
use fmt::{self, Write, FlagV1};
313

@@ -69,6 +79,7 @@ impl<'a, 'b: 'a> DebugStruct<'a, 'b> {
6979
self
7080
}
7181

82+
#[inline(never)]
7283
fn field_inner(&mut self, name: &str, value: &fmt::Debug) {
7384
self.result = self.result.and_then(|_| {
7485
let prefix = if self.has_fields {
@@ -97,6 +108,7 @@ impl<'a, 'b: 'a> DebugStruct<'a, 'b> {
97108
self.result
98109
}
99110

111+
#[inline(never)]
100112
fn finish_inner(&mut self) {
101113
if self.has_fields {
102114
self.result = self.result.and_then(|_| {
@@ -142,6 +154,7 @@ impl<'a, 'b: 'a> DebugTuple<'a, 'b> {
142154
self
143155
}
144156

157+
#[inline(never)]
145158
fn field_inner(&mut self, value: &fmt::Debug) {
146159
self.result = self.result.and_then(|_| {
147160
let (prefix, space) = if self.has_fields {
@@ -170,6 +183,7 @@ impl<'a, 'b: 'a> DebugTuple<'a, 'b> {
170183
self.result
171184
}
172185

186+
#[inline(never)]
173187
fn finish_inner(&mut self) {
174188
if self.has_fields {
175189
self.result = self.result.and_then(|_| {
@@ -215,6 +229,7 @@ impl<'a, 'b: 'a> DebugSet<'a, 'b> {
215229
self
216230
}
217231

232+
#[inline(never)]
218233
fn entry_inner(&mut self, entry: &fmt::Debug) {
219234
self.result = self.result.and_then(|_| {
220235
let prefix = if self.has_fields {
@@ -243,6 +258,7 @@ impl<'a, 'b: 'a> DebugSet<'a, 'b> {
243258
self.result
244259
}
245260

261+
#[inline(never)]
246262
fn finish_inner(&mut self) {
247263
self.result = self.result.and_then(|_| {
248264
let end = match (self.has_fields, self.is_pretty()) {
@@ -287,6 +303,7 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> {
287303
self
288304
}
289305

306+
#[inline(never)]
290307
fn entry_inner(&mut self, key: &fmt::Debug, value: &fmt::Debug) {
291308
self.result = self.result.and_then(|_| {
292309
let prefix = if self.has_fields {
@@ -315,6 +332,7 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> {
315332
self.result
316333
}
317334

335+
#[inline(never)]
318336
fn finish_inner(&mut self) {
319337
self.result = self.result.and_then(|_| {
320338
let end = match (self.has_fields, self.is_pretty()) {

src/libcore/fmt/mod.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -644,6 +644,7 @@ impl<'a> Formatter<'a> {
644644
/// println!("{:?}", Foo { bar: 10, baz: "Hello World".to_string() });
645645
/// ```
646646
#[unstable(feature = "core", reason = "method was just created")]
647+
#[inline]
647648
pub fn debug_struct<'b>(&'b mut self, name: &str) -> DebugStruct<'b, 'a> {
648649
builders::debug_struct_new(self, name)
649650
}
@@ -671,6 +672,7 @@ impl<'a> Formatter<'a> {
671672
/// println!("{:?}", Foo(10, "Hello World".to_string()));
672673
/// ```
673674
#[unstable(feature = "core", reason = "method was just created")]
675+
#[inline]
674676
pub fn debug_tuple<'b>(&'b mut self, name: &str) -> DebugTuple<'b, 'a> {
675677
builders::debug_tuple_new(self, name)
676678
}
@@ -699,6 +701,7 @@ impl<'a> Formatter<'a> {
699701
/// println!("{:?}", Foo(vec![10, 11]));
700702
/// ```
701703
#[unstable(feature = "core", reason = "method was just created")]
704+
#[inline]
702705
pub fn debug_set<'b>(&'b mut self, name: &str) -> DebugSet<'b, 'a> {
703706
builders::debug_set_new(self, name)
704707
}
@@ -724,9 +727,10 @@ impl<'a> Formatter<'a> {
724727
/// }
725728
///
726729
/// // prints "Foo { "A": 10, "B": 11 }"
727-
/// println!("{:?}", Foo(vec![("A".to_string(), 10), ("B".to_string(), 11)));
730+
/// println!("{:?}", Foo(vec![("A".to_string(), 10), ("B".to_string(), 11)]));
728731
/// ```
729732
#[unstable(feature = "core", reason = "method was just created")]
733+
#[inline]
730734
pub fn debug_map<'b>(&'b mut self, name: &str) -> DebugMap<'b, 'a> {
731735
builders::debug_map_new(self, name)
732736
}

src/libcoretest/fmt/builders.rs

+10
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
111
mod debug_struct {
212
use std::fmt;
313

src/libsyntax/ext/deriving/show.rs

+40-62
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,13 @@
1111
use ast;
1212
use ast::{MetaItem, Item, Expr,};
1313
use codemap::Span;
14-
use ext::format;
1514
use ext::base::ExtCtxt;
1615
use ext::build::AstBuilder;
1716
use ext::deriving::generic::*;
1817
use ext::deriving::generic::ty::*;
1918
use parse::token;
2019
use ptr::P;
2120

22-
use std::collections::HashMap;
23-
2421
pub fn expand_deriving_show<F>(cx: &mut ExtCtxt,
2522
span: Span,
2623
mitem: &MetaItem,
@@ -56,14 +53,12 @@ pub fn expand_deriving_show<F>(cx: &mut ExtCtxt,
5653
trait_def.expand(cx, mitem, item, push)
5754
}
5855

59-
/// We construct a format string and then defer to std::fmt, since that
60-
/// knows what's up with formatting and so on.
56+
/// We use the debug builders to do the heavy lifting here
6157
fn show_substructure(cx: &mut ExtCtxt, span: Span,
6258
substr: &Substructure) -> P<Expr> {
63-
// build `<name>`, `<name>({}, {}, ...)` or `<name> { <field>: {},
64-
// <field>: {}, ... }` based on the "shape".
65-
//
66-
// Easy start: they all start with the name.
59+
// build fmt.debug_struct(<name>).field(<fieldname>, &<fieldval>)....build()
60+
// or fmt.debug_tuple(<name>).field(&<fieldval>)....build()
61+
// based on the "shape".
6762
let name = match *substr.fields {
6863
Struct(_) => substr.type_ident,
6964
EnumMatching(_, v, _) => v.node.name,
@@ -72,70 +67,53 @@ fn show_substructure(cx: &mut ExtCtxt, span: Span,
7267
}
7368
};
7469

75-
let mut format_string = String::from_str(&token::get_ident(name));
76-
// the internal fields we're actually formatting
77-
let mut exprs = Vec::new();
70+
// We want to make sure we have the expn_id set so that we can use unstable methods
71+
let span = Span { expn_id: cx.backtrace(), .. span };
72+
let name = cx.expr_lit(span, ast::Lit_::LitStr(token::get_ident(name),
73+
ast::StrStyle::CookedStr));
74+
let mut expr = substr.nonself_args[0].clone();
7875

79-
// Getting harder... making the format string:
8076
match *substr.fields {
81-
// unit struct/nullary variant: no work necessary!
82-
Struct(ref fields) if fields.len() == 0 => {}
83-
EnumMatching(_, _, ref fields) if fields.len() == 0 => {}
84-
8577
Struct(ref fields) | EnumMatching(_, _, ref fields) => {
86-
if fields[0].name.is_none() {
78+
if fields.is_empty() || fields[0].name.is_none() {
8779
// tuple struct/"normal" variant
88-
89-
format_string.push_str("(");
90-
91-
for (i, field) in fields.iter().enumerate() {
92-
if i != 0 { format_string.push_str(", "); }
93-
94-
format_string.push_str("{:?}");
95-
96-
exprs.push(field.self_.clone());
80+
expr = cx.expr_method_call(span,
81+
expr,
82+
token::str_to_ident("debug_tuple"),
83+
vec![name]);
84+
85+
for field in fields {
86+
expr = cx.expr_method_call(span,
87+
expr,
88+
token::str_to_ident("field"),
89+
vec![cx.expr_addr_of(field.span,
90+
field.self_.clone())]);
9791
}
98-
99-
format_string.push_str(")");
10092
} else {
10193
// normal struct/struct variant
102-
103-
format_string.push_str(" {{");
104-
105-
for (i, field) in fields.iter().enumerate() {
106-
if i != 0 { format_string.push_str(","); }
107-
108-
let name = token::get_ident(field.name.unwrap());
109-
format_string.push_str(" ");
110-
format_string.push_str(&name);
111-
format_string.push_str(": {:?}");
112-
113-
exprs.push(field.self_.clone());
94+
expr = cx.expr_method_call(span,
95+
expr,
96+
token::str_to_ident("debug_struct"),
97+
vec![name]);
98+
99+
for field in fields {
100+
let name = cx.expr_lit(field.span, ast::Lit_::LitStr(
101+
token::get_ident(field.name.clone().unwrap()),
102+
ast::StrStyle::CookedStr));
103+
expr = cx.expr_method_call(span,
104+
expr,
105+
token::str_to_ident("field"),
106+
vec![name,
107+
cx.expr_addr_of(field.span,
108+
field.self_.clone())]);
114109
}
115-
116-
format_string.push_str(" }}");
117110
}
118111
}
119112
_ => unreachable!()
120113
}
121114

122-
// AST construction!
123-
// we're basically calling
124-
//
125-
// format_arg_method!(fmt, write_fmt, "<format_string>", exprs...)
126-
//
127-
// but doing it directly via ext::format.
128-
let formatter = substr.nonself_args[0].clone();
129-
130-
let meth = cx.ident_of("write_fmt");
131-
let s = token::intern_and_get_ident(&format_string[..]);
132-
let format_string = cx.expr_str(span, s);
133-
134-
// phew, not our responsibility any more!
135-
136-
let args = vec![
137-
format::expand_preparsed_format_args(cx, span, format_string,
138-
exprs, vec![], HashMap::new())
139-
];
140-
cx.expr_method_call(span, formatter, meth, args)
115+
cx.expr_method_call(span,
116+
expr,
117+
token::str_to_ident("finish"),
118+
vec![])
141119
}

src/libsyntax/ext/expand.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1121,7 +1121,7 @@ fn expand_annotatable(a: Annotatable,
11211121
callee: NameAndSpan {
11221122
name: mname.to_string(),
11231123
format: MacroAttribute,
1124-
span: None,
1124+
span: Some(attr.span),
11251125
// attributes can do whatever they like,
11261126
// for now.
11271127
allow_internal_unstable: true,

0 commit comments

Comments
 (0)