Repository: rust-lang/rustfmt (rust)

Issue:
Panicks at match arm that starts with non-ascii char
```rust
enum NonAscii {
    Abcd,
    Éfgh,
}

use NonAscii::*;

fn f(x: NonAscii) -> bool {
    match x {
        Éfgh => true,
        _ => false,
    }
}

fn main() {
    dbg!(f(Abcd));
}
```

Rustfmt on Playground (1.4.37-nightly (2021-06-12 24bdc6d)) fails to format the above code:
```
thread 'main' panicked at 'byte index 109 is not a char boundary; it is inside 'É' (bytes 108..110) of `enum NonAscii {
    Abcd,
    Éfgh,
}

use NonAscii::*;

fn f(x: NonAscii) -> bool {
    match x {
        Éfgh => true,
        _ => false,
    }
}

fn main() {
    dbg!(f(Abcd));
}
`', src/tools/rustfmt/src/visitor.rs:47:15
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
```

Pull request:
Correct approach for detecting leading pipes in match arms
Fixes #4868 

Patch:
diff --git a/src/matches.rs b/src/matches.rs
index f33fedce..140ec226 100644
--- a/src/matches.rs
+++ b/src/matches.rs
@@ -19,7 +19,7 @@ use crate::source_map::SpanUtils;
 use crate::spanned::Spanned;
 use crate::utils::{
     contains_skip, extra_offset, first_line_width, inner_attributes, last_line_extendable, mk_sp,
-    mk_sp_lo_plus_one, semicolon_for_expr, trimmed_last_line_width, unicode_str_width,
+    semicolon_for_expr, trimmed_last_line_width, unicode_str_width,
 };
 
 /// A simple wrapper type against `ast::Arm`. Used inside `write_list()`.
@@ -167,8 +167,9 @@ fn collect_beginning_verts(
     arms.iter()
         .map(|a| {
             context
-                .snippet_provider
-                .opt_span_before(mk_sp_lo_plus_one(a.pat.span.lo()), "|")
+                .snippet(a.pat.span)
+                .starts_with("|")
+                .then(|| a.pat.span().lo())
         })
         .collect()
 }


Test patch:
diff --git a/tests/source/configs/match_arm_leading_pipes/preserve.rs b/tests/source/configs/match_arm_leading_pipes/preserve.rs
index ea303e85..5486877b 100644
--- a/tests/source/configs/match_arm_leading_pipes/preserve.rs
+++ b/tests/source/configs/match_arm_leading_pipes/preserve.rs
@@ -26,3 +26,11 @@ fn bar() {
         _ => {}
     }
 }
+
+fn f(x: NonAscii) -> bool {
+    match x {
+      // foo
+              |   Éfgh => true,
+        _ => false,
+    }
+}
\ No newline at end of file
diff --git a/tests/target/configs/match_arm_leading_pipes/preserve.rs b/tests/target/configs/match_arm_leading_pipes/preserve.rs
index 2beb1f5d..47755758 100644
--- a/tests/target/configs/match_arm_leading_pipes/preserve.rs
+++ b/tests/target/configs/match_arm_leading_pipes/preserve.rs
@@ -25,3 +25,11 @@ fn bar() {
         _ => {}
     }
 }
+
+fn f(x: NonAscii) -> bool {
+    match x {
+        // foo
+        | Éfgh => true,
+        _ => false,
+    }
+}
diff --git a/tests/target/issue_4868.rs b/tests/target/issue_4868.rs
new file mode 100644
index 00000000..763a82c3
--- /dev/null
+++ b/tests/target/issue_4868.rs
@@ -0,0 +1,17 @@
+enum NonAscii {
+    Abcd,
+    Éfgh,
+}
+
+use NonAscii::*;
+
+fn f(x: NonAscii) -> bool {
+    match x {
+        Éfgh => true,
+        _ => false,
+    }
+}
+
+fn main() {
+    dbg!(f(Abcd));
+}