Skip to content

Commit 56e38b3

Browse files
committed
[SE-0470] Promote isolated-conformance-to-sendable-metatype protocol to error
Forming an isolated conformance to a SendableMetatype-inherting protocol opens up a soundness hole any time the conformance is used. Reword the recently-introduced diagnostic for this case and promote it to an error (except when it's preconcurrency). Fixes rdar://154808002.
1 parent 62770ff commit 56e38b3

File tree

6 files changed

+63
-28
lines changed

6 files changed

+63
-28
lines changed

include/swift/AST/Concurrency.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,11 @@
1919

2020
namespace swift {
2121

22+
/// Find the imported module that treats the given nominal type as "preconcurrency", or return `nullptr`
23+
/// if there is no such module.
24+
ModuleDecl *moduleImportForPreconcurrency(NominalTypeDecl *nominal,
25+
const DeclContext *fromDC);
26+
2227
/// Determinate the appropriate diagnostic behavior to used when emitting
2328
/// concurrency diagnostics when referencing the given nominal type from the
2429
/// given declaration context.

include/swift/AST/DiagnosticsSema.def

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8681,9 +8681,9 @@ GROUPED_ERROR(isolated_conformance_wrong_domain,IsolatedConformances,none,
86818681
GROUPED_WARNING(isolated_conformance_will_become_nonisolated,IsolatedConformances,none,
86828682
"conformance of %0 to %1 should be marked 'nonisolated' to retain its behavior with upcoming feature 'InferIsolatedConformances'",
86838683
(const ValueDecl *, const ValueDecl *))
8684-
GROUPED_WARNING(isolated_conformance_to_sendable_metatype,IsolatedConformances,none,
8685-
"%0 conformance of %1 to SendableMetatype-inheriting %kind2 can never "
8686-
"be used with generic code", (ActorIsolation, Type, const ValueDecl *))
8684+
GROUPED_ERROR(isolated_conformance_to_sendable_metatype,IsolatedConformances,none,
8685+
"cannot form %0 conformance of %1 to SendableMetatype-inheriting %kind2",
8686+
(ActorIsolation, Type, const ValueDecl *))
86878687
86888688
//===----------------------------------------------------------------------===//
86898689
// MARK: @_inheritActorContext

lib/AST/Concurrency.cpp

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -19,29 +19,35 @@
1919

2020
using namespace swift;
2121

22-
std::optional<DiagnosticBehavior>
23-
swift::getConcurrencyDiagnosticBehaviorLimit(NominalTypeDecl *nominal,
24-
const DeclContext *fromDC,
25-
bool ignoreExplicitConformance) {
26-
ModuleDecl *importedModule = nullptr;
22+
ModuleDecl *swift::moduleImportForPreconcurrency(
23+
NominalTypeDecl *nominal, const DeclContext *fromDC) {
24+
// If the declaration itself has the @preconcurrency attribute,
25+
// respect it.
2726
if (nominal->getAttrs().hasAttribute<PreconcurrencyAttr>()) {
28-
// If the declaration itself has the @preconcurrency attribute,
29-
// respect it.
30-
importedModule = nominal->getParentModule();
31-
} else {
32-
// Determine whether this nominal type is visible via a @preconcurrency
33-
// import.
34-
auto import = nominal->findImport(fromDC);
35-
auto sourceFile = fromDC->getParentSourceFile();
27+
return nominal->getParentModule();
28+
}
3629

37-
if (!import || !import->options.contains(ImportFlags::Preconcurrency))
38-
return std::nullopt;
30+
// Determine whether this nominal type is visible via a @preconcurrency
31+
// import.
32+
auto import = nominal->findImport(fromDC);
33+
auto sourceFile = fromDC->getParentSourceFile();
3934

40-
if (sourceFile)
41-
sourceFile->setImportUsedPreconcurrency(*import);
35+
if (!import || !import->options.contains(ImportFlags::Preconcurrency))
36+
return nullptr;
4237

43-
importedModule = import->module.importedModule;
44-
}
38+
if (sourceFile)
39+
sourceFile->setImportUsedPreconcurrency(*import);
40+
41+
return import->module.importedModule;
42+
}
43+
44+
std::optional<DiagnosticBehavior>
45+
swift::getConcurrencyDiagnosticBehaviorLimit(NominalTypeDecl *nominal,
46+
const DeclContext *fromDC,
47+
bool ignoreExplicitConformance) {
48+
ModuleDecl *importedModule = moduleImportForPreconcurrency(nominal, fromDC);
49+
if (!importedModule)
50+
return std::nullopt;
4551

4652
// When the type is explicitly non-Sendable, @preconcurrency imports
4753
// downgrade the diagnostic to a warning in Swift 6.

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8303,18 +8303,20 @@ RawConformanceIsolationRequest::evaluate(
83038303
globalActorTypeExpr->setType(MetatypeType::get(globalActorType));
83048304
}
83058305

8306-
// Isolated conformance to a SendableMetatype-inheriting protocol can
8307-
// never be used generically. Warn about it.
8306+
// Cannot form an isolated conformance to a SendableMetatype-inheriting
8307+
// protocol. Diagnose it.
83088308
if (auto sendableMetatype =
83098309
ctx.getProtocol(KnownProtocolKind::SendableMetatype)) {
8310-
if (proto->inheritsFrom(sendableMetatype) &&
8311-
!getActorIsolation(proto).preconcurrency()) {
8310+
if (proto->inheritsFrom(sendableMetatype)) {
8311+
bool isPreconcurrency = moduleImportForPreconcurrency(
8312+
proto, conformance->getDeclContext()) != nullptr;
83128313
ctx.Diags.diagnose(
83138314
conformance->getLoc(),
83148315
diag::isolated_conformance_to_sendable_metatype,
83158316
ActorIsolation::forGlobalActor(globalActorType),
83168317
conformance->getType(),
8317-
proto);
8318+
proto)
8319+
.limitBehaviorIf(isPreconcurrency, DiagnosticBehavior::Warning);
83188320
}
83198321
}
83208322

test/Concurrency/isolated_conformance.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ protocol R: SendableMetatype {
151151
func f()
152152
}
153153

154-
// expected-warning@+1{{main actor-isolated conformance of 'RSendableSMainActor' to SendableMetatype-inheriting protocol 'R' can never be used with generic code}}
154+
// expected-error@+1{{cannot form main actor-isolated conformance of 'RSendableSMainActor' to SendableMetatype-inheriting protocol 'R'}}
155155
@MainActor struct RSendableSMainActor: @MainActor R {
156156
func f() { }
157157
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// RUN: %target-swift-frontend -typecheck -verify -target %target-swift-5.1-abi-triple -swift-version 6 %s
2+
3+
// REQUIRES: concurrency
4+
5+
protocol P: SendableMetatype {
6+
func f()
7+
}
8+
9+
@preconcurrency
10+
protocol Q: SendableMetatype {
11+
func f()
12+
}
13+
14+
// expected-error@+1{{cannot form main actor-isolated conformance of 'PSendableSMainActor' to SendableMetatype-inheriting protocol 'P'}}
15+
@MainActor struct PSendableSMainActor: @MainActor P {
16+
func f() { }
17+
}
18+
19+
// expected-warning@+1{{cannot form main actor-isolated conformance of 'QSendableSMainActor' to SendableMetatype-inheriting protocol 'Q'}}
20+
@MainActor struct QSendableSMainActor: @MainActor Q {
21+
func f() { }
22+
}

0 commit comments

Comments
 (0)