Skip to content

Commit 235c3f6

Browse files
committed
Implement pinned borrows, part of pin_ergonomics
1 parent 49e5e4e commit 235c3f6

File tree

18 files changed

+471
-18
lines changed

18 files changed

+471
-18
lines changed

compiler/rustc_ast/src/ast.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -886,6 +886,10 @@ pub enum BorrowKind {
886886
/// The resulting type is either `*const T` or `*mut T`
887887
/// where `T = typeof($expr)`.
888888
Raw,
889+
/// A pinned borrow, `&pin const $expr` or `&pin mut $expr`.
890+
/// The resulting type is either `Pin<&'a T>` or `Pin<&'a mut T>`
891+
/// where `T = typeof($expr)` and `'a` is some lifetime.
892+
Pin,
889893
}
890894

891895
#[derive(Clone, Copy, Debug, PartialEq, Encodable, Decodable, HashStable_Generic)]

compiler/rustc_ast_pretty/src/pprust/state/expr.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,10 @@ impl<'a> State<'a> {
339339
self.word_nbsp("raw");
340340
self.print_mutability(mutability, true);
341341
}
342+
ast::BorrowKind::Pin => {
343+
self.word_nbsp("pin");
344+
self.print_mutability(mutability, true);
345+
}
342346
}
343347
self.print_expr_cond_paren(
344348
expr,

compiler/rustc_const_eval/src/check_consts/ops.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -619,11 +619,13 @@ impl<'tcx> NonConstOp<'tcx> for EscapingMutBorrow {
619619
kind: ccx.const_kind(),
620620
teach: ccx.tcx.sess.teach(E0764),
621621
}),
622-
hir::BorrowKind::Ref => ccx.dcx().create_err(errors::MutableRefEscaping {
623-
span,
624-
kind: ccx.const_kind(),
625-
teach: ccx.tcx.sess.teach(E0764),
626-
}),
622+
hir::BorrowKind::Ref | hir::BorrowKind::Pin => {
623+
ccx.dcx().create_err(errors::MutableRefEscaping {
624+
span,
625+
kind: ccx.const_kind(),
626+
teach: ccx.tcx.sess.teach(E0764),
627+
})
628+
}
627629
}
628630
}
629631
}

compiler/rustc_hir_pretty/src/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1325,6 +1325,10 @@ impl<'a> State<'a> {
13251325
self.word_nbsp("raw");
13261326
self.print_mutability(mutability, true);
13271327
}
1328+
hir::BorrowKind::Pin => {
1329+
self.word_nbsp("pin");
1330+
self.print_mutability(mutability, true);
1331+
}
13281332
}
13291333
self.print_expr_cond_paren(expr, expr.precedence() < ExprPrecedence::Prefix);
13301334
}

compiler/rustc_hir_typeck/src/expr.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -673,7 +673,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
673673
self.check_named_place_expr(oprnd);
674674
Ty::new_ptr(self.tcx, ty, mutbl)
675675
}
676-
hir::BorrowKind::Ref => {
676+
hir::BorrowKind::Ref | hir::BorrowKind::Pin => {
677677
// Note: at this point, we cannot say what the best lifetime
678678
// is to use for resulting pointer. We want to use the
679679
// shortest lifetime possible so as to avoid spurious borrowck
@@ -689,7 +689,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
689689
// whose address was taken can actually be made to live as long
690690
// as it needs to live.
691691
let region = self.next_region_var(infer::BorrowRegion(expr.span));
692-
Ty::new_ref(self.tcx, region, ty, mutbl)
692+
match kind {
693+
hir::BorrowKind::Ref => Ty::new_ref(self.tcx, region, ty, mutbl),
694+
hir::BorrowKind::Pin => Ty::new_pinned_ref(self.tcx, region, ty, mutbl),
695+
_ => unreachable!(),
696+
}
693697
}
694698
}
695699
}

compiler/rustc_mir_build/src/thir/cx/expr.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -476,6 +476,31 @@ impl<'tcx> ThirBuildCx<'tcx> {
476476
ExprKind::RawBorrow { mutability, arg: self.mirror_expr(arg) }
477477
}
478478

479+
// Make `&pin mut $expr` and `&pin const $expr` into
480+
// `Pin { __pointer: &mut $expr }` and `Pin { __pointer: &$expr }`.
481+
hir::ExprKind::AddrOf(hir::BorrowKind::Pin, mutbl, arg) => match expr_ty.kind() {
482+
&ty::Adt(adt_def, args)
483+
if tcx.is_lang_item(adt_def.did(), rustc_hir::LangItem::Pin) =>
484+
{
485+
let arg = self.mirror_expr(arg);
486+
let expr = self.thir.exprs.push(Expr {
487+
temp_lifetime: TempLifetime { temp_lifetime, backwards_incompatible },
488+
ty: args.type_at(0),
489+
span: expr.span,
490+
kind: ExprKind::Borrow { borrow_kind: mutbl.to_borrow_kind(), arg },
491+
});
492+
ExprKind::Adt(Box::new(AdtExpr {
493+
adt_def,
494+
variant_index: FIRST_VARIANT,
495+
args,
496+
fields: Box::new([FieldExpr { name: FieldIdx::from(0u32), expr }]),
497+
user_ty: None,
498+
base: AdtExprBase::None,
499+
}))
500+
}
501+
_ => span_bug!(expr.span, "unexpected type for pinned borrow: {:?}", expr_ty),
502+
},
503+
479504
hir::ExprKind::Block(blk, _) => ExprKind::Block { block: self.mirror_block(blk) },
480505

481506
hir::ExprKind::Assign(lhs, rhs, _) => {

compiler/rustc_parse/src/parser/expr.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -846,14 +846,19 @@ impl<'a> Parser<'a> {
846846
self.dcx().emit_err(errors::LifetimeInBorrowExpression { span, lifetime_span: lt_span });
847847
}
848848

849-
/// Parse `mut?` or `raw [ const | mut ]`.
849+
/// Parse `mut?` or `[ raw | pin ] [ const | mut ]`.
850850
fn parse_borrow_modifiers(&mut self) -> (ast::BorrowKind, ast::Mutability) {
851851
if self.check_keyword(exp!(Raw)) && self.look_ahead(1, Token::is_mutability) {
852852
// `raw [ const | mut ]`.
853853
let found_raw = self.eat_keyword(exp!(Raw));
854854
assert!(found_raw);
855855
let mutability = self.parse_const_or_mut().unwrap();
856856
(ast::BorrowKind::Raw, mutability)
857+
} else if let Some((ast::Pinnedness::Pinned, mutbl)) = self.parse_pin_and_mut() {
858+
// `pin [ const | mut ]`.
859+
// `pin` has been gated in `self.parse_pin_and_mut()` so we don't
860+
// need to gate it here.
861+
(ast::BorrowKind::Pin, mutbl)
857862
} else {
858863
// `mut?`
859864
(ast::BorrowKind::Ref, self.parse_mutability())

src/tools/rustfmt/src/expr.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2289,8 +2289,10 @@ fn rewrite_expr_addrof(
22892289
) -> RewriteResult {
22902290
let operator_str = match (mutability, borrow_kind) {
22912291
(ast::Mutability::Not, ast::BorrowKind::Ref) => "&",
2292+
(ast::Mutability::Not, ast::BorrowKind::Pin) => "&pin const ",
22922293
(ast::Mutability::Not, ast::BorrowKind::Raw) => "&raw const ",
22932294
(ast::Mutability::Mut, ast::BorrowKind::Ref) => "&mut ",
2295+
(ast::Mutability::Mut, ast::BorrowKind::Pin) => "&pin mut ",
22942296
(ast::Mutability::Mut, ast::BorrowKind::Raw) => "&raw mut ",
22952297
};
22962298
rewrite_unary_prefix(context, operator_str, expr, shape)

src/tools/rustfmt/tests/source/pin_sugar.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,13 @@ impl Foo {
1818
mut self) {}
1919
fn i(&pin mut self) {}
2020
}
21+
22+
fn borrows() {
23+
let mut foo = 0_i32;
24+
let x: Pin<&mut _> = & pin
25+
mut foo;
26+
27+
let x: Pin<&_> = &
28+
pin const
29+
foo;
30+
}

src/tools/rustfmt/tests/target/pin_sugar.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,10 @@ impl Foo {
1616
fn h<'a>(&'a pin mut self) {}
1717
fn i(&pin mut self) {}
1818
}
19+
20+
fn borrows() {
21+
let mut foo = 0_i32;
22+
let x: Pin<&mut _> = &pin mut foo;
23+
24+
let x: Pin<&_> = &pin const foo;
25+
}

0 commit comments

Comments
 (0)