Skip to content

Commit bc55d02

Browse files
authored
Merge pull request swiftlang#38717 from slavapestov/tiny-requirement-machine-fixes
Tiny RequirementMachine fixes
2 parents 2d851ff + 58cb851 commit bc55d02

File tree

4 files changed

+57
-8
lines changed

4 files changed

+57
-8
lines changed

include/swift/AST/ASTContext.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1181,6 +1181,11 @@ class ASTContext final {
11811181
rewriting::RequirementMachine *getOrCreateRequirementMachine(
11821182
CanGenericSignature sig);
11831183

1184+
/// This is a hack to break cycles. Don't introduce new callers of this
1185+
/// method.
1186+
bool isRecursivelyConstructingRequirementMachine(
1187+
CanGenericSignature sig);
1188+
11841189
/// Retrieve a generic signature with a single unconstrained type parameter,
11851190
/// like `<T>`.
11861191
CanGenericSignature getSingleGenericParameterSignature() const;

lib/AST/ASTContext.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1997,6 +1997,22 @@ ASTContext::getOrCreateRequirementMachine(CanGenericSignature sig) {
19971997
return machine;
19981998
}
19991999

2000+
bool ASTContext::isRecursivelyConstructingRequirementMachine(
2001+
CanGenericSignature sig) {
2002+
auto &rewriteCtx = getImpl().TheRewriteContext;
2003+
if (!rewriteCtx)
2004+
return false;
2005+
2006+
auto arena = getArena(sig);
2007+
auto &machines = getImpl().getArena(arena).RequirementMachines;
2008+
2009+
auto found = machines.find(sig);
2010+
if (found == machines.end())
2011+
return false;
2012+
2013+
return !found->second->isComplete();
2014+
}
2015+
20002016
Optional<llvm::TinyPtrVector<ValueDecl *>>
20012017
OverriddenDeclsRequest::getCachedResult() const {
20022018
auto decl = std::get<0>(getStorage());

lib/AST/GenericSignature.cpp

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -349,22 +349,36 @@ GenericSignatureImpl::getLocalRequirements(Type depType) const {
349349
auto rqmResult = computeViaRQM();
350350
auto gsbResult = computeViaGSB();
351351

352-
auto typesEqual = [&](Type lhs, Type rhs) {
352+
auto typesEqual = [&](Type lhs, Type rhs, bool canonical) {
353353
if (!lhs || !rhs)
354354
return !lhs == !rhs;
355-
return lhs->isEqual(rhs);
355+
if (lhs->isEqual(rhs))
356+
return true;
357+
358+
if (canonical)
359+
return false;
360+
361+
if (getCanonicalTypeInContext(lhs) ==
362+
getCanonicalTypeInContext(rhs))
363+
return true;
364+
365+
return false;
356366
};
357367

358368
auto compare = [&]() {
359369
// If the types are concrete, we don't care about the rest.
360370
if (gsbResult.concreteType || rqmResult.concreteType) {
361-
if (!typesEqual(gsbResult.concreteType, rqmResult.concreteType))
371+
if (!typesEqual(gsbResult.concreteType,
372+
rqmResult.concreteType,
373+
false))
362374
return false;
363375

364376
return true;
365377
}
366378

367-
if (!typesEqual(gsbResult.anchor, rqmResult.anchor))
379+
if (!typesEqual(gsbResult.anchor,
380+
rqmResult.anchor,
381+
true))
368382
return false;
369383

370384
if (gsbResult.layout != rqmResult.layout)
@@ -378,6 +392,11 @@ GenericSignatureImpl::getLocalRequirements(Type depType) const {
378392
if (lhsProtos != rhsProtos)
379393
return false;
380394

395+
if (!typesEqual(gsbResult.superclass,
396+
rqmResult.superclass,
397+
false))
398+
return false;
399+
381400
return true;
382401
};
383402

@@ -770,7 +789,11 @@ Type GenericSignatureImpl::getConcreteType(Type type) const {
770789
auto check = [&]() {
771790
if (!gsbResult || !rqmResult)
772791
return !gsbResult == !rqmResult;
773-
return gsbResult->isEqual(rqmResult);
792+
if (gsbResult->isEqual(rqmResult))
793+
return true;
794+
795+
return (getCanonicalTypeInContext(gsbResult)
796+
== getCanonicalTypeInContext(rqmResult));
774797
};
775798

776799
if (!check()) {

lib/Sema/TypeCheckProtocolInference.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -819,9 +819,14 @@ Type AssociatedTypeInference::computeFixedTypeWitness(
819819
!conformedProto->inheritsFrom(assocType->getProtocol()))
820820
continue;
821821

822-
const auto ty =
823-
conformedProto->getGenericSignature()->getCanonicalTypeInContext(
824-
structuralTy);
822+
auto sig = conformedProto->getGenericSignature();
823+
824+
// FIXME: The RequirementMachine will assert on re-entrant construction.
825+
// We should find a more principled way of breaking this cycle.
826+
if (ctx.isRecursivelyConstructingRequirementMachine(sig.getCanonicalSignature()))
827+
continue;
828+
829+
const auto ty = sig->getCanonicalTypeInContext(structuralTy);
825830

826831
// A dependent member type with an identical base and name indicates that
827832
// the protocol does not same-type constrain it in any way; move on to

0 commit comments

Comments
 (0)