Skip to content
Open
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
3 changes: 0 additions & 3 deletions include/swift/Basic/Features.def
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
1 change: 0 additions & 1 deletion lib/AST/FeatureSet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
196 changes: 40 additions & 156 deletions lib/Sema/TypeCheckConcurrency.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2389,16 +2389,6 @@ namespace {
/// an expression or function.
llvm::SmallDenseMap<const DeclContext *, ActorIsolation> requiredIsolation;

using ActorRefKindPair = std::pair<ReferencedActor::Kind, ActorIsolation>;

using IsolationPair = std::pair<ActorIsolation, ActorIsolation>;

using DiagnosticList = std::vector<IsolationError>;

llvm::DenseMap<ActorRefKindPair, DiagnosticList> refErrors;

llvm::DenseMap<IsolationPair, DiagnosticList> applyErrors;

/// Keeps track of the capture context of variables that have been
/// explicitly captured in closures.
llvm::SmallDenseMap<VarDecl *, TinyPtrVector<const DeclContext *>>
Expand Down Expand Up @@ -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<DeclContext *>(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<DeclContext *>(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();
Expand Down Expand Up @@ -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<DeclContext *>(getDeclContext()),
unsatisfiedIsolation->getGlobalActor(), DiagnosticBehavior::Note);
}
if (unsatisfiedIsolation->isGlobalActor()) {
missingGlobalActorOnContext(
const_cast<DeclContext *>(getDeclContext()),
unsatisfiedIsolation->getGlobalActor(), DiagnosticBehavior::Note);
}

return true;
Expand Down Expand Up @@ -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<ValueDecl>(getDeclContext()->getAsDecl());
ctx.Diags.diagnose(loc, diag::in_derived_witness, decl,
requirementName, derivedConformanceType);
}
if (derivedConformanceType) {
auto *decl = dyn_cast<ValueDecl>(getDeclContext()->getAsDecl());
ctx.Diags.diagnose(loc, diag::in_derived_witness, decl,
requirementName, derivedConformanceType);
}

noteIsolatedActorMember(decl, context);
if (result.isolation.isGlobalActor()) {
missingGlobalActorOnContext(
const_cast<DeclContext *>(getDeclContext()),
result.isolation.getGlobalActor(), DiagnosticBehavior::Note);
}
noteIsolatedActorMember(decl, context);
if (result.isolation.isGlobalActor()) {
missingGlobalActorOnContext(
const_cast<DeclContext *>(getDeclContext()),
result.isolation.getGlobalActor(), DiagnosticBehavior::Note);
}

return true;
Expand Down Expand Up @@ -5147,13 +5035,9 @@ void swift::checkFunctionActorIsolation(AbstractFunctionDecl *decl) {
if (decl->getAttrs().hasAttribute<LLDBDebuggerFunctionAttr>())
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<ConstructorDecl>(decl)) {
if (auto superInit = ctor->getSuperInitCall())
Expand Down
137 changes: 0 additions & 137 deletions test/Concurrency/grouped_actor_isolation_diagnostics.swift

This file was deleted.