Skip to content

Fix num-macros FromPrimitive implementation#228

Merged
homu merged 7 commits into
masterfrom
fix/num-macros
Sep 30, 2016
Merged

Fix num-macros FromPrimitive implementation#228
homu merged 7 commits into
masterfrom
fix/num-macros

Conversation

@hauleth

hauleth commented Sep 18, 2016

Copy link
Copy Markdown
Member Author

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

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

@hauleth

hauleth commented Sep 18, 2016

Copy link
Copy Markdown
Member Author

cc @cuviper

@cuviper

cuviper commented Sep 18, 2016

Copy link
Copy Markdown
Member

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

hauleth commented Sep 18, 2016

Copy link
Copy Markdown
Member Author

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

cuviper commented Sep 18, 2016

Copy link
Copy Markdown
Member

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

hauleth commented Sep 18, 2016

Copy link
Copy Markdown
Member Author

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

bluss commented Sep 18, 2016

Copy link
Copy Markdown
Contributor

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

@hauleth

hauleth commented Sep 18, 2016

Copy link
Copy Markdown
Member Author

@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

hauleth commented Sep 18, 2016

Copy link
Copy Markdown
Member Author

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

@bluss

bluss commented Sep 18, 2016

Copy link
Copy Markdown
Contributor

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

bluss commented Sep 18, 2016

Copy link
Copy Markdown
Contributor

#229 is the fix

@hauleth

hauleth commented Sep 18, 2016

Copy link
Copy Markdown
Member Author

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

homu commented Sep 18, 2016

Copy link
Copy Markdown
Contributor

☔ 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

cuviper commented Sep 19, 2016

Copy link
Copy Markdown
Member

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

@hauleth

hauleth commented Sep 19, 2016

Copy link
Copy Markdown
Member Author

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

@dtolnay

dtolnay commented Sep 24, 2016

Copy link
Copy Markdown

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

bluss commented Sep 26, 2016

Copy link
Copy Markdown
Contributor

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.

@cuviper cuviper left a comment

Copy link
Copy Markdown
Member

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.

Comment thread macros/src/lib.rs Outdated
if let Some(val) = variant.discriminant {
idx = val.value;
}
let tt = quote!(#idx => Some(#name::#ident));

@cuviper cuviper Sep 27, 2016

Copy link
Copy Markdown
Member

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
Copy Markdown
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
Copy Markdown
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.

Comment thread macros/Cargo.toml Outdated
plugin = true
[dependencies]
quote = "0.1.3"
syn = "0.6.0"

Copy link
Copy Markdown
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
Copy Markdown

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

cuviper commented Sep 27, 2016 via email

Copy link
Copy Markdown
Member

Comment thread macros/Cargo.toml Outdated
[lib]
crate-type = ["rustc-macro"]
name = "num_macros"
rustc-macro = true

Copy link
Copy Markdown

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
Copy Markdown
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

hauleth commented Sep 27, 2016

Copy link
Copy Markdown
Member Author

@cuviper all done.

@dtolnay

dtolnay commented Sep 27, 2016

Copy link
Copy Markdown

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

cuviper commented Sep 27, 2016

Copy link
Copy Markdown
Member

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

cuviper commented Sep 27, 2016

Copy link
Copy Markdown
Member

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

@hauleth

hauleth commented Sep 27, 2016

Copy link
Copy Markdown
Member Author

@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

dtolnay commented Sep 27, 2016

Copy link
Copy Markdown

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

cuviper commented Sep 27, 2016

Copy link
Copy Markdown
Member

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

hauleth commented Sep 28, 2016

Copy link
Copy Markdown
Member Author

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

@cuviper

cuviper commented Sep 30, 2016

Copy link
Copy Markdown
Member

@homu r+ b7e6407

@homu

homu commented Sep 30, 2016

Copy link
Copy Markdown
Contributor

⚡ 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