-
Notifications
You must be signed in to change notification settings - Fork 4.2k
Fix issue parsing for-statement initializer chain with commas and no initializers #77184
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
Fix issue parsing for-statement initializer chain with commas and no initializers #77184
Conversation
|
@dotnet/roslyn-compiler ptal. |
Is the intent of this Refers to: src/Compilers/CSharp/Portable/Parser/LanguageParser.cs:5067 in 3d427cd. [](commit_id = 3d427cd, deletion_comment = False) |
We def can't remove the entire if-block as it is necessary to know how to process a variable-declarator in a for-statement (where it must be followed by a I tried removing the |
This When that block is removed, the only compiler tests named |
|
Yes. If we remove the error recovery logic tweaks from before, all the code that tests that those error recovery tweaks produce less errors and a nicer tree demonstrate the worse outcome. :) In the case of the 'comma' tests, they demonstrate that the parser loses control very quickly when encountering the errant With the error recovery the syntax/semantic errors are only: Without the error recovery, the syntax/semantic errors are: First, this is much more noise, with lots of strange errors. Why am i being told that 'i' is already declared here? Why am i being told it is never used? Second, the recommended fixes are not great. I'm being told i'm missing a semicolon before the '<' and that Compare with the original case where the error is correct and tells the person exactly the right thing to fixup (a comma needs to become a semicolon). There are also no errant cascading errors/warnings that clutter and obfuscate the original issue. Yes, we can roll back the error recovery improvement here. But i'm loathe to do that as this does genuinely make things better in terms of the UX and for the downstream clients of the syntax tree. |
| public void TestMultipleDeclaratorsWithExpression1() | ||
| { | ||
| UsingStatement(""" | ||
| for (Console.WriteLine("Blah"); true;) |
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.
I was being serious about having more comprehensive testing of other possible forms. For example, let's look at something like: for (MyType m = new() { A = 1,; true; m++). We need to have a bunch of test additions here to make sure that we've adequately covered this testing gap.
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.
sgtm.
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.
added a lot more tets.
| // (1,15): error CS1002: ; expected | ||
| // for (int i = 0, i) ; | ||
| Diagnostic(ErrorCode.ERR_InvalidExprTerm, ")").WithArguments(")").WithLocation(1, 18), | ||
| Diagnostic(ErrorCode.ERR_SemicolonExpected, ",").WithLocation(1, 15), |
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 is a better result, as this is illegal code, andth e vast majority of the time, this code is hte precursor to int i = 0; i ... so stating that the comma should be a semicolon is a better error.
| Diagnostic(ErrorCode.ERR_SyntaxError, "for").WithArguments("foreach").WithLocation(1, 1), | ||
| // (1,18): error CS1026: ) expected | ||
| // for (from a in b select c;from a in b select c;from a in b select c); | ||
| Diagnostic(ErrorCode.ERR_CloseParenExpected, "select").WithLocation(1, 18)); |
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 is surprising, and likely a parsing bug (though practically impossible for it to matter in practice). It looks like we see from a and think that that's the start of a variable declarator (with type from and identifier a).
| Diagnostic(ErrorCode.ERR_InvalidExprTerm, "ref a").WithArguments("ref").WithLocation(1, 13), | ||
| // (1,20): error CS1525: Invalid expression term 'ref' | ||
| // for (ref a; ref a; ref a); | ||
| Diagnostic(ErrorCode.ERR_InvalidExprTerm, "ref a").WithArguments("ref").WithLocation(1, 20)); |
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.
also surprising, but not really a problem. the strict ang grammar truly does not allow 'ref' here. We could support parsing this, but would have to then ensure binding errors. a s this is extremely unlikely to be written, no need to do extra work here.
| public void TestVariousExpressions_With1() | ||
| { | ||
| UsingStatement(""" | ||
| for (a with { }; a with { }; a with { }) |
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.
similar issue, parser sees this as a var decl for a with with a as the type and with as the name. As this is vastly unlikely to be ever written, fixing this seems unnecessary.
| else if (this.CurrentToken.Kind == SyntaxKind.CommaToken) | ||
| { | ||
| // If we see `for (int i = 0, j < ...` then we do not want to consume j as the next declarator. | ||
| // If we see `for (int i = 0, i < ...` then we do not want to the second 'i' as the next declarator as it |
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.
Consider testing: Refers to: src/Compilers/CSharp/Test/Syntax/Parsing/ForStatementParsingTest.cs:4449 in 310bde0. [](commit_id = 310bde0, deletion_comment = False) |
|
/backport release/dev17.13 |
|
/backport to release/dev17.13 |
|
Started backporting to release/dev17.13: https://github.com/dotnet/roslyn/actions/runs/13549852813 |
Fixes #77160