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

Projects
None yet
7 participants
@dtolnay
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

This comment has been minimized.

Member

steveklabnik commented Oct 25, 2018

Whoops!

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

@coder543

This comment has been minimized.

coder543 commented Oct 25, 2018

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

@steveklabnik

This comment has been minimized.

Member

steveklabnik commented Oct 25, 2018

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

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

@dtolnay

This comment has been minimized.

Member

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

This comment has been minimized.

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

This comment has been minimized.

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

This comment has been minimized.

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

This comment has been minimized.

ubnt-intrepid commented Nov 1, 2018

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

This comment has been minimized.

Member

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