-
Notifications
You must be signed in to change notification settings - Fork 34
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
test macro hygiene #24
Comments
Can you provide a minimal example illustrating the issue? |
Yes, sorry. test-log = { version = "0.2", features = ["trace"] }
env_logger = "0.9"
tracing = {version = "0.1", default-features = false}
tracing-subscriber = {version = "0.3", default-features = false, features = ["env-filter", "fmt"]} trait Foo: Sized {
fn map(self) -> Self {
self
}
}
impl<T> Foo for T {}
#[cfg(test)]
mod tests {
use super::*;
#[test_log::test]
fn foo() {
42.map();
}
}
cause Line 120 in 3b60bc9
I believe #15 (comment) would help on this matter. But unsure, I don't know much about proc macro. rust-lang/rust#54727 is about proc macro hygiene. |
Interestingly, it's not even that the proc macro is polluting your namespace, it's that you are polluting the proc macro's namespace from what I understand. It's reasonably easy to fix in this case, even in a generic manner. Happy to be proven wrong, but I am not convinced that #15 (comment) has any bearing on the issue. All it suggests is putting the proc macro logic into a different crate and then importing the macros through this crate. That shouldn't have any impact on method resolution or really much of the compilation process. |
The initialization code that we generate as part of the procedural macro effectively lives in the same namespace (for values, but also types) as client code. That can actually cause issues due to missing proc macro hygiene. Specifically, we have seen cases where a trait, let's call it Foo, is implemented for any T, and it contains a very generic method such as map. In such a scenario, the emitted initialization code could result in an ambiguous method call, should it use, say, Iterator::map somewhere. That is because we do not use fully qualified calling syntax everywhere in generated code. The ultimate fix should come from the Rust side in the form of proper proc macro hygiene, but for now we prevent problems like this by putting all initialization code into a generated module. The module boundary ensures that only explicitly imported functions are available -- and we do not import anything. Closes #24
The initialization code that we generate as part of the procedural macro effectively lives in the same namespace (for values, but also types) as client code. That can actually cause issues due to missing proc macro hygiene. Specifically, we have seen cases where a trait, let's call it Foo, is implemented for any T, and it contains a very generic method such as map. In such a scenario, the emitted initialization code could result in an ambiguous method call, should it use, say, Iterator::map somewhere. That is because we do not use fully qualified calling syntax everywhere in generated code. The ultimate fix should come from the Rust side in the form of proper proc macro hygiene, but for now we prevent problems like this by putting all initialization code into a generated module. The module boundary ensures that only explicitly imported functions are available -- and we do not import anything. Closes #24
Should be fixed now. Let me know if you encounter any problems with the fix. Should be able to cut a release in the next few days or so. Thanks for reporting this issue! |
I have a trait that have a
map
method, it's look the macro use imported item from user code.The text was updated successfully, but these errors were encountered: