diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/libcore/fmt/builders.rs | 18 | ||||
| -rw-r--r-- | src/libcore/fmt/mod.rs | 6 | ||||
| -rw-r--r-- | src/libcoretest/fmt/builders.rs | 10 | ||||
| -rw-r--r-- | src/libsyntax/ext/deriving/show.rs | 102 | ||||
| -rw-r--r-- | src/libsyntax/ext/expand.rs | 2 |
5 files changed, 74 insertions, 64 deletions
diff --git a/src/libcore/fmt/builders.rs b/src/libcore/fmt/builders.rs index d96da4cafb0..37165cdc5ed 100644 --- a/src/libcore/fmt/builders.rs +++ b/src/libcore/fmt/builders.rs @@ -1,3 +1,13 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + use prelude::*; use fmt::{self, Write, FlagV1}; @@ -69,6 +79,7 @@ impl<'a, 'b: 'a> DebugStruct<'a, 'b> { self } + #[inline(never)] fn field_inner(&mut self, name: &str, value: &fmt::Debug) { self.result = self.result.and_then(|_| { let prefix = if self.has_fields { @@ -97,6 +108,7 @@ impl<'a, 'b: 'a> DebugStruct<'a, 'b> { self.result } + #[inline(never)] fn finish_inner(&mut self) { if self.has_fields { self.result = self.result.and_then(|_| { @@ -142,6 +154,7 @@ impl<'a, 'b: 'a> DebugTuple<'a, 'b> { self } + #[inline(never)] fn field_inner(&mut self, value: &fmt::Debug) { self.result = self.result.and_then(|_| { let (prefix, space) = if self.has_fields { @@ -170,6 +183,7 @@ impl<'a, 'b: 'a> DebugTuple<'a, 'b> { self.result } + #[inline(never)] fn finish_inner(&mut self) { if self.has_fields { self.result = self.result.and_then(|_| { @@ -215,6 +229,7 @@ impl<'a, 'b: 'a> DebugSet<'a, 'b> { self } + #[inline(never)] fn entry_inner(&mut self, entry: &fmt::Debug) { self.result = self.result.and_then(|_| { let prefix = if self.has_fields { @@ -243,6 +258,7 @@ impl<'a, 'b: 'a> DebugSet<'a, 'b> { self.result } + #[inline(never)] fn finish_inner(&mut self) { self.result = self.result.and_then(|_| { let end = match (self.has_fields, self.is_pretty()) { @@ -287,6 +303,7 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> { self } + #[inline(never)] fn entry_inner(&mut self, key: &fmt::Debug, value: &fmt::Debug) { self.result = self.result.and_then(|_| { let prefix = if self.has_fields { @@ -315,6 +332,7 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> { self.result } + #[inline(never)] fn finish_inner(&mut self) { self.result = self.result.and_then(|_| { let end = match (self.has_fields, self.is_pretty()) { diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index 572d613f192..741cf7b47fa 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -644,6 +644,7 @@ impl<'a> Formatter<'a> { /// println!("{:?}", Foo { bar: 10, baz: "Hello World".to_string() }); /// ``` #[unstable(feature = "core", reason = "method was just created")] + #[inline] pub fn debug_struct<'b>(&'b mut self, name: &str) -> DebugStruct<'b, 'a> { builders::debug_struct_new(self, name) } @@ -671,6 +672,7 @@ impl<'a> Formatter<'a> { /// println!("{:?}", Foo(10, "Hello World".to_string())); /// ``` #[unstable(feature = "core", reason = "method was just created")] + #[inline] pub fn debug_tuple<'b>(&'b mut self, name: &str) -> DebugTuple<'b, 'a> { builders::debug_tuple_new(self, name) } @@ -699,6 +701,7 @@ impl<'a> Formatter<'a> { /// println!("{:?}", Foo(vec![10, 11])); /// ``` #[unstable(feature = "core", reason = "method was just created")] + #[inline] pub fn debug_set<'b>(&'b mut self, name: &str) -> DebugSet<'b, 'a> { builders::debug_set_new(self, name) } @@ -724,9 +727,10 @@ impl<'a> Formatter<'a> { /// } /// /// // prints "Foo { "A": 10, "B": 11 }" - /// println!("{:?}", Foo(vec![("A".to_string(), 10), ("B".to_string(), 11))); + /// println!("{:?}", Foo(vec![("A".to_string(), 10), ("B".to_string(), 11)])); /// ``` #[unstable(feature = "core", reason = "method was just created")] + #[inline] pub fn debug_map<'b>(&'b mut self, name: &str) -> DebugMap<'b, 'a> { builders::debug_map_new(self, name) } diff --git a/src/libcoretest/fmt/builders.rs b/src/libcoretest/fmt/builders.rs index 84076b349d2..b2fbc90be59 100644 --- a/src/libcoretest/fmt/builders.rs +++ b/src/libcoretest/fmt/builders.rs @@ -1,3 +1,13 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + mod debug_struct { use std::fmt; diff --git a/src/libsyntax/ext/deriving/show.rs b/src/libsyntax/ext/deriving/show.rs index ce89c541fd4..ae9a4020060 100644 --- a/src/libsyntax/ext/deriving/show.rs +++ b/src/libsyntax/ext/deriving/show.rs @@ -11,7 +11,6 @@ use ast; use ast::{MetaItem, Item, Expr,}; use codemap::Span; -use ext::format; use ext::base::ExtCtxt; use ext::build::AstBuilder; use ext::deriving::generic::*; @@ -19,8 +18,6 @@ use ext::deriving::generic::ty::*; use parse::token; use ptr::P; -use std::collections::HashMap; - pub fn expand_deriving_show<F>(cx: &mut ExtCtxt, span: Span, mitem: &MetaItem, @@ -56,14 +53,12 @@ pub fn expand_deriving_show<F>(cx: &mut ExtCtxt, trait_def.expand(cx, mitem, item, push) } -/// We construct a format string and then defer to std::fmt, since that -/// knows what's up with formatting and so on. +/// We use the debug builders to do the heavy lifting here fn show_substructure(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<Expr> { - // build `<name>`, `<name>({}, {}, ...)` or `<name> { <field>: {}, - // <field>: {}, ... }` based on the "shape". - // - // Easy start: they all start with the name. + // build fmt.debug_struct(<name>).field(<fieldname>, &<fieldval>)....build() + // or fmt.debug_tuple(<name>).field(&<fieldval>)....build() + // based on the "shape". let name = match *substr.fields { Struct(_) => substr.type_ident, EnumMatching(_, v, _) => v.node.name, @@ -72,70 +67,53 @@ fn show_substructure(cx: &mut ExtCtxt, span: Span, } }; - let mut format_string = String::from_str(&token::get_ident(name)); - // the internal fields we're actually formatting - let mut exprs = Vec::new(); + // 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::Lit_::LitStr(token::get_ident(name), + ast::StrStyle::CookedStr)); + let mut expr = substr.nonself_args[0].clone(); - // Getting harder... making the format string: match *substr.fields { - // unit struct/nullary variant: no work necessary! - Struct(ref fields) if fields.len() == 0 => {} - EnumMatching(_, _, ref fields) if fields.len() == 0 => {} - Struct(ref fields) | EnumMatching(_, _, ref fields) => { - if fields[0].name.is_none() { + if fields.is_empty() || fields[0].name.is_none() { // tuple struct/"normal" variant - - format_string.push_str("("); - - for (i, field) in fields.iter().enumerate() { - if i != 0 { format_string.push_str(", "); } - - format_string.push_str("{:?}"); - - exprs.push(field.self_.clone()); + expr = cx.expr_method_call(span, + expr, + token::str_to_ident("debug_tuple"), + vec![name]); + + for field in fields { + expr = cx.expr_method_call(span, + expr, + token::str_to_ident("field"), + vec![cx.expr_addr_of(field.span, + field.self_.clone())]); } - - format_string.push_str(")"); } else { // normal struct/struct variant - - format_string.push_str(" {{"); - - for (i, field) in fields.iter().enumerate() { - if i != 0 { format_string.push_str(","); } - - let name = token::get_ident(field.name.unwrap()); - format_string.push_str(" "); - format_string.push_str(&name); - format_string.push_str(": {:?}"); - - exprs.push(field.self_.clone()); + expr = cx.expr_method_call(span, + expr, + token::str_to_ident("debug_struct"), + vec![name]); + + for field in fields { + let name = cx.expr_lit(field.span, ast::Lit_::LitStr( + token::get_ident(field.name.clone().unwrap()), + ast::StrStyle::CookedStr)); + expr = cx.expr_method_call(span, + expr, + token::str_to_ident("field"), + vec![name, + cx.expr_addr_of(field.span, + field.self_.clone())]); } - - format_string.push_str(" }}"); } } _ => unreachable!() } - // AST construction! - // we're basically calling - // - // format_arg_method!(fmt, write_fmt, "<format_string>", exprs...) - // - // but doing it directly via ext::format. - let formatter = substr.nonself_args[0].clone(); - - let meth = cx.ident_of("write_fmt"); - let s = token::intern_and_get_ident(&format_string[..]); - let format_string = cx.expr_str(span, s); - - // phew, not our responsibility any more! - - let args = vec![ - format::expand_preparsed_format_args(cx, span, format_string, - exprs, vec![], HashMap::new()) - ]; - cx.expr_method_call(span, formatter, meth, args) + cx.expr_method_call(span, + expr, + token::str_to_ident("finish"), + vec![]) } diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 98c7aefcd8a..6883395933e 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -1121,7 +1121,7 @@ fn expand_annotatable(a: Annotatable, callee: NameAndSpan { name: mname.to_string(), format: MacroAttribute, - span: None, + span: Some(attr.span), // attributes can do whatever they like, // for now. allow_internal_unstable: true, |
