-
Notifications
You must be signed in to change notification settings - Fork 14
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
Addressing T19, and adding explicit generic type parameters to delegated methods #35
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Glad to see your PR. Thanks :)
I left a few line comments. And I have a few additional comments:
- Could you rename your test to
non_inferred_generic_types_for_all_refs
(or something like that)? The test names can be very verbose IMO. Then the trait should be implemented for other proxy types as well:#[auto_impl(Arc, Box, Rc, &, &mut)]
- Please add another test
non_inferred_generic_types_for_box
:#[auto_impl(Box)] trait Foo { fn foo<T>(); fn bar<U>(&self); fn baz<V>(&mut self); fn qux<W>(self); }
- With the test above you will notice a thing we forgot: the
self
receiver case.
If anything is unclear, please let us know. Thanks again ^_^
src/gen.rs
Outdated
@@ -430,6 +430,10 @@ fn gen_method_item( | |||
// Generate the list of argument used to call the method. | |||
let args = get_arg_list(sig.decl.inputs.iter())?; | |||
|
|||
// Determines the number of generic parameters, and what they are | |||
let type_param_count = sig.decl.generics.type_params().count(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't actually think we have to distinguish between 0 or more type parameters. Rust accepts empty parameter lists like foo::<>()
. Playground. Unless I'm missing something, I think we can drop this distinction.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I initially just tried adding it as such, but it seems that some field expressions will not accept generic types, meaning that some expansions will fail in that case. Specifically I believe #[auto_impl(Box)]
was throwing errors if we don't make this check.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, now I get it. So the problem is that an empty "type generics" from syn is an empty token stream and not <>
. This means that we generate self.method::(args)
when we don't have generics. That's incorrect syntax, hence the error.
But I found the method TypeGenerics::as_turbofish()
. This adds the double-colon if the token tree is not empty. So with that, we don't need that distinction. So what you basically need to do:
- Write
let generic_types = generic_types.as_turbofish();
in the line below thesplit_for_impl
line. - Remove the
::
from thequote!
s, like this:quote! { #proxy_ty_param::#name #generic_types(#args) }
(because if we don't have generics#generic_types
will be an empty token stream, otherwise::<T ...>
) - Then you can remove this
count()
line and thematch
-distinctions below.
src/gen.rs
Outdated
@@ -430,6 +430,10 @@ fn gen_method_item( | |||
// Generate the list of argument used to call the method. | |||
let args = get_arg_list(sig.decl.inputs.iter())?; | |||
|
|||
// Determines the number of generic parameters, and what they are | |||
let type_param_count = sig.decl.generics.type_params().count(); | |||
let (_, generic_types, _ ) = &sig.decl.generics.split_for_impl(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The space between _
and )
should be removed.
Why is there a &
before sig
? I don't think that's necessary, so we could remove it.
src/gen.rs
Outdated
match type_param_count { | ||
0 => quote! { (*self).#name(#args) }, | ||
_ => quote! { (*self).#name::#generic_types(#args) } | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was thinking about if we should maybe use the explicit form here: #proxy_ty_param::#name::#generic_types(*self, #args)
. @KodrAus any opinions about this? I think it is more explicit and it should work.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm, being consistent about always calling methods as path(args)
whether they're static or instance seems nice to me 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@saresend Could you also change this? :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, will do!
fn bar<U>(&self); | ||
fn baz<V>(&mut self); | ||
fn qux<W>(self); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you add a newline here? As a general hint: it's usually expected that all files end with a single trailing newline. You should probably configure your editor to automatically insert one. While doing that you should also configure your editor to automatically remove any trailing whitespace (whitespace at the end of a line). That's also something most people don't want in their code. Thanks! :)
@saresend Thanks for updating the PR and including another test. That lifetime test was a good idea! If you address the three line comments that are still up to date right now, I think this PR would be ready to merge :) |
Hey! A couple of things that I ran into while trying to fix the previous issues. First, would it be possible to provide a rustfmt.toml file? Unfortunately the latest commit I provided was formatted with default rustfmt, and to try to stay in line with your current formatting it would be helpful to have a formatting config specified. Also, when moving from |
Hi! Regarding rustfmt: I'm not a big fan of global automatic formatting. Rustfmt can't get everything right everywhere. While I think it's super useful in some situations (keeping import lists sorted), it's really bad in others. I'm very committed to keeping the Rust standard style, but I disagree with quite a few minor changes done by rustfmt here. Regarding the So I think your PR is feature complete, but the rustfmt formatting should be removed. If you don't mind, I would just do that. I think this cleanup is only boring work, so I can quickly do everything I would like to see. If you enabled the "allow modifications from maintainers" box, I can just push a new commit to your branch (to be included in this PR). Then I can merge it. And if you don't mind, I would squash all your commits when merging. |
Okay, update: I just created that commit and already pushed it. That way I can merge this now (otherwise async communication is too slow :P). Travis will not succeed, but this is not your fault and it will be fixed in a later PR. Thanks again for your PR :) |
Hey, thanks so much for being so helpful, I really appreciate it! |
Thanks for being patient with me! The current implementation is quite naive, but effectively what it is doing is simply computing the number of needed type params, and if there is a non-zero quantity then adds them explicitly to the output, and otherwise elides the generic type params.