Simin Xiong
Simin Xiong

Reputation: 45

Why doesn't Rust support trait objects with associated constants?

I know it's because of object safety:

Object safe traits can be the base trait of a trait object. A trait is object safe if it has the following qualities (defined in RFC 255):

  • ...
  • It must not have any associated constants.

But if an associated constant is declared with a specific value, why does Rust still not support it? Here is an example:

trait Trait {
    const A: i32 = 64;
}

fn fun(t: Box<dyn Trait>) -> bool {
    return  true;
}

I want to use a function to return a constant value, and deliberately omit the &self parameter, but it still doesn't work. Here is the code:

trait Trait {
    fn getA() -> i32 {
        64
    }
}

fn fun(t: Box<dyn Trait>) -> bool {
    return  true;
}

Is there a low level reason why Rust doesn't support it? Or is it just because of the RFC rules?

Upvotes: 3

Views: 1222

Answers (3)

Kaplan
Kaplan

Reputation: 3758

The trait Trait can't be made into an object. So you must change the function parameter for fn fun():

trait Trait {
    const A: i32 = 64;
}

fn fun(t: impl Trait) -> bool {
    // do something with the Trait implementation t
    true
}

struct WithTrait;

impl Trait for WithTrait {
    const A: i32 = 64;
}

As soon you have an object implementing Trait you can pass it to the fun() function:
Playground

Similar example can be found in the Rust reference under Associated Constants Examples

Upvotes: -1

cg909
cg909

Reputation: 2556

They aren't object-safe, because the constant value may differ for trait implementers:

trait Foo {
    const A: i32 = 4;
}

impl Foo for bool {
    const A: i32 = 5;
}

Which value should (dyn Foo)::A produce?

By using dyn Foo the original type is erased, and without a pointer/reference to a dyn Foo value there is no vtable that could be consulted. The same problem exists for a trait method without a self parameter.

You need regular generics for this:

trait Trait {
    const A: i32 = 64;
}

fn fun<T: Trait>(t: T) -> i32 {
    T::A
}

Upvotes: 8

BallpointBen
BallpointBen

Reputation: 13867

It seems like you understand why a trait cannot have an associated type or constant in order to be object safe. The question of why a trait can't have an associated constant with a specific value is simple: just as a function definition in the trait definition is merely a default implementation and can be overridden by implementors of the trait, the value of an associated constant in the trait definition can also be overridden by implementors. Therefore this value would be unknown for a given dyn Trait, which — for the same reason that associated types make a trait object unsafe — makes Trait object unsafe.

Upvotes: 3

Related Questions