-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
Add a DynSized trait #44469
Add a DynSized trait #44469
Conversation
Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @pnkfelix (or someone else) soon. If any changes to this PR are deemed necessary, please add them as extra commits. This ensures that the reviewer can see what has changed since they last reviewed the code. Due to the way GitHub handles out-of-date commits, this should also make it reasonably obvious what issues have or haven't been addressed. Large or tricky changes may require several passes of review and changes. Please see the contribution instructions for more information. |
@@ -13,6 +13,7 @@ | |||
struct Foo { | |||
bytes: [u8; std::mem::size_of::<Foo>()] | |||
//~^ ERROR unsupported cyclic reference between types/traits detected | |||
//~^^ ERROR unsupported cyclic reference between types/traits detected |
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 error message is now thrown twice, once when checking if the field type is WF, and once when checking that it is DynSized
.
I'm not sure how to prevent this, or whether it even matters.
e5c3032
to
4bf8bbb
Compare
Rustdoc output is not great with this (it displays the implicit I'm working on a fix for it, should I add it to this PR, or as a follow up one ? |
Personally I'd prefer if the last field of a struct could be a |
That would be a problem because of alignment concerns - you can't do the "DST align" thing without knowing the alignment. However, we could allow it for I don't want to add a new |
@arielb1 Why should it need to know the alignment if I have a pointer? The alignment of the EDIT: Hmmmmm, the alignment of the |
☔ The latest upstream changes (presumably #44316) made this pull request unmergeable. Please resolve the merge conflicts. |
@retep998 Yes, that's definitely a use case I'd like to support eventually. My goal was to keep the feature conservative for now, and expand with an RFC. OTOH, there was already an RFC for extern types, so maybe opaque tails falls under that RFC. I'm happy to include it if there's consensus about it. @arielb1 Something like #[repr(C)]
struct Foo {
x: u8,
tail: Opaque, // OK
}
fn use_foo(foo: &Foo) -> &Opaque {
&foo.tail // ERROR: Cannot access field `foo`, type `Opaque` doesn't implement `DynSized`
} There are cases where it could be allowed, such as single field structs, |
I'll try to look at this somewhat soon, but I assume the review should not be considered pressing until #44295 successfully lands, right? |
r? @arielb1 cc @rust-lang/compiler Does this need FCP? |
I think this does |
@arielb1 is this ready to be proposed to be fcped? if so, could you do that please? if not, what needs to be done first? |
@rfcbot fcp merge |
I don't think I can invoke rfcbot. I'll need to ask @nikomatsakis for help. |
Team member @arielb1 has proposed to merge this. The next step is review by the rest of the tagged teams:
No concerns currently listed. Once these reviewers reach consensus, this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up! See this document for info about what commands tagged team members can give me. |
Note that this will likely break the use std::fmt::Debug;
trait DescriptiveSpec<'r> {}
impl<'r, T> DescriptiveSpec<'r> for &'r T {}
fn from_spec<'r, T: DescriptiveSpec<'r>>(spec: &'r T) {}
fn matching_contains<'s, T: 's, I>(a: &mut &'s I) where &'s I: Debug {
from_spec(a);
}
fn main() {} See #21974 (comment) It would also be a good idea to use crater on this. |
Did you check that spectral isn't fixed by the sized-constraint "hack"? This should still break your example, but I'm not sure how bad that is (that's why we want a crater run) - it "only" makes an existing bug worse (e.g. the |
Also I suggest you remove the documentation on |
@plietar Hi, could you resolve the merge conflict and fix the CI failure? Thanks.
|
Rustfmt needs support for extern types, and rls depends on rustfmt.
The DynSized trait is implemented by all types which have a size and alignment known at runtime. This includes every type other than extern types, introduced in RFC 1861 and implemented in rust-lang#44295, which are completely opaque. The main motivation for this trait is to prevent the use of !DynSized types as struct tails. Consider for example the following types : ```rust extern { type foo; } struct A<T: ?Sized> { a_x: u8 a_y: T } struct B<T: ?Sized> { b_x: u8 b_y: T } ``` Before this change, the type `A<B<foo>>` is considered well-formed. However, the alignment of `B<foo>` and thus the offset of the `a_y` field depends on the alignment of `foo`, which is unknown. By introducing this new trait, struct tails are now required to implement `DynSized`, such that their alignment is known. The trait is an implicit bound, making `A<B<foo>>` ill-formed. Just like the `Sized` trait, the default bound can be opted-out by using `?DynSized`.
Checking off for @nrc, who is away for some time. @petrochenkov, are you OK with this landing? |
Oh, I didn't even notice it was pending on me. |
🔔 This is now entering its final comment period, as per the review above. 🔔 |
☔ The latest upstream changes (presumably #44901) made this pull request unmergeable. Please resolve the merge conflicts. |
The final comment period is now complete. |
Heads-up @plietar — you have merge conflicts that need to be addressed before this can progress. |
triage ping for @plietar! out of curiosity, any update on this? |
I'm going to close this PR due to inactivity; looks like even though this has made it through FCP the merge conflicts need to be resolved and then a crater run needs to happen. @plietar thank you for your contribution, please feel free to reopen this when you have a chance to resolve the merge conflicts! Let us know if you need any help!! |
Is there a discussion taking place somewhere on the bullet points @plietar outlined in the first comment on this PR? |
(This depends on #44295)
The DynSized trait is implemented by all types which have a size and alignment
known at runtime. This includes every type other than extern types, introduced
in RFC 1861 and implemented in #44295, which are completely opaque.
The main motivation for this trait is to prevent the use of
!DynSized
types asstruct tails. Consider for example the following types :
Before this change, the type
A<B<foo>>
is considered well-formed. However,the alignment of
B<foo>
and thus the offset of thea_y
field depends on thealignment of
foo
, which is unknown.By introducing this new trait, struct tails are now required to implement
DynSized
, such that their alignment is known. The trait is an implicit bound,making
A<B<foo>>
ill-formed.Just like the
Sized
trait, the default bound can be opted-out by using?DynSized
.The trait also prevents the use of the
size_of_val
andalign_of_val
functions with extern types.After discussion on IRC, the intention here is to include
DynSized
as an "implementation detail" for now just to fix extern types, and propose an RFC later to extend it / stabilize it. Until this is the case, generic functions/types can't be defined for extern types.The implementation here is deliberately conservative. There's a number of open questions to be resolved by the future RFC. All the answers are no in the current implementation.
DynSized
be in the prelude ??Sized
to?DynSized
(where applicable) ? For now I have only change theis_null
andas_ref
functions on raw pointers, since they should frequently be used with extern types.!DynSized
tails be allowed in structs, as long as they are never accessed ?struct A { x: u8, y: foo }
could be accepted buta.y
rejected, since getting the offset ofy
is the part that can't be done.DynSized
? This would allow things like C strings (null terminated) and Pascal strings (length prefixed). This has some overlap with the "custom DST" proposal.