Giter VIP home page Giter VIP logo

paste's Introduction

Macros for all your token pasting needs

github crates.io docs.rs build status

The nightly-only concat_idents! macro in the Rust standard library is notoriously underpowered in that its concatenated identifiers can only refer to existing items, they can never be used to define something new.

This crate provides a flexible way to paste together identifiers in a macro, including using pasted identifiers to define new items.

[dependencies]
paste = "1.0"

This approach works with any Rust compiler 1.31+.


Pasting identifiers

Within the paste! macro, identifiers inside [<...>] are pasted together to form a single identifier.

use paste::paste;

paste! {
    // Defines a const called `QRST`.
    const [<Q R S T>]: &str = "success!";
}

fn main() {
    assert_eq!(
        paste! { [<Q R S T>].len() },
        8,
    );
}

More elaborate example

The next example shows a macro that generates accessor methods for some struct fields. It demonstrates how you might find it useful to bundle a paste invocation inside of a macro_rules macro.

use paste::paste;

macro_rules! make_a_struct_and_getters {
    ($name:ident { $($field:ident),* }) => {
        // Define a struct. This expands to:
        //
        //     pub struct S {
        //         a: String,
        //         b: String,
        //         c: String,
        //     }
        pub struct $name {
            $(
                $field: String,
            )*
        }

        // Build an impl block with getters. This expands to:
        //
        //     impl S {
        //         pub fn get_a(&self) -> &str { &self.a }
        //         pub fn get_b(&self) -> &str { &self.b }
        //         pub fn get_c(&self) -> &str { &self.c }
        //     }
        paste! {
            impl $name {
                $(
                    pub fn [<get_ $field>](&self) -> &str {
                        &self.$field
                    }
                )*
            }
        }
    }
}

make_a_struct_and_getters!(S { a, b, c });

fn call_some_getters(s: &S) -> bool {
    s.get_a() == s.get_b() && s.get_c().is_empty()
}

Case conversion

Use $var:lower or $var:upper in the segment list to convert an interpolated segment to lower- or uppercase as part of the paste. For example, [<ld_ $reg:lower _expr>] would paste to ld_bc_expr if invoked with $reg=Bc.

Use $var:snake to convert CamelCase input to snake_case. Use $var:camel to convert snake_case to CamelCase. These compose, so for example $var:snake:upper would give you SCREAMING_CASE.

The precise Unicode conversions are as defined by str::to_lowercase and str::to_uppercase.


Pasting documentation strings

Within the paste! macro, arguments to a #[doc ...] attribute are implicitly concatenated together to form a coherent documentation string.

use paste::paste;

macro_rules! method_new {
    ($ret:ident) => {
        paste! {
            #[doc = "Create a new `" $ret "` object."]
            pub fn new() -> $ret { todo!() }
        }
    };
}

pub struct Paste {}

method_new!(Paste);  // expands to #[doc = "Create a new `Paste` object"]

License

Licensed under either of Apache License, Version 2.0 or MIT license at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this crate by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

paste's People

Contributors

cad97 avatar dtolnay avatar eijebong avatar rozaliev avatar ryanobeirne avatar sameer avatar scalexm avatar thedavidmeister avatar wez avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

paste's Issues

E0463 when linking dead code

When I try to build code that uses paste and my RUSTFLAGS is contains the -Clink-dead-code, the compiler complains that it can't find the paste crate.

Minimal reproducible example:

use paste::paste;

fn hello_world() {
    println!("Hello, world!");
}

fn main() {
    paste! { [<hello _world>](); }
}

This works fine without -Clink-dead-code but fails with it.

I'm using Rust on Windows. I haven't tried this on a different OS.

Error with paste-impl 0.1.3 and --release with msys2

When trying to build rav1e under windows10/msys2 I got this:

with cargo build is OK but

cargo build --release
Compiling proc-macro2 v0.4.23
Compiling unicode-xid v0.1.0
Compiling winapi-x86_64-pc-windows-gnu v0.4.0
Compiling winapi v0.3.6
Compiling unicode-width v0.1.5
Compiling num-traits v0.2.6
Compiling nasm-rs v0.1.3 (https://github.com/tdaede/nasm-rs.git#7c01c74c)
Compiling rand_core v0.3.0
Compiling bitflags v1.0.4
Compiling vec_map v0.8.1
Compiling strsim v0.7.0
Compiling rustc-demangle v0.1.9
Compiling cfg-if v0.1.6
Compiling y4m v0.3.1
Compiling bitstream-io v0.8.1
Compiling libc v0.2.43
Compiling textwrap v0.10.0
Compiling rand_core v0.2.2
Compiling rav1e v0.1.0 (C:\media-autobuild_suite\build\rav1e-git)
Compiling quote v0.6.10
Compiling atty v0.2.11
Compiling rand v0.5.5
Compiling backtrace v0.3.9
Compiling clap v2.32.0
Compiling syn v0.15.20
Compiling proc-macro-hack v0.5.1
Compiling paste-impl v0.1.3
Compiling paste v0.1.3
error: Could not compile rav1e.

after checking I think it come from paste-impl v0.1.3
when I force "cargo update -p paste-impl --precise 0.1.2" it build ok
paste v0.1.3 is ok only paste-impl v0.1.3 give error

Can't access local variable when on a nested macro

It fails to use the local variable in [1], but it works fine in [2]

#[derive(Default, Debug)]
struct Test {
    val: i32,
}

impl Test {
    fn set_val(&mut self, arg: i32) {
        self.val = arg;
    }
}

macro_rules! setter {
    ($obj:expr, $field:ident, $value:expr) => {
        paste::expr! { $obj.[<set_ $field>]($value); }
    };

    // this should work [1]
    ($field:ident, $value:expr) => {{
        let mut new = Test::default();
        setter!(new, val, $value);
        new
    }};
}

fn main() {
    // error: cannot find value `new` in this scope
    let a = setter!(val, 42);
    println!("{:?}", a);
    // works fine this way [2]
    let b = {
        let mut new = Test::default();
        setter!(new, val, 42);
        new
    };
    println!("{:?}", b);
}

Tested on Rust 1.31.1 stable, Gentoo Linux x86_64.

Behavior changes unexpectedly in 0.1.17

Is there a known change in behavior in 0.1.17 ?

I see that the changes 0.1.16...0.1.17 are significant in terms of implementation, but it is not obvious that there should be different behavior. However, I found in lightning-sys that the macro expansion was significantly different.

As of petelliott/lightning-sys@ba3bffb :

$ cargo update -p paste --precise 0.1.16
$ cargo expand --lib | sed -n '/^pub mod jitstate/,/^}/p' > with-0.1.16.txt
$ cargo update -p paste --precise 0.1.17
$ cargo expand --lib | sed -n '/^pub mod jitstate/,/^}/p' > with-0.1.17.txt
$ wc -l with-0.1.1*.txt
    4950 with-0.1.16.txt
    4229 with-0.1.17.txt

with-0.1.16.txt
with-0.1.17.txt

I have not boiled down a small test case.

Access to variable declared in macro

Greetings!

I don't know, maybe it related with #7, but I can't use variable from macro:

use paste::paste;

macro_rules! gen {
    ( $name:tt, $plural:tt ) => {
        paste! {
            let [<$name $plural _str >] = stringify!([<Str $name:camel $plural>]);
        }
    };
}

fn main() {
    gen!("foo", "s");

    println!("{}", foos_str);
}

I'm getting:

error[E0425]: cannot find value `foos_str` in this scope
  --> src/main.rs:14:20
   |
14 |     println!("{}", foos_str);
   |                    ^^^^^^^^ not found in this scope

Macro Expansion on Windows Stable Fails

I am getting error[E0658]: procedural macros cannot be expanded to statements and error[E0658]: procedural macros cannot be expanded to expressions for these two macros respectively only on Windows Stable. Not sure if this is a known limitation, but was just curious.

#[macro_export]
macro_rules! set {
    ($self:ident, $field:ident, $value:expr) => {
        paste::item! {
            $self.[<set_ $field:snake>]($value)
        }
    };
}

#[macro_export]
macro_rules! get {
    ($self:ident, $field:ident) => {
        paste::item! {
            $self.[<get_ $field:snake>]()
        }
    };
}

Conflict with extended_key_value_attributes

The following macro call compiles successfully on every rustc from 1.31.0 through 1.46.0:

macro_rules! repro {
    ($doc:expr) => {
        paste::item! {
            #[doc = $doc]
            pub struct Struct;
        }
    };
}

macro_rules! call {
    ($name:ident) => {
        repro!(stringify!($name));
    };
}

call!(documentation);

However 1.47.0 started failing with:

error: unexpected token: `stringify`
  --> src/main.rs:3:9
   |
3  | /         paste::item! {
4  | |             #[doc = $doc]
5  | |             pub struct Struct;
6  | |         }
   | |_________^
...
16 |   call!(documentation);
   |   --------------------- in this macro invocation
   |
   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)

And with a somewhat different message since 1.50.0:

error[E0658]: arbitrary expressions in key-value attributes are unstable
  --> src/main.rs:12:16
   |
12 |         repro!(stringify!($name));
   |                ^^^^^^^^^^^^^^^^^
...
16 | call!(documentation);
   | --------------------- in this macro invocation
   |
   = note: see issue #78835 <https://github.com/rust-lang/rust/issues/78835> for more information
   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)

Support paste in cfg feature context

I wonder if there is a way to express the following macro:

#[macro_export]
macro_rules! checked_feature {
    ($feature:ident, $current_protocol_version:expr) => {{
        paste! {
            #[cfg(feature = "protocol_feature_" $feature:snake)]
            let is_feature_enabled = PROTOCOL_FEATURES_TO_VERSION_MAPPING[&ProtocolFeature::$feature] >= $current_protocol_version;
            #[cfg(not(feature = "protocol_feature_" $feature:snake))]
            let is_feature_enabled = false;
            is_feature_enabled
        }
    }};
}

This gives me quite a cryptic message when use:

let q = checked_feature!(ForwardChunkParts, _protocol_version);
error: expected `,`, found `ForwardChunkParts`
   --> chain/chunks/src/lib.rs:654:34
    |
654 |                 checked_feature!(ForwardChunkParts, _protocol_version);
    |                 -----------------^^^^^^^^^^^^^^^^^--------------------
    |                 |                |
    |                 |                unexpected token
    |                 expected `,`

I have tried various combinations of stringify! and it seems that Rust just does not like anything but plain string literal there. I assume that the #[doc] support might be quite close to what I want here for the features.

Even if I use #[cfg(feature = stringify!($feature))] I get:

error: expected unsuffixed literal or identifier, found `stringify`

use of undeclared crate or module `paste`

I have two crates, a lib that defined macro and an app that uses that macro. and I get this error:

use of undeclared crate or module `paste`

tree:

├── Cargo.lock
├── Cargo.toml
├── app
│   └── my-app
│       ├── Cargo.toml
│       └── src
│           └── main.rs
└── lib
    └── my-macro
        ├── Cargo.toml
        └── src
            ├── lib.rs
            └── the_macro.rs

lib

./lib/my-macro/src/the_macro.rs

#[macro_export]
macro_rules! the_macro {
    ($result:ident, $field:ident) => {
        paste::paste! {
            struct $result {
                [<$field>]: String,
            }
        }
    };
}

./lib/my-macro/src/lib.rs

mod the_macro;

./lib/my-macro/Cargo.toml

[package]
name = "my-macro"
version = "0.1.0"
edition = "2021"

[dependencies]
paste = "1.0"

app

./app/my-app/src/main.rs

use my_macro::the_macro;

the_macro!(Foo, bar);

fn main() {
    println!("Hello, world!");
}

./app/my-app/Cargo.toml

[package]
name = "my-app"
version = "0.1.0"
edition = "2021"

[dependencies]
my-macro = { path = "../../lib/my-macro" }

root

[workspace]
members = [
    "app/my-app",
    "lib/*"
]
default-members = ["app/my-app"]

Error

error[E0433]: failed to resolve: use of undeclared crate or module `paste`
 --> app/my-app/src/main.rs:3:1
  |
3 | the_macro!(Foo, bar);
  | ^^^^^^^^^^^^^^^^^^^^^ use of undeclared crate or module `paste`
  |
  = note: this error originates in the macro `the_macro` (in Nightly builds, run with -Z macro-backtrace for more info)

For more information about this error, try `rustc --explain E0433`.
error: could not compile `my-app` due to previous error

sample repo

Inconsistent expression precedence when using camel

Hey! I have encountered an edge case with a surprising behavior. When using an expression in a macro along with camel and using a unary operator on the expression, the parentheses are eliminated resulting in a faulty short circuit.
Reproducible with:
paste = 1.0.12
rustc = 1.68.0

macro_rules! test {
    ($($name:ident $pred:expr),*) => {
        paste::paste! {
            $(
                if !$pred {
                    let camel = [<$name:camel>]::new();
                    println!("{}", $pred);
                }
            )*
        }
    }
}

fn main() {
    test!(String false || true);
}

Expanded to the following via cargo expand:

fn main() {
    if !false || true {
        let camel = String::new();
        {
            ::std::io::_print(format_args!("{0}\n", false || true));
        };
    }
}

Whereas without using camel it expands to:

fn main() {
    if !(false || true) {
        {
            ::std::io::_print(format_args!("{0}\n", false || true));
        };
    }
} 

paste 0.1.13 is not backwards compatible

The new version released yesterday (0.1.13) breaks dependent modules. For example jemalloc-ctl compiles with paste 0.1.12, but not with 0.1.13:

   Compiling jemalloc-ctl v0.3.3
error: expected identifier, found `Mib<[usize; 2]>`
##[error]  --> /home/runner/.cargo/registry/src/github.com-1ecc6299db9ec823/jemalloc-ctl-0.3.3/src/macros.rs:8:9
   |
8  | /          paste::item! {
9  | |              $(#[$doc])*
10 | |              #[allow(non_camel_case_types)]
11 | |              pub struct $id;
...  |
39 | |              pub struct [<$id _mib>](pub ::keys::$mib);
40 | |          }
   | |__________^
   | 
  ::: /home/runner/.cargo/registry/src/github.com-1ecc6299db9ec823/jemalloc-ctl-0.3.3/src/arenas.rs:3:1
   |
3  |  / option! {
4  |  |     narenas[ str: b"arenas.narenas\0", non_str: 2 ] => libc::c_uint |
5  |  |     ops: r |
6  |  |     docs:
...   |
26 |  |     mib_docs: /// See [`narenas`].
27 |  | }
   |  |_- in this macro invocation

The above compiler error was fixed by forcing Cargo to select version 0.1.12 of paste instead of 0.1.13.

Based on cargo's scheme to by default select the "maximum compatible" version based semantic versioning, if a backwards-incompatible change needs to be made, a new minor version should be used (e.g., 0.2.0) so that dependent crates do not break. Thanks!

[Feature Request] Inflection (aka plurals and sinulars)

Hi, thank for the nice crate, it save me time and boilerplate today!

Motivaiton

This modifiers like $var:snake:upper are very helpful and prevents from some repetition.
However, sometimes there are not sufficient, there some cases when a thing needs to be converted to it's plural (or maybe singular form).

For example: it would be cool to be able to derive from User model a table where it's stored (users).

Examples

  • when $var = user
    • $var:plural => users
    • $var:singular => user
  • when $var = users
    • $var:plural => users
    • $var:singular => user

Challenges

Due to the English grammar, just adding s is not always sufficient.
For example:

  • category -> categories
  • box -> boxes
  • mouse -> mice

So the problem is not very trivial. A good news, that Rails has it for almost 2 decades, and we can peek some ideas there.
In Rails, the module responsible for this is called Inflector: https://api.rubyonrails.org/classes/ActiveSupport/Inflector.html

It seems to be that this problem also already solved in Rust.
There are plenty of crates doing this: https://crates.io/search?q=singular%20plural
inflection-rs seems to be the most decent among them.

I'd like to hear from you:

  • Would you consider adding this feature to the paste crate?
  • If yes, would you like to implement it on your own, or you're fine to accept a PR?
  • And would you consider for possible using a third crate for inflection? (it can be behind feature flag)

Thank you in advance!

Compile error with old Glibc?

My CI just failed with this (after no apparent change)

error: /lib64/libc.so.6: version `GLIBC_2.34' not found (required by /__w/target/release/deps/libpaste-9f4ba831280a7332.so)
  --> /github/home/.cargo/registry/src/github.com-1ecc6299db9ec823/simba-0.7.1/src/scalar/complex.rs:23:9
   |
23 |         paste::item! {
   |         ^^^^^

error: cannot determine resolution for the macro `paste::item`

The code runs on a Fedora 34 which ships glibc 2.33 (IIRC), so it makes sense. Would you please confirm that a recent change increased the minimum required version? (Because otherwise I'd seriously confused about how any of this ever worked before)

"Expected identifier after `:`" error when `::` is used inside attribute

This simple example:

macro_rules! a { (#[x = $x:ty]) => {}; }
paste::paste!(a!(#[x = foo::Bar]));

Fails with the error message:

error: expected identifier after `:`
 --> src/lib.rs:3:27
  |
3 | paste::paste!(a!(#[x = foo::Bar]));
  |                           ^^

It seems like paste! is treating the attribute as a doc attribute even though it isn't.

can't concat namespace

I tried concat namespace using following code

macro_rules! call {
  ($path: expr) => {
    [<$path::call>]()
  };
}

And get compile error

error: expected `::`, found `]`
  --> .../src/lib.rs:20:11
   |
20 |           [<$path::call>]()
   |           ^^^^^^^^^^^^^^^ expected `::`

Consider supporting namespace ?

Feature requests: Concatenate integer literals & create identifiers based on a given range

I have two feature requests, but I'm not sure if either is within the scope of this crate. Both are motivated by the same example. I'm working in an embedded context, writing a module for GPIO pins. The pins are in four groups of 32, labeled PA00-PA31, PB00-PB31, PC00-PC31 and PD00-PD31. Within a macro, I generate marker types for each pin, and each one implements a PinId trait with an associated constant containing the pin group (A-D) and pin number (0-31).

Right now, I supply the pin name and number as a tuple containing an identifier and a literal, like this

[
    (PA00, 00),
    // ...
    (PA31, 31),
]

But that approach is redundant and error prone. It would be really nice if there were a way to concatenate the integer literal, so the macro call could look like this

PA: [
    00,
    // ...
    31,
]

Within the macro, I'm imagining a syntax like this

( $prefix:ident: [ $( $num:literal, )+ ] ) => {
    paste! {
        enum [<$prefix $num:2>] {}
        impl PinId for [<$prefix $num:2>] {
            const NUM: u8 = $num;
        }
    }
}

The :2 here tells paste to print the literal with a width of two, where zero padding is implied.

I've thought through some of the potential problems and didn't see any showstoppers. For instance, I think it only makes sense to support unsigned integer literals. Negative or floating point numbers wouldn't make any sense. I suppose you could also accept string literals, but that seems pointless compared to an identifier. When converting the integer literal to an identifier, it would be nice if you could specify a field width. Zero padding would be implied, because spaces can't be part of an identifier. If the integer doesn't fit within the specified width, it should be a compile-time error. If possible, I would also like to see hex output supported, so something like this [<$prefix $num:hex:2>].

Is this within the scope of paste?

To simplify the previous example even more, would it be possible to create all possible identifiers within a given range? Something like this

PA: (0..32)

I also have a use case for letters, where alternate peripheral pin functions are labeled AlternateA through AlternateN. It would be better if I didn't have to write out all of them

Alternate: ('A'..='N')

I feel like concatenating integer literals is fairly straightforward, but I'm much less certain about this feature. First of all, you would have to create a repeating unit within a macro where it didn't exist previously, which may not be possible. Or maybe alternatively, you write it like this

( $prefix:ident: ( $( $range:literal, )+ ) ) => {
    paste! {
        $(
            enum [<$prefix $range:2>] {}
        )+
    }
}

And call it like this

PA: (00, 31,)

In this case, there is already a repeating $()+. paste is just transforming it from length 2 to length 32. But again, this may not be possible.

Is there any reasonable way to generate a range of identifiers like this?

Cannot generate f32/f64 values

paste: 1.0.12
rustc: 1.68.2

When I try to concatenate a minus sign (-), a float literal (e.g. 0.0), and a type suffix (e.g. f32 or f64), rustc reports errors. Here is a reproduction code:

use paste::paste;

fn main() {
    paste! {
        let _ = [< 0.0 f32 >]; // rustc:Error:unsupported literal
        let _ = [< -0.0 f32 >]; // rustc:Error:unexpected punct
    }
}

In my actual project, I used the paste! macro with the duplicate! macro for unit tests using f32/f64 values like this:

use duplicate::duplicate;
use paste::paste;

duplicate! {
    [ float; [f32]; [f64]; ]
    // In this code block, the word `float` is replaced with `f32` and `f64`.
    paste! {
        #[test]
        fn [< ulp_should_return_EPSILON_when_self_is_1_ float >]() {
            // Here is the problematic code `[< 1.0 float >]`.
            assert_eq!([< 1.0 float >].ulp(), float::EPSILON);
        }

        // Many other test functions using f32 and f64 are omitted.
        // ...
    }
}

I expected the following code to be generated:

#[test]
fn ulp_should_return_EPSILON_when_self_is_1_f32() {
    assert_eq!(1.0f32.ulp(), f32::EPSILON);
}

#[test]
fn ulp_should_return_EPSILON_when_self_is_1_f64() {
    assert_eq!(1.0f64.ulp(), f64::EPSILON);
}

The duplicate! macro is not the cause of the compilation error, as shown in the reproduction code at the top of this post.

Please make the paste! macro able to concatenate signs, floating point numbers, and type suffixes 🙏

Can not use in literals?

use paste::paste;
macro_rules! vec_insert {
    ($bit: tt) => {
        paste! {
            fn [<vector_insert_ $bit _bit>](insert_size: usize) {
                let mut [<vec_ $bit>] = Vec::new();
                for _ in 0..insert_size {
                    [<vec_ $bit>].insert(0, [<1_u $bit>]);
                }
            }
        }
    };
}

vec_insert!(32);

expected to expand into

fn vector_insert_32_bit(insert_size: usize) {
    let mut vec_32 = Vec::new();
    for _ in 0..insert_size {
        vec_32.insert(0, 1_u32);
    }
}

but it show error:
`"1_u32"` is not a valid identifier

Can paste used in literal such as 1_u32?

Edge cases with `:camel`

Hey 👋

Thanks for the awesome crate 🙏

Reading from the code they're seems to be some un-intentional edge cases with :camel. For example:

  1. my__ident will be converted to MyIdent and not My_Ident.
  2. _my_ident will be converted MyIdent intead of _MyIdent (maybe intentional)

I don't think any of the PascalCase, the CamelCase nor the snake_case conventions specify those edge cases.

My use case for 1 is the following:
We have a data base containing a table with quite a lot of colums, the columns name are therefore scoped with scope_with_multiple_words__my_name. The database is accessed with diesel, the column name is therefore taken as such. I need to convert those columns to a Grpc enum, the enum variants are scoped as: ScopeWithMultipleWords_MyName

I don't have a specific use case for 2, just found that it was weird to remove the first _ if someone intentionally put it there.

Would you be open to such change? If yes, I can submit a PR 😊

(I do realise it's a breaking change, I just don't think there's a lot of people with ident containing two or more consecutive underscore)

Parser error with `:lifetime` param in expanded code

Minimal repro:

macro_rules! m {(
    $lt:lifetime
) => (
    ::paste::item! {
        impl<$lt> () {}
    }
)}

m! { 'lt }

leads to a parser error saying that:

  • 1.45.0-nightly (90931d9b3 2020-04-28)

    error: lifetime in trait object type must be followed by `+`
    
  • 1.43.0 (3532cf738 2020-03-17)

    error: expected type, found `'lt`
    
  • A run with cargo bisect seems to indicate this bug has always been present.


EDIT: After some testing, here is a minimal proc-macro repro (that is, if we replace ::paste::item! by foo!, the same parsing error is triggered):

#[proc_macro] pub
fn foo (it: TokenStream) -> TokenStream
{
    it  .into_iter()
        .map(|tt| tt) // without this line, there is no error (I imagine due to some specialization) 
        .collect::<TokenStream>()
      //.to_string().parse().unwrap() /* workaround! */
}

This minimal repro suggests that this is not really an issue with paste, but with some proc-macro :lifetime capture interaction... Since you know the internals of a TokenStream better, @dtolnay, I'll let you investigate it further and post an appropriate issue on rust-lang/rust.

macro expansion fails with formating types inside a string literal

regarding this code :

use paste::paste;
use serenity::{
    framework::standard::{macros::command, CommandResult},
    model::prelude::*,
    prelude::*,
};

macro_rules! gen_random_funs {
    [$($x:ty),*] => {
        paste! {
        $(
            #[command("`"$x"`")]
            #[description = "generates a random `" $x "`"]
            async fn [<_ $x>](ctx: &Context, msg: &Message) -> CommandResult {
                msg.reply(ctx, rand::random::<$x>()).await?;
                Ok(())
            }

        )*
    }
    };
}

gen_random_funs![u8, u16, u32, u64, u128, i8, i16, i32, i64, i128, f32, f64];

this fails with all the argument, quote unexpected token, note that macro also fail to expand in attributes in paste! blocks, this prevents the use of stringify! and such.

More backwards compatibility breakage in paste >=0.1.13

We encountered a failure to compile in rav1e after paste 0.1.13 was released. We have tested that this failure still occurs in 0.1.14. The errors are of the following form:

error: expected expression, found `TxType::H_FLIPADST`
   --> src/asm/x86/transform/inverse.rs:67:33
    |
67  |               out[get_tx_type_idx($ENUM)] = Some([<rav1e_inv_txfm_add_$TYPE2 _$TYPE1 _$W x $H _$OPT_LOWER>]);
    |                                   ^^^^^ expected expression
...
134 | / impl_itx_fns!(
135 | |   // 64x
136 | |   [(TxType::DCT_DCT, dct, dct)],
137 | |   [(64, 64), (64, 32), (32, 64), (16, 64), (64, 16)],
...   |
163 | |   [(avx2, AVX2), (ssse3, SSSE3)]
164 | | );
    | |__- in this macro invocation
    |
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)

Within a variety of macros. We were able to fix the issue in latest master via this change, but all previous commits are broken. We depend on the ability to run prior commits to compare encoding efficiency. I have confirmed that the commit prior to our fix, https://github.com/xiph/rav1e/tree/7d617a479d1d1a7051993d71ff92c1e2287fc955, builds if we hardcode paste to 0.1.12 and fails to build against any newer versions.

Paste sometimes produces keywords

Paste will produce a keyword instead of an identifier in some cases:

use paste::paste;

macro_rules! empty_items{
    ($name:ident $(- $name_tail:ident)*) => { paste!{
        struct [< $name:camel $( $name_tail)* >];

        fn [< $name:snake $( _ $name_tail:snake)* >]() {}
    }}
}

empty_items!(r#loop); // Error: expected identifier, found keyword `loop`
empty_items!(se-lf); // Error: expected identifier, found keyword `Self`
empty_items!(Loop); // Error: expected identifier, found keyword `loop`
empty_items!(r#loop-xyz); // Ok

Note that fixing this would be a breaking change as currently paste could be (ab)used to remove the r# from raw idents (say, for stringify!).

Maybe it's also worth thinking about whether, for example, paste!{ [< loop >] } should produce a raw identifier, rather than a keyword.

Support ident modifiers in doc

Currently, the following is not possible:

macro_rules! method {
    ($method:ident) => {
	#[doc = " Define an endpoint with path that allows only `" $method:snake:upper "` HTTP method"]
	pub fn $method() {}
    }
}

I looked into implementing it and send a PR but it looks like the doc.rs code is not using anything from lib.rs. I could have just copied the modifier code, but it felt like a hack reducing code quality. So, here I am creating an issue.

paste doesnt seem to like stringify in this context

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

Add $var:unquote modifier

I'd like to propose a new modifier for variable conversion named unquote. When applied to a string literal variable, it should remove the quotes, producing tokens.

Example:

fn foo() {}

macro_rules! bar {
    ($literal:literal) => {
        paste!([<$literal:unquote>]());
    };
}

bar!("foo"); // - expands to foo().

Use case:

I have a macro_rules derive macro, implemented using https://crates.io/crates/macro_rules_attribute. User input is expected to contain an attribute, #[foo(some_attr = "path::to::func")]. Since it is impossible to specify paths in Rust meta, a common pattern is to ask users to provide a string literal instead, the proc macro then parses it as expected token type. One example of a crate that uses this pattern is serde: https://serde.rs/container-attrs.html#default--path.

Since the purpose of paste is to enable macro_rules to do what normally only proc macros can do, I think this would be a nice addition.

Does not preserve invisible delimiters from declarative macros

The below example requires parentheses around the $val to compile, which it doesn't without paste.

macro_rules! clone {
  ($val:expr) => {
    paste::paste! {
      $val.clone()
    }
  }
}

#[derive(Clone)]
struct A;

impl A {
  fn consume_self(self) {}
}

fn main() {
  clone!(&A).consume_self();
}

The correct resulting token tree would be ⟦⟦&A⟧.clone()⟧.consume_self(), but with paste, it appears to be flattened to ⟦&A.clone()⟧.consume_self().

The docs do say null delimiters might not survive roundtripping, but I think it should be possible to avoid here.

Cannot use stringify! within paste::item! in a #[doc] attribute

This may be an odd edge case, but I want to have this bit of code within a macro:

paste::item! {
    /// The error type returned when a checked
    #[doc = $name_str]
    /// type conversion fails.
    #[derive(Debug, Copy, Clone, Eq, PartialEq)]
    pub enum [< TryFrom $name Error >] {
        /// The error type returned when a checked integral type conversion fails.
        TryFromIntError(TryFromIntError),
        /// The error type returned when a floating point value is outside the range
        /// of the integer type it needs to be converted to.
        FloatToInt,
    }
    impl From<TryFromIntError> for [< TryFrom $name Error >] {
        fn from(e: TryFromIntError) -> Self {
            Self::TryFromIntError(e)
        }
    }
}

It gives this compiler error:

error: unexpected token: `stringify`
   --> src\base\def_macro.rs:714:9
    |
714 | /         paste::item! {
715 | |             /// The error type returned when a checked
716 | |             #[doc = $name_str]
717 | |             /// type conversion fails.
...   |
730 | |             }
731 | |         }
    | |_________^
    | 
   ::: src\base.rs:40:1

The $name_str is passed into this invocation as stringify!($name). This works just fine if done outside of a paste::item!, so there must be something going on in the interaction between paste::item!, stringify! and/or #[doc].

It does not work with #[doc = stringify!($name)] either (same exact error), but #[doc = "a regular string"] works just fine.

Ident concatenation doesn't work

Greetings!

Ident concatenation doesn't work for some reason:

macro_rules! gen_limit {
    ($name:ident, $limit:literal) => {
        paste::paste! {
            let [<number_of_ $name>] = std::env::var(stringify!([<NUMBER_OF_ $name:upper>]))
                .as_deref()
                .unwrap_or($limit)
                .parse::<usize>()
                .expect(concat!("Wrong ", stringify!([<NUMBER_OF_ $name:upper>])));
        }
    };
}

fn main() {
    gen_limit!(test, "100");
    println!("{number_of_test}");
}
error[E0425]: cannot find value `number_of_test` in this scope
  --> src/main.rs:15:16
   |
15 |     println!("{number_of_test}");
   |                ^^^^^^^^^^^^^^ not found in this scope

error: aborting due to previous error

For more information about this error, try `rustc --explain E0425`.
error: could not compile `playground` due to 2 previous errors
Process finished with exit code 101

But without it everything work fine:

macro_rules! gen_limit {
    ($name:ident, $limit:literal) => {
        paste::paste! {
            let $name = std::env::var(stringify!([<$name:upper>]))
                .as_deref()
                .unwrap_or($limit)
                .parse::<usize>()
                .expect(concat!("Wrong ", stringify!([<$name:upper>])));
        }
    };
}

fn main() {
    gen_limit!(number_of_test, "100");
    println!("{number_of_test}");
}
100

Generate doc-comments based on provided tokens

Would it be possible to use paste as a workaround for rust-lang/rust#52607? I was thinking you could add a :stringify modifier which will wrap the concatenated text in a string literal.

Imagine being able to write something like this:

macro_rules! func {
  ($name:ident, $ret:ident) => {
    /// Create a new [`
    #[doc = [< $ret:stringify >] ]
    /// `] object.
    pub fn $name() -> $ret { todo!() }
  }
}

func!(foo, Bar);

// expands to

/// Create a new [`Bar`] object.
pub fn foo() -> Bar { todo!() }

This is kinda related to #29 in that we're playing with #[doc] attributes, with the difference being where the string comes from. In that issue it comes from stringify!($name) in a previous macro invocation, but here we'd be using paste to generate the doc string directly.

Pasted identifier may not refer to a captured local variable

This is a consequence of hygiene rules.

extern crate paste;

fn main() {
    let yy = 0;

    paste::expr! {
        println!("{}", [<y y>]);
    }
}
error[E0425]: cannot find value `yy` in this scope                                                                             
 --> src/main.rs:6:5                                                                                                           
  |                                                                                                                            
6 | /     paste::expr! {                                                                                                       
7 | |         println!("{}", [<y y>]);                                                                                         
8 | |     }                                                                                                                    
  | |_____^ not found in this scope

no_std support

Like the title says, could you support #![no_std] environment?

CamelCase conversion

Hi,

I need the exact opposite of $var:snake:
$var:camel to convert snake_case input to CamelCase

Thank you for your great work!

Possible to use bracket inside a paste expansion?

I've got a use case where I need to do something like this:

[< <T>::read_ $type>](&buf)

And, from what I can tell, it seems like paste! might not like the nested brackets. The error I get when building is:

expected one of `(`, `::`, `<`, `>`, or `as`

Is this supported and I'm just missing something? Or is this not possible in paste!?

Identifier case conversion

Use case provided to me by email:

macro_rules! ld_r16_expr {
    ($($reg:ident)*) => {
        $(
            paste::item! {
                pub fn [<ld_ $reg _expr>] (val: Expr) -> Token {
                    token_for_opcode_two_args(
                        Mnemonic::Ld,
                        Register16::$reg.into(),
                        val.into(),
                    )
                }
            }
        )*
    }
}

ld_r16_expr!(Af Bc De Hl);

We would like some way to end up with functions ld_af_expr ld_bc_expr etc rather than ld_Af_expr ld_Bc_expr.

I would be be prepared to consider a PR implementing this as something like [<ld_ $reg:lower _expr>].

Build errors following the release of `1.0.9`

Thank you for your work on this crate! It's very useful for building HALs :)

Unfortunately with the release of 1.0.9 our builds over at a esp-hal have begun failing. The builds were working yesterday, and today we get this output:
https://gist.github.com/jessebraham/8fe1d8575c923e788a799262736a7a5e

I cloned this repo and set a local path for [patch.crates-io.paste], and I'm able to reproduce the build errors. Changing let mut contains_paste = false to true instead results in the build succeeding. I'm not really familiar with the inner workings of the crate and this does not seem like a solution, but I'm hoping it may help locate the problem.

pub fn paste(input: TokenStream) -> TokenStream {
    let mut contains_paste = false;
    let flatten_single_interpolation = true;
    match expand(
        input.clone(),
        &mut contains_paste,
        flatten_single_interpolation,
    ) {
        Ok(expanded) => {
            if contains_paste {
                expanded
            } else {
                input
            }
        }
        Err(err) => err.to_compile_error(),
    }
}

"Arbitrary expressions aren't allowed in patterns" error

Looks like some backwards incompatible changes (semver breaking) were included in recent releases.

Since at least v0.1.15v0.1.13 a down stream crate breaks with the following:

error: expected one of `...`, `..=`, `..`, `=>`, `if`, or `|`, found `..='f' | 'A'`
  --> src/json_parser.rs:21:1
   |
21 | / literals! {
22 | |     pub WhitespaceChar => '\u{0020}' | '\u{000D}' | '\u{000A}' | '\u{0009}';
23 | |     pub SignChar => '+' | '-';
24 | |     pub NegativeSignChar => '-';
...  |
35 | |     pub CloseSquareBracketChar => ']';
36 | | }
   | |_^ expected one of `...`, `..=`, `..`, `=>`, `if`, or `|`
   |
   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)

error: arbitrary expressions aren't allowed in patterns
  --> src/json_parser.rs:22:27
   |
22 |     pub WhitespaceChar => '\u{0020}' | '\u{000D}' | '\u{000A}' | '\u{0009}';
   |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: arbitrary expressions aren't allowed in patterns
  --> src/json_parser.rs:23:21
   |
23 |     pub SignChar => '+' | '-';
   |                     ^^^^^^^^^

error: arbitrary expressions aren't allowed in patterns
  --> src/json_parser.rs:25:18
   |
25 |     pub EChar => 'E' | 'e';
   |                  ^^^^^^^^^

error: arbitrary expressions aren't allowed in patterns
  --> src/json_parser.rs:26:26
   |
26 |     pub OneToNineChar => '1' ..= '9';
   |                          ^^^^^^^^^^^

error: arbitrary expressions aren't allowed in patterns
  --> src/json_parser.rs:27:22
   |
27 |     pub DigitChar => '0' ..= '9';
   |                      ^^^^^^^^^^^

error[E0369]: no implementation for `char | char`
  --> src/json_parser.rs:22:38
   |
22 |     pub WhitespaceChar => '\u{0020}' | '\u{000D}' | '\u{000A}' | '\u{0009}';
   |                           ---------- ^ ---------- char
   |                           |
   |                           char

error[E0369]: no implementation for `char | char`
  --> src/json_parser.rs:23:25
   |
23 |     pub SignChar => '+' | '-';
   |                     --- ^ --- char
   |                     |
   |                     char

error[E0369]: no implementation for `char | char`
  --> src/json_parser.rs:25:22
   |
25 |     pub EChar => 'E' | 'e';
   |                  --- ^ --- char
   |                  |
   |                  char

error[E0308]: mismatched types
  --> src/json_parser.rs:21:1
   |
21 | / literals! {
22 | |     pub WhitespaceChar => '\u{0020}' | '\u{000D}' | '\u{000A}' | '\u{0009}';
23 | |     pub SignChar => '+' | '-';
24 | |     pub NegativeSignChar => '-';
...  |
35 | |     pub CloseSquareBracketChar => ']';
36 | | }
   | | ^
   | | |
   | |_expected `char`, found struct `std::ops::RangeInclusive`
   |   this expression has type `char`
   |
   = note: expected type `char`
            found struct `std::ops::RangeInclusive<char>`
   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0308]: mismatched types
  --> src/json_parser.rs:21:1
   |
21 | / literals! {
22 | |     pub WhitespaceChar => '\u{0020}' | '\u{000D}' | '\u{000A}' | '\u{0009}';
23 | |     pub SignChar => '+' | '-';
24 | |     pub NegativeSignChar => '-';
...  |
35 | |     pub CloseSquareBracketChar => ']';
36 | | }
   | | ^
   | | |
   | |_expected `char`, found struct `std::ops::RangeInclusive`
   |   this expression has type `char`
   |
   = note: expected type `char`
            found struct `std::ops::RangeInclusive<char>`
   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)

code link:
https://github.com/xlc/lite-json/blob/82d863506b652790c49df9b0fa0ceda87f600ee0/parser/src/parser.rs#L237-L256

Update

  • Added full error log and link to relevant code
  • Last working version: 0.1.12

Cannot use with an expr containing "::": expected identifier after `:`

I want to use this crate to template function names that are not in the current module.
It's because I have a weird use-case where I have routes like get_blob, get_blob_2level, ... here.

This example speaks for itself:

/// calls ${fn}(), ${fn}_1(), ${fn}_2()
macro_rules! super_caller {
    ($fn:expr) => {
        paste::paste! {
            $fn();
            [< $fn _1 >]();
            [< $fn _2 >]();
        }
    }
}

fn toto() {}
fn toto_1() {}
fn toto_2() {}

fn main() {
    super_caller!(toto); // OK
    super_caller!(crate::toto); // expected identifier after `:`
}

Add repository topics

I'll probably forget that this exists by the time I'll need it so let's make this repository more discoverable :)

Can't paste together `use` import

I'm trying to construct an identifier of a namespace from parts, but that does not seem to be supported.

use paste::paste;

mod test {
    const X: u32 = 2;
}

use paste!{ [< te st >] }::X;

fn main() {
    println!("Hello, world!, {}", X);
}

results in

   Compiling playground v0.0.1 (/playground)
error: expected one of `::`, `;`, or `as`, found `!`
 --> src/main.rs:7:10
  |
7 | use paste!{ [< te st >] }::X;
  |          ^ expected one of `::`, `;`, or `as`

error: aborting due to previous error

error: could not compile `playground`

https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=5cb2fb8f9b67684f1a271dd51fedffc7

Wishlist: local token identifiers?

I have some uses of paste where the same set of token pastes are repeated a few times. For example, within a macro_rules:

paste::paste! {
    struct [<$name:camel Struct>] {
      // ...
    }

    impl [<$name:camel Struct>] {
       // ...
    }

    impl SomeTrait for [<$name:camel Struct>] { ... }
}

It would be nice to have a mechanism to locally define a symbol representing the [<$name:camel Struct>] token pasting expression. I could add a new layer of macro expansion to capture that expression, but that doesn't feel like a great solution.

Is there some other existing idiom for this?

If not, then as a total straw-man suggestion for syntax, maybe something like:

paste::paste! {
    paste::define!(structname, [<$name:camel Struct>]);

    struct $structname {
    ...

Snake case preserving `/` (slash) characters

I'm attempting to use $expr:snake with a path containing slashes. My use-case is for automating tests, where test fixtures are in a hierarchical structure, and I'm auto-generating test modules based on the path I want to test:

mymacro!("some/file/path");

// I'd like this to expand to:
mod test_mymacro_some_file_path {..}

When using something like:

[< test_mymacro_ $expr:snake >]

it preserves the slash. I'm not sure what the expected/desired behavior is here; I see that the source explicitly only checks for case, not symbols, etc. Is there a way to achieve this with paste, or should I be doing something else, like using a $(path:ident)/+ pattern or something in my macro? I'm relatively new to writing macros, so apologies if I'm missing something obvious. This crate has been amazing for creating a robust test suite.

Lifetime idents support

Is it possible to create lifetimes with paste?

For example:

macro_rules! impl_types {
    ( $($ty:ident),* ) => {
        paste::paste! {
            impl<$( '[< $ty >], $ty ),*> … {}
        }
    }
}

cargo test is broken on non-x86

error[E0658]: use of unstable library feature 'stdsimd'
   --> tests/test.rs:394:29
    |
394 |                     let _ = is_x86_feature_detected!($feat);
    |                             ^^^^^^^^^^^^^^^^^^^^^^^
...
400 |     my_is_x86_feature_detected!("mmx");
    |     ----------------------------------- in this macro invocation
    |
    = note: see issue #27731 <https://github.com/rust-lang/rust/issues/27731> for more information
    = help: add `#![feature(stdsimd)]` to the crate attributes to enable
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: 
        is_x86_feature_detected can only be used on x86 and x86_64 targets.
        You can prevent it from being used in other architectures by
        guarding it behind a cfg(target_arch) as follows:
            #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] {
                if is_x86_feature_detected(...) { ... }
            }
        
   --> tests/test.rs:400:5
    |
400 |     my_is_x86_feature_detected!("mmx");
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)

This was fine on 0.1.14, but not on 0.1.15.

Doesn't work with raw idents

I tried porting the following code from mashup:

#[macro_export]
macro_rules! wrap_pymodule {
    ($module_name:ident) => {{
        use pyo3::mashup::*;

        mashup! {
            m["method"] = PyInit_ $module_name;
        }

        m! {
            &|py| unsafe { crate::PyObject::from_owned_ptr(py, "method"()) }
        }
    }};
}

Code ported to paste:

#[macro_export]
macro_rules! wrap_pymodule {
    ($module_name:ident) => {{
        pyo3::paste::expr! {
            &|py| unsafe { crate::PyObject::from_owned_ptr(py, [<PyInit_ $module_name>]()) }
        }
    }};
}

This makes the raw idents tests fail, which passes with mashup:

error: expected one of `!`, `(`, `+`, `::`, `<`, `>`, or `as`, found `r#r`
   --> tests/test_module.rs:145:24
    |
145 |     module.add_wrapped(wrap_pyfunction!(r#move))
    |                        ^^^^^^^^^^^^^^^^^^^^^^^^ expected one of 7 possible tokens here
    |
    = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)

I can create a minimal example reproducing this if required.

rav1e crashes on compiling paste for Arm64 Windows

Over at rav1e we are trying to get Arm64 Windows (aarch64-pc-windows-msvc) builds working, but right now it seems to crash on compiling paste. With #11 I tried building paste for Arm64 Windows, which succeeds (but crashes on testing). Do you guys have any idea what's going wrong?

The error from xiph/rav1e#1209 on AppVeyor.

   Compiling paste v0.1.5
error: linking with `link.exe` failed: exit code: 1112
  |
  = note: "C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\Community\\VC\\Tools\\MSVC\\14.16.27023\\bin\\HostX64\\x64\\link.exe" "/NOLOGO" "/NXCOMPAT" "/LIBPATH:C:\\Users\\appveyor\\.rustup\\toolchains\\nightly-x86_64-pc-windows-msvc\\lib\\rustlib\\aarch64-pc-windows-msvc\\lib" "C:\\projects\\rav1e\\target\\aarch64-pc-windows-msvc\\release\\deps\\rav1e-ea777a993130cf0c.rav1e.8w2jlir1-cgu.0.rcgu.o" "/OUT:C:\\projects\\rav1e\\target\\aarch64-pc-windows-msvc\\release\\deps\\rav1e-ea777a993130cf0c.exe" "/OPT:REF,ICF" "/DEBUG" "/NATVIS:C:\\Users\\appveyor\\.rustup\\toolchains\\nightly-x86_64-pc-windows-msvc\\lib\\rustlib\\etc\\intrinsic.natvis" "/NATVIS:C:\\Users\\appveyor\\.rustup\\toolchains\\nightly-x86_64-pc-windows-msvc\\lib\\rustlib\\etc\\liballoc.natvis" "/NATVIS:C:\\Users\\appveyor\\.rustup\\toolchains\\nightly-x86_64-pc-windows-msvc\\lib\\rustlib\\etc\\libcore.natvis" "/LIBPATH:C:\\projects\\rav1e\\target\\aarch64-pc-windows-msvc\\release\\deps" "/LIBPATH:C:\\projects\\rav1e\\target\\release\\deps" "/LIBPATH:C:\\Users\\appveyor\\.rustup\\toolchains\\nightly-x86_64-pc-windows-msvc\\lib\\rustlib\\aarch64-pc-windows-msvc\\lib" "C:\\Users\\appveyor\\.rustup\\toolchains\\nightly-x86_64-pc-windows-msvc\\lib\\rustlib\\aarch64-pc-windows-msvc\\lib\\libcompiler_builtins-cc0bf6ece960e8d2.rlib" "advapi32.lib" "ws2_32.lib" "userenv.lib" "msvcrt.lib"
  = note: advapi32.lib(ADVAPI32.dll) : fatal error LNK1112: module machine type 'x64' conflicts with target machine type 'ARM64'
          
error: aborting due to previous error
error: Could not compile `rav1e`.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.