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

Move feature check from lexer to binder. #57113

Merged
merged 3 commits into from
Oct 13, 2021

Conversation

CyrusNajmabadi
Copy link
Member

Note: this is not part of more work to do this in other locations.

This change is very specific as the way this current check works is complex, difficult to sustain for raw-string-literals, and also (IMO) violates how the lexer/parser should work.

Specifically, the lexer, today, needs to recurse back into itself when dealing with interpolated string literals. It does this both at lex time (to make the initial token and figure out interpolation boundaries), and it then does it again when teh parser comes in and makes the real InterpolationExpressionSyntax. As such, it is both confusing, and error-prone for errors to be added here in the interpolation holes as both the lexer and parser take over the same responsibility. Indeed, it is necessary for these lexer errors to not bubble up as they must get reported now by the parser. This complicates lexing (esp. interpolation lexing) by effectively making it so that some errors are reported internally, but not bubbled up. And some errors are reported internally, stored, and bubbled up to the parser.

I do not want to try to maintain/duplicate that conceptual complexity. As such, i'm moving this logic entirely to the binder. This has the benefit of reverse-smearing things. What was three checks, with a complex relation betwen them, becomes one simple check.

@@ -18,6 +18,10 @@ internal partial class Binder
{
private BoundExpression BindInterpolatedString(InterpolatedStringExpressionSyntax node, BindingDiagnosticBag diagnostics)
{
var startText = node.StringStartToken.Text;
if (startText.StartsWith("@$\""))
CheckFeatureAvailability(node, MessageID.IDS_FeatureAltInterpolatedVerbatimStrings, diagnostics, node.StringStartToken.GetLocation());
Copy link
Member Author

Choose a reason for hiding this comment

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

one single check in one location.

if (feature == MessageID.IDS_FeatureAltInterpolatedVerbatimStrings)
{
return new CSDiagnosticInfo(ErrorCode.ERR_AltInterpolatedVerbatimStringsNotAvailable, new CSharpRequiredLanguageVersion(feature.RequiredVersion()));
}
Copy link
Member Author

Choose a reason for hiding this comment

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

preserves the special error message we give here (the parser used to special case this as well).

if (isAltInterpolatedVerbatim)
{
openQuote = CheckFeatureAvailability(openQuote, MessageID.IDS_FeatureAltInterpolatedVerbatimStrings);
}
Copy link
Member Author

Choose a reason for hiding this comment

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

parser check.

@@ -771,7 +771,6 @@ private void ScanSyntaxToken(ref TokenInfo info)
else if (TextWindow.PeekChar(1) == '$' && TextWindow.PeekChar(2) == '"')
{
this.ScanInterpolatedStringLiteral(isVerbatim: true, ref info);
CheckFeatureAvailability(MessageID.IDS_FeatureAltInterpolatedVerbatimStrings);
Copy link
Member Author

Choose a reason for hiding this comment

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

lexer check #1. intended to be overridden by parser.

@@ -628,7 +628,6 @@ private void ScanInterpolatedStringLiteralHoleBalancedText(char endingChar, bool
}
else if (_lexer.TextWindow.PeekChar(1) == '$' && _lexer.TextWindow.PeekChar(2) == '"')
{
_lexer.CheckFeatureAvailability(MessageID.IDS_FeatureAltInterpolatedVerbatimStrings);
Copy link
Member Author

Choose a reason for hiding this comment

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

lexer check #2, during recursive interpolated string lexing. Intended to be overridden by parser.

return availableVersion >= requiredVersion
? node
: this.AddError(node, ErrorCode.ERR_AltInterpolatedVerbatimStringsNotAvailable,
new CSharpRequiredLanguageVersion(requiredVersion));
Copy link
Member Author

Choose a reason for hiding this comment

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

@CyrusNajmabadi
Copy link
Member Author

@dotnet/roslyn-compiler @jcouv for another set of eyes. Thanks!

@CyrusNajmabadi CyrusNajmabadi merged commit 241ed70 into dotnet:main Oct 13, 2021
@ghost ghost added this to the Next milestone Oct 13, 2021
@CyrusNajmabadi CyrusNajmabadi deleted the moveFeatureCheck branch October 13, 2021 23:44
@CyrusNajmabadi
Copy link
Member Author

Thanks!

@jcouv
Copy link
Member

jcouv commented Oct 14, 2021

Please remember to squash compiler changes. Thanks

@RikkiGibson RikkiGibson modified the milestones: Next, 17.1.P1 Oct 25, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants