Skip to content

Commit

Permalink
[RemoteMirror] Handle UnsafeContinuation
Browse files Browse the repository at this point in the history
UnsafeContinuations can be stored in variables or properties,
so it's important for RemoteMirror to be able to at least minimally
recognize them.

This just treats an UnsafeContinuation as a refcounted pointer.
Which might be "good enough" for now.

Working towards rdar://110351406
  • Loading branch information
tbkka committed Aug 1, 2024
1 parent 541ee12 commit 9e1dcd6
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 0 deletions.
1 change: 1 addition & 0 deletions include/swift/RemoteInspection/TypeLowering.h
Original file line number Diff line number Diff line change
Expand Up @@ -428,6 +428,7 @@ class TypeConverter {
const TypeInfo *getThickFunctionTypeInfo();
const TypeInfo *getAnyMetatypeTypeInfo();
const TypeInfo *getDefaultActorStorageTypeInfo();
const TypeInfo *getRawUnsafeContinuationTypeInfo();
const TypeInfo *getEmptyTypeInfo();

template <typename TypeInfoTy, typename... Args>
Expand Down
8 changes: 8 additions & 0 deletions stdlib/public/RemoteInspection/TypeLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1602,6 +1602,12 @@ const TypeInfo *TypeConverter::getDefaultActorStorageTypeInfo() {
return DefaultActorStorageTI;
}

const TypeInfo *TypeConverter::getRawUnsafeContinuationTypeInfo() {
// FIXME: This is a bad approximation
return getReferenceTypeInfo(ReferenceKind::Strong,
ReferenceCounting::Native);
}

const TypeInfo *TypeConverter::getEmptyTypeInfo() {
if (EmptyTI != nullptr)
return EmptyTI;
Expand Down Expand Up @@ -2208,6 +2214,8 @@ class LowerType
ReferenceCounting::Unknown);
} else if (B->getMangledName() == "BD") {
return TC.getDefaultActorStorageTypeInfo();
} else if (B->getMangledName() == "Bc") {
return TC.getRawUnsafeContinuationTypeInfo();
}

/// Otherwise, get the fixed layout information from reflection
Expand Down
57 changes: 57 additions & 0 deletions validation-test/Reflection/reflect_UnsafeContinuation.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// RUN: %empty-directory(%t)
// RUN: %target-build-swift -lswiftSwiftReflectionTest %s -o %t/reflect_UnsafeContinuation
// RUN: %target-codesign %t/reflect_UnsafeContinuation

// RUN: %target-run %target-swift-reflection-test %t/reflect_UnsafeContinuation | %FileCheck %s --check-prefix=CHECK-%target-ptrsize

// REQUIRES: reflection_test_support
// REQUIRES: executable_test
// UNSUPPORTED: use_os_stdlib
// UNSUPPORTED: ASAN

import SwiftReflectionTest

struct MyValue {
let u: UInt
}

struct MyError: Error {
let i: Int
}

@available(SwiftStdlib 5.1, *)
class MyClass {
let cont: UnsafeContinuation<MyValue, any Error>

init(cont: UnsafeContinuation<MyValue, any Error>) {
self.cont = cont
}
}

if #available(SwiftStdlib 5.1, *) {
_ = try await withUnsafeThrowingContinuation { unsafeContinuation in
let myClass = MyClass(cont: unsafeContinuation)
reflect(object: myClass)
unsafeContinuation.resume(returning: MyValue(u: 1))
}
}

// CHECK: Reflecting an object.
// CHECK-NEXT: Instance pointer in child address space: 0x{{[0-9a-fA-F]+}}
// CHECK-NEXT: Type reference:
// CHECK-NEXT: (class reflect_UnsafeContinuation.MyClass)

// CHECK-64: Type info:
// CHECK-64-NEXT: (class_instance size=24 alignment=8 stride=24 num_extra_inhabitants=0 bitwise_takable=1
// CHECK-64-NEXT: (field name=cont offset=16
// CHECK-64-NEXT: (struct size=8 alignment=8 stride=8 num_extra_inhabitants=2147483647 bitwise_takable=1
// CHECK-64-NEXT: (field name=context offset=0
// CHECK-64-NEXT: (reference kind=strong refcounting=native)))))

// TODO: 32-bit layout

doneReflecting()

// CHECK-64: Done.

// CHECK-32: Done.

0 comments on commit 9e1dcd6

Please sign in to comment.