Skip to content
This repository has been archived by the owner on Oct 6, 2024. It is now read-only.

paste doesnt seem to like stringify in this context #50

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

paste doesnt seem to like stringify in this context #50

sarvi opened this issue Sep 2, 2020 · 4 comments

Comments

@sarvi
Copy link

sarvi commented Sep 2, 2020

This compiles fine

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
    }
}

with paste, fails to compile

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
    }
}

Errors as below

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$ 

Changing stringify!($real_fn) to "something" then compiles fine

@dtolnay
Copy link
Owner

dtolnay commented Sep 2, 2020

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.

#[macro_export]
macro_rules! testhook {
    (unsafe fn $real_fn:ident ( $($v:ident : $t:ty),* ) -> $r:ty => $hook_fn:ident { $($body:tt)* }) => {
        paste! {
            pub unsafe fn $hook_fn ( $($v : $t),* ) -> $r {
                println!("{}()", stringify!($real_fn));
                $($body)*
            }
        }
    };
}

@sarvi
Copy link
Author

sarvi commented Sep 3, 2020

Thx for the pointer. The problem also happens for
event!(Level::INFO, "{}()", stringify!($real_fn));

where event is macro in the tracing module.
https://github.com/tokio-rs/tracing

@sarvi
Copy link
Author

sarvi commented Sep 3, 2020

Should I create a bug against rustc ?

sarvi added a commit to sarvi/redhook that referenced this issue Sep 3, 2020
$body:block) because of rustc bug
refered to  in
dtolnay/paste#50
@dtolnay
Copy link
Owner

dtolnay commented Oct 1, 2020

Fixed by rust-lang/rust#75800.

@dtolnay dtolnay closed this as completed Oct 1, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants