Skip to content
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

2018: #[macro_export(local_inner_macros)] breaks recursion in submodules #52726

Closed
durka opened this issue Jul 26, 2018 · 4 comments · Fixed by #52234
Closed

2018: #[macro_export(local_inner_macros)] breaks recursion in submodules #52726

durka opened this issue Jul 26, 2018 · 4 comments · Fixed by #52234

Comments

@durka
Copy link
Contributor

durka commented Jul 26, 2018

I tried adding #[macro_export(local_inner_macros)] to make a macro usable outside my crate, but it broke usability inside the crate (like for tests). The code:

#[macro_export(local_inner_macros)]
macro_rules! foo {
    () => { bar!(); };
}

macro_rules! bar {
    () => {}
}

mod tests {
    foo!();
}

This works in 2015, and it works in 2018 if you remove (local_inner_macros), but with both it doesn't. This seems like a problem for the migration path.

@dtolnay
Copy link
Member

dtolnay commented Jul 26, 2018

This is being fixed in #52234.

bors added a commit that referenced this issue Jul 31, 2018
resolve: Modularize crate-local `#[macro_export] macro_rules`

Based on #50911, cc #50911 (comment)

`#[macro_export] macro_rules` items are collected from the whole crate and are planted into the root module as items, so the external view of the crate is symmetric with its internal view and something like `$crate::my_macro` where `my_macro` is `#[macro_export] macro_rules` works both locally and from other crates.

Closes #52726
@ghost
Copy link

ghost commented Sep 17, 2018

I have a similar problem. In crossbeam-channel I put #[macro_export(local_inner_macros)] above the select macro:

#[macro_export(local_inner_macros)]
macro_rules! select {
    // ...
}

Then, in another crate I invoke the macro like this:

select! { default => {} }

This works on stable Rust, but doesn't compile on nightly anymore:

error[E0433]: failed to resolve. Could not find `unreachable` in `$crate`
  --> examples/csp.rs:40:5
   |
40 |     select! { default => {} }
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^ Could not find `unreachable` in `$crate`
   |
   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)

It's complaining about this invocation of unreachable!():

#[macro_export(local_inner_macros)]
macro_rules! select {
    // ...

    (@codegen_finalize
        $token:ident
        $index:ident
        $selected:ident
        $handles:ident
        ()
        ()
        ()
    ) => {
        unreachable!("internal error in crossbeam-channel")
    };

    // ...
}

If I change this to std::unreachable!, it will compile on nightly but not on stable anymore. Ugh. :(

Is there anything I can do to make this compile on both stable and nightly?

@dtolnay
Copy link
Member

dtolnay commented Sep 17, 2018

unreachable! is not a local macro defined in crossbeam so I believe the behavior is correct.

You can re-export unreachable like this:

#[macro_export]
#[doc(hidden)]
macro_rules! crossbeam_unreachable {
    ($($args:tt)*) => {
        unreachable! { $($args)* }
    };
}

@ghost
Copy link

ghost commented Sep 18, 2018

Works perfectly, thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants