Skip to content

Disable the ability to use $ as an identifier head harder #5270

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

Merged
merged 1 commit into from
Oct 28, 2016

Conversation

CodaFi
Copy link
Contributor

@CodaFi CodaFi commented Oct 13, 2016

Due to the rejection of SE-0144, this patch adds support for forming identifiers out of single dollar characters when in Swift 3 compatibility mode. Otherwise, we now suggest and allow adding backticks around dollar identifiers to make the lexer happy again.

@CodaFi CodaFi added the swift evolution pending discussion Flag → feature: A feature that has a Swift evolution proposal currently in review label Oct 13, 2016
@CodaFi
Copy link
Contributor Author

CodaFi commented Oct 13, 2016

@lattner I defer to you for a bit of code review and whether I hit everything you discussed under my last patch.

@CodaFi
Copy link
Contributor Author

CodaFi commented Oct 13, 2016

@swift-ci please smoke test.

Copy link
Member

@DougGregor DougGregor left a comment

Choose a reason for hiding this comment

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

Swift 3 is done, and (incorrectly!) accepted $ as an identifier. When in Swift 3 mode, we should continue to (silently) accept $ as an identifier so we don't break existing Swift 3 code bases. The bug fix that rejects $ as an identifier should kick in with Swift version >= 4... we should do that part regardless of the outcome of the swift-evolution discussion on $. If the proposal to make $ an identifier passes, this diagnostic will go away entirely.

// It's always an error to see a standalone $ in Swift 3.
if (LangOpts.isSwiftVersion3()) {
// Offer to replace it with '`$`'.
diagnose(tokStart, diag::expected_dollar_numeric);
Copy link
Member

Choose a reason for hiding this comment

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

I suggest flipping the polarity of this if... more detailed comment below.

return formToken(tok::unknown, tokStart);
} else{
// Else form an identifier token.
return formToken(tok::identifier, tokStart);
Copy link
Member

Choose a reason for hiding this comment

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

We should always treat it as an identifier, even after complaining, because we should recover as-if the user had accepted the Fix-It and compiled again.

Copy link
Contributor Author

@CodaFi CodaFi Oct 24, 2016

Choose a reason for hiding this comment

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

It looks like if I take that route we backtrack over this diagnostic and double-emit while parsing the unqualified decl name for print(_:). Recovery is bad, I give you that, but the diagnostics that are emitted do give the user quite a bit of context as to where, how, and why the parser isn't happy.

"expected named member of numeric literal", ())
"expected named member of numeric literal", ())
NOTE(suggest_backtick_dollar_identifier,none,
"to use '$' as an identifier use backticks to escape it", ())
Copy link
Member

Choose a reason for hiding this comment

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

I think you should fold the error and note together, and put the Fix-It on the error itself. Perhaps wording of something like:

'$' is not an identifier; use backticks ($) to escape it

// expected-note@-1 {{to use '$' as an identifier use backticks to escape it}} {{9-10=`$`}}
// expected-error@-2 {{expression resolves to an unused function}}
// expected-error@-3 {{expected identifier in class declaration}}
// expected-error@-4 {{braced block of statements is an unused closure}}
Copy link
Member

Choose a reason for hiding this comment

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

The recovery will be a whole lot nicer when we pretend as if it were escaped.

@jdfweb
Copy link

jdfweb commented Oct 13, 2016

Awesome

@CodaFi CodaFi force-pushed the going-toe-to-toe-on-bird-law branch from 7bd5367 to 5047d20 Compare October 24, 2016 16:27
@CodaFi CodaFi changed the title Re-enable the ability to use $ as an identifier head Disable the ability to use $ as an identifier head harder Oct 24, 2016
@CodaFi CodaFi force-pushed the going-toe-to-toe-on-bird-law branch 2 times, most recently from e651e89 to c4a9f92 Compare October 24, 2016 17:45
@CodaFi
Copy link
Contributor Author

CodaFi commented Oct 24, 2016

@swift-ci please smoke test.

// Else offer to replace '$' with '`$`'.
diagnose(tokStart, diag::standalone_dollar_identifier)
.fixItReplaceChars(getSourceLoc(tokStart), getSourceLoc(CurPtr), "`$`");
return formToken(tok::unknown, tokStart);
Copy link
Member

Choose a reason for hiding this comment

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

Please still return this as tok::identifier for recovery purposes.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Even with the double diagnostic?

Copy link
Member

Choose a reason for hiding this comment

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

I was hoping we could find a way to suppress the double diagnostic. If we return tok::unknown, that code is basically a parsing train-wreck, and we get no more useful diagnostics out of it. If we return tok::identifier, everything else works fine except that there are a few Fix-Its to apply. The latter is a much better experience, particularly in Xcode where one can "Fix All In Scope".

I think the lexer has a general problem with diagnostics and backtracking. It wouldn't be totally unreasonable to hold on to a set of locations at which diagnostics were emitting, and check that right before emitting the diagnostics.

@rintaro
Copy link
Member

rintaro commented Oct 26, 2016

I'm a little concerned about this change, in very edge case.
Consider:

func foo(`$`: Int) {}
foo(`$`: 42)

This might lead a warning loop, no?

warning: keyword '$' does not need to be escaped in argument list
warning: '$' is not an identifier; use backticks to escape it

Maybe, we should add "$" in swift::canBeArgumentLabel (lib/Basic/StringExtras.cpp)

@CodaFi
Copy link
Contributor Author

CodaFi commented Oct 26, 2016

Thanks for bringing that up, I'll patch it and add it to the tests.

@rintaro
Copy link
Member

rintaro commented Oct 26, 2016

As for "double diagnostic",
I think we can handle that by creating DiagnosticTransaction along with BacktrackingScope.
Here's the patch.
master...rintaro:backtrackingscope-diagtransaction
@DougGregor Do you think it's reasonable?

@DougGregor
Copy link
Member

Yeah, adding a DiagnosticTransaction is a great way to fix this. Thanks, @rintaro !

When in Swift 3 Compatibility Mode we now acceptable a standalone
'$' as an identifier.  In all other cases this is now disallowed
and must be surrounded by backticks.
@CodaFi CodaFi force-pushed the going-toe-to-toe-on-bird-law branch from 5f523f0 to 6accc59 Compare October 27, 2016 20:51
@CodaFi
Copy link
Contributor Author

CodaFi commented Oct 27, 2016

Done.

@swift-ci please smoke test.

@CodaFi
Copy link
Contributor Author

CodaFi commented Oct 27, 2016

@DougGregor How's it look?

Copy link
Member

@DougGregor DougGregor left a comment

Choose a reason for hiding this comment

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

Looks great!

@DougGregor DougGregor merged commit bd71e63 into swiftlang:master Oct 28, 2016
@CodaFi CodaFi deleted the going-toe-to-toe-on-bird-law branch October 29, 2016 04:40
@AnthonyLatsis AnthonyLatsis removed the swift evolution pending discussion Flag → feature: A feature that has a Swift evolution proposal currently in review label Mar 22, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants