//===--- ActorIsolation.h - Actor isolation ---------------------*- C++ -*-===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See https://swift.org/LICENSE.txt for license information // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// // // This file provides a description of actor isolation state. // //===----------------------------------------------------------------------===// #ifndef SWIFT_AST_ACTORISOLATIONSTATE_H #define SWIFT_AST_ACTORISOLATIONSTATE_H #include "swift/AST/Type.h" #include "llvm/ADT/Hashing.h" namespace llvm { class raw_ostream; } namespace swift { class DeclContext; class ModuleDecl; class NominalTypeDecl; class SubstitutionMap; /// Determine whether the given types are (canonically) equal, declared here /// to avoid having to include Types.h. bool areTypesEqual(Type type1, Type type2); /// Determine whether the given type is suitable as a concurrent value type. bool isSendableType(ModuleDecl *module, Type type); /// Describes the actor isolation of a given declaration, which determines /// the actors with which it can interact. class ActorIsolation { public: enum Kind { /// The actor isolation has not been specified. It is assumed to be /// unsafe to interact with this declaration from any actor. Unspecified = 0, /// The declaration is isolated to the instance of an actor. /// For example, a mutable stored property or synchronous function within /// the actor is isolated to the instance of that actor. ActorInstance, /// The declaration is isolated to a (potentially) distributed actor. /// Distributed actors may access _their_ state (same as 'ActorInstance') /// however others may not access any properties on other distributed actors. DistributedActorInstance, /// The declaration is explicitly specified to be independent of any actor, /// meaning that it can be used from any actor but is also unable to /// refer to the isolated state of any given actor. Independent, /// The declaration is isolated to a global actor. It can refer to other /// entities with the same global actor. GlobalActor, /// The declaration is isolated to a global actor but with the "unsafe" /// annotation, which means that we only enforce the isolation if we're /// coming from something with specific isolation. GlobalActorUnsafe, }; private: Kind kind; union { NominalTypeDecl *actor; Type globalActor; void *pointer; }; ActorIsolation(Kind kind, NominalTypeDecl *actor) : kind(kind), actor(actor) { } ActorIsolation(Kind kind, Type globalActor) : kind(kind), globalActor(globalActor) { } public: static ActorIsolation forUnspecified() { return ActorIsolation(Unspecified, nullptr); } static ActorIsolation forIndependent() { return ActorIsolation(Independent, nullptr); } static ActorIsolation forActorInstance(NominalTypeDecl *actor) { return ActorIsolation(ActorInstance, actor); } static ActorIsolation forDistributedActorInstance(NominalTypeDecl *actor) { return ActorIsolation(DistributedActorInstance, actor); } static ActorIsolation forGlobalActor(Type globalActor, bool unsafe) { return ActorIsolation( unsafe ? GlobalActorUnsafe : GlobalActor, globalActor); } Kind getKind() const { return kind; } operator Kind() const { return getKind(); } bool isUnspecified() const { return kind == Unspecified; } bool isIndependent() const { return kind == Independent; } NominalTypeDecl *getActor() const { assert(getKind() == ActorInstance || getKind() == DistributedActorInstance); return actor; } bool isGlobalActor() const { return getKind() == GlobalActor || getKind() == GlobalActorUnsafe; } Type getGlobalActor() const { assert(isGlobalActor()); return globalActor; } /// Determine whether this isolation will require substitution to be /// evaluated. bool requiresSubstitution() const; /// Substitute into types within the actor isolation. ActorIsolation subst(SubstitutionMap subs) const; friend bool operator==(const ActorIsolation &lhs, const ActorIsolation &rhs) { if (lhs.isGlobalActor() && rhs.isGlobalActor()) return areTypesEqual(lhs.globalActor, rhs.globalActor); if (lhs.kind != rhs.kind) return false; switch (lhs.kind) { case Independent: case Unspecified: return true; case ActorInstance: case DistributedActorInstance: return lhs.actor == rhs.actor; case GlobalActor: case GlobalActorUnsafe: llvm_unreachable("Global actors handled above"); } } friend bool operator!=(const ActorIsolation &lhs, const ActorIsolation &rhs) { return !(lhs == rhs); } friend llvm::hash_code hash_value(const ActorIsolation &state) { return llvm::hash_combine(state.kind, state.pointer); } }; /// Determine how the given value declaration is isolated. ActorIsolation getActorIsolation(ValueDecl *value); /// Determine how the given declaration context is isolated. ActorIsolation getActorIsolationOfContext(DeclContext *dc); void simple_display(llvm::raw_ostream &out, const ActorIsolation &state); } // end namespace swift #endif /* SWIFT_AST_ACTORISOLATIONSTATE_H */