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

Implement tool_attributes feature (RFC 2103) #47773

Closed
wants to merge 7 commits into from

Conversation

topecongiro
Copy link
Contributor

This PR implements a tool_attributes feature. If this implementaion is acceptable, I am going to create a similar PR that implements tool_lints.

This PR only adds rustfmt and clippy to known tool name list. The list resides in libsyntax/attr.rs.

cc #44690.

r? @nrc

@petrochenkov petrochenkov self-assigned this Jan 26, 2018
@petrochenkov petrochenkov added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Jan 26, 2018
@topecongiro
Copy link
Contributor Author

Hmm. Should I add the section to the unstable book after this PR is merged, or am I missing something? I followed the instruction in https://forge.rust-lang.org/feature-guide.html.

@kennytm
Copy link
Member

kennytm commented Jan 26, 2018

@topecongiro The problem is that unstable book file should be written in hyphenated lower case. Try to rename it as tool-attributes.md.

@topecongiro
Copy link
Contributor Author

@kennytm Thank you!

#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub struct MetaItem {
pub name: Name,
pub name: MetaItemName,
pub node: MetaItemKind,
pub span: Span,
Copy link
Contributor

@petrochenkov petrochenkov Jan 27, 2018

Choose a reason for hiding this comment

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

Contents of ast::Attribute and ast::MetaItem are the same thing by definition, but in the compiler they diverged significantly in recent months.
An attribute is a "macro invocation" that consists of a Path and a TokenStream, MetaItem should have the same structure and they should share code, ideally.
I'd rather do this refactoring instead of adding temporary hacks like Vec<Name>, preferably in a separate PR.

(The attribute/meta-item Path goes through usual path resolution procedure, and that's where resolution of the "tool module" rustfmt or clippy should be added as well, ideally.)

Copy link
Member

@nrc nrc left a comment

Choose a reason for hiding this comment

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

This looks fine to me, but I think someone more active in compiler work should sign off too.

/// Unscoped name, e.g. `name` in `#[name(..)]`.
Single(Name),
/// Scoped name, e.g. `rustfmt::skip` in `#[rustfmt::skip]`.
Scoped(Vec<Name>),
Copy link
Member

Choose a reason for hiding this comment

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

Could we use a Path here, rather than Vec<Name>?

Copy link
Member

Choose a reason for hiding this comment

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

In fact I wonder if we could use Path instead of MetaItemName and always treat attributes as paths rather than names (we have to do this for macro attributes anyway)

@nrc
Copy link
Member

nrc commented Jan 29, 2018

r? @petrochenkov

@petrochenkov petrochenkov added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jan 29, 2018
@topecongiro
Copy link
Contributor Author

topecongiro commented Jan 29, 2018

@petrochenkov @nrc Thank you for you reviews!

So I am going to replace MetaItemName with Path, and move the tool name checking from feature_gate.rs to somewhere in parser code.

EDIT: I actually kept the tool name checking in feature_gate.rs.

@@ -708,6 +708,22 @@ pub trait PrintState<'a> {
Ok(())
}

fn print_attribute_path(&mut self, path: &ast::Path) -> io::Result<()> {
Copy link
Contributor

Choose a reason for hiding this comment

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

Looks like existing print_path can be used instead of introducing this new function.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

print_path is not a method of PrintState trait, so I am not sure how to exploit it. Should I write like self.writer().word(&path_to_string(path))?

@petrochenkov
Copy link
Contributor

The Travis CI build failed

rustdoc build fails

let (span, name) = match tokens.next() {
Some(TokenTree::Token(span, Token::Ident(ident))) => (span, ident.name),
let name = match tokens.next() {
Some(TokenTree::Token(span, Token::Ident(ident))) => {
Copy link
Contributor

Choose a reason for hiding this comment

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

This looks like an imitation of parse_path, but I don't know how make the normal version and tokenstream version reuse the same code.
Could you leave a FIXME comment here?

@@ -1972,26 +1972,6 @@ impl<'a> Parser<'a> {
Ok(ast::Path { segments, span: lo.to(self.prev_span) })
}

/// Like `parse_path`, but also supports parsing `Word` meta items into paths for back-compat.
Copy link
Contributor

Choose a reason for hiding this comment

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

Where does this special back-compat support of Word meta items happen now?

Copy link
Contributor

Choose a reason for hiding this comment

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

Oh, wait parse_path_allowing_meta is reintroduced in the next commit.

@@ -205,6 +211,10 @@ impl NestedMetaItem {
}
}

fn name_from_path(path: &ast::Path) -> Name {
path.segments.iter().next().unwrap().identifier.name
Copy link
Contributor

Choose a reason for hiding this comment

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

Could you use the last segment instead?
In #[a::b::c] a and b are modules (possibly "tool modules") in which the attribute c is defined, and the last segment c is the attribute itself.

added to it in the future",
attr.path));
if attr.is_scoped() {
gate_feature!(self, tool_attributes, attr.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 solution is 100% technical debt, but I guess it can work while everything is unstable, and we go into this branch only if previous ways to resolve the attribute failed.

I described the proper solution in rust-lang/rfcs#2103 (comment).
TLDR: a::b::c in #[a::b::c(...)] should be resolved as a usual path in macro namespace and therefore rustfmt and clippy should be added into the language prelude as special modules (primitive types u8, u16, etc work in very similar way).
I don't suggest to implement this now though.

Copy link
Contributor

Choose a reason for hiding this comment

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

I don't suggest to implement this now though.

But I suggest to implement this eventually, if you plan to continue working on macros/attributes and name resolution in rustc.

self.parse_sess.span_diagnostic,
attr.span,
E0693,
"An unkown tool name found in scoped attributes: `{}`.",
Copy link
Contributor

Choose a reason for hiding this comment

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

Typo "unkown" -> "unknown"

@topecongiro
Copy link
Contributor Author

@petrochenkov Thank you for your reviews and I am sorry for the late reply. I hope that I can update this PR today...

@petrochenkov
Copy link
Contributor

@bors r+

@bors
Copy link
Contributor

bors commented Feb 4, 2018

📌 Commit 30214c9 has been approved by petrochenkov

@kennytm kennytm added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Feb 4, 2018
@bors
Copy link
Contributor

bors commented Feb 4, 2018

⌛ Testing commit 30214c90d560ddc3b6e83992f34afb340dd43d5e with merge cac046403a27dd42eb53ef8b9c94801592a12b5d...

@bors
Copy link
Contributor

bors commented Feb 4, 2018

💔 Test failed - status-travis

@topecongiro
Copy link
Contributor Author

Rebased against master.

I have a problem reproducing the above failures locally... running ./x.py test src/test/run-pass-fulldeps/ does succeed without any failure.

@kennytm kennytm added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Feb 12, 2018
@petrochenkov
Copy link
Contributor

@topecongiro
This is actually a pretty-printing test, not run-pass-fulldeps test itself.
This should be reproducible with ./x.py test src/test/run-pass-fulldeps/pretty.

It is possible that this is an expected pretty-printer failure, then you can disable the test with // ignore-pretty if you are sure this is not this PR's fault.

@petrochenkov petrochenkov added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Feb 12, 2018
@topecongiro
Copy link
Contributor Author

@petrochenkov Thank you for your advice, I could reproduce this locally.

I cannot tell whether this is an expected pretty-printer failure or not. I looked at the original PR that added this test (#40346). It looks like now arbitrary tokens could appear as arguments to procedural macros. So I guess that this PR is trying to parse random tokens inside procedural macros as some valid paths when it shouldn't? Again, I am not sure, though.

self.parse_sess.span_diagnostic,
attr.span,
E0693,
"An unknown tool name found in scoped attributes: `{}`.",
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: error messages conventionally start with a lower-case letter.
(Same in the feature gate message below.)

@petrochenkov
Copy link
Contributor

@topecongiro
Pretty-printed code from run-pass-fulldeps/proc-macro/derive-b is identical before and after this PR, so the only difference is how name resolution treats B in #[cfg_attr(all(), B arbitrary tokens)].

I don't quite see where is the difference in name resolution comes from. Please make sure the logic for single-segment attribute paths is identical to what it was before. For example, fn name previously returned None for multi-segment attribute paths and now it's always successful, maybe it unintendedly makes difference somewhere.

@pietroalbini
Copy link
Member

@topecongiro can you fix that failing test so the PR can be merged?

@bors
Copy link
Contributor

bors commented Feb 25, 2018

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

@shepmaster
Copy link
Member

Thank you for your hard work, @topecongiro ! However, we haven't heard from you in a few weeks, so I'm going to close this PR for now to keep the queue tidy. Please feel free to reopen this when you have a chance to fix the merge conflicts and the failing test.

@shepmaster shepmaster closed this Mar 2, 2018
@shepmaster shepmaster added S-inactive Status: Inactive and waiting on the author. This is often applied to closed PRs. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Mar 2, 2018
bors added a commit that referenced this pull request May 3, 2018
Implement tool_attributes feature (RFC 2103)

cc #44690

This is currently just a rebased and compiling (hopefully) version of #47773.

Let's see if travis likes this. I will add the implementation for `tool_lints` this week.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-inactive Status: Inactive and waiting on the author. This is often applied to closed PRs.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants