Skip to content

Commit 86fa47b

Browse files
authored
Merge pull request swiftlang#36402 from slavapestov/another-conformance-access-path-cleanup
GSB: getConformanceAccessPath() doesn't need to use getMinimalConformanceSource()
2 parents e1e0f54 + d59f01d commit 86fa47b

File tree

2 files changed

+49
-41
lines changed

2 files changed

+49
-41
lines changed

lib/AST/GenericSignature.cpp

Lines changed: 27 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -776,9 +776,21 @@ GenericSignatureImpl::getConformanceAccessPath(Type type,
776776
auto conforms = equivClass->conformsTo.find(protocol);
777777
assert(conforms != equivClass->conformsTo.end());
778778

779-
// Look at every requirement source for this conformance. If all sources are
780-
// explicit, leave these three values empty. Otherwise, they are computed
781-
// from the 'best' derived requirement source for this conformance.
779+
auto rootType = equivClass->getAnchor(builder, { });
780+
if (hasConformanceInSignature(getRequirements(), rootType, protocol)) {
781+
ConformanceAccessPath::Entry root(rootType, protocol);
782+
ArrayRef<ConformanceAccessPath::Entry> path(root);
783+
784+
ConformanceAccessPath result(builder.getASTContext().AllocateCopy(path));
785+
equivClass->conformanceAccessPathCache.insert({protocol, result});
786+
787+
return result;
788+
}
789+
790+
// This conformance comes from a derived source.
791+
//
792+
// To recover this the conformance, we recursively recover the conformance
793+
// of the shortest parent type to the parent protocol first.
782794
Type shortestParentType;
783795
Type shortestSubjectType;
784796
ProtocolDecl *shortestParentProto = nullptr;
@@ -823,28 +835,13 @@ GenericSignatureImpl::getConformanceAccessPath(Type type,
823835

824836
case RequirementSource::ProtocolRequirement:
825837
case RequirementSource::InferredProtocolRequirement: {
826-
if (source->parent->kind == RequirementSource::RequirementSignatureSelf) {
827-
// This is a top-level requirement in the requirement signature that is
828-
// currently being computed. This is not a derived source, so it
829-
// contributes nothing to the "shortest parent type" computation.
830-
break;
831-
}
832-
833-
auto constraintType = constraint.getSubjectDependentType({ });
834-
835-
// Skip self-recursive sources.
836-
bool derivedViaConcrete = false;
837-
if (source->getMinimalConformanceSource(builder, constraintType, protocol,
838-
derivedViaConcrete) != source)
839-
break;
840-
838+
assert(source->parent->kind != RequirementSource::RequirementSignatureSelf);
841839

842840
// If we have a derived conformance requirement like T[.P].X : Q, we can
843841
// recursively compute the conformance access path for T : P, and append
844842
// the path element (Self.X : Q).
845843
auto parentType = source->parent->getAffectedType()->getCanonicalType();
846844
auto subjectType = source->getStoredType()->getCanonicalType();
847-
848845
auto *parentProto = source->getProtocolDecl();
849846

850847
// We might have multiple candidate parent types and protocols for the
@@ -861,33 +858,22 @@ GenericSignatureImpl::getConformanceAccessPath(Type type,
861858
}
862859
}
863860

861+
assert(shortestParentType);
862+
864863
SmallVector<ConformanceAccessPath::Entry, 2> path;
865864

866-
if (!shortestParentType) {
867-
// All requirement sources were explicit. This means we can recover the
868-
// conformance directly from the generic signature; canonicalize the
869-
// dependent type and add it as an initial path element.
870-
auto rootType = equivClass->getAnchor(builder, { });
871-
assert(hasConformanceInSignature(getRequirements(), rootType, protocol));
872-
path.emplace_back(rootType, protocol);
873-
} else {
874-
// This conformance comes from a derived source.
875-
//
876-
// To recover this the conformance, we recursively recover the conformance
877-
// of the parent type to the parent protocol first.
878-
auto parentPath = getConformanceAccessPath(
879-
shortestParentType, shortestParentProto);
880-
for (auto entry : parentPath)
881-
path.push_back(entry);
882-
883-
// Then, we add the subject type from the parent protocol's requirement
884-
// signature.
885-
path.emplace_back(shortestSubjectType, protocol);
886-
}
865+
auto parentPath = getConformanceAccessPath(
866+
shortestParentType, shortestParentProto);
867+
for (auto entry : parentPath)
868+
path.push_back(entry);
887869

888-
ConformanceAccessPath result(getASTContext().AllocateCopy(path));
870+
// Then, we add the subject type from the parent protocol's requirement
871+
// signature.
872+
path.emplace_back(shortestSubjectType, protocol);
889873

874+
ConformanceAccessPath result(builder.getASTContext().AllocateCopy(path));
890875
equivClass->conformanceAccessPathCache.insert({protocol, result});
876+
891877
return result;
892878
}
893879

test/Generics/sr11153.swift

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// RUN: %target-swift-frontend -typecheck -debug-generic-signatures %s 2>&1 | not %FileCheck %s
2+
// RUN: %target-swift-frontend -emit-ir %s
3+
4+
// CHECK: Requirement signature: <Self where Self.Field : FieldAlgebra>
5+
public protocol VectorSpace {
6+
associatedtype Field: FieldAlgebra
7+
}
8+
9+
// CHECK: Requirement signature: <Self where Self : VectorSpace, Self == Self.Field, Self.ComparableSubalgebra : ComparableFieldAlgebra>
10+
public protocol FieldAlgebra: VectorSpace where Self.Field == Self {
11+
associatedtype ComparableSubalgebra: ComparableFieldAlgebra
12+
static var zero: Self { get }
13+
}
14+
15+
// CHECK: Requirement signature: <Self where Self : FieldAlgebra, Self == Self.ComparableSubalgebra>
16+
public protocol ComparableFieldAlgebra: FieldAlgebra where Self.ComparableSubalgebra == Self {
17+
}
18+
19+
// CHECK: Generic signature: <F where F : FieldAlgebra>
20+
public func test<F: FieldAlgebra>(_ f: F) {
21+
_ = F.ComparableSubalgebra.zero
22+
}

0 commit comments

Comments
 (0)