std: Remove i18n/l10n from format!

* The select/plural methods from format strings are removed
* The # character no longer needs to be escaped
* The \-based escapes have been removed
* '{{' is now an escape for '{'
* '}}' is now an escape for '}'

Closes #14810
[breaking-change]
This commit is contained in:
Alex Crichton 2014-05-28 09:24:28 -07:00
parent f9260d41d6
commit cac7a2053a
57 changed files with 736 additions and 1087 deletions

View File

@ -842,6 +842,7 @@ impl cmp::PartialEq for BitvSet {
}
impl fmt::Show for BitvSet {
#[cfg(stage0)]
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
try!(write!(fmt, r"\{"));
let mut first = true;
@ -854,6 +855,19 @@ impl fmt::Show for BitvSet {
}
write!(fmt, r"\}")
}
#[cfg(not(stage0))]
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
try!(write!(fmt, "{{"));
let mut first = true;
for n in self.iter() {
if !first {
try!(write!(fmt, ", "));
}
try!(write!(fmt, "{}", n));
first = false;
}
write!(fmt, "}}")
}
}
impl<S: hash::Writer> hash::Hash<S> for BitvSet {

View File

@ -185,6 +185,7 @@ impl<V:Clone> SmallIntMap<V> {
}
impl<V: fmt::Show> fmt::Show for SmallIntMap<V> {
#[cfg(stage0)]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
try!(write!(f, r"\{"));
@ -195,6 +196,17 @@ impl<V: fmt::Show> fmt::Show for SmallIntMap<V> {
write!(f, r"\}")
}
#[cfg(not(stage0))]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
try!(write!(f, "{{"));
for (i, (k, v)) in self.iter().enumerate() {
if i != 0 { try!(write!(f, ", ")); }
try!(write!(f, "{}: {}", k, *v));
}
write!(f, "}}")
}
}
macro_rules! iterator {

View File

@ -76,6 +76,7 @@ impl<K: PartialOrd + Ord, V: PartialOrd> PartialOrd for TreeMap<K, V> {
}
impl<K: Ord + Show, V: Show> Show for TreeMap<K, V> {
#[cfg(stage0)]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
try!(write!(f, r"\{"));
@ -86,6 +87,17 @@ impl<K: Ord + Show, V: Show> Show for TreeMap<K, V> {
write!(f, r"\}")
}
#[cfg(not(stage0))]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
try!(write!(f, "{{"));
for (i, (k, v)) in self.iter().enumerate() {
if i != 0 { try!(write!(f, ", ")); }
try!(write!(f, "{}: {}", *k, *v));
}
write!(f, "}}")
}
}
impl<K: Ord, V> Collection for TreeMap<K, V> {
@ -574,6 +586,7 @@ impl<T: PartialOrd + Ord> PartialOrd for TreeSet<T> {
}
impl<T: Ord + Show> Show for TreeSet<T> {
#[cfg(stage0)]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
try!(write!(f, r"\{"));
@ -584,6 +597,17 @@ impl<T: Ord + Show> Show for TreeSet<T> {
write!(f, r"\}")
}
#[cfg(not(stage0))]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
try!(write!(f, "{{"));
for (i, x) in self.iter().enumerate() {
if i != 0 { try!(write!(f, ", ")); }
try!(write!(f, "{}", *x));
}
write!(f, "}}")
}
}
impl<T: Ord> Collection for TreeSet<T> {

View File

@ -97,12 +97,6 @@ pub struct Formatter<'a> {
args: &'a [Argument<'a>],
}
enum CurrentlyFormatting<'a> {
Nothing,
RawString(&'a str),
Number(uint),
}
/// This struct represents the generic "argument" which is taken by the Xprintf
/// family of functions. It contains a function to format the given value. At
/// compile time it is ensured that the function and the value have the correct
@ -279,7 +273,7 @@ pub fn write(output: &mut FormatWriter, args: &Arguments) -> Result {
curarg: args.args.iter(),
};
for piece in args.fmt.iter() {
try!(formatter.run(piece, Nothing));
try!(formatter.run(piece));
}
Ok(())
}
@ -290,16 +284,9 @@ impl<'a> Formatter<'a> {
// at runtime. This consumes all of the compile-time statics generated by
// the format! syntax extension.
fn run(&mut self, piece: &rt::Piece, cur: CurrentlyFormatting) -> Result {
fn run(&mut self, piece: &rt::Piece) -> Result {
match *piece {
rt::String(s) => self.buf.write(s.as_bytes()),
rt::CurrentArgument(()) => {
match cur {
Nothing => Ok(()),
Number(n) => secret_show(&radix(n, 10), self),
RawString(s) => self.buf.write(s.as_bytes()),
}
}
rt::Argument(ref arg) => {
// Fill in the format parameters into the formatter
self.fill = arg.format.fill;
@ -315,10 +302,7 @@ impl<'a> Formatter<'a> {
};
// Then actually do some printing
match arg.method {
None => (value.formatter)(value.value, self),
Some(ref method) => self.execute(*method, value)
}
(value.formatter)(value.value, self)
}
}
}
@ -338,82 +322,6 @@ impl<'a> Formatter<'a> {
}
}
fn execute(&mut self, method: &rt::Method, arg: Argument) -> Result {
match *method {
// Pluralization is selection upon a numeric value specified as the
// parameter.
rt::Plural(offset, ref selectors, ref default) => {
// This is validated at compile-time to be a pointer to a
// '&uint' value.
let value: &uint = unsafe { mem::transmute(arg.value) };
let value = *value;
// First, attempt to match against explicit values without the
// offsetted value
for s in selectors.iter() {
match s.selector {
rt::Literal(val) if value == val => {
return self.runplural(value, s.result);
}
_ => {}
}
}
// Next, offset the value and attempt to match against the
// keyword selectors.
let value = value - match offset { Some(i) => i, None => 0 };
for s in selectors.iter() {
let run = match s.selector {
rt::Keyword(rt::Zero) => value == 0,
rt::Keyword(rt::One) => value == 1,
rt::Keyword(rt::Two) => value == 2,
// FIXME: Few/Many should have a user-specified boundary
// One possible option would be in the function
// pointer of the 'arg: Argument' struct.
rt::Keyword(rt::Few) => value < 8,
rt::Keyword(rt::Many) => value >= 8,
rt::Literal(..) => false
};
if run {
return self.runplural(value, s.result);
}
}
self.runplural(value, *default)
}
// Select is just a matching against the string specified.
rt::Select(ref selectors, ref default) => {
// This is validated at compile-time to be a pointer to a
// string slice,
let value: & &str = unsafe { mem::transmute(arg.value) };
let value = *value;
for s in selectors.iter() {
if s.selector == value {
for piece in s.result.iter() {
try!(self.run(piece, RawString(value)));
}
return Ok(());
}
}
for piece in default.iter() {
try!(self.run(piece, RawString(value)));
}
Ok(())
}
}
}
fn runplural(&mut self, value: uint, pieces: &[rt::Piece]) -> Result {
for piece in pieces.iter() {
try!(self.run(piece, Number(value)));
}
Ok(())
}
// Helper methods used for padding and processing formatting arguments that
// all formatting traits can use.
@ -841,9 +749,14 @@ impl Show for () {
}
impl<T: Copy + Show> Show for Cell<T> {
#[cfg(stage0)]
fn fmt(&self, f: &mut Formatter) -> Result {
write!(f, r"Cell \{ value: {} \}", self.get())
}
#[cfg(not(stage0))]
fn fmt(&self, f: &mut Formatter) -> Result {
write!(f, "Cell {{ value: {} }}", self.get())
}
}
// If you expected tests to be here, look instead at the run-pass/ifmt.rs test,

View File

@ -14,13 +14,13 @@
//! These definitions are similar to their `ct` equivalents, but differ in that
//! these can be statically allocated and are slightly optimized for the runtime
#[cfg(stage0)]
use option::Option;
#[doc(hidden)]
pub enum Piece<'a> {
String(&'a str),
// FIXME(#8259): this shouldn't require the unit-value here
CurrentArgument(()),
Argument(Argument<'a>),
}
@ -28,7 +28,8 @@ pub enum Piece<'a> {
pub struct Argument<'a> {
pub position: Position,
pub format: FormatSpec,
pub method: Option<&'a Method<'a>>
#[cfg(stage0)]
pub method: Option<uint>,
}
#[doc(hidden)]
@ -80,36 +81,3 @@ pub enum Flag {
/// being aware of the sign to be printed.
FlagSignAwareZeroPad,
}
#[doc(hidden)]
pub enum Method<'a> {
Plural(Option<uint>, &'a [PluralArm<'a>], &'a [Piece<'a>]),
Select(&'a [SelectArm<'a>], &'a [Piece<'a>]),
}
#[doc(hidden)]
pub enum PluralSelector {
Keyword(PluralKeyword),
Literal(uint),
}
#[doc(hidden)]
pub enum PluralKeyword {
Zero,
One,
Two,
Few,
Many,
}
#[doc(hidden)]
pub struct PluralArm<'a> {
pub selector: PluralSelector,
pub result: &'a [Piece<'a>],
}
#[doc(hidden)]
pub struct SelectArm<'a> {
pub selector: &'a str,
pub result: &'a [Piece<'a>],
}

View File

@ -30,9 +30,6 @@ use std::str;
pub enum Piece<'a> {
/// A literal string which should directly be emitted
String(&'a str),
/// A back-reference to whatever the current argument is. This is used
/// inside of a method call to refer back to the original argument.
CurrentArgument,
/// This describes that formatting should process the next argument (as
/// specified inside) for emission.
Argument(Argument<'a>),
@ -45,8 +42,6 @@ pub struct Argument<'a> {
pub position: Position<'a>,
/// How to format the argument
pub format: FormatSpec<'a>,
/// If not `None`, what method to invoke on the argument
pub method: Option<Box<Method<'a>>>
}
/// Specification for the formatting of an argument in the format string.
@ -122,76 +117,6 @@ pub enum Count<'a> {
CountImplied,
}
/// Enum describing all of the possible methods which the formatting language
/// currently supports.
#[deriving(PartialEq)]
pub enum Method<'a> {
/// A plural method selects on an integer over a list of either integer or
/// keyword-defined clauses. The meaning of the keywords is defined by the
/// current locale.
///
/// An offset is optionally present at the beginning which is used to
/// match against keywords, but it is not matched against the literal
/// integers.
///
/// The final element of this enum is the default "other" case which is
/// always required to be specified.
Plural(Option<uint>, Vec<PluralArm<'a>>, Vec<Piece<'a>>),
/// A select method selects over a string. Each arm is a different string
/// which can be selected for.
///
/// As with `Plural`, a default "other" case is required as well.
Select(Vec<SelectArm<'a>>, Vec<Piece<'a>>),
}
/// A selector for what pluralization a plural method should take
#[deriving(PartialEq, Eq, Hash)]
pub enum PluralSelector {
/// One of the plural keywords should be used
Keyword(PluralKeyword),
/// A literal pluralization should be used
Literal(uint),
}
/// Structure representing one "arm" of the `plural` function.
#[deriving(PartialEq)]
pub struct PluralArm<'a> {
/// A selector can either be specified by a keyword or with an integer
/// literal.
pub selector: PluralSelector,
/// Array of pieces which are the format of this arm
pub result: Vec<Piece<'a>>,
}
/// Enum of the 5 CLDR plural keywords. There is one more, "other", but that
/// is specially placed in the `Plural` variant of `Method`.
///
/// http://www.icu-project.org/apiref/icu4c/classicu_1_1PluralRules.html
#[deriving(PartialEq, Eq, Hash, Show)]
#[allow(missing_doc)]
pub enum PluralKeyword {
/// The plural form for zero objects.
Zero,
/// The plural form for one object.
One,
/// The plural form for two objects.
Two,
/// The plural form for few objects.
Few,
/// The plural form for many objects.
Many,
}
/// Structure representing one "arm" of the `select` function.
#[deriving(PartialEq)]
pub struct SelectArm<'a> {
/// String selector which guards this arm
pub selector: &'a str,
/// Array of pieces which are the format of this arm
pub result: Vec<Piece<'a>>,
}
/// The parser structure for interpreting the input format string. This is
/// modelled as an iterator over `Piece` structures to form a stream of tokens
/// being output.
@ -201,7 +126,6 @@ pub struct SelectArm<'a> {
pub struct Parser<'a> {
input: &'a str,
cur: str::CharOffsets<'a>,
depth: uint,
/// Error messages accumulated during parsing
pub errors: Vec<String>,
}
@ -209,27 +133,27 @@ pub struct Parser<'a> {
impl<'a> Iterator<Piece<'a>> for Parser<'a> {
fn next(&mut self) -> Option<Piece<'a>> {
match self.cur.clone().next() {
Some((_, '#')) => { self.cur.next(); Some(CurrentArgument) }
Some((_, '{')) => {
Some((pos, '{')) => {
self.cur.next();
let ret = Some(Argument(self.argument()));
self.must_consume('}');
ret
if self.consume('{') {
Some(String(self.string(pos + 1)))
} else {
let ret = Some(Argument(self.argument()));
self.must_consume('}');
ret
}
}
Some((pos, '\\')) => {
Some((pos, '}')) => {
self.cur.next();
self.escape(); // ensure it's a valid escape sequence
Some(String(self.string(pos + 1))) // skip the '\' character
}
Some((_, '}')) if self.depth == 0 => {
self.cur.next();
self.err("unmatched `}` found");
None
}
Some((_, '}')) | None => { None }
Some((pos, _)) => {
Some(String(self.string(pos)))
if self.consume('}') {
Some(String(self.string(pos + 1)))
} else {
self.err("unmatched `}` found");
None
}
}
Some((pos, _)) => { Some(String(self.string(pos))) }
None => None
}
}
}
@ -240,7 +164,6 @@ impl<'a> Parser<'a> {
Parser {
input: s,
cur: s.char_indices(),
depth: 0,
errors: vec!(),
}
}
@ -285,11 +208,6 @@ impl<'a> Parser<'a> {
}
}
/// Attempts to consume any amount of whitespace followed by a character
fn wsconsume(&mut self, c: char) -> bool {
self.ws(); self.consume(c)
}
/// Consumes all whitespace characters until the first non-whitespace
/// character
fn ws(&mut self) {
@ -301,32 +219,12 @@ impl<'a> Parser<'a> {
}
}
/// Consumes an escape sequence, failing if there is not a valid character
/// to be escaped.
fn escape(&mut self) -> char {
match self.cur.next() {
Some((_, c @ '#')) | Some((_, c @ '{')) |
Some((_, c @ '\\')) | Some((_, c @ '}')) => { c }
Some((_, c)) => {
self.err(format!("invalid escape character `{}`",
c).as_slice());
c
}
None => {
self.err("expected an escape sequence, but format string was \
terminated");
' '
}
}
}
/// Parses all of a string which is to be considered a "raw literal" in a
/// format string. This is everything outside of the braces.
fn string(&mut self, start: uint) -> &'a str {
loop {
// we may not consume the character, so clone the iterator
match self.cur.clone().next() {
Some((pos, '\\')) | Some((pos, '#')) |
Some((pos, '}')) | Some((pos, '{')) => {
return self.input.slice(start, pos);
}
@ -345,7 +243,6 @@ impl<'a> Parser<'a> {
Argument {
position: self.position(),
format: self.format(),
method: self.method(),
}
}
@ -440,173 +337,6 @@ impl<'a> Parser<'a> {
return spec;
}
/// Parses a method to be applied to the previously specified argument and
/// its format. The two current supported methods are 'plural' and 'select'
fn method(&mut self) -> Option<Box<Method<'a>>> {
if !self.wsconsume(',') {
return None;
}
self.ws();
match self.word() {
"select" => {
self.must_consume(',');
Some(self.select())
}
"plural" => {
self.must_consume(',');
Some(self.plural())
}
"" => {
self.err("expected method after comma");
return None;
}
method => {
self.err(format!("unknown method: `{}`", method).as_slice());
return None;
}
}
}
/// Parses a 'select' statement (after the initial 'select' word)
fn select(&mut self) -> Box<Method<'a>> {
let mut other = None;
let mut arms = vec!();
// Consume arms one at a time
loop {
self.ws();
let selector = self.word();
if selector == "" {
self.err("cannot have an empty selector");
break
}
self.must_consume('{');
self.depth += 1;
let pieces = self.collect();
self.depth -= 1;
self.must_consume('}');
if selector == "other" {
if !other.is_none() {
self.err("multiple `other` statements in `select");
}
other = Some(pieces);
} else {
arms.push(SelectArm { selector: selector, result: pieces });
}
self.ws();
match self.cur.clone().next() {
Some((_, '}')) => { break }
Some(..) | None => {}
}
}
// The "other" selector must be present
let other = match other {
Some(arm) => { arm }
None => {
self.err("`select` statement must provide an `other` case");
vec!()
}
};
box Select(arms, other)
}
/// Parses a 'plural' statement (after the initial 'plural' word)
fn plural(&mut self) -> Box<Method<'a>> {
let mut offset = None;
let mut other = None;
let mut arms = vec!();
// First, attempt to parse the 'offset:' field. We know the set of
// selector words which can appear in plural arms, and the only ones
// which start with 'o' are "other" and "offset", hence look two
// characters deep to see if we can consume the word "offset"
self.ws();
let mut it = self.cur.clone();
match it.next() {
Some((_, 'o')) => {
match it.next() {
Some((_, 'f')) => {
let word = self.word();
if word != "offset" {
self.err(format!("expected `offset`, found `{}`",
word).as_slice());
} else {
self.must_consume(':');
match self.integer() {
Some(i) => { offset = Some(i); }
None => {
self.err("offset must be an integer");
}
}
}
}
Some(..) | None => {}
}
}
Some(..) | None => {}
}
// Next, generate all the arms
loop {
let mut isother = false;
let selector = if self.wsconsume('=') {
match self.integer() {
Some(i) => Literal(i),
None => {
self.err("plural `=` selectors must be followed by an \
integer");
Literal(0)
}
}
} else {
let word = self.word();
match word {
"other" => { isother = true; Keyword(Zero) }
"zero" => Keyword(Zero),
"one" => Keyword(One),
"two" => Keyword(Two),
"few" => Keyword(Few),
"many" => Keyword(Many),
word => {
self.err(format!("unexpected plural selector `{}`",
word).as_slice());
if word == "" {
break
} else {
Keyword(Zero)
}
}
}
};
self.must_consume('{');
self.depth += 1;
let pieces = self.collect();
self.depth -= 1;
self.must_consume('}');
if isother {
if !other.is_none() {
self.err("multiple `other` statements in `select");
}
other = Some(pieces);
} else {
arms.push(PluralArm { selector: selector, result: pieces });
}
self.ws();
match self.cur.clone().next() {
Some((_, '}')) => { break }
Some(..) | None => {}
}
}
let other = match other {
Some(arm) => { arm }
None => {
self.err("`plural` statement must provide an `other` case");
vec!()
}
};
box Plural(offset, arms, other)
}
/// Parses a Count parameter at the current position. This does not check
/// for 'CountIsNextParam' because that is only used in precision, not
/// width.
@ -715,16 +445,15 @@ mod tests {
#[test]
fn simple() {
same("asdf", [String("asdf")]);
same("a\\{b", [String("a"), String("{b")]);
same("a\\#b", [String("a"), String("#b")]);
same("a\\}b", [String("a"), String("}b")]);
same("a\\}", [String("a"), String("}")]);
same("\\}", [String("}")]);
same("a{{b", [String("a"), String("{b")]);
same("a}}b", [String("a"), String("}b")]);
same("a}}", [String("a"), String("}")]);
same("}}", [String("}")]);
same("\\}}", [String("\\"), String("}")]);
}
#[test] fn invalid01() { musterr("{") }
#[test] fn invalid02() { musterr("\\") }
#[test] fn invalid03() { musterr("\\a") }
#[test] fn invalid02() { musterr("}") }
#[test] fn invalid04() { musterr("{3a}") }
#[test] fn invalid05() { musterr("{:|}") }
#[test] fn invalid06() { musterr("{:>>>}") }
@ -734,7 +463,6 @@ mod tests {
same("{}", [Argument(Argument {
position: ArgumentNext,
format: fmtdflt(),
method: None,
})]);
}
#[test]
@ -742,7 +470,6 @@ mod tests {
same("{3}", [Argument(Argument {
position: ArgumentIs(3),
format: fmtdflt(),
method: None,
})]);
}
#[test]
@ -750,7 +477,6 @@ mod tests {
same("{3:}", [Argument(Argument {
position: ArgumentIs(3),
format: fmtdflt(),
method: None,
})]);
}
#[test]
@ -765,7 +491,6 @@ mod tests {
width: CountImplied,
ty: "a",
},
method: None,
})]);
}
#[test]
@ -780,7 +505,6 @@ mod tests {
width: CountImplied,
ty: "",
},
method: None,
})]);
same("{3:0<}", [Argument(Argument {
position: ArgumentIs(3),
@ -792,7 +516,6 @@ mod tests {
width: CountImplied,
ty: "",
},
method: None,
})]);
same("{3:*<abcd}", [Argument(Argument {
position: ArgumentIs(3),
@ -804,7 +527,6 @@ mod tests {
width: CountImplied,
ty: "abcd",
},
method: None,
})]);
}
#[test]
@ -819,7 +541,6 @@ mod tests {
width: CountIs(10),
ty: "s",
},
method: None,
})]);
same("{:10$.10s}", [Argument(Argument {
position: ArgumentNext,
@ -831,7 +552,6 @@ mod tests {
width: CountIsParam(10),
ty: "s",
},
method: None,
})]);
same("{:.*s}", [Argument(Argument {
position: ArgumentNext,
@ -843,7 +563,6 @@ mod tests {
width: CountImplied,
ty: "s",
},
method: None,
})]);
same("{:.10$s}", [Argument(Argument {
position: ArgumentNext,
@ -855,7 +574,6 @@ mod tests {
width: CountImplied,
ty: "s",
},
method: None,
})]);
same("{:a$.b$s}", [Argument(Argument {
position: ArgumentNext,
@ -867,7 +585,6 @@ mod tests {
width: CountIsName("a"),
ty: "s",
},
method: None,
})]);
}
#[test]
@ -882,7 +599,6 @@ mod tests {
width: CountImplied,
ty: "",
},
method: None,
})]);
same("{:+#}", [Argument(Argument {
position: ArgumentNext,
@ -894,7 +610,6 @@ mod tests {
width: CountImplied,
ty: "",
},
method: None,
})]);
}
#[test]
@ -909,83 +624,6 @@ mod tests {
width: CountImplied,
ty: "a",
},
method: None,
}), String(" efg")]);
}
#[test]
fn select_simple() {
same("{, select, other { haha } }", [Argument(Argument{
position: ArgumentNext,
format: fmtdflt(),
method: Some(box Select(vec![], vec![String(" haha ")]))
})]);
same("{1, select, other { haha } }", [Argument(Argument{
position: ArgumentIs(1),
format: fmtdflt(),
method: Some(box Select(vec![], vec![String(" haha ")]))
})]);
same("{1, select, other {#} }", [Argument(Argument{
position: ArgumentIs(1),
format: fmtdflt(),
method: Some(box Select(vec![], vec![CurrentArgument]))
})]);
same("{1, select, other {{2, select, other {lol}}} }", [Argument(Argument{
position: ArgumentIs(1),
format: fmtdflt(),
method: Some(box Select(vec![], vec![Argument(Argument{
position: ArgumentIs(2),
format: fmtdflt(),
method: Some(box Select(vec![], vec![String("lol")]))
})])) // wat
})]);
}
#[test]
fn select_cases() {
same("{1, select, a{1} b{2} c{3} other{4} }", [Argument(Argument{
position: ArgumentIs(1),
format: fmtdflt(),
method: Some(box Select(vec![
SelectArm{ selector: "a", result: vec![String("1")] },
SelectArm{ selector: "b", result: vec![String("2")] },
SelectArm{ selector: "c", result: vec![String("3")] },
], vec![String("4")]))
})]);
}
#[test] fn badselect01() { musterr("{select, }") }
#[test] fn badselect02() { musterr("{1, select}") }
#[test] fn badselect03() { musterr("{1, select, }") }
#[test] fn badselect04() { musterr("{1, select, a {}}") }
#[test] fn badselect05() { musterr("{1, select, other }}") }
#[test] fn badselect06() { musterr("{1, select, other {}") }
#[test] fn badselect07() { musterr("{select, other {}") }
#[test] fn badselect08() { musterr("{1 select, other {}") }
#[test] fn badselect09() { musterr("{:d select, other {}") }
#[test] fn badselect10() { musterr("{1:d select, other {}") }
#[test]
fn plural_simple() {
same("{, plural, other { haha } }", [Argument(Argument{
position: ArgumentNext,
format: fmtdflt(),
method: Some(box Plural(None, vec![], vec![String(" haha ")]))
})]);
same("{:, plural, other { haha } }", [Argument(Argument{
position: ArgumentNext,
format: fmtdflt(),
method: Some(box Plural(None, vec![], vec![String(" haha ")]))
})]);
same("{, plural, offset:1 =2{2} =3{3} many{yes} other{haha} }",
[Argument(Argument{
position: ArgumentNext,
format: fmtdflt(),
method: Some(box Plural(Some(1), vec![
PluralArm{ selector: Literal(2), result: vec![String("2")] },
PluralArm{ selector: Literal(3), result: vec![String("3")] },
PluralArm{ selector: Keyword(Many), result: vec![String("yes")] }
], vec![String("haha")]))
})]);
}
}

View File

@ -634,9 +634,14 @@ impl<'a> Parser<'a> {
let closer =
match self.pos('}') {
Some(i) => i,
#[cfg(stage0)]
None => return self.err(format!(
"Missing '\\}' for unclosed '\\{' at position {}",
self.chari).as_slice()),
#[cfg(not(stage0))]
None => return self.err(format!(
"Missing '}}' for unclosed '{{' at position {}",
self.chari).as_slice()),
};
if closer - self.chari + 1 == 0 {
return self.err("No Unicode class name found.")
@ -695,11 +700,18 @@ impl<'a> Parser<'a> {
let start = self.chari + 2;
let closer =
match self.pos('}') {
#[cfg(stage0)]
None => {
return self.err(format!("Missing '\\}' for unclosed \
'\\{' at position {}",
start).as_slice())
}
#[cfg(not(stage0))]
None => {
return self.err(format!("Missing '}}' for unclosed \
'{{' at position {}",
start).as_slice())
}
Some(i) => i,
};
self.chari = closer;

View File

@ -108,6 +108,7 @@ struct Context<'a> {
}
impl<'a> Context<'a> {
#[cfg(stage0)]
fn gate_feature(&self, feature: &str, span: Span, explain: &str) {
if !self.has_feature(feature) {
self.sess.span_err(span, explain);
@ -116,6 +117,15 @@ impl<'a> Context<'a> {
feature).as_slice());
}
}
#[cfg(not(stage0))]
fn gate_feature(&self, feature: &str, span: Span, explain: &str) {
if !self.has_feature(feature) {
self.sess.span_err(span, explain);
self.sess.span_note(span, format!("add #![feature({})] to the \
crate attributes to enable",
feature).as_slice());
}
}
fn gate_box(&self, span: Span) {
self.gate_feature("managed_boxes", span,

View File

@ -63,12 +63,20 @@ struct StandardLibraryInjector<'a> {
pub fn with_version(krate: &str) -> Option<(InternedString, ast::StrStyle)> {
match option_env!("CFG_DISABLE_INJECT_STD_VERSION") {
Some("1") => None,
#[cfg(stage0)]
_ => {
Some((token::intern_and_get_ident(format!("{}\\#{}",
krate,
VERSION).as_slice()),
ast::CookedStr))
}
#[cfg(not(stage0))]
_ => {
Some((token::intern_and_get_ident(format!("{}#{}",
krate,
VERSION).as_slice()),
ast::CookedStr))
}
}
}

View File

@ -146,8 +146,8 @@ impl<'a> Context<'a> {
self.triple).as_slice());
for (i, &CrateMismatch{ ref path, ref got }) in mismatches.enumerate() {
self.sess.fileline_note(self.span,
format!("crate `{}` path \\#{}, triple {}: {}",
self.ident, i+1, got, path.display()).as_slice());
format!("crate `{}` path {}{}, triple {}: {}",
self.ident, "#", i+1, got, path.display()).as_slice());
}
}
if self.rejected_via_hash.len() > 0 {
@ -156,11 +156,12 @@ impl<'a> Context<'a> {
let mismatches = self.rejected_via_hash.iter();
for (i, &CrateMismatch{ ref path, .. }) in mismatches.enumerate() {
self.sess.fileline_note(self.span,
format!("crate `{}` path \\#{}: {}",
self.ident, i+1, path.display()).as_slice());
format!("crate `{}` path {}{}: {}",
self.ident, "#", i+1, path.display()).as_slice());
}
match self.root {
&None => {}
#[cfg(stage0)]
&Some(ref r) => {
for (i, path) in r.paths().iter().enumerate() {
self.sess.fileline_note(self.span,
@ -168,6 +169,14 @@ impl<'a> Context<'a> {
r.ident, i+1, path.display()).as_slice());
}
}
#[cfg(not(stage0))]
&Some(ref r) => {
for (i, path) in r.paths().iter().enumerate() {
self.sess.fileline_note(self.span,
format!("crate `{}` path #{}: {}",
r.ident, i+1, path.display()).as_slice());
}
}
}
}
self.sess.abort_if_errors();

View File

@ -47,6 +47,7 @@ pub struct ty_abbrev {
pub type abbrev_map = RefCell<HashMap<ty::t, ty_abbrev>>;
#[cfg(stage0)]
pub fn enc_ty(w: &mut MemWriter, cx: &ctxt, t: ty::t) {
match cx.abbrevs.borrow_mut().find(&t) {
Some(a) => { w.write(a.s.as_bytes()); return; }
@ -70,6 +71,30 @@ pub fn enc_ty(w: &mut MemWriter, cx: &ctxt, t: ty::t) {
});
}
}
#[cfg(not(stage0))]
pub fn enc_ty(w: &mut MemWriter, cx: &ctxt, t: ty::t) {
match cx.abbrevs.borrow_mut().find(&t) {
Some(a) => { w.write(a.s.as_bytes()); return; }
None => {}
}
let pos = w.tell().unwrap();
enc_sty(w, cx, &ty::get(t).sty);
let end = w.tell().unwrap();
let len = end - pos;
fn estimate_sz(u: u64) -> u64 {
let mut n = u;
let mut len = 0;
while n != 0 { len += 1; n = n >> 4; }
return len;
}
let abbrev_len = 3 + estimate_sz(pos) + estimate_sz(len);
if abbrev_len < len {
// I.e. it's actually an abbreviation.
cx.abbrevs.borrow_mut().insert(t, ty_abbrev {
s: format!("#{:x}:{:x}#", pos, len)
});
}
}
fn enc_mutability(w: &mut MemWriter, mt: ast::Mutability) {
match mt {

View File

@ -493,10 +493,16 @@ pub fn emit_lint(level: Level, src: LintSource, msg: &str, span: Span,
let mut note = None;
let msg = match src {
#[cfg(stage0)]
Default => {
format!("{}, \\#[{}({})] on by default", msg,
level_to_str(level), lint_str)
},
#[cfg(not(stage0))]
Default => {
format!("{}, #[{}({})] on by default", msg,
level_to_str(level), lint_str)
},
CommandLine => {
format!("{} [-{} {}]", msg,
match level {

View File

@ -1253,6 +1253,7 @@ impl cmt_ {
}
impl Repr for cmt_ {
#[cfg(stage0)]
fn repr(&self, tcx: &ty::ctxt) -> String {
format!("\\{{} id:{} m:{:?} ty:{}\\}",
self.cat.repr(tcx),
@ -1260,6 +1261,14 @@ impl Repr for cmt_ {
self.mutbl,
self.ty.repr(tcx))
}
#[cfg(not(stage0))]
fn repr(&self, tcx: &ty::ctxt) -> String {
format!("{{{} id:{} m:{:?} ty:{}}}",
self.cat.repr(tcx),
self.id,
self.mutbl,
self.ty.repr(tcx))
}
}
impl Repr for categorization {
@ -1306,7 +1315,10 @@ impl Repr for InteriorKind {
InteriorField(NamedField(fld)) => {
token::get_name(fld).get().to_str()
}
#[cfg(stage0)]
InteriorField(PositionalField(i)) => format!("\\#{:?}", i),
#[cfg(not(stage0))]
InteriorField(PositionalField(i)) => format!("#{:?}", i),
InteriorElement(_) => "[]".to_string(),
}
}

View File

@ -642,8 +642,12 @@ impl<'a> PrivacyVisitor<'a> {
let msg = match name {
NamedField(name) => format!("field `{}` of {} is private",
token::get_ident(name), struct_desc),
#[cfg(stage0)]
UnnamedField(idx) => format!("field \\#{} of {} is private",
idx + 1, struct_desc),
#[cfg(not(stage0))]
UnnamedField(idx) => format!("field #{} of {} is private",
idx + 1, struct_desc),
};
self.tcx.sess.span_err(span, msg.as_slice());
}

View File

@ -4075,6 +4075,7 @@ impl<'a> Resolver<'a> {
for (&key, &binding_0) in map_0.iter() {
match map_i.find(&key) {
#[cfg(stage0)]
None => {
self.resolve_error(
p.span,
@ -4083,6 +4084,16 @@ impl<'a> Resolver<'a> {
token::get_name(key),
i + 1).as_slice());
}
#[cfg(not(stage0))]
None => {
self.resolve_error(
p.span,
format!("variable `{}` from pattern #1 is \
not bound in pattern #{}",
token::get_name(key),
i + 1).as_slice());
}
#[cfg(stage0)]
Some(binding_i) => {
if binding_0.binding_mode != binding_i.binding_mode {
self.resolve_error(
@ -4093,6 +4104,17 @@ impl<'a> Resolver<'a> {
i + 1).as_slice());
}
}
#[cfg(not(stage0))]
Some(binding_i) => {
if binding_0.binding_mode != binding_i.binding_mode {
self.resolve_error(
binding_i.span,
format!("variable `{}` is bound with different \
mode in pattern #{} than in pattern #1",
token::get_name(key),
i + 1).as_slice());
}
}
}
}
@ -4100,10 +4122,10 @@ impl<'a> Resolver<'a> {
if !map_0.contains_key(&key) {
self.resolve_error(
binding.span,
format!("variable `{}` from pattern \\#{} is \
not bound in pattern \\#1",
format!("variable `{}` from pattern {}{} is \
not bound in pattern {}1",
token::get_name(key),
i + 1).as_slice());
"#", i + 1, "#").as_slice());
}
}
}
@ -5108,6 +5130,7 @@ impl<'a> Resolver<'a> {
// structs, which wouldn't result in this error.)
match self.with_no_errors(|this|
this.resolve_path(expr.id, path, TypeNS, false)) {
#[cfg(stage0)]
Some((DefTy(struct_id), _))
if self.structs.contains_key(&struct_id) => {
self.resolve_error(expr.span,
@ -5121,6 +5144,21 @@ impl<'a> Resolver<'a> {
`{} \\{ /* fields */ \\}`?",
wrong_name).as_slice());
}
#[cfg(not(stage0))]
Some((DefTy(struct_id), _))
if self.structs.contains_key(&struct_id) => {
self.resolve_error(expr.span,
format!("`{}` is a structure name, but \
this expression \
uses it like a function name",
wrong_name).as_slice());
self.session.span_note(expr.span,
format!("Did you mean to write: \
`{} {{ /* fields */ }}`?",
wrong_name).as_slice());
}
_ => {
let mut method_scope = false;

View File

@ -761,7 +761,8 @@ impl<'a> Builder<'a> {
pub fn add_comment(&self, text: &str) {
if self.ccx.sess().asm_comments() {
let sanitized = text.replace("$", "");
let comment_text = format!("\\# {}", sanitized.replace("\n", "\n\t# "));
let comment_text = format!("{} {}", "#",
sanitized.replace("\n", "\n\t# "));
self.count_insn("inlineasm");
let asm = comment_text.as_slice().with_c_str(|c| {
unsafe {

View File

@ -692,7 +692,7 @@ pub fn trans_rust_fn_with_foreign_abi(ccx: &CrateContext,
let foreign_index = next_foreign_arg(llforeign_arg_ty.pad.is_some());
let mut llforeign_arg = llvm::LLVMGetParam(llwrapfn, foreign_index);
debug!("llforeign_arg \\#{}: {}",
debug!("llforeign_arg {}{}: {}", "#",
i, ccx.tn.val_to_str(llforeign_arg));
debug!("rust_indirect = {}, foreign_indirect = {}",
rust_indirect, foreign_indirect);
@ -725,7 +725,7 @@ pub fn trans_rust_fn_with_foreign_abi(ccx: &CrateContext,
llvm::LLVMBuildLoad(builder, llforeign_arg, noname())
};
debug!("llrust_arg \\#{}: {}",
debug!("llrust_arg {}{}: {}", "#",
i, ccx.tn.val_to_str(llrust_arg));
llrust_args.push(llrust_arg);
}

View File

@ -391,12 +391,14 @@ pub fn trans_intrinsic(ccx: &CrateContext,
};
ccx.sess().span_fatal(sp,
format!("transmute called on types with different sizes: \
{intype} ({insize, plural, =1{# bit} other{# bits}}) to \
{outtype} ({outsize, plural, =1{# bit} other{# bits}})",
intype = ty_to_str(ccx.tcx(), in_type),
insize = in_type_size as uint,
outtype = ty_to_str(ccx.tcx(), out_type),
outsize = out_type_size as uint).as_slice());
{} ({} bit{}) to \
{} ({} bit{})",
ty_to_str(ccx.tcx(), in_type),
in_type_size,
if in_type_size == 1 {""} else {"s"},
ty_to_str(ccx.tcx(), out_type),
out_type_size,
if out_type_size == 1 {""} else {"s"}).as_slice());
}
if !return_type_is_void(ccx, out_type) {

View File

@ -73,6 +73,7 @@ pub struct VecTypes {
}
impl VecTypes {
#[cfg(stage0)]
pub fn to_str(&self, ccx: &CrateContext) -> String {
format!("VecTypes \\{unit_ty={}, llunit_ty={}, \
llunit_size={}, llunit_alloc_size={}\\}",
@ -81,6 +82,15 @@ impl VecTypes {
ccx.tn.val_to_str(self.llunit_size),
self.llunit_alloc_size)
}
#[cfg(not(stage0))]
pub fn to_str(&self, ccx: &CrateContext) -> String {
format!("VecTypes {{unit_ty={}, llunit_ty={}, \
llunit_size={}, llunit_alloc_size={}}}",
ty_to_str(ccx.tcx(), self.unit_ty),
ccx.tn.type_to_str(self.llunit_ty),
ccx.tn.val_to_str(self.llunit_size),
self.llunit_alloc_size)
}
}
pub fn trans_fixed_vstore<'a>(

View File

@ -317,7 +317,7 @@ pub fn llvm_type_name(cx: &CrateContext,
if did.krate == 0 {
format!("{}.{}", name, tstr)
} else {
format!("{}.{}[\\#{}]", name, tstr, did.krate)
format!("{}.{}[{}{}]", name, tstr, "#", did.krate)
}
}

View File

@ -884,9 +884,14 @@ impl Vid for TyVid {
}
impl fmt::Show for TyVid {
#[cfg(stage0)]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result{
write!(f, "<generic \\#{}>", self.to_uint())
}
#[cfg(not(stage0))]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result{
write!(f, "<generic #{}>", self.to_uint())
}
}
impl Vid for IntVid {
@ -894,9 +899,14 @@ impl Vid for IntVid {
}
impl fmt::Show for IntVid {
#[cfg(stage0)]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "<generic integer \\#{}>", self.to_uint())
}
#[cfg(not(stage0))]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "<generic integer #{}>", self.to_uint())
}
}
impl Vid for FloatVid {
@ -904,9 +914,14 @@ impl Vid for FloatVid {
}
impl fmt::Show for FloatVid {
#[cfg(stage0)]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "<generic float \\#{}>", self.to_uint())
}
#[cfg(not(stage0))]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "<generic float #{}>", self.to_uint())
}
}
impl Vid for RegionVid {

View File

@ -256,13 +256,13 @@ pub fn check_pat_variant(pcx: &pat_ctxt, pat: &ast::Pat, path: &ast::Path,
if arg_len > 0 {
// N-ary variant.
if arg_len != subpats_len {
let s = format!("this pattern has \
{npat, plural, =1{# field} other{# fields}}, \
but the corresponding {kind} has \
{narg, plural, =1{# field} other{# fields}}",
npat = subpats_len,
kind = kind_name,
narg = arg_len);
let s = format!("this pattern has {} field{}, \
but the corresponding {} has {} field{}",
subpats_len,
if subpats_len == 1 {""} else {"s"},
kind_name,
arg_len,
if arg_len == 1 {""} else {"s"});
tcx.sess.span_err(pat.span, s.as_slice());
error_happened = true;
}
@ -276,11 +276,11 @@ pub fn check_pat_variant(pcx: &pat_ctxt, pat: &ast::Pat, path: &ast::Path,
}
} else if subpats_len > 0 {
tcx.sess.span_err(pat.span,
format!("this pattern has \
{npat, plural, =1{# field} other{# fields}}, \
but the corresponding {kind} has no fields",
npat = subpats_len,
kind = kind_name).as_slice());
format!("this pattern has {} field{}, \
but the corresponding {} has no fields",
subpats_len,
if subpats_len == 1 {""} else {"s"},
kind_name).as_slice());
error_happened = true;
}

View File

@ -1435,6 +1435,7 @@ impl<'a> LookupContext<'a> {
}
}
#[cfg(stage0)]
fn report_static_candidate(&self, idx: uint, did: DefId) {
let span = if did.krate == ast::LOCAL_CRATE {
self.tcx().map.span(did.node)
@ -1448,6 +1449,7 @@ impl<'a> LookupContext<'a> {
ty::item_path_str(self.tcx(), did)).as_slice());
}
#[cfg(stage0)]
fn report_param_candidate(&self, idx: uint, did: DefId) {
self.tcx().sess.span_note(
self.span,
@ -1456,6 +1458,7 @@ impl<'a> LookupContext<'a> {
ty::item_path_str(self.tcx(), did)).as_slice());
}
#[cfg(stage0)]
fn report_trait_candidate(&self, idx: uint, did: DefId) {
self.tcx().sess.span_note(
self.span,
@ -1465,6 +1468,39 @@ impl<'a> LookupContext<'a> {
ty::item_path_str(self.tcx(), did)).as_slice());
}
#[cfg(not(stage0))]
fn report_static_candidate(&self, idx: uint, did: DefId) {
let span = if did.krate == ast::LOCAL_CRATE {
self.tcx().map.span(did.node)
} else {
self.span
};
self.tcx().sess.span_note(
span,
format!("candidate #{} is `{}`",
idx + 1u,
ty::item_path_str(self.tcx(), did)).as_slice());
}
#[cfg(not(stage0))]
fn report_param_candidate(&self, idx: uint, did: DefId) {
self.tcx().sess.span_note(
self.span,
format!("candidate #{} derives from the bound `{}`",
idx + 1u,
ty::item_path_str(self.tcx(), did)).as_slice());
}
#[cfg(not(stage0))]
fn report_trait_candidate(&self, idx: uint, did: DefId) {
self.tcx().sess.span_note(
self.span,
format!("candidate #{} derives from the type of the receiver, \
which is the trait `{}`",
idx + 1u,
ty::item_path_str(self.tcx(), did)).as_slice());
}
fn infcx(&'a self) -> &'a infer::InferCtxt<'a> {
&self.fcx.inh.infcx
}

View File

@ -902,26 +902,26 @@ fn compare_impl_method(tcx: &ty::ctxt,
if num_impl_m_type_params != num_trait_m_type_params {
tcx.sess.span_err(
impl_m_span,
format!("method `{method}` has {nimpl, plural, =1{# type parameter} \
other{# type parameters}}, \
but its trait declaration has {ntrait, plural, =1{# type parameter} \
other{# type parameters}}",
method = token::get_ident(trait_m.ident),
nimpl = num_impl_m_type_params,
ntrait = num_trait_m_type_params).as_slice());
format!("method `{}` has {} type parameter{} \
but its trait declaration has {} type parameter{}",
token::get_ident(trait_m.ident),
num_impl_m_type_params,
if num_impl_m_type_params == 1 {""} else {"s"},
num_trait_m_type_params,
if num_trait_m_type_params == 1 {""} else {"s"}).as_slice());
return;
}
if impl_m.fty.sig.inputs.len() != trait_m.fty.sig.inputs.len() {
tcx.sess.span_err(
impl_m_span,
format!("method `{method}` has {nimpl, plural, =1{# parameter} \
other{# parameters}} \
but the declaration in trait `{trait}` has {ntrait}",
method = token::get_ident(trait_m.ident),
nimpl = impl_m.fty.sig.inputs.len(),
trait = ty::item_path_str(tcx, trait_m.def_id),
ntrait = trait_m.fty.sig.inputs.len()).as_slice());
format!("method `{}` has {} parameter{} \
but the declaration in trait `{}` has {}",
token::get_ident(trait_m.ident),
impl_m.fty.sig.inputs.len(),
if impl_m.fty.sig.inputs.len() == 1 {""} else {"s"},
ty::item_path_str(tcx, trait_m.def_id),
trait_m.fty.sig.inputs.len()).as_slice());
return;
}
@ -954,20 +954,19 @@ fn compare_impl_method(tcx: &ty::ctxt,
if impl_param_def.bounds.trait_bounds.len() !=
trait_param_def.bounds.trait_bounds.len()
{
let found = impl_param_def.bounds.trait_bounds.len();
let expected = trait_param_def.bounds.trait_bounds.len();
tcx.sess.span_err(
impl_m_span,
format!("in method `{method}`, \
type parameter {typaram} has \
{nimpl, plural, =1{# trait bound} other{# trait bounds}}, \
but the corresponding type parameter in \
the trait declaration has \
{ntrait, plural, =1{# trait bound} other{# trait bounds}}",
method = token::get_ident(trait_m.ident),
typaram = i,
nimpl = impl_param_def.bounds.trait_bounds.len(),
ntrait = trait_param_def.bounds
.trait_bounds
.len()).as_slice());
format!("in method `{}`, type parameter {} has {} trait \
bound{}, but the corresponding type parameter in \
the trait declaration has {} trait bound{}",
token::get_ident(trait_m.ident),
i,
found,
if found == 1 {""} else {"s"},
expected,
if expected == 1 {""} else {"s"}).as_slice());
return;
}
}
@ -1526,13 +1525,12 @@ fn check_argument_types(fcx: &FnCtxt,
ty::ty_tup(ref arg_types) => {
if arg_types.len() != args.len() {
let msg = format!(
"this function takes \
{nexpected, plural, =1{# parameter} \
other{# parameters}} \
but {nsupplied, plural, =1{# parameter was} \
other{# parameters were}} supplied",
nexpected = arg_types.len(),
nsupplied = args.len());
"this function takes {} parameter{} \
but {} parameter{} supplied",
arg_types.len(),
if arg_types.len() == 1 {""} else {"s"},
args.len(),
if args.len() == 1 {" was"} else {"s were"});
tcx.sess.span_err(sp, msg.as_slice());
err_args(args.len())
} else {
@ -1543,9 +1541,9 @@ fn check_argument_types(fcx: &FnCtxt,
if args.len() != 0 {
let msg = format!(
"this function takes 0 parameters \
but {nsupplied, plural, =1{# parameter was} \
other{# parameters were}} supplied",
nsupplied = args.len());
but {} parameter{} supplied",
args.len(),
if args.len() == 1 {" was"} else {"s were"});
tcx.sess.span_err(sp, msg.as_slice());
}
Vec::new()
@ -1566,12 +1564,12 @@ fn check_argument_types(fcx: &FnCtxt,
fn_inputs.iter().map(|a| *a).collect()
} else {
let msg = format!(
"this function takes at least {nexpected, plural, =1{# parameter} \
other{# parameters}} \
but {nsupplied, plural, =1{# parameter was} \
other{# parameters were}} supplied",
nexpected = expected_arg_count,
nsupplied = supplied_arg_count);
"this function takes at least {} parameter{} \
but {} parameter{} supplied",
expected_arg_count,
if expected_arg_count == 1 {""} else {"s"},
supplied_arg_count,
if supplied_arg_count == 1 {" was"} else {"s were"});
tcx.sess.span_err(sp, msg.as_slice());
@ -1579,12 +1577,12 @@ fn check_argument_types(fcx: &FnCtxt,
}
} else {
let msg = format!(
"this function takes {nexpected, plural, =1{# parameter} \
other{# parameters}} \
but {nsupplied, plural, =1{# parameter was} \
other{# parameters were}} supplied",
nexpected = expected_arg_count,
nsupplied = supplied_arg_count);
"this function takes {} parameter{} \
but {} parameter{} supplied",
expected_arg_count,
if expected_arg_count == 1 {""} else {"s"},
supplied_arg_count,
if supplied_arg_count == 1 {" was"} else {"s were"});
tcx.sess.span_err(sp, msg.as_slice());
@ -1932,12 +1930,14 @@ fn check_type_parameter_positions_in_path(function_context: &FnCtxt,
function_context.tcx()
.sess
.span_err(path.span,
format!("expected {nexpected, plural, =1{# lifetime parameter} \
other{# lifetime parameters}}, \
found {nsupplied, plural, =1{# lifetime parameter} \
other{# lifetime parameters}}",
nexpected = trait_region_parameter_count,
nsupplied = supplied_region_parameter_count).as_slice());
format!("expected {} lifetime parameter{} \
found {} liftime parameter{}",
trait_region_parameter_count,
if trait_region_parameter_count == 1 {""}
else {"s"},
supplied_region_parameter_count,
if supplied_region_parameter_count == 1 {""}
else {"s"}).as_slice());
}
// Make sure the number of type parameters supplied on the trait
@ -1950,45 +1950,41 @@ fn check_type_parameter_positions_in_path(function_context: &FnCtxt,
let supplied_ty_param_count = trait_segment.types.len();
if supplied_ty_param_count < required_ty_param_count {
let msg = if required_ty_param_count < generics.type_param_defs().len() {
format!("the {trait_or_impl} referenced by this path needs at least \
{nexpected, plural, =1{# type parameter} \
other{# type parameters}}, \
but {nsupplied, plural, =1{# type parameter} \
other{# type parameters}} were supplied",
trait_or_impl = name,
nexpected = required_ty_param_count,
nsupplied = supplied_ty_param_count)
format!("the {} referenced by this path needs at least \
{} type parameter{}, but {} type parameters were \
supplied",
name,
required_ty_param_count,
if required_ty_param_count == 1 {""} else {"s"},
supplied_ty_param_count)
} else {
format!("the {trait_or_impl} referenced by this path needs \
{nexpected, plural, =1{# type parameter} \
other{# type parameters}}, \
but {nsupplied, plural, =1{# type parameter} \
other{# type parameters}} were supplied",
trait_or_impl = name,
nexpected = required_ty_param_count,
nsupplied = supplied_ty_param_count)
format!("the {} referenced by this path needs \
{} type parameter{}, but {} type parameters were \
supplied",
name,
required_ty_param_count,
if required_ty_param_count == 1 {""} else {"s"},
supplied_ty_param_count)
};
function_context.tcx().sess.span_err(path.span,
msg.as_slice())
} else if supplied_ty_param_count > formal_ty_param_count {
let msg = if required_ty_param_count < generics.type_param_defs().len() {
format!("the {trait_or_impl} referenced by this path needs at most \
{nexpected, plural, =1{# type parameter} \
other{# type parameters}}, \
but {nsupplied, plural, =1{# type parameter} \
other{# type parameters}} were supplied",
trait_or_impl = name,
nexpected = formal_ty_param_count,
nsupplied = supplied_ty_param_count)
format!("the {} referenced by this path needs at most \
{} type parameter{}, but {} type parameters were \
supplied",
name,
formal_ty_param_count,
if formal_ty_param_count == 1 {""} else {"s"},
supplied_ty_param_count)
} else {
format!("the {trait_or_impl} referenced by this path needs \
{nexpected, plural, =1{# type parameter} \
other{# type parameters}}, \
but {nsupplied, plural, =1{# type parameter} \
other{# type parameters}} were supplied",
trait_or_impl = name,
nexpected = formal_ty_param_count,
nsupplied = supplied_ty_param_count)
format!("the {} referenced by this path needs \
{} type parameter{}, but {} type parameters were \
supplied",
name,
formal_ty_param_count,
if formal_ty_param_count == 1 {""} else {"s"},
supplied_ty_param_count)
};
function_context.tcx().sess.span_err(path.span,
msg.as_slice())
@ -2670,8 +2666,8 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
tcx.sess.span_err(span,
format!(
"missing {nfields, plural, =1{field} other{fields}}: {fields}",
nfields = missing_fields.len(),
"missing field{}: {fields}",
if missing_fields.len() == 1 {""} else {"s"},
fields = missing_fields.connect(", ")).as_slice());
}
}
@ -4021,12 +4017,12 @@ pub fn instantiate_path(fcx: &FnCtxt,
if num_supplied_regions != 0 {
fcx.ccx.tcx.sess.span_err(
span,
format!("expected {nexpected, plural, =1{# lifetime parameter} \
other{# lifetime parameters}}, \
found {nsupplied, plural, =1{# lifetime parameter} \
other{# lifetime parameters}}",
nexpected = num_expected_regions,
nsupplied = num_supplied_regions).as_slice());
format!("expected {} lifetime parameter{}, \
found {} lifetime parameter{}",
num_expected_regions,
if num_expected_regions == 1 {""} else {"s"},
num_supplied_regions,
if num_supplied_regions == 1 {""} else {"s"}).as_slice());
}
fcx.infcx().region_vars_for_defs(span, tpt.generics.region_param_defs.as_slice())
@ -4296,10 +4292,16 @@ pub fn check_bounds_are_used(ccx: &CrateCtxt,
ty::walk_ty(ty, |t| {
match ty::get(t).sty {
#[cfg(stage0)]
ty::ty_param(param_ty {idx, ..}) => {
debug!("Found use of ty param \\#{}", idx);
*tps_used.get_mut(idx) = true;
}
#[cfg(not(stage0))]
ty::ty_param(param_ty {idx, ..}) => {
debug!("Found use of ty param #{}", idx);
*tps_used.get_mut(idx) = true;
}
_ => ()
}
});

View File

@ -386,8 +386,8 @@ fn search_for_vtable(vcx: &VtableContext,
// some value of U) with some_trait<T>. This would fail if T
// and U weren't compatible.
debug!("(checking vtable) \\#2 relating trait \
ty {} to of_trait_ref {}",
debug!("(checking vtable) {}2 relating trait \
ty {} to of_trait_ref {}", "#",
vcx.infcx.trait_ref_to_str(&*trait_ref),
vcx.infcx.trait_ref_to_str(&*of_trait_ref));

View File

@ -1323,7 +1323,7 @@ impl<'a> RegionVarBindings<'a> {
while changed {
changed = false;
iteration += 1;
debug!("---- {} Iteration \\#{}", tag, iteration);
debug!("---- {} Iteration {}{}", "#", tag, iteration);
for (constraint, _) in self.constraints.borrow().iter() {
let edge_changed = body(constraint);
if edge_changed {

View File

@ -61,9 +61,14 @@ impl<V:InferStr> InferStr for Bound<V> {
}
impl<T:InferStr> InferStr for Bounds<T> {
#[cfg(stage0)]
fn inf_str(&self, cx: &InferCtxt) -> String {
format!("\\{{} <: {}\\}", self.lb.inf_str(cx), self.ub.inf_str(cx))
}
#[cfg(not(stage0))]
fn inf_str(&self, cx: &InferCtxt) -> String {
format!("{{{} <: {}}}", self.lb.inf_str(cx), self.ub.inf_str(cx))
}
}
impl<V:Vid + ToStr,T:InferStr> InferStr for VarValue<V, T> {

View File

@ -232,11 +232,18 @@ pub struct impl_res {
}
impl Repr for impl_res {
#[cfg(stage0)]
fn repr(&self, tcx: &ty::ctxt) -> String {
format!("impl_res \\{trait_vtables={}, self_vtables={}\\}",
self.trait_vtables.repr(tcx),
self.self_vtables.repr(tcx))
}
#[cfg(not(stage0))]
fn repr(&self, tcx: &ty::ctxt) -> String {
format!("impl_res {{trait_vtables={}, self_vtables={}}}",
self.trait_vtables.repr(tcx),
self.self_vtables.repr(tcx))
}
}
pub type impl_vtable_map = RefCell<DefIdMap<impl_res>>;

View File

@ -95,9 +95,14 @@ pub fn explain_region_and_span(cx: &ctxt, region: ty::Region)
ReFree(ref fr) => {
let prefix = match fr.bound_region {
#[cfg(stage0)]
BrAnon(idx) => {
format!("the anonymous lifetime \\#{} defined on", idx + 1)
}
#[cfg(not(stage0))]
BrAnon(idx) => {
format!("the anonymous lifetime #{} defined on", idx + 1)
}
BrFresh(_) => "an anonymous lifetime defined on".to_string(),
_ => {
format!("the lifetime {} as defined on",
@ -375,7 +380,10 @@ pub fn ty_to_str(cx: &ctxt, typ: t) -> String {
Some(def) => token::get_ident(def.ident).get().to_string(),
// This can only happen when a type mismatch error happens and
// the actual type has more type parameters than the expected one.
None => format!("<generic \\#{}>", id)
#[cfg(stage0)]
None => format!("<generic \\#{}>", id),
#[cfg(not(stage0))]
None => format!("<generic #{}>", id),
};
if !cx.sess.verbose() {
ident
@ -729,11 +737,18 @@ impl Repr for ast::DefId {
}
impl Repr for ty::ty_param_bounds_and_ty {
#[cfg(stage0)]
fn repr(&self, tcx: &ctxt) -> String {
format!("ty_param_bounds_and_ty \\{generics: {}, ty: {}\\}",
self.generics.repr(tcx),
self.ty.repr(tcx))
}
#[cfg(not(stage0))]
fn repr(&self, tcx: &ctxt) -> String {
format!("ty_param_bounds_and_ty {{generics: {}, ty: {}}}",
self.generics.repr(tcx),
self.ty.repr(tcx))
}
}
impl Repr for ty::Generics {
@ -800,12 +815,20 @@ impl Repr for ast::Visibility {
}
impl Repr for ty::BareFnTy {
#[cfg(stage0)]
fn repr(&self, tcx: &ctxt) -> String {
format!("BareFnTy \\{fn_style: {:?}, abi: {}, sig: {}\\}",
self.fn_style,
self.abi.to_str(),
self.sig.repr(tcx))
}
#[cfg(not(stage0))]
fn repr(&self, tcx: &ctxt) -> String {
format!("BareFnTy {{fn_style: {:?}, abi: {}, sig: {}}}",
self.fn_style,
self.abi.to_str(),
self.sig.repr(tcx))
}
}
impl Repr for ty::FnSig {
@ -815,12 +838,20 @@ impl Repr for ty::FnSig {
}
impl Repr for typeck::MethodCallee {
#[cfg(stage0)]
fn repr(&self, tcx: &ctxt) -> String {
format!("MethodCallee \\{origin: {}, ty: {}, {}\\}",
self.origin.repr(tcx),
self.ty.repr(tcx),
self.substs.repr(tcx))
}
#[cfg(not(stage0))]
fn repr(&self, tcx: &ctxt) -> String {
format!("MethodCallee {{origin: {}, ty: {}, {}}}",
self.origin.repr(tcx),
self.ty.repr(tcx),
self.substs.repr(tcx))
}
}
impl Repr for typeck::MethodOrigin {

View File

@ -348,8 +348,7 @@ impl fmt::Show for clean::Type {
clean::Self(..) => f.write("Self".as_bytes()),
clean::Primitive(prim) => primitive_link(f, prim, prim.to_str()),
clean::Closure(ref decl, ref region) => {
write!(f, "{style}{lifetimes}|{args}|{bounds}\
{arrow, select, yes{ -&gt; {ret}} other{}}",
write!(f, "{style}{lifetimes}|{args}|{bounds}{arrow}",
style = FnStyleSpace(decl.fn_style),
lifetimes = if decl.lifetimes.len() == 0 {
"".to_string()
@ -358,10 +357,9 @@ impl fmt::Show for clean::Type {
},
args = decl.decl.inputs,
arrow = match decl.decl.output {
clean::Primitive(clean::Nil) => "no",
_ => "yes",
clean::Primitive(clean::Nil) => "".to_string(),
_ => format!(" -&gt; {}", decl.decl.output),
},
ret = decl.decl.output,
bounds = {
let mut ret = String::new();
match *region {
@ -389,8 +387,7 @@ impl fmt::Show for clean::Type {
})
}
clean::Proc(ref decl) => {
write!(f, "{style}{lifetimes}proc({args}){bounds}\
{arrow, select, yes{ -&gt; {ret}} other{}}",
write!(f, "{style}{lifetimes}proc({args}){bounds}{arrow}",
style = FnStyleSpace(decl.fn_style),
lifetimes = if decl.lifetimes.len() == 0 {
"".to_string()
@ -409,10 +406,9 @@ impl fmt::Show for clean::Type {
m.collect::<Vec<String>>().connect(" + "))
},
arrow = match decl.decl.output {
clean::Primitive(clean::Nil) => "no",
_ => "yes",
},
ret = decl.decl.output)
clean::Primitive(clean::Nil) => "".to_string(),
_ => format!(" -&gt; {}", decl.decl.output)
})
}
clean::BareFunction(ref decl) => {
write!(f, "{}{}fn{}{}",
@ -468,13 +464,12 @@ impl fmt::Show for clean::Arguments {
impl fmt::Show for clean::FnDecl {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "({args}){arrow, select, yes{ -&gt; {ret}} other{}}",
write!(f, "({args}){arrow}",
args = self.inputs,
arrow = match self.output {
clean::Primitive(clean::Nil) => "no",
_ => "yes"
},
ret = self.output)
clean::Primitive(clean::Nil) => "".to_string(),
_ => format!(" -&gt; {}", self.output),
})
}
}
@ -502,14 +497,12 @@ impl<'a> fmt::Show for Method<'a> {
}
args.push_str(format!("{}", input.type_).as_slice());
}
write!(f,
"({args}){arrow, select, yes{ -&gt; {ret}} other{}}",
write!(f, "({args}){arrow}",
args = args,
arrow = match d.output {
clean::Primitive(clean::Nil) => "no",
_ => "yes"
},
ret = d.output)
clean::Primitive(clean::Nil) => "".to_string(),
_ => format!(" -&gt; {}", d.output),
})
}
}
@ -545,14 +538,14 @@ impl fmt::Show for clean::ViewPath {
write!(f, "use {}::*;", *src)
}
clean::ImportList(ref src, ref names) => {
try!(write!(f, "use {}::\\{", *src));
try!(write!(f, "use {}::{{", *src));
for (i, n) in names.iter().enumerate() {
if i > 0 {
try!(write!(f, ", "));
}
try!(write!(f, "{}", *n));
}
write!(f, "\\};")
write!(f, "}};")
}
}
}

View File

@ -43,7 +43,7 @@ r##"<!DOCTYPE html>
rel='stylesheet' type='text/css'>
<link rel="stylesheet" type="text/css" href="{root_path}main.css">
{favicon, select, none{} other{<link rel="shortcut icon" href="#">}}
{favicon}
</head>
<body>
<!--[if lte IE 8]>
@ -54,10 +54,7 @@ r##"<!DOCTYPE html>
<![endif]-->
<section class="sidebar">
{logo, select, none{} other{
<a href='{root_path}{krate}/index.html'><img src='#' alt='' width='100'></a>
}}
{logo}
{sidebar}
</section>
@ -122,9 +119,20 @@ r##"<!DOCTYPE html>
content = *t,
root_path = page.root_path,
ty = page.ty,
logo = nonestr(layout.logo.as_slice()),
logo = if layout.logo.len() == 0 {
"".to_string()
} else {
format!("<a href='{}{}/index.html'>\
<img src='{}' alt='' width='100'></a>",
page.root_path, layout.krate,
layout.logo)
},
title = page.title,
favicon = nonestr(layout.favicon.as_slice()),
favicon = if layout.favicon.len() == 0 {
"".to_string()
} else {
format!(r#"<link rel="shortcut icon" href="{}">"#, layout.favicon)
},
sidebar = *sidebar,
krate = layout.krate,
play_url = layout.playground_url,
@ -136,10 +144,6 @@ r##"<!DOCTYPE html>
)
}
fn nonestr<'a>(s: &'a str) -> &'a str {
if s == "" { "none" } else { s }
}
pub fn redirect(dst: &mut io::Writer, url: &str) -> io::IoResult<()> {
write!(dst,
r##"<!DOCTYPE html>

View File

@ -260,9 +260,13 @@ pub fn render(w: &mut fmt::Formatter, s: &str, print_toc: bool) -> fmt::Result {
// Render the HTML
let text = format!(r#"<h{lvl} id="{id}" class='section-header'><a
href="\#{id}">{sec_len,plural,=0{}other{{sec} }}{}</a></h{lvl}>"#,
href="\#{id}">{sec}{}</a></h{lvl}>"#,
s, lvl = level, id = id,
sec_len = sec.len(), sec = sec);
sec = if sec.len() == 0 {
sec.to_string()
} else {
format!("{} ", sec)
});
text.with_c_str(|p| unsafe { hoedown_buffer_puts(ob, p) });
}

View File

@ -399,7 +399,7 @@ fn build_index(krate: &clean::Crate, cache: &mut Cache) -> io::IoResult<String>
// Collect the index into a string
let mut w = MemWriter::new();
try!(write!(&mut w, r#"searchIndex['{}'] = \{"items":["#, krate.name));
try!(write!(&mut w, r#"searchIndex['{}'] = {{"items":["#, krate.name));
let mut lastpath = "".to_string();
for (i, item) in cache.search_index.iter().enumerate() {
@ -439,7 +439,7 @@ fn build_index(krate: &clean::Crate, cache: &mut Cache) -> io::IoResult<String>
short, *fqp.last().unwrap()));
}
try!(write!(&mut w, r"]\};"));
try!(write!(&mut w, "]}};"));
Ok(str::from_utf8(w.unwrap().as_slice()).unwrap().to_string())
}
@ -498,7 +498,7 @@ fn write_shared(cx: &Context,
let all_indexes = try!(collect(&dst, krate.name.as_slice(),
"searchIndex"));
let mut w = try!(File::create(&dst));
try!(writeln!(&mut w, r"var searchIndex = \{\};"));
try!(writeln!(&mut w, "var searchIndex = {{}};"));
try!(writeln!(&mut w, "{}", search_index));
for index in all_indexes.iter() {
try!(writeln!(&mut w, "{}", *index));
@ -534,7 +534,7 @@ fn write_shared(cx: &Context,
try!(mkdir(&mydst.dir_path()));
let mut f = BufferedWriter::new(try!(File::create(&mydst)));
try!(writeln!(&mut f, r"(function() \{var implementors = \{\};"));
try!(writeln!(&mut f, "(function() {{var implementors = {{}};"));
for implementor in all_implementors.iter() {
try!(write!(&mut f, "{}", *implementor));
@ -558,7 +558,7 @@ fn write_shared(cx: &Context,
window.pending_implementors = implementors;
}
"));
try!(writeln!(&mut f, r"\})()"));
try!(writeln!(&mut f, r"}})()"));
}
Ok(())
}
@ -1178,7 +1178,7 @@ impl<'a> Item<'a> {
self.item.source.loline,
self.item.source.hiline)
};
Some(format!("{root}src/{krate}/{path}.html\\#{href}",
Some(format!("{root}src/{krate}/{path}.html#{href}",
root = self.cx.root_path,
krate = self.cx.layout.krate,
path = path.connect("/"),
@ -1423,7 +1423,7 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context,
};
try!(write!(w,
"<h2 id='{id}' class='section-header'>\
<a href=\"\\#{id}\">{name}</a></h2>\n<table>",
<a href=\"#{id}\">{name}</a></h2>\n<table>",
id = short, name = name));
}
@ -1538,9 +1538,9 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
let provided = t.methods.iter().filter(|m| !m.is_req()).collect::<Vec<&clean::TraitMethod>>();
if t.methods.len() == 0 {
try!(write!(w, "\\{ \\}"));
try!(write!(w, "{{ }}"));
} else {
try!(write!(w, "\\{\n"));
try!(write!(w, "{{\n"));
for m in required.iter() {
try!(write!(w, " "));
try!(render_method(w, m.item()));
@ -1552,9 +1552,9 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
for m in provided.iter() {
try!(write!(w, " "));
try!(render_method(w, m.item()));
try!(write!(w, " \\{ ... \\}\n"));
try!(write!(w, " {{ ... }}\n"));
}
try!(write!(w, "\\}"));
try!(write!(w, "}}"));
}
try!(write!(w, "</pre>"));
@ -1627,7 +1627,7 @@ fn render_method(w: &mut fmt::Formatter, meth: &clean::Item) -> fmt::Result {
fn fun(w: &mut fmt::Formatter, it: &clean::Item, fn_style: ast::FnStyle,
g: &clean::Generics, selfty: &clean::SelfTy,
d: &clean::FnDecl) -> fmt::Result {
write!(w, "{}fn <a href='\\#{ty}.{name}' class='fnname'>{name}</a>\
write!(w, "{}fn <a href='#{ty}.{name}' class='fnname'>{name}</a>\
{generics}{decl}",
match fn_style {
ast::UnsafeFn => "unsafe ",
@ -1693,9 +1693,9 @@ fn item_enum(w: &mut fmt::Formatter, it: &clean::Item,
it.name.get_ref().as_slice(),
e.generics));
if e.variants.len() == 0 && !e.variants_stripped {
try!(write!(w, " \\{\\}"));
try!(write!(w, " {{}}"));
} else {
try!(write!(w, " \\{\n"));
try!(write!(w, " {{\n"));
for v in e.variants.iter() {
try!(write!(w, " "));
let name = v.name.get_ref().as_slice();
@ -1732,7 +1732,7 @@ fn item_enum(w: &mut fmt::Formatter, it: &clean::Item,
if e.variants_stripped {
try!(write!(w, " // some variants omitted\n"));
}
try!(write!(w, "\\}"));
try!(write!(w, "}}"));
}
try!(write!(w, "</pre>"));
@ -1799,7 +1799,7 @@ fn render_struct(w: &mut fmt::Formatter, it: &clean::Item,
}
match ty {
doctree::Plain => {
try!(write!(w, " \\{\n{}", tab));
try!(write!(w, " {{\n{}", tab));
let mut fields_stripped = false;
for field in fields.iter() {
match field.inner {
@ -1820,7 +1820,7 @@ fn render_struct(w: &mut fmt::Formatter, it: &clean::Item,
if fields_stripped {
try!(write!(w, " // some fields omitted\n{}", tab));
}
try!(write!(w, "\\}"));
try!(write!(w, "}}"));
}
doctree::Tuple | doctree::Newtype => {
try!(write!(w, "("));
@ -1979,7 +1979,7 @@ impl<'a> fmt::Show for Sidebar<'a> {
let len = cx.current.len() - if it.is_mod() {1} else {0};
for (i, name) in cx.current.iter().take(len).enumerate() {
if i > 0 {
try!(write!(fmt, "&\\#8203;::"));
try!(write!(fmt, "&#8203;::"));
}
try!(write!(fmt, "<a href='{}index.html'>{}</a>",
cx.root_path
@ -1998,22 +1998,18 @@ impl<'a> fmt::Show for Sidebar<'a> {
try!(write!(w, "<div class='block {}'><h2>{}</h2>", short, longty));
for item in items.iter() {
let curty = shortty(cur).to_static_str();
let class = if cur.name.get_ref() == item && short == curty {
"current"
} else {
""
};
try!(write!(w, "<a class='{ty} {class}' href='{curty, select,
mod{../}
other{}
}{tysel, select,
mod{{name}/index.html}
other{#.{name}.html}
}'>{name}</a><br/>",
let class = if cur.name.get_ref() == item &&
short == curty { "current" } else { "" };
try!(write!(w, "<a class='{ty} {class}' href='{href}{path}'>\
{name}</a><br/>",
ty = short,
tysel = short,
class = class,
curty = curty,
href = if curty == "mod" {"../"} else {""},
path = if short == "mod" {
format!("{}/index.html", item.as_slice())
} else {
format!("{}.{}.html", short, item.as_slice())
},
name = item.as_slice()));
}
try!(write!(w, "</div>"));

View File

@ -430,6 +430,7 @@ impl<'a> ::Encoder<io::IoError> for Encoder<'a> {
_name: &str,
f: |&mut Encoder<'a>| -> EncodeResult) -> EncodeResult { f(self) }
#[cfg(stage0)]
fn emit_enum_variant(&mut self,
name: &str,
_id: uint,
@ -448,6 +449,25 @@ impl<'a> ::Encoder<io::IoError> for Encoder<'a> {
write!(self.wr, "]\\}")
}
}
#[cfg(not(stage0))]
fn emit_enum_variant(&mut self,
name: &str,
_id: uint,
cnt: uint,
f: |&mut Encoder<'a>| -> EncodeResult) -> EncodeResult {
// enums are encoded as strings or objects
// Bunny => "Bunny"
// Kangaroo(34,"William") => {"variant": "Kangaroo", "fields": [34,"William"]}
if cnt == 0 {
write!(self.wr, "{}", escape_str(name))
} else {
try!(write!(self.wr, "{{\"variant\":"));
try!(write!(self.wr, "{}", escape_str(name)));
try!(write!(self.wr, ",\"fields\":["));
try!(f(self));
write!(self.wr, "]}}")
}
}
fn emit_enum_variant_arg(&mut self,
idx: uint,
@ -473,6 +493,7 @@ impl<'a> ::Encoder<io::IoError> for Encoder<'a> {
self.emit_enum_variant_arg(idx, f)
}
#[cfg(stage0)]
fn emit_struct(&mut self,
_: &str,
_: uint,
@ -481,6 +502,15 @@ impl<'a> ::Encoder<io::IoError> for Encoder<'a> {
try!(f(self));
write!(self.wr, r"\}")
}
#[cfg(not(stage0))]
fn emit_struct(&mut self,
_: &str,
_: uint,
f: |&mut Encoder<'a>| -> EncodeResult) -> EncodeResult {
try!(write!(self.wr, "{{"));
try!(f(self));
write!(self.wr, "}}")
}
fn emit_struct_field(&mut self,
name: &str,
@ -533,11 +563,18 @@ impl<'a> ::Encoder<io::IoError> for Encoder<'a> {
f(self)
}
#[cfg(stage0)]
fn emit_map(&mut self, _len: uint, f: |&mut Encoder<'a>| -> EncodeResult) -> EncodeResult {
try!(write!(self.wr, r"\{"));
try!(f(self));
write!(self.wr, r"\}")
}
#[cfg(not(stage0))]
fn emit_map(&mut self, _len: uint, f: |&mut Encoder<'a>| -> EncodeResult) -> EncodeResult {
try!(write!(self.wr, "{{"));
try!(f(self));
write!(self.wr, "}}")
}
fn emit_map_elt_key(&mut self,
idx: uint,
@ -670,6 +707,7 @@ impl<'a> ::Encoder<io::IoError> for PrettyEncoder<'a> {
}
#[cfg(stage0)]
fn emit_struct(&mut self,
_: &str,
len: uint,
@ -684,6 +722,21 @@ impl<'a> ::Encoder<io::IoError> for PrettyEncoder<'a> {
write!(self.wr, "\n{}\\}", spaces(self.indent))
}
}
#[cfg(not(stage0))]
fn emit_struct(&mut self,
_: &str,
len: uint,
f: |&mut PrettyEncoder<'a>| -> EncodeResult) -> EncodeResult {
if len == 0 {
write!(self.wr, "{{}}")
} else {
try!(write!(self.wr, "{{"));
self.indent += 2;
try!(f(self));
self.indent -= 2;
write!(self.wr, "\n{}}}", spaces(self.indent))
}
}
fn emit_struct_field(&mut self,
name: &str,
@ -755,6 +808,7 @@ impl<'a> ::Encoder<io::IoError> for PrettyEncoder<'a> {
f(self)
}
#[cfg(stage0)]
fn emit_map(&mut self,
len: uint,
f: |&mut PrettyEncoder<'a>| -> EncodeResult) -> EncodeResult {
@ -768,6 +822,20 @@ impl<'a> ::Encoder<io::IoError> for PrettyEncoder<'a> {
write!(self.wr, "\n{}\\}", spaces(self.indent))
}
}
#[cfg(not(stage0))]
fn emit_map(&mut self,
len: uint,
f: |&mut PrettyEncoder<'a>| -> EncodeResult) -> EncodeResult {
if len == 0 {
write!(self.wr, "{{}}")
} else {
try!(write!(self.wr, "{{"));
self.indent += 2;
try!(f(self));
self.indent -= 2;
write!(self.wr, "\n{}}}", spaces(self.indent))
}
}
fn emit_map_elt_key(&mut self,
idx: uint,

View File

@ -1424,6 +1424,7 @@ impl<K: Eq + Hash<S>, V: PartialEq, S, H: Hasher<S>> PartialEq for HashMap<K, V,
impl<K: Eq + Hash<S>, V: Eq, S, H: Hasher<S>> Eq for HashMap<K, V, H> {}
impl<K: Eq + Hash<S> + Show, V: Show, S, H: Hasher<S>> Show for HashMap<K, V, H> {
#[cfg(stage0)]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
try!(write!(f, r"\{"));
@ -1434,6 +1435,17 @@ impl<K: Eq + Hash<S> + Show, V: Show, S, H: Hasher<S>> Show for HashMap<K, V, H>
write!(f, r"\}")
}
#[cfg(not(stage0))]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
try!(write!(f, "{{"));
for (i, (k, v)) in self.iter().enumerate() {
if i != 0 { try!(write!(f, ", ")); }
try!(write!(f, "{}: {}", *k, *v));
}
write!(f, "}}")
}
}
impl<K: Eq + Hash<S>, V, S, H: Hasher<S> + Default> Default for HashMap<K, V, H> {
@ -1617,6 +1629,7 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
}
impl<T: Eq + Hash<S> + fmt::Show, S, H: Hasher<S>> fmt::Show for HashSet<T, H> {
#[cfg(stage0)]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
try!(write!(f, r"\{"));
@ -1627,6 +1640,17 @@ impl<T: Eq + Hash<S> + fmt::Show, S, H: Hasher<S>> fmt::Show for HashSet<T, H> {
write!(f, r"\}")
}
#[cfg(not(stage0))]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
try!(write!(f, "{{"));
for (i, x) in self.iter().enumerate() {
if i != 0 { try!(write!(f, ", ")); }
try!(write!(f, "{}", *x));
}
write!(f, "}}")
}
}
impl<T: Eq + Hash<S>, S, H: Hasher<S> + Default> FromIterator<T> for HashSet<T, H> {

View File

@ -208,6 +208,7 @@ impl<K: Hash + Eq, V> LruCache<K, V> {
impl<A: fmt::Show + Hash + Eq, B: fmt::Show> fmt::Show for LruCache<A, B> {
/// Return a string that lists the key-value pairs from most-recently
/// used to least-recently used.
#[cfg(stage0)]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
try!(write!(f, r"\{"));
let mut cur = self.head;
@ -224,6 +225,25 @@ impl<A: fmt::Show + Hash + Eq, B: fmt::Show> fmt::Show for LruCache<A, B> {
}
write!(f, r"\}")
}
/// Return a string that lists the key-value pairs from most-recently
/// used to least-recently used.
#[cfg(not(stage0))]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
try!(write!(f, "{{"));
let mut cur = self.head;
for i in range(0, self.len()) {
if i > 0 { try!(write!(f, ", ")) }
unsafe {
cur = (*cur).next;
try!(write!(f, "{}", (*cur).key));
}
try!(write!(f, ": "));
unsafe {
try!(write!(f, "{}", (*cur).value));
}
}
write!(f, r"}}")
}
}
impl<K: Hash + Eq, V> Collection for LruCache<K, V> {

View File

@ -317,76 +317,6 @@ checks provided by the compiler. The `format_args!` macro is the only method of
safely creating these structures, but they can be unsafely created with the
constructor provided.
## Internationalization
The formatting syntax supported by the `format!` extension supports
internationalization by providing "methods" which execute various different
outputs depending on the input. The syntax and methods provided are similar to
other internationalization systems, so again nothing should seem alien.
Currently two methods are supported by this extension: "select" and "plural".
Each method will execute one of a number of clauses, and then the value of the
clause will become what's the result of the argument's format. Inside of the
cases, nested argument strings may be provided, but all formatting arguments
must not be done through implicit positional means. All arguments inside of each
case of a method must be explicitly selected by their name or their integer
position.
Furthermore, whenever a case is running, the special character `#` can be used
to reference the string value of the argument which was selected upon. As an
example:
```rust
format!("{0, select, other{#}}", "hello"); // => "hello"
```
This example is the equivalent of `{0:s}` essentially.
### Select
The select method is a switch over a `&str` parameter, and the parameter *must*
be of the type `&str`. An example of the syntax is:
```text
{0, select, male{...} female{...} other{...}}
```
Breaking this down, the `0`-th argument is selected upon with the `select`
method, and then a number of cases follow. Each case is preceded by an
identifier which is the match-clause to execute the given arm. In this case,
there are two explicit cases, `male` and `female`. The case will be executed if
the string argument provided is an exact match to the case selected.
The `other` case is also a required case for all `select` methods. This arm will
be executed if none of the other arms matched the word being selected over.
### Plural
The plural method is a switch statement over a `uint` parameter, and the
parameter *must* be a `uint`. A plural method in its full glory can be specified
as:
```text
{0, plural, offset=1 =1{...} two{...} many{...} other{...}}
```
To break this down, the first `0` indicates that this method is selecting over
the value of the first positional parameter to the format string. Next, the
`plural` method is being executed. An optionally-supplied `offset` is then given
which indicates a number to subtract from argument `0` when matching. This is
then followed by a list of cases.
Each case is allowed to supply a specific value to match upon with the syntax
`=N`. This case is executed if the value at argument `0` matches N exactly,
without taking the offset into account. A case may also be specified by one of
five keywords: `zero`, `one`, `two`, `few`, and `many`. These cases are matched
on after argument `0` has the offset taken into account. Currently the
definitions of `many` and `few` are hardcoded, but they are in theory defined by
the current locale.
Finally, all `plural` methods must have an `other` case supplied which will be
executed if none of the other cases match.
## Syntax
The syntax for the formatting language used is drawn from other languages, so it
@ -396,7 +326,7 @@ actual grammar for the formatting syntax is:
```text
format_string := <text> [ format <text> ] *
format := '{' [ argument ] [ ':' format_spec ] [ ',' function_spec ] '}'
format := '{' [ argument ] [ ':' format_spec ] '}'
argument := integer | identifier
format_spec := [[fill]align][sign]['#'][0][width]['.' precision][type]
@ -408,13 +338,6 @@ precision := count | '*'
type := identifier | ''
count := parameter | integer
parameter := integer '$'
function_spec := plural | select
select := 'select' ',' ( identifier arm ) *
plural := 'plural' ',' [ 'offset:' integer ] ( selector arm ) *
selector := '=' integer | keyword
keyword := 'zero' | 'one' | 'two' | 'few' | 'many' | 'other'
arm := '{' format_string '}'
```
## Formatting Parameters
@ -483,10 +406,9 @@ should be printed.
## Escaping
The literal characters `{`, `}`, or `#` may be included in a string by
preceding them with the `\` character. Since `\` is already an
escape character in Rust strings, a string literal using this escape
will look like `"\\{"`.
The literal characters `{` and `}` may be included in a string by preceding them
with the same character. For example, the `{` character is escaped with `{{` and
the `}` character is escaped with `}}`.
*/

View File

@ -899,10 +899,16 @@ pub fn make_non_verbatim(path: &Path) -> Option<Path> {
// \\?\D:\
Path::new(repr.slice_from(4))
}
#[cfg(stage0)]
Some(VerbatimUNCPrefix(_,_)) => {
// \\?\UNC\server\share
Path::new(format!(r"\\{}", repr.slice_from(7)))
}
#[cfg(not(stage0))]
Some(VerbatimUNCPrefix(_,_)) => {
// \\?\UNC\server\share
Path::new(format!(r"\{}", repr.slice_from(7)))
}
};
if new_path.prefix.is_none() {
// \\?\UNC\server is a VerbatimUNCPrefix

View File

@ -32,6 +32,7 @@ pub struct CrateId {
}
impl fmt::Show for CrateId {
#[cfg(stage0)]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
try!(write!(f, "{}", self.path));
let version = match self.version {
@ -47,6 +48,22 @@ impl fmt::Show for CrateId {
write!(f, "\\#{}:{}", self.name, version)
}
}
#[cfg(not(stage0))]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
try!(write!(f, "{}", self.path));
let version = match self.version {
None => "0.0",
Some(ref version) => version.as_slice(),
};
if self.path == self.name ||
self.path
.as_slice()
.ends_with(format!("/{}", self.name).as_slice()) {
write!(f, "#{}", version)
} else {
write!(f, "#{}:{}", self.name, version)
}
}
}
impl FromStr for CrateId {

View File

@ -143,6 +143,7 @@ pub fn expand_asm(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
inputs.push((constraint, input));
}
}
#[cfg(stage0)]
Clobbers => {
let mut clobs = Vec::new();
while p.token != token::EOF &&
@ -164,6 +165,28 @@ pub fn expand_asm(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
cons = clobs.connect(",");
}
#[cfg(not(stage0))]
Clobbers => {
let mut clobs = Vec::new();
while p.token != token::EOF &&
p.token != token::COLON &&
p.token != token::MOD_SEP {
if clobs.len() != 0 {
p.eat(&token::COMMA);
}
let (s, _str_style) = p.parse_str();
let clob = format!("~{{{}}}", s);
clobs.push(clob);
if OPTIONS.iter().any(|opt| s.equiv(opt)) {
cx.span_warn(p.last_span, "expected a clobber, but found an option");
}
}
cons = clobs.connect(",");
}
Options => {
let (option, _str_style) = p.parse_str();

View File

@ -100,7 +100,7 @@ fn show_substructure(cx: &mut ExtCtxt, span: Span,
} else {
// normal struct/struct variant
format_string.push_str(" \\{");
format_string.push_str(" {{");
for (i, field) in fields.iter().enumerate() {
if i != 0 { format_string.push_str(","); }
@ -113,7 +113,7 @@ fn show_substructure(cx: &mut ExtCtxt, span: Span,
exprs.push(field.self_);
}
format_string.push_str(" \\}");
format_string.push_str(" }}");
}
}
_ => unreachable!()

View File

@ -19,7 +19,7 @@ use parse::token;
use rsparse = parse;
use parse = fmt_macros;
use std::collections::{HashMap, HashSet};
use std::collections::HashMap;
use std::gc::Gc;
#[deriving(PartialEq)]
@ -165,13 +165,6 @@ impl<'a, 'b> Context<'a, 'b> {
fn verify_piece(&mut self, p: &parse::Piece) {
match *p {
parse::String(..) => {}
parse::CurrentArgument => {
if self.nest_level == 0 {
self.ecx.span_err(self.fmtsp,
"`#` reference used with nothing to \
reference back to");
}
}
parse::Argument(ref arg) => {
// width/precision first, if they have implicit positional
// parameters it makes more sense to consume them first.
@ -192,24 +185,12 @@ impl<'a, 'b> Context<'a, 'b> {
parse::ArgumentNamed(s) => Named(s.to_string()),
};
// and finally the method being applied
match arg.method {
None => {
let ty = Known(arg.format.ty.to_string());
self.verify_arg_type(pos, ty);
}
Some(ref method) => { self.verify_method(pos, *method); }
}
let ty = Known(arg.format.ty.to_string());
self.verify_arg_type(pos, ty);
}
}
}
fn verify_pieces(&mut self, pieces: &[parse::Piece]) {
for piece in pieces.iter() {
self.verify_piece(piece);
}
}
fn verify_count(&mut self, c: parse::Count) {
match c {
parse::CountImplied | parse::CountIs(..) => {}
@ -238,53 +219,6 @@ impl<'a, 'b> Context<'a, 'b> {
}
}
fn verify_method(&mut self, pos: Position, m: &parse::Method) {
self.nest_level += 1;
match *m {
parse::Plural(_, ref arms, ref default) => {
let mut seen_cases = HashSet::new();
self.verify_arg_type(pos, Unsigned);
for arm in arms.iter() {
if !seen_cases.insert(arm.selector) {
match arm.selector {
parse::Keyword(name) => {
self.ecx.span_err(self.fmtsp,
format!("duplicate \
selector `{}`",
name).as_slice());
}
parse::Literal(idx) => {
self.ecx.span_err(self.fmtsp,
format!("duplicate \
selector `={}`",
idx).as_slice());
}
}
}
self.verify_pieces(arm.result.as_slice());
}
self.verify_pieces(default.as_slice());
}
parse::Select(ref arms, ref default) => {
self.verify_arg_type(pos, String);
let mut seen_cases = HashSet::new();
for arm in arms.iter() {
if !seen_cases.insert(arm.selector) {
self.ecx.span_err(self.fmtsp,
format!("duplicate selector `{}`",
arm.selector).as_slice());
} else if arm.selector == "" {
self.ecx.span_err(self.fmtsp,
"empty selector in `select`");
}
self.verify_pieces(arm.result.as_slice());
}
self.verify_pieces(default.as_slice());
}
}
self.nest_level -= 1;
}
fn verify_arg_type(&mut self, arg: Position, ty: ArgumentType) {
match arg {
Exact(arg) => {
@ -400,23 +334,6 @@ impl<'a, 'b> Context<'a, 'b> {
self.ecx.ident_of("rt"), self.ecx.ident_of(s))
}
fn none(&self) -> Gc<ast::Expr> {
let none = self.ecx.path_global(self.fmtsp, vec!(
self.ecx.ident_of("std"),
self.ecx.ident_of("option"),
self.ecx.ident_of("None")));
self.ecx.expr_path(none)
}
fn some(&self, e: Gc<ast::Expr>) -> Gc<ast::Expr> {
let p = self.ecx.path_global(self.fmtsp, vec!(
self.ecx.ident_of("std"),
self.ecx.ident_of("option"),
self.ecx.ident_of("Some")));
let p = self.ecx.expr_path(p);
self.ecx.expr_call(self.fmtsp, p, vec!(e))
}
fn trans_count(&self, c: parse::Count) -> Gc<ast::Expr> {
let sp = self.fmtsp;
match c {
@ -448,86 +365,6 @@ impl<'a, 'b> Context<'a, 'b> {
}
}
fn trans_method(&mut self, method: &parse::Method) -> Gc<ast::Expr> {
let sp = self.fmtsp;
let method = match *method {
parse::Select(ref arms, ref default) => {
let arms = arms.iter().map(|arm| {
let p = self.ecx.path_global(sp, self.rtpath("SelectArm"));
let result = arm.result.iter().map(|p| {
self.trans_piece(p)
}).collect();
let s = token::intern_and_get_ident(arm.selector);
let selector = self.ecx.expr_str(sp, s);
self.ecx.expr_struct(sp, p, vec!(
self.ecx.field_imm(sp,
self.ecx.ident_of("selector"),
selector),
self.ecx.field_imm(sp, self.ecx.ident_of("result"),
self.ecx.expr_vec_slice(sp, result))))
}).collect();
let default = default.iter().map(|p| {
self.trans_piece(p)
}).collect();
self.ecx.expr_call_global(sp, self.rtpath("Select"), vec!(
self.ecx.expr_vec_slice(sp, arms),
self.ecx.expr_vec_slice(sp, default)))
}
parse::Plural(offset, ref arms, ref default) => {
let offset = match offset {
Some(i) => { self.some(self.ecx.expr_uint(sp, i)) }
None => { self.none() }
};
let arms = arms.iter().map(|arm| {
let p = self.ecx.path_global(sp, self.rtpath("PluralArm"));
let result = arm.result.iter().map(|p| {
self.trans_piece(p)
}).collect();
let (lr, selarg) = match arm.selector {
parse::Keyword(t) => {
let p = self.rtpath(t.to_str().as_slice());
let p = self.ecx.path_global(sp, p);
(self.rtpath("Keyword"), self.ecx.expr_path(p))
}
parse::Literal(i) => {
(self.rtpath("Literal"), self.ecx.expr_uint(sp, i))
}
};
let selector = self.ecx.expr_call_global(sp,
lr, vec!(selarg));
self.ecx.expr_struct(sp, p, vec!(
self.ecx.field_imm(sp,
self.ecx.ident_of("selector"),
selector),
self.ecx.field_imm(sp, self.ecx.ident_of("result"),
self.ecx.expr_vec_slice(sp, result))))
}).collect();
let default = default.iter().map(|p| {
self.trans_piece(p)
}).collect();
self.ecx.expr_call_global(sp, self.rtpath("Plural"), vec!(
offset,
self.ecx.expr_vec_slice(sp, arms),
self.ecx.expr_vec_slice(sp, default)))
}
};
let life = self.ecx.lifetime(sp, self.ecx.ident_of("static").name);
let ty = self.ecx.ty_path(self.ecx.path_all(
sp,
true,
self.rtpath("Method"),
vec!(life),
Vec::new()
), None);
let st = ast::ItemStatic(ty, ast::MutImmutable, method);
let static_name = self.ecx.ident_of(format!("__STATIC_METHOD_{}",
self.method_statics
.len()).as_slice());
let item = self.ecx.item(sp, static_name, self.static_attrs(), st);
self.method_statics.push(item);
self.ecx.expr_ident(sp, static_name)
}
/// Translate a `parse::Piece` to a static `rt::Piece`
fn trans_piece(&mut self, piece: &parse::Piece) -> Gc<ast::Expr> {
let sp = self.fmtsp;
@ -540,10 +377,6 @@ impl<'a, 'b> Context<'a, 'b> {
self.ecx.expr_str(sp, s)
))
}
parse::CurrentArgument => {
let nil = self.ecx.expr_lit(sp, ast::LitNil);
self.ecx.expr_call_global(sp, self.rtpath("CurrentArgument"), vec!(nil))
}
parse::Argument(ref arg) => {
// Translate the position
let pos = match arg.position {
@ -596,19 +429,10 @@ impl<'a, 'b> Context<'a, 'b> {
self.ecx.field_imm(sp, self.ecx.ident_of("precision"), prec),
self.ecx.field_imm(sp, self.ecx.ident_of("width"), width)));
// Translate the method (if any)
let method = match arg.method {
None => { self.none() }
Some(ref m) => {
let m = self.trans_method(*m);
self.some(self.ecx.expr_addr_of(sp, m))
}
};
let path = self.ecx.path_global(sp, self.rtpath("Argument"));
let s = self.ecx.expr_struct(sp, path, vec!(
self.ecx.field_imm(sp, self.ecx.ident_of("position"), pos),
self.ecx.field_imm(sp, self.ecx.ident_of("format"), fmt),
self.ecx.field_imm(sp, self.ecx.ident_of("method"), method)));
self.ecx.field_imm(sp, self.ecx.ident_of("format"), fmt)));
self.ecx.expr_call_global(sp, self.rtpath("Argument"), vec!(s))
}
}

View File

@ -129,11 +129,13 @@ fn generic_extension(cx: &ExtCtxt,
rhses: &[Rc<NamedMatch>])
-> Box<MacResult> {
if cx.trace_macros() {
println!("{}! \\{ {} \\}",
println!("{}! {} {} {}",
token::get_ident(name),
"{",
print::pprust::tt_to_str(&TTDelim(Rc::new(arg.iter()
.map(|x| (*x).clone())
.collect()))));
.collect()))),
"}");
}
// Which arm's failure should we report? (the one furthest along)

View File

@ -89,11 +89,18 @@ impl<'a> ParserAttr for Parser<'a> {
let hi = self.span.hi;
(mk_sp(lo, hi), meta_item, style)
}
#[cfg(stage0)]
_ => {
let token_str = self.this_token_to_str();
self.fatal(format!("expected `\\#` but found `{}`",
token_str).as_slice());
}
#[cfg(not(stage0))]
_ => {
let token_str = self.this_token_to_str();
self.fatal(format!("expected `#` but found `{}`",
token_str).as_slice());
}
};
if permit_inner && self.eat(&token::SEMI) {

View File

@ -1208,11 +1208,18 @@ impl<'a> Parser<'a> {
})
}
#[cfg(stage0)]
_ => {
let token_str = p.this_token_to_str();
p.fatal((format!("expected `;` or `\\{` but found `{}`",
token_str)).as_slice())
}
#[cfg(not(stage0))]
_ => {
let token_str = p.this_token_to_str();
p.fatal((format!("expected `;` or `{{` but found `{}`",
token_str)).as_slice())
}
}
})
}
@ -2738,7 +2745,7 @@ impl<'a> Parser<'a> {
self.bump();
if self.token != token::RBRACE {
let token_str = self.this_token_to_str();
self.fatal(format!("expected `\\}`, found `{}`",
self.fatal(format!("expected `{}`, found `{}`", "}",
token_str).as_slice())
}
etc = true;
@ -3148,6 +3155,7 @@ impl<'a> Parser<'a> {
// consuming more tokens).
let (bra, ket) = match token::close_delimiter_for(&self.token) {
Some(ket) => (self.token.clone(), ket),
#[cfg(stage0)]
None => {
// we only expect an ident if we didn't parse one
// above.
@ -3161,6 +3169,20 @@ impl<'a> Parser<'a> {
ident_str,
tok_str).as_slice())
}
#[cfg(not(stage0))]
None => {
// we only expect an ident if we didn't parse one
// above.
let ident_str = if id == token::special_idents::invalid {
"identifier, "
} else {
""
};
let tok_str = self.this_token_to_str();
self.fatal(format!("expected {}`(` or `{{`, but found `{}`",
ident_str,
tok_str).as_slice())
}
};
let tts = self.parse_unspanned_seq(
@ -4040,8 +4062,8 @@ impl<'a> Parser<'a> {
fields = Vec::new();
} else {
let token_str = self.this_token_to_str();
self.fatal(format!("expected `\\{`, `(`, or `;` after struct \
name but found `{}`",
self.fatal(format!("expected `{}`, `(`, or `;` after struct \
name but found `{}`", "{",
token_str).as_slice())
}
@ -4068,12 +4090,20 @@ impl<'a> Parser<'a> {
self.bump();
}
token::RBRACE => {}
#[cfg(stage0)]
_ => {
let token_str = self.this_token_to_str();
self.span_fatal(self.span,
format!("expected `,`, or `\\}` but found `{}`",
token_str).as_slice())
}
#[cfg(not(stage0))]
_ => {
let token_str = self.this_token_to_str();
self.span_fatal(self.span,
format!("expected `,`, or `}}` but found `{}`",
token_str).as_slice())
}
}
a_var
}
@ -4683,7 +4713,7 @@ impl<'a> Parser<'a> {
let token_str = self.this_token_to_str();
self.span_fatal(self.span,
format!("expected `\\{` or `fn` but found `{}`",
format!("expected `{}` or `fn` but found `{}`", "{",
token_str).as_slice());
}

View File

@ -645,15 +645,15 @@ mod test {
fn test_comparison_ops() {
let v = [('<', [1u8, 0u8, 0u8]), ('=', [0u8, 1u8, 0u8]), ('>', [0u8, 0u8, 1u8])];
for &(op, bs) in v.iter() {
let s = format!("%\\{1\\}%\\{2\\}%{}%d", op);
let s = format!("%{{1}}%{{2}}%{}%d", op);
let res = expand(s.as_bytes(), [], &mut Variables::new());
assert!(res.is_ok(), res.unwrap_err());
assert_eq!(res.unwrap(), vec!('0' as u8 + bs[0]));
let s = format!("%\\{1\\}%\\{1\\}%{}%d", op);
let s = format!("%{{1}}%{{1}}%{}%d", op);
let res = expand(s.as_bytes(), [], &mut Variables::new());
assert!(res.is_ok(), res.unwrap_err());
assert_eq!(res.unwrap(), vec!('0' as u8 + bs[1]));
let s = format!("%\\{2\\}%\\{1\\}%{}%d", op);
let s = format!("%{{2}}%{{1}}%{}%d", op);
let res = expand(s.as_bytes(), [], &mut Variables::new());
assert!(res.is_ok(), res.unwrap_err());
assert_eq!(res.unwrap(), vec!('0' as u8 + bs[2]));

View File

@ -416,7 +416,7 @@ pub fn write_boxplot<T: Float + Show + FromPrimitive>(
v = v + char_step;
c += 1;
}
try!(write!(w, r"\#"));
try!(write!(w, "#"));
c += 1;
while c < range_width && v < q3 {
try!(write!(w, "*"));

View File

@ -845,7 +845,7 @@ impl fmt::Show for Url {
match self.fragment {
Some(ref fragment) => {
write!(f, "\\#{}", encode_component(fragment.as_slice()))
write!(f, "#{}", encode_component(fragment.as_slice()))
}
None => Ok(()),
}
@ -861,7 +861,7 @@ impl fmt::Show for Path {
match self.fragment {
Some(ref fragment) => {
write!(f, "\\#{}", encode_component(fragment.as_slice()))
write!(f, "#{}", encode_component(fragment.as_slice()))
}
None => Ok(())
}

View File

@ -27,47 +27,11 @@ fn main() {
format!("{foo:d} {foo:s}", foo=1); //~ ERROR: redeclared with type `s`
format!("{foo}", foo=1, foo=2); //~ ERROR: duplicate argument
format!("#"); //~ ERROR: `#` reference used
format!("", foo=1, 2); //~ ERROR: positional arguments cannot follow
format!("{0, select, a{} a{} other{}}", "a"); //~ ERROR: duplicate selector
format!("{0, plural, =1{} =1{} other{}}", 1u); //~ ERROR: duplicate selector
format!("{0, plural, one{} one{} other{}}", 1u); //~ ERROR: duplicate selector
// bad syntax of the format string
format!("{"); //~ ERROR: expected `}` but string was terminated
format!("\\ "); //~ ERROR: invalid escape
format!("\\"); //~ ERROR: expected an escape
format!("{0, }", 1); //~ ERROR: expected method
format!("{0, foo}", 1); //~ ERROR: unknown method
format!("{0, select}", "a"); //~ ERROR: expected `,` but found `}`
format!("{0, plural}", 1); //~ ERROR: expected `,` but found `}`
format!("{0, select, a{{}", 1); //~ ERROR: expected `}` but string was terminated
format!("{0, select, {} other{}}", "a"); //~ ERROR: empty selector
format!("{0, select, other{} other{}}", "a"); //~ ERROR: multiple `other`
format!("{0, plural, offset: other{}}", "a"); //~ ERROR: must be an integer
format!("{0, plural, offset 1 other{}}", "a"); //~ ERROR: expected `:` but found `1`
format!("{0, plural, =a{} other{}}", "a"); //~ ERROR: followed by an integer
format!("{0, plural, a{} other{}}", "a"); //~ ERROR: unexpected plural
format!("{0, select, a{}}", "a"); //~ ERROR: must provide an `other`
format!("{0, plural, =1{}}", "a"); //~ ERROR: must provide an `other`
format!("{0, plural, other{{0:s}}}", "a"); //~ ERROR: previously used as
format!("{:s} {0, plural, other{}}", "a"); //~ ERROR: argument used to
format!("{0, select, other{}} \
{0, plural, other{}}", "a");
//~^ ERROR: declared with multiple formats
// It should be illegal to use implicit placement arguments nested inside of
// format strings because otherwise the "internal pointer of which argument
// is next" would be invalidated if different cases had different numbers of
// arguments.
format!("{1, select, other{{}}}", 1, "a"); //~ ERROR: cannot use implicit
format!("{1, plural, other{{}}}", 1, 1); //~ ERROR: cannot use implicit
format!("{0, plural, other{{1:.*d}}}", 1, 2); //~ ERROR: cannot use implicit
format!("foo } bar"); //~ ERROR: unmatched `}` found
format!("foo }"); //~ ERROR: unmatched `}` found

View File

@ -1,14 +0,0 @@
// Copyright 2013 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.
fn main() {
format!("{0, plural, other{}}", "a");
//~^ ERROR: expected uint but found
}

View File

@ -1,14 +0,0 @@
// Copyright 2013 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.
fn main() {
format!("{0, select, other{}}", 2);
//~^ ERROR: mismatched types: expected `&&str` but found `&<generic integer #0>` (expected &-ptr
}

View File

@ -42,7 +42,7 @@ fn main() {
{
let _ = write!(&mut File::create(&main_file).unwrap(),
r"\#![feature(non_ascii_idents)] fn main() \{ {} \}",
"#![feature(non_ascii_idents)] fn main() {{ {} }}",
// random string of length n
range(0, n).map(|_| random_char()).collect::<String>());
}

View File

@ -16,7 +16,7 @@ static y: &'static Pair<'static> = &Pair {a: 15, b: x};
pub fn main() {
println!("x = {}", *x);
println!("y = \\{a: {}, b: {}\\}", y.a, *(y.b));
println!("y = {{a: {}, b: {}}}", y.a, *(y.b));
assert_eq!(*x, 10);
assert_eq!(*(y.b), 10);
}

View File

@ -1,15 +0,0 @@
// Copyright 2013 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.
#![deny(non_uppercase_statics)]
pub fn main() {
println!("I generate statics with {0, select, other{#}}", "weird names");
}

View File

@ -48,7 +48,7 @@ pub fn main() {
// Various edge cases without formats
t!(format!(""), "");
t!(format!("hello"), "hello");
t!(format!("hello \\{"), "hello {");
t!(format!("hello {{"), "hello {");
// default formatters should work
t!(format!("{}", 1.0f32), "1");
@ -81,18 +81,6 @@ pub fn main() {
t!(format!("{foo_bar}", foo_bar=1), "1");
t!(format!("{:d}", 5 + 5), "10");
// Methods should probably work
t!(format!("{0, plural, =1{a#} =2{b#} zero{c#} other{d#}}", 0u), "c0");
t!(format!("{0, plural, =1{a#} =2{b#} zero{c#} other{d#}}", 1u), "a1");
t!(format!("{0, plural, =1{a#} =2{b#} zero{c#} other{d#}}", 2u), "b2");
t!(format!("{0, plural, =1{a#} =2{b#} zero{c#} other{d#}}", 3u), "d3");
t!(format!("{0, select, a{a#} b{b#} c{c#} other{d#}}", "a"), "aa");
t!(format!("{0, select, a{a#} b{b#} c{c#} other{d#}}", "b"), "bb");
t!(format!("{0, select, a{a#} b{b#} c{c#} other{d#}}", "c"), "cc");
t!(format!("{0, select, a{a#} b{b#} c{c#} other{d#}}", "d"), "dd");
t!(format!("{1, select, a{#{0:s}} other{#}}", "b", "a"), "ab");
t!(format!("{1, select, a{#{0}} other{#}}", "c", "b"), "b");
// Formatting strings and their arguments
t!(format!("{:s}", "a"), "a");
t!(format!("{:4s}", "a"), "a ");
@ -136,10 +124,8 @@ pub fn main() {
t!(format!("{:+10.3e}", -1.2345e6f64), " -1.234e6");
// Escaping
t!(format!("\\{"), "{");
t!(format!("\\}"), "}");
t!(format!("\\#"), "#");
t!(format!("\\\\"), "\\");
t!(format!("{{"), "{");
t!(format!("}}"), "}");
test_write();
test_print();

View File

@ -17,7 +17,7 @@ struct Thingy {
impl fmt::Show for Thingy {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "\\{ x: {}, y: {} \\}", self.x, self.y)
write!(f, "{{ x: {}, y: {} }}", self.x, self.y)
}
}

Binary file not shown.