Skip to content

Commit 7a682a4

Browse files
committed
[Parse] Allow self rebinding
Instead of parisng identifiers and fallthrough to self, treat `kw_self` the same as identifiers. This enables binding to self.
1 parent ef4353f commit 7a682a4

File tree

2 files changed

+61
-1
lines changed

2 files changed

+61
-1
lines changed

Diff for: lib/Parse/ParseExpr.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -1537,6 +1537,7 @@ ParserResult<Expr> Parser::parseExprPrimary(Diag<> ID, bool isExprBasic) {
15371537
}
15381538

15391539
case tok::identifier: // foo
1540+
case tok::kw_self: // self
15401541
// Attempt to parse for 'type(of: <expr>)'.
15411542
if (canParseTypeOf(*this)) {
15421543
return parseExprTypeOf();
@@ -1571,7 +1572,6 @@ ParserResult<Expr> Parser::parseExprPrimary(Diag<> ID, bool isExprBasic) {
15711572
}
15721573

15731574
LLVM_FALLTHROUGH;
1574-
case tok::kw_self: // self
15751575
case tok::kw_Self: // Self
15761576
return makeParserResult(parseExprIdentifier());
15771577

Diff for: test/Parse/self_rebinding.swift

+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
// RUN: %target-typecheck-verify-swift
2+
3+
class Writer {
4+
private var articleWritten = 47
5+
6+
func stop() {
7+
let rest: () -> Void = { [weak self] in
8+
let articleWritten = self?.articleWritten ?? 0
9+
guard let `self` = self else {
10+
return
11+
}
12+
13+
self.articleWritten = articleWritten
14+
}
15+
16+
fatalError("I'm running out of time")
17+
rest()
18+
}
19+
20+
func nonStop() {
21+
let write: () -> Void = { [weak self] in
22+
self?.articleWritten += 1
23+
24+
if let self = self {
25+
self.articleWritten += 1
26+
}
27+
28+
if let `self` = self {
29+
self.articleWritten += 1
30+
}
31+
32+
guard let self = self else {
33+
return
34+
}
35+
36+
self.articleWritten += 1
37+
}
38+
39+
write()
40+
}
41+
}
42+
43+
struct T {
44+
var mutable: Int = 0
45+
func f() {
46+
// expected-error @+2 {{keyword 'self' cannot be used as an identifier here}}
47+
// expected-note @+1 {{if this name is unavoidable, use backticks to escape it}}
48+
let self = self
49+
}
50+
}
51+
52+
class MyCls {
53+
func something() {}
54+
55+
func test() {
56+
// expected-warning @+1 {{initialization of immutable value 'self' was never used}}
57+
let `self` = Writer() // Even if `self` is shadowed,
58+
something() // this should still refer `MyCls.something`.
59+
}
60+
}

0 commit comments

Comments
 (0)