Skip to content

Commit 1b2e05e

Browse files
committed
Use more idiomatic rust, comment for lint logic
1 parent 1a08b17 commit 1b2e05e

File tree

1 file changed

+79
-50
lines changed

1 file changed

+79
-50
lines changed

compiler/rustc_builtin_macros/src/format.rs

+79-50
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ use rustc_lint_defs::builtin::NAMED_ARGUMENTS_USED_POSITIONALLY;
1818
use rustc_lint_defs::{BufferedEarlyLint, BuiltinLintDiagnostics, LintId};
1919
use std::borrow::Cow;
2020
use std::collections::hash_map::Entry;
21-
use std::ops::Deref;
2221

2322
#[derive(PartialEq)]
2423
enum ArgumentType {
@@ -71,14 +70,10 @@ impl PositionalNamedArg {
7170
// In the case of a named argument whose position is implicit, there will not be a span
7271
// to replace. Instead, we insert the name after the `{`, which is the first character
7372
// of arg_span.
74-
if let Some(arg_span) = cx.arg_spans.get(self.cur_piece).copied() {
75-
return Some(Span::new(
76-
arg_span.lo() + BytePos(1),
77-
arg_span.lo() + BytePos(1),
78-
self.positional_named_arg_span.ctxt(),
79-
self.positional_named_arg_span.parent(),
80-
));
81-
}
73+
return cx
74+
.arg_spans
75+
.get(self.cur_piece)
76+
.map(|arg_span| arg_span.with_lo(arg_span.lo() + BytePos(1)).shrink_to_lo());
8277
}
8378

8479
None
@@ -92,6 +87,43 @@ struct PositionalNamedArgsLint {
9287
}
9388

9489
impl PositionalNamedArgsLint {
90+
/// For a given positional argument, check if the index is for a named argument.
91+
///
92+
/// Since positional arguments are required to come before named arguments, if the positional
93+
/// index is greater than or equal to the start of named arguments, we know it's a named
94+
/// argument used positionally.
95+
///
96+
/// Example:
97+
/// println!("{} {} {2}", 0, a=1, b=2);
98+
///
99+
/// In this case, the first piece (`{}`) would be ArgumentImplicitlyIs with an index of 0. The
100+
/// total number of arguments is 3 and the number of named arguments is 2, so the start of named
101+
/// arguments is index 1. Therefore, the index of 0 is okay.
102+
///
103+
/// The second piece (`{}`) would be ArgumentImplicitlyIs with an index of 1, which is the start
104+
/// of named arguments, and so we should add a lint to use the named argument `a`.
105+
///
106+
/// The third piece (`{2}`) would be ArgumentIs with an index of 2, which is greater than the
107+
/// start of named arguments, and so we should add a lint to use the named argument `b`.
108+
///
109+
/// This same check also works for width and precision formatting when either or both are
110+
/// CountIsParam, which contains an index into the arguments.
111+
fn maybe_add_positional_named_arg(
112+
&mut self,
113+
current_positional_arg: usize,
114+
total_args_length: usize,
115+
format_argument_index: usize,
116+
ty: PositionalNamedArgType,
117+
cur_piece: usize,
118+
inner_span_to_replace: Option<rustc_parse_format::InnerSpan>,
119+
names: &FxHashMap<Symbol, (usize, Span)>,
120+
) {
121+
let start_of_named_args = total_args_length - names.len();
122+
if current_positional_arg >= start_of_named_args {
123+
self.maybe_push(format_argument_index, ty, cur_piece, inner_span_to_replace, names)
124+
}
125+
}
126+
95127
/// Try constructing a PositionalNamedArg struct and pushing it into the vec of positional
96128
/// named arguments. If a named arg associated with `format_argument_index` cannot be found,
97129
/// a new item will not be added as the lint cannot be emitted in this case.
@@ -100,30 +132,30 @@ impl PositionalNamedArgsLint {
100132
format_argument_index: usize,
101133
ty: PositionalNamedArgType,
102134
cur_piece: usize,
103-
mut inner_span_to_replace: Option<rustc_parse_format::InnerSpan>,
135+
inner_span_to_replace: Option<rustc_parse_format::InnerSpan>,
104136
names: &FxHashMap<Symbol, (usize, Span)>,
105137
) {
106138
let named_arg = names
107139
.iter()
108-
.find(|name| name.deref().1.0 == format_argument_index)
140+
.find(|&(_, &(index, _))| index == format_argument_index)
109141
.map(|found| found.clone());
110142

111-
if let Some(named_arg) = named_arg {
143+
if let Some((&replacement, &(_, positional_named_arg_span))) = named_arg {
112144
// In FormatSpec, `precision_span` starts at the leading `.`, which we want to keep in
113145
// the lint suggestion, so increment `start` by 1 when `PositionalArgumentType` is
114146
// `Precision`.
115-
if ty == PositionalNamedArgType::Precision {
116-
inner_span_to_replace = inner_span_to_replace.map(|mut is| {
117-
is.start += 1;
118-
is
119-
});
120-
}
147+
let inner_span_to_replace = if ty == PositionalNamedArgType::Precision {
148+
inner_span_to_replace
149+
.map(|is| rustc_parse_format::InnerSpan { start: is.start + 1, end: is.end })
150+
} else {
151+
inner_span_to_replace
152+
};
121153
self.positional_named_args.push(PositionalNamedArg {
122154
ty,
123155
cur_piece,
124156
inner_span_to_replace,
125-
replacement: named_arg.0.clone(),
126-
positional_named_arg_span: named_arg.1.1.clone(),
157+
replacement,
158+
positional_named_arg_span,
127159
});
128160
}
129161
}
@@ -386,30 +418,28 @@ impl<'a, 'b> Context<'a, 'b> {
386418
// it's written second, so it should come after width/precision.
387419
let pos = match arg.position {
388420
parse::ArgumentIs(i, arg_end) => {
389-
let start_of_named_args = self.args.len() - self.names.len();
390-
if self.curpiece >= start_of_named_args {
391-
self.unused_names_lint.maybe_push(
392-
i,
393-
PositionalNamedArgType::Arg,
394-
self.curpiece,
395-
arg_end,
396-
&self.names,
397-
);
398-
}
421+
self.unused_names_lint.maybe_add_positional_named_arg(
422+
i,
423+
self.args.len(),
424+
i,
425+
PositionalNamedArgType::Arg,
426+
self.curpiece,
427+
arg_end,
428+
&self.names,
429+
);
399430

400431
Exact(i)
401432
}
402433
parse::ArgumentImplicitlyIs(i) => {
403-
let start_of_named_args = self.args.len() - self.names.len();
404-
if self.curpiece >= start_of_named_args {
405-
self.unused_names_lint.maybe_push(
406-
i,
407-
PositionalNamedArgType::Arg,
408-
self.curpiece,
409-
None,
410-
&self.names,
411-
);
412-
}
434+
self.unused_names_lint.maybe_add_positional_named_arg(
435+
i,
436+
self.args.len(),
437+
i,
438+
PositionalNamedArgType::Arg,
439+
self.curpiece,
440+
None,
441+
&self.names,
442+
);
413443
Exact(i)
414444
}
415445
parse::ArgumentNamed(s, span) => {
@@ -491,16 +521,15 @@ impl<'a, 'b> Context<'a, 'b> {
491521
match c {
492522
parse::CountImplied | parse::CountIs(..) => {}
493523
parse::CountIsParam(i) => {
494-
let start_of_named_args = self.args.len() - self.names.len();
495-
if i >= start_of_named_args {
496-
self.unused_names_lint.maybe_push(
497-
i,
498-
named_arg_type,
499-
self.curpiece,
500-
inner_span.clone(),
501-
&self.names,
502-
);
503-
}
524+
self.unused_names_lint.maybe_add_positional_named_arg(
525+
i,
526+
self.args.len(),
527+
i,
528+
named_arg_type,
529+
self.curpiece,
530+
*inner_span,
531+
&self.names,
532+
);
504533
self.verify_arg_type(Exact(i), Count);
505534
}
506535
parse::CountIsName(s, span) => {

0 commit comments

Comments
 (0)