-
Notifications
You must be signed in to change notification settings - Fork 9
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
Support macros in renamed crate scenario #20
Comments
I dove deeper into the issue reported by @sffc and as far as I can tell Rust does not have a solution to that at the moment. The scenario is very edge-casey. It happens when you import the crate and rename it: [dependencies]
foo = { package = "tinystr", path = "../../tinystr", features = ["macros"] } In that scenario, you have use foo::macros::tinystr4;
pub fn use_macro() {
let x = tinystr4!("foo");
assert_eq!(x, "foo");
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn it_works() {
use_macro();
}
} You'd expect that to work, but since our code in macro does: #[proc_macro]
pub fn tinystr4(input: TokenStream) -> TokenStream {
let val = get_value_from_token_stream(input);
let bytes: u32 = tinystr::TinyStr4::from_bytes(val.as_bytes())
.expect("Failed to construct TinyStr from input")
.into();
let formula = format!("unsafe {{ tinystr::TinyStr4::new_unchecked({}) }}", bytes);
formula.parse().unwrap()
} it will not - it expects There is an issue on file for it rust-lang/rust#54363 and there's a workaround crate - https://crates.io/crates/proc-macro-crate which reads your I'd love to avoid that solution, and hence I'm proposing to consider using I'm willing to keep this issue open and fix it when Rust introduces a solution, but for now, I believe that it is reasonable to assume that a rename scenario with proc-macro use is an edge case. @sffc @Manishearth - would you be ok with that approach? |
I don't get it: doesn't But yes, renamed crates are extremely rare and it's kinda typical for macros to break in that situation (not everyone remembers to use |
I'm okay declaring the problem out of scope, but I don't understand why we don't just fix it the right way. |
It seems it doesn't, or at least I can't get it to work. I tried doing what this PR does but with TokenStream [
Ident {
ident: "unsafe",
span: #12 bytes(240..256),
},
Group {
delimiter: Brace,
stream: TokenStream [
Punct {
ch: '$',
spacing: Alone,
span: #12 bytes(240..256),
},
Ident {
ident: "crate",
span: #12 bytes(240..256),
},
Punct {
ch: ':',
spacing: Joint,
span: #12 bytes(240..256),
},
Punct {
ch: ':',
spacing: Alone,
span: #12 bytes(240..256),
},
Ident {
ident: "TinyStr4",
span: #12 bytes(240..256),
},
Punct {
ch: ':',
spacing: Joint,
span: #12 bytes(240..256),
},
Punct {
ch: ':',
spacing: Alone,
span: #12 bytes(240..256),
},
Ident {
ident: "new_unchecked",
span: #12 bytes(240..256),
},
Group {
delimiter: Parenthesis,
stream: TokenStream [
Literal {
kind: Integer,
symbol: "7303014",
suffix: Some("u32"),
span: #12 bytes(240..256),
},
],
span: #12 bytes(240..256),
},
],
span: #12 bytes(240..256),
},
] which leads to this error:
As I said, the
Because there is no "clean" fix. It's either a heavy dependency or a declarative macro handled in the What I think I see differently from you is that the solution you proposed is not, in my opinion, "just a fix". It's a quite elaborate and quirky way to add support for something that is a very uncommon scenario. |
Just to make sure we're on the same page: my "fix" is: // In child crate
#[proc_macro]
pub fn tinystr4_bytes(input: TokenStream) -> TokenStream {
let val = get_value_from_token_stream(input);
let bytes: u32 = tinystr::TinyStr4::from_bytes(val.as_bytes())
.expect("Failed to construct TinyStr from input")
.into();
let formula = format!("{}", bytes);
formula.parse().unwrap()
}
// In main crate (untested)
macro_rules! tinystr4 {
($s:tt) => {
unsafe { $crate::TinyStr4::new_unchecked(tinystr4_bytes!($s)) }
}
} I don't find this quirky or elaborate at all. I find it to be a clean separation between what is best done as a proc macro (performing a complicated calculation) and what is best done as a normal macro (interpolating the computed value into syntax). |
That won't work because that's a cyclic dependency. Interpolating computed values is pretty easy in both proc and regular macros. |
This was fixed in #26. |
What do you think about making this sub-crate only emit the bytes themselves, and wrapping the bytes in a normal
macro_rules
in the main crate, such that you can use$crate::TinyStr4
for better resolution behavior?Originally posted by @sffc in #18
The text was updated successfully, but these errors were encountered: