Skip to content

Commit

Permalink
Merge #39
Browse files Browse the repository at this point in the history
39: Provide nicer parse errors and suggest "full-syntax" r=cuviper a=cuviper

The included `compile_fail` test has this output:

```
error: expected `,`
  --> src/test.rs:13:24
   |
10 |     VarA = get_an_isize!(), // error without "syn/full"
   |                        ^

error: this might need the "full-syntax" feature of `num-derive`
 --> src/test.rs:11:10
  |
8 | #[derive(num_derive::FromPrimitive)]
  |          ^^^^^^^^^^^^^^^^^^^^^^^^^
  |
  = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
```

Closes #16.

Co-authored-by: Josh Stone <[email protected]>
  • Loading branch information
bors[bot] and cuviper authored Jul 29, 2020
2 parents ed849ab + 522017c commit 77c551f
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 9 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ categories = [ "science" ]
license = "MIT/Apache-2.0"
name = "num-derive"
repository = "https://github.com/rust-num/num-derive"
version = "0.3.0"
version = "0.3.1"
readme = "README.md"
exclude = ["/bors.toml", "/ci/*", "/.github/*"]
edition = "2018"
Expand Down
6 changes: 6 additions & 0 deletions RELEASES.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
# Release 0.3.1 (2020-07-28)

- [Provide nicer parse errors and suggest "full-syntax"][39]

[39]: https://github.com/rust-num/num-derive/pull/39

# Release 0.3.0 (2019-09-27)

- [Updated the `proc-macro2`, `quote`, and `syn` dependencies to 1.0][28],
Expand Down
38 changes: 30 additions & 8 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,26 @@ use proc_macro2::{Span, TokenStream as TokenStream2};
use quote::quote;
use syn::{Data, Fields, Ident};

/// Try to parse the tokens, or else return a compilation error
/// suggesting "full-syntax" if that's not already enabled.
macro_rules! parse {
($tokens:ident as $type:ty) => {
match syn::parse::<$type>($tokens) {
Ok(parsed) => parsed,
Err(mut error) => {
if cfg!(not(feature = "full-syntax")) {
let hint = syn::Error::new(
Span::call_site(),
r#"this might need the "full-syntax" feature of `num-derive`"#,
);
error.combine(hint);
}
return TokenStream::from(error.to_compile_error());
}
}
};
}

// Within `exp`, you can bring things into scope with `extern crate`.
//
// We don't want to assume that `num_traits::` is in scope - the user may have imported it under a
Expand Down Expand Up @@ -230,7 +250,7 @@ impl NumTraits {
/// ```
#[proc_macro_derive(FromPrimitive, attributes(num_traits))]
pub fn from_primitive(input: TokenStream) -> TokenStream {
let ast: syn::DeriveInput = syn::parse(input).unwrap();
let ast = parse!(input as syn::DeriveInput);
let name = &ast.ident;

let import = NumTraits::new(&ast);
Expand Down Expand Up @@ -388,7 +408,7 @@ pub fn from_primitive(input: TokenStream) -> TokenStream {
/// ```
#[proc_macro_derive(ToPrimitive, attributes(num_traits))]
pub fn to_primitive(input: TokenStream) -> TokenStream {
let ast: syn::DeriveInput = syn::parse(input).unwrap();
let ast = parse!(input as syn::DeriveInput);
let name = &ast.ident;

let import = NumTraits::new(&ast);
Expand Down Expand Up @@ -509,7 +529,7 @@ const NEWTYPE_ONLY: &str = "This trait can only be derived for newtypes";
/// `Output=Self`.
#[proc_macro_derive(NumOps)]
pub fn num_ops(input: TokenStream) -> TokenStream {
let ast: syn::DeriveInput = syn::parse(input).unwrap();
let ast = parse!(input as syn::DeriveInput);
let name = &ast.ident;
let inner_ty = newtype_inner(&ast.data).expect(NEWTYPE_ONLY);
let impl_ = quote! {
Expand Down Expand Up @@ -553,7 +573,7 @@ pub fn num_ops(input: TokenStream) -> TokenStream {
/// [num_cast]: https://docs.rs/num-traits/0.2/num_traits/cast/trait.NumCast.html
#[proc_macro_derive(NumCast, attributes(num_traits))]
pub fn num_cast(input: TokenStream) -> TokenStream {
let ast: syn::DeriveInput = syn::parse(input).unwrap();
let ast = parse!(input as syn::DeriveInput);
let name = &ast.ident;
let inner_ty = newtype_inner(&ast.data).expect(NEWTYPE_ONLY);

Expand All @@ -575,7 +595,7 @@ pub fn num_cast(input: TokenStream) -> TokenStream {
/// [zero]: https://docs.rs/num-traits/0.2/num_traits/identities/trait.Zero.html
#[proc_macro_derive(Zero, attributes(num_traits))]
pub fn zero(input: TokenStream) -> TokenStream {
let ast: syn::DeriveInput = syn::parse(input).unwrap();
let ast = parse!(input as syn::DeriveInput);
let name = &ast.ident;
let inner_ty = newtype_inner(&ast.data).expect(NEWTYPE_ONLY);

Expand All @@ -600,7 +620,7 @@ pub fn zero(input: TokenStream) -> TokenStream {
/// [one]: https://docs.rs/num-traits/0.2/num_traits/identities/trait.One.html
#[proc_macro_derive(One, attributes(num_traits))]
pub fn one(input: TokenStream) -> TokenStream {
let ast: syn::DeriveInput = syn::parse(input).unwrap();
let ast = parse!(input as syn::DeriveInput);
let name = &ast.ident;
let inner_ty = newtype_inner(&ast.data).expect(NEWTYPE_ONLY);

Expand All @@ -625,7 +645,7 @@ pub fn one(input: TokenStream) -> TokenStream {
/// [num]: https://docs.rs/num-traits/0.2/num_traits/trait.Num.html
#[proc_macro_derive(Num, attributes(num_traits))]
pub fn num(input: TokenStream) -> TokenStream {
let ast: syn::DeriveInput = syn::parse(input).unwrap();
let ast = parse!(input as syn::DeriveInput);
let name = &ast.ident;
let inner_ty = newtype_inner(&ast.data).expect(NEWTYPE_ONLY);

Expand All @@ -649,7 +669,7 @@ pub fn num(input: TokenStream) -> TokenStream {
/// [float]: https://docs.rs/num-traits/0.2/num_traits/float/trait.Float.html
#[proc_macro_derive(Float, attributes(num_traits))]
pub fn float(input: TokenStream) -> TokenStream {
let ast: syn::DeriveInput = syn::parse(input).unwrap();
let ast = parse!(input as syn::DeriveInput);
let name = &ast.ident;
let inner_ty = newtype_inner(&ast.data).expect(NEWTYPE_ONLY);

Expand Down Expand Up @@ -834,3 +854,5 @@ pub fn float(input: TokenStream) -> TokenStream {

import.wrap("Float", &name, impl_).into()
}

mod test;
31 changes: 31 additions & 0 deletions src/test.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
//! This module uses doc-tests on modules for `compile_fail`
// We need "syn/full" to parse macros.
// Use `--nocapture` to check the quality of the error message.
#[cfg(not(feature = "full-syntax"))]
/// ```compile_fail
/// macro_rules! get_an_isize {
/// () => (0_isize)
/// }
///
/// #[derive(num_derive::FromPrimitive)]
/// pub enum CLikeEnum {
/// VarA = get_an_isize!(), // error without "syn/full"
/// VarB = 2,
/// }
/// ```
mod issue16 {}

#[cfg(feature = "full-syntax")]
/// ```
/// macro_rules! get_an_isize {
/// () => (0_isize)
/// }
///
/// #[derive(num_derive::FromPrimitive)]
/// pub enum CLikeEnum {
/// VarA = get_an_isize!(), // ok with "syn/full"
/// VarB = 2,
/// }
/// ```
mod issue16 {}

0 comments on commit 77c551f

Please sign in to comment.