Skip to content

Commit d5fd497

Browse files
committed
Merge remote-tracking branch 'origin/main' into rebranch
2 parents f15fd33 + 9ae9696 commit d5fd497

File tree

7 files changed

+104
-10
lines changed

7 files changed

+104
-10
lines changed

include/swift/AST/DiagnosticsSIL.def

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -857,7 +857,8 @@ ERROR(sil_movechecking_borrowed_parameter_captured_by_closure, none,
857857
"parameter",
858858
(StringRef))
859859
ERROR(sil_movechecking_capture_consumed, none,
860-
"noncopyable '%0' cannot be consumed when captured by an escaping closure", (StringRef))
860+
"noncopyable '%0' cannot be consumed when captured by an escaping closure or borrowed by a non-Escapable type",
861+
(StringRef))
861862
ERROR(sil_movechecking_not_reinitialized_before_end_of_function, none,
862863
"missing reinitialization of %select{inout parameter|closure capture}1 '%0' "
863864
"after consume", (StringRef, bool))

lib/SILGen/SILGenConcurrency.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,8 @@ void SILGenFunction::emitExpectedExecutorProlog() {
136136
// Defer bodies are always called synchronously within their enclosing
137137
// function, so the check is unnecessary; in addition, we cannot
138138
// necessarily perform the check because the defer may not have
139-
// captured the isolated parameter of the enclosing function.
139+
// captured the isolated parameter of the enclosing function, and
140+
// forcing a capture would cause DI problems in actor initializers.
140141
bool wantDataRaceChecks = [&] {
141142
if (F.isAsync() || F.isDefer())
142143
return false;

lib/Sema/TypeCheckCaptures.cpp

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -744,6 +744,31 @@ class FindCapturedVars : public ASTWalker {
744744

745745
} // end anonymous namespace
746746

747+
/// Given that a local function is isolated to the given var, should we
748+
/// force a capture of the var?
749+
static bool shouldCaptureIsolationInLocalFunc(AbstractFunctionDecl *AFD,
750+
VarDecl *var) {
751+
assert(isa<ParamDecl>(var));
752+
753+
// Don't try to capture an isolated parameter of the function itself.
754+
if (var->getDeclContext() == AFD)
755+
return false;
756+
757+
// We only *need* to force a capture of the isolation in an async function
758+
// (in which case it's needed for executor switching) or if we're in the
759+
// mode that forces an executor check in all synchronous functions. But
760+
// it's a simpler rule if we just do it unconditionally.
761+
762+
// However, don't do it for the implicit functions that represent defer
763+
// bodies, where it is both unnecessary and likely to lead to bad diagnostics.
764+
// We already suppress the executor check in defer bodies.
765+
if (auto FD = dyn_cast<FuncDecl>(AFD))
766+
if (FD->isDeferBody())
767+
return false;
768+
769+
return true;
770+
}
771+
747772
CaptureInfo CaptureInfoRequest::evaluate(Evaluator &evaluator,
748773
AbstractFunctionDecl *AFD) const {
749774
auto type = AFD->getInterfaceType();
@@ -767,10 +792,7 @@ CaptureInfo CaptureInfoRequest::evaluate(Evaluator &evaluator,
767792
auto actorIsolation = getActorIsolation(AFD);
768793
if (actorIsolation.getKind() == ActorIsolation::ActorInstance) {
769794
if (auto *var = actorIsolation.getActorInstance()) {
770-
assert(isa<ParamDecl>(var));
771-
// Don't capture anything if the isolation parameter is a parameter
772-
// of the local function.
773-
if (var->getDeclContext() != AFD)
795+
if (shouldCaptureIsolationInLocalFunc(AFD, var))
774796
finder.addCapture(CapturedValue(var, 0, AFD->getLoc()));
775797
}
776798
}

test/SILGen/local_function_isolation.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ actor GenericActor<K> {
7171
// Make sure defer doesn't capture anything.
7272
actor DeferInsideInitActor {
7373
init(foo: ()) async throws {
74-
// CHECK-LABEL: sil private [ossa] @$s24local_function_isolation20DeferInsideInitActorC3fooACyt_tYaKcfc6$deferL_yyF : $@convention(thin) (@sil_isolated @guaranteed DeferInsideInitActor) -> () {
74+
// CHECK-LABEL: sil private [ossa] @$s24local_function_isolation20DeferInsideInitActorC3fooACyt_tYaKcfc6$deferL_yyF : $@convention(thin) () -> () {
7575
defer {}
7676
self.init()
7777
}

test/SILOptimizer/definite_init_actor.swift

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
func neverReturn() -> Never { fatalError("quit!") }
1212
func arbitraryAsync() async {}
13+
func makeIntOrThrow() throws -> Int { return 0 }
1314

1415
actor BoringActor {
1516

@@ -402,3 +403,40 @@ actor Ahmad {
402403
// CHECK: } // end sil function '$s4test5AhmadCACyYacfc'
403404
nonisolated init() async {}
404405
}
406+
407+
// This should not complain about needing self in the defer prior to it being
408+
// fully initialized.
409+
actor Customer {
410+
var x: Int
411+
var y: Int
412+
413+
// CHECK-LABEL: sil hidden @$s4test8CustomerCACyYaKcfc :
414+
init() async throws {
415+
// CHECK: [[GENERIC:%[0-9]+]] = enum $Optional<Builtin.Executor>, #Optional.none!enumelt
416+
// CHECK-NEXT: hop_to_executor [[GENERIC]]
417+
// CHECK: [[SELF:%.*]] = end_init_let_ref %0 : $Customer
418+
419+
defer { print("I have a complaint") }
420+
421+
// CHECK: try_apply {{.*}}, error [[FAIL1:bb[0-9]+]]
422+
self.x = try makeIntOrThrow()
423+
424+
// CHECK: try_apply {{.*}}, error [[FAIL2:bb[0-9]+]]
425+
// CHECK: hop_to_executor [[SELF]] : $Customer
426+
self.y = try makeIntOrThrow()
427+
428+
// CHECK: [[DEFER:%.*]] = function_ref @$s4test8CustomerCACyYaKcfc6$deferL_yyF :
429+
// CHECK-NEXT: apply [[DEFER]]()
430+
// CHECK-NEXT: return [[SELF]] : $Customer
431+
432+
// CHECK: [[FAIL1]]({{%.*}} : $any Error):
433+
// CHECK-NEXT: // function_ref
434+
// CHECK-NEXT: [[DEFER:%.*]] = function_ref @$s4test8CustomerCACyYaKcfc6$deferL_yyF :
435+
// CHECK-NEXT: apply [[DEFER]]()
436+
437+
// CHECK: [[FAIL2]]({{%.*}} : $any Error):
438+
// CHECK-NEXT: // function_ref
439+
// CHECK-NEXT: [[DEFER:%.*]] = function_ref @$s4test8CustomerCACyYaKcfc6$deferL_yyF :
440+
// CHECK-NEXT: apply [[DEFER]]()
441+
}
442+
}

test/SILOptimizer/lifetime_dependence/verify_diagnostics.swift

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,23 @@ struct TestDeinitCallsAddressor: ~Copyable, ~Escapable {
121121
}
122122
}
123123

124+
struct NCBuffer: ~Copyable {
125+
fileprivate let buffer: UnsafeMutableRawBufferPointer
126+
127+
public init() {
128+
let ptr = UnsafeMutableRawPointer.init(bitPattern: 0)
129+
self.buffer = UnsafeMutableRawBufferPointer(start: ptr, count: 0)
130+
}
131+
132+
public var bytes: Span<UInt8> {
133+
@_lifetime(borrow self)
134+
borrowing get {
135+
let span: Span<UInt8> = Span(_bytes: self.buffer.bytes)
136+
return span
137+
}
138+
}
139+
}
140+
124141
// Test a borrowed dependency on an address
125142
@_lifetime(immortal)
126143
public func testGenericDep<T: ~Escapable>(type: T.Type) -> T {
@@ -287,3 +304,15 @@ func testSpanMayThrow(buffer: inout [Int]) {
287304
let bufferSpan = buffer.mutableSpan
288305
try! mutableSpanMayThrow(bufferSpan)
289306
}
307+
308+
// =============================================================================
309+
// Dependence on non-Copyable values
310+
// =============================================================================
311+
312+
@_lifetime(immortal)
313+
func dependOnNonCopyable() -> NCBuffer {
314+
let buffer = NCBuffer()
315+
let count = buffer.bytes.count
316+
_ = count
317+
return buffer // expected-error {{noncopyable 'buffer' cannot be consumed when captured by an escaping closure or borrowed by a non-Escapable type}}
318+
}

utils/swift_build_support/swift_build_support/products/wasmswiftsdk.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,8 @@ def _build_libxml2(self, swift_host_triple, has_pthread, wasi_sysroot):
130130
libxml2.cmake_options.define('HAVE_PTHREAD_H', cmake_thread_enabled)
131131

132132
libxml2.build_with_cmake([], self.args.build_variant, [],
133-
prefer_native_toolchain=True)
133+
prefer_native_toolchain=True,
134+
ignore_extra_cmake_options=True)
134135
with shell.pushd(libxml2.build_dir):
135136
shell.call([self.toolchain.cmake, '--install', '.', '--prefix', '/', '--component', 'development'],
136137
env={'DESTDIR': wasi_sysroot})
@@ -158,7 +159,8 @@ def _build_foundation(self, swift_host_triple, has_pthread, wasi_sysroot):
158159
foundation.cmake_options.define('LIBXML2_LIBRARY', os.path.join(wasi_sysroot, 'lib'))
159160

160161
foundation.build_with_cmake([], self.args.build_variant, [],
161-
prefer_native_toolchain=True)
162+
prefer_native_toolchain=True,
163+
ignore_extra_cmake_options=True)
162164

163165
dest_dir = self._target_package_path(swift_host_triple)
164166
with shell.pushd(foundation.build_dir):
@@ -184,7 +186,8 @@ def _build_swift_testing(self, swift_host_triple, has_pthread, wasi_sysroot):
184186
swift_testing.cmake_options.define('SwiftTesting_MACRO', 'NO')
185187

186188
swift_testing.build_with_cmake([], self.args.build_variant, [],
187-
prefer_native_toolchain=True)
189+
prefer_native_toolchain=True,
190+
ignore_extra_cmake_options=True)
188191
dest_dir = self._target_package_path(swift_host_triple)
189192
with shell.pushd(swift_testing.build_dir):
190193
shell.call([self.toolchain.cmake, '--install', '.', '--prefix', '/usr'],

0 commit comments

Comments
 (0)