Skip to content

Commit b2fa269

Browse files
authored
Merge pull request #33886 from AnthonyLatsis/fixed-means-same-type
2 parents 9d77017 + 8cae50a commit b2fa269

File tree

3 files changed

+38
-14
lines changed

3 files changed

+38
-14
lines changed

lib/Sema/TypeCheckProtocol.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -873,8 +873,7 @@ class AssociatedTypeInference {
873873
const llvm::SetVector<AssociatedTypeDecl *> &assocTypes);
874874

875875
/// Compute a "fixed" type witness for an associated type, e.g.,
876-
/// if the refined protocol requires it to be equivalent to some other
877-
/// concrete type.
876+
/// if the refined protocol requires it to be equivalent to some other type.
878877
Type computeFixedTypeWitness(AssociatedTypeDecl *assocType);
879878

880879
/// Compute the default type witness from an associated type default,

lib/Sema/TypeCheckProtocolInference.cpp

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -809,33 +809,37 @@ AssociatedTypeDecl *AssociatedTypeInference::findDefaultedAssociatedType(
809809

810810
Type AssociatedTypeInference::computeFixedTypeWitness(
811811
AssociatedTypeDecl *assocType) {
812+
Type resultType;
813+
auto *const structuralTy = DependentMemberType::get(
814+
proto->getSelfInterfaceType(), assocType->getName());
815+
812816
// Look at all of the inherited protocols to determine whether they
813817
// require a fixed type for this associated type.
814-
Type resultType;
815818
for (auto conformedProto : adoptee->getAnyNominal()->getAllProtocols()) {
816819
if (conformedProto != assocType->getProtocol() &&
817820
!conformedProto->inheritsFrom(assocType->getProtocol()))
818821
continue;
819822

820-
const auto genericSig = conformedProto->getGenericSignature();
821-
if (!genericSig) return Type();
823+
const auto ty =
824+
conformedProto->getGenericSignature()->getCanonicalTypeInContext(
825+
structuralTy);
822826

823-
const auto nestedType = genericSig->getCanonicalTypeInContext(
824-
DependentMemberType::get(conformedProto->getSelfInterfaceType(),
825-
assocType->getName()));
826-
if (nestedType->isEqual(conformedProto->getSelfInterfaceType())) {
827-
// Self is a valid fixed type witness.
828-
} else if (nestedType->isTypeParameter()) {
829-
continue;
827+
// A dependent member type with an identical base and name indicates that
828+
// the protocol does not same-type constrain it in any way; move on to
829+
// the next protocol.
830+
if (auto *const memberTy = ty->getAs<DependentMemberType>()) {
831+
if (memberTy->getBase()->isEqual(structuralTy->getBase()) &&
832+
memberTy->getName() == structuralTy->getName())
833+
continue;
830834
}
831835

832836
if (!resultType) {
833-
resultType = nestedType;
837+
resultType = ty;
834838
continue;
835839
}
836840

837841
// FIXME: Bailing out on ambiguity.
838-
if (!resultType->isEqual(nestedType))
842+
if (!resultType->isEqual(ty))
839843
return Type();
840844
}
841845

test/decl/protocol/req/associated_type_inference_fixed_type.swift

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,3 +99,24 @@ protocol Q11 {
9999
// expected-error@+2 {{type 'S11' does not conform to protocol 'P11a'}}
100100
// expected-error@+1 {{type 'S11' does not conform to protocol 'P11b'}}
101101
struct S11: Q11, P11b {}
102+
103+
protocol P12 where A == B {
104+
associatedtype A
105+
associatedtype B
106+
func foo(arg: A)
107+
}
108+
struct S12: P12 { // OK, A == B == Never
109+
func foo(arg: Never) {}
110+
}
111+
112+
protocol P13a {
113+
associatedtype A
114+
func foo(arg: A)
115+
}
116+
protocol P13b {
117+
associatedtype B
118+
}
119+
protocol P13c: P13a, P13b where A == B {}
120+
struct S13: P13c { // OK, A == B == Never
121+
func foo(arg: Never) {}
122+
}

0 commit comments

Comments
 (0)