-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
unified function call syntax #4
Closed
Closed
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
- Start Date: 2014-03-17 | ||
- RFC PR #: 4 | ||
- Rust Issue #: | ||
|
||
# Summary | ||
|
||
Universal Function Call Syntax (UFCS) and syntax for associated items. | ||
|
||
Add syntax for calling associated functions (aka static methods) where both the | ||
definition and declaration of the function can be un-ambiguously specified. | ||
|
||
Note, this does not block 1.0, but we need to ensure our plan is backwards | ||
compatible. | ||
|
||
# Motivation | ||
|
||
``` | ||
Trait T1 { fn f() -> Self; } | ||
|
||
Trait T2 { fn f() -> Self; } | ||
|
||
fn g1<X: T1 + T2>() -> X { X::f() // hypothetical ideal syntax } | ||
``` | ||
|
||
We need a way to call 'static method's (hereafter referred to as associated | ||
funtions) which can distinguish between `f()` declared in `T1` and `f()` | ||
declared in `T2`. We also need to specify the `Self` type for these methods, | ||
i.e., specify the implementation of `f()`. | ||
|
||
Our current syntax is to use `T1::f()` which allows the former but not the | ||
latter. Furthermore, it is counter-intuitive in the common case of not having a | ||
method declared in multiple traits (e.g., `X: T2`). The common example is that | ||
we would like to write `X::size_of()` | ||
|
||
# Background | ||
|
||
Issues #6894, #8888, #12330. | ||
|
||
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/ | ||
|
||
# Detailed design | ||
|
||
Wherever type variables appear in the program they may be annotated with a bound | ||
to remove ambiguity in the bound of the type variable used for typing. This is | ||
analogous to using type ascription to remove ambiguity on the type of variables | ||
which have polymorphic type. Where necessary, brackets can be used around types | ||
in paths. For example the fully specified method call in the above example would | ||
be `(X:T1)::f()` which would call `f()` defined in the implementation of `X` for | ||
`T1`. | ||
|
||
In the common case of no conflicting method definitions in traits, we would | ||
allow `X::f()`. | ||
|
||
## Extension to associated items. | ||
|
||
The syntax extends in the obvious way to associated types and values, if and | ||
when we add those. This would allow the following kinds of uses | ||
|
||
``` | ||
// n1 and n2 have the same type | ||
fn f<G: Graph>(n1: (G:Graph)::Node, n2: G::Node) { | ||
... | ||
let x = G::Node::magic_number; // associated value | ||
} | ||
``` | ||
|
||
(Note: associated types and values are not part of this RFC, but we should make | ||
(sure we don't close any doors in that direction). | ||
|
||
# Alternatives | ||
|
||
We could use `as` rather than `:`. That reads better but requires whitespace in | ||
paths (which pnkfelix objects to). It is analagous to casting, but I'm not sure | ||
if that is a nice symetry or misleading. | ||
|
||
There have been other, similar proposals. See the background section for links. | ||
|
||
# Unresolved questions | ||
|
||
Do we allow the shorthand `T1::f()` if the `Self` type can be inferred (as in | ||
the example given due to the return type). This would be required for backwards | ||
compatibility with the current syntax. | ||
|
||
Do we generalise and allow bound ascription anywhere type variables can be used | ||
(other than there declaration)? | ||
|
||
Do we generalise further and allow type ascription? (I don't think there is any | ||
motivation for doing so, other than symetry). |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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 full syntax for this is written as
(G: Graph)::Node::magic_number
, right?I'm still mildly concerned about this from a grammar perspective, especially if we ever use
:
for type ascription on expressions (because then in(x: y...
,x
can legitimately be either a type or an expression).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 think there is any particular ambiguity so long as we restrict the set of type expressions to paths. Though this is perhaps an unfortunate limitation.
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.
Even with just paths, it means that something like
(Foo<T>: Graph)
can't work (unless we useFoo::<T>
there too).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.
Right, you would write
Foo::<T>
if this appears in an expression context.