2

Say I have some simple struct, eg:

struct SomeStruct {
  things: Vec<usize>
  recent_thing: Option<usize>
}

I'm trying to assert some invariant on this struct. For example, maybe we want to assert that "recent_thing" is only ever None just after creation (eg, with SomeStruct::new()), and any subsequent method call will ensure it's updated.

How can you do this? In part, my solution has been the establishment of a true sentinel value (maybe Default::default()), which, if you could restrict the user from creating its value (eg its the only value for which every byte is 0xf3), would ensure you can uphold the invariant strictly using the API (which internally upholds the invariant using typestate). You'd have to somehow make sure the user cannot use ..Default::default() in struct construction.

I dont think the solution is just Option<SomeStruct> because that still doesn't enforce the upholding of the actual invariant.

I'm aware of this related question, whose answer is unfortunately not what I'm looking for: Can you disable constructor syntax for a type?

Also open to suggestions for improvement of the question in comments or chat

5
  • 5
    This is usually solved through the builder pattern: have a builder struct that contains an Option<usize>, and a build method that converts it to the final struct that only contains a usize, after the appropriate checks.
    – Jmb
    Commented Apr 11 at 7:20
  • @Jmb: I don't think that's what the OP is asking for; they do want SomeStruct to exist with Option<usize> between construction and first update, as far as I can tell. Commented Apr 11 at 7:21
  • 3
    "You'd have to somehow make sure the user cannot use ..Default::default() in struct construction." => this syntax is only available in contexts where the fields are visible, and private fields are only visible in modules & sub-modules, could you specify your misgivings with it then? Commented Apr 11 at 7:22
  • Is there a reason you aren't happy with just wrapping the api in a module so the fields are only accessible within that module? Commented Apr 11 at 13:28
  • 1
    I think the builder pattern is the term I was missing, thanks! Commented Apr 11 at 14:09

0

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.