Why Does Specific Type Pattern Matching Fail in Nested Rust Macros?

⚓ Rust    📅 2025-07-08    👤 surdeus    👁️ 4      

surdeus

Hello Rust community,

I'm new to writing Rust macros and could use some help with an issue I'm facing. I'm trying to create a nested macro that processes values differently based on their type, but the specific type pattern (e.g., String) fails to match in a nested setup, even though it works fine in a non-nested macro. Below is a minimal example to show the problem, followed by my questions.

Sample Code

Non-Nested Macro (Works as Expected)

macro_rules! single_macro {
    ($value:expr, String) => {
        println!("String value: PREFIX_{}", $value);
    };
    ($value:expr, $ty:ty) => {
        println!("Non-String value: {}", $value);
    };
}

fn main() {
    let s = String::from("hello");
    let i = 42;
    single_macro!(s, String); // Outputs: String value: PREFIX_hello
    single_macro!(i, i32);    // Outputs: Non-String value: 42
}

Nested Macro (Doesn't Work as Expected)

macro_rules! inner_macro {
    ($value:expr, String) => {
        format!("String value: PREFIX_{}", $value)
    };
    ($value:expr, $ty:ty) => {
        format!("Non-String value: {}", $value)
    };
}

macro_rules! outer_macro {
    ($value:expr, $ty:ty) => {
        println!("{}", inner_macro!($value, $ty));
    };
}

fn main() {
    let s = String::from("hello");
    let i = 42;
    outer_macro!(s, String); // Outputs: Non-String value: hello (Expected: String value: PREFIX_hello)
    outer_macro!(i, i32);    // Outputs: Non-String value: 42 (Correct)
}

Problem

In the non-nested macro (single_macro), the ($value:expr, String) pattern correctly matches for the String type, producing String value: PREFIX_hello. However, in the nested macro (outer_macro and inner_macro), the same pattern fails to match for String, and the ($value:expr, $ty:ty) pattern is used instead, resulting in Non-String value: hello.

Questions

  1. Why does the specific type pattern (e.g., String) match correctly in a non-nested macro but fail in a nested macro?
  2. Is there a way to reliably match specific types like String in nested macros?
  3. Are there documented limitations or best practices for matching specific type literals in Rust macros that a beginner should know?

Context

  • Rust version: Latest stable (as of July 2025).
  • Goal: Create a reusable nested macro for type-specific formatting.

Thanks for any insights or advice!

1 post - 1 participant

Read full topic

🏷️ rust_feed