Skip to content

Experimental type-checking support for @isolated(any) function types. #71433

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions docs/ABI/Mangling.rst
Original file line number Diff line number Diff line change
Expand Up @@ -643,7 +643,7 @@ Types
C-TYPE is mangled according to the Itanium ABI, and prefixed with the length.
Non-ASCII identifiers are preserved as-is; we do not use Punycode.

function-signature ::= params-type params-type async? sendable? throws? differentiable? global-actor? // results and parameters
function-signature ::= params-type params-type async? sendable? throws? differentiable? function-isolation? // results and parameters

params-type ::= type 'z'? 'h'? // tuple in case of multiple parameters or a single parameter with a single tuple type
// with optional inout convention, shared convention. parameters don't have labels,
Expand All @@ -653,11 +653,12 @@ Types
#if SWIFT_RUNTIME_VERSION >= 5.5
async ::= 'Ya' // 'async' annotation on function types
sendable ::= 'Yb' // @Sendable on function types
global-actor :: = type 'Yc' // Global actor on function type
function-isolation ::= type 'Yc' // Global actor on function type
#endif
throws ::= 'K' // 'throws' annotation on function types
#if SWIFT_RUNTIME_VERSION >= 5.11
throws ::= type 'YK' // 'throws(type)' annotation on function types
function-isolation ::= type 'YA' // @isolated(any) on function type
#endif
differentiable ::= 'Yjf' // @differentiable(_forward) on function type
differentiable ::= 'Yjr' // @differentiable(reverse) on function type
Expand Down
19 changes: 19 additions & 0 deletions include/swift/ABI/MetadataValues.h
Original file line number Diff line number Diff line change
Expand Up @@ -1183,6 +1183,10 @@ template <typename int_type>
class TargetExtendedFunctionTypeFlags {
enum : int_type {
TypedThrowsMask = 0x00000001U,
IsolationMask = 0x0000000EU, // three bits

// Values for the enumerated isolation kinds
IsolatedAny = 0x00000002U,
};
int_type Data;

Expand All @@ -1196,8 +1200,23 @@ class TargetExtendedFunctionTypeFlags {
(Data & ~TypedThrowsMask) | (typedThrows ? TypedThrowsMask : 0));
}

const TargetExtendedFunctionTypeFlags<int_type>
withNonIsolated() const {
return TargetExtendedFunctionTypeFlags<int_type>(Data & ~IsolationMask);
}

const TargetExtendedFunctionTypeFlags<int_type>
withIsolatedAny() const {
return TargetExtendedFunctionTypeFlags<int_type>(
(Data & ~IsolationMask) | IsolatedAny);
}

bool isTypedThrows() const { return bool(Data & TypedThrowsMask); }

bool isIsolatedAny() const {
return (Data & IsolationMask) == IsolatedAny;
}

int_type getIntValue() const {
return Data;
}
Expand Down
11 changes: 11 additions & 0 deletions include/swift/AST/ASTBridging.h
Original file line number Diff line number Diff line change
Expand Up @@ -1466,6 +1466,17 @@ BridgedTypeAttribute BridgedTypeAttribute_createSimple(
BridgedASTContext cContext, BridgedTypeAttrKind cKind,
BridgedSourceLoc cAtLoc, BridgedSourceLoc cNameLoc);

enum ENUM_EXTENSIBILITY_ATTR(closed) BridgedIsolatedTypeAttrIsolationKind {
BridgedIsolatedTypeAttrIsolationKind_DynamicIsolation,
};

SWIFT_NAME("BridgedTypeAttribute.createIsolated(_:atLoc:nameLoc:lpLoc:isolationKindLoc:isolationKind:rpLoc:)")
BridgedTypeAttribute BridgedTypeAttribute_createIsolated(
BridgedASTContext cContext,
BridgedSourceLoc cAtLoc, BridgedSourceLoc cNameLoc,
BridgedSourceLoc cLPLoc, BridgedSourceLoc cIsolationLoc,
BridgedIsolatedTypeAttrIsolationKind cIsolation, BridgedSourceLoc cRPLoc);

//===----------------------------------------------------------------------===//
// MARK: TypeReprs
//===----------------------------------------------------------------------===//
Expand Down
11 changes: 11 additions & 0 deletions include/swift/AST/ActorIsolation.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@ class ActorIsolation {
/// The declaration is isolated to a global actor. It can refer to other
/// entities with the same global actor.
GlobalActor,
/// The actor isolation iss statically erased, as for a call to
/// an isolated(any) function. This is not possible for declarations.
Erased,
};

private:
Expand Down Expand Up @@ -129,6 +132,10 @@ class ActorIsolation {
return ActorIsolation(GlobalActor, globalActor);
}

static ActorIsolation forErased() {
return ActorIsolation(Erased);
}

static std::optional<ActorIsolation> forSILString(StringRef string) {
auto kind =
llvm::StringSwitch<std::optional<ActorIsolation::Kind>>(string)
Expand Down Expand Up @@ -174,6 +181,7 @@ class ActorIsolation {
switch (getKind()) {
case ActorInstance:
case GlobalActor:
case Erased:
return true;

case Unspecified:
Expand Down Expand Up @@ -259,6 +267,9 @@ class ActorIsolation {
case GlobalActor:
os << "global_actor";
return;
case Erased:
os << "erased";
return;
}
llvm_unreachable("Covered switch isn't covered?!");
}
Expand Down
37 changes: 37 additions & 0 deletions include/swift/AST/Attr.h
Original file line number Diff line number Diff line change
Expand Up @@ -2936,6 +2936,10 @@ class alignas(1 << AttrAlignInBits) TypeAttribute
: NumPadBits,
Index : 32
);

SWIFT_INLINE_BITFIELD_FULL(IsolatedTypeAttr, TypeAttribute, 8,
Kind : 8
);
} Bits;
// clang-format on

Expand Down Expand Up @@ -3161,6 +3165,39 @@ class PackElementTypeAttr
void printImpl(ASTPrinter &printer, const PrintOptions &options) const;
};

/// The @isolated function type attribute, not to be confused with the
/// `isolated` declaration modifier (IsolatedAttr) or the `isolated`
/// parameter specifier (IsolatedTypeRepr).
class IsolatedTypeAttr : public SimpleTypeAttrWithArgs<TypeAttrKind::Isolated> {
public:
enum class IsolationKind : uint8_t {
Dynamic
};

private:
SourceLoc KindLoc;

public:
IsolatedTypeAttr(SourceLoc atLoc, SourceLoc kwLoc, SourceRange parensRange,
Located<IsolationKind> kind)
: SimpleTypeAttr(atLoc, kwLoc, parensRange), KindLoc(kind.Loc) {
Bits.IsolatedTypeAttr.Kind = uint8_t(kind.Item);
}

IsolationKind getIsolationKind() const {
return IsolationKind(Bits.IsolatedTypeAttr.Kind);
}
SourceLoc getIsolationKindLoc() const {
return KindLoc;
}
const char *getIsolationKindName() const {
return getIsolationKindName(getIsolationKind());
}
static const char *getIsolationKindName(IsolationKind kind);

void printImpl(ASTPrinter &printer, const PrintOptions &options) const;
};

using TypeOrCustomAttr =
llvm::PointerUnion<CustomAttr*, TypeAttribute*>;

Expand Down
8 changes: 8 additions & 0 deletions include/swift/AST/DiagnosticsParse.def
Original file line number Diff line number Diff line change
Expand Up @@ -1711,6 +1711,14 @@ ERROR(expected_rparen_after_thrown_error_type,none,
ERROR(rethrows_with_thrown_error,none,
"'rethrows' cannot be combined with a specific thrown error type", ())

ERROR(attr_isolated_expected_lparen,none,
"expected '(' after '@isolated'; did you mean the 'isolated' modifier?",
())
ERROR(attr_isolated_expected_rparen,none,
"expected ')' after isolation kind", ())
ERROR(attr_isolated_expected_kind,none,
"expected 'any' as the isolation kind", ())

ERROR(attr_private_import_expected_rparen,none,
"expected ')' after function name for @_private", ())
ERROR(attr_private_import_expected_sourcefile, none,
Expand Down
11 changes: 11 additions & 0 deletions include/swift/AST/DiagnosticsSema.def
Original file line number Diff line number Diff line change
Expand Up @@ -5548,6 +5548,14 @@ ERROR(isolated_parameter_global_actor_type,none,
ERROR(isolated_parameter_combined_nonisolated,none,
"%0 with 'isolated' parameter cannot be 'nonisolated'",
(DescriptiveDeclKind))
ERROR(isolated_parameter_isolated_attr_type,none,
"function with 'isolated' parameter cannot also be '@isolated(%0)'",
(StringRef))
ERROR(isolated_any_experimental,none,
"attribute requires '-enable-experimental-feature IsolatedAny'", ())
ERROR(isolated_attr_global_actor_type,none,
"function type cannot have both a global actor and '@isolated(%0)'",
(StringRef))
ERROR(isolation_macro_experimental,none,
"#isolation macro is experimental", ())

Expand Down Expand Up @@ -6001,6 +6009,9 @@ ERROR(generic_function_type,none,
"function values cannot be generic", ())
ERROR(unsupported_convention,none,
"convention '%0' not supported", (StringRef))
ERROR(invalid_isolated_and_convention_attributes,none,
"'@convention(%0)' attribute is not allowed on '@isolated' types",
(StringRef))
ERROR(unreferenced_generic_parameter,NoUsage,
"generic parameter '%0' is not used in function signature", (StringRef))
ERROR(unexpected_ctype_for_non_c_convention,none,
Expand Down
16 changes: 8 additions & 8 deletions include/swift/AST/ExtInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,8 @@ class FunctionTypeIsolation {
/// the parameter list.
Parameter,

/// The function is dynamically isolated.
Dynamic,
/// The function's isolation is statically erased with @isolated(any).
Erased,
};

static constexpr size_t NumBits = 3; // future-proof this slightly
Expand All @@ -85,8 +85,8 @@ class FunctionTypeIsolation {
static FunctionTypeIsolation forParameter() {
return { Kind::Parameter };
}
static FunctionTypeIsolation forDynamic() {
return { Kind::Dynamic };
static FunctionTypeIsolation forErased() {
return { Kind::Erased };
}

Kind getKind() const { return value.getInt(); }
Expand All @@ -103,8 +103,8 @@ class FunctionTypeIsolation {
bool isParameter() const {
return getKind() == Kind::Parameter;
}
bool isDynamic() const {
return getKind() == Kind::Dynamic;
bool isErased() const {
return getKind() == Kind::Erased;
}

// The opaque accessors below are just for the benefit of ExtInfoBuilder,
Expand Down Expand Up @@ -543,8 +543,8 @@ class ASTExtInfoBuilder {
return FunctionTypeIsolation::Kind(
(bits & IsolationMask) >> IsolationMaskOffset);
}
bool isDynamicallyIsolated() const {
return getIsolationKind() == FunctionTypeIsolation::Kind::Dynamic;
bool isIsolationStaticallyErased() const {
return getIsolationKind() == FunctionTypeIsolation::Kind::Erased;
}
static bool hasGlobalActorFromBits(unsigned bits) {
return getIsolationKindFromBits(bits)
Expand Down
1 change: 1 addition & 0 deletions include/swift/AST/TypeAttr.def
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ SIMPLE_TYPE_ATTR(preconcurrency, Preconcurrency)
SIMPLE_TYPE_ATTR(_local, Local)
SIMPLE_TYPE_ATTR(_noMetadata, NoMetadata)
TYPE_ATTR(_opaqueReturnTypeOf, OpaqueReturnTypeOf)
TYPE_ATTR(isolated, Isolated)

// SIL-specific attributes
SIMPLE_SIL_TYPE_ATTR(block_storage, BlockStorage)
Expand Down
3 changes: 0 additions & 3 deletions include/swift/AST/Types.h
Original file line number Diff line number Diff line change
Expand Up @@ -3444,9 +3444,6 @@ class AnyFunctionType : public TypeBase {
return getExtInfo().getIsolation();
return FunctionTypeIsolation::forNonIsolated();
}
bool isDynamicallyIsolated() const {
return getIsolation().isDynamic();
}

/// Retrieve the "effective" thrown interface type, or llvm::None if
/// this function cannot throw.
Expand Down
3 changes: 3 additions & 0 deletions include/swift/Basic/Features.def
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,9 @@ EXPERIMENTAL_FEATURE(DynamicActorIsolation, false)
// Allow for `switch` of noncopyable values to be borrowing or consuming.
EXPERIMENTAL_FEATURE(BorrowingSwitch, true)

// Enable isolated(any) attribute on function types.
EXPERIMENTAL_FEATURE(IsolatedAny, false)

#undef EXPERIMENTAL_FEATURE_EXCLUDED_FROM_MODULE_INTERFACE
#undef EXPERIMENTAL_FEATURE
#undef UPCOMING_FEATURE
Expand Down
1 change: 1 addition & 0 deletions include/swift/Demangling/DemangleNodes.def
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ NODE(InfixOperator)
CONTEXT_NODE(Initializer)
CONTEXT_NODE(InitAccessor)
NODE(Isolated)
NODE(IsolatedAnyFunctionType)
NODE(KeyPathGetterThunkHelper)
NODE(KeyPathSetterThunkHelper)
NODE(KeyPathEqualsThunkHelper)
Expand Down
5 changes: 3 additions & 2 deletions include/swift/Demangling/TypeDecoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -846,10 +846,11 @@ class TypeDecoder {

globalActorType = globalActorResult.getType();
++firstChildIdx;
} else if (Node->getChild(firstChildIdx)->getKind() ==
NodeKind::IsolatedAnyFunctionType) {
extFlags = extFlags.withIsolatedAny();
}

// FIXME: other kinds of isolation

FunctionMetadataDifferentiabilityKind diffKind;
if (Node->getChild(firstChildIdx)->getKind() ==
NodeKind::DifferentiableFunctionType) {
Expand Down
17 changes: 13 additions & 4 deletions include/swift/RemoteInspection/TypeRef.h
Original file line number Diff line number Diff line change
Expand Up @@ -483,12 +483,14 @@ class FunctionTypeRef final : public TypeRef {
std::vector<Param> Parameters;
const TypeRef *Result;
FunctionTypeFlags Flags;
ExtendedFunctionTypeFlags ExtFlags;
FunctionMetadataDifferentiabilityKind DifferentiabilityKind;
const TypeRef *GlobalActor;
const TypeRef *ThrownError;

static TypeRefID Profile(const std::vector<Param> &Parameters,
const TypeRef *Result, FunctionTypeFlags Flags,
ExtendedFunctionTypeFlags ExtFlags,
FunctionMetadataDifferentiabilityKind DiffKind,
const TypeRef *GlobalActor,
const TypeRef *ThrownError) {
Expand All @@ -500,6 +502,7 @@ class FunctionTypeRef final : public TypeRef {
}
ID.addPointer(Result);
ID.addInteger(static_cast<uint64_t>(Flags.getIntValue()));
ID.addInteger(static_cast<uint64_t>(ExtFlags.getIntValue()));
ID.addInteger(static_cast<uint64_t>(DiffKind.getIntValue()));
ID.addPointer(GlobalActor);
ID.addPointer(ThrownError);
Expand All @@ -510,21 +513,23 @@ class FunctionTypeRef final : public TypeRef {
public:
FunctionTypeRef(std::vector<Param> Params, const TypeRef *Result,
FunctionTypeFlags Flags,
ExtendedFunctionTypeFlags ExtFlags,
FunctionMetadataDifferentiabilityKind DiffKind,
const TypeRef *GlobalActor,
const TypeRef *ThrownError)
: TypeRef(TypeRefKind::Function), Parameters(Params), Result(Result),
Flags(Flags), DifferentiabilityKind(DiffKind),
Flags(Flags), ExtFlags(ExtFlags), DifferentiabilityKind(DiffKind),
GlobalActor(GlobalActor), ThrownError(ThrownError) {}

template <typename Allocator>
static const FunctionTypeRef *create(
Allocator &A, std::vector<Param> Params, const TypeRef *Result,
FunctionTypeFlags Flags, FunctionMetadataDifferentiabilityKind DiffKind,
FunctionTypeFlags Flags, ExtendedFunctionTypeFlags ExtFlags,
FunctionMetadataDifferentiabilityKind DiffKind,
const TypeRef *GlobalActor, const TypeRef *ThrownError) {
FIND_OR_CREATE_TYPEREF(
A, FunctionTypeRef, Params, Result, Flags, DiffKind, GlobalActor,
ThrownError);
A, FunctionTypeRef, Params, Result, Flags, ExtFlags, DiffKind,
GlobalActor, ThrownError);
}

const std::vector<Param> &getParameters() const { return Parameters; };
Expand All @@ -537,6 +542,10 @@ class FunctionTypeRef final : public TypeRef {
return Flags;
}

ExtendedFunctionTypeFlags getExtFlags() const {
return ExtFlags;
}

FunctionMetadataDifferentiabilityKind getDifferentiabilityKind() const {
return DifferentiabilityKind;
}
Expand Down
9 changes: 5 additions & 4 deletions include/swift/RemoteInspection/TypeRefBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -1125,8 +1125,8 @@ class TypeRefBuilder {
ExtendedFunctionTypeFlags extFlags,
FunctionMetadataDifferentiabilityKind diffKind,
const TypeRef *globalActor, const TypeRef *thrownError) {
return FunctionTypeRef::create(*this, params, result, flags, diffKind,
globalActor, thrownError);
return FunctionTypeRef::create(*this, params, result, flags, extFlags,
diffKind, globalActor, thrownError);
}

const FunctionTypeRef *createImplFunctionType(
Expand All @@ -1139,6 +1139,7 @@ class TypeRefBuilder {
// reflection as capture types. For the reflection library's
// purposes, the only part that matters is the convention.
FunctionTypeFlags funcFlags;
ExtendedFunctionTypeFlags extFuncFlags;
switch (flags.getRepresentation()) {
case Demangle::ImplFunctionRepresentation::Thick:
case Demangle::ImplFunctionRepresentation::Closure:
Expand Down Expand Up @@ -1183,8 +1184,8 @@ class TypeRefBuilder {
}

auto result = createTupleType({}, llvm::ArrayRef<llvm::StringRef>());
return FunctionTypeRef::create(*this, {}, result, funcFlags, diffKind,
nullptr, nullptr);
return FunctionTypeRef::create(*this, {}, result, funcFlags, extFuncFlags,
diffKind, nullptr, nullptr);
}

BuiltType createProtocolTypeFromDecl(BuiltProtocolDecl protocol) {
Expand Down
Loading