| //===--- TypeRef.cpp - TypeRef tests --------------------------------------===// |
| // |
| // This source file is part of the Swift.org open source project |
| // |
| // Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors |
| // Licensed under Apache License v2.0 with Runtime Library Exception |
| // |
| // See https://swift.org/LICENSE.txt for license information |
| // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "swift/Reflection/TypeRefBuilder.h" |
| #include "swift/Remote/MetadataReader.h" |
| #include "gtest/gtest.h" |
| |
| using namespace swift; |
| using namespace reflection; |
| |
| static const std::string ABC = "ABC"; |
| static const std::string ABCD = "ABCD"; |
| static const std::string XYZ = "XYZ"; |
| static const std::string Empty = ""; |
| static const std::string MyClass = "MyClass"; |
| static const std::string NotMyClass = "NotMyClass"; |
| static const std::string MyModule = "MyModule"; |
| static const std::string Shmodule = "Shmodule"; |
| static const std::string MyProtocol = "MyProtocol"; |
| static const std::string Shmrotocol = "Shmrotocol"; |
| |
| using Param = remote::FunctionParam<const TypeRef *>; |
| |
| TEST(TypeRefTest, UniqueBuiltinTypeRef) { |
| TypeRefBuilder Builder; |
| |
| auto BI1 = Builder.createBuiltinType(ABC, ABC); |
| auto BI2 = Builder.createBuiltinType(ABC, ABC); |
| auto BI3 = Builder.createBuiltinType(ABCD, ABCD); |
| |
| EXPECT_EQ(BI1, BI2); |
| EXPECT_NE(BI2, BI3); |
| } |
| |
| TEST(TypeRefTest, UniqueNominalTypeRef) { |
| TypeRefBuilder Builder; |
| |
| auto N1 = Builder.createNominalType(ABC, nullptr); |
| auto N2 = Builder.createNominalType(ABC, nullptr); |
| auto N3 = Builder.createNominalType(ABCD, nullptr); |
| |
| EXPECT_EQ(N1, N2); |
| EXPECT_NE(N2, N3); |
| |
| auto N4 = Builder.createNominalType(ABC, N1); |
| auto N5 = Builder.createNominalType(ABC, N1); |
| |
| EXPECT_EQ(N4, N5); |
| } |
| |
| TEST(TypeRefTest, UniqueBoundGenericTypeRef) { |
| TypeRefBuilder Builder; |
| |
| auto GTP00 = Builder.createGenericTypeParameterType(0, 0); |
| auto GTP01 = Builder.createGenericTypeParameterType(0, 1); |
| |
| auto BG1 = Builder.createBoundGenericType(ABC, {}, nullptr); |
| auto BG2 = Builder.createBoundGenericType(ABC, {}, nullptr); |
| auto BG3 = Builder.createBoundGenericType(ABCD, {}, nullptr); |
| |
| EXPECT_EQ(BG1, BG2); |
| EXPECT_NE(BG2, BG3); |
| |
| std::vector<const TypeRef *> GenericParams { GTP00, GTP01 }; |
| |
| auto BG4 = Builder.createBoundGenericType(ABC, GenericParams, nullptr); |
| auto BG5 = Builder.createBoundGenericType(ABC, GenericParams, nullptr); |
| auto BG6 = Builder.createBoundGenericType(ABCD, GenericParams, nullptr); |
| |
| EXPECT_EQ(BG4, BG5); |
| EXPECT_NE(BG5, BG6); |
| EXPECT_NE(BG5, BG1); |
| } |
| |
| TEST(TypeRefTest, UniqueTupleTypeRef) { |
| TypeRefBuilder Builder; |
| |
| auto N1 = Builder.createNominalType(ABC, nullptr); |
| auto N2 = Builder.createNominalType(XYZ, nullptr); |
| |
| std::vector<const TypeRef *> Void; |
| auto Void1 = Builder.createTupleType(Void, "", false); |
| auto Void2 = Builder.createTupleType(Void, "", false); |
| |
| EXPECT_EQ(Void1, Void2); |
| |
| std::vector<const TypeRef *> Elements1 { N1, N2 }; |
| std::vector<const TypeRef *> Elements2 { N1, N2, N2 }; |
| |
| auto T1 = Builder.createTupleType(Elements1, "", false); |
| auto T2 = Builder.createTupleType(Elements1, "", false); |
| auto T3 = Builder.createTupleType(Elements2, "", false); |
| |
| EXPECT_EQ(T1, T2); |
| EXPECT_NE(T2, T3); |
| EXPECT_NE(T1, Void1); |
| |
| auto T4 = Builder.createTupleType(Elements1, "", true); |
| auto T5 = Builder.createTupleType(Elements1, "", true); |
| auto T6 = Builder.createTupleType(Elements1, "", false); |
| |
| EXPECT_EQ(T4, T5); |
| EXPECT_NE(T5, T6); |
| } |
| |
| TEST(TypeRefTest, UniqueFunctionTypeRef) { |
| |
| TypeRefBuilder Builder; |
| |
| std::vector<const TypeRef *> Void; |
| auto VoidResult = Builder.createTupleType(Void, "", false); |
| Param Param1 = Builder.createNominalType(ABC, nullptr); |
| Param Param2 = Builder.createNominalType(XYZ, nullptr); |
| |
| std::vector<Param> VoidParams; |
| std::vector<Param> Parameters1{Param1, Param2}; |
| std::vector<Param> Parameters2{Param1, Param1}; |
| |
| auto Result = |
| Builder.createTupleType({Param1.getType(), Param2.getType()}, "", false); |
| |
| auto F1 = |
| Builder.createFunctionType(Parameters1, Result, FunctionTypeFlags()); |
| auto F2 = |
| Builder.createFunctionType(Parameters1, Result, FunctionTypeFlags()); |
| auto F3 = |
| Builder.createFunctionType(Parameters2, Result, FunctionTypeFlags()); |
| |
| EXPECT_EQ(F1, F2); |
| EXPECT_NE(F2, F3); |
| |
| auto F4 = Builder.createFunctionType(Parameters1, Result, |
| FunctionTypeFlags().withThrows(true)); |
| auto F5 = Builder.createFunctionType(Parameters1, Result, |
| FunctionTypeFlags().withThrows(true)); |
| |
| EXPECT_EQ(F4, F5); |
| EXPECT_NE(F4, F1); |
| |
| // Test parameter with and without inout/shared/variadic and/or label. |
| ParameterFlags paramFlags; |
| auto inoutFlags = paramFlags.withValueOwnership(ValueOwnership::InOut); |
| auto variadicFlags = paramFlags.withVariadic(true); |
| auto sharedFlags = paramFlags.withValueOwnership(ValueOwnership::Shared); |
| auto ownedFlags = paramFlags.withValueOwnership(ValueOwnership::Owned); |
| |
| auto F6 = Builder.createFunctionType({Param1.withFlags(inoutFlags)}, Result, |
| FunctionTypeFlags()); |
| auto F6_1 = Builder.createFunctionType({Param1.withFlags(inoutFlags)}, Result, |
| FunctionTypeFlags()); |
| EXPECT_EQ(F6, F6_1); |
| |
| auto F7 = Builder.createFunctionType({Param1.withFlags(variadicFlags)}, |
| Result, FunctionTypeFlags()); |
| auto F7_1 = Builder.createFunctionType({Param1.withFlags(variadicFlags)}, |
| Result, FunctionTypeFlags()); |
| EXPECT_EQ(F7, F7_1); |
| |
| auto F8 = Builder.createFunctionType({Param1.withFlags(sharedFlags)}, Result, |
| FunctionTypeFlags()); |
| auto F8_1 = Builder.createFunctionType({Param1.withFlags(sharedFlags)}, |
| Result, FunctionTypeFlags()); |
| EXPECT_EQ(F8, F8_1); |
| |
| auto F9 = Builder.createFunctionType({Param1.withFlags(ownedFlags)}, Result, |
| FunctionTypeFlags()); |
| auto F9_1 = Builder.createFunctionType({Param1.withFlags(ownedFlags)}, |
| Result, FunctionTypeFlags()); |
| EXPECT_EQ(F9, F9_1); |
| |
| auto F10 = Builder.createFunctionType({Param1}, Result, FunctionTypeFlags()); |
| auto F10_1 = Builder.createFunctionType({Param1.withLabel("foo")}, Result, |
| FunctionTypeFlags()); |
| EXPECT_NE(F10, F10_1); |
| |
| EXPECT_NE(F6, F7); |
| EXPECT_NE(F6, F8); |
| EXPECT_NE(F6, F9); |
| EXPECT_NE(F6, F10); |
| EXPECT_NE(F7, F8); |
| EXPECT_NE(F7, F9); |
| EXPECT_NE(F7, F10); |
| EXPECT_NE(F8, F9); |
| EXPECT_NE(F8, F10); |
| EXPECT_NE(F9, F10); |
| |
| auto VoidVoid1 = |
| Builder.createFunctionType(VoidParams, VoidResult, FunctionTypeFlags()); |
| auto VoidVoid2 = |
| Builder.createFunctionType(VoidParams, VoidResult, FunctionTypeFlags()); |
| |
| EXPECT_EQ(VoidVoid1, VoidVoid2); |
| EXPECT_NE(VoidVoid1, F1); |
| |
| // Test escaping. |
| auto F11 = Builder.createFunctionType(Parameters1, Result, |
| FunctionTypeFlags().withEscaping(true)); |
| auto F12 = Builder.createFunctionType(Parameters1, Result, |
| FunctionTypeFlags().withEscaping(true)); |
| auto F13 = Builder.createFunctionType( |
| Parameters1, Result, FunctionTypeFlags().withEscaping(false)); |
| EXPECT_EQ(F11, F12); |
| EXPECT_NE(F11, F13); |
| } |
| |
| TEST(TypeRefTest, UniqueProtocolTypeRef) { |
| TypeRefBuilder Builder; |
| |
| TypeRefBuilder::BuiltProtocolDecl P1 = std::make_pair(ABC, false); |
| TypeRefBuilder::BuiltProtocolDecl P2 = std::make_pair(ABC, false); |
| TypeRefBuilder::BuiltProtocolDecl P3 = std::make_pair(ABCD, false); |
| TypeRefBuilder::BuiltProtocolDecl P4 = std::make_pair(XYZ, false); |
| |
| EXPECT_EQ(P1, P2); |
| EXPECT_NE(P2, P3); |
| EXPECT_NE(P2, P3); |
| EXPECT_NE(P3, P4); |
| |
| auto PC1 = Builder.createProtocolCompositionType({P1, P2}, nullptr, false); |
| auto PC2 = Builder.createProtocolCompositionType({P1, P2}, nullptr, false); |
| auto PC3 = |
| Builder.createProtocolCompositionType({P1, P2, P2}, nullptr, false); |
| auto Any = Builder.createProtocolCompositionType({}, nullptr, false); |
| |
| EXPECT_EQ(PC1, PC2); |
| EXPECT_NE(PC2, PC3); |
| EXPECT_NE(PC1, Any); |
| } |
| |
| TEST(TypeRefTest, UniqueMetatypeTypeRef) { |
| TypeRefBuilder Builder; |
| |
| auto N1 = Builder.createNominalType(ABC, nullptr); |
| auto M1 = Builder.createMetatypeType(N1, None); |
| auto M2 = Builder.createMetatypeType(N1, None); |
| auto MM3 = Builder.createMetatypeType(M1, None); |
| auto M4 = Builder.createMetatypeType(N1, Demangle::ImplMetatypeRepresentation::Thick); |
| |
| EXPECT_EQ(M1, M2); |
| EXPECT_NE(M2, MM3); |
| EXPECT_NE(M1, M4); |
| } |
| |
| TEST(TypeRefTest, UniqueExistentialMetatypeTypeRef) { |
| TypeRefBuilder Builder; |
| |
| auto N1 = Builder.createNominalType(ABC, nullptr); |
| auto M1 = Builder.createExistentialMetatypeType(N1); |
| auto M2 = Builder.createExistentialMetatypeType(N1); |
| auto MM3 = Builder.createExistentialMetatypeType(M1); |
| |
| EXPECT_EQ(M1, M2); |
| EXPECT_NE(M2, MM3); |
| } |
| |
| TEST(TypeRefTest, UniqueGenericTypeParameterTypeRef) { |
| TypeRefBuilder Builder; |
| |
| auto GTP00 = Builder.createGenericTypeParameterType(0, 0); |
| auto GTP00_2 = Builder.createGenericTypeParameterType(0, 0); |
| auto GTP01 = Builder.createGenericTypeParameterType(0, 1); |
| auto GTP10 = Builder.createGenericTypeParameterType(1, 0); |
| |
| EXPECT_EQ(GTP00, GTP00_2); |
| EXPECT_NE(GTP00, GTP01); |
| EXPECT_NE(GTP01, GTP10); |
| } |
| |
| TEST(TypeRefTest, UniqueDependentMemberTypeRef) { |
| TypeRefBuilder Builder; |
| |
| auto N1 = Builder.createNominalType(ABC, nullptr); |
| auto N2 = Builder.createNominalType(XYZ, nullptr); |
| TypeRefBuilder::BuiltProtocolDecl P1 = std::make_pair(ABC, false); |
| TypeRefBuilder::BuiltProtocolDecl P2 = std::make_pair(ABCD, false); |
| |
| auto DM1 = Builder.createDependentMemberType("Index", N1, P1); |
| auto DM2 = Builder.createDependentMemberType("Index", N1, P1); |
| auto DM3 = Builder.createDependentMemberType("Element", N1, P1); |
| auto DM4 = Builder.createDependentMemberType("Index", N2, P1); |
| auto DM5 = Builder.createDependentMemberType("Index", N2, P2); |
| |
| EXPECT_EQ(DM1, DM2); |
| EXPECT_NE(DM2, DM3); |
| EXPECT_NE(DM2, DM4); |
| EXPECT_NE(DM4, DM5); |
| } |
| |
| TEST(TypeRefTest, UniqueForeignClassTypeRef) { |
| TypeRefBuilder Builder; |
| |
| auto UN1 = Builder.getUnnamedForeignClassType(); |
| auto UN2 = Builder.getUnnamedForeignClassType(); |
| auto FC1 = Builder.createForeignClassType(ABC); |
| auto FC2 = Builder.createForeignClassType(ABC); |
| auto FC3 = Builder.createForeignClassType(ABCD); |
| |
| EXPECT_EQ(UN1, UN2); |
| EXPECT_EQ(FC1, FC2); |
| EXPECT_NE(FC2, FC3); |
| } |
| |
| TEST(TypeRefTest, UniqueObjCClassTypeRef) { |
| TypeRefBuilder Builder; |
| |
| auto UN1 = Builder.getUnnamedObjCClassType(); |
| auto UN2 = Builder.getUnnamedObjCClassType(); |
| auto FC1 = Builder.createObjCClassType(ABC); |
| auto FC2 = Builder.createObjCClassType(ABC); |
| auto FC3 = Builder.createObjCClassType(ABCD); |
| |
| EXPECT_EQ(UN1, UN2); |
| EXPECT_EQ(FC1, FC2); |
| EXPECT_NE(FC2, FC3); |
| } |
| |
| TEST(TypeRefTest, UniqueOpaqueTypeRef) { |
| TypeRefBuilder Builder; |
| |
| auto Op = OpaqueTypeRef::get(); |
| auto Op1 = Builder.getOpaqueType(); |
| auto Op2 = Builder.getOpaqueType(); |
| |
| EXPECT_EQ(Op, Op1); |
| EXPECT_EQ(Op1, Op2); |
| } |
| |
| TEST(TypeRefTest, UniqueUnownedStorageType) { |
| TypeRefBuilder Builder; |
| |
| auto N1 = Builder.createNominalType(MyClass, nullptr); |
| auto N2 = Builder.createNominalType(NotMyClass, nullptr); |
| auto RS1 = Builder.createUnownedStorageType(N1); |
| auto RS2 = Builder.createUnownedStorageType(N1); |
| auto RS3 = Builder.createUnownedStorageType(N2); |
| |
| EXPECT_EQ(RS1, RS2); |
| EXPECT_NE(RS2, RS3); |
| } |
| |
| TEST(TypeRefTest, UniqueWeakStorageType) { |
| TypeRefBuilder Builder; |
| |
| auto N1 = Builder.createNominalType(MyClass, nullptr); |
| auto N2 = Builder.createNominalType(NotMyClass, nullptr); |
| auto RS1 = Builder.createWeakStorageType(N1); |
| auto RS2 = Builder.createWeakStorageType(N1); |
| auto RS3 = Builder.createWeakStorageType(N2); |
| |
| EXPECT_EQ(RS1, RS2); |
| EXPECT_NE(RS2, RS3); |
| } |
| |
| TEST(TypeRefTest, UniqueUnmanagedStorageType) { |
| TypeRefBuilder Builder; |
| |
| auto N1 = Builder.createNominalType(MyClass, nullptr); |
| auto N2 = Builder.createNominalType(NotMyClass, nullptr); |
| auto RS1 = Builder.createUnmanagedStorageType(N1); |
| auto RS2 = Builder.createUnmanagedStorageType(N1); |
| auto RS3 = Builder.createUnmanagedStorageType(N2); |
| |
| EXPECT_EQ(RS1, RS2); |
| EXPECT_NE(RS2, RS3); |
| } |
| |
| // Tests that a concrete ABC<Int, Int> is the exact same typeref |
| // (with the same pointer) as an ABC<T, U> that got substituted |
| // with T : Int and U : Int. |
| TEST(TypeRefTest, UniqueAfterSubstitution) { |
| TypeRefBuilder Builder; |
| |
| std::string MangledIntName("Si"); |
| auto NominalInt = Builder.createNominalType(MangledIntName, |
| /*parent*/ nullptr); |
| std::vector<const TypeRef *> ConcreteArgs { NominalInt, NominalInt }; |
| |
| std::string MangledName("ABC"); |
| |
| auto ConcreteBG = Builder.createBoundGenericType(MangledName, |
| ConcreteArgs, |
| /*parent*/ nullptr); |
| |
| auto GTP00 = Builder.createGenericTypeParameterType(0, 0); |
| auto GTP01 = Builder.createGenericTypeParameterType(0, 1); |
| std::vector<const TypeRef *> GenericParams { GTP00, GTP01 }; |
| |
| auto Unbound = Builder.createBoundGenericType(MangledName, GenericParams, |
| /*parent*/ nullptr); |
| |
| GenericArgumentMap Subs; |
| Subs[{0,0}] = NominalInt; |
| Subs[{0,1}] = NominalInt; |
| |
| auto SubstitutedBG = Unbound->subst(Builder, Subs); |
| |
| EXPECT_EQ(ConcreteBG, SubstitutedBG); |
| } |
| |
| // Make sure subst() and isConcrete() walk into parent types |
| TEST(TypeRefTest, NestedTypes) { |
| TypeRefBuilder Builder; |
| |
| auto GTP00 = Builder.createGenericTypeParameterType(0, 0); |
| |
| std::string ParentName("parent"); |
| std::vector<const TypeRef *> ParentArgs { GTP00 }; |
| auto Parent = Builder.createBoundGenericType(ParentName, ParentArgs, |
| /*parent*/ nullptr); |
| |
| std::string ChildName("child"); |
| auto Child = Builder.createNominalType(ChildName, Parent); |
| |
| EXPECT_FALSE(Child->isConcrete()); |
| |
| std::string SubstName("subst"); |
| auto SubstArg = Builder.createNominalType(SubstName, /*parent*/ nullptr); |
| |
| std::vector<const TypeRef *> SubstParentArgs { SubstArg }; |
| auto SubstParent = Builder.createBoundGenericType(ParentName, |
| SubstParentArgs, |
| /*parent*/ nullptr); |
| auto SubstChild = Builder.createNominalType(ChildName, SubstParent); |
| |
| GenericArgumentMap Subs; |
| Subs[{0,0}] = SubstArg; |
| |
| EXPECT_TRUE(Child->isConcreteAfterSubstitutions(Subs)); |
| EXPECT_EQ(SubstChild, Child->subst(Builder, Subs)); |
| } |
| |
| TEST(TypeRefTest, DeriveSubstitutions) { |
| TypeRefBuilder Builder; |
| |
| auto GTP00 = Builder.createGenericTypeParameterType(0, 0); |
| auto GTP01 = Builder.createGenericTypeParameterType(0, 1); |
| |
| std::string NominalName("nominal"); |
| std::vector<const TypeRef *> NominalArgs { GTP00 }; |
| auto Nominal = Builder.createBoundGenericType(NominalName, NominalArgs, |
| /*parent*/ nullptr); |
| |
| auto Result = Builder.createTupleType({GTP00, GTP01}, "", false); |
| auto Func = |
| Builder.createFunctionType({Nominal}, Result, FunctionTypeFlags()); |
| |
| std::string SubstOneName("subst1"); |
| auto SubstOne = Builder.createNominalType(SubstOneName, /*parent*/ nullptr); |
| |
| std::string SubstTwoName("subst2"); |
| auto SubstTwo = Builder.createNominalType(SubstTwoName, /*parent*/ nullptr); |
| |
| GenericArgumentMap Subs; |
| Subs[{0,0}] = SubstOne; |
| Subs[{0,1}] = SubstTwo; |
| |
| auto Subst = Func->subst(Builder, Subs); |
| |
| GenericArgumentMap DerivedSubs; |
| EXPECT_TRUE(TypeRef::deriveSubstitutions(DerivedSubs, Func, Subst)); |
| |
| auto ResultOne = DerivedSubs[{0,0}]; |
| auto ResultTwo = DerivedSubs[{0,1}]; |
| EXPECT_EQ(SubstOne, ResultOne); |
| EXPECT_EQ(SubstTwo, ResultTwo); |
| } |