Skip to content

Commit 22f0f40

Browse files
committed
RequirementMachine: Copy over GSB logic where inheritance of JSExport protocol can be re-stated redundantly
1 parent 01fea56 commit 22f0f40

File tree

2 files changed

+49
-4
lines changed

2 files changed

+49
-4
lines changed

lib/AST/RequirementMachine/RewriteSystem.cpp

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -608,6 +608,41 @@ void RewriteSystem::verifyRewriteRules(ValidityPolicy policy) const {
608608
#undef ASSERT_RULE
609609
}
610610

611+
/// Determine whether this is a redundantly inheritable Objective-C protocol.
612+
///
613+
/// A redundantly-inheritable Objective-C protocol is one where we will
614+
/// silently accept a directly-stated redundant conformance to this protocol,
615+
/// and emit this protocol in the list of "inherited" protocols. There are
616+
/// two cases where we allow this:
617+
///
618+
// 1) For a protocol defined in Objective-C, so that we will match Clang's
619+
/// behavior, and
620+
/// 2) For an @objc protocol defined in Swift that directly inherits from
621+
/// JavaScriptCore's JSExport, which depends on this behavior.
622+
static bool isRedundantlyInheritableObjCProtocol(const ProtocolDecl *inheritingProto,
623+
const ProtocolDecl *proto) {
624+
if (!proto->isObjC()) return false;
625+
626+
// Check the two conditions in which we will suppress the diagnostic and
627+
// emit the redundant inheritance.
628+
if (!inheritingProto->hasClangNode() && !proto->getName().is("JSExport"))
629+
return false;
630+
631+
// If the inheriting protocol already has @_restatedObjCConformance with
632+
// this protocol, we're done.
633+
for (auto *attr : inheritingProto->getAttrs()
634+
.getAttributes<RestatedObjCConformanceAttr>()) {
635+
if (attr->Proto == proto) return true;
636+
}
637+
638+
// Otherwise, add @_restatedObjCConformance.
639+
auto &ctx = proto->getASTContext();
640+
const_cast<ProtocolDecl *>(inheritingProto)
641+
->getAttrs().add(new (ctx) RestatedObjCConformanceAttr(
642+
const_cast<ProtocolDecl *>(proto)));
643+
return true;
644+
}
645+
611646
/// Computes the set of explicit redundant requirements to
612647
/// emit warnings for in the source code.
613648
void RewriteSystem::computeRedundantRequirementDiagnostics(
@@ -689,8 +724,18 @@ void RewriteSystem::computeRedundantRequirementDiagnostics(
689724
auto isRedundantRule = [&](unsigned ruleID) {
690725
const auto &rule = getRules()[ruleID];
691726

692-
return (rule.isRedundant() &&
693-
nonExplicitNonRedundantRules.count(ruleID) == 0);
727+
if (!rule.isRedundant())
728+
return false;
729+
730+
if (nonExplicitNonRedundantRules.count(ruleID) > 0)
731+
return false;
732+
733+
if (rule.isProtocolRefinementRule(Context) &&
734+
isRedundantlyInheritableObjCProtocol(rule.getLHS()[0].getProtocol(),
735+
rule.getLHS()[1].getProtocol()))
736+
return false;
737+
738+
return true;
694739
};
695740

696741
// Finally walk through the written requirements, diagnosing any that are

test/decl/protocol/special/JSExport.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
// RUN: %target-typecheck-verify-swift
1+
// RUN: %target-typecheck-verify-swift -requirement-machine-protocol-signatures=on -requirement-machine-inferred-signatures=on
22

3-
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -I %S/Inputs/abi %s -emit-ir | %FileCheck %s
3+
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -I %S/Inputs/abi %s -emit-ir -requirement-machine-protocol-signatures=on -requirement-machine-inferred-signatures=on | %FileCheck %s
44

55
// REQUIRES: objc_interop
66
import Foundation

0 commit comments

Comments
 (0)