strum icon indicating copy to clipboard operation
strum copied to clipboard

EnumProperty: opting-in stronger guarantees on properties

Open lucab opened this issue 7 years ago • 3 comments

Currently deriving EnumProperty results in a bunch of get*() -> Option<*>. This works quite well in general, but it moves some property checking to runtime option-handling.

What I'd like to see provided in this crate is some way of opting-in to stronger guarantees and typing of properties, such that I could:

  • annotate the enum to require that all variants declare some specific property
  • either annotate or infer the type of this mandatory property
  • generate specific getter for each mandatory property, such that there is a single get_prop() -> PropType generated

The usestory for this is: complex enums declarations (with attributes) can become quite long and some variants can end up with missing prop-attributes or with copy-paste type mistakes. Those would only be catched when unwrapping the Option at runtime, but the compiler should be able to sanity-check this at buildtime. Also it would make the getter more specifically named and remove the needs of Option wrapping.

Some hypotetical syntax (but feel free to design your one discarding this) could be:

#[derive(EnumProperty)]
#[strum(props(room: i32))]
enum Class {
    #[strum(props(teacher="foo", room=101))]
    History,
    #[strum(props(room=2))]
    Mathematics,
    #[strum(props(room=-1))]
    Science,
}

fn main() {
    let history = Class::History;
    assert_eq!(101, history.get_room());
}

Where adding a variant without the room prop or with a non-matching type would fail type-checking / compilation.

lucab avatar Apr 27 '17 20:04 lucab

This is a good idea!

Originally when I wrote the EnumProperty code, custom attributes were relatively limited in that they supported types other than strings, but it required a feature gate to use other types. I'm not sure if that's changed, but that doesn't mean I can't add it now and wait for it to be stabilized.

A quick note though, I don't believe -1 is supported though since that's an expression, not a literal in the grammar sense.

With respect to custom getters, I'm debating whether or not it makes sense to derive a trait YourStructPropertyGetters with your specific methods and implementing that. With these auto-derives, I'm always hesitant to implement them directly on the type because it can cause collisions with other user defined methods.

Peternator7 avatar Apr 28 '17 16:04 Peternator7

A quick note though, I don't believe -1 is supported though since that's an expression, not a literal in the grammar sense.

I fear you are right: https://github.com/rust-lang/rust/issues/34981#issuecomment-277510573

lucab avatar Jun 01 '17 22:06 lucab

With these auto-derives, I'm always hesitant to implement them directly on the type because it can cause collisions with other user defined methods.

In this case, the user is almost explicitly naming the method, so it should be OK.

meithecatte avatar Nov 27 '19 17:11 meithecatte