std::pair<SynthesizedExtensionInfo, ExtensionMergeInfo> isApplicable(ExtensionDecl *Ext, bool IsSynthesized, ExtensionDecl *EnablingExt, NormalProtocolConformance *Conf) { SynthesizedExtensionInfo Result(IsSynthesized, EnablingExt); ExtensionMergeInfo MergeInfo; MergeInfo.HasDocComment = !Ext->getRawComment().isEmpty(); MergeInfo.InheritsCount = countInherits(Ext); // There's (up to) two extensions here: the extension with the items that we // might be merging, plus the "enabling extension", which is the route // through which \c Ext itself applies, e.g. extension SomeProtocol {} // extension SomeType: SomeProtocol where T: SomeProtocol {}. The former is // Ext and the latter is EnablingExt/Conf. Either of these can be // conditional in ways that need to be considered when merging. auto conformanceIsConditional = Conf && !Conf->getConditionalRequirements().empty(); if (!Ext->isConstrainedExtension() && !conformanceIsConditional) { if (IncludeUnconditional) Result.Ext = Ext; return {Result, MergeInfo}; } auto handleRequirements = [&](SubstitutionMap subMap, GenericSignature *GenericSig, ArrayRef<Requirement> Reqs) { for (auto Req : Reqs) { auto Kind = Req.getKind(); // FIXME: Could do something here if (Kind == RequirementKind::Layout) continue; auto First = Req.getFirstType(); auto Second = Req.getSecondType(); if (!BaseType->isExistentialType()) { First = First.subst(subMap); Second = Second.subst(subMap); if (!First || !Second) { // Substitution with interface type bases can only fail // if a concrete type fails to conform to a protocol. // In this case, just give up on the extension altogether. return true; } } switch (Kind) { case RequirementKind::Conformance: case RequirementKind::Superclass: // FIXME: This could be more accurate; check // conformance instead of subtyping if (!canPossiblyConvertTo(First, Second, *DC)) return true; else if (!isConvertibleTo(First, Second, *DC)) MergeInfo.addRequirement(GenericSig, First, Second, Kind); break; case RequirementKind::SameType: if (!canPossiblyEqual(First, Second, *DC)) { return true; } else if (!First->isEqual(Second)) { MergeInfo.addRequirement(GenericSig, First, Second, Kind); } break; case RequirementKind::Layout: llvm_unreachable("Handled above"); } } return false; }; auto *M = DC->getParentModule(); if (Ext->isConstrainedExtension()) { // Get the substitutions from the generic signature of // the extension to the interface types of the base type's // declaration. SubstitutionMap subMap; if (!BaseType->isExistentialType()) subMap = BaseType->getContextSubstitutionMap(M, Ext); assert(Ext->getGenericSignature() && "No generic signature."); auto GenericSig = Ext->getGenericSignature(); if (handleRequirements(subMap, GenericSig, GenericSig->getRequirements())) return {Result, MergeInfo}; } if (Conf && handleRequirements(Conf->getSubstitutions(M), Conf->getGenericSignature(), Conf->getConditionalRequirements())) return {Result, MergeInfo}; Result.Ext = Ext; return {Result, MergeInfo}; }
std::pair<SynthesizedExtensionInfo, ExtensionMergeInfo> isApplicable(ExtensionDecl *Ext, bool IsSynthesized) { SynthesizedExtensionInfo Result(IsSynthesized); ExtensionMergeInfo MergeInfo; MergeInfo.HasDocComment = !Ext->getRawComment().isEmpty(); MergeInfo.InheritsCount = countInherits(Ext); if (!Ext->isConstrainedExtension()) { if (IncludeUnconditional) Result.Ext = Ext; return {Result, MergeInfo}; } // Get the substitutions from the generic signature of // the extension to the interface types of the base type's // declaration. 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(); // FIXME: Could do something here if (Kind == RequirementKind::Layout) continue; auto First = Req.getFirstType(); auto Second = Req.getSecondType(); if (!BaseType->isExistentialType()) { First = First.subst(subMap); Second = Second.subst(subMap); if (!First || !Second) { // Substitution with interface type bases can only fail // if a concrete type fails to conform to a protocol. // In this case, just give up on the extension altogether. return {Result, MergeInfo}; } } switch (Kind) { case RequirementKind::Conformance: case RequirementKind::Superclass: // FIXME: This could be more accurate; check // conformance instead of subtyping if (!canPossiblyConvertTo(First, Second, *DC)) return {Result, MergeInfo}; else if (!isConvertibleTo(First, Second, *DC)) MergeInfo.addRequirement(First, Second, Kind); break; case RequirementKind::SameType: if (!canPossiblyEqual(First, Second, *DC)) { return {Result, MergeInfo}; } else if (!First->isEqual(Second)) { MergeInfo.addRequirement(First, Second, Kind); } break; case RequirementKind::Layout: llvm_unreachable("Handled above"); } } Result.Ext = Ext; return {Result, MergeInfo}; }