Bring back capture by box

This commit is contained in:
Mykola Pokhylets
2025-08-02 20:02:58 +02:00
parent 4e233706b9
commit 0496ca421a
4 changed files with 15 additions and 9 deletions

View File

@@ -170,6 +170,15 @@ CaptureKind TypeConverter::getDeclCaptureKind(CapturedValue capture,
return CaptureKind::StorageAddress;
}
// Reference storage types can appear in a capture list, which means
// we might allocate boxes to store the captures. However, those boxes
// have the same lifetime as the closure itself, so we must capture
// the box itself and not the payload, even if the closure is noescape,
// otherwise they will be destroyed when the closure is formed.
if (var->getInterfaceType()->is<ReferenceStorageType>()) {
return CaptureKind::Box;
}
// For 'let' constants
if (!var->supportsMutation()) {
assert(getTypeProperties(

View File

@@ -34,8 +34,7 @@ class C {
func returnsSelf1() -> Self {
return { [weak self] in self?.f(); return .init() }()
// CHECK-NO-WEAK-LET-LABEL: sil private [ossa] @{{.*}}returnsSelf{{.*}} : $@convention(thin) (@inout_aliasable @sil_weak Optional<C>, @thick @dynamic_self C.Type) -> @owned C {
// CHECK-HAS-WEAK-LET-LABEL: sil private [ossa] @{{.*}}returnsSelf{{.*}} : $@convention(thin) (@in_guaranteed @sil_weak Optional<C>, @thick @dynamic_self C.Type) -> @owned C {
// CHECK-LABEL: sil private [ossa] @{{.*}}returnsSelf{{.*}} : $@convention(thin) (@guaranteed { var @sil_weak Optional<C> }, @thick @dynamic_self C.Type) -> @owned C
}
func returnsSelf2() -> Self {

View File

@@ -241,12 +241,10 @@ class Z {
// CHECK: [[WEAK_SELF:%.*]] = alloc_box ${ var @sil_weak Optional<Z> }
// CHECK: [[WEAK_SELF_LIFETIME:%.*]] = begin_borrow [lexical] [var_decl] [[WEAK_SELF]]
// CHECK: [[WEAK_SELF_ADDR:%.*]] = project_box [[WEAK_SELF_LIFETIME]] : ${ var @sil_weak Optional<Z> }, 0
// CHECK: [[FN:%.*]] = function_ref @$s12dynamic_self1ZC23testDynamicSelfCaptures1xACXDSi_tFyycfU1_ : $@convention(thin) (@in_guaranteed @sil_weak Optional<Z>, @thick @dynamic_self Z.Type) -> ()
// CHECK: [[WEAK_SELF_COPY:%.*]] = alloc_stack $@sil_weak Optional<Z>
// CHECK: copy_addr [[WEAK_SELF_ADDR]] to [init] [[WEAK_SELF_COPY]] : $*@sil_weak Optional<Z>
// CHECK: [[FN:%.*]] = function_ref @$s12dynamic_self1ZC23testDynamicSelfCaptures1xACXDSi_tFyycfU1_ : $@convention(thin) (@guaranteed { var @sil_weak Optional<Z> }, @thick @dynamic_self Z.Type) -> ()
// CHECK: [[WEAK_SELF_COPY:%.*]] = copy_value [[WEAK_SELF_LIFETIME]] : ${ var @sil_weak Optional<Z> }
// CHECK-NEXT: [[DYNAMIC_SELF:%.*]] = metatype $@thick @dynamic_self Z.Type
// CHECK: partial_apply [callee_guaranteed] [[FN]]([[WEAK_SELF_COPY]], [[DYNAMIC_SELF]]) : $@convention(thin) (@in_guaranteed @sil_weak Optional<Z>, @thick @dynamic_self Z.Type) -> ()
// CHECK: partial_apply [callee_guaranteed] [[FN]]([[WEAK_SELF_COPY]], [[DYNAMIC_SELF]]) : $@convention(thin) (@guaranteed { var @sil_weak Optional<Z> }, @thick @dynamic_self Z.Type) -> ()
let fn3 = {
[weak self] in
_ = self
@@ -429,7 +427,7 @@ class Derived : Base {
class Generic<T> {
// Examples where we have to add a special argument to capture Self's metadata
func t1() -> Self {
// CHECK-LABEL: sil private [ossa] @$s12dynamic_self7GenericC2t1ACyxGXDyFAEXDSgycfU_ : $@convention(thin) <T> (@in_guaranteed @sil_weak Optional<Generic<T>>, @thick @dynamic_self Generic<T>.Type) -> @owned Optional<Generic<T>>
// CHECK-LABEL: sil private [ossa] @$s12dynamic_self7GenericC2t1ACyxGXDyFAEXDSgycfU_ : $@convention(thin) <T> (@guaranteed <τ_0_0> { var @sil_weak Optional<Generic<τ_0_0>> } <T>, @thick @dynamic_self Generic<T>.Type) -> @owned Optional<Generic<T>>
_ = {[weak self] in self }
return self
}

View File

@@ -8,7 +8,7 @@ func makeGenericClosureWithUnknownClass<T>(t: T) where T : ClassProtocol {
_ = { [unowned t] in _ = t }
}
// CHECK-LABEL: sil private [ossa] @$s4main34makeGenericClosureWithUnknownClass1tyx_tAA0G8ProtocolRzlFyycfU_ : $@convention(thin) <T where T : ClassProtocol> (@in_guaranteed @sil_unowned T) -> () {
// CHECK-LABEL: sil private [ossa] @$s4main34makeGenericClosureWithUnknownClass1tyx_tAA0G8ProtocolRzlFyycfU_ : $@convention(thin) <T where T : ClassProtocol> (@guaranteed <τ_0_0 where τ_0_0 : ClassProtocol> { var @sil_unowned τ_0_0 } <T>) -> () {
func makeGenericClosureWithNativeClass1<T>(t: T) where T : BaseClass {
_ = { [unowned t] in _ = t }