Skip to content
This repository has been archived by the owner on Jun 6, 2021. It is now read-only.

Note: Method and Field Access

Alex Rønne Petersen edited this page Jun 7, 2013 · 4 revisions

Using the . operator both for method calls and field access is ambiguous.

Let's say we have:

pub struct Foo {
    fun: fn() -> int;
}

trait SomeTrait {
    fn fun(ref this : self) -> int;
}

impl SomeTrait for Foo {
    fn fun(ref this : self) -> int {
        42;
    }
}

And suppose we do:

pub fn f() -> () {
}

let foo = new Foo { &f };
foo.fun();

We now have an ambiguity on our hands. Are we calling the method fun, part of SomeTrait, or are we calling the function pointer sitting in the fun field?

At first glance, there are three ways to solve this problem:

  • Wrap parentheses around the field access if the intention was to call the function pointer (i.e. (foo.fun)();). Not very pretty.
  • Use a cast to a trait if the intention was to call the method (i.e. (foo as SomeTrait).fun();). Not very efficient because it involves setting up a method table for the resulting first-class trait value.
  • Tell people not to write code like this. Not a very practical solution, especially considering structure fields and trait methods are two completely unrelated things. Conflicts are bound to happen.

So instead, we use the -> operator to do method calls. That means the above would either be written as:

foo.fun(); // Calls the function pointer.

Or:

foo->fun(); // Calls the trait method.

The ambiguity is eliminated, the code is clearer about what it's doing, and the semantics can now be understood by a parser without having to do semantic analysis.

Clone this wiki locally