diff --git a/lib/ConstExtract/ConstExtract.cpp b/lib/ConstExtract/ConstExtract.cpp index 669878075f8b1..481ca9cd9aa84 100644 --- a/lib/ConstExtract/ConstExtract.cpp +++ b/lib/ConstExtract/ConstExtract.cpp @@ -811,79 +811,41 @@ void writeAttrInformation(llvm::json::OStream &JSON, }); } -void writeParameterizedProtocolSameTypeRequirements( - llvm::json::OStream &JSON, - const ParameterizedProtocolType &ParameterizedProtoTy) { - auto Protocol = ParameterizedProtoTy.getProtocol(); - auto ProtocolTy = ParameterizedProtoTy.getBaseType(); - auto Requirements = Protocol->getProtocolRequirements(); - auto ParameterTypeNames = Protocol->getPrimaryAssociatedTypeNames(); - auto ProtocolArguments = ParameterizedProtoTy.getArgs(); - llvm::dbgs() << Requirements.size() << "\n"; - assert(ProtocolArguments.size() >= ParameterTypeNames.size()); - - for (size_t i = 0; i < ProtocolArguments.size(); ++i) { - auto ProtocolArgumentTy = ProtocolArguments[i]; - std::string ArgumentName = ParameterTypeNames.size() > i - ? ParameterTypeNames[i].first.str().str() - : "unknown"; - - JSON.object([&] { - auto QualifiedTypeAliasName = toFullyQualifiedProtocolNameString( - *ParameterizedProtoTy.getProtocol()) + - "." + ArgumentName; - JSON.attribute("typeAliasName", QualifiedTypeAliasName); - JSON.attribute("substitutedTypeName", - toFullyQualifiedTypeNameString(ProtocolArgumentTy)); - JSON.attribute("substitutedMangledTypeName", - toMangledTypeNameString(ProtocolArgumentTy)); - }); - } -} - -void writeOpaqueTypeProtocolCompositionSameTypeRequirements( - llvm::json::OStream &JSON, - const ProtocolCompositionType &ProtocolCompositionTy) { - for (auto CompositionMemberProto : ProtocolCompositionTy.getMembers()) { - if (auto ParameterizedProtoTy = - CompositionMemberProto->getAs()) { - writeParameterizedProtocolSameTypeRequirements(JSON, - *ParameterizedProtoTy); - } - } -} - void writeSubstitutedOpaqueTypeAliasDetails( llvm::json::OStream &JSON, const OpaqueTypeArchetypeType &OpaqueTy) { + auto Signature = OpaqueTy.getDecl()->getOpaqueInterfaceGenericSignature(); + JSON.attributeArray("opaqueTypeProtocolRequirements", [&] { - auto ConformsToProtocols = OpaqueTy.getConformsTo(); - for (auto Proto : ConformsToProtocols) { - JSON.value(toFullyQualifiedProtocolNameString(*Proto)); + for (const auto Requirement : Signature.getRequirements()) { + // Ignore requirements whose subject type is that of the owner decl + if (!Requirement.getFirstType()->isEqual(OpaqueTy.getInterfaceType())) + continue; + if (Requirement.getKind() == RequirementKind::Conformance) + JSON.value( + toFullyQualifiedProtocolNameString(*Requirement.getProtocolDecl())); } }); + JSON.attributeArray("opaqueTypeSameTypeRequirements", [&] { - auto GenericSig = OpaqueTy.getDecl() - ->getNamingDecl() - ->getInnermostDeclContext() - ->getGenericSignatureOfContext(); - auto ConstraintTy = OpaqueTy.getExistentialType(); - if (auto existential = ConstraintTy->getAs()) - ConstraintTy = existential->getConstraintType(); - - // Opaque archetype substitutions are always canonical, so - // re-sugar the constraint type using the owning - // declaration's generic parameter names. - if (GenericSig) - ConstraintTy = GenericSig->getSugaredType(ConstraintTy); - - if (auto ParameterizedProtoTy = - ConstraintTy->getAs()) { - writeParameterizedProtocolSameTypeRequirements(JSON, - *ParameterizedProtoTy); - } else if (auto ProtocolCompositionTy = - ConstraintTy->getAs()) { - writeOpaqueTypeProtocolCompositionSameTypeRequirements( - JSON, *ProtocolCompositionTy); + for (const auto Requirement : Signature.getRequirements()) { + if (Requirement.getKind() == RequirementKind::SameType) { + auto TypeAliasType = Requirement.getFirstType(); + auto TypeWitness = Requirement.getSecondType(); + JSON.object([&] { + auto TypeAliasName = toFullyQualifiedTypeNameString(TypeAliasType); + if (auto DependentMemberTy = + TypeAliasType->getAs()) + if (const auto *Assoc = DependentMemberTy->getAssocType()) + TypeAliasName = + toFullyQualifiedProtocolNameString(*Assoc->getProtocol()) + + "." + DependentMemberTy->getName().str().str(); + JSON.attribute("typeAliasName", TypeAliasName); + JSON.attribute("substitutedTypeName", + toFullyQualifiedTypeNameString(TypeWitness)); + JSON.attribute("substitutedMangledTypeName", + toMangledTypeNameString(TypeWitness)); + }); + } } }); } diff --git a/test/ConstExtraction/ExtractOpaqueGenericTypealias.swift b/test/ConstExtraction/ExtractOpaqueGenericTypealias.swift new file mode 100644 index 0000000000000..a94b941c0b58b --- /dev/null +++ b/test/ConstExtraction/ExtractOpaqueGenericTypealias.swift @@ -0,0 +1,57 @@ +// REQUIRES: OS=macosx +// RUN: %empty-directory(%t) +// RUN: %empty-directory(%t/includes) +// RUN: echo "[myProto]" > %t/protocols.json + +// RUN: %target-swift-frontend -target %target-cpu-apple-macosx10.15 -typecheck -emit-const-values-path %t/ExtractOpaqueGenericTypealias.swiftconstvalues -const-gather-protocols-file %t/protocols.json -primary-file %s -I %t/includes +// RUN: cat %t/ExtractOpaqueGenericTypealias.swiftconstvalues 2>&1 | %FileCheck %s + +protocol myProto { + associatedtype T + func foo() -> T +} + +protocol protoA { + associatedtype T +} + +struct A : protoA { + typealias T = K +} + +struct Foo : myProto { + func foo() -> some protoA { return A() } + func bar(_ param : L) {} +} + +// CHECK: [ +// CHECK-NEXT: { +// CHECK-NEXT: "typeName": "ExtractOpaqueGenericTypealias.Foo", +// CHECK-NEXT: "mangledTypeName": "29ExtractOpaqueGenericTypealias3FooVyxG", +// CHECK-NEXT: "kind": "generic struct", +// CHECK-NEXT: "file": "{{.*}}test{{/|\\\\}}ConstExtraction{{/|\\\\}}ExtractOpaqueGenericTypealias.swift", +// CHECK-NEXT: "line": 22, +// CHECK-NEXT: "conformances": [ +// CHECK-NEXT: "ExtractOpaqueGenericTypealias.myProto", +// CHECK-NEXT: "Swift.Sendable" +// CHECK-NEXT: ], +// CHECK-NEXT: "associatedTypeAliases": [ +// CHECK-NEXT: { +// CHECK-NEXT: "typeAliasName": "T", +// CHECK-NEXT: "substitutedTypeName": "some ExtractOpaqueGenericTypealias.protoA", +// CHECK-NEXT: "substitutedMangledTypeName": "29ExtractOpaqueGenericTypealias3FooV3fooQryFQOyx_Qo_", +// CHECK-NEXT: "opaqueTypeProtocolRequirements": [ +// CHECK-NEXT: "ExtractOpaqueGenericTypealias.protoA" +// CHECK-NEXT: ], +// CHECK-NEXT: "opaqueTypeSameTypeRequirements": [ +// CHECK-NEXT: { +// CHECK-NEXT: "typeAliasName": "ExtractOpaqueGenericTypealias.protoA.T", +// CHECK-NEXT: "substitutedTypeName": "Swift.Int", +// CHECK-NEXT: "substitutedMangledTypeName": "Si" +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ], +// CHECK-NEXT: "properties": [] +// CHECK-NEXT: } +// CHECK-NEXT: ] diff --git a/test/ConstExtraction/ExtractOpaqueTypealias.swift b/test/ConstExtraction/ExtractOpaqueTypealias.swift index a30e739481d01..92fee013ac132 100644 --- a/test/ConstExtraction/ExtractOpaqueTypealias.swift +++ b/test/ConstExtraction/ExtractOpaqueTypealias.swift @@ -56,15 +56,15 @@ private func baz() -> some protoA & protoB & testModBProt // CHECK-NEXT: ], // CHECK-NEXT: "opaqueTypeSameTypeRequirements": [ // CHECK-NEXT: { -// CHECK-NEXT: "typeAliasName": "ExtractOpaqueTypealias.protoA.T", -// CHECK-NEXT: "substitutedTypeName": "testModB.testModBStruct", -// CHECK-NEXT: "substitutedMangledTypeName": "8testModB0aB7BStructV" -// CHECK-NEXT: }, -// CHECK-NEXT: { // CHECK-NEXT: "typeAliasName": "ExtractOpaqueTypealias.protoB.K", // CHECK-NEXT: "substitutedTypeName": "Swift.Float", // CHECK-NEXT: "substitutedMangledTypeName": "Sf" // CHECK-NEXT: } +// CHECK-NEXT: { +// CHECK-NEXT: "typeAliasName": "ExtractOpaqueTypealias.protoA.T", +// CHECK-NEXT: "substitutedTypeName": "testModB.testModBStruct", +// CHECK-NEXT: "substitutedMangledTypeName": "8testModB0aB7BStructV" +// CHECK-NEXT: } // CHECK-NEXT: ] // CHECK-NEXT: } // CHECK-NEXT: ],