-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
Can't define a function name using concat_idents!() #12249
Comments
A duplicate of #4365. Should we make this an RFC? |
I think it's a pretty essential feature. Even C macros can do this with To give a more realistic use case, Servo has functions like
and I generate these from macro invocations
but would much rather have
|
Just ran into this problem wanting to generate two tests for encoder I'm implementing. One checking if encoding is correct and the other if |
cc @lpy |
cc #13294 |
+1 for implementing this, seems like the kind of thing macros would be useful for |
Another use case: a macro used to define both |
I just ran into this. a few of uses I had in mind- convenience for making a single-function trait, rolling accessors for emulating anon structs; convenience for rolling double-dispatch traits to emulate overloading. |
This is really just due to how hacky and awful macro expansion is. Macro invocation is only allowed in certain predesignated places in the ast. |
Note that this can't be implemented if we enforce hygiene for all macros (including syntax extensions). |
A more wholesome design is needed, I don't want to keep extending the macro system ad-hoc. The monthish I spent around and with @jbclements inspired me to want to take ownership of macros. |
Leveraging some of the recent code from @jbclements in the macro_rules implementation this can technically be done in a user-defined syntax extension. The method is... well, it's utterly horrifying, but it works for now. #[feature(macro_rules)];
macro_rules! mymacro( ($x:ident) => (
expand_string_to_expr!(concat!("fn foo_", stringify!($x),"() { }"))
))
mymacro!(bar)
fn main() {
foo_bar();
} Where expand_string_to_expr! is a registered macro leveraging the ParserAnyMacro type from macro_rules.rs as below. #[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
reg.register_macro("expand_string_to_expr", expand_string_to_expr);
}
fn expand_string_to_expr(cx: &mut ExtCtxt, sp: codemap::Span, tts: &[ast::TokenTree]) -> Box<MacResult> {
use syntax::print::pprust;
let mut parser = parse::new_parser_from_tts(cx.parse_sess(), cx.cfg(), Vec::from_slice(tts));
let arg = cx.expand_expr(parser.parse_expr());
let expr_string = match arg.node {
ast::ExprLit(spanned) => {
match spanned.node {
ast::LitStr(ref s, _) => s.to_string(),
_ => {
cx.span_err(sp, format!(
"expected string literal but got `{}`",
pprust::lit_to_string(&*spanned)).as_slice());
return DummyResult::expr(sp)
}
}
}
_ => {
cx.span_err(sp, format!(
"expected string literal but got `{}`",
pprust::expr_to_string(&*arg)).as_slice());
return DummyResult::expr(sp)
}
};
if !parser.eat(&token::EOF) {
cx.span_err(parser.span, "only one string literal allowed");
return DummyResult::expr(sp);
}
let mut p = parse::new_parser_from_source_str(cx.parse_sess(), cx.cfg(), "string_expr".to_string(), expr_string);
return box ParserAnyMacro{
parser: std::cell::RefCell::new(p),
} as Box<MacResult>
} |
In case anyone wants a slightly simpler solution to this problem while waiting for better macros, I made a syntax plugin that's sure to break once after each nightly release: interpolate_idents. I would be very cautious to use this for anything. |
This is an issue that I find frustrating when working on We've already had a working PR that was closed due to needing an RFC and then an RFC that was closed due to trying to avoid jamming up the macro system with 1.0 approaching. Now that Rust has had several stable versions and the magical new macro system that people are heralding is nowhere in sight still, maybe we can consider opening an RFC for allowing macros in ident positions and actually having a discussion instead of just shutting it down immediately. |
macro reform is in the works right now, expect an internals post soon addressing things to fix (although a plan will take a bit longer). Concatenating identifiers is definitely on the agenda. It is a hard problem though - hygiene considerations means there is no easy solution. |
Awesome, thanks for working on this. Definitely a 👍 from me. Looking forward to it. |
Closing in favor of #29599 |
I want
mymacro!(bar)
to expand tofn foo_bar() { }
.gives
on
The text was updated successfully, but these errors were encountered: