Skip to content

Commit b2b76fb

Browse files
committed
Allow shortening reborrows
Generating a call to `as_mut()` let to more restrictive borrows than what reborrowing usually gives us. Instead, we change the desugaring to reborrow the pin internals directly which makes things more expressive.
1 parent a73c8b1 commit b2b76fb

File tree

8 files changed

+79
-60
lines changed

8 files changed

+79
-60
lines changed

Diff for: compiler/rustc_hir/src/lang_items.rs

-1
Original file line numberDiff line numberDiff line change
@@ -395,7 +395,6 @@ language_item_table! {
395395
IteratorNext, sym::next, next_fn, Target::Method(MethodKind::Trait { body: false}), GenericRequirement::None;
396396

397397
PinNewUnchecked, sym::new_unchecked, new_unchecked_fn, Target::Method(MethodKind::Inherent), GenericRequirement::None;
398-
PinAsMut, sym::pin_as_mut, as_mut_fn, Target::Method(MethodKind::Inherent), GenericRequirement::None;
399398

400399
RangeFrom, sym::RangeFrom, range_from_struct, Target::Struct, GenericRequirement::None;
401400
RangeFull, sym::RangeFull, range_full_struct, Target::Struct, GenericRequirement::None;

Diff for: compiler/rustc_hir_typeck/src/coercion.rs

+1-4
Original file line numberDiff line numberDiff line change
@@ -824,10 +824,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
824824
// add the adjustments.
825825
self.unify_and(a, b, |_inner_ty| {
826826
vec![Adjustment {
827-
kind: Adjust::ReborrowPin(AutoBorrow::Ref(
828-
b_region,
829-
AutoBorrowMutability::Mut { allow_two_phase_borrow: AllowTwoPhase::No },
830-
)),
827+
kind: Adjust::ReborrowPin(b_region, hir::Mutability::Mut),
831828
target: b,
832829
}]
833830
})

Diff for: compiler/rustc_hir_typeck/src/expr_use_visitor.rs

+5-7
Original file line numberDiff line numberDiff line change
@@ -781,14 +781,12 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
781781
self.walk_autoref(expr, &place_with_id, autoref);
782782
}
783783

784-
adjustment::Adjust::ReborrowPin(ref autoref) => {
784+
adjustment::Adjust::ReborrowPin(_, mutbl) => {
785785
// Reborrowing a Pin is like a combinations of a deref and a borrow, so we do
786786
// both.
787-
let bk = match autoref {
788-
adjustment::AutoBorrow::Ref(_, m) => {
789-
ty::BorrowKind::from_mutbl((*m).into())
790-
}
791-
adjustment::AutoBorrow::RawPtr(m) => ty::BorrowKind::from_mutbl(*m),
787+
let bk = match mutbl {
788+
ty::Mutability::Not => ty::BorrowKind::ImmBorrow,
789+
ty::Mutability::Mut => ty::BorrowKind::MutBorrow,
792790
};
793791
self.delegate.borrow_mut().borrow(&place_with_id, place_with_id.hir_id, bk);
794792
}
@@ -1296,7 +1294,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
12961294
adjustment::Adjust::NeverToAny
12971295
| adjustment::Adjust::Pointer(_)
12981296
| adjustment::Adjust::Borrow(_)
1299-
| adjustment::Adjust::ReborrowPin(_)
1297+
| adjustment::Adjust::ReborrowPin(..)
13001298
| adjustment::Adjust::DynStar => {
13011299
// Result is an rvalue.
13021300
Ok(self.cat_rvalue(expr.hir_id, target))

Diff for: compiler/rustc_middle/src/ty/adjustment.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -105,9 +105,8 @@ pub enum Adjust<'tcx> {
105105
/// Cast into a dyn* object.
106106
DynStar,
107107

108-
/// Take a `Pin<Ptr>` and call either `as_mut()` or `as_ref()` to get a `Pin<&mut T>` or
109-
/// `Pin<&T>`.
110-
ReborrowPin(AutoBorrow<'tcx>),
108+
/// Take a pinned reference and reborrow as a `Pin<&mut T>` or `Pin<&T>`.
109+
ReborrowPin(ty::Region<'tcx>, hir::Mutability),
111110
}
112111

113112
/// An overloaded autoderef step, representing a `Deref(Mut)::deref(_mut)`

Diff for: compiler/rustc_mir_build/src/thir/cx/expr.rs

+57-43
Original file line numberDiff line numberDiff line change
@@ -147,50 +147,64 @@ impl<'tcx> Cx<'tcx> {
147147
ExprKind::RawBorrow { mutability, arg: self.thir.exprs.push(expr) }
148148
}
149149
Adjust::DynStar => ExprKind::Cast { source: self.thir.exprs.push(expr) },
150-
Adjust::ReborrowPin(AutoBorrow::Ref(region, m)) => {
150+
Adjust::ReborrowPin(region, mutbl) => {
151151
debug!("apply ReborrowPin adjustment");
152-
match m {
153-
AutoBorrowMutability::Mut { .. } => {
154-
// Rewrite `$expr` as `Pin::as_mut(&mut $expr)`
155-
let as_mut_method =
156-
self.tcx().require_lang_item(rustc_hir::LangItem::PinAsMut, Some(span));
157-
let pin_ty_args = match expr.ty.kind() {
158-
ty::Adt(_, args) => args,
159-
_ => bug!("ReborrowPin with non-Pin type"),
160-
};
161-
let as_mut_ty =
162-
Ty::new_fn_def(self.tcx, as_mut_method, pin_ty_args.into_iter());
163-
164-
let ty = Ty::new_ref(self.tcx, region, expr.ty, ty::Mutability::Mut);
165-
let arg = ExprKind::Borrow {
166-
borrow_kind: BorrowKind::Mut { kind: mir::MutBorrowKind::Default },
167-
arg: self.thir.exprs.push(expr),
168-
};
169-
debug!(?arg, "borrow arg");
170-
let arg = self.thir.exprs.push(Expr { temp_lifetime, ty, span, kind: arg });
171-
172-
let kind = ExprKind::Call {
173-
ty: as_mut_ty,
174-
fun: self.thir.exprs.push(Expr {
175-
temp_lifetime,
176-
ty: as_mut_ty,
177-
span,
178-
kind: ExprKind::ZstLiteral { user_ty: None },
179-
}),
180-
args: Box::new([arg]),
181-
from_hir_call: true,
182-
fn_span: span,
183-
};
184-
debug!(?kind);
185-
kind
186-
}
187-
AutoBorrowMutability::Not => {
188-
// FIXME: We need to call Pin::as_ref on the expression
189-
bug!("ReborrowPin with shared reference is not implemented yet")
190-
}
191-
}
152+
// Rewrite `$expr` as `Pin { __pointer: &(mut)? *($expr).__pointer }`
153+
154+
// We'll need these types later on
155+
let pin_ty_args = match expr.ty.kind() {
156+
ty::Adt(_, args) => args,
157+
_ => bug!("ReborrowPin with non-Pin type"),
158+
};
159+
let pin_ty = pin_ty_args.iter().next().unwrap().expect_ty();
160+
let ptr_target_ty = match pin_ty.kind() {
161+
ty::Ref(_, ty, _) => *ty,
162+
_ => bug!("ReborrowPin with non-Ref type"),
163+
};
164+
165+
// pointer = ($expr).__pointer
166+
let pointer_target = ExprKind::Field {
167+
lhs: self.thir.exprs.push(expr),
168+
variant_index: FIRST_VARIANT,
169+
name: FieldIdx::from(0u32),
170+
};
171+
let arg = Expr { temp_lifetime, ty: pin_ty, span, kind: pointer_target };
172+
let arg = self.thir.exprs.push(arg);
173+
174+
// arg = *pointer
175+
let expr = ExprKind::Deref { arg };
176+
let arg = self.thir.exprs.push(Expr {
177+
temp_lifetime,
178+
ty: ptr_target_ty,
179+
span,
180+
kind: expr,
181+
});
182+
183+
// expr = &mut target
184+
let expr = self.thir.exprs.push(Expr {
185+
temp_lifetime,
186+
ty: Ty::new_ref(self.tcx, region, ptr_target_ty, mutbl),
187+
span,
188+
kind: ExprKind::Borrow {
189+
borrow_kind: BorrowKind::Mut { kind: mir::MutBorrowKind::Default },
190+
arg,
191+
},
192+
});
193+
194+
// kind = Pin { __pointer: pointer }
195+
let pin_did = self.tcx.require_lang_item(rustc_hir::LangItem::Pin, Some(span));
196+
let kind = ExprKind::Adt(Box::new(AdtExpr {
197+
adt_def: self.tcx.adt_def(pin_did),
198+
variant_index: FIRST_VARIANT,
199+
args: pin_ty_args,
200+
fields: Box::new([FieldExpr { name: FieldIdx::from(0u32), expr }]),
201+
user_ty: None,
202+
base: None,
203+
}));
204+
205+
debug!(?kind);
206+
kind
192207
}
193-
Adjust::ReborrowPin(AutoBorrow::RawPtr(_)) => bug!("ReborrowPin with raw pointer"),
194208
};
195209

196210
Expr { temp_lifetime, ty: adjustment.target, span, kind }
@@ -1059,7 +1073,7 @@ impl<'tcx> Cx<'tcx> {
10591073

10601074
// Reconstruct the output assuming it's a reference with the
10611075
// same region and mutability as the receiver. This holds for
1062-
// `Deref(Mut)::Deref(_mut)` and `Index(Mut)::index(_mut)`.
1076+
// `Deref(Mut)::deref(_mut)` and `Index(Mut)::index(_mut)`.
10631077
let ty::Ref(region, _, mutbl) = *self.thir[args[0]].ty.kind() else {
10641078
span_bug!(span, "overloaded_place: receiver is not a reference");
10651079
};

Diff for: compiler/rustc_span/src/symbol.rs

-1
Original file line numberDiff line numberDiff line change
@@ -1418,7 +1418,6 @@ symbols! {
14181418
pic,
14191419
pie,
14201420
pin,
1421-
pin_as_mut,
14221421
pin_ergonomics,
14231422
platform_intrinsics,
14241423
plugin,

Diff for: library/core/src/pin.rs

-1
Original file line numberDiff line numberDiff line change
@@ -1408,7 +1408,6 @@ impl<Ptr: DerefMut> Pin<Ptr> {
14081408
/// }
14091409
/// }
14101410
/// ```
1411-
#[cfg_attr(not(bootstrap), lang = "pin_as_mut")]
14121411
#[stable(feature = "pin", since = "1.33.0")]
14131412
#[inline(always)]
14141413
pub fn as_mut(&mut self) -> Pin<&mut Ptr::Target> {

Diff for: tests/ui/async-await/pin-reborrow-shorter.rs

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
//@check-pass
2+
3+
#![feature(pin_ergonomics)]
4+
#![allow(dead_code, incomplete_features)]
5+
6+
use std::pin::Pin;
7+
8+
fn shorter<'b, T: 'b>(_: Pin<&'b mut T>) {}
9+
10+
fn test<'a: 'b, 'b, T: 'a>(x: Pin<&'a mut T>) {
11+
shorter::<'b>(x);
12+
}
13+
14+
fn main() {}

0 commit comments

Comments
 (0)