Rollup merge of #110259 - ndrewxie:issue-109964-fix-gitstuff, r=cjgillot

Added diagnostic for pin! macro in addition to Box::pin if Unpin isn't implemented

I made a PR earlier, but accidentally renamed a branch and that deleted the PR... sorry for the duplicate

Currently, if an operation on `Pin<T>` is performed that requires `T` to implement `Unpin`, the diagnostic suggestion is to use `Box::pin` ("note: consider using `Box::pin`").

This PR suggests pin! as well, as that's another valid way of pinning a value, and avoids a heap allocation. Appropriate diagnostic suggestions were included to highlight the difference in semantics (local pinning for pin! vs non-local for Box::pin).

Fixes #109964
This commit is contained in:
Matthias Krüger 2023-04-13 21:58:37 +02:00 committed by GitHub
commit e413c2e770
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 55 additions and 7 deletions

View File

@ -823,7 +823,7 @@ unsafe impl<T: ?Sized> Freeze for &mut T {}
/// [`pin` module]: crate::pin /// [`pin` module]: crate::pin
#[stable(feature = "pin", since = "1.33.0")] #[stable(feature = "pin", since = "1.33.0")]
#[rustc_on_unimplemented( #[rustc_on_unimplemented(
note = "consider using `Box::pin`", note = "consider using the `pin!` macro\nconsider using `Box::pin` if you need to access the pinned value outside of the current scope",
message = "`{Self}` cannot be unpinned" message = "`{Self}` cannot be unpinned"
)] )]
#[lang = "unpin"] #[lang = "unpin"]

View File

@ -6,7 +6,8 @@ LL | Pin::new(&mut self.sleep).poll(cx)
| | | |
| required by a bound introduced by this call | required by a bound introduced by this call
| |
= note: consider using `Box::pin` = note: consider using the `pin!` macro
consider using `Box::pin` if you need to access the pinned value outside of the current scope
note: required because it appears within the type `Sleep` note: required because it appears within the type `Sleep`
--> $DIR/pin-needed-to-poll-2.rs:8:8 --> $DIR/pin-needed-to-poll-2.rs:8:8
| |

View File

@ -6,7 +6,8 @@ LL | assert_unpin(generator);
| | | |
| required by a bound introduced by this call | required by a bound introduced by this call
| |
= note: consider using `Box::pin` = note: consider using the `pin!` macro
consider using `Box::pin` if you need to access the pinned value outside of the current scope
note: required by a bound in `assert_unpin` note: required by a bound in `assert_unpin`
--> $DIR/static-not-unpin.rs:7:20 --> $DIR/static-not-unpin.rs:7:20
| |

View File

@ -50,7 +50,8 @@ LL | Pin::new(x)
| | | |
| required by a bound introduced by this call | required by a bound introduced by this call
| |
= note: consider using `Box::pin` = note: consider using the `pin!` macro
consider using `Box::pin` if you need to access the pinned value outside of the current scope
note: required by a bound in `Pin::<P>::new` note: required by a bound in `Pin::<P>::new`
--> $SRC_DIR/core/src/pin.rs:LL:COL --> $SRC_DIR/core/src/pin.rs:LL:COL
@ -62,7 +63,8 @@ LL | Pin::new(Box::new(x))
| | | |
| required by a bound introduced by this call | required by a bound introduced by this call
| |
= note: consider using `Box::pin` = note: consider using the `pin!` macro
consider using `Box::pin` if you need to access the pinned value outside of the current scope
note: required by a bound in `Pin::<P>::new` note: required by a bound in `Pin::<P>::new`
--> $SRC_DIR/core/src/pin.rs:LL:COL --> $SRC_DIR/core/src/pin.rs:LL:COL

View File

@ -39,7 +39,8 @@ LL | f_unpin(static || { yield; });
| | | |
| required by a bound introduced by this call | required by a bound introduced by this call
| |
= note: consider using `Box::pin` = note: consider using the `pin!` macro
consider using `Box::pin` if you need to access the pinned value outside of the current scope
note: required by a bound in `f_unpin` note: required by a bound in `f_unpin`
--> $DIR/issue-84973-blacklist.rs:8:15 --> $DIR/issue-84973-blacklist.rs:8:15
| |

View File

@ -0,0 +1,23 @@
use std::pin::Pin;
use std::marker::PhantomPinned;
#[derive(Debug)]
struct Test {
_marker: PhantomPinned,
}
impl Test {
fn new() -> Self {
Test {
_marker: PhantomPinned, // This makes our type `!Unpin`
}
}
}
fn dummy(_: &mut Test) {}
pub fn main() {
let mut test1 = Test::new();
let mut test1 = unsafe { Pin::new_unchecked(&mut test1) };
dummy(test1.get_mut()); //~ ERROR E0277
}

View File

@ -0,0 +1,19 @@
error[E0277]: `PhantomPinned` cannot be unpinned
--> $DIR/suggest-pin-macro.rs:22:17
|
LL | dummy(test1.get_mut());
| ^^^^^^^ within `Test`, the trait `Unpin` is not implemented for `PhantomPinned`
|
= note: consider using the `pin!` macro
consider using `Box::pin` if you need to access the pinned value outside of the current scope
note: required because it appears within the type `Test`
--> $DIR/suggest-pin-macro.rs:5:8
|
LL | struct Test {
| ^^^^
note: required by a bound in `Pin::<&'a mut T>::get_mut`
--> $SRC_DIR/core/src/pin.rs:LL:COL
error: aborting due to previous error
For more information about this error, try `rustc --explain E0277`.

View File

@ -6,7 +6,8 @@ LL | copy(r, w);
| | | |
| required by a bound introduced by this call | required by a bound introduced by this call
| |
= note: consider using `Box::pin` = note: consider using the `pin!` macro
consider using `Box::pin` if you need to access the pinned value outside of the current scope
note: required by a bound in `copy` note: required by a bound in `copy`
--> $DIR/issue-90164.rs:1:12 --> $DIR/issue-90164.rs:1:12
| |