about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_hir/src/lang_items.rs1
-rw-r--r--compiler/rustc_hir_typeck/src/coercion.rs5
-rw-r--r--compiler/rustc_hir_typeck/src/expr_use_visitor.rs12
-rw-r--r--compiler/rustc_middle/src/ty/adjustment.rs5
-rw-r--r--compiler/rustc_mir_build/src/thir/cx/expr.rs100
-rw-r--r--compiler/rustc_span/src/symbol.rs1
-rw-r--r--library/core/src/pin.rs1
-rw-r--r--tests/ui/async-await/pin-reborrow-shorter.rs14
8 files changed, 79 insertions, 60 deletions
diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs
index 60e024068e9..e7398fd2226 100644
--- a/compiler/rustc_hir/src/lang_items.rs
+++ b/compiler/rustc_hir/src/lang_items.rs
@@ -395,7 +395,6 @@ language_item_table! {
     IteratorNext,            sym::next,                next_fn,                    Target::Method(MethodKind::Trait { body: false}), GenericRequirement::None;
 
     PinNewUnchecked,         sym::new_unchecked,       new_unchecked_fn,           Target::Method(MethodKind::Inherent), GenericRequirement::None;
-    PinAsMut,                sym::pin_as_mut,              as_mut_fn,                  Target::Method(MethodKind::Inherent), GenericRequirement::None;
 
     RangeFrom,               sym::RangeFrom,           range_from_struct,          Target::Struct,         GenericRequirement::None;
     RangeFull,               sym::RangeFull,           range_full_struct,          Target::Struct,         GenericRequirement::None;
diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs
index d548df98bf9..d45d7f54ed4 100644
--- a/compiler/rustc_hir_typeck/src/coercion.rs
+++ b/compiler/rustc_hir_typeck/src/coercion.rs
@@ -824,10 +824,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
         // add the adjustments.
         self.unify_and(a, b, |_inner_ty| {
             vec![Adjustment {
-                kind: Adjust::ReborrowPin(AutoBorrow::Ref(
-                    b_region,
-                    AutoBorrowMutability::Mut { allow_two_phase_borrow: AllowTwoPhase::No },
-                )),
+                kind: Adjust::ReborrowPin(b_region, hir::Mutability::Mut),
                 target: b,
             }]
         })
diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
index 95a3cf7b96b..3b2ddf659a1 100644
--- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
+++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
@@ -781,14 +781,12 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
                     self.walk_autoref(expr, &place_with_id, autoref);
                 }
 
-                adjustment::Adjust::ReborrowPin(ref autoref) => {
+                adjustment::Adjust::ReborrowPin(_, mutbl) => {
                     // Reborrowing a Pin is like a combinations of a deref and a borrow, so we do
                     // both.
-                    let bk = match autoref {
-                        adjustment::AutoBorrow::Ref(_, m) => {
-                            ty::BorrowKind::from_mutbl((*m).into())
-                        }
-                        adjustment::AutoBorrow::RawPtr(m) => ty::BorrowKind::from_mutbl(*m),
+                    let bk = match mutbl {
+                        ty::Mutability::Not => ty::BorrowKind::ImmBorrow,
+                        ty::Mutability::Mut => ty::BorrowKind::MutBorrow,
                     };
                     self.delegate.borrow_mut().borrow(&place_with_id, place_with_id.hir_id, bk);
                 }
@@ -1296,7 +1294,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
             adjustment::Adjust::NeverToAny
             | adjustment::Adjust::Pointer(_)
             | adjustment::Adjust::Borrow(_)
-            | adjustment::Adjust::ReborrowPin(_)
+            | adjustment::Adjust::ReborrowPin(..)
             | adjustment::Adjust::DynStar => {
                 // Result is an rvalue.
                 Ok(self.cat_rvalue(expr.hir_id, target))
diff --git a/compiler/rustc_middle/src/ty/adjustment.rs b/compiler/rustc_middle/src/ty/adjustment.rs
index 7f56e05901c..5a32078760e 100644
--- a/compiler/rustc_middle/src/ty/adjustment.rs
+++ b/compiler/rustc_middle/src/ty/adjustment.rs
@@ -105,9 +105,8 @@ pub enum Adjust<'tcx> {
     /// Cast into a dyn* object.
     DynStar,
 
-    /// Take a `Pin<Ptr>` and call either `as_mut()` or `as_ref()` to get a `Pin<&mut T>` or
-    /// `Pin<&T>`.
-    ReborrowPin(AutoBorrow<'tcx>),
+    /// Take a pinned reference and reborrow as a `Pin<&mut T>` or `Pin<&T>`.
+    ReborrowPin(ty::Region<'tcx>, hir::Mutability),
 }
 
 /// An overloaded autoderef step, representing a `Deref(Mut)::deref(_mut)`
diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs
index 8e6e13f94e0..3bb00e0b028 100644
--- a/compiler/rustc_mir_build/src/thir/cx/expr.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs
@@ -147,50 +147,64 @@ impl<'tcx> Cx<'tcx> {
                 ExprKind::RawBorrow { mutability, arg: self.thir.exprs.push(expr) }
             }
             Adjust::DynStar => ExprKind::Cast { source: self.thir.exprs.push(expr) },
-            Adjust::ReborrowPin(AutoBorrow::Ref(region, m)) => {
+            Adjust::ReborrowPin(region, mutbl) => {
                 debug!("apply ReborrowPin adjustment");
-                match m {
-                    AutoBorrowMutability::Mut { .. } => {
-                        // Rewrite `$expr` as `Pin::as_mut(&mut $expr)`
-                        let as_mut_method =
-                            self.tcx().require_lang_item(rustc_hir::LangItem::PinAsMut, Some(span));
-                        let pin_ty_args = match expr.ty.kind() {
-                            ty::Adt(_, args) => args,
-                            _ => bug!("ReborrowPin with non-Pin type"),
-                        };
-                        let as_mut_ty =
-                            Ty::new_fn_def(self.tcx, as_mut_method, pin_ty_args.into_iter());
-
-                        let ty = Ty::new_ref(self.tcx, region, expr.ty, ty::Mutability::Mut);
-                        let arg = ExprKind::Borrow {
-                            borrow_kind: BorrowKind::Mut { kind: mir::MutBorrowKind::Default },
-                            arg: self.thir.exprs.push(expr),
-                        };
-                        debug!(?arg, "borrow arg");
-                        let arg = self.thir.exprs.push(Expr { temp_lifetime, ty, span, kind: arg });
-
-                        let kind = ExprKind::Call {
-                            ty: as_mut_ty,
-                            fun: self.thir.exprs.push(Expr {
-                                temp_lifetime,
-                                ty: as_mut_ty,
-                                span,
-                                kind: ExprKind::ZstLiteral { user_ty: None },
-                            }),
-                            args: Box::new([arg]),
-                            from_hir_call: true,
-                            fn_span: span,
-                        };
-                        debug!(?kind);
-                        kind
-                    }
-                    AutoBorrowMutability::Not => {
-                        // FIXME: We need to call Pin::as_ref on the expression
-                        bug!("ReborrowPin with shared reference is not implemented yet")
-                    }
-                }
+                // Rewrite `$expr` as `Pin { __pointer: &(mut)? *($expr).__pointer }`
+
+                // We'll need these types later on
+                let pin_ty_args = match expr.ty.kind() {
+                    ty::Adt(_, args) => args,
+                    _ => bug!("ReborrowPin with non-Pin type"),
+                };
+                let pin_ty = pin_ty_args.iter().next().unwrap().expect_ty();
+                let ptr_target_ty = match pin_ty.kind() {
+                    ty::Ref(_, ty, _) => *ty,
+                    _ => bug!("ReborrowPin with non-Ref type"),
+                };
+
+                // pointer = ($expr).__pointer
+                let pointer_target = ExprKind::Field {
+                    lhs: self.thir.exprs.push(expr),
+                    variant_index: FIRST_VARIANT,
+                    name: FieldIdx::from(0u32),
+                };
+                let arg = Expr { temp_lifetime, ty: pin_ty, span, kind: pointer_target };
+                let arg = self.thir.exprs.push(arg);
+
+                // arg = *pointer
+                let expr = ExprKind::Deref { arg };
+                let arg = self.thir.exprs.push(Expr {
+                    temp_lifetime,
+                    ty: ptr_target_ty,
+                    span,
+                    kind: expr,
+                });
+
+                // expr = &mut target
+                let expr = self.thir.exprs.push(Expr {
+                    temp_lifetime,
+                    ty: Ty::new_ref(self.tcx, region, ptr_target_ty, mutbl),
+                    span,
+                    kind: ExprKind::Borrow {
+                        borrow_kind: BorrowKind::Mut { kind: mir::MutBorrowKind::Default },
+                        arg,
+                    },
+                });
+
+                // kind = Pin { __pointer: pointer }
+                let pin_did = self.tcx.require_lang_item(rustc_hir::LangItem::Pin, Some(span));
+                let kind = ExprKind::Adt(Box::new(AdtExpr {
+                    adt_def: self.tcx.adt_def(pin_did),
+                    variant_index: FIRST_VARIANT,
+                    args: pin_ty_args,
+                    fields: Box::new([FieldExpr { name: FieldIdx::from(0u32), expr }]),
+                    user_ty: None,
+                    base: None,
+                }));
+
+                debug!(?kind);
+                kind
             }
-            Adjust::ReborrowPin(AutoBorrow::RawPtr(_)) => bug!("ReborrowPin with raw pointer"),
         };
 
         Expr { temp_lifetime, ty: adjustment.target, span, kind }
@@ -1059,7 +1073,7 @@ impl<'tcx> Cx<'tcx> {
 
         // Reconstruct the output assuming it's a reference with the
         // same region and mutability as the receiver. This holds for
-        // `Deref(Mut)::Deref(_mut)` and `Index(Mut)::index(_mut)`.
+        // `Deref(Mut)::deref(_mut)` and `Index(Mut)::index(_mut)`.
         let ty::Ref(region, _, mutbl) = *self.thir[args[0]].ty.kind() else {
             span_bug!(span, "overloaded_place: receiver is not a reference");
         };
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 979294563d7..27ff9afa92c 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -1418,7 +1418,6 @@ symbols! {
         pic,
         pie,
         pin,
-        pin_as_mut,
         pin_ergonomics,
         platform_intrinsics,
         plugin,
diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs
index bb1196e82de..9c13662e08e 100644
--- a/library/core/src/pin.rs
+++ b/library/core/src/pin.rs
@@ -1408,7 +1408,6 @@ impl<Ptr: DerefMut> Pin<Ptr> {
     ///     }
     /// }
     /// ```
-    #[cfg_attr(not(bootstrap), lang = "pin_as_mut")]
     #[stable(feature = "pin", since = "1.33.0")]
     #[inline(always)]
     pub fn as_mut(&mut self) -> Pin<&mut Ptr::Target> {
diff --git a/tests/ui/async-await/pin-reborrow-shorter.rs b/tests/ui/async-await/pin-reborrow-shorter.rs
new file mode 100644
index 00000000000..06c266e0035
--- /dev/null
+++ b/tests/ui/async-await/pin-reborrow-shorter.rs
@@ -0,0 +1,14 @@
+//@check-pass
+
+#![feature(pin_ergonomics)]
+#![allow(dead_code, incomplete_features)]
+
+use std::pin::Pin;
+
+fn shorter<'b, T: 'b>(_: Pin<&'b mut T>) {}
+
+fn test<'a: 'b, 'b, T: 'a>(x: Pin<&'a mut T>) {
+    shorter::<'b>(x);
+}
+
+fn main() {}