diff --git a/include/swift/AST/ProtocolConformance.h b/include/swift/AST/ProtocolConformance.h index 218c1a8b9ab..15221819ae0 100644 --- a/include/swift/AST/ProtocolConformance.h +++ b/include/swift/AST/ProtocolConformance.h @@ -40,7 +40,7 @@ enum class AllocationArena; /// \brief Type substitution mapping from substitutable types to their /// replacements. -typedef llvm::DenseMap TypeSubstitutionMap; +typedef llvm::DenseMap TypeSubstitutionMap; /// Map from non-type requirements to the corresponding conformance witnesses. typedef llvm::DenseMap WitnessMap; diff --git a/include/swift/AST/Type.h b/include/swift/AST/Type.h index 084ee398e7a..c58a0432eff 100644 --- a/include/swift/AST/Type.h +++ b/include/swift/AST/Type.h @@ -43,7 +43,7 @@ class TypeWalker; /// \brief Type substitution mapping from substitutable types to their /// replacements. -typedef llvm::DenseMap TypeSubstitutionMap; +typedef llvm::DenseMap TypeSubstitutionMap; /// Type - This is a simple value object that contains a pointer to a type /// class. This is potentially sugared. We use this throughout the codebase diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index 8dfaf36d754..dc7e9d67fe0 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -1640,10 +1640,6 @@ GenericParamList::getSubstitutionMap(ArrayRef Subs) const { auto sub = Subs.front(); Subs = Subs.slice(1); - // Only substitute primary archetypes. - if (!arch->isPrimary()) - continue; - map.insert({arch, sub.Replacement}); } @@ -1757,15 +1753,24 @@ GenericSignature::getSubstitutionMap(ArrayRef args) const { return subs; } + // Seed the type map with pre-existing substitutions. + for (auto sub : args) { + subs[sub.Archetype] = sub.Replacement; + } + for (auto depTy : getAllDependentTypes()) { auto replacement = args.front().Replacement; args = args.slice(1); - // FIXME: DependentMemberTypes aren't SubstitutableTypes. - if (auto subTy = depTy->getAs()) + + if (auto subTy = depTy->getAs()) { subs[subTy] = replacement; + } + else if (auto dTy = depTy->getAs()) { + subs[dTy] = replacement; + } } - assert(args.empty() && "did not use all substitutions?!"); + assert(args.empty() && "did not use all substitutions?!"); return subs; } @@ -1896,8 +1901,15 @@ Type Type::subst(Module *module, TypeSubstitutionMap &substitutions, .subst(module, substitutions, ignoreMissing, resolver); // Resolve the member relative to the substituted base. - if (Type r = depMemTy->substBaseType(module, newBase, resolver)) + if (Type r = depMemTy->substBaseType(module, newBase, resolver)) { + + // Substitute archtypes for generic type parameters to prevent + // dependent types from leaking. + if (auto GTPT = r->getAs()) { + return GTPT->getDecl()->getArchetype(); + } return r; + } return failed(type); } diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp index 08fe7215e8c..cdbf00375c0 100644 --- a/lib/Sema/CSSimplify.cpp +++ b/lib/Sema/CSSimplify.cpp @@ -566,8 +566,8 @@ ConstraintSystem::matchTypes(Type type1, Type type2, TypeMatchKind kind, // Add a new constraint between these types. We consider the current // type-matching problem to the "solved" by this addition, because // this new constraint will be solved at a later point. - // Obviously, this must not happen at the top level, or the algorithm - // would not terminate. + // Obviously, this must not happen at the top level, or the + // algorithm would not terminate. addConstraint(getConstraintKind(kind), rep1, rep2, getConstraintLocator(locator)); return SolutionKind::Solved; diff --git a/lib/Sema/ConstraintSystem.cpp b/lib/Sema/ConstraintSystem.cpp index 588cc0a59ce..41d4710b736 100644 --- a/lib/Sema/ConstraintSystem.cpp +++ b/lib/Sema/ConstraintSystem.cpp @@ -1189,10 +1189,17 @@ void ConstraintSystem::resolveOverload(ConstraintLocator *locator, // in the case of a conformance check against an associated type rooted off of // "Self"), we'll need to open the type up so as not to short-circuit the // binding constraint against the already bound overload type. - if ((choice.getKind() == OverloadChoiceKind::TypeDecl) && - refType->getAs()) { + if (refType->isDependentType()) { + openedFullType = openType(openedFullType, + choice.getDecl()-> + getPotentialGenericDeclContext()); refType = openType(refType, choice.getDecl()->getPotentialGenericDeclContext()); + + if (auto FT = openedFullType->getAs()) { + auto returnType = FT->getResult(); + addConstraint(ConstraintKind::Bind, returnType, refType); + } } // Add the type binding constraint. diff --git a/lib/Sema/TypeCheckGeneric.cpp b/lib/Sema/TypeCheckGeneric.cpp index b56b7389689..8b988fc6efa 100644 --- a/lib/Sema/TypeCheckGeneric.cpp +++ b/lib/Sema/TypeCheckGeneric.cpp @@ -824,9 +824,11 @@ bool TypeChecker::checkSubstitutions(TypeSubstitutionMap &Substitutions, // Find all of the primary archetypes and enter them into the archetype // stack. for (const auto &sub : Substitutions) { - auto archetype = sub.first->getArchetype(); - if (archetype->isPrimary() && knownArchetypes.insert(archetype)) - archetypeStack.push_back(archetype); + if (auto subTy = sub.first->getAs()) { + auto archetype = subTy->getArchetype(); + if (archetype->isPrimary() && knownArchetypes.insert(archetype)) + archetypeStack.push_back(archetype); + } } // Check that each of the replacements for the archetypes conform diff --git a/lib/Sema/TypeCheckPattern.cpp b/lib/Sema/TypeCheckPattern.cpp index d5e9a770ba3..a6adde48c75 100644 --- a/lib/Sema/TypeCheckPattern.cpp +++ b/lib/Sema/TypeCheckPattern.cpp @@ -352,8 +352,8 @@ public: // then required to have keywords for every argument that name properties // of the type. Pattern *visitCallExpr(CallExpr *ce) { - DependentGenericTypeResolver resolver; - + PartialGenericTypeToArchetypeResolver resolver(TC); + SmallVector components; if (!ExprToIdentTypeRepr(components, TC.Context).visit(ce->getFn())) return nullptr;