diff options
| author | Eric Holk <ericholk@microsoft.com> | 2024-09-19 17:23:46 -0700 |
|---|---|---|
| committer | Eric Holk <ericholk@microsoft.com> | 2024-09-23 09:12:36 -0700 |
| commit | 97fbcf6773fa2d00675cbd7ea8dcdac1d6772072 (patch) | |
| tree | dd78c090c8e789eb8e7e7c49c9aee0da94bd2cda | |
| parent | c22a4215a0f6fb676d3774d3763d9da1462414f5 (diff) | |
| download | rust-97fbcf6773fa2d00675cbd7ea8dcdac1d6772072.tar.gz rust-97fbcf6773fa2d00675cbd7ea8dcdac1d6772072.zip | |
Allow reborrowing Pin<&mut Self>
| -rw-r--r-- | compiler/rustc_hir_typeck/src/method/confirm.rs | 9 | ||||
| -rw-r--r-- | compiler/rustc_hir_typeck/src/method/prelude_edition_lints.rs | 32 | ||||
| -rw-r--r-- | compiler/rustc_hir_typeck/src/method/probe.rs | 32 | ||||
| -rw-r--r-- | tests/ui/async-await/pin-reborrow-self.rs | 20 |
4 files changed, 74 insertions, 19 deletions
diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs index e3b0fa78eb7..0d11df11334 100644 --- a/compiler/rustc_hir_typeck/src/method/confirm.rs +++ b/compiler/rustc_hir_typeck/src/method/confirm.rs @@ -235,6 +235,15 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { target, }); } + + Some(probe::AutorefOrPtrAdjustment::ReborrowPin(mutbl)) => { + let region = self.next_region_var(infer::Autoref(self.span)); + + adjustments.push(Adjustment { + kind: Adjust::ReborrowPin(region, mutbl), + target, + }); + } None => {} } diff --git a/compiler/rustc_hir_typeck/src/method/prelude_edition_lints.rs b/compiler/rustc_hir_typeck/src/method/prelude_edition_lints.rs index a8b5b6165db..b20592c85d2 100644 --- a/compiler/rustc_hir_typeck/src/method/prelude_edition_lints.rs +++ b/compiler/rustc_hir_typeck/src/method/prelude_edition_lints.rs @@ -121,16 +121,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { mutbl.ref_prefix_str() } Some(probe::AutorefOrPtrAdjustment::ToConstPtr) | None => "", + Some(probe::AutorefOrPtrAdjustment::ReborrowPin(mutbl)) => match mutbl { + hir::Mutability::Mut => "Pin<&mut ", + hir::Mutability::Not => "Pin<&", + }, }; if let Ok(self_expr) = self.sess().source_map().span_to_snippet(self_expr.span) { - let self_adjusted = if let Some(probe::AutorefOrPtrAdjustment::ToConstPtr) = + let mut self_adjusted = + if let Some(probe::AutorefOrPtrAdjustment::ToConstPtr) = + pick.autoref_or_ptr_adjustment + { + format!("{derefs}{self_expr} as *const _") + } else { + format!("{autoref}{derefs}{self_expr}") + }; + + if let Some(probe::AutorefOrPtrAdjustment::ReborrowPin(_)) = pick.autoref_or_ptr_adjustment { - format!("{derefs}{self_expr} as *const _") - } else { - format!("{autoref}{derefs}{self_expr}") - }; + self_adjusted.push('>'); + } lint.span_suggestion( sp, @@ -400,6 +411,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let autoref = match pick.autoref_or_ptr_adjustment { Some(probe::AutorefOrPtrAdjustment::Autoref { mutbl, .. }) => mutbl.ref_prefix_str(), Some(probe::AutorefOrPtrAdjustment::ToConstPtr) | None => "", + Some(probe::AutorefOrPtrAdjustment::ReborrowPin(mutbl)) => match mutbl { + hir::Mutability::Mut => "Pin<&mut ", + hir::Mutability::Not => "Pin<&", + }, }; let (expr_text, precise) = if let Some(expr_text) = expr @@ -412,7 +427,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ("(..)".to_string(), false) }; - let adjusted_text = if let Some(probe::AutorefOrPtrAdjustment::ToConstPtr) = + let mut adjusted_text = if let Some(probe::AutorefOrPtrAdjustment::ToConstPtr) = pick.autoref_or_ptr_adjustment { format!("{derefs}{expr_text} as *const _") @@ -420,6 +435,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { format!("{autoref}{derefs}{expr_text}") }; + if let Some(probe::AutorefOrPtrAdjustment::ReborrowPin(_)) = pick.autoref_or_ptr_adjustment + { + adjusted_text.push('>'); + } + (adjusted_text, precise) } } diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index 3828b40b885..43481c9704a 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -136,7 +136,7 @@ enum ProbeResult { /// `mut`), or it has type `*mut T` and we convert it to `*const T`. #[derive(Debug, PartialEq, Copy, Clone)] pub(crate) enum AutorefOrPtrAdjustment { - /// Receiver has type `T`, add `&` or `&mut` (it `T` is `mut`), and maybe also "unsize" it. + /// Receiver has type `T`, add `&` or `&mut` (if `T` is `mut`), and maybe also "unsize" it. /// Unsizing is used to convert a `[T; N]` to `[T]`, which only makes sense when autorefing. Autoref { mutbl: hir::Mutability, @@ -147,6 +147,9 @@ pub(crate) enum AutorefOrPtrAdjustment { }, /// Receiver has type `*mut T`, convert to `*const T` ToConstPtr, + + /// Reborrow a `Pin<&mut T>` or `Pin<&T>`. + ReborrowPin(hir::Mutability), } impl AutorefOrPtrAdjustment { @@ -154,6 +157,7 @@ impl AutorefOrPtrAdjustment { match self { AutorefOrPtrAdjustment::Autoref { mutbl: _, unsize } => *unsize, AutorefOrPtrAdjustment::ToConstPtr => false, + AutorefOrPtrAdjustment::ReborrowPin(_) => false, } } } @@ -1133,13 +1137,25 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { r.map(|mut pick| { pick.autoderefs = step.autoderefs; - // Insert a `&*` or `&mut *` if this is a reference type: - if let ty::Ref(_, _, mutbl) = *step.self_ty.value.value.kind() { - pick.autoderefs += 1; - pick.autoref_or_ptr_adjustment = Some(AutorefOrPtrAdjustment::Autoref { - mutbl, - unsize: pick.autoref_or_ptr_adjustment.is_some_and(|a| a.get_unsize()), - }) + match *step.self_ty.value.value.kind() { + // Insert a `&*` or `&mut *` if this is a reference type: + ty::Ref(_, _, mutbl) => { + pick.autoderefs += 1; + pick.autoref_or_ptr_adjustment = Some(AutorefOrPtrAdjustment::Autoref { + mutbl, + unsize: pick.autoref_or_ptr_adjustment.is_some_and(|a| a.get_unsize()), + }) + } + + ty::Adt(def, args) if self.tcx.is_lang_item(def.did(), hir::LangItem::Pin) => { + // make sure this is a pinned reference (and not a `Pin<Box>` or something) + if let ty::Ref(_, _, mutbl) = args[0].expect_ty().kind() { + pick.autoref_or_ptr_adjustment = + Some(AutorefOrPtrAdjustment::ReborrowPin(*mutbl)); + } + } + + _ => (), } pick diff --git a/tests/ui/async-await/pin-reborrow-self.rs b/tests/ui/async-await/pin-reborrow-self.rs index b60b6982bb8..ab36ce575e1 100644 --- a/tests/ui/async-await/pin-reborrow-self.rs +++ b/tests/ui/async-await/pin-reborrow-self.rs @@ -1,24 +1,34 @@ //@ check-pass -//@ignore-test - -// Currently ignored due to self reborrowing not being implemented for Pin #![feature(pin_ergonomics)] #![allow(incomplete_features)] use std::pin::Pin; -struct Foo; +pub struct Foo; impl Foo { fn foo(self: Pin<&mut Self>) { } + + fn baz(self: Pin<&Self>) { + } } -fn bar(x: Pin<&mut Foo>) { +pub fn bar(x: Pin<&mut Foo>) { x.foo(); x.foo(); // for this to work we need to automatically reborrow, // as if the user had written `x.as_mut().foo()`. + + Foo::baz(x); + + // FIXME: We should allow downgrading a Pin<&mut T> to Pin<&T> + // x.baz(); +} + +pub fn baaz(x: Pin<&Foo>) { + x.baz(); + x.baz(); } fn main() {} |
