-
Notifications
You must be signed in to change notification settings - Fork 12.9k
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
Account for missing keyword in fn/struct definition #45997
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, looking more closely, I think this is overkill. I'll leave a more detailed comment with an alternative shortly.
Currently, after failing to parse, the parser invokes this commonly used method: rust/src/libsyntax/parse/parser.rs Lines 6267 to 6275 in ce2b8a4
This is intended to look for a macro use like I think we should customize what happens when we "expect" this To start, we can look at the path. If it was multipart, like If the path is a single identifier, we can then examine the next character: if it is |
It is reasonable to go ahead and do that change, but I also feel there's value in modifying the current PR to keep doing what it is doing and returning |
@estebank that's a good point. On the other hand, I wonder, could we get a similar effect by just skipping over entire token trees? I feel like only being able to recover when the input is perfect is perhaps not ideal. |
though man but mismatched braces are the worst sort of parse errors =) |
In any case, I could go either way. But I'd like to see us able to recover even from something like this: pub foo(x: u32) {
x->foo(); // whoops, too much C++
} |
#41282 already implemented this recovery for trait and impl items, it can be adapted to normal items as well. |
I have modified the code to not perform the rewind. The outwards behavior now is similar to what it already was (the parser will not let the compiler to continue, but it will try to consume the continuing code in order to identify what it was meant (fn or struct), regardless of code errors (just looks for enclosed |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This all looks quite cool. I do have one concern about the recovery condition I'd like to get resolved though.
| | ||
help: add `fn` here to parse `foo` as a public method | ||
| | ||
11 | pub fn foo(s: usize) { bar() } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
that is pretty slick =)
// Verify wether we have encountered a struct or method definition where the user forgot to | ||
// add the `struct` or `fn` keyword after writing `pub`: `pub S {}` | ||
if visibility == Visibility::Public && | ||
self.check_ident() && |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't it possible these days to have paths to macros? e.g., foo::bar!
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The way the fall back happens, if the code isn't either pub foo (
or pub foo {
, the current macro handling will happen. In the case of pub foo::bar
this new branch will not be executed. As long as parse_macro_use_or_failure
does the right thing with paths, this should be fine :)
610cf72
to
35fbdd4
Compare
When encountering `pub ident`, attempt to identify the code that comes afterwards, wether it is a brace block (assume it is a struct), a paren list followed by a colon (assume struct) or a paren list followed by a block (assume a fn). Consume those blocks to avoid any further parser errors and return a `Placeholder` item in order to allow the parser to continue. In the case of unenclosed blocks, the behavior is the same as it is currently: no further errors are processed.
Try to identify the following code in order to provide better diagnostics, but return the error to bail out early during the parse.
@bors try |
⌛ Trying commit f103342 with merge 1026513cc276e201297365f43014ee01b2df9b06... |
@nikomatsakis this PR is ballooning in size with multiple independent changes that are kind or related but not entirely. There's a very small one liner suggestion underline fix, emitting inappropriate Because of these changes, in the case of As for the first paragraph, should I try to split this in a bunch of different dependent PRs? Edit: I have fixed the issue for all proc macros now: made it check the error count before and after and emit the appropriate diagnostic if it has increased. This should be resilient to further changes in the parser, although it will leak parsing errors from the proc macro to the user. I feel that this is not a bad thing, even if it was an unintended effect originally. |
@nikomatsakis let me know if the output changes are reasonable or if I should keep working on this PR to get to minimal changes from the status quo. |
📌 Commit cf9283e has been approved by |
Account for missing keyword in fn/struct definition Fix #38911.
☀️ Test successful - status-appveyor, status-travis |
…henkov Suggest an appropriate token when encountering `pub Ident<'a>` Fix rust-lang#55403. Follow up to rust-lang#45997.
self.check(&token::OpenDelim(token::Brace)) | ||
{ | ||
("fn", "method", false) | ||
} else if self.check(&token::Colon) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@estebank sorry for the enormous necropost, but do you know what the idea behind this was? It matches pub foo(stuff):
and suggests adding struct
, but where does that colon come from? Is it possible this was intended to be token::Semi
instead? The behaviour isn't covered by any tests, unfortunately.
Fix #38911.