diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs index e5d66364c2a6e..9d8a84c52e980 100644 --- a/compiler/rustc_feature/src/removed.rs +++ b/compiler/rustc_feature/src/removed.rs @@ -271,6 +271,8 @@ declare_features! ( /// Allows `#[link(kind = "static-nobundle", ...)]`. (removed, static_nobundle, "1.63.0", Some(37403), Some(r#"subsumed by `#[link(kind = "static", modifiers = "-bundle", ...)]`"#), 95818), + /// Allows string patterns to dereference values to match them. + (removed, string_deref_patterns, "CURRENT_RUSTC_VERSION", Some(87121), Some("superseded by `deref_patterns`"), 150530), (removed, struct_inherit, "1.0.0", None, None), (removed, test_removed_feature, "1.0.0", None, None), /// Allows using items which are missing stability attributes diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 692cba8035c49..34b7cac5c941f 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -647,8 +647,6 @@ declare_features! ( (unstable, stmt_expr_attributes, "1.6.0", Some(15701)), /// Allows lints part of the strict provenance effort. (unstable, strict_provenance_lints, "1.61.0", Some(130351)), - /// Allows string patterns to dereference values to match them. - (unstable, string_deref_patterns, "1.67.0", Some(87121)), /// Allows `super let` statements. (unstable, super_let, "1.88.0", Some(139076)), /// Allows subtrait items to shadow supertrait items. diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index 1a579c4c6fa4a..90e22b2cd381a 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -996,20 +996,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pat_ty = self.tcx.types.str_; } - if self.tcx.features().string_deref_patterns() - && let hir::PatExprKind::Lit { - lit: Spanned { node: ast::LitKind::Str(..), .. }, .. - } = lt.kind - { - let tcx = self.tcx; - let expected = self.resolve_vars_if_possible(expected); - pat_ty = match expected.kind() { - ty::Adt(def, _) if tcx.is_lang_item(def.did(), LangItem::String) => expected, - ty::Str => Ty::new_static_str(tcx), - _ => pat_ty, - }; - } - // Somewhat surprising: in this case, the subtyping relation goes the // opposite way as the other cases. Actually what we really want is not // a subtyping relation at all but rather that there exists a LUB diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index 65bfc7d362b61..3683c1cfb7ddb 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -827,7 +827,6 @@ pub enum PatKind<'tcx> { /// much simpler. /// * raw pointers derived from integers, other raw pointers will have already resulted in an /// error. - /// * `String`, if `string_deref_patterns` is enabled. Constant { value: ty::Value<'tcx>, }, diff --git a/compiler/rustc_mir_build/src/builder/matches/test.rs b/compiler/rustc_mir_build/src/builder/matches/test.rs index cac4f7b7ab4f8..972d9f66faddc 100644 --- a/compiler/rustc_mir_build/src/builder/matches/test.rs +++ b/compiler/rustc_mir_build/src/builder/matches/test.rs @@ -150,7 +150,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let mut expect = self.literal_operand(test.span, Const::from_ty_value(tcx, value)); let mut place = place; - let mut block = block; + match cast_ty.kind() { ty::Str => { // String literal patterns may have type `str` if `deref_patterns` is @@ -175,34 +175,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { place = ref_place; cast_ty = ref_str_ty; } - ty::Adt(def, _) if tcx.is_lang_item(def.did(), LangItem::String) => { - if !tcx.features().string_deref_patterns() { - span_bug!( - test.span, - "matching on `String` went through without enabling string_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_str = self.temp(ref_str_ty, test.span); - let eq_block = self.cfg.start_new_block(); - // `let ref_str: &str = ::deref(&place);` - self.call_deref( - block, - eq_block, - place, - Mutability::Not, - cast_ty, - ref_str, - test.span, - ); - // Since we generated a `ref_str = ::deref(&place) -> eq_block` terminator, - // we need to add all further statements to `eq_block`. - // Similarly, the normal test code should be generated for the `&str`, instead of the `String`. - block = eq_block; - place = ref_str; - cast_ty = ref_str_ty; - } &ty::Pat(base, _) => { assert_eq!(cast_ty, value.ty); assert!(base.is_trivially_pure_clone_copy()); diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index 063bb4a3d461a..0310003e7d58e 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -11,7 +11,7 @@ use rustc_abi::{FieldIdx, Integer}; use rustc_errors::codes::*; use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::pat_util::EnumerateAndAdjustIterator; -use rustc_hir::{self as hir, LangItem, RangeEnd}; +use rustc_hir::{self as hir, RangeEnd}; use rustc_index::Idx; use rustc_middle::mir::interpret::LitToConstInput; use rustc_middle::thir::{ @@ -626,23 +626,7 @@ impl<'tcx> PatCtxt<'tcx> { // the pattern's type will be `&[u8]` whereas the literal's type is `&[u8; 3]`; using the // pattern's type means we'll properly translate it to a slice reference pattern. This works // because slices and arrays have the same valtree representation. - // HACK: As an exception, use the literal's type if `pat_ty` is `String`; this can happen if - // `string_deref_patterns` is enabled. There's a special case for that when lowering to MIR. - // FIXME(deref_patterns): This hack won't be necessary once `string_deref_patterns` is - // superseded by a more general implementation of deref patterns. let ct_ty = match pat_ty { - Some(pat_ty) - if let ty::Adt(def, _) = *pat_ty.kind() - && self.tcx.is_lang_item(def.did(), LangItem::String) => - { - if !self.tcx.features().string_deref_patterns() { - span_bug!( - expr.span, - "matching on `String` went through without enabling string_deref_patterns" - ); - } - self.typeck_results.node_type(expr.hir_id) - } Some(pat_ty) => pat_ty, None => self.typeck_results.node_type(expr.hir_id), }; 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 4c3d456b9af80..23c2dc688400b 100644 --- a/src/doc/unstable-book/src/language-features/deref-patterns.md +++ b/src/doc/unstable-book/src/language-features/deref-patterns.md @@ -7,7 +7,7 @@ The tracking issue for this feature is: [#87121] ------------------------ > **Note**: This feature is incomplete. In the future, it is meant to supersede -> [`box_patterns`] and [`string_deref_patterns`]. +> [`box_patterns`]. This feature permits pattern matching on [smart pointers in the standard library] through their `Deref` target types, either implicitly or with explicit `deref!(_)` patterns (the syntax of which @@ -103,5 +103,4 @@ match *(b"test" as &[u8]) { ``` [`box_patterns`]: ./box-patterns.md -[`string_deref_patterns`]: ./string-deref-patterns.md [smart pointers in the standard library]: https://doc.rust-lang.org/std/ops/trait.DerefPure.html#implementors diff --git a/src/doc/unstable-book/src/language-features/string-deref-patterns.md b/src/doc/unstable-book/src/language-features/string-deref-patterns.md deleted file mode 100644 index 366bb15d4ea86..0000000000000 --- a/src/doc/unstable-book/src/language-features/string-deref-patterns.md +++ /dev/null @@ -1,48 +0,0 @@ -# `string_deref_patterns` - -The tracking issue for this feature is: [#87121] - -[#87121]: https://github.com/rust-lang/rust/issues/87121 - ------------------------- - -> **Note**: This feature will be superseded by [`deref_patterns`] in the future. - -This feature permits pattern matching `String` to `&str` through [its `Deref` implementation]. - -```rust -#![feature(string_deref_patterns)] - -pub enum Value { - String(String), - Number(u32), -} - -pub fn is_it_the_answer(value: Value) -> bool { - match value { - Value::String("42") => true, - Value::Number(42) => true, - _ => false, - } -} -``` - -Without this feature other constructs such as match guards have to be used. - -```rust -# pub enum Value { -# String(String), -# Number(u32), -# } -# -pub fn is_it_the_answer(value: Value) -> bool { - match value { - Value::String(s) if s == "42" => true, - Value::Number(42) => true, - _ => false, - } -} -``` - -[`deref_patterns`]: ./deref-patterns.md -[its `Deref` implementation]: https://doc.rust-lang.org/std/string/struct.String.html#impl-Deref-for-String diff --git a/tests/mir-opt/building/match/deref-patterns/string.foo.PreCodegen.after.mir b/tests/mir-opt/building/match/deref-patterns/string.foo.PreCodegen.after.mir index 9f52a8cd1e55e..c7c26d6351ad2 100644 --- a/tests/mir-opt/building/match/deref-patterns/string.foo.PreCodegen.after.mir +++ b/tests/mir-opt/building/match/deref-patterns/string.foo.PreCodegen.after.mir @@ -7,10 +7,11 @@ fn foo(_1: Option) -> i32 { let mut _3: isize; let mut _4: &std::string::String; let mut _5: &str; - let mut _6: bool; - let _7: std::option::Option; + let mut _6: &str; + let mut _7: bool; + let _8: std::option::Option; scope 1 { - debug s => _7; + debug s => _8; } bb0: { @@ -26,11 +27,12 @@ fn foo(_1: Option) -> i32 { } bb2: { - _6 = ::eq(copy _5, const "a") -> [return: bb3, unwind unreachable]; + _6 = &(*_5); + _7 = ::eq(copy _6, const "a") -> [return: bb3, unwind unreachable]; } bb3: { - switchInt(move _6) -> [0: bb5, otherwise: bb4]; + switchInt(move _7) -> [0: bb5, otherwise: bb4]; } bb4: { @@ -39,15 +41,15 @@ fn foo(_1: Option) -> i32 { } bb5: { - StorageLive(_7); + StorageLive(_8); _2 = const false; - _7 = move _1; + _8 = move _1; _0 = const 4321_i32; - drop(_7) -> [return: bb6, unwind unreachable]; + drop(_8) -> [return: bb6, unwind unreachable]; } bb6: { - StorageDead(_7); + StorageDead(_8); goto -> bb7; } diff --git a/tests/mir-opt/building/match/deref-patterns/string.rs b/tests/mir-opt/building/match/deref-patterns/string.rs index bb4b5379b2751..1f8d6fbb0bd25 100644 --- a/tests/mir-opt/building/match/deref-patterns/string.rs +++ b/tests/mir-opt/building/match/deref-patterns/string.rs @@ -1,7 +1,8 @@ // skip-filecheck //@ compile-flags: -Z mir-opt-level=0 -C panic=abort -#![feature(string_deref_patterns)] +#![feature(deref_patterns)] +#![expect(incomplete_features)] #![crate_type = "lib"] // EMIT_MIR string.foo.PreCodegen.after.mir diff --git a/tests/ui/README.md b/tests/ui/README.md index b1c813cce93fb..4c91f313a7351 100644 --- a/tests/ui/README.md +++ b/tests/ui/README.md @@ -380,12 +380,6 @@ These tests use the unstable command line option `query-dep-graph` to examine th Tests for `#[deprecated]` attribute and `deprecated_in_future` internal lint. -## `tests/ui/deref-patterns/`: `#![feature(deref_patterns)]` and `#![feature(string_deref_patterns)]` - -Tests for `#![feature(deref_patterns)]` and `#![feature(string_deref_patterns)]`. See [Deref patterns | The Unstable book](https://doc.rust-lang.org/nightly/unstable-book/language-features/deref-patterns.html). - -**FIXME**: May have some overlap with `tests/ui/pattern/deref-patterns`. - ## `tests/ui/derived-errors/`: Derived Error Messages Tests for quality of diagnostics involving suppression of cascading errors in some cases to avoid overwhelming the user. diff --git a/tests/ui/deref-patterns/gate.rs b/tests/ui/deref-patterns/gate.rs deleted file mode 100644 index 835fdf854d2c4..0000000000000 --- a/tests/ui/deref-patterns/gate.rs +++ /dev/null @@ -1,7 +0,0 @@ -// gate-test-string_deref_patterns -fn main() { - match String::new() { - "" | _ => {} - //~^ ERROR mismatched types - } -} diff --git a/tests/ui/deref-patterns/gate.stderr b/tests/ui/deref-patterns/gate.stderr deleted file mode 100644 index e3cbded339d7f..0000000000000 --- a/tests/ui/deref-patterns/gate.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0308]: mismatched types - --> $DIR/gate.rs:4:9 - | -LL | match String::new() { - | ------------- this expression has type `String` -LL | "" | _ => {} - | ^^ expected `String`, found `&str` - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/deref-patterns/basic.rs b/tests/ui/pattern/deref-patterns/basic.rs similarity index 83% rename from tests/ui/deref-patterns/basic.rs rename to tests/ui/pattern/deref-patterns/basic.rs index d76fb697f4062..dee4521e1f95c 100644 --- a/tests/ui/deref-patterns/basic.rs +++ b/tests/ui/pattern/deref-patterns/basic.rs @@ -1,6 +1,7 @@ //@ run-pass //@ check-run-results -#![feature(string_deref_patterns)] +#![feature(deref_patterns)] +#![expect(incomplete_features)] fn main() { test(Some(String::from("42"))); diff --git a/tests/ui/deref-patterns/basic.run.stdout b/tests/ui/pattern/deref-patterns/basic.run.stdout similarity index 100% rename from tests/ui/deref-patterns/basic.run.stdout rename to tests/ui/pattern/deref-patterns/basic.run.stdout diff --git a/tests/ui/deref-patterns/default-infer.rs b/tests/ui/pattern/deref-patterns/default-infer.rs similarity index 66% rename from tests/ui/deref-patterns/default-infer.rs rename to tests/ui/pattern/deref-patterns/default-infer.rs index 4f926175bd335..fb0b2add132a3 100644 --- a/tests/ui/deref-patterns/default-infer.rs +++ b/tests/ui/pattern/deref-patterns/default-infer.rs @@ -1,5 +1,6 @@ //@ check-pass -#![feature(string_deref_patterns)] +#![feature(deref_patterns)] +#![expect(incomplete_features)] fn main() { match <_ as Default>::default() { diff --git a/tests/ui/deref-patterns/refs.rs b/tests/ui/pattern/deref-patterns/refs.rs similarity index 79% rename from tests/ui/deref-patterns/refs.rs rename to tests/ui/pattern/deref-patterns/refs.rs index c93e579bfd804..51826225856bd 100644 --- a/tests/ui/deref-patterns/refs.rs +++ b/tests/ui/pattern/deref-patterns/refs.rs @@ -1,5 +1,6 @@ //@ check-pass -#![feature(string_deref_patterns)] +#![feature(deref_patterns)] +#![expect(incomplete_features)] fn foo(s: &String) -> i32 { match *s {