On 03.04.24 11:47, Andreas Hindborg wrote: > Benno Lossin <benno.lossin@xxxxxxxxx> writes: > > [...] > >> >> >> So I did some digging and there are multiple things at play. I am going >> to explain the second error first, since that one might be a problem >> with `pin_init`: >> - the `params` extension of the `module!` macro creates constants with >> snake case names. >> - your `QueueData` struct has the same name as a field. >> - `pin_init!` generates `let $field_name = ...` statements for each >> field you initialize >> >> Now when you define a constant in Rust, you are able to pattern-match >> with that constant, eg: >> >> const FOO: u8 = 0; >> >> fn main() { >> match 10 { >> FOO => println!("foo"), >> _ => {} >> } >> } >> >> So when you do `let FOO = x;`, then it interprets `FOO` as the constant. >> This is still true if the constant has a snake case name. >> Since the expression in the `pin_init!` macro has type >> `DropGuard<$field_type>`, we get the error "expected >> `DropGuard<IRQMode>`, found `__rnull_mod_irq_mode`". > > Thanks for the analysis! > > So in this expanded code: > > 1 { > 2 unsafe { ::core::ptr::write(&raw mut ((*slot).irq_mode), irq_mode) }; > 3 } > 4 let irq_mode = unsafe { > 5 $crate::init::__internal::DropGuard::new(&raw mut ((*slot).irq_mode)) > 6 }; > > the `irq_mode` on line 2 will refer to the correct thing, but the one on > line 6 will be a pattern match against a constant? That is really > surprising to me. Can we make the let binding in line 6 be `let > irq_mode_pin_init` or something similar? The first occurrence of `irq_mode` in line 2 will refer to the field of `QueueData`. The second one in line 2 will refer to the constant. The one in line 4 is a pattern-match of the constant (since the type of the constant is a fieldless struct, only one value exists. Thus making the match irrefutable.) The occurrence in line 5 is again referring to the field of `QueueData`. If you have a constant `FOO`, you are unable to create a local binding with the name `FOO`. So by creating the `irq_mode` constant, you cannot create (AFAIK) a `irq_mode` local variable (if the constant is in-scope). > >> >> Now to the first error, this is a problem with the parameter handling of >> `module`. By the same argument above, your let binding in line 104: >> >> let irq_mode = (*irq_mode.read()).try_into()?; >> >> Tries to pattern-match the `irq_mode` constant with the right >> expression. Since you use the `try_into` function, it tries to search >> for a `TryInto` implementation for the type of `irq_mode` which is >> generated by the `module!` macro. The type is named >> __rnull_mod_irq_mode. >> >> >> Now what to do about this. For the second error (the one related to >> `pin_init`), I could create a patch that fixes it by adding the suffix >> `_guard` to those let bindings, preventing the issue. Not sure if we >> need that though, since it will not get rid of the first issue. > > I think that is a good idea 👍 Will do that. > >> >> For the first issue, I think there is no other way than to use a >> different name for either the field or the constant. Since constants are >> usually named using screaming snake case, I think it should be renamed. >> I believe your reason for using a snake case name is that these names >> are used directly as the names for the parameters when loading the >> module and there the convention is to use snake case, right? >> In that case I think we could expect people to write the screaming snake >> case name in rust and have it automatically be lower-cased by the >> `module!` macro when it creates the names that the parameters are shown >> with. > > I was thinking about putting the parameters in a separate name space, > but making them screaming snake case is also a good idea. So it would > be `module_parameters::IRQ_MODE` to access the parameter with the name > `irq_mode` exposed towards the user. Developers can always opt in to bringing > the symbols into scope with a `use`. I really like the idea of putting them in a module. At the very first glance at the usage, I thought "where does this come from?!". So having `module_parameters` in front is really valuable. -- Cheers, Benno