Skip to content

Commit a098393

Browse files
authored
Handle optional promotion in CasePath.init (#87)
* Handle optional promotion in CasePath.init Fixes #86. * fix for swift 5.1
1 parent b4a8729 commit a098393

File tree

2 files changed

+265
-72
lines changed

2 files changed

+265
-72
lines changed

Sources/CasePaths/EnumReflection.swift

Lines changed: 34 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,18 @@ extension CasePath {
66
/// - Parameter embed: An embed function.
77
/// - Returns: A case path.
88
public init(_ embed: @escaping (Value) -> Root) {
9-
self.init(embed: embed, extract: extractHelp(embed))
10-
}
11-
12-
/// Returns a case path for the given embed function.
13-
///
14-
/// - Note: This operator is only intended to be used with enum cases that have no associated
15-
/// values. Its behavior is otherwise undefined.
16-
/// - Parameter embed: An embed function.
17-
/// - Returns: A case path.
18-
public init<Wrapped>(_ embed: @escaping (Value) -> Root) where Root == Wrapped? {
19-
self.init(embed: embed, extract: optionalPromotedExtractHelp(embed))
9+
func open<Wrapped>(_: Wrapped.Type) -> (Root) -> Value? {
10+
optionalPromotedExtractHelp(unsafeBitCast(embed, to: ((Value) -> Wrapped?).self))
11+
as! (Root) -> Value?
12+
}
13+
let extract =
14+
((_Witness<Root>.self as? _AnyOptional.Type)?.wrappedType)
15+
.map { _openExistential($0, do: open) }
16+
?? extractHelp(embed)
17+
self.init(
18+
embed: embed,
19+
extract: extract
20+
)
2021
}
2122
}
2223

@@ -28,17 +29,14 @@ extension CasePath where Value == Void {
2829
/// - Parameter root: A case with no an associated value.
2930
/// - Returns: A void case path.
3031
public init(_ root: Root) {
31-
self.init(embed: { root }, extract: extractVoidHelp(root))
32-
}
33-
34-
/// Returns a void case path for a case with no associated value.
35-
///
36-
/// - Note: This operator is only intended to be used with enum cases that have no associated
37-
/// values. Its behavior is otherwise undefined.
38-
/// - Parameter root: A case with no an associated value.
39-
/// - Returns: A void case path.
40-
public init<Wrapped>(_ root: Root) where Root == Wrapped? {
41-
self.init(embed: { root }, extract: optionalPromotedExtractVoidHelp(root))
32+
func open<Wrapped>(_: Wrapped.Type) -> (Root) -> Void? {
33+
optionalPromotedExtractVoidHelp(unsafeBitCast(root, to: Wrapped?.self)) as! (Root) -> Void?
34+
}
35+
let extract =
36+
((_Witness<Root>.self as? _AnyOptional.Type)?.wrappedType)
37+
.map { _openExistential($0, do: open) }
38+
?? extractVoidHelp(root)
39+
self.init(embed: { root }, extract: extract)
4240
}
4341
}
4442

@@ -704,3 +702,17 @@ extension UnsafeRawPointer {
704702

705703
// This is the size of any Unsafe*Pointer and also the size of Int and UInt.
706704
private let pointerSize = MemoryLayout<UnsafeRawPointer>.size
705+
706+
private protocol _Optional {
707+
associatedtype Wrapped
708+
}
709+
extension Optional: _Optional {}
710+
private enum _Witness<A> {}
711+
private protocol _AnyOptional {
712+
static var wrappedType: Any.Type { get }
713+
}
714+
extension _Witness: _AnyOptional where A: _Optional {
715+
static var wrappedType: Any.Type {
716+
A.Wrapped.self
717+
}
718+
}

0 commit comments

Comments
 (0)