Skip to content
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 support for labelling TupleStructs by index #144

Merged
merged 5 commits into from
Feb 9, 2019
Merged

Add support for labelling TupleStructs by index #144

merged 5 commits into from
Feb 9, 2019

Conversation

bossmc
Copy link
Contributor

@bossmc bossmc commented Jan 22, 2019

This is a little unusual, since it basically undoes the good that LabelledGenerics by allowing someone to transmute in a way that switches the meaning of two members of the tuple but:

  1. This allows mixing tuple structs (especially "new-type" structs) into LabelledGenerics and still transmogrify freely.
  2. Tuple structs are "named" by their indexes, there's no better naming (unlike named structs where the field labels are meaningful)
  3. LabelledGeneric is opt-in so if there's a struct that's too primitive for transmogrifying to make sense (e..g Pair<T>(T, T)) then don't opt-in.

fn build_new_labelled_tuple_struct_constr(
struct_name: &Ident,
bindnames: &Vec<Ident>,
) -> Box<dyn ToTokens> {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason why impl ToTokens doesn't work here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These return types have to unify in the match statement when they're called, and impl Trait return values cannot unify (except with themselves).

By returning a trait object, these two return types can be used interchangeably.

Copy link
Collaborator

@Centril Centril Jan 22, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, the match expression is somewhere else... OK, let's move the Box::new(...) to that place instead and write -> impl Trait here so that the reason for the dynamic dispatch is clearer and so that it is done where it is actually needed.

fn build_new_labelled_struct_constr(
struct_name: &Ident,
bindnames: &Vec<Ident>,
) -> Box<dyn ToTokens> {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

here too...?

@bossmc
Copy link
Contributor Author

bossmc commented Jan 22, 2019

Markups applied

Copy link
Owner

@lloydmeta lloydmeta left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking quite good; do you mind adding a unit test for this?

@ExpHP
Copy link
Collaborator

ExpHP commented Jan 26, 2019

Okay; supporting this makes sense from the standpoint of generic interfaces (i.e. writing a function that uses the semantics of LabelledGeneric for structs, and still supports tuple structs).


Should we similarly impl LabeledGeneric for tuples? (I think so, because they impl Generic.)


There is a question here of whether tuple structs should use underscore-prefixed names or not.

  • _0, _1, _2... have the advantage of being valid identifiers.
  • 0, 1, 2... have the advantage of being consistent with the actual field names. (usable with field-access syntax and struct literal/pattern syntax TupleStruct { 0: value })

However, the difference may be moot, because ISTM there are vanishingly few places that can make use of either of these advantages. (these differences sound like they would be useful mostly in codegen, but codegen cannot make use of type information)

@bossmc
Copy link
Contributor Author

bossmc commented Jan 29, 2019

Unit test - Yes, sure, there are no tests in the derive crate, where's the best place to test the derive code?

Field names - I'll admit I didn't think too hard about this... I went for _x since they're valid identifiers, but this does allow transmogrifying between Foo(String) and Bar { _0: String } which is a little surprising. Since it's not possible to define Bar { 0: String } the confusion disappears, but this precludes conversion from named structs to tuple structs forever...

LabelledGeneric for Tuples? Seems reasonable, does that block this PR?

@ExpHP
Copy link
Collaborator

ExpHP commented Jan 29, 2019 via email

@lloydmeta
Copy link
Owner

Unit test - Yes, sure, there are no tests in the derive crate, where's the best place to test the derive code?
..
I think tests for derives are in frunk/tests as integration tests (you can't unit test a proc macro from within it's own crate)

Sorry yeah, I meant integration tests under /tests and/or doc tests ( I think they work in there for some reason ?). https://docs.rs/frunk/0.2.2/frunk/

this does allow transmogrifying between Foo(String) and Bar { _0: String } which is a little surprising. Since it's not possible to define Bar { 0: String } the confusion disappears, but this precludes conversion from named structs to tuple structs forever...

Good point; that is a bit surprising and yet .. precluding conversion from named structs to tuple structs might not be desirable? One could make the argument that if someone is naming their field _$someNumber that they might be doing it on purpose to allow conversion?

@ExpHP
Copy link
Collaborator

ExpHP commented Jan 30, 2019

Okay, it's hard to predict which is the better choice. Since nobody seems to have a strong opinion the current implementation is probably fine for now.


Re: tuple impl, I don't think we need to block on it. I do think it should be added before the next release though.

@ExpHP
Copy link
Collaborator

ExpHP commented Jan 30, 2019

Oh: add a note to the release notes under "Unreleased"

@ExpHP ExpHP added this to the 0.2.3 milestone Jan 30, 2019
@bossmc
Copy link
Contributor Author

bossmc commented Feb 4, 2019

I've added a couple of UTs (one for the use case I care about, that of new-type wrappers being interchangeable if the inner type is the same), and added an entry to the changelog.

Copy link
Owner

@lloydmeta lloydmeta left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

As with #142 , @ExpHP @Centril if you'd like to review this before merging, just shout :), else I'm thinking we merge this sometime this week and push out a release this weekend :)

@lloydmeta lloydmeta merged commit 80683de into lloydmeta:master Feb 9, 2019
@lloydmeta
Copy link
Owner

Released as 0.2.4 thanks for the great work 😄

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants