diff --git a/include/swift/Basic/Features.def b/include/swift/Basic/Features.def index f589e62963a47..e686de81fa6ec 100644 --- a/include/swift/Basic/Features.def +++ b/include/swift/Basic/Features.def @@ -464,9 +464,6 @@ EXPERIMENTAL_FEATURE(ManualOwnership, false) /// Enable the @extractConstantsFromMembers attribute. EXPERIMENTAL_FEATURE(ExtractConstantsFromMembers, false) -// Group Main Actor Isolation Errors by Scope -EXPERIMENTAL_FEATURE(GroupActorErrors, true) - // Enable explicit isolation of closures. EXPERIMENTAL_FEATURE(ClosureIsolation, true) diff --git a/lib/AST/FeatureSet.cpp b/lib/AST/FeatureSet.cpp index dd0b636893dc2..7d831813d0b2c 100644 --- a/lib/AST/FeatureSet.cpp +++ b/lib/AST/FeatureSet.cpp @@ -143,7 +143,6 @@ static bool usesFeatureInlineArrayTypeSugar(Decl *D) { UNINTERESTING_FEATURE(StaticExclusiveOnly) UNINTERESTING_FEATURE(ManualOwnership) UNINTERESTING_FEATURE(ExtractConstantsFromMembers) -UNINTERESTING_FEATURE(GroupActorErrors) UNINTERESTING_FEATURE(SameElementRequirements) UNINTERESTING_FEATURE(SendingArgsAndResults) UNINTERESTING_FEATURE(CheckImplementationOnly) diff --git a/lib/Sema/TypeCheckConcurrency.cpp b/lib/Sema/TypeCheckConcurrency.cpp index 9cfe3bac19fc5..0c855ca0aaf36 100644 --- a/lib/Sema/TypeCheckConcurrency.cpp +++ b/lib/Sema/TypeCheckConcurrency.cpp @@ -2389,16 +2389,6 @@ namespace { /// an expression or function. llvm::SmallDenseMap requiredIsolation; - using ActorRefKindPair = std::pair; - - using IsolationPair = std::pair; - - using DiagnosticList = std::vector; - - llvm::DenseMap refErrors; - - llvm::DenseMap applyErrors; - /// Keeps track of the capture context of variables that have been /// explicitly captured in closures. llvm::SmallDenseMap> @@ -2465,77 +2455,6 @@ namespace { return false; } - public: - bool diagnoseIsolationErrors() { - bool diagnosedError = false; - - for (auto list : refErrors) { - ActorRefKindPair key = list.getFirst(); - DiagnosticList errors = list.getSecond(); - ActorIsolation isolation = key.second; - - auto behavior = DiagnosticBehavior::Warning; - // Upgrade behavior if @preconcurrency not detected - if (llvm::any_of(errors, [&](IsolationError error) { - return !error.preconcurrency; - })) { - behavior = DiagnosticBehavior::Error; - } - - // Add Fix-it for missing @SomeActor annotation - if (isolation.isGlobalActor()) { - if (missingGlobalActorOnContext( - const_cast(getDeclContext()), - isolation.getGlobalActor(), behavior) && - errors.size() > 1) { - behavior = DiagnosticBehavior::Note; - } - } - - for (IsolationError error : errors) { - // Diagnose actor_isolated_non_self_reference as note - // if there are multiple of these diagnostics - ctx.Diags.diagnose(error.loc, error.diag) - .limitBehaviorUntilLanguageMode(behavior, 6); - } - } - - for (auto list : applyErrors) { - IsolationPair key = list.getFirst(); - DiagnosticList errors = list.getSecond(); - ActorIsolation isolation = key.first; - - auto behavior = DiagnosticBehavior::Warning; - // Upgrade behavior if @preconcurrency not detected - if (llvm::any_of(errors, [&](IsolationError error) { - return !error.preconcurrency; - })) { - behavior = DiagnosticBehavior::Error; - } - - - // Add Fix-it for missing @SomeActor annotation - if (isolation.isGlobalActor()) { - if (missingGlobalActorOnContext( - const_cast(getDeclContext()), - isolation.getGlobalActor(), behavior) && - errors.size() > 1) { - behavior = DiagnosticBehavior::Note; - } - } - - for (IsolationError error : errors) { - // Diagnose actor_isolated_call as note if - // if there are multiple actor-isolated function calls - // from outside the actor - ctx.Diags.diagnose(error.loc, error.diag) - .limitBehaviorUntilLanguageMode(behavior, 6); - } - } - - return diagnosedError; - } - private: const PatternBindingDecl *getTopPatternBindingDecl() const { return patternBindingStack.empty() ? nullptr : patternBindingStack.back(); @@ -4263,37 +4182,24 @@ namespace { /*args*/*unsatisfiedIsolation, getContextIsolation() ); - if (ctx.LangOpts.hasFeature(Feature::GroupActorErrors)) { - IsolationError mismatch(apply->getLoc(), preconcurrency, diagnostic); - auto key = std::make_pair( - unsatisfiedIsolation->withPreconcurrency(false), - getContextIsolation()); - if (applyErrors.find(key) == applyErrors.end()) { - applyErrors.insert(std::make_pair(key, DiagnosticList())); - } - - applyErrors[key].push_back(mismatch); - } else { - ctx.Diags - .diagnose(apply->getLoc(), diagnostic.getID(), - diagnostic.getArgs()) - .limitBehaviorIf(preconcurrency, DiagnosticBehavior::Warning); - - if (calleeDecl) { - auto calleeIsolation = getInferredActorIsolation(calleeDecl); - calleeDecl->diagnose(diag::actor_isolated_sync_func, calleeDecl); - if (calleeIsolation.source.isInferred()) { - calleeDecl->diagnose(diag::actor_isolation_source, - calleeIsolation.isolation, - calleeIsolation.source); - } + ctx.Diags + .diagnose(apply->getLoc(), diagnostic.getID(), diagnostic.getArgs()) + .limitBehaviorIf(preconcurrency, DiagnosticBehavior::Warning); + + if (calleeDecl) { + auto calleeIsolation = getInferredActorIsolation(calleeDecl); + calleeDecl->diagnose(diag::actor_isolated_sync_func, calleeDecl); + if (calleeIsolation.source.isInferred()) { + calleeDecl->diagnose(diag::actor_isolation_source, + calleeIsolation.isolation, + calleeIsolation.source); } + } - if (unsatisfiedIsolation->isGlobalActor()) { - missingGlobalActorOnContext( - const_cast(getDeclContext()), - unsatisfiedIsolation->getGlobalActor(), DiagnosticBehavior::Note); - } + if (unsatisfiedIsolation->isGlobalActor()) { + missingGlobalActorOnContext( + const_cast(getDeclContext()), + unsatisfiedIsolation->getGlobalActor(), DiagnosticBehavior::Note); } return true; @@ -4836,51 +4742,33 @@ namespace { } } - if (ctx.LangOpts.hasFeature(Feature::GroupActorErrors)) { - IsolationError mismatch = IsolationError(loc, - preconcurrencyContext, - Diagnostic(diag::actor_isolated_non_self_reference, - decl, useKind, refKind + 1, refGlobalActor, - result.isolation)); - - auto iter = refErrors.find(std::make_pair(refKind,result.isolation)); - if (iter != refErrors.end()) { - iter->second.push_back(mismatch); - } else { - DiagnosticList list; - list.push_back(mismatch); - auto keyPair = std::make_pair(refKind,result.isolation); - refErrors.insert(std::make_pair(keyPair, list)); - } - } else { - { - auto diagnostic = ctx.Diags.diagnose( - loc, diag::actor_isolated_non_self_reference, decl, useKind, - refKind + 1, refGlobalActor, result.isolation); - - // For compatibility downgrades - the error is downgraded until - // Swift 6, for preconcurrency - always. - if (shouldDowngradeToWarning) - diagnostic.limitBehaviorWithPreconcurrency( - DiagnosticBehavior::Warning, preconcurrencyContext); - } + { + auto diagnostic = ctx.Diags.diagnose( + loc, diag::actor_isolated_non_self_reference, decl, useKind, + refKind + 1, refGlobalActor, result.isolation); + + // For compatibility downgrades - the error is downgraded until + // Swift 6, for preconcurrency - always. + if (shouldDowngradeToWarning) + diagnostic.limitBehaviorWithPreconcurrency( + DiagnosticBehavior::Warning, preconcurrencyContext); + } - maybeNoteMutatingMethodSuggestion( - ctx, decl, loc, getDeclContext(), result.isolation, - kindOfUsage(decl, context).value_or(VarRefUseEnv::Read)); + maybeNoteMutatingMethodSuggestion( + ctx, decl, loc, getDeclContext(), result.isolation, + kindOfUsage(decl, context).value_or(VarRefUseEnv::Read)); - if (derivedConformanceType) { - auto *decl = dyn_cast(getDeclContext()->getAsDecl()); - ctx.Diags.diagnose(loc, diag::in_derived_witness, decl, - requirementName, derivedConformanceType); - } + if (derivedConformanceType) { + auto *decl = dyn_cast(getDeclContext()->getAsDecl()); + ctx.Diags.diagnose(loc, diag::in_derived_witness, decl, + requirementName, derivedConformanceType); + } - noteIsolatedActorMember(decl, context); - if (result.isolation.isGlobalActor()) { - missingGlobalActorOnContext( - const_cast(getDeclContext()), - result.isolation.getGlobalActor(), DiagnosticBehavior::Note); - } + noteIsolatedActorMember(decl, context); + if (result.isolation.isGlobalActor()) { + missingGlobalActorOnContext( + const_cast(getDeclContext()), + result.isolation.getGlobalActor(), DiagnosticBehavior::Note); } return true; @@ -5147,13 +5035,9 @@ void swift::checkFunctionActorIsolation(AbstractFunctionDecl *decl) { if (decl->getAttrs().hasAttribute()) return; - auto &ctx = decl->getASTContext(); ActorIsolationChecker checker(decl); if (auto body = decl->getBody()) { body->walk(checker); - if (ctx.LangOpts.hasFeature(Feature::GroupActorErrors)) { - checker.diagnoseIsolationErrors(); - } } if (auto ctor = dyn_cast(decl)) { if (auto superInit = ctor->getSuperInitCall()) diff --git a/test/Concurrency/grouped_actor_isolation_diagnostics.swift b/test/Concurrency/grouped_actor_isolation_diagnostics.swift deleted file mode 100644 index 1add4b88a2702..0000000000000 --- a/test/Concurrency/grouped_actor_isolation_diagnostics.swift +++ /dev/null @@ -1,137 +0,0 @@ -// RUN: %target-typecheck-verify-swift -target %target-swift-5.1-abi-triple -enable-experimental-feature GroupActorErrors -strict-concurrency=complete -// REQUIRES: concurrency -// REQUIRES: swift_feature_GroupActorErrors - -@MainActor -protocol P { - func f() - nonisolated func g() -} - -@preconcurrency @MainActor -protocol Q { - func f() - nonisolated func g() -} - -struct S: P { - func f() { } - func g() { } -} - -@preconcurrency -struct NonConcurrentS: Q { - func f() { } - func g() { } -} - -// expected-note@+1{{add '@MainActor' to make global function 'testP(s:p:)' part of global actor 'MainActor'}} -func testP(s: S, p: P) { // expected-error {{calls to '@MainActor'-isolated' code in global function 'testP(s:p:)'}} - p.f() // expected-note{{call to main actor-isolated instance method 'f()' in a synchronous nonisolated context}} - p.f() // expected-note{{call to main actor-isolated instance method 'f()' in a synchronous nonisolated context}} - p.f() // expected-note{{call to main actor-isolated instance method 'f()' in a synchronous nonisolated context}} - p.g() // OKAY - s.f() // expected-note{{call to main actor-isolated instance method 'f()' in a synchronous nonisolated context}} - s.f() // expected-note{{call to main actor-isolated instance method 'f()' in a synchronous nonisolated context}} - s.f() // expected-note{{call to main actor-isolated instance method 'f()' in a synchronous nonisolated context}} - s.g() // OKAY -} -// expected-note @+1{{add '@MainActor' to make global function 'testPreconcurrency(ncs:s:)' part of global actor 'MainActor'}} -func testPreconcurrency(ncs: NonConcurrentS, s:S ) { // expected-error {{calls to '@MainActor'-isolated' code in global function 'testPreconcurrency(ncs:s:)'}} - ncs.f() // expected-note{{call to main actor-isolated instance method 'f()' in a synchronous nonisolated context}} - ncs.f() // expected-note{{call to main actor-isolated instance method 'f()' in a synchronous nonisolated context}} - ncs.f() // expected-note{{call to main actor-isolated instance method 'f()' in a synchronous nonisolated context}} - ncs.g() // OKAY - s.f() // expected-note{{call to main actor-isolated instance method 'f()' in a synchronous nonisolated context}} - s.f() // expected-note{{call to main actor-isolated instance method 'f()' in a synchronous nonisolated context}} - s.f() // expected-note{{call to main actor-isolated instance method 'f()' in a synchronous nonisolated context}} - s.g() // OKAY -} - -// expected-note @+1{{add '@MainActor' to make global function 'testOnlyPreconcurrency(ncs:)' part of global actor 'MainActor'}} -func testOnlyPreconcurrency(ncs: NonConcurrentS) { // expected-warning {{calls to '@MainActor'-isolated' code in global function 'testOnlyPreconcurrency(ncs:)'}} - ncs.f() // expected-note{{call to main actor-isolated instance method 'f()' in a synchronous nonisolated context}} - ncs.f() // expected-note{{call to main actor-isolated instance method 'f()' in a synchronous nonisolated context}} - ncs.f() // expected-note{{call to main actor-isolated instance method 'f()' in a synchronous nonisolated context}} - ncs.g() // OKAY -} - -actor SomeActor { } - -@globalActor -struct SomeGlobalActor { - static let shared = SomeActor() -} - -@propertyWrapper -struct WrapperOnActor { - private var stored: Wrapped - - nonisolated init(wrappedValue: Wrapped) { - stored = wrappedValue - } - - @MainActor var wrappedValue: Wrapped { - get { } - set { } - } - - @SomeGlobalActor var projectedValue: Wrapped { - get { } - set { } - } -} - -struct HasWrapperOnActor { - @WrapperOnActor var x: Int = 0 - @WrapperOnActor var y: String = "" - @WrapperOnActor var z: (Double, Double) = (1.0,2.0) - - // expected-error@+2{{calls to '@MainActor'-isolated' code in instance method 'testWrapped()'}} - // expected-note@+1{{add '@MainActor' to make instance method 'testWrapped()' part of global actor 'MainActor'}} - func testWrapped() { - _ = x // expected-note{{main actor-isolated property 'x' can not be referenced from a nonisolated context}} - _ = y // expected-note{{main actor-isolated property 'y' can not be referenced from a nonisolated context}} - _ = z // expected-note{{main actor-isolated property 'z' can not be referenced from a nonisolated context}} - } - - // expected-error@+2{{calls to '@SomeGlobalActor'-isolated' code in instance method 'testProjected()'}} - // expected-note@+1{{add '@SomeGlobalActor' to make instance method 'testProjected()' part of global actor 'SomeGlobalActor'}} - func testProjected(){ - _ = $x // expected-note{{global actor 'SomeGlobalActor'-isolated property '$x' can not be referenced from a nonisolated context}} - _ = $y // expected-note{{global actor 'SomeGlobalActor'-isolated property '$y' can not be referenced from a nonisolated context}} - _ = $z // expected-note{{global actor 'SomeGlobalActor'-isolated property '$z' can not be referenced from a nonisolated context}} - } - - @MainActor - func testMA(){ } - - // expected-note@+1{{add '@MainActor' to make instance method 'testErrors()' part of global actor 'MainActor'}} - func testErrors() { // expected-error{{calls to '@MainActor'-isolated' code in instance method 'testErrors()'}} - testMA() // expected-error{{call to main actor-isolated instance method 'testMA()' in a synchronous nonisolated context}} - } -} - -@preconcurrency @MainActor -class MainActorPreconcurrency {} - -class InferMainActorPreconcurrency: MainActorPreconcurrency { - static func predatesConcurrency() {} - func predatesConcurrency (s: String) -> String { return s } - func predatesConcurrency (n: Int) -> Int { return n } -} - -nonisolated func testPreconcurrency() { - InferMainActorPreconcurrency.predatesConcurrency() - // expected-warning@-1 {{call to main actor-isolated static method 'predatesConcurrency()' in a synchronous nonisolated context}} -} - -func testPreconcurrencyGrouped() { // expected-warning {{calls to '@MainActor'-isolated' code in global function 'testPreconcurrencyGrouped()'}} - // expected-note@-1 {{add '@MainActor' to make global function 'testPreconcurrencyGrouped()' part of global actor 'MainActor'}} - InferMainActorPreconcurrency.predatesConcurrency() - // expected-note@-1 {{call to main actor-isolated static method 'predatesConcurrency()' in a synchronous nonisolated context}} - let _ = InferMainActorPreconcurrency().predatesConcurrency(s:"swift 6") - // expected-note@-1 {{call to main actor-isolated instance method 'predatesConcurrency(s:)' in a synchronous nonisolated context}} - let _ = InferMainActorPreconcurrency().predatesConcurrency(n:4) - // expected-note@-1 {{call to main actor-isolated instance method 'predatesConcurrency(n:)' in a synchronous nonisolated context}} -}