Skip to content

Commit 22c7bbf

Browse files
committed
Delegate {} to Default instead of Poly
By using a separate trait this is overridable on a per-type basis and makes room for the possibility of even more arguments passed in for the future.
1 parent 1092744 commit 22c7bbf

File tree

4 files changed

+100
-29
lines changed

4 files changed

+100
-29
lines changed

src/libstd/fmt/mod.rs

+50
Original file line numberDiff line numberDiff line change
@@ -356,28 +356,46 @@ pub struct Argument<'self> {
356356
priv value: &'self util::Void,
357357
}
358358

359+
/// When a format is not otherwise specified, types are formatted by ascribing
360+
/// to this trait. There is not an explicit way of selecting this trait to be
361+
/// used for formatting, it is only if no other format is specified.
362+
#[allow(missing_doc)]
363+
pub trait Default { fn fmt(&Self, &mut Formatter); }
364+
365+
/// Format trait for the `b` character
359366
#[allow(missing_doc)]
360367
pub trait Bool { fn fmt(&Self, &mut Formatter); }
368+
/// Format trait for the `c` character
361369
#[allow(missing_doc)]
362370
pub trait Char { fn fmt(&Self, &mut Formatter); }
371+
/// Format trait for the `i` and `d` characters
363372
#[allow(missing_doc)]
364373
pub trait Signed { fn fmt(&Self, &mut Formatter); }
374+
/// Format trait for the `u` character
365375
#[allow(missing_doc)]
366376
pub trait Unsigned { fn fmt(&Self, &mut Formatter); }
377+
/// Format trait for the `o` character
367378
#[allow(missing_doc)]
368379
pub trait Octal { fn fmt(&Self, &mut Formatter); }
380+
/// Format trait for the `b` character
369381
#[allow(missing_doc)]
370382
pub trait Binary { fn fmt(&Self, &mut Formatter); }
383+
/// Format trait for the `x` character
371384
#[allow(missing_doc)]
372385
pub trait LowerHex { fn fmt(&Self, &mut Formatter); }
386+
/// Format trait for the `X` character
373387
#[allow(missing_doc)]
374388
pub trait UpperHex { fn fmt(&Self, &mut Formatter); }
389+
/// Format trait for the `s` character
375390
#[allow(missing_doc)]
376391
pub trait String { fn fmt(&Self, &mut Formatter); }
392+
/// Format trait for the `?` character
377393
#[allow(missing_doc)]
378394
pub trait Poly { fn fmt(&Self, &mut Formatter); }
395+
/// Format trait for the `p` character
379396
#[allow(missing_doc)]
380397
pub trait Pointer { fn fmt(&Self, &mut Formatter); }
398+
/// Format trait for the `f` character
381399
#[allow(missing_doc)]
382400
pub trait Float { fn fmt(&Self, &mut Formatter); }
383401

@@ -855,5 +873,37 @@ impl<T> Pointer for *const T {
855873
}
856874
}
857875

876+
// Implementation of Default for various core types
877+
878+
macro_rules! delegate(($ty:ty to $other:ident) => {
879+
impl<'self> Default for $ty {
880+
fn fmt(me: &$ty, f: &mut Formatter) {
881+
$other::fmt(me, f)
882+
}
883+
}
884+
})
885+
delegate!(int to Signed)
886+
delegate!( i8 to Signed)
887+
delegate!(i16 to Signed)
888+
delegate!(i32 to Signed)
889+
delegate!(i64 to Signed)
890+
delegate!(uint to Unsigned)
891+
delegate!( u8 to Unsigned)
892+
delegate!( u16 to Unsigned)
893+
delegate!( u32 to Unsigned)
894+
delegate!( u64 to Unsigned)
895+
delegate!(@str to String)
896+
delegate!(~str to String)
897+
delegate!(&'self str to String)
898+
delegate!(bool to Bool)
899+
delegate!(char to Char)
900+
delegate!(float to Float)
901+
delegate!(f32 to Float)
902+
delegate!(f64 to Float)
903+
904+
impl<T> Default for *const T {
905+
fn fmt(me: &*const T, f: &mut Formatter) { Pointer::fmt(me, f) }
906+
}
907+
858908
// If you expected tests to be here, look instead at the run-pass/ifmt.rs test,
859909
// it's a lot easier than creating all of the rt::Piece structures here.

src/libstd/fmt/parse.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -339,7 +339,11 @@ impl<'self> Parser<'self> {
339339
}
340340
}
341341
// Finally the actual format specifier
342-
spec.ty = self.word();
342+
if self.consume('?') {
343+
spec.ty = "?";
344+
} else {
345+
spec.ty = self.word();
346+
}
343347
return spec;
344348
}
345349

src/libsyntax/ext/ifmt.rs

+20-23
Original file line numberDiff line numberDiff line change
@@ -623,19 +623,16 @@ impl Context {
623623

624624
fn format_arg(&self, sp: span, arg: Either<uint, @str>,
625625
ident: ast::ident) -> @ast::expr {
626-
let mut ty = match arg {
626+
let ty = match arg {
627627
Left(i) => self.arg_types[i].unwrap(),
628628
Right(s) => *self.name_types.get(&s)
629629
};
630-
// Default types to '?' if nothing else is specified.
631-
if ty == Unknown {
632-
ty = Known(@"?");
633-
}
634630

635631
let argptr = self.ecx.expr_addr_of(sp, self.ecx.expr_ident(sp, ident));
636-
match ty {
632+
let fmt_trait = match ty {
633+
Unknown => "Default",
637634
Known(tyname) => {
638-
let fmt_trait = match tyname.as_slice() {
635+
match tyname.as_slice() {
639636
"?" => "Poly",
640637
"b" => "Bool",
641638
"c" => "Char",
@@ -653,35 +650,35 @@ impl Context {
653650
`%s`", tyname));
654651
"Dummy"
655652
}
656-
};
657-
let format_fn = self.ecx.path_global(sp, ~[
658-
self.ecx.ident_of("std"),
659-
self.ecx.ident_of("fmt"),
660-
self.ecx.ident_of(fmt_trait),
661-
self.ecx.ident_of("fmt"),
662-
]);
663-
self.ecx.expr_call_global(sp, ~[
664-
self.ecx.ident_of("std"),
665-
self.ecx.ident_of("fmt"),
666-
self.ecx.ident_of("argument"),
667-
], ~[self.ecx.expr_path(format_fn), argptr])
653+
}
668654
}
669655
String => {
670-
self.ecx.expr_call_global(sp, ~[
656+
return self.ecx.expr_call_global(sp, ~[
671657
self.ecx.ident_of("std"),
672658
self.ecx.ident_of("fmt"),
673659
self.ecx.ident_of("argumentstr"),
674660
], ~[argptr])
675661
}
676662
Unsigned => {
677-
self.ecx.expr_call_global(sp, ~[
663+
return self.ecx.expr_call_global(sp, ~[
678664
self.ecx.ident_of("std"),
679665
self.ecx.ident_of("fmt"),
680666
self.ecx.ident_of("argumentuint"),
681667
], ~[argptr])
682668
}
683-
Unknown => { fail!() }
684-
}
669+
};
670+
671+
let format_fn = self.ecx.path_global(sp, ~[
672+
self.ecx.ident_of("std"),
673+
self.ecx.ident_of("fmt"),
674+
self.ecx.ident_of(fmt_trait),
675+
self.ecx.ident_of("fmt"),
676+
]);
677+
self.ecx.expr_call_global(sp, ~[
678+
self.ecx.ident_of("std"),
679+
self.ecx.ident_of("fmt"),
680+
self.ecx.ident_of("argument"),
681+
], ~[self.ecx.expr_path(format_fn), argptr])
685682
}
686683
}
687684

src/test/run-pass/ifmt.rs

+25-5
Original file line numberDiff line numberDiff line change
@@ -25,16 +25,36 @@ pub fn main() {
2525
macro_rules! t(($a:expr, $b:expr) => { assert_eq!($a, $b.to_owned()) })
2626

2727
// Make sure there's a poly formatter that takes anything
28-
t!(ifmt!("{}", 1), "1");
29-
t!(ifmt!("{}", A), "{}");
30-
t!(ifmt!("{}", ()), "()");
31-
t!(ifmt!("{}", @(~1, "foo")), "@(~1, \"foo\")");
28+
t!(ifmt!("{:?}", 1), "1");
29+
t!(ifmt!("{:?}", A), "{}");
30+
t!(ifmt!("{:?}", ()), "()");
31+
t!(ifmt!("{:?}", @(~1, "foo")), "@(~1, \"foo\")");
3232

3333
// Various edge cases without formats
3434
t!(ifmt!(""), "");
3535
t!(ifmt!("hello"), "hello");
3636
t!(ifmt!("hello \\{"), "hello {");
3737

38+
// default formatters should work
39+
t!(ifmt!("{}", 1i), "1");
40+
t!(ifmt!("{}", 1i8), "1");
41+
t!(ifmt!("{}", 1i16), "1");
42+
t!(ifmt!("{}", 1i32), "1");
43+
t!(ifmt!("{}", 1i64), "1");
44+
t!(ifmt!("{}", 1u), "1");
45+
t!(ifmt!("{}", 1u8), "1");
46+
t!(ifmt!("{}", 1u16), "1");
47+
t!(ifmt!("{}", 1u32), "1");
48+
t!(ifmt!("{}", 1u64), "1");
49+
t!(ifmt!("{}", 1.0f), "1");
50+
t!(ifmt!("{}", 1.0f32), "1");
51+
t!(ifmt!("{}", 1.0f64), "1");
52+
t!(ifmt!("{}", "a"), "a");
53+
t!(ifmt!("{}", ~"a"), "a");
54+
t!(ifmt!("{}", @"a"), "a");
55+
t!(ifmt!("{}", false), "false");
56+
t!(ifmt!("{}", 'a'), "a");
57+
3858
// At least exercise all the formats
3959
t!(ifmt!("{:b}", true), "true");
4060
t!(ifmt!("{:c}", '☃'), "☃");
@@ -56,7 +76,7 @@ pub fn main() {
5676
t!(ifmt!("{foo} {bar}", foo=0, bar=1), "0 1");
5777
t!(ifmt!("{foo} {1} {bar} {0}", 0, 1, foo=2, bar=3), "2 1 3 0");
5878
t!(ifmt!("{} {0:s}", "a"), "a a");
59-
t!(ifmt!("{} {0}", "a"), "\"a\" \"a\"");
79+
t!(ifmt!("{} {0}", "a"), "a a");
6080

6181
// Methods should probably work
6282
t!(ifmt!("{0, plural, =1{a#} =2{b#} zero{c#} other{d#}}", 0u), "c0");

0 commit comments

Comments
 (0)