From c41740d7d2fc3902ac9cc17b0fd6c6bde69ed231 Mon Sep 17 00:00:00 2001 From: dianne Date: Mon, 24 Mar 2025 17:08:14 -0700 Subject: [PATCH 1/3] make `str` literal patterns usable in deref patterns Specifically, this allows string literal patterns to be used where a `str` is expected when `deref_patterns` is enabled. --- compiler/rustc_hir_typeck/src/pat.rs | 11 +++++++ .../src/builder/matches/test.rs | 23 +++++++++++++ compiler/rustc_mir_build/src/thir/constant.rs | 6 ++++ .../src/thir/pattern/const_to_pat.rs | 9 ++++++ tests/ui/pattern/deref-patterns/needs-gate.rs | 7 ++++ .../pattern/deref-patterns/needs-gate.stderr | 10 +++++- tests/ui/pattern/deref-patterns/strings.rs | 32 +++++++++++++++++++ .../ui/pattern/deref-patterns/typeck_fail.rs | 8 ++--- .../pattern/deref-patterns/typeck_fail.stderr | 26 +++------------ 9 files changed, 103 insertions(+), 29 deletions(-) create mode 100644 tests/ui/pattern/deref-patterns/strings.rs diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index e5e4fc7f8b77f..bb85396277c5c 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -775,6 +775,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } + // 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 73cc3c86e22f7..210b9cce581fd 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 b3210813703ca..a5ae74280d06e 100644 --- a/compiler/rustc_mir_build/src/thir/constant.rs +++ b/compiler/rustc_mir_build/src/thir/constant.rs @@ -37,6 +37,12 @@ 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(_)) => { 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 a40001bf74556..b2a9315e3f5bc 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,15 @@ 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`. + 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/tests/ui/pattern/deref-patterns/needs-gate.rs b/tests/ui/pattern/deref-patterns/needs-gate.rs index 2d5ec45217fbb..a26a4fedc5c51 100644 --- a/tests/ui/pattern/deref-patterns/needs-gate.rs +++ b/tests/ui/pattern/deref-patterns/needs-gate.rs @@ -12,4 +12,11 @@ fn main() { //~^ ERROR: mismatched types _ => {} } + + // `deref_patterns` allows string and byte string literals to have non-ref types. + match *"test" { + "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 8687b5dc977db..b1ae03753fec7 100644 --- a/tests/ui/pattern/deref-patterns/needs-gate.stderr +++ b/tests/ui/pattern/deref-patterns/needs-gate.stderr @@ -23,7 +23,15 @@ 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: aborting due to 3 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 0000000000000..b55451e318179 --- /dev/null +++ b/tests/ui/pattern/deref-patterns/strings.rs @@ -0,0 +1,32 @@ +//@ 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"); +} diff --git a/tests/ui/pattern/deref-patterns/typeck_fail.rs b/tests/ui/pattern/deref-patterns/typeck_fail.rs index 4b9ad7d25f090..52d84f7a34de3 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 3e2f356188220..e87528c1c51a9 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`. From 0a92d84b6ce31db6bc8675cb823cdd04df16e94f Mon Sep 17 00:00:00 2001 From: dianne Date: Tue, 15 Apr 2025 23:35:52 -0700 Subject: [PATCH 2/3] make `[u8]` and `[u8;N]` literal patterns usable in deref patterns Specifically, this allows byte string literal patterns to be used where a `[u8]` or `[u8;N]` is expected when `deref_patterns` is enabled. --- compiler/rustc_hir_typeck/src/pat.rs | 35 ++++++++++--- compiler/rustc_mir_build/src/thir/constant.rs | 8 ++- .../deref-patterns/byte-string-type-errors.rs | 34 ++++++++++++ .../byte-string-type-errors.stderr | 52 +++++++++++++++++++ tests/ui/pattern/deref-patterns/needs-gate.rs | 10 ++++ .../pattern/deref-patterns/needs-gate.stderr | 18 ++++++- tests/ui/pattern/deref-patterns/strings.rs | 34 ++++++++++++ 7 files changed, 181 insertions(+), 10 deletions(-) create mode 100644 tests/ui/pattern/deref-patterns/byte-string-type-errors.rs create mode 100644 tests/ui/pattern/deref-patterns/byte-string-type-errors.stderr diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index bb85396277c5c..6391e843dc4af 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -759,19 +759,40 @@ 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`. 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]` + _ => {} } } diff --git a/compiler/rustc_mir_build/src/thir/constant.rs b/compiler/rustc_mir_build/src/thir/constant.rs index a5ae74280d06e..b4fa55e1c1fdb 100644 --- a/compiler/rustc_mir_build/src/thir/constant.rs +++ b/compiler/rustc_mir_build/src/thir/constant.rs @@ -44,12 +44,16 @@ pub(crate) fn lit_to_const<'tcx>( 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`. let bytes = data as &[u8]; ty::ValTree::from_raw_bytes(tcx, bytes) } 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 0000000000000..29a33e3e2c3b6 --- /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 0000000000000..d29a5b59252c9 --- /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 a26a4fedc5c51..7944744ee839c 100644 --- a/tests/ui/pattern/deref-patterns/needs-gate.rs +++ b/tests/ui/pattern/deref-patterns/needs-gate.rs @@ -19,4 +19,14 @@ fn main() { //~^ 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 b1ae03753fec7..e886ca9805581 100644 --- a/tests/ui/pattern/deref-patterns/needs-gate.stderr +++ b/tests/ui/pattern/deref-patterns/needs-gate.stderr @@ -31,7 +31,23 @@ LL | match *"test" { LL | "test" => {} | ^^^^^^ expected `str`, found `&str` -error: aborting due to 3 previous errors +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 index b55451e318179..536e943b3f672 100644 --- a/tests/ui/pattern/deref-patterns/strings.rs +++ b/tests/ui/pattern/deref-patterns/strings.rs @@ -29,4 +29,38 @@ fn main() { 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); + } } From eaa8ab1592322b534b4e3298f57c4341dfc3c47d Mon Sep 17 00:00:00 2001 From: dianne Date: Fri, 18 Apr 2025 21:49:40 -0700 Subject: [PATCH 3/3] update unstable book to mention string/bytestring typing --- .../src/language-features/deref-patterns.md | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) 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 d0102a665b0b0..d0a64538e8ccc 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