mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[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.
This commit is contained in:
@@ -19,6 +19,11 @@
|
||||
|
||||
namespace swift {
|
||||
|
||||
/// Find the imported module that treats the given nominal type as "preconcurrency", or return `nullptr`
|
||||
/// if there is no such module.
|
||||
ModuleDecl *moduleImportForPreconcurrency(NominalTypeDecl *nominal,
|
||||
const DeclContext *fromDC);
|
||||
|
||||
/// Determinate the appropriate diagnostic behavior to used when emitting
|
||||
/// concurrency diagnostics when referencing the given nominal type from the
|
||||
/// given declaration context.
|
||||
|
||||
@@ -8681,9 +8681,9 @@ GROUPED_ERROR(isolated_conformance_wrong_domain,IsolatedConformances,none,
|
||||
GROUPED_WARNING(isolated_conformance_will_become_nonisolated,IsolatedConformances,none,
|
||||
"conformance of %0 to %1 should be marked 'nonisolated' to retain its behavior with upcoming feature 'InferIsolatedConformances'",
|
||||
(const ValueDecl *, const ValueDecl *))
|
||||
GROUPED_WARNING(isolated_conformance_to_sendable_metatype,IsolatedConformances,none,
|
||||
"%0 conformance of %1 to SendableMetatype-inheriting %kind2 can never "
|
||||
"be used with generic code", (ActorIsolation, Type, const ValueDecl *))
|
||||
GROUPED_ERROR(isolated_conformance_to_sendable_metatype,IsolatedConformances,none,
|
||||
"cannot form %0 conformance of %1 to SendableMetatype-inheriting %kind2",
|
||||
(ActorIsolation, Type, const ValueDecl *))
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// MARK: @_inheritActorContext
|
||||
|
||||
@@ -19,29 +19,35 @@
|
||||
|
||||
using namespace swift;
|
||||
|
||||
ModuleDecl *swift::moduleImportForPreconcurrency(
|
||||
NominalTypeDecl *nominal, const DeclContext *fromDC) {
|
||||
// If the declaration itself has the @preconcurrency attribute,
|
||||
// respect it.
|
||||
if (nominal->getAttrs().hasAttribute<PreconcurrencyAttr>()) {
|
||||
return nominal->getParentModule();
|
||||
}
|
||||
|
||||
// Determine whether this nominal type is visible via a @preconcurrency
|
||||
// import.
|
||||
auto import = nominal->findImport(fromDC);
|
||||
auto sourceFile = fromDC->getParentSourceFile();
|
||||
|
||||
if (!import || !import->options.contains(ImportFlags::Preconcurrency))
|
||||
return nullptr;
|
||||
|
||||
if (sourceFile)
|
||||
sourceFile->setImportUsedPreconcurrency(*import);
|
||||
|
||||
return import->module.importedModule;
|
||||
}
|
||||
|
||||
std::optional<DiagnosticBehavior>
|
||||
swift::getConcurrencyDiagnosticBehaviorLimit(NominalTypeDecl *nominal,
|
||||
const DeclContext *fromDC,
|
||||
bool ignoreExplicitConformance) {
|
||||
ModuleDecl *importedModule = nullptr;
|
||||
if (nominal->getAttrs().hasAttribute<PreconcurrencyAttr>()) {
|
||||
// If the declaration itself has the @preconcurrency attribute,
|
||||
// respect it.
|
||||
importedModule = nominal->getParentModule();
|
||||
} else {
|
||||
// Determine whether this nominal type is visible via a @preconcurrency
|
||||
// import.
|
||||
auto import = nominal->findImport(fromDC);
|
||||
auto sourceFile = fromDC->getParentSourceFile();
|
||||
|
||||
if (!import || !import->options.contains(ImportFlags::Preconcurrency))
|
||||
return std::nullopt;
|
||||
|
||||
if (sourceFile)
|
||||
sourceFile->setImportUsedPreconcurrency(*import);
|
||||
|
||||
importedModule = import->module.importedModule;
|
||||
}
|
||||
ModuleDecl *importedModule = moduleImportForPreconcurrency(nominal, fromDC);
|
||||
if (!importedModule)
|
||||
return std::nullopt;
|
||||
|
||||
// When the type is explicitly non-Sendable, @preconcurrency imports
|
||||
// downgrade the diagnostic to a warning in Swift 6.
|
||||
|
||||
@@ -8303,18 +8303,20 @@ RawConformanceIsolationRequest::evaluate(
|
||||
globalActorTypeExpr->setType(MetatypeType::get(globalActorType));
|
||||
}
|
||||
|
||||
// Isolated conformance to a SendableMetatype-inheriting protocol can
|
||||
// never be used generically. Warn about it.
|
||||
// Cannot form an isolated conformance to a SendableMetatype-inheriting
|
||||
// protocol. Diagnose it.
|
||||
if (auto sendableMetatype =
|
||||
ctx.getProtocol(KnownProtocolKind::SendableMetatype)) {
|
||||
if (proto->inheritsFrom(sendableMetatype) &&
|
||||
!getActorIsolation(proto).preconcurrency()) {
|
||||
if (proto->inheritsFrom(sendableMetatype)) {
|
||||
bool isPreconcurrency = moduleImportForPreconcurrency(
|
||||
proto, conformance->getDeclContext()) != nullptr;
|
||||
ctx.Diags.diagnose(
|
||||
conformance->getLoc(),
|
||||
diag::isolated_conformance_to_sendable_metatype,
|
||||
ActorIsolation::forGlobalActor(globalActorType),
|
||||
conformance->getType(),
|
||||
proto);
|
||||
proto)
|
||||
.limitBehaviorIf(isPreconcurrency, DiagnosticBehavior::Warning);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -151,7 +151,7 @@ protocol R: SendableMetatype {
|
||||
func f()
|
||||
}
|
||||
|
||||
// expected-warning@+1{{main actor-isolated conformance of 'RSendableSMainActor' to SendableMetatype-inheriting protocol 'R' can never be used with generic code}}
|
||||
// expected-error@+1{{cannot form main actor-isolated conformance of 'RSendableSMainActor' to SendableMetatype-inheriting protocol 'R'}}
|
||||
@MainActor struct RSendableSMainActor: @MainActor R {
|
||||
func f() { }
|
||||
}
|
||||
|
||||
22
test/Concurrency/isolated_conformance_6.swift
Normal file
22
test/Concurrency/isolated_conformance_6.swift
Normal file
@@ -0,0 +1,22 @@
|
||||
// RUN: %target-swift-frontend -typecheck -verify -target %target-swift-5.1-abi-triple -swift-version 6 %s
|
||||
|
||||
// REQUIRES: concurrency
|
||||
|
||||
protocol P: SendableMetatype {
|
||||
func f()
|
||||
}
|
||||
|
||||
@preconcurrency
|
||||
protocol Q: SendableMetatype {
|
||||
func f()
|
||||
}
|
||||
|
||||
// expected-error@+1{{cannot form main actor-isolated conformance of 'PSendableSMainActor' to SendableMetatype-inheriting protocol 'P'}}
|
||||
@MainActor struct PSendableSMainActor: @MainActor P {
|
||||
func f() { }
|
||||
}
|
||||
|
||||
// expected-warning@+1{{cannot form main actor-isolated conformance of 'QSendableSMainActor' to SendableMetatype-inheriting protocol 'Q'}}
|
||||
@MainActor struct QSendableSMainActor: @MainActor Q {
|
||||
func f() { }
|
||||
}
|
||||
Reference in New Issue
Block a user