-
Notifications
You must be signed in to change notification settings - Fork 12.9k
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
Rework generic paths for associated functions: T::function() #6894
Comments
See also: #5635 |
Something that needs consideration would be how to handle more complex types. Assuming there was a |
@nikomatsakis Ah, I didn't realize it was another case of the |
I have been wanting to work on this, but it may be too big a task for me to take on immediately. If I decide that I can indeed tackle it, I will assign this issue to myself. |
@pnkfelix Unfortunately I was having a little trouble following your blog post as the issue is pretty involved (that's no slight against it though). Unfortunately I come from a position of ignorance, without a full understanding of the moving pieces involved. Which approach do you favour? Personally, from an ignorant user perspective, I think something like At least we can agree that the current way of doing things must be improved (eg. #6898). |
@pnkfelix for reference, here is the log of our discussion: https://botbot.me/mozilla/rust/msg/3557231/ |
@bjz I didn't meant to give the impression it can't be done... just that there are situations that syntax can't express, and other considerations as well. I tried to explain those considerations as well as I could in these blog posts http://www.smallcultfollowing.com/babysteps/blog/2013/04/02/associated-items/ |
@bjz The context of the IRC log doesn't tell me how deeply you all got into this, so forgive me if I cover ground you've already covered. Also, I'm working mostly from memory here, and I may well get some of the details wrong. Syntax like So that's why my proposal factors out A goal I was trying to achieve in my proposal was "minimize changes to the core of the syntax, and hopefully the compiler too." My usual justification for that sort of goal when it comes to adding features like this goes something like "Longer term, after we gather experience with an implementation that can express these general associated items (even if it requires some local syntactic gymnastics), we'll be in a better place to evaluate more expressive options." But a problem with the above justification is that if the syntax is poorly chosen now, then that may adversely affect the body of code that uses associated items that would be used as the basis for coming up with a better syntax. Because of this problem, I plan to consider any reasonable suggestions for alternative syntax that are offered up. For example, if you can present an argument for why tree-structured path syntax will pay for itself, or is inevitable, then maybe that would help us reconsider whether More concretely: You may need to even incorporate issues like how the macro-expander works. I do not know off-hand whether our term-rewriting macro_rules! can deconstruct and/or introduce new paths, or if paths are treated as atomic entities in that context. But either way, a change to the path syntax will affect either the definition of such macros or how one uses them. |
This may have been an over-statement on my part. (There may be a way to generalize the path syntax to allow tree structure that does not break old macro definitions.) But I am not certain either way, and in any case I think there would be push-back to putting tree structure into paths. |
@pnkfelix Thanks for the responses! Could you re-explain what you mean by 'tree structure in paths'? And why is this considered undesirable? |
I guess one of the other issues I have with the current way of accessing associated functions via the trait is the asymmetry with method calls. That is, |
@pnkfelix Sorry for the multi-posting, but I just had a thought. If we go with what @pcwalton initially described on the mailing list and my original issue description, what would the difference be between: use impl OwnedOptFloat = SizeOf for ~Option<float>;
...
OwnedOptFloat::size_of(); ...and: type OwnedOptFloat = ~Option<float>;
...
OwnedOptFloat::size_of(); ...other than the specification of the specific trait? Also, why would you have to specify the specific trait impl when you don't have to do that for methods? |
|
From IRC:
But why the asymmetry with method calls? If folks are capable of dealing with this for with methods, why not for associated items as well? Why aren't we pushing for |
@bjz paths right now are sequences of identifiers: An expression tree has richer structure. Instead of looking like a linear sequence, there is instead some amount of recursive nesting: The path has type expressions inside of it, which in turn can have more paths inside of them, etc. Right now, the grammar for Rust keeps paths segregated from the grammar for types as well as other expressions; I am trying to maintain that segregation, if only to keep the amount of change to the language low. |
@bjz The specification of the specific trait is the difference between the two options you presented. It makes the method selection unambiguous, regardless of what other traits are implemented by |
Just curious, why aren't we using the
I just worry about things like this: |
@bjz I don't have an immediate response to your point about the asymmetry with method calls, apart from: "I am more concerned about ensuring that new features I introduce do not have expressiveness bugs." I'll think more on the asymmetry question. |
@pnkfelix Definitely, that is a very valid concern. I would hate to be the one responsible for pushing something that we'd later regret (and be cursed for years to come). |
@bjz Regarding your Otherwise, I was planning to live with putting in the |
@pcwalton reread the blog post. I agree that |
@pnkfelix one thing that has been bugging me about this is that I believe that these named "type+trait" pairs must inhabit the same namespace as types, so having |
To clarify, are you saying that Re-reading the Associated Items Continued post, I'm pretty sure the OO-syntax pretty much what I am proposing. Again, that approach has it's drawbacks, but it seems to be relegated to the library/api author. And as a library/api author, I know that we're more than happy to jump through hoops to craft a beautiful interface for our users. |
@nikomatsakis Back when I wrote the proposal, I thought the two would be in different namespaces (and thus they do not shadow, but rather co-exist naturally). In particular, my thinking was that the namespace for the leading components of a path would be distinct from the namespace for a final component of a path. Reflecting on that now, I guess the two namespaces would not be disjoint (since I think the names of modules would need to be in both places). But maybe that is not workable. I will need to review. |
@nikomatsakis A question, and a response to a long-standing point you made.
sounds fine to me, as long as (1.) we're okay with the outcome that adding a new associated item to a trait could force other client code to become invalidated, and (2.) no one complains if I write code that uses the explicit names "unnecessarily" in the presence of such a rule. :) |
@pnkfelix I don't see why there'd be any soundness issues to allowing the name to be used in place of a type, it'd just be a ... complication. It seems to me like the name for the type+trait pair would effectively be an alias for the type in a context where the trait wasn't needed? |
@nikomatsakis right. I just see it as an attempt to make sensible the rewriting: |
@pnkfelix Yes, I see the motivation. I am somewhat indifferent though making the default more special, in that it searches all the bounds, seems potentially nicer in practice, since it means that |
benh on IRC:
Just a thought. I like it. That said, we don't want to make things complex just to please a potential minority (me?), and end up making life difficult in the long run for everyone. |
Just one note: I don't mind the combination of approaches outlined by benh (as quoted by bjz), that combination still overlooks one important use case: I (and perhaps we) want to be able to introduce the That is, we want to be able to define a polymorphic function I had to go review the blog post to remind myself why the proposed combination would not be 100% satisfactory to me, so I thought a reminder here would be justified. Having said that, I do not object to adding the features proposed in benh/bjz's note. And the |
Tagging RFC. |
Nominating for backwards compat. |
I'm not sure that we should do this for type aliases ( |
@alexcrichton In the long term, if we support |
If the implementation "Just works" such that type aliases work, then I'm all for it! I certainly don't want to explicitly forbid them if they happen to work. |
Accepted for P-high. |
cc me |
This issue has been moved to the RFCs repo: rust-lang/rfcs#288 |
This issue formalizes @pcwalton's RFC on the mailing list. This was also discussed in the 2013-05-14 meeting and in #6087. Steps towards this have already been made in #6462.
Whilst this is not a high priority change at the moment (understandably there are far bigger fish to fry), this is a semi-common question on the IRC and I think it's good if we have some place to redirect questions to.
Instead of the current:
this change would allow you to do:
or
This could also allow for neat things like a generic
SizeOf
trait:T::size_of()
, which is far nicer than the currentsize_of::<T>()
. Or maybe there could be anInit
trait for default initializers:T::init()
.The text was updated successfully, but these errors were encountered: