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

Feature gate clean #32791

Merged
merged 5 commits into from
Apr 28, 2016
Merged

Feature gate clean #32791

merged 5 commits into from
Apr 28, 2016

Conversation

LeoTestard
Copy link
Contributor

This PR does a bit of cleaning in the feature-gate-handling code of libsyntax. It also fixes two bugs (#32782 and #32648). Changes include:

  • Change the way the existing features are declared in feature_gate.rs. The array of features and the Features struct are now defined together by a single macro. featureck.py has been updated accordingly. Note: there are now three different arrays for active, removed and accepted features instead of a single one with a Status item to tell wether a feature is active, removed, or accepted. This is mainly due to the way I implemented my macro in the first time and I can switch back to a single array if needed. But an advantage of the way it is now is that when an active feature is used, the parser only searches through the list of active features. It goes through the other arrays only if the feature is not found. I like to think that error checking (in this case, checking that an used feature is active) does not slow down compilation of valid code. :) But this is not very important...
  • Feature-gate checking pass now use the Features structure instead of looking through a string vector. This should speed them up a bit. The construction of the Features struct should be faster too since it is build directly when parsing features instead of calling has_feature dozens of times.
  • The MacroVisitor pass has been removed, it was mostly useless since the #[cfg]-stripping phase happens before (fixes Invocation of feature-gated macros inside #[cfg]-guarded code is not checked. #32648). The features that must actually be checked before expansion are now checked at the time they are used. This also allows us to check attributes that are generated by macro expansion and not visible to MacroVisitor, but are also removed by macro expansion and thus not visible to PostExpansionVisitor either. This fixes Attributes on macro-generated macro invocations are not feature-gate-checked #32782. Note that in order for #[derive_*] to be feature-gated but still accepted when generated by #[derive(Trait)], I had to do a little bit of trickery with spans that I'm not totally confident into. Please review that part carefully. (It's in libsyntax_ext/deriving/mod.rs.)::

Note: this is a [breaking change], since programs with feature-gated attributes on macro-generated macro invocations were not rejected before. For example:

macro_rules! bar (
    () => ()
);

macro_rules! foo (
    () => (
        #[allow_internal_unstable] //~ ERROR allow_internal_unstable side-steps
        bar!();
    );
);

foo!();

@rust-highfive
Copy link
Collaborator

r? @nrc

(rust_highfive has picked a reviewer for you, use r? to override)

@eddyb
Copy link
Member

eddyb commented Apr 7, 2016

cc #32655 and #32671

@LeoTestard
Copy link
Contributor Author

@eddyb: Ha, I see we used the same trick for spans for #[derive_*]. :) This reassures me a bit. What do you think we should do? Do you want to merge your own PR first and me to rebase mine? Or should we just merge that one?

@eddyb
Copy link
Member

eddyb commented Apr 7, 2016

@LeoTestard AFAICT syntex was fixed not to generate code that trips over such a check, but @nikomatsakis would still like a warning for a release cycle (old syntex output might still be around).

@LeoTestard
Copy link
Contributor Author

You mean (well, he means) generate a warning instead of an error? That sounds tricky with my approach since the check in libsyntax_ext/deriving/mod.rs now not only catches uses inside macros but also all other uses. I have no idea how to check if a use comes from a macro or not. Suggesting to run cargo update when the error comes from syntex sounds feasible though.

@eddyb
Copy link
Member

eddyb commented Apr 7, 2016

@LeoTestard the error is not "from syntex", but rather you get a file that syntex pretty-printed. I can't think of a way to distinguish that, since the actual code could be anything the user put through syntex.

@LeoTestard
Copy link
Contributor Author

Ok now it should only warn for #[derive_*] for the cases that did not error before. It's tricky and based on whether the parent of the top of the expansion backtrace points to a valid ExpnInfo and is not NO_EXPANSION. It seems to work for the few interesting cases I've tested.

Note that this PR is still a breaking change for all the other uses of feature-gated attributes that were not checked in macro expansion (see #32782) and that are now checked and just reported as errors.

r?

@bors
Copy link
Contributor

bors commented Apr 7, 2016

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

@LeoTestard LeoTestard force-pushed the feature-gate-clean branch 2 times, most recently from 7493c3c to f654c8c Compare April 7, 2016 23:28
@LeoTestard
Copy link
Contributor Author

Rebased onto master. r?
(cc @nikomatsakis @pnkfelix)

@jseyfried
Copy link
Contributor

@LeoTestard I believe this PR is only feature gate checking attributes of macros in item positions.

For example, the following would be erroneously allowed (it is an currently error):

macro_rules! method {
    () => { fn f() {} }
}

struct S;
impl S {
    #[allow_internal_unstable]
    method! {}
}

@@ -96,6 +96,36 @@ fn expand_derive(cx: &mut ExtCtxt,
let mut found_partial_eq = false;
let mut found_eq = false;

// This span is **very** sensitive and crucial to
// getting the stability behavior we want. What we are
// doing is marking `#[structural_match]` with the
Copy link
Contributor

Choose a reason for hiding this comment

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

If I understand correctly, we could also be marking #[derive_*] with this span -- the comment should probably reflect that.

@jseyfried
Copy link
Contributor

Reviewed, LGTM modulo comments.

@LeoTestard LeoTestard force-pushed the feature-gate-clean branch 2 times, most recently from 6151172 to aa36987 Compare April 9, 2016 16:01
@LeoTestard
Copy link
Contributor Author

@jseyfried Ok, I fixed what you said. I added another commit for removing useless code since it's not directly related. Let me know if you want me to squash it/rebase it/whatever.

if let Some(&Features { pushpop_unsafe: false, .. }) =
fld.cx.ecfg.features {
feature_gate::emit_feature_err(
&fld.cx.parse_sess.span_diagnostic, "pushpop_unsafe", expr_span,
Copy link
Contributor

Choose a reason for hiding this comment

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

This should be "placement_in_syntax" (Travis is failing because of this).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah I saw that but I didn't have the time to fix it earlier... I guess I copy-pasted too fast. Sorry about that.

Copy link
Contributor

Choose a reason for hiding this comment

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

No prob!

@LeoTestard LeoTestard force-pushed the feature-gate-clean branch 2 times, most recently from 2650886 to cb29b20 Compare April 9, 2016 21:38
&fld.cx.parse_sess.codemap(),
&fld.cx.ecfg.features.unwrap());
}

Copy link
Contributor

Choose a reason for hiding this comment

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

I believe we still need to stability check macros in expression and statement positions (search for drop(attrs) in this file).
I would refactor this out into a new function in expand.rs (something like check_attributes(attr: &ast::Attribute, fld: &mut MacroExpander)) and then inline and remove feature_gate::check_attribute.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Are you sure we should inline? feature_gate::Context is private for the moment...

Copy link
Contributor

Choose a reason for hiding this comment

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

Good point -- not inlining is ok

@LeoTestard
Copy link
Contributor Author

Done. r?

@nikomatsakis
Copy link
Contributor

@LeoTestard it seems like tidy doesn't build on this branch?

@LeoTestard
Copy link
Contributor Author

@nikomatsakis Huh, yeah, my bad, I thought I tested this but that was before I had to rebase it against the complete rewriting of tidy checks I guess. u__u

@LeoTestard
Copy link
Contributor Author

@nikomatsakis Fixed, I think.

This pass was supposed to check use of gated features before
`#[cfg]`-stripping but this was not the case since it in fact happens
after. Checks that are actually important and must be done before macro
expansion are now made where the features are actually used. Close rust-lang#32648.
Also ensure that attributes on macro-generated macro invocations are
checked as well. Close rust-lang#32782 and rust-lang#32655.
@nikomatsakis
Copy link
Contributor

r? @nikomatsakis

@rust-highfive rust-highfive assigned nikomatsakis and unassigned nrc Apr 28, 2016
@nikomatsakis
Copy link
Contributor

@bors r+

@bors
Copy link
Contributor

bors commented Apr 28, 2016

📌 Commit fa23d10 has been approved by nikomatsakis

@bors
Copy link
Contributor

bors commented Apr 28, 2016

⌛ Testing commit fa23d10 with merge 435095f...

bors added a commit that referenced this pull request Apr 28, 2016
Feature gate clean

This PR does a bit of cleaning in the feature-gate-handling code of libsyntax. It also fixes two bugs (#32782 and #32648). Changes include:

* Change the way the existing features are declared in `feature_gate.rs`. The array of features and the `Features` struct are now defined together by a single macro. `featureck.py` has been updated accordingly. Note: there are now three different arrays for active, removed and accepted features instead of a single one with a `Status` item to tell wether a feature is active, removed, or accepted. This is mainly due to the way I implemented my macro in the first time and I can switch back to a single array if needed. But an advantage of the way it is now is that when an active feature is used, the parser only searches through the list of active features. It goes through the other arrays only if the feature is not found. I like to think that error checking (in this case, checking that an used feature is active) does not slow down compilation of valid code. :) But this is not very important...
* Feature-gate checking pass now use the `Features` structure instead of looking through a string vector. This should speed them up a bit. The construction of the `Features` struct should be faster too since it is build directly when parsing features instead of calling `has_feature` dozens of times.
* The MacroVisitor pass has been removed, it was mostly useless since the `#[cfg]-stripping` phase happens before (fixes #32648). The features that must actually be checked before expansion are now checked at the time they are used. This also allows us to check attributes that are generated by macro expansion and not visible to MacroVisitor, but are also removed by macro expansion and thus not visible to PostExpansionVisitor either. This fixes #32782. Note that in order for `#[derive_*]` to be feature-gated but still accepted when generated by `#[derive(Trait)]`, I had to do a little bit of trickery with spans that I'm not totally confident into. Please review that part carefully. (It's in `libsyntax_ext/deriving/mod.rs`.)::

Note: this is a [breaking change], since programs with feature-gated attributes on macro-generated macro invocations were not rejected before. For example:

```rust
macro_rules! bar (
    () => ()
);

macro_rules! foo (
    () => (
        #[allow_internal_unstable] //~ ERROR allow_internal_unstable side-steps
        bar!();
    );
);
```
foo!();
@bors bors merged commit fa23d10 into rust-lang:master Apr 28, 2016
@bluss bluss added the relnotes Marks issues that should be documented in the release notes of the next release. label Apr 28, 2016
nikomatsakis added a commit to nikomatsakis/rust that referenced this pull request Nov 2, 2016
brson pushed a commit to brson/rust that referenced this pull request Nov 3, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
relnotes Marks issues that should be documented in the release notes of the next release.
Projects
None yet
8 participants