Skip to content

Commit 2d63331

Browse files
Implement macro-based deref!() syntax for deref patterns
Stop using `box PAT` syntax for deref patterns, as it's misleading and also causes their semantics being tangled up.
1 parent 2627e9f commit 2d63331

File tree

31 files changed

+123
-35
lines changed

31 files changed

+123
-35
lines changed

compiler/rustc_ast/src/ast.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -621,7 +621,9 @@ impl Pat {
621621
| PatKind::Or(s) => s.iter().for_each(|p| p.walk(it)),
622622

623623
// Trivial wrappers over inner patterns.
624-
PatKind::Box(s) | PatKind::Ref(s, _) | PatKind::Paren(s) => s.walk(it),
624+
PatKind::Box(s) | PatKind::Deref(s) | PatKind::Ref(s, _) | PatKind::Paren(s) => {
625+
s.walk(it)
626+
}
625627

626628
// These patterns do not contain subpatterns, skip.
627629
PatKind::Wild
@@ -792,6 +794,9 @@ pub enum PatKind {
792794
/// A `box` pattern.
793795
Box(P<Pat>),
794796

797+
/// A `deref` pattern (currently `deref!()` macro-based syntax).
798+
Deref(P<Pat>),
799+
795800
/// A reference pattern (e.g., `&mut (a, b)`).
796801
Ref(P<Pat>, Mutability),
797802

compiler/rustc_ast/src/mut_visit.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1295,6 +1295,7 @@ pub fn noop_visit_pat<T: MutVisitor>(pat: &mut P<Pat>, vis: &mut T) {
12951295
fields.flat_map_in_place(|field| vis.flat_map_pat_field(field));
12961296
}
12971297
PatKind::Box(inner) => vis.visit_pat(inner),
1298+
PatKind::Deref(inner) => vis.visit_pat(inner),
12981299
PatKind::Ref(inner, _mutbl) => vis.visit_pat(inner),
12991300
PatKind::Range(e1, e2, Spanned { span: _, node: _ }) => {
13001301
visit_opt(e1, |e| vis.visit_expr(e));

compiler/rustc_ast/src/visit.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -576,7 +576,10 @@ pub fn walk_pat<'a, V: Visitor<'a>>(visitor: &mut V, pattern: &'a Pat) -> V::Res
576576
try_visit!(visitor.visit_path(path, pattern.id));
577577
walk_list!(visitor, visit_pat_field, fields);
578578
}
579-
PatKind::Box(subpattern) | PatKind::Ref(subpattern, _) | PatKind::Paren(subpattern) => {
579+
PatKind::Box(subpattern)
580+
| PatKind::Deref(subpattern)
581+
| PatKind::Ref(subpattern, _)
582+
| PatKind::Paren(subpattern) => {
580583
try_visit!(visitor.visit_pat(subpattern));
581584
}
582585
PatKind::Ident(_, ident, optional_subpattern) => {

compiler/rustc_ast_lowering/src/pat.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
9191
PatKind::Box(inner) => {
9292
break hir::PatKind::Box(self.lower_pat(inner));
9393
}
94+
PatKind::Deref(inner) => {
95+
break hir::PatKind::Deref(self.lower_pat(inner));
96+
}
9497
PatKind::Ref(inner, mutbl) => {
9598
break hir::PatKind::Ref(self.lower_pat(inner), *mutbl);
9699
}

compiler/rustc_ast_passes/src/feature_gate.rs

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -413,10 +413,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
413413
}
414414
}
415415
PatKind::Box(..) => {
416-
if !self.features.deref_patterns {
417-
// Allow box patterns under `deref_patterns`.
418-
gate!(&self, box_patterns, pattern.span, "box pattern syntax is experimental");
419-
}
416+
gate!(&self, box_patterns, pattern.span, "box pattern syntax is experimental");
420417
}
421418
PatKind::Range(_, Some(_), Spanned { node: RangeEnd::Excluded, .. }) => {
422419
gate!(
@@ -610,10 +607,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
610607
};
611608
}
612609

613-
if !visitor.features.deref_patterns {
614-
// Allow box patterns under `deref_patterns`.
615-
gate_all_legacy_dont_use!(box_patterns, "box pattern syntax is experimental");
616-
}
610+
gate_all_legacy_dont_use!(box_patterns, "box pattern syntax is experimental");
617611
gate_all_legacy_dont_use!(trait_alias, "trait aliases are experimental");
618612
// Despite being a new feature, `where T: Trait<Assoc(): Sized>`, which is RTN syntax now,
619613
// used to be gated under associated_type_bounds, which are right above, so RTN needs to

compiler/rustc_ast_pretty/src/pprust/state.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1626,6 +1626,12 @@ impl<'a> State<'a> {
16261626
self.word("box ");
16271627
self.print_pat(inner);
16281628
}
1629+
PatKind::Deref(inner) => {
1630+
self.word("deref!");
1631+
self.popen();
1632+
self.print_pat(inner);
1633+
self.pclose();
1634+
}
16291635
PatKind::Ref(inner, mutbl) => {
16301636
self.word("&");
16311637
if mutbl.is_mut() {

compiler/rustc_hir/src/hir.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1015,7 +1015,7 @@ impl<'hir> Pat<'hir> {
10151015
use PatKind::*;
10161016
match self.kind {
10171017
Wild | Never | Lit(_) | Range(..) | Binding(.., None) | Path(_) | Err(_) => true,
1018-
Box(s) | Ref(s, _) | Binding(.., Some(s)) => s.walk_short_(it),
1018+
Box(s) | Deref(s) | Ref(s, _) | Binding(.., Some(s)) => s.walk_short_(it),
10191019
Struct(_, fields, _) => fields.iter().all(|field| field.pat.walk_short_(it)),
10201020
TupleStruct(_, s, _) | Tuple(s, _) | Or(s) => s.iter().all(|p| p.walk_short_(it)),
10211021
Slice(before, slice, after) => {
@@ -1042,7 +1042,7 @@ impl<'hir> Pat<'hir> {
10421042
use PatKind::*;
10431043
match self.kind {
10441044
Wild | Never | Lit(_) | Range(..) | Binding(.., None) | Path(_) | Err(_) => {}
1045-
Box(s) | Ref(s, _) | Binding(.., Some(s)) => s.walk_(it),
1045+
Box(s) | Deref(s) | Ref(s, _) | Binding(.., Some(s)) => s.walk_(it),
10461046
Struct(_, fields, _) => fields.iter().for_each(|field| field.pat.walk_(it)),
10471047
TupleStruct(_, s, _) | Tuple(s, _) | Or(s) => s.iter().for_each(|p| p.walk_(it)),
10481048
Slice(before, slice, after) => {
@@ -1185,6 +1185,9 @@ pub enum PatKind<'hir> {
11851185
/// A `box` pattern.
11861186
Box(&'hir Pat<'hir>),
11871187

1188+
/// A `deref` pattern (currently `deref!()` macro-based syntax).
1189+
Deref(&'hir Pat<'hir>),
1190+
11881191
/// A reference pattern (e.g., `&mut (a, b)`).
11891192
Ref(&'hir Pat<'hir>, Mutability),
11901193

compiler/rustc_hir/src/intravisit.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -660,7 +660,9 @@ pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat<'v>) -> V:
660660
PatKind::Tuple(tuple_elements, _) => {
661661
walk_list!(visitor, visit_pat, tuple_elements);
662662
}
663-
PatKind::Box(ref subpattern) | PatKind::Ref(ref subpattern, _) => {
663+
PatKind::Box(ref subpattern)
664+
| PatKind::Deref(ref subpattern)
665+
| PatKind::Ref(ref subpattern, _) => {
664666
try_visit!(visitor.visit_pat(subpattern));
665667
}
666668
PatKind::Binding(_, _hir_id, ident, ref optional_subpattern) => {

compiler/rustc_hir_analysis/src/check/region.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -668,7 +668,7 @@ fn resolve_local<'tcx>(
668668
| PatKind::TupleStruct(_, subpats, _)
669669
| PatKind::Tuple(subpats, _) => subpats.iter().any(|p| is_binding_pat(p)),
670670

671-
PatKind::Box(subpat) => is_binding_pat(subpat),
671+
PatKind::Box(subpat) | PatKind::Deref(subpat) => is_binding_pat(subpat),
672672

673673
PatKind::Ref(_, _)
674674
| PatKind::Binding(hir::BindingAnnotation(hir::ByRef::No, _), ..)

compiler/rustc_hir_pretty/src/lib.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1808,6 +1808,12 @@ impl<'a> State<'a> {
18081808
self.pclose();
18091809
}
18101810
}
1811+
PatKind::Deref(inner) => {
1812+
self.word("deref!");
1813+
self.popen();
1814+
self.print_pat(inner);
1815+
self.pclose();
1816+
}
18111817
PatKind::Ref(inner, mutbl) => {
18121818
let is_range_inner = matches!(inner.kind, PatKind::Range(..));
18131819
self.word("&");

0 commit comments

Comments
 (0)