Skip to content

Commit 1d53d74

Browse files
committed
Cleanup actor protocol conformance error
This patch cleans up how we emit the errors for disallowing the properties and methods of an actor to be applied to the protocol conformance. Rather than having multiple error messages for each case, we keep one error message saying that the actor-isolated method/variable/what-have-you cannot be used to satisfy a protocol requirement, then allow multiple notes with fix-its to allow the programmer to choose what they want to do. The notes have a better description of what each option does.
1 parent f3da35a commit 1d53d74

File tree

4 files changed

+31
-17
lines changed

4 files changed

+31
-17
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4132,6 +4132,9 @@ NOTE(note_add_async_to_function,none,
41324132
"add 'async' to function %0 to make it asynchronous", (DeclName))
41334133
NOTE(note_add_asynchandler_to_function,none,
41344134
"add '@asyncHandler' to function %0 to create an implicit asynchronous context", (DeclName))
4135+
NOTE(note_add_actorindependent_to_decl,none,
4136+
"add '@actorIndependent' to %0 to make this %1 independent of the actor",
4137+
(DeclName, DescriptiveDeclKind))
41354138
NOTE(note_add_globalactor_to_function,none,
41364139
"add '@%0' to make %1 %2 part of global actor %3",
41374140
(StringRef, DescriptiveDeclKind, DeclName, Type))
@@ -4255,10 +4258,6 @@ WARNING(shared_mutable_state_access,none,
42554258
ERROR(actor_isolated_witness,none,
42564259
"actor-isolated %0 %1 cannot be used to satisfy a protocol requirement",
42574260
(DescriptiveDeclKind, DeclName))
4258-
ERROR(actor_isolated_witness_could_be_async_handler,none,
4259-
"actor-isolated %0 %1 cannot be used to satisfy a protocol requirement; "
4260-
"did you mean to make it an asychronous handler?",
4261-
(DescriptiveDeclKind, DeclName))
42624261
ERROR(global_actor_isolated_requirement,none,
42634262
"%0 %1 must be isolated to the global actor %2 to satisfy corresponding "
42644263
"requirement from protocol %3",

lib/Sema/TypeCheckProtocol.cpp

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2654,20 +2654,29 @@ bool ConformanceChecker::checkActorIsolation(
26542654
ActorIsolationRestriction::forDeclaration(witness)) {
26552655
case ActorIsolationRestriction::ActorSelf: {
26562656
// Actor-isolated witnesses cannot conform to protocol requirements.
2657-
bool canBeAsyncHandler = false;
2657+
witness->diagnose(diag::actor_isolated_witness,
2658+
witness->getDescriptiveKind(),
2659+
witness->getName());
26582660
if (auto witnessFunc = dyn_cast<FuncDecl>(witness)) {
2659-
canBeAsyncHandler = !witnessFunc->isAsyncHandler() &&
26602661
witnessFunc->canBeAsyncHandler();
2662+
if (!witnessFunc->isAsyncHandler()) {
2663+
auto handlerNote = witness->diagnose(
2664+
diag::note_add_asynchandler_to_function,
2665+
witness->getName());
2666+
handlerNote.fixItInsert(witness->getAttributeInsertionLoc(false),
2667+
"@asyncHandler ");
2668+
}
26612669
}
2662-
auto diag = witness->diagnose(
2663-
canBeAsyncHandler
2664-
? diag::actor_isolated_witness_could_be_async_handler
2665-
: diag::actor_isolated_witness,
2666-
witness->getDescriptiveKind(), witness->getName());
2667-
2668-
if (canBeAsyncHandler) {
2669-
diag.fixItInsert(
2670-
witness->getAttributeInsertionLoc(false), "@asyncHandler ");
2670+
2671+
{
2672+
auto witnessVar = dyn_cast<VarDecl>(witness);
2673+
if ((witnessVar && !witnessVar->hasStorage()) || !witnessVar) {
2674+
auto independentNote = witness->diagnose(
2675+
diag::note_add_actorindependent_to_decl,
2676+
witness->getName(), witness->getDescriptiveKind());
2677+
independentNote.fixItInsert(witness->getAttributeInsertionLoc(false),
2678+
"@actorIndependent ");
2679+
}
26712680
}
26722681

26732682
return true;

test/decl/class/actor/conformance.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,12 @@ actor class OtherActor: SyncProtocol {
3737

3838
var propertyA: Int { 17 }
3939
// expected-error@-1{{actor-isolated property 'propertyA' cannot be used to satisfy a protocol requirement}}
40+
// expected-note@-2{{add '@actorIndependent' to 'propertyA' to make this property independent of the actor}}{{3-3=@actorIndependent }}
4041

4142
func syncMethodA() { }
42-
// expected-error@-1{{actor-isolated instance method 'syncMethodA()' cannot be used to satisfy a protocol requirement; did you mean to make it an asychronous handler?}}{{3-3=@asyncHandler }}
43+
// expected-error@-1{{actor-isolated instance method 'syncMethodA()' cannot be used to satisfy a protocol requirement}}
44+
// expected-note@-2{{add '@actorIndependent' to 'syncMethodA()' to make this instance method independent of the actor}}{{3-3=@actorIndependent }}
45+
// expected-note@-3{{add '@asyncHandler' to function 'syncMethodA()' to create an implicit asynchronous context}}{{3-3=@asyncHandler }}
4346

4447
// Async handlers are okay.
4548
@asyncHandler
@@ -51,6 +54,7 @@ actor class OtherActor: SyncProtocol {
5154

5255
subscript (index: Int) -> String { "\(index)" }
5356
// expected-error@-1{{actor-isolated subscript 'subscript(_:)' cannot be used to satisfy a protocol requirement}}
57+
// expected-note@-2{{add '@actorIndependent' to 'subscript(_:)' to make this subscript independent of the actor}}{{3-3=@actorIndependent }}
5458

5559
// Static methods and properties are okay.
5660
static func staticMethod() { }

test/decl/protocol/special/Actor.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,9 @@ class C1: Actor {
4141

4242
// Method that is not usable as a witness.
4343
actor class BA1 {
44-
func enqueue(partialTask: PartialAsyncTask) { } // expected-error{{actor-isolated instance method 'enqueue(partialTask:)' cannot be used to satisfy a protocol requirement; did you mean to make it an asychronous handler?}}
44+
func enqueue(partialTask: PartialAsyncTask) { } // expected-error{{actor-isolated instance method 'enqueue(partialTask:)' cannot be used to satisfy a protocol requirement}}
45+
//expected-note@-1{{add '@asyncHandler' to function 'enqueue(partialTask:)' to create an implicit asynchronous context}}{{3-3=@asyncHandler }}
46+
//expected-note@-2{{add '@actorIndependent' to 'enqueue(partialTask:)' to make this instance method independent of the actor}}{{3-3=@actorIndependent }}
4547
}
4648

4749
// Method that isn't part of the main class definition cannot be used to

0 commit comments

Comments
 (0)