]> git.lizzy.rs Git - rust.git/commitdiff
Fix `match_str_case_mismatch` false positives
authorMike Welsh <mwelsh@gmail.com>
Sat, 23 Oct 2021 06:47:38 +0000 (23:47 -0700)
committerMike Welsh <mwelsh@gmail.com>
Sat, 23 Oct 2021 09:03:15 +0000 (02:03 -0700)
Properly consider uncased and titlecased characters.
Fixes #7863.

clippy_lints/src/match_str_case_mismatch.rs
tests/ui/match_str_case_mismatch.rs
tests/ui/match_str_case_mismatch.stderr

index a83f38e3d516e5c74c345cc2de119f57468710e2..f501593c5187e36e99b823f0a1a6919df425bc86 100644 (file)
@@ -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()),
index 208a4bba3d23c40d5cf2cbe4a2f650c18ba584b5..ac555c87d83b21a14beecece000d2cd7a55cbbdf 100644 (file)
@@ -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";
 
index fa023477a9c334d20c7a934e93091b270bd41bf0..92baa40ef28f06f99746326de19b31e53055d703 100644 (file)
@@ -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