diff --git a/include/swift/AST/GenericSignatureBuilder.h b/include/swift/AST/GenericSignatureBuilder.h index 8be9f17551d6a..0b4226351c533 100644 --- a/include/swift/AST/GenericSignatureBuilder.h +++ b/include/swift/AST/GenericSignatureBuilder.h @@ -679,6 +679,21 @@ class GenericSignatureBuilder { ArchetypeResolutionKind resolutionKind); public: + /// \brief Resolve the equivalence class for the given type parameter, + /// which provides information about that type. + /// + /// 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 equivalence class, this routine + /// returns null. + EquivalenceClass *resolveEquivalenceClass( + Type type, + ArchetypeResolutionKind resolutionKind); + /// \brief Resolve the given type to the potential archetype it names. /// /// The \c resolutionKind parameter describes how resolution should be diff --git a/lib/AST/GenericSignature.cpp b/lib/AST/GenericSignature.cpp index 2b7e5da098578..161da2399a443 100644 --- a/lib/AST/GenericSignature.cpp +++ b/lib/AST/GenericSignature.cpp @@ -484,31 +484,27 @@ bool GenericSignature::requiresClass(Type type, ModuleDecl &mod) { if (!type->isTypeParameter()) return false; auto &builder = *getGenericSignatureBuilder(mod); - auto pa = - builder.resolveArchetype(type, ArchetypeResolutionKind::CompleteWellFormed); - if (!pa) return false; - - if (pa->isConcreteType()) return false; + auto equivClass = + builder.resolveEquivalenceClass( + type, + ArchetypeResolutionKind::CompleteWellFormed); + if (!equivClass) return false; // If this type was mapped to a concrete type, then there is no // requirement. - pa = pa->getRepresentative(); - - if (pa->isConcreteType()) return false; + if (equivClass->concreteType) return false; // If there is a layout constraint, it might be a class. - if (auto layout = pa->getLayout()) { - if (layout->isClass()) return true; - } + if (equivClass->layout && equivClass->layout->isClass()) return true; // If there is a superclass bound, then obviously it must be a class. // FIXME: We shouldn't need this? - if (pa->getSuperclass()) return true; + if (equivClass->superclass) return true; // If any of the protocols are class-bound, then it must be a class. // FIXME: We shouldn't need this? - for (auto proto : pa->getConformsTo()) { - if (proto->requiresClass()) return true; + for (const auto &conforms : equivClass->conformsTo) { + if (conforms.first->requiresClass()) return true; } return false; @@ -519,37 +515,41 @@ Type GenericSignature::getSuperclassBound(Type type, ModuleDecl &mod) { if (!type->isTypeParameter()) return nullptr; auto &builder = *getGenericSignatureBuilder(mod); - auto pa = - builder.resolveArchetype(type, ArchetypeResolutionKind::CompleteWellFormed); - if (!pa) return nullptr; + auto equivClass = + builder.resolveEquivalenceClass( + type, + ArchetypeResolutionKind::CompleteWellFormed); + if (!equivClass) return nullptr; // If this type was mapped to a concrete type, then there is no // requirement. - if (pa->isConcreteType()) return nullptr; + if (equivClass->concreteType) return nullptr; // Retrieve the superclass bound. - return pa->getSuperclass(); + return equivClass->superclass; } /// Determine the set of protocols to which the given dependent type /// must conform. -SmallVector GenericSignature::getConformsTo(Type type, - ModuleDecl &mod) { +SmallVector +GenericSignature::getConformsTo(Type type, ModuleDecl &mod) { if (!type->isTypeParameter()) return { }; auto &builder = *getGenericSignatureBuilder(mod); - auto pa = - builder.resolveArchetype(type, ArchetypeResolutionKind::CompleteWellFormed); - if (!pa) return { }; + auto equivClass = + builder.resolveEquivalenceClass( + type, + ArchetypeResolutionKind::CompleteWellFormed); + if (!equivClass) return { }; // If this type was mapped to a concrete type, then there are no // requirements. - if (pa->isConcreteType()) return { }; + if (equivClass->concreteType) return { }; // Retrieve the protocols to which this type conforms. SmallVector result; - for (auto proto : pa->getConformsTo()) - result.push_back(proto); + for (const auto &conforms : equivClass->conformsTo) + result.push_back(conforms.first); // Canonicalize the resulting set of protocols. ProtocolType::canonicalizeProtocols(result); @@ -563,19 +563,17 @@ bool GenericSignature::conformsToProtocol(Type type, ProtocolDecl *proto, if (!type->isTypeParameter()) return false; auto &builder = *getGenericSignatureBuilder(mod); - auto pa = - builder.resolveArchetype(type, ArchetypeResolutionKind::CompleteWellFormed); - if (!pa) return false; + auto equivClass = + builder.resolveEquivalenceClass( + type, + ArchetypeResolutionKind::CompleteWellFormed); + if (!equivClass) return false; // FIXME: Deal with concrete conformances here? - if (pa->isConcreteType()) return false; + if (equivClass->concreteType) return false; // Check whether the representative conforms to this protocol. - if (auto equivClass = pa->getEquivalenceClassIfPresent()) - if (equivClass->conformsTo.count(proto) > 0) - return true; - - return false; + return equivClass->conformsTo.count(proto) > 0; } /// Determine whether the given dependent type is equal to a concrete type. @@ -590,11 +588,13 @@ Type GenericSignature::getConcreteType(Type type, ModuleDecl &mod) { if (!type->isTypeParameter()) return Type(); auto &builder = *getGenericSignatureBuilder(mod); - auto pa = - builder.resolveArchetype(type, ArchetypeResolutionKind::CompleteWellFormed); - if (!pa) return Type(); + auto equivClass = + builder.resolveEquivalenceClass( + type, + ArchetypeResolutionKind::CompleteWellFormed); + if (!equivClass) return Type(); - return pa->getConcreteType(); + return equivClass->concreteType; } LayoutConstraint GenericSignature::getLayoutConstraint(Type type, @@ -602,11 +602,13 @@ LayoutConstraint GenericSignature::getLayoutConstraint(Type type, if (!type->isTypeParameter()) return LayoutConstraint(); auto &builder = *getGenericSignatureBuilder(mod); - auto pa = - builder.resolveArchetype(type, ArchetypeResolutionKind::CompleteWellFormed); - if (!pa) return LayoutConstraint(); + auto equivClass = + builder.resolveEquivalenceClass( + type, + ArchetypeResolutionKind::CompleteWellFormed); + if (!equivClass) return LayoutConstraint(); - return pa->getLayout(); + return equivClass->layout; } bool GenericSignature::areSameTypeParameterInContext(Type type1, Type type2, @@ -618,21 +620,21 @@ bool GenericSignature::areSameTypeParameterInContext(Type type1, Type type2, return true; auto &builder = *getGenericSignatureBuilder(mod); - auto pa1 = - builder.resolveArchetype(type1, + auto equivClass1 = + builder.resolveEquivalenceClass( + type1, ArchetypeResolutionKind::CompleteWellFormed); - assert(pa1 && "not a valid dependent type of this signature?"); - pa1 = pa1->getRepresentative(); - assert(!pa1->isConcreteType()); + assert(equivClass1 && "not a valid dependent type of this signature?"); + assert(!equivClass1->concreteType); - auto pa2 = - builder.resolveArchetype(type2, + auto equivClass2 = + builder.resolveEquivalenceClass( + type2, ArchetypeResolutionKind::CompleteWellFormed); - assert(pa2 && "not a valid dependent type of this signature?"); - pa2 = pa2->getRepresentative(); - assert(!pa2->isConcreteType()); + assert(equivClass2 && "not a valid dependent type of this signature?"); + assert(!equivClass2->concreteType); - return pa1 == pa2; + return equivClass1 == equivClass2; } bool GenericSignature::isCanonicalTypeInContext(Type type, ModuleDecl &mod) { @@ -772,9 +774,10 @@ ConformanceAccessPath GenericSignature::getConformanceAccessPath( // Resolve this type to a potential archetype. auto &builder = *getGenericSignatureBuilder(mod); - auto pa = - builder.resolveArchetype(type, ArchetypeResolutionKind::CompleteWellFormed); - auto equivClass = pa->getOrCreateEquivalenceClass(); + auto equivClass = + builder.resolveEquivalenceClass( + type, + ArchetypeResolutionKind::CompleteWellFormed); // Dig out the conformance of this type to the given protocol, because we // want its requirement source. @@ -873,11 +876,10 @@ ConformanceAccessPath GenericSignature::getConformanceAccessPath( Type storedType = eraseAssociatedTypes(source->getStoredType()); // Dig out the potential archetype for this stored type. - auto pa = - inProtoSigBuilder.resolveArchetype( + auto equivClass = + inProtoSigBuilder.resolveEquivalenceClass( storedType, ArchetypeResolutionKind::CompleteWellFormed); - auto equivClass = pa->getOrCreateEquivalenceClass(); // Find the conformance of this potential archetype to the protocol in // question. diff --git a/lib/AST/GenericSignatureBuilder.cpp b/lib/AST/GenericSignatureBuilder.cpp index f19767a84a2be..19f11ec8500b2 100644 --- a/lib/AST/GenericSignatureBuilder.cpp +++ b/lib/AST/GenericSignatureBuilder.cpp @@ -2770,6 +2770,15 @@ auto GenericSignatureBuilder::resolvePotentialArchetype( return (EquivalenceClass *)nullptr; } +EquivalenceClass *GenericSignatureBuilder::resolveEquivalenceClass( + Type type, + ArchetypeResolutionKind resolutionKind) { + auto pa = resolveArchetype(type, resolutionKind); + if (!pa) return nullptr; + + return pa->getOrCreateEquivalenceClass(); +} + PotentialArchetype *GenericSignatureBuilder::resolveArchetype( Type type, ArchetypeResolutionKind resolutionKind) { diff --git a/lib/AST/LookupVisibleDecls.cpp b/lib/AST/LookupVisibleDecls.cpp index ee701ff34db4b..54ad443d91441 100644 --- a/lib/AST/LookupVisibleDecls.cpp +++ b/lib/AST/LookupVisibleDecls.cpp @@ -564,26 +564,26 @@ static void lookupVisibleMemberDeclsImpl( // If we're looking into a type parameter and we have a generic signature // builder, use the GSB to resolve where we should look. if (BaseTy->isTypeParameter() && GSB) { - auto PA = GSB->resolveArchetype( - BaseTy, - ArchetypeResolutionKind::CompleteWellFormed); - if (!PA) return; + auto EquivClass = + GSB->resolveEquivalenceClass(BaseTy, + ArchetypeResolutionKind::CompleteWellFormed); + if (!EquivClass) return; - if (auto Concrete = PA->getConcreteType()) { - BaseTy = Concrete; + if (EquivClass->concreteType) { + BaseTy = EquivClass->concreteType; } else { // Conformances - for (auto Proto : PA->getConformsTo()) { + for (const auto &Conforms : EquivClass->conformsTo) { lookupVisibleProtocolMemberDecls( - BaseTy, Proto->getDeclaredType(), Consumer, CurrDC, LS, - getReasonForSuper(Reason), TypeResolver, GSB, Visited); + BaseTy, Conforms.first->getDeclaredType(), Consumer, CurrDC, + LS, getReasonForSuper(Reason), TypeResolver, GSB, Visited); } // Superclass. - if (auto Superclass = PA->getSuperclass()) { - lookupVisibleMemberDeclsImpl(Superclass, Consumer, CurrDC, LS, - getReasonForSuper(Reason), TypeResolver, - GSB, Visited); + if (EquivClass->superclass) { + lookupVisibleMemberDeclsImpl(EquivClass->superclass, Consumer, CurrDC, + LS, getReasonForSuper(Reason), + TypeResolver, GSB, Visited); } return; } diff --git a/lib/Sema/TypeCheckGeneric.cpp b/lib/Sema/TypeCheckGeneric.cpp index ff8e1f4c31874..d325f6be28962 100644 --- a/lib/Sema/TypeCheckGeneric.cpp +++ b/lib/Sema/TypeCheckGeneric.cpp @@ -222,14 +222,16 @@ bool CompleteGenericTypeResolver::areSameType(Type type1, Type type2) { if (!type1->hasTypeParameter() && !type2->hasTypeParameter()) return type1->isEqual(type2); - auto pa1 = - Builder.resolveArchetype(type1, + auto equivClass1 = + Builder.resolveEquivalenceClass( + type1, ArchetypeResolutionKind::CompleteWellFormed); - auto pa2 = - Builder.resolveArchetype(type2, + auto equivClass2 = + Builder.resolveEquivalenceClass( + type2, ArchetypeResolutionKind::CompleteWellFormed); - if (pa1 && pa2) - return pa1->isInSameEquivalenceClassAs(pa2); + if (equivClass1 && equivClass2) + return equivClass1 == equivClass2; return type1->isEqual(type2); }