blob: 1c4922c375301b307bb76a9289d4a5f37ff6c899 [file] [log] [blame]
//===--- 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 ClassDecl;
class SubstitutionMap;
class Type;
/// Determine whether the given types are (canonically) equal, declared here
/// to avoid having to include Types.h.
bool areTypesEqual(Type type1, Type type2);
/// 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 class.
/// For example, a mutable stored property or synchronous function within
/// the actor is isolated to the instance of that actor.
ActorInstance,
/// 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 explicitly specified to be independent of any actor,
/// but the programmer promises to protect the declaration from concurrent
/// accesses manually. Thus, it is okay if this declaration is a mutable
/// variable that creates storage.
IndependentUnsafe,
/// The declaration is isolated to a global actor. It can refer to other
/// entities with the same global actor.
GlobalActor,
};
private:
Kind kind;
union {
ClassDecl *actor;
Type globalActor;
void *pointer;
};
ActorIsolation(Kind kind, ClassDecl *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(ActorIndependentKind indepKind) {
ActorIsolation::Kind isoKind;
switch (indepKind) {
case ActorIndependentKind::Safe:
isoKind = Independent;
break;
case ActorIndependentKind::Unsafe:
isoKind = IndependentUnsafe;
break;
}
return ActorIsolation(isoKind, nullptr);
}
static ActorIsolation forActorInstance(ClassDecl *actor) {
return ActorIsolation(ActorInstance, actor);
}
static ActorIsolation forGlobalActor(Type globalActor) {
return ActorIsolation(GlobalActor, globalActor);
}
Kind getKind() const { return kind; }
operator Kind() const { return getKind(); }
bool isUnspecified() const { return kind == Unspecified; }
ClassDecl *getActor() const {
assert(getKind() == ActorInstance);
return actor;
}
Type getGlobalActor() const {
assert(getKind() == GlobalActor);
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.kind != rhs.kind)
return false;
switch (lhs.kind) {
case Independent:
case IndependentUnsafe:
case Unspecified:
return true;
case ActorInstance:
return lhs.actor == rhs.actor;
case GlobalActor:
return areTypesEqual(lhs.globalActor, rhs.globalActor);
}
}
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);
void simple_display(llvm::raw_ostream &out, const ActorIsolation &state);
} // end namespace swift
#endif /* SWIFT_AST_ACTORISOLATIONSTATE_H */