From dfbe7c1e7a9c2b985c6a8e0cf4938979d20b1f76 Mon Sep 17 00:00:00 2001 From: Michael Gottesman Date: Mon, 20 Oct 2025 12:28:39 -0700 Subject: [PATCH 1/3] [rbi] Refactor out code for handling ref_element_addr so I can use it for class_methods as well. The two pieces of code are fundamentally doing the same thing so I can reuse the code. I am doing the refactoring as a separate change so that it is easier to review. --- lib/SILOptimizer/Utils/SILIsolationInfo.cpp | 99 ++++++++++++--------- 1 file changed, 58 insertions(+), 41 deletions(-) diff --git a/lib/SILOptimizer/Utils/SILIsolationInfo.cpp b/lib/SILOptimizer/Utils/SILIsolationInfo.cpp index e8145d1c4e4fc..41256a898c32c 100644 --- a/lib/SILOptimizer/Utils/SILIsolationInfo.cpp +++ b/lib/SILOptimizer/Utils/SILIsolationInfo.cpp @@ -426,6 +426,61 @@ static bool isPartialApplyNonisolatedUnsafe(PartialApplyInst *pai) { return foundOneNonIsolatedUnsafe; } +/// Return the SILIsolationInfo for a class field. +/// +/// \arg queriedValue the actual value that SILIsolationInfo::get was called +/// upon. This is used for IsolationHistory. +/// +/// \arg classValue this is the actual underlying class value that we are +/// extracting a field out of. As an example this is the base passed to +/// ref_element_addr or class_method. +/// +/// \arg field the actual AST field that we discovered we are querying. This +/// could be the field of the ref_element_addr or an accessor decl extracted +/// from a SILDeclRef of a class_method. +static SILIsolationInfo computeIsolationForClassField(SILValue queriedValue, + SILValue classValue, + ValueDecl *field) { + auto varIsolation = swift::getActorIsolation(field); + + // If we have a global actor isolated field, then we know that we override + // the actual isolation of the actor or global actor isolated class with + // some other form of isolation. In such a case, we need to use that + // isolation instead. + if (varIsolation.isGlobalActor()) { + assert(!varIsolation.isNonisolatedUnsafe() && + "Cannot apply both nonisolated(unsafe) and a global actor attribute " + "to the same declaration"); + return SILIsolationInfo::getGlobalActorIsolated( + queriedValue, varIsolation.getGlobalActor()); + } + + if (auto instance = ActorInstance::getForValue(classValue)) { + if (auto *fArg = llvm::dyn_cast_or_null( + instance.maybeGetValue())) { + if (auto info = + SILIsolationInfo::getActorInstanceIsolated(queriedValue, fArg)) + return info.withUnsafeNonIsolated(varIsolation.isNonisolatedUnsafe()); + } + } + + auto *nomDecl = classValue->getType().getNominalOrBoundGenericNominal(); + + if (nomDecl->isAnyActor()) + return SILIsolationInfo::getActorInstanceIsolated(queriedValue, classValue, + nomDecl) + .withUnsafeNonIsolated(varIsolation.isNonisolatedUnsafe()); + + if (auto isolation = swift::getActorIsolation(nomDecl); + isolation && isolation.isGlobalActor()) { + return SILIsolationInfo::getGlobalActorIsolated(queriedValue, + isolation.getGlobalActor()) + .withUnsafeNonIsolated(varIsolation.isNonisolatedUnsafe()); + } + + return SILIsolationInfo::getDisconnected(varIsolation.isNonisolatedUnsafe()); +} + SILIsolationInfo SILIsolationInfo::get(SILInstruction *inst) { if (auto fas = FullApplySite::isa(inst)) { // Before we do anything, see if we have a sending result. In such a case, @@ -594,48 +649,10 @@ SILIsolationInfo SILIsolationInfo::get(SILInstruction *inst) { return SILIsolationInfo::getDisconnected(partialApplyIsNonIsolatedUnsafe); } - // See if the memory base is a ref_element_addr from an address. If so, add - // the actor derived flag. - // - // This is important so we properly handle setters. + // See if the memory base is a ref_element_addr from an address. if (auto *rei = dyn_cast(inst)) { - auto varIsolation = swift::getActorIsolation(rei->getField()); - - // If we have a global actor isolated field, then we know that we override - // the actual isolation of the actor or global actor isolated class with - // some other form of isolation. In such a case, we need to use that - // isolation instead. - if (varIsolation.isGlobalActor()) { - return SILIsolationInfo::getGlobalActorIsolated( - rei, varIsolation.getGlobalActor()) - .withUnsafeNonIsolated(varIsolation.isNonisolatedUnsafe()); - } - - if (auto instance = ActorInstance::getForValue(rei->getOperand())) { - if (auto *fArg = llvm::dyn_cast_or_null( - instance.maybeGetValue())) { - if (auto info = SILIsolationInfo::getActorInstanceIsolated(rei, fArg)) - return info.withUnsafeNonIsolated(varIsolation.isNonisolatedUnsafe()); - } - } - - auto *nomDecl = - rei->getOperand()->getType().getNominalOrBoundGenericNominal(); - - if (nomDecl->isAnyActor()) - return SILIsolationInfo::getActorInstanceIsolated(rei, rei->getOperand(), - nomDecl) - .withUnsafeNonIsolated(varIsolation.isNonisolatedUnsafe()); - - if (auto isolation = swift::getActorIsolation(nomDecl); - isolation && isolation.isGlobalActor()) { - return SILIsolationInfo::getGlobalActorIsolated( - rei, isolation.getGlobalActor()) - .withUnsafeNonIsolated(varIsolation.isNonisolatedUnsafe()); - } - - return SILIsolationInfo::getDisconnected( - varIsolation.isNonisolatedUnsafe()); + return computeIsolationForClassField(rei, rei->getOperand(), + rei->getField()); } // Check if we have a global_addr inst. From 8016bf23321efcae89d80d6f21df52c27e522e50 Mon Sep 17 00:00:00 2001 From: Michael Gottesman Date: Sun, 19 Oct 2025 14:00:19 -0700 Subject: [PATCH 2/3] [sil] Change SILIsolationInfo inference for classmethods to use SILDeclRef instead of using the AST directly. We are creating/relying on a contract between the AST and SIL... that SILDeclRef should accurately describe the method/accessor that a class_method is from. By doing this we eliminate pattern matching on the AST which ties this code too tightly to the AST and makes it brittle in the face of AST changes. This also fixes an issue where we were not handling setters correctly. I am doing this now since it is natural to fix it along side fixing the ref_element_addr issue in the previous commit since they are effectively doing the same thing. rdar://153207557 --- include/swift/SIL/SILArgument.h | 6 + .../SILOptimizer/Utils/SILIsolationInfo.h | 21 +- lib/SILOptimizer/Utils/SILIsolationInfo.cpp | 186 ++--- .../silisolationinfo_inference.sil | 672 ++++++++++++++++++ .../transfernonsendable_global_actor.swift | 18 +- 5 files changed, 807 insertions(+), 96 deletions(-) diff --git a/include/swift/SIL/SILArgument.h b/include/swift/SIL/SILArgument.h index f042bb13547ed..d64e8d41206b4 100644 --- a/include/swift/SIL/SILArgument.h +++ b/include/swift/SIL/SILArgument.h @@ -429,6 +429,12 @@ class SILFunctionArgument : public SILArgument { /// Returns true if this SILFunctionArgument is an 'inout sending' parameter. bool isInOutSending() const; + bool isIsolated() const { + return !isIndirectResult() && !isIndirectErrorResult() && + getKnownParameterInfo().getOptions().contains( + SILParameterInfo::Isolated); + } + Lifetime getLifetime() const { return getType() .getLifetime(*getFunction()) diff --git a/include/swift/SILOptimizer/Utils/SILIsolationInfo.h b/include/swift/SILOptimizer/Utils/SILIsolationInfo.h index 54f2916695a6a..ecf4338b0e0ed 100644 --- a/include/swift/SILOptimizer/Utils/SILIsolationInfo.h +++ b/include/swift/SILOptimizer/Utils/SILIsolationInfo.h @@ -53,10 +53,16 @@ class ActorInstance { /// function)... so we just use an artificial ActorInstance to represent /// self in this case. CapturedActorSelf = 0x2, + + /// An actor instance in an async allocating init where we are going to + /// allocate the actual actor internally. This is considered to be isolated + /// to the actor instance. + ActorAsyncAllocatingInit = 0x3, }; - /// Set to (SILValue(), $KIND) if we have an ActorAccessorInit|CapturedSelf. - /// Is null if we have (SILValue(), Kind::Value). + /// Set to (SILValue(), $KIND) if we have an + /// ActorAccessorInit|CapturedSelf|ActorAsyncAllocatingInit. Is null if we + /// have (SILValue(), Kind::Value). llvm::PointerIntPair value; ActorInstance(SILValue value, Kind kind) @@ -94,6 +100,12 @@ class ActorInstance { return ActorInstance(SILValue(), Kind::CapturedActorSelf); } + /// See Kind::ActorAsyncAllocatingInit for explanation on what a + /// ActorAsyncAllocatingInit is. + static ActorInstance getForActorAsyncAllocatingInit() { + return ActorInstance(SILValue(), Kind::ActorAsyncAllocatingInit); + } + explicit operator bool() const { return bool(value.getOpaqueValue()); } Kind getKind() const { return Kind(value.getInt()); } @@ -117,6 +129,10 @@ class ActorInstance { return getKind() == Kind::CapturedActorSelf; } + bool isActorAsyncAllocatingInit() const { + return getKind() == Kind::ActorAsyncAllocatingInit; + } + bool operator==(const ActorInstance &other) const { // If both are null, return true. if (!bool(*this) && !bool(other)) @@ -132,6 +148,7 @@ class ActorInstance { return getValue() == other.getValue(); case Kind::ActorAccessorInit: case Kind::CapturedActorSelf: + case Kind::ActorAsyncAllocatingInit: return true; } } diff --git a/lib/SILOptimizer/Utils/SILIsolationInfo.cpp b/lib/SILOptimizer/Utils/SILIsolationInfo.cpp index 41256a898c32c..6ae7feffa307f 100644 --- a/lib/SILOptimizer/Utils/SILIsolationInfo.cpp +++ b/lib/SILOptimizer/Utils/SILIsolationInfo.cpp @@ -426,14 +426,17 @@ static bool isPartialApplyNonisolatedUnsafe(PartialApplyInst *pai) { return foundOneNonIsolatedUnsafe; } -/// Return the SILIsolationInfo for a class field. +/// Return the SILIsolationInfo for a class field for a ref_element_addr or +/// class_method. Methods that are direct should get their isolation information +/// from the static function rather than from this function. /// /// \arg queriedValue the actual value that SILIsolationInfo::get was called /// upon. This is used for IsolationHistory. /// /// \arg classValue this is the actual underlying class value that we are /// extracting a field out of. As an example this is the base passed to -/// ref_element_addr or class_method. +/// ref_element_addr or class_method. This /can/ be a metatype potentially in +/// the case of class 'class' methods and computed properties. /// /// \arg field the actual AST field that we discovered we are querying. This /// could be the field of the ref_element_addr or an accessor decl extracted @@ -441,12 +444,13 @@ static bool isPartialApplyNonisolatedUnsafe(PartialApplyInst *pai) { static SILIsolationInfo computeIsolationForClassField(SILValue queriedValue, SILValue classValue, ValueDecl *field) { + // First look for explicit isolation on the field itself. These always + // override what is on the class. auto varIsolation = swift::getActorIsolation(field); - // If we have a global actor isolated field, then we know that we override - // the actual isolation of the actor or global actor isolated class with - // some other form of isolation. In such a case, we need to use that - // isolation instead. + // If we have an explicitly global actor isolated field, then we must prefer + // that isolation since it takes precedence over any isolation directly on the + // underlying class type. if (varIsolation.isGlobalActor()) { assert(!varIsolation.isNonisolatedUnsafe() && "Cannot apply both nonisolated(unsafe) and a global actor attribute " @@ -455,27 +459,74 @@ static SILIsolationInfo computeIsolationForClassField(SILValue queriedValue, queriedValue, varIsolation.getGlobalActor()); } + // Then check if our field is explicitly nonisolated (not + // nonisolated(unsafe)). In such a case, we want to return disconnected since + // we are overriding the isolation of the actual nominal type. If we have + // nonisolated(unsafe), we want to respect the isolation of the nominal type + // since we just want to squelch the error but still have it be isolated in + // its normal way. This provides more information since we know what the + // underlying isolation /would/ have been. + if (varIsolation.isNonisolated() && !varIsolation.isNonisolatedUnsafe()) + return SILIsolationInfo::getDisconnected(false /*nonisolated unsafe*/); + + // Ok, we know that we do not have any overriding isolation from the var + // itself... so now we should use isolation from the underlying nominal type. + + // First see if we have an actor instance value from an isolated + // SILFunctionArgument. if (auto instance = ActorInstance::getForValue(classValue)) { if (auto *fArg = llvm::dyn_cast_or_null( instance.maybeGetValue())) { if (auto info = - SILIsolationInfo::getActorInstanceIsolated(queriedValue, fArg)) + SILIsolationInfo::getActorInstanceIsolated(queriedValue, fArg)) { return info.withUnsafeNonIsolated(varIsolation.isNonisolatedUnsafe()); + } } } - auto *nomDecl = classValue->getType().getNominalOrBoundGenericNominal(); + // First find out if our classValue is a nominal type and exit early... + if (auto *nomDecl = classValue->getType().getNominalOrBoundGenericNominal()) { + if (auto isolation = swift::getActorIsolation(nomDecl); + isolation && isolation.isGlobalActor()) { + return SILIsolationInfo::getGlobalActorIsolated( + queriedValue, isolation.getGlobalActor()) + .withUnsafeNonIsolated(varIsolation.isNonisolatedUnsafe()); + } - if (nomDecl->isAnyActor()) - return SILIsolationInfo::getActorInstanceIsolated(queriedValue, classValue, - nomDecl) - .withUnsafeNonIsolated(varIsolation.isNonisolatedUnsafe()); + if (nomDecl->isAnyActor()) + return SILIsolationInfo::getActorInstanceIsolated(queriedValue, + classValue, nomDecl) + .withUnsafeNonIsolated(varIsolation.isNonisolatedUnsafe()); + } + + // If we have a metatype... + if (classValue->getType().isMetatype()) { + // And we can a class nominal decl... + if (auto *nomDecl = + classValue->getType() + .getLoweredInstanceTypeOfMetatype(classValue->getFunction()) + .getNominalOrBoundGenericNominal()) { - if (auto isolation = swift::getActorIsolation(nomDecl); - isolation && isolation.isGlobalActor()) { - return SILIsolationInfo::getGlobalActorIsolated(queriedValue, - isolation.getGlobalActor()) - .withUnsafeNonIsolated(varIsolation.isNonisolatedUnsafe()); + // See if the nominal decl is global actor isolated. In such a case, we + // know that the metatype is also actor isolated. + if (auto isolation = swift::getActorIsolation(nomDecl); + isolation && isolation.isGlobalActor()) { + return SILIsolationInfo::getGlobalActorIsolated( + queriedValue, isolation.getGlobalActor()) + .withUnsafeNonIsolated(varIsolation.isNonisolatedUnsafe()); + } + + // Then finally check if we have an actor instance and we are getting an + // async allocating initializer for it. + if (nomDecl->isAnyActor()) { + if (auto *constructorDecl = dyn_cast(field); + constructorDecl && constructorDecl->isAsync()) { + return SILIsolationInfo::getActorInstanceIsolated( + classValue, ActorInstance::getForActorAsyncAllocatingInit(), + nomDecl); + } + } + } } return SILIsolationInfo::getDisconnected(varIsolation.isNonisolatedUnsafe()); @@ -759,81 +810,19 @@ SILIsolationInfo SILIsolationInfo::get(SILInstruction *inst) { } if (auto *cmi = dyn_cast(inst)) { - // Ok, we know that we do not have an actor... but we might have a global - // actor isolated method. Use the AST to compute the actor isolation and - // check if we are self. If we are not self, we want this to be - // disconnected. - if (auto *expr = cmi->getLoc().getAsASTNode()) { - DeclRefExprAnalysis exprAnalysis; - if (exprAnalysis.compute(expr)) { - auto *dre = exprAnalysis.getResult(); - - // First see if we can get any information from the actual var decl of - // the class_method. We could find isolation or if our value is marked - // as nonisolated(unsafe), we could find that as well. If we have - // nonisolated(unsafe), we just propagate the value. Otherwise, we - // return the isolation. - bool isNonIsolatedUnsafe = exprAnalysis.hasNonisolatedUnsafe(); - { - auto isolation = swift::getActorIsolation(dre->getDecl()); - - if (isolation.isActorIsolated()) { - // Check if we have a global actor and handle it appropriately. - if (isolation.getKind() == ActorIsolation::GlobalActor) { - bool localNonIsolatedUnsafe = - isNonIsolatedUnsafe | isolation.isNonisolatedUnsafe(); - return SILIsolationInfo::getGlobalActorIsolated( - cmi, isolation.getGlobalActor()) - .withUnsafeNonIsolated(localNonIsolatedUnsafe); - } - - // In this case, we have an actor instance that is self. - if (isolation.getKind() != ActorIsolation::ActorInstance && - isolation.isActorInstanceForSelfParameter()) { - bool localNonIsolatedUnsafe = - isNonIsolatedUnsafe | isolation.isNonisolatedUnsafe(); - return SILIsolationInfo::getActorInstanceIsolated( - cmi, cmi->getOperand(), - cmi->getOperand() - ->getType() - .getNominalOrBoundGenericNominal()) - .withUnsafeNonIsolated(localNonIsolatedUnsafe); - } - } - } - - if (auto type = dre->getType()->getNominalOrBoundGenericNominal()) { - if (auto isolation = swift::getActorIsolation(type)) { - if (isolation.isActorIsolated()) { - // Check if we have a global actor and handle it appropriately. - if (isolation.getKind() == ActorIsolation::GlobalActor) { - bool localNonIsolatedUnsafe = - isNonIsolatedUnsafe | isolation.isNonisolatedUnsafe(); - return SILIsolationInfo::getGlobalActorIsolated( - cmi, isolation.getGlobalActor()) - .withUnsafeNonIsolated(localNonIsolatedUnsafe); - } + auto base = cmi->getOperand(); + auto member = cmi->getMember(); - // In this case, we have an actor instance that is self. - if (isolation.getKind() != ActorIsolation::ActorInstance && - isolation.isActorInstanceForSelfParameter()) { - bool localNonIsolatedUnsafe = - isNonIsolatedUnsafe | isolation.isNonisolatedUnsafe(); - return SILIsolationInfo::getActorInstanceIsolated( - cmi, cmi->getOperand(), - cmi->getOperand() - ->getType() - .getNominalOrBoundGenericNominal()) - .withUnsafeNonIsolated(localNonIsolatedUnsafe); - } - } - } - } + // First see if we can use our SILDeclRef to infer isolation. + if (auto *accessor = member.getAccessorDecl()) { + return computeIsolationForClassField(cmi, base, accessor); + } - if (isNonIsolatedUnsafe) - return SILIsolationInfo::getDisconnected(isNonIsolatedUnsafe); - } + if (auto *funcDecl = member.getAbstractFunctionDecl()) { + return computeIsolationForClassField(cmi, base, funcDecl); } + + llvm_unreachable("Unsupported?!"); } // See if we have a struct_extract from a global-actor-isolated type. @@ -1392,6 +1381,12 @@ void SILIsolationInfo::print(SILFunction *fn, llvm::raw_ostream &os) const { os << '\n'; os << "instance: captured actor instance self\n"; return; + case ActorInstance::Kind::ActorAsyncAllocatingInit: + os << "'self'-isolated"; + printOptions(os); + os << '\n'; + os << "instance: actor async allocating init\n"; + return; } } @@ -1522,9 +1517,8 @@ void SILIsolationInfo::printForDiagnostics(SILFunction *fn, break; } case ActorInstance::Kind::ActorAccessorInit: - os << "'self'-isolated"; - return; case ActorInstance::Kind::CapturedActorSelf: + case ActorInstance::Kind::ActorAsyncAllocatingInit: os << "'self'-isolated"; return; } @@ -1591,9 +1585,8 @@ void SILIsolationInfo::printForCodeDiagnostic(SILFunction *fn, break; } case ActorInstance::Kind::ActorAccessorInit: - os << "'self'-isolated code"; - return; case ActorInstance::Kind::CapturedActorSelf: + case ActorInstance::Kind::ActorAsyncAllocatingInit: os << "'self'-isolated code"; return; } @@ -1645,6 +1638,10 @@ void SILIsolationInfo::printForOneLineLogging(SILFunction *fn, os << "'self'-isolated (captured-actor-self)"; printOptions(os); return; + case ActorInstance::Kind::ActorAsyncAllocatingInit: + os << "'self'-isolated (actor-async-allocating-init)"; + printOptions(os); + return; } } @@ -1876,6 +1873,9 @@ void ActorInstance::print(llvm::raw_ostream &os) const { case Kind::CapturedActorSelf: os << "CapturedActorSelf."; break; + case Kind::ActorAsyncAllocatingInit: + os << "ActorAsyncAllocatingInit."; + break; } if (auto value = maybeGetValue()) { diff --git a/test/Concurrency/silisolationinfo_inference.sil b/test/Concurrency/silisolationinfo_inference.sil index b37566dd62e28..8733347710f39 100644 --- a/test/Concurrency/silisolationinfo_inference.sil +++ b/test/Concurrency/silisolationinfo_inference.sil @@ -22,10 +22,22 @@ class NonSendableKlass { } actor MyActor { + init() + @MainActor init(_ x: NonSendableKlass) + init() async + var ns: NonSendableKlass @MainActor var globalActorNS: NonSendableKlass nonisolated(unsafe) var nsNonisolatedUnsafe: NonSendableKlass + var nsComputed: NonSendableKlass { get set } + @MainActor var globalActorNSComputed: NonSendableKlass { get set } + nonisolated var nsNonisolatedComputed: NonSendableKlass { get set } + + func getNS() -> NonSendableKlass + @MainActor func getNSGlobalActor() -> NonSendableKlass + nonisolated func getNSNonisolated() -> NonSendableKlass + func doSomething() async -> NonSendableKlass } @@ -40,12 +52,46 @@ struct CustomActor { var ns: NonSendableKlass @CustomActor var globalActorNS: NonSendableKlass nonisolated(unsafe) var nsNonisolatedUnsafe: NonSendableKlass + + var nsComputed: NonSendableKlass { get } + @CustomActor var globalActorNSComputed: NonSendableKlass { get set } + nonisolated var nsNonisolatedComputed: NonSendableKlass { get set } + + func getNS() -> NonSendableKlass + @CustomActor func getNSGlobalActor() -> NonSendableKlass + nonisolated func getNSNonisolated() -> NonSendableKlass + + class var nsClassComputed: NonSendableKlass { get set } + @CustomActor class var globalActorNSClassComputed: NonSendableKlass { get set } + nonisolated(unsafe) class var nsNonisolatedUnsafeClassComputed: NonSendableKlass { get set } + nonisolated class var nsNonisolatedClassComputed: NonSendableKlass { get set } + + class func getNSClassFunc() -> NonSendableKlass + @CustomActor class func getNSGlobalActorClassFunc() -> NonSendableKlass + nonisolated class func getNSNonisolatedClassFunc() -> NonSendableKlass } class NonisolatedKlass { var ns: NonSendableKlass @CustomActor var globalActorNS: NonSendableKlass nonisolated(unsafe) var nsNonisolatedUnsafe: NonSendableKlass + + var nsComputed: NonSendableKlass { get set } + @CustomActor var globalActorNSComputed: NonSendableKlass { get set } + nonisolated var nsNonisolatedComputed: NonSendableKlass { get set } + + func getNS() -> NonSendableKlass + @CustomActor func getNSGlobalActor() -> NonSendableKlass + nonisolated func getNSNonisolated() -> NonSendableKlass + + class var nsClassComputed: NonSendableKlass { get set } + @CustomActor class var globalActorNSClassComputed: NonSendableKlass { get set } + nonisolated(unsafe) class var nsNonisolatedUnsafeClassComputed: NonSendableKlass { get set } + nonisolated class var nsNonisolatedClassComputed: NonSendableKlass { get set } + + class func getNSClassFunc() -> NonSendableKlass + @CustomActor class func getNSGlobalActorClassFunc() -> NonSendableKlass + nonisolated class func getNSNonisolatedClassFunc() -> NonSendableKlass } @MainActor struct MainActorIsolatedStruct { @@ -1226,3 +1272,629 @@ bb0(%0 : $*NonisolatedStruct): %9999 = tuple () return %9999 : $() } + +/////////////////////////////// +// MARK: Computed Properties // +/////////////////////////////// + +// CHECK-LABEL: begin running test 1 of 1 on test_globalactor_inference_on_nominal_computedproperty_actor: sil_isolation_info_inference with: @trace[0] +// CHECK: Input Value: %2 = class_method %0 : $MyActor, #MyActor.nsComputed!getter : (isolated MyActor) -> () -> NonSendableKlass, $@convention(method) (@sil_isolated @guaranteed MyActor) -> @owned NonSendableKlass +// CHECK: Isolation: 'self'-isolated +// CHECK: end running test 1 of 1 on test_globalactor_inference_on_nominal_computedproperty_actor: sil_isolation_info_inference with: @trace[0] +sil [ossa] @test_globalactor_inference_on_nominal_computedproperty_actor : $@convention(thin) (@guaranteed @sil_isolated MyActor) -> () { +bb0(%0 : @guaranteed $MyActor): + specify_test "sil_isolation_info_inference @trace[0]" + debug_value %0 : $MyActor, let, name "self" + %1 = class_method %0 : $MyActor, #MyActor.nsComputed!getter : (isolated MyActor) -> () -> NonSendableKlass, $@convention(method) (@sil_isolated @guaranteed MyActor) -> @owned NonSendableKlass + debug_value [trace] %1 + %9999 = tuple () + return %9999 : $() +} + +// CHECK-LABEL: begin running test 1 of 1 on test_globalactor_inference_on_nominal_computedproperty_actor_globalactor: sil_isolation_info_inference with: @trace[0] +// CHECK: Input Value: %2 = class_method %0 : $MyActor, #MyActor.globalActorNSComputed!getter : (MyActor) -> () -> NonSendableKlass, $@convention(method) (@guaranteed MyActor) -> @owned NonSendableKlass +// CHECK: Isolation: main actor-isolated +// CHECK: end running test 1 of 1 on test_globalactor_inference_on_nominal_computedproperty_actor_globalactor: sil_isolation_info_inference with: @trace[0] +sil [ossa] @test_globalactor_inference_on_nominal_computedproperty_actor_globalactor : $@convention(thin) (@guaranteed MyActor) -> () { +bb0(%0 : @guaranteed $MyActor): + specify_test "sil_isolation_info_inference @trace[0]" + debug_value %0 : $MyActor, let, name "self" + %1 = class_method %0, #MyActor.globalActorNSComputed!getter : (MyActor) -> () -> NonSendableKlass, $@convention(method) (@guaranteed MyActor) -> @owned NonSendableKlass + debug_value [trace] %1 + %9999 = tuple () + return %9999 : $() +} + +// CHECK-LABEL: begin running test 1 of 1 on test_globalactor_inference_on_nominal_computedproperty_actor_nonisolated: sil_isolation_info_inference with: @trace[0] +// CHECK: Input Value: %2 = class_method %0 : $MyActor, #MyActor.nsNonisolatedComputed!getter : (MyActor) -> () -> NonSendableKlass, $@convention(method) (@guaranteed MyActor) -> @owned NonSendableKlass +// CHECK: Isolation: disconnected +// CHECK: end running test 1 of 1 on test_globalactor_inference_on_nominal_computedproperty_actor_nonisolated: sil_isolation_info_inference with: @trace[0] +sil [ossa] @test_globalactor_inference_on_nominal_computedproperty_actor_nonisolated : $@convention(thin) (@sil_isolated @guaranteed MyActor) -> () { +bb0(%0 : @guaranteed $MyActor): + specify_test "sil_isolation_info_inference @trace[0]" + debug_value %0 : $MyActor, let, name "self" + %1 = class_method %0 : $MyActor, #MyActor.nsNonisolatedComputed!getter : (MyActor) -> () -> NonSendableKlass, $@convention(method) (@guaranteed MyActor) -> @owned NonSendableKlass + debug_value [trace] %1 + %9999 = tuple () + return %9999 : $() +} + +// CHECK-LABEL: begin running test 1 of 1 on test_globalactor_inference_on_nominal_computedproperty_globalactorklass: sil_isolation_info_inference with: @trace[0] +// CHECK: Input Value: %2 = class_method %0 : $MainActorIsolatedKlass, #MainActorIsolatedKlass.nsComputed!getter : (MainActorIsolatedKlass) -> () -> NonSendableKlass, $@convention(method) (@guaranteed MainActorIsolatedKlass) -> @owned NonSendableKlass +// CHECK: Isolation: main actor-isolated +// CHECK: end running test 1 of 1 on test_globalactor_inference_on_nominal_computedproperty_globalactorklass: sil_isolation_info_inference with: @trace[0] +sil [ossa] @test_globalactor_inference_on_nominal_computedproperty_globalactorklass : $@convention(thin) (@guaranteed MainActorIsolatedKlass) -> () { +bb0(%0 : @guaranteed $MainActorIsolatedKlass): + specify_test "sil_isolation_info_inference @trace[0]" + debug_value %0 : $MainActorIsolatedKlass, let, name "self" + %1 = class_method %0 : $MainActorIsolatedKlass, #MainActorIsolatedKlass.nsComputed!getter : (MainActorIsolatedKlass) -> () -> NonSendableKlass, $@convention(method) (@guaranteed MainActorIsolatedKlass) -> @owned NonSendableKlass + debug_value [trace] %1 + %9999 = tuple () + return %9999 : $() +} + +// CHECK-LABEL: begin running test 1 of 1 on test_globalactor_inference_on_nominal_computedproperty_globalactorklass_globalactor: sil_isolation_info_inference with: @trace[0] +// CHECK: Input Value: %2 = class_method %0 : $MainActorIsolatedKlass, #MainActorIsolatedKlass.globalActorNSComputed!getter : (MainActorIsolatedKlass) -> () -> NonSendableKlass, $@convention(method) (@guaranteed MainActorIsolatedKlass) -> @owned NonSendableKlass +// CHECK: Isolation: global actor 'CustomActor'-isolated +// CHECK: end running test 1 of 1 on test_globalactor_inference_on_nominal_computedproperty_globalactorklass_globalactor: sil_isolation_info_inference with: @trace[0] +sil [ossa] @test_globalactor_inference_on_nominal_computedproperty_globalactorklass_globalactor : $@convention(thin) (@guaranteed MainActorIsolatedKlass) -> () { +bb0(%0 : @guaranteed $MainActorIsolatedKlass): + specify_test "sil_isolation_info_inference @trace[0]" + debug_value %0 : $MainActorIsolatedKlass, let, name "self" + %1 = class_method %0, #MainActorIsolatedKlass.globalActorNSComputed!getter : (MainActorIsolatedKlass) -> () -> NonSendableKlass, $@convention(method) (@guaranteed MainActorIsolatedKlass) -> @owned NonSendableKlass + debug_value [trace] %1 + %9999 = tuple () + return %9999 : $() +} + +// CHECK-LABEL: begin running test 1 of 1 on test_globalactor_inference_on_nominal_computedproperty_globalactorklass_nonisolated: sil_isolation_info_inference with: @trace[0] +// CHECK: Input Value: %2 = class_method %0 : $MainActorIsolatedKlass, #MainActorIsolatedKlass.nsNonisolatedComputed!getter : (MainActorIsolatedKlass) -> () -> NonSendableKlass, $@convention(method) (@guaranteed MainActorIsolatedKlass) -> @owned NonSendableKlass +// CHECK: Isolation: disconnected +// CHECK: end running test 1 of 1 on test_globalactor_inference_on_nominal_computedproperty_globalactorklass_nonisolated: sil_isolation_info_inference with: @trace[0] +sil [ossa] @test_globalactor_inference_on_nominal_computedproperty_globalactorklass_nonisolated : $@convention(thin) (@guaranteed MainActorIsolatedKlass) -> () { +bb0(%0 : @guaranteed $MainActorIsolatedKlass): + specify_test "sil_isolation_info_inference @trace[0]" + debug_value %0 : $MainActorIsolatedKlass, let, name "self" + %1 = class_method %0 : $MainActorIsolatedKlass, #MainActorIsolatedKlass.nsNonisolatedComputed!getter : (MainActorIsolatedKlass) -> () -> NonSendableKlass, $@convention(method) (@guaranteed MainActorIsolatedKlass) -> @owned NonSendableKlass + debug_value [trace] %1 + %9999 = tuple () + return %9999 : $() +} + +// CHECK-LABEL: begin running test 1 of 1 on test_globalactor_inference_on_nominal_computedproperty_nonisolatedklass: sil_isolation_info_inference with: @trace[0] +// CHECK: Input Value: %2 = class_method %0 : $NonisolatedKlass, #NonisolatedKlass.nsComputed!getter : (NonisolatedKlass) -> () -> NonSendableKlass, $@convention(method) (@guaranteed NonisolatedKlass) -> @owned NonSendableKlass +// CHECK: Isolation: disconnected +// CHECK: end running test 1 of 1 on test_globalactor_inference_on_nominal_computedproperty_nonisolatedklass: sil_isolation_info_inference with: @trace[0] +sil [ossa] @test_globalactor_inference_on_nominal_computedproperty_nonisolatedklass : $@convention(thin) (@guaranteed NonisolatedKlass) -> () { +bb0(%0 : @guaranteed $NonisolatedKlass): + specify_test "sil_isolation_info_inference @trace[0]" + debug_value %0 : $NonisolatedKlass, let, name "self" + %1 = class_method %0 : $NonisolatedKlass, #NonisolatedKlass.nsComputed!getter : (NonisolatedKlass) -> () -> NonSendableKlass, $@convention(method) (@guaranteed NonisolatedKlass) -> @owned NonSendableKlass + debug_value [trace] %1 + %9999 = tuple () + return %9999 : $() +} + +// CHECK-LABEL: begin running test 1 of 1 on test_globalactor_inference_on_nominal_computedproperty_nonisolatedklass_globalactor: sil_isolation_info_inference with: @trace[0] +// CHECK: Input Value: %2 = class_method %0 : $NonisolatedKlass, #NonisolatedKlass.globalActorNSComputed!getter : (NonisolatedKlass) -> () -> NonSendableKlass, $@convention(method) (@guaranteed NonisolatedKlass) -> @owned NonSendableKlass +// CHECK: Isolation: global actor 'CustomActor'-isolated +// CHECK: end running test 1 of 1 on test_globalactor_inference_on_nominal_computedproperty_nonisolatedklass_globalactor: sil_isolation_info_inference with: @trace[0] +sil [ossa] @test_globalactor_inference_on_nominal_computedproperty_nonisolatedklass_globalactor : $@convention(thin) (@guaranteed NonisolatedKlass) -> () { +bb0(%0 : @guaranteed $NonisolatedKlass): + specify_test "sil_isolation_info_inference @trace[0]" + debug_value %0 : $NonisolatedKlass, let, name "self" + %1 = class_method %0, #NonisolatedKlass.globalActorNSComputed!getter : (NonisolatedKlass) -> () -> NonSendableKlass, $@convention(method) (@guaranteed NonisolatedKlass) -> @owned NonSendableKlass + debug_value [trace] %1 + %9999 = tuple () + return %9999 : $() +} + +// CHECK-LABEL: begin running test 1 of 1 on test_globalactor_inference_on_nominal_computedproperty_nonisolatedklass_nonisolated: sil_isolation_info_inference with: @trace[0] +// CHECK: Input Value: %2 = class_method %0 : $NonisolatedKlass, #NonisolatedKlass.nsNonisolatedComputed!getter : (NonisolatedKlass) -> () -> NonSendableKlass, $@convention(method) (@guaranteed NonisolatedKlass) -> @owned NonSendableKlass +// CHECK: Isolation: disconnected +// CHECK: end running test 1 of 1 on test_globalactor_inference_on_nominal_computedproperty_nonisolatedklass_nonisolated: sil_isolation_info_inference with: @trace[0] +sil [ossa] @test_globalactor_inference_on_nominal_computedproperty_nonisolatedklass_nonisolated : $@convention(thin) (@guaranteed NonisolatedKlass) -> () { +bb0(%0 : @guaranteed $NonisolatedKlass): + specify_test "sil_isolation_info_inference @trace[0]" + debug_value %0 : $NonisolatedKlass, let, name "self" + %1 = class_method %0 : $NonisolatedKlass, #NonisolatedKlass.nsNonisolatedComputed!getter : (NonisolatedKlass) -> () -> NonSendableKlass, $@convention(method) (@guaranteed NonisolatedKlass) -> @owned NonSendableKlass + debug_value [trace] %1 + %9999 = tuple () + return %9999 : $() +} + +////////////////////////////////// +// MARK: class method functions // +////////////////////////////////// + +// CHECK-LABEL: begin running test 1 of 1 on test_globalactor_inference_on_nominal_method_actor: sil_isolation_info_inference with: @trace[0] +// CHECK: Input Value: %2 = class_method %0 : $MyActor, #MyActor.getNS : (isolated MyActor) -> () -> NonSendableKlass, $@convention(method) (@sil_isolated @guaranteed MyActor) -> @owned NonSendableKlass +// CHECK: Isolation: 'self'-isolated +// CHECK: end running test 1 of 1 on test_globalactor_inference_on_nominal_method_actor: sil_isolation_info_inference with: @trace[0] +sil [ossa] @test_globalactor_inference_on_nominal_method_actor : $@convention(thin) (@guaranteed @sil_isolated MyActor) -> () { +bb0(%0 : @guaranteed $MyActor): + specify_test "sil_isolation_info_inference @trace[0]" + debug_value %0 : $MyActor, let, name "self" + %1 = class_method %0 : $MyActor, #MyActor.getNS : (isolated MyActor) -> () -> NonSendableKlass, $@convention(method) (@sil_isolated @guaranteed MyActor) -> @owned NonSendableKlass + debug_value [trace] %1 + %9999 = tuple () + return %9999 : $() +} + +// CHECK-LABEL: begin running test 1 of 1 on test_globalactor_inference_on_nominal_method_actor_globalactor: sil_isolation_info_inference with: @trace[0] +// CHECK: Input Value: %2 = class_method %0 : $MyActor, #MyActor.getNSGlobalActor : (MyActor) -> () -> NonSendableKlass, $@convention(method) (@guaranteed MyActor) -> @owned NonSendableKlass +// CHECK: Isolation: main actor-isolated +// CHECK: end running test 1 of 1 on test_globalactor_inference_on_nominal_method_actor_globalactor: sil_isolation_info_inference with: @trace[0] +sil [ossa] @test_globalactor_inference_on_nominal_method_actor_globalactor : $@convention(thin) (@guaranteed MyActor) -> () { +bb0(%0 : @guaranteed $MyActor): + specify_test "sil_isolation_info_inference @trace[0]" + debug_value %0 : $MyActor, let, name "self" + %1 = class_method %0, #MyActor.getNSGlobalActor : (MyActor) -> () -> NonSendableKlass, $@convention(method) (@guaranteed MyActor) -> @owned NonSendableKlass + debug_value [trace] %1 + %9999 = tuple () + return %9999 : $() +} + +// CHECK-LABEL: begin running test 1 of 1 on test_globalactor_inference_on_nominal_method_actor_nonisolated: sil_isolation_info_inference with: @trace[0] +// CHECK: Input Value: %2 = class_method %0 : $MyActor, #MyActor.getNSNonisolated : (MyActor) -> () -> NonSendableKlass, $@convention(method) (@guaranteed MyActor) -> @owned NonSendableKlass +// CHECK: Isolation: disconnected +// CHECK: end running test 1 of 1 on test_globalactor_inference_on_nominal_method_actor_nonisolated: sil_isolation_info_inference with: @trace[0] +sil [ossa] @test_globalactor_inference_on_nominal_method_actor_nonisolated : $@convention(thin) (@sil_isolated @guaranteed MyActor) -> () { +bb0(%0 : @guaranteed $MyActor): + specify_test "sil_isolation_info_inference @trace[0]" + debug_value %0 : $MyActor, let, name "self" + %1 = class_method %0 : $MyActor, #MyActor.getNSNonisolated : (MyActor) -> () -> NonSendableKlass, $@convention(method) (@guaranteed MyActor) -> @owned NonSendableKlass + debug_value [trace] %1 + %9999 = tuple () + return %9999 : $() +} + +// CHECK-LABEL: begin running test 1 of 1 on test_globalactor_inference_on_nominal_method_globalactorklass: sil_isolation_info_inference with: @trace[0] +// CHECK: Input Value: %2 = class_method %0 : $MainActorIsolatedKlass, #MainActorIsolatedKlass.getNS : (MainActorIsolatedKlass) -> () -> NonSendableKlass, $@convention(method) (@guaranteed MainActorIsolatedKlass) -> @owned NonSendableKlass +// CHECK: Isolation: main actor-isolated +// CHECK: end running test 1 of 1 on test_globalactor_inference_on_nominal_method_globalactorklass: sil_isolation_info_inference with: @trace[0] +sil [ossa] @test_globalactor_inference_on_nominal_method_globalactorklass : $@convention(thin) (@guaranteed MainActorIsolatedKlass) -> () { +bb0(%0 : @guaranteed $MainActorIsolatedKlass): + specify_test "sil_isolation_info_inference @trace[0]" + debug_value %0 : $MainActorIsolatedKlass, let, name "self" + %1 = class_method %0 : $MainActorIsolatedKlass, #MainActorIsolatedKlass.getNS : (MainActorIsolatedKlass) -> () -> NonSendableKlass, $@convention(method) (@guaranteed MainActorIsolatedKlass) -> @owned NonSendableKlass + debug_value [trace] %1 + %9999 = tuple () + return %9999 : $() +} + +// CHECK-LABEL: begin running test 1 of 1 on test_globalactor_inference_on_nominal_method_globalactorklass_globalactor: sil_isolation_info_inference with: @trace[0] +// CHECK: Input Value: %2 = class_method %0 : $MainActorIsolatedKlass, #MainActorIsolatedKlass.getNSGlobalActor : (MainActorIsolatedKlass) -> () -> NonSendableKlass, $@convention(method) (@guaranteed MainActorIsolatedKlass) -> @owned NonSendableKlass +// CHECK: Isolation: global actor 'CustomActor'-isolated +// CHECK: end running test 1 of 1 on test_globalactor_inference_on_nominal_method_globalactorklass_globalactor: sil_isolation_info_inference with: @trace[0] +sil [ossa] @test_globalactor_inference_on_nominal_method_globalactorklass_globalactor : $@convention(thin) (@guaranteed MainActorIsolatedKlass) -> () { +bb0(%0 : @guaranteed $MainActorIsolatedKlass): + specify_test "sil_isolation_info_inference @trace[0]" + debug_value %0 : $MainActorIsolatedKlass, let, name "self" + %1 = class_method %0, #MainActorIsolatedKlass.getNSGlobalActor : (MainActorIsolatedKlass) -> () -> NonSendableKlass, $@convention(method) (@guaranteed MainActorIsolatedKlass) -> @owned NonSendableKlass + debug_value [trace] %1 + %9999 = tuple () + return %9999 : $() +} + +// CHECK-LABEL: begin running test 1 of 1 on test_globalactor_inference_on_nominal_method_globalactorklass_nonisolated: sil_isolation_info_inference with: @trace[0] +// CHECK: Input Value: %2 = class_method %0 : $MainActorIsolatedKlass, #MainActorIsolatedKlass.getNSNonisolated : (MainActorIsolatedKlass) -> () -> NonSendableKlass, $@convention(method) (@guaranteed MainActorIsolatedKlass) -> @owned NonSendableKlass +// CHECK: Isolation: disconnected +// CHECK: end running test 1 of 1 on test_globalactor_inference_on_nominal_method_globalactorklass_nonisolated: sil_isolation_info_inference with: @trace[0] +sil [ossa] @test_globalactor_inference_on_nominal_method_globalactorklass_nonisolated : $@convention(thin) (@guaranteed MainActorIsolatedKlass) -> () { +bb0(%0 : @guaranteed $MainActorIsolatedKlass): + specify_test "sil_isolation_info_inference @trace[0]" + debug_value %0 : $MainActorIsolatedKlass, let, name "self" + %1 = class_method %0 : $MainActorIsolatedKlass, #MainActorIsolatedKlass.getNSNonisolated : (MainActorIsolatedKlass) -> () -> NonSendableKlass, $@convention(method) (@guaranteed MainActorIsolatedKlass) -> @owned NonSendableKlass + debug_value [trace] %1 + %9999 = tuple () + return %9999 : $() +} + +// CHECK-LABEL: begin running test 1 of 1 on test_globalactor_inference_on_nominal_method_nonisolatedklass: sil_isolation_info_inference with: @trace[0] +// CHECK: Input Value: %2 = class_method %0 : $NonisolatedKlass, #NonisolatedKlass.getNS : (NonisolatedKlass) -> () -> NonSendableKlass, $@convention(method) (@guaranteed NonisolatedKlass) -> @owned NonSendableKlass +// CHECK: Isolation: disconnected +// CHECK: end running test 1 of 1 on test_globalactor_inference_on_nominal_method_nonisolatedklass: sil_isolation_info_inference with: @trace[0] +sil [ossa] @test_globalactor_inference_on_nominal_method_nonisolatedklass : $@convention(thin) (@guaranteed NonisolatedKlass) -> () { +bb0(%0 : @guaranteed $NonisolatedKlass): + specify_test "sil_isolation_info_inference @trace[0]" + debug_value %0 : $NonisolatedKlass, let, name "self" + %1 = class_method %0 : $NonisolatedKlass, #NonisolatedKlass.getNS : (NonisolatedKlass) -> () -> NonSendableKlass, $@convention(method) (@guaranteed NonisolatedKlass) -> @owned NonSendableKlass + debug_value [trace] %1 + %9999 = tuple () + return %9999 : $() +} + +// CHECK-LABEL: begin running test 1 of 1 on test_globalactor_inference_on_nominal_method_nonisolatedklass_globalactor: sil_isolation_info_inference with: @trace[0] +// CHECK: Input Value: %2 = class_method %0 : $NonisolatedKlass, #NonisolatedKlass.getNSGlobalActor : (NonisolatedKlass) -> () -> NonSendableKlass, $@convention(method) (@guaranteed NonisolatedKlass) -> @owned NonSendableKlass +// CHECK: Isolation: global actor 'CustomActor'-isolated +// CHECK: end running test 1 of 1 on test_globalactor_inference_on_nominal_method_nonisolatedklass_globalactor: sil_isolation_info_inference with: @trace[0] +sil [ossa] @test_globalactor_inference_on_nominal_method_nonisolatedklass_globalactor : $@convention(thin) (@guaranteed NonisolatedKlass) -> () { +bb0(%0 : @guaranteed $NonisolatedKlass): + specify_test "sil_isolation_info_inference @trace[0]" + debug_value %0 : $NonisolatedKlass, let, name "self" + %1 = class_method %0, #NonisolatedKlass.getNSGlobalActor : (NonisolatedKlass) -> () -> NonSendableKlass, $@convention(method) (@guaranteed NonisolatedKlass) -> @owned NonSendableKlass + debug_value [trace] %1 + %9999 = tuple () + return %9999 : $() +} + +// CHECK-LABEL: begin running test 1 of 1 on test_globalactor_inference_on_nominal_method_nonisolatedklass_nonisolated: sil_isolation_info_inference with: @trace[0] +// CHECK: Input Value: %2 = class_method %0 : $NonisolatedKlass, #NonisolatedKlass.getNSNonisolated : (NonisolatedKlass) -> () -> NonSendableKlass, $@convention(method) (@guaranteed NonisolatedKlass) -> @owned NonSendableKlass +// CHECK: Isolation: disconnected +// CHECK: end running test 1 of 1 on test_globalactor_inference_on_nominal_method_nonisolatedklass_nonisolated: sil_isolation_info_inference with: @trace[0] +sil [ossa] @test_globalactor_inference_on_nominal_method_nonisolatedklass_nonisolated : $@convention(thin) (@guaranteed NonisolatedKlass) -> () { +bb0(%0 : @guaranteed $NonisolatedKlass): + specify_test "sil_isolation_info_inference @trace[0]" + debug_value %0 : $NonisolatedKlass, let, name "self" + %1 = class_method %0 : $NonisolatedKlass, #NonisolatedKlass.getNSNonisolated : (NonisolatedKlass) -> () -> NonSendableKlass, $@convention(method) (@guaranteed NonisolatedKlass) -> @owned NonSendableKlass + debug_value [trace] %1 + %9999 = tuple () + return %9999 : $() +} + +////////////////////////////// +// MARK: metatype allocator // +////////////////////////////// + +// CHECK-LABEL: begin running test 1 of 1 on test_globalactor_inference_on_nominal_metatype_actor: sil_isolation_info_inference with: @trace[0] +// CHECK: Input Value: %1 = class_method %0 : $@thick MyActor.Type, #MyActor.init!allocator : (MyActor.Type) -> () -> MyActor, $@convention(method) (@thick MyActor.Type) -> @owned MyActor +// CHECK: Isolation: disconnected +// CHECK: end running test 1 of 1 on test_globalactor_inference_on_nominal_metatype_actor: sil_isolation_info_inference with: @trace[0] +sil [ossa] @test_globalactor_inference_on_nominal_metatype_actor : $@convention(thin) () -> () { +bb0: + specify_test "sil_isolation_info_inference @trace[0]" + %0 = metatype $@thick MyActor.Type + %1 = class_method %0, #MyActor.init!allocator : (MyActor.Type) -> () -> MyActor, $@convention(method) (@thick MyActor.Type) -> @owned MyActor + debug_value [trace] %1 + %9999 = tuple () + return %9999 : $() +} + +// CHECK-LABEL: begin running test 1 of 1 on test_globalactor_inference_on_nominal_metatype_actor_global: sil_isolation_info_inference with: @trace[0] +// CHECK: Input Value: %1 = class_method %0 : $@thick MyActor.Type, #MyActor.init!allocator : (MyActor.Type) -> (NonSendableKlass) -> MyActor, $@convention(method) (@owned NonSendableKlass, @thick MyActor.Type) -> @owned MyActor +// CHECK: Isolation: main actor-isolated +// CHECK: end running test 1 of 1 on test_globalactor_inference_on_nominal_metatype_actor_global: sil_isolation_info_inference with: @trace[0] +sil [ossa] @test_globalactor_inference_on_nominal_metatype_actor_global : $@convention(thin) () -> () { +bb0: + specify_test "sil_isolation_info_inference @trace[0]" + %0 = metatype $@thick MyActor.Type + %1 = class_method %0, #MyActor.init!allocator : (MyActor.Type) -> (NonSendableKlass) -> MyActor, $@convention(method) (@owned NonSendableKlass, @thick MyActor.Type) -> @owned MyActor + debug_value [trace] %1 + %9999 = tuple () + return %9999 : $() +} + +// CHECK-LABEL: begin running test 1 of 1 on test_globalactor_inference_on_nominal_metatype_actor_global_2: sil_isolation_info_inference with: @trace[0] +// CHECK: Input Value: %1 = class_method %0 : $@thick MyActor.Type, #MyActor.init!allocator : (MyActor.Type) -> () async -> MyActor, $@convention(method) @async (@thick MyActor.Type) -> @owned MyActor +// CHECK: Isolation: 'self'-isolated (actor-async-allocating-init) +// CHECK: end running test 1 of 1 on test_globalactor_inference_on_nominal_metatype_actor_global_2: sil_isolation_info_inference with: @trace[0] +sil [ossa] @test_globalactor_inference_on_nominal_metatype_actor_global_2 : $@convention(thin) () -> () { +bb0: + specify_test "sil_isolation_info_inference @trace[0]" + %0 = metatype $@thick MyActor.Type + %1 = class_method %0, #MyActor.init!allocator : (MyActor.Type) -> () async -> MyActor, $@convention(method) @async (@thick MyActor.Type) -> @owned MyActor + debug_value [trace] %1 + %9999 = tuple () + return %9999 : $() +} + +////////////////////////////////////// +// MARK: dynamic 'class' properties // +////////////////////////////////////// +// +// DISCUSSION: This is for methods on a class called a 'class method', that is +// methods that are dynamic methods on the metatype. These can only appear on +// classes, not on actors. + +// CHECK-LABEL: begin running test 1 of 1 on globalactor_isolated_class_classproperty_getter: sil_isolation_info_inference with: @trace[0] +// CHECK: Input Value: %1 = class_method %0 : $@thick MainActorIsolatedKlass.Type, #MainActorIsolatedKlass.nsClassComputed!getter : (MainActorIsolatedKlass.Type) -> () -> NonSendableKlass, $@convention(method) (@thick MainActorIsolatedKlass.Type) -> @owned NonSendableKlass +// CHECK: Isolation: main actor-isolated +// CHECK: end running test 1 of 1 on globalactor_isolated_class_classproperty_getter: sil_isolation_info_inference with: @trace[0] +sil [ossa] @globalactor_isolated_class_classproperty_getter : $@convention(thin) () -> () { +bb0: + specify_test "sil_isolation_info_inference @trace[0]" + %0 = metatype $@thick MainActorIsolatedKlass.Type + %1 = class_method %0, #MainActorIsolatedKlass.nsClassComputed!getter : (MainActorIsolatedKlass.Type) -> () -> NonSendableKlass, $@convention(method) (@thick MainActorIsolatedKlass.Type) -> @owned NonSendableKlass + debug_value [trace] %1 + %9999 = tuple () + return %9999 : $() +} + +// CHECK-LABEL: begin running test 1 of 1 on globalactor_isolated_class_classproperty_setter: sil_isolation_info_inference with: @trace[0] +// CHECK: Input Value: %1 = class_method %0 : $@thick MainActorIsolatedKlass.Type, #MainActorIsolatedKlass.nsClassComputed!setter : (MainActorIsolatedKlass.Type) -> (NonSendableKlass) -> (), $@convention(method) (@owned NonSendableKlass, @thick MainActorIsolatedKlass.Type) -> () +// CHECK: Isolation: main actor-isolated +// CHECK: end running test 1 of 1 on globalactor_isolated_class_classproperty_setter: sil_isolation_info_inference with: @trace[0] +sil [ossa] @globalactor_isolated_class_classproperty_setter : $@convention(thin) () -> () { +bb0: + specify_test "sil_isolation_info_inference @trace[0]" + %0 = metatype $@thick MainActorIsolatedKlass.Type +%1 = class_method %0, #MainActorIsolatedKlass.nsClassComputed!setter : (MainActorIsolatedKlass.Type) -> (NonSendableKlass) -> (), $@convention(method) (@owned NonSendableKlass, @thick MainActorIsolatedKlass.Type) -> () + debug_value [trace] %1 + %9999 = tuple () + return %9999 : $() +} + +// CHECK-LABEL: begin running test 1 of 1 on globalactor_isolated_class_globalactorclassproperty_getter: sil_isolation_info_inference with: @trace[0] +// CHECK: Input Value: %1 = class_method %0 : $@thick MainActorIsolatedKlass.Type, #MainActorIsolatedKlass.globalActorNSClassComputed!getter : (MainActorIsolatedKlass.Type) -> () -> NonSendableKlass, $@convention(method) (@thick MainActorIsolatedKlass.Type) -> @owned NonSendableKlass +// CHECK: Isolation: global actor 'CustomActor'-isolated +// CHECK: end running test 1 of 1 on globalactor_isolated_class_globalactorclassproperty_getter: sil_isolation_info_inference with: @trace[0] +sil [ossa] @globalactor_isolated_class_globalactorclassproperty_getter : $@convention(thin) () -> () { +bb0: + specify_test "sil_isolation_info_inference @trace[0]" + %0 = metatype $@thick MainActorIsolatedKlass.Type + %1 = class_method %0, #MainActorIsolatedKlass.globalActorNSClassComputed!getter : (MainActorIsolatedKlass.Type) -> () -> NonSendableKlass, $@convention(method) (@thick MainActorIsolatedKlass.Type) -> @owned NonSendableKlass + debug_value [trace] %1 + %9999 = tuple () + return %9999 : $() +} + +// CHECK-LABEL: begin running test 1 of 1 on globalactor_isolated_class_globalactorclassproperty_setter: sil_isolation_info_inference with: @trace[0] +// CHECK: Input Value: %1 = class_method %0 : $@thick MainActorIsolatedKlass.Type, #MainActorIsolatedKlass.globalActorNSClassComputed!setter : (MainActorIsolatedKlass.Type) -> (NonSendableKlass) -> (), $@convention(method) (@owned NonSendableKlass, @thick MainActorIsolatedKlass.Type) -> () +// CHECK: Isolation: global actor 'CustomActor'-isolated +// CHECK: end running test 1 of 1 on globalactor_isolated_class_globalactorclassproperty_setter: sil_isolation_info_inference with: @trace[0] +sil [ossa] @globalactor_isolated_class_globalactorclassproperty_setter : $@convention(thin) () -> () { +bb0: + specify_test "sil_isolation_info_inference @trace[0]" + %0 = metatype $@thick MainActorIsolatedKlass.Type + %1 = class_method %0, #MainActorIsolatedKlass.globalActorNSClassComputed!setter : (MainActorIsolatedKlass.Type) -> (NonSendableKlass) -> (), $@convention(method) (@owned NonSendableKlass, @thick MainActorIsolatedKlass.Type) -> () + debug_value [trace] %1 + %9999 = tuple () + return %9999 : $() +} + +// CHECK-LABEL: begin running test 1 of 1 on globalactor_isolated_class_nonisolatedunsafeclassproperty_getter: sil_isolation_info_inference with: @trace[0] +// CHECK: Input Value: %1 = class_method %0 : $@thick MainActorIsolatedKlass.Type, #MainActorIsolatedKlass.nsNonisolatedUnsafeClassComputed!getter : (MainActorIsolatedKlass.Type) -> () -> NonSendableKlass, $@convention(method) (@thick MainActorIsolatedKlass.Type) -> @owned NonSendableKlass +// CHECK: Isolation: main actor-isolated: nonisolated(unsafe) +// CHECK: end running test 1 of 1 on globalactor_isolated_class_nonisolatedunsafeclassproperty_getter: sil_isolation_info_inference with: @trace[0] +sil [ossa] @globalactor_isolated_class_nonisolatedunsafeclassproperty_getter : $@convention(thin) () -> () { +bb0: + specify_test "sil_isolation_info_inference @trace[0]" + %0 = metatype $@thick MainActorIsolatedKlass.Type + %1 = class_method %0, #MainActorIsolatedKlass.nsNonisolatedUnsafeClassComputed!getter : (MainActorIsolatedKlass.Type) -> () -> NonSendableKlass, $@convention(method) (@thick MainActorIsolatedKlass.Type) -> @owned NonSendableKlass + debug_value [trace] %1 + %9999 = tuple () + return %9999 : $() +} + +// CHECK-LABEL: begin running test 1 of 1 on globalactor_isolated_class_nonisolatedunsafeclassproperty_setter: sil_isolation_info_inference with: @trace[0] +// CHECK: Input Value: %1 = class_method %0 : $@thick MainActorIsolatedKlass.Type, #MainActorIsolatedKlass.nsNonisolatedUnsafeClassComputed!setter : (MainActorIsolatedKlass.Type) -> (NonSendableKlass) -> (), $@convention(method) (@owned NonSendableKlass, @thick MainActorIsolatedKlass.Type) -> () +// CHECK: Isolation: main actor-isolated: nonisolated(unsafe) +// CHECK: end running test 1 of 1 on globalactor_isolated_class_nonisolatedunsafeclassproperty_setter: sil_isolation_info_inference with: @trace[0] +sil [ossa] @globalactor_isolated_class_nonisolatedunsafeclassproperty_setter : $@convention(thin) () -> () { +bb0: + specify_test "sil_isolation_info_inference @trace[0]" + %0 = metatype $@thick MainActorIsolatedKlass.Type + %1 = class_method %0, #MainActorIsolatedKlass.nsNonisolatedUnsafeClassComputed!setter : (MainActorIsolatedKlass.Type) -> (NonSendableKlass) -> (), $@convention(method) (@owned NonSendableKlass, @thick MainActorIsolatedKlass.Type) -> () + debug_value [trace] %1 + %9999 = tuple () + return %9999 : $() +} + +// CHECK-LABEL: begin running test 1 of 1 on globalactor_isolated_class_nonisolatedclassproperty_getter: sil_isolation_info_inference with: @trace[0] +// CHECK: Input Value: %1 = class_method %0 : $@thick MainActorIsolatedKlass.Type, #MainActorIsolatedKlass.nsNonisolatedClassComputed!getter : (MainActorIsolatedKlass.Type) -> () -> NonSendableKlass, $@convention(method) (@thick MainActorIsolatedKlass.Type) -> @owned NonSendableKlass +// CHECK: Isolation: disconnected +// CHECK: end running test 1 of 1 on globalactor_isolated_class_nonisolatedclassproperty_getter: sil_isolation_info_inference with: @trace[0] +sil [ossa] @globalactor_isolated_class_nonisolatedclassproperty_getter : $@convention(thin) () -> () { +bb0: + specify_test "sil_isolation_info_inference @trace[0]" + %0 = metatype $@thick MainActorIsolatedKlass.Type + %1 = class_method %0, #MainActorIsolatedKlass.nsNonisolatedClassComputed!getter : (MainActorIsolatedKlass.Type) -> () -> NonSendableKlass, $@convention(method) (@thick MainActorIsolatedKlass.Type) -> @owned NonSendableKlass + debug_value [trace] %1 + %9999 = tuple () + return %9999 : $() +} + +// CHECK-LABEL: begin running test 1 of 1 on globalactor_isolated_class_nonisolatedclassproperty_setter: sil_isolation_info_inference with: @trace[0] +// CHECK: Input Value: %1 = class_method %0 : $@thick MainActorIsolatedKlass.Type, #MainActorIsolatedKlass.nsNonisolatedClassComputed!setter : (MainActorIsolatedKlass.Type) -> (NonSendableKlass) -> (), $@convention(method) (@owned NonSendableKlass, @thick MainActorIsolatedKlass.Type) -> () +// CHECK: Isolation: disconnected +// CHECK: end running test 1 of 1 on globalactor_isolated_class_nonisolatedclassproperty_setter: sil_isolation_info_inference with: @trace[0] +sil [ossa] @globalactor_isolated_class_nonisolatedclassproperty_setter : $@convention(thin) () -> () { +bb0: + specify_test "sil_isolation_info_inference @trace[0]" + %0 = metatype $@thick MainActorIsolatedKlass.Type + %1 = class_method %0, #MainActorIsolatedKlass.nsNonisolatedClassComputed!setter : (MainActorIsolatedKlass.Type) -> (NonSendableKlass) -> (), $@convention(method) (@owned NonSendableKlass, @thick MainActorIsolatedKlass.Type) -> () + debug_value [trace] %1 + %9999 = tuple () + return %9999 : $() +} + +// CHECK-LABEL: begin running test 1 of 1 on nonisolated_class_classproperty_getter: sil_isolation_info_inference with: @trace[0] +// CHECK: Input Value: %1 = class_method %0 : $@thick NonisolatedKlass.Type, #NonisolatedKlass.nsClassComputed!getter : (NonisolatedKlass.Type) -> () -> NonSendableKlass, $@convention(method) (@thick NonisolatedKlass.Type) -> @owned NonSendableKlass +// CHECK: Isolation: disconnected +// CHECK: end running test 1 of 1 on nonisolated_class_classproperty_getter: sil_isolation_info_inference with: @trace[0] +sil [ossa] @nonisolated_class_classproperty_getter : $@convention(thin) () -> () { +bb0: + specify_test "sil_isolation_info_inference @trace[0]" + %0 = metatype $@thick NonisolatedKlass.Type + %1 = class_method %0, #NonisolatedKlass.nsClassComputed!getter : (NonisolatedKlass.Type) -> () -> NonSendableKlass, $@convention(method) (@thick NonisolatedKlass.Type) -> @owned NonSendableKlass + debug_value [trace] %1 + %9999 = tuple () + return %9999 : $() +} + +// CHECK-LABEL: begin running test 1 of 1 on nonisolated_class_classproperty_setter: sil_isolation_info_inference with: @trace[0] +// CHECK: Input Value: %1 = class_method %0 : $@thick NonisolatedKlass.Type, #NonisolatedKlass.nsClassComputed!setter : (NonisolatedKlass.Type) -> (NonSendableKlass) -> (), $@convention(method) (@owned NonSendableKlass, @thick NonisolatedKlass.Type) -> () +// CHECK: Isolation: disconnected +// CHECK: end running test 1 of 1 on nonisolated_class_classproperty_setter: sil_isolation_info_inference with: @trace[0] +sil [ossa] @nonisolated_class_classproperty_setter : $@convention(thin) () -> () { +bb0: + specify_test "sil_isolation_info_inference @trace[0]" + %0 = metatype $@thick NonisolatedKlass.Type +%1 = class_method %0, #NonisolatedKlass.nsClassComputed!setter : (NonisolatedKlass.Type) -> (NonSendableKlass) -> (), $@convention(method) (@owned NonSendableKlass, @thick NonisolatedKlass.Type) -> () + debug_value [trace] %1 + %9999 = tuple () + return %9999 : $() +} + +// CHECK-LABEL: begin running test 1 of 1 on nonisolated_class_globalactorclassproperty_getter: sil_isolation_info_inference with: @trace[0] +// CHECK: Input Value: %1 = class_method %0 : $@thick NonisolatedKlass.Type, #NonisolatedKlass.globalActorNSClassComputed!getter : (NonisolatedKlass.Type) -> () -> NonSendableKlass, $@convention(method) (@thick NonisolatedKlass.Type) -> @owned NonSendableKlass +// CHECK: Isolation: global actor 'CustomActor'-isolated +// CHECK: end running test 1 of 1 on nonisolated_class_globalactorclassproperty_getter: sil_isolation_info_inference with: @trace[0] +sil [ossa] @nonisolated_class_globalactorclassproperty_getter : $@convention(thin) () -> () { +bb0: + specify_test "sil_isolation_info_inference @trace[0]" + %0 = metatype $@thick NonisolatedKlass.Type + %1 = class_method %0, #NonisolatedKlass.globalActorNSClassComputed!getter : (NonisolatedKlass.Type) -> () -> NonSendableKlass, $@convention(method) (@thick NonisolatedKlass.Type) -> @owned NonSendableKlass + debug_value [trace] %1 + %9999 = tuple () + return %9999 : $() +} + +// CHECK-LABEL: begin running test 1 of 1 on nonisolated_class_globalactorclassproperty_setter: sil_isolation_info_inference with: @trace[0] +// CHECK: Input Value: %1 = class_method %0 : $@thick NonisolatedKlass.Type, #NonisolatedKlass.globalActorNSClassComputed!setter : (NonisolatedKlass.Type) -> (NonSendableKlass) -> (), $@convention(method) (@owned NonSendableKlass, @thick NonisolatedKlass.Type) -> () +// CHECK: Isolation: global actor 'CustomActor'-isolated +// CHECK: end running test 1 of 1 on nonisolated_class_globalactorclassproperty_setter: sil_isolation_info_inference with: @trace[0] +sil [ossa] @nonisolated_class_globalactorclassproperty_setter : $@convention(thin) () -> () { +bb0: + specify_test "sil_isolation_info_inference @trace[0]" + %0 = metatype $@thick NonisolatedKlass.Type + %1 = class_method %0, #NonisolatedKlass.globalActorNSClassComputed!setter : (NonisolatedKlass.Type) -> (NonSendableKlass) -> (), $@convention(method) (@owned NonSendableKlass, @thick NonisolatedKlass.Type) -> () + debug_value [trace] %1 + %9999 = tuple () + return %9999 : $() +} + +// CHECK-LABEL: begin running test 1 of 1 on nonisolated_class_nonisolatedunsafeclassproperty_getter: sil_isolation_info_inference with: @trace[0] +// CHECK: Input Value: %1 = class_method %0 : $@thick NonisolatedKlass.Type, #NonisolatedKlass.nsNonisolatedUnsafeClassComputed!getter : (NonisolatedKlass.Type) -> () -> NonSendableKlass, $@convention(method) (@thick NonisolatedKlass.Type) -> @owned NonSendableKlass +// CHECK: Isolation: disconnected: nonisolated(unsafe) +// CHECK: end running test 1 of 1 on nonisolated_class_nonisolatedunsafeclassproperty_getter: sil_isolation_info_inference with: @trace[0] +sil [ossa] @nonisolated_class_nonisolatedunsafeclassproperty_getter : $@convention(thin) () -> () { +bb0: + specify_test "sil_isolation_info_inference @trace[0]" + %0 = metatype $@thick NonisolatedKlass.Type + %1 = class_method %0, #NonisolatedKlass.nsNonisolatedUnsafeClassComputed!getter : (NonisolatedKlass.Type) -> () -> NonSendableKlass, $@convention(method) (@thick NonisolatedKlass.Type) -> @owned NonSendableKlass + debug_value [trace] %1 + %9999 = tuple () + return %9999 : $() +} + +// CHECK-LABEL: begin running test 1 of 1 on nonisolated_class_nonisolatedunsafeclassproperty_setter: sil_isolation_info_inference with: @trace[0] +// CHECK: Input Value: %1 = class_method %0 : $@thick NonisolatedKlass.Type, #NonisolatedKlass.nsNonisolatedUnsafeClassComputed!setter : (NonisolatedKlass.Type) -> (NonSendableKlass) -> (), $@convention(method) (@owned NonSendableKlass, @thick NonisolatedKlass.Type) -> () +// CHECK: Isolation: disconnected: nonisolated(unsafe) +// CHECK: end running test 1 of 1 on nonisolated_class_nonisolatedunsafeclassproperty_setter: sil_isolation_info_inference with: @trace[0] +sil [ossa] @nonisolated_class_nonisolatedunsafeclassproperty_setter : $@convention(thin) () -> () { +bb0: + specify_test "sil_isolation_info_inference @trace[0]" + %0 = metatype $@thick NonisolatedKlass.Type + %1 = class_method %0, #NonisolatedKlass.nsNonisolatedUnsafeClassComputed!setter : (NonisolatedKlass.Type) -> (NonSendableKlass) -> (), $@convention(method) (@owned NonSendableKlass, @thick NonisolatedKlass.Type) -> () + debug_value [trace] %1 + %9999 = tuple () + return %9999 : $() +} + +// CHECK-LABEL: begin running test 1 of 1 on nonisolated_class_nonisolatedclassproperty_getter: sil_isolation_info_inference with: @trace[0] +// CHECK: Input Value: %1 = class_method %0 : $@thick NonisolatedKlass.Type, #NonisolatedKlass.nsNonisolatedClassComputed!getter : (NonisolatedKlass.Type) -> () -> NonSendableKlass, $@convention(method) (@thick NonisolatedKlass.Type) -> @owned NonSendableKlass +// CHECK: Isolation: disconnected +// CHECK: end running test 1 of 1 on nonisolated_class_nonisolatedclassproperty_getter: sil_isolation_info_inference with: @trace[0] +sil [ossa] @nonisolated_class_nonisolatedclassproperty_getter : $@convention(thin) () -> () { +bb0: + specify_test "sil_isolation_info_inference @trace[0]" + %0 = metatype $@thick NonisolatedKlass.Type + %1 = class_method %0, #NonisolatedKlass.nsNonisolatedClassComputed!getter : (NonisolatedKlass.Type) -> () -> NonSendableKlass, $@convention(method) (@thick NonisolatedKlass.Type) -> @owned NonSendableKlass + debug_value [trace] %1 + %9999 = tuple () + return %9999 : $() +} + +// CHECK-LABEL: begin running test 1 of 1 on nonisolated_class_nonisolatedclassproperty_setter: sil_isolation_info_inference with: @trace[0] +// CHECK: Input Value: %1 = class_method %0 : $@thick NonisolatedKlass.Type, #NonisolatedKlass.nsNonisolatedClassComputed!setter : (NonisolatedKlass.Type) -> (NonSendableKlass) -> (), $@convention(method) (@owned NonSendableKlass, @thick NonisolatedKlass.Type) -> () +// CHECK: Isolation: disconnected +// CHECK: end running test 1 of 1 on nonisolated_class_nonisolatedclassproperty_setter: sil_isolation_info_inference with: @trace[0] +sil [ossa] @nonisolated_class_nonisolatedclassproperty_setter : $@convention(thin) () -> () { +bb0: + specify_test "sil_isolation_info_inference @trace[0]" + %0 = metatype $@thick NonisolatedKlass.Type + %1 = class_method %0, #NonisolatedKlass.nsNonisolatedClassComputed!setter : (NonisolatedKlass.Type) -> (NonSendableKlass) -> (), $@convention(method) (@owned NonSendableKlass, @thick NonisolatedKlass.Type) -> () + debug_value [trace] %1 + %9999 = tuple () + return %9999 : $() +} + +/////////////////////////////////// +// MARK: Dynamic 'class' methods // +/////////////////////////////////// + +// CHECK-LABEL: begin running test 1 of 1 on globalactor_isolated_class_nonisolatedclassmethod: sil_isolation_info_inference with: @trace[0] +// CHECK: Input Value: %1 = class_method %0 : $@thick MainActorIsolatedKlass.Type, #MainActorIsolatedKlass.getNSClassFunc : (MainActorIsolatedKlass.Type) -> () -> NonSendableKlass, $@convention(method) (@thick MainActorIsolatedKlass.Type) -> @owned NonSendableKlass +// CHECK: Isolation: main actor-isolated +// CHECK: end running test 1 of 1 on globalactor_isolated_class_nonisolatedclassmethod: sil_isolation_info_inference with: @trace[0] +sil [ossa] @globalactor_isolated_class_nonisolatedclassmethod : $@convention(thin) () -> () { +bb0: + specify_test "sil_isolation_info_inference @trace[0]" + %0 = metatype $@thick MainActorIsolatedKlass.Type + %1 = class_method %0, #MainActorIsolatedKlass.getNSClassFunc : (MainActorIsolatedKlass.Type) -> () -> NonSendableKlass, $@convention(method) (@thick MainActorIsolatedKlass.Type) -> @owned NonSendableKlass + debug_value [trace] %1 + %9999 = tuple () + return %9999 : $() +} + +// CHECK-LABEL: begin running test 1 of 1 on globalactor_isolated_class_globalactorisolatedclassmethod: sil_isolation_info_inference with: @trace[0] +// CHECK: Input Value: %1 = class_method %0 : $@thick MainActorIsolatedKlass.Type, #MainActorIsolatedKlass.getNSGlobalActorClassFunc : (MainActorIsolatedKlass.Type) -> () -> NonSendableKlass, $@convention(method) (@thick MainActorIsolatedKlass.Type) -> @owned NonSendableKlass +// CHECK: Isolation: global actor 'CustomActor'-isolated +// CHECK: end running test 1 of 1 on globalactor_isolated_class_globalactorisolatedclassmethod: sil_isolation_info_inference with: @trace[0] +sil [ossa] @globalactor_isolated_class_globalactorisolatedclassmethod : $@convention(thin) () -> () { +bb0: + specify_test "sil_isolation_info_inference @trace[0]" + %0 = metatype $@thick MainActorIsolatedKlass.Type + %1 = class_method %0, #MainActorIsolatedKlass.getNSGlobalActorClassFunc : (MainActorIsolatedKlass.Type) -> () -> NonSendableKlass, $@convention(method) (@thick MainActorIsolatedKlass.Type) -> @owned NonSendableKlass + debug_value [trace] %1 + %9999 = tuple () + return %9999 : $() +} + +// CHECK-LABEL: begin running test 1 of 1 on globalactor_isolated_class_nonisolatedclassmethod_: sil_isolation_info_inference with: @trace[0] +// CHECK: Input Value: %1 = class_method %0 : $@thick MainActorIsolatedKlass.Type, #MainActorIsolatedKlass.getNSNonisolatedClassFunc : (MainActorIsolatedKlass.Type) -> () -> NonSendableKlass, $@convention(method) (@thick MainActorIsolatedKlass.Type) -> @owned NonSendableKlass +// CHECK: Isolation: disconnected +// CHECK: end running test 1 of 1 on globalactor_isolated_class_nonisolatedclassmethod_: sil_isolation_info_inference with: @trace[0] +sil [ossa] @globalactor_isolated_class_nonisolatedclassmethod_ : $@convention(thin) () -> () { +bb0: + specify_test "sil_isolation_info_inference @trace[0]" + %0 = metatype $@thick MainActorIsolatedKlass.Type + %1 = class_method %0, #MainActorIsolatedKlass.getNSNonisolatedClassFunc : (MainActorIsolatedKlass.Type) -> () -> NonSendableKlass, $@convention(method) (@thick MainActorIsolatedKlass.Type) -> @owned NonSendableKlass + debug_value [trace] %1 + %9999 = tuple () + return %9999 : $() +} + +// CHECK-LABEL: begin running test 1 of 1 on nonisolated_class_nonisolatedclassmethod: sil_isolation_info_inference with: @trace[0] +// CHECK: Input Value: %1 = class_method %0 : $@thick NonisolatedKlass.Type, #NonisolatedKlass.getNSClassFunc : (NonisolatedKlass.Type) -> () -> NonSendableKlass, $@convention(method) (@thick NonisolatedKlass.Type) -> @owned NonSendableKlass +// CHECK: Isolation: disconnected +// CHECK: end running test 1 of 1 on nonisolated_class_nonisolatedclassmethod: sil_isolation_info_inference with: @trace[0] +sil [ossa] @nonisolated_class_nonisolatedclassmethod : $@convention(thin) () -> () { +bb0: + specify_test "sil_isolation_info_inference @trace[0]" + %0 = metatype $@thick NonisolatedKlass.Type + %1 = class_method %0, #NonisolatedKlass.getNSClassFunc : (NonisolatedKlass.Type) -> () -> NonSendableKlass, $@convention(method) (@thick NonisolatedKlass.Type) -> @owned NonSendableKlass + debug_value [trace] %1 + %9999 = tuple () + return %9999 : $() +} + +// CHECK-LABEL: begin running test 1 of 1 on nonisolated_class_globalactorisolatedclassmethod: sil_isolation_info_inference with: @trace[0] +// CHECK: Input Value: %1 = class_method %0 : $@thick NonisolatedKlass.Type, #NonisolatedKlass.getNSGlobalActorClassFunc : (NonisolatedKlass.Type) -> () -> NonSendableKlass, $@convention(method) (@thick NonisolatedKlass.Type) -> @owned NonSendableKlass +// CHECK: Isolation: global actor 'CustomActor'-isolated +// CHECK: end running test 1 of 1 on nonisolated_class_globalactorisolatedclassmethod: sil_isolation_info_inference with: @trace[0] +sil [ossa] @nonisolated_class_globalactorisolatedclassmethod : $@convention(thin) () -> () { +bb0: + specify_test "sil_isolation_info_inference @trace[0]" + %0 = metatype $@thick NonisolatedKlass.Type + %1 = class_method %0, #NonisolatedKlass.getNSGlobalActorClassFunc : (NonisolatedKlass.Type) -> () -> NonSendableKlass, $@convention(method) (@thick NonisolatedKlass.Type) -> @owned NonSendableKlass + debug_value [trace] %1 + %9999 = tuple () + return %9999 : $() +} + +// CHECK-LABEL: begin running test 1 of 1 on nonisolated_class_nonisolatedclassmethod_: sil_isolation_info_inference with: @trace[0] +// CHECK: Input Value: %1 = class_method %0 : $@thick NonisolatedKlass.Type, #NonisolatedKlass.getNSNonisolatedClassFunc : (NonisolatedKlass.Type) -> () -> NonSendableKlass, $@convention(method) (@thick NonisolatedKlass.Type) -> @owned NonSendableKlass +// CHECK: Isolation: disconnected +// CHECK: end running test 1 of 1 on nonisolated_class_nonisolatedclassmethod_: sil_isolation_info_inference with: @trace[0] +sil [ossa] @nonisolated_class_nonisolatedclassmethod_ : $@convention(thin) () -> () { +bb0: + specify_test "sil_isolation_info_inference @trace[0]" + %0 = metatype $@thick NonisolatedKlass.Type + %1 = class_method %0, #NonisolatedKlass.getNSNonisolatedClassFunc : (NonisolatedKlass.Type) -> () -> NonSendableKlass, $@convention(method) (@thick NonisolatedKlass.Type) -> @owned NonSendableKlass + debug_value [trace] %1 + %9999 = tuple () + return %9999 : $() +} \ No newline at end of file diff --git a/test/Concurrency/transfernonsendable_global_actor.swift b/test/Concurrency/transfernonsendable_global_actor.swift index 778f06d9f572e..cdc4372d1d0eb 100644 --- a/test/Concurrency/transfernonsendable_global_actor.swift +++ b/test/Concurrency/transfernonsendable_global_actor.swift @@ -12,7 +12,9 @@ class NonSendableKlass {} final class SendableKlass : Sendable {} -actor CustomActorInstance {} +actor CustomActorInstance { + func acceptValue(_ x: NonSendableKlass) {} +} @globalActor struct CustomActor { @@ -379,3 +381,17 @@ actor PreferIsolationOfFieldToIsolationOfActor { } } } + +// We need to error on this below since ns becomes main actor isolated and then +// we send it into a different actor. +@MainActor +class SetterAssignmentMustInferGlobalIsolationTest { + var nsField = NonSendableKlass() + + func send() async { + let ns = NonSendableKlass() + nsField = ns + await CustomActor.shared.acceptValue(ns) // expected-warning {{sending 'ns' risks causing data races}} + // expected-note @-1 {{sending main actor-isolated 'ns' to actor-isolated instance method 'acceptValue' risks causing data races between actor-isolated and main actor-isolated uses}} + } +} From 91444dd0bd7a21e5e4199c45ef9556a69a61db5c Mon Sep 17 00:00:00 2001 From: Michael Gottesman Date: Wed, 22 Oct 2025 09:37:00 -0700 Subject: [PATCH 3/3] Delete dead code. --- lib/SILOptimizer/Utils/SILIsolationInfo.cpp | 96 --------------------- 1 file changed, 96 deletions(-) diff --git a/lib/SILOptimizer/Utils/SILIsolationInfo.cpp b/lib/SILOptimizer/Utils/SILIsolationInfo.cpp index 6ae7feffa307f..5cb950f48b88e 100644 --- a/lib/SILOptimizer/Utils/SILIsolationInfo.cpp +++ b/lib/SILOptimizer/Utils/SILIsolationInfo.cpp @@ -53,102 +53,6 @@ getGlobalActorInitIsolation(SILFunction *fn) { return getActorIsolation(globalDecl); } -class DeclRefExprAnalysis { - DeclRefExpr *result = nullptr; - - // Be greedy with the small size so we very rarely allocate. - SmallVector lookThroughExprs; - -public: - bool compute(Expr *expr); - - DeclRefExpr *getResult() const { - assert(result && "Not computed?!"); - return result; - } - - ArrayRef getLookThroughExprs() const { - assert(result && "Not computed?!"); - return lookThroughExprs; - } - - void print(llvm::raw_ostream &os) const { - if (!result) { - os << "DeclRefExprAnalysis: None."; - return; - } - - os << "DeclRefExprAnalysis:\n"; - result->dump(os); - os << "\n"; - if (lookThroughExprs.size()) { - os << "LookThroughExprs:\n"; - for (auto *expr : lookThroughExprs) { - expr->dump(os, 4); - } - } - } - - SWIFT_DEBUG_DUMP { print(llvm::dbgs()); } - - bool hasNonisolatedUnsafe() const { - // See if our initial member_ref_expr is actor instance isolated. - for (auto *expr : lookThroughExprs) { - // We can skip load expr. - if (isa(expr)) - continue; - - if (auto *mri = dyn_cast(expr)) { - if (mri->hasDecl()) { - auto isolation = swift::getActorIsolation(mri->getDecl().getDecl()); - if (isolation.isNonisolatedUnsafe()) - return true; - } - } - - break; - } - - return false; - } -}; - -bool DeclRefExprAnalysis::compute(Expr *expr) { - struct LocalWalker final : ASTWalker { - DeclRefExprAnalysis &parentAnalysis; - - LocalWalker(DeclRefExprAnalysis &parentAnalysis) - : parentAnalysis(parentAnalysis) {} - - PreWalkResult walkToExprPre(Expr *expr) override { - assert(!parentAnalysis.result && "Shouldn't have a result yet"); - - if (auto *dre = dyn_cast(expr)) { - parentAnalysis.result = dre; - return Action::Stop(); - } - - if (isa( - expr)) { - parentAnalysis.lookThroughExprs.push_back(expr); - return Action::Continue(expr); - } - - return Action::Stop(); - } - }; - - LocalWalker walker(*this); - - if (auto *ae = dyn_cast(expr)) { - ae->getSrc()->walk(walker); - } else { - expr->walk(walker); - } - - return result; -} - static SILIsolationInfo inferIsolationInfoForTempAllocStack(AllocStackInst *asi) { // We want to search for an alloc_stack that is not from a VarDecl and that is