Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 1 addition & 5 deletions compiler/rustc_ast/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -688,8 +688,7 @@ impl Pat {
| PatKind::Or(s) => s.iter().for_each(|p| p.walk(it)),

// Trivial wrappers over inner patterns.
PatKind::Box(s)
| PatKind::Deref(s)
PatKind::Deref(s)
| PatKind::Ref(s, _, _)
| PatKind::Paren(s)
| PatKind::Guard(s, _) => s.walk(it),
Expand Down Expand Up @@ -902,9 +901,6 @@ pub enum PatKind {
/// A tuple pattern (`(a, b)`).
Tuple(ThinVec<Pat>),

/// A `box` pattern.
Box(Box<Pat>),

/// A `deref` pattern (currently `deref!()` macro-based syntax).
Deref(Box<Pat>),

Expand Down
3 changes: 0 additions & 3 deletions compiler/rustc_ast_lowering/src/pat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,9 +117,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
let (pats, ddpos) = self.lower_pat_tuple(pats, "tuple");
break hir::PatKind::Tuple(pats, ddpos);
}
PatKind::Box(inner) => {
break hir::PatKind::Box(self.lower_pat(inner));
}
PatKind::Deref(inner) => {
break hir::PatKind::Deref(self.lower_pat(inner));
}
Expand Down
4 changes: 0 additions & 4 deletions compiler/rustc_ast_passes/src/feature_gate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -375,9 +375,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
}
}
}
PatKind::Box(..) => {
gate!(self, box_patterns, pattern.span, "box pattern syntax is experimental");
}
_ => {}
}
visit::walk_pat(self, pattern)
Expand Down Expand Up @@ -615,7 +612,6 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {

// tidy-alphabetical-start
soft_gate_all_legacy_dont_use!(auto_traits, "`auto` traits are unstable");
soft_gate_all_legacy_dont_use!(box_patterns, "box pattern syntax is experimental");
soft_gate_all_legacy_dont_use!(decl_macro, "`macro` is experimental");
soft_gate_all_legacy_dont_use!(negative_impls, "negative impls are experimental");
soft_gate_all_legacy_dont_use!(specialization, "specialization is experimental");
Expand Down
4 changes: 0 additions & 4 deletions compiler/rustc_ast_pretty/src/pprust/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1980,10 +1980,6 @@ impl<'a> State<'a> {
}
self.pclose();
}
PatKind::Box(inner) => {
self.word("box ");
self.print_pat_paren_if_or(inner);
}
PatKind::Deref(inner) => {
self.word("deref!");
self.popen();
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_feature/src/removed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ declare_features! (
Some("merged into `min_generic_const_args`")),
(removed, await_macro, "1.38.0", Some(50547),
Some("subsumed by `.await` syntax"), 62293),
/// Allows using `box` in patterns (RFC 469).
(removed, box_patterns, "CURRENT_RUSTC_VERSION", Some(29641), Some("superseded by `deref_patterns`")),
/// Allows using the `box $expr` syntax.
(removed, box_syntax, "1.70.0", Some(49733), Some("replaced with `#[rustc_box]`"), 108471),
/// Allows capturing disjoint fields in a closure/coroutine (RFC 2229).
Expand Down
2 changes: 0 additions & 2 deletions compiler/rustc_feature/src/unstable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -311,8 +311,6 @@ declare_features! (
/// Allows features specific to auto traits.
/// Renamed from `optin_builtin_traits`.
(unstable, auto_traits, "1.50.0", Some(13231)),
/// Allows using `box` in patterns (RFC 469).
(unstable, box_patterns, "1.0.0", Some(29641)),
/// Allows builtin # foo() syntax
(internal, builtin_syntax, "1.71.0", Some(110680)),
/// Allows `#[doc(notable_trait)]`.
Expand Down
3 changes: 0 additions & 3 deletions compiler/rustc_lint/src/internal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -674,9 +674,6 @@ impl EarlyLintPass for BadUseOfFindAttr {
find_attr_kind_in_pat(cx, pat);
}
}
PatKind::Box(pat) => {
find_attr_kind_in_pat(cx, pat);
}
PatKind::Deref(pat) => {
find_attr_kind_in_pat(cx, pat);
}
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_lint/src/unused.rs
Original file line number Diff line number Diff line change
Expand Up @@ -784,8 +784,8 @@ impl EarlyLintPass for UnusedParens {
self.check_unused_parens_pat(cx, &f.pat, false, false, keep_space);
}
}
// Avoid linting on `i @ (p0 | .. | pn)` and `box (p0 | .. | pn)`, #64106.
Ident(.., Some(p)) | Box(p) | Deref(p) | Guard(p, _) => {
// Avoid linting on `i @ (p0 | .. | pn)`, #64106.
Ident(.., Some(p)) | Deref(p) | Guard(p, _) => {
self.check_unused_parens_pat(cx, p, true, false, keep_space)
}
// Avoid linting on `&(mut x)` as `&mut x` has a different meaning, #55342.
Expand Down
7 changes: 7 additions & 0 deletions compiler/rustc_parse/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3702,6 +3702,13 @@ pub(crate) struct AddBoxNew {
pub hi: Span,
}

#[derive(Diagnostic)]
#[diag("`box_patterns` have been removed")]

@Kivooeo Kivooeo Jun 4, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
#[diag("`box_patterns` have been removed")]
#[diag("`box_patterns` has been removed")]

View changes since the review

pub(crate) struct BoxPatternsRemoved {
#[primary_span]
pub span: Span,
}

#[derive(Diagnostic)]
#[diag("return type not allowed with return type notation")]
pub(crate) struct BadReturnTypeNotationOutput {
Expand Down
23 changes: 11 additions & 12 deletions compiler/rustc_parse/src/parser/pat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -671,7 +671,7 @@ impl<'a> Parser<'a> {

// Sub-patterns
// FIXME: this doesn't work with recursive subpats (`&mut &mut <err>`)
PatKind::Box(subpat) | PatKind::Ref(subpat, _, _)
PatKind::Ref(subpat, _, _)
if matches!(subpat.kind, PatKind::Err(_) | PatKind::Expr(_)) =>
{
self.maybe_add_suggestions_then_emit(subpat.span, p.span, false)
Expand Down Expand Up @@ -1495,9 +1495,11 @@ impl<'a> Parser<'a> {

Ok(PatKind::Ident(BindingMode::NONE, Ident::new(kw::Box, box_span), sub))
} else {
let pat = Box::new(self.parse_pat_with_range_pat(false, None, None)?);
self.psess.gated_spans.gate(sym::box_patterns, box_span.to(self.prev_token.span));
Ok(PatKind::Box(pat))
self.parse_pat_with_range_pat(false, None, None)?;
let guar = self
.dcx()
.emit_err(errors::BoxPatternsRemoved { span: box_span.to(self.prev_token.span) });
Ok(PatKind::Err(guar))
}
}

Expand Down Expand Up @@ -1731,7 +1733,7 @@ impl<'a> Parser<'a> {
/// Parse a field in a struct pattern.
///
/// ```ebnf
/// PatField = FieldName ":" Pat | "box"? "mut"? ByRef? Ident
/// PatField = FieldName ":" Pat | "mut"? ByRef? Ident
/// ```
fn parse_pat_field(&mut self, lo: Span, attrs: AttrVec) -> PResult<'a, PatField> {
let hi;
Expand All @@ -1749,7 +1751,9 @@ impl<'a> Parser<'a> {
} else {
let is_box = self.eat_keyword(exp!(Box));
if is_box {
self.psess.gated_spans.gate(sym::box_patterns, self.prev_token.span);
return Err(self
.dcx()
.create_err(errors::BoxPatternsRemoved { span: self.prev_token.span }));
}
let boxed_span = self.token.span;
let mutability = self.parse_mutability();
Expand All @@ -1765,12 +1769,7 @@ impl<'a> Parser<'a> {
) {
self.psess.gated_spans.gate(sym::mut_ref, fieldpat.span);
}
let subpat = if is_box {
self.mk_pat(lo.to(hi), PatKind::Box(Box::new(fieldpat)))
} else {
fieldpat
};
(subpat, fieldname, true)
(fieldpat, fieldname, true)
};

Ok(PatField {
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_passes/src/input_stats.rs
Original file line number Diff line number Diff line change
Expand Up @@ -634,7 +634,6 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> {
Or,
Path,
Tuple,
Box,
Deref,
Ref,
Expr,
Expand Down
34 changes: 0 additions & 34 deletions src/doc/unstable-book/src/language-features/box-patterns.md

This file was deleted.

5 changes: 2 additions & 3 deletions src/doc/unstable-book/src/language-features/deref-patterns.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ The tracking issue for this feature is: [#87121]

------------------------

> **Note**: This feature supersedes [`box_patterns`].
> **Note**: This feature supersedes `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
Expand Down Expand Up @@ -52,7 +52,7 @@ if let [b] = &mut *v {
assert_eq!(v, [Box::new(Some(2))]);
```

Like [`box_patterns`], deref patterns may move out of boxes:
Deref patterns may move out of boxes:

```rust
# #![feature(deref_patterns)]
Expand Down Expand Up @@ -98,5 +98,4 @@ match *(b"test" as &[u8]) {
}
```

[`box_patterns`]: ./box-patterns.md
[smart pointers in the standard library]: https://doc.rust-lang.org/std/ops/trait.DerefPure.html#implementors
11 changes: 2 additions & 9 deletions src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,8 +150,8 @@ fn insert_necessary_parens(pat: &mut Pat) {
use ast::BindingMode;
walk_pat(self, pat);
let target = match &mut pat.kind {
// `i @ a | b`, `box a | b`, and `& mut? a | b`.
Ident(.., Some(p)) | Box(p) | Ref(p, _, _)
// `i @ a | b` and `& mut? a | b`.
Ident(.., Some(p)) | Ref(p, _, _)
if let Or(ps) = &p.kind
&& ps.len() > 1 =>
{
Expand Down Expand Up @@ -251,15 +251,8 @@ fn transform_with_focus_on_idx(alternatives: &mut ThinVec<Pat>, focus_idx: usize
| Ref(_, _, Mutability::Not)
// Dealt with elsewhere.
| Or(_) | Paren(_) | Deref(_) | Guard(..) => false,
// Transform `box x | ... | box y` into `box (x | y)`.
//
// The cases below until `Slice(...)` deal with *singleton* products.
// These patterns have the shape `C(p)`, and not e.g., `C(p0, ..., pn)`.
Box(target) => extend_with_matching(
target, start, alternatives,
|k| matches!(k, Box(_)),
|k| always_pat!(k, Box(p) => *p),
),
// Transform `&mut x | ... | &mut y` into `&mut (x | y)`.
Ref(target, _, Mutability::Mut) => extend_with_matching(
target, start, alternatives,
Expand Down
1 change: 0 additions & 1 deletion src/tools/clippy/clippy_utils/src/ast_utils/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ pub fn eq_pat(l: &Pat, r: &Pat) -> bool {
&& eq_expr_opt(lt.as_deref(), rt.as_deref())
&& eq_range_end(le.node, re.node)
},
(Box(l), Box(r)) => eq_pat(l, r),
(Ref(l, l_pin, l_mut), Ref(r, r_pin, r_mut)) => l_pin == r_pin && l_mut == r_mut && eq_pat(l, r),
(Tuple(l), Tuple(r)) | (Slice(l), Slice(r)) => over(l, r, eq_pat),
(Path(lq, lp), Path(rq, rp)) => both(lq.as_deref(), rq.as_deref(), eq_qself) && eq_path(lp, rp),
Expand Down
6 changes: 2 additions & 4 deletions src/tools/rustfmt/src/patterns.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,7 @@ fn is_short_pattern_inner(context: &RewriteContext<'_>, pat: &ast::Pat) -> bool
ast::PatKind::TupleStruct(_, ref path, ref subpats) => {
path.segments.len() <= 1 && subpats.len() <= 1
}
ast::PatKind::Box(ref p)
| PatKind::Deref(ref p)
PatKind::Deref(ref p)
| ast::PatKind::Ref(ref p, _, _)
| ast::PatKind::Paren(ref p) => is_short_pattern_inner(context, &*p),
PatKind::Or(ref pats) => pats.iter().all(|p| is_short_pattern_inner(context, p)),
Expand Down Expand Up @@ -131,7 +130,6 @@ impl Rewrite for Pat {
.ends_with_newline(false);
write_list(&items, &fmt)
}
PatKind::Box(ref pat) => rewrite_unary_prefix(context, "box ", &**pat, shape),
PatKind::Ident(BindingMode(by_ref, mutability), ident, ref sub_pat) => {
let mut_prefix = format_mutability(mutability).trim();

Expand Down Expand Up @@ -585,7 +583,7 @@ pub(crate) fn can_be_overflowed_pat(
| ast::PatKind::Tuple(..)
| ast::PatKind::Struct(..)
| ast::PatKind::TupleStruct(..) => context.use_block_indent() && len == 1,
ast::PatKind::Ref(ref p, _, _) | ast::PatKind::Box(ref p) => {
ast::PatKind::Ref(ref p, _, _) => {
can_be_overflowed_pat(context, &TuplePatField::Pat(p), len)
}
ast::PatKind::Expr(ref expr) => can_be_overflowed_expr(context, expr, len),
Expand Down
4 changes: 2 additions & 2 deletions tests/debuginfo/destructured-fn-argument.rs
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,7 @@
//@ lldb-command:continue

#![allow(unused_variables)]
#![feature(box_patterns)]
#![feature(deref_patterns)]

use self::Univariant::Unit;

Expand Down Expand Up @@ -370,7 +370,7 @@ fn contained_borrowed_pointer((&cc, _): (&isize, isize)) {
zzz(); // #break
}

fn unique_pointer(box dd: Box<(isize, isize, isize)>) {
fn unique_pointer(deref!(dd): Box<(isize, isize, isize)>) {
zzz(); // #break
}

Expand Down
4 changes: 2 additions & 2 deletions tests/debuginfo/destructured-for-loop-variable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@
//@ lldb-command:continue

#![allow(unused_variables)]
#![feature(box_patterns)]
#![feature(deref_patterns)]

struct Struct {
x: i16,
Expand Down Expand Up @@ -186,7 +186,7 @@ fn main() {
for &(v1,
&Struct { x: x1, y: ref y1, z: z1 },
Struct { x: ref x2, y: y2, z: ref z2 },
box v2) in [more_complex].iter() {
deref!(v2)) in [more_complex].iter() {
zzz(); // #break
}

Expand Down
4 changes: 2 additions & 2 deletions tests/debuginfo/destructured-local.rs
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@


#![allow(unused_variables)]
#![feature(box_patterns)]
#![feature(deref_patterns)]

use self::Univariant::Unit;

Expand Down Expand Up @@ -291,7 +291,7 @@ fn main() {
let (&cc, _) = (&38, 39);

// unique pointer
let box dd = Box::new((40, 41, 42));
let deref!(dd) = Box::new((40, 41, 42));

// ref binding
let ref ee = (43, 44, 45);
Expand Down
4 changes: 2 additions & 2 deletions tests/pretty/or-pattern-paren.pp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#![feature(prelude_import)]
#![no_std]
#![feature(box_patterns)]
#![feature(deref_patterns)]
extern crate std;
#[prelude_import]
use ::std::prelude::rust_2015::*;
Expand All @@ -23,5 +23,5 @@
}
}
fn check_ref(x: &i32) { match x { &(1 | 2 | 3) => {} _ => {} } }
fn check_box(x: Box<i32>) { match x { box (1 | 2 | 3) => {} _ => {} } }
fn check_box(x: Box<i32>) { match x { deref!(1 | 2 | 3) => {} _ => {} } }
fn main() { check_at(Some(2)); check_ref(&1); check_box(Box::new(1)); }
4 changes: 2 additions & 2 deletions tests/pretty/or-pattern-paren.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#![feature(box_patterns)]
#![feature(deref_patterns)]

//@ pretty-compare-only
//@ pretty-mode:expanded
Expand All @@ -24,7 +24,7 @@ fn check_ref(x: &i32) {

fn check_box(x: Box<i32>) {
match x {
box or_pat!(1, 2, 3) => {}
deref!(or_pat!(1, 2, 3)) => {}
_ => {}
}
}
Expand Down
3 changes: 1 addition & 2 deletions tests/ui/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -179,12 +179,11 @@ Tests for borrow checking. E.g. lifetime analysis, borrowing rules, and diagnost

## `tests/ui/box/`: Box Behavior

Tests for `Box<T>` smart pointer and `#![feature(box_patterns)]`. E.g. allocation, deref coercion, and edge cases in box pattern matching and placement.
Tests for the `Box<T>` smart pointer. E.g. allocation, deref coercion, and edge cases in box pattern matching and placement.

See:

- [`std::box::Boxed`](https://doc.rust-lang.org/std/boxed/struct.Box.html)
- [Tracking issue for `box_patterns` feature #29641](https://github.com/rust-lang/rust/issues/29641)

## `tests/ui/builtin-superkinds/`: Built-in Trait Hierarchy Tests

Expand Down
Loading
Loading