-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
[RFC] Proposal for infix .
associated/'static' method syntax
#12358
Comments
General point: |
Under this proposal, these would be (in full form) |
The latter one was calling a normal method. struct Foo;
struct g;
impl Foo { fn T<A>(&self); {} }
fn main() {
let f = Foo;
f.T::<g>();
} i.e. things with extremely unconventional names. (I only brought it up because I thought the similarity is worth some consideration, I think it will be rare for it to be a point of confusion in practice. In any case, this proposal seems reasonable to me.) |
Is |
for some reason the way I"m reading this makes me think of the "path dependent types" in scala. Is that resemblance accidental / deliberate / me being tired and way too caffeinated? |
@nick29581 yes, |
@cartazio Kinda similar - Scala's path dependent types are virtual types and are what you get if you allow associated types to interact with inheritance in fun ways. I'm not proposing that here, but there is a similarity and when we think seriously about full associated items we will need to consider a lot of the issues Scala faced. |
@huonw I see, thanks. I will ponder how that fits in with this proposal. At first blush, I think there is no ambiguity. More generally, I'm OK with virtual method calls and static method calls looking similar because they are similar. I hope the case conventions are enough to avoid confusion when reading. Not sure how others feel about that. |
ok. Well my 2 cents is "evade emulating scala, pleaseeeeee". scala has a lot of unanticipated complexity in its types. |
Note that types and values are in different namespaces so @cartazio This is not related to path dependent types, it's just a very explicit syntax for the same stuff that's in Haskell 98. |
On first blush, I like the idea. My initial concerns are that the more verbose But I do prefer my paths to be free of space characters, which thìs offers. (I continue to believe there may be value in a shorthand for naming the impl (I.e. type/trait pair), e.g. if one is dealing with a long trait name. But that is an exceptional case for now.) |
I prefer the |
(updated title to "Proposal for infix |
@pcwalton ok cool, i'll stare at this more and try to understand it properly |
ok, I think i like this. Would this also allow sort of associated data families (eventually?) eg If I wanted to write a Struct of Arrays trait that have an array data type parameterized by the element typed, would i be able to express that (eventually) with this proposal? |
I'm not quite sure what you are proposing, but I think so. However, it would depend on how the eventual discussion on associated types pans out. |
reasonable, i'm not sure how it'd translate to rust, but I'm thinking something that would make something analogous to the Struct of Arrays format supported by haskell would be nice eg see http://hackage.haskell.org/package/vector-0.10.9.1/docs/Data-Vector-Unboxed-Mutable.html and the associated source http://hackage.haskell.org/package/vector-0.10.9.1/docs/src/Data-Vector-Unboxed-Base.html#Unbox and https://github.com/haskell/vector/blob/master/internal/unbox-tuple-instances |
Will change to |
#12390 was updated to path syntax |
I echo @pcwalton's concern about the namespaces. |
This is superseded by the UFCS RFC (rust-lang/rfcs#4) |
minor: Simplify syntax-highlighting macro checks
The following code used to trigger the lint: ```rs macro_rules! make_closure { () => { (|| {}) }; } make_closure!()(); ``` The lint would suggest to replace `make_closure!()()` with `make_closure!()`, which changes the code and removes the call to the closure from the macro. This commit fixes that. Fixes rust-lang#12358
[`redundant_closure_call`]: Don't lint if closure origins from a macro The following code used to trigger the lint: ```rs macro_rules! make_closure { () => { (|| {}) }; } make_closure!()(); ``` The lint would suggest to replace `make_closure!()()` with `make_closure!()`, which changes the code and removes the call to the closure from the macro. This commit fixes that. Fixes rust-lang#12358 ---- changelog: [`redundant_closure_call`]: If `x!()` returns a closure, don't suggest replacing `x!()()` with `x!()`
Background
Issues #6894 and #8888.
pnkfelix's blog post: http://blog.pnkfx.org/blog/2013/04/22/designing-syntax-for-associated-items-in-rust/
nmatsakis's blog posts: http://www.smallcultfollowing.com/babysteps/blog/2013/04/02/associated-items/ and http://www.smallcultfollowing.com/babysteps/blog/2013/04/03/associated-items-continued/
Proposal
Use dot syntax for associated items. We use a type before the dot to define which implementation to call and a path to a function (via traits) after the dot to define the fully qualified name of the method. E.g.,
Rationale
Use :: paths to indicate the name of an item only, i.e., the fully qualified name.
Use . paths to specify the implementation of the item called.
This intuition applies equally to regular methods and 'static' methods.
Syntax
(Just looking at methods for now)
regular methods:
Note that we're using the dynamic type of e, whereas for static methods we use the static type.
static methods:
where:
Shorthands
If a name is un-ambiguous, it does not need qualification (this gives backwards compatability for non-static methods). This also gives a nice syntax for the common use case - the
T::size_of()
example is common, which here would beT.size_of()
E.g.,If the implementing type is unambiguous (e.g., from the return type) then the target is optional (this gives backwards compatability with static methods). E.g,
By applying both shorthands, the following is allowed, which I don't like - it seems too magical. But I think it is not, so I could live with it.
(Personally, I do not like inference relying on the return type so would be happy to see it go and thus avoid the 'magical' example. But that would break backwards compatibility and it is just a personal preference, let's ignore this possibility for now).
Generalising to associated items
(note: this section is post-1.0 stuff)
If traits can declare types, etc. as well as just methods we should be able to refer to them in same way, e.g.,
Note that this needs a lot more thinking about wrt semantics and especially inheritance (see literature on virtual types, virtual classes).
Issues
Accessing functions from struct impls not in traits - I don't think this is an issue since you wouldn't use a struct as a bound on a type parameter.
grep-ability - not great because of the shorthands you can not grep to find all uses. But that is the price of shorthands. A semantic tool like DXR would still find everything.
Do we allow
.
in types? I can't think of a use. If so (perhaps associated types using this proposed syntax is an example) we would require wrapping the type in parentheses or something.Hat-tips
bjz for the idea of using .
nmatsakis/pcwalton for the
T::<for X>::f()
syntax of which this is a variation.pnkfelix/nmatsakis for the explanations
The text was updated successfully, but these errors were encountered: