Repository: rust
Issue: Extremely weird hygiene behavior when invoking a macro from the calling crate in a Derive
Labels: T-compiler,A-macros-2.0,C-bug,A-hygiene

I'm not entirely sure whether this is a bug or not, but the current behavior seems super finicky and unintuitive at worst, and I think it's likely a bug. I think this warrants some context on the use case, so I'd like to preface with that. There's a repro script at the bottom if you don't care about the context.

Custom derives have to work around the fact that they don't have access to `$crate` for the crate they're associated with. Typically the way this is worked around is by doing `const UNIQUE_NAME: () 
= { extern crate your_crate; /*code*/ };`. Diesel provides several derives which we want to allow third party crates to use, but *also* use them within Diesel itself. This means that the `extern crate` workaround won't work for us. Instead we have this macro in Diesel:

```rust
macro_rules! __diesel_use_everything {
  () => { pub use $crate::*; }
}
```

and then the generated code looks like this:

```rust
mod unique_name {
    mod diesel {
        __diesel_use_everything!();
    }
    /*code*/
}
```

However, this gets super finicky with hygiene. If we try to do that with nightly, using the derives within Diesel itself will complain that `__diesel_use_everything!` can't be found. The fix for this is to give `__diesel_use_everything!()` a `call_site` span. Interestingly, the semicolon after it *must* have a `def_site` span, or nothing it imported will be visible. The semicolon being significant is particularly weird to me, because it's basically enforcing that `()` or `[]` be used as the delimiters. If I wanted to invoke the macro with `{}`, ~it would be impossible for me to make it work~ I have to ensure the braces have a `def_site` span.

Anyway it's possible to work around this in the most basic cases by giving `__diesel_use_everything!()` a `call_site` span. However, we run into additional trouble when the use of the `derive` originates inside a macro from Diesel (the actual macro is [`sql_function!`](http://docs.diesel.rs/diesel/macro.sql_function.html) if you want a real use case). It'll still find `__diesel_use_everything!()` but we get the same problem that we had if the `;` has a `call_site` span. Nothing in this `diesel` module is visible. `use self::diesel::anything` will fail.

With all that said, here's a minimum repro script:

### foo/lib.rs

```rust
#[macro_use]
extern crate bar;

macro_rules! __foo_use_everything {
    () => {
        pub use $crate::*;
    };
}

pub struct Foo;

macro_rules! make_a_struct {
    () => {
        #[derive(Thingy)]
        pub struct Bar;
    };
}

make_a_struct!();
```

### bar/lib.rs

```rust
#![feature(proc_macro)]

#[macro_use]
extern crate quote;
extern crate proc_macro2;
extern crate proc_macro;

use proc_macro::TokenStream;
use proc_macro2::Span;

#[proc_macro_derive(Thingy)]
pub fn derive(_: TokenStream) -> TokenStream {
    let call_site = Span::call_site();
    let use_everything = quote_spanned!(call_site=> __foo_use_everything!());
    quote!(
        mod a_unique_name {
            mod foo {
                #use_everything;
            }
            use self::foo::Foo;
        }
    ).into()
}
```

The workaround here is to call `source` on the `call_site` span (in `proc_macro2` that looks like `Span::call_site().unstable().source().into()`), but this requirement seems really weird to me. For that matter, the need to give the macro invocation any particular span at all is really surprising to me. This is a `macro_rules!` macro, which by its very nature is non-hygienic and global. I think this invocation should work regardless of the span the macro name has. Even putting that aside though, it seems to me that a derive used inside a `macro_rules!` macro should behave basically the same as one without (e.g. `__diesel_use_everything!` should certainly resolve with `call_site` regardless of where it's used)