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

Seems like the bug is with $:block macro expansion #76300

Closed
sarvi opened this issue Sep 3, 2020 · 2 comments
Closed

Seems like the bug is with $:block macro expansion #76300

sarvi opened this issue Sep 3, 2020 · 2 comments
Labels
A-macros Area: All kinds of macros (custom derive, macro_rules!, proc macros, ..) C-bug Category: This is a bug. E-needs-mcve Call for participation: This issue has a repro, but needs a Minimal Complete and Verifiable Example

Comments

@sarvi
Copy link

sarvi commented Sep 3, 2020

I tried this code:
the problem is tracked in the paste crate here, but the paste deveoper thinks it is a bug in rustc
dtolnay/paste#50

This fails to compile. It uses the paste crate for symbol expansion inside macros

extern crate paste;
extern crate libc;

use paste::paste;
use std::ffi::CStr;
use libc::{c_void,c_char,c_int,size_t,ssize_t};

#[macro_export]
macro_rules! testhook {

    (unsafe fn $real_fn:ident ( $($v:ident : $t:ty),* ) -> $r:ty => $hook_fn:ident $body:block) => {
        paste! {
            pub unsafe fn $hook_fn ( $($v : $t),* ) -> $r {
                println!("{}()", stringify!($real_fn));
                $body
            }               
        }
    };
}

testhook! {
    unsafe fn readlink(path: *const c_char, buf: *mut c_char, bufsiz: size_t) -> ssize_t => my_readlink {
        println!("readlink({})", CStr::from_ptr(path).to_string_lossy());
        0
    }
}

Erroring out as

bash-4.4$ cargo clean ; cargo build
   Compiling proc-macro2 v1.0.19
   Compiling unicode-xid v0.2.1
   Compiling syn v1.0.39
   Compiling libc v0.2.76
   Compiling paste v1.0.0
   Compiling quote v1.0.7
   Compiling ctor v0.1.15
   Compiling readlink v0.1.0 (/ws/sarvi-sjc/redhook/examples/readlink)
error[E0423]: expected value, found built-in attribute `path`
  --> src/lib.rs:15:17
   |
15 |                   $body
   |                   ^^^^^ not a value
...
21 | / testhook! {
22 | |     unsafe fn readlink(path: *const c_char, buf: *mut c_char, bufsiz: size_t) -> ssize_t => my_readlink {
23 | |         println!("readlink({})", CStr::from_ptr(path).to_string_lossy());
24 | |         0
25 | |     }
26 | | }
   | |_- in this macro invocation
   |
   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)

warning: unused imports: `c_int`, `c_void`
 --> src/lib.rs:6:12
  |
6 | use libc::{c_void,c_char,c_int,size_t,ssize_t};
  |            ^^^^^^        ^^^^^
  |
  = note: `#[warn(unused_imports)]` on by default

error: aborting due to previous error; 1 warning emitted

For more information about this error, try `rustc --explain E0423`.
error: could not compile `readlink`.

To learn more, run the command again with --verbose.
bash-4.4$ 

This compiles fine, without using paste, The only difference is the use of the paste! macro which does symbol expansion, though no actual symbol expansion code exists in the macro at this point. Just the mere act of invoking paste!{} caused the error.
And fix it as
Changing stringify!($real_fn) to "something" then compiles fine.
Below is the code that compiles without using paste! {}

extern crate paste;
extern crate libc;

use paste::paste;
use std::ffi::CStr;
use libc::{c_void,c_char,c_int,size_t,ssize_t};

#[macro_export]
macro_rules! testhook {

    (unsafe fn $real_fn:ident ( $($v:ident : $t:ty),* ) -> $r:ty => $hook_fn:ident $body:block) => {
            pub unsafe fn $hook_fn ( $($v : $t),* ) -> $r {
                    println!("{}()", extern crate paste;
                    extern crate libc;
                    
                    use paste::paste;
                    use std::ffi::CStr;
                    use libc::{c_void,c_char,c_int,size_t,ssize_t};
                    
                    #[macro_export]
                    macro_rules! testhook {
                    
                        (unsafe fn $real_fn:ident ( $($v:ident : $t:ty),* ) -> $r:ty => $hook_fn:ident $body:block) => {
                                pub unsafe fn $hook_fn ( $($v : $t),* ) -> $r {
                                        println!("{}()", stringify!($real_fn));
                                        $body
                                }
                        };
                    }
                    
                    testhook! {
                        unsafe fn readlink(path: *const c_char, buf: *mut c_char, bufsiz: size_t) -> ssize_t => my_readlink {
                            println!("readlink({})", CStr::from_ptr(path).to_string_lossy());
                            0
                        }
                    }
                    );
                    $body
            }
    };
}

testhook! {
    unsafe fn readlink(path: *const c_char, buf: *mut c_char, bufsiz: size_t) -> ssize_t => my_readlink {
        println!("readlink({})", CStr::from_ptr(path).to_string_lossy());
        0
    }
}

The developer of the paste!{} crate thinks this is a bug in rustc and commented as below

This looks like a rustc bug. Putting println!("{:#?}", input) at the beginning of the paste implementation to see what tokens the compiler is passing in as macro input, it shows:

...
                    Ident {
                        ident: "path",
                        span: #0 bytes(456..460),
                    },
...
                                            Ident {
                                                ident: "path",
                                                span: #22 bytes(381..386),
                                            },
...

where the two path tokens have totally different hygiene context (the #0 vs #22) and so do not resolve to each other.

It seems like the bug is with $:block, so you should be able to work around it by not using $:block.

I expected to see this happen: explanation

Instead, this happened: explanation

Meta

rustc --version --verbose:

bash-4.4$ rustc -vV
rustc 1.47.0-nightly (7e6d6e5f5 2020-08-16)
binary: rustc
commit-hash: 7e6d6e5f535321c2223f044caba16f97b825009c
commit-date: 2020-08-16
host: x86_64-unknown-linux-gnu
release: 1.47.0-nightly
LLVM version: 10.0
bash-4.4$ 
Backtrace

<backtrace>

@sarvi sarvi added the C-bug Category: This is a bug. label Sep 3, 2020
@jyn514 jyn514 added A-macros Area: All kinds of macros (custom derive, macro_rules!, proc macros, ..) E-needs-mcve Call for participation: This issue has a repro, but needs a Minimal Complete and Verifiable Example labels Sep 3, 2020
@Aaron1011
Copy link
Member

Aaron1011 commented Sep 4, 2020

I suspect that this will be fixed by #75800

EDIT: This is definitely fixed by #75800

@dtolnay
Copy link
Member

dtolnay commented Oct 1, 2020

Verified fixed as of nightly-2020-09-12.

@dtolnay dtolnay closed this as completed Oct 1, 2020
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, ..) C-bug Category: This is a bug. E-needs-mcve Call for participation: This issue has a repro, but needs a Minimal Complete and Verifiable Example
Projects
None yet
Development

No branches or pull requests

4 participants