mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Merge pull request #85625 from aschwaighofer/wip_embedded_cast_tuples
[embedded] Allow casting to tuples and tighten the check which existentials we support in embedded with existentials
This commit is contained in:
@@ -94,6 +94,11 @@ private struct FunctionChecker {
|
||||
for conf in ie.conformances {
|
||||
try checkConformance(conf, location: ie.location)
|
||||
}
|
||||
} else if instruction is OpenExistentialAddrInst {
|
||||
// okay in embedded with exitentials
|
||||
} else {
|
||||
// not supported even in embedded with exitentials
|
||||
throw Diagnostic(.embedded_swift_existential_type, instruction.operands[0].value.type, at: instruction.location)
|
||||
}
|
||||
|
||||
case let aeb as AllocExistentialBoxInst:
|
||||
|
||||
@@ -1051,8 +1051,7 @@ func isCastSupportedInEmbeddedSwift(from sourceType: Type,
|
||||
return false
|
||||
}
|
||||
|
||||
// Tuple?
|
||||
if !destType.isStruct && !destType.isClass && !destType.isEnum {
|
||||
if !destType.isStruct && !destType.isClass && !destType.isEnum && !destType.isTuple {
|
||||
return false
|
||||
}
|
||||
|
||||
|
||||
@@ -216,6 +216,92 @@ func test7(_ p: any Any) {
|
||||
c.a()
|
||||
}
|
||||
|
||||
class BaseClass {
|
||||
func foo() { print("BaseClass.foo") }
|
||||
deinit {
|
||||
print("BaseClass.deinit")
|
||||
}
|
||||
}
|
||||
|
||||
class SubClass : BaseClass {
|
||||
override func foo() { print("SubClass.foo") }
|
||||
}
|
||||
|
||||
func test8(_ p: any Any) {
|
||||
print("test any as? SubClass")
|
||||
if let c = p as? SubClass {
|
||||
print("success")
|
||||
c.foo()
|
||||
} else {
|
||||
print("cast failed")
|
||||
}
|
||||
}
|
||||
|
||||
func test9(_ p: any Any) {
|
||||
print("test any as? BaseClass")
|
||||
if let c = p as? BaseClass {
|
||||
print("success")
|
||||
c.foo()
|
||||
} else {
|
||||
print("cast failed")
|
||||
}
|
||||
}
|
||||
|
||||
func test10(_ p: any Any) {
|
||||
print("test any as! BaseClass")
|
||||
let c = p as! BaseClass
|
||||
c.foo()
|
||||
}
|
||||
|
||||
func test11(_ p: any Any) {
|
||||
print("test any as! SubClass")
|
||||
let c = p as! SubClass
|
||||
c.foo()
|
||||
}
|
||||
|
||||
func test12(_ p: any Any) {
|
||||
print("test any as! (Int, Int, Int, Int)")
|
||||
if let c = p as? (Int, Int, Int, Int) {
|
||||
print("success")
|
||||
print("tuple: \(c.0)")
|
||||
} else {
|
||||
print("cast failed")
|
||||
}
|
||||
}
|
||||
|
||||
protocol Q {
|
||||
func printit()
|
||||
}
|
||||
|
||||
protocol P4<T> {
|
||||
associatedtype T: Q
|
||||
|
||||
var t: T { get }
|
||||
}
|
||||
|
||||
struct QConformer : Q {
|
||||
var x = (0, 1, 2,3)
|
||||
|
||||
func printit() {
|
||||
print("QConformer \(x.3)")
|
||||
}
|
||||
}
|
||||
|
||||
struct P4Conformer : P4 {
|
||||
var q = QConformer()
|
||||
|
||||
var t : QConformer {
|
||||
get {
|
||||
return q
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func test13(_ p: any P4) {
|
||||
print("test13")
|
||||
p.t.printit()
|
||||
}
|
||||
|
||||
@main
|
||||
struct Main {
|
||||
static func main() {
|
||||
@@ -262,7 +348,7 @@ struct Main {
|
||||
// OUTPUT: deinit called
|
||||
// OUTPUT: cast failed
|
||||
// OUTPUT-NOT: deinit called
|
||||
test5(GenericStructWithClass<Int>())
|
||||
test5(GenericStructWithClass<Int>())
|
||||
// OUTPUT: test any as? MyStruct
|
||||
// OUTPUT: cast failed
|
||||
// OUTPUT: deinit called
|
||||
@@ -289,5 +375,53 @@ struct Main {
|
||||
// OUTPUT: a LargeMyStruct 5
|
||||
// OUTPUT: deinit called
|
||||
// OUTPUT-NOT: deinit called
|
||||
test8(SubClass())
|
||||
// OUTPUT: success
|
||||
// OUTPUT: SubClass.foo
|
||||
// OUTPUT: BaseClass.deinit
|
||||
// OUTPUT-NOT: deinit
|
||||
test8(BaseClass())
|
||||
// OUTPUT: test any as? SubClass
|
||||
// OUTPUT: cast failed
|
||||
// OUTPUT: BaseClass.deinit
|
||||
// OUTPUT-NOT: deinit
|
||||
test9(SubClass())
|
||||
// OUTPUT: test any as? BaseClass
|
||||
// OUTPUT: success
|
||||
// OUTPUT: SubClass.foo
|
||||
// OUTPUT: BaseClass.deinit
|
||||
// OUTPUT-NOT: deinit
|
||||
test9(BaseClass())
|
||||
// OUTPUT: test any as? BaseClass
|
||||
// OUTPUT: success
|
||||
// OUTPUT: BaseClass.foo
|
||||
// OUTPUT: BaseClass.deinit
|
||||
// OUTPUT-NOT: deinit
|
||||
test9(C())
|
||||
// OUTPUT: test any as? BaseClass
|
||||
// OUTPUT: cast failed
|
||||
// OUTPUT-NOT: deinit
|
||||
test10(BaseClass())
|
||||
// OUTPUT: test any as! BaseClass
|
||||
// OUTPUT: BaseClass.foo
|
||||
// OUTPUT: BaseClass.deinit
|
||||
// OUTPUT-NOT: deinit
|
||||
test10(SubClass())
|
||||
// OUTPUT: test any as! BaseClass
|
||||
// OUTPUT: SubClass.foo
|
||||
// OUTPUT: BaseClass.deinit
|
||||
// OUTPUT-NOT: deinit
|
||||
test11(SubClass())
|
||||
// OUTPUT: test any as! SubClass
|
||||
// OUTPUT: SubClass.foo
|
||||
// OUTPUT: BaseClass.deinit
|
||||
// OUTPUT-NOT: deinit
|
||||
test12((0, 1, 2, 3))
|
||||
// OUTPUT: test any as! (Int, Int, Int, Int)
|
||||
// OUTPUT: success
|
||||
// OUTPUT: tuple: 0
|
||||
test13(P4Conformer())
|
||||
// OUTPUT: test13
|
||||
// OUTPUT: QConformer 3
|
||||
}
|
||||
}
|
||||
|
||||
109
test/embedded/existential_cast_fails.swift
Normal file
109
test/embedded/existential_cast_fails.swift
Normal file
@@ -0,0 +1,109 @@
|
||||
// RUN: %empty-directory(%t)
|
||||
|
||||
// RUN: %target-clang -x c -c %S/Inputs/unbuffered-putchar.c -o %t/unbuffered-putchar.o
|
||||
|
||||
// RUN: %target-build-swift -DT1 -enable-experimental-feature Embedded \
|
||||
// RUN: -parse-as-library -Xlinker %t/unbuffered-putchar.o \
|
||||
// RUN: -enable-experimental-feature EmbeddedExistentials \
|
||||
// RUN: -wmo -runtime-compatibility-version none %s -o %t/t1.out
|
||||
// RUN: not --crash %t/t1.out 2>&1 | %FileCheck %s --check-prefix=CHECK-T1
|
||||
|
||||
// RUN: %target-build-swift -DT2 -enable-experimental-feature Embedded \
|
||||
// RUN: -parse-as-library -Xlinker %t/unbuffered-putchar.o \
|
||||
// RUN: -enable-experimental-feature EmbeddedExistentials \
|
||||
// RUN: -wmo -runtime-compatibility-version none %s -o %t/t2.out
|
||||
// RUN: not --crash %t/t2.out 2>&1 | %FileCheck %s --check-prefix=CHECK-T2
|
||||
|
||||
// RUN: %target-build-swift -DT3 -enable-experimental-feature Embedded \
|
||||
// RUN: -parse-as-library -Xlinker %t/unbuffered-putchar.o \
|
||||
// RUN: -enable-experimental-feature EmbeddedExistentials \
|
||||
// RUN: -wmo -runtime-compatibility-version none %s -o %t/t3.out
|
||||
// RUN: not --crash %t/t3.out 2>&1 | %FileCheck %s --check-prefix=CHECK-T3
|
||||
|
||||
// RUN: %target-build-swift -DT4 -enable-experimental-feature Embedded \
|
||||
// RUN: -parse-as-library -Xlinker %t/unbuffered-putchar.o \
|
||||
// RUN: -enable-experimental-feature EmbeddedExistentials \
|
||||
// RUN: -wmo -runtime-compatibility-version none %s -o %t/t4.out
|
||||
// RUN: not --crash %t/t4.out 2>&1 | %FileCheck %s --check-prefix=CHECK-T4
|
||||
|
||||
// REQUIRES: swift_in_compiler
|
||||
// REQUIRES: executable_test
|
||||
// REQUIRES: optimized_stdlib
|
||||
// REQUIRES: swift_feature_Embedded
|
||||
// REQUIRES: swift_feature_EmbeddedExistentials
|
||||
|
||||
// REQUIRES: OS=macosx
|
||||
|
||||
class CP {
|
||||
func foo() { print("foo called") }
|
||||
deinit {
|
||||
print("deinit called")
|
||||
}
|
||||
}
|
||||
|
||||
class C : CP {
|
||||
override func foo() { print("C.foo called") }
|
||||
}
|
||||
|
||||
class CP2 {
|
||||
func foo() { print("CP2.foo called") }
|
||||
deinit {
|
||||
print("deinit called")
|
||||
}
|
||||
}
|
||||
|
||||
struct StructWithClass {
|
||||
var c = C()
|
||||
}
|
||||
|
||||
|
||||
struct LargeStructWithClass {
|
||||
var c = C()
|
||||
var t = (0, 1, 2, 3, 4, 5, 6, 7, 8)
|
||||
func foo() { c.foo() }
|
||||
}
|
||||
|
||||
struct LargetMyStruct {
|
||||
var l = LargeStructWithClass()
|
||||
}
|
||||
|
||||
func test1(_ p: any Any) {
|
||||
print("test any as! CP")
|
||||
let c = p as! CP
|
||||
c.foo()
|
||||
}
|
||||
|
||||
func test2(_ p: any Any) {
|
||||
print("test any as! LargeStructWithClass")
|
||||
let c = p as! LargeStructWithClass
|
||||
c.foo()
|
||||
}
|
||||
|
||||
@main
|
||||
struct Main {
|
||||
static func main() {
|
||||
#if T1
|
||||
test1(StructWithClass())
|
||||
// CHECK-T1: test any as! CP
|
||||
// CHECK-T1: failed cast
|
||||
#endif
|
||||
|
||||
#if T2
|
||||
test1(CP2())
|
||||
// CHECK-T2: test any as! CP
|
||||
// CHECK-T2: failed cast
|
||||
#endif
|
||||
|
||||
#if T3
|
||||
test2(StructWithClass())
|
||||
// CHECK-T3: test any as! LargeStructWithClass
|
||||
// CHECK-T3: failed cast
|
||||
#endif
|
||||
|
||||
#if T4
|
||||
test2(CP2())
|
||||
// CHECK-T4: test any as! LargeStructWithClass
|
||||
// CHECK-T4: failed cast
|
||||
#endif
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user