about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_hir_typeck/src/pat.rs46
-rw-r--r--compiler/rustc_mir_build/src/builder/matches/test.rs23
-rw-r--r--compiler/rustc_mir_build/src/thir/constant.rs14
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs10
-rw-r--r--src/doc/unstable-book/src/language-features/deref-patterns.md21
-rw-r--r--tests/ui/pattern/byte-string-mutability-mismatch.rs19
-rw-r--r--tests/ui/pattern/byte-string-mutability-mismatch.stderr25
-rw-r--r--tests/ui/pattern/deref-patterns/byte-string-type-errors.rs34
-rw-r--r--tests/ui/pattern/deref-patterns/byte-string-type-errors.stderr52
-rw-r--r--tests/ui/pattern/deref-patterns/needs-gate.rs17
-rw-r--r--tests/ui/pattern/deref-patterns/needs-gate.stderr26
-rw-r--r--tests/ui/pattern/deref-patterns/strings.rs66
-rw-r--r--tests/ui/pattern/deref-patterns/typeck_fail.rs8
-rw-r--r--tests/ui/pattern/deref-patterns/typeck_fail.stderr26
14 files changed, 349 insertions, 38 deletions
diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs
index 7e7079f09ad..7520782930a 100644
--- a/compiler/rustc_hir_typeck/src/pat.rs
+++ b/compiler/rustc_hir_typeck/src/pat.rs
@@ -759,22 +759,54 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         // Byte string patterns behave the same way as array patterns
         // They can denote both statically and dynamically-sized byte arrays.
+        // Additionally, when `deref_patterns` is enabled, byte string literal patterns may have
+        // types `[u8]` or `[u8; N]`, in order to type, e.g., `deref!(b"..."): Vec<u8>`.
         let mut pat_ty = ty;
         if let hir::PatExprKind::Lit {
             lit: Spanned { node: ast::LitKind::ByteStr(..), .. }, ..
         } = lt.kind
         {
+            let tcx = self.tcx;
             let expected = self.structurally_resolve_type(span, expected);
-            if let ty::Ref(_, inner_ty, _) = *expected.kind()
-                && self.try_structurally_resolve_type(span, inner_ty).is_slice()
-            {
-                let tcx = self.tcx;
-                trace!(?lt.hir_id.local_id, "polymorphic byte string lit");
-                pat_ty =
-                    Ty::new_imm_ref(tcx, tcx.lifetimes.re_static, Ty::new_slice(tcx, tcx.types.u8));
+            match *expected.kind() {
+                // Allow `b"...": &[u8]`
+                ty::Ref(_, inner_ty, _)
+                    if self.try_structurally_resolve_type(span, inner_ty).is_slice() =>
+                {
+                    trace!(?lt.hir_id.local_id, "polymorphic byte string lit");
+                    pat_ty = Ty::new_imm_ref(
+                        tcx,
+                        tcx.lifetimes.re_static,
+                        Ty::new_slice(tcx, tcx.types.u8),
+                    );
+                }
+                // Allow `b"...": [u8; 3]` for `deref_patterns`
+                ty::Array(..) if tcx.features().deref_patterns() => {
+                    pat_ty = match *ty.kind() {
+                        ty::Ref(_, inner_ty, _) => inner_ty,
+                        _ => span_bug!(span, "found byte string literal with non-ref type {ty:?}"),
+                    }
+                }
+                // Allow `b"...": [u8]` for `deref_patterns`
+                ty::Slice(..) if tcx.features().deref_patterns() => {
+                    pat_ty = Ty::new_slice(tcx, tcx.types.u8);
+                }
+                // Otherwise, `b"...": &[u8; 3]`
+                _ => {}
             }
         }
 
+        // When `deref_patterns` is enabled, in order to allow `deref!("..."): String`, we allow
+        // string literal patterns to have type `str`. This is accounted for when lowering to MIR.
+        if self.tcx.features().deref_patterns()
+            && let hir::PatExprKind::Lit {
+                lit: Spanned { node: ast::LitKind::Str(..), .. }, ..
+            } = lt.kind
+            && self.try_structurally_resolve_type(span, expected).is_str()
+        {
+            pat_ty = self.tcx.types.str_;
+        }
+
         if self.tcx.features().string_deref_patterns()
             && let hir::PatExprKind::Lit {
                 lit: Spanned { node: ast::LitKind::Str(..), .. }, ..
diff --git a/compiler/rustc_mir_build/src/builder/matches/test.rs b/compiler/rustc_mir_build/src/builder/matches/test.rs
index 73cc3c86e22..210b9cce581 100644
--- a/compiler/rustc_mir_build/src/builder/matches/test.rs
+++ b/compiler/rustc_mir_build/src/builder/matches/test.rs
@@ -146,6 +146,29 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 let mut place = place;
                 let mut block = block;
                 match ty.kind() {
+                    ty::Str => {
+                        // String literal patterns may have type `str` if `deref_patterns` is
+                        // enabled, in order to allow `deref!("..."): String`. In this case, `value`
+                        // is of type `&str`, so we compare it to `&place`.
+                        if !tcx.features().deref_patterns() {
+                            span_bug!(
+                                test.span,
+                                "matching on `str` went through without enabling deref_patterns"
+                            );
+                        }
+                        let re_erased = tcx.lifetimes.re_erased;
+                        let ref_str_ty = Ty::new_imm_ref(tcx, re_erased, tcx.types.str_);
+                        let ref_place = self.temp(ref_str_ty, test.span);
+                        // `let ref_place: &str = &place;`
+                        self.cfg.push_assign(
+                            block,
+                            self.source_info(test.span),
+                            ref_place,
+                            Rvalue::Ref(re_erased, BorrowKind::Shared, place),
+                        );
+                        place = ref_place;
+                        ty = ref_str_ty;
+                    }
                     ty::Adt(def, _) if tcx.is_lang_item(def.did(), LangItem::String) => {
                         if !tcx.features().string_deref_patterns() {
                             span_bug!(
diff --git a/compiler/rustc_mir_build/src/thir/constant.rs b/compiler/rustc_mir_build/src/thir/constant.rs
index b3210813703..b4fa55e1c1f 100644
--- a/compiler/rustc_mir_build/src/thir/constant.rs
+++ b/compiler/rustc_mir_build/src/thir/constant.rs
@@ -37,13 +37,23 @@ pub(crate) fn lit_to_const<'tcx>(
             let str_bytes = s.as_str().as_bytes();
             ty::ValTree::from_raw_bytes(tcx, str_bytes)
         }
+        (ast::LitKind::Str(s, _), ty::Str) if tcx.features().deref_patterns() => {
+            // String literal patterns may have type `str` if `deref_patterns` is enabled, in order
+            // to allow `deref!("..."): String`.
+            let str_bytes = s.as_str().as_bytes();
+            ty::ValTree::from_raw_bytes(tcx, str_bytes)
+        }
         (ast::LitKind::ByteStr(data, _), ty::Ref(_, inner_ty, _))
-            if matches!(inner_ty.kind(), ty::Slice(_)) =>
+            if matches!(inner_ty.kind(), ty::Slice(_) | ty::Array(..)) =>
         {
             let bytes = data as &[u8];
             ty::ValTree::from_raw_bytes(tcx, bytes)
         }
-        (ast::LitKind::ByteStr(data, _), ty::Ref(_, inner_ty, _)) if inner_ty.is_array() => {
+        (ast::LitKind::ByteStr(data, _), ty::Slice(_) | ty::Array(..))
+            if tcx.features().deref_patterns() =>
+        {
+            // Byte string literal patterns may have type `[u8]` or `[u8; N]` if `deref_patterns` is
+            // enabled, in order to allow, e.g., `deref!(b"..."): Vec<u8>`.
             let bytes = data as &[u8];
             ty::ValTree::from_raw_bytes(tcx, bytes)
         }
diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
index a40001bf745..b7d203e3cd7 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
@@ -280,6 +280,16 @@ impl<'tcx> ConstToPat<'tcx> {
                 slice: None,
                 suffix: Box::new([]),
             },
+            ty::Str => {
+                // String literal patterns may have type `str` if `deref_patterns` is enabled, in
+                // order to allow `deref!("..."): String`. Since we need a `&str` for the comparison
+                // when lowering to MIR in `Builder::perform_test`, treat the constant as a `&str`.
+                // This works because `str` and `&str` have the same valtree representation.
+                let ref_str_ty = Ty::new_imm_ref(tcx, tcx.lifetimes.re_erased, ty);
+                PatKind::Constant {
+                    value: mir::Const::Ty(ref_str_ty, ty::Const::new_value(tcx, cv, ref_str_ty)),
+                }
+            }
             ty::Ref(_, pointee_ty, ..) => match *pointee_ty.kind() {
                 // `&str` is represented as a valtree, let's keep using this
                 // optimization for now.
diff --git a/src/doc/unstable-book/src/language-features/deref-patterns.md b/src/doc/unstable-book/src/language-features/deref-patterns.md
index d0102a665b0..d0a64538e8c 100644
--- a/src/doc/unstable-book/src/language-features/deref-patterns.md
+++ b/src/doc/unstable-book/src/language-features/deref-patterns.md
@@ -54,4 +54,25 @@ if let [b] = &mut *v {
 assert_eq!(v, [Box::new(Some(2))]);
 ```
 
+Additionally, when `deref_patterns` is enabled, string literal patterns may be written where `str`
+is expected. Likewise, byte string literal patterns may be written where `[u8]` or `[u8; _]` is
+expected. This lets them be used in `deref!(_)` patterns:
+
+```rust
+# #![feature(deref_patterns)]
+# #![allow(incomplete_features)]
+match ("test".to_string(), b"test".to_vec()) {
+    (deref!("test"), deref!(b"test")) => {}
+    _ => panic!(),
+}
+
+// Matching on slices and arrays using literals is possible elsewhere as well:
+match *"test" {
+    "test" => {}
+    _ => panic!(),
+}
+```
+
+Implicit deref pattern syntax is not yet supported for string or byte string literals.
+
 [smart pointers in the standard library]: https://doc.rust-lang.org/std/ops/trait.DerefPure.html#implementors
diff --git a/tests/ui/pattern/byte-string-mutability-mismatch.rs b/tests/ui/pattern/byte-string-mutability-mismatch.rs
new file mode 100644
index 00000000000..4ffdb5f9b99
--- /dev/null
+++ b/tests/ui/pattern/byte-string-mutability-mismatch.rs
@@ -0,0 +1,19 @@
+//! Byte string literal patterns use the mutability of the literal, rather than the mutability of
+//! the pattern's scrutinee. Since byte string literals are always shared references, it's a
+//! mismatch to use a byte string literal pattern to match on a mutable array or slice reference.
+
+fn main() {
+    let mut val = [97u8, 10u8];
+    match &mut val {
+        b"a\n" => {},
+        //~^ ERROR mismatched types
+        //~| types differ in mutability
+        _ => {},
+    }
+    match &mut val[..] {
+         b"a\n" => {},
+        //~^ ERROR mismatched types
+        //~| types differ in mutability
+         _ => {},
+    }
+}
diff --git a/tests/ui/pattern/byte-string-mutability-mismatch.stderr b/tests/ui/pattern/byte-string-mutability-mismatch.stderr
new file mode 100644
index 00000000000..ee796278e69
--- /dev/null
+++ b/tests/ui/pattern/byte-string-mutability-mismatch.stderr
@@ -0,0 +1,25 @@
+error[E0308]: mismatched types
+  --> $DIR/byte-string-mutability-mismatch.rs:8:9
+   |
+LL |     match &mut val {
+   |           -------- this expression has type `&mut [u8; 2]`
+LL |         b"a\n" => {},
+   |         ^^^^^^ types differ in mutability
+   |
+   = note: expected mutable reference `&mut _`
+                      found reference `&'static _`
+
+error[E0308]: mismatched types
+  --> $DIR/byte-string-mutability-mismatch.rs:14:10
+   |
+LL |     match &mut val[..] {
+   |           ------------ this expression has type `&mut [u8]`
+LL |          b"a\n" => {},
+   |          ^^^^^^ types differ in mutability
+   |
+   = note: expected mutable reference `&mut _`
+                      found reference `&'static _`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/pattern/deref-patterns/byte-string-type-errors.rs b/tests/ui/pattern/deref-patterns/byte-string-type-errors.rs
new file mode 100644
index 00000000000..29a33e3e2c3
--- /dev/null
+++ b/tests/ui/pattern/deref-patterns/byte-string-type-errors.rs
@@ -0,0 +1,34 @@
+//! Test type errors for byte string literal patterns. `deref_patterns` allows byte string literal
+//! patterns to have type `[u8]` or `[u8; N]` when matching on a slice or array; this can affect the
+//! "found" type reported in error messages when matching on a slice or array of the wrong type.
+
+#![feature(deref_patterns)]
+#![expect(incomplete_features)]
+
+fn main() {
+    // Baseline 1: under normal circumstances, byte string literal patterns have type `&[u8; N]`,
+    // the same as byte string literals.
+    if let b"test" = () {}
+    //~^ ERROR mismatched types
+    //~| expected `()`, found `&[u8; 4]`
+
+    // Baseline 2: there's a special case for byte string patterns in stable rust, allowing them to
+    // match on slice references. This affects the error when matching on a non-`&[u8]` slice ref,
+    // reporting the "found" type as `&[u8]`.
+    if let b"test" = &[] as &[i8] {}
+    //~^ ERROR mismatched types
+    //~| expected `&[i8]`, found `&[u8]`
+
+    // Test matching on a non-`[u8]` slice: the pattern has type `[u8]` if a slice is expected.
+    if let b"test" = *(&[] as &[i8]) {}
+    //~^ ERROR mismatched types
+    //~| expected `[i8]`, found `[u8]`
+
+    // Test matching on a non-`[u8;4]` array: the pattern has type `[u8;4]` if an array is expected.
+    if let b"test" = [()] {}
+    //~^ ERROR mismatched types
+    //~| expected `[(); 1]`, found `[u8; 4]`
+    if let b"test" = *b"this array is too long" {}
+    //~^ ERROR mismatched types
+    //~| expected an array with a size of 22, found one with a size of 4
+}
diff --git a/tests/ui/pattern/deref-patterns/byte-string-type-errors.stderr b/tests/ui/pattern/deref-patterns/byte-string-type-errors.stderr
new file mode 100644
index 00000000000..d29a5b59252
--- /dev/null
+++ b/tests/ui/pattern/deref-patterns/byte-string-type-errors.stderr
@@ -0,0 +1,52 @@
+error[E0308]: mismatched types
+  --> $DIR/byte-string-type-errors.rs:11:12
+   |
+LL |     if let b"test" = () {}
+   |            ^^^^^^^   -- this expression has type `()`
+   |            |
+   |            expected `()`, found `&[u8; 4]`
+
+error[E0308]: mismatched types
+  --> $DIR/byte-string-type-errors.rs:18:12
+   |
+LL |     if let b"test" = &[] as &[i8] {}
+   |            ^^^^^^^   ------------ this expression has type `&[i8]`
+   |            |
+   |            expected `&[i8]`, found `&[u8]`
+   |
+   = note: expected reference `&[i8]`
+              found reference `&'static [u8]`
+
+error[E0308]: mismatched types
+  --> $DIR/byte-string-type-errors.rs:23:12
+   |
+LL |     if let b"test" = *(&[] as &[i8]) {}
+   |            ^^^^^^^   --------------- this expression has type `[i8]`
+   |            |
+   |            expected `[i8]`, found `[u8]`
+   |
+   = note: expected slice `[i8]`
+              found slice `[u8]`
+
+error[E0308]: mismatched types
+  --> $DIR/byte-string-type-errors.rs:28:12
+   |
+LL |     if let b"test" = [()] {}
+   |            ^^^^^^^   ---- this expression has type `[(); 1]`
+   |            |
+   |            expected `[(); 1]`, found `[u8; 4]`
+   |
+   = note: expected array `[(); 1]`
+              found array `[u8; 4]`
+
+error[E0308]: mismatched types
+  --> $DIR/byte-string-type-errors.rs:31:12
+   |
+LL |     if let b"test" = *b"this array is too long" {}
+   |            ^^^^^^^   -------------------------- this expression has type `[u8; 22]`
+   |            |
+   |            expected an array with a size of 22, found one with a size of 4
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/pattern/deref-patterns/needs-gate.rs b/tests/ui/pattern/deref-patterns/needs-gate.rs
index 2d5ec45217f..7944744ee83 100644
--- a/tests/ui/pattern/deref-patterns/needs-gate.rs
+++ b/tests/ui/pattern/deref-patterns/needs-gate.rs
@@ -12,4 +12,21 @@ fn main() {
         //~^ ERROR: mismatched types
         _ => {}
     }
+
+    // `deref_patterns` allows string and byte string literals to have non-ref types.
+    match *"test" {
+        "test" => {}
+        //~^ ERROR: mismatched types
+        _ => {}
+    }
+    match *b"test" {
+        b"test" => {}
+        //~^ ERROR: mismatched types
+        _ => {}
+    }
+    match *(b"test" as &[u8]) {
+        b"test" => {}
+        //~^ ERROR: mismatched types
+        _ => {}
+    }
 }
diff --git a/tests/ui/pattern/deref-patterns/needs-gate.stderr b/tests/ui/pattern/deref-patterns/needs-gate.stderr
index 8687b5dc977..e886ca98055 100644
--- a/tests/ui/pattern/deref-patterns/needs-gate.stderr
+++ b/tests/ui/pattern/deref-patterns/needs-gate.stderr
@@ -23,7 +23,31 @@ help: consider dereferencing to access the inner value using the Deref trait
 LL |     match *Box::new(0) {
    |           +
 
-error: aborting due to 2 previous errors
+error[E0308]: mismatched types
+  --> $DIR/needs-gate.rs:18:9
+   |
+LL |     match *"test" {
+   |           ------- this expression has type `str`
+LL |         "test" => {}
+   |         ^^^^^^ expected `str`, found `&str`
+
+error[E0308]: mismatched types
+  --> $DIR/needs-gate.rs:23:9
+   |
+LL |     match *b"test" {
+   |           -------- this expression has type `[u8; 4]`
+LL |         b"test" => {}
+   |         ^^^^^^^ expected `[u8; 4]`, found `&[u8; 4]`
+
+error[E0308]: mismatched types
+  --> $DIR/needs-gate.rs:28:9
+   |
+LL |     match *(b"test" as &[u8]) {
+   |           ------------------- this expression has type `[u8]`
+LL |         b"test" => {}
+   |         ^^^^^^^ expected `[u8]`, found `&[u8; 4]`
+
+error: aborting due to 5 previous errors
 
 Some errors have detailed explanations: E0308, E0658.
 For more information about an error, try `rustc --explain E0308`.
diff --git a/tests/ui/pattern/deref-patterns/strings.rs b/tests/ui/pattern/deref-patterns/strings.rs
new file mode 100644
index 00000000000..536e943b3f6
--- /dev/null
+++ b/tests/ui/pattern/deref-patterns/strings.rs
@@ -0,0 +1,66 @@
+//@ run-pass
+//! Test deref patterns using string and bytestring literals.
+
+#![feature(deref_patterns)]
+#![allow(incomplete_features)]
+
+fn main() {
+    for (test_in, test_expect) in [("zero", 0), ("one", 1), ("two", 2)] {
+        // Test string literal patterns having type `str`.
+        let test_actual = match *test_in {
+            "zero" => 0,
+            "one" => 1,
+            _ => 2,
+        };
+        assert_eq!(test_actual, test_expect);
+
+        // Test string literals in explicit `deref!(_)` patterns.
+        let test_actual = match test_in.to_string() {
+            deref!("zero") => 0,
+            deref!("one") => 1,
+            _ => 2,
+        };
+        assert_eq!(test_actual, test_expect);
+    }
+
+    // Test that we can still mutate in the match arm after using a literal to test equality:
+    let mut test = "test".to_string();
+    if let deref!(s @ "test") = &mut test {
+        s.make_ascii_uppercase();
+    }
+    assert_eq!(test, "TEST");
+
+    for (test_in, test_expect) in [(b"0", 0), (b"1", 1), (b"2", 2)] {
+        // Test byte string literal patterns having type `[u8; N]`
+        let test_actual = match *test_in {
+            b"0" => 0,
+            b"1" => 1,
+            _ => 2,
+        };
+        assert_eq!(test_actual, test_expect);
+
+        // Test byte string literal patterns having type `[u8]`
+        let test_actual = match *(test_in as &[u8]) {
+            b"0" => 0,
+            b"1" => 1,
+            _ => 2,
+        };
+        assert_eq!(test_actual, test_expect);
+
+        // Test byte string literals used as arrays in explicit `deref!(_)` patterns.
+        let test_actual = match Box::new(*test_in) {
+            deref!(b"0") => 0,
+            deref!(b"1") => 1,
+            _ => 2,
+        };
+        assert_eq!(test_actual, test_expect);
+
+        // Test byte string literals used as slices in explicit `deref!(_)` patterns.
+        let test_actual = match test_in.to_vec() {
+            deref!(b"0") => 0,
+            deref!(b"1") => 1,
+            _ => 2,
+        };
+        assert_eq!(test_actual, test_expect);
+    }
+}
diff --git a/tests/ui/pattern/deref-patterns/typeck_fail.rs b/tests/ui/pattern/deref-patterns/typeck_fail.rs
index 4b9ad7d25f0..52d84f7a34d 100644
--- a/tests/ui/pattern/deref-patterns/typeck_fail.rs
+++ b/tests/ui/pattern/deref-patterns/typeck_fail.rs
@@ -2,18 +2,14 @@
 #![allow(incomplete_features)]
 
 fn main() {
-    // FIXME(deref_patterns): fails to typecheck because `"foo"` has type &str but deref creates a
-    // place of type `str`.
+    // FIXME(deref_patterns): fails to typecheck because string literal patterns don't peel
+    // references from the scrutinee.
     match "foo".to_string() {
-        deref!("foo") => {}
-        //~^ ERROR: mismatched types
         "foo" => {}
         //~^ ERROR: mismatched types
         _ => {}
     }
     match &"foo".to_string() {
-        deref!("foo") => {}
-        //~^ ERROR: mismatched types
         "foo" => {}
         //~^ ERROR: mismatched types
         _ => {}
diff --git a/tests/ui/pattern/deref-patterns/typeck_fail.stderr b/tests/ui/pattern/deref-patterns/typeck_fail.stderr
index 3e2f3561882..e87528c1c51 100644
--- a/tests/ui/pattern/deref-patterns/typeck_fail.stderr
+++ b/tests/ui/pattern/deref-patterns/typeck_fail.stderr
@@ -1,34 +1,16 @@
 error[E0308]: mismatched types
-  --> $DIR/typeck_fail.rs:8:16
+  --> $DIR/typeck_fail.rs:8:9
    |
 LL |     match "foo".to_string() {
    |           ----------------- this expression has type `String`
-LL |         deref!("foo") => {}
-   |                ^^^^^ expected `str`, found `&str`
-
-error[E0308]: mismatched types
-  --> $DIR/typeck_fail.rs:10:9
-   |
-LL |     match "foo".to_string() {
-   |           ----------------- this expression has type `String`
-...
 LL |         "foo" => {}
    |         ^^^^^ expected `String`, found `&str`
 
 error[E0308]: mismatched types
-  --> $DIR/typeck_fail.rs:15:16
-   |
-LL |     match &"foo".to_string() {
-   |           ------------------ this expression has type `&String`
-LL |         deref!("foo") => {}
-   |                ^^^^^ expected `str`, found `&str`
-
-error[E0308]: mismatched types
-  --> $DIR/typeck_fail.rs:17:9
+  --> $DIR/typeck_fail.rs:13:9
    |
 LL |     match &"foo".to_string() {
    |           ------------------ this expression has type `&String`
-...
 LL |         "foo" => {}
    |         ^^^^^ expected `&String`, found `&str`
    |
@@ -36,7 +18,7 @@ LL |         "foo" => {}
               found reference `&'static str`
 
 error[E0308]: mismatched types
-  --> $DIR/typeck_fail.rs:24:9
+  --> $DIR/typeck_fail.rs:20:9
    |
 LL |     match Some(0) {
    |           ------- this expression has type `Option<{integer}>`
@@ -46,6 +28,6 @@ LL |         Ok(0) => {}
    = note: expected enum `Option<{integer}>`
               found enum `Result<_, _>`
 
-error: aborting due to 5 previous errors
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0308`.