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

Fix num-macros FromPrimitive implementation #228

Merged
merged 7 commits into from
Sep 30, 2016
Merged

Fix num-macros FromPrimitive implementation #228

merged 7 commits into from
Sep 30, 2016

Conversation

@hauleth
Copy link
Member Author

hauleth commented Sep 18, 2016

Unfortunately due to bug dtolnay/syn#12 this syntax will currently fail:

#[derive(FromPrimitive)]
enum Foo {
    A = 1,
    B
}

@hauleth
Copy link
Member Author

hauleth commented Sep 18, 2016

cc @cuviper

@cuviper
Copy link
Member

cuviper commented Sep 18, 2016

Does the existing code work with that problem case? (Apart from the current nightly break.). If so, I think we should try to fix that break and add a test like that. Then when syn releases a fix for that bug, we can land this PR.

@hauleth
Copy link
Member Author

hauleth commented Sep 18, 2016

Existing code doesn't work at all as there was breaking change in compiler plugins (again) and that made num-macros uncompilable. Current version compile and works except that one case.

@cuviper
Copy link
Member

cuviper commented Sep 18, 2016

That's what I meant by the current nightly break. Can we fix that without this whole rewrite, then switch when syn is ready?

@hauleth
Copy link
Member Author

hauleth commented Sep 18, 2016

I haven't written compiler plugin even once so I am not sure if I can fix this. About this issue I can use syntex crate but this will significantly increase compile times for num-macros.

@bluss
Copy link
Contributor

bluss commented Sep 18, 2016

Syntax extensions are annoying for now that they break so often, but the fixes are usually very simple to make.

@hauleth
Copy link
Member Author

hauleth commented Sep 18, 2016

@bluss probably it is just fixing the name, but since rust-lang/rfcs#1681 was accepted I think we should jump into that train and use Macros 1.1 syntax. As you can see in the PR it makes whole code much simpler. The only problem is that syn crate need a little fix (which I cannot make because I am not the nom wizard and I always forget how to write parsers in it. However it should be also quite simple task.

@hauleth
Copy link
Member Author

hauleth commented Sep 18, 2016

We can always drop syn and use syntex instead, but AFAIK syntex compile times aren't the best.

@bluss
Copy link
Contributor

bluss commented Sep 18, 2016

Not disagreeing about the plan for the future, but fixing the num-macros nightly issue seems like the reasonable first thing to do right now.

@bluss
Copy link
Contributor

bluss commented Sep 18, 2016

#229 is the fix

@hauleth
Copy link
Member Author

hauleth commented Sep 18, 2016

So in sake of future changes:

  • this PR rename #[derive(NumFromPrimitive)] to more natural #[derive(FromPrimitive)]
  • user should use #![feature(rustc_macro)] instead of #![feature(custom_derive, plugin)]
  • user should use #[macro_use] extern crate num_macros; instead of #![plugin(num_macros)]

In future it should also be allowed to use #[macro_use] extern crate num; and also be able to use custom derives.

@homu
Copy link
Contributor

homu commented Sep 18, 2016

☔ The latest upstream changes (presumably #229) made this pull request unmergeable. Please resolve the merge conflicts.

@hauleth hauleth modified the milestone: v0.2.0 Sep 18, 2016
@cuviper
Copy link
Member

cuviper commented Sep 19, 2016

BTW, how did you get that "code broken after change" list? Is crater available to us now?

@hauleth
Copy link
Member Author

hauleth commented Sep 19, 2016

@cuviper no, just GitHub search and copy&paste 😄

@dtolnay
Copy link

dtolnay commented Sep 24, 2016

I fixed the syn enum parsing issue in 0.6.0. Sorry for the slow response - I was away without internet access for a week.

@bluss
Copy link
Contributor

bluss commented Sep 26, 2016

cargo-crusader was kind of a bare bones "crater" for rdeps, but it errors when I try to use it nowadays. Not sure if there was a crates.io api change or what happened.

Copy link
Member

@cuviper cuviper left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is your list of breakages solved by the new syn, or are there still other problems?

We should do better about rejecting enums with data in them.

The old code also rejected empty enums, which are weird but sometimes found in FFI for opaque structs.

if let Some(val) = variant.discriminant {
idx = val.value;
}
let tt = quote!(#idx => Some(#name::#ident));
Copy link
Member

@cuviper cuviper Sep 27, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remember that enums can have data too, but FromPrimitive only makes sense for integral enums. It looks like that's where Variant.data is VariantData::Unit. If any variant is something else, we need to reject the whole thing.

For instance, try adding something like Other(u8, u8, u8) to one of the Color tests. It does get an error, but it's a very confusing one:

error[E0308]: mismatched types
  --> tests/trivial.rs:18:1
   |
18 | enum Color {
   | ^ expected enum `Color`, found fn item
   |
   = note: expected type `Color`
   = note:    found type `fn(u8, u8, u8) -> Color {Color::Other}`

The derivation tried to output Some(Color::Other) here, but that's actually a type constructor, not a value in itself, which is why the error is talking about a fn. Similarly if it were Other{ r:u8, g:u8, b:u8 } you get the error struct called like a function. We should catch this up front to identify the root problem.

We could use compiletest-rs to have some negative tests.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh yeah, I have forgotten about that.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added better error message and compiletest-rs crate to test against invalid code.

plugin = true
[dependencies]
quote = "0.1.3"
syn = "0.6.0"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's even 0.7 now. Don't know if it matters to us, but we probably should try to keep up.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't bother trying to keep up for now. I am sprinting to get serde codegen working with syn (serde-rs/serde#548) so there may be another break coming up. When serde is done I will make a PR here bumping the version and fixing anything I broke (although I doubt there would be anything affecting the code in this PR). Also starting with the next release I will start doing proper release notes explaining the changes.

@cuviper
Copy link
Member

cuviper commented Sep 27, 2016 via email

[lib]
crate-type = ["rustc-macro"]
name = "num_macros"
rustc-macro = true
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From what I have seen in serde, this line is sufficient. You don't need crate-type = ["rustc-macro"] and #![crate_type = "rustc-macro"]. Is there a reason to have those?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

None, but it isn't harmful in any way and this helps with visibility (you do not need to check Cargo.toml for crate type, it is already there).

@hauleth
Copy link
Member Author

hauleth commented Sep 27, 2016

@cuviper all done.

@dtolnay
Copy link

dtolnay commented Sep 27, 2016

I haven't reviewed carefully but I just want to say what a massive improvement in readability of lib.rs, nicely done. Once this merges I will link to this from the syn and quote readmes as an example of how to do things right.

@cuviper
Copy link
Member

cuviper commented Sep 27, 2016

You didn't answer my question about the "Code broken after change" status, but I suppose they must still be broken since you changed the derivation name. Let's back that change out and save it for 0.2, so we can merge the syn rewrite now.

@cuviper
Copy link
Member

cuviper commented Sep 27, 2016

Or if you really want the new name now, add a derivation by the old name too for compatibility.

@hauleth
Copy link
Member Author

hauleth commented Sep 27, 2016

@cuviper it is and will be broken even if I keep the name as "requiring" syntax has changed.

Ex.

Old

#![features(plugin, custom_derive)]
#![plugin(num_macros)]

extern crate num;

#[derive(FromPrimitive)]
enum Foo { Bar }

// ...

New

#![features(rustc_macro)]

#[use_macros] extern crate num_macros;
extern crate num;

#[derive(FromPrimitive)]
enum Foo { Bar }

So either way it is still breaking change.

@dtolnay
Copy link

dtolnay commented Sep 27, 2016

For serde we decided to keep "serde_macros" as the feature(plugin) one and use "serde_derive" as the feature(rustc_macro) one. I think "derive" is a lot more evocative in terms of how the crate is used, and "macros" just happens to be an implementation detail of Rust.

@cuviper
Copy link
Member

cuviper commented Sep 27, 2016

OK, I'd be fine with forking num_macros into a syn-based num_derive crate, and leave the former alone. That would also make it easier to show side-by-side for your syn case study. :)

@hauleth
Copy link
Member Author

hauleth commented Sep 28, 2016

Ok. I have moved it to new crate num-derived and restored old num-macros.

@cuviper
Copy link
Member

cuviper commented Sep 30, 2016

@homu r+ b7e6407

@homu
Copy link
Contributor

homu commented Sep 30, 2016

⚡ Test exempted - status

@hauleth hauleth deleted the fix/num-macros branch October 1, 2016 19:16
remexre pushed a commit to remexre/num that referenced this pull request Jun 1, 2017
Add a short example to `<Value as Index>::index`
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

Successfully merging this pull request may close these issues.

5 participants