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

Function-like procedural macros in expression position as seen in 1.30 announcement are not stable yet #285

Closed
dtolnay opened this issue Oct 25, 2018 · 9 comments

Comments

@dtolnay
Copy link
Member

dtolnay commented Oct 25, 2018

Only macros in statement position are stable in 1.30.

error[E0658]: procedural macros cannot be expanded to expressions (see issue #38356)                                           
 --> src/main.rs:5:15                                                                                                          
  |                                                                                                                            
5 |     let sql = sql!(SELECT * FROM posts WHERE id=1);                                                                        
  |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

The stabilization hasn't landed in nightly yet either.

error[E0658]: procedural macros cannot be expanded to expressions (see issue #54727)                                           
 --> src/main.rs:5:15                                                                                                          
  |                                                                                                                            
5 |     let sql = sql!(SELECT * FROM posts WHERE id=1);                                                                        
  |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^                                                                         
  |                                                                                                                            
  = help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable

Mentioning @steveklabnik.

@steveklabnik
Copy link
Member

Whoops!

Any ideas on a decent example we could change it to?

@coder543
Copy link

Will this be stabilized for 1.31? Or is there an issue to track the status of proc macros in expression position?

@steveklabnik
Copy link
Member

No, it's not clear when this will become stable.

As the error message says, rust-lang/rust#54727 is the tracking issue.

@dtolnay
Copy link
Member Author

dtolnay commented Oct 25, 2018

@steveklabnik the include_dir! macro from https://github.com/Michael-F-Bryan/include_dir would make a good example. It is currently implemented using proc-macro-hack and has some crates using it. Could now be written stably as an ordinary procedural macro.

@sgrif
Copy link
Contributor

sgrif commented Oct 25, 2018

We're going to change the sql_function! macro in Diesel to a proc macro since parsing Rust function syntax + looking for special attributes in macro_rules! is not fun

@Ralith
Copy link

Ralith commented Oct 25, 2018

Any ideas on a decent example we could change it to?

Something that compiles a GLSL shader program, perhaps? e.g. vulkano has some really ugly hacks to accomplish this at present.

@rukai
Copy link

rukai commented Oct 26, 2018

@Ralith Not anymore! :D vulkano-rs/vulkano#1062
Vulkano now uses the newly stabilised function-like macros, instead of hacking it via [#derive()]

@ubnt-intrepid
Copy link

I'm currently working on introducing a new helper macros in my project, based on #[proc_macro] , and found that the expression-style macros could be defined by doing as follows:

#[proc_macro]
pub fn sql_impl(input: TokenStream) -> TokenStream {
    let expr = derive_sql_expr(input);
    quote::quote!(
        fn output() -> impl sql::Sql {
            #output
        }
    ).into()
}
extern crate sql_impl;
#[doc(hidden)]
pub use sql_impl::*;

#[macro_export(local_inner_macros)]
macro_rules! sql {
    ($($t:tt)*) => {{
        struct __Dummy;
        impl __Dummy {
            sql_impl!($($t)*);
        }
        __Dummy::output()
    }}
}

Restrictions:

  • The token streams cannot capture any identifiers contained in the caller's scope
    • let i=0; sql!(SELECT * FROM users WHERE id=i) should be rejected
  • the type of generated expression must be written as a return type (or impl Trait)

@dtolnay
Copy link
Member Author

dtolnay commented Nov 1, 2018

Or use https://github.com/dtolnay/proc-macro-hack which lifts both of those restrictions.

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

No branches or pull requests

7 participants