Skip to content

Commit b4dbdc4

Browse files
committed
Provide a more specific diag when using keywords as identifiers
When declaring a function like func repeat(){}, the diagnostic is "expected an identifier" but 'repeat' looks like a reasonable identifier at first glance, so actually say why it isn't. rdar://problem/25761380
1 parent e7c81c5 commit b4dbdc4

File tree

8 files changed

+32
-8
lines changed

8 files changed

+32
-8
lines changed

include/swift/AST/DiagnosticsParse.def

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -659,8 +659,10 @@ ERROR(expected_rangle_protocol,PointsToFirstBadToken,
659659

660660
ERROR(expected_pattern,PointsToFirstBadToken,
661661
"expected pattern", ())
662-
ERROR(expected_pattern_is_keyword,none,
663-
"keyword '%0' cannot be used as an identifier", (StringRef))
662+
ERROR(keyword_cant_be_identifier,none,
663+
"keyword '%0' cannot be used as an identifier here", (StringRef))
664+
NOTE(backticks_to_escape,none,
665+
"backticks can escape this name if it is important to use", ())
664666
ERROR(expected_rparen_tuple_pattern_list,none,
665667
"expected ')' at end of tuple pattern", ())
666668
ERROR(untyped_pattern_ellipsis,none,

include/swift/AST/DiagnosticsSema.def

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -462,8 +462,6 @@ ERROR(serialization_target_too_new_repl,none,
462462
ERROR(reserved_member_name,none,
463463
"type member may not be named %0, since it would conflict with the"
464464
" 'foo.%1' expression", (DeclName, StringRef))
465-
NOTE(backticks_to_escape,none,
466-
"backticks can escape this name if it is important to use", ())
467465

468466
ERROR(invalid_redecl,none,"invalid redeclaration of %0", (DeclName))
469467
NOTE(invalid_redecl_prev,none,

lib/Parse/ParseDecl.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
12
//===--- ParseDecl.cpp - Swift Language Parser for Declarations -----------===//
23
//
34
// This source file is part of the Swift.org open source project
@@ -2424,6 +2425,8 @@ ParserResult<ImportDecl> Parser::parseDeclImport(ParseDeclOptions Flags,
24242425
break;
24252426
default:
24262427
diagnose(Tok, diag::expected_identifier_in_decl, "import");
2428+
diagnose(Tok, diag::keyword_cant_be_identifier, Tok.getText());
2429+
diagnose(Tok, diag::backticks_to_escape);
24272430
return nullptr;
24282431
}
24292432
KindLoc = consumeToken();

lib/Parse/ParsePattern.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -823,7 +823,8 @@ ParserResult<Pattern> Parser::parsePattern() {
823823
default:
824824
if (Tok.isKeyword() &&
825825
(peekToken().is(tok::colon) || peekToken().is(tok::equal))) {
826-
diagnose(Tok, diag::expected_pattern_is_keyword, Tok.getText());
826+
diagnose(Tok, diag::keyword_cant_be_identifier, Tok.getText());
827+
diagnose(Tok, diag::backticks_to_escape);
827828
SourceLoc Loc = Tok.getLoc();
828829
consumeToken();
829830
return makeParserErrorResult(new (Context) AnyPattern(Loc));

lib/Parse/Parser.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -600,7 +600,14 @@ bool Parser::parseAnyIdentifier(Identifier &Result, SourceLoc &Loc,
600600
}
601601

602602
checkForInputIncomplete();
603-
diagnose(Tok, D);
603+
604+
if (Tok.isKeyword()) {
605+
diagnose(Tok, diag::keyword_cant_be_identifier, Tok.getText());
606+
diagnose(Tok, diag::backticks_to_escape);
607+
} else {
608+
diagnose(Tok, D);
609+
}
610+
604611
return true;
605612
}
606613

test/Parse/invalid.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,3 +89,11 @@ class VarTester {
8989
b += 10
9090
}
9191
}
92+
93+
func repeat() {}
94+
// expected-error @-1 {{keyword 'repeat' cannot be used as an identifier here}}
95+
// expected-note @-2 {{backticks can escape this name if it is important to use}}
96+
97+
let for = 2
98+
// expected-error @-1 {{keyword 'for' cannot be used as an identifier here}}
99+
// expected-note @-2 {{backticks can escape this name if it is important to use}}

test/decl/import/import.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,12 @@ import func Swift.min
4343
import var x // expected-error {{expected module name}}
4444
import struct Swift.nonexistent // expected-error {{no such decl in module}}
4545

46-
import Swift.import.abc // expected-error 2 {{expected identifier}}
46+
import Swift.import.abc // expected-error {{expected identifier in import declaration}}
47+
// expected-error @-1 {{keyword 'import' cannot be used as an identifier here}}
48+
// expected-note @-2 {{backticks can escape this name if it is important to use}}
4749
import where Swift.Int // expected-error {{expected identifier}}
50+
// expected-error @-1 {{keyword 'where' cannot be used as an identifier here}}
51+
// expected-note @-2 {{backticks can escape this name if it is important to use}}
4852
import 2 // expected-error {{expected identifier}}
4953

5054
import really.nonexistent // expected-error {{no such module 'really.nonexistent'}}

test/decl/var/variables.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ var bfx : Int, bfy : Int
1414

1515
_ = 10
1616

17-
func _(_ x: Int) {} // expected-error {{expected identifier in function declaration}}
17+
func _(_ x: Int) {} // expected-error {{keyword '_' cannot be used as an identifier here}}
18+
// expected-note @-1 {{backticks can escape this name if it is important to use}}
1819

1920

2021
var self1 = self1 // expected-error {{variable used within its own initial value}}

0 commit comments

Comments
 (0)