Skip to content

Cannot hygienically create test functions in macro #28335

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

Closed
tbu- opened this issue Sep 10, 2015 · 9 comments
Closed

Cannot hygienically create test functions in macro #28335

tbu- opened this issue Sep 10, 2015 · 9 comments
Labels
A-macros Area: All kinds of macros (custom derive, macro_rules!, proc macros, ..)

Comments

@tbu-
Copy link
Contributor

tbu- commented Sep 10, 2015

Code:

macro_rules! macro_ {
    ($t:ty) => {
        #[test]
        fn test() { }
    }
}

struct Foo;
struct Bar;
macro_!(Foo);
macro_!(Bar);

Error:

a.rs:4:9: 4:22 error: duplicate definition of value `test` [E0428]
a.rs:4         fn test() { }
               ^~~~~~~~~~~~~
a.rs:1:1: 6:2 note: in expansion of macro_!
a.rs:11:1: 11:14 note: expansion site
a.rs:4:9: 4:22 help: run `rustc --explain E0428` to see a detailed explanation
a.rs:4:9: 4:22 note: first definition of value `test` here
a.rs:4         fn test() { }
               ^~~~~~~~~~~~~
a.rs:1:1: 6:2 note: in expansion of macro_!
a.rs:10:1: 10:14 note: expansion site
error: aborting due to previous error
@tomjakubowski
Copy link
Contributor

The #[test] attribute is irrelevant; fails with the same message without it.

@alexispurslane
Copy link
Contributor

So we can't hygienically create any functions? That seems odd.

@lambda-fairy
Copy link
Contributor

One workaround is to nest the function in a module:

macro_rules! generate_tests {
    ($m:ident, $t:ty) => {
        #[cfg(test)]
        mod $m {
            #[test]
            fn test() { }
        }
    }
}

struct Foo;
generate_tests!(foo, Foo);

@semmaz
Copy link
Contributor

semmaz commented Sep 13, 2015

The problem here is not about hygiene of your macro,

macro_!(Foo);
macro_!(Bar);

will expand into two functions with same identifier (name) - test, hence the error message about duplicate definition of value 'test'.

So, as @lfairy pointed out, you can workaround this, I'll only add that module usage is unnecessary.

@tbu-
Copy link
Contributor Author

tbu- commented Sep 13, 2015

@semmaz

I thought this is what macro hygiene is: The identifiers within your macro don't clash with those outside of it?

@jonas-schievink
Copy link
Contributor

@tbu- That's true, but I think only locals are hygienic

@steveklabnik steveklabnik added the A-macros Area: All kinds of macros (custom derive, macro_rules!, proc macros, ..) label Sep 14, 2015
@durka
Copy link
Contributor

durka commented Sep 30, 2015

It says in the book, "This [macro hygiene] holds for let bindings and loop labels, but not for items."

@steveklabnik
Copy link
Member

Triage: it's been 18 months, and it's not clear that there's actually a bug here. Closing! If that's wrong, please open a new bug with the exact details today, thank you!

@tbu-
Copy link
Contributor Author

tbu- commented Mar 8, 2017

Yea, probably not a bug. Sorry for not closing it before.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-macros Area: All kinds of macros (custom derive, macro_rules!, proc macros, ..)
Projects
None yet
Development

No branches or pull requests

8 participants