From b891b564ac2853f1b20e0aef75bc9d6f08c9917e Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Wed, 11 Oct 2023 17:12:42 -0400 Subject: [PATCH 1/3] Sema: Use forEachAssociatedConformance() from ensureRequirementsAreSatisfied() --- lib/Sema/TypeCheckProtocol.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/lib/Sema/TypeCheckProtocol.cpp b/lib/Sema/TypeCheckProtocol.cpp index eeea76df49ecd..c55979a775ffb 100644 --- a/lib/Sema/TypeCheckProtocol.cpp +++ b/lib/Sema/TypeCheckProtocol.cpp @@ -5196,10 +5196,8 @@ void ConformanceChecker::ensureRequirementsAreSatisfied() { return false; }); - for (auto req : proto->getRequirementSignature().getRequirements()) { - if (req.getKind() == RequirementKind::Conformance) { - auto depTy = req.getFirstType(); - auto *proto = req.getProtocolDecl(); + Conformance->forEachAssociatedConformance( + [&](Type depTy, ProtocolDecl *proto, unsigned index) { auto conformance = Conformance->getAssociatedConformance(depTy, proto); if (conformance.isConcrete()) { auto *concrete = conformance.getConcrete(); @@ -5208,8 +5206,9 @@ void ConformanceChecker::ensureRequirementsAreSatisfied() { conformance, where, depTy, replacementTy); } - } - } + + return false; + }); } #pragma mark Protocol conformance checking From 82cbcf11610aaea99555ef5a07fe346b6bac05d3 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Thu, 12 Oct 2023 15:32:32 -0400 Subject: [PATCH 2/3] Sema: Remove some code from checkTypeWitness() that no longer appears to be needed --- lib/Sema/TypeCheckProtocol.cpp | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/lib/Sema/TypeCheckProtocol.cpp b/lib/Sema/TypeCheckProtocol.cpp index c55979a775ffb..b26562c9b3b05 100644 --- a/lib/Sema/TypeCheckProtocol.cpp +++ b/lib/Sema/TypeCheckProtocol.cpp @@ -4763,21 +4763,6 @@ swift::checkTypeWitness(Type type, AssociatedTypeDecl *assocType, KnownProtocolKind::Sendable)) .isInvalid()) return CheckTypeWitnessResult::forConformance(reqProto); - - // FIXME: Why is conformsToProtocol() not enough? The stdlib doesn't - // build unless we fail here while inferring an associated type - // somewhere. - if (contextType->isSpecialized()) { - auto *decl = contextType->getAnyNominal(); - auto subMap = contextType->getContextSubstitutionMap( - module, - decl, - decl->getGenericEnvironmentOfContext()); - for (auto replacement : subMap.getReplacementTypes()) { - if (replacement->hasError()) - return CheckTypeWitnessResult::forConformance(reqProto); - } - } } if (sig->requiresClass(depTy) && From 273baf560734487cf09519b49e3c1c5e428dffc0 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Thu, 12 Oct 2023 15:43:00 -0400 Subject: [PATCH 3/3] Sema: Remove bespoke recursivelySubstituteBaseType() in favor of plain old Type::subst() --- lib/Sema/TypeCheckProtocol.cpp | 43 ++++------------------------------ 1 file changed, 5 insertions(+), 38 deletions(-) diff --git a/lib/Sema/TypeCheckProtocol.cpp b/lib/Sema/TypeCheckProtocol.cpp index b26562c9b3b05..0d120306c72ee 100644 --- a/lib/Sema/TypeCheckProtocol.cpp +++ b/lib/Sema/TypeCheckProtocol.cpp @@ -7054,51 +7054,18 @@ ValueWitnessRequest::evaluate(Evaluator &eval, return known->second; } -/// A stripped-down version of Type::subst that only works on the protocol -/// Self type wrapped in zero or more DependentMemberTypes. -static Type -recursivelySubstituteBaseType(ModuleDecl *module, - NormalProtocolConformance *conformance, - DependentMemberType *depMemTy) { - Type origBase = depMemTy->getBase(); - - // Recursive case. - if (auto *depBase = origBase->getAs()) { - Type substBase = recursivelySubstituteBaseType( - module, conformance, depBase); - return depMemTy->substBaseType(module, substBase); - } - - // Base case. The associated type's protocol should be either the - // conformance protocol or an inherited protocol. - auto *reqProto = depMemTy->getAssocType()->getProtocol(); - assert(origBase->isEqual(reqProto->getSelfInterfaceType())); - - ProtocolConformance *reqConformance = conformance; - - // If we have an inherited protocol just look up the conformance. - if (reqProto != conformance->getProtocol()) { - reqConformance = module->lookupConformance(conformance->getType(), reqProto) - .getConcrete(); - } - - return reqConformance->getTypeWitness(depMemTy->getAssocType()); -} - ProtocolConformanceRef AssociatedConformanceRequest::evaluate(Evaluator &eval, NormalProtocolConformance *conformance, CanType origTy, ProtocolDecl *reqProto, unsigned index) const { auto *module = conformance->getDeclContext()->getParentModule(); - Type substTy; - if (origTy->isEqual(conformance->getProtocol()->getSelfInterfaceType())) { - substTy = conformance->getType(); - } else { - auto *depMemTy = origTy->castTo(); - substTy = recursivelySubstituteBaseType(module, conformance, depMemTy); - } + auto subMap = SubstitutionMap::getProtocolSubstitutions( + conformance->getProtocol(), + conformance->getType(), + ProtocolConformanceRef(conformance)); + auto substTy = origTy.subst(subMap); // Looking up a conformance for a contextual type and mapping the // conformance context produces a more accurate result than looking