adamgreig/ral-registers

Local variables 'mask', 'offset' shadowed in macros

Closed this issue · 3 comments

A variable named mask or offset is shadowed by the imports within the modify_reg! and write_reg! macros:

let mask = 6;
ral::write_reg!(self, &register_block, register, field_foo: mask);

This results in the following compiler warning:

warning: unused variable: `mask`
  --> tests/macros.rs:87:9
   |
87 |     let mask = 6;
   |         ^^^^ help: if this is intentional, prefix it with an underscore: `_mask`

Ah, nice catch. Is there a general solution here? We can name the interior variables something like __mask instead, but of course it could still shadow an outer scope variable.

Using { use $periph::{$reg::$field::mask}; mask } instead of mask solved the problem for me.

A unique name for each constant was my first approach, though I do like using module-qualified constants. Either way works for me.

I'm also not sure of a general solution. Though this issue is only focused on two variable names, we can also demonstrate the shadowing by selecting a symbol imported by the globs, like RW::*. I might not expect this kind of usage in real-world code, so relying on compiler warnings seems reasonable.

use stm32ral as stm32;
use ral_registers as ral;

const Input: u32 = 42; // Same name as a constant, 'Input', imported via glob.

let gpioa = gpio::GPIOA::take().unwrap();
ral::modify_reg!(stm32::gpio, gpioa, MODER, MODER1: Input);
warning: constant is never used: `Input`
   --> tests/macros.rs:112:5
    |
112 |     const Input: u32 = 42;
    |     ^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: `#[warn(dead_code)]` on by default

(First attempt: since each macro defines a new scope, and it seems each scope can re-define the same function, I thought about an immediately-invoked #[inline(always)] function that could keep the scopes separate. I couldn't figure out the syntax, particularly when dealing with variable field-value inputs. Curious to know if / how codegen would work.)