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

rustc_parse: restore public visibility on parse_attribute #79433

Merged
merged 1 commit into from
Nov 27, 2020

Conversation

calebcartwright
Copy link
Member

Make parse_attribute public as rustfmt is a downstream consumer. Refs #78782 (comment)

r? @petrochenkov

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Nov 26, 2020
Permitted,
Forbidden { reason: &'a str, saw_doc_comment: bool, prev_attr_sp: Option<Span> },
}

const DEFAULT_UNEXPECTED_INNER_ATTR_ERR_MSG: &str = "an inner attribute is not \
permitted in this context";

pub(super) const DEFAULT_INNER_ATTR_FORBIDDEN: InnerAttrPolicy<'_> = InnerAttrPolicy::Forbidden {
// Public for rustfmt usage
pub const DEFAULT_INNER_ATTR_FORBIDDEN: InnerAttrPolicy<'_> = InnerAttrPolicy::Forbidden {
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 think rustfmt need to report these errors?
It could always pass InnerAttrPolicy::Permitted instead, and keep this constant private.

Copy link
Member Author

Choose a reason for hiding this comment

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

We only use this parse_attribute function within a special case handling of cfg_if, and in this case immediately following the if kw. AIUI an inner attribute is not allowed here, which I presume is why we were passing false as the arg to the parse_attribute function before, which in turn applied the DEFAULT_INNER_ATTR_FORBIDDEN policy.

Are you saying we should still use the Permitted variant anyway?

https://github.com/rust-lang/rustfmt/blob/003786228d65135b9bae20a260caefc0248eb375/src/syntux/parser.rs#L225-L233

Copy link
Contributor

@petrochenkov petrochenkov Nov 26, 2020

Choose a reason for hiding this comment

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

I mean the only effect of setting InnerAttrPolicy::Forbidden is a call to span_err, which results in nothing in rustfmt?
I don't see any error diagnosticss when run rustfmt even on a wildly syntactically incorrect piece of Rust code.
So it shouldn't matter which argument is passed.

Copy link
Member Author

Choose a reason for hiding this comment

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

I don't see any error diagnosticss when run rustfmt even on a wildly syntactically incorrect piece of Rust code.

Are you speaking in general/categorical terms or specifically within a cfg_if block? By any chance do you have hide_parse_errors enabled?

There are indeed a handful of cases were rustfmt forcibly suppresses the diagnostic detail, but in most cases the diagnostics are emitted (and the cases where we suppress have proven to be an occasional source of confusion for our users)

$ echo "pub struct S" | rustfmt
error: expected `where`, `{`, `(`, or `;` after struct name, found `<eof>`
 --> <stdin>:1:12
  |
1 | pub struct S
  |            ^ expected `where`, `{`, `(`, or `;` after struct name

And current behavior even within a cfg_if block would be for the forbidden inner attr error message to be displayed:

$ rustfmt --version
rustfmt 1.4.24-stable (eb894d5 2020-11-05)
$ cat src/lib.rs 
cfg_if! {
    if #![cfg(any(target_arch = "x86", target_arch = "x86_64"))] {
        println!("x86");
    } else if #[cfg(target_arch = "arm")] {
        println!("ARM");
    } else {
        // Unimplemented architecture:
        println!("unimplemented");
    }
}
$ rustfmt src/lib.rs --check
error: an inner attribute is not permitted in this context
 --> /home/caleb/dev/rustfmt-sandbox/cfg-if-inner/src/lib.rs:2:8
  |
2 |     if #![cfg(any(target_arch = "x86", target_arch = "x86_64"))] {
  |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  |
  = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.

However, and perhaps to your point, while an inner attribute here is invalid that doesn't impact our ability to parse the contained items which is really what we're after on the rustfmt side. There's a few other cases of invalid syntax where we're still able to get the info needed for formatting and carry on anyway, so I think it's fair we do the same here (though it would be a slight behavior change).

I am a bit concerned that you aren't seeing any error diagnostics though, so any additional info you could share would be greatly appreciated!

Copy link
Contributor

Choose a reason for hiding this comment

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

Ok, I used a wrong snipped previously.
I do see errors from the cfg_if! example above.
Why on earth does rustfmt reports them though? It's not its job?

Copy link
Contributor

Choose a reason for hiding this comment

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

(Anyway, rustfmt is not obliged to report errors and this specific error doesn't affect formatting in any way, so it can be omitted.)

Copy link
Member Author

Choose a reason for hiding this comment

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

Why on earth does rustfmt reports them though? It's not its job?

Generally speaking rustfmt doesn't suppress parser errors so that it doesn't silently fail and exit without giving users any inclination as to why it was unable to format. Since rustfmt works directly with the AST we're reliant on the parsing calls to succeed so that we have something valid/safe to reformat. However, in cases like this where invalid syntax doesn't impact formatting one way or the other, it really isn't necessary to emit and we can suppress/skip emission; user's will be informed whenever they actually run rustc.

(Anyway, rustfmt is not obliged to report errors and this specific error doesn't affect formatting in any way, so it can be omitted.)

Agreed! Will update momentarily

Copy link
Member Author

Choose a reason for hiding this comment

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

Went ahead and squashed into a single commit vs adding a separate one for this, as the diff is so tiny

@@ -8,16 +8,18 @@ use rustc_span::{sym, Span};

use tracing::debug;

// Public for rustfmt usage
Copy link
Contributor

Choose a reason for hiding this comment

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

You cannot make this private if parse_attribute is public, so the comment seems unnecessary.

Copy link
Member Author

Choose a reason for hiding this comment

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

I can remove this if you'd prefer, but I've been trying to be very explicit about calling out instances where rustfmt ends up needing a higher visibility on something within the compiler than what would've been done otherwise.

Naturally the public visibility on the function requires this to be public as well, and in this case the two happen to be in the same file and fairly close together. However, I just think that for anyone looking at this code down the road and wondering "why is this enum public?" that it's beneficial to have the inline comment in context vs. having to do a search to find the comment on the function or reducing the visibility to try to let the compiler tell them.

Let me know how you'd like to proceed

Copy link
Contributor

Choose a reason for hiding this comment

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

Ok, leaving this at your discretion.

@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 Nov 26, 2020
@petrochenkov
Copy link
Contributor

Thanks for the explanation!
@bors r+ rollup

@bors
Copy link
Contributor

bors commented Nov 26, 2020

📌 Commit 5930a8a has been approved by petrochenkov

@bors bors 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 Nov 26, 2020
@bors
Copy link
Contributor

bors commented Nov 27, 2020

⌛ Testing commit 5930a8a with merge 361543d...

@bors
Copy link
Contributor

bors commented Nov 27, 2020

☀️ Test successful - checks-actions
Approved by: petrochenkov
Pushing 361543d to master...

@bors bors added the merged-by-bors This PR was explicitly merged by bors. label Nov 27, 2020
@bors bors merged commit 361543d into rust-lang:master Nov 27, 2020
@rustbot rustbot added this to the 1.50.0 milestone Nov 27, 2020
@calebcartwright calebcartwright deleted the parse-attr-vis branch June 4, 2021 01:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
merged-by-bors This PR was explicitly merged by bors. S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants