-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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 tuple cons cell syntax #1582
Conversation
One possible alternative syntax is |
If you’re proposing syntax changes/additions/removals, please strive to describe the changes in terms of changes to the grammar in the RFC as well. |
Yay, variadic generics. |
I feel like there must be some kind of complications around this but I can't think of them at the moment. Maybe they'll come to me later. If there actually aren't then let's definitely do this. Is there any use case where you would ever want to use this outside of trait |
Thanks, I've updated the RFC to mention other syntaxes.
You mean supply a diff for
Ah, I'd forgotten about that RFC.
Good point. The RFC as it is would at least get you some of the way there because it would be possible to
Not that I can think of. You do need to be able to pattern-match on generically sized tuples in order to write those trait impls though (eg. |
It occurred to me that this could be extended for structs, perhaps with some sort of brace-based syntax (I consider the syntax unimportant because I have a feeling this would be a separate RFC). basically, in some sense, a struct is itself a tuple, with types equivalent to the types of the fields as declared in the struct. If the syntax were to be extended to structs, it would provide a method to implement traits that apply if all contained fields of a struct implement a specific trait. This would be hard to work with for traits that actually do things, but might be useful for marker traits (but then we need a syntax to opt out which I'm not sure we have). Possibly I'm saying the same thing @petrochenkov is. On another note, this gets us to within 6 inches of variadic functions and let me be the first to say that I'll certainly be entering the race to submit that RFC, should this one get accepted. Speaking as a C++ programmer, I don't use them often. But they're a godsend when they're needed. |
The type Example: |
@bluss That sucks. Is the representation of tuples set in stone? |
Also, not sure whether to close this and just turn it into a comment on #376. It's the same basic idea as that RFC just done a little bit differently. |
The representation is not set in stone. That the tuple |
Would a workable alternative be to be a bit cleverer about how we do padding? We could represent a |
@canndrew It's an interesting idea and it fixes some cases, but the rule does not handle this example type T = (u32, u8, u8, u16);
type Tail = (u8, u16); The tail of This kind of cons-tail scheme seems to be much easier to work out for value-only destructuring (which may require copying). Just notice today how much |
Not if we ensure that modifications to a tuple never modify any "padding" bytes at the start of the tuple. I imagine this might cause extra overhead some of the time. For example it might be more efficient to modify the |
It's incompatible with all the tools of a low level language like rust, that assumes it can for example memcpy over the whole memory of a value (like std::mem::swap does). |
Right, of course. Well that screws this whole plan then as far as I can see. You can't implement |
This also sounds potentially related to #1397 |
It seems like this can not be done in regular rust reference to compound type parts semantics, instead variadic generics needs its own syntax and semantics. |
@bluss Actually, if we implemented the suggestion in the link @glaebhoerl posted it seems like we could do this. Just layout tuples the other way around than to what I was proposing. |
There is an unused syntax, I like the solution for the representation incompatibility, seems easier than my contraptions to turn e.g. I'm cc-ing @ubsan as them and I have experimented with (working) prototypes of variadic generics, one of mine being https://play.rust-lang.org/?gist=030b0b74b3a72eecd09d567368a592bb&version=nightly. What's really cool in that one is that |
Ah, I should've known it was too good to be true. In that case, I prefer my "take references to all fields" contraptions. |
@canndrew I see your point about the reverse layout order. Seems interesting to say the least. It makes sense that to add an element (the head) and keep the rest (the tail), you need to add it at the end. As for |
Yeah I'd prefer reverse layout order. |
I'm wondering why do we need extra syntax (";" or "...") for this feature at all. let (head, tail) = (1, 2, 3, "4"); // 1. head = 1, tail = (2, 3, "4")
let (head1, head2, tail) = (1, 2, 3, "4"); // 2. head1 = 1, head2 = 2, tail = (3, "4")
let (head1, head2, tail) = (1, 2, 3); // 3. head1 = 1, head2 = 2, tail = 3
let (head1, head2, tail) = (1, 2); // 4. head1 = 1, head2 = 2, tail = () Am I miss some Rust feature that prevents this? |
@HaronK You can't do that without knowing you have a type mismatch first, so what if you need to retcon it? let x = (1, 2, 3);
let y: &(_, _) = &x; You also still need a syntax for expanding a tuple value/type in-place and (variadic) function arguments. |
I understand that it's not possible right now. That's why we have this RFC. I only suggest instead of extending tuple syntax, update current type-checking system to group tail part of the tuple. |
There is a lot more one could do at compile time obviously. As a first, it's quite obnoxious that
In general, there are way too many libraries using About tuples though : I doubt one can impose alignment requirements on tuples. Instead, one might do tuple cons backwards, so if As for looping over tuples at compile time, @Amanieu's generic closures sound way nicer than |
There's an RFC for type-level integers which I can never find quickly, and thus I don't have the link. My work on layout which is maybe 2/3rds finished if I'm lucky will make changing the representation of a tuple a trivial operation. It will also probably make a tuple not necessarily ordered in memory to match the field indexes. Miri could allow for compile-time maps and (with generic closures) folds of constant tuples. I can't quite envision how you write the types though; it seems like the constraints on the closure that the mapping function takes would have to somehow match those on the closure as written at the call site. |
@burdges Yeah, we really need constexpr. I myself also like the idea of |
@camlorn Do you mean the const-dependent type system RFC? |
@mglagla Someone needs to work out how to make a system like this come up with memorable identifiers. |
@rfcbot fcp postpone As of this writing we have 34 open lang RFCs. People who follow many RFCs may have noticed that there's been an effort recently to move many of the open RFCs to a resolution, especially if they haven't seen recent activity. This RFC has had basically no activity since June, and isn't likely to be prioritized as a result of the 2017 roadmap. However, this RFC is a big proposal, taking steps to solve a big problem (variadic generics), and so I want to be emphatic that I'm proposing postponement only because it seems likely to sit quietly open for a good long while before we take further action on it. Once solving this problem is a more immediate term priority, I'd be glad to see it re-opened. |
My own opinion is that it seems like the solution proposes by this RFC is improperly generalized. The problem this RFC is trying to solve is "implementing a trait for all tuples." This RFC solves that problem, but the connection between the problem and the proposed syntax is not obvious. The syntax is general purpose, but as far as I can tell it would be dubious to use the syntax for anything other than implementing traits for all tuples. Basically, I wonder if there is a solution to this problem that is more targeted on implementing traits for tuples. Unless we have other motivations for this syntax, I don't want to add overly general features because that has its own complexity cost. I do think this RFC takes the right approach to solving variadic generics though - start with solving the most common problem (implementing a trait for all tuples), before moving to the wider problem. |
Team member @withoutboats has proposed to postpone 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. |
Status update on "static for" mentioned above:
The lambda's |
@petrochenkov I've mentioned generic closures for this before, I also think it has a lot of potential. |
🔔 This is now entering its final comment period, as per the review above. 🔔 |
I see a lot of discussion in the abstract with A and B and such, but more concrete examples would make the motivation more clear. Are there examples of projects that suffer for the lackof this? |
Tuples are product types where cons cell lists are sum types. My intuition says mixing them together is asking for trouble. The construct proposed here reminds me of HList, which, IIRC, requires HKT. |
|
I find the "change the layout of tuples" solution very, very surprising. It feels totally reasonable to me to expect that I would be very confused to find my code breaking or its performance changing because I went from a For consistency and simplicity, I hope that it always remains true that "a tuple is the same as the equivalent struct with 0, 1, ... for the field names". |
@scottmcm I don't believe the layout of homogenous tuples would be impacted? I think there is a completely principled reason for tuples and structs to have different representation: one is ordered, the other is not. Just like you presumably don't find it surprising that
|
Tuples wouldn't have to be strictly ordered under this proposal. The fundamental unit here is pairs, and pairs can be ordered either which way the compiler chooses. For an n-tuple that still gives the compiler 2^(n-1) different layout options (rather than n! in the case of structs). ie. for a tuple |
Something else I noticed: RFC 1506 uses and extends the "a tuple struct is equivalent to a braced struct with integer literal field names" idea: https://github.com/rust-lang/rfcs/blob/master/text/1506-adt-kinds.md. @glaebhoerl The RFC says "Secondly, we layout tuples in reverse order". I don't see any note about homogeneous sections being different. Also, it's not completely true that "one is ordered, the other is not". The last field in a braced struct is already special: only the last field of a struct may have a dynamically sized type. The drop order (currently and proposed) is also dependent on declaration order. |
The final comment period is now complete. |
I'm going to close this RFC as postponed. While there's desire to eventually support this kind of tuple-generic programming, there are many thorny issues and in terms of the roadmap the feature doesn't rank high enough to devote the necessary bandwidth at this time. |
@eddyb Looking back on this, it seems like most of the disagreements were focused around the tuple representation and the new syntax. Is there any reason not to reopen a more minimal proposal based on your playground example? It seems like this approach avoids the representation issue, and any special syntax for pattern matching out the head of a tuple could be implemented as sugar for P.S. If such a proposal were to move forward, I'd also highly suggest implementing |
I thought so too, a long time ago, but we're actually closer to the latter at this point. |
@eddyb Even if so, I think there are many cases where it's useful to be generic over both tuples and arrays, and getting both with one trait impl seems like a great advantage to this approach. That aside, is there a reason not to have these traits in the language? The only downside I can think to avoiding them is that it wouldn't be immediately obvious to library consumers that a |
Add syntax for expressing tuples as a head and tail pair, similar to a Lisp cons cell.
Rendered