Associated constants

Minimum Rust version: 1.20

You can define traits, structs, and enums that have “associated functions”:

  1. struct Struct;
  2. impl Struct {
  3. fn foo() {
  4. println!("foo is an associated function of Struct");
  5. }
  6. }
  7. fn main() {
  8. Struct::foo();
  9. }

These are called “associated functions” because they are functions that areassociated with the type, that is, they’re attached to the type itself, andnot any particular instance.

Rust 1.20 adds the ability to define “associated constants” as well:

  1. struct Struct;
  2. impl Struct {
  3. const ID: u32 = 0;
  4. }
  5. fn main() {
  6. println!("the ID of Struct is: {}", Struct::ID);
  7. }

That is, the constant ID is associated with Struct. Like functions,associated constants work with traits and enums as well.

Traits have an extra ability with associated constants that gives them someextra power. With a trait, you can use an associated constant in the same wayyou’d use an associated type: by declaring it, but not giving it a value. Theimplementor of the trait then declares its value upon implementation:

  1. trait Trait {
  2. const ID: u32;
  3. }
  4. struct Struct;
  5. impl Trait for Struct {
  6. const ID: u32 = 5;
  7. }
  8. fn main() {
  9. println!("{}", Struct::ID);
  10. }

Before this feature, if you wanted to make a trait that represented floatingpoint numbers, you’d have to write this:

  1. #![allow(unused_variables)]
  2. fn main() {
  3. trait Float {
  4. fn nan() -> Self;
  5. fn infinity() -> Self;
  6. // ...
  7. }
  8. }

This is slightly unwieldy, but more importantly, because they’re functions,they cannot be used in constant expressions, even though they only return aconstant. Because of this, a design for Float would also have to includeconstants as well:

  1. mod f32 {
  2. const NAN: f32 = 0.0f32 / 0.0f32;
  3. const INFINITY: f32 = 1.0f32 / 0.0f32;
  4. impl Float for f32 {
  5. fn nan() -> Self {
  6. f32::NAN
  7. }
  8. fn infinity() -> Self {
  9. f32::INFINITY
  10. }
  11. }
  12. }

Associated constants let you do this in a much cleaner way. This traitdefinition:

  1. #![allow(unused_variables)]
  2. fn main() {
  3. trait Float {
  4. const NAN: Self;
  5. const INFINITY: Self;
  6. // ...
  7. }
  8. }

Leads to this implementation:

  1. mod f32 {
  2. impl Float for f32 {
  3. const NAN: f32 = 0.0f32 / 0.0f32;
  4. const INFINITY: f32 = 1.0f32 / 0.0f32;
  5. }
  6. }

much cleaner, and more versatile.