Extend is_case_difference to handle digit-letter confusables
Signed-off-by: xizheyin <xizheyin@smail.nju.edu.cn>
This commit is contained in:
@@ -262,19 +262,11 @@ pub trait Emitter {
|
|||||||
format!("help: {msg}")
|
format!("help: {msg}")
|
||||||
} else {
|
} else {
|
||||||
// Show the default suggestion text with the substitution
|
// Show the default suggestion text with the substitution
|
||||||
format!(
|
let confusion_type = self
|
||||||
"help: {}{}: `{}`",
|
|
||||||
msg,
|
|
||||||
if self
|
|
||||||
.source_map()
|
.source_map()
|
||||||
.is_some_and(|sm| is_case_difference(sm, snippet, part.span,))
|
.map(|sm| detect_confusion_type(sm, snippet, part.span))
|
||||||
{
|
.unwrap_or(ConfusionType::None);
|
||||||
" (notice the capitalization)"
|
format!("help: {}{}: `{}`", msg, confusion_type.label_text(), snippet,)
|
||||||
} else {
|
|
||||||
""
|
|
||||||
},
|
|
||||||
snippet,
|
|
||||||
)
|
|
||||||
};
|
};
|
||||||
primary_span.push_span_label(part.span, msg);
|
primary_span.push_span_label(part.span, msg);
|
||||||
|
|
||||||
@@ -2028,12 +2020,12 @@ impl HumanEmitter {
|
|||||||
buffer.append(0, ": ", Style::HeaderMsg);
|
buffer.append(0, ": ", Style::HeaderMsg);
|
||||||
|
|
||||||
let mut msg = vec![(suggestion.msg.to_owned(), Style::NoStyle)];
|
let mut msg = vec![(suggestion.msg.to_owned(), Style::NoStyle)];
|
||||||
if suggestions
|
if let Some(confusion_type) =
|
||||||
.iter()
|
suggestions.iter().take(MAX_SUGGESTIONS).find_map(|(_, _, _, confusion_type)| {
|
||||||
.take(MAX_SUGGESTIONS)
|
if confusion_type.has_confusion() { Some(*confusion_type) } else { None }
|
||||||
.any(|(_, _, _, only_capitalization)| *only_capitalization)
|
})
|
||||||
{
|
{
|
||||||
msg.push((" (notice the capitalization difference)".into(), Style::NoStyle));
|
msg.push((confusion_type.label_text().into(), Style::NoStyle));
|
||||||
}
|
}
|
||||||
self.msgs_to_buffer(
|
self.msgs_to_buffer(
|
||||||
&mut buffer,
|
&mut buffer,
|
||||||
@@ -3528,24 +3520,107 @@ pub fn is_different(sm: &SourceMap, suggested: &str, sp: Span) -> bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Whether the original and suggested code are visually similar enough to warrant extra wording.
|
/// Whether the original and suggested code are visually similar enough to warrant extra wording.
|
||||||
pub fn is_case_difference(sm: &SourceMap, suggested: &str, sp: Span) -> bool {
|
pub fn detect_confusion_type(sm: &SourceMap, suggested: &str, sp: Span) -> ConfusionType {
|
||||||
// FIXME: this should probably be extended to also account for `FO0` → `FOO` and unicode.
|
|
||||||
let found = match sm.span_to_snippet(sp) {
|
let found = match sm.span_to_snippet(sp) {
|
||||||
Ok(snippet) => snippet,
|
Ok(snippet) => snippet,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
warn!(error = ?e, "Invalid span {:?}", sp);
|
warn!(error = ?e, "Invalid span {:?}", sp);
|
||||||
return false;
|
return ConfusionType::None;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let mut has_case_confusion = false;
|
||||||
|
let mut has_digit_letter_confusion = false;
|
||||||
|
|
||||||
|
if found.len() == suggested.len() {
|
||||||
|
let mut has_case_diff = false;
|
||||||
|
let mut has_digit_letter_confusable = false;
|
||||||
|
let mut has_other_diff = false;
|
||||||
|
|
||||||
let ascii_confusables = &['c', 'f', 'i', 'k', 'o', 's', 'u', 'v', 'w', 'x', 'y', 'z'];
|
let ascii_confusables = &['c', 'f', 'i', 'k', 'o', 's', 'u', 'v', 'w', 'x', 'y', 'z'];
|
||||||
// All the chars that differ in capitalization are confusable (above):
|
|
||||||
let confusable = iter::zip(found.chars(), suggested.chars())
|
let digit_letter_confusables = [('0', 'O'), ('1', 'l'), ('5', 'S'), ('8', 'B'), ('9', 'g')];
|
||||||
.filter(|(f, s)| f != s)
|
|
||||||
.all(|(f, s)| ascii_confusables.contains(&f) || ascii_confusables.contains(&s));
|
for (f, s) in iter::zip(found.chars(), suggested.chars()) {
|
||||||
confusable && found.to_lowercase() == suggested.to_lowercase()
|
if f != s {
|
||||||
// FIXME: We sometimes suggest the same thing we already have, which is a
|
if f.to_lowercase().to_string() == s.to_lowercase().to_string() {
|
||||||
// bug, but be defensive against that here.
|
// Check for case differences (any character that differs only in case)
|
||||||
&& found != suggested
|
if ascii_confusables.contains(&f) || ascii_confusables.contains(&s) {
|
||||||
|
has_case_diff = true;
|
||||||
|
} else {
|
||||||
|
has_other_diff = true;
|
||||||
|
}
|
||||||
|
} else if digit_letter_confusables.contains(&(f, s))
|
||||||
|
|| digit_letter_confusables.contains(&(s, f))
|
||||||
|
{
|
||||||
|
// Check for digit-letter confusables (like 0 vs O, 1 vs l, etc.)
|
||||||
|
has_digit_letter_confusable = true;
|
||||||
|
} else {
|
||||||
|
has_other_diff = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we have case differences and no other differences
|
||||||
|
if has_case_diff && !has_other_diff && found != suggested {
|
||||||
|
has_case_confusion = true;
|
||||||
|
}
|
||||||
|
if has_digit_letter_confusable && !has_other_diff && found != suggested {
|
||||||
|
has_digit_letter_confusion = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
match (has_case_confusion, has_digit_letter_confusion) {
|
||||||
|
(true, true) => ConfusionType::Both,
|
||||||
|
(true, false) => ConfusionType::Case,
|
||||||
|
(false, true) => ConfusionType::DigitLetter,
|
||||||
|
(false, false) => ConfusionType::None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Represents the type of confusion detected between original and suggested code.
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
pub enum ConfusionType {
|
||||||
|
/// No confusion detected
|
||||||
|
None,
|
||||||
|
/// Only case differences (e.g., "hello" vs "Hello")
|
||||||
|
Case,
|
||||||
|
/// Only digit-letter confusion (e.g., "0" vs "O", "1" vs "l")
|
||||||
|
DigitLetter,
|
||||||
|
/// Both case and digit-letter confusion
|
||||||
|
Both,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ConfusionType {
|
||||||
|
/// Returns the appropriate label text for this confusion type.
|
||||||
|
pub fn label_text(&self) -> &'static str {
|
||||||
|
match self {
|
||||||
|
ConfusionType::None => "",
|
||||||
|
ConfusionType::Case => " (notice the capitalization)",
|
||||||
|
ConfusionType::DigitLetter => " (notice the digit/letter confusion)",
|
||||||
|
ConfusionType::Both => " (notice the capitalization and digit/letter confusion)",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Combines two confusion types. If either is `Both`, the result is `Both`.
|
||||||
|
/// If one is `Case` and the other is `DigitLetter`, the result is `Both`.
|
||||||
|
/// Otherwise, returns the non-`None` type, or `None` if both are `None`.
|
||||||
|
pub fn combine(self, other: ConfusionType) -> ConfusionType {
|
||||||
|
match (self, other) {
|
||||||
|
(ConfusionType::None, other) => other,
|
||||||
|
(this, ConfusionType::None) => this,
|
||||||
|
(ConfusionType::Both, _) | (_, ConfusionType::Both) => ConfusionType::Both,
|
||||||
|
(ConfusionType::Case, ConfusionType::DigitLetter)
|
||||||
|
| (ConfusionType::DigitLetter, ConfusionType::Case) => ConfusionType::Both,
|
||||||
|
(ConfusionType::Case, ConfusionType::Case) => ConfusionType::Case,
|
||||||
|
(ConfusionType::DigitLetter, ConfusionType::DigitLetter) => ConfusionType::DigitLetter,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns true if this confusion type represents any kind of confusion.
|
||||||
|
pub fn has_confusion(&self) -> bool {
|
||||||
|
*self != ConfusionType::None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn should_show_source_code(
|
pub(crate) fn should_show_source_code(
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ pub use diagnostic_impls::{
|
|||||||
IndicateAnonymousLifetime, SingleLabelManySpans,
|
IndicateAnonymousLifetime, SingleLabelManySpans,
|
||||||
};
|
};
|
||||||
pub use emitter::ColorConfig;
|
pub use emitter::ColorConfig;
|
||||||
use emitter::{DynEmitter, Emitter, is_case_difference, is_different};
|
use emitter::{ConfusionType, DynEmitter, Emitter, detect_confusion_type, is_different};
|
||||||
use rustc_data_structures::AtomicRef;
|
use rustc_data_structures::AtomicRef;
|
||||||
use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
|
use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
|
||||||
use rustc_data_structures::stable_hasher::StableHasher;
|
use rustc_data_structures::stable_hasher::StableHasher;
|
||||||
@@ -308,7 +308,7 @@ impl CodeSuggestion {
|
|||||||
pub(crate) fn splice_lines(
|
pub(crate) fn splice_lines(
|
||||||
&self,
|
&self,
|
||||||
sm: &SourceMap,
|
sm: &SourceMap,
|
||||||
) -> Vec<(String, Vec<SubstitutionPart>, Vec<Vec<SubstitutionHighlight>>, bool)> {
|
) -> Vec<(String, Vec<SubstitutionPart>, Vec<Vec<SubstitutionHighlight>>, ConfusionType)> {
|
||||||
// For the `Vec<Vec<SubstitutionHighlight>>` value, the first level of the vector
|
// For the `Vec<Vec<SubstitutionHighlight>>` value, the first level of the vector
|
||||||
// corresponds to the output snippet's lines, while the second level corresponds to the
|
// corresponds to the output snippet's lines, while the second level corresponds to the
|
||||||
// substrings within that line that should be highlighted.
|
// substrings within that line that should be highlighted.
|
||||||
@@ -414,14 +414,15 @@ impl CodeSuggestion {
|
|||||||
// We need to keep track of the difference between the existing code and the added
|
// We need to keep track of the difference between the existing code and the added
|
||||||
// or deleted code in order to point at the correct column *after* substitution.
|
// or deleted code in order to point at the correct column *after* substitution.
|
||||||
let mut acc = 0;
|
let mut acc = 0;
|
||||||
let mut only_capitalization = false;
|
let mut confusion_type = ConfusionType::None;
|
||||||
for part in &mut substitution.parts {
|
for part in &mut substitution.parts {
|
||||||
// If this is a replacement of, e.g. `"a"` into `"ab"`, adjust the
|
// If this is a replacement of, e.g. `"a"` into `"ab"`, adjust the
|
||||||
// suggestion and snippet to look as if we just suggested to add
|
// suggestion and snippet to look as if we just suggested to add
|
||||||
// `"b"`, which is typically much easier for the user to understand.
|
// `"b"`, which is typically much easier for the user to understand.
|
||||||
part.trim_trivial_replacements(sm);
|
part.trim_trivial_replacements(sm);
|
||||||
|
|
||||||
only_capitalization |= is_case_difference(sm, &part.snippet, part.span);
|
let part_confusion = detect_confusion_type(sm, &part.snippet, part.span);
|
||||||
|
confusion_type = confusion_type.combine(part_confusion);
|
||||||
let cur_lo = sm.lookup_char_pos(part.span.lo());
|
let cur_lo = sm.lookup_char_pos(part.span.lo());
|
||||||
if prev_hi.line == cur_lo.line {
|
if prev_hi.line == cur_lo.line {
|
||||||
let mut count =
|
let mut count =
|
||||||
@@ -511,7 +512,7 @@ impl CodeSuggestion {
|
|||||||
if highlights.iter().all(|parts| parts.is_empty()) {
|
if highlights.iter().all(|parts| parts.is_empty()) {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
Some((buf, substitution.parts, highlights, only_capitalization))
|
Some((buf, substitution.parts, highlights, confusion_type))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ error: this `match` arm has a differing case than its expression
|
|||||||
LL | "~!@#$%^&*()-_=+Foo" => {},
|
LL | "~!@#$%^&*()-_=+Foo" => {},
|
||||||
| ^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
help: consider changing the case of this arm to respect `to_ascii_lowercase` (notice the capitalization difference)
|
help: consider changing the case of this arm to respect `to_ascii_lowercase` (notice the capitalization)
|
||||||
|
|
|
|
||||||
LL - "~!@#$%^&*()-_=+Foo" => {},
|
LL - "~!@#$%^&*()-_=+Foo" => {},
|
||||||
LL + "~!@#$%^&*()-_=+foo" => {},
|
LL + "~!@#$%^&*()-_=+foo" => {},
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ help: use struct literal syntax instead
|
|||||||
LL - let f = Foo();
|
LL - let f = Foo();
|
||||||
LL + let f = Foo { a: val };
|
LL + let f = Foo { a: val };
|
||||||
|
|
|
|
||||||
help: a function with a similar name exists (notice the capitalization difference)
|
help: a function with a similar name exists (notice the capitalization)
|
||||||
|
|
|
|
||||||
LL - let f = Foo();
|
LL - let f = Foo();
|
||||||
LL + let f = foo();
|
LL + let f = foo();
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ warning: const parameter `foo` should have an upper case name
|
|||||||
LL | fn foo<const foo: u32>() {
|
LL | fn foo<const foo: u32>() {
|
||||||
| ^^^
|
| ^^^
|
||||||
|
|
|
|
||||||
help: convert the identifier to upper case (notice the capitalization difference)
|
help: convert the identifier to upper case (notice the capitalization)
|
||||||
|
|
|
|
||||||
LL - fn foo<const foo: u32>() {
|
LL - fn foo<const foo: u32>() {
|
||||||
LL + fn foo<const FOO: u32>() {
|
LL + fn foo<const FOO: u32>() {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ error: keyword `use` is written in the wrong case
|
|||||||
LL | Use std::ptr::read;
|
LL | Use std::ptr::read;
|
||||||
| ^^^
|
| ^^^
|
||||||
|
|
|
|
||||||
help: write it in the correct case (notice the capitalization difference)
|
help: write it in the correct case (notice the capitalization)
|
||||||
|
|
|
|
||||||
LL - Use std::ptr::read;
|
LL - Use std::ptr::read;
|
||||||
LL + use std::ptr::read;
|
LL + use std::ptr::read;
|
||||||
@@ -28,7 +28,7 @@ error: keyword `fn` is written in the wrong case
|
|||||||
LL | async Fn _a() {}
|
LL | async Fn _a() {}
|
||||||
| ^^
|
| ^^
|
||||||
|
|
|
|
||||||
help: write it in the correct case (notice the capitalization difference)
|
help: write it in the correct case (notice the capitalization)
|
||||||
|
|
|
|
||||||
LL - async Fn _a() {}
|
LL - async Fn _a() {}
|
||||||
LL + async fn _a() {}
|
LL + async fn _a() {}
|
||||||
@@ -40,7 +40,7 @@ error: keyword `fn` is written in the wrong case
|
|||||||
LL | Fn _b() {}
|
LL | Fn _b() {}
|
||||||
| ^^
|
| ^^
|
||||||
|
|
|
|
||||||
help: write it in the correct case (notice the capitalization difference)
|
help: write it in the correct case (notice the capitalization)
|
||||||
|
|
|
|
||||||
LL - Fn _b() {}
|
LL - Fn _b() {}
|
||||||
LL + fn _b() {}
|
LL + fn _b() {}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ error: expected identifier, found keyword `fn`
|
|||||||
LL | fn _f<F: fn(), G>(_: impl fn(), _: &dyn fn())
|
LL | fn _f<F: fn(), G>(_: impl fn(), _: &dyn fn())
|
||||||
| ^^
|
| ^^
|
||||||
|
|
|
|
||||||
help: use `Fn` to refer to the trait (notice the capitalization difference)
|
help: use `Fn` to refer to the trait (notice the capitalization)
|
||||||
|
|
|
|
||||||
LL - fn _f<F: fn(), G>(_: impl fn(), _: &dyn fn())
|
LL - fn _f<F: fn(), G>(_: impl fn(), _: &dyn fn())
|
||||||
LL + fn _f<F: Fn(), G>(_: impl fn(), _: &dyn fn())
|
LL + fn _f<F: Fn(), G>(_: impl fn(), _: &dyn fn())
|
||||||
@@ -16,7 +16,7 @@ error: expected identifier, found keyword `fn`
|
|||||||
LL | fn _f<F: fn(), G>(_: impl fn(), _: &dyn fn())
|
LL | fn _f<F: fn(), G>(_: impl fn(), _: &dyn fn())
|
||||||
| ^^
|
| ^^
|
||||||
|
|
|
|
||||||
help: use `Fn` to refer to the trait (notice the capitalization difference)
|
help: use `Fn` to refer to the trait (notice the capitalization)
|
||||||
|
|
|
|
||||||
LL - fn _f<F: fn(), G>(_: impl fn(), _: &dyn fn())
|
LL - fn _f<F: fn(), G>(_: impl fn(), _: &dyn fn())
|
||||||
LL + fn _f<F: fn(), G>(_: impl Fn(), _: &dyn fn())
|
LL + fn _f<F: fn(), G>(_: impl Fn(), _: &dyn fn())
|
||||||
@@ -28,7 +28,7 @@ error: expected identifier, found keyword `fn`
|
|||||||
LL | fn _f<F: fn(), G>(_: impl fn(), _: &dyn fn())
|
LL | fn _f<F: fn(), G>(_: impl fn(), _: &dyn fn())
|
||||||
| ^^
|
| ^^
|
||||||
|
|
|
|
||||||
help: use `Fn` to refer to the trait (notice the capitalization difference)
|
help: use `Fn` to refer to the trait (notice the capitalization)
|
||||||
|
|
|
|
||||||
LL - fn _f<F: fn(), G>(_: impl fn(), _: &dyn fn())
|
LL - fn _f<F: fn(), G>(_: impl fn(), _: &dyn fn())
|
||||||
LL + fn _f<F: fn(), G>(_: impl fn(), _: &dyn Fn())
|
LL + fn _f<F: fn(), G>(_: impl fn(), _: &dyn Fn())
|
||||||
@@ -40,7 +40,7 @@ error: expected identifier, found keyword `fn`
|
|||||||
LL | G: fn(),
|
LL | G: fn(),
|
||||||
| ^^
|
| ^^
|
||||||
|
|
|
|
||||||
help: use `Fn` to refer to the trait (notice the capitalization difference)
|
help: use `Fn` to refer to the trait (notice the capitalization)
|
||||||
|
|
|
|
||||||
LL - G: fn(),
|
LL - G: fn(),
|
||||||
LL + G: Fn(),
|
LL + G: Fn(),
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ error: expected one of `!`, `(`, `+`, `::`, `<`, `where`, or `{`, found keyword
|
|||||||
LL | Where for<'a> F: Fn(&'a (u8, u16)) -> &'a u8,
|
LL | Where for<'a> F: Fn(&'a (u8, u16)) -> &'a u8,
|
||||||
| ^^^ expected one of 7 possible tokens
|
| ^^^ expected one of 7 possible tokens
|
||||||
|
|
|
|
||||||
help: write keyword `where` in lowercase (notice the capitalization difference)
|
help: write keyword `where` in lowercase (notice the capitalization)
|
||||||
|
|
|
|
||||||
LL - Where for<'a> F: Fn(&'a (u8, u16)) -> &'a u8,
|
LL - Where for<'a> F: Fn(&'a (u8, u16)) -> &'a u8,
|
||||||
LL + where for<'a> F: Fn(&'a (u8, u16)) -> &'a u8,
|
LL + where for<'a> F: Fn(&'a (u8, u16)) -> &'a u8,
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ error: expected one of `!`, `(`, `+`, `::`, `<`, `where`, or `{`, found `Display
|
|||||||
LL | fn code() -> Impl Display {}
|
LL | fn code() -> Impl Display {}
|
||||||
| ^^^^^^^ expected one of 7 possible tokens
|
| ^^^^^^^ expected one of 7 possible tokens
|
||||||
|
|
|
|
||||||
help: write keyword `impl` in lowercase (notice the capitalization difference)
|
help: write keyword `impl` in lowercase (notice the capitalization)
|
||||||
|
|
|
|
||||||
LL - fn code() -> Impl Display {}
|
LL - fn code() -> Impl Display {}
|
||||||
LL + fn code() -> impl Display {}
|
LL + fn code() -> impl Display {}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ error: expected one of `!` or `::`, found `a`
|
|||||||
LL | Static a = 0;
|
LL | Static a = 0;
|
||||||
| ^ expected one of `!` or `::`
|
| ^ expected one of `!` or `::`
|
||||||
|
|
|
|
||||||
help: write keyword `static` in lowercase (notice the capitalization difference)
|
help: write keyword `static` in lowercase (notice the capitalization)
|
||||||
|
|
|
|
||||||
LL - Static a = 0;
|
LL - Static a = 0;
|
||||||
LL + static a = 0;
|
LL + static a = 0;
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ error: expected one of `!` or `::`, found `Foor`
|
|||||||
LL | Struct Foor {
|
LL | Struct Foor {
|
||||||
| ^^^^ expected one of `!` or `::`
|
| ^^^^ expected one of `!` or `::`
|
||||||
|
|
|
|
||||||
help: write keyword `struct` in lowercase (notice the capitalization difference)
|
help: write keyword `struct` in lowercase (notice the capitalization)
|
||||||
|
|
|
|
||||||
LL - Struct Foor {
|
LL - Struct Foor {
|
||||||
LL + struct Foor {
|
LL + struct Foor {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ error: expected identifier, found keyword `fn`
|
|||||||
LL | fn foo(_: impl fn() -> i32) {}
|
LL | fn foo(_: impl fn() -> i32) {}
|
||||||
| ^^
|
| ^^
|
||||||
|
|
|
|
||||||
help: use `Fn` to refer to the trait (notice the capitalization difference)
|
help: use `Fn` to refer to the trait (notice the capitalization)
|
||||||
|
|
|
|
||||||
LL - fn foo(_: impl fn() -> i32) {}
|
LL - fn foo(_: impl fn() -> i32) {}
|
||||||
LL + fn foo(_: impl Fn() -> i32) {}
|
LL + fn foo(_: impl Fn() -> i32) {}
|
||||||
@@ -16,7 +16,7 @@ error: expected identifier, found keyword `fn`
|
|||||||
LL | fn foo2<T: fn(i32)>(_: T) {}
|
LL | fn foo2<T: fn(i32)>(_: T) {}
|
||||||
| ^^
|
| ^^
|
||||||
|
|
|
|
||||||
help: use `Fn` to refer to the trait (notice the capitalization difference)
|
help: use `Fn` to refer to the trait (notice the capitalization)
|
||||||
|
|
|
|
||||||
LL - fn foo2<T: fn(i32)>(_: T) {}
|
LL - fn foo2<T: fn(i32)>(_: T) {}
|
||||||
LL + fn foo2<T: Fn(i32)>(_: T) {}
|
LL + fn foo2<T: Fn(i32)>(_: T) {}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ error: `const` keyword was mistyped as `Const`
|
|||||||
LL | pub fn foo<Const N: u8>() {}
|
LL | pub fn foo<Const N: u8>() {}
|
||||||
| ^^^^^
|
| ^^^^^
|
||||||
|
|
|
|
||||||
help: use the `const` keyword (notice the capitalization difference)
|
help: use the `const` keyword (notice the capitalization)
|
||||||
|
|
|
|
||||||
LL - pub fn foo<Const N: u8>() {}
|
LL - pub fn foo<Const N: u8>() {}
|
||||||
LL + pub fn foo<const N: u8>() {}
|
LL + pub fn foo<const N: u8>() {}
|
||||||
@@ -16,7 +16,7 @@ error: `const` keyword was mistyped as `Const`
|
|||||||
LL | pub fn baz<Const N: u8, T>() {}
|
LL | pub fn baz<Const N: u8, T>() {}
|
||||||
| ^^^^^
|
| ^^^^^
|
||||||
|
|
|
|
||||||
help: use the `const` keyword (notice the capitalization difference)
|
help: use the `const` keyword (notice the capitalization)
|
||||||
|
|
|
|
||||||
LL - pub fn baz<Const N: u8, T>() {}
|
LL - pub fn baz<Const N: u8, T>() {}
|
||||||
LL + pub fn baz<const N: u8, T>() {}
|
LL + pub fn baz<const N: u8, T>() {}
|
||||||
@@ -28,7 +28,7 @@ error: `const` keyword was mistyped as `Const`
|
|||||||
LL | pub fn qux<T, Const N: u8>() {}
|
LL | pub fn qux<T, Const N: u8>() {}
|
||||||
| ^^^^^
|
| ^^^^^
|
||||||
|
|
|
|
||||||
help: use the `const` keyword (notice the capitalization difference)
|
help: use the `const` keyword (notice the capitalization)
|
||||||
|
|
|
|
||||||
LL - pub fn qux<T, Const N: u8>() {}
|
LL - pub fn qux<T, Const N: u8>() {}
|
||||||
LL + pub fn qux<T, const N: u8>() {}
|
LL + pub fn qux<T, const N: u8>() {}
|
||||||
@@ -40,7 +40,7 @@ error: `const` keyword was mistyped as `Const`
|
|||||||
LL | pub fn quux<T, Const N: u8, U>() {}
|
LL | pub fn quux<T, Const N: u8, U>() {}
|
||||||
| ^^^^^
|
| ^^^^^
|
||||||
|
|
|
|
||||||
help: use the `const` keyword (notice the capitalization difference)
|
help: use the `const` keyword (notice the capitalization)
|
||||||
|
|
|
|
||||||
LL - pub fn quux<T, Const N: u8, U>() {}
|
LL - pub fn quux<T, Const N: u8, U>() {}
|
||||||
LL + pub fn quux<T, const N: u8, U>() {}
|
LL + pub fn quux<T, const N: u8, U>() {}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ LL | let x: i32 = MyS::foo;
|
|||||||
|
|
|
|
||||||
= note: expected type `i32`
|
= note: expected type `i32`
|
||||||
found fn item `fn() -> MyS {MyS::foo}`
|
found fn item `fn() -> MyS {MyS::foo}`
|
||||||
help: try referring to the associated const `FOO` instead (notice the capitalization difference)
|
help: try referring to the associated const `FOO` instead (notice the capitalization)
|
||||||
|
|
|
|
||||||
LL - let x: i32 = MyS::foo;
|
LL - let x: i32 = MyS::foo;
|
||||||
LL + let x: i32 = MyS::FOO;
|
LL + let x: i32 = MyS::FOO;
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ error[E0425]: cannot find value `False` in this scope
|
|||||||
LL | let y = False;
|
LL | let y = False;
|
||||||
| ^^^^^ not found in this scope
|
| ^^^^^ not found in this scope
|
||||||
|
|
|
|
||||||
help: you may want to use a bool value instead (notice the capitalization difference)
|
help: you may want to use a bool value instead (notice the capitalization)
|
||||||
|
|
|
|
||||||
LL - let y = False;
|
LL - let y = False;
|
||||||
LL + let y = false;
|
LL + let y = false;
|
||||||
|
|||||||
57
tests/ui/suggestions/case-difference-suggestions.rs
Normal file
57
tests/ui/suggestions/case-difference-suggestions.rs
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
fn main() {
|
||||||
|
|
||||||
|
// Simple case difference, no hit
|
||||||
|
let hello = "hello";
|
||||||
|
println!("{}", Hello); //~ ERROR cannot find value `Hello` in this scope
|
||||||
|
|
||||||
|
// Multiple case differences, hit
|
||||||
|
let myVariable = 10;
|
||||||
|
println!("{}", myvariable); //~ ERROR cannot find value `myvariable` in this scope
|
||||||
|
|
||||||
|
// Case difference with special characters, hit
|
||||||
|
let user_name = "john";
|
||||||
|
println!("{}", User_Name); //~ ERROR cannot find value `User_Name` in this scope
|
||||||
|
|
||||||
|
// All uppercase vs all lowercase, hit
|
||||||
|
let FOO = 42;
|
||||||
|
println!("{}", foo); //~ ERROR cannot find value `foo` in this scope
|
||||||
|
|
||||||
|
|
||||||
|
// 0 vs O
|
||||||
|
let FFO0 = 100;
|
||||||
|
println!("{}", FFOO); //~ ERROR cannot find value `FFOO` in this scope
|
||||||
|
|
||||||
|
let l1st = vec![1, 2, 3];
|
||||||
|
println!("{}", list); //~ ERROR cannot find value `list` in this scope
|
||||||
|
|
||||||
|
let S5 = "test";
|
||||||
|
println!("{}", SS); //~ ERROR cannot find value `SS` in this scope
|
||||||
|
|
||||||
|
let aS5 = "test";
|
||||||
|
println!("{}", a55); //~ ERROR cannot find value `a55` in this scope
|
||||||
|
|
||||||
|
let B8 = 8;
|
||||||
|
println!("{}", BB); //~ ERROR cannot find value `BB` in this scope
|
||||||
|
|
||||||
|
let g9 = 9;
|
||||||
|
println!("{}", gg); //~ ERROR cannot find value `gg` in this scope
|
||||||
|
|
||||||
|
let o1d = "old";
|
||||||
|
println!("{}", old); //~ ERROR cannot find value `old` in this scope
|
||||||
|
|
||||||
|
let new1 = "new";
|
||||||
|
println!("{}", newl); //~ ERROR cannot find value `newl` in this scope
|
||||||
|
|
||||||
|
let apple = "apple";
|
||||||
|
println!("{}", app1e); //~ ERROR cannot find value `app1e` in this scope
|
||||||
|
|
||||||
|
let a = 1;
|
||||||
|
println!("{}", A); //~ ERROR cannot find value `A` in this scope
|
||||||
|
|
||||||
|
let worldlu = "world";
|
||||||
|
println!("{}", world1U); //~ ERROR cannot find value `world1U` in this scope
|
||||||
|
|
||||||
|
let myV4rlable = 42;
|
||||||
|
println!("{}", myv4r1able); //~ ERROR cannot find value `myv4r1able` in this scope
|
||||||
|
|
||||||
|
}
|
||||||
99
tests/ui/suggestions/case-difference-suggestions.stderr
Normal file
99
tests/ui/suggestions/case-difference-suggestions.stderr
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
error[E0425]: cannot find value `Hello` in this scope
|
||||||
|
--> $DIR/case-difference-suggestions.rs:5:20
|
||||||
|
|
|
||||||
|
LL | println!("{}", Hello);
|
||||||
|
| ^^^^^ help: a local variable with a similar name exists: `hello`
|
||||||
|
|
||||||
|
error[E0425]: cannot find value `myvariable` in this scope
|
||||||
|
--> $DIR/case-difference-suggestions.rs:9:20
|
||||||
|
|
|
||||||
|
LL | println!("{}", myvariable);
|
||||||
|
| ^^^^^^^^^^ help: a local variable with a similar name exists (notice the capitalization): `myVariable`
|
||||||
|
|
||||||
|
error[E0425]: cannot find value `User_Name` in this scope
|
||||||
|
--> $DIR/case-difference-suggestions.rs:13:20
|
||||||
|
|
|
||||||
|
LL | println!("{}", User_Name);
|
||||||
|
| ^^^^^^^^^ help: a local variable with a similar name exists: `user_name`
|
||||||
|
|
||||||
|
error[E0425]: cannot find value `foo` in this scope
|
||||||
|
--> $DIR/case-difference-suggestions.rs:17:20
|
||||||
|
|
|
||||||
|
LL | println!("{}", foo);
|
||||||
|
| ^^^ help: a local variable with a similar name exists (notice the capitalization): `FOO`
|
||||||
|
|
||||||
|
error[E0425]: cannot find value `FFOO` in this scope
|
||||||
|
--> $DIR/case-difference-suggestions.rs:22:20
|
||||||
|
|
|
||||||
|
LL | println!("{}", FFOO);
|
||||||
|
| ^^^^ help: a local variable with a similar name exists (notice the digit/letter confusion): `FFO0`
|
||||||
|
|
||||||
|
error[E0425]: cannot find value `list` in this scope
|
||||||
|
--> $DIR/case-difference-suggestions.rs:25:20
|
||||||
|
|
|
||||||
|
LL | println!("{}", list);
|
||||||
|
| ^^^^ help: a local variable with a similar name exists: `l1st`
|
||||||
|
|
||||||
|
error[E0425]: cannot find value `SS` in this scope
|
||||||
|
--> $DIR/case-difference-suggestions.rs:28:20
|
||||||
|
|
|
||||||
|
LL | println!("{}", SS);
|
||||||
|
| ^^ help: a local variable with a similar name exists (notice the digit/letter confusion): `S5`
|
||||||
|
|
||||||
|
error[E0425]: cannot find value `a55` in this scope
|
||||||
|
--> $DIR/case-difference-suggestions.rs:31:20
|
||||||
|
|
|
||||||
|
LL | println!("{}", a55);
|
||||||
|
| ^^^ help: a local variable with a similar name exists (notice the digit/letter confusion): `aS5`
|
||||||
|
|
||||||
|
error[E0425]: cannot find value `BB` in this scope
|
||||||
|
--> $DIR/case-difference-suggestions.rs:34:20
|
||||||
|
|
|
||||||
|
LL | println!("{}", BB);
|
||||||
|
| ^^ help: a local variable with a similar name exists (notice the digit/letter confusion): `B8`
|
||||||
|
|
||||||
|
error[E0425]: cannot find value `gg` in this scope
|
||||||
|
--> $DIR/case-difference-suggestions.rs:37:20
|
||||||
|
|
|
||||||
|
LL | println!("{}", gg);
|
||||||
|
| ^^ help: a local variable with a similar name exists (notice the digit/letter confusion): `g9`
|
||||||
|
|
||||||
|
error[E0425]: cannot find value `old` in this scope
|
||||||
|
--> $DIR/case-difference-suggestions.rs:40:20
|
||||||
|
|
|
||||||
|
LL | println!("{}", old);
|
||||||
|
| ^^^ help: a local variable with a similar name exists (notice the digit/letter confusion): `o1d`
|
||||||
|
|
||||||
|
error[E0425]: cannot find value `newl` in this scope
|
||||||
|
--> $DIR/case-difference-suggestions.rs:43:20
|
||||||
|
|
|
||||||
|
LL | println!("{}", newl);
|
||||||
|
| ^^^^ help: a local variable with a similar name exists (notice the digit/letter confusion): `new1`
|
||||||
|
|
||||||
|
error[E0425]: cannot find value `app1e` in this scope
|
||||||
|
--> $DIR/case-difference-suggestions.rs:46:20
|
||||||
|
|
|
||||||
|
LL | println!("{}", app1e);
|
||||||
|
| ^^^^^ help: a local variable with a similar name exists (notice the digit/letter confusion): `apple`
|
||||||
|
|
||||||
|
error[E0425]: cannot find value `A` in this scope
|
||||||
|
--> $DIR/case-difference-suggestions.rs:49:20
|
||||||
|
|
|
||||||
|
LL | println!("{}", A);
|
||||||
|
| ^ help: a local variable with a similar name exists: `a`
|
||||||
|
|
||||||
|
error[E0425]: cannot find value `world1U` in this scope
|
||||||
|
--> $DIR/case-difference-suggestions.rs:52:20
|
||||||
|
|
|
||||||
|
LL | println!("{}", world1U);
|
||||||
|
| ^^^^^^^ help: a local variable with a similar name exists (notice the capitalization and digit/letter confusion): `worldlu`
|
||||||
|
|
||||||
|
error[E0425]: cannot find value `myv4r1able` in this scope
|
||||||
|
--> $DIR/case-difference-suggestions.rs:55:20
|
||||||
|
|
|
||||||
|
LL | println!("{}", myv4r1able);
|
||||||
|
| ^^^^^^^^^^ help: a local variable with a similar name exists (notice the capitalization and digit/letter confusion): `myV4rlable`
|
||||||
|
|
||||||
|
error: aborting due to 16 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0425`.
|
||||||
@@ -455,7 +455,7 @@
|
|||||||
</tspan>
|
</tspan>
|
||||||
<tspan x="10px" y="3916px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
|
<tspan x="10px" y="3916px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
|
||||||
</tspan>
|
</tspan>
|
||||||
<tspan x="10px" y="3934px"><tspan class="fg-ansi256-014 bold">help</tspan><tspan>: there is a variant with a similar name (notice the capitalization difference)</tspan>
|
<tspan x="10px" y="3934px"><tspan class="fg-ansi256-014 bold">help</tspan><tspan>: there is a variant with a similar name (notice the capitalization)</tspan>
|
||||||
</tspan>
|
</tspan>
|
||||||
<tspan x="10px" y="3952px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
|
<tspan x="10px" y="3952px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
|
||||||
</tspan>
|
</tspan>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 82 KiB After Width: | Height: | Size: 82 KiB |
Reference in New Issue
Block a user