Skip to content

Commit e4115a2

Browse files
committed
GSB: New way of handling concrete same-type requirements when rebuilding a signature
After we drop redundant conformance requirements, the left hand side of a concrete same-type requirement might become unresolvable: protocol P { associatedtype T where T == Self } struct S : P {} extension P where T == S {} Here, we begin with <Self where Self : P, Self.T == S>, and then we drop (Self : P). However, <Self where Self.T == S> is no longer a valid generic signature. We can canonicalize Self.T down to Self before we build the new signature, but we must only do this for concrete same-type requirements, since canonicalizing the subject type of an abstract same-type requirement might lose information produce a trivial requirement of the form 'T == T'. This is really unprincipled, and no doubt other counter-examples exist. The entire procedure for rebuilding a generic signature needs to be re-designed from first principles. Fixes rdar://problem/80503090.
1 parent 106decb commit e4115a2

File tree

2 files changed

+43
-0
lines changed

2 files changed

+43
-0
lines changed

lib/AST/GenericSignatureBuilder.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8355,6 +8355,40 @@ GenericSignature GenericSignatureBuilder::rebuildSignatureWithoutRedundantRequir
83558355
}
83568356
};
83578357

8358+
// If we have a same-type requirement where the right hand side is concrete,
8359+
// canonicalize the left hand side, in case dropping some redundant
8360+
// conformance requirement turns the original left hand side into an
8361+
// unresolvable type.
8362+
if (!req.getRHS().get<Type>()->isTypeParameter()) {
8363+
auto resolvedSubject =
8364+
maybeResolveEquivalenceClass(req.getSubjectType(),
8365+
ArchetypeResolutionKind::WellFormed,
8366+
/*wantExactPotentialArchetype=*/false);
8367+
8368+
auto *resolvedEquivClass = resolvedSubject.getEquivalenceClass(*this);
8369+
auto resolvedSubjectType = resolvedEquivClass->getAnchor(*this, { });
8370+
8371+
auto constraintType = resolveType(req.getRHS().get<Type>());
8372+
8373+
auto newReq = stripBoundDependentMemberTypes(
8374+
Requirement(RequirementKind::SameType,
8375+
resolvedSubjectType, constraintType));
8376+
8377+
if (Impl->DebugRedundantRequirements) {
8378+
llvm::dbgs() << "=> ";
8379+
newReq.dump(llvm::dbgs());
8380+
llvm::dbgs() << "\n";
8381+
}
8382+
newBuilder.addRequirement(newReq, getRebuiltSource(req.getSource()),
8383+
nullptr);
8384+
8385+
continue;
8386+
}
8387+
8388+
// Otherwise, we can't canonicalize the two sides of the requirement, since
8389+
// doing so will produce a trivial same-type requirement T == T. Instead,
8390+
// apply some ad-hoc rules to improve the odds that the requirement will
8391+
// resolve in the rebuilt GSB.
83588392
auto subjectType = resolveType(req.getSubjectType());
83598393
auto constraintType = resolveType(req.getRHS().get<Type>());
83608394

test/Generics/rdar80503090.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,13 @@ extension P where T : C {
2525
func test() {
2626
missing()
2727
}
28+
}
29+
30+
struct S : P {}
31+
32+
extension P where T == S {
33+
// CHECK-LABEL: Generic signature: <Self where Self == S>
34+
func test() {
35+
missing()
36+
}
2837
}

0 commit comments

Comments
 (0)