Skip to content

Commit 7f0ef3d

Browse files
committed
[move-only] When assigning a var that escapes into a closure into another local, emit the correct error message.
With some of the changes that I have made, we began to emit a mark_must_check [no_copy] on a copy_addr here. This change teaches the move address checker how to recognize that in this case if we have a project_box it is actually b/c we have something captured by an escaping closure.
1 parent 4cd7a3b commit 7f0ef3d

5 files changed

+41
-12
lines changed

lib/SILOptimizer/Mandatory/MoveOnlyAddressCheckerUtils.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1526,6 +1526,13 @@ bool GatherUsesVisitor::visitUse(Operand *op) {
15261526

15271527
if (markedValue->getCheckKind() ==
15281528
MarkMustCheckInst::CheckKind::NoConsumeOrAssign) {
1529+
if (isa<ProjectBoxInst>(stripAccessMarkers(markedValue->getOperand()))) {
1530+
LLVM_DEBUG(llvm::dbgs()
1531+
<< "Found mark must check [nocopy] use of escaping box: " << *user);
1532+
diagnosticEmitter.emitAddressEscapingClosureCaptureLoadedAndConsumed(markedValue);
1533+
emittedEarlyDiagnostic = true;
1534+
return true;
1535+
}
15291536
LLVM_DEBUG(llvm::dbgs()
15301537
<< "Found mark must check [nocopy] error: " << *user);
15311538
diagnosticEmitter.emitAddressDiagnosticNoCopy(markedValue, copyAddr);

test/SILOptimizer/moveonly_addresschecker_diagnostics.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3109,9 +3109,9 @@ public func closureCaptureClassUseAfterConsumeError() {
31093109
consumeVal(x2) // expected-error {{'x2' was consumed but it is illegal to consume a noncopyable mutable capture of an escaping closure. One can only read from it or assign over it}}
31103110
}
31113111
f()
3112-
// TODO: This is wrong
3113-
let x3 = x2 // expected-note {{consuming use here}}
3114-
// expected-error @-1 {{'x2' has guaranteed ownership but was consumed}}
3112+
consumeVal(x2) // expected-error {{'x2' was consumed but it is illegal to consume a noncopyable mutable capture of an escaping closure. One can only read from it or assign over it}}
3113+
let x3 = x2 // expected-error {{'x2' was consumed but it is illegal to consume a noncopyable mutable capture of an escaping closure. One can only read from it or assign over it}}
3114+
x2 = Klass()
31153115
let _ = x3
31163116
}
31173117

test/SILOptimizer/moveonly_objectchecker_diagnostics.swift

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2870,9 +2870,9 @@ public func closureCaptureClassOwnedArgUseAfterConsume4(_ x2: consuming Klass) {
28702870
consumeVal(x2) // expected-error {{'x2' was consumed but it is illegal to consume a noncopyable mutable capture of an escaping closure. One can only read from it or assign over it}}
28712871
}
28722872
f()
2873-
// TODO: This is wrong
2874-
let x3 = x2 // expected-note {{consuming use here}}
2875-
// expected-error @-1 {{'x2' has guaranteed ownership but was consumed}}
2873+
let x3 = x2 // expected-error {{'x2' was consumed but it is illegal to consume a noncopyable mutable capture of an escaping closure. One can only read from it or assign over it}}
2874+
consumeVal(x2) // expected-error {{'x2' was consumed but it is illegal to consume a noncopyable mutable capture of an escaping closure. One can only read from it or assign over it}}
2875+
x2 = Klass()
28762876
let _ = x3
28772877
}
28782878

@@ -3107,8 +3107,29 @@ public func closureAndClosureCaptureClassUseAfterConsume2(_ x: borrowing Klass)
31073107
}
31083108
f()
31093109
consumeVal(x2) // expected-error {{'x2' was consumed but it is illegal to consume a noncopyable immutable capture of an escaping closure. One can only read from it}}
3110+
let x3 = x2 // expected-error {{'x2' was consumed but it is illegal to consume a noncopyable immutable capture of an escaping closure. One can only read from it}}
3111+
_ = x3
31103112
}
31113113

3114+
public func closureAndClosureCaptureClassUseAfterConsume3(_ x: borrowing Klass) { // expected-error {{'x' has guaranteed ownership but was consumed}}
3115+
var x2 = x
3116+
// expected-note @-1 {{consuming use here}}
3117+
x2 = x
3118+
// expected-note @-1 {{consuming use here}}
3119+
3120+
let f = {
3121+
let g = {
3122+
borrowVal(x2)
3123+
consumeVal(x2) // expected-error {{'x2' was consumed but it is illegal to consume a noncopyable mutable capture of an escaping closure. One can only read from it or assign over it}}
3124+
consumeVal(x2) // expected-error {{'x2' was consumed but it is illegal to consume a noncopyable mutable capture of an escaping closure. One can only read from it or assign over it}}
3125+
}
3126+
g()
3127+
}
3128+
f()
3129+
consumeVal(x2) // expected-error {{'x2' was consumed but it is illegal to consume a noncopyable mutable capture of an escaping closure. One can only read from it or assign over it}}
3130+
let x3 = x2 // expected-error {{'x2' was consumed but it is illegal to consume a noncopyable mutable capture of an escaping closure. One can only read from it or assign over it}}
3131+
_ = x3
3132+
}
31123133

31133134
public func closureAndClosureCaptureClassArgUseAfterConsume(_ x2: borrowing Klass) {
31143135
// expected-error @-1 {{'x2' consumed in closure. This is illegal since if the closure is invoked more than once the binding will be uninitialized on later invocations}}

test/SILOptimizer/moveonly_trivial_addresschecker_diagnostics.swift

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1218,9 +1218,11 @@ public func closureCaptureClassUseAfterConsumeError() {
12181218
consumeVal(x2) // expected-error {{'x2' was consumed but it is illegal to consume a noncopyable mutable capture of an escaping closure. One can only read from it or assign over it}}
12191219
}
12201220
f()
1221-
// TODO: MG This is wrong
1222-
let x3 = x2 // expected-note {{consuming use here}}
1223-
// expected-error @-1 {{'x2' has guaranteed ownership but was consumed}}
1221+
let x3 = x2 // expected-error {{'x2' was consumed but it is illegal to consume a noncopyable mutable capture of an escaping closure. One can only read from it or assign over it}}
1222+
consumeVal(x2) // expected-error {{'x2' was consumed but it is illegal to consume a noncopyable mutable capture of an escaping closure. One can only read from it or assign over it}}
1223+
var x4 = x2 // expected-error {{'x2' was consumed but it is illegal to consume a noncopyable mutable capture of an escaping closure. One can only read from it or assign over it}}
1224+
x4 = x2 // expected-error {{'x2' was consumed but it is illegal to consume a noncopyable mutable capture of an escaping closure. One can only read from it or assign over it}}
1225+
_ = x4
12241226
let _ = x3
12251227
}
12261228

test/SILOptimizer/moveonly_trivial_objectchecker_diagnostics.swift

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1829,9 +1829,8 @@ public func closureCaptureClassOwnedArgUseAfterConsume4(_ x2: consuming NonTrivi
18291829
consumeVal(x2) // expected-error {{'x2' was consumed but it is illegal to consume a noncopyable mutable capture of an escaping closure. One can only read from it or assign over it}}
18301830
}
18311831
f()
1832-
// TODO (MG): This is wrong
1833-
let x3 = x2 // expected-note {{consuming use here}}
1834-
// expected-error @-1 {{'x2' has guaranteed ownership but was consumed}}
1832+
let x3 = x2 // expected-error {{'x2' was consumed but it is illegal to consume a noncopyable mutable capture of an escaping closure. One can only read from it or assign over it}}
1833+
consumeVal(x2) // expected-error {{'x2' was consumed but it is illegal to consume a noncopyable mutable capture of an escaping closure. One can only read from it or assign over it}}
18351834
let _ = x3
18361835
}
18371836

0 commit comments

Comments
 (0)