Question Details

No question body available.

Tags

debugging rust conditional-compilation

Answers (2)

Accepted Answer Available
Accepted Answer
February 7, 2026 Score: 1 Rep: 172,590 Quality: High Completeness: 80%

The simplest option would be if true { ... } else { ... } but this can change the meaning of your code if variables are introduced in the blocks, as any variables created within the blocks won't exist after the if block. Further, this will require both blocks are valid Rust code, and the dead arm must still make semantic sense.

A macro can (mostly1) get around both limitations. Here is an example with explicit but verbose syntax:

macrorules! alternate {
    ( enabled => { $( $exp:tt )* } $( $tail:tt )* ) => {
        $( $exp )*
        alternate!($( $tail )*)
    };

( disabled => { $( $exp:tt )* } $( $tail:tt )* ) => { alternate!($( $tail )*) };

() => {}; }

Using this, your example becomes:

alternate!(
    enabled => {
        printf("This is implementation 1\n");
        foo = foo / 2;
    }
    disabled => {
        printf("This is implementation 2\n");
        foo >>= 1;
    }
)

Arms with enabled are emitted, and arms with disabled are erased. You can have as many arms as you want.

(Playground)


If you want a macro that can only have two options, with a single flag indicating which arm to take, then perhaps something like this would work:

macrorules! alternate {
    ( first ; { $( $first:tt ) } { $( $second:tt ) } ) => {
        $( $first )
    };

( second ; { $( $first:tt ) } { $( $second:tt ) } ) => { $( $second ) }; }

Example:

alternate!(
    first;
    {
        printf("This is implementation 1\n");
        foo = foo / 2;
    }
    {
        printf("This is implementation 2\n");
        foo >>= 1;
    }
)

Changing first to second will use the second block instead.

(Playground)


Whether using a macro like one of these would be better or worse than using comment blocks is probably a matter of opinion.


1 The rules for tt variables in macros require that all braces be matched, so while you can have nonsense like { let x = ; } in a dead arm, you cannot have nonsense like { let x = [; } due to the mismatched [.

February 8, 2026 Score: 1 Rep: 23,634 Quality: Medium Completeness: 80%

In general, the cfg attribute is already close to what you need. It's not just allowed for functions; it can also enable/disable {} code blocks.

It must still contain valid Rust code, but compared to an if/else, it can for example contain non-existent function calls:

fn main() {
    let mut foo = 9;

#[cfg(true)] { println!("This is implementation 1"); foo /= 2; } #[cfg(false)] { println!("This is implementation 2"); foo >>= 1;

nonexistantfunction(); }

println!("Result: {foo}"); }

Sadly, there is no else mechanism for cfg's built into Rust. There's the cfgif crate that would provide that, though:

fn main() {
    let mut foo = 9;

cfgif::cfgif! { if #[cfg(true)] { println!("This is implementation 1"); foo /= 2; } else { println!("This is implementation 2"); foo >>= 1;

nonexistant_function(); } }

println!("Result: {foo}"); }

But as already mentioned, I'm not really sure if that's more ergonomic than / / comment blocks.