Skip to content

Commit e627f88

Browse files
committed
Implement pinned borrows, part of pin_ergonomics
1 parent 49a8ba0 commit e627f88

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
@@ -898,6 +898,10 @@ pub enum BorrowKind {
898898
/// The resulting type is either `*const T` or `*mut T`
899899
/// where `T = typeof($expr)`.
900900
Raw,
901+
/// A pinned borrow, `&pin const $expr` or `&pin mut $expr`.
902+
/// The resulting type is either `Pin<&'a T>` or `Pin<&'a mut T>`
903+
/// where `T = typeof($expr)` and `'a` is some lifetime.
904+
Pin,
901905
}
902906

903907
#[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
@@ -357,6 +357,10 @@ impl<'a> State<'a> {
357357
self.word_nbsp("raw");
358358
self.print_mutability(mutability, true);
359359
}
360+
ast::BorrowKind::Pin => {
361+
self.word_nbsp("pin");
362+
self.print_mutability(mutability, true);
363+
}
360364
}
361365
self.print_expr_cond_paren(
362366
expr,

compiler/rustc_const_eval/src/check_consts/ops.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -616,11 +616,13 @@ impl<'tcx> NonConstOp<'tcx> for EscapingMutBorrow {
616616
kind: ccx.const_kind(),
617617
teach: ccx.tcx.sess.teach(E0764),
618618
}),
619-
hir::BorrowKind::Ref => ccx.dcx().create_err(errors::MutableRefEscaping {
620-
span,
621-
kind: ccx.const_kind(),
622-
teach: ccx.tcx.sess.teach(E0764),
623-
}),
619+
hir::BorrowKind::Ref | hir::BorrowKind::Pin => {
620+
ccx.dcx().create_err(errors::MutableRefEscaping {
621+
span,
622+
kind: ccx.const_kind(),
623+
teach: ccx.tcx.sess.teach(E0764),
624+
})
625+
}
624626
}
625627
}
626628
}

compiler/rustc_hir_pretty/src/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1339,6 +1339,10 @@ impl<'a> State<'a> {
13391339
self.word_nbsp("raw");
13401340
self.print_mutability(mutability, true);
13411341
}
1342+
hir::BorrowKind::Pin => {
1343+
self.word_nbsp("pin");
1344+
self.print_mutability(mutability, true);
1345+
}
13421346
}
13431347
self.print_expr_cond_paren(expr, expr.precedence() < ExprPrecedence::Prefix);
13441348
}

compiler/rustc_hir_typeck/src/expr.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -664,7 +664,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
664664
self.check_named_place_expr(oprnd);
665665
Ty::new_ptr(self.tcx, ty, mutbl)
666666
}
667-
hir::BorrowKind::Ref => {
667+
hir::BorrowKind::Ref | hir::BorrowKind::Pin => {
668668
// Note: at this point, we cannot say what the best lifetime
669669
// is to use for resulting pointer. We want to use the
670670
// shortest lifetime possible so as to avoid spurious borrowck
@@ -680,7 +680,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
680680
// whose address was taken can actually be made to live as long
681681
// as it needs to live.
682682
let region = self.next_region_var(infer::BorrowRegion(expr.span));
683-
Ty::new_ref(self.tcx, region, ty, mutbl)
683+
match kind {
684+
hir::BorrowKind::Ref => Ty::new_ref(self.tcx, region, ty, mutbl),
685+
hir::BorrowKind::Pin => Ty::new_pinned_ref(self.tcx, region, ty, mutbl),
686+
_ => unreachable!(),
687+
}
684688
}
685689
}
686690
}

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

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

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

484509
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
@@ -847,14 +847,19 @@ impl<'a> Parser<'a> {
847847
self.dcx().emit_err(errors::LifetimeInBorrowExpression { span, lifetime_span: lt_span });
848848
}
849849

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