> > --- > > Other thought: would a wrapper type make more sense here? Something like this: > > ``` > /* implementation */ > struct ModParam<T>(UnsafeCell<T>); > > // `Parameter` is the existing `ModParameter` (could be > // any name). It could be sealed. > impl<T: Parameter> ModParam<T> { > #[doc(hidden)] // used in the macro > fn new(value: T) -> Self { ... } > > fn get(&self) -> T::Value { ... } > fn set(&self, v: T::Value) { ... } > } > ``` > > With usage: > > ``` > module! { > // ... > // instantiated as: > // `static MY_PARAM: ModParam<i64> = ModParam::new(1);` > MY_PARAM: i64 { > default: 1, > description: "foo", > }, > } > > fn foo() { > pr_info!("My param is {}", MY_PARAM.get()); > } > ``` > > Advantages I see: > - You bring your own name, rather than being scoped and needing to > remember the module name The scoping is intentional. We did not want to pollute the name space, and `pin_init` had some issues when names were clashing. I think maybe this was discussed in v1. > - You can check `ModParam` in the docs to see the API, rather than > needing to refer to source for the exact signatures of `read` and > `write` Yes, that is a bit annoying. We could also implement `read` as a trait impl, so the trait would be documented in the `kernel` crate. In the original code that this patch descends from, `read` was generated differently, depending on how the parameter would integrate with sysfs. We might be able to do that with generics withthe `ModParam` you suggest. > - The interface gets a bit more like a mutex or atomic We discussed passing `self` in v1 and dropped it in favor of the associated method accessor. It would make sense with the `ModParam` approach you suggest though. Best regards, Andreas [1] https://rust-for-linux.zulipchat.com/#narrow/stream/x/topic/x/with/465040682