Remove feature(string_deref_patterns)

This commit is contained in:
Zalathar 2025-12-31 11:10:29 +11:00
parent 0e89999425
commit ef8d943ecd
17 changed files with 24 additions and 150 deletions

View file

@ -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

View file

@ -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.

View file

@ -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

View file

@ -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>,
},

View file

@ -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 = <String as Deref>::deref(&place);`
self.call_deref(
block,
eq_block,
place,
Mutability::Not,
cast_ty,
ref_str,
test.span,
);
// Since we generated a `ref_str = <String as Deref>::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());

View file

@ -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),
};

View file

@ -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

View file

@ -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

View file

@ -7,10 +7,11 @@ fn foo(_1: Option<String>) -> i32 {
let mut _3: isize;
let mut _4: &std::string::String;
let mut _5: &str;
let mut _6: bool;
let _7: std::option::Option<std::string::String>;
let mut _6: &str;
let mut _7: bool;
let _8: std::option::Option<std::string::String>;
scope 1 {
debug s => _7;
debug s => _8;
}
bb0: {
@ -26,11 +27,12 @@ fn foo(_1: Option<String>) -> i32 {
}
bb2: {
_6 = <str as PartialEq>::eq(copy _5, const "a") -> [return: bb3, unwind unreachable];
_6 = &(*_5);
_7 = <str as PartialEq>::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<String>) -> 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;
}

View file

@ -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

View file

@ -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.

View file

@ -1,7 +0,0 @@
// gate-test-string_deref_patterns
fn main() {
match String::new() {
"" | _ => {}
//~^ ERROR mismatched types
}
}

View file

@ -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`.

View file

@ -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")));

View file

@ -1,5 +1,6 @@
//@ check-pass
#![feature(string_deref_patterns)]
#![feature(deref_patterns)]
#![expect(incomplete_features)]
fn main() {
match <_ as Default>::default() {

View file

@ -1,5 +1,6 @@
//@ check-pass
#![feature(string_deref_patterns)]
#![feature(deref_patterns)]
#![expect(incomplete_features)]
fn foo(s: &String) -> i32 {
match *s {