-
Notifications
You must be signed in to change notification settings - Fork 12.9k
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
Tracking issue for DST coercions (coerce_unsized, unsize) stabilization #27732
Comments
@nrc, what's your sense of the status for these features? Do you feel ready to stabilize after the libs team takes a look? |
My feeling (and it is really just a feeling, I have no data to back this up) is that DST coercions haven't yet got the use they need to prove themselves for stabilisation. I'd love to be wrong about this - if someone could show me a bunch of code doing stuff with DST coercions I'd be very happy. OTOH, I don't think there is anything fundamentally wrong with them, so it would not be a waste of time for the libs team to take a look. |
Why is the marker named |
It goes the wrong way around - for example, we have |
Can we move to stabilize this? It's been unchanged for 5 months and I've heard no complaints about it. |
I don't recall having any issues with this in libstd. The correct way to use this is basically a witchcraft incantation (mostly because these are under-the-covers things one never interacts with in real code), but as far as I know, there's know way to use it dangerously wrong? The whole thing Just Works. I guess one thing I've never really thought about is why one needs to talk about whether the pointed-to value is unsizeable or whatever. Why can't one simply declare that pointer X is an unsizable one, and have all that junk automatic? Is this desirable to have for generic consumers...? |
It's desirable for generic consumers of e.g. Arena allocators that allocate a Sized type that implements a trait unknown to the allocator, and the consumer wants to coerce the allocated result to an allocated trait object. See https://gitlab.com/Bastacyclop/rust_arena/blob/master/src/lib.rs in the tests. It's a decent use case. How would you recommend doing this otherwise? |
Is the lack of support for enums deliberate, temporary, or merely overlooked? |
I'm nominating this for discussion at the next lang team meeting. |
@jnicholls maybe I'm missing something, but just mark the one pointer field that will be Unsized as coercable: https://gitlab.com/Bastacyclop/rust_arena/blob/master/src/lib.rs#L41 It seems to me that all the |
@gankro Sorry I don't follow what you mean. Can you provide an example? |
Oops, something clobbered my selection, I meant to link to: https://gitlab.com/Bastacyclop/rust_arena/blob/master/src/lib.rs#L59 Basically instead of pub struct Allocated<'a, 'b, T: 'b + ?Sized> {
reference: &'b mut T,
phantom: PhantomData<&'a ()>
}
impl<'a, 'b, T: ?Sized, U: ?Sized> CoerceUnsized<Allocated<'a, 'b, U>> for Allocated<'a, 'b, T>
where U: 'b, T: 'b + Unsize<U> {} You would just do something like: #[coerce_unsized(T)]
pub struct Allocated<'a, 'b, T: 'b + ?Sized> {
reference: &'b mut T,
phantom: PhantomData<&'a ()>
} |
cc @eddyb |
Removed T-libs tag, but note that we'd like to review the naming conventions here before stabilization. |
There's room for generalization and a good chance we might want |
Right now, because |
I'm not very familiar with how this works, but shouldn't the |
You implement e.g. impl<'a, T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<&'a mut U> for &'a mut T {} |
(adding T-libs as this has a library API associated with it which needs stabilization) |
So at a recent @rust-lang/lang meeting we discussed this. I think everyone felt...somewhat comfortable with the idea of going forward, but we also wanted to do a thorough review of the current status of the code, along with a comparison against the existing specifications, to make sure everything is well aligned. |
@nikomatsakis The problem, though, is that the RFC is intentionally provisional, mostly to get Maybe with specialization we can even encode |
@eddyb we discussed in @rust-lang/lang meeting today -- splitting off into two feature gates makes sense, provided we have a good description of what the two gates cover and the interaction between them. (e.g., as the issue comments) |
Has any consideration been given to having When attempting to use |
@matthieu-m That playground example is currently throwing an ICE, in case that's new. Error gist. |
I think this is new, but as I mentioned because |
Currently, there's no std/core type for a "sized str" (by which I mean an array of UTF-8 bytes). Of course, one can create a custom version: use core::str;
#[repr(transparent)]
pub struct Str<const N: usize>([u8; N]);
impl<const N: usize> Str<N> {
pub fn new(s: [u8; N]) -> Result<Self, str::Utf8Error> {
str::from_utf8(&s)?;
Ok(Self(s))
}
pub unsafe fn new_unchecked(s: [u8; N]) -> Self {
Self(s)
}
} But such a custom type cannot be "unsized" to |
impl<const N: usize> Deref for Str<N> {
type Target = str;
fn deref(&self) -> &str {
unsafe {
str::from_utf8_unchecked(&self.0)
}
}
} allows you to "unsize" |
@bjorn3 Of course, but that's not a coercion (the point of this feature, no?). In particular, given |
I have a problem where I want to be generic over reference-like types, and I feel like the current mechanism doesn't allow me something what I would like to do. |
Yes, they can, that's what Deref provides. Your example of |
Apologies, perhaps my previous comment could have been clearer: a deref coercion is not an unsize coercion. What one cannot do (without either some relaxation of coherence rules or else fn generic<U: ?Sized>(t: impl Unsize<U>) {
todo!() // something involving &t as &U
}
fn foo<const N: usize>(s: Str<N>) {
generic::<str>(s); // Str<N> does not implement Unsize<str>
} For context, this is what prevents strings being "thinnable" in my (experimental) thinnable crate. |
Is there something wrong with the rule
when it works with a trait object with associate type, such as For example: trait Foo {
fn foo(&self);
}
trait Bar: Foo {
type Assoc;
fn bar(&self);
}
fn upcast<Dyn>(bar: &Dyn) -> &dyn Foo
where
Dyn: ?Sized + Unsize<dyn Foo>,
{
bar
}
impl Foo for i32 {
fn foo(&self) {
println!("foo");
}
}
impl Bar for i32 {
type Assoc = i32;
fn bar(&self) {
println!("bar");
}
}
fn main() {
let bar: &dyn Bar<Assoc = i32> = &42;
let foo = upcast(bar);
foo.foo();
} in which the compiler says
But if I try to manually impl the trait
Here's the minimal example: https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=85925cd4977fc95beb52ce9a03653755 , |
FWIW, that's effectively relying on the incomplete feature |
Closing in favor of #18598 -- they seem to cover the same ground. |
…g#18598 Issue rust-lang#27732 was closed as a duplicate of rust-lang#18598. Signed-off-by: Anders Kaseorg <andersk@mit.edu>
…=Dylan-DPC Update coerce_unsized tracking issue from rust-lang#27732 to rust-lang#18598 Issue rust-lang#27732 was closed as a duplicate of rust-lang#18598.
…iaskrgr Rollup of 7 pull requests Successful merges: - rust-lang#105835 (Refactor post borrowck cleanup passes) - rust-lang#105930 (Disable `NormalizeArrayLen`) - rust-lang#105938 (Update coerce_unsized tracking issue from rust-lang#27732 to rust-lang#18598) - rust-lang#105939 (Improve description of struct-fields GUI test) - rust-lang#105943 (Add regression test for rust-lang#102206) - rust-lang#105944 (Add regression test for rust-lang#80816) - rust-lang#105945 (Add regression test for rust-lang#57404) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
DST coercions were the last part of DST to land, and are still undergoing some changes.
Before stabilization, at the very least the API surface here needs some scrutiny from the libs team for naming and other conventions issues.
cc @nrc @gankro
Things to consider prior to stabilization
Pin
is unsound due to transitive effects ofCoerceUnsized
#68015 for details.The text was updated successfully, but these errors were encountered: