|
18 | 18 | #include "swift/AST/ASTWalker.h"
|
19 | 19 | #include "swift/AST/ParameterList.h"
|
20 | 20 | #include "swift/AST/ProtocolConformance.h"
|
| 21 | +#include "swift/AST/NameLookupRequests.h" |
21 | 22 | #include "swift/AST/TypeCheckRequests.h"
|
22 | 23 |
|
23 | 24 | using namespace swift;
|
@@ -327,6 +328,77 @@ VarDecl *GlobalActorInstanceRequest::evaluate(
|
327 | 328 | return nullptr;
|
328 | 329 | }
|
329 | 330 |
|
| 331 | +CustomAttr *GlobalActorAttributeRequest::evaluate( |
| 332 | + Evaluator &evaluator, Decl *decl) const { |
| 333 | + ASTContext &ctx = decl->getASTContext(); |
| 334 | + auto dc = decl->getDeclContext(); |
| 335 | + CustomAttr *globalActorAttr = nullptr; |
| 336 | + NominalTypeDecl *globalActorNominal = nullptr; |
| 337 | + |
| 338 | + for (auto attr : decl->getAttrs().getAttributes<CustomAttr>()) { |
| 339 | + auto mutableAttr = const_cast<CustomAttr *>(attr); |
| 340 | + // Figure out which nominal declaration this custom attribute refers to. |
| 341 | + auto nominal = evaluateOrDefault(ctx.evaluator, |
| 342 | + CustomAttrNominalRequest{mutableAttr, dc}, |
| 343 | + nullptr); |
| 344 | + |
| 345 | + // Ignore unresolvable custom attributes. |
| 346 | + if (!nominal) |
| 347 | + continue; |
| 348 | + |
| 349 | + // We are only interested in global actor types. |
| 350 | + if (!nominal->isGlobalActor()) |
| 351 | + continue; |
| 352 | + |
| 353 | + // Only a single global actor can be applied to a given declaration. |
| 354 | + if (globalActorAttr) { |
| 355 | + decl->diagnose( |
| 356 | + diag::multiple_global_actors, globalActorNominal->getName(), |
| 357 | + nominal->getName()); |
| 358 | + continue; |
| 359 | + } |
| 360 | + |
| 361 | + globalActorAttr = const_cast<CustomAttr *>(attr); |
| 362 | + globalActorNominal = nominal; |
| 363 | + } |
| 364 | + |
| 365 | + if (!globalActorAttr) |
| 366 | + return nullptr; |
| 367 | + |
| 368 | + // Check that a global actor attribute makes sense on this kind of |
| 369 | + // declaration. |
| 370 | + if (auto nominal = dyn_cast<NominalTypeDecl>(decl)) { |
| 371 | + // Nominal types are okay... |
| 372 | + if (auto classDecl = dyn_cast<ClassDecl>(nominal)){ |
| 373 | + if (classDecl->isActor()) { |
| 374 | + // ... except for actor classes. |
| 375 | + nominal->diagnose(diag::global_actor_on_actor_class, nominal->getName()) |
| 376 | + .highlight(globalActorAttr->getRangeWithAt()); |
| 377 | + return nullptr; |
| 378 | + } |
| 379 | + } |
| 380 | + } else if (auto storage = dyn_cast<AbstractStorageDecl>(decl)) { |
| 381 | + // Subscripts and properties are fine... |
| 382 | + if (auto var = dyn_cast<VarDecl>(storage)) { |
| 383 | + if (var->getDeclContext()->isLocalContext()) { |
| 384 | + var->diagnose(diag::global_actor_on_local_variable, var->getName()) |
| 385 | + .highlight(globalActorAttr->getRangeWithAt()); |
| 386 | + return nullptr; |
| 387 | + } |
| 388 | + } |
| 389 | + } else if (isa<ExtensionDecl>(decl)) { |
| 390 | + // Extensions are okay. |
| 391 | + } else if (isa<ConstructorDecl>(decl) || isa<FuncDecl>(decl)) { |
| 392 | + // Functions are okay. |
| 393 | + } else { |
| 394 | + // Everything else is disallowed. |
| 395 | + decl->diagnose(diag::global_actor_disallowed, decl->getDescriptiveKind()); |
| 396 | + return nullptr; |
| 397 | + } |
| 398 | + |
| 399 | + return globalActorAttr; |
| 400 | +} |
| 401 | + |
330 | 402 | namespace {
|
331 | 403 |
|
332 | 404 | /// The isolation restriction in effect for a given declaration that is
|
|
0 commit comments