Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the best way to refer to a static method from another static method of the same class in Rust?

In a new Rust module, I can write:

struct myStruct {
    x : u32
}

impl myStruct {
    fn new() -> myStruct{
        myStruct{ x : other()}
    }

    fn other() -> u32 {
        6
    }
}

Coming from other OO languages, I would expect other() to be in scope for new(). That is, I would expect to be able to call one static method of a class from another static method of the same class. However, rustc produces the message:

error[E0425]: cannot find function `other` in this scope
 --> dummy_module.rs:9:23
  |
9 |         myStruct{ x : other()}
  |                       ^^^^^ not found in this scope

In contrast, the following Java code compiles fine:

public class myStruct{
    int x;

    public myStruct(){
        x = other();
    }

    private int other(){
        return 5;
    }
}

I don't recall seeing any mention of this in the Rust book I'm using, and I can't seem to find a clear answer online. I can fix it by explicitly scoping the call to other with myStruct::other(), but this seems cumbersome. If I try use myStruct, then I get the cryptic message

7 |     use myStruct;
  |     ^^^ unexpected token

Is this explicit scoping always required? If so, why?

Am I doing something incorrect? Is there an idiomatic workaround to this?

like image 373
John Doucette Avatar asked Sep 03 '18 15:09

John Doucette


1 Answers

The Rust designers have made the following choice: everything related to the scope is explicit. So, just as you must type self to call a member function from another member function: self.foo(), you must call a static member with Self: Self::bar().

I think that it is the case because self could not be implicit: indeed it had to be added as a parameter either by value or borrowed, unlike in Java where this is always taken by value. Thus, because self was already an explicit parameter, it was needed as an explicit caller for consistency.

Because of its memory model, Rust expliciteness permit to give better error messages. For example, consider this code:

struct Struct;

impl Struct {
    fn foo(&mut self) {
        self.consume();
    }

    fn consume(self) {}
}

The error message is:

error[E0507]: cannot move out of borrowed content
 --> src/main.rs:5:9
  |
5 |         self.consume();
  |         ^^^^ cannot move out of borrowed content

Then the team made the choice of full expliciteness to maintain the grammar coherent.

like image 169
Boiethios Avatar answered Jan 23 '23 00:01

Boiethios