Skip to content

[SE-0470] Promote isolated-conformance-to-sendable-metatype protocol to an error #82846

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions include/swift/AST/Concurrency.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
6 changes: 3 additions & 3 deletions include/swift/AST/DiagnosticsSema.def
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
44 changes: 25 additions & 19 deletions lib/AST/Concurrency.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,29 +19,35 @@

using namespace swift;

std::optional<DiagnosticBehavior>
swift::getConcurrencyDiagnosticBehaviorLimit(NominalTypeDecl *nominal,
const DeclContext *fromDC,
bool ignoreExplicitConformance) {
ModuleDecl *importedModule = nullptr;
ModuleDecl *swift::moduleImportForPreconcurrency(
NominalTypeDecl *nominal, const DeclContext *fromDC) {
// If the declaration itself has the @preconcurrency attribute,
// respect it.
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();
return nominal->getParentModule();
}

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

if (sourceFile)
sourceFile->setImportUsedPreconcurrency(*import);
if (!import || !import->options.contains(ImportFlags::Preconcurrency))
return nullptr;

importedModule = import->module.importedModule;
}
if (sourceFile)
sourceFile->setImportUsedPreconcurrency(*import);

return import->module.importedModule;
}

std::optional<DiagnosticBehavior>
swift::getConcurrencyDiagnosticBehaviorLimit(NominalTypeDecl *nominal,
const DeclContext *fromDC,
bool ignoreExplicitConformance) {
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.
Expand Down
12 changes: 7 additions & 5 deletions lib/Sema/TypeCheckConcurrency.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}

Expand Down
2 changes: 1 addition & 1 deletion test/Concurrency/isolated_conformance.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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() { }
}
Expand Down
22 changes: 22 additions & 0 deletions test/Concurrency/isolated_conformance_6.swift
Original file line number Diff line number Diff line change
@@ -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() { }
}