-
Notifications
You must be signed in to change notification settings - Fork 15
guideline: a macro should not be used in place of a function #74
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank @x0rw for adding this. Could you take a look at some of the comments?
Co-authored-by: Pete LeVasseur <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @x0rw! Please take a look at the comments I left
Co-authored-by: Pete LeVasseur <[email protected]>
37ed838
to
63e8d48
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @x0rw -- this looks good!
in markdown for easier reading and review:
(i'm unsure about the proper term for every italicized word below)
A macro should not be used in place of a function
:category: mandatory
:tags: reduce-human-error
:decidability: decidable
Functions should always be preferred over macros, except when macros provide essential functionality that functions cannot, such as variadic interfaces, compile-time code generation, or syntax extensions via custom derive and attribute macros.
Rationale:
Macros are powerful but they come at the cost of readability, complexity, and maintainability. They obfuscate control flow and type signatures,
Debugging Complexity
Errors point to expanded code rather than source locations, making it difficult to trace compile-time errors back to the original macro invocation.(edit: outdated, misleading)Although the compiler reports both the macro expansion and its invocation site, diagnostics originating within macros can be more difficult to interpret than those from ordinary function or type definitions. Complex or deeply nested macros may obscure intent and hinder static analysis, increasing the risk of misinterpretation or overlooked errors during code review.
Optimization
#[inline(always)]
functions, which can lead to code bloat.Functions provide
Non compliant example
Using a macro where a simple function would suffice, leads to hidden mutation:
In this example, calling the macro both increments and returns the value in one go—without any clear indication in its “signature” that it mutates its argument. As a result, num is changed behind the scenes, which can surprise readers and make debugging more difficult.
Compliant example
The same functionality, implemented as a function with explicit borrowing:
The function version makes the mutation and borrowing explicit in its signature, improving readability, safety, and debuggability.