Skip to content

Commit e0a41b1

Browse files
committed
Break some cycles
Computing the generic signature changes the way that cycles appear in the compiler. For now, break these cycles. We should investigate each place where hasComputedGenericSignature() is used in service of breaking cycles. See rdar://55263708
1 parent d68f125 commit e0a41b1

9 files changed

+47
-30
lines changed

lib/AST/GenericSignatureBuilder.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5296,6 +5296,12 @@ class GenericSignatureBuilder::InferRequirementsWalker : public TypeWalker {
52965296
auto decl = ty->getAnyNominal();
52975297
if (!decl) return Action::Continue;
52985298

5299+
// FIXME: The GSB and the request evaluator both detect a cycle here if we
5300+
// force a recursive generic signature. We should look into moving cycle
5301+
// detection into the generic signature request(s) - see rdar://55263708
5302+
if (!decl->hasComputedGenericSignature())
5303+
return Action::Continue;
5304+
52995305
auto genericSig = decl->getGenericSignature();
53005306
if (!genericSig)
53015307
return Action::Continue;

lib/AST/ProtocolConformance.cpp

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -547,17 +547,9 @@ void NormalProtocolConformance::differenceAndStoreConditionalRequirements()
547547
return;
548548
}
549549

550-
auto extensionSig = ext->getGenericSignature();
551-
if (!extensionSig) {
552-
if (auto lazyResolver = ctxt.getLazyResolver()) {
553-
lazyResolver->resolveExtension(ext);
554-
extensionSig = ext->getGenericSignature();
555-
}
556-
}
557-
558550
// The type is generic, but the extension doesn't have a signature yet, so
559551
// we might be in a recursive validation situation.
560-
if (!extensionSig) {
552+
if (!ext->hasComputedGenericSignature()) {
561553
// If the extension is invalid, it won't ever get a signature, so we
562554
// "succeed" with an empty result instead.
563555
if (ext->isInvalid()) {
@@ -569,6 +561,15 @@ void NormalProtocolConformance::differenceAndStoreConditionalRequirements()
569561
failure();
570562
return;
571563
}
564+
565+
// FIXME: All of this will be removed when validateExtension goes away.
566+
auto extensionSig = ext->getGenericSignature();
567+
if (!extensionSig) {
568+
if (auto lazyResolver = ctxt.getLazyResolver()) {
569+
lazyResolver->resolveExtension(ext);
570+
extensionSig = ext->getGenericSignature();
571+
}
572+
}
572573

573574
auto canExtensionSig = extensionSig->getCanonicalSignature();
574575
auto canTypeSig = typeSig->getCanonicalSignature();

lib/Sema/ConstraintSystem.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -501,7 +501,9 @@ Type ConstraintSystem::openUnboundGenericType(UnboundGenericType *unbound,
501501

502502
// If the unbound decl hasn't been validated yet, we have a circular
503503
// dependency that isn't being diagnosed properly.
504-
if (!unboundDecl->getGenericSignature()) {
504+
//
505+
// FIXME: Delete this condition. He's dead Jim.
506+
if (!unboundDecl->hasComputedGenericSignature()) {
505507
TC.diagnose(unboundDecl, diag::circular_reference);
506508
return Type();
507509
}

lib/Sema/MiscDiagnostics.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1478,9 +1478,13 @@ bool TypeChecker::getDefaultGenericArgumentsString(
14781478
genericParamText << contextTy;
14791479
};
14801480

1481-
interleave(typeDecl->getInnermostGenericParamTypes(),
1482-
printGenericParamSummary, [&]{ genericParamText << ", "; });
1483-
1481+
// FIXME: We can potentially be in the middle of creating a generic signature
1482+
// if we get here. Break this cycle.
1483+
if (typeDecl->hasComputedGenericSignature()) {
1484+
interleave(typeDecl->getInnermostGenericParamTypes(),
1485+
printGenericParamSummary, [&]{ genericParamText << ", "; });
1486+
}
1487+
14841488
genericParamText << ">";
14851489
return true;
14861490
}

lib/Sema/TypeCheckDecl.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3720,8 +3720,8 @@ static void validateResultType(TypeChecker &TC,
37203720
resultTyLoc.setType(
37213721
TC.getOrCreateOpaqueResultType(resolution, decl, opaqueTy));
37223722
} else {
3723-
TC.validateType(resultTyLoc, resolution,
3724-
TypeResolverContext::FunctionResult);
3723+
TypeChecker::validateType(TC.Context, resultTyLoc, resolution,
3724+
TypeResolverContext::FunctionResult);
37253725
}
37263726
}
37273727

@@ -3862,7 +3862,6 @@ void TypeChecker::validateDecl(ValueDecl *D) {
38623862
for (auto member : proto->getMembers()) {
38633863
if (auto *aliasDecl = dyn_cast<TypeAliasDecl>(member)) {
38643864
if (!aliasDecl->isGeneric()) {
3865-
assert(aliasDecl->getGenericSignature() == proto->getGenericSignature());
38663865
// FIXME: Force creation of the protocol's generic environment now.
38673866
(void) proto->getGenericEnvironment();
38683867

lib/Sema/TypeCheckProtocolInference.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -197,10 +197,11 @@ AssociatedTypeInference::inferTypeWitnessesViaValueWitnesses(
197197
// Build a generic signature.
198198
tc.validateExtension(extension);
199199

200-
// The extension may not have a generic signature set up yet, as a
201-
// recursion breaker, in which case we can't yet confidently reject its
202-
// witnesses.
203-
if (!extension->getGenericSignature())
200+
// FIXME: The extension may not have a generic signature set up yet as
201+
// resolving signatures may trigger associated type inference. This cycle
202+
// is now detectable and we should look into untangling it
203+
// - see rdar://55263708
204+
if (!extension->hasComputedGenericSignature())
204205
return true;
205206

206207
// The condition here is a bit more fickle than

lib/Sema/TypeCheckType.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -977,7 +977,7 @@ static Type resolveTypeDecl(TypeDecl *typeDecl, SourceLoc loc,
977977
if (!options.is(TypeResolverContext::ExtensionBinding) ||
978978
!isa<NominalTypeDecl>(typeDecl)) {
979979
// Validate the declaration.
980-
if (lazyResolver)
980+
if (lazyResolver && !typeDecl->hasInterfaceType())
981981
lazyResolver->resolveDeclSignature(typeDecl);
982982

983983
// If we were not able to validate recursively, bail out.

test/decl/nested/protocol.swift

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,10 +57,10 @@ protocol SillyProtocol {
5757
class InnerClass<T> {} // expected-error {{type 'InnerClass' cannot be nested in protocol 'SillyProtocol'}}
5858
}
5959

60+
// N.B. Redeclaration checks don't see this case because `protocol A` is invalid.
6061
enum OuterEnum {
6162
protocol C {} // expected-error{{protocol 'C' cannot be nested inside another declaration}}
62-
// expected-note@-1{{'C' previously declared here}}
63-
case C(C) // expected-error{{invalid redeclaration of 'C'}}
63+
case C(C)
6464
}
6565

6666
class OuterClass {
@@ -105,7 +105,9 @@ func testLookup(_ x: OuterForUFI.Inner) {
105105
x.req()
106106
x.extMethod()
107107
}
108+
109+
// N.B. Lookup fails here because OuterForUFI.Inner is marked invalid.
108110
func testLookup<T: OuterForUFI.Inner>(_ x: T) {
109-
x.req()
110-
x.extMethod()
111+
x.req() // expected-error {{value of type 'T' has no member 'req'}}
112+
x.extMethod() // expected-error {{value of type 'T' has no member 'extMethod'}}
111113
}

test/decl/overload.swift

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -536,9 +536,10 @@ enum SR_10084_E_2 {
536536
}
537537
}
538538

539+
// N.B. Redeclaration checks don't see this case because `protocol A` is invalid.
539540
enum SR_10084_E_3 {
540-
protocol A {} //expected-error {{protocol 'A' cannot be nested inside another declaration}} // expected-note {{'A' previously declared here}}
541-
case A // expected-error {{invalid redeclaration of 'A'}}
541+
protocol A {} //expected-error {{protocol 'A' cannot be nested inside another declaration}}
542+
case A
542543
}
543544

544545
enum SR_10084_E_4 {
@@ -551,9 +552,10 @@ enum SR_10084_E_5 {
551552
case C // expected-error {{invalid redeclaration of 'C'}}
552553
}
553554

555+
// N.B. Redeclaration checks don't see this case because `protocol D` is invalid.
554556
enum SR_10084_E_6 {
555-
case D // expected-note {{'D' previously declared here}}
556-
protocol D {} //expected-error {{protocol 'D' cannot be nested inside another declaration}} // expected-error {{invalid redeclaration of 'D'}}
557+
case D
558+
protocol D {} //expected-error {{protocol 'D' cannot be nested inside another declaration}}
557559
}
558560

559561
enum SR_10084_E_7 {
@@ -604,4 +606,4 @@ enum SR_10084_E_15 {
604606
enum SR_10084_E_16 {
605607
typealias Z = Int // expected-note {{'Z' previously declared here}}
606608
case Z // expected-error {{invalid redeclaration of 'Z'}}
607-
}
609+
}

0 commit comments

Comments
 (0)