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

Detect async visibility wrong order, async pub #76447

Merged
merged 3 commits into from
Mar 18, 2021

Conversation

pickfire
Copy link
Contributor

@pickfire pickfire commented Sep 7, 2020

Partially address #76437.

@rust-highfive
Copy link
Collaborator

r? @nikomatsakis

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

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Sep 7, 2020
@pickfire
Copy link
Contributor Author

pickfire commented Sep 7, 2020

niko is probably the wrong reviewer for this maybe

r? @estebank

@jyn514 jyn514 added A-diagnostics Area: Messages for errors, warnings, and lints T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. A-parser Area: The parsing of Rust source code to an AST labels Sep 7, 2020
Copy link
Contributor

@estebank estebank left a comment

Choose a reason for hiding this comment

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

I would prefer to make this change to parse_fn_front_matter:

/// Parses all the "front matter" (or "qualifiers") for a `fn` declaration,
/// up to and including the `fn` keyword. The formal grammar is:
///
/// ```
/// Extern = "extern" StringLit ;
/// FnQual = "const"? "async"? "unsafe"? Extern? ;
/// FnFrontMatter = FnQual? "fn" ;
/// ```
pub(super) fn parse_fn_front_matter(&mut self) -> PResult<'a, FnHeader> {
let constness = self.parse_constness();
let asyncness = self.parse_asyncness();
let unsafety = self.parse_unsafety();
let ext = self.parse_extern()?;
if let Async::Yes { span, .. } = asyncness {
self.ban_async_in_2015(span);
}
if !self.eat_keyword(kw::Fn) {
// It is possible for `expect_one_of` to recover given the contents of
// `self.expected_tokens`, therefore, do not use `self.unexpected()` which doesn't
// account for this.
if !self.expect_one_of(&[], &[])? {
unreachable!()
}
}
Ok(FnHeader { constness, unsafety, asyncness, ext })
}

That way the parser can recover more gracefully and you also have the spans for each element to work with more easily. You could also check for other permutations, like async const pub fn and unsafe async fn.

| ^^^
| |
| expected one of 9 possible tokens
| help: visibility `pub` must come before `pub pub`: `pub pub pub`
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is weird, but at least users can know that visibility is duplicated. We could add a check but I probably don't want to do it in this patch.

@pickfire
Copy link
Contributor Author

pickfire commented Sep 8, 2020

What's left for another patch

extern "C" pub

error: expected `{`, found keyword `pub`
 --> test.rs:1:16
  |
1 |     extern "C" pub fn t() {}
  |                ^^^ expected `{`

error: aborting due to previous error

unsafe const and the other permutations

error: expected one of `extern` or `fn`, found keyword `const`
 --> test.rs:1:12
  |
1 |     unsafe const pub fn t() {}
  |            ^^^^^ expected one of `extern` or `fn`

error: aborting due to previous error

Duplicate visibility (this one is obvious unlike the rest)

error: expected one of `(`, `async`, `const`, `default`, `extern`, `fn`, `pub`, `unsafe`, or `use`, found keyword `pub`
  --> $DIR/duplicate-visibility.rs:4:9
   |
LL | extern {
   |        - while parsing this item list starting here
LL |     pub pub fn foo();
   |         ^^^
   |         |
   |         expected one of 9 possible tokens
   |         help: visibility `pub` must come before `pub pub`: `pub pub pub`
LL |
LL | }
   | - the item list ends here

error: aborting due to previous error

@pickfire pickfire force-pushed the async-pub branch 2 times, most recently from 2e9de38 to 2c6ae2d Compare September 9, 2020 09:07
@pickfire
Copy link
Contributor Author

pickfire commented Sep 9, 2020

tidy error: /checkout/src/test/ui/parser/default.rs:24: line longer than 100 chars
tidy error: /checkout/src/test/ui/parser/duplicate-visibility.rs:5: line longer than 100 chars

I don't know how to fix this without using // ignore tidy-line-length, asking in another group.

@pickfire
Copy link
Contributor Author

@estebank Do you know how should I fix this?

@jyn514
Copy link
Member

jyn514 commented Sep 14, 2020

I would add the // ignore-tidy-linelength if it's just a test, rustdoc does this for all the intra-doc link tests.

@pickfire
Copy link
Contributor Author

@estebank Can you please help to review again?

Comment on lines 6 to 10
LL | default pub fn foo<T: Default>() -> T { T::default() }
| ^^^ non-item starts here
...
| ^^^
| |
| expected one of 7 possible tokens
| help: visibility `pub` must come before `default pub`: `pub default pub`
Copy link
Contributor

Choose a reason for hiding this comment

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

Only one nitpick: this suggestion is incorrect. The span should point at default pub and the suggestion content should be pub default.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

pub default? Can you show me an example output you mentioned? I don't think default pub should be there, it should be pub only right?

Copy link
Contributor

Choose a reason for hiding this comment

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

Actually, it should be only default, as pub is implied, but yes the correct syntactic order is pub default fn foo().

Copy link
Contributor Author

Choose a reason for hiding this comment

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

How should I check that? It doesn't seemed to be part of parse_fn_front_matter but rather in parse_fn_kind, I think it is related to

} else if self.check_fn_front_matter() {
    // FUNCTION ITEM
    let (ident, sig, generics, body) = self.parse_fn(attrs, req_name, lo)?;
    (ident, ItemKind::Fn(def(), sig, generics, body))

It feels weird that defaultness is not parsed as part of parse_fn_front_matter.

I feel lazy to do this, requires cleaning on other parts, @estebank do you want to do it?

Copy link
Contributor Author

@pickfire pickfire Dec 7, 2020

Choose a reason for hiding this comment

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

This should be fixed. I didn't know this is a regression created by the patch I made.

@JohnCSimon JohnCSimon 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 Oct 19, 2020
@JohnCSimon
Copy link
Member

ping from triage:
@pickfire this conversation seems to have stalled out, can you address the comments or ping the reviewer for clarification?

@pickfire
Copy link
Contributor Author

I haven't get myself to work on the last thing the reviewer mentioned.

I think it may be a bit different from where I worked on this, it would be good if @estebank could point out where needs to be changed, I feel less motivated to work on the remaining parts either since this may need changes in other parts. If @estebank want to work on this then he can take this up, otherwise I can take a look at it this weekend.

@Dylan-DPC-zz
Copy link

@pickfire can you resolve the conflict ? will be faster as we can get a review and then merge it quickly

@rust-log-analyzer

This comment has been minimized.

@pickfire
Copy link
Contributor Author

@Dylan-DPC done

@bors
Copy link
Contributor

bors commented Feb 25, 2021

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

@JohnCSimon
Copy link
Member

triage: @pickfire unfortunately there's another merge conflict.
Can you please resolve this and set it to S-waiting-on-review ? Thank you.

@JohnCSimon
Copy link
Member

@rustbot label: -S-waiting-on-review +S-waiting-on-author

@rustbot rustbot 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 Mar 16, 2021
@pickfire
Copy link
Contributor Author

@JohnCSimon Do I have to keep on updating it? I am thinking of getting a review first before updating it, I have updated a few times in the past for merge conflict but still no review.

@Dylan-DPC-zz
Copy link

@pickfire better to, makes it easier to merge if the review is green after that

Redirects `const? async? unsafe? pub` to `pub const? async? unsafe?`.

Fix rust-lang#76437
async-pub check created a regression for default
@JohnTitor JohnTitor 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 Mar 17, 2021
@estebank
Copy link
Contributor

@pickfire my apologies. I believed I could get around this to point you towards an alternative way of doing this, but there's no reason not to merge this as is and potentially implement my idea later.

So it isn't lost to the corners of my mind, my thinking here was to make the parser advance through tokens that can be part of the fn front matter (fn, pub, async, etc) and keep track of whether they've been found and whether they are in the right order. If not, construct an appropriate front matter string and suggest that in the error. Doing that would get us for free support for fixing things like async fn pub async foo() without any extra effort.

@bors r+

@bors
Copy link
Contributor

bors commented Mar 18, 2021

📌 Commit 21c1574 has been approved by estebank

@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-review Status: Awaiting review from the assignee but also interested parties. labels Mar 18, 2021
@bors
Copy link
Contributor

bors commented Mar 18, 2021

⌛ Testing commit 21c1574 with merge 81c1d7a...

@bors
Copy link
Contributor

bors commented Mar 18, 2021

☀️ Test successful - checks-actions
Approved by: estebank
Pushing 81c1d7a to master...

@bors bors added the merged-by-bors This PR was explicitly merged by bors. label Mar 18, 2021
@bors bors merged commit 81c1d7a into rust-lang:master Mar 18, 2021
@rustbot rustbot added this to the 1.52.0 milestone Mar 18, 2021
@pickfire
Copy link
Contributor Author

So it isn't lost to the corners of my mind, my thinking here was to make the parser advance through tokens that can be part of the fn front matter (fn, pub, async, etc) and keep track of whether they've been found and whether they are in the right order. If not, construct an appropriate front matter string and suggest that in the error. Doing that would get us for free support for fixing things like async fn pub async foo() without any extra effort.

Ah, but it seems like something that we aren't going to need. Why would someone duplicate the header? I don't see any reason someone would do so. Order I can understand if they are wrong, but maybe duplicating them is too much I believe. Maybe I am wrong, if people copy pasted it could happen, but we may need extra care not to slow down the usual path.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-diagnostics Area: Messages for errors, warnings, and lints A-parser Area: The parsing of Rust source code to an AST 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. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.