Skip to content

Macro replacement fails if the macro name is in parentheses #1824

@Rua

Description

@Rua
#define FOO 42

void foo(void) {
    int i = (FOO);
}

result:

pub const FOO: ::core::ffi::c_int = 42 as ::core::ffi::c_int;
#[no_mangle]
pub unsafe extern "C" fn foo() {
    let mut i: ::core::ffi::c_int = 42 as ::core::ffi::c_int;
}

The macro itself is emitted, but then does not get used. The reason is that indexing TypedAstContext with an expression ID automatically skips over parentheses. So, when convert_expr is called with the ID of a parenthesis expression, it checks if that expression is a macro invocation (which it's not), then proceeds to convert it as if it were the inner expression (the 42 literal). convert_expr is never called with the expression ID of the 42 literal expression itself, so it's never replaced with a macro.

In general, automatically bypassing parentheses is a footgun precisely because of things like this, so I wonder if it would be better removed.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions