Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 39 additions & 33 deletions include/swift/AST/GenericSignatureBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,22 @@ class TypeRepr;
class ASTContext;
class DiagnosticEngine;

/// Determines how to resolve a dependent type to a potential archetype.
enum class ArchetypeResolutionKind {
/// Always create a new potential archetype to describe this dependent type,
/// which might be invalid and may not provide complete information.
AlwaysPartial,

/// Only create a potential archetype when it is well-formed (e.g., a nested
/// type should exist) and make sure we have complete information about
/// that potential archetype.
CompleteWellFormed,

/// Only create a new potential archetype to describe this dependent type
/// if it is already known.
AlreadyKnown,
};

/// \brief Collects a set of requirements of generic parameters, both explicitly
/// stated and inferred, and determines the set of archetypes for each of
/// the generic parameters.
Expand Down Expand Up @@ -251,12 +267,6 @@ class GenericSignatureBuilder {
ProtocolDecl *Proto,
const RequirementSource *Source);

ConstraintResult addConformanceRequirement(
PotentialArchetype *T,
ProtocolDecl *Proto,
const RequirementSource *Source,
llvm::SmallPtrSetImpl<ProtocolDecl *> &Visited);

public:
/// \brief Add a new same-type requirement between two fully resolved types
/// (output of \c GenericSignatureBuilder::resolve).
Expand Down Expand Up @@ -322,9 +332,7 @@ class GenericSignatureBuilder {
UnresolvedType subject,
UnresolvedType constraint,
FloatingRequirementSource source,
UnresolvedHandlingKind unresolvedHandling,
llvm::SmallPtrSetImpl<ProtocolDecl *> *visited
= nullptr);
UnresolvedHandlingKind unresolvedHandling);

/// \brief Add a new conformance requirement specifying that the given
/// potential archetypes are equivalent.
Expand Down Expand Up @@ -370,9 +378,8 @@ class GenericSignatureBuilder {
/// relative to the given module.
ConstraintResult addInheritedRequirements(
TypeDecl *decl,
PotentialArchetype *pa,
UnresolvedType type,
const RequirementSource *parentSource,
llvm::SmallPtrSetImpl<ProtocolDecl *> &visited,
ModuleDecl *inferForModule);

/// Visit all of the potential archetypes.
Expand Down Expand Up @@ -464,13 +471,6 @@ class GenericSignatureBuilder {
ModuleDecl *inferForModule,
const SubstitutionMap *subMap = nullptr);

ConstraintResult addRequirement(
const Requirement &req,
FloatingRequirementSource source,
ModuleDecl *inferForModule,
const SubstitutionMap *subMap,
llvm::SmallPtrSetImpl<ProtocolDecl *> &Visited);

/// \brief Add all of a generic signature's parameters and requirements.
void addGenericSignature(GenericSignature *sig);

Expand Down Expand Up @@ -623,14 +623,15 @@ class GenericSignatureBuilder {
public:
/// \brief Resolve the given type to the potential archetype it names.
///
/// This routine will synthesize nested types as required to refer to a
/// potential archetype, even in cases where no requirement specifies the
/// requirement for such an archetype. FIXME: The failure to include such a
/// requirement will be diagnosed at some point later (when the types in the
/// signature are fully resolved).
/// The \c resolutionKind parameter describes how resolution should be
/// performed. If the potential archetype named by the given dependent type
/// already exists, it will be always returned. If it doesn't exist yet,
/// the \c resolutionKind dictates whether the potential archetype will
/// be created or whether null will be returned.
///
/// For any type that cannot refer to an archetype, this routine returns null.
PotentialArchetype *resolveArchetype(Type type);
PotentialArchetype *resolveArchetype(Type type,
ArchetypeResolutionKind resolutionKind);

/// \brief Resolve the given type as far as this Builder knows how.
///
Expand Down Expand Up @@ -1171,6 +1172,10 @@ class GenericSignatureBuilder::FloatingRequirementSource {
/// Return the "inferred" version of this source, if it isn't already
/// inferred.
FloatingRequirementSource asInferred(const TypeRepr *typeRepr) const;

/// Whether this requirement source is recursive when composed with
/// the given type.
bool isRecursive(Type rootType, GenericSignatureBuilder &builder) const;
};

class GenericSignatureBuilder::PotentialArchetype {
Expand Down Expand Up @@ -1504,15 +1509,6 @@ class GenericSignatureBuilder::PotentialArchetype {
PotentialArchetype *getNestedType(TypeAliasDecl *typealias,
GenericSignatureBuilder &builder);

/// \brief Retrieve (or create) a nested type that is the current best
/// nested archetype anchor (locally) with the given name.
///
/// When called on the archetype anchor, this will produce the named
/// archetype anchor.
PotentialArchetype *getNestedArchetypeAnchor(
Identifier name,
GenericSignatureBuilder &builder);

/// Describes the kind of update that is performed.
enum class NestedTypeUpdate {
/// Resolve an existing potential archetype, but don't create a new
Expand All @@ -1525,6 +1521,16 @@ class GenericSignatureBuilder::PotentialArchetype {
AddIfBetterAnchor,
};

/// \brief Retrieve (or create) a nested type that is the current best
/// nested archetype anchor (locally) with the given name.
///
/// When called on the archetype anchor, this will produce the named
/// archetype anchor.
PotentialArchetype *getNestedArchetypeAnchor(
Identifier name,
GenericSignatureBuilder &builder,
NestedTypeUpdate kind = NestedTypeUpdate::AddIfMissing);

/// Update the named nested type when we know this type conforms to the given
/// protocol.
///
Expand Down
6 changes: 5 additions & 1 deletion lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3130,10 +3130,14 @@ void ProtocolDecl::computeRequirementSignature() {
GenericSignatureBuilder builder(getASTContext(),
LookUpConformanceInModule(module));
builder.addGenericParameter(selfType);
auto selfPA =
builder.resolveArchetype(selfType,
ArchetypeResolutionKind::CompleteWellFormed);

builder.addRequirement(
requirement,
GenericSignatureBuilder::RequirementSource
::forRequirementSignature(builder.resolveArchetype(selfType), this),
::forRequirementSignature(selfPA, this),
nullptr);
builder.finalize(SourceLoc(), { selfType });

Expand Down
5 changes: 4 additions & 1 deletion lib/AST/GenericEnvironment.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,10 @@ Type GenericEnvironment::QueryInterfaceTypeSubstitutions::operator()(
Type contextType = self->getContextTypes()[index];
if (!contextType) {
assert(self->Builder && "Missing generic signature builder for lazy query");
auto potentialArchetype = self->Builder->resolveArchetype(type);
auto potentialArchetype =
self->Builder->resolveArchetype(
type,
ArchetypeResolutionKind::CompleteWellFormed);

auto mutableSelf = const_cast<GenericEnvironment *>(self);
contextType =
Expand Down
43 changes: 31 additions & 12 deletions lib/AST/GenericSignature.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -489,7 +489,8 @@ bool GenericSignature::requiresClass(Type type, ModuleDecl &mod) {
if (!type->isTypeParameter()) return false;

auto &builder = *getGenericSignatureBuilder(mod);
auto pa = builder.resolveArchetype(type);
auto pa =
builder.resolveArchetype(type, ArchetypeResolutionKind::CompleteWellFormed);
if (!pa) return false;

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

auto &builder = *getGenericSignatureBuilder(mod);
auto pa = builder.resolveArchetype(type);
auto pa =
builder.resolveArchetype(type, ArchetypeResolutionKind::CompleteWellFormed);
if (!pa) return nullptr;

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

auto &builder = *getGenericSignatureBuilder(mod);
auto pa = builder.resolveArchetype(type);
auto pa =
builder.resolveArchetype(type, ArchetypeResolutionKind::CompleteWellFormed);
if (!pa) return { };

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

auto &builder = *getGenericSignatureBuilder(mod);
auto pa = builder.resolveArchetype(type);
auto pa =
builder.resolveArchetype(type, ArchetypeResolutionKind::CompleteWellFormed);
if (!pa) return false;

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

auto &builder = *getGenericSignatureBuilder(mod);
auto pa = builder.resolveArchetype(type);
auto pa =
builder.resolveArchetype(type, ArchetypeResolutionKind::CompleteWellFormed);
if (!pa) return Type();

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

auto &builder = *getGenericSignatureBuilder(mod);
auto pa = builder.resolveArchetype(type);
auto pa =
builder.resolveArchetype(type, ArchetypeResolutionKind::CompleteWellFormed);
if (!pa) return LayoutConstraint();

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

auto &builder = *getGenericSignatureBuilder(mod);
auto pa1 = builder.resolveArchetype(type1);
auto pa1 =
builder.resolveArchetype(type1,
ArchetypeResolutionKind::CompleteWellFormed);
assert(pa1 && "not a valid dependent type of this signature?");
pa1 = pa1->getRepresentative();
assert(!pa1->isConcreteType());

auto pa2 = builder.resolveArchetype(type2);
auto pa2 =
builder.resolveArchetype(type2,
ArchetypeResolutionKind::CompleteWellFormed);
assert(pa2 && "not a valid dependent type of this signature?");
pa2 = pa2->getRepresentative();
assert(!pa2->isConcreteType());
Expand Down Expand Up @@ -667,7 +677,9 @@ bool GenericSignature::isCanonicalTypeInContext(Type type,
return !type.findIf([&](Type component) -> bool {
if (!component->isTypeParameter()) return false;

auto pa = builder.resolveArchetype(component);
auto pa =
builder.resolveArchetype(component,
ArchetypeResolutionKind::CompleteWellFormed);
if (!pa) return false;

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

// Resolve the potential archetype. This can be null in nested generic
// types, which we can't immediately canonicalize.
auto pa = builder.resolveArchetype(Type(component));
auto pa =
builder.resolveArchetype(Type(component),
ArchetypeResolutionKind::CompleteWellFormed);
if (!pa) return None;

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

// Resolve this type to a potential archetype.
auto &builder = *getGenericSignatureBuilder(mod);
auto pa = builder.resolveArchetype(type);
auto pa =
builder.resolveArchetype(type, ArchetypeResolutionKind::CompleteWellFormed);
auto equivClass = pa->getOrCreateEquivalenceClass();

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

// Dig out the potential archetype for this stored type.
auto pa = reqSigBuilder.resolveArchetype(storedType);
// FIXME: CompleteWellFormed here?
auto pa =
reqSigBuilder.resolveArchetype(
storedType,
ArchetypeResolutionKind::AlwaysPartial);
auto equivClass = pa->getOrCreateEquivalenceClass();

// Find the conformance of this potential archetype to the protocol in
Expand Down
Loading