Skip to content

Commit 58a9435

Browse files
committed
Sema: Don't complain about implied Sendable conformance of imported type being retroactive
- Fixes rdar://145184871.
1 parent 1e35fff commit 58a9435

File tree

5 files changed

+43
-11
lines changed

5 files changed

+43
-11
lines changed

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6935,13 +6935,16 @@ bool swift::checkSendableConformance(
69356935
return false;
69366936
}
69376937

6938+
// An implied conformance is generated when you state a conformance to
6939+
// a protocol P that inherits from Sendable.
6940+
bool wasImplied = (conformance->getSourceKind() ==
6941+
ConformanceEntryKind::Implied);
6942+
69386943
// Sendable can only be used in the same source file.
69396944
auto conformanceDecl = conformanceDC->getAsDecl();
69406945
SendableCheckContext checkContext(conformanceDC, check);
69416946
DiagnosticBehavior behavior = checkContext.defaultDiagnosticBehavior();
6942-
if (conformance->getSourceKind() == ConformanceEntryKind::Implied &&
6943-
conformance->getProtocol()->isSpecificProtocol(
6944-
KnownProtocolKind::Sendable)) {
6947+
if (wasImplied) {
69456948
if (auto optBehavior = checkContext.preconcurrencyBehavior(
69466949
nominal, /*ignoreExplicitConformance=*/true))
69476950
behavior = *optBehavior;
@@ -6950,12 +6953,14 @@ bool swift::checkSendableConformance(
69506953
if (conformanceDC->getOutermostParentSourceFile() &&
69516954
conformanceDC->getOutermostParentSourceFile() !=
69526955
nominal->getOutermostParentSourceFile()) {
6953-
conformanceDecl->diagnose(diag::concurrent_value_outside_source_file,
6954-
nominal)
6955-
.limitBehaviorUntilSwiftVersion(behavior, 6);
6956+
if (!(nominal->hasClangNode() && wasImplied)) {
6957+
conformanceDecl->diagnose(diag::concurrent_value_outside_source_file,
6958+
nominal)
6959+
.limitBehaviorUntilSwiftVersion(behavior, 6);
69566960

6957-
if (behavior == DiagnosticBehavior::Unspecified)
6958-
return true;
6961+
if (behavior == DiagnosticBehavior::Unspecified)
6962+
return true;
6963+
}
69596964
}
69606965

69616966
if (classDecl && classDecl->getParentSourceFile()) {
@@ -6993,7 +6998,7 @@ bool swift::checkSendableConformance(
69936998
// a Sendable conformance. The implied conformance is unconditional, so check
69946999
// the storage for sendability as if the conformance was declared on the nominal,
69957000
// and not some (possibly constrained) extension.
6996-
if (conformance->getSourceKind() == ConformanceEntryKind::Implied)
7001+
if (wasImplied)
69977002
conformanceDC = nominal;
69987003
return checkSendableInstanceStorage(nominal, conformanceDC, check);
69997004
}

lib/Sema/TypeCheckDeclPrimary.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1844,6 +1844,18 @@ static void diagnoseRetroactiveConformances(
18441844
bool inserted = protocols.insert(std::make_pair(
18451845
proto, conformance->isRetroactive())).second;
18461846
ASSERT(inserted);
1847+
1848+
if (proto->isSpecificProtocol(KnownProtocolKind::SendableMetatype)) {
1849+
protocolsWithRetroactiveAttr.insert(proto);
1850+
}
1851+
1852+
// Implied conformance to Sendable is a special case that should not be
1853+
// diagnosed. Pretend it's always @retroactive.
1854+
if (conformance->getSourceKind() == ConformanceEntryKind::Implied &&
1855+
proto->isSpecificProtocol(KnownProtocolKind::Sendable) &&
1856+
extendedNominalDecl->hasClangNode()) {
1857+
protocolsWithRetroactiveAttr.insert(proto);
1858+
}
18471859
}
18481860

18491861
for (const InheritedEntry &entry : ext->getInherited().getEntries()) {
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -emit-sil -o /dev/null -I %S/Inputs/custom-modules %s -verify -parse-as-library -swift-version 6
2+
3+
// REQUIRES: objc_interop
4+
// REQUIRES: concurrency
5+
6+
import Foundation
7+
8+
extension CGRect: Sendable {}
9+
// expected-warning@-1 {{extension declares a conformance of imported type 'CGRect' to imported protocol 'Sendable'; this will not behave correctly if the owners of 'CoreGraphics' introduce this conformance in the future}}
10+
// expected-note@-2 {{add '@retroactive' to silence this warning}}
11+
// expected-error@-3 {{conformance to 'Sendable' must occur in the same source file as struct 'CGRect'; use '@unchecked Sendable' for retroactive conformance}}
12+
protocol P: Sendable {}
13+
14+
extension CGPoint: P {}
15+

test/Inputs/clang-importer-sdk/swift-modules/CoreFoundation.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
protocol _CFObject: Hashable {}
44

55
#if CGFLOAT_IN_COREFOUNDATION
6-
public struct CGFloat {
6+
public struct CGFloat: @unchecked Sendable {
77
#if _pointerBitWidth(_32)
88
public typealias UnderlyingType = Float
99
#elseif _pointerBitWidth(_64)

test/Inputs/clang-importer-sdk/swift-modules/CoreGraphics.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ public func == (lhs: CGPoint, rhs: CGPoint) -> Bool {
66
}
77

88
#if !CGFLOAT_IN_COREFOUNDATION
9-
public struct CGFloat {
9+
public struct CGFloat: Sendable {
1010
#if _pointerBitWidth(_32)
1111
public typealias UnderlyingType = Float
1212
#elseif _pointerBitWidth(_64)

0 commit comments

Comments
 (0)