Uh oh!
There was an error while loading. Please reload this page.
RFC: truly unsized types - #709
Conversation
mzabaluev
commented
Jan 22, 2015
Examples where this is needed (part courtesy of @SSheldon on the forum): |
ftxqxd
commented
Jan 23, 2015
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? |
mzabaluev
commented
Jan 24, 2015
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. |
Ericson2314
commented
Jan 25, 2015
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. |
mzabaluev
commented
Jan 25, 2015
@Ericson2314: you might be referring to #661. |
Ericson2314
commented
Jan 26, 2015
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). |
ftxqxd
commented
Jan 26, 2015
@Ericson2314 Is this discuss post on |
Ericson2314
commented
Jan 26, 2015
@P1start well, not exactly as I remembered, but that's probably it. Thanks! |
Diggsey
commented
Jan 29, 2015
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. |
eddyb
commented
Jan 29, 2015
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. |
Kimundi
commented
Jan 29, 2015
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. |
mzabaluev
commented
Jan 29, 2015
@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 |
Diggsey
commented
Jan 29, 2015
@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". |
Kimundi
commented
Jan 29, 2015
@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". |
Diggsey
commented
Jan 29, 2015
@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*). |
Ericson2314
commented
Jan 29, 2015
It was my understanding that this would support cases where you couldn't find out. This is needed for functions. |
mzabaluev
commented
Jan 29, 2015
@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. |
mzabaluev
commented
Jan 30, 2015
@Diggsey If I understood your proposal about |
Diggsey
commented
Jan 30, 2015
@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:
|
SSheldon
commented
Jan 30, 2015
@Diggsey, fyi |
Diggsey
commented
Jan 30, 2015
@SSheldon Ah, I didn't realise that - I've updated my previous post to reflect that. |
mzabaluev
commented
Jan 30, 2015
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. |
alexcrichton
commented
Feb 3, 2015
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: structCStr{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) |
pnkfelix
commented
Feb 5, 2015
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.) |
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