@@ -3833,6 +3833,25 @@ void ConformanceChecker::checkNonFinalClassWitness(ValueDecl *requirement,
3833
3833
}
3834
3834
}
3835
3835
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
+ return fnDecl && fnDecl->isGeneric () &&
3844
+ llvm::all_of (
3845
+ fnDecl->getGenericRequirements (), [&](Requirement genericReq) {
3846
+ return genericReq.getKind () == RequirementKind::Conformance &&
3847
+ (genericReq.getProtocolDecl () ==
3848
+ ctx.getProtocol (
3849
+ KnownProtocolKind::RawRepresentable) ||
3850
+ genericReq.getProtocolDecl () ==
3851
+ conformance->getProtocol ());
3852
+ });
3853
+ }
3854
+
3836
3855
ResolveWitnessResult
3837
3856
ConformanceChecker::resolveWitnessViaLookup (ValueDecl *requirement) {
3838
3857
assert (!isa<AssociatedTypeDecl>(requirement) && " Use resolveTypeWitnessVia*" );
@@ -3881,6 +3900,16 @@ ConformanceChecker::resolveWitnessViaLookup(ValueDecl *requirement) {
3881
3900
bool considerRenames =
3882
3901
!canDerive && !requirement->getAttrs ().hasAttribute <OptionalAttr>() &&
3883
3902
!requirement->getAttrs ().isUnavailable (getASTContext ());
3903
+
3904
+ auto &ctx = getASTContext ();
3905
+ bool isEquatableConformance = Conformance->getProtocol () ==
3906
+ ctx.getProtocol (KnownProtocolKind::Equatable);
3907
+
3908
+ auto decl = Conformance->getDeclContext ()->getSelfNominalTypeDecl ();
3909
+ auto *enumDecl = dyn_cast_or_null<EnumDecl>(decl);
3910
+ bool isSwiftRawRepresentableEnum =
3911
+ enumDecl && enumDecl->hasRawType () && !enumDecl->isObjC ();
3912
+
3884
3913
if (findBestWitness (requirement,
3885
3914
considerRenames ? &ignoringNames : nullptr ,
3886
3915
Conformance,
@@ -3889,6 +3918,17 @@ ConformanceChecker::resolveWitnessViaLookup(ValueDecl *requirement) {
3889
3918
const auto &best = matches[bestIdx];
3890
3919
auto witness = best.Witness ;
3891
3920
3921
+ if (canDerive && isSwiftRawRepresentableEnum && isEquatableConformance) {
3922
+ // For swift enum types that can derive equatable conformance,
3923
+ // if the best witness is default generic conditional conforming
3924
+ // `func == <T : RawRepresentable>(lhs: T, rhs: T) -> Bool where
3925
+ // T.RawValue : Equatable` let's return as missing and derive
3926
+ // the conformance since it is possible.
3927
+ if (isRawRepresentableGenericFunction (ctx, witness, Conformance)) {
3928
+ return ResolveWitnessResult::Missing;
3929
+ }
3930
+ }
3931
+
3892
3932
// If the name didn't actually line up, complain.
3893
3933
if (ignoringNames &&
3894
3934
requirement->getName () != best.Witness ->getName () &&
0 commit comments