Skip to content

Commit 7cd9063

Browse files
committed
[Distributed] Diagnose missing import also for funcs in extensions
Resolves rdar://125813581
1 parent fb4ffb4 commit 7cd9063

14 files changed

+132
-29
lines changed

include/swift/AST/Decl.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,11 +173,13 @@ enum class DescriptiveDeclKind : uint8_t {
173173
Struct,
174174
Class,
175175
Actor,
176+
DistributedActor,
176177
Protocol,
177178
GenericEnum,
178179
GenericStruct,
179180
GenericClass,
180181
GenericActor,
182+
GenericDistributedActor,
181183
GenericType,
182184
Subscript,
183185
StaticSubscript,

include/swift/AST/DiagnosticsSema.def

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5431,9 +5431,9 @@ ERROR(isolated_default_argument_context,none,
54315431
ERROR(conflicting_default_argument_isolation,none,
54325432
"default argument cannot be both %0 and %1",
54335433
(ActorIsolation, ActorIsolation))
5434-
ERROR(distributed_actor_needs_explicit_distributed_import,none,
5435-
"'Distributed' module not imported, required for 'distributed actor'",
5436-
())
5434+
ERROR(distributed_decl_needs_explicit_distributed_import,none,
5435+
"%kind0 requires explicit import of Distributed module",
5436+
(const ValueDecl *))
54375437
NOTE(distributed_func_cannot_overload_on_async_only,none,
54385438
"%0 previously declared here, cannot overload distributed methods on effect only", (const ValueDecl *))
54395439
NOTE(distributed_func_other_ambiguous_overload_here,none,

include/swift/AST/TypeCheckRequests.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3025,7 +3025,7 @@ class HasCircularRawValueRequest
30253025

30263026
/// Checks if the Distributed module is available.
30273027
class DistributedModuleIsAvailableRequest
3028-
: public SimpleRequest<DistributedModuleIsAvailableRequest, bool(Decl *),
3028+
: public SimpleRequest<DistributedModuleIsAvailableRequest, bool(const ValueDecl *),
30293029
RequestFlags::Cached> {
30303030
public:
30313031
using SimpleRequest::SimpleRequest;
@@ -3034,7 +3034,7 @@ class DistributedModuleIsAvailableRequest
30343034
friend SimpleRequest;
30353035

30363036
// Evaluation.
3037-
bool evaluate(Evaluator &evaluator, Decl *decl) const;
3037+
bool evaluate(Evaluator &evaluator, const ValueDecl *decl) const;
30383038

30393039
public:
30403040
// Cached.

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ SWIFT_REQUEST(TypeChecker, InferredGenericSignatureRequest,
200200
SourceLoc, bool, bool),
201201
Uncached, NoLocationInfo)
202202
SWIFT_REQUEST(TypeChecker, DistributedModuleIsAvailableRequest,
203-
bool(ModuleDecl *), Cached, NoLocationInfo)
203+
bool(const ValueDecl *), Cached, NoLocationInfo)
204204
SWIFT_REQUEST(TypeChecker, InheritedTypeRequest,
205205
Type(llvm::PointerUnion<const TypeDecl *, const ExtensionDecl *>,
206206
unsigned, TypeResolutionStage),

lib/AST/Decl.cpp

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -187,12 +187,23 @@ DescriptiveDeclKind Decl::getDescriptiveKind() const {
187187
: DescriptiveDeclKind::Struct;
188188

189189
case DeclKind::Class: {
190-
bool isActor = cast<ClassDecl>(this)->isActor();
191-
return cast<ClassDecl>(this)->getGenericParams()
192-
? (isActor ? DescriptiveDeclKind::GenericActor
193-
: DescriptiveDeclKind::GenericClass)
194-
: (isActor ? DescriptiveDeclKind::Actor
195-
: DescriptiveDeclKind::Class);
190+
auto clazz = cast<ClassDecl>(this);
191+
bool isAnyActor = clazz->isAnyActor();
192+
bool isGeneric = clazz->getGenericParams();
193+
194+
auto kind = isGeneric ? DescriptiveDeclKind::GenericClass
195+
: DescriptiveDeclKind::Class;
196+
197+
if (isAnyActor) {
198+
if (clazz->isDistributedActor()) {
199+
kind = isGeneric ? DescriptiveDeclKind::GenericDistributedActor
200+
: DescriptiveDeclKind::DistributedActor;
201+
} else {
202+
kind = isGeneric ? DescriptiveDeclKind::GenericActor
203+
: DescriptiveDeclKind::Actor;
204+
}
205+
}
206+
return kind;
196207
}
197208

198209
case DeclKind::Var: {
@@ -332,11 +343,13 @@ StringRef Decl::getDescriptiveKindName(DescriptiveDeclKind K) {
332343
ENTRY(Struct, "struct");
333344
ENTRY(Class, "class");
334345
ENTRY(Actor, "actor");
346+
ENTRY(DistributedActor, "distributed actor");
335347
ENTRY(Protocol, "protocol");
336348
ENTRY(GenericEnum, "generic enum");
337349
ENTRY(GenericStruct, "generic struct");
338350
ENTRY(GenericClass, "generic class");
339351
ENTRY(GenericActor, "generic actor");
352+
ENTRY(GenericDistributedActor, "generic distributed actor");
340353
ENTRY(GenericType, "generic type");
341354
ENTRY(Subscript, "subscript");
342355
ENTRY(StaticSubscript, "static subscript");

lib/Sema/CodeSynthesisDistributedActor.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,7 @@ deriveBodyDistributed_thunk(AbstractFunctionDecl *thunk, void *context) {
231231

232232
// === Type:
233233
StructDecl *RCT = C.getRemoteCallTargetDecl();
234+
assert(RCT && "Missing RemoteCalLTarget declaration");
234235
Type remoteCallTargetTy = RCT->getDeclaredInterfaceType();
235236

236237
// === __isRemoteActor(self)

lib/Sema/TypeCheckDistributed.cpp

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "swift/AST/NameLookupRequests.h"
2626
#include "swift/AST/TypeCheckRequests.h"
2727
#include "swift/AST/TypeVisitor.h"
28+
#include "swift/AST/ImportCache.h"
2829
#include "swift/AST/ExistentialLayout.h"
2930
#include "swift/Basic/Defer.h"
3031
#include "swift/AST/ASTPrinter.h"
@@ -33,7 +34,7 @@ using namespace swift;
3334

3435
// ==== ------------------------------------------------------------------------
3536

36-
bool swift::ensureDistributedModuleLoaded(Decl *decl) {
37+
bool swift::ensureDistributedModuleLoaded(const ValueDecl *decl) {
3738
auto &C = decl->getASTContext();
3839
auto moduleAvailable = evaluateOrDefault(
3940
C.evaluator, DistributedModuleIsAvailableRequest{decl}, false);
@@ -42,14 +43,24 @@ bool swift::ensureDistributedModuleLoaded(Decl *decl) {
4243

4344
bool
4445
DistributedModuleIsAvailableRequest::evaluate(Evaluator &evaluator,
45-
Decl *decl) const {
46+
const ValueDecl *decl) const {
4647
auto &C = decl->getASTContext();
4748

48-
if (C.getLoadedModule(C.Id_Distributed))
49+
auto DistributedModule = C.getLoadedModule(C.Id_Distributed);
50+
if (!DistributedModule) {
51+
decl->diagnose(diag::distributed_decl_needs_explicit_distributed_import,
52+
decl);
53+
return false;
54+
}
55+
56+
auto &importCache = C.getImportCache();
57+
if (importCache.isImportedBy(DistributedModule, decl->getDeclContext())) {
4958
return true;
59+
}
5060

5161
// seems we're missing the Distributed module, ask to import it explicitly
52-
decl->diagnose(diag::distributed_actor_needs_explicit_distributed_import);
62+
decl->diagnose(diag::distributed_decl_needs_explicit_distributed_import,
63+
decl);
5364
return false;
5465
}
5566

@@ -502,6 +513,10 @@ bool swift::checkDistributedFunction(AbstractFunctionDecl *func) {
502513
if (!func->isDistributed())
503514
return false;
504515

516+
// ==== Ensure the Distributed module is available,
517+
if (!swift::ensureDistributedModuleLoaded(func))
518+
return true;
519+
505520
auto &C = func->getASTContext();
506521
return evaluateOrDefault(C.evaluator,
507522
CheckDistributedFunctionRequest{func},
@@ -521,13 +536,11 @@ bool CheckDistributedFunctionRequest::evaluate(
521536
auto module = func->getParentModule();
522537

523538
/// If no distributed module is available, then no reason to even try checks.
524-
if (!C.getLoadedModule(C.Id_Distributed))
539+
if (!C.getLoadedModule(C.Id_Distributed)) {
540+
func->diagnose(diag::distributed_decl_needs_explicit_distributed_import,
541+
func);
525542
return true;
526-
527-
// // No checking for protocol requirements because they are not required
528-
// // to have `SerializationRequirement`.
529-
// if (isa<ProtocolDecl>(func->getDeclContext()))
530-
// return false;
543+
}
531544

532545
Type serializationReqType =
533546
getDistributedActorSerializationType(func->getDeclContext());

lib/Sema/TypeCheckDistributed.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ class NominalTypeDecl;
3535
/******************************************************************************/
3636

3737
// Diagnose an error if the Distributed module is not loaded.
38-
bool ensureDistributedModuleLoaded(Decl *decl);
38+
bool ensureDistributedModuleLoaded(const ValueDecl *decl);
3939

4040
/// Check for illegal property declarations (e.g. re-declaring transport or id)
4141
void checkDistributedActorProperties(const NominalTypeDecl *decl);

test/Distributed/Inputs/FakeDistributedActorSystems.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,13 @@
1414

1515
import Distributed
1616

17+
// ==== Example Distributed Actors ----------------------------------------------
18+
19+
@available(SwiftStdlib 5.7, *)
20+
public distributed actor FakeRoundtripActorSystemDistributedActor {
21+
public typealias ActorSystem = FakeRoundtripActorSystem
22+
}
23+
1724
// ==== Fake Address -----------------------------------------------------------
1825

1926
public struct ActorAddress: Hashable, Sendable, Codable {
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-swift-frontend-emit-module -emit-module-path %t/FakeDistributedActorSystems.swiftmodule -module-name FakeDistributedActorSystems -disable-availability-checking %S/../Inputs/FakeDistributedActorSystems.swift
3+
// RUN: %target-build-swift -module-name main -Xfrontend -disable-availability-checking -j2 -parse-as-library -I %t %s %S/../Inputs/FakeDistributedActorSystems.swift -o %t/a.out
4+
// RUN: %target-codesign %t/a.out
5+
// RUN: %target-run %t/a.out | %FileCheck %s --dump-input=always
6+
7+
// REQUIRES: executable_test
8+
// REQUIRES: concurrency
9+
// REQUIRES: distributed
10+
11+
// rdar://76038845
12+
// UNSUPPORTED: use_os_stdlib
13+
// UNSUPPORTED: back_deployment_runtime
14+
15+
// UNSUPPORTED: OS=windows-msvc
16+
17+
import Distributed
18+
import FakeDistributedActorSystems
19+
20+
typealias DefaultDistributedActorSystem = FakeRoundtripActorSystem
21+
22+
extension FakeRoundtripActorSystemDistributedActor {
23+
distributed func echo(name: String) -> String {
24+
return "Echo: \(name)"
25+
}
26+
}
27+
28+
func test() async throws {
29+
let system = DefaultDistributedActorSystem()
30+
31+
let local = FakeRoundtripActorSystemDistributedActor(actorSystem: system)
32+
let ref = try FakeRoundtripActorSystemDistributedActor.resolve(id: local.id, using: system)
33+
34+
let reply = try await ref.echo(name: "Caplin")
35+
// CHECK: >> remoteCall: on:main.FakeRoundtripActorSystemDistributedActor, target:main.FakeRoundtripActorSystemDistributedActor.echo(name:), invocation:FakeInvocationEncoder(genericSubs: [], arguments: ["Caplin"], returnType: Optional(Swift.String), errorType: nil), throwing:Swift.Never, returning:Swift.String
36+
37+
// CHECK: << remoteCall return: Echo: Caplin
38+
print("reply: \(reply)")
39+
// CHECK: reply: Echo: Caplin
40+
}
41+
42+
@main struct Main {
43+
static func main() async {
44+
try! await test()
45+
}
46+
}

test/Distributed/distributed_actor_derived_conformances.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,4 @@ typealias DefaultDistributedActorSystem = FakeActorSystem
1111

1212
distributed actor DA: Comparable {}
1313
// expected-error@-1 {{type 'DA' does not conform to protocol 'Comparable'}}
14-
// expected-note@-2 {{automatic synthesis of 'Comparable' is not supported for actor declarations}}
14+
// expected-note@-2 {{automatic synthesis of 'Comparable' is not supported for distributed actor declarations}}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-swift-frontend-emit-module -emit-module-path %t/FakeDistributedActorSystems.swiftmodule -module-name FakeDistributedActorSystems -disable-availability-checking %S/Inputs/FakeDistributedActorSystems.swift
3+
// RUN: %target-swift-frontend -typecheck -verify -verify-ignore-unknown -disable-availability-checking -I %t 2>&1 %s
4+
// REQUIRES: concurrency
5+
// REQUIRES: distributed
6+
7+
// On purpose missing 'import Distributed'
8+
import FakeDistributedActorSystems
9+
10+
extension FakeRoundtripActorSystemDistributedActor {
11+
// expected-error@+1{{}}
12+
distributed func echo(name: String) -> String {
13+
return "Echo: \(name)"
14+
}
15+
}

test/Distributed/distributed_actor_is_experimental_enabled_missing_import.swift renamed to test/Distributed/distributed_actor_missing_distributed_import.swift

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
actor SomeActor {}
66

77
distributed actor DA {}
8-
// expected-error@-1{{'Distributed' module not imported, required for 'distributed actor'}}
8+
// expected-error@-1{{distributed actor 'DA' requires explicit import of Distributed module}}
99

1010
distributed actor class DAC {}
1111
// expected-error@-1{{distributed' can only be applied to 'actor' definitions, and distributed actor-isolated async functions}}
@@ -18,18 +18,24 @@ actor A {
1818
}
1919

2020
actor B {
21-
distributed var neverOk: String { // expected-error{{'Distributed' module not imported, required for 'distributed actor'}}
21+
distributed var neverOk: String { // expected-error{{distributed property 'neverOk' requires explicit import of Distributed module}}
2222
""
2323
}
2424
}
2525

26+
// expected-error@+1{{distributed actor 'DA2' requires explicit import of Distributed module}}
2627
distributed actor DA2 {
27-
// expected-error@-1{{'Distributed' module not imported, required for 'distributed actor'}}
28+
2829
func normal() async {}
30+
31+
// expected-error@+1{{distributed instance method 'dist()' requires explicit import of Distributed module}}
2932
distributed func dist() {}
33+
34+
// expected-error@+1{{distributed instance method 'distAsync()' requires explicit import of Distributed module}}
3035
distributed func distAsync() async {}
3136

32-
distributed var neverOk: String { // expected-error{{'Distributed' module not imported, required for 'distributed actor'}}
37+
// expected-error@+1{{distributed property 'neverOk' requires explicit import of Distributed module}}
38+
distributed var neverOk: String {
3339
""
3440
}
3541
}

test/Distributed/distributed_missing_import.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
actor SomeActor { }
66

77
distributed actor MissingImportDistributedActor_0 { }
8-
// expected-error@-1{{'Distributed' module not imported, required for 'distributed actor'}}
8+
// expected-error@-1{{distributed actor 'MissingImportDistributedActor_0' requires explicit import of Distributed module}}
99

1010
let t: DistributedActorSystem // expected-error{{cannot find type 'DistributedActorSystem' in scope}}
1111
let a: ActorAddress // expected-error{{cannot find type 'ActorAddress' in scope}}

0 commit comments

Comments
 (0)