Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.
Sign upRFC: truly unsized types #709
Conversation
This comment has been minimized.
This comment has been minimized.
|
Examples where this is needed (part courtesy of @SSheldon on the forum): |
mzabaluev
added some commits
Jan 22, 2015
This comment has been minimized.
This comment has been minimized.
|
What exactly is the difference between ‘truly’ unsized types and DSTs? The only difference I can see is that DSTs use fat pointers, while ‘truly’ unsized types use thin pointers. I don’t think that’s a necessary distinction to make, because they both have the same restriction: they cannot be used without being behind a pointer. If we, for example, introduced fat pointers that have more than one word of extra data (a feature I’ve wanted a few times), they wouldn’t need extra traits for each separate size, so why should having zero bytes of extra data be any different? |
This comment has been minimized.
This comment has been minimized.
DSTs are dynamically sized types, meaning that the size of the value is known while the value exists. To reconstruct a reference to a DST from a raw pointer, one has to obtain the size. This RFC proposes to lift this restriction in cases when the size of the holistic value is not needed immediately or is unknown. |
This comment has been minimized.
This comment has been minimized.
|
A huge area this would help is disambiguating function pointers and functions. Basically it would be cool if There was a thread around this, but I'm afraid and I can't find it. IIRC @eddyb said it wouldn't work exactly because the unsized vs dynamically sized problem. |
This comment has been minimized.
This comment has been minimized.
|
@Ericson2314: you might be referring to #661. |
mzabaluev
referenced this pull request
Jan 26, 2015
Merged
RFC: Convention for constructing lifetime-bound values from raw pointers #556
This comment has been minimized.
This comment has been minimized.
|
Hmm, that didn't have the conversation with eddyb I remember, but that's definitely one example of people wanting safer dynamic linking. Might of been a conversation about JITing, where perhaps this is even more useful (I've never heard of unlinking dynamically linked libraries). |
This comment has been minimized.
This comment has been minimized.
|
@Ericson2314 Is this discuss post on |
This comment has been minimized.
This comment has been minimized.
|
@P1start well, not exactly as I remembered, but that's probably it. Thanks! |
dgrunwald
referenced this pull request
Jan 27, 2015
Closed
Empty structs should not need #[repr(C)] #750
This comment has been minimized.
This comment has been minimized.
|
This is a bit of a crazy idea, but you could give DynamicSize an associated type (Ptr) which the compiler would automatically use for references to that type. This would eliminate the need for special handling of slices and trait objects within the compiler. This type would fullfill the role of a raw pointer, *T by implementing Deref, from which the compiler constructs an implicit reference type &T which enforces the correct borrow rules, but otherwise acts like the Ptr type. A &T then implicitly converts only to DynamicSize::Ptr, but not *T. The Unsized bound is equivalent to DynamicSize<Ptr = *T>, ie. a raw pointer. |
This comment has been minimized.
This comment has been minimized.
|
My understanding of "unsized" is that it is the result of "unsizing", which turns static type info into dynamic values. Not that I have a better name for the types that lack any size information whatsoever. |
This comment has been minimized.
This comment has been minimized.
|
I agree with @Diggsey that a generalization of DST metadata might be more worthwhile than adding special cases to the possible DST values. At least, if those special cases add additional syntax and semantic, like in this proposal. |
This comment has been minimized.
This comment has been minimized.
|
@Kimundi, what additional syntax you are referring to? The only visible changes this proposal adds are a new marker type and the Semantics do change, but I think there are two different use cases currently lumped in with
I'm not entirely sure that case 2 is a real concern, since an implementation of a generic trait parametric on an |
This comment has been minimized.
This comment has been minimized.
|
@mzabaluev With regard case 2: there was a PR somewhere to allow "size_of_val" and friends to work on DSTs, so the distinction between DynamicSize and !Sized is definitely needed, although there's still a bit of a grey area between the cases of "raw pointer, but can figure out the size at runtime (not necessarily in an efficient way)" vs "raw pointer, can't figure out size/type has no concept of size". |
This comment has been minimized.
This comment has been minimized.
|
@mzabaluev: I meant the addition of the additional marker types and traits as additional "syntax". In my opinion, there is no difference between unsized and dynamically sized - in both cases being sized refers the knowing the size at compiletime, and in both cases there is some runtime mechanism for finding it out. Whether that runtime mechanism involves storing the size directly (slices), or in form of a vtable (trait objects), or as part of the data structure pointed-at ( I'm not saying that a DST value with a thin pointer representation is not useful, I just don't think it needs to be its own "thing". |
This comment has been minimized.
This comment has been minimized.
|
@Kimundi I think there is a useful difference between thin/fat pointer DSTs, which is that thin pointers can be transmuted between each other, and passed to C/C++ code as a raw pointer. It's quite easy to come up with examples where the generic constraints should be "is a thin pointer" rather than "is not a DST" (for example, compatibility with void*). |
This comment has been minimized.
This comment has been minimized.
It was my understanding that this would support cases where you couldn't find out. This is needed for functions. |
This comment has been minimized.
This comment has been minimized.
|
@Kimundi even the types with a size that can be calculated from content may have sufficiently different performance characteristics for this operation (e.g. O(N) for C strings vs O(1) for DSTs) so genericity may not be desirable. Anyway, there doesn't seem to be a generic way to calculate the size of a DST value, so the only difference is whether a fat pointer is required to represent a reference. |
This comment has been minimized.
This comment has been minimized.
|
@Diggsey If I understood your proposal about |
This comment has been minimized.
This comment has been minimized.
|
@mzabaluev Originally, I was thinking of something like this:
However, it might make more sense like this:
So the useful bounds become:
And for any type, it's pointer type can be obtained via:
|
This comment has been minimized.
This comment has been minimized.
SSheldon
commented
Jan 30, 2015
@Diggsey, fyi |
This comment has been minimized.
This comment has been minimized.
|
@SSheldon Ah, I didn't realise that - I've updated my previous post to reflect that. |
This comment has been minimized.
This comment has been minimized.
That's quite a mouthful, and I don't think current Rust allows expressions as bounds. But if bounds like that could actually be used, a convenience trait could be provided to assert it. |
This comment has been minimized.
This comment has been minimized.
|
Given #738 it looks like we may end up removing all of the various marker structs, in which case adding a new Perhaps we could beef up the compiler to consider types unsized such as: struct CStr {
data: c_char,
marker: Phantom<[c_char]>,
}In this case we'd basically be saying that the compiler for type analysis should consider (just a thought) |
This comment has been minimized.
This comment has been minimized.
|
postponing for post 1.0; cannot spend time thinking about this. (Also, RFC is thin on details, at least for a change of this size.) |
mzabaluev commentedJan 22, 2015
Further subdivide unsized types into dynamically-sized types, implementing
an intrinsic trait
DynamicSize, and types of indeterminate size. Referencesfor the latter kind will be thin, while allocating slots or copying values
of such types is not possible outside unsafe code.
Rendered