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

Tuple-Based Variadic Generics #1935

Closed
wants to merge 22 commits into
base: master
from

Conversation

Projects
None yet
@cramertj
Member

cramertj commented Feb 28, 2017

Rendered

cc @eddyb @sgrif

@aturon aturon added the T-lang label Feb 28, 2017

@withoutboats

This comment has been minimized.

Show comment
Hide comment
@withoutboats

withoutboats Feb 28, 2017

Contributor

How would you actually write variadic functions under this proposal? Am I correct that you'd still have to write something like foo( (arg1, arg2, arg3) ), or would there be some kind of sugar?

I guess the unresolved questions covers this?

Contributor

withoutboats commented Feb 28, 2017

How would you actually write variadic functions under this proposal? Am I correct that you'd still have to write something like foo( (arg1, arg2, arg3) ), or would there be some kind of sugar?

I guess the unresolved questions covers this?

@camlorn

This comment has been minimized.

Show comment
Hide comment
@camlorn

camlorn Feb 28, 2017

It is not a major deal breaker or anything, but it's worth noting that my field reordering stuff does currently affect tuples, and we probably want it to continue doing so where possible, I'd think.

Now if only the world would leave me alone for the like 2 days I need to finish my field reordering stuff, but that's another discussion.

camlorn commented Feb 28, 2017

It is not a major deal breaker or anything, but it's worth noting that my field reordering stuff does currently affect tuples, and we probably want it to continue doing so where possible, I'd think.

Now if only the world would leave me alone for the like 2 days I need to finish my field reordering stuff, but that's another discussion.

@cramertj

This comment has been minimized.

Show comment
Hide comment
@cramertj

cramertj Feb 28, 2017

Member

@withoutboats You're correct, the current proposal would require something like foo((arg1, arg2, arg3)). However, as you noticed, the "unresolved questions" section mentions a possible extension to allow things like fn foo<Args: Tuple + MyTrait>(args: ...Args), which could be called like foo(arg1, arg2, arg3).

Member

cramertj commented Feb 28, 2017

@withoutboats You're correct, the current proposal would require something like foo((arg1, arg2, arg3)). However, as you noticed, the "unresolved questions" section mentions a possible extension to allow things like fn foo<Args: Tuple + MyTrait>(args: ...Args), which could be called like foo(arg1, arg2, arg3).

type AsRefs<'a>: Tuple + 'a;
type AsMuts<'a>: Tuple + 'a;
fn elements_as_refs<'a>(&'a self) -> Self::AsRefs<'a>;
fn elements_as_mut<'a>(&'a mut self) -> Self::AsMuts<'a>;

This comment has been minimized.

@eddyb

eddyb Feb 28, 2017

Member

I would prefer to avoid a hard dependency on ATC here, and I'm not sure the functionality needs to be in Tuple itself.
IOW, we can do this more transparently to the user with a recursive impl perhaps? Well, no, "compiler knows best", it could project AsRefs partially (e.g. (A, ...B, C)::AsRefs == (&A, ...B::AsRefs, &C)), but we can probably experiment with a recursive impl in a library, for a trait TupleAsRefs<'a>, to start with.

@eddyb

eddyb Feb 28, 2017

Member

I would prefer to avoid a hard dependency on ATC here, and I'm not sure the functionality needs to be in Tuple itself.
IOW, we can do this more transparently to the user with a recursive impl perhaps? Well, no, "compiler knows best", it could project AsRefs partially (e.g. (A, ...B, C)::AsRefs == (&A, ...B::AsRefs, &C)), but we can probably experiment with a recursive impl in a library, for a trait TupleAsRefs<'a>, to start with.

This comment has been minimized.

@eddyb

eddyb Feb 28, 2017

Member

To be clear, it's likely we'll want to only stabilize the ATC form itself, for convenience's sake, but it's not needed to experiment IMO.

@eddyb

eddyb Feb 28, 2017

Member

To be clear, it's likely we'll want to only stabilize the ATC form itself, for convenience's sake, but it's not needed to experiment IMO.

This comment has been minimized.

@cramertj

cramertj Feb 28, 2017

Member

Yeah-- I left a comment about this in the "unresolved questions" section. Separate traits (TupleAsRef<'a> and TupleAsMut<'b>) work and eliminate the dependency on ATCs, but I think it's slightly less clear to the end user.

@cramertj

cramertj Feb 28, 2017

Member

Yeah-- I left a comment about this in the "unresolved questions" section. Separate traits (TupleAsRef<'a> and TupleAsMut<'b>) work and eliminate the dependency on ATCs, but I think it's slightly less clear to the end user.

Show outdated Hide outdated text/0000-variadic-generics.md Outdated
Show outdated Hide outdated text/0000-variadic-generics.md Outdated
Show outdated Hide outdated text/0000-variadic-generics.md Outdated
Show outdated Hide outdated text/0000-variadic-generics.md Outdated
Show outdated Hide outdated text/0000-variadic-generics.md Outdated
@eddyb

This comment has been minimized.

Show comment
Hide comment
@eddyb

eddyb Feb 28, 2017

Member

@camlorn Right, and nothing in the RFC assumes field order matters, i.e. there are no "partial tail borrows" or anything like that, it can all be implemented in a library with safe code for a fixed number of arities.

Member

eddyb commented Feb 28, 2017

@camlorn Right, and nothing in the RFC assumes field order matters, i.e. there are no "partial tail borrows" or anything like that, it can all be implemented in a library with safe code for a fixed number of arities.

@eddyb

This comment has been minimized.

Show comment
Hide comment
@eddyb

eddyb Feb 28, 2017

Member

fn foo<Args: Tuple + MyTrait>(args: ...Args)

MyTrait would presumably imply Tuple, especially if it's a helper specifically for foo.
I was thinking at some point that it makes sense to put ... on the pattern but I was wrong!

  • the signature is fn(...Args) which needs the ... for all external interactions
  • the pattern is matching against a tuple, e.g. these should be equivalent:
fn foo<H, T: Trait>((head, ...tail): ...(H, ...T)) {...}
fn foo<H, T: Trait>(head: H, tail: ...T) {...}
fn foo<H, T: Trait>(args: ...(H, ...T)) { let (head, ...tail) = args; ...}
Member

eddyb commented Feb 28, 2017

fn foo<Args: Tuple + MyTrait>(args: ...Args)

MyTrait would presumably imply Tuple, especially if it's a helper specifically for foo.
I was thinking at some point that it makes sense to put ... on the pattern but I was wrong!

  • the signature is fn(...Args) which needs the ... for all external interactions
  • the pattern is matching against a tuple, e.g. these should be equivalent:
fn foo<H, T: Trait>((head, ...tail): ...(H, ...T)) {...}
fn foo<H, T: Trait>(head: H, tail: ...T) {...}
fn foo<H, T: Trait>(args: ...(H, ...T)) { let (head, ...tail) = args; ...}
Show outdated Hide outdated text/0000-variadic-generics.md Outdated
@cramertj

This comment has been minimized.

Show comment
Hide comment
@cramertj

cramertj May 25, 2017

Member

@nikomatsakis

tuples which appear in certain contexts (e.g., as the target type of a reference) are limited to being "representable"

@Kimundi proposed a similar "Representable" idea.

Personally, I'd prefer to make &(str, str) "just work". &(str, str) could be represented by a pointer along with two integers for the lengths of each str. In general, I think it would be useful to be able to place multiple unsized types into a single datastructure, especially if something like the unsized-Rvalues RFC lands.

The downside of this approach is that fat pointers would no longer have a guaranteed maximum size, which might break some libraries that assume that sizeof(&T) == sizeof((usize, usize)) when T: !Sized.

Member

cramertj commented May 25, 2017

@nikomatsakis

tuples which appear in certain contexts (e.g., as the target type of a reference) are limited to being "representable"

@Kimundi proposed a similar "Representable" idea.

Personally, I'd prefer to make &(str, str) "just work". &(str, str) could be represented by a pointer along with two integers for the lengths of each str. In general, I think it would be useful to be able to place multiple unsized types into a single datastructure, especially if something like the unsized-Rvalues RFC lands.

The downside of this approach is that fat pointers would no longer have a guaranteed maximum size, which might break some libraries that assume that sizeof(&T) == sizeof((usize, usize)) when T: !Sized.

@eddyb

This comment has been minimized.

Show comment
Hide comment
@eddyb

eddyb May 25, 2017

Member

@cramertj There was never such a guarantee, other than by accident - breaking it eventually was always the plan - the problem is the "eventually".

Member

eddyb commented May 25, 2017

@cramertj There was never such a guarantee, other than by accident - breaking it eventually was always the plan - the problem is the "eventually".

@cramertj

This comment has been minimized.

Show comment
Hide comment
@cramertj

cramertj May 25, 2017

Member

@eddyb Yeah, I realize that it's technically undefined behavior, but people still do it. I definitely think it falls under "acceptable breakage."

Member

cramertj commented May 25, 2017

@eddyb Yeah, I realize that it's technically undefined behavior, but people still do it. I definitely think it falls under "acceptable breakage."

@aturon

This comment has been minimized.

Show comment
Hide comment
@aturon

aturon Jun 6, 2017

Member

@cramertj Do you think this has reached the point where it'd be useful to discuss in a lang team meeting?

Member

aturon commented Jun 6, 2017

@cramertj Do you think this has reached the point where it'd be useful to discuss in a lang team meeting?

@cramertj

This comment has been minimized.

Show comment
Hide comment
@cramertj

cramertj Jun 6, 2017

Member

@aturon A few of the points I listed above would benefit from some lang team discussion:

  • Discussing the possibility of an RFC for structures with multiple DST elements, e.g. (str, str).
  • Possibly extending the negative reasoning around the Tuple trait. #[fundamental] isn't enough to allow a blanket impl for Tuples and a blanket impl for another trait. Perhaps a #[sealed] annotation would be appropriate to guarantee to the compiler that no Tuple implementations will be added in the future. However, even with #[sealed], the problem isn't solved. For example, consider implementing a trait for T: Tuple and T: Display. This can't ever be coherent, no matter if Tuple is represented by a trait, a concrete type, or a "type list"-- there's nothing to tell the compiler that an impl of Display for some T: Tuple won't be added at a later date, causing conflicts. I suspect that implementing a trait for all tuples and for all T: SomeTrait will require some degree of specialization / lattice impls no matter which design we pursue in this RFC.

I'll also check in @withoutboats again to see if we can come to some consensus WRT their preference for first-class "type lists."

Member

cramertj commented Jun 6, 2017

@aturon A few of the points I listed above would benefit from some lang team discussion:

  • Discussing the possibility of an RFC for structures with multiple DST elements, e.g. (str, str).
  • Possibly extending the negative reasoning around the Tuple trait. #[fundamental] isn't enough to allow a blanket impl for Tuples and a blanket impl for another trait. Perhaps a #[sealed] annotation would be appropriate to guarantee to the compiler that no Tuple implementations will be added in the future. However, even with #[sealed], the problem isn't solved. For example, consider implementing a trait for T: Tuple and T: Display. This can't ever be coherent, no matter if Tuple is represented by a trait, a concrete type, or a "type list"-- there's nothing to tell the compiler that an impl of Display for some T: Tuple won't be added at a later date, causing conflicts. I suspect that implementing a trait for all tuples and for all T: SomeTrait will require some degree of specialization / lattice impls no matter which design we pursue in this RFC.

I'll also check in @withoutboats again to see if we can come to some consensus WRT their preference for first-class "type lists."

@eddyb

This comment has been minimized.

Show comment
Hide comment
@eddyb

eddyb Jun 6, 2017

Member

@cramertj I don't recall where the T: Tuple and T: Trait overlap comes from.
Are there any examples of usecases that involve it? I thought you'd have traits implemented for tuples for certain kinds of recursion, and traits implemented for tuples and other types (so no blanket impl would be acceptable anyway - I could be wrong though).

Member

eddyb commented Jun 6, 2017

@cramertj I don't recall where the T: Tuple and T: Trait overlap comes from.
Are there any examples of usecases that involve it? I thought you'd have traits implemented for tuples for certain kinds of recursion, and traits implemented for tuples and other types (so no blanket impl would be acceptable anyway - I could be wrong though).

@cramertj

This comment has been minimized.

Show comment
Hide comment
@cramertj

cramertj Jun 6, 2017

Member

@eddyb @sgrif expressed interest in it-- I'm imagining they have some use case in mind.

I'd expect the desire is related to implementing a function that takes either a single argument (of type T: SomeTrait) or a tuple of arguments, however if the future extensions to allow fn my_func(...args: ...Args) are accepted, then this could be represented as a function that takes one arguments or many arguments, and in the meantime single-argument calls to the function could use my_func((arg)).

Edit: I think @sgrif first mentioned this concern here.

Member

cramertj commented Jun 6, 2017

@eddyb @sgrif expressed interest in it-- I'm imagining they have some use case in mind.

I'd expect the desire is related to implementing a function that takes either a single argument (of type T: SomeTrait) or a tuple of arguments, however if the future extensions to allow fn my_func(...args: ...Args) are accepted, then this could be represented as a function that takes one arguments or many arguments, and in the meantime single-argument calls to the function could use my_func((arg)).

Edit: I think @sgrif first mentioned this concern here.

@eddyb

This comment has been minimized.

Show comment
Hide comment
@eddyb

eddyb Jun 6, 2017

Member

It makes more sense IMO to go straight to variadic functions & methods than have multiple arguments manually packaged in tuples.

Member

eddyb commented Jun 6, 2017

It makes more sense IMO to go straight to variadic functions & methods than have multiple arguments manually packaged in tuples.

@cramertj

This comment has been minimized.

Show comment
Hide comment
@cramertj

cramertj Jun 6, 2017

Member

@eddyb Yes, I've been gradually drifting towards preferring an "all at once" approach myself. My initial goal was to keep this RFC as minimal as possible in the hopes that it would be merged sooner. However, in order to know what the right "first steps" are, you have to consider how they move the language towards a comprehensive solution.

Member

cramertj commented Jun 6, 2017

@eddyb Yes, I've been gradually drifting towards preferring an "all at once" approach myself. My initial goal was to keep this RFC as minimal as possible in the hopes that it would be merged sooner. However, in order to know what the right "first steps" are, you have to consider how they move the language towards a comprehensive solution.

@aturon

This comment has been minimized.

Show comment
Hide comment
@aturon

aturon Sep 6, 2017

Member

We're clearly not going to get to this before the impl period, so I propose we formally postpone it and start a fresh thread when we're ready to consider it.

@rfcbot fcp postpone

Member

aturon commented Sep 6, 2017

We're clearly not going to get to this before the impl period, so I propose we formally postpone it and start a fresh thread when we're ready to consider it.

@rfcbot fcp postpone

@rfcbot

This comment has been minimized.

Show comment
Hide comment
@rfcbot

rfcbot Sep 6, 2017

Team member @aturon 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.

rfcbot commented Sep 6, 2017

Team member @aturon 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.

@cramertj

This comment has been minimized.

Show comment
Hide comment
@cramertj

cramertj Sep 6, 2017

Member

Alas, what symmetry that my first ever ticked checkbox as a lang team member should be to postpone my first ever RFC. 😄

I'm excited to work more on this next year after we've had a chance to implement the host of wonderful RFCs currently in the queue.

Member

cramertj commented Sep 6, 2017

Alas, what symmetry that my first ever ticked checkbox as a lang team member should be to postpone my first ever RFC. 😄

I'm excited to work more on this next year after we've had a chance to implement the host of wonderful RFCs currently in the queue.

@rfcbot

This comment has been minimized.

Show comment
Hide comment
@rfcbot

rfcbot Sep 19, 2017

🔔 This is now entering its final comment period, as per the review above. 🔔

rfcbot commented Sep 19, 2017

🔔 This is now entering its final comment period, as per the review above. 🔔

1 similar comment
@rfcbot

This comment has been minimized.

Show comment
Hide comment
@rfcbot

rfcbot Sep 19, 2017

🔔 This is now entering its final comment period, as per the review above. 🔔

rfcbot commented Sep 19, 2017

🔔 This is now entering its final comment period, as per the review above. 🔔

@aturon

This comment has been minimized.

Show comment
Hide comment
@aturon

aturon Sep 29, 2017

Member

I'm now closing this RFC as postponed. Thanks, @cramertj and everyone else for pushing further on this issue -- something we'll definitely want to come back to in the future!

Member

aturon commented Sep 29, 2017

I'm now closing this RFC as postponed. Thanks, @cramertj and everyone else for pushing further on this issue -- something we'll definitely want to come back to in the future!

@aturon aturon closed this Sep 29, 2017

sstangl added a commit to sstangl/openpowerlifting that referenced this pull request Oct 5, 2017

Successfully infers the SQLite3 schema.
Unfortunately, we have 28 columns, which requires Diesel's "huge-tables"
support. This dramatically increases compile time of the Diesel
dependency to ~3-4 minutes, up from negligible.

Diesel's team says it's tracked by:
  - diesel-rs/diesel#747
  - rust-lang/rfcs#1921
  - rust-lang/rfcs#1935
@alexreg

This comment has been minimized.

Show comment
Hide comment
@alexreg

alexreg May 5, 2018

Has there been any interest in reviving this lately?

alexreg commented May 5, 2018

Has there been any interest in reviving this lately?

@scottmcm

This comment has been minimized.

Show comment
Hide comment
@scottmcm

scottmcm May 6, 2018

Member

@alexreg There's still general interest in the feature, but it's not the kind of change that's targeted for the roadmap this year, so there's probably nothing going on with it right now. (Doing it and const generics could be an interesting thing to consider for next year's roadmap, once we're past the stabilize year.)

Member

scottmcm commented May 6, 2018

@alexreg There's still general interest in the feature, but it's not the kind of change that's targeted for the roadmap this year, so there's probably nothing going on with it right now. (Doing it and const generics could be an interesting thing to consider for next year's roadmap, once we're past the stabilize year.)

@alexreg

This comment has been minimized.

Show comment
Hide comment
@alexreg

alexreg May 6, 2018

@scottmcm Fair enough. w.r.t. Const generics, I thought they were targeted for this year?

alexreg commented May 6, 2018

@scottmcm Fair enough. w.r.t. Const generics, I thought they were targeted for this year?

@est31

This comment has been minimized.

Show comment
Hide comment
@est31

est31 May 6, 2018

Contributor

@alexreg const generics has an RFC merged but implementing it is no official priority of the compiler team. All of the statements were of the form "maybe we can have const generics in nightly by end of 2018"...

Contributor

est31 commented May 6, 2018

@alexreg const generics has an RFC merged but implementing it is no official priority of the compiler team. All of the statements were of the form "maybe we can have const generics in nightly by end of 2018"...

@mbrubeck mbrubeck added the postponed label Sep 21, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment