2929#include " swift/AST/DiagnosticsSema.h"
3030#include " swift/AST/ExistentialLayout.h"
3131#include " swift/AST/GenericEnvironment.h"
32- #include " swift/AST/InverseMarking.h"
3332#include " swift/AST/NameLookup.h"
3433#include " swift/AST/NameLookupRequests.h"
3534#include " swift/AST/PackConformance.h"
@@ -403,39 +402,6 @@ static ProtocolConformanceRef getBuiltinMetaTypeTypeConformance(
403402 return ProtocolConformanceRef::forMissingOrInvalid (type, protocol);
404403}
405404
406- static ProtocolConformanceRef
407- getBuiltinInvertibleProtocolConformance (NominalTypeDecl *nominal,
408- Type type,
409- ProtocolDecl *protocol) {
410- assert (isa<ClassDecl>(nominal));
411- ASTContext &ctx = protocol->getASTContext ();
412-
413- auto ip = protocol->getInvertibleProtocolKind ();
414- switch (*ip) {
415- case InvertibleProtocolKind::Copyable:
416- // If move-only classes is enabled, we'll check the markings.
417- if (ctx.LangOpts .hasFeature (Feature::MoveOnlyClasses)) {
418- switch (nominal->hasInverseMarking (*ip).getKind ()) {
419- case InverseMarking::Kind::LegacyExplicit:
420- case InverseMarking::Kind::Explicit:
421- // An inverse ~Copyable prevents conformance.
422- return ProtocolConformanceRef::forInvalid ();
423-
424- case InverseMarking::Kind::None:
425- break ;
426- }
427- }
428- break ;
429- case InvertibleProtocolKind::Escapable:
430- // Always conforms.
431- break ;
432- }
433-
434- return ProtocolConformanceRef (
435- ctx.getBuiltinConformance (type, protocol,
436- BuiltinConformanceKind::Synthesized));
437- }
438-
439405// / Synthesize a builtin type conformance to the given protocol, if
440406// / appropriate.
441407static ProtocolConformanceRef
@@ -625,13 +591,6 @@ LookupConformanceInModuleRequest::evaluate(
625591 if (!nominal || isa<ProtocolDecl>(nominal))
626592 return ProtocolConformanceRef::forMissingOrInvalid (type, protocol);
627593
628- // We specially avoid recording conformances to invertible protocols in a
629- // class's conformance table. This prevents an evaluator cycle.
630- if (ctx.LangOpts .hasFeature (Feature::NoncopyableGenerics)
631- && isa<ClassDecl>(nominal)
632- && protocol->getInvertibleProtocolKind ())
633- return getBuiltinInvertibleProtocolConformance (nominal, type, protocol);
634-
635594 // Expand conformances added by extension macros.
636595 //
637596 // FIXME: This expansion should only be done if the
@@ -643,8 +602,12 @@ LookupConformanceInModuleRequest::evaluate(
643602 ExpandExtensionMacros{nominal},
644603 { });
645604
646- // Find the (unspecialized) conformance.
605+ // Find the root conformance in the nominal type declaration's
606+ // conformance lookup table.
647607 SmallVector<ProtocolConformance *, 2 > conformances;
608+
609+ // If the conformance lookup table produced nothing, we try to derive the
610+ // conformance for a few special protocol kinds.
648611 if (!nominal->lookupConformance (protocol, conformances)) {
649612 if (protocol->isSpecificProtocol (KnownProtocolKind::Sendable)) {
650613 // Try to infer Sendable conformance.
@@ -677,31 +640,17 @@ LookupConformanceInModuleRequest::evaluate(
677640 } else {
678641 return ProtocolConformanceRef::forMissingOrInvalid (type, protocol);
679642 }
680- } else if (protocol->isSpecificProtocol (KnownProtocolKind::Copyable)
681- || protocol->isSpecificProtocol (KnownProtocolKind::Escapable)) {
682- const auto kp = protocol->getKnownProtocolKind ().value ();
683-
684- if (!ctx.LangOpts .hasFeature (Feature::NoncopyableGenerics)
685- && kp == KnownProtocolKind::Copyable) {
643+ } else if (protocol->isSpecificProtocol (KnownProtocolKind::Copyable)) {
644+ if (!ctx.LangOpts .hasFeature (Feature::NoncopyableGenerics)) {
686645 // Return an abstract conformance to maintain legacy compatability.
687646 // We only need to do this until we are properly dealing with or
688647 // omitting Copyable conformances in modules/interfaces.
689648
690649 if (nominal->canBeCopyable ())
691650 return ProtocolConformanceRef (protocol);
692- else
693- return ProtocolConformanceRef::forMissingOrInvalid (type, protocol);
694651 }
695652
696- // Try to infer the conformance.
697- ImplicitKnownProtocolConformanceRequest cvRequest{nominal, kp};
698- if (auto conformance = evaluateOrDefault (
699- ctx.evaluator , cvRequest, nullptr )) {
700- conformances.clear ();
701- conformances.push_back (conformance);
702- } else {
703- return ProtocolConformanceRef::forMissingOrInvalid (type, protocol);
704- }
653+ return ProtocolConformanceRef::forMissingOrInvalid (type, protocol);
705654 } else if (protocol->isSpecificProtocol (
706655 KnownProtocolKind::BitwiseCopyable)) {
707656 // Try to infer BitwiseCopyable conformance.
@@ -720,6 +669,8 @@ LookupConformanceInModuleRequest::evaluate(
720669 }
721670 }
722671
672+ // We should have at least one conformance by now, or we would have returned
673+ // above.
723674 assert (!conformances.empty ());
724675
725676 // If we have multiple conformances, first try to filter out any that are
@@ -768,27 +719,32 @@ LookupConformanceInModuleRequest::evaluate(
768719 return ProtocolConformanceRef (conformance);
769720 }
770721
771- // If the type is specialized, find the conformance for the generic type.
722+ // We now have a root conformance for the nominal's declared interface type.
723+ // If our type is specialized, apply a substitution map to the root
724+ // conformance.
772725 if (type->isSpecialized ()) {
773- // Figure out the type that's explicitly conforming to this protocol.
774- Type explicitConformanceType = conformance->getType ();
775- DeclContext *explicitConformanceDC = conformance->getDeclContext ();
776-
777- // If the explicit conformance is associated with a type that is different
778- // from the type we're checking, retrieve generic conformance.
779- if (!explicitConformanceType->isEqual (type)) {
780- // Gather the substitutions we need to map the generic conformance to
781- // the specialized conformance.
782- auto subMap = type->getContextSubstitutionMap (mod, explicitConformanceDC);
783-
784- // Create the specialized conformance entry.
785- auto result = ctx.getSpecializedConformance (type,
786- cast<RootProtocolConformance>(conformance), subMap);
787- return ProtocolConformanceRef (result);
726+ if (!conformance->getType ()->isEqual (type)) {
727+ // We use a builtin conformance for unconditional Copyable and Escapable
728+ // conformances. Avoid building a substitution map and just return the
729+ // correct builtin conformance for the specialized type.
730+ if (auto *builtinConf = dyn_cast<BuiltinProtocolConformance>(conformance)) {
731+ return ProtocolConformanceRef (
732+ ctx.getBuiltinConformance (type, protocol,
733+ builtinConf->getBuiltinConformanceKind ()));
734+ }
735+
736+ // Otherwise, we have a normal conformance, so we're going to build a
737+ // specialized conformance from the context substitution map of the
738+ // specialized type.
739+ auto *normalConf = cast<NormalProtocolConformance>(conformance);
740+ auto *conformanceDC = normalConf->getDeclContext ();
741+ auto subMap = type->getContextSubstitutionMap (mod, conformanceDC);
742+ return ProtocolConformanceRef (
743+ ctx.getSpecializedConformance (type, normalConf, subMap));
788744 }
789745 }
790746
791- // Record and return the simple conformance.
747+ // Return the root conformance.
792748 return ProtocolConformanceRef (conformance);
793749}
794750
0 commit comments