Make InferIsolatedConformances a migratable upcoming feature

When migrating, provide warnings that add 'nonisolated' to nonisolated
conformances that don't already have it and would end up being inferred
to be isolated under the upcoming feature.
This commit is contained in:
Doug Gregor
2025-05-20 16:07:44 +01:00
parent 799e0f81b0
commit a32782bcbc
4 changed files with 80 additions and 1 deletions

View File

@@ -8619,6 +8619,9 @@ GROUPED_ERROR(isolated_conformance_with_sendable_simple,IsolatedConformances,
GROUPED_ERROR(isolated_conformance_wrong_domain,IsolatedConformances,none, GROUPED_ERROR(isolated_conformance_wrong_domain,IsolatedConformances,none,
"%0 conformance of %1 to %2 cannot be used in %3 context", "%0 conformance of %1 to %2 cannot be used in %3 context",
(ActorIsolation, Type, DeclName, ActorIsolation)) (ActorIsolation, Type, DeclName, ActorIsolation))
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 *))
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// MARK: @_inheritActorContext // MARK: @_inheritActorContext

View File

@@ -283,7 +283,7 @@ UPCOMING_FEATURE(GlobalActorIsolatedTypesUsability, 0434, 6)
MIGRATABLE_UPCOMING_FEATURE(ExistentialAny, 335, 7) MIGRATABLE_UPCOMING_FEATURE(ExistentialAny, 335, 7)
UPCOMING_FEATURE(InternalImportsByDefault, 409, 7) UPCOMING_FEATURE(InternalImportsByDefault, 409, 7)
UPCOMING_FEATURE(MemberImportVisibility, 444, 7) UPCOMING_FEATURE(MemberImportVisibility, 444, 7)
UPCOMING_FEATURE(InferIsolatedConformances, 470, 7) MIGRATABLE_UPCOMING_FEATURE(InferIsolatedConformances, 470, 7)
MIGRATABLE_UPCOMING_FEATURE(NonisolatedNonsendingByDefault, 461, 7) MIGRATABLE_UPCOMING_FEATURE(NonisolatedNonsendingByDefault, 461, 7)
// Optional language features / modes // Optional language features / modes

View File

@@ -6675,6 +6675,49 @@ void TypeChecker::checkConformancesInContext(IterableDeclContext *idc) {
} }
} }
// If we are migrating to InferIsolatedConformances, and the
// nominal type is global-actor-isolated, look for conformances
// that are nonisolated but were not explicitly marked as such.
// These conformances will need to be marked 'nonisolated' to
// retain their current behavior.
if (Context.LangOpts
.getFeatureState(Feature::InferIsolatedConformances)
.isEnabledForMigration() &&
getActorIsolation(const_cast<NominalTypeDecl *>(nominal))
.isGlobalActor()) {
for (auto conformance : conformances) {
auto normal = dyn_cast<NormalProtocolConformance>(conformance);
if (!normal)
continue;
// Explicit nonisolated and @preconcurrency suppress this.
auto options = normal->getOptions();
if (options.contains(ProtocolConformanceFlags::Nonisolated) ||
options.contains(ProtocolConformanceFlags::Preconcurrency))
continue;
// Only consider conformances that were explicitly written in the source.
if (normal->getSourceKind() != ConformanceEntryKind::Explicit)
continue;
// Only consider conformances to non-marker, nonisolated protocols.
auto proto = normal->getProtocol();
if (proto->isMarkerProtocol() || getActorIsolation(proto).isActorIsolated())
continue;
// Only nonisolated conformances can be affected.
if (!conformance->getIsolation().isNonisolated())
continue;
auto nameLoc = normal->getProtocolNameLoc();
if (nameLoc.isValid()) {
Context.Diags.diagnose(
nameLoc, diag::isolated_conformance_will_become_nonisolated, nominal, proto)
.fixItInsert(nameLoc, "nonisolated ");
}
}
}
if (Context.TypeCheckerOpts.DebugGenericSignatures && if (Context.TypeCheckerOpts.DebugGenericSignatures &&
!conformances.empty()) { !conformances.empty()) {
// Now that they're filled out, print out information about the conformances // Now that they're filled out, print out information about the conformances

View File

@@ -0,0 +1,33 @@
// RUN: %target-swift-frontend -typecheck -verify -target %target-swift-5.1-abi-triple -swift-version 6 -enable-upcoming-feature InferIsolatedConformances:migrate %s
// REQUIRES: concurrency
protocol P { }
protocol Q: P { }
struct S: P { }
struct S2: Q { }
@MainActor
struct MA1: P { }
// expected-warning@-1{{conformance of 'MA1' to 'P' should be marked 'nonisolated' to retain its behavior with upcoming feature 'InferIsolatedConformances'}}{{13-13=nonisolated }}
@MainActor
struct MA2: Q { }
// expected-warning@-1{{conformance of 'MA2' to 'Q' should be marked 'nonisolated' to retain its behavior with upcoming feature 'InferIsolatedConformances'}}{{13-13=nonisolated }}
@MainActor
struct MA3 { }
extension MA3: P, Q { }
// expected-warning@-1{{conformance of 'MA3' to 'P' should be marked 'nonisolated' to retain its behavior with upcoming feature 'InferIsolatedConformances'}}{{16-16=nonisolated }}
// expected-warning@-2{{conformance of 'MA3' to 'Q' should be marked 'nonisolated' to retain its behavior with upcoming feature 'InferIsolatedConformances'}}{{19-19=nonisolated }}
@MainActor
struct MA4: @MainActor P { }
@MainActor
struct MA5: nonisolated P { }