Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 29 additions & 67 deletions lib/ConstExtract/ConstExtract.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<ParameterizedProtocolType>()) {
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<ExistentialType>())
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<ParameterizedProtocolType>()) {
writeParameterizedProtocolSameTypeRequirements(JSON,
*ParameterizedProtoTy);
} else if (auto ProtocolCompositionTy =
ConstraintTy->getAs<ProtocolCompositionType>()) {
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<DependentMemberType>())
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));
});
}
}
});
}
Expand Down
57 changes: 57 additions & 0 deletions test/ConstExtraction/ExtractOpaqueGenericTypealias.swift
Original file line number Diff line number Diff line change
@@ -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<T> {
associatedtype T
}

struct A<K> : protoA {
typealias T = K
}

struct Foo<L : Hashable> : myProto {
func foo() -> some protoA<Int> { return A() }
func bar(_ param : L) {}
}

// CHECK: [
// CHECK-NEXT: {
// CHECK-NEXT: "typeName": "ExtractOpaqueGenericTypealias.Foo<L>",
// 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<Swift.Int>",
// 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: ]
10 changes: 5 additions & 5 deletions test/ConstExtraction/ExtractOpaqueTypealias.swift
Original file line number Diff line number Diff line change
Expand Up @@ -56,15 +56,15 @@ private func baz() -> some protoA<testModBStruct> & protoB<Float> & 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: ],
Expand Down