Skip to content

Commit 47329dc

Browse files
frank-king王俊吉
authored andcommitted
Implement &pin patterns and ref pin bindings
1 parent f2bae99 commit 47329dc

File tree

27 files changed

+454
-160
lines changed

27 files changed

+454
-160
lines changed

compiler/rustc_ast/src/ast.rs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -648,10 +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-
}
654-
// A slice/array pattern `[P]` can be reparsed as `[T]`, an unsized array,
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+
})?,
655655
// when `P` can be reparsed as a type `T`.
656656
PatKind::Slice(pats) if let [pat] = pats.as_slice() => {
657657
pat.to_ty().map(TyKind::Slice)?
@@ -696,7 +696,7 @@ impl Pat {
696696
// Trivial wrappers over inner patterns.
697697
PatKind::Box(s)
698698
| PatKind::Deref(s)
699-
| PatKind::Ref(s, _)
699+
| PatKind::Ref(s, _, _)
700700
| PatKind::Paren(s)
701701
| PatKind::Guard(s, _) => s.walk(it),
702702

@@ -756,7 +756,9 @@ impl Pat {
756756
PatKind::Missing => unreachable!(),
757757
PatKind::Wild => Some("_".to_string()),
758758
PatKind::Ident(BindingMode::NONE, ident, None) => Some(format!("{ident}")),
759-
PatKind::Ref(pat, mutbl) => pat.descr().map(|d| format!("&{}{d}", mutbl.prefix_str())),
759+
PatKind::Ref(pat, pinned, mutbl) => {
760+
pat.descr().map(|d| format!("&{}{d}", pinned.prefix_str(*mutbl)))
761+
}
760762
_ => None,
761763
}
762764
}
@@ -904,7 +906,7 @@ pub enum PatKind {
904906
Deref(Box<Pat>),
905907

906908
/// A reference pattern (e.g., `&mut (a, b)`).
907-
Ref(Box<Pat>, Mutability),
909+
Ref(Box<Pat>, Pinnedness, Mutability),
908910

909911
/// A literal, const block or path.
910912
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
@@ -765,11 +765,11 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
765765
&& let Some(hir_id) = (BindingFinder { span: pat_span }).visit_body(&body).break_value()
766766
&& let node = self.infcx.tcx.hir_node(hir_id)
767767
&& let hir::Node::LetStmt(hir::LetStmt {
768-
pat: hir::Pat { kind: hir::PatKind::Ref(_, _), .. },
768+
pat: hir::Pat { kind: hir::PatKind::Ref(_, _, _), .. },
769769
..
770770
})
771771
| hir::Node::Param(Param {
772-
pat: hir::Pat { kind: hir::PatKind::Ref(_, _), .. },
772+
pat: hir::Pat { kind: hir::PatKind::Ref(_, _, _), .. },
773773
..
774774
}) = node
775775
{
@@ -1444,7 +1444,7 @@ impl<'tcx> Visitor<'tcx> for BindingFinder {
14441444
}
14451445

14461446
fn visit_param(&mut self, param: &'tcx hir::Param<'tcx>) -> Self::Result {
1447-
if let hir::Pat { kind: hir::PatKind::Ref(_, _), span, .. } = param.pat
1447+
if let hir::Pat { kind: hir::PatKind::Ref(_, _, _), span, .. } = param.pat
14481448
&& *span == self.span
14491449
{
14501450
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
@@ -1697,7 +1697,9 @@ impl<'hir> Pat<'hir> {
16971697
match self.kind {
16981698
Missing => unreachable!(),
16991699
Wild | Never | Expr(_) | Range(..) | Binding(.., None) | Err(_) => true,
1700-
Box(s) | Deref(s) | Ref(s, _) | Binding(.., Some(s)) | Guard(s, _) => s.walk_short_(it),
1700+
Box(s) | Deref(s) | Ref(s, _, _) | Binding(.., Some(s)) | Guard(s, _) => {
1701+
s.walk_short_(it)
1702+
}
17011703
Struct(_, fields, _) => fields.iter().all(|field| field.pat.walk_short_(it)),
17021704
TupleStruct(_, s, _) | Tuple(s, _) | Or(s) => s.iter().all(|p| p.walk_short_(it)),
17031705
Slice(before, slice, after) => {
@@ -1724,7 +1726,7 @@ impl<'hir> Pat<'hir> {
17241726
use PatKind::*;
17251727
match self.kind {
17261728
Missing | Wild | Never | Expr(_) | Range(..) | Binding(.., None) | Err(_) => {}
1727-
Box(s) | Deref(s) | Ref(s, _) | Binding(.., Some(s)) | Guard(s, _) => s.walk_(it),
1729+
Box(s) | Deref(s) | Ref(s, _, _) | Binding(.., Some(s)) | Guard(s, _) => s.walk_(it),
17281730
Struct(_, fields, _) => fields.iter().for_each(|field| field.pat.walk_(it)),
17291731
TupleStruct(_, s, _) | Tuple(s, _) | Or(s) => s.iter().for_each(|p| p.walk_(it)),
17301732
Slice(before, slice, after) => {
@@ -1913,7 +1915,7 @@ pub enum PatKind<'hir> {
19131915
Deref(&'hir Pat<'hir>),
19141916

19151917
/// A reference pattern (e.g., `&mut (a, b)`).
1916-
Ref(&'hir Pat<'hir>, Mutability),
1918+
Ref(&'hir Pat<'hir>, Pinnedness, Mutability),
19171919

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

compiler/rustc_hir/src/intravisit.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -748,7 +748,7 @@ pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat<'v>) -> V:
748748
}
749749
PatKind::Box(ref subpattern)
750750
| PatKind::Deref(ref subpattern)
751-
| PatKind::Ref(ref subpattern, _) => {
751+
| PatKind::Ref(ref subpattern, _, _) => {
752752
try_visit!(visitor.visit_pat(subpattern));
753753
}
754754
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
@@ -2020,9 +2020,15 @@ impl<'a> State<'a> {
20202020
self.print_pat(inner);
20212021
self.pclose();
20222022
}
2023-
PatKind::Ref(inner, mutbl) => {
2023+
PatKind::Ref(inner, pinned, mutbl) => {
20242024
let is_range_inner = matches!(inner.kind, PatKind::Range(..));
20252025
self.word("&");
2026+
if pinned.is_pinned() {
2027+
self.word("pin ");
2028+
if mutbl.is_not() {
2029+
self.word("const ");
2030+
}
2031+
}
20262032
self.word(mutbl.prefix_str());
20272033
if is_range_inner {
20282034
self.popen();

0 commit comments

Comments
 (0)