Universal Function Call Syntax - The Rust Programming Language

# Universal Function Call Syntax

Sometimes, functions can have the same names. Consider this code:

    # #![allow(unused_variables)]
    #fn main() {
    trait Foo {
        fn f(&self);
    }

    trait Bar {
        fn f(&self);
    }

    struct Baz;

    impl Foo for Baz {
        fn f(&self) { println!("Baz’s impl of Foo"); }
    }

    impl Bar for Baz {
        fn f(&self) { println!("Baz’s impl of Bar"); }
    }

    let b = Baz;
    #}

If we were to try to call `b.f()`, we’d get an error:

    error: multiple applicable methods in scope [E0034]
    b.f();
      ^~~
    note: candidate #1 is defined in an impl of the trait `main::Foo` for the type
    `main::Baz`
        fn f(&self) { println!("Baz’s impl of Foo"); }
        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    note: candidate #2 is defined in an impl of the trait `main::Bar` for the type
    `main::Baz`
        fn f(&self) { println!("Baz’s impl of Bar"); }
        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

We need a way to disambiguate which method we need. This feature is called ‘universal function call syntax’, and it looks like this:

    # #![allow(unused_variables)]
    #fn main() {
    # trait Foo {
    #     fn f(&self);
    # }
    # trait Bar {
    #     fn f(&self);
    # }
    # struct Baz;
    # impl Foo for Baz {
    #     fn f(&self) { println!("Baz’s impl of Foo"); }
    # }
    # impl Bar for Baz {
    #     fn f(&self) { println!("Baz’s impl of Bar"); }
    # }
    # let b = Baz;
    Foo::f(&b);
    Bar::f(&b);
    #}

Let’s break it down.

    Foo::
    Bar::

These halves of the invocation are the types of the two traits: `Foo` and `Bar`. This is what ends up actually doing the disambiguation between the two: Rust calls the one from the trait name you use.

    f(&b)

When we call a method like `b.f()` using method syntax, Rust will automatically borrow `b` if `f()` takes `&self`. In this case, Rust will not, and so we need to pass an explicit `&b`.

# Angle-bracket Form

The form of UFCS we just talked about:

    Trait::method(args);

Is a short-hand. There’s an expanded form of this that’s needed in some situations:

    <Type as Trait>::method(args);

The `<>::` syntax is a means of providing a type hint. The type goes inside the `<>`s. In this case, the type is `Type as Trait`, indicating that we want `Trait`’s version of `method` to be called here. The `as Trait` part is optional if it’s not ambiguous. Same with the angle brackets, hence the shorter form.

Here’s an example of using the longer form.

    trait Foo {
        fn foo() -> i32;
    }

    struct Bar;

    impl Bar {
        fn foo() -> i32 {
            20
        }
    }

    impl Foo for Bar {
        fn foo() -> i32 {
            10
        }
    }

    fn main() {
        assert_eq!(10, <Bar as Foo>::foo());
        assert_eq!(20, Bar::foo());
    }

Using the angle bracket syntax lets you call the trait method instead of the inherent one.