Skip to content

Commit 78bf97c

Browse files
authored
Merge pull request #20847 from xedin/sr-9314
[TypeChecker] Improve error about mutating self capture by escaping c…
2 parents 70bb9fe + 8a79fa1 commit 78bf97c

File tree

3 files changed

+29
-3
lines changed

3 files changed

+29
-3
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2944,8 +2944,11 @@ ERROR(closure_implicit_capture_without_noescape,none,
29442944
"escaping closures can only capture inout parameters explicitly by value",
29452945
())
29462946
ERROR(closure_implicit_capture_mutating_self,none,
2947-
"closure cannot implicitly capture a mutating self parameter",
2947+
"escaping closure cannot capture a mutating self parameter",
29482948
())
2949+
NOTE(create_mutating_copy_or_capture_self,none,
2950+
"create a mutating copy of self, or explicitly capture self for immutability",
2951+
())
29492952
ERROR(nested_function_with_implicit_capture_argument,none,
29502953
"nested function with %select{an |}0implicitly captured inout "
29512954
"parameter%select{|s}0 can only be used as a non-escaping argument", (bool))

lib/Sema/TypeCheckCaptures.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -402,7 +402,9 @@ class FindCapturedVars : public ASTWalker {
402402
if (isInOut && !AFR.isKnownNoEscape() && !isNested) {
403403
if (D->getBaseName() == D->getASTContext().Id_self) {
404404
TC.diagnose(DRE->getLoc(),
405-
diag::closure_implicit_capture_mutating_self);
405+
diag::closure_implicit_capture_mutating_self);
406+
TC.diagnose(DRE->getLoc(),
407+
diag::create_mutating_copy_or_capture_self);
406408
} else {
407409
TC.diagnose(DRE->getLoc(),
408410
diag::closure_implicit_capture_without_noescape);

test/Sema/diag_invalid_inout_captures.swift

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ func do_escape(_ not_a_price_you_are_willing_to_pay: @escaping () -> ()) {}
66
struct you_cry_in_your_tea {
77
mutating func which_you_hurl_in_the_sea_when_you_see_me_go_by() {
88
no_escape { _ = self } // OK
9-
do_escape { _ = self } // expected-error {{closure cannot implicitly capture a mutating self parameter}}
9+
do_escape { _ = self } // expected-error {{escaping closure cannot capture a mutating self parameter}}
10+
// expected-note@-1 {{create a mutating copy of self, or explicitly capture self for immutability}}
1011
do_escape {
1112
[self] in
1213
_ = self // OK
@@ -40,3 +41,23 @@ func remember(line: inout String) -> () -> Void {
4041
func its_complicated(condition: inout Int) {
4142
no_escape(condition == 0 ? { condition = 1 } : { condition = 2}) // expected-error 2 {{escaping closures can only capture inout parameters explicitly by value}}
4243
}
44+
45+
// rdar://problem/46322943 - Improve error message about mutating self capture in escaping closures
46+
func rdar46322943() {
47+
struct S {
48+
var bar = 1
49+
50+
func foo(_ fn: () -> Void) {
51+
fn()
52+
}
53+
54+
mutating func main() {
55+
let fn = {
56+
self.bar += 1
57+
// expected-error@-1 {{escaping closure cannot capture a mutating self parameter}}
58+
// expected-note@-2 {{create a mutating copy of self, or explicitly capture self for immutability}}
59+
}
60+
self.foo(fn)
61+
}
62+
}
63+
}

0 commit comments

Comments
 (0)