#[macro_export
can be simplified while also better expressing the pain

```
#[macro_export]
#[doc(hidden)]
macro_rules! count {
() => { 0 };
( A $( $t:ident )* ) => { 1 + count!( $( $t )* ) };
}

fn main() {
let n = count!(A A A A A A A A A);
println!("{n}");
}
```
December 24, 2025 at 3:19 PM
`No syntax variables matched as repeating at this depth` for recursive macro
I have _a lot_ of structs and need to generically get types out of them. Before today I did not have a need for `Option` and everything worked fine, but now I can't figure out how to add it... Here is a simplified example: struct Foo { bar: i32, baz: Option<u8>, } impl Foo { fn get<T: 'static>(&self) -> Option<&T> { impl_field_access_opt!(ref: self.bar, self.baz?) } } #[macro_export] macro_rules! impl_field_access_opt { (ref: $parent:ident.$head:ident $(, $pt:ident.$t:ident $(?)?)* $(,)?) => { (&$parent.$head as &dyn core::any::Any).downcast_ref::<T>() .or_else(|| impl_field_access_opt!(ref: $($pt.$t $(?)?),*)) }; (ref: $parent:ident.$head:ident ? $(, $pt:ident.$t:ident $(?)?)* $(,)?) => { (&$parent.$head as &dyn core::any::Any).downcast_ref::<Option<T>>()?.as_ref() .or_else(|| impl_field_access_opt!(ref: $($pt.$t $(?)?),*) $(,)?); }; (ref: $(,)?) => { None }; } fn main() { let foo = Foo { bar: 1, baz: Some(2), }; assert_eq!(foo.get::<i32>(), Some(&1)); assert_eq!(foo.get::<u8>(), Some(&2)); } Error: 1 error: attempted to repeat an expression containing no syntax variables matched as repeating at this depth --> src/main.rs:16:63 | 16 | .or_else(|| impl_field_access_opt!(ref: $($pt.$t $(?)?),*)) | ^^^
users.rust-lang.org
February 19, 2025 at 4:17 PM
Sized (or Sizeable) str, e.g. str<const N: usize>
daniel-pfeiffer: > Is there already a way of achieving this? This method is fully `const` as of Rust 1.88 (for `<[_]>::as_chunks`). There are other methods for supporting earlier Rust versions (e.g. unsafely assume length in `new_unchecked`). [playground] #[macro_export] macro_rules! array_str { ($lit:literal) => { const { const LIT: &str = $lit; const LEN: usize = LIT.len(); $crate::ArrayStr::<LEN>::new(LIT).unwrap() }}} #[derive(Copy, Clone)] pub struct ArrayStr<const LEN: usize>([u8; LEN]); impl<const LEN: usize> ArrayStr<LEN> { #[inline] pub const fn new(s: &str) -> Option<&Self> { if let ([bytes], []) = s.as_bytes().as_chunks() { let ptr = core::ptr::from_ref::<[u8; LEN]>(bytes); // SAFETY: Self is a transparent wrapper type // SAFETY: bytes are UTF-8 and verified equal len unsafe { ptr.cast::<Self>().as_ref() } } else { None } } } pub const BYTES: [u8; 5] = *b"hello"; pub const STR: ArrayStr<5> = *array_str!("hello"); I license any code I post here under SPDX: MIT-0 OR Apache-2.0. Note that the `Option::unwrap` occurs _at`const` time_ due to the `const` block, so there is guaranteed no runtime overhead. kpreid: > you can obtain the string length at compile time to derive the type from the literal value I see I was ninjad while putting together my example. But! Note that your example _could_ be ~~unsound~~ (EDIT: panicky) in the future if `$:literal` matchers can match custom type literals, as such a custom type could provide a `.len()` which does not match its deref-coercion to `str`. (This was more important before `$:literal`, when such macros had to take `$:expr` instead.)
internals.rust-lang.org
April 30, 2026 at 5:53 PM
Interaction of `#[macro_export]` and macro definition scope
… yikes, and `macro` items (`feature(decl_macro)`) behave the same way. I posit the possible behaviors are: * item, item, item — just wrong * item, item, local — **current** ; macro expanded identifiers refer to locals textually after the macro is defined and "captures" the hygiene, items otherwise * item, local, local — macro expanded identifiers refer to locals when that local is in scope, items otherwise; consistent with writing that name in that location * local, local, local — compile error; macro expanded identifiers always refer to the local it names at the definition site, and can't use it before initialization With the usage of `#[macro_export]`, there's a fourth case of expanding the macro after the "captured" name is out of scope. This also currently refers to the item name. The "item, local, local" case I could see as just a result of name lookup rules being to check for a local then for an item if there's no local in scope to match. The actual "item, item, local" behavior… it's almost certainly an implementation artifact of how hygiene isolation works and retrofitting the lexically scoped macros 1.0 to allow namespaced lookup. My guess is that the lookup information is `let`-scope defined alongside with the macro, essentially capturing the identifier and defining a place alias name which the macro expands to, thus it not resolving to the local before the macro in the code block.
internals.rust-lang.org
February 9, 2025 at 10:45 PM
Interaction of `#[macro_export]` and macro definition scope
Macros seem to be usable either in a sort-of “direct” manner, in which case, ordering matters, e.g. fn main() { let x = 1; macro_rules! fun { () => { x }; } dbg!(fun!()); } fn main() { let x = 1; dbg!(fun!()); // error: cannot find macro `fun` in this scope macro_rules! fun { () => { x }; } } and you can do things like shadowing: fn main() { let x = 1; macro_rules! fun { () => { what? }; } macro_rules! fun { () => { x }; } dbg!(fun!()); } or through the mechanisms of _item_ visibility, like other items such as `fn foo` or `struct Bar`, which you can get via `#[macro_export]` as you did, or with a `use` statement, e.g. fn main() { let x = 1; dbg!(fun!()); // error (like above) macro_rules! fun { () => { 42 }; } } vs fn main() { let x = 1; dbg!(fun!()); // works! macro_rules! fun { () => { 42 }; // n.b. we still aren't using `x` here at the moment } use fun; } where duplicate `use` would simply be an error fn main() { let x = || 1337; dbg!(fun!()); macro_rules! fun { () => { x() }; } use fun; dbg!(fun!()); macro_rules! fun { () => { x() + 1 }; } use fun; // error[E0252]: the name `fun` is defined multiple times dbg!(fun!()); } * * * I’d assume, the behavior is explained by implementation details of the mechanism that allows macros to be used like other items in the first place; items, even if contained within block expressions, are generally _independent_ of the block they are defined in, acting as-if they were implemented as static/global stuff on the module level. It doesn’t surprise me that a macro that’s made to “behave like other items” like this can end up switching “too” strongly into such a “behave like an item” mode. Do note, that the behavior here appears to be “resolve `x` like an item” i.e. if there's for instance some `fn x`, that’ll do, and there’s no compilation error after all. fn x() -> i32 { 42 } fn main() { let x = || 1337; dbg!(fun!()); // 42 macro_rules! fun { () => { x() }; } dbg!(fun!()); // 1337 use fun; } * * * It also seems like another macro definition can _shadow_ an external - or `use`d - item without problems: fn x() -> i32 { 42 } fn main() { let x = || 1337; dbg!(fun!()); // 42 macro_rules! fun { () => { x() }; } use fun; dbg!(fun!()); // 1337 macro_rules! fun { () => { x() + 1 }; } dbg!(fun!()); // 1338 } * * * I think this completes the picture above _both_ `macro_rules` declarations do also _shadow_ the macro provided via the `use`; and it’s also this _shadowing_ why the ordering mattered in your original code: fn main() { let x = 1; dbg!(fun!()); // <- resolves to `fun` available via `#[macro_export]` #[macro_export] macro_rules! fun { () => { x }; } } fn main() { let x = 1; #[macro_export] macro_rules! fun { // this macro_rules shadows () => { x }; // the globally available macro `fun` } // just like `let x` would shadow some `fn x` dbg!(fun!()); } `fun`’s definition – for purposes of through local variable-like scoping rules, shadows “itself”. * * * Is this whole exact behavior desirable? IDK; probably not really. Certainly it could be technically-breaking to change it (but it’s also somewhat realistic that nobody might actually depend on this). That a top-level macro_rules! fun { () => { x }; } fn main() { let x = 1; dbg!(fun!()); // error } can never refer to a local variable is also clear; that’s “just hygiene”. But arguably, the fact that the `x` can _fall back_ to referring to a top-level thing seems pretty surprising. Maybe considering this to be turned into a error first can open up space for future changes like making your original code example compile, too. Without such a restriction, I’d think that alternatives such as making fn x() -> i32 { 42 } fn main() { dbg!(fun!()); // 42 let x = || 1337; dbg!(fun!()); // 42 macro_rules! fun { () => { x() }; } dbg!(fun!()); // 1337 use fun; } instead behave like fn x() -> i32 { 42 } fn main() { dbg!(fun!()); // 42 let x = || 1337; dbg!(fun!()); // 1337 // <- this changed macro_rules! fun { () => { x() }; } dbg!(fun!()); // 1337 use fun; } feel very much against proper hygiene, now the resolution of a name in a macro-expansion depends on whether or not a local variable was in scope which (that local variable) _wasn’t_ mentioned in the macro-call. (But instead at the macro definition, but there, it’s always in-scope.) The current status where the behavior changes with the question of which `fun` / or which _way_ the same `fun` / was imported, might be less bad? Except… now I’m noticing some more cursed cases – you can rename the macro with `use`, and the behavior stays the same fn x() -> i32 { 42 } fn main() { use fun2 as fun3; // a second step of `use` for good measure // but skippin this second step and using `fun2` below has the same behavior, too let x = || 1337; dbg!(fun3!()); // 42 macro_rules! fun { // there's no way this now () => { x() }; // also *actually shadows* fun2 and fun3, is there!? } dbg!(fun3!()); // 1337 // <- still prints 1337 here, vs 42 above.. use fun as fun2; } * * * And I keep coming up with interesting test cases. E.g. if this is working with `x` being a macro, which is[1] something where hygiene doesn’t apply like for local variables then the behavior is “simply” depending on the new shadowing `x` being in scope or not: fn main() { dbg!(fun!()); // 42 macro_rules! x { () => { 1337 } } dbg!(fun!()); // 1337 macro_rules! fun { () => { x!() }; } use fun; dbg!(fun!()); // 1337 } macro_rules! x { () => { 42 } } use x; * * * 1. i.e. name-resolution of macros ↩︎
internals.rust-lang.org
February 9, 2025 at 6:45 PM