mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Disable the ability to use '$' as an identifier harder
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.
This commit is contained in:
@@ -995,6 +995,8 @@ ERROR(dollar_numeric_too_large,none,
|
||||
"numeric value following '$' is too large", ())
|
||||
ERROR(numeric_literal_numeric_member,none,
|
||||
"expected named member of numeric literal", ())
|
||||
ERROR(standalone_dollar_identifier,none,
|
||||
"'$' is not an identifier; use backticks to escape it", ())
|
||||
|
||||
ERROR(anon_closure_arg_not_in_closure,none,
|
||||
"anonymous closure argument not contained in a closure", ())
|
||||
|
||||
@@ -28,7 +28,8 @@ using namespace swift;
|
||||
using namespace camel_case;
|
||||
|
||||
bool swift::canBeArgumentLabel(StringRef identifier) {
|
||||
if (identifier == "var" || identifier == "let" || identifier == "inout")
|
||||
if (identifier == "var" || identifier == "let" || identifier == "inout" ||
|
||||
identifier == "$")
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
||||
@@ -474,7 +474,7 @@ static bool isValidIdentifierContinuationCodePoint(uint32_t c) {
|
||||
static bool isValidIdentifierStartCodePoint(uint32_t c) {
|
||||
if (!isValidIdentifierContinuationCodePoint(c))
|
||||
return false;
|
||||
if (c < 0x80 && (isDigit(c) || c == '$'))
|
||||
if (c < 0x80 && isDigit(c))
|
||||
return false;
|
||||
|
||||
// N1518: Recommendations for extended identifier characters for C and C++
|
||||
@@ -819,10 +819,15 @@ void Lexer::lexDollarIdent() {
|
||||
}
|
||||
}
|
||||
|
||||
// It's always an error to see a standalone $
|
||||
if (CurPtr == tokStart + 1) {
|
||||
diagnose(tokStart, diag::expected_dollar_numeric);
|
||||
return formToken(tok::unknown, tokStart);
|
||||
// It is always an error to see a standalone '$' when not in Swift 3
|
||||
// compatibility mode.
|
||||
if (!LangOpts.isSwiftVersion3()) {
|
||||
// Offer to replace '$' with '`$`'.
|
||||
diagnose(tokStart, diag::standalone_dollar_identifier)
|
||||
.fixItReplaceChars(getSourceLoc(tokStart), getSourceLoc(CurPtr), "`$`");
|
||||
}
|
||||
return formToken(tok::identifier, tokStart);
|
||||
}
|
||||
|
||||
// We reserve $nonNumeric for persistent bindings in the debugger.
|
||||
|
||||
23
test/Compatibility/dollar_identifier.swift
Normal file
23
test/Compatibility/dollar_identifier.swift
Normal file
@@ -0,0 +1,23 @@
|
||||
// RUN: %target-parse-verify-swift -swift-version 3
|
||||
|
||||
// Dollar is allowed as an identifier head in Swift 3.
|
||||
|
||||
func dollarVar() {
|
||||
var $ : Int = 42 // No error
|
||||
$ += 1
|
||||
print($)
|
||||
}
|
||||
func dollarLet() {
|
||||
let $ = 42 // No error
|
||||
print($)
|
||||
}
|
||||
func dollarClass() {
|
||||
class $ {} // No error
|
||||
}
|
||||
func dollarEnum() {
|
||||
enum $ {} // No error
|
||||
}
|
||||
func dollarStruct() {
|
||||
struct $ {} // No error
|
||||
}
|
||||
|
||||
@@ -1,29 +1,56 @@
|
||||
// RUN: %target-parse-verify-swift
|
||||
// RUN: %target-parse-verify-swift -swift-version 4
|
||||
|
||||
// SR-1661: Dollar was accidentally allowed as an identifier and identifier head.
|
||||
// SR-1661: Dollar was accidentally allowed as an identifier in Swift 3.
|
||||
// SE-0144: Reject this behavior in the future.
|
||||
|
||||
func dollarVar() {
|
||||
var $ : Int = 42 // expected-error {{expected numeric value following '$'}} expected-error {{expected pattern}}
|
||||
var $ : Int = 42 // expected-error {{'$' is not an identifier; use backticks to escape it}} {{7-8=`$`}}
|
||||
$ += 1 // expected-error {{'$' is not an identifier; use backticks to escape it}} {{3-4=`$`}}
|
||||
print($) // expected-error {{'$' is not an identifier; use backticks to escape it}} {{9-10=`$`}}
|
||||
}
|
||||
func dollarLet() {
|
||||
let $ = 42 // expected-error {{expected numeric value following '$'}} expected-error {{expected pattern}}
|
||||
let $ = 42 // expected-error {{'$' is not an identifier; use backticks to escape it}} {{7-8=`$`}}
|
||||
print($) // expected-error {{'$' is not an identifier; use backticks to escape it}} {{9-10=`$`}}
|
||||
}
|
||||
func dollarClass() {
|
||||
class $ {} // expected-error {{expected numeric value following '$'}}
|
||||
// expected-error@-1 {{expression resolves to an unused function}}
|
||||
// expected-error@-2 {{expected identifier in class declaration}}
|
||||
// expected-error@-3 {{braced block of statements is an unused closure}}
|
||||
class $ {} // expected-error {{'$' is not an identifier; use backticks to escape it}} {{9-10=`$`}}
|
||||
}
|
||||
func dollarEnum() {
|
||||
enum $ {} // expected-error {{expected numeric value following '$'}}
|
||||
// expected-error@-1 {{expected identifier in enum declaration}}
|
||||
// expected-error@-2 {{expression resolves to an unused function}}
|
||||
// expected-error@-3 {{braced block of statements is an unused closure}}
|
||||
enum $ {} // expected-error {{'$' is not an identifier; use backticks to escape it}} {{8-9=`$`}}
|
||||
}
|
||||
func dollarStruct() {
|
||||
struct $ {} // expected-error {{expected numeric value following '$'}}
|
||||
// expected-error@-1 {{expected identifier in struct declaration}}
|
||||
// expected-error@-2 {{braced block of statements is an unused closure}}
|
||||
// expected-error@-3 {{expression resolves to an unused function}}
|
||||
struct $ {} // expected-error {{'$' is not an identifier; use backticks to escape it}} {{10-11=`$`}}
|
||||
}
|
||||
|
||||
func dollarFunc() {
|
||||
func $($ dollarParam: Int) {}
|
||||
// expected-error@-1 {{'$' is not an identifier; use backticks to escape it}} {{8-9=`$`}}
|
||||
// expected-error@-2 {{'$' is not an identifier; use backticks to escape it}} {{10-11=`$`}}
|
||||
$($: 24)
|
||||
// expected-error@-1 {{'$' is not an identifier; use backticks to escape it}} {{3-4=`$`}}
|
||||
// expected-error@-2 {{'$' is not an identifier; use backticks to escape it}} {{5-6=`$`}}
|
||||
}
|
||||
|
||||
func escapedDollarVar() {
|
||||
var `$` : Int = 42 // no error
|
||||
`$` += 1
|
||||
print(`$`)
|
||||
}
|
||||
func escapedDollarLet() {
|
||||
let `$` = 42 // no error
|
||||
print(`$`)
|
||||
}
|
||||
func escapedDollarClass() {
|
||||
class `$` {} // no error
|
||||
}
|
||||
func escapedDollarEnum() {
|
||||
enum `$` {} // no error
|
||||
}
|
||||
func escapedDollarStruct() {
|
||||
struct `$` {} // no error
|
||||
}
|
||||
|
||||
func escapedDollarFunc() {
|
||||
func `$`(`$`: Int) {} // no error
|
||||
`$`(`$`: 25) // no error
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user