diff --git a/include/swift/AST/GenericSignature.h b/include/swift/AST/GenericSignature.h index 800bff85591ab..fdd024bce3fc5 100644 --- a/include/swift/AST/GenericSignature.h +++ b/include/swift/AST/GenericSignature.h @@ -141,6 +141,12 @@ class alignas(1 << TypeAlignInBits) GenericSignature final void getSubstitutionMap(ArrayRef args, SubstitutionMap &subMap) const; + /// Build an interface type substitution map from a type substitution function + /// and conformance lookup function. + SubstitutionMap + getSubstitutionMap(TypeSubstitutionFn subs, + LookupConformanceFn lookupConformance) const; + using GenericFunction = auto(CanType canType, Type conformingReplacementType, ProtocolType *conformedProtocol) ->Optional; diff --git a/include/swift/AST/Type.h b/include/swift/AST/Type.h index 16c0015544d93..1809402f8da1f 100644 --- a/include/swift/AST/Type.h +++ b/include/swift/AST/Type.h @@ -249,21 +249,6 @@ class Type { }); } - /// Replace references to substitutable types with new, concrete types and - /// return the substituted result. - /// - /// \param module The module to use for conformance lookups. - /// - /// \param substitutions The mapping from substitutable types to their - /// replacements. - /// - /// \param options Options that affect the substitutions. - /// - /// \returns the substituted type, or a null type if an error occurred. - Type subst(ModuleDecl *module, - const TypeSubstitutionMap &substitutions, - SubstOptions options = None) const; - /// Replace references to substitutable types with new, concrete types and /// return the substituted result. /// diff --git a/include/swift/AST/Types.h b/include/swift/AST/Types.h index f1eceddaa1162..762aa7d7bab76 100644 --- a/include/swift/AST/Types.h +++ b/include/swift/AST/Types.h @@ -873,6 +873,10 @@ class alignas(1 << TypeAlignInBits) TypeBase { /// the context of the extension above will produce substitutions T /// -> Int and U -> String suitable for mapping the type of /// \c SomeArray. + SubstitutionMap getContextSubstitutionMap(ModuleDecl *module, + const DeclContext *dc); + + /// Deprecated version of the above. TypeSubstitutionMap getContextSubstitutions(const DeclContext *dc); /// Get the substitutions to apply to the type of the given member as seen @@ -880,6 +884,10 @@ class alignas(1 << TypeAlignInBits) TypeBase { /// /// If the member has its own generic parameters, they will remain unchanged /// by the substitution. + SubstitutionMap getMemberSubstitutionMap(ModuleDecl *module, + const ValueDecl *member); + + /// Deprecated version of the above. TypeSubstitutionMap getMemberSubstitutions(const ValueDecl *member); /// Retrieve the type of the given member as seen through the given base @@ -903,16 +911,13 @@ class alignas(1 << TypeAlignInBits) TypeBase { /// /// \param member The member whose type we are substituting. /// - /// \param resolver The resolver for lazy type checking, which may be null for - /// a fully-type-checked AST. - /// /// \param memberType The type of the member, in which archetypes will be /// replaced by the generic arguments provided by the base type. If null, /// the member's type will be used. /// /// \returns the resulting member type. Type getTypeOfMember(ModuleDecl *module, const ValueDecl *member, - LazyResolver *resolver, Type memberType = Type()); + Type memberType = Type()); /// Get the type of a superclass member as seen from the subclass, /// substituting generic parameters, dynamic Self return, and the diff --git a/lib/AST/ASTPrinter.cpp b/lib/AST/ASTPrinter.cpp index f68512bf3677e..ff18a13f22929 100644 --- a/lib/AST/ASTPrinter.cpp +++ b/lib/AST/ASTPrinter.cpp @@ -224,19 +224,18 @@ struct SynthesizedExtensionAnalyzer::Implementation { // Get the substitutions from the generic signature of // the extension to the interface types of the base type's // declaration. - TypeSubstitutionMap subMap; - if (!BaseType->isExistentialType()) - subMap = BaseType->getContextSubstitutions(Ext); auto *M = DC->getParentModule(); + SubstitutionMap subMap; + if (!BaseType->isExistentialType()) + subMap = BaseType->getContextSubstitutionMap(M, Ext); assert(Ext->getGenericSignature() && "No generic signature."); for (auto Req : Ext->getGenericSignature()->getRequirements()) { auto Kind = Req.getKind(); - Type First = Req.getFirstType().subst( - M, subMap, SubstOptions()); - Type Second = Req.getSecondType().subst( - M, subMap, SubstOptions()); + Type First = Req.getFirstType().subst(subMap); + Type Second = Req.getSecondType().subst(subMap); + if (!First || !Second) { // Substitution with interface type bases can only fail // if a concrete type fails to conform to a protocol. @@ -874,9 +873,9 @@ class PrintAST : public ASTVisitor { assert(DC->isTypeContext()); // Get the substitutions from our base type. - auto subMap = CurrentType->getContextSubstitutions(DC); auto *M = DC->getParentModule(); - T = T.subst(M, subMap, SubstFlags::DesugarMemberTypes); + auto subMap = CurrentType->getContextSubstitutionMap(M, DC); + T = T.subst(subMap, SubstFlags::DesugarMemberTypes); } printType(T); @@ -995,9 +994,9 @@ class PrintAST : public ASTVisitor { Type OldType = CurrentType; if (CurrentType && (Old != nullptr || Options.PrintAsMember)) { if (auto *NTD = dyn_cast(D)) { - CurrentType = NTD->getDeclaredInterfaceType().subst( - Options.CurrentModule, - CurrentType->getContextSubstitutions(NTD->getDeclContext())); + auto Subs = CurrentType->getContextSubstitutionMap( + Options.CurrentModule, NTD->getDeclContext()); + CurrentType = NTD->getDeclaredInterfaceType().subst(Subs); } } @@ -1268,17 +1267,19 @@ void PrintAST::printSingleDepthOfGenericSignature( bool printParams = (flags & PrintParams); bool printRequirements = (flags & PrintRequirements); - TypeSubstitutionMap subMap; - ModuleDecl *M = nullptr; - + SubstitutionMap subMap; if (CurrentType) { if (!CurrentType->isExistentialType()) { auto *DC = Current->getInnermostDeclContext()->getInnermostTypeContext(); - subMap = CurrentType->getContextSubstitutions(DC); - M = DC->getParentModule(); + auto *M = DC->getParentModule(); + subMap = CurrentType->getContextSubstitutionMap(M, DC); } } + auto substParam = [&](Type param) -> Type { + return param.subst(subMap); + }; + if (printParams) { // Print the generic parameters. Printer << "<"; @@ -1290,7 +1291,7 @@ void PrintAST::printSingleDepthOfGenericSignature( Printer << ", "; if (!subMap.empty()) { - if (auto argTy = Type(param).subst(M, subMap)) + if (auto argTy = substParam(param)) printType(argTy); else printType(param); @@ -1322,10 +1323,10 @@ void PrintAST::printSingleDepthOfGenericSignature( } if (!subMap.empty()) { - if (Type subFirst = first.subst(M, subMap)) + if (Type subFirst = substParam(first)) first = subFirst; if (second) { - if (Type subSecond = second.subst(M, subMap)) + if (Type subSecond = substParam(second)) second = subSecond; if (!(first->is() || first->isTypeParameter()) && !(second->is() || second->isTypeParameter())) diff --git a/lib/AST/GenericEnvironment.cpp b/lib/AST/GenericEnvironment.cpp index a76c156ab6852..521f9a8210d5e 100644 --- a/lib/AST/GenericEnvironment.cpp +++ b/lib/AST/GenericEnvironment.cpp @@ -332,15 +332,10 @@ Type GenericEnvironment::getSugaredType(Type type) const { ArrayRef GenericEnvironment::getForwardingSubstitutions() const { - auto lookupConformanceFn = - [&](CanType original, Type replacement, ProtocolType *protoType) - -> Optional { - return ProtocolConformanceRef(protoType->getDecl()); - }; - SmallVector result; getGenericSignature()->getSubstitutions(QueryInterfaceTypeSubstitutions(this), - lookupConformanceFn, result); + MakeAbstractConformanceForGenericType(), + result); return getGenericSignature()->getASTContext().AllocateCopy(result); } diff --git a/lib/AST/GenericSignature.cpp b/lib/AST/GenericSignature.cpp index b1d4aa58d4b9e..8109743fd9749 100644 --- a/lib/AST/GenericSignature.cpp +++ b/lib/AST/GenericSignature.cpp @@ -347,6 +347,62 @@ GenericSignature::getSubstitutionMap(ArrayRef subs, assert(subs.empty() && "did not use all substitutions?!"); } +SubstitutionMap +GenericSignature:: +getSubstitutionMap(TypeSubstitutionFn subs, + GenericSignature::LookupConformanceFn lookupConformance) const { + SubstitutionMap subMap; + + // Enumerate all of the requirements that require substitution. + enumeratePairedRequirements([&](Type depTy, ArrayRef reqs) { + auto canTy = depTy->getCanonicalType(); + + // Compute the replacement type. + Type currentReplacement = depTy.subst(subs, lookupConformance, + SubstFlags::UseErrorType); + if (auto substTy = dyn_cast(canTy)) + subMap.addSubstitution(substTy, currentReplacement); + + // Collect the conformances. + for (auto req: reqs) { + assert(req.getKind() == RequirementKind::Conformance); + auto protoType = req.getSecondType()->castTo(); + if (auto conformance = lookupConformance(canTy, + currentReplacement, + protoType)) { + subMap.addConformance(canTy, *conformance); + } + } + + return false; + }); + + for (auto reqt : getRequirements()) { + if (reqt.getKind() != RequirementKind::SameType) + continue; + + auto first = reqt.getFirstType(); + auto second = reqt.getSecondType(); + + if (!first->isTypeParameter() || !second->isTypeParameter()) + continue; + + if (auto *firstMemTy = first->getAs()) { + subMap.addParent(second->getCanonicalType(), + firstMemTy->getBase()->getCanonicalType(), + firstMemTy->getAssocType()); + } + + if (auto *secondMemTy = second->getAs()) { + subMap.addParent(first->getCanonicalType(), + secondMemTy->getBase()->getCanonicalType(), + secondMemTy->getAssocType()); + } + } + + return subMap; +} + SmallVector GenericSignature::getAllDependentTypes() const { SmallVector result; enumeratePairedRequirements([&](Type type, ArrayRef) { @@ -409,13 +465,9 @@ getSubstitutions(TypeSubstitutionFn subs, void GenericSignature:: getSubstitutions(const SubstitutionMap &subMap, SmallVectorImpl &result) const { - auto lookupConformanceFn = - [&](CanType original, Type replacement, ProtocolType *protoType) - -> Optional { - return subMap.lookupConformance(original, protoType->getDecl()); - }; - - getSubstitutions(subMap.getMap(), lookupConformanceFn, result); + getSubstitutions(subMap.getMap(), + LookUpConformanceInSubstitutionMap(subMap), + result); } bool GenericSignature::requiresClass(Type type, ModuleDecl &mod) { diff --git a/lib/AST/LookupVisibleDecls.cpp b/lib/AST/LookupVisibleDecls.cpp index f35e9458e2be0..07c9b39870f58 100644 --- a/lib/AST/LookupVisibleDecls.cpp +++ b/lib/AST/LookupVisibleDecls.cpp @@ -732,8 +732,8 @@ class OverrideFilteringConsumer : public VisibleDeclConsumer { auto FoundSignature = VD->getOverloadSignature(); if (FoundSignature.InterfaceType && shouldSubst) { - auto subs = BaseTy->getMemberSubstitutions(VD); - if (auto CT = FoundSignature.InterfaceType.subst(M, subs, None)) + auto subs = BaseTy->getMemberSubstitutionMap(M, VD); + if (auto CT = FoundSignature.InterfaceType.subst(subs)) FoundSignature.InterfaceType = CT->getCanonicalType(); } @@ -748,8 +748,8 @@ class OverrideFilteringConsumer : public VisibleDeclConsumer { auto OtherSignature = OtherVD->getOverloadSignature(); if (OtherSignature.InterfaceType && shouldSubst) { - auto subs = BaseTy->getMemberSubstitutions(OtherVD); - if (auto CT = OtherSignature.InterfaceType.subst(M, subs, None)) + auto subs = BaseTy->getMemberSubstitutionMap(M, OtherVD); + if (auto CT = OtherSignature.InterfaceType.subst(subs)) OtherSignature.InterfaceType = CT->getCanonicalType(); } diff --git a/lib/AST/Module.cpp b/lib/AST/Module.cpp index 4c65ea988db7d..5bdd1e247d8da 100644 --- a/lib/AST/Module.cpp +++ b/lib/AST/Module.cpp @@ -634,31 +634,9 @@ TypeBase::gatherAllSubstitutions(ModuleDecl *module, } } - auto lookupConformanceFn = - [&](CanType original, Type replacement, ProtocolType *protoType) - -> Optional { - auto *proto = protoType->getDecl(); - - // If the type is a type variable or is dependent, just fill in empty - // conformances. - if (replacement->isTypeVariableOrMember() || - replacement->isTypeParameter()) - return ProtocolConformanceRef(proto); - - // Otherwise, try to find the conformance. - auto conforms = module->lookupConformance(replacement, proto, resolver); - if (conforms) - return *conforms; - - // FIXME: Should we ever end up here? - // We should return None and let getSubstitutions handle the error - // if we do. - return ProtocolConformanceRef(proto); - }; - SmallVector result; genericSig->getSubstitutions(substitutions, - lookupConformanceFn, + LookUpConformanceInModule(module), result); // Before recording substitutions, make sure we didn't end up doing it @@ -762,9 +740,8 @@ ModuleDecl::lookupConformance(Type type, ProtocolDecl *protocol, } // Type variables have trivial conformances. - if (type->isTypeVariableOrMember()) { + if (type->isTypeVariableOrMember()) return ProtocolConformanceRef(protocol); - } // UnresolvedType is a placeholder for an unknown type used when generating // diagnostics. We consider it to conform to all protocols, since the diff --git a/lib/AST/SubstitutionMap.cpp b/lib/AST/SubstitutionMap.cpp index abe0c5ee9b13c..070e6a70e6ff5 100644 --- a/lib/AST/SubstitutionMap.cpp +++ b/lib/AST/SubstitutionMap.cpp @@ -93,12 +93,12 @@ Optional SubstitutionMap::forEachConformance( return found; } } else { - auto sub = conformance.getConcrete()->getTypeWitnessSubstAndDecl( + auto sub = conformance.getConcrete()->getTypeWitnessSubstAndDecl( protoAssocType, nullptr).first; - for (auto subConformance : sub.getConformances()) { - if (auto found = fn(subConformance)) - return found; - } + for (auto subConformance : sub.getConformances()) { + if (auto found = fn(subConformance)) + return found; + } } } @@ -130,7 +130,8 @@ SubstitutionMap::lookupConformance( CanType type, ProtocolDecl *proto, llvm::SmallPtrSetImpl *visitedParents) const { // Local function to either record an abstract conformance or return a - // concrete conformance. This allows us to + // concrete conformance. This allows us to check multiple parents and + // find the most specific conformance that applies. Optional abstractConformance; auto recordOrReturn = [&](ProtocolConformanceRef conformance) -> Optional { @@ -232,8 +233,7 @@ SubstitutionMap::getOverrideSubstitutions(const ClassDecl *baseClass, auto baseClassTy = derivedClassTy->getSuperclassForDecl(baseClass, resolver); auto *M = baseClass->getParentModule(); - auto subs = baseClassTy->gatherAllSubstitutions(M, resolver); - genericSig->getSubstitutionMap(subs, subMap); + subMap = baseClassTy->getContextSubstitutionMap(M, baseClass); minDepth = genericSig->getGenericParams().back()->getDepth() + 1; } diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index 81d7441db78bf..d24735758897d 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -2909,9 +2909,8 @@ static Type getMemberForBaseType(LookupConformanceFn lookupConformances, LazyResolver *resolver = substBase->getASTContext().getLazyResolver(); if (assocType) { auto proto = assocType->getProtocol(); - // FIXME: Introduce substituted type node here? Optional conformance - = lookupConformances(origBase ? origBase->getCanonicalType() : CanType(), + = lookupConformances(origBase->getCanonicalType(), substBase, proto->getDeclaredType()); @@ -2950,6 +2949,9 @@ Optional LookUpConformanceInModule::operator()(CanType dependentType, Type conformingReplacementType, ProtocolType *conformedProtocol) const { + if (conformingReplacementType->isTypeParameter()) + return ProtocolConformanceRef(conformedProtocol->getDecl()); + return M->lookupConformance(conformingReplacementType, conformedProtocol->getDecl(), conformingReplacementType->getASTContext().getLazyResolver()); @@ -2984,7 +2986,7 @@ Type DependentMemberType::substBaseType(Type substBase, substBase->hasTypeParameter()) return this; - return getMemberForBaseType(lookupConformance, Type(), substBase, + return getMemberForBaseType(lookupConformance, getBase(), substBase, getAssocType(), getName(), None); } @@ -3085,15 +3087,6 @@ static Type substType(Type derivedType, }); } -Type Type::subst(ModuleDecl *module, - const TypeSubstitutionMap &substitutions, - SubstOptions options) const { - return substType(*this, - QueryTypeSubstitutionMap{substitutions}, - LookUpConformanceInModule(module), - options); -} - Type Type::subst(const SubstitutionMap &substitutions, SubstOptions options) const { return substType(*this, @@ -3213,6 +3206,16 @@ TypeSubstitutionMap TypeBase::getContextSubstitutions(const DeclContext *dc) { return substitutions; } +SubstitutionMap TypeBase::getContextSubstitutionMap( + ModuleDecl *module, const DeclContext *dc) { + auto *genericSig = dc->getGenericSignatureOfContext(); + if (genericSig == nullptr) + return SubstitutionMap(); + return genericSig->getSubstitutionMap( + QueryTypeSubstitutionMap{getContextSubstitutions(dc)}, + LookUpConformanceInModule(module)); +} + TypeSubstitutionMap TypeBase::getMemberSubstitutions(const ValueDecl *member) { auto *memberDC = member->getDeclContext(); @@ -3241,16 +3244,27 @@ TypeSubstitutionMap TypeBase::getMemberSubstitutions(const ValueDecl *member) { return substitutions; } +SubstitutionMap TypeBase::getMemberSubstitutionMap( + ModuleDecl *module, const ValueDecl *member) { + auto *genericSig = member->getInnermostDeclContext() + ->getGenericSignatureOfContext(); + if (genericSig == nullptr) + return SubstitutionMap(); + return genericSig->getSubstitutionMap( + QueryTypeSubstitutionMap{getMemberSubstitutions(member)}, + LookUpConformanceInModule(module)); +} + Type TypeBase::getTypeOfMember(ModuleDecl *module, const ValueDecl *member, - LazyResolver *resolver, Type memberType) { + Type memberType) { // If no member type was provided, use the member's type. if (!memberType) memberType = member->getInterfaceType(); assert(memberType); - auto substitutions = getMemberSubstitutions(member); - return memberType.subst(module, substitutions, SubstFlags::UseErrorType); + auto substitutions = getMemberSubstitutionMap(module, member); + return memberType.subst(substitutions, SubstFlags::UseErrorType); } Type TypeBase::adjustSuperclassMemberDeclType(const ValueDecl *baseDecl, diff --git a/lib/ClangImporter/ImportType.cpp b/lib/ClangImporter/ImportType.cpp index 81384b3cd8ce4..46e35e377dc9a 100644 --- a/lib/ClangImporter/ImportType.cpp +++ b/lib/ClangImporter/ImportType.cpp @@ -1861,11 +1861,11 @@ Type ClangImporter::Implementation::importMethodType( // Get the substitutions that we need to access a member of // 'origDC' on 'dc'. auto subs = dc->getDeclaredTypeInContext() - ->getContextSubstitutions(origDC); + ->getContextSubstitutionMap(dc->getParentModule(), origDC); // Apply them to the interface type to produce the final // substituted type. - type = type.subst(dc->getParentModule(), subs); + type = type.subst(subs); } return type; }; @@ -2170,11 +2170,11 @@ Type ClangImporter::Implementation::importAccessorMethodType( // Get the substitutions that we need to access a member of // 'origDC' on 'dc'. auto subs = dc->getDeclaredTypeInContext() - ->getContextSubstitutions(origDC); + ->getContextSubstitutionMap(dc->getParentModule(), origDC); // Apply them to the interface type to produce the final // substituted type. - type = type.subst(dc->getParentModule(), subs); + type = type.subst(subs); } return type; }; diff --git a/lib/IDE/CodeCompletion.cpp b/lib/IDE/CodeCompletion.cpp index 7827d0c0ba2a5..06611b6de579c 100644 --- a/lib/IDE/CodeCompletion.cpp +++ b/lib/IDE/CodeCompletion.cpp @@ -2003,12 +2003,13 @@ class CompletionLookup final : public swift::VisibleDeclConsumer { return T; // For everything else, substitute in the base type. - auto Subs = MaybeNominalType->getMemberSubstitutions(VD); + auto Subs = MaybeNominalType->getMemberSubstitutionMap(M, VD); // Pass in DesugarMemberTypes so that we see the actual // concrete type witnesses instead of type alias types. - T = T.subst(M, Subs, (SubstFlags::DesugarMemberTypes | - SubstFlags::UseErrorType)); + T = T.subst(Subs, + (SubstFlags::DesugarMemberTypes | + SubstFlags::UseErrorType)); } } diff --git a/lib/IRGen/Fulfillment.cpp b/lib/IRGen/Fulfillment.cpp index a7602efaf1f29..b4220cf66b532 100644 --- a/lib/IRGen/Fulfillment.cpp +++ b/lib/IRGen/Fulfillment.cpp @@ -242,7 +242,7 @@ bool FulfillmentMap::searchBoundGenericTypeMetadata(IRGenModule &IGM, GenericTypeRequirements requirements(IGM, type->getDecl()); requirements.enumerateFulfillments( - IGM, type->gatherAllSubstitutions(IGM.getSwiftModule(), nullptr), + IGM, type->getContextSubstitutionMap(IGM.getSwiftModule(), type->getDecl()), [&](unsigned reqtIndex, CanType arg, Optional conf) { // Skip uninteresting type arguments. diff --git a/lib/IRGen/GenFunc.cpp b/lib/IRGen/GenFunc.cpp index 7540c22c4b4c0..4e7913daf2979 100644 --- a/lib/IRGen/GenFunc.cpp +++ b/lib/IRGen/GenFunc.cpp @@ -848,7 +848,8 @@ static llvm::Function *emitPartialApplicationForwarder(IRGenModule &IGM, && "should have substitutions iff original function is generic"); WitnessMetadata witnessMetadata; if (hasPolymorphicParameters(origType)) { - emitPolymorphicArguments(subIGF, origType, substType, subs, + auto subMap = origType->getGenericSignature()->getSubstitutionMap(subs); + emitPolymorphicArguments(subIGF, origType, substType, subMap, &witnessMetadata, polyArgs); } @@ -1169,8 +1170,11 @@ void irgen::emitFunctionPartialApplication(IRGenFunction &IGF, SmallVector argConventions; // Reserve space for polymorphic bindings. + SubstitutionMap subMap; + if (auto genericSig = origType->getGenericSignature()) + subMap = genericSig->getSubstitutionMap(subs); auto bindings = NecessaryBindings::forFunctionInvocations(IGF.IGM, - origType, substType, subs); + origType, substType, subMap); if (!bindings.empty()) { hasSingleSwiftRefcountedContext = No; auto bindingsSize = bindings.getBufferSize(IGF.IGM); diff --git a/lib/IRGen/GenMeta.cpp b/lib/IRGen/GenMeta.cpp index 05302beef69da..331a2aeb2d942 100644 --- a/lib/IRGen/GenMeta.cpp +++ b/lib/IRGen/GenMeta.cpp @@ -208,7 +208,7 @@ namespace { } auto subs = - type->gatherAllSubstitutions(IGF.IGM.getSwiftModule(), nullptr); + type->getContextSubstitutionMap(IGF.IGM.getSwiftModule(), decl); requirements.enumerateFulfillments(IGF.IGM, subs, [&](unsigned reqtIndex, CanType type, Optional conf) { diff --git a/lib/IRGen/GenProto.cpp b/lib/IRGen/GenProto.cpp index 29498d7b79f50..77db344d1bbd6 100644 --- a/lib/IRGen/GenProto.cpp +++ b/lib/IRGen/GenProto.cpp @@ -623,49 +623,6 @@ void irgen::setProtocolWitnessTableName(IRGenModule &IGM, llvm::Value *wtable, wtable->setName(name); } -/// Return the index of the given dependent type in the list of all -/// dependent types. -/// -/// This will be its index in the list of substitutions. -static unsigned getDependentTypeIndex(CanGenericSignature generics, - ModuleDecl &M, CanType type) { - assert(type->isTypeParameter()); - - // Make a pass over all the dependent types. - unsigned index = 0; - for (auto depTy : generics->getAllDependentTypes()) { - if (depTy->isEqual(type)) - return index; - index++; - } - - llvm_unreachable("didn't find dependent type in all-dependent-types list"); -} - -/// Return the index of the given protocol conformance in the list of all -/// protocol conformances for the given dependent type in the given signature. -/// -/// This will be its index in the list of protocol conformances on the -/// dependent type's substitution. -static unsigned -getProtocolConformanceIndex(CanGenericSignature generics, ModuleDecl &M, - CanType type, ProtocolDecl *protocol) { - assert(type->isTypeParameter()); - - // Make a pass over all the dependent types. - unsigned index = 0; - for (auto reqt : generics->getRequirements()) { - if (reqt.getKind() == RequirementKind::Conformance && - reqt.getFirstType()->isEqual(type)) { - if (reqt.getSecondType()->getAnyNominal() == protocol) - return index; - index++; - } - } - - llvm_unreachable("didn't find dependent type in all-dependent-types list"); -} - namespace { /// A concrete witness table, together with its known layout. class WitnessTable { @@ -2037,15 +1994,12 @@ llvm::Value *MetadataPath::followComponent(IRGenFunction &IGF, auto &requirement = requirements.getRequirements()[reqtIndex]; auto module = IGF.getSwiftModule(); - auto generics = generic->getDecl()->getGenericSignatureOfContext() - ->getCanonicalSignature(); - - auto argIndex = - getDependentTypeIndex(generics, *module, requirement.TypeParameter); - Substitution sub = generic->gatherAllSubstitutions(module, nullptr)[argIndex]; + auto subs = generic->getContextSubstitutionMap(module, + generic->getDecl()); + auto sub = requirement.TypeParameter.subst(subs)->getCanonicalType(); // In either case, we need to change the type. - sourceKey.Type = sub.getReplacement()->getCanonicalType(); + sourceKey.Type = sub; // If this is a type argument, we've fully updated sourceKey. if (component.getKind() == Component::Kind::NominalTypeArgument) { @@ -2060,10 +2014,8 @@ llvm::Value *MetadataPath::followComponent(IRGenFunction &IGF, // conformance kind. } else { assert(requirement.Protocol && "index mismatch!"); - auto confIndex = getProtocolConformanceIndex(generics, *module, - requirement.TypeParameter, - requirement.Protocol); - auto conformance = sub.getConformances()[confIndex]; + auto conformance = *subs.lookupConformance(requirement.TypeParameter, + requirement.Protocol); assert(conformance.getRequirement() == requirement.Protocol); sourceKey.Kind = LocalTypeDataKind::forProtocolWitnessTable(conformance); @@ -2339,7 +2291,7 @@ void irgen::emitWitnessTableRefs(IRGenFunction &IGF, } static CanType getSubstSelfType(CanSILFunctionType origFnType, - ArrayRef subs) { + const SubstitutionMap &subs) { // Grab the apparent 'self' type. If there isn't a 'self' type, // we're not going to try to access this anyway. assert(!origFnType->getParameters().empty()); @@ -2366,8 +2318,7 @@ static CanType getSubstSelfType(CanSILFunctionType origFnType, // SIL function type to make that work, which could be managed by having a // "substituted generic signature" concept. if (!subs.empty()) { - auto subMap = origFnType->getGenericSignature()->getSubstitutionMap(subs); - inputType = inputType.subst(subMap)->getCanonicalType(); + inputType = inputType.subst(subs)->getCanonicalType(); } return inputType; @@ -2381,11 +2332,11 @@ namespace { CanSILFunctionType polyFn) : PolymorphicConvention(IGF.IGM, polyFn), IGF(IGF) {} - void emit(CanSILFunctionType substFnType, ArrayRef subs, + void emit(CanSILFunctionType substFnType, const SubstitutionMap &subs, WitnessMetadata *witnessMetadata, Explosion &out); private: - void emitEarlySources(ArrayRef subs, Explosion &out) { + void emitEarlySources(const SubstitutionMap &subs, Explosion &out) { for (auto &source : getSources()) { switch (source.getKind()) { // Already accounted for in the parameters. @@ -2415,7 +2366,7 @@ namespace { void irgen::emitPolymorphicArguments(IRGenFunction &IGF, CanSILFunctionType origFnType, CanSILFunctionType substFnType, - ArrayRef subs, + const SubstitutionMap &subs, WitnessMetadata *witnessMetadata, Explosion &out) { EmitPolymorphicArguments(IGF, origFnType).emit(substFnType, subs, @@ -2423,7 +2374,7 @@ void irgen::emitPolymorphicArguments(IRGenFunction &IGF, } void EmitPolymorphicArguments::emit(CanSILFunctionType substFnType, - ArrayRef subs, + const SubstitutionMap &subs, WitnessMetadata *witnessMetadata, Explosion &out) { // Add all the early sources. @@ -2469,7 +2420,7 @@ NecessaryBindings NecessaryBindings::forFunctionInvocations(IRGenModule &IGM, CanSILFunctionType origType, CanSILFunctionType substType, - ArrayRef subs) { + const SubstitutionMap &subs) { NecessaryBindings bindings; // Bail out early if we don't have polymorphic parameters. @@ -2482,21 +2433,11 @@ NecessaryBindings::forFunctionInvocations(IRGenModule &IGM, // - unfulfilled requirements convention.enumerateUnfulfilledRequirements( [&](GenericRequirement requirement) { - auto depTyIndex = - getDependentTypeIndex(origType->getGenericSignature(), - *IGM.getSwiftModule(), - requirement.TypeParameter); - - auto &sub = subs[depTyIndex]; - CanType type = sub.getReplacement()->getCanonicalType(); + CanType type = requirement.TypeParameter.subst(subs)->getCanonicalType(); if (requirement.Protocol) { - auto confIndex = - getProtocolConformanceIndex(origType->getGenericSignature(), - *IGM.getSwiftModule(), - requirement.TypeParameter, - requirement.Protocol); - auto conf = sub.getConformances()[confIndex]; + auto conf = *subs.lookupConformance(requirement.TypeParameter, + requirement.Protocol); bindings.addProtocolConformance(type, conf); } else { bindings.addTypeMetadata(type); @@ -2583,23 +2524,16 @@ GenericTypeRequirements::GenericTypeRequirements(IRGenModule &IGM, void GenericTypeRequirements::enumerateFulfillments(IRGenModule &IGM, - ArrayRef subs, + const SubstitutionMap &subs, FulfillmentCallback callback) { if (empty()) return; - auto signature = - TheDecl->getGenericSignatureOfContext()->getCanonicalSignature(); for (auto reqtIndex : indices(getRequirements())) { auto &reqt = getRequirements()[reqtIndex]; - auto typeIndex = getDependentTypeIndex(signature, *IGM.getSwiftModule(), - reqt.TypeParameter); - auto &sub = subs[typeIndex]; - CanType type = sub.getReplacement()->getCanonicalType(); + CanType type = reqt.TypeParameter.subst(subs)->getCanonicalType(); if (reqt.Protocol) { - auto confIndex = - getProtocolConformanceIndex(signature, *IGM.getSwiftModule(), - reqt.TypeParameter, reqt.Protocol); - auto conformance = sub.getConformances()[confIndex]; + auto conformance = *subs.lookupConformance(reqt.TypeParameter, + reqt.Protocol); callback(reqtIndex, type, conformance); } else { callback(reqtIndex, type, None); @@ -2608,7 +2542,7 @@ GenericTypeRequirements::enumerateFulfillments(IRGenModule &IGM, } void GenericTypeRequirements::emitInitOfBuffer(IRGenFunction &IGF, - ArrayRef subs, + const SubstitutionMap &subs, Address buffer) { if (Requirements.empty()) return; @@ -2652,11 +2586,9 @@ irgen::emitGenericRequirementFromSubstitutions(IRGenFunction &IGF, CanGenericSignature generics, ModuleDecl &module, GenericRequirement requirement, - ArrayRef subs) { + const SubstitutionMap &subs) { CanType depTy = requirement.TypeParameter; - auto typeIndex = getDependentTypeIndex(generics, module, depTy); - const Substitution &sub = subs[typeIndex]; - CanType argType = sub.getReplacement()->getCanonicalType(); + CanType argType = depTy.subst(subs)->getCanonicalType(); if (!requirement.Protocol) { auto argMetadata = IGF.emitTypeMetadataRef(argType); @@ -2664,8 +2596,7 @@ irgen::emitGenericRequirementFromSubstitutions(IRGenFunction &IGF, } auto proto = requirement.Protocol; - auto protoIndex = getProtocolConformanceIndex(generics, module, depTy, proto); - auto conformance = sub.getConformances()[protoIndex]; + auto conformance = *subs.lookupConformance(depTy, proto); assert(conformance.getRequirement() == proto); llvm::Value *metadata = nullptr; auto wtable = emitWitnessTableRef(IGF, argType, &metadata, conformance); diff --git a/lib/IRGen/GenProto.h b/lib/IRGen/GenProto.h index 67aad46fc3fda..f92434680df7b 100644 --- a/lib/IRGen/GenProto.h +++ b/lib/IRGen/GenProto.h @@ -136,7 +136,7 @@ namespace irgen { void emitPolymorphicArguments(IRGenFunction &IGF, CanSILFunctionType origType, CanSILFunctionType substType, - ArrayRef subs, + const SubstitutionMap &subs, WitnessMetadata *witnessMetadata, Explosion &args); diff --git a/lib/IRGen/GenericRequirement.h b/lib/IRGen/GenericRequirement.h index 6896b53e1f007..0afa31365a370 100644 --- a/lib/IRGen/GenericRequirement.h +++ b/lib/IRGen/GenericRequirement.h @@ -33,7 +33,7 @@ class CanGenericSignature; class ModuleDecl; class NominalTypeDecl; class ProtocolDecl; -class Substitution; +class SubstitutionMap; namespace irgen { class Address; @@ -54,7 +54,7 @@ emitGenericRequirementFromSubstitutions(IRGenFunction &IGF, CanGenericSignature signature, ModuleDecl &module, GenericRequirement requirement, - ArrayRef subs); + const SubstitutionMap &subs); using EmitGenericRequirementFn = llvm::function_ref; @@ -141,10 +141,10 @@ class GenericTypeRequirements { llvm::function_ref conf)>; - void enumerateFulfillments(IRGenModule &IGM, ArrayRef subs, + void enumerateFulfillments(IRGenModule &IGM, const SubstitutionMap &subs, FulfillmentCallback callback); - void emitInitOfBuffer(IRGenFunction &IGF, ArrayRef subs, + void emitInitOfBuffer(IRGenFunction &IGF, const SubstitutionMap &subs, Address buffer); void bindFromBuffer(IRGenFunction &IGF, Address buffer, diff --git a/lib/IRGen/IRGenSIL.cpp b/lib/IRGen/IRGenSIL.cpp index ae91a6fe09998..c9879dbc09bda 100644 --- a/lib/IRGen/IRGenSIL.cpp +++ b/lib/IRGen/IRGenSIL.cpp @@ -2075,8 +2075,11 @@ void IRGenSILFunction::visitFullApplySite(FullApplySite site) { // Pass the generic arguments. if (hasPolymorphicParameters(origCalleeType)) { + SubstitutionMap subMap; + if (auto genericSig = origCalleeType->getGenericSignature()) + subMap = genericSig->getSubstitutionMap(site.getSubstitutions()); emitPolymorphicArguments(*this, origCalleeType, substCalleeType, - site.getSubstitutions(), &witnessMetadata, llArgs); + subMap, &witnessMetadata, llArgs); } // Add all those arguments. diff --git a/lib/IRGen/MetadataLayout.h b/lib/IRGen/MetadataLayout.h index 27ee5aca3fc1a..dbc8a60d95c5d 100644 --- a/lib/IRGen/MetadataLayout.h +++ b/lib/IRGen/MetadataLayout.h @@ -66,7 +66,8 @@ template class MetadataLayout { if (requirements.empty()) return; auto subs = type->castTo() - ->gatherAllSubstitutions(IGM.getSwiftModule(), nullptr); + ->getContextSubstitutionMap(IGM.getSwiftModule(), + typeDecl); requirements.enumerateFulfillments(IGM, subs, [&](unsigned reqtIndex, CanType argType, Optional conf) { diff --git a/lib/IRGen/NecessaryBindings.h b/lib/IRGen/NecessaryBindings.h index 417e7289decf0..63af9055409e4 100644 --- a/lib/IRGen/NecessaryBindings.h +++ b/lib/IRGen/NecessaryBindings.h @@ -49,7 +49,7 @@ class NecessaryBindings { static NecessaryBindings forFunctionInvocations(IRGenModule &IGM, CanSILFunctionType origType, CanSILFunctionType substType, - ArrayRef subs); + const SubstitutionMap &subs); /// Add whatever information is necessary to reconstruct type metadata /// for the given type. diff --git a/lib/SIL/SILType.cpp b/lib/SIL/SILType.cpp index e48223f9c2338..97192b8b1f75c 100644 --- a/lib/SIL/SILType.cpp +++ b/lib/SIL/SILType.cpp @@ -319,8 +319,7 @@ SILType SILType::getEnumElementType(EnumElementDecl *elt, SILModule &M) const { } auto substEltTy = - getSwiftRValueType()->getTypeOfMember(M.getSwiftModule(), - elt, nullptr, + getSwiftRValueType()->getTypeOfMember(M.getSwiftModule(), elt, elt->getArgumentInterfaceType()); auto loweredTy = M.Types.getLoweredType(M.Types.getAbstractionPattern(elt), substEltTy); diff --git a/lib/SIL/TypeLowering.cpp b/lib/SIL/TypeLowering.cpp index 8f07de21896f1..69f68d489f28a 100644 --- a/lib/SIL/TypeLowering.cpp +++ b/lib/SIL/TypeLowering.cpp @@ -1255,8 +1255,7 @@ namespace { } auto substEltType = enumType->getTypeOfMember( - D->getModuleContext(), - elt, nullptr, + D->getModuleContext(), elt, elt->getArgumentInterfaceType()) ->getCanonicalType(); diff --git a/lib/SILGen/SILGenDecl.cpp b/lib/SILGen/SILGenDecl.cpp index f5afd7e3b4136..573ee54465e1f 100644 --- a/lib/SILGen/SILGenDecl.cpp +++ b/lib/SILGen/SILGenDecl.cpp @@ -763,7 +763,7 @@ emitEnumMatch(ManagedValue value, EnumElementDecl *ElementDecl, // Reabstract to the substituted type, if needed. CanType substEltTy = value.getSwiftType()->getTypeOfMember(SGF.SGM.M.getSwiftModule(), - ElementDecl, nullptr, + ElementDecl, ElementDecl->getArgumentInterfaceType()) ->getCanonicalType(); diff --git a/lib/SILGen/SILGenMaterializeForSet.cpp b/lib/SILGen/SILGenMaterializeForSet.cpp index 2963d41b31dec..6fa6a18390f14 100644 --- a/lib/SILGen/SILGenMaterializeForSet.cpp +++ b/lib/SILGen/SILGenMaterializeForSet.cpp @@ -387,8 +387,8 @@ struct MaterializeForSetEmitter { /// substitution according to the witness substitutions. CanType getSubstWitnessInterfaceType(CanType type) { auto subs = SubstSelfType->getRValueInstanceType() - ->getMemberSubstitutions(WitnessStorage); - return type.subst(SGM.SwiftModule, subs)->getCanonicalType(); + ->getMemberSubstitutionMap(SGM.SwiftModule, WitnessStorage); + return type.subst(subs)->getCanonicalType(); } }; diff --git a/lib/SILGen/SILGenPattern.cpp b/lib/SILGen/SILGenPattern.cpp index 02c80ee4748b4..5d2ad05a1eaa8 100644 --- a/lib/SILGen/SILGenPattern.cpp +++ b/lib/SILGen/SILGenPattern.cpp @@ -1803,8 +1803,7 @@ emitEnumElementDispatch(ArrayRef rows, // Reabstract to the substituted type, if needed. CanType substEltTy = - sourceType->getTypeOfMember(SGF.SGM.M.getSwiftModule(), - formalElt, nullptr, + sourceType->getTypeOfMember(SGF.SGM.M.getSwiftModule(), formalElt, formalElt->getArgumentInterfaceType()) ->getCanonicalType(); diff --git a/lib/Sema/CSApply.cpp b/lib/Sema/CSApply.cpp index 8fcd4fbf93aac..8a6a59a6ed4ea 100644 --- a/lib/Sema/CSApply.cpp +++ b/lib/Sema/CSApply.cpp @@ -1592,13 +1592,15 @@ namespace { /*Implicit=*/true); fnRef->setFunctionRefKind(FunctionRefKind::SingleApply); - TypeSubstitutionMap subMap; + SubstitutionMap subMap; auto genericParam = fnGenericParams[0]; - subMap[genericParam->getCanonicalType()->castTo()] - = valueType; - cs.setType(fnRef, fn->getInterfaceType().subst(dc->getParentModule(), - subMap, - None)); + auto selfTy = cast(genericParam->getCanonicalType()); + + subMap.addSubstitution(selfTy, valueType); + for (auto conformance : Conformances) + subMap.addConformance(selfTy, conformance); + + cs.setType(fnRef, fn->getInterfaceType().subst(subMap)); // Form the arguments. Expr *args[2] = { diff --git a/lib/Sema/CSDiag.cpp b/lib/Sema/CSDiag.cpp index 00667f52d71e9..243af502edc87 100644 --- a/lib/Sema/CSDiag.cpp +++ b/lib/Sema/CSDiag.cpp @@ -5738,31 +5738,23 @@ bool FailureDiagnosis::diagnoseArgumentGenericRequirements( return false; class RequirementsListener : public GenericRequirementsCheckListener { - private: - bool DiagnosedAny = false; - public: bool shouldCheck(RequirementKind kind, Type first, Type second) override { // This means that we have encountered requirement which references // generic parameter not used in the arguments, we can't diagnose it here. return !(first->hasTypeParameter() || first->isTypeVariableOrMember()); } - - void diagnosed(const Requirement *requirement) override { - DiagnosedAny = true; - } - - bool foundProblems() const { return DiagnosedAny; } }; RequirementsListener genericReqListener; - TC.checkGenericArguments(env->getOwningDeclContext(), argExpr->getLoc(), - AFD->getLoc(), AFD->getInterfaceType(), - env->getGenericSignature(), substitutions, nullptr, - ConformanceCheckFlags::SuppressDependencyTracking, - &genericReqListener); - - return genericReqListener.foundProblems(); + auto result = + TC.checkGenericArguments(env->getOwningDeclContext(), argExpr->getLoc(), + AFD->getLoc(), AFD->getInterfaceType(), + env->getGenericSignature(), substitutions, nullptr, + ConformanceCheckFlags::SuppressDependencyTracking, + &genericReqListener); + + return !result.second; } /// When initializing Unsafe[Mutable]Pointer from Unsafe[Mutable]RawPointer, diff --git a/lib/Sema/CSGen.cpp b/lib/Sema/CSGen.cpp index d98a78e472c01..3a2b3e7f0dd1b 100644 --- a/lib/Sema/CSGen.cpp +++ b/lib/Sema/CSGen.cpp @@ -3232,9 +3232,10 @@ bool swift::isExtensionApplied(DeclContext &DC, Type BaseTy, SmallVector TypeScratch; // Prepare type substitution map. - TypeSubstitutionMap Substitutions = BaseTy->getContextSubstitutions(ED); + SubstitutionMap Substitutions = BaseTy->getContextSubstitutionMap( + DC.getParentModule(), ED); auto resolveType = [&](Type Ty) { - return Ty.subst(DC.getParentModule(), Substitutions); + return Ty.subst(Substitutions); }; auto createMemberConstraint = [&](Requirement &Req, ConstraintKind Kind) { diff --git a/lib/Sema/ConstraintSystem.cpp b/lib/Sema/ConstraintSystem.cpp index d95448471261f..65527e0643102 100644 --- a/lib/Sema/ConstraintSystem.cpp +++ b/lib/Sema/ConstraintSystem.cpp @@ -1568,20 +1568,11 @@ Type simplifyTypeImpl(ConstraintSystem &cs, Type type, Fn getFixedTypeFn) { auto assocType = depMemTy->getAssocType(); assert(depMemTy->getAssocType() && "Expected associated type!"); + // FIXME: It's kind of weird in general that we have to look + // through lvalue, inout and IUO types here Type lookupBaseType = newBase->getLValueOrInOutObjectType(); - if (!lookupBaseType->mayHaveMembers()) return type; - - auto result = assocType->getDeclaredInterfaceType() - .subst(cs.DC->getParentModule(), - lookupBaseType->getContextSubstitutions( - assocType->getDeclContext())); - - - if (result) - return result; - if (!lookupBaseType->getImplicitlyUnwrappedOptionalObjectType()) - return DependentMemberType::get(ErrorType::get(newBase), assocType); + auto *module = cs.DC->getParentModule(); // "Force" the IUO for substitution purposes. We can end up in // this situation if we use the results of overload resolution @@ -1589,15 +1580,23 @@ Type simplifyTypeImpl(ConstraintSystem &cs, Type type, Fn getFixedTypeFn) { // IUO-typed entity. while (auto objectType = lookupBaseType->getImplicitlyUnwrappedOptionalObjectType()) { + // If we're accessing a type member of the IUO itself, + // stop here. Ugh... + if (module->lookupConformance(lookupBaseType, + assocType->getProtocol(), + &cs.getTypeChecker())) { + break; + } + lookupBaseType = objectType; } if (!lookupBaseType->mayHaveMembers()) return type; - result = assocType->getDeclaredInterfaceType() - .subst(cs.DC->getParentModule(), - lookupBaseType->getContextSubstitutions( - assocType->getDeclContext())); + auto subs = lookupBaseType->getContextSubstitutionMap( + cs.DC->getParentModule(), + assocType->getDeclContext()); + auto result = assocType->getDeclaredInterfaceType().subst(subs); if (result) return result; diff --git a/lib/Sema/TypeCheckConstraints.cpp b/lib/Sema/TypeCheckConstraints.cpp index fd98b56ec1b24..1a370f730593d 100644 --- a/lib/Sema/TypeCheckConstraints.cpp +++ b/lib/Sema/TypeCheckConstraints.cpp @@ -1388,9 +1388,6 @@ bool GenericRequirementsCheckListener::shouldCheck(RequirementKind kind, return true; } -void GenericRequirementsCheckListener::diagnosed( - const Requirement *requirement) {} - bool TypeChecker:: solveForExpression(Expr *&expr, DeclContext *dc, Type convertType, FreeTypeVariableBinding allowFreeTypeVariables, @@ -2102,9 +2099,11 @@ bool TypeChecker::typeCheckForEachBinding(DeclContext *dc, ForEachStmt *stmt) { cast( sequenceProto->lookupDirect(ctx.Id_Iterator).front()); + auto subs = sequenceType->getContextSubstitutionMap( + cs.DC->getParentModule(), + sequenceProto); iteratorType = iteratorAssocType->getDeclaredInterfaceType() - .subst(cs.DC->getParentModule(), - sequenceType->getContextSubstitutions(sequenceProto)); + .subst(subs); if (iteratorType) { auto iteratorProto = @@ -2120,7 +2119,6 @@ bool TypeChecker::typeCheckForEachBinding(DeclContext *dc, ForEachStmt *stmt) { elementType = iteratorType->getTypeOfMember( cs.DC->getParentModule(), elementAssocType, - &tc, elementAssocType->getDeclaredInterfaceType()); } } diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp index 74b8c01b020de..72813cad296d8 100644 --- a/lib/Sema/TypeCheckDecl.cpp +++ b/lib/Sema/TypeCheckDecl.cpp @@ -6867,7 +6867,7 @@ static bool checkEnumDeclCircularity(EnumDecl *E, NominalDeclSet &known, continue; auto eltType = baseType->getTypeOfMember(E->getModuleContext(), elt, - nullptr, elt->getArgumentInterfaceType()); + elt->getArgumentInterfaceType()); if (deconstructTypeForDeclCircularity(eltType, known)) return true; diff --git a/lib/Sema/TypeCheckExprObjC.cpp b/lib/Sema/TypeCheckExprObjC.cpp index d113953af1e61..c57b32584e511 100644 --- a/lib/Sema/TypeCheckExprObjC.cpp +++ b/lib/Sema/TypeCheckExprObjC.cpp @@ -331,7 +331,7 @@ Optional TypeChecker::checkObjCKeyPathExpr(DeclContext *dc, Type newType; if (lookupType && !lookupType->isAnyObject()) { - newType = lookupType->getTypeOfMember(dc->getParentModule(), type, this, + newType = lookupType->getTypeOfMember(dc->getParentModule(), type, type->getDeclaredInterfaceType()); } else { newType = type->getDeclaredInterfaceType(); diff --git a/lib/Sema/TypeCheckGeneric.cpp b/lib/Sema/TypeCheckGeneric.cpp index 9200d3647c73c..2b82e620ab61b 100644 --- a/lib/Sema/TypeCheckGeneric.cpp +++ b/lib/Sema/TypeCheckGeneric.cpp @@ -862,7 +862,9 @@ std::pair TypeChecker::checkGenericArguments( // Check each of the requirements. ModuleDecl *module = dc->getParentModule(); for (const auto &req : genericSig->getRequirements()) { - Type firstType = req.getFirstType().subst(module, substitutions); + Type firstType = req.getFirstType().subst( + QueryTypeSubstitutionMap{substitutions}, + LookUpConformanceInModule(module)); if (firstType.isNull()) { // Another requirement will fail later; just continue. continue; @@ -872,7 +874,8 @@ std::pair TypeChecker::checkGenericArguments( if (req.getKind() != RequirementKind::Layout) secondType = req.getSecondType(); if (secondType) { - secondType = secondType.subst(module, substitutions); + secondType = secondType.subst(QueryTypeSubstitutionMap{substitutions}, + LookUpConformanceInModule(module)); if (secondType.isNull()) { // Another requirement will fail later; just continue. continue; @@ -900,12 +903,8 @@ std::pair TypeChecker::checkGenericArguments( return std::make_pair(true, false); // Conformance check failure case. - if (!result.second) { - if (listener && loc.isValid()) - listener->diagnosed(&req); - + if (!result.second) return std::make_pair(false, false); - } continue; } @@ -929,9 +928,6 @@ std::pair TypeChecker::checkGenericArguments( genericSig->gatherGenericParamBindingsText( {req.getFirstType(), req.getSecondType()}, substitutions)); - if (listener) - listener->diagnosed(&req); - return std::make_pair(false, false); } continue; @@ -946,9 +942,6 @@ std::pair TypeChecker::checkGenericArguments( genericSig->gatherGenericParamBindingsText( {req.getFirstType(), req.getSecondType()}, substitutions)); - if (listener) - listener->diagnosed(&req); - return std::make_pair(false, false); } continue; diff --git a/lib/Sema/TypeCheckPattern.cpp b/lib/Sema/TypeCheckPattern.cpp index c8ebac73eb59b..0a3131e67d43b 100644 --- a/lib/Sema/TypeCheckPattern.cpp +++ b/lib/Sema/TypeCheckPattern.cpp @@ -1436,7 +1436,7 @@ bool TypeChecker::coercePatternToType(Pattern *&P, DeclContext *dc, Type type, Type elementType; if (auto argType = elt->getArgumentInterfaceType()) elementType = enumTy->getTypeOfMember(elt->getModuleContext(), - elt, this, argType); + elt, argType); else elementType = TupleType::getEmpty(Context); Pattern *sub = EEP->getSubPattern(); diff --git a/lib/Sema/TypeCheckProtocol.cpp b/lib/Sema/TypeCheckProtocol.cpp index 426a5cb1148fa..afa6aba80b5b1 100644 --- a/lib/Sema/TypeCheckProtocol.cpp +++ b/lib/Sema/TypeCheckProtocol.cpp @@ -3211,7 +3211,9 @@ static Type getWitnessTypeForMatching(TypeChecker &tc, } ModuleDecl *module = conformance->getDeclContext()->getParentModule(); - auto resultType = type.subst(module, substitutions, SubstFlags::UseErrorType); + auto resultType = type.subst(QueryTypeSubstitutionMap{substitutions}, + LookUpConformanceInModule(module), + SubstFlags::UseErrorType); if (!resultType->hasError()) return resultType; // Map error types with original types *back* to the original, dependent type. @@ -3664,8 +3666,9 @@ void ConformanceChecker::resolveTypeWitnesses() { TC.validateDecl(assocType); Type defaultType = assocType->getDefaultDefinitionLoc().getType().subst( - DC->getParentModule(), - substitutions); + QueryTypeSubstitutionMap{substitutions}, + LookUpConformanceInModule(DC->getParentModule())); + if (!defaultType) return Type(); diff --git a/lib/Sema/TypeCheckType.cpp b/lib/Sema/TypeCheckType.cpp index 5b8334ec85d77..9ef4966e1bb34 100644 --- a/lib/Sema/TypeCheckType.cpp +++ b/lib/Sema/TypeCheckType.cpp @@ -394,15 +394,14 @@ Type TypeChecker::resolveTypeInContext( bool hasDependentType = typeDecl->getDeclaredInterfaceType() ->hasTypeParameter(); + // If we found a generic parameter, map to the archetype if there is one. + if (auto genericParam = dyn_cast(typeDecl)) { + return resolver->resolveGenericTypeParamType( + genericParam->getDeclaredInterfaceType() + ->castTo()); + } if (!foundNominal || !hasDependentType) { - // If we found a generic parameter, map to the archetype if there is one. - if (auto genericParam = dyn_cast(typeDecl)) { - return resolver->resolveGenericTypeParamType( - genericParam->getDeclaredInterfaceType() - ->castTo()); - } - // If this is a typealias not in type context, we still need the // interface type; the typealias might be in a function context, and // its underlying type might reference outer generic parameters. @@ -645,7 +644,9 @@ Type TypeChecker::applyUnboundGenericArguments( // Apply substitutions to the interface type of the typealias. type = TAD->getDeclaredInterfaceType(); - return type.subst(dc->getParentModule(), subs, SubstFlags::UseErrorType); + return type.subst(QueryTypeSubstitutionMap{subs}, + LookUpConformanceInModule(dc->getParentModule()), + SubstFlags::UseErrorType); } // Form the bound generic type. @@ -2951,8 +2952,9 @@ Type TypeChecker::substMemberTypeWithBase(ModuleDecl *module, if (!parentTy) return memberType; - auto subs = parentTy->getContextSubstitutions(member->getDeclContext()); - return memberType.subst(module, subs, SubstFlags::UseErrorType); + auto subs = parentTy->getContextSubstitutionMap( + module, member->getDeclContext()); + return memberType.subst(subs, SubstFlags::UseErrorType); } Type TypeChecker::getSuperClassOf(Type type) { diff --git a/lib/Sema/TypeChecker.h b/lib/Sema/TypeChecker.h index 8382c5f522775..e5be1bb0a9804 100644 --- a/lib/Sema/TypeChecker.h +++ b/lib/Sema/TypeChecker.h @@ -352,12 +352,6 @@ class GenericRequirementsCheckListener { /// /// \returns true if it's ok to validate requirement, false otherwise. virtual bool shouldCheck(RequirementKind kind, Type first, Type second); - - /// Callback invoked when given requirement has been diagnosed as invalid. - /// - /// \param requirement The requirement which didn't pass the check. - /// - virtual void diagnosed(const Requirement *requirement); }; /// Flags that describe the context of type checking a pattern or