-
Notifications
You must be signed in to change notification settings - Fork 12.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
PinCoerceUnsized trait into core #125048
base: master
Are you sure you want to change the base?
PinCoerceUnsized trait into core #125048
Conversation
This comment has been minimized.
This comment has been minimized.
library/core/src/ops/deref.rs
Outdated
#[unstable(feature = "stable_deref_trait", issue = "123430")] | ||
/// # Safety | ||
/// | ||
/// Any two calls to `deref` must return the same value at the same address unless |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"same value at the same address" here is pretty vague, and it's unclear to me without reading the RFC thread what exactly that entails and how it compares to the stable deref trait crate. notably, the preconditions on the crate are currently not satisfied by Box because of the special strict aliasing rules imposed by it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The meaning of "same value" is that the concrete type must not change. I copied the explanation in below. Was it unclear?
Here, "same value" means that if
deref
returns a trait object, then the actual type behind that trait object must not change. Additionally, when you unsize coerce fromSelf
toUnsized
, then if you callderef
onUnsized
and get a trait object, then the underlying type of that trait object must be<Self as Deref>::Target
.Analogous requirements apply to other unsized types. E.g., if
deref
returns[T]
, then the length must not change. In other words, the underlying type must not change from[T; N]
to[T; M]
.
The motivation for this requirement is that with trait objects, you could otherwise first return one struct, and then later return some wrapper struct that wraps the original struct using #[repr(transparent)]
.
library/core/src/ops/deref.rs
Outdated
@@ -309,3 +309,25 @@ impl<T: ?Sized> Receiver for &T {} | |||
|
|||
#[unstable(feature = "receiver_trait", issue = "none")] | |||
impl<T: ?Sized> Receiver for &mut T {} | |||
|
|||
#[lang = "stable_deref"] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This shouldn't be made into a lang item until it's actually used by the compiler. I feel like having unused lang items is not desirable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is there any chance of us somehow managing to check and error in that case?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thinks okay the moment this left my hands the answer came to me as "probably not usefully" (it would only be one more formality-tier listing somewhere and someone will just add it to that).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the use of it is rather imminent. Ideally with #123472 this would go into the trait bounds that #[derive(SmartPointer)]
generates.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I came to my right sense! I have dropped the lang term here.
711777b
to
269eff8
Compare
This comment has been minimized.
This comment has been minimized.
1795d68
to
77f8779
Compare
77f8779
to
5b034e4
Compare
This comment has been minimized.
This comment has been minimized.
5b034e4
to
072c114
Compare
072c114
to
d5e4fcb
Compare
It would make sense to add the following as a test: use core::cell::{Cell, RefCell, UnsafeCell};
use core::pin::Pin;
pub trait MyTrait {}
impl MyTrait for String {}
pub fn cell(arg: Pin<Cell<Box<String>>>) -> Pin<Cell<Box<dyn MyTrait>>> {
arg
}
pub fn refcell(arg: Pin<RefCell<Box<String>>>) -> Pin<RefCell<Box<dyn MyTrait>>> {
arg
}
pub fn ucell(arg: Pin<UnsafeCell<Box<String>>>) -> Pin<UnsafeCell<Box<dyn MyTrait>>> {
arg
} This compiles today, so we shouldn't break it. |
d5e4fcb
to
ea678b7
Compare
@Darksonn test cases have been added. |
@rustbot labels +I-lang-nominated +T-lang Nominating as @dingxiangfei2009 requested lang review. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit
library/core/src/pin.rs
Outdated
/// `[T]`, then the length must not change. In other words, the underlying type | ||
/// must not change from `[T; N]` to `[T; M]` with an `N` different from `M`. | ||
/// | ||
/// If this type alos implements `DerefMut`, then the same guarantee must be upheld by |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/// If this type alos implements `DerefMut`, then the same guarantee must be upheld by | |
/// If this type also implements `DerefMut`, then the same guarantee must be upheld by |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Applied
r? @scottmcm |
@rustbot labels -I-lang-nominated We talked about this in the meeting between members of the lang team and RfL. We felt this work was sufficiently covered by the RFC that no lang team decision was needed here for this nightly work. It just needs review, and we'll leave that to @scottmcm as he has context here. |
#[stable(feature = "pin", since = "1.33.0")] | ||
unsafe impl<'a, T: ?Sized> PinCoerceUnsized for &'a T {} | ||
|
||
#[stable(feature = "pin", since = "1.33.0")] | ||
unsafe impl<'a, T: ?Sized> PinCoerceUnsized for &'a mut T {} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you should also implement for raw pointers and NonNull
. (And add a test.)
2248400
to
447bf72
Compare
This comment has been minimized.
This comment has been minimized.
a380055
to
02ae2b1
Compare
library/core/src/pin.rs
Outdated
/// # Safety | ||
/// | ||
/// Implementing this unsafe traits requires the guarantee that any two calls | ||
/// to `Deref::deref` must return the same value at the same address, **even after moves | ||
/// or unsize-coercions of `self`**, with exceptions of mutations to `self`. | ||
/// | ||
/// Here, "same value" means that if `deref` returns a trait object, then the actual | ||
/// concrete type behind that trait object must not change. | ||
/// Additionally, when you unsize- coerce from `Self` to `Unsized`, | ||
/// then if you call `deref` on `Unsized` which returns a trait object reference, | ||
/// the underlying type of that trait object must be `<Self as Deref>::Target`. | ||
/// | ||
/// Analogous requirements apply to other unsized types. E.g., if `deref` returns | ||
/// `[T]`, then the length must not change. In other words, the underlying type | ||
/// must not change from `[T; N]` to `[T; M]` with an `N` different from `M`. | ||
/// | ||
/// If this type also implements `DerefMut`, then the same guarantee must be upheld by | ||
/// calls to `deref_mut`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like this is using the old safety comment. The RFC was updated to use these safety requirements instead:
/// Trait that indicates that this is a pointer or a wrapper for one, where
/// unsizing can be performed on the pointee when it is pinned.
///
/// # Safety
///
/// If this type implements `Deref`, then the concrete type returned by `deref`
/// and `deref_mut` must not change without a modification. The following
/// operations are not considered modifications:
///
/// * Moving the pointer.
/// * Performing unsizing coercions on the pointer.
/// * Performing dynamic dispatch with the pointer.
/// * Calling `deref` or `deref_mut` on the pointer.
///
/// The concrete type of a trait object is the type that the vtable corresponds
/// to. The concrete type of a slice is an array of the same element type and
/// the length specified in the metadata. The concrete type of a sized type
/// is the type itself.
It gets rid of the requirement that the address is the same, and simplifies it to just requiring that the concrete type is unchanged.
02ae2b1
to
ea1ba36
Compare
cc @Darksonn @wedsonaf @ojeda
This is a PR to introduce a
PinCoerceUnsized
trait in order to make trait impls generated by the proc-macro#[derive(SmartPointer)]
, proposed by RFC, sound. There you may find explanation, justification and discussion about the alternatives.Note that we do not seek stabilization of this
PinCoerceUnsized
trait in the near future. The stabilisation of this trait does not block the eventual stabilization process of the#[derive(SmartPointer)]
macro. Ideally, use ofDerefPure
is more preferrable except this will actually constitute a breaking change.PinCoerceUnsized
emerges as a solution to the said soundness hole while avoiding the breaking change. More details on theDerefPure
option have been described in this section of the RFC linked above.Earlier discussion can be found in this Zulip stream and rust-for-linux thread.