Skip to content

Commit 72a0070

Browse files
authored
Add TypeConformance (#61)
* Add TypeConformance implementation * Update ProtocolDescriptor * Add AnyView.init(_fromValue) implementation * Add AnyView Tests
1 parent 82cb56c commit 72a0070

File tree

11 files changed

+189
-35
lines changed

11 files changed

+189
-35
lines changed
+23-7
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,39 @@
11
//
22
// ProtocolDescriptor.c
3-
//
4-
//
5-
//
3+
// COpenSwiftUI
4+
65

76
#include "ProtocolDescriptor.h"
87

8+
void _OpenSwiftUI_callVisitViewType(void *visitor_value,
9+
const void *view_type,
10+
const void *view_type2,
11+
const void *view_pwt);
12+
913
OPENSWIFTUI_EXPORT
1014
const void *$s11OpenSwiftUI4ViewMp;
1115

12-
OPENSWIFTUI_EXPORT
13-
const void *_viewProtocolDescriptor(void) {
16+
const void *_OpenSwiftUI_viewProtocolDescriptor(void) {
1417
return &$s11OpenSwiftUI4ViewMp;
1518
}
1619

1720
OPENSWIFTUI_EXPORT
1821
const void *$s11OpenSwiftUI12ViewModifierMp;
1922

20-
OPENSWIFTUI_EXPORT
21-
const void *_viewModifierProtocolDescriptor(void) {
23+
const void *_OpenSwiftUI_viewModifierProtocolDescriptor(void) {
2224
return &$s11OpenSwiftUI12ViewModifierMp;
2325
}
26+
27+
void _OpenSwiftUI_callVisitViewType1(void *visitor_value,
28+
const void *view_type,
29+
const void *view_pwt) {
30+
_OpenSwiftUI_callVisitViewType2(visitor_value, view_type, view_type, view_pwt);
31+
}
32+
33+
OPENSWIFTUI_EXPORT
34+
void _OpenSwiftUI_callVisitViewType2(void *visitor_value,
35+
const void *view_type,
36+
const void *view_type2,
37+
const void *view_pwt) {
38+
_OpenSwiftUI_callVisitViewType(visitor_value, view_type, view_type2, view_pwt);
39+
}

Sources/COpenSwiftUI/include/ProtocolDescriptor.h

+13-2
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,21 @@
1313
OPENSWIFTUI_ASSUME_NONNULL_BEGIN
1414

1515
OPENSWIFTUI_EXPORT
16-
const void *_viewProtocolDescriptor(void);
16+
const void *_OpenSwiftUI_viewProtocolDescriptor(void);
1717

1818
OPENSWIFTUI_EXPORT
19-
const void *_viewModifierProtocolDescriptor(void);
19+
const void *_OpenSwiftUI_viewModifierProtocolDescriptor(void);
20+
21+
OPENSWIFTUI_EXPORT
22+
void _OpenSwiftUI_callVisitViewType1(void *visitor_value,
23+
const void *view_type,
24+
const void *view_pwt);
25+
26+
OPENSWIFTUI_EXPORT
27+
void _OpenSwiftUI_callVisitViewType2(void *visitor_value,
28+
const void *view_type,
29+
const void *view_type2,
30+
const void *view_pwt);
2031

2132
OPENSWIFTUI_ASSUME_NONNULL_END
2233

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
//
2+
// ProtocolDescriptor.swift
3+
// OpenSwiftUI
4+
//
5+
// Audited for RELEASE_2021
6+
// Status: WIP
7+
8+
internal import COpenSwiftUI
9+
internal import OpenGraphShims
10+
11+
// MARK: - ProtocolDescriptor
12+
13+
protocol ProtocolDescriptor {
14+
static var descriptor: UnsafeRawPointer { get }
15+
}
16+
17+
// MARK: - TupleDescriptor
18+
19+
protocol TupleDescriptor: ProtocolDescriptor {
20+
static var typeCache: [ObjectIdentifier: TupleTypeDescription<Self>] { get set }
21+
}
22+
23+
extension TupleDescriptor {
24+
static func tupleDescription(_ type: OGTupleType) -> TupleTypeDescription<Self> {
25+
let id = ObjectIdentifier(type.type)
26+
if let cache = typeCache[id] {
27+
return cache
28+
} else {
29+
let description = TupleTypeDescription<Self>(type)
30+
typeCache[id] = description
31+
return description
32+
}
33+
}
34+
}
35+
36+
// MARK: - TupleTypeDescription
37+
38+
struct TupleTypeDescription<PD: ProtocolDescriptor> {
39+
let contentTypes: [(Int, TypeConformance<PD>)]
40+
41+
init(_ tupleType: OGTupleType) {
42+
contentTypes = tupleType.indices.compactMap { index in
43+
let type = tupleType.type(at: index)
44+
guard let comformance = TypeConformance<PD>(type) else {
45+
print("Ignoring invalid type, type \(type) at index \(index)")
46+
return nil
47+
}
48+
return (index, comformance)
49+
}
50+
}
51+
}
52+
53+
// MARK: - ViewDescriptor
54+
55+
struct ViewDescriptor: TupleDescriptor {
56+
static var descriptor: UnsafeRawPointer {
57+
_OpenSwiftUI_viewProtocolDescriptor()
58+
}
59+
static var typeCache: [ObjectIdentifier: TupleTypeDescription<ViewDescriptor>] = [:]
60+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
//
2+
// TypeConformance.swift
3+
// OpenSwiftUI
4+
//
5+
// Audited for RELEASE_2021
6+
// Status: Complete
7+
8+
struct TypeConformance<PD: ProtocolDescriptor> {
9+
var metadata: UnsafeRawPointer
10+
var conformance: UnsafeRawPointer
11+
12+
init?(_ type: Any.Type) {
13+
guard let conformance = swiftConformsToProtocol(type, PD.descriptor) else {
14+
return nil
15+
}
16+
self.metadata = unsafeBitCast(type, to: UnsafeRawPointer.self)
17+
self.conformance = conformance
18+
}
19+
}
20+
21+
func conformsToProtocol(_ type: Any.Type, _ protocolDescriptor: UnsafeRawPointer) -> Bool {
22+
swiftConformsToProtocol(type, protocolDescriptor) != nil
23+
}
24+
25+
@_silgen_name("swift_conformsToProtocol")
26+
@inline(__always)
27+
private func swiftConformsToProtocol(
28+
_ type: Any.Type,
29+
_ protocolDescriptor: UnsafeRawPointer
30+
) -> UnsafeRawPointer?

Sources/OpenSwiftUI/Core/Util/ProtocolDescriptor.swift

-9
This file was deleted.

Sources/OpenSwiftUI/View/Debug/TODO/ViewDebug.swift

+6-6
Original file line numberDiff line numberDiff line change
@@ -201,10 +201,10 @@ extension _ViewDebug.Data {
201201
init(type anyType: Any.Type) {
202202
name = nil
203203
type = String(reflecting: anyType)
204-
readableType = "" // TODO: /*OGTypeID(anyType).description*/
204+
readableType = OGTypeID(anyType).description
205205
flags = [
206-
conformsToProtocol(anyType, _viewProtocolDescriptor()) ? .view : [],
207-
conformsToProtocol(anyType, _viewModifierProtocolDescriptor()) ? .viewModifier : [],
206+
conformsToProtocol(anyType, _OpenSwiftUI_viewProtocolDescriptor()) ? .view : [],
207+
conformsToProtocol(anyType, _OpenSwiftUI_viewModifierProtocolDescriptor()) ? .viewModifier : [],
208208
]
209209
value = nil
210210
subattributes = nil
@@ -214,10 +214,10 @@ extension _ViewDebug.Data {
214214
name = label
215215
let anyType = Swift.type(of: inputValue)
216216
type = String(reflecting: anyType)
217-
readableType = "" // TODO: /*OGTypeID(anyType).description*/
217+
readableType = OGTypeID(anyType).description
218218
flags = [
219-
conformsToProtocol(anyType, _viewProtocolDescriptor()) ? .view : [],
220-
conformsToProtocol(anyType, _viewModifierProtocolDescriptor()) ? .viewModifier : [],
219+
conformsToProtocol(anyType, _OpenSwiftUI_viewProtocolDescriptor()) ? .view : [],
220+
conformsToProtocol(anyType, _OpenSwiftUI_viewModifierProtocolDescriptor()) ? .viewModifier : [],
221221
]
222222
if serializeValue {
223223
value = SerializedAttribute.serialize(value: inputValue)

Sources/OpenSwiftUI/View/View/AnyView.swift

+27-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
// ID: A96961F3546506F21D8995C6092F15B5
88

99
internal import OpenGraphShims
10+
internal import COpenSwiftUI
1011

1112
@frozen
1213
public struct AnyView: PrimitiveView {
@@ -30,7 +31,23 @@ public struct AnyView: PrimitiveView {
3031
view = AnyView(value as! V)
3132
}
3233
}
33-
fatalError("TODO")
34+
guard let conformace = TypeConformance<ViewDescriptor>(type(of: value)) else {
35+
return nil
36+
}
37+
// FIXME: pass a structure like the following to _OpenSwiftUI_callVisitViewType1 and remove _OpenSwiftUI_callVisitViewType
38+
// x0 = pointer
39+
// x1 = View.self
40+
// x2 = PWT V: View.self
41+
// pointer+0x0 -> pointer+0x18
42+
// pointer+0x8 -> Visitor.self
43+
// pointer+0x10 -> PWT Visitor: ViewTypeVisitor
44+
// pointer+0x18~0x37 -> visitor.value
45+
// pointer+0x38 -> visitor.view
46+
var visitor: any ViewTypeVisitor = Visitor(value: value)
47+
withUnsafeMutablePointer(to: &visitor) { value in
48+
_OpenSwiftUI_callVisitViewType1(value, conformace.metadata, conformace.conformance)
49+
}
50+
self = (visitor as! Visitor).view!
3451
}
3552

3653
init<V: View>(_ view: V, id: UniqueID?) {
@@ -226,3 +243,12 @@ private struct AnyViewChildList<V: View> {
226243
@Attribute var view: AnyView
227244
var id: UniqueID?
228245
}
246+
247+
@_silgen_name("_OpenSwiftUI_callVisitViewType1")
248+
func visitViewType(_ visitor: UnsafeMutablePointer<any ViewTypeVisitor>, type: UnsafeRawPointer, pwt: UnsafeRawPointer)
249+
250+
// Called by _OpenSwiftUI_callVisitViewType2 as a temporary workaround implementation
251+
@_silgen_name("_OpenSwiftUI_callVisitViewType")
252+
func visit<V: View>(_ visitor: UnsafeMutablePointer<any ViewTypeVisitor>, type: V.Type) {
253+
visitor.pointee.visit(type: V.self)
254+
}

Tests/OpenSwiftUICompatibilityTests/EnvironmentValuesTest.swift renamed to Tests/OpenSwiftUICompatibilityTests/Data/Environment/EnvironmentValuesTest.swift

-5
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,6 @@
55
// Created by Kyle on 2023/11/21.
66
//
77

8-
#if OPENSWIFTUI_COMPATIBILITY_TEST
9-
import SwiftUI
10-
#else
11-
import OpenSwiftUI
12-
#endif
138
import Testing
149

1510
struct EnvironmentValuesTest {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
//
2+
// Export.swift
3+
// OpenSwiftUICompatibilityTests
4+
5+
6+
#if OPENSWIFTUI_COMPATIBILITY_TEST
7+
@_exported import SwiftUI
8+
let compatibilityTestEnabled = true
9+
#else
10+
@_exported import OpenSwiftUI
11+
let compatibilityTestEnabled = false
12+
#endif
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
//
2+
// AnyViewTests.swift
3+
// OpenSwiftUICompatibilityTests
4+
5+
import Testing
6+
7+
struct AnyViewTests {
8+
@Test
9+
func testInitFromValue() {
10+
let empty = EmptyView()
11+
#expect(AnyView(_fromValue: empty) != nil)
12+
}
13+
}

Tests/OpenSwiftUITests/Core/Util/ProtocolDescriptorTests.swift

+5-5
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,10 @@ struct ProtocolDescriptorTests {
2323
EmptyView()
2424
}
2525
}
26-
27-
#expect(conformsToProtocol(ContentView.self, _viewProtocolDescriptor()))
28-
#expect(!conformsToProtocol(ContentView.self, _viewModifierProtocolDescriptor()))
29-
#expect(!conformsToProtocol(ContentViewModifier.self, _viewProtocolDescriptor()))
30-
#expect(conformsToProtocol(ContentViewModifier.self, _viewModifierProtocolDescriptor()))
26+
27+
#expect(conformsToProtocol(ContentView.self, _OpenSwiftUI_viewProtocolDescriptor()))
28+
#expect(!conformsToProtocol(ContentView.self, _OpenSwiftUI_viewModifierProtocolDescriptor()))
29+
#expect(!conformsToProtocol(ContentViewModifier.self, _OpenSwiftUI_viewProtocolDescriptor()))
30+
#expect(conformsToProtocol(ContentViewModifier.self, _OpenSwiftUI_viewModifierProtocolDescriptor()))
3131
}
3232
}

0 commit comments

Comments
 (0)