Is it possible to add type of constant values in struct?

I wanna make a function that only takes const values that are defined in the Container impl block. Is it possible to do that?
The reason why I wanna do it is that Rust doesn't support __call__ like Python if I understand Rust correctly.

struct Container;

impl Container {
    const CON_A: &static str = "a";
    const CON_B: &static str = "b";
  
    // this function just want to take constant value here (CON_A or CON_B)
    fn call(const_val_of_container: ???) { // <- what type should it be?
        todo!();
    }
}

fn main() {
    Container::call("a"); // <- should be error
    Container::call(Container:: CON_A); // should be good
}

Thanks!

rust is statically typed, and the type checker uses strict rules to ensure type safety. you can use a dedicated type (e.g. define a custom type or a newtype wrapper) for the constants and parameter type.

but I feel this is probably an XY problem. what's the actual problem you are trying to solve? a concrete example would explain the problem better.

3 Likes

The most direct translation of your given code is probably something like this, but it's a very unusual pattern— I suspect that there is a better way to solve whatever problem you have that led you to seek this solution.

struct Container;
struct A;
struct B;

// This is a trait of `Container` so that orphan rules prevent external implementations
trait ConstArg<T> {
    const ARG: &'static str;
}

impl Container {
    fn call<T>() where Self: ConstArg<T> {
        let const_val_of_container = <Self as ConstArg<T>>::ARG;
        todo!();
    }
}

impl ConstArg<A> for Container {
    const ARG: &'static str = "a";
}

impl ConstArg<B> for Container {
    const ARG: &'static str = "b";
}

fn main() {
    Container::call::<A>();
}
1 Like

Or maybe, you're looking for something like an enum? I'm just guessing here...

struct Container;
#[derive(Copy,Clone)]
enum ContainerArgs { A, B };

impl ContainerArgs {
    const fn as_str(self)->&'static str {
        match self {
            Self::A => "a",
            Self::B => "b"
        }
    }
}

impl Container {
    fn call(arg: ContainerArgs) {
        let const_val_of_container = arg.as_str();
        todo!();
    }
}

fn main() {
   Container::call(ContainerArgs::A);
}
3 Likes

I am trying to fetch data from GraphQL without using libraries, but looks like using libraries iseems easier than implementing it myself.

This is clean! I like it. I probably wouldn't use it this time because I've decided to use GraphQL library but I'll keep it in mind. Thanks!