Skip to content

Commit 17846e2

Browse files
committed
[GSB] Cope with recursive requirements by delaying them.
Rather than detecting recursion and bailing early, delay requirements that would form recursive types. Note that we aren't actually processing them later.
1 parent 995de88 commit 17846e2

File tree

6 files changed

+220
-78
lines changed

6 files changed

+220
-78
lines changed

include/swift/AST/GenericSignatureBuilder.h

Lines changed: 37 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,22 @@ class TypeRepr;
5959
class ASTContext;
6060
class DiagnosticEngine;
6161

62+
/// Determines how to resolve a dependent type to a potential archetype.
63+
enum class ArchetypeResolutionKind {
64+
/// Always create a new potential archetype to describe this dependent type,
65+
/// which might be invalid and may not provide complete information.
66+
AlwaysPartial,
67+
68+
/// Only create a potential archetype when it is well-formed (e.g., a nested
69+
/// type should exist) and make sure we have complete information about
70+
/// that potential archetype.
71+
CompleteWellFormed,
72+
73+
/// Only create a new potential archetype to describe this dependent type
74+
/// if it is already known.
75+
AlreadyKnown,
76+
};
77+
6278
/// \brief Collects a set of requirements of generic parameters, both explicitly
6379
/// stated and inferred, and determines the set of archetypes for each of
6480
/// the generic parameters.
@@ -623,14 +639,15 @@ class GenericSignatureBuilder {
623639
public:
624640
/// \brief Resolve the given type to the potential archetype it names.
625641
///
626-
/// This routine will synthesize nested types as required to refer to a
627-
/// potential archetype, even in cases where no requirement specifies the
628-
/// requirement for such an archetype. FIXME: The failure to include such a
629-
/// requirement will be diagnosed at some point later (when the types in the
630-
/// signature are fully resolved).
642+
/// The \c resolutionKind parameter describes how resolution should be
643+
/// performed. If the potential archetype named by the given dependent type
644+
/// already exists, it will be always returned. If it doesn't exist yet,
645+
/// the \c resolutionKind dictates whether the potential archetype will
646+
/// be created or whether null will be returned.
631647
///
632648
/// For any type that cannot refer to an archetype, this routine returns null.
633-
PotentialArchetype *resolveArchetype(Type type);
649+
PotentialArchetype *resolveArchetype(Type type,
650+
ArchetypeResolutionKind resolutionKind);
634651

635652
/// \brief Resolve the given type as far as this Builder knows how.
636653
///
@@ -1171,6 +1188,10 @@ class GenericSignatureBuilder::FloatingRequirementSource {
11711188
/// Return the "inferred" version of this source, if it isn't already
11721189
/// inferred.
11731190
FloatingRequirementSource asInferred(const TypeRepr *typeRepr) const;
1191+
1192+
/// Whether this requirement source is recursive when composed with
1193+
/// the given type.
1194+
bool isRecursive(Type rootType, GenericSignatureBuilder &builder) const;
11741195
};
11751196

11761197
class GenericSignatureBuilder::PotentialArchetype {
@@ -1504,15 +1525,6 @@ class GenericSignatureBuilder::PotentialArchetype {
15041525
PotentialArchetype *getNestedType(TypeAliasDecl *typealias,
15051526
GenericSignatureBuilder &builder);
15061527

1507-
/// \brief Retrieve (or create) a nested type that is the current best
1508-
/// nested archetype anchor (locally) with the given name.
1509-
///
1510-
/// When called on the archetype anchor, this will produce the named
1511-
/// archetype anchor.
1512-
PotentialArchetype *getNestedArchetypeAnchor(
1513-
Identifier name,
1514-
GenericSignatureBuilder &builder);
1515-
15161528
/// Describes the kind of update that is performed.
15171529
enum class NestedTypeUpdate {
15181530
/// Resolve an existing potential archetype, but don't create a new
@@ -1525,6 +1537,16 @@ class GenericSignatureBuilder::PotentialArchetype {
15251537
AddIfBetterAnchor,
15261538
};
15271539

1540+
/// \brief Retrieve (or create) a nested type that is the current best
1541+
/// nested archetype anchor (locally) with the given name.
1542+
///
1543+
/// When called on the archetype anchor, this will produce the named
1544+
/// archetype anchor.
1545+
PotentialArchetype *getNestedArchetypeAnchor(
1546+
Identifier name,
1547+
GenericSignatureBuilder &builder,
1548+
NestedTypeUpdate kind = NestedTypeUpdate::AddIfMissing);
1549+
15281550
/// Update the named nested type when we know this type conforms to the given
15291551
/// protocol.
15301552
///

lib/AST/Decl.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3130,10 +3130,14 @@ void ProtocolDecl::computeRequirementSignature() {
31303130
GenericSignatureBuilder builder(getASTContext(),
31313131
LookUpConformanceInModule(module));
31323132
builder.addGenericParameter(selfType);
3133+
auto selfPA =
3134+
builder.resolveArchetype(selfType,
3135+
ArchetypeResolutionKind::CompleteWellFormed);
3136+
31333137
builder.addRequirement(
31343138
requirement,
31353139
GenericSignatureBuilder::RequirementSource
3136-
::forRequirementSignature(builder.resolveArchetype(selfType), this),
3140+
::forRequirementSignature(selfPA, this),
31373141
nullptr);
31383142
builder.finalize(SourceLoc(), { selfType });
31393143

lib/AST/GenericEnvironment.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,10 @@ Type GenericEnvironment::QueryInterfaceTypeSubstitutions::operator()(
201201
Type contextType = self->getContextTypes()[index];
202202
if (!contextType) {
203203
assert(self->Builder && "Missing generic signature builder for lazy query");
204-
auto potentialArchetype = self->Builder->resolveArchetype(type);
204+
auto potentialArchetype =
205+
self->Builder->resolveArchetype(
206+
type,
207+
ArchetypeResolutionKind::CompleteWellFormed);
205208

206209
auto mutableSelf = const_cast<GenericEnvironment *>(self);
207210
contextType =

lib/AST/GenericSignature.cpp

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -489,7 +489,8 @@ bool GenericSignature::requiresClass(Type type, ModuleDecl &mod) {
489489
if (!type->isTypeParameter()) return false;
490490

491491
auto &builder = *getGenericSignatureBuilder(mod);
492-
auto pa = builder.resolveArchetype(type);
492+
auto pa =
493+
builder.resolveArchetype(type, ArchetypeResolutionKind::CompleteWellFormed);
493494
if (!pa) return false;
494495

495496
pa = pa->getRepresentative();
@@ -519,7 +520,8 @@ Type GenericSignature::getSuperclassBound(Type type, ModuleDecl &mod) {
519520
if (!type->isTypeParameter()) return nullptr;
520521

521522
auto &builder = *getGenericSignatureBuilder(mod);
522-
auto pa = builder.resolveArchetype(type);
523+
auto pa =
524+
builder.resolveArchetype(type, ArchetypeResolutionKind::CompleteWellFormed);
523525
if (!pa) return nullptr;
524526

525527
pa = pa->getRepresentative();
@@ -539,7 +541,8 @@ SmallVector<ProtocolDecl *, 2> GenericSignature::getConformsTo(Type type,
539541
if (!type->isTypeParameter()) return { };
540542

541543
auto &builder = *getGenericSignatureBuilder(mod);
542-
auto pa = builder.resolveArchetype(type);
544+
auto pa =
545+
builder.resolveArchetype(type, ArchetypeResolutionKind::CompleteWellFormed);
543546
if (!pa) return { };
544547

545548
pa = pa->getRepresentative();
@@ -565,7 +568,8 @@ bool GenericSignature::conformsToProtocol(Type type, ProtocolDecl *proto,
565568
if (!type->isTypeParameter()) return false;
566569

567570
auto &builder = *getGenericSignatureBuilder(mod);
568-
auto pa = builder.resolveArchetype(type);
571+
auto pa =
572+
builder.resolveArchetype(type, ArchetypeResolutionKind::CompleteWellFormed);
569573
if (!pa) return false;
570574

571575
pa = pa->getRepresentative();
@@ -593,7 +597,8 @@ Type GenericSignature::getConcreteType(Type type, ModuleDecl &mod) {
593597
if (!type->isTypeParameter()) return Type();
594598

595599
auto &builder = *getGenericSignatureBuilder(mod);
596-
auto pa = builder.resolveArchetype(type);
600+
auto pa =
601+
builder.resolveArchetype(type, ArchetypeResolutionKind::CompleteWellFormed);
597602
if (!pa) return Type();
598603

599604
pa = pa->getRepresentative();
@@ -607,7 +612,8 @@ LayoutConstraint GenericSignature::getLayoutConstraint(Type type,
607612
if (!type->isTypeParameter()) return LayoutConstraint();
608613

609614
auto &builder = *getGenericSignatureBuilder(mod);
610-
auto pa = builder.resolveArchetype(type);
615+
auto pa =
616+
builder.resolveArchetype(type, ArchetypeResolutionKind::CompleteWellFormed);
611617
if (!pa) return LayoutConstraint();
612618

613619
pa = pa->getRepresentative();
@@ -623,12 +629,16 @@ bool GenericSignature::areSameTypeParameterInContext(Type type1, Type type2,
623629
return true;
624630

625631
auto &builder = *getGenericSignatureBuilder(mod);
626-
auto pa1 = builder.resolveArchetype(type1);
632+
auto pa1 =
633+
builder.resolveArchetype(type1,
634+
ArchetypeResolutionKind::CompleteWellFormed);
627635
assert(pa1 && "not a valid dependent type of this signature?");
628636
pa1 = pa1->getRepresentative();
629637
assert(!pa1->isConcreteType());
630638

631-
auto pa2 = builder.resolveArchetype(type2);
639+
auto pa2 =
640+
builder.resolveArchetype(type2,
641+
ArchetypeResolutionKind::CompleteWellFormed);
632642
assert(pa2 && "not a valid dependent type of this signature?");
633643
pa2 = pa2->getRepresentative();
634644
assert(!pa2->isConcreteType());
@@ -667,7 +677,9 @@ bool GenericSignature::isCanonicalTypeInContext(Type type,
667677
return !type.findIf([&](Type component) -> bool {
668678
if (!component->isTypeParameter()) return false;
669679

670-
auto pa = builder.resolveArchetype(component);
680+
auto pa =
681+
builder.resolveArchetype(component,
682+
ArchetypeResolutionKind::CompleteWellFormed);
671683
if (!pa) return false;
672684

673685
auto rep = pa->getArchetypeAnchor(builder);
@@ -692,7 +704,9 @@ CanType GenericSignature::getCanonicalTypeInContext(Type type,
692704

693705
// Resolve the potential archetype. This can be null in nested generic
694706
// types, which we can't immediately canonicalize.
695-
auto pa = builder.resolveArchetype(Type(component));
707+
auto pa =
708+
builder.resolveArchetype(Type(component),
709+
ArchetypeResolutionKind::CompleteWellFormed);
696710
if (!pa) return None;
697711

698712
auto rep = pa->getArchetypeAnchor(builder);
@@ -768,7 +782,8 @@ ConformanceAccessPath GenericSignature::getConformanceAccessPath(
768782

769783
// Resolve this type to a potential archetype.
770784
auto &builder = *getGenericSignatureBuilder(mod);
771-
auto pa = builder.resolveArchetype(type);
785+
auto pa =
786+
builder.resolveArchetype(type, ArchetypeResolutionKind::CompleteWellFormed);
772787
auto equivClass = pa->getOrCreateEquivalenceClass();
773788

774789
// Dig out the conformance of this type to the given protocol, because we
@@ -859,7 +874,11 @@ ConformanceAccessPath GenericSignature::getConformanceAccessPath(
859874
Type storedType = eraseAssociatedTypes(source->getStoredType());
860875

861876
// Dig out the potential archetype for this stored type.
862-
auto pa = reqSigBuilder.resolveArchetype(storedType);
877+
// FIXME: CompleteWellFormed here?
878+
auto pa =
879+
reqSigBuilder.resolveArchetype(
880+
storedType,
881+
ArchetypeResolutionKind::AlwaysPartial);
863882
auto equivClass = pa->getOrCreateEquivalenceClass();
864883

865884
// Find the conformance of this potential archetype to the protocol in

0 commit comments

Comments
 (0)