Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.
Sign upInfer function signatures from trait declaration into 'impl's #2063
Conversation
and others
added some commits
Jul 1, 2014
This comment has been minimized.
This comment has been minimized.
|
I'm not sure what's going on with this PR since it appears to delete the RFC template and add a second rather detailed RFC unrelated to the PR's title, but I assume this was only meant to include the "infer function signatures from trait declaration into impls" file so I'm only responding to that. Overall, I think I like the idea but I'm not sure how far I'd want to go with it. Omitting the return type feels iffy to me since it's easy to mistake that for a function that returns nothing, whereas an omitted argument type is obviously not an argument of type I'm also not sure if I'd want these types to be omitted when the impl and the trait are in separate files/modules, though that's probably a matter of style rather than something the compiler should enforce. This does seem like rules out ever supporting overloaded functions. I don't know if overloading ever has a chance of happening, and I'm not sure that I want it to happen, but I think we should clearly decide that it's never going to happen before adopting something like this. That probably should get discussed in the Alternatives or Unresolved Questions sections. I think the "implied bounds" idea tackles an even more unnecessary source of verbosity in exactly this sort of code, makes sense for a lot of the same reasons, and doesn't have some of the drawbacks I just mentioned, so my gut feeling is implied bounds ought to come before this. Though we don't appear to have an RFC for that yet. |
This comment has been minimized.
This comment has been minimized.
If I may be pedantic, the desugaring has to be semantic because of generic parameters in the There's also the possibility of inferring associated types from the signatures of methods, but that would still not be inferring from the body of a method ("global inference"). Both approaches would ideally use the inference engine internally for maximal flexibility, but the scope of the inference would be very small. We use inference to check that an Either way, the implementation in the compiler should be straight-forward and self-contained. |
This comment has been minimized.
This comment has been minimized.
|
Another thing to mention here:- Theoretically I definitely prefer rusts idea of putting the type afterward (and the 'type syntax' is so much cleaner), but the 20-year habit of C/C++ is buried too deep. The point I'm making is this idea would smooth things out for me by more than you might guess from the simple 'screen space saving'/'character saving' alone |
dobkeratops
added some commits
Jul 29, 2017
This comment has been minimized.
This comment has been minimized.
|
@dobkeratops could you consider signing off to the MIT/Apache 2.0 licensing terms inside this issue: #2096 ? Thanks! |
This comment has been minimized.
This comment has been minimized.
anowell
commented
Aug 30, 2017
|
As an example usage, I recently had a trait that defined 18 functions (each generating templates for a generic provider). Here's a small snippet from one of the implementations: fn frontend_app_conf<'a>(
plan: &'a Plan<Self::Plan>,
tfstate: &'a TfState<Self::Tf>,
secrets: &'a ConfigSecrets
) -> Box<Template + 'a> {
Box::new(frontend::aws_app_conf(plan, tfstate, secrets))
}
fn apiserver_deployment_yaml(
plan: &'a Plan<Self::Plan>,
confs: &'a [&'a ::stages::AppConf]
) -> Box<Template + 'a> {
Box::new(apiserver::aws_deployment_yaml(plan, confs))
}The fact that all those types were fully defined in the trait definition made it feel particularly verbose to rewrite them 18 times per provider, so I finally caved and wrote a macro: macro_rules! magic_types {
// These are the valid keywords
(plan) => { &'a Plan<Self::Plan> };
(tfstate) => { &'a TfState<Self::Tf> };
(secrets) => { &'a ConfigSecrets };
(confs) => { &'a [&'a ::stages::AppConf] };
// This is the meat of the macro
($(fn $src:ident($($arg:ident),*) $body:block)*) => {
$(
#[allow(unused_variables)]
fn $src<'a>( $($arg: magic_types!($arg)),* ) -> Box<Template + 'a> $body
)*
};
}just so I could write this instead: magic_types! {
fn frontend_app_conf(plan, tfstate, secrets) {
Box::new(frontend::aws_app_conf(plan, tfstate, secrets))
}
fn apiserver_deployment_yaml(plan, confs) {
Box::new(apiserver::aws_deployment_yaml(plan, confs))
}
// 16 other similar functions
}In general, I love that all functions/methods are explicitly typed, exactly for the readability argument discussed. This was a case where I found the types and lifetimes started getting in my way of reading the implementations. Maybe this is rare enough that macros like mine, or maybe a slighly more generalized solution are sufficient; I just thought I'd weigh in with an example where the intent of this RFC appealed to me. |
This comment has been minimized.
This comment has been minimized.
shanavas786
commented
Aug 30, 2017
|
I feel this RFC will reduce readability as one need to peek into trait definition to get type info. |
This comment has been minimized.
This comment has been minimized.
but the user would look at the trait definition first and foremost, similarly a trait implementor would always have to refer to the trait. Similarly people might be reading docs where these things can be filled out/hyperlinked. I would equally argue the 'rust-language-server' would assist with navigating back to the trait declaration, but the declaration is already very easy to find in rust with grep |
This comment has been minimized.
This comment has been minimized.
repax
commented
Sep 3, 2017
The RLS can also provide type info when you're hovering an argument/variable. I'm not yet sure how I feel about this RFC. Perhaps some hands-on experience would be a good way to find out. How about conducting an experiment? |
This comment has been minimized.
This comment has been minimized.
(I will note, however, that Haskell in general permits much more type elision than Rust, so it's hard to know how this would carry over.)
So, the RFC as written needs a lot of work, and there's very limited time to reach any full consensus prior to the impl period, but I wonder whether we should consider accepting provisinally as an experimental RFC, i.e. that we'd allow a feature like this to land in nightly to see how it feels, but would require a full RFC before any stabilization. cc @rust-lang/lang, do we think there's enough potential here to open the door to experimentation? I admit that when I first saw this RFC, my kneejerk reaction was to say "no way", but @petrochenkov's point about prototyping in particular caught my attention. |
aturon
added
the
I-nominated
label
Sep 6, 2017
This comment has been minimized.
This comment has been minimized.
|
@aturon thanks for the feedback.. am I reading this right, that there's a chance this could be tried out in 'nightly' (disabled by default), just not available in the stable compiler? If so that would be awesome. |
This comment has been minimized.
This comment has been minimized.
|
@dobkeratops Yep, that's exactly what I'm proposing. This would let us get a feel for the idea before writing up and approving a complete RFC. |
This comment has been minimized.
This comment has been minimized.
|
I personally would not be opposed to an Experimental RFC here. I've not read the details of this RFC in particular, but I have certainly felt the desire to write "tighter" impls from time to time, that don't repeat information from the trait. |
dobkeratops
added some commits
Sep 6, 2017
aturon
removed
the
I-nominated
label
Sep 7, 2017
This comment has been minimized.
This comment has been minimized.
|
The lang team discussed this RFC in today's meeting, and it quickly became clear that there is not even consensus that there is a problem here to be solved, nor on the best approach to tackle it. For example, it was pointed out that IDEs should be able to auto-generate Others felt that it was worth addressing this issue within Rust itself, but there was a lot of uncertainty over what should be required (e.g. for return types and where clauses), as well as what the best practices should be. In general, while the team remains open to experimentation here, the general feeling was that there's going to be so much else going on in the compiler during the impl period, and we're uncertain enough of the motivation here (as well as the RFC text), that it's best not to take it as an experiment right now. We'd welcome a more formal eRFC after the impl period, though. Thanks, @dobkeratops, for initiating this discussion! @rfcbot fcp postpone |
rfcbot
added
the
proposed-final-comment-period
label
Sep 7, 2017
This comment has been minimized.
This comment has been minimized.
rfcbot
commented
Sep 7, 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. |
This comment has been minimized.
This comment has been minimized.
|
I think the case for this RFC is very similar to the "Implied bounds" RFC in the way it deals with redundant information. I don't think the argument @aturon mentions regarding IDE's holds up... one could make the case that the IDE should auto-generate the implied bounds (sure, it might be a bit more tricky for the IDE, but still doable). For the sake of consistency, I voice my support to merge the "idea" behind this RFC. |
rfcbot
added
final-comment-period
and removed
proposed-final-comment-period
labels
Sep 18, 2017
This comment has been minimized.
This comment has been minimized.
rfcbot
commented
Sep 18, 2017
|
|
1 similar comment
This comment has been minimized.
This comment has been minimized.
rfcbot
commented
Sep 18, 2017
|
|
This comment has been minimized.
This comment has been minimized.
|
yes regarding IDE assistance, rather than have the IDE copy/paste, other features like hover showing full types might be more useful.. (e.g you'll want that to show types of locals aswell) Many IDEs have a a top-bar that shows the prototype of the current function (useful when scrolling into the function body) - perhaps it could show the full prototype there Given traits sometimes have defaults impls - you might not always be implementing every function - the ability to show the 'current trait' in some side panel or popup might be useful (think how class-based IDEs have 'class-explorers', you could have a 'trait-view', which can show everything, with superior formatting. (see other ideas, intellij-rust/intellij-rust#1545) |
This comment has been minimized.
This comment has been minimized.
rfcbot
commented
Sep 28, 2017
|
The final comment period is now complete. |
This comment has been minimized.
This comment has been minimized.
|
Closing as postponed. Thanks @dobkeratops -- this is something we should consider revisiting on an experimental basis in the future. |
dobkeratops commentedJul 13, 2017
•
edited
RFC: suggestion to allow ommitting type information in function signatures in 'trait impls', i.e. just take this information directly from the trait declaration (see behaviour in haskell for reference)
https://github.com/dobkeratops/rfcs/blob/infer-function-signatures-from-trait-declaration-into-'impl's/text/infer%20function%20signatures%20from%20trait%20declaration%20into%20impls.md