Home > Mobile >  Rust: Default structure member initialization for static structures?
Rust: Default structure member initialization for static structures?

Time:11-08

I'm evaluating Rust as a possible replacement for C/C in a new iteration of embedded FW. As I create simple projects, potential inconveniences come up. It's important for this application that migration be relatively painless, meaning that the most idiomatic Rust approach to a design pattern may not be possible. But it is also valuable to learn those idioms, so I'd like to learn. With that background ....

In C , it is easy to create default values for structures and allocate statically.

struct foo {
  int bar = 3;
  float baz = 10.0;
  char* msg = "hello there";
}

foo my_foo;

However, in Rust, getting default values for structure members seems to require using the Default::default() functionality. Consider this similar try:

struct MyStruct {
  a: i32,
  b: f32,
  c: bool,
}

impl Default for MyStruct {
  fn default() -> MyStruct {
      MyStruct {
          a: 3,
          b: 4.0,
          c: true,
      }
  }
}

static FOO: MyStruct = MyStruct { a:1, ..Default::default() };

So not only do I have to write a completely separate piece of code to create the defaults, but static allocation doesn't seem to be supported:

error[E0015]: cannot call non-const fn `<MyStruct as Default>::default` in statics
  --> src/main.rs:92:42
   |
92 | static FOO: MyStruct = MyStruct { a:1, ..Default::default() };
   |                                          ^^^^^^^^^^^^^^^^^^
   |
   = note: calls in statics are limited to constant functions, tuple structs and tuple variants

This all seems very awkward compared to C . I understand the idioms may be different, but relatively straightforward migration from C is important in this application - more appropriate Rust idioms can be brought in over time. And also, having to write more code to accomplish what was done previously is not likely to go over well. Is there another approach to this problem?

CodePudding user response:

The sticking point that you've hit is that static intializers must be const expressions but traits (like Default) do not have const support (yet). You'll need to implement a const function to construct your MyStruct without using Default:

impl MyStruct {
    pub const fn new() -> MyStruct {
        MyStruct {
            a: 3,
            b: 4.0,
            c: true,
        }
    }
}

static FOO: MyStruct = MyStruct { a:1, ..MyStruct::new() };

Or if this is common, you may want a dedicated constructor for it:

impl MyStruct {
    pub const fn with_a(a: i32) -> MyStruct {
        MyStruct {
            a,
            b: 4.0,
            c: true,
        }
    }
}

static FOO: MyStruct = MyStruct::with_a(1);
  • Related