Skip to content

Commit 06b034a

Browse files
committed
format: remove all implicit ref handling outside of libfmt_macros
format: beautifully get rid of ArgumentNext and CountIsNextParam Now that CountIsNextParam and ArgumentNext are resolved during parse, the need for handling them outside of libfmt_macros is obviated. Note: *one* instance of implicit reference handling still remains, and that's for implementing `all_args_simple`. It's trivial enough though, so in this case it may be tolerable.
1 parent 71949f3 commit 06b034a

File tree

3 files changed

+36
-54
lines changed

3 files changed

+36
-54
lines changed

src/libfmt_macros/lib.rs

Lines changed: 23 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,6 @@ pub struct FormatSpec<'a> {
8080
/// Enum describing where an argument for a format can be located.
8181
#[derive(Copy, Clone, PartialEq)]
8282
pub enum Position<'a> {
83-
/// The argument will be in the next position. This is the default.
84-
ArgumentNext,
8583
/// The argument is located at a specific index.
8684
ArgumentIs(usize),
8785
/// The argument has a name.
@@ -127,8 +125,6 @@ pub enum Count<'a> {
127125
CountIsName(&'a str),
128126
/// The count is specified by the argument at the given index.
129127
CountIsParam(usize),
130-
/// The count is specified by the next parameter.
131-
CountIsNextParam,
132128
/// The count is implied and cannot be explicitly specified.
133129
CountImplied,
134130
}
@@ -262,37 +258,18 @@ impl<'a> Parser<'a> {
262258
/// Parses an Argument structure, or what's contained within braces inside
263259
/// the format string
264260
fn argument(&mut self) -> Argument<'a> {
265-
let mut pos = self.position();
266-
let mut format = self.format();
267-
268-
// Resolve CountIsNextParam's into absolute references.
269-
// Current argument's position must be known so this is done after
270-
// format parsing.
271-
// Curiously, currently {:.*} for named arguments is implemented,
272-
// and it consumes a positional arg slot just like a positional {:.*}
273-
// does. The current behavior is reproduced to prevent any
274-
// incompatibilities.
275-
match format.precision {
276-
CountIsNextParam => {
277-
// eat the current implicit arg
278-
let i = self.curarg;
279-
self.curarg += 1;
280-
format.precision = CountIsParam(i);
281-
}
282-
_ => {}
283-
}
261+
let pos = self.position();
262+
let format = self.format();
284263

285-
// Resolve ArgumentNext's into absolute references.
286-
// This must come after count resolution because we may consume one
287-
// more arg if precision is CountIsNextParam.
288-
match pos {
289-
ArgumentNext => {
264+
// Resolve position after parsing format spec.
265+
let pos = match pos {
266+
Some(position) => position,
267+
None => {
290268
let i = self.curarg;
291269
self.curarg += 1;
292-
pos = ArgumentIs(i);
270+
ArgumentIs(i)
293271
}
294-
_ => {}
295-
}
272+
};
296273

297274
Argument {
298275
position: pos,
@@ -302,13 +279,19 @@ impl<'a> Parser<'a> {
302279

303280
/// Parses a positional argument for a format. This could either be an
304281
/// integer index of an argument, a named argument, or a blank string.
305-
fn position(&mut self) -> Position<'a> {
282+
/// Returns `Some(parsed_position)` if the position is not implicitly
283+
/// consuming a macro argument, `None` if it's the case.
284+
fn position(&mut self) -> Option<Position<'a>> {
306285
if let Some(i) = self.integer() {
307-
ArgumentIs(i)
286+
Some(ArgumentIs(i))
308287
} else {
309288
match self.cur.peek() {
310-
Some(&(_, c)) if c.is_alphabetic() => ArgumentNamed(self.word()),
311-
_ => ArgumentNext,
289+
Some(&(_, c)) if c.is_alphabetic() => Some(ArgumentNamed(self.word())),
290+
291+
// This is an `ArgumentNext`.
292+
// Record the fact and do the resolution after parsing the
293+
// format spec, to make things like `{:.*}` work.
294+
_ => None,
312295
}
313296
}
314297
}
@@ -375,7 +358,11 @@ impl<'a> Parser<'a> {
375358
}
376359
if self.consume('.') {
377360
if self.consume('*') {
378-
spec.precision = CountIsNextParam;
361+
// Resolve `CountIsNextParam`.
362+
// We can do this immediately as `position` is resolved later.
363+
let i = self.curarg;
364+
self.curarg += 1;
365+
spec.precision = CountIsParam(i);
379366
} else {
380367
spec.precision = self.count();
381368
}

src/librustc_typeck/check/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -881,7 +881,7 @@ fn check_on_unimplemented<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
881881
}
882882
},
883883
// `{:1}` and `{}` are not to be used
884-
Position::ArgumentIs(_) | Position::ArgumentNext => {
884+
Position::ArgumentIs(_) => {
885885
span_err!(ccx.tcx.sess, attr.span, E0231,
886886
"only named substitution \
887887
parameters are allowed");

src/libsyntax_ext/format.rs

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,10 @@ struct Context<'a, 'b:'a> {
6868

6969
name_positions: HashMap<String, usize>,
7070

71-
/// Updated as arguments are consumed
72-
next_arg: usize,
71+
/// Current position of the implicit positional arg pointer, as if it
72+
/// still existed in this phase of processing.
73+
/// Used only for `all_pieces_simple` tracking in `trans_piece`.
74+
curarg: usize,
7375
}
7476

7577
/// Parses the arguments from the given list of tokens, returning None
@@ -159,11 +161,6 @@ impl<'a, 'b> Context<'a, 'b> {
159161
// argument second, if it's an implicit positional parameter
160162
// it's written second, so it should come after width/precision.
161163
let pos = match arg.position {
162-
parse::ArgumentNext => {
163-
let i = self.next_arg;
164-
self.next_arg += 1;
165-
Exact(i)
166-
}
167164
parse::ArgumentIs(i) => Exact(i),
168165
parse::ArgumentNamed(s) => Named(s.to_string()),
169166
};
@@ -183,11 +180,6 @@ impl<'a, 'b> Context<'a, 'b> {
183180
parse::CountIsName(s) => {
184181
self.verify_arg_type(Named(s.to_string()), Unsigned);
185182
}
186-
parse::CountIsNextParam => {
187-
let next_arg = self.next_arg;
188-
self.verify_arg_type(Exact(next_arg), Unsigned);
189-
self.next_arg += 1;
190-
}
191183
}
192184
}
193185

@@ -309,7 +301,6 @@ impl<'a, 'b> Context<'a, 'b> {
309301
count("Param", Some(self.ecx.expr_usize(sp, i)))
310302
}
311303
parse::CountImplied => count("Implied", None),
312-
parse::CountIsNextParam => count("NextParam", None),
313304
parse::CountIsName(n) => {
314305
let i = match self.name_positions.get(n) {
315306
Some(&i) => i,
@@ -355,8 +346,6 @@ impl<'a, 'b> Context<'a, 'b> {
355346
}
356347
};
357348
match arg.position {
358-
// These two have a direct mapping
359-
parse::ArgumentNext => pos("Next", None),
360349
parse::ArgumentIs(i) => pos("At", Some(i)),
361350

362351
// Named arguments are converted to positional arguments
@@ -373,7 +362,13 @@ impl<'a, 'b> Context<'a, 'b> {
373362
};
374363

375364
let simple_arg = parse::Argument {
376-
position: parse::ArgumentNext,
365+
position: {
366+
// We don't have ArgumentNext any more, so we have to
367+
// track the current argument ourselves.
368+
let i = self.curarg;
369+
self.curarg += 1;
370+
parse::ArgumentIs(i)
371+
},
377372
format: parse::FormatSpec {
378373
fill: arg.format.fill,
379374
align: parse::AlignUnknown,
@@ -640,7 +635,7 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, sp: Span,
640635
name_positions: HashMap::new(),
641636
name_types: HashMap::new(),
642637
name_ordering: name_ordering,
643-
next_arg: 0,
638+
curarg: 0,
644639
literal: String::new(),
645640
pieces: Vec::new(),
646641
str_pieces: Vec::new(),

0 commit comments

Comments
 (0)