Skip to content

Commit 29a6971

Browse files
committed
Auto merge of #148397 - frank-king:feature/pin-pattern, r=Nadrieril,traviscross
Implement `&pin` patterns and `ref pin` binding modes Implement `&pin` patterns and `ref pin` binding modes, part of [pin ergonomics](#130494). r? `@Nadrieril` cc `@traviscross` `@eholk`
2 parents 055d0d6 + 5ef48ed commit 29a6971

File tree

62 files changed

+886
-240
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

62 files changed

+886
-240
lines changed

compiler/rustc_ast/src/ast.rs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -648,9 +648,10 @@ impl Pat {
648648
PatKind::Path(qself, path) => TyKind::Path(qself.clone(), path.clone()),
649649
PatKind::MacCall(mac) => TyKind::MacCall(mac.clone()),
650650
// `&mut? P` can be reinterpreted as `&mut? T` where `T` is `P` reparsed as a type.
651-
PatKind::Ref(pat, mutbl) => {
652-
pat.to_ty().map(|ty| TyKind::Ref(None, MutTy { ty, mutbl: *mutbl }))?
653-
}
651+
PatKind::Ref(pat, pinned, mutbl) => pat.to_ty().map(|ty| match pinned {
652+
Pinnedness::Not => TyKind::Ref(None, MutTy { ty, mutbl: *mutbl }),
653+
Pinnedness::Pinned => TyKind::PinnedRef(None, MutTy { ty, mutbl: *mutbl }),
654+
})?,
654655
// A slice/array pattern `[P]` can be reparsed as `[T]`, an unsized array,
655656
// when `P` can be reparsed as a type `T`.
656657
PatKind::Slice(pats) if let [pat] = pats.as_slice() => {
@@ -696,7 +697,7 @@ impl Pat {
696697
// Trivial wrappers over inner patterns.
697698
PatKind::Box(s)
698699
| PatKind::Deref(s)
699-
| PatKind::Ref(s, _)
700+
| PatKind::Ref(s, _, _)
700701
| PatKind::Paren(s)
701702
| PatKind::Guard(s, _) => s.walk(it),
702703

@@ -717,7 +718,7 @@ impl Pat {
717718
/// Strip off all reference patterns (`&`, `&mut`) and return the inner pattern.
718719
pub fn peel_refs(&self) -> &Pat {
719720
let mut current = self;
720-
while let PatKind::Ref(inner, _) = &current.kind {
721+
while let PatKind::Ref(inner, _, _) = &current.kind {
721722
current = inner;
722723
}
723724
current
@@ -765,7 +766,9 @@ impl Pat {
765766
PatKind::Missing => unreachable!(),
766767
PatKind::Wild => Some("_".to_string()),
767768
PatKind::Ident(BindingMode::NONE, ident, None) => Some(format!("{ident}")),
768-
PatKind::Ref(pat, mutbl) => pat.descr().map(|d| format!("&{}{d}", mutbl.prefix_str())),
769+
PatKind::Ref(pat, pinned, mutbl) => {
770+
pat.descr().map(|d| format!("&{}{d}", pinned.prefix_str(*mutbl)))
771+
}
769772
_ => None,
770773
}
771774
}
@@ -913,7 +916,7 @@ pub enum PatKind {
913916
Deref(Box<Pat>),
914917

915918
/// A reference pattern (e.g., `&mut (a, b)`).
916-
Ref(Box<Pat>, Mutability),
919+
Ref(Box<Pat>, Pinnedness, Mutability),
917920

918921
/// A literal, const block or path.
919922
Expr(Box<Expr>),

compiler/rustc_ast_ir/src/lib.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,4 +317,15 @@ impl Pinnedness {
317317
pub fn is_pinned(self) -> bool {
318318
matches!(self, Self::Pinned)
319319
}
320+
321+
/// Returns `""` (empty string), "mut", `"pin mut "` or `"pin const "` depending
322+
/// on the pinnedness and mutability.
323+
pub fn prefix_str(self, mutbl: Mutability) -> &'static str {
324+
match (self, mutbl) {
325+
(Pinnedness::Pinned, Mutability::Mut) => "pin mut ",
326+
(Pinnedness::Pinned, Mutability::Not) => "pin const ",
327+
(Pinnedness::Not, Mutability::Mut) => "mut ",
328+
(Pinnedness::Not, Mutability::Not) => "",
329+
}
330+
}
320331
}

compiler/rustc_ast_lowering/src/pat.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,8 +124,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
124124
PatKind::Deref(inner) => {
125125
break hir::PatKind::Deref(self.lower_pat(inner));
126126
}
127-
PatKind::Ref(inner, mutbl) => {
128-
break hir::PatKind::Ref(self.lower_pat(inner), *mutbl);
127+
PatKind::Ref(inner, pinned, mutbl) => {
128+
break hir::PatKind::Ref(self.lower_pat(inner), *pinned, *mutbl);
129129
}
130130
PatKind::Range(e1, e2, Spanned { node: end, .. }) => {
131131
break hir::PatKind::Range(

compiler/rustc_ast_pretty/src/pprust/state.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1807,8 +1807,14 @@ impl<'a> State<'a> {
18071807
self.print_pat(inner);
18081808
self.pclose();
18091809
}
1810-
PatKind::Ref(inner, mutbl) => {
1810+
PatKind::Ref(inner, pinned, mutbl) => {
18111811
self.word("&");
1812+
if pinned.is_pinned() {
1813+
self.word("pin ");
1814+
if mutbl.is_not() {
1815+
self.word("const ");
1816+
}
1817+
}
18121818
if mutbl.is_mut() {
18131819
self.word("mut ");
18141820
}

compiler/rustc_borrowck/src/diagnostics/move_errors.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -867,11 +867,12 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
867867
for (binding_span, opt_ref_pat) in finder.ref_pat_for_binding {
868868
if let Some(ref_pat) = opt_ref_pat
869869
&& !finder.cannot_remove.contains(&ref_pat.hir_id)
870-
&& let hir::PatKind::Ref(subpat, mutbl) = ref_pat.kind
870+
&& let hir::PatKind::Ref(subpat, pinned, mutbl) = ref_pat.kind
871871
&& let Some(ref_span) = ref_pat.span.trim_end(subpat.span)
872872
{
873+
let pinned_str = if pinned.is_pinned() { "pinned " } else { "" };
873874
let mutable_str = if mutbl.is_mut() { "mutable " } else { "" };
874-
let msg = format!("consider removing the {mutable_str}borrow");
875+
let msg = format!("consider removing the {pinned_str}{mutable_str}borrow");
875876
suggestions.push((ref_span, msg, "".to_string()));
876877
} else {
877878
let msg = "consider borrowing the pattern binding".to_string();

compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -772,11 +772,11 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
772772
&& let Some(hir_id) = (BindingFinder { span: pat_span }).visit_body(&body).break_value()
773773
&& let node = self.infcx.tcx.hir_node(hir_id)
774774
&& let hir::Node::LetStmt(hir::LetStmt {
775-
pat: hir::Pat { kind: hir::PatKind::Ref(_, _), .. },
775+
pat: hir::Pat { kind: hir::PatKind::Ref(_, _, _), .. },
776776
..
777777
})
778778
| hir::Node::Param(Param {
779-
pat: hir::Pat { kind: hir::PatKind::Ref(_, _), .. },
779+
pat: hir::Pat { kind: hir::PatKind::Ref(_, _, _), .. },
780780
..
781781
}) = node
782782
{
@@ -1494,7 +1494,7 @@ impl<'tcx> Visitor<'tcx> for BindingFinder {
14941494
}
14951495

14961496
fn visit_param(&mut self, param: &'tcx hir::Param<'tcx>) -> Self::Result {
1497-
if let hir::Pat { kind: hir::PatKind::Ref(_, _), span, .. } = param.pat
1497+
if let hir::Pat { kind: hir::PatKind::Ref(_, _, _), span, .. } = param.pat
14981498
&& *span == self.span
14991499
{
15001500
ControlFlow::Break(param.hir_id)

compiler/rustc_hir/src/hir.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1722,7 +1722,9 @@ impl<'hir> Pat<'hir> {
17221722
match self.kind {
17231723
Missing => unreachable!(),
17241724
Wild | Never | Expr(_) | Range(..) | Binding(.., None) | Err(_) => true,
1725-
Box(s) | Deref(s) | Ref(s, _) | Binding(.., Some(s)) | Guard(s, _) => s.walk_short_(it),
1725+
Box(s) | Deref(s) | Ref(s, _, _) | Binding(.., Some(s)) | Guard(s, _) => {
1726+
s.walk_short_(it)
1727+
}
17261728
Struct(_, fields, _) => fields.iter().all(|field| field.pat.walk_short_(it)),
17271729
TupleStruct(_, s, _) | Tuple(s, _) | Or(s) => s.iter().all(|p| p.walk_short_(it)),
17281730
Slice(before, slice, after) => {
@@ -1749,7 +1751,7 @@ impl<'hir> Pat<'hir> {
17491751
use PatKind::*;
17501752
match self.kind {
17511753
Missing | Wild | Never | Expr(_) | Range(..) | Binding(.., None) | Err(_) => {}
1752-
Box(s) | Deref(s) | Ref(s, _) | Binding(.., Some(s)) | Guard(s, _) => s.walk_(it),
1754+
Box(s) | Deref(s) | Ref(s, _, _) | Binding(.., Some(s)) | Guard(s, _) => s.walk_(it),
17531755
Struct(_, fields, _) => fields.iter().for_each(|field| field.pat.walk_(it)),
17541756
TupleStruct(_, s, _) | Tuple(s, _) | Or(s) => s.iter().for_each(|p| p.walk_(it)),
17551757
Slice(before, slice, after) => {
@@ -1938,7 +1940,7 @@ pub enum PatKind<'hir> {
19381940
Deref(&'hir Pat<'hir>),
19391941

19401942
/// A reference pattern (e.g., `&mut (a, b)`).
1941-
Ref(&'hir Pat<'hir>, Mutability),
1943+
Ref(&'hir Pat<'hir>, Pinnedness, Mutability),
19421944

19431945
/// A literal, const block or path.
19441946
Expr(&'hir PatExpr<'hir>),

compiler/rustc_hir/src/intravisit.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -752,7 +752,7 @@ pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat<'v>) -> V:
752752
}
753753
PatKind::Box(ref subpattern)
754754
| PatKind::Deref(ref subpattern)
755-
| PatKind::Ref(ref subpattern, _) => {
755+
| PatKind::Ref(ref subpattern, _, _) => {
756756
try_visit!(visitor.visit_pat(subpattern));
757757
}
758758
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
@@ -593,7 +593,7 @@ fn resolve_local<'tcx>(
593593
is_binding_pat(subpat)
594594
}
595595

596-
PatKind::Ref(_, _)
596+
PatKind::Ref(_, _, _)
597597
| PatKind::Binding(hir::BindingMode(hir::ByRef::No, _), ..)
598598
| PatKind::Missing
599599
| PatKind::Wild

compiler/rustc_hir_pretty/src/lib.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2028,9 +2028,15 @@ impl<'a> State<'a> {
20282028
self.print_pat(inner);
20292029
self.pclose();
20302030
}
2031-
PatKind::Ref(inner, mutbl) => {
2031+
PatKind::Ref(inner, pinned, mutbl) => {
20322032
let is_range_inner = matches!(inner.kind, PatKind::Range(..));
20332033
self.word("&");
2034+
if pinned.is_pinned() {
2035+
self.word("pin ");
2036+
if mutbl.is_not() {
2037+
self.word("const ");
2038+
}
2039+
}
20342040
self.word(mutbl.prefix_str());
20352041
if is_range_inner {
20362042
self.popen();

0 commit comments

Comments
 (0)