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:
@@ -994,7 +994,9 @@ ERROR(expected_dollar_numeric,none,
|
|||||||
ERROR(dollar_numeric_too_large,none,
|
ERROR(dollar_numeric_too_large,none,
|
||||||
"numeric value following '$' is too large", ())
|
"numeric value following '$' is too large", ())
|
||||||
ERROR(numeric_literal_numeric_member,none,
|
ERROR(numeric_literal_numeric_member,none,
|
||||||
"expected named member of numeric literal", ())
|
"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,
|
ERROR(anon_closure_arg_not_in_closure,none,
|
||||||
"anonymous closure argument not contained in a closure", ())
|
"anonymous closure argument not contained in a closure", ())
|
||||||
|
|||||||
@@ -28,7 +28,8 @@ using namespace swift;
|
|||||||
using namespace camel_case;
|
using namespace camel_case;
|
||||||
|
|
||||||
bool swift::canBeArgumentLabel(StringRef identifier) {
|
bool swift::canBeArgumentLabel(StringRef identifier) {
|
||||||
if (identifier == "var" || identifier == "let" || identifier == "inout")
|
if (identifier == "var" || identifier == "let" || identifier == "inout" ||
|
||||||
|
identifier == "$")
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -474,7 +474,7 @@ static bool isValidIdentifierContinuationCodePoint(uint32_t c) {
|
|||||||
static bool isValidIdentifierStartCodePoint(uint32_t c) {
|
static bool isValidIdentifierStartCodePoint(uint32_t c) {
|
||||||
if (!isValidIdentifierContinuationCodePoint(c))
|
if (!isValidIdentifierContinuationCodePoint(c))
|
||||||
return false;
|
return false;
|
||||||
if (c < 0x80 && (isDigit(c) || c == '$'))
|
if (c < 0x80 && isDigit(c))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// N1518: Recommendations for extended identifier characters for C and C++
|
// 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) {
|
if (CurPtr == tokStart + 1) {
|
||||||
diagnose(tokStart, diag::expected_dollar_numeric);
|
// It is always an error to see a standalone '$' when not in Swift 3
|
||||||
return formToken(tok::unknown, tokStart);
|
// 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.
|
// 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() {
|
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() {
|
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() {
|
func dollarClass() {
|
||||||
class $ {} // expected-error {{expected numeric value following '$'}}
|
class $ {} // expected-error {{'$' is not an identifier; use backticks to escape it}} {{9-10=`$`}}
|
||||||
// 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}}
|
|
||||||
}
|
}
|
||||||
func dollarEnum() {
|
func dollarEnum() {
|
||||||
enum $ {} // expected-error {{expected numeric value following '$'}}
|
enum $ {} // expected-error {{'$' is not an identifier; use backticks to escape it}} {{8-9=`$`}}
|
||||||
// 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}}
|
|
||||||
}
|
}
|
||||||
func dollarStruct() {
|
func dollarStruct() {
|
||||||
struct $ {} // expected-error {{expected numeric value following '$'}}
|
struct $ {} // expected-error {{'$' is not an identifier; use backticks to escape it}} {{10-11=`$`}}
|
||||||
// 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}}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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