Rollup merge of #56820 - ljedrz:format_tweaks, r=alexcrichton
format-related tweaks - remove an unreachable condition - inline one-liners related to `parse_expr` (called in succession) - refactor `report_invalid_references` - refactor `verify_arg_type` - minor stylistic improvements
This commit is contained in:
commit
29aa466508
2 changed files with 55 additions and 81 deletions
|
@ -3062,6 +3062,7 @@ impl<'a> Parser<'a> {
|
||||||
///
|
///
|
||||||
/// This parses an expression accounting for associativity and precedence of the operators in
|
/// This parses an expression accounting for associativity and precedence of the operators in
|
||||||
/// the expression.
|
/// the expression.
|
||||||
|
#[inline]
|
||||||
fn parse_assoc_expr(&mut self,
|
fn parse_assoc_expr(&mut self,
|
||||||
already_parsed_attrs: Option<ThinVec<Attribute>>)
|
already_parsed_attrs: Option<ThinVec<Attribute>>)
|
||||||
-> PResult<'a, P<Expr>> {
|
-> PResult<'a, P<Expr>> {
|
||||||
|
@ -3722,6 +3723,7 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse an expression
|
/// Parse an expression
|
||||||
|
#[inline]
|
||||||
pub fn parse_expr(&mut self) -> PResult<'a, P<Expr>> {
|
pub fn parse_expr(&mut self) -> PResult<'a, P<Expr>> {
|
||||||
self.parse_expr_res(Restrictions::empty(), None)
|
self.parse_expr_res(Restrictions::empty(), None)
|
||||||
}
|
}
|
||||||
|
@ -3741,6 +3743,7 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse an expression, subject to the given restrictions
|
/// Parse an expression, subject to the given restrictions
|
||||||
|
#[inline]
|
||||||
fn parse_expr_res(&mut self, r: Restrictions,
|
fn parse_expr_res(&mut self, r: Restrictions,
|
||||||
already_parsed_attrs: Option<ThinVec<Attribute>>)
|
already_parsed_attrs: Option<ThinVec<Attribute>>)
|
||||||
-> PResult<'a, P<Expr>> {
|
-> PResult<'a, P<Expr>> {
|
||||||
|
|
|
@ -158,28 +158,15 @@ fn parse_args(ecx: &mut ExtCtxt,
|
||||||
} // accept trailing commas
|
} // accept trailing commas
|
||||||
if named || (p.token.is_ident() && p.look_ahead(1, |t| *t == token::Eq)) {
|
if named || (p.token.is_ident() && p.look_ahead(1, |t| *t == token::Eq)) {
|
||||||
named = true;
|
named = true;
|
||||||
let ident = match p.token {
|
let ident = if let token::Ident(i, _) = p.token {
|
||||||
token::Ident(i, _) => {
|
p.bump();
|
||||||
p.bump();
|
i
|
||||||
i
|
} else {
|
||||||
}
|
ecx.span_err(
|
||||||
_ if named => {
|
p.span,
|
||||||
ecx.span_err(
|
"expected ident, positional arguments cannot follow named arguments",
|
||||||
p.span,
|
);
|
||||||
"expected ident, positional arguments cannot follow named arguments",
|
return None;
|
||||||
);
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
ecx.span_err(
|
|
||||||
p.span,
|
|
||||||
&format!(
|
|
||||||
"expected ident for named argument, found `{}`",
|
|
||||||
p.this_token_to_string()
|
|
||||||
),
|
|
||||||
);
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
let name: &str = &ident.as_str();
|
let name: &str = &ident.as_str();
|
||||||
|
|
||||||
|
@ -286,11 +273,11 @@ impl<'a, 'b> Context<'a, 'b> {
|
||||||
} else {
|
} else {
|
||||||
MultiSpan::from_span(self.fmtsp)
|
MultiSpan::from_span(self.fmtsp)
|
||||||
};
|
};
|
||||||
let mut refs: Vec<_> = self
|
let refs_len = self.invalid_refs.len();
|
||||||
|
let mut refs = self
|
||||||
.invalid_refs
|
.invalid_refs
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(r, pos)| (r.to_string(), self.arg_spans.get(*pos)))
|
.map(|(r, pos)| (r.to_string(), self.arg_spans.get(*pos)));
|
||||||
.collect();
|
|
||||||
|
|
||||||
if self.names.is_empty() && !numbered_position_args {
|
if self.names.is_empty() && !numbered_position_args {
|
||||||
e = self.ecx.mut_span_err(
|
e = self.ecx.mut_span_err(
|
||||||
|
@ -303,28 +290,24 @@ impl<'a, 'b> Context<'a, 'b> {
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
let (arg_list, mut sp) = match refs.len() {
|
let (arg_list, mut sp) = if refs_len == 1 {
|
||||||
1 => {
|
let (reg, pos) = refs.next().unwrap();
|
||||||
let (reg, pos) = refs.pop().unwrap();
|
(
|
||||||
(
|
format!("argument {}", reg),
|
||||||
format!("argument {}", reg),
|
MultiSpan::from_span(*pos.unwrap_or(&self.fmtsp)),
|
||||||
MultiSpan::from_span(*pos.unwrap_or(&self.fmtsp)),
|
)
|
||||||
)
|
} else {
|
||||||
}
|
let (mut refs, spans): (Vec<_>, Vec<_>) = refs.unzip();
|
||||||
_ => {
|
let pos = MultiSpan::from_spans(spans.into_iter().map(|s| *s.unwrap()).collect());
|
||||||
let pos =
|
let reg = refs.pop().unwrap();
|
||||||
MultiSpan::from_spans(refs.iter().map(|(_, p)| *p.unwrap()).collect());
|
(
|
||||||
let mut refs: Vec<String> = refs.iter().map(|(s, _)| s.to_owned()).collect();
|
format!(
|
||||||
let reg = refs.pop().unwrap();
|
"arguments {head} and {tail}",
|
||||||
(
|
head = refs.join(", "),
|
||||||
format!(
|
tail = reg,
|
||||||
"arguments {head} and {tail}",
|
),
|
||||||
tail = reg,
|
pos,
|
||||||
head = refs.join(", ")
|
)
|
||||||
),
|
|
||||||
pos,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
if !self.is_literal {
|
if !self.is_literal {
|
||||||
sp = MultiSpan::from_span(self.fmtsp);
|
sp = MultiSpan::from_span(self.fmtsp);
|
||||||
|
@ -353,33 +336,30 @@ impl<'a, 'b> Context<'a, 'b> {
|
||||||
Placeholder(_) => {
|
Placeholder(_) => {
|
||||||
// record every (position, type) combination only once
|
// record every (position, type) combination only once
|
||||||
let ref mut seen_ty = self.arg_unique_types[arg];
|
let ref mut seen_ty = self.arg_unique_types[arg];
|
||||||
let i = match seen_ty.iter().position(|x| *x == ty) {
|
let i = seen_ty.iter().position(|x| *x == ty).unwrap_or_else(|| {
|
||||||
Some(i) => i,
|
let i = seen_ty.len();
|
||||||
None => {
|
seen_ty.push(ty);
|
||||||
let i = seen_ty.len();
|
i
|
||||||
seen_ty.push(ty);
|
});
|
||||||
i
|
|
||||||
}
|
|
||||||
};
|
|
||||||
self.arg_types[arg].push(i);
|
self.arg_types[arg].push(i);
|
||||||
}
|
}
|
||||||
Count => {
|
Count => {
|
||||||
match self.count_positions.entry(arg) {
|
if let Entry::Vacant(e) = self.count_positions.entry(arg) {
|
||||||
Entry::Vacant(e) => {
|
let i = self.count_positions_count;
|
||||||
let i = self.count_positions_count;
|
e.insert(i);
|
||||||
e.insert(i);
|
self.count_args.push(Exact(arg));
|
||||||
self.count_args.push(Exact(arg));
|
self.count_positions_count += 1;
|
||||||
self.count_positions_count += 1;
|
|
||||||
}
|
|
||||||
Entry::Occupied(_) => {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Named(name) => {
|
Named(name) => {
|
||||||
let idx = match self.names.get(&name) {
|
match self.names.get(&name) {
|
||||||
Some(e) => *e,
|
Some(idx) => {
|
||||||
|
// Treat as positional arg.
|
||||||
|
self.verify_arg_type(Exact(*idx), ty)
|
||||||
|
}
|
||||||
None => {
|
None => {
|
||||||
let msg = format!("there is no argument named `{}`", name);
|
let msg = format!("there is no argument named `{}`", name);
|
||||||
let sp = if self.is_literal {
|
let sp = if self.is_literal {
|
||||||
|
@ -389,11 +369,8 @@ impl<'a, 'b> Context<'a, 'b> {
|
||||||
};
|
};
|
||||||
let mut err = self.ecx.struct_span_err(sp, &msg[..]);
|
let mut err = self.ecx.struct_span_err(sp, &msg[..]);
|
||||||
err.emit();
|
err.emit();
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
// Treat as positional arg.
|
|
||||||
self.verify_arg_type(Exact(idx), ty)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -436,12 +413,10 @@ impl<'a, 'b> Context<'a, 'b> {
|
||||||
parse::CountIs(i) => count("Is", Some(self.ecx.expr_usize(sp, i))),
|
parse::CountIs(i) => count("Is", Some(self.ecx.expr_usize(sp, i))),
|
||||||
parse::CountIsParam(i) => {
|
parse::CountIsParam(i) => {
|
||||||
// This needs mapping too, as `i` is referring to a macro
|
// This needs mapping too, as `i` is referring to a macro
|
||||||
// argument.
|
// argument. If `i` is not found in `count_positions` then
|
||||||
let i = match self.count_positions.get(&i) {
|
// the error had already been emitted elsewhere.
|
||||||
Some(&i) => i,
|
let i = self.count_positions.get(&i).cloned().unwrap_or(0)
|
||||||
None => 0, // error already emitted elsewhere
|
+ self.count_args_index_offset;
|
||||||
};
|
|
||||||
let i = i + self.count_args_index_offset;
|
|
||||||
count("Param", Some(self.ecx.expr_usize(sp, i)))
|
count("Param", Some(self.ecx.expr_usize(sp, i)))
|
||||||
}
|
}
|
||||||
parse::CountImplied => count("Implied", None),
|
parse::CountImplied => count("Implied", None),
|
||||||
|
@ -526,10 +501,7 @@ impl<'a, 'b> Context<'a, 'b> {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
let fill = match arg.format.fill {
|
let fill = arg.format.fill.unwrap_or(' ');
|
||||||
Some(c) => c,
|
|
||||||
None => ' ',
|
|
||||||
};
|
|
||||||
|
|
||||||
if *arg != simple_arg || fill != ' ' {
|
if *arg != simple_arg || fill != ' ' {
|
||||||
self.all_pieces_simple = false;
|
self.all_pieces_simple = false;
|
||||||
|
@ -828,8 +800,7 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt,
|
||||||
if !parser.errors.is_empty() {
|
if !parser.errors.is_empty() {
|
||||||
let err = parser.errors.remove(0);
|
let err = parser.errors.remove(0);
|
||||||
let sp = fmt.span.from_inner_byte_pos(err.start, err.end);
|
let sp = fmt.span.from_inner_byte_pos(err.start, err.end);
|
||||||
let mut e = ecx.struct_span_err(sp, &format!("invalid format string: {}",
|
let mut e = ecx.struct_span_err(sp, &format!("invalid format string: {}", err.description));
|
||||||
err.description));
|
|
||||||
e.span_label(sp, err.label + " in format string");
|
e.span_label(sp, err.label + " in format string");
|
||||||
if let Some(note) = err.note {
|
if let Some(note) = err.note {
|
||||||
e.note(¬e);
|
e.note(¬e);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue