Skip to content

Commit 9bff2b4

Browse files
committed
fix SILGen bug for cross-module actor let accesses
When trying to access a let-bound property of an actor across a moudule boundary, the operation should be treated as async. But, upon reaching SILGen, the compiler would crash when trying to emit the needed hop, because the base of the element reference was missing. This commit fixes that and adds regression coverage. resolves rdar://81812013
1 parent 1069225 commit 9bff2b4

File tree

4 files changed

+58
-1
lines changed

4 files changed

+58
-1
lines changed

lib/SILGen/SILGenLValue.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4215,7 +4215,7 @@ RValue SILGenFunction::emitLoadOfLValue(SILLocation loc, LValue &&src,
42154215
auto actorIso = component.asPhysical().takeActorIsolation();
42164216

42174217
// If the load must happen in the context of an actor, do a hop first.
4218-
prevExecutor = emitHopToTargetActor(loc, actorIso, /*actorSelf=*/None);
4218+
prevExecutor = emitHopToTargetActor(loc, actorIso, addr);
42194219
projection =
42204220
emitLoad(loc, projection.getValue(), origFormalType,
42214221
substFormalType, rvalueTL, C, IsNotTake, isBaseGuaranteed);
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
public class SomeClass { }
2+
public final class SomeSendableClass: Sendable { }
23

34
public actor OtherModuleActor {
45
public let a: Int = 1
56
public nonisolated let b: Int = 2
67
public let c: SomeClass = SomeClass()
8+
public let d: SomeSendableClass = SomeSendableClass()
79
}

test/Concurrency/actor_isolation.swift

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -822,6 +822,23 @@ func testCrossModuleLets(actor: OtherModuleActor) async {
822822
// expected-note@-1{{property access is 'async'}}
823823
// expected-warning@-2{{cannot use property 'c' with a non-sendable type 'SomeClass' across actors}}
824824
_ = await actor.c // expected-warning{{cannot use property 'c' with a non-sendable type 'SomeClass' across actors}}
825+
_ = await actor.d // okay
826+
}
827+
828+
func testCrossModuleAsIsolated(actor: isolated OtherModuleActor) {
829+
_ = actor.a
830+
_ = actor.b
831+
_ = actor.c
832+
_ = actor.d
833+
}
834+
835+
extension OtherModuleActor {
836+
func testCrossModuleInExtension() {
837+
_ = self.a
838+
_ = self.b
839+
_ = self.c
840+
_ = self.d
841+
}
825842
}
826843

827844

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-swift-frontend -emit-module -emit-module-path %t/OtherActors.swiftmodule -module-name OtherActors %S/Inputs/OtherActors.swift -disable-availability-checking
3+
// RUN: %target-swift-emit-silgen -verify -module-name test -I %t -disable-availability-checking -warn-concurrency %s | %FileCheck %s --implicit-check-not=hop_to_executor --enable-var-scope
4+
// REQUIRES: concurrency
5+
6+
import OtherActors
7+
8+
// CHECK: sil hidden [ossa] @$s4test6check1ySi11OtherActors0C11ModuleActorCYaF : $@convention(thin) @async (@guaranteed OtherModuleActor) -> Int {
9+
// CHECK: bb0([[SELF:%[0-9]+]] : @guaranteed $OtherModuleActor):
10+
// CHECK: [[REF:%[0-9]+]] = ref_element_addr [[SELF]] : $OtherModuleActor, #OtherModuleActor.a
11+
// CHECK: [[OLD:%[0-9]+]] = builtin "getCurrentExecutor"() : $Optional<Builtin.Executor>
12+
// CHECK: hop_to_executor [[SELF]] : $OtherModuleActor
13+
// CHECK-NEXT: load [trivial] [[REF]]
14+
// CHECK-NEXT: hop_to_executor [[OLD]] : $Optional<Builtin.Executor>
15+
// CHECK: } // end sil function '$s4test6check1ySi11OtherActors0C11ModuleActorCYaF'
16+
func check1(_ actor: OtherModuleActor) async -> Int {
17+
return await actor.a
18+
}
19+
20+
func check2(_ actor: isolated OtherModuleActor) -> Int {
21+
return actor.a
22+
}
23+
24+
func check3(_ actor: OtherModuleActor) async -> Int {
25+
return actor.b
26+
}
27+
28+
// CHECK: sil hidden [ossa] @$s4test6check4y11OtherActors17SomeSendableClassCAC0C11ModuleActorCYaF : $@convention(thin) @async (@guaranteed OtherModuleActor) -> @owned SomeSendableClass {
29+
// CHECK: bb0([[SELF:%[0-9]+]] : @guaranteed $OtherModuleActor):
30+
// CHECK: [[REF:%[0-9]+]] = ref_element_addr [[SELF]] : $OtherModuleActor, #OtherModuleActor.d
31+
// CHECK: [[OLD:%[0-9]+]] = builtin "getCurrentExecutor"() : $Optional<Builtin.Executor>
32+
// CHECK: hop_to_executor [[SELF]] : $OtherModuleActor
33+
// CHECK-NEXT: load [copy] [[REF]]
34+
// CHECK-NEXT: hop_to_executor [[OLD]] : $Optional<Builtin.Executor>
35+
// CHECK: } // end sil function '$s4test6check4y11OtherActors17SomeSendableClassCAC0C11ModuleActorCYaF'
36+
func check4(_ actor: OtherModuleActor) async -> SomeSendableClass {
37+
return await actor.d
38+
}

0 commit comments

Comments
 (0)