diff --git a/0000-ufcs.md b/0000-ufcs.md new file mode 100644 index 00000000000..91d72a52a97 --- /dev/null +++ b/0000-ufcs.md @@ -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 { 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(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).