// RUN: %empty-directory(%t) // RUN: %target-build-swift -target %target-swift-5.1-abi-triple -parse-stdlib %s -module-name main -o %t/a.out \ // RUN: -enable-experimental-feature LifetimeDependence // RUN: %target-codesign %t/a.out // RUN: %target-run %t/a.out // REQUIRES: executable_test // REQUIRES: concurrency // REQUIRES: swift_feature_LifetimeDependence // UNSUPPORTED: use_os_stdlib // UNSUPPORTED: back_deployment_runtime import Swift import StdlibUnittest import _Concurrency let DemangleToMetadataTests = TestSuite("DemangleToMetadata") DemangleToMetadataTests.test("malformed mangled names") { expectNil(_typeByName("blah")) } DemangleToMetadataTests.test("tuple types") { expectEqual(type(of: ()), _typeByName("yt")!) expectEqual(type(of: ((), ())), _typeByName("yt_ytt")!) expectEqual(type(of: ((), b: ())), _typeByName("yt_yt1bt")!) expectEqual(type(of: (a: (), ())), _typeByName("yt1a_ytt")!) expectEqual(type(of: (a: (), b: ())), _typeByName("yt1a_yt1bt")!) // Initial creation of metadata via demangling a type name. expectNotNil(_typeByName("yt1a_yt3bcdt")) } func f0() { } var f0_thin: @convention(thin) () -> Void = f0 var f0_c: @convention(c) () -> Void = f0 #if _runtime(_ObjC) var f0_block: @convention(block) () -> Void = f0 #endif func f0_async() async { } func f0_throws() throws { } func f1(x: ()) { } func f2(x: (), y: ()) { } func f1_variadic(x: ()...) { } func f1_inout(x: inout ()) { } func f1_shared(x: __shared AnyObject) { } func f1_owned(x: __owned AnyObject) { } func f1_takes_concurrent(_: @Sendable () -> Void) { } func f2_variadic_inout(x: ()..., y: inout ()) { } func f1_escaping(_: @escaping (Int) -> Float) { } func f1_autoclosure(_: @autoclosure () -> Float) { } func f1_escaping_autoclosure(_: @autoclosure @escaping () -> Float) { } func f1_mainactor(_: @MainActor () -> Float) { } func globalActorMetatypeFn(_: T.Type) -> Any.Type { typealias Fn = @MainActor () -> T return Fn.self } @available(SwiftStdlib 5.1, *) func f1_actor(_: (isolated Actor) -> Void) { } DemangleToMetadataTests.test("function types") { // Conventions expectEqual(type(of: f0), _typeByName("yyc")!) expectEqual(type(of: f0_thin), _typeByName("yyXf")!) expectEqual(type(of: f0_c), _typeByName("yyXC")!) #if _runtime(_ObjC) expectEqual(type(of: f0_block), _typeByName("yyXB")!) #endif // Async functions expectEqual(type(of: f0_async), _typeByName("yyYac")!) // Throwing functions expectEqual(type(of: f0_throws), _typeByName("yyKc")!) // More parameters. expectEqual(type(of: f1), _typeByName("yyt_tc")!) expectEqual(type(of: f2), _typeByName("yyt_yttc")!) // Variadic parameters. expectEqual(type(of: f1_variadic), _typeByName("yytd_tc")!) // Inout parameters. expectEqual(type(of: f1_inout), _typeByName("yytzc")!) // Ownership parameters. expectEqual(type(of: f1_shared), _typeByName("yyXlhc")!) expectEqual(type(of: f1_owned), _typeByName("yyXlnc")!) // Concurrent function types. expectEqual(type(of: f1_takes_concurrent), _typeByName("yyyYbXEc")!) // Mix-and-match. expectEqual(type(of: f2_variadic_inout), _typeByName("yytd_ytztc")!) // A function type that hasn't been built before. expectEqual("(Int, Float, Double, String, Character, UInt, Bool) -> ()", String(describing: _typeByName("ySi_SfSdSSs9CharacterVSuSbtc")!)) // Escaping expectEqual(type(of: f1_escaping), _typeByName("ySfSicc")!) // Autoclosure expectEqual(type(of: f1_autoclosure), _typeByName("ySfyXKc")!) expectEqual(type(of: f1_escaping_autoclosure), _typeByName("ySfyXAc")!) // MainActor expectEqual(type(of: f1_mainactor), _typeByName("ySfyScMYcXEc")!) expectEqual( "(@MainActor () -> Float) -> ()", String(describing: _typeByName("ySfyScMYcXEc")!)) typealias MainActorFn = @MainActor () -> Float expectEqual(MainActorFn.self, _typeByName("SfyScMYcc")!) expectEqual(MainActorFn.self, globalActorMetatypeFn(Float.self)) // isolated parameters if #available(SwiftStdlib 5.1, *) { expectEqual(type(of: f1_actor), _typeByName("yyScA_pYiXEc")!) typealias IsolatedFn = ((isolated Actor) -> Void) -> Void expectEqual(IsolatedFn.self, type(of: f1_actor)) } } DemangleToMetadataTests.test("metatype types") { expectEqual(type(of: type(of: ())), _typeByName("ytm")!) expectEqual(type(of: type(of: f0)), _typeByName("yycm")!) } func f2_any_anyobject(_: Any, _: AnyObject) { } class C { } protocol P1 { } protocol P2 { } protocol P3 { } func f1_composition(_: P1 & P2) { } func f1_composition_anyobject(_: AnyObject & P1) { } func f1_composition_superclass(_: C & P1 & P2) { } DemangleToMetadataTests.test("existential types") { // Any, AnyObject expectEqual(type(of: f2_any_anyobject), _typeByName("yyp_yXltc")!) // References to protocols. expectEqual(type(of: f1_composition), _typeByName("y4main2P1_4main2P2pc")!) // Reference to protocol with AnyObject. expectEqual(type(of: f1_composition_anyobject), _typeByName("y4main2P1_Xlc")!) // References to superclass. expectEqual(type(of: f1_composition_superclass), _typeByName("y4main2P1_4main2P2AA1CCXcc")!) // Demangle an existential type that hasn't been seen before. expectEqual("P1 & P2 & P3", String(describing: _typeByName("4main2P1_4main2P24main2P3p")!)) } DemangleToMetadataTests.test("existential metatype types") { // Any expectEqual(type(of: Any.self), _typeByName("ypm")!) // AnyObject expectEqual(type(of: AnyObject.self), _typeByName("yXlm")!) // References to metatype of protocols. expectEqual(type(of: (P1 & P2).self), _typeByName("4main2P1_4main2P2pm")!) // References to metatype involving protocols and superclass. expectEqual(type(of: (C & P1 & P2).self), _typeByName("4main2P1_4main2P2AA1CCXcm")!) } struct S { struct Nested { } } enum E { case e } DemangleToMetadataTests.test("nominal types") { // Simple Struct expectEqual(type(of: S()), _typeByName("4main1SV")!) // Simple Enum expectEqual(type(of: E.e), _typeByName("4main1EO")!) // Simple Class expectEqual(type(of: C()), _typeByName("4main1CC")!) // Swift standard library types expectEqual(type(of: Int()), _typeByName("Si")!) expectEqual(type(of: Int16()), _typeByName("s5Int16V")!) // Nested struct expectEqual(type(of: S.Nested()), _typeByName("4main1SV6NestedV")!) // Class referenced by "ModuleName.ClassName" syntax. expectEqual(type(of: C()), _typeByName("main.C")!) } protocol P4 { associatedtype Assoc1 associatedtype Assoc2 } extension S: P4 { typealias Assoc1 = Int typealias Assoc2 = String } enum EG { case a } class CG3 { } DemangleToMetadataTests.test("simple generic specializations") { expectEqual([Int].self, _typeByName("SaySiG")!) expectEqual(EG.self, _typeByName("4main2EGOySiSSG")!) expectEqual(CG3.self, _typeByName("4main3CG3CySiSdSSG")!) } extension EG { struct NestedSG { } } extension C { enum Nested { case a struct Innermore { struct Innermost { } } } } class CG2 { class Inner { struct Innermost { } } } struct ReallyLongGeneric {} extension ReallyLongGeneric where T == U, U == V.Element, V == W, W: Collection { struct Nested {} } DemangleToMetadataTests.test("nested generic specializations") { expectEqual(EG.NestedSG.self, _typeByName("4main2EGO8NestedSGVySiSS_SdG")!) expectEqual(C.Nested.Innermore.Innermost.self, _typeByName("4main1CC6NestedO9InnermoreV9InnermostVy_SiSS__SdG")!) expectEqual(CG2.Inner.self, _typeByName("4main3CG2C5InnerCySiSS_SdG")!) expectEqual( CG2.Inner.Innermost.self, _typeByName("4main3CG2C5InnerC9InnermostVySiSS_Sd_s4Int8Vs5Int16Vs5Int32Vs5Int64VG")!) expectEqual( ReallyLongGeneric.Nested.self, _typeByName("4main17ReallyLongGenericVAAE6NestedVyS2iSaySiGAF_G")! ) } DemangleToMetadataTests.test("demangle built-in types") { expectEqual(Builtin.Int8.self, _typeByName("Bi8_")!) expectEqual(Builtin.Int16.self, _typeByName("Bi16_")!) expectEqual(Builtin.Int32.self, _typeByName("Bi32_")!) expectEqual(Builtin.Int64.self, _typeByName("Bi64_")!) expectEqual(Builtin.Int128.self, _typeByName("Bi128_")!) expectEqual(Builtin.Int256.self, _typeByName("Bi256_")!) expectEqual(Builtin.Int512.self, _typeByName("Bi512_")!) expectEqual(Builtin.NativeObject.self, _typeByName("Bo")!) expectEqual(Builtin.BridgeObject.self, _typeByName("Bb")!) expectEqual(Builtin.UnsafeValueBuffer.self, _typeByName("BB")!) expectEqual(Builtin.FPIEEE32.self, _typeByName("Bf32_")!) expectEqual(Builtin.FPIEEE64.self, _typeByName("Bf64_")!) expectEqual(Builtin.Vec4xFPIEEE32.self, _typeByName("Bf32_Bv4_")!) expectEqual(Builtin.RawUnsafeContinuation.self, _typeByName("Bc")!) expectEqual(Builtin.Executor.self, _typeByName("Be")!) expectNotNil(_typeByName("BD")) expectNotNil(_typeByName("Bd")) // NonDefaultDistributedActor storage expectEqual(Builtin.Job.self, _typeByName("Bj")!) } class CG4 { struct InnerGeneric { } } struct ConformsToP1: P1 { } struct ConformsToP2: P2 { } struct ConformsToP3: P3 { } struct ContextualWhere1 { class Nested1 where T: P1 { } struct Nested2 where T == Int { } } DemangleToMetadataTests.test("protocol conformance requirements") { expectEqual(CG4.self, _typeByName("4main3CG4CyAA12ConformsToP1VAA12ConformsToP2VG")!) expectEqual(CG4.InnerGeneric.self, _typeByName("4main3CG4C12InnerGenericVyAA12ConformsToP1VAA12ConformsToP2V_AA12ConformsToP3VG")!) expectEqual(ContextualWhere1.Nested1.self, _typeByName("4main16ContextualWhere1V7Nested1CyAA12ConformsToP1V_G")!) // Failure cases: failed conformance requirements. expectNil(_typeByName("4main3CG4CyAA12ConformsToP1VAA12ConformsToP1VG")) expectNil(_typeByName("4main3CG4CyAA12ConformsToP2VAA12ConformsToP2VG")) expectNil(_typeByName("4main3CG4C12InnerGenericVyAA12ConformsToP1VAA12ConformsToP2V_AA12ConformsToP2VG")) } struct SG5 where T.Assoc1: P1, T.Assoc2: P2 { } struct ConformsToP4a : P4 { typealias Assoc1 = ConformsToP1 typealias Assoc2 = ConformsToP2 } struct ConformsToP4b : P4 { typealias Assoc1 = ConformsToP1 typealias Assoc2 = ConformsToP1 } struct ConformsToP4c : P4 { typealias Assoc1 = ConformsToP2 typealias Assoc2 = ConformsToP2 } struct ContextualWhere2 { struct Nested1 where U.Assoc1: P1, U.Assoc2: P2 { } enum Nested2 where U.Assoc1 == U.Assoc2 { } } DemangleToMetadataTests.test("associated type conformance requirements") { expectEqual(SG5.self, _typeByName("4main3SG5VyAA13ConformsToP4aVG")!) expectEqual(ContextualWhere2.Nested1.self, _typeByName("4main16ContextualWhere2V7Nested1VyAA13ConformsToP4aV_G")!) // Failure cases: failed conformance requirements. expectNil(_typeByName("4main3SG5VyAA13ConformsToP4bVG")) expectNil(_typeByName("4main3SG5VyAA13ConformsToP4cVG")) expectNil(_typeByName("4main3SG5VyAA12ConformsToP1cVG")) } struct SG6 where T.Assoc1 == T.Assoc2 { } struct SG7 where T.Assoc1 == Int { } struct SG8 where T.Assoc1 == [T.Assoc2] { } struct ConformsToP4d : P4 { typealias Assoc1 = [ConformsToP2] typealias Assoc2 = ConformsToP2 } DemangleToMetadataTests.test("same-type requirements") { // Concrete type. expectEqual(SG7.self, _typeByName("4main3SG7VyAA1SVG")!) expectEqual(ContextualWhere1.Nested2.self, _typeByName("4main16ContextualWhere1V7Nested2VySi_G")!) // Other associated type. expectEqual(SG6.self, _typeByName("4main3SG6VyAA13ConformsToP4bVG")!) expectEqual(SG6.self, _typeByName("4main3SG6VyAA13ConformsToP4cVG")!) expectEqual(ContextualWhere2.Nested2.self, _typeByName("4main16ContextualWhere2V7Nested2OyAA13ConformsToP4bV_G")!) // Structural type. expectEqual(SG8.self, _typeByName("4main3SG8VyAA13ConformsToP4dVG")!) // Failure cases: types don't match. expectNil(_typeByName("4main3SG7VyAA13ConformsToP4aVG")) expectNil(_typeByName("4main3SG6VyAA13ConformsToP4aVG")) expectNil(_typeByName("4main3SG8VyAA13ConformsToP4cVG")) } struct SG9 { } DemangleToMetadataTests.test("AnyObject requirements") { expectEqual(SG9.self, _typeByName("4main3SG9VyAA1CCG")!) // Failure cases: failed AnyObject constraint. expectNil(_typeByName("4main3SG9VyAA1SVG")) } struct SG10 { } class C2 : C { } class C3 { } DemangleToMetadataTests.test("superclass requirements") { expectEqual(SG10.self, _typeByName("4main4SG10VyAA1CCG")!) expectEqual(SG10.self, _typeByName("4main4SG10VyAA2C2CG")!) // Failure cases: not a subclass. expectNil(_typeByName("4main4SG10VyAA2C3CG")) } // // Extensions of external types, and constrained extensions // struct SG11 {} extension Dictionary { struct Inner {} } extension SG11 where T: P1 { struct InnerTConformsToP1 { } } extension SG11.InnerTConformsToP1 where U: P3 { struct InnermostUConformsToP3 { } } struct ConformsToP2AndP3: P2, P3 { } DemangleToMetadataTests.test("Nested types in extensions") { expectEqual( Dictionary.Inner.self, _typeByName("s10DictionaryV4mainE5InnerVySSSi_AC12ConformsToP1VG")!) expectEqual( SG11.InnerTConformsToP1.self, _typeByName("4main4SG11VA2A2P1RzlE016InnerTConformsToC0VyAA08ConformsfC0V_AA0gF2P2VG")!) expectEqual( SG11.InnerTConformsToP1 .InnermostUConformsToP3.self, _typeByName("4main4SG11VA2A2P1RzlE016InnerTConformsToC0VA2A2P3Rd__rlE018InnermostUConformsfG0VyAA08ConformsfC0V_AA0jf5P2AndG0V_AA0jF3P4aVG")!) // Failure case: Dictionary's outer `Key: Hashable` constraint not satisfied expectNil(_typeByName("s10DictionaryV4mainE5InnerVyAC12ConformsToP1VSi_AC12ConformsToP1VG")) // Failure case: Dictionary's inner `V: P1` constraint not satisfied expectNil(_typeByName("s10DictionaryV4mainE5InnerVySSSi_AC12ConformsToP2VG")) // Failure case: SG11's outer `T: P1` constraint not satisfied expectNil(_typeByName("4main4SG11VA2A2P1RzlE016InnerTConformsToC0VyAA08ConformsF2P2V_AHGMa")) // Failure case: SG11's inner `U: P2` constraint not satisfied expectNil(_typeByName("4main4SG11VA2A2P1RzlE016InnerTConformsToC0VyAA08ConformsfC0V_AHGMa")) // TODO: Failure case: InnermostUConformsToP3's 'U: P3' constraint not satisfied } // // Nested types in same-type-constrained extensions // struct SG12 {} struct ConformsToP1AndP2 : P1, P2 { } extension SG12 where U == T { struct InnerTEqualsU { } } extension SG12 where T == ConformsToP1 { struct InnerTEqualsConformsToP1 { } } extension SG12 where U == ConformsToP2 { struct InnerUEqualsConformsToP2 { } } DemangleToMetadataTests.test("Nested types in same-type-constrained extensions") { expectEqual( SG12.InnerTEqualsU.self, _typeByName("4main4SG12VA2A2P2Rzq_RszrlE13InnerTEqualsUVyAA015ConformsToP1AndC0VAH_AA0fG2P3VG")!) expectEqual( SG12.InnerTEqualsConformsToP1.self, _typeByName("4main4SG12VA2A12ConformsToP1VRszrlE012InnerTEqualscdE0VyAeA0cD2P2V_AA0cD2P3VG")!) expectEqual( SG12.InnerUEqualsConformsToP2.self, _typeByName("4main4SG12VA2A12ConformsToP2VRs_rlE012InnerUEqualscdE0VyAA0cD2P1VAE_AA0cD2P3VG")!) // TODO: Cases where mangled name doesn't match constraints // T != U in InnerTEqualsU // V !: P3 in InnerTEqualsU // T != ConformsToP1 in InnerTEqualsConformsToP1 // V !: P3 in InnerTEqualsConformsToP1 } struct NonCopyable: ~Copyable {} struct NonEscapable: ~Escapable {} if #available(SwiftStdlib 5.3, *) { DemangleToMetadataTests.test("Round-trip with _mangledTypeName and _typeByName") { func roundTrip(_ type: T.Type) { let mangledName: String? = _mangledTypeName(type) let recoveredType: Any.Type? = _typeByName(mangledName!) expectEqual(String(reflecting: type), String(reflecting: recoveredType!)) expectEqual(type, recoveredType! as! T.Type) } roundTrip(Int.self) roundTrip(String.self) roundTrip(ConformsToP2AndP3.self) roundTrip(SG12.self) roundTrip(SG12.InnerTEqualsU.self) roundTrip(SG12.InnerTEqualsConformsToP1.self) roundTrip(SG12.InnerUEqualsConformsToP2.self) } DemangleToMetadataTests.test("Check _mangledTypeName, _typeName use appropriate cache keys") { // soundness check that name functions use the right keys to store cached names: for _ in 1...2 { expectEqual("Si", _mangledTypeName(Int.self)!) expectEqual("Swift.Int", _typeName(Int.self, qualified: true)) expectEqual("Int", _typeName(Int.self, qualified: false)) } } DemangleToMetadataTests.test("Check _mangledTypeName with Any.Type") { let type: Any.Type = Int.self expectEqual("Si", _mangledTypeName(type)) } DemangleToMetadataTests.test("Check _MangledTypeName with any ~Copyable.Type") { let type: any ~Copyable.Type = NonCopyable.self expectEqual("4main11NonCopyableV", _mangledTypeName(type)) } DemangleToMetadataTests.test("Check _MangledTypeName with any ~Escapable.Type") { let type: any ~Escapable.Type = NonEscapable.self expectEqual("4main12NonEscapableV", _mangledTypeName(type)) } } if #available(SwiftStdlib 5.1, *) { DemangleToMetadataTests.test("Concurrency standard substitutions") { expectEqual(TaskGroup.self, _typeByName("ScGySiG")!) } } enum MyBigError: Error { case epicFail } @available(SwiftStdlib 6.0, *) func getFnTypeWithThrownError(_: E.Type) -> Any.Type { typealias Fn = (Int) throws(E) -> Void return Fn.self } if #available(SwiftStdlib 6.0, *) { DemangleToMetadataTests.test("typed throws") { typealias Fn = (Int) throws(MyBigError) -> Void expectEqual("ySi4main10MyBigErrorOYKc", _mangledTypeName(Fn.self)!) expectEqual(Fn.self, _typeByName("ySi4main10MyBigErrorOYKc")!) expectEqual(getFnTypeWithThrownError(MyBigError.self), _typeByName("ySi4main10MyBigErrorOYKc")!) // throws(any Error) -> throws expectEqual(getFnTypeWithThrownError((any Error).self), _typeByName("ySiKc")!) // throws(Never) -> non-throwing expectEqual(getFnTypeWithThrownError(Never.self), _typeByName("ySic")!) } } if #available(SwiftStdlib 6.1, *) { DemangleToMetadataTests.test("NUL-terminated name, excessive length value") { let t = _typeByName("4main1SV\0random stuff here") expectNotNil(t) if let t { expectEqual(type(of: S()), t) } } } runAllTests()