diff --git a/include/swift/AST/ActorIsolation.h b/include/swift/AST/ActorIsolation.h index 6dba92fdad5f2..9d2f60388e90a 100644 --- a/include/swift/AST/ActorIsolation.h +++ b/include/swift/AST/ActorIsolation.h @@ -233,6 +233,10 @@ class ActorIsolation { bool isDistributedActor() const; + bool isCallerIsolationInheriting() const { + return getKind() == CallerIsolationInheriting; + } + Type getGlobalActor() const { assert(isGlobalActor()); diff --git a/lib/AST/ASTDumper.cpp b/lib/AST/ASTDumper.cpp index 4f4cd4be38ab8..28d3f0819e7d6 100644 --- a/lib/AST/ASTDumper.cpp +++ b/lib/AST/ASTDumper.cpp @@ -6299,6 +6299,22 @@ namespace { break; } } + auto isolation = T->getIsolation(); + switch (isolation.getKind()) { + case FunctionTypeIsolation::Kind::NonIsolated: + case FunctionTypeIsolation::Kind::Parameter: + break; + case FunctionTypeIsolation::Kind::GlobalActor: + printRec(isolation.getGlobalActorType(), + Label::always("global_actor")); + break; + case FunctionTypeIsolation::Kind::Erased: + printFlag("@isolated(any)"); + break; + case FunctionTypeIsolation::Kind::NonIsolatedCaller: + printFlag("@execution(caller)"); + break; + } } if (Type globalActor = T->getGlobalActor()) { printFieldQuoted(globalActor.getString(), Label::always("global_actor")); diff --git a/lib/SIL/IR/SILFunctionType.cpp b/lib/SIL/IR/SILFunctionType.cpp index ac7d7f6cb2c18..5f5156b15ab43 100644 --- a/lib/SIL/IR/SILFunctionType.cpp +++ b/lib/SIL/IR/SILFunctionType.cpp @@ -1662,8 +1662,7 @@ class DestructureInputs { // If we are an async function that is unspecified or nonisolated, insert an // isolated parameter if AsyncCallerExecution is enabled. - if (IsolationInfo && - IsolationInfo->getKind() == ActorIsolation::CallerIsolationInheriting && + if (IsolationInfo && IsolationInfo->isCallerIsolationInheriting() && extInfoBuilder.isAsync()) { auto actorProtocol = TC.Context.getProtocol(KnownProtocolKind::Actor); auto actorType = @@ -2584,6 +2583,13 @@ static CanSILFunctionType getSILFunctionType( actorIsolation = getActorIsolationOfContext(constant->getInnermostDeclContext()); } + } else if (substFnInterfaceType->hasExtInfo() && + substFnInterfaceType->getExtInfo() + .getIsolation() + .isNonIsolatedCaller()) { + // If our function type is a nonisolated caller and we can not infer from + // our constant, we must be caller isolation inheriting. + actorIsolation = ActorIsolation::forCallerIsolationInheriting(); } DestructureInputs destructurer(expansionContext, TC, conventions, foreignInfo, actorIsolation, inputs, diff --git a/test/SILGen/execution_attr.swift b/test/SILGen/execution_attr.swift index c6449cdf78919..b3b8ba348a367 100644 --- a/test/SILGen/execution_attr.swift +++ b/test/SILGen/execution_attr.swift @@ -1,5 +1,5 @@ -// RUN: %target-swift-emit-silgen %s -enable-experimental-feature ExecutionAttribute | %FileCheck %s -// RUN: %target-swift-emit-silgen %s -enable-experimental-feature ExecutionAttribute -enable-experimental-feature AsyncCallerExecution | %FileCheck %s +// RUN: %target-swift-emit-silgen %s -enable-experimental-feature ExecutionAttribute | %FileCheck -check-prefix CHECK -check-prefix DISABLED %s +// RUN: %target-swift-emit-silgen %s -enable-experimental-feature ExecutionAttribute -enable-experimental-feature AsyncCallerExecution | %FileCheck -check-prefix CHECK -check-prefix ENABLED %s // REQUIRES: concurrency // REQUIRES: asserts @@ -20,3 +20,47 @@ func executionCaller() async {} // CHECK: sil hidden [ossa] @$s14execution_attr0A10ConcurrentyyYaF : $@convention(thin) @async () -> () { @execution(concurrent) func executionConcurrent() async {} + +// DISABLED: sil hidden [ossa] @$s14execution_attr0A15CallerParameteryyyyYaYCXEYaF : $@convention(thin) @async (@guaranteed @noescape @async @callee_guaranteed (@sil_isolated @sil_implicit_leading_param @guaranteed Optional) -> ()) -> () { +// ENABLED: sil hidden [ossa] @$s14execution_attr0A15CallerParameteryyyyYaYCXEYaF : $@convention(thin) @async (@sil_isolated @sil_implicit_leading_param @guaranteed Optional, @guaranteed @noescape @async @callee_guaranteed (@sil_isolated @sil_implicit_leading_param @guaranteed Optional) -> ()) -> () { +// CHECK: } // end sil function '$s14execution_attr0A15CallerParameteryyyyYaYCXEYaF' +func executionCallerParameter(_ x: @execution(caller) () async -> ()) async { + await x() +} + +// DISABLED-LABEL: sil hidden [ossa] @$s14execution_attr0A19ConcurrentParameteryyyyYaXEYaF : $@convention(thin) @async (@guaranteed @noescape @async @callee_guaranteed () -> ()) -> () { +// ENABLED-LABEL: sil hidden [ossa] @$s14execution_attr0A19ConcurrentParameteryyyyYaXEYaF : $@convention(thin) @async (@sil_isolated @sil_implicit_leading_param @guaranteed Optional, @guaranteed @noescape @async @callee_guaranteed () -> ()) -> () { +func executionConcurrentParameter(_ x: @execution(concurrent) () async -> ()) async { + await x() +} + +struct S { + let field: @execution(caller) () async -> () +} + +// DISABLED: sil hidden [ossa] @$s14execution_attr0A11CallerFieldyyAA1SVYaF : $@convention(thin) @async (@guaranteed S) -> () { +// DISABLED: bb0([[ARG:%.*]] : @guaranteed $S): +// DISABLED: [[FIELD:%.*]] = struct_extract [[ARG]] +// DISABLED: [[FIELD_COPY:%.*]] = copy_value [[FIELD]] +// DISABLED: [[ACTOR_NONE:%.*]] = enum $Optional, #Optional.none!enumelt +// DISABLED: [[BORROWED_FIELD:%.*]] = begin_borrow [[FIELD_COPY]] +// DISABLED: apply [[BORROWED_FIELD]]([[ACTOR_NONE]]) +// DISABLED: } // end sil function '$s14execution_attr0A11CallerFieldyyAA1SVYaF' + +// ENABLED: sil hidden [ossa] @$s14execution_attr0A11CallerFieldyyAA1SVYaF : $@convention(thin) @async (@sil_isolated @sil_implicit_leading_param @guaranteed Optional, @guaranteed S) -> () { +// ENABLED: bb0([[ACTOR:%.*]] : @guaranteed $Optional, [[ARG:%.*]] : @guaranteed $S): +// ENABLED: [[FIELD:%.*]] = struct_extract [[ARG]] +// ENABLED: [[FIELD_COPY:%.*]] = copy_value [[FIELD]] +// ENABLED: [[BORROWED_FIELD:%.*]] = begin_borrow [[FIELD_COPY]] +// ENABLED: apply [[BORROWED_FIELD]]([[ACTOR]]) +// ENABLED: } // end sil function '$s14execution_attr0A11CallerFieldyyAA1SVYaF' +func executionCallerField(_ s: S) async { + await s.field() +} + +extension S { + // CHECK-LABEL: // S.executionCallerFieldMethod(_:) + // CHECK: // Isolation: unspecified + // CHECK: sil hidden [ossa] @$s14execution_attr1SV0A17CallerFieldMethodyyyyYaYCXEF : $@convention(method) (@guaranteed @noescape @async @callee_guaranteed (@sil_isolated @sil_implicit_leading_param @guaranteed Optional) -> (), @guaranteed S) -> () { + func executionCallerFieldMethod(_ x: @execution(caller) () async -> ()) {} +}