Skip to content

Commit 73e749d

Browse files
authored
Merge pull request #65594 from Azoy/identitycastthing
[stdlib] Add a conditional identity cast
2 parents 0bdb39f + 4c8c828 commit 73e749d

File tree

2 files changed

+33
-0
lines changed

2 files changed

+33
-0
lines changed

stdlib/public/core/Builtin.swift

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,20 @@ public func _identityCast<T, U>(_ x: T, to expectedType: U.Type) -> U {
109109
return Builtin.reinterpretCast(x)
110110
}
111111

112+
/// Returns `x` as its concrete type `U`, or `nil` if `x` has a different
113+
/// concrete type.
114+
///
115+
/// This cast can be useful for dispatching to specializations of generic
116+
/// functions.
117+
@_alwaysEmitIntoClient
118+
public func _specialize<T, U>(_ x: T, for: U.Type) -> U? {
119+
guard T.self == U.self else {
120+
return nil
121+
}
122+
123+
return Builtin.reinterpretCast(x)
124+
}
125+
112126
/// `unsafeBitCast` something to `AnyObject`.
113127
@usableFromInline @_transparent
114128
internal func _reinterpretCastToAnyObject<T>(_ x: T) -> AnyObject {

test/stdlib/Builtins.swift

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,4 +307,23 @@ tests.test("_isConcrete") {
307307
expectFalse(isConcrete_false(Int.self))
308308
}
309309

310+
tests.test("_specialize") {
311+
func something<T>(with x: some Collection<T>) -> Int {
312+
if let y = _specialize(x, for: [Int].self) {
313+
return y[0]
314+
} else {
315+
return 1234567890
316+
}
317+
}
318+
319+
let x = [0987654321, 1, 2]
320+
expectEqual(something(with: x), 0987654321)
321+
322+
let y = CollectionOfOne<String>("hello world")
323+
expectEqual(something(with: y), 1234567890)
324+
325+
let z: Any = [0, 1, 2, 3]
326+
expectNil(_specialize(z, for: [Int].self))
327+
}
328+
310329
runAllTests()

0 commit comments

Comments
 (0)