Auto merge of #7865 - Herschel:fix-match-str-case-mismatch, r=xFrednet
Fix `match_str_case_mismatch` on uncased chars False positives would result because `char::is_lowercase` and friends will return `false` for non-alphabetic chars and alphabetic chars lacking case (such as CJK scripts). Care also has to be taken for handling titlecase characters (`Dz`) and lowercased chars with no uppercase equivalent (`ʁ`). For example, when verifying lowercase: * Check `!any(char::is_ascii_uppercase)` instead of `all(char::is_ascii_lowercase)` for ASCII. * Check that `all(|c| c.to_lowercase() == c)` instead of `all(char::is_lowercase)` for non-ASCII Fixes #7863. changelog: Fix false positives in [`match_str_case_mismatch`] on uncased characters
This commit is contained in:
commit
cb0132d209
@ -127,10 +127,10 @@ fn get_case_method(segment_ident_str: &str) -> Option<CaseMethod> {
|
||||
|
||||
fn verify_case<'a>(case_method: &'a CaseMethod, arms: &'a [Arm<'_>]) -> Option<(Span, SymbolStr)> {
|
||||
let case_check = match case_method {
|
||||
CaseMethod::LowerCase => |input: &str| -> bool { input.chars().all(char::is_lowercase) },
|
||||
CaseMethod::AsciiLowerCase => |input: &str| -> bool { input.chars().all(|c| matches!(c, 'a'..='z')) },
|
||||
CaseMethod::UpperCase => |input: &str| -> bool { input.chars().all(char::is_uppercase) },
|
||||
CaseMethod::AsciiUppercase => |input: &str| -> bool { input.chars().all(|c| matches!(c, 'A'..='Z')) },
|
||||
CaseMethod::LowerCase => |input: &str| -> bool { input.chars().all(|c| c.to_lowercase().next() == Some(c)) },
|
||||
CaseMethod::AsciiLowerCase => |input: &str| -> bool { !input.chars().any(|c| c.is_ascii_uppercase()) },
|
||||
CaseMethod::UpperCase => |input: &str| -> bool { input.chars().all(|c| c.to_uppercase().next() == Some(c)) },
|
||||
CaseMethod::AsciiUppercase => |input: &str| -> bool { !input.chars().any(|c| c.is_ascii_lowercase()) },
|
||||
};
|
||||
|
||||
for arm in arms {
|
||||
@ -153,7 +153,7 @@ fn verify_case<'a>(case_method: &'a CaseMethod, arms: &'a [Arm<'_>]) -> Option<(
|
||||
|
||||
fn lint(cx: &LateContext<'_>, case_method: &CaseMethod, bad_case_span: Span, bad_case_str: &str) {
|
||||
let (method_str, suggestion) = match case_method {
|
||||
CaseMethod::LowerCase => ("to_lower_case", bad_case_str.to_lowercase()),
|
||||
CaseMethod::LowerCase => ("to_lowercase", bad_case_str.to_lowercase()),
|
||||
CaseMethod::AsciiLowerCase => ("to_ascii_lowercase", bad_case_str.to_ascii_lowercase()),
|
||||
CaseMethod::UpperCase => ("to_uppercase", bad_case_str.to_uppercase()),
|
||||
CaseMethod::AsciiUppercase => ("to_ascii_uppercase", bad_case_str.to_ascii_uppercase()),
|
||||
|
@ -12,6 +12,49 @@ fn as_str_match() {
|
||||
}
|
||||
}
|
||||
|
||||
fn non_alphabetic() {
|
||||
let var = "~!@#$%^&*()-_=+FOO";
|
||||
|
||||
match var.to_ascii_lowercase().as_str() {
|
||||
"1234567890" => {},
|
||||
"~!@#$%^&*()-_=+foo" => {},
|
||||
"\n\r\t\x7F" => {},
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
|
||||
fn unicode_cased() {
|
||||
let var = "ВОДЫ";
|
||||
|
||||
match var.to_lowercase().as_str() {
|
||||
"水" => {},
|
||||
"νερό" => {},
|
||||
"воды" => {},
|
||||
"물" => {},
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
|
||||
fn titlecase() {
|
||||
let var = "BarDz";
|
||||
|
||||
match var.to_lowercase().as_str() {
|
||||
"foolj" => {},
|
||||
"bardz" => {},
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
|
||||
fn no_case_equivalent() {
|
||||
let var = "barʁ";
|
||||
|
||||
match var.to_uppercase().as_str() {
|
||||
"FOOɕ" => {},
|
||||
"BARʁ" => {},
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
|
||||
fn addrof_unary_match() {
|
||||
let var = "BAR";
|
||||
|
||||
@ -70,6 +113,49 @@ fn as_str_match_mismatch() {
|
||||
}
|
||||
}
|
||||
|
||||
fn non_alphabetic_mismatch() {
|
||||
let var = "~!@#$%^&*()-_=+FOO";
|
||||
|
||||
match var.to_ascii_lowercase().as_str() {
|
||||
"1234567890" => {},
|
||||
"~!@#$%^&*()-_=+Foo" => {},
|
||||
"\n\r\t\x7F" => {},
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
|
||||
fn unicode_cased_mismatch() {
|
||||
let var = "ВОДЫ";
|
||||
|
||||
match var.to_lowercase().as_str() {
|
||||
"水" => {},
|
||||
"νερό" => {},
|
||||
"Воды" => {},
|
||||
"물" => {},
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
|
||||
fn titlecase_mismatch() {
|
||||
let var = "BarDz";
|
||||
|
||||
match var.to_lowercase().as_str() {
|
||||
"foolj" => {},
|
||||
"barDz" => {},
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
|
||||
fn no_case_equivalent_mismatch() {
|
||||
let var = "barʁ";
|
||||
|
||||
match var.to_uppercase().as_str() {
|
||||
"FOOɕ" => {},
|
||||
"bARʁ" => {},
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
|
||||
fn addrof_unary_match_mismatch() {
|
||||
let var = "BAR";
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
error: this `match` arm has a differing case than its expression
|
||||
--> $DIR/match_str_case_mismatch.rs:68:9
|
||||
--> $DIR/match_str_case_mismatch.rs:111:9
|
||||
|
|
||||
LL | "Bar" => {},
|
||||
| ^^^^^
|
||||
@ -11,7 +11,51 @@ LL | "bar" => {},
|
||||
| ~~~~~
|
||||
|
||||
error: this `match` arm has a differing case than its expression
|
||||
--> $DIR/match_str_case_mismatch.rs:78:9
|
||||
--> $DIR/match_str_case_mismatch.rs:121:9
|
||||
|
|
||||
LL | "~!@#$%^&*()-_=+Foo" => {},
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: consider changing the case of this arm to respect `to_ascii_lowercase`
|
||||
|
|
||||
LL | "~!@#$%^&*()-_=+foo" => {},
|
||||
| ~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
error: this `match` arm has a differing case than its expression
|
||||
--> $DIR/match_str_case_mismatch.rs:133:9
|
||||
|
|
||||
LL | "Воды" => {},
|
||||
| ^^^^^^
|
||||
|
|
||||
help: consider changing the case of this arm to respect `to_lowercase`
|
||||
|
|
||||
LL | "воды" => {},
|
||||
| ~~~~~~
|
||||
|
||||
error: this `match` arm has a differing case than its expression
|
||||
--> $DIR/match_str_case_mismatch.rs:144:9
|
||||
|
|
||||
LL | "barDz" => {},
|
||||
| ^^^^^^
|
||||
|
|
||||
help: consider changing the case of this arm to respect `to_lowercase`
|
||||
|
|
||||
LL | "bardz" => {},
|
||||
| ~~~~~~
|
||||
|
||||
error: this `match` arm has a differing case than its expression
|
||||
--> $DIR/match_str_case_mismatch.rs:154:9
|
||||
|
|
||||
LL | "bARʁ" => {},
|
||||
| ^^^^^^
|
||||
|
|
||||
help: consider changing the case of this arm to respect `to_uppercase`
|
||||
|
|
||||
LL | "BARʁ" => {},
|
||||
| ~~~~~~
|
||||
|
||||
error: this `match` arm has a differing case than its expression
|
||||
--> $DIR/match_str_case_mismatch.rs:164:9
|
||||
|
|
||||
LL | "Bar" => {},
|
||||
| ^^^^^
|
||||
@ -22,7 +66,7 @@ LL | "bar" => {},
|
||||
| ~~~~~
|
||||
|
||||
error: this `match` arm has a differing case than its expression
|
||||
--> $DIR/match_str_case_mismatch.rs:93:9
|
||||
--> $DIR/match_str_case_mismatch.rs:179:9
|
||||
|
|
||||
LL | "bAR" => {},
|
||||
| ^^^^^
|
||||
@ -32,5 +76,5 @@ help: consider changing the case of this arm to respect `to_ascii_uppercase`
|
||||
LL | "BAR" => {},
|
||||
| ~~~~~
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
error: aborting due to 7 previous errors
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user