[rust-dev] RFC: Method call syntax as sugar

Patrick Walton pwalton at mozilla.com
Sun Dec 9 22:20:37 PST 2012


Hi everyone,

This has been proposed in some form several times by different people, 
and I think we could possibly make it work now. It would be a 
low-priority, backwards-compatible change that would make the language 
somewhat simpler.

Today, there is the distinction between static methods (invokable as 
functions, but not using dot notation) and non-static methods (invokable 
using dot notation, but not as functions). This proposal would unify the 
two.

Briefly, suppose that we have a method call like:

     a.foo(b, ...)

Assuming `a` does not have object type, this would be equivalent to this:

     NAMESPACE::foo(OPERATION(a), b...)

Where `NAMESPACE` is one of:

1. The anonymous trait associated with the type of `a`, if `a` is an 
enum or struct (or coercible to one, or a pointer to one) and has an 
anonymous trait defined for it. (Note on terminology: the "anonymous 
trait" is the new name for a "trait-less impl" or "an inherent 
implementation".)

2. The traits in scope at the call site.

And `OPERATION` is one of:

1. One or more dereference operations (`*a`).

2. An address-of operation (`&a`, `&const a`, `&mut a`).

3. A coercion from `~[T]` or `@[T]` to `&[T]` (or the mutable variants 
to the corresponding mutable slice) followed by an address-of operation. 
(This is probably the ugliest rule here, but it seems necessary to allow 
`for [ 1, 2, 3 ].each |x| { ... }` to work.)

So, in our example above, if `a` had type `T`, we might transform 
`a.foo(b)` to `T::foo(&a, b)`.

The other change that needs to happen is that what we've been calling 
"explicit self" needs to become syntactic sugar for an explicit first 
argument. For instance:

     struct T { ... }

     impl T {
         fn foo(&self, b: int) { ... }
     }

Is exactly the same as:

     struct T { ... }

     impl T {
         /*static*/ fn foo(self: &T, b: int) { ... }
     }

(The keyword `static` is commented out because, while it is necessary 
today for backwards compatibility, it will not be necessary, and in fact 
will likely be removed, in the near future.)

The most immediate practical benefit of this would be that methods that 
today must be invoked with dot notation would become useful as arguments 
to higher-order functions. The other main benefit is that the language 
design becomes simpler and tidier. We no longer need to think of the 
method call as a core construct in the language (except for objects) but 
rather as a form of sugar guided by scope and type information.

Again, none of this is particularly high-priority, as I don't think 
it'll have much immediate practical impact, but I do think it's a 
simplification worth considering.

Thoughts?

Patrick


More information about the Rust-dev mailing list