Auto merge of #99263 - compiler-errors:issue-99261, r=jyn514
Fix ICE in `named_arguments_used_positionally` lint Fixes #99261 Fixes #99289 Fixes #99284 Fixes #99273 Fixes #99297 Fixes #99271 This match pattern: ``` FormatSpec { width: Count::CountIsName(s, _), .. } | FormatSpec { precision: Count::CountIsName(s, _), .. } ``` does not account for when both `width` and `precision` are both `Count::CountIsName`, so split the check for these two fields into two separate `if let`. Also, remove any future potential for ICEs by removing the index operator altogether. --- It is still suspicious that this indexing was broken and caused the ICE, as opposed to just causing a spurious lint message. cc `@PrestonFrom,` who may be familiar with this code because of implementing the lint this touches, perhaps you'd like to look into why named arguments in `FormatSpec.precision` seem to have indices that don't correspond to a span in `Context.arg_spans`? Edit: Opened #99265 to track a (related?) incorrect argument indexing issue.
This commit is contained in:
commit
56351589f8
@ -16,7 +16,7 @@
|
||||
|
||||
use rustc_lint_defs::builtin::NAMED_ARGUMENTS_USED_POSITIONALLY;
|
||||
use rustc_lint_defs::{BufferedEarlyLint, BuiltinLintDiagnostics, LintId};
|
||||
use rustc_parse_format::{Count, FormatSpec};
|
||||
use rustc_parse_format::Count;
|
||||
use std::borrow::Cow;
|
||||
use std::collections::hash_map::Entry;
|
||||
|
||||
@ -985,20 +985,19 @@ fn lint_named_arguments_used_positionally(
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
match a.format {
|
||||
FormatSpec { width: Count::CountIsName(s, _), .. }
|
||||
| FormatSpec { precision: Count::CountIsName(s, _), .. } => {
|
||||
used_argument_names.insert(s);
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
if let Count::CountIsName(s, _) = a.format.width {
|
||||
used_argument_names.insert(s);
|
||||
}
|
||||
if let Count::CountIsName(s, _) = a.format.precision {
|
||||
used_argument_names.insert(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (symbol, (index, span)) in names {
|
||||
if !used_argument_names.contains(symbol.as_str()) {
|
||||
let msg = format!("named argument `{}` is not used by name", symbol.as_str());
|
||||
let arg_span = cx.arg_spans[index];
|
||||
let arg_span = cx.arg_spans.get(index).copied();
|
||||
cx.ecx.buffered_early_lint.push(BufferedEarlyLint {
|
||||
span: MultiSpan::from_span(span),
|
||||
msg: msg.clone(),
|
||||
|
@ -858,15 +858,16 @@ fn lookup_with_diagnostics(
|
||||
},
|
||||
BuiltinLintDiagnostics::NamedArgumentUsedPositionally(positional_arg, named_arg, name) => {
|
||||
db.span_label(named_arg, "this named argument is only referred to by position in formatting string");
|
||||
let msg = format!("this formatting argument uses named argument `{}` by position", name);
|
||||
db.span_label(positional_arg, msg);
|
||||
db.span_suggestion_verbose(
|
||||
positional_arg,
|
||||
"use the named argument by name to avoid ambiguity",
|
||||
format!("{{{}}}", name),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
|
||||
if let Some(positional_arg) = positional_arg {
|
||||
let msg = format!("this formatting argument uses named argument `{}` by position", name);
|
||||
db.span_label(positional_arg, msg);
|
||||
db.span_suggestion_verbose(
|
||||
positional_arg,
|
||||
"use the named argument by name to avoid ambiguity",
|
||||
format!("{{{}}}", name),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Rewrap `db`, and pass control to the user.
|
||||
|
@ -467,7 +467,7 @@ pub enum BuiltinLintDiagnostics {
|
||||
/// If true, the lifetime will be fully elided.
|
||||
use_span: Option<(Span, bool)>,
|
||||
},
|
||||
NamedArgumentUsedPositionally(Span, Span, String),
|
||||
NamedArgumentUsedPositionally(Option<Span>, Span, String),
|
||||
}
|
||||
|
||||
/// Lints that are buffered up early on in the `Session` before the
|
||||
|
17
src/test/ui/macros/issue-99261.rs
Normal file
17
src/test/ui/macros/issue-99261.rs
Normal file
@ -0,0 +1,17 @@
|
||||
// check-pass
|
||||
|
||||
#![deny(named_arguments_used_positionally)]
|
||||
|
||||
fn main() {
|
||||
let value: f64 = 314.15926;
|
||||
let digits_before_decimal = 1;
|
||||
let digits_after_decimal = 2;
|
||||
let width = digits_before_decimal + 1 + digits_after_decimal;
|
||||
|
||||
println!(
|
||||
"{value:0>width$.digits_after_decimal$}",
|
||||
value = value,
|
||||
width = width,
|
||||
digits_after_decimal = digits_after_decimal,
|
||||
);
|
||||
}
|
Loading…
Reference in New Issue
Block a user