Calling trait static method from another static method (rust)
Asked Answered
W

3

6

Can you call a trait static method implemented by types from another trait static method implemented in the trait? For example:

trait SqlTable {
  fn table_name() -> String;

  fn load(id: i32) -> Something {
    ...
    Self::table_name()    // <-- this is not right
    ...
  }
}

This is now working thanks to Chris and Arjan (see comments/answers below)

fn main() {
  let kiwibank = SqlTable::get_description(15,None::<Account>);
}

trait SqlTable {
    fn table_name(_: Option<Self>) -> String;

    fn get_description(id: i32, _: Option<Self>) -> String {
        println!("Fetching from {} table", SqlTable::table_name(None::<Self>) );
        String::from_str("dummy result")
    }
}

struct Account {
    id: i32,
    name: String,
}
impl SqlTable for Account {
    fn table_name(_: Option<Account>) -> String { String::from_str("account") }
}
Walburga answered 2/7, 2014 at 21:9 Comment(4)
Where there is no Self or self in the function signature, it is not callable at present. The standard workaround until UFCS comes is to take an argument _: Option<Self> and pass it None::<T>.Berlin
Thanks that workaround gets me closer and solves the call in main(). But it doesn't address the argument in println!() which cannot determine a type. Edits forthcoming above. I'm starting to think the answer to the original question is simply "no" and I need to rethink the paradigm.Walburga
table_name is still not callable as it has no connection with the Self type. But you are right—rethinking the paradigm is probably a good idea.Berlin
Hey I think I just got it working! thanks, updating above...Walburga
W
3
  • Yes, you can call a trait static method [implemented by types] from another trait static method [implemented in the trait].
  • Static methods are always called on a trait like SomeTrait::some_method().
  • Where there is no Self or self in [a trait] function signature, it is not callable at present. The standard workaround until UFCS comes is to take an argument _: Option<Self> and pass it None::<T>.

See original question for code that (as of today) compiles.

Walburga answered 3/7, 2014 at 0:32 Comment(1)
Clever workaround. By the looks of it UFCS has since been implemented, I think <Account as SqlTable>::get_description(15) would work now.Brusquerie
W
3

You have to change Self to SqlTable:

trait SqlTable {
  fn table_name() -> String;

  fn load(id: i32) -> Self {
    ...
    SqlTable::table_name()    // <-- this is not right
    ...
  }
}

Static methods are always called on a trait like SomeTrait::some_method(). Bug #6894 covers this issue.

Welles answered 2/7, 2014 at 21:21 Comment(2)
Thanks that got me closer but I still have no compilable simple example of this form.Walburga
Note that the compiler needs a way to work out what the Self type is, that is, which impl is being called (see the updated question for the work-around that's idiomatic until UFCS lands).Superscription
W
3
  • Yes, you can call a trait static method [implemented by types] from another trait static method [implemented in the trait].
  • Static methods are always called on a trait like SomeTrait::some_method().
  • Where there is no Self or self in [a trait] function signature, it is not callable at present. The standard workaround until UFCS comes is to take an argument _: Option<Self> and pass it None::<T>.

See original question for code that (as of today) compiles.

Walburga answered 3/7, 2014 at 0:32 Comment(1)
Clever workaround. By the looks of it UFCS has since been implemented, I think <Account as SqlTable>::get_description(15) would work now.Brusquerie
N
1

This works without any workarounds with current Rust (verified with 1.65.0):

trait Trait {
    fn x() -> i32 {
        1
    }
}

struct Struct {
    y: i32,
}

impl Struct {
    fn new(y: i32) -> Self {
        Self { y }
    }

    fn f(self) -> i32 {
        Self::x() + self.y
    }
}

impl Trait for Struct {}

fn main() {
    assert_eq!(Struct::new(1).f(), 2);
}
Near answered 9/12, 2022 at 16:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.