@@ -3833,6 +3833,30 @@ void ConformanceChecker::checkNonFinalClassWitness(ValueDecl *requirement,
38333833 }
38343834}
38353835
3836+ // If the given witness matches a generic RawRepresentable function conforming
3837+ // with a given protocol e.g. `func == <T : RawRepresentable>(lhs: T, rhs: T) ->
3838+ // Bool where T.RawValue : Equatable`
3839+ static bool isRawRepresentableGenericFunction (
3840+ ASTContext &ctx, const ValueDecl *witness,
3841+ const NormalProtocolConformance *conformance) {
3842+ auto *fnDecl = dyn_cast<AbstractFunctionDecl>(witness);
3843+ if (!fnDecl || !fnDecl->isStdlibDecl ())
3844+ return false ;
3845+
3846+ return fnDecl->isGeneric () && fnDecl->getGenericParams ()->size () == 1 &&
3847+ fnDecl->getGenericRequirements ().size () == 2 &&
3848+ llvm::all_of (
3849+ fnDecl->getGenericRequirements (), [&](Requirement genericReq) {
3850+ if (genericReq.getKind () != RequirementKind::Conformance)
3851+ return false ;
3852+ return genericReq.getProtocolDecl () ==
3853+ ctx.getProtocol (
3854+ KnownProtocolKind::RawRepresentable) ||
3855+ genericReq.getProtocolDecl () ==
3856+ conformance->getProtocol ();
3857+ });
3858+ }
3859+
38363860ResolveWitnessResult
38373861ConformanceChecker::resolveWitnessViaLookup (ValueDecl *requirement) {
38383862 assert (!isa<AssociatedTypeDecl>(requirement) && " Use resolveTypeWitnessVia*" );
@@ -3881,6 +3905,16 @@ ConformanceChecker::resolveWitnessViaLookup(ValueDecl *requirement) {
38813905 bool considerRenames =
38823906 !canDerive && !requirement->getAttrs ().hasAttribute <OptionalAttr>() &&
38833907 !requirement->getAttrs ().isUnavailable (getASTContext ());
3908+
3909+ auto &ctx = getASTContext ();
3910+ bool isEquatableConformance = Conformance->getProtocol () ==
3911+ ctx.getProtocol (KnownProtocolKind::Equatable);
3912+
3913+ auto decl = Conformance->getDeclContext ()->getSelfNominalTypeDecl ();
3914+ auto *enumDecl = dyn_cast_or_null<EnumDecl>(decl);
3915+ bool isSwiftRawRepresentableEnum =
3916+ enumDecl && enumDecl->hasRawType () && !enumDecl->isObjC ();
3917+
38843918 if (findBestWitness (requirement,
38853919 considerRenames ? &ignoringNames : nullptr ,
38863920 Conformance,
@@ -3889,6 +3923,17 @@ ConformanceChecker::resolveWitnessViaLookup(ValueDecl *requirement) {
38893923 const auto &best = matches[bestIdx];
38903924 auto witness = best.Witness ;
38913925
3926+ if (canDerive && isSwiftRawRepresentableEnum && isEquatableConformance) {
3927+ // For swift enum types that can derive equatable conformance,
3928+ // if the best witness is default generic conditional conforming
3929+ // `func == <T : RawRepresentable>(lhs: T, rhs: T) -> Bool where
3930+ // T.RawValue : Equatable` let's return as missing and derive
3931+ // the conformance since it is possible.
3932+ if (isRawRepresentableGenericFunction (ctx, witness, Conformance)) {
3933+ return ResolveWitnessResult::Missing;
3934+ }
3935+ }
3936+
38923937 // If the name didn't actually line up, complain.
38933938 if (ignoringNames &&
38943939 requirement->getName () != best.Witness ->getName () &&
0 commit comments