Merge pull request #12075 from apple/revert-12062-make-fewer-gsbs
Revert "Create fewer generic signature builders"
diff --git a/include/swift/AST/ASTContext.h b/include/swift/AST/ASTContext.h
index b5c9da2..5a75c21 100644
--- a/include/swift/AST/ASTContext.h
+++ b/include/swift/AST/ASTContext.h
@@ -846,16 +846,6 @@
/// not necessarily loaded.
void getVisibleTopLevelClangModules(SmallVectorImpl<clang::Module*> &Modules) const;
-private:
- /// Register the given generic signature builder to be used as the canonical
- /// generic signature builder for the given signature, if we don't already
- /// have one.
- void registerGenericSignatureBuilder(GenericSignature *sig,
- ModuleDecl &module,
- GenericSignatureBuilder &&builder);
- friend class GenericSignatureBuilder;
-
-public:
/// Retrieve or create the stored generic signature builder for the given
/// canonical generic signature and module.
GenericSignatureBuilder *getOrCreateGenericSignatureBuilder(CanGenericSignature sig,
diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h
index f9a2668..1727e84 100644
--- a/include/swift/AST/Decl.h
+++ b/include/swift/AST/Decl.h
@@ -4591,7 +4591,7 @@
/// Clone constructor, allocates a new ParamDecl identical to the first.
/// Intentionally not defined as a typical copy constructor to avoid
/// accidental copies.
- ParamDecl(ParamDecl *PD, bool withTypes);
+ ParamDecl(ParamDecl *PD);
/// Retrieve the argument (API) name for this function parameter.
Identifier getArgumentName() const { return ArgumentName; }
diff --git a/include/swift/AST/GenericSignatureBuilder.h b/include/swift/AST/GenericSignatureBuilder.h
index dd8db75..ddf8ebe 100644
--- a/include/swift/AST/GenericSignatureBuilder.h
+++ b/include/swift/AST/GenericSignatureBuilder.h
@@ -215,14 +215,6 @@
/// a superclass requirement.
bool isConformanceSatisfiedBySuperclass(ProtocolDecl *proto) const;
- /// Lookup a nested type with the given name within this equivalence
- /// class.
- ///
- /// \param otherConcreteTypes If non-null, will be filled in the all of the
- /// concrete types we found (other than the result) with the same name.
- TypeDecl *lookupNestedType(Identifier name,
- SmallVectorImpl<TypeDecl *> *otherConcreteTypes);
-
/// Dump a debugging representation of this equivalence class.
void dump(llvm::raw_ostream &out) const;
@@ -240,17 +232,6 @@
/// anchor was cached.
unsigned numMembers;
} archetypeAnchorCache;
-
- /// Describes a cached nested type.
- struct CachedNestedType {
- unsigned numConformancesPresent;
- CanType superclassPresent;
- llvm::TinyPtrVector<TypeDecl *> types;
- };
-
- /// Cached nested-type information, which contains the best declaration
- /// for a given name.
- llvm::SmallDenseMap<Identifier, CachedNestedType> nestedTypeNameCache;
};
friend class RequirementSource;
@@ -541,6 +522,9 @@
/// \brief Add all of a generic signature's parameters and requirements.
void addGenericSignature(GenericSignature *sig);
+ /// \brief Build the generic signature.
+ GenericSignature *getGenericSignature();
+
/// Infer requirements from the given type, recursively.
///
/// This routine infers requirements from a type that occurs within the
@@ -574,14 +558,11 @@
/// \brief Finalize the set of requirements and compute the generic
/// signature.
///
- /// After this point, one cannot introduce new requirements, and the
- /// generic signature builder no longer has valid state.
+ /// After this point, one cannot introduce new requirements.
GenericSignature *computeGenericSignature(
- ModuleDecl &module,
SourceLoc loc,
- bool allowConcreteGenericParams = false) &&;
+ bool allowConcreteGenericParams = false);
-private:
/// Finalize the set of requirements, performing any remaining checking
/// required before generating archetypes.
///
@@ -591,7 +572,6 @@
ArrayRef<GenericTypeParamType *> genericParams,
bool allowConcreteGenericParams=false);
-public:
/// Process any delayed requirements that can be handled now.
void processDelayedRequirements();
@@ -1495,12 +1475,6 @@
return pa->parentOrBuilder.get<GenericSignatureBuilder *>();
}
- // Replace the generic signature builder.
- void replaceBuilder(GenericSignatureBuilder *builder) {
- assert(parentOrBuilder.is<GenericSignatureBuilder *>());
- parentOrBuilder = builder;
- }
-
friend class GenericSignatureBuilder;
friend class GenericSignature;
@@ -1516,12 +1490,6 @@
return parentOrBuilder.dyn_cast<PotentialArchetype *>();
}
- /// Retrieve the type declaration to which this nested type was resolved.
- TypeDecl *getResolvedType() const {
- assert(getParent() && "Not an associated type");
- return identifier.assocTypeOrConcrete;
- }
-
/// Retrieve the associated type to which this potential archetype
/// has been resolved.
AssociatedTypeDecl *getResolvedAssociatedType() const {
@@ -1664,8 +1632,13 @@
ArchetypeResolutionKind kind,
GenericSignatureBuilder &builder);
- /// \brief Retrieve (or create) a nested type with a known type.
- PotentialArchetype *getNestedType(TypeDecl *type,
+ /// \brief Retrieve (or create) a nested type with a known associated type.
+ PotentialArchetype *getNestedType(AssociatedTypeDecl *assocType,
+ GenericSignatureBuilder &builder);
+
+ /// \brief Retrieve (or create) a nested type with a known concrete type
+ /// declaration.
+ PotentialArchetype *getNestedType(TypeDecl *concreteDecl,
GenericSignatureBuilder &builder);
/// \brief Retrieve (or create) a nested type that is the current best
@@ -1685,8 +1658,8 @@
/// type or typealias of the given protocol, unless the \c kind implies that
/// a potential archetype should not be created if it's missing.
PotentialArchetype *updateNestedTypeForConformance(
- TypeDecl *type,
- ArchetypeResolutionKind kind);
+ PointerUnion<AssociatedTypeDecl *, TypeDecl *> type,
+ ArchetypeResolutionKind kind);
/// Update the named nested type when we know this type conforms to the given
/// protocol.
diff --git a/include/swift/AST/ParameterList.h b/include/swift/AST/ParameterList.h
index 09c275b..6238d1c 100644
--- a/include/swift/AST/ParameterList.h
+++ b/include/swift/AST/ParameterList.h
@@ -128,15 +128,9 @@
Implicit = 0x01,
/// The cloned pattern is for an inherited constructor; mark default
/// arguments as inherited, and mark unnamed arguments as named.
- Inherited = 0x02,
- /// The cloned pattern will strip type information.
- WithoutTypes = 0x04,
+ Inherited = 0x02
};
-
- friend OptionSet<CloneFlags> operator|(CloneFlags flag1, CloneFlags flag2) {
- return OptionSet<CloneFlags>(flag1) | flag2;
- }
-
+
/// Make a duplicate copy of this parameter list. This allocates copies of
/// the ParamDecls, so they can be reparented into a new DeclContext.
ParameterList *clone(const ASTContext &C,
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index dd159c0..7917da8 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -43,7 +43,6 @@
#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/Preprocessor.h"
#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/Allocator.h"
@@ -53,12 +52,6 @@
using namespace swift;
-#define DEBUG_TYPE "ASTContext"
-STATISTIC(NumRegisteredGenericSignatureBuilders,
- "# of generic signature builders successfully registered");
-STATISTIC(NumRegisteredGenericSignatureBuildersAlready,
- "# of generic signature builders already registered");
-
/// Define this to 1 to enable expensive assertions of the
/// GenericSignatureBuilder.
#define SWIFT_GSB_EXPENSIVE_ASSERTIONS 0
@@ -1430,22 +1423,6 @@
collectAllModules(Modules);
}
-void ASTContext::registerGenericSignatureBuilder(
- GenericSignature *sig,
- ModuleDecl &module,
- GenericSignatureBuilder &&builder) {
- auto canSig = sig->getCanonicalSignature();
- auto known = Impl.GenericSignatureBuilders.find({canSig, &module});
- if (known != Impl.GenericSignatureBuilders.end()) {
- ++NumRegisteredGenericSignatureBuildersAlready;
- return;
- }
-
- ++NumRegisteredGenericSignatureBuilders;
- Impl.GenericSignatureBuilders[{canSig, &module}] =
- llvm::make_unique<GenericSignatureBuilder>(std::move(builder));
-}
-
GenericSignatureBuilder *ASTContext::getOrCreateGenericSignatureBuilder(
CanGenericSignature sig,
ModuleDecl *mod) {
@@ -4614,7 +4591,7 @@
GenericSignatureBuilder::FloatingRequirementSource::forAbstract();
builder.addRequirement(requirement, source, nullptr);
- CanGenericSignature genericSig(std::move(builder).computeGenericSignature(*mod, SourceLoc()));
+ CanGenericSignature genericSig(builder.computeGenericSignature(SourceLoc()));
auto result = Impl.ExistentialSignatures.insert(
std::make_pair(existential, genericSig));
diff --git a/lib/AST/Builtins.cpp b/lib/AST/Builtins.cpp
index f55762c..a7c473a 100644
--- a/lib/AST/Builtins.cpp
+++ b/lib/AST/Builtins.cpp
@@ -491,9 +491,7 @@
Builder.addGenericParameter(gp);
}
- auto GenericSig =
- std::move(Builder).computeGenericSignature(*ctx.TheBuiltinModule,
- SourceLoc());
+ auto GenericSig = Builder.computeGenericSignature(SourceLoc());
GenericEnv = GenericSig->createGenericEnvironment(*ctx.TheBuiltinModule);
}
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index 65d720a..7bd97a1 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -3419,8 +3419,7 @@
nullptr);
// Compute and record the signature.
- auto requirementSig =
- std::move(builder).computeGenericSignature(*module, SourceLoc());
+ auto requirementSig = builder.computeGenericSignature(SourceLoc());
RequirementSignature = requirementSig->getRequirements().data();
assert(RequirementSignature != nullptr);
NumRequirementsInSignature = requirementSig->getRequirements().size();
@@ -4218,11 +4217,10 @@
/// Clone constructor, allocates a new ParamDecl identical to the first.
/// Intentionally not defined as a copy constructor to avoid accidental copies.
-ParamDecl::ParamDecl(ParamDecl *PD, bool withTypes)
+ParamDecl::ParamDecl(ParamDecl *PD)
: VarDecl(DeclKind::Param, /*IsStatic*/false, PD->getSpecifier(),
/*IsCaptureList*/false, PD->getNameLoc(), PD->getName(),
- PD->hasType() && withTypes? PD->getType() : Type(),
- PD->getDeclContext()),
+ PD->hasType() ? PD->getType() : Type(), PD->getDeclContext()),
ArgumentName(PD->getArgumentName()),
ArgumentNameLoc(PD->getArgumentNameLoc()),
SpecifierLoc(PD->getSpecifierLoc()),
@@ -4230,10 +4228,7 @@
IsTypeLocImplicit(PD->IsTypeLocImplicit),
defaultArgumentKind(PD->defaultArgumentKind) {
typeLoc = PD->getTypeLoc().clone(PD->getASTContext());
- if (!withTypes && typeLoc.getTypeRepr())
- typeLoc.setType(Type());
-
- if (withTypes && PD->hasInterfaceType())
+ if (PD->hasInterfaceType())
setInterfaceType(PD->getInterfaceType());
}
diff --git a/lib/AST/GenericSignatureBuilder.cpp b/lib/AST/GenericSignatureBuilder.cpp
index 3177d3d..f0b85ea 100644
--- a/lib/AST/GenericSignatureBuilder.cpp
+++ b/lib/AST/GenericSignatureBuilder.cpp
@@ -76,10 +76,6 @@
"# of hits in the archetype anchor cache");
STATISTIC(NumArchetypeAnchorCacheMisses,
"# of misses in the archetype anchor cache");
-STATISTIC(NumNestedTypeCacheHits,
- "# of hits in the equivalence class nested type cache");
-STATISTIC(NumNestedTypeCacheMisses,
- "# of misses in the equivalence class nested type cache");
STATISTIC(NumProcessDelayedRequirements,
"# of times we process delayed requirements");
STATISTIC(NumProcessDelayedRequirementsUnchanged,
@@ -118,12 +114,6 @@
/// Whether we are currently processing delayed requirements.
bool ProcessingDelayedRequirements = false;
- /// Whether there were any errors.
- bool HadAnyError = false;
-
- /// FIXME: Hack to work around a small number of minimization bugs.
- bool HadAnyRedundantConstraints = false;
-
#ifndef NDEBUG
/// Whether we've already finalized the builder.
bool finalized = false;
@@ -1564,159 +1554,6 @@
return false;
}
-/// Compare two associated types.
-static int compareAssociatedTypes(AssociatedTypeDecl *assocType1,
- AssociatedTypeDecl *assocType2) {
- // - by name.
- if (int result = assocType1->getName().str().compare(
- assocType2->getName().str()))
- return result;
-
- // - by protocol, so t_n_m.`P.T` < t_n_m.`Q.T` (given P < Q)
- auto proto1 = assocType1->getProtocol();
- auto proto2 = assocType2->getProtocol();
- if (int compareProtocols = ProtocolType::compareProtocols(&proto1, &proto2))
- return compareProtocols;
-
- // Error case: if we have two associated types with the same name in the
- // same protocol, just tie-break based on address.
- if (assocType1 != assocType2)
- return assocType1 < assocType2 ? -1 : +1;
-
- return 0;
-}
-
-TypeDecl *EquivalenceClass::lookupNestedType(
- Identifier name,
- SmallVectorImpl<TypeDecl *> *otherConcreteTypes) {
- // Populates the result structures from the given cache entry.
- auto populateResult = [&](const CachedNestedType &cache) -> TypeDecl * {
- if (otherConcreteTypes)
- otherConcreteTypes->clear();
-
- // If there aren't any types in the cache, we're done.
- if (cache.types.empty()) return nullptr;
-
- // The first type in the cache is always the final result.
- // Collect the rest in the concrete-declarations list, if needed.
- if (otherConcreteTypes) {
- for (auto type : ArrayRef<TypeDecl *>(cache.types).slice(1)) {
- otherConcreteTypes->push_back(type);
- }
- }
-
- return cache.types.front();
- };
-
- // If we have a cached value that is up-to-date, use that.
- auto cached = nestedTypeNameCache.find(name);
- if (cached != nestedTypeNameCache.end() &&
- cached->second.numConformancesPresent == conformsTo.size() &&
- (!superclass ||
- cached->second.superclassPresent == superclass->getCanonicalType())) {
- ++NumNestedTypeCacheHits;
- return populateResult(cached->second);
- }
-
- // Cache miss; go compute the result.
- ++NumNestedTypeCacheMisses;
-
- // Look for types with the given name in protocols that we know about.
- AssociatedTypeDecl *bestAssocType = nullptr;
- SmallVector<TypeDecl *, 4> concreteDecls;
- for (const auto &conforms : conformsTo) {
- ProtocolDecl *proto = conforms.first;
-
- // Look for an associated type and/or concrete type with this name.
- for (auto member : proto->lookupDirect(name,
- /*ignoreNewExtensions=*/true)) {
- // If this is an associated type, record whether it is the best
- // associated type we've seen thus far.
- if (auto assocType = dyn_cast<AssociatedTypeDecl>(member)) {
- if (!bestAssocType ||
- compareAssociatedTypes(assocType, bestAssocType) < 0)
- bestAssocType = assocType;
-
- continue;
- }
-
- // If this is another type declaration, determine whether we should
- // record it.
- if (auto type = dyn_cast<TypeDecl>(member)) {
- // FIXME: Filter out type declarations that aren't in the same
- // module as the protocol itself. This is an unprincipled hack, but
- // provides consistent lookup semantics for the generic signature
- // builder in all contents.
- if (type->getDeclContext()->getParentModule()
- != proto->getParentModule())
- continue;
-
- // Resolve the signature of this type.
- if (!type->hasInterfaceType()) {
- type->getASTContext().getLazyResolver()->resolveDeclSignature(type);
- if (!type->hasInterfaceType())
- continue;
- }
-
- concreteDecls.push_back(type);
- continue;
- }
- }
- }
-
- // If we haven't found anything yet but have a superclass, look for a type
- // in the superclass.
- // FIXME: Shouldn't we always look in the superclass?
- if (!bestAssocType && concreteDecls.empty() && superclass) {
- if (auto classDecl = superclass->getClassOrBoundGenericClass()) {
- SmallVector<ValueDecl *, 2> superclassMembers;
- classDecl->getParentModule()->lookupQualified(
- superclass, name,
- NL_QualifiedDefault | NL_OnlyTypes | NL_ProtocolMembers, nullptr,
- superclassMembers);
- for (auto member : superclassMembers) {
- if (auto type = dyn_cast<TypeDecl>(member)) {
- // Resolve the signature of this type.
- if (!type->hasInterfaceType()) {
- type->getASTContext().getLazyResolver()->resolveDeclSignature(type);
- if (!type->hasInterfaceType())
- continue;
- }
-
- concreteDecls.push_back(type);
- }
- }
- }
- }
-
- // Form the new cache entry.
- CachedNestedType entry;
- entry.numConformancesPresent = conformsTo.size();
- entry.superclassPresent =
- superclass ? superclass->getCanonicalType() : CanType();
- if (bestAssocType) {
- entry.types.push_back(bestAssocType);
- entry.types.insert(entry.types.end(),
- concreteDecls.begin(), concreteDecls.end());
- } else if (!concreteDecls.empty()) {
- // Find the best concrete type.
- auto bestConcreteTypeIter =
- std::min_element(concreteDecls.begin(), concreteDecls.end(),
- [](TypeDecl *type1, TypeDecl *type2) {
- return TypeDecl::compare(type1, type2) < 0;
- });
-
- // Put the best concrete type first; the rest will follow.
- entry.types.push_back(*bestConcreteTypeIter);
- entry.types.insert(entry.types.end(),
- concreteDecls.begin(), bestConcreteTypeIter);
- entry.types.insert(entry.types.end(),
- bestConcreteTypeIter + 1, concreteDecls.end());
- }
-
- return populateResult((nestedTypeNameCache[name] = std::move(entry)));
-}
-
void EquivalenceClass::dump(llvm::raw_ostream &out) const {
out << "Equivalence class represented by "
<< members.front()->getRepresentative()->getDebugName() << ":\n";
@@ -1896,14 +1733,11 @@
->castTo<ProtocolType>());
if (!conformance) {
if (!concrete->hasError() && concreteSource->getLoc().isValid()) {
- Impl->HadAnyError = true;
-
Diags.diagnose(concreteSource->getLoc(),
diag::requires_generic_param_same_type_does_not_conform,
concrete, proto->getName());
}
- Impl->HadAnyError = true;
paEquivClass->invalidConcreteType = true;
return nullptr;
}
@@ -2127,6 +1961,28 @@
return result;
}
+/// Compare two associated types.
+static int compareAssociatedTypes(AssociatedTypeDecl *assocType1,
+ AssociatedTypeDecl *assocType2) {
+ // - by name.
+ if (int result = assocType1->getName().str().compare(
+ assocType2->getName().str()))
+ return result;
+
+ // - by protocol, so t_n_m.`P.T` < t_n_m.`Q.T` (given P < Q)
+ auto proto1 = assocType1->getProtocol();
+ auto proto2 = assocType2->getProtocol();
+ if (int compareProtocols = ProtocolType::compareProtocols(&proto1, &proto2))
+ return compareProtocols;
+
+ // Error case: if we have two associated types with the same name in the
+ // same protocol, just tie-break based on address.
+ if (assocType1 != assocType2)
+ return assocType1 < assocType2 ? -1 : +1;
+
+ return 0;
+}
+
/// Whether there are any concrete type declarations in the potential archetype.
static bool hasConcreteDecls(const PotentialArchetype *pa) {
auto parent = pa->getParent();
@@ -2354,9 +2210,16 @@
}
PotentialArchetype *PotentialArchetype::getNestedType(
- TypeDecl *type,
+ AssociatedTypeDecl *assocType,
GenericSignatureBuilder &builder) {
- return updateNestedTypeForConformance(type,
+ return updateNestedTypeForConformance(assocType,
+ ArchetypeResolutionKind::WellFormed);
+}
+
+PotentialArchetype *PotentialArchetype::getNestedType(
+ TypeDecl *getConcreteTypeDecl,
+ GenericSignatureBuilder &builder) {
+ return updateNestedTypeForConformance(getConcreteTypeDecl,
ArchetypeResolutionKind::WellFormed);
}
@@ -2364,21 +2227,94 @@
Identifier name,
GenericSignatureBuilder &builder,
ArchetypeResolutionKind kind) {
+ // Look for the best associated type or concrete type within the protocols
+ // we know about.
+ AssociatedTypeDecl *bestAssocType = nullptr;
+ TypeDecl *bestConcreteDecl = nullptr;
SmallVector<TypeDecl *, 4> concreteDecls;
- auto bestType =
- getOrCreateEquivalenceClass()->lookupNestedType(name, &concreteDecls);
+ auto rep = getRepresentative();
+ for (auto proto : rep->getConformsTo()) {
+ // Look for an associated type and/or concrete type with this name.
+ AssociatedTypeDecl *assocType = nullptr;
+ TypeDecl *concreteDecl = nullptr;
+ for (auto member : proto->lookupDirect(name,
+ /*ignoreNewExtensions=*/true)) {
+ if (!assocType)
+ assocType = dyn_cast<AssociatedTypeDecl>(member);
- // We didn't find any type with this name.
- if (!bestType) return nullptr;
+ // FIXME: Filter out type declarations that aren't in the protocol itself?
+ if (!concreteDecl && !isa<AssociatedTypeDecl>(member)) {
+ if (!member->hasInterfaceType())
+ builder.getLazyResolver()->resolveDeclSignature(member);
+ if (member->hasInterfaceType())
+ concreteDecl = dyn_cast<TypeDecl>(member);
+ }
+ }
- // Resolve the nested type.
- auto resultPA = updateNestedTypeForConformance(bestType, kind);
+ if (assocType &&
+ (!bestAssocType ||
+ compareAssociatedTypes(assocType, bestAssocType) < 0))
+ bestAssocType = assocType;
+
+ if (concreteDecl) {
+ // Record every concrete type.
+ concreteDecls.push_back(concreteDecl);
+
+ // Track the best concrete type.
+ if (!bestConcreteDecl ||
+ TypeDecl::compare(concreteDecl, bestConcreteDecl) < 0)
+ bestConcreteDecl = concreteDecl;
+ }
+ }
+
+ // If we found an associated type, use it.
+ PotentialArchetype *resultPA = nullptr;
+ if (bestAssocType) {
+ resultPA = updateNestedTypeForConformance(bestAssocType, kind);
+ }
+
+ // If we have an associated type, drop any concrete decls that aren't in
+ // the same module as the protocol.
+ // FIXME: This is an unprincipled hack for an unprincipled feature.
+ concreteDecls.erase(
+ std::remove_if(concreteDecls.begin(), concreteDecls.end(),
+ [&](TypeDecl *concreteDecl) {
+ return concreteDecl->getDeclContext()->getParentModule() !=
+ concreteDecl->getDeclContext()
+ ->getAsNominalTypeOrNominalTypeExtensionContext()->getParentModule();
+ }),
+ concreteDecls.end());
+
+ // If we haven't found anything yet but have a superclass, look for a type
+ // in the superclass.
+ if (!resultPA && concreteDecls.empty()) {
+ if (auto superclass = getSuperclass()) {
+ if (auto classDecl = superclass->getClassOrBoundGenericClass()) {
+ SmallVector<ValueDecl *, 2> superclassMembers;
+ classDecl->getParentModule()->lookupQualified(superclass, name, NL_QualifiedDefault | NL_OnlyTypes | NL_ProtocolMembers, nullptr,
+ superclassMembers);
+ for (auto member : superclassMembers) {
+ if (auto concreteDecl = dyn_cast<TypeDecl>(member)) {
+ // Track the best concrete type.
+ if (!bestConcreteDecl ||
+ TypeDecl::compare(concreteDecl, bestConcreteDecl) < 0)
+ bestConcreteDecl = concreteDecl;
+
+ concreteDecls.push_back(concreteDecl);
+ }
+ }
+ }
+ }
+ }
// Update for all of the concrete decls with this name, which will introduce
// various same-type constraints.
for (auto concreteDecl : concreteDecls) {
- (void)updateNestedTypeForConformance(concreteDecl,
- ArchetypeResolutionKind::WellFormed);
+ auto concreteDeclPA = updateNestedTypeForConformance(
+ concreteDecl,
+ ArchetypeResolutionKind::WellFormed);
+ if (!resultPA && concreteDecl == bestConcreteDecl)
+ resultPA = concreteDeclPA;
}
return resultPA;
@@ -2389,22 +2325,43 @@
Identifier name,
ProtocolDecl *proto,
ArchetypeResolutionKind kind) {
- // Lookup the best type for this name.
- auto bestType =
- getOrCreateEquivalenceClass()->lookupNestedType(name, nullptr);
- if (!bestType) return nullptr;
+ /// Determine whether there is an associated type or concrete type with this
+ /// name in this protocol. If not, there's nothing to do.
+ AssociatedTypeDecl *assocType = nullptr;
+ TypeDecl *concreteDecl = nullptr;
+ for (auto member : proto->lookupDirect(name, /*ignoreNewExtensions=*/true)) {
+ if (!assocType)
+ assocType = dyn_cast<AssociatedTypeDecl>(member);
- // Form the potential archetype.
- return updateNestedTypeForConformance(bestType, kind);
+ // FIXME: Filter out concrete types that aren't in the protocol itself?
+ if (!concreteDecl && !isa<AssociatedTypeDecl>(member)) {
+ if (!member->hasInterfaceType())
+ proto->getASTContext().getLazyResolver()->resolveDeclSignature(member);
+ if (member->hasInterfaceType())
+ concreteDecl = dyn_cast<TypeDecl>(member);
+ }
+ }
+
+ // There is no associated type or concrete type with this name in this
+ // protocol
+ if (!assocType && !concreteDecl)
+ return nullptr;
+
+ // If we had both an associated type and a concrete type, ignore the latter.
+ // This is for ill-formed code.
+ if (assocType)
+ return updateNestedTypeForConformance(assocType, kind);
+
+ return updateNestedTypeForConformance(concreteDecl, kind);
}
PotentialArchetype *PotentialArchetype::updateNestedTypeForConformance(
- TypeDecl *type,
- ArchetypeResolutionKind kind) {
- if (!type) return nullptr;
-
- AssociatedTypeDecl *assocType = dyn_cast<AssociatedTypeDecl>(type);
- TypeDecl *concreteDecl = assocType ? nullptr : type;
+ PointerUnion<AssociatedTypeDecl *, TypeDecl *> type,
+ ArchetypeResolutionKind kind) {
+ auto *assocType = type.dyn_cast<AssociatedTypeDecl *>();
+ auto *concreteDecl = type.dyn_cast<TypeDecl *>();
+ if (!assocType && !concreteDecl)
+ return nullptr;
// If we were asked for a complete, well-formed archetype, make sure we
// process delayed requirements if anything changed.
@@ -2865,23 +2822,7 @@
Context.Stats->getFrontendCounters().NumGenericSignatureBuilders++;
}
-GenericSignatureBuilder::GenericSignatureBuilder(
- GenericSignatureBuilder &&other)
- : Context(other.Context), Diags(other.Diags), Impl(std::move(other.Impl))
-{
- other.Impl.reset();
-
- if (Impl) {
- // Update the generic parameters to their canonical types.
- for (auto &gp : Impl->GenericParams) {
- gp = gp->getCanonicalType()->castTo<GenericTypeParamType>();
- }
-
- // Point each root potential archetype at this generic signature builder.
- for (auto pa : Impl->PotentialArchetypes)
- pa->replaceBuilder(this);
- }
-}
+GenericSignatureBuilder::GenericSignatureBuilder(GenericSignatureBuilder &&) = default;
GenericSignatureBuilder::~GenericSignatureBuilder() {
if (!Impl)
@@ -3431,8 +3372,6 @@
// If a layout requirement was explicitly written on a concrete type,
// complain.
if (source.isExplicit() && source.getLoc().isValid()) {
- Impl->HadAnyError = true;
-
Diags.diagnose(source.getLoc(), diag::requires_not_suitable_archetype,
TypeLoc::withoutLoc(resolvedSubject->getType()));
return ConstraintResult::Concrete;
@@ -3576,7 +3515,6 @@
subjectType = subject.get<PotentialArchetype *>()
->getDependentType(Impl->GenericParams);
- Impl->HadAnyError = true;
Diags.diagnose(source.getLoc(), diag::requires_conformance_nonprotocol,
TypeLoc::withoutLoc(subjectType),
TypeLoc::withoutLoc(constraintType));
@@ -3605,7 +3543,6 @@
// One cannot explicitly write a constraint on a concrete type.
if (source.isExplicit()) {
if (source.getLoc().isValid()) {
- Impl->HadAnyError = true;
Diags.diagnose(source.getLoc(), diag::requires_not_suitable_archetype,
TypeLoc::withoutLoc(resolvedSubject->getType()));
}
@@ -3696,8 +3633,13 @@
auto parentRepPA = parentPA->getRepresentative();
if (parentPA == parentRepPA) return;
- PotentialArchetype *existingPA =
- parentRepPA->getNestedType(nestedPA->getResolvedType(), *this);
+ PotentialArchetype *existingPA;
+ if (auto assocType = nestedPA->getResolvedAssociatedType()) {
+ existingPA = parentRepPA->getNestedType(assocType, *this);
+ } else {
+ existingPA = parentRepPA->getNestedType(nestedPA->getConcreteTypeDecl(),
+ *this);
+ }
auto sameNamedSource =
FloatingRequirementSource::forNestedTypeNameMatch(
@@ -3951,11 +3893,8 @@
UnresolvedHandlingKind unresolvedHandling) {
return addSameTypeRequirement(paOrT1, paOrT2, source, unresolvedHandling,
[&](Type type1, Type type2) {
- Impl->HadAnyError = true;
- if (source.getLoc().isValid()) {
- Diags.diagnose(source.getLoc(), diag::requires_same_concrete_type,
- type1, type2);
- }
+ Diags.diagnose(source.getLoc(), diag::requires_same_concrete_type,
+ type1, type2);
});
}
@@ -4132,8 +4071,6 @@
!Req->getSecondType()->hasTypeParameter()) {
if (!Req->getFirstType()->hasError() &&
!Req->getSecondType()->hasError()) {
- Impl->HadAnyError = true;
-
Diags.diagnose(Req->getEqualLoc(),
diag::requires_no_same_type_archetype)
.highlight(Req->getFirstTypeLoc().getSourceRange())
@@ -4233,11 +4170,9 @@
firstType, secondType, source,
UnresolvedHandlingKind::GenerateConstraints,
[&](Type type1, Type type2) {
- Impl->HadAnyError = true;
- if (source.getLoc().isValid()) {
+ if (source.getLoc().isValid())
Diags.diagnose(source.getLoc(), diag::requires_same_concrete_type,
type1, type2);
- }
});
}
}
@@ -4582,8 +4517,6 @@
if (isRecursiveConcreteType(archetype, /*isSuperclass=*/false)) {
if (auto constraint =
equivClass->findAnyConcreteConstraintAsWritten()) {
- Impl->HadAnyError = true;
-
Diags.diagnose(constraint->source->getLoc(),
diag::recursive_same_type_constraint,
archetype->getDependentType(genericParams),
@@ -4600,8 +4533,6 @@
if (equivClass->superclass) {
if (isRecursiveConcreteType(archetype, /*isSuperclass=*/true)) {
if (auto source = equivClass->findAnySuperclassConstraintAsWritten()) {
- Impl->HadAnyError = true;
-
Diags.diagnose(source->source->getLoc(),
diag::recursive_superclass_constraint,
source->archetype->getDependentType(genericParams),
@@ -4663,13 +4594,10 @@
// because then we don't actually have a parameter.
auto equivClass = rep->getOrCreateEquivalenceClass();
if (equivClass->concreteType) {
- if (auto constraint = equivClass->findAnyConcreteConstraintAsWritten()){
- Impl->HadAnyError = true;
-
+ if (auto constraint = equivClass->findAnyConcreteConstraintAsWritten())
Diags.diagnose(constraint->source->getLoc(),
diag::requires_generic_param_made_equal_to_concrete,
rep->getDependentType(genericParams));
- }
continue;
}
@@ -4699,8 +4627,6 @@
}
if (repConstraint && repConstraint->source->getLoc().isValid()) {
- Impl->HadAnyError = true;
-
Diags.diagnose(repConstraint->source->getLoc(),
diag::requires_generic_params_made_equal,
pa->getDependentType(genericParams),
@@ -4980,8 +4906,6 @@
// The requirement conflicts. If this constraint has a location, complain
// about it.
if (constraint.source->getLoc().isValid()) {
- Impl->HadAnyError = true;
-
auto subject = getSubjectType(constraint.archetype);
Diags.diagnose(constraint.source->getLoc(), *conflictingDiag,
subject.first, subject.second,
@@ -4996,8 +4920,6 @@
// do so now.
if (!diagnosedConflictingRepresentative &&
representativeConstraint->source->getLoc().isValid()) {
- Impl->HadAnyError = true;
-
auto subject = getSubjectType(representativeConstraint->archetype);
Diags.diagnose(representativeConstraint->source->getLoc(),
*conflictingDiag,
@@ -5014,7 +4936,6 @@
case ConstraintRelation::Redundant:
// If this requirement is not derived or inferred (but has a useful
// location) complain that it is redundant.
- Impl->HadAnyRedundantConstraints = true;
if (!constraint.source->isDerivedRequirement() &&
!constraint.source->isInferredRequirement(
/*includeQuietInferred=*/true) &&
@@ -5982,8 +5903,6 @@
if (!equivClass->superclass->isExactSuperclassOf(equivClass->concreteType)) {
if (auto existing = equivClass->findAnyConcreteConstraintAsWritten(
representativeConstraint.archetype)) {
- Impl->HadAnyError = true;
-
Diags.diagnose(existing->source->getLoc(), diag::type_does_not_inherit,
existing->archetype->getDependentType(
genericParams),
@@ -5991,8 +5910,6 @@
// FIXME: Note the representative constraint.
} else if (representativeConstraint.source->getLoc().isValid()) {
- Impl->HadAnyError = true;
-
Diags.diagnose(representativeConstraint.source->getLoc(),
diag::type_does_not_inherit,
representativeConstraint.archetype->getDependentType(
@@ -6376,53 +6293,21 @@
});
}
-GenericSignature *GenericSignatureBuilder::computeGenericSignature(
- ModuleDecl &module,
- SourceLoc loc,
- bool allowConcreteGenericParams) && {
- // Finalize the builder, producing any necessary diagnostics.
- finalize(loc, Impl->GenericParams, allowConcreteGenericParams);
+GenericSignature *GenericSignatureBuilder::getGenericSignature() {
+ assert(Impl->finalized && "Must finalize builder first");
// Collect the requirements placed on the generic parameter types.
SmallVector<Requirement, 4> requirements;
collectRequirements(*this, Impl->GenericParams, requirements);
- // Form the generic signature.
auto sig = GenericSignature::get(Impl->GenericParams, requirements);
-
- // Was this a requirement signature?
- bool isRequirementSignature = false;
- if (auto firstEquivClass =
- Impl->PotentialArchetypes.front()->getEquivalenceClassIfPresent()) {
- if (!firstEquivClass->conformsTo.empty() &&
- firstEquivClass->conformsTo.front().second.front().source->getRoot()
- ->kind == RequirementSource::RequirementSignatureSelf)
- isRequirementSignature = true;
- }
-
- // When we can, move this generic signature builder to make it the canonical
- // builder, rather than constructing a new generic signature builder that
- // will produce the same thing.
- //
- // We cannot do this for requirement signatures (because they aren't
- // fully-formed generic signatures) or when there were errors.
- // FIXME: hadAnyError() is a big over-approximation here.
- // FIXME: The HadAnyRedundantConstraints bit is a hack because we are
- // over-minimizing.
- if (!isRequirementSignature && !Impl->HadAnyError &&
- !Impl->HadAnyRedundantConstraints) {
- // Set the conformance lookup function to something that works canonically.
- Impl->LookupConformance = LookUpConformanceInModule(&module);
-
- // Register this generic signature builer as the canonical builder for the
- // given signature.
- Context.registerGenericSignatureBuilder(sig, module, std::move(*this));
- }
-
- // Wipe out the internal state, ensuring that nobody uses this builder for
- // anything more.
- Impl.reset();
-
return sig;
}
+GenericSignature *GenericSignatureBuilder::computeGenericSignature(
+ SourceLoc loc,
+ bool allowConcreteGenericParams) {
+ finalize(loc, Impl->GenericParams, allowConcreteGenericParams);
+ return getGenericSignature();
+}
+
diff --git a/lib/AST/Parameter.cpp b/lib/AST/Parameter.cpp
index 4c15b4c..e86697f 100644
--- a/lib/AST/Parameter.cpp
+++ b/lib/AST/Parameter.cpp
@@ -88,12 +88,11 @@
SmallVector<ParamDecl*, 8> params(begin(), end());
// Remap the ParamDecls inside of the ParameterList.
- bool withTypes = !options.contains(ParameterList::WithoutTypes);
for (auto &decl : params) {
bool hadDefaultArgument =
decl->getDefaultArgumentKind() == DefaultArgumentKind::Normal;
- decl = new (C) ParamDecl(decl, withTypes);
+ decl = new (C) ParamDecl(decl);
if (options & Implicit)
decl->setImplicit();
diff --git a/lib/ClangImporter/ImportDecl.cpp b/lib/ClangImporter/ImportDecl.cpp
index c74ed44..ca99376 100644
--- a/lib/ClangImporter/ImportDecl.cpp
+++ b/lib/ClangImporter/ImportDecl.cpp
@@ -7653,8 +7653,7 @@
(void) result;
}
- return std::move(builder).computeGenericSignature(*dc->getParentModule(),
- SourceLoc());
+ return builder.computeGenericSignature(SourceLoc());
}
// Calculate the generic environment from an imported generic param list.
diff --git a/lib/SILGen/SILGenPoly.cpp b/lib/SILGen/SILGenPoly.cpp
index 14b1769..829c219 100644
--- a/lib/SILGen/SILGenPoly.cpp
+++ b/lib/SILGen/SILGenPoly.cpp
@@ -2695,7 +2695,7 @@
builder.addRequirement(newRequirement, source, nullptr);
GenericSignature *genericSig =
- std::move(builder).computeGenericSignature(*mod, SourceLoc(),
+ builder.computeGenericSignature(SourceLoc(),
/*allowConcreteGenericParams=*/true);
genericEnv = genericSig->createGenericEnvironment(*mod);
diff --git a/lib/SILOptimizer/Utils/Generics.cpp b/lib/SILOptimizer/Utils/Generics.cpp
index da1a9f1..1bf8554 100644
--- a/lib/SILOptimizer/Utils/Generics.cpp
+++ b/lib/SILOptimizer/Utils/Generics.cpp
@@ -800,8 +800,7 @@
}
auto NewGenSig =
- std::move(Builder).computeGenericSignature(*M.getSwiftModule(),
- SourceLoc(),
+ Builder.computeGenericSignature(SourceLoc(),
/*allowConcreteGenericParams=*/true);
auto NewGenEnv = NewGenSig->createGenericEnvironment(*M.getSwiftModule());
return { NewGenEnv, NewGenSig };
@@ -1491,8 +1490,7 @@
// Finalize the archetype builder.
auto GenSig =
- std::move(Builder).computeGenericSignature(*M.getSwiftModule(),
- SourceLoc(),
+ Builder.computeGenericSignature(SourceLoc(),
/*allowConcreteGenericParams=*/true);
auto GenEnv = GenSig->createGenericEnvironment(*M.getSwiftModule());
return { GenEnv, GenSig };
diff --git a/lib/Sema/CodeSynthesis.cpp b/lib/Sema/CodeSynthesis.cpp
index 727f365..692dfde 100644
--- a/lib/Sema/CodeSynthesis.cpp
+++ b/lib/Sema/CodeSynthesis.cpp
@@ -104,8 +104,7 @@
// Clone the parameter list over for a new decl, so we get new ParamDecls.
auto indices = subscript->getIndices()->clone(context,
- ParameterList::Implicit|
- ParameterList::WithoutTypes);
+ ParameterList::Implicit);
if (prefix.empty())
return indices;
diff --git a/lib/Sema/GenericTypeResolver.h b/lib/Sema/GenericTypeResolver.h
index b7a9763..02b63fc 100644
--- a/lib/Sema/GenericTypeResolver.h
+++ b/lib/Sema/GenericTypeResolver.h
@@ -130,14 +130,14 @@
/// to check the signature of a generic declaration and resolve (for example)
/// all dependent member refers to archetype members.
class CompleteGenericTypeResolver : public GenericTypeResolver {
- TypeChecker &tc;
- GenericSignature *genericSig;
- ModuleDecl &module;
- GenericSignatureBuilder &builder;
+ TypeChecker &TC;
+ GenericSignatureBuilder &Builder;
+ ArrayRef<GenericTypeParamType *> GenericParams;
public:
- CompleteGenericTypeResolver(TypeChecker &tc, GenericSignature *genericSig,
- ModuleDecl &module);
+ CompleteGenericTypeResolver(TypeChecker &tc, GenericSignatureBuilder &builder,
+ ArrayRef<GenericTypeParamType *> genericParams)
+ : TC(tc), Builder(builder), GenericParams(genericParams) { }
virtual Type mapTypeIntoContext(Type type);
diff --git a/lib/Sema/TypeCheckAttr.cpp b/lib/Sema/TypeCheckAttr.cpp
index f3438d3..63d7375 100644
--- a/lib/Sema/TypeCheckAttr.cpp
+++ b/lib/Sema/TypeCheckAttr.cpp
@@ -1851,9 +1851,7 @@
Builder.addRequirement(&req, DC->getParentModule());
// Check the result.
- (void)std::move(Builder).computeGenericSignature(
- *DC->getParentModule(),
- attr->getLocation(),
+ (void)Builder.computeGenericSignature(attr->getLocation(),
/*allowConcreteGenericParams=*/true);
}
diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp
index a9db914..fcfc379 100644
--- a/lib/Sema/TypeCheckDecl.cpp
+++ b/lib/Sema/TypeCheckDecl.cpp
@@ -827,8 +827,7 @@
prepareGenericParamList(genericParams, DC);
parentEnv = checkGenericEnvironment(genericParams, DC, parentSig,
- /*allowConcreteGenericParams=*/true,
- /*ext=*/nullptr);
+ /*allowConcreteGenericParams=*/true);
parentSig = parentEnv->getGenericSignature();
// Compute the final set of archetypes.
@@ -5234,18 +5233,10 @@
// Revert the types within the signature so it can be type-checked with
// archetypes below.
TC.revertGenericFuncSignature(FD);
- } else if (auto genericSig =
- FD->getDeclContext()->getGenericSignatureOfContext()) {
- if (!FD->getAccessorStorageDecl()) {
- (void)TC.validateGenericFuncSignature(FD);
-
- // Revert all of the types within the signature of the function.
- TC.revertGenericFuncSignature(FD);
- } else {
- // We've inherited all of the type information already.
- TC.configureInterfaceType(FD, genericSig);
- }
-
+ } else if (FD->getDeclContext()->getGenericSignatureOfContext()) {
+ (void)TC.validateGenericFuncSignature(FD);
+ // Revert all of the types within the signature of the function.
+ TC.revertGenericFuncSignature(FD);
FD->setGenericEnvironment(
FD->getDeclContext()->getGenericEnvironmentOfContext());
}
@@ -8048,7 +8039,7 @@
auto *env = tc.checkGenericEnvironment(genericParams,
ext->getDeclContext(), nullptr,
/*allowConcreteGenericParams=*/true,
- ext, inferExtendedTypeReqs);
+ inferExtendedTypeReqs);
// Validate the generic parameters for the last time, to splat down
// actual archetypes.
diff --git a/lib/Sema/TypeCheckGeneric.cpp b/lib/Sema/TypeCheckGeneric.cpp
index 8ca70e1..a7c6d01 100644
--- a/lib/Sema/TypeCheckGeneric.cpp
+++ b/lib/Sema/TypeCheckGeneric.cpp
@@ -116,17 +116,6 @@
"recording a param type of a protocol requirement doesn't make sense");
}
-CompleteGenericTypeResolver::CompleteGenericTypeResolver(
- TypeChecker &tc,
- GenericSignature *genericSig,
- ModuleDecl &module)
- : tc(tc), genericSig(genericSig), module(module),
- builder(*tc.Context.getOrCreateGenericSignatureBuilder(
- genericSig->getCanonicalSignature(),
- &module))
-{
-}
-
Type CompleteGenericTypeResolver::mapTypeIntoContext(Type type) {
return type;
}
@@ -138,7 +127,7 @@
ComponentIdentTypeRepr *ref) {
// Resolve the base to a potential archetype.
auto basePA =
- builder.resolveArchetype(baseTy,
+ Builder.resolveArchetype(baseTy,
ArchetypeResolutionKind::CompleteWellFormed);
assert(basePA && "Missing potential archetype for base");
@@ -146,17 +135,17 @@
auto nestedPA =
basePA->getNestedType(ref->getIdentifier(),
ArchetypeResolutionKind::CompleteWellFormed,
- builder);
+ Builder);
// If there was no such nested type, produce an error.
if (!nestedPA) {
// Perform typo correction.
LookupResult corrections;
- tc.performTypoCorrection(DC, DeclRefKind::Ordinary,
+ TC.performTypoCorrection(DC, DeclRefKind::Ordinary,
MetatypeType::get(baseTy),
ref->getIdentifier(), ref->getIdLoc(),
NameLookupFlags::ProtocolMembers,
- corrections, &builder);
+ corrections, &Builder);
// Filter out non-types.
corrections.filter([](const LookupResultEntry &result) {
@@ -170,17 +159,17 @@
if (!singleType) {
Identifier name = ref->getIdentifier();
SourceLoc nameLoc = ref->getIdLoc();
- tc.diagnose(nameLoc, diag::invalid_member_type, name, baseTy)
+ TC.diagnose(nameLoc, diag::invalid_member_type, name, baseTy)
.highlight(baseRange);
for (const auto &suggestion : corrections)
- tc.noteTypoCorrection(name, DeclNameLoc(nameLoc),
+ TC.noteTypoCorrection(name, DeclNameLoc(nameLoc),
suggestion.getValueDecl());
- return ErrorType::get(tc.Context);
+ return ErrorType::get(TC.Context);
}
// We have a single type result. Suggest it.
- tc.diagnose(ref->getIdLoc(), diag::invalid_member_type_suggest,
+ TC.diagnose(ref->getIdLoc(), diag::invalid_member_type_suggest,
baseTy, ref->getIdentifier(),
singleType->getBaseName().getIdentifier())
.fixItReplace(ref->getIdLoc(),
@@ -204,14 +193,14 @@
// Otherwise, the nested type comes from a concrete type. Substitute the
// base type into it.
auto concrete = ref->getBoundDecl();
- tc.validateDeclForNameLookup(concrete);
+ TC.validateDeclForNameLookup(concrete);
if (!concrete->hasInterfaceType())
- return ErrorType::get(tc.Context);
+ return ErrorType::get(TC.Context);
if (baseTy->isTypeParameter()) {
if (auto proto =
concrete->getDeclContext()
->getAsProtocolOrProtocolExtensionContext()) {
- tc.validateDecl(proto);
+ TC.validateDecl(proto);
auto subMap = SubstitutionMap::getProtocolSubstitutions(
proto, baseTy, ProtocolConformanceRef(proto));
return concrete->getDeclaredInterfaceType().subst(subMap);
@@ -226,12 +215,25 @@
llvm_unreachable("shouldn't have a concrete decl here");
}
- return tc.substMemberTypeWithBase(DC->getParentModule(), concrete, baseTy);
+ return TC.substMemberTypeWithBase(DC->getParentModule(), concrete, baseTy);
}
bool CompleteGenericTypeResolver::areSameType(Type type1, Type type2) {
- return genericSig->getCanonicalTypeInContext(type1, module)
- == genericSig->getCanonicalTypeInContext(type2, module);
+ if (!type1->hasTypeParameter() && !type2->hasTypeParameter())
+ return type1->isEqual(type2);
+
+ auto equivClass1 =
+ Builder.resolveEquivalenceClass(
+ type1,
+ ArchetypeResolutionKind::CompleteWellFormed);
+ auto equivClass2 =
+ Builder.resolveEquivalenceClass(
+ type2,
+ ArchetypeResolutionKind::CompleteWellFormed);
+ if (equivClass1 && equivClass2)
+ return equivClass1 == equivClass2;
+
+ return type1->isEqual(type2);
}
void
@@ -748,55 +750,61 @@
TypeChecker::validateGenericFuncSignature(AbstractFunctionDecl *func) {
bool invalid = false;
- GenericSignature *sig;
- if (auto gp = func->getGenericParams()) {
+ auto *gp = func->getGenericParams();
+ if (gp)
prepareGenericParamList(gp, func);
- // Create the generic signature builder.
- GenericSignatureBuilder builder(Context, LookUpConformance(*this, func));
+ // Collect the generic parameters.
+ SmallVector<GenericTypeParamType *, 4> allGenericParams;
+ if (auto parentSig = func->getDeclContext()->getGenericSignatureOfContext())
+ allGenericParams.append(parentSig->getGenericParams().begin(),
+ parentSig->getGenericParams().end());
+ addGenericParamTypes(gp, allGenericParams);
- // Type check the function declaration, treating all generic type
- // parameters as dependent, unresolved.
- DependentGenericTypeResolver dependentResolver;
- if (checkGenericFuncSignature(*this, &builder, func, dependentResolver))
- invalid = true;
+ // Create the generic signature builder.
+ GenericSignatureBuilder builder(Context, LookUpConformance(*this, func));
- // The generic function signature is complete and well-formed. Determine
- // the type of the generic function.
- sig = std::move(builder).computeGenericSignature(*func->getParentModule(),
- func->getLoc());
+ // Type check the function declaration, treating all generic type
+ // parameters as dependent, unresolved.
+ DependentGenericTypeResolver dependentResolver;
+ if (checkGenericFuncSignature(*this, &builder, func, dependentResolver))
+ invalid = true;
- // The generic signature builder now has all of the requirements, although
- // there might still be errors that have not yet been diagnosed. Revert the
- // generic function signature and type-check it again, completely.
- revertGenericFuncSignature(func);
- if (gp)
- revertGenericParamList(gp);
+ // Finalize the generic requirements.
+ (void)builder.finalize(func->getLoc(), allGenericParams);
- // Debugging of the generic signature.
- if (Context.LangOpts.DebugGenericSignatures) {
- func->dumpRef(llvm::errs());
- llvm::errs() << "\n";
- llvm::errs() << "Generic signature: ";
- sig->print(llvm::errs());
- llvm::errs() << "\n";
- llvm::errs() << "Canonical generic signature: ";
- sig->getCanonicalSignature()->print(llvm::errs());
- llvm::errs() << "\n";
- }
- } else {
- // Inherit the signature of our environment.
- sig = func->getDeclContext()->getGenericSignatureOfContext();
- }
+ // The generic signature builder now has all of the requirements, although
+ // there might still be errors that have not yet been diagnosed. Revert the
+ // generic function signature and type-check it again, completely.
+ revertGenericFuncSignature(func);
+ if (gp)
+ revertGenericParamList(gp);
- CompleteGenericTypeResolver completeResolver(*this, sig,
- *func->getModuleContext());
+ CompleteGenericTypeResolver completeResolver(*this, builder,
+ allGenericParams);
if (checkGenericFuncSignature(*this, nullptr, func, completeResolver))
invalid = true;
+ // The generic function signature is complete and well-formed. Determine
+ // the type of the generic function.
+ auto sig = builder.getGenericSignature();
+
if (!invalid)
invalid = checkProtocolSelfRequirements(sig, func, *this);
+ // Debugging of the generic signature builder and generic signature generation.
+ if (Context.LangOpts.DebugGenericSignatures) {
+ func->dumpRef(llvm::errs());
+ llvm::errs() << "\n";
+ builder.dump(llvm::errs());
+ llvm::errs() << "Generic signature: ";
+ sig->print(llvm::errs());
+ llvm::errs() << "\n";
+ llvm::errs() << "Canonical generic signature: ";
+ sig->getCanonicalSignature()->print(llvm::errs());
+ llvm::errs() << "\n";
+ }
+
if (invalid) {
func->setInterfaceType(ErrorType::get(Context));
func->setInvalid();
@@ -972,57 +980,62 @@
TypeChecker::validateGenericSubscriptSignature(SubscriptDecl *subscript) {
bool invalid = false;
- GenericSignature *sig;
- if (auto *gp = subscript->getGenericParams()) {
+ auto *gp = subscript->getGenericParams();
+ if (gp)
prepareGenericParamList(gp, subscript);
- // Create the generic signature builder.
- GenericSignatureBuilder builder(Context,
- LookUpConformance(*this, subscript));
+ // Collect the generic parameters.
+ SmallVector<GenericTypeParamType *, 4> allGenericParams;
+ if (auto parentSig = subscript->getDeclContext()->getGenericSignatureOfContext())
+ allGenericParams.append(parentSig->getGenericParams().begin(),
+ parentSig->getGenericParams().end());
+ addGenericParamTypes(gp, allGenericParams);
- // Type check the function declaration, treating all generic type
- // parameters as dependent, unresolved.
- DependentGenericTypeResolver dependentResolver;
- if (checkGenericSubscriptSignature(*this, &builder, subscript,
- dependentResolver))
- invalid = true;
+ // Create the generic signature builder.
+ GenericSignatureBuilder builder(Context, LookUpConformance(*this, subscript));
- // The generic subscript signature is complete and well-formed. Determine
- // the type of the generic subscript.
- sig =
- std::move(builder).computeGenericSignature(*subscript->getParentModule(),
- subscript->getLoc());
+ // Type check the function declaration, treating all generic type
+ // parameters as dependent, unresolved.
+ DependentGenericTypeResolver dependentResolver;
+ if (checkGenericSubscriptSignature(*this, &builder, subscript,
+ dependentResolver))
+ invalid = true;
- // The generic signature builder now has all of the requirements, although
- // there might still be errors that have not yet been diagnosed. Revert the
- // generic function signature and type-check it again, completely.
- revertGenericSubscriptSignature(subscript);
+ // Finalize the generic requirements.
+ (void)builder.finalize(subscript->getLoc(), allGenericParams);
+
+ // The generic signature builder now has all of the requirements, although
+ // there might still be errors that have not yet been diagnosed. Revert the
+ // generic function signature and type-check it again, completely.
+ revertGenericSubscriptSignature(subscript);
+ if (gp)
revertGenericParamList(gp);
- // Debugging of generic signature generation.
- if (Context.LangOpts.DebugGenericSignatures) {
- subscript->dumpRef(llvm::errs());
- llvm::errs() << "\n";
- llvm::errs() << "Generic signature: ";
- sig->print(llvm::errs());
- llvm::errs() << "\n";
- llvm::errs() << "Canonical generic signature: ";
- sig->getCanonicalSignature()->print(llvm::errs());
- llvm::errs() << "\n";
- }
- } else {
- // Inherit the signature of our environment.
- sig = subscript->getDeclContext()->getGenericSignatureOfContext();
- }
-
- CompleteGenericTypeResolver completeResolver(*this, sig,
- *subscript->getModuleContext());
+ CompleteGenericTypeResolver completeResolver(*this, builder,
+ allGenericParams);
if (checkGenericSubscriptSignature(*this, nullptr, subscript, completeResolver))
invalid = true;
+ // The generic subscript signature is complete and well-formed. Determine
+ // the type of the generic subscript.
+ auto sig = builder.getGenericSignature();
+
if (!invalid)
invalid = checkProtocolSelfRequirements(sig, subscript, *this);
+ // Debugging of the generic signature builder and generic signature generation.
+ if (Context.LangOpts.DebugGenericSignatures) {
+ subscript->dumpRef(llvm::errs());
+ llvm::errs() << "\n";
+ builder.dump(llvm::errs());
+ llvm::errs() << "Generic signature: ";
+ sig->print(llvm::errs());
+ llvm::errs() << "\n";
+ llvm::errs() << "Canonical generic signature: ";
+ sig->getCanonicalSignature()->print(llvm::errs());
+ llvm::errs() << "\n";
+ }
+
if (invalid) {
subscript->setInterfaceType(ErrorType::get(Context));
subscript->setInvalid();
@@ -1067,105 +1080,72 @@
visitor(genericParams);
}
-/// Retrieve the generic parameter depth of the extended type.
-static unsigned getExtendedTypeGenericDepth(ExtensionDecl *ext) {
- auto nominal = ext->getAsNominalTypeOrNominalTypeExtensionContext();
- if (!nominal) return static_cast<unsigned>(-1);
-
- auto sig = nominal->getGenericSignatureOfContext();
- if (!sig) return static_cast<unsigned>(-1);
-
- return sig->getGenericParams().back()->getDepth();
-}
-
GenericEnvironment *TypeChecker::checkGenericEnvironment(
GenericParamList *genericParams,
DeclContext *dc,
GenericSignature *parentSig,
bool allowConcreteGenericParams,
- ExtensionDecl *ext,
llvm::function_ref<void(GenericSignatureBuilder &)>
inferRequirements) {
assert(genericParams && "Missing generic parameters?");
bool recursivelyVisitGenericParams =
genericParams->getOuterParameters() && !parentSig;
- GenericSignature *sig;
- if (!ext || ext->getTrailingWhereClause() ||
- getExtendedTypeGenericDepth(ext) != genericParams->getDepth()) {
- // Collect the generic parameters.
- SmallVector<GenericTypeParamType *, 4> allGenericParams;
- if (recursivelyVisitGenericParams) {
- visitOuterToInner(genericParams,
- [&](GenericParamList *gpList) {
- addGenericParamTypes(gpList, allGenericParams);
- });
- } else {
- if (parentSig) {
- allGenericParams.append(parentSig->getGenericParams().begin(),
- parentSig->getGenericParams().end());
- }
-
- addGenericParamTypes(genericParams, allGenericParams);
- }
-
- // Create the generic signature builder.
- GenericSignatureBuilder builder(Context, LookUpConformance(*this, dc));
-
- // Type check the generic parameters, treating all generic type
- // parameters as dependent, unresolved.
- DependentGenericTypeResolver dependentResolver;
- if (recursivelyVisitGenericParams) {
- visitOuterToInner(genericParams,
- [&](GenericParamList *gpList) {
- checkGenericParamList(&builder, gpList, nullptr, &dependentResolver);
- });
- } else {
- checkGenericParamList(&builder, genericParams, parentSig,
- &dependentResolver);
- }
-
- /// Perform any necessary requirement inference.
- inferRequirements(builder);
-
- // Record the generic type parameter types and the requirements.
- sig = std::move(builder).computeGenericSignature(
- *dc->getParentModule(),
- genericParams->getSourceRange().Start,
- allowConcreteGenericParams);
-
- // The generic signature builder now has all of the requirements, although
- // there might still be errors that have not yet been diagnosed. Revert the
- // signature and type-check it again, completely.
- if (recursivelyVisitGenericParams) {
- visitOuterToInner(genericParams,
- [&](GenericParamList *gpList) {
- revertGenericParamList(gpList);
- });
- } else {
- revertGenericParamList(genericParams);
- }
-
- // Debugging of the generic signature builder and generic signature
- // generation.
- if (Context.LangOpts.DebugGenericSignatures) {
- dc->printContext(llvm::errs());
- llvm::errs() << "\n";
- llvm::errs() << "Generic signature: ";
- sig->print(llvm::errs());
- llvm::errs() << "\n";
- llvm::errs() << "Canonical generic signature: ";
- sig->getCanonicalSignature()->print(llvm::errs());
- llvm::errs() << "\n";
- }
+ // Collect the generic parameters.
+ SmallVector<GenericTypeParamType *, 4> allGenericParams;
+ if (recursivelyVisitGenericParams) {
+ visitOuterToInner(genericParams,
+ [&](GenericParamList *gpList) {
+ addGenericParamTypes(gpList, allGenericParams);
+ });
} else {
- // Re-use the signature of the type being extended.
- sig = ext->getAsNominalTypeOrNominalTypeExtensionContext()
- ->getGenericSignatureOfContext();
+ if (parentSig) {
+ allGenericParams.append(parentSig->getGenericParams().begin(),
+ parentSig->getGenericParams().end());
+ }
+
+ addGenericParamTypes(genericParams, allGenericParams);
}
- CompleteGenericTypeResolver completeResolver(*this, sig,
- *dc->getParentModule());
+ // Create the generic signature builder.
+ ModuleDecl *module = dc->getParentModule();
+ GenericSignatureBuilder builder(Context, LookUpConformance(*this, dc));
+
+ // Type check the generic parameters, treating all generic type
+ // parameters as dependent, unresolved.
+ DependentGenericTypeResolver dependentResolver;
+ if (recursivelyVisitGenericParams) {
+ visitOuterToInner(genericParams,
+ [&](GenericParamList *gpList) {
+ checkGenericParamList(&builder, gpList, nullptr, &dependentResolver);
+ });
+ } else {
+ checkGenericParamList(&builder, genericParams, parentSig,
+ &dependentResolver);
+ }
+
+ /// Perform any necessary requirement inference.
+ inferRequirements(builder);
+
+ // Finalize the generic requirements.
+ (void)builder.finalize(genericParams->getSourceRange().Start,
+ allGenericParams,
+ allowConcreteGenericParams);
+
+ // The generic signature builder now has all of the requirements, although
+ // there might still be errors that have not yet been diagnosed. Revert the
+ // signature and type-check it again, completely.
+ if (recursivelyVisitGenericParams) {
+ visitOuterToInner(genericParams,
+ [&](GenericParamList *gpList) {
+ revertGenericParamList(gpList);
+ });
+ } else {
+ revertGenericParamList(genericParams);
+ }
+
+ CompleteGenericTypeResolver completeResolver(*this, builder,
+ allGenericParams);
if (recursivelyVisitGenericParams) {
visitOuterToInner(genericParams,
[&](GenericParamList *gpList) {
@@ -1176,8 +1156,23 @@
&completeResolver);
}
+ // Record the generic type parameter types and the requirements.
+ auto sig = builder.getGenericSignature();
+
+ // Debugging of the generic signature builder and generic signature generation.
+ if (Context.LangOpts.DebugGenericSignatures) {
+ dc->printContext(llvm::errs());
+ llvm::errs() << "\n";
+ builder.dump(llvm::errs());
+ llvm::errs() << "Generic signature: ";
+ sig->print(llvm::errs());
+ llvm::errs() << "\n";
+ llvm::errs() << "Canonical generic signature: ";
+ sig->getCanonicalSignature()->print(llvm::errs());
+ llvm::errs() << "\n";
+ }
+
// Form the generic environment.
- ModuleDecl *module = dc->getParentModule();
return sig->createGenericEnvironment(*module);
}
@@ -1202,10 +1197,8 @@
proto->computeRequirementSignature();
}
- auto *env = checkGenericEnvironment(gp, dc,
- dc->getGenericSignatureOfContext(),
- /*allowConcreteGenericParams=*/false,
- /*ext=*/nullptr);
+ auto *env = checkGenericEnvironment(gp, dc, dc->getGenericSignatureOfContext(),
+ /*allowConcreteGenericParams=*/false);
typeDecl->setGenericEnvironment(env);
}
diff --git a/lib/Sema/TypeCheckProtocol.cpp b/lib/Sema/TypeCheckProtocol.cpp
index 1bc58f0..d730a4a 100644
--- a/lib/Sema/TypeCheckProtocol.cpp
+++ b/lib/Sema/TypeCheckProtocol.cpp
@@ -1156,10 +1156,7 @@
// Produce the generic signature and environment.
// FIXME: Pass in a source location for the conformance, perhaps? It seems
// like this could fail.
- syntheticSignature =
- std::move(builder).computeGenericSignature(
- *conformanceDC->getParentModule(),
- SourceLoc());
+ syntheticSignature = builder.computeGenericSignature(SourceLoc());
syntheticEnvironment = syntheticSignature->createGenericEnvironment(
*conformanceDC->getParentModule());
}
diff --git a/lib/Sema/TypeChecker.h b/lib/Sema/TypeChecker.h
index 0c3e4d8..4a7a0d9 100644
--- a/lib/Sema/TypeChecker.h
+++ b/lib/Sema/TypeChecker.h
@@ -1367,9 +1367,6 @@
/// context, if not available as part of the \c dc argument (used
/// for SIL parsing).
///
- /// \param ext The extension for which we're checking the generic
- /// environment, or null if we're not checking an extension.
- ///
/// \param inferRequirements When non-empty, callback that will be invoked
/// to perform any additional requirement inference that contributes to the
/// generic environment..
@@ -1380,7 +1377,6 @@
DeclContext *dc,
GenericSignature *outerSignature,
bool allowConcreteGenericParams,
- ExtensionDecl *ext,
llvm::function_ref<void(GenericSignatureBuilder &)>
inferRequirements);
@@ -1398,10 +1394,9 @@
GenericParamList *genericParams,
DeclContext *dc,
GenericSignature *outerSignature,
- bool allowConcreteGenericParams,
- ExtensionDecl *ext) {
+ bool allowConcreteGenericParams) {
return checkGenericEnvironment(genericParams, dc, outerSignature,
- allowConcreteGenericParams, ext,
+ allowConcreteGenericParams,
[&](GenericSignatureBuilder &) { });
}
diff --git a/test/Generics/associated_type_typo.swift b/test/Generics/associated_type_typo.swift
index 4ac5b86..f023418 100644
--- a/test/Generics/associated_type_typo.swift
+++ b/test/Generics/associated_type_typo.swift
@@ -34,6 +34,13 @@
// expected-error@+1{{'T' does not have a member type named 'Assocp2'; did you mean 'AssocP2'?}}{{39-46=AssocP2}}
func typoAssoc4<T : P2>(_: T) where T.Assocp2.assoc : P3 {}
+
+// CHECK-GENERIC-LABEL: .typoAssoc4@
+// CHECK-GENERIC-NEXT: Requirements:
+// CHECK-GENERIC-NEXT: τ_0_0 : P2 [τ_0_0: Explicit @ {{.*}}:21]
+// CHECK-GENERIC-NEXT: τ_0_0[.P2].AssocP2 : P1 [τ_0_0: Explicit @ {{.*}}:21 -> Protocol requirement (via Self.AssocP2 in P2)
+// CHECK-GENERIC-NEXT: Potential archetypes
+
// <rdar://problem/19620340>
func typoFunc1<T : P1>(x: TypoType) { // expected-error{{use of undeclared type 'TypoType'}}
diff --git a/test/Generics/protocol_type_aliases.swift b/test/Generics/protocol_type_aliases.swift
index 9c083d4..afb2661 100644
--- a/test/Generics/protocol_type_aliases.swift
+++ b/test/Generics/protocol_type_aliases.swift
@@ -14,6 +14,10 @@
}
// CHECK-LABEL: .requirementOnNestedTypeAlias@
+// CHECK-NEXT: Requirements:
+// CHECK-NEXT: τ_0_0 : Q [τ_0_0: Explicit @ 22:51]
+// CHECK-NEXT: τ_0_0[.Q].B : P [τ_0_0: Explicit @ 22:51 -> Protocol requirement (via Self.B in Q)
+// CHECK-NEXT: τ_0_0[.Q].B[.P].A == Int [τ_0_0[.Q].B[.P].X: Explicit @ 22:62]
// CHECK: Canonical generic signature: <τ_0_0 where τ_0_0 : Q, τ_0_0.B.A == Int>
func requirementOnNestedTypeAlias<T>(_: T) where T: Q, T.B.X == Int {}
@@ -29,10 +33,20 @@
}
// CHECK-LABEL: .requirementOnConcreteNestedTypeAlias@
+// CHECK-NEXT: Requirements:
+// CHECK-NEXT: τ_0_0 : Q2 [τ_0_0: Explicit @ 42:59]
+// CHECK-NEXT: τ_0_0[.Q2].B : P2 [τ_0_0: Explicit @ 42:59 -> Protocol requirement (via Self.B in Q2)
+// CHECK-NEXT: τ_0_0[.Q2].C == S<T.B.A> [τ_0_0[.Q2].C: Explicit]
+// CHECK-NEXT: τ_0_0[.Q2].B[.P2].X == S<T.B.A> [τ_0_0[.Q2].B[.P2].X: Concrete type binding]
// CHECK: Canonical generic signature: <τ_0_0 where τ_0_0 : Q2, τ_0_0.C == S<τ_0_0.B.A>>
func requirementOnConcreteNestedTypeAlias<T>(_: T) where T: Q2, T.C == T.B.X {}
// CHECK-LABEL: .concreteRequirementOnConcreteNestedTypeAlias@
+// CHECK-NEXT: Requirements:
+// CHECK-NEXT: τ_0_0 : Q2 [τ_0_0: Explicit @ 51:67]
+// CHECK-NEXT: τ_0_0[.Q2].B : P2 [τ_0_0: Explicit @ 51:67 -> Protocol requirement (via Self.B in Q2)
+// CHECK-NEXT: τ_0_0[.Q2].C == τ_0_0[.Q2].B[.P2].A [τ_0_0[.Q2].C: Explicit]
+// CHECK-NEXT: τ_0_0[.Q2].B[.P2].X == S<T.B.A> [τ_0_0[.Q2].B[.P2].X: Concrete type binding]
// CHECK: Canonical generic signature: <τ_0_0 where τ_0_0 : Q2, τ_0_0.C == τ_0_0.B.A>
func concreteRequirementOnConcreteNestedTypeAlias<T>(_: T) where T: Q2, S<T.C> == T.B.X {}
diff --git a/test/Generics/requirement_inference.swift b/test/Generics/requirement_inference.swift
index 391c9b4..755d24d 100644
--- a/test/Generics/requirement_inference.swift
+++ b/test/Generics/requirement_inference.swift
@@ -54,9 +54,11 @@
func p1() {}
}
-class Box<T : Fox, U> {
+class Box<T : Fox> {
+// CHECK-LABEL: .unpack@
+// CHECK-NEXT: Requirements:
+// CHECK-NEXT: τ_0_0 : Fox [τ_0_0: Explicit]
func unpack(_ x: X1<T>) {}
- func unpackFail(_ X: X1<U>) { } // expected-error{{type 'U' does not conform to protocol 'P1'}}
}
// ----------------------------------------------------------------------------
@@ -72,14 +74,16 @@
struct V<T : Canidae> {}
// CHECK-LABEL: .inferSuperclassRequirement1@
-// CHECK: Canonical generic signature: <τ_0_0 where τ_0_0 : Canidae>
+// CHECK-NEXT: Requirements:
+// CHECK-NEXT: τ_0_0 : Canidae
func inferSuperclassRequirement1<T : Carnivora>(
_ v: V<T>) {}
// expected-warning@-2{{redundant superclass constraint 'T' : 'Carnivora'}}
// expected-note@-2{{superclass constraint 'T' : 'Canidae' inferred from type here}}
// CHECK-LABEL: .inferSuperclassRequirement2@
-// CHECK: Canonical generic signature: <τ_0_0 where τ_0_0 : Canidae>
+// CHECK-NEXT: Requirements:
+// CHECK-NEXT: τ_0_0 : Canidae
func inferSuperclassRequirement2<T : Canidae>(_ v: U<T>) {}
// ----------------------------------------------------------------------------
@@ -108,17 +112,33 @@
struct Model_P3_P4_Eq<T : P3, U : P4> where T.P3Assoc == U.P4Assoc {}
-func inferSameType1<T, U>(_ x: Model_P3_P4_Eq<T, U>) {
- let u: U.P4Assoc? = nil
- let _: T.P3Assoc? = u!
-}
+// CHECK-LABEL: .inferSameType1@
+// CHECK-NEXT: Requirements:
+// CHECK-NEXT: τ_0_0 : P3 [τ_0_0: Inferred @ {{.*}}:32]
+// CHECK-NEXT: τ_0_1 : P4 [τ_0_1: Inferred @ {{.*}}:32]
+// CHECK-NEXT: τ_0_0[.P3].P3Assoc : P1 [τ_0_1: Inferred @ {{.*}}:32 -> Protocol requirement (via Self.P4Assoc in P4)
+// CHECK-NEXT: τ_0_0[.P3].P3Assoc : P2 [τ_0_0: Inferred @ {{.*}}:32 -> Protocol requirement (via Self.P3Assoc in P3)
+// FIXME: τ_0_0[.P3].P3Assoc == τ_0_1[.P4].P4Assoc [τ_0_0: Inferred]
+func inferSameType1<T, U>(_ x: Model_P3_P4_Eq<T, U>) { }
+// CHECK-LABEL: .inferSameType2@
+// CHECK-NEXT: Requirements:
+// CHECK-NEXT: τ_0_0 : P3 [τ_0_0: Explicit @ {{.*}}:25]
+// CHECK-NEXT: τ_0_1 : P4 [τ_0_1: Explicit @ {{.*}}:33]
+// CHECK-NEXT: τ_0_0[.P3].P3Assoc : P1 [τ_0_1: Explicit @ {{.*}}:33 -> Protocol requirement (via Self.P4Assoc in P4)
+// CHECK-NEXT: τ_0_0[.P3].P3Assoc : P2 [τ_0_0: Explicit @ {{.*}}:25 -> Protocol requirement (via Self.P3Assoc in P3)
+// CHECK-NEXT: τ_0_0[.P3].P3Assoc == τ_0_1[.P4].P4Assoc [τ_0_0[.P3].P3Assoc: Explicit]
func inferSameType2<T : P3, U : P4>(_: T, _: U) where U.P4Assoc : P2, T.P3Assoc == U.P4Assoc {}
// expected-warning@-1{{redundant conformance constraint 'T.P3Assoc': 'P2'}}
// expected-note@-2{{conformance constraint 'T.P3Assoc': 'P2' implied here}}
-func inferSameType3<T : PCommonAssoc1>(_: T) where T.CommonAssoc : P1, T : PCommonAssoc2 {
-}
+// CHECK-LABEL: .inferSameType3@
+// CHECK-NEXT: Requirements:
+// CHECK-NEXT: τ_0_0 : PCommonAssoc1 [τ_0_0: Explicit @ {{.*}}:25]
+// CHECK-NEXT: τ_0_0 : PCommonAssoc2 [τ_0_0: Explicit @ {{.*}}:74]
+// CHECK-NEXT: τ_0_0[.PCommonAssoc1].CommonAssoc : P1 [τ_0_0[.PCommonAssoc1].CommonAssoc: Explicit @ {{.*}}:66]
+// CHECK-NEXT: Potential archetypes
+func inferSameType3<T : PCommonAssoc1>(_: T) where T.CommonAssoc : P1, T : PCommonAssoc2 {}
protocol P5 {
associatedtype Element
@@ -132,7 +152,7 @@
associatedtype AssocP7: P6
}
-// CHECK-LABEL: P7@
+// CHECK-LABEL: P7.nestedSameType1()@
// CHECK: Canonical generic signature: <τ_0_0 where τ_0_0 : P7, τ_0_0.AssocP6.Element : P6, τ_0_0.AssocP6.Element == τ_0_0.AssocP7.AssocP6.Element>
extension P7 where AssocP6.Element : P6, // expected-note{{conformance constraint 'Self.AssocP6.Element': 'P6' written here}}
AssocP7.AssocP6.Element : P6, // expected-warning{{redundant conformance constraint 'Self.AssocP6.Element': 'P6'}}
@@ -167,7 +187,7 @@
// Note: a standard-library-based stress test to make sure we don't inject
// any additional requirements.
-// CHECK-LABEL: RangeReplaceableCollection
+// CHECK-LABEL: RangeReplaceableCollection.f()@
// CHECK: Canonical generic signature: <τ_0_0 where τ_0_0 : MutableCollection, τ_0_0 : RangeReplaceableCollection, τ_0_0.SubSequence == MutableRangeReplaceableSlice<τ_0_0>>
extension RangeReplaceableCollection where
Self: MutableCollection,
diff --git a/test/Generics/superclass_constraint.swift b/test/Generics/superclass_constraint.swift
index b27d7af..16ed23b 100644
--- a/test/Generics/superclass_constraint.swift
+++ b/test/Generics/superclass_constraint.swift
@@ -66,7 +66,18 @@
typealias T = C
}
+extension P2 where Self.T : C {
+ // CHECK: superclass_constraint.(file).P2.concreteTypeWitnessViaSuperclass1
+ // CHECK: Generic signature: <Self where Self : P2, Self.T : C>
+ // CHECK: Canonical generic signature: <τ_0_0 where τ_0_0 : P2, τ_0_0.T : C>
+ func concreteTypeWitnessViaSuperclass1(x: Self.T.T) {}
+}
+
// CHECK: superclassConformance1
+// CHECK: Requirements:
+// CHECK-NEXT: τ_0_0 : C [τ_0_0: Explicit @ {{.*}}:11]
+// CHECK-NEXT: τ_0_0 : _NativeClass [τ_0_0: Explicit @ {{.*}}:11 -> Derived]
+// CHECK-NEXT: τ_0_0 : P3 [τ_0_0: Explicit @ {{.*}}:11 -> Superclass (C: P3)]
// CHECK: Canonical generic signature: <τ_0_0 where τ_0_0 : C>
func superclassConformance1<T>(t: T)
where T : C, // expected-note{{conformance constraint 'T': 'P3' implied here}}
@@ -75,6 +86,10 @@
// CHECK: superclassConformance2
+// CHECK: Requirements:
+// CHECK-NEXT: τ_0_0 : C [τ_0_0: Explicit @ {{.*}}:11]
+// CHECK-NEXT: τ_0_0 : _NativeClass [τ_0_0: Explicit @ {{.*}}:11 -> Derived]
+// CHECK-NEXT: τ_0_0 : P3 [τ_0_0: Explicit @ {{.*}}:11 -> Superclass (C: P3)]
// CHECK: Canonical generic signature: <τ_0_0 where τ_0_0 : C>
func superclassConformance2<T>(t: T)
where T : C, // expected-note{{conformance constraint 'T': 'P3' implied here}}
@@ -85,6 +100,10 @@
class C2 : C, P4 { }
// CHECK: superclassConformance3
+// CHECK: Requirements:
+// CHECK-NEXT: τ_0_0 : C2 [τ_0_0: Explicit @ {{.*}}:61]
+// CHECK-NEXT: τ_0_0 : _NativeClass [τ_0_0: Explicit @ {{.*}}:46 -> Derived]
+// CHECK-NEXT: τ_0_0 : P4 [τ_0_0: Explicit @ {{.*}}:61 -> Superclass (C2: P4)]
// CHECK: Canonical generic signature: <τ_0_0 where τ_0_0 : C2>
func superclassConformance3<T>(t: T) where T : C, T : P4, T : C2 {}
// expected-warning@-1{{redundant superclass constraint 'T' : 'C'}}
diff --git a/test/Sema/availability_versions.swift b/test/Sema/availability_versions.swift
index e96f91a..5f1da36 100644
--- a/test/Sema/availability_versions.swift
+++ b/test/Sema/availability_versions.swift
@@ -1345,7 +1345,7 @@
// Protocol Conformances
protocol ProtocolWithRequirementMentioningUnavailable {
- // expected-note@-1 4{{add @available attribute to enclosing protocol}}
+ // expected-note@-1 6{{add @available attribute to enclosing protocol}}
func hasUnavailableParameter(_ p: ClassAvailableOn10_51) // expected-error * {{'ClassAvailableOn10_51' is only available on OS X 10.51 or newer}}
// expected-note@-1 * {{add @available attribute to enclosing instance method}}
diff --git a/validation-test/compiler_crashers_fixed/28783-hasconformanceinsignature-inprotocol-getrequirementsignature-subjecttype-conform.swift b/validation-test/compiler_crashers/28783-hasconformanceinsignature-inprotocol-getrequirementsignature-subjecttype-conform.swift
similarity index 88%
rename from validation-test/compiler_crashers_fixed/28783-hasconformanceinsignature-inprotocol-getrequirementsignature-subjecttype-conform.swift
rename to validation-test/compiler_crashers/28783-hasconformanceinsignature-inprotocol-getrequirementsignature-subjecttype-conform.swift
index 1900ef7..bcd5e1c 100644
--- a/validation-test/compiler_crashers_fixed/28783-hasconformanceinsignature-inprotocol-getrequirementsignature-subjecttype-conform.swift
+++ b/validation-test/compiler_crashers/28783-hasconformanceinsignature-inprotocol-getrequirementsignature-subjecttype-conform.swift
@@ -6,7 +6,7 @@
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
// REQUIRES: asserts
-// RUN: not %target-swift-frontend %s -emit-ir
+// RUN: not --crash %target-swift-frontend %s -emit-ir
class a:A
protocol A:a{
protocol A{struct a{var f:A