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

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

surdeus

Warning

This post was published 120 days ago. The information described in this article may have changed.

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