mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-28 03:07:24 +03:00
prevent deref coercions in pin!
This commit is contained in:
@@ -157,6 +157,7 @@
|
||||
#![feature(no_core)]
|
||||
#![feature(optimize_attribute)]
|
||||
#![feature(pattern_types)]
|
||||
#![feature(pin_macro_internals)]
|
||||
#![feature(prelude_import)]
|
||||
#![feature(repr_simd)]
|
||||
#![feature(rustc_attrs)]
|
||||
|
||||
+18
-3
@@ -2021,14 +2021,29 @@ unsafe impl<T: PinCoerceUnsized> PinCoerceUnsized for Pin<T> {}
|
||||
/// [`Box::pin`]: ../../std/boxed/struct.Box.html#method.pin
|
||||
#[stable(feature = "pin_macro", since = "1.68.0")]
|
||||
#[rustc_macro_transparency = "semiopaque"]
|
||||
#[allow_internal_unstable(super_let)]
|
||||
#[allow_internal_unstable(pin_macro_internals, super_let)]
|
||||
#[rustc_diagnostic_item = "pin_macro"]
|
||||
// `super` gets removed by rustfmt
|
||||
#[rustfmt::skip]
|
||||
pub macro pin($value:expr $(,)?) {
|
||||
{
|
||||
'p: {
|
||||
super let mut pinned = $value;
|
||||
// SAFETY: The value is pinned: it is the local above which cannot be named outside this macro.
|
||||
unsafe { $crate::pin::Pin::new_unchecked(&mut pinned) }
|
||||
break 'p unsafe { $crate::pin::Pin::new_unchecked(&mut pinned) };
|
||||
|
||||
// HACK: We need to ensure that, given `$value: T`, `pin!($value)` has type `Pin<&mut T>`.
|
||||
// Otherwise, it's possible for a type annotation on the result of `pin!` to unsoundly add
|
||||
// deref coercions. E.g. for `$value: &mut T`, we could get `pin!($value): Pin<&mut T>`,
|
||||
// violating the pinning invariant; see <https://github.com/rust-lang/rust/issues/153438>.
|
||||
#[expect(unreachable_code)]
|
||||
$crate::pin::unreachable_pin_macro_type_constraint(pinned)
|
||||
}
|
||||
}
|
||||
|
||||
/// Helper for `pin!` to enforce its type signature.
|
||||
/// See <https://github.com/rust-lang/rust/issues/153438>.
|
||||
#[unstable(feature = "pin_macro_internals", issue = "none")]
|
||||
#[doc(hidden)]
|
||||
pub fn unreachable_pin_macro_type_constraint<'a, T>(_: T) -> Pin<&'a mut T> {
|
||||
unreachable!()
|
||||
}
|
||||
|
||||
@@ -27,6 +27,8 @@ fn main() {
|
||||
//~^^ ERROR AsyncFnOnce()` is not satisfied
|
||||
//~^^^ ERROR AsyncFnOnce()` is not satisfied
|
||||
//~^^^^ ERROR AsyncFnOnce()` is not satisfied
|
||||
//~^^^^^ ERROR AsyncFnOnce()` is not satisfied
|
||||
//~^^^^^^ ERROR AsyncFnOnce()` is not satisfied
|
||||
x.poll(&mut Context::from_waker(Waker::noop()));
|
||||
//~^ ERROR AsyncFnOnce()` is not satisfied
|
||||
}
|
||||
|
||||
@@ -49,7 +49,31 @@ LL | async fn call_async_once(f: impl AsyncFnOnce()) {
|
||||
| ^^^^^^^^^^^^^ required by this bound in `call_async_once`
|
||||
|
||||
error[E0277]: the trait bound `{gen closure@$DIR/iter-macro-not-async-closure.rs:19:21: 19:28}: AsyncFnOnce()` is not satisfied
|
||||
--> $DIR/iter-macro-not-async-closure.rs:30:5
|
||||
--> $DIR/iter-macro-not-async-closure.rs:25:13
|
||||
|
|
||||
LL | let x = pin!(call_async_once(f));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `AsyncFnOnce()` is not implemented for `{gen closure@$DIR/iter-macro-not-async-closure.rs:19:21: 19:28}`
|
||||
|
|
||||
note: required by a bound in `call_async_once`
|
||||
--> $DIR/iter-macro-not-async-closure.rs:14:34
|
||||
|
|
||||
LL | async fn call_async_once(f: impl AsyncFnOnce()) {
|
||||
| ^^^^^^^^^^^^^ required by this bound in `call_async_once`
|
||||
|
||||
error[E0277]: the trait bound `{gen closure@$DIR/iter-macro-not-async-closure.rs:19:21: 19:28}: AsyncFnOnce()` is not satisfied
|
||||
--> $DIR/iter-macro-not-async-closure.rs:25:13
|
||||
|
|
||||
LL | let x = pin!(call_async_once(f));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `AsyncFnOnce()` is not implemented for `{gen closure@$DIR/iter-macro-not-async-closure.rs:19:21: 19:28}`
|
||||
|
|
||||
note: required by a bound in `call_async_once`
|
||||
--> $DIR/iter-macro-not-async-closure.rs:14:34
|
||||
|
|
||||
LL | async fn call_async_once(f: impl AsyncFnOnce()) {
|
||||
| ^^^^^^^^^^^^^ required by this bound in `call_async_once`
|
||||
|
||||
error[E0277]: the trait bound `{gen closure@$DIR/iter-macro-not-async-closure.rs:19:21: 19:28}: AsyncFnOnce()` is not satisfied
|
||||
--> $DIR/iter-macro-not-async-closure.rs:32:5
|
||||
|
|
||||
LL | x.poll(&mut Context::from_waker(Waker::noop()));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `AsyncFnOnce()` is not implemented for `{gen closure@$DIR/iter-macro-not-async-closure.rs:19:21: 19:28}`
|
||||
@@ -60,6 +84,6 @@ note: required by a bound in `call_async_once`
|
||||
LL | async fn call_async_once(f: impl AsyncFnOnce()) {
|
||||
| ^^^^^^^^^^^^^ required by this bound in `call_async_once`
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
error: aborting due to 7 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
|
||||
@@ -2,12 +2,12 @@
|
||||
//! expectation on `pin!`'s result, make sure we don't deref-coerce the argument to
|
||||
//! `Pin::new_unchecked` to get its type to match up. That violates the pinning invariant, leading
|
||||
//! to unsoundness!
|
||||
//@ check-pass
|
||||
|
||||
use std::pin::{Pin, pin};
|
||||
|
||||
fn wrong_pin<T>(data: &mut T, callback: impl FnOnce(Pin<&mut T>)) {
|
||||
callback(pin!(data));
|
||||
//~^ ERROR: mismatched types
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/dont-deref-coerce-pinned-value.rs:9:14
|
||||
|
|
||||
LL | fn wrong_pin<T>(data: &mut T, callback: impl FnOnce(Pin<&mut T>)) {
|
||||
| - expected this type parameter
|
||||
LL | callback(pin!(data));
|
||||
| ^^^^^^^^^^
|
||||
| |
|
||||
| expected type parameter `T`, found `&mut T`
|
||||
| arguments to this function are incorrect
|
||||
|
|
||||
= note: expected type parameter `_`
|
||||
found mutable reference `&mut _`
|
||||
help: the return type of this call is `&mut T` due to the type of the argument passed
|
||||
--> $DIR/dont-deref-coerce-pinned-value.rs:9:14
|
||||
|
|
||||
LL | callback(pin!(data));
|
||||
| ^^^^^^^^^^ this argument influences the return type of `unreachable_pin_macro_type_constraint`
|
||||
note: function defined here
|
||||
--> $SRC_DIR/core/src/pin.rs:LL:COL
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
Reference in New Issue
Block a user