Skip to content

Commit afdb54a

Browse files
committed
Move the place in &pin mut $place when !Unpin to ensure soundness
1 parent 2090f40 commit afdb54a

File tree

9 files changed

+559
-191
lines changed

9 files changed

+559
-191
lines changed

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

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -480,15 +480,39 @@ impl<'tcx> ThirBuildCx<'tcx> {
480480
}
481481

482482
// 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);
483+
// `Pin { __pointer: &mut { $expr } }` and `Pin { __pointer: &$expr }`.
484+
hir::ExprKind::AddrOf(hir::BorrowKind::Pin, mutbl, arg_expr) => match expr_ty.kind() {
485+
&ty::Adt(adt_def, args) if tcx.is_lang_item(adt_def.did(), hir::LangItem::Pin) => {
486+
let ty = args.type_at(0);
487+
let arg_ty = self.typeck_results.expr_ty(arg_expr);
488+
let mut arg = self.mirror_expr(arg_expr);
489+
// For `&pin mut $place` where `$place` is not `Unpin`, move the place
490+
// `$place` to ensure it will not be used afterwards.
491+
if mutbl.is_mut() && !arg_ty.is_unpin(self.tcx, self.typing_env) {
492+
let block = self.thir.blocks.push(Block {
493+
targeted_by_break: false,
494+
region_scope: region::Scope {
495+
local_id: arg_expr.hir_id.local_id,
496+
data: region::ScopeData::Node,
497+
},
498+
span: arg_expr.span,
499+
stmts: Box::new([]),
500+
expr: Some(arg),
501+
safety_mode: BlockSafety::Safe,
502+
});
503+
let (temp_lifetime, backwards_incompatible) = self
504+
.rvalue_scopes
505+
.temporary_scope(self.region_scope_tree, arg_expr.hir_id.local_id);
506+
arg = self.thir.exprs.push(Expr {
507+
temp_lifetime: TempLifetime { temp_lifetime, backwards_incompatible },
508+
ty: arg_ty,
509+
span: arg_expr.span,
510+
kind: ExprKind::Block { block },
511+
});
512+
}
489513
let expr = self.thir.exprs.push(Expr {
490514
temp_lifetime: TempLifetime { temp_lifetime, backwards_incompatible },
491-
ty: args.type_at(0),
515+
ty,
492516
span: expr.span,
493517
kind: ExprKind::Borrow { borrow_kind: mutbl.to_borrow_kind(), arg },
494518
});

tests/pretty/pin-ergonomics-hir.pp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
//@ pretty-mode:hir
33
//@ pp-exact:pin-ergonomics-hir.pp
44

5-
#![feature(pin_ergonomics)]#![allow(dead_code, incomplete_features)]
5+
#![feature(pin_ergonomics)]
6+
#![allow(dead_code, incomplete_features)]
67
#[prelude_import]
78
use ::std::prelude::rust_2015::*;
89
#[macro_use]

tests/pretty/pin-ergonomics.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ fn bar() {
3030
foo_const(x);
3131

3232
let x: Pin<&_> = &pin const Foo;
33-
3433
foo_const(x);
3534
foo_const(x);
3635
}

tests/ui/pin-ergonomics/borrow-mut-xor-share.rs

Lines changed: 0 additions & 59 deletions
This file was deleted.

tests/ui/pin-ergonomics/borrow-mut-xor-share.stderr

Lines changed: 0 additions & 121 deletions
This file was deleted.

0 commit comments

Comments
 (0)