Skip to content

Commit 806231b

Browse files
committed
Merge pull request #35153 from kavon/warn-unqualified-await
[concurrency] warn about future reservation of 'await' as contextual keyword
1 parent 2d6e570 commit 806231b

File tree

3 files changed

+86
-9
lines changed

3 files changed

+86
-9
lines changed

include/swift/AST/DiagnosticsParse.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1223,6 +1223,9 @@ NOTE(super_in_closure_with_capture_here,none,
12231223
"'self' explicitly captured here", ())
12241224

12251225
ERROR(try_before_await,none, "'await' must precede 'try'", ())
1226+
WARNING(warn_await_keyword,none,
1227+
"future versions of Swift reserve the word 'await'; "
1228+
"if this name is unavoidable, use backticks to escape it", ())
12261229

12271230
// Tuples and parenthesized expressions
12281231
ERROR(expected_expr_in_expr_list,none,

lib/Parse/ParseExpr.cpp

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -393,16 +393,22 @@ ParserResult<Expr> Parser::parseExprSequenceElement(Diag<> message,
393393
SyntaxParsingContext ElementContext(SyntaxContext,
394394
SyntaxContextKind::Expr);
395395

396-
if (shouldParseExperimentalConcurrency() && Tok.isContextualKeyword("await")) {
397-
SourceLoc awaitLoc = consumeToken();
398-
ParserResult<Expr> sub =
399-
parseExprSequenceElement(diag::expected_expr_after_await, isExprBasic);
400-
if (!sub.hasCodeCompletion() && !sub.isNull()) {
401-
ElementContext.setCreateSyntax(SyntaxKind::AwaitExpr);
402-
sub = makeParserResult(new (Context) AwaitExpr(awaitLoc, sub.get()));
403-
}
396+
if (Tok.isContextualKeyword("await")) {
397+
if (shouldParseExperimentalConcurrency()) {
398+
SourceLoc awaitLoc = consumeToken();
399+
ParserResult<Expr> sub =
400+
parseExprSequenceElement(diag::expected_expr_after_await, isExprBasic);
401+
if (!sub.hasCodeCompletion() && !sub.isNull()) {
402+
ElementContext.setCreateSyntax(SyntaxKind::AwaitExpr);
403+
sub = makeParserResult(new (Context) AwaitExpr(awaitLoc, sub.get()));
404+
}
404405

405-
return sub;
406+
return sub;
407+
} else {
408+
// warn that future versions of Swift will parse this token differently.
409+
diagnose(Tok.getLoc(), diag::warn_await_keyword)
410+
.fixItReplace(Tok.getLoc(), "`await`");
411+
}
406412
}
407413

408414
SourceLoc tryLoc;
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
// RUN: %target-typecheck-verify-swift
2+
// now check that the fix-its, if applied, will fix the warnings.
3+
// RUN: %empty-directory(%t.scratch)
4+
// RUN: cp %s %t.scratch/fixits.swift
5+
// RUN: %target-swift-frontend -typecheck %t.scratch/fixits.swift -fixit-all -emit-fixits-path %t.scratch/fixits.remap 2> /dev/null
6+
// RUN: %{python} %utils/apply-fixit-edits.py %t.scratch
7+
// RUN: %target-swift-frontend -typecheck %t.scratch/fixits.swift -warnings-as-errors
8+
// RUN: %target-swift-frontend -typecheck %t.scratch/fixits.swift -warnings-as-errors -enable-experimental-concurrency
9+
10+
// REQUIRES: concurrency
11+
12+
func await(_ f : () -> Void) {}
13+
14+
func ordinaryCalls() {
15+
await({})
16+
// expected-warning@-1 {{future versions of Swift reserve the word 'await'; if this name is unavoidable, use backticks to escape it}}
17+
18+
await {}
19+
// expected-warning@-1 {{future versions of Swift reserve the word 'await'; if this name is unavoidable, use backticks to escape it}}
20+
21+
let _ = `await`
22+
let _ = `await`({})
23+
24+
let _ = await
25+
// expected-warning@-1 {{future versions of Swift reserve the word 'await'; if this name is unavoidable, use backticks to escape it}}
26+
27+
let k = Klass()
28+
k.await()
29+
_ = k.await
30+
}
31+
32+
func localVar() {
33+
var await = 1
34+
35+
let two = await + await
36+
// expected-warning@-1 2 {{future versions of Swift reserve the word 'await'; if this name is unavoidable, use backticks to escape it}}
37+
38+
_ = await==two-await
39+
// expected-warning@-1 2 {{future versions of Swift reserve the word 'await'; if this name is unavoidable, use backticks to escape it}}
40+
41+
takesInout(await: &await)
42+
}
43+
44+
func takesUnitFunc(_ f : () -> Void) {}
45+
46+
func takesInout(await : inout Int) {
47+
await += 1
48+
// expected-warning@-1 {{future versions of Swift reserve the word 'await'; if this name is unavoidable, use backticks to escape it}}
49+
}
50+
51+
class Klass {
52+
init() { await() }
53+
// expected-warning@-1 {{future versions of Swift reserve the word 'await'; if this name is unavoidable, use backticks to escape it}}
54+
55+
func await() {
56+
57+
takesUnitFunc(await)
58+
// expected-warning@-1 {{future versions of Swift reserve the word 'await'; if this name is unavoidable, use backticks to escape it}}
59+
}
60+
61+
func method() {
62+
let _ = self.await
63+
self.await()
64+
65+
await()
66+
// expected-warning@-1 {{future versions of Swift reserve the word 'await'; if this name is unavoidable, use backticks to escape it}}
67+
}
68+
}

0 commit comments

Comments
 (0)