Skip to content

Commit abe099d

Browse files
authored
Merge pull request #40360 from DougGregor/align-unavailable-sendable
Align unavailable Sendable diagnostics with the proposal for staging Sendable
2 parents 8163168 + f9636af commit abe099d

File tree

2 files changed

+65
-29
lines changed

2 files changed

+65
-29
lines changed

lib/Sema/TypeCheckAvailability.cpp

Lines changed: 23 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1779,6 +1779,22 @@ void TypeChecker::diagnosePotentialAccessorUnavailability(
17791779
fixAvailability(ReferenceRange, ReferenceDC, RequiredRange, Context);
17801780
}
17811781

1782+
static DiagnosticBehavior
1783+
behaviorLimitForExplicitUnavailability(
1784+
const RootProtocolConformance *rootConf,
1785+
const DeclContext *fromDC) {
1786+
auto protoDecl = rootConf->getProtocol();
1787+
1788+
// Soften errors about unavailable `Sendable` conformances depending on the
1789+
// concurrency checking mode
1790+
if (protoDecl->isSpecificProtocol(KnownProtocolKind::Sendable) ||
1791+
protoDecl->isSpecificProtocol(KnownProtocolKind::UnsafeSendable)) {
1792+
return SendableCheckContext(fromDC).defaultDiagnosticBehavior();
1793+
}
1794+
1795+
return DiagnosticBehavior::Unspecified;
1796+
}
1797+
17821798
void TypeChecker::diagnosePotentialUnavailability(
17831799
const RootProtocolConformance *rootConf,
17841800
const ExtensionDecl *ext,
@@ -1795,11 +1811,13 @@ void TypeChecker::diagnosePotentialUnavailability(
17951811
auto diagID = (ctx.LangOpts.EnableConformanceAvailabilityErrors
17961812
? diag::conformance_availability_only_version_newer
17971813
: diag::conformance_availability_only_version_newer_warn);
1814+
auto behavior = behaviorLimitForExplicitUnavailability(rootConf, dc);
17981815
auto err =
17991816
ctx.Diags.diagnose(
18001817
loc, diagID,
18011818
type, proto, prettyPlatformString(targetPlatform(ctx.LangOpts)),
18021819
reason.getRequiredOSVersionRange().getLowerEndpoint());
1820+
err.limitBehavior(behavior);
18031821

18041822
// Direct a fixit to the error if an existing guard is nearly-correct
18051823
if (fixAvailabilityByNarrowingNearbyVersionCheck(loc, dc,
@@ -2422,31 +2440,6 @@ bool swift::diagnoseExplicitUnavailability(const ValueDecl *D, SourceRange R,
24222440
});
24232441
}
24242442

2425-
static DiagnosticBehavior
2426-
behaviorLimitForExplicitUnavailability(const RootProtocolConformance *rootConf) {
2427-
auto protoDecl = rootConf->getProtocol();
2428-
2429-
// Soften errors about unavailable `Sendable` conformances depending on the
2430-
// concurrency checking mode
2431-
if (protoDecl->isSpecificProtocol(KnownProtocolKind::Sendable) ||
2432-
protoDecl->isSpecificProtocol(KnownProtocolKind::UnsafeSendable)) {
2433-
// TODO: Base this on concurrency checking mode from ExportContext so it
2434-
// detects when you're in concurrency code without -warn-concurrency.
2435-
auto &langOpts = protoDecl->getASTContext().LangOpts;
2436-
if (langOpts.isSwiftVersionAtLeast(6))
2437-
/* fall through */;
2438-
else if (!langOpts.WarnConcurrency)
2439-
// TODO: Needs more conditions--should only do this if we aren't in a
2440-
// concurrent context, and either the import or the declaration is
2441-
// @predatesConcurrency.
2442-
return DiagnosticBehavior::Ignore;
2443-
else
2444-
return DiagnosticBehavior::Warning;
2445-
}
2446-
2447-
return DiagnosticBehavior::Unspecified;
2448-
}
2449-
24502443
/// Emit a diagnostic for references to declarations that have been
24512444
/// marked as unavailable, either through "unavailable" or "obsoleted:".
24522445
bool swift::diagnoseExplicitUnavailability(SourceLoc loc,
@@ -2482,11 +2475,12 @@ bool swift::diagnoseExplicitUnavailability(SourceLoc loc,
24822475
// This was platform-specific; indicate the platform.
24832476
platform = attr->prettyPlatformString();
24842477
break;
2485-
} else {
2486-
// Downgrade unavailable Sendable conformances to warnings prior to
2487-
// Swift 6.
2488-
behavior = behaviorLimitForExplicitUnavailability(rootConf);
24892478
}
2479+
2480+
// Downgrade unavailable Sendable conformance diagnostics where
2481+
// appropriate.
2482+
behavior = behaviorLimitForExplicitUnavailability(
2483+
rootConf, where.getDeclContext());
24902484
LLVM_FALLTHROUGH;
24912485

24922486
case PlatformAgnosticAvailabilityKind::SwiftVersionSpecific:
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// RUN: %target-typecheck-verify-swift
2+
// REQUIRES: concurrency
3+
// REQUIRES: OS=macosx
4+
5+
@available(SwiftStdlib 5.1, *)
6+
struct NS1 { }
7+
8+
@available(SwiftStdlib 5.1, *)
9+
@available(*, unavailable)
10+
extension NS1: Sendable { }
11+
// expected-note@-1 2{{conformance of 'NS1' to 'Sendable' has been explicitly marked unavailable here}}
12+
13+
@available(SwiftStdlib 5.1, *)
14+
struct NS2 { // expected-note{{consider making struct 'NS2' conform to the 'Sendable' protocol}}
15+
var ns1: NS1
16+
}
17+
18+
@available(SwiftStdlib 5.1, *)
19+
struct NS3 { }
20+
21+
@available(SwiftStdlib 5.3, *)
22+
extension NS3: Sendable { }
23+
24+
@available(SwiftStdlib 5.1, *)
25+
func acceptCV<T: Sendable>(_: T) { }
26+
27+
@available(SwiftStdlib 5.1, *)
28+
func testCV(ns1: NS1, ns1array: [NS1], ns2: NS2, ns3: NS3) {
29+
acceptCV(ns1)
30+
acceptCV(ns1array)
31+
acceptCV(ns2)
32+
acceptCV(ns3)
33+
}
34+
35+
@available(SwiftStdlib 5.1, *)
36+
func testCV(ns1: NS1, ns1array: [NS1], ns2: NS2, ns3: NS3) async {
37+
acceptCV(ns1) // expected-warning{{conformance of 'NS1' to 'Sendable' is unavailable}}
38+
acceptCV(ns1array) // expected-warning{{conformance of 'NS1' to 'Sendable' is unavailable}}
39+
acceptCV(ns2) // expected-warning{{type 'NS2' does not conform to the 'Sendable' protocol}}
40+
acceptCV(ns3) // expected-warning{{conformance of 'NS3' to 'Sendable' is only available in macOS 11.0 or newer}}
41+
// expected-note@-1{{add 'if #available' version check}}
42+
}

0 commit comments

Comments
 (0)