-
Notifications
You must be signed in to change notification settings - Fork 13.6k
Open
Labels
A-macrosArea: All kinds of macros (custom derive, macro_rules!, proc macros, ..)Area: All kinds of macros (custom derive, macro_rules!, proc macros, ..)A-proc-macro-back-compatArea: Backwards compatibility hacks for proc macrosArea: Backwards compatibility hacks for proc macrosC-discussionCategory: Discussion or questions that doesn't represent real issues.Category: Discussion or questions that doesn't represent real issues.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.Relevant to the compiler team, which will review and decide on the PR/issue.T-langRelevant to the language teamRelevant to the language teamWG-macrosWorking group: MacrosWorking group: Macros
Description
Should this example
macro_rules! mac {
($a:tt sep $b:tt) => { 1 $a$b 2 }
}
fn main() {
mac!(= sep =);
}
emit 1 == 2
and compile successfully?
Or, in other words, should the first emitted =
have the Spacing::Joint
set, if the output is processed by a proc macro?
We need some well-defined rule for setting spacing for tokens produced from macro variables.
Possible alternatives:
-
- Always use
Joint
.- This is very unreasonable.
- Always use
-
- Always use
Alone
.- This is the first reasonable alternative.
- Always use
-
- Inherit from the passed token - that means
Alone
in the example above because there is a space after the first=
inmac!(= sep =)
.- Probably unreasonable, the token sequence in the input have little relation to the output sequence for which we emit the spacing, in the example above it is demonstrated by
sep
being present in the input but not in the output. - Note: the issue is about single passed token trees (or last token trees in sequences), tokens passed in the middle of something like
$($tt)*
should of course use this option.
- Probably unreasonable, the token sequence in the input have little relation to the output sequence for which we emit the spacing, in the example above it is demonstrated by
- Inherit from the passed token - that means
-
- Inherit from the macro parameter declaration - i.e.
$a:tt
in the example (or just the$a
part of it).- This doesn't seem reasonable to me
- Inherit from the macro parameter declaration - i.e.
-
- Inherit from the macro parameter use, that means
Joint
in the example above because there is no space after$a
in1 $a$b 2
.- This is the second reasonable alternative.
- Inherit from the macro parameter use, that means
Right now the spacing is emitted inconsistently, sometimes it follows the rule 2.
, sometimes 3.
.
Adopting any consistent rule may cause breakage (@nnethercote may remember which exactly) and needs to go through crater.
- I would personally try the rule
5.
first, because it gives macro author freedom to control and change spacing as they want, unlike rule2.
that prevents joining entirely. - However we may be forced to adopt rule
2.
instead due to backward compatibility issues. It would be less flexible, but macro variables creating a "barrier" for joining is also a reasonable enough model.
Metadata
Metadata
Assignees
Labels
A-macrosArea: All kinds of macros (custom derive, macro_rules!, proc macros, ..)Area: All kinds of macros (custom derive, macro_rules!, proc macros, ..)A-proc-macro-back-compatArea: Backwards compatibility hacks for proc macrosArea: Backwards compatibility hacks for proc macrosC-discussionCategory: Discussion or questions that doesn't represent real issues.Category: Discussion or questions that doesn't represent real issues.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.Relevant to the compiler team, which will review and decide on the PR/issue.T-langRelevant to the language teamRelevant to the language teamWG-macrosWorking group: MacrosWorking group: Macros