diff --git a/include/swift/AST/ActorIsolation.h b/include/swift/AST/ActorIsolation.h index b0ab364d4b9..ae64e65416b 100644 --- a/include/swift/AST/ActorIsolation.h +++ b/include/swift/AST/ActorIsolation.h @@ -133,6 +133,8 @@ public: return ActorIsolation(GlobalActor, globalActor); } + static ActorIsolation forMainActor(ASTContext &ctx); + static ActorIsolation forErased() { return ActorIsolation(Erased); } diff --git a/include/swift/Basic/Features.def b/include/swift/Basic/Features.def index 16cd362e583..0a59dd28307 100644 --- a/include/swift/Basic/Features.def +++ b/include/swift/Basic/Features.def @@ -408,9 +408,15 @@ SUPPRESSIBLE_EXPERIMENTAL_FEATURE(AllowUnsafeAttribute, true) /// Warn on use of unsafe constructs. EXPERIMENTAL_FEATURE(WarnUnsafe, true) +/// Import unsafe C and C++ constructs as @unsafe. +EXPERIMENTAL_FEATURE(SafeInterop, true) + // Enable values in generic signatures, e.g. EXPERIMENTAL_FEATURE(ValueGenerics, true) +// When a parameter has unspecified isolation, infer it as main actor isolated. +EXPERIMENTAL_FEATURE(UnspecifiedMeansMainActorIsolated, false) + #undef EXPERIMENTAL_FEATURE_EXCLUDED_FROM_MODULE_INTERFACE #undef EXPERIMENTAL_FEATURE #undef UPCOMING_FEATURE diff --git a/include/swift/SIL/SILFunction.h b/include/swift/SIL/SILFunction.h index 5e0217b47f1..cad3934e940 100644 --- a/include/swift/SIL/SILFunction.h +++ b/include/swift/SIL/SILFunction.h @@ -351,7 +351,7 @@ private: unsigned BlockListChangeIdx = 0; /// The isolation of this function. - ActorIsolation actorIsolation = ActorIsolation::forUnspecified(); + std::optional actorIsolation; /// The function's bare attribute. Bare means that the function is SIL-only /// and does not require debug info. @@ -1451,7 +1451,9 @@ public: actorIsolation = newActorIsolation; } - ActorIsolation getActorIsolation() const { return actorIsolation; } + std::optional getActorIsolation() const { + return actorIsolation; + } /// Return the source file that this SILFunction belongs to if it exists. SourceFile *getSourceFile() const; diff --git a/include/swift/SILOptimizer/Utils/PartitionUtils.h b/include/swift/SILOptimizer/Utils/PartitionUtils.h index d971d5d5af9..9e334dd9e90 100644 --- a/include/swift/SILOptimizer/Utils/PartitionUtils.h +++ b/include/swift/SILOptimizer/Utils/PartitionUtils.h @@ -1425,9 +1425,9 @@ private: // our transferring operand. If so, we can squelch this. if (auto functionIsolation = transferringOp->getUser()->getFunction()->getActorIsolation()) { - if (functionIsolation.isActorIsolated() && + if (functionIsolation->isActorIsolated() && SILIsolationInfo::get(transferringOp->getUser()) - .hasSameIsolation(functionIsolation)) + .hasSameIsolation(*functionIsolation)) return; } } diff --git a/lib/AST/ActorIsolation.cpp b/lib/AST/ActorIsolation.cpp new file mode 100644 index 00000000000..ad73caf6f60 --- /dev/null +++ b/lib/AST/ActorIsolation.cpp @@ -0,0 +1,21 @@ +//===--- ActorIsolation.cpp -----------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2024 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// + +#include "swift/AST/ActorIsolation.h" +#include "swift/AST/ASTContext.h" + +using namespace swift; + +ActorIsolation ActorIsolation::forMainActor(ASTContext &ctx) { + return ActorIsolation::forGlobalActor( + ctx.getMainActorType()->mapTypeOutOfContext()); +} diff --git a/lib/AST/CMakeLists.txt b/lib/AST/CMakeLists.txt index 699623cab09..b6cd4c2ebb2 100644 --- a/lib/AST/CMakeLists.txt +++ b/lib/AST/CMakeLists.txt @@ -9,6 +9,7 @@ add_swift_host_library(swiftAST STATIC AbstractSourceFileDepGraphFactory.cpp AccessNotes.cpp AccessRequests.cpp + ActorIsolation.cpp ArgumentList.cpp ASTBridging.cpp ASTContext.cpp diff --git a/lib/AST/FeatureSet.cpp b/lib/AST/FeatureSet.cpp index 7857c8a014b..58f4659ab5f 100644 --- a/lib/AST/FeatureSet.cpp +++ b/lib/AST/FeatureSet.cpp @@ -204,6 +204,7 @@ UNINTERESTING_FEATURE(ExtractConstantsFromMembers) UNINTERESTING_FEATURE(FixedArrays) UNINTERESTING_FEATURE(GroupActorErrors) UNINTERESTING_FEATURE(SameElementRequirements) +UNINTERESTING_FEATURE(UnspecifiedMeansMainActorIsolated) static bool usesFeatureSendingArgsAndResults(Decl *decl) { auto isFunctionTypeWithSending = [](Type type) { @@ -300,6 +301,7 @@ static bool usesFeatureAllowUnsafeAttribute(Decl *decl) { } UNINTERESTING_FEATURE(WarnUnsafe) +UNINTERESTING_FEATURE(SafeInterop) static bool usesFeatureValueGenerics(Decl *decl) { auto genericContext = decl->getAsGenericContext(); diff --git a/lib/ClangImporter/ClangImporter.cpp b/lib/ClangImporter/ClangImporter.cpp index bf91afa55be..8a2f6e2bca5 100644 --- a/lib/ClangImporter/ClangImporter.cpp +++ b/lib/ClangImporter/ClangImporter.cpp @@ -7393,6 +7393,10 @@ bool importer::hasNonEscapableAttr(const clang::RecordDecl *decl) { return hasSwiftAttribute(decl, "~Escapable"); } +bool importer::hasEscapableAttr(const clang::RecordDecl *decl) { + return hasSwiftAttribute(decl, "Escapable"); +} + /// Recursively checks that there are no pointers in any fields or base classes. /// Does not check C++ records with specific API annotations. static bool hasPointerInSubobjects(const clang::CXXRecordDecl *decl) { diff --git a/lib/ClangImporter/ImportDecl.cpp b/lib/ClangImporter/ImportDecl.cpp index 41781959fef..9507176b18e 100644 --- a/lib/ClangImporter/ImportDecl.cpp +++ b/lib/ClangImporter/ImportDecl.cpp @@ -37,6 +37,7 @@ #include "swift/AST/PrettyStackTrace.h" #include "swift/AST/ProtocolConformance.h" #include "swift/AST/Stmt.h" +#include "swift/AST/Type.h" #include "swift/AST/TypeCheckRequests.h" #include "swift/AST/Types.h" #include "swift/Basic/Assertions.h" @@ -8131,6 +8132,21 @@ bool swift::importer::isMutabilityAttr(const clang::SwiftAttrAttr *swiftAttr) { swiftAttr->getAttribute() == "nonmutating"; } +static bool importAsUnsafe(const ASTContext &context, + const clang::RecordDecl *decl, + const Decl *MappedDecl) { + if (!context.LangOpts.hasFeature(Feature::SafeInterop) || + !context.LangOpts.hasFeature(Feature::AllowUnsafeAttribute) || !decl) + return false; + + if (isa(MappedDecl)) + return false; + + // TODO: Add logic to cover structural rules. + return !importer::hasNonEscapableAttr(decl) && + !importer::hasEscapableAttr(decl); +} + void ClangImporter::Implementation::importSwiftAttrAttributes(Decl *MappedDecl) { auto ClangDecl = @@ -8155,6 +8171,7 @@ ClangImporter::Implementation::importSwiftAttrAttributes(Decl *MappedDecl) { // // __attribute__((swift_attr("attribute"))) // + bool seenUnsafe = false; for (auto swiftAttr : ClangDecl->specific_attrs()) { // FIXME: Hard-code @MainActor and @UIActor, because we don't have a // point at which to do name lookup for imported entities. @@ -8264,8 +8281,7 @@ ClangImporter::Implementation::importSwiftAttrAttributes(Decl *MappedDecl) { if (swiftAttr->getAttribute() == "unsafe") { if (!SwiftContext.LangOpts.hasFeature(Feature::AllowUnsafeAttribute)) continue; - auto attr = new (SwiftContext) UnsafeAttr(/*implicit=*/false); - MappedDecl->getAttrs().add(attr); + seenUnsafe = true; continue; } @@ -8309,6 +8325,13 @@ ClangImporter::Implementation::importSwiftAttrAttributes(Decl *MappedDecl) { swiftAttr->getAttribute()); } } + + if (seenUnsafe || + importAsUnsafe(SwiftContext, dyn_cast(ClangDecl), + MappedDecl)) { + auto attr = new (SwiftContext) UnsafeAttr(/*implicit=*/!seenUnsafe); + MappedDecl->getAttrs().add(attr); + } }; importAttrsFromDecl(ClangDecl); diff --git a/lib/ClangImporter/ImporterImpl.h b/lib/ClangImporter/ImporterImpl.h index d22aab99eed..18939159e27 100644 --- a/lib/ClangImporter/ImporterImpl.h +++ b/lib/ClangImporter/ImporterImpl.h @@ -2031,6 +2031,8 @@ bool hasUnsafeAPIAttr(const clang::Decl *decl); bool hasNonEscapableAttr(const clang::RecordDecl *decl); +bool hasEscapableAttr(const clang::RecordDecl *decl); + bool isViewType(const clang::CXXRecordDecl *decl); } // end namespace importer diff --git a/lib/ClangImporter/SwiftBridging/swift/bridging b/lib/ClangImporter/SwiftBridging/swift/bridging index 8530321a798..703f1e305d1 100644 --- a/lib/ClangImporter/SwiftBridging/swift/bridging +++ b/lib/ClangImporter/SwiftBridging/swift/bridging @@ -164,6 +164,13 @@ #define SWIFT_NONESCAPABLE \ __attribute__((swift_attr("~Escapable"))) +/// Specifies that a specific c++ type such class or struct should be imported +/// as a escapable Swift value. While this matches the default behavior, +/// in safe mode interop mode it ensures that the type is not marked as +/// unsafe. +#define SWIFT_ESCAPABLE \ + __attribute__((swift_attr("Escapable"))) + /// Specifies that the return value is passed as owned for C++ functions and /// methods returning types annotated as `SWIFT_SHARED_REFERENCE` #define SWIFT_RETURNS_RETAINED __attribute__((swift_attr("returns_retained"))) @@ -187,6 +194,7 @@ #define SWIFT_UNCHECKED_SENDABLE #define SWIFT_NONCOPYABLE #define SWIFT_NONESCAPABLE +#define SWIFT_ESCAPABLE #define SWIFT_RETURNS_RETAINED #define SWIFT_RETURNS_UNRETAINED diff --git a/lib/SIL/IR/SILPrinter.cpp b/lib/SIL/IR/SILPrinter.cpp index 98d09771944..024b4d9fa0f 100644 --- a/lib/SIL/IR/SILPrinter.cpp +++ b/lib/SIL/IR/SILPrinter.cpp @@ -3376,9 +3376,10 @@ void SILFunction::print(SILPrintContext &PrintCtx) const { if (auto functionIsolation = getActorIsolation()) { OS << "// Isolation: "; - functionIsolation.print(OS); + functionIsolation->print(OS); OS << '\n'; } + printClangQualifiedNameCommentIfPresent(OS, getClangDecl()); OS << "sil "; diff --git a/lib/SILGen/SILGen.cpp b/lib/SILGen/SILGen.cpp index 9262b0daf97..7aaa4962043 100644 --- a/lib/SILGen/SILGen.cpp +++ b/lib/SILGen/SILGen.cpp @@ -754,10 +754,7 @@ SILFunction *SILGenModule::getFunction(SILDeclRef constant, // If we have global actor isolation for our constant, put the isolation onto // the function. - if (auto isolation = - getActorIsolationOfContext(constant.getInnermostDeclContext())) { - F->setActorIsolation(isolation); - } + F->setActorIsolation(getActorIsolationOfContext(constant.getInnermostDeclContext())); assert(F && "SILFunction should have been defined"); @@ -1248,12 +1245,7 @@ void SILGenModule::preEmitFunction(SILDeclRef constant, SILFunction *F, F->setGenericEnvironment(genericEnv, capturedEnvs, forwardingSubs); } - // If we have global actor isolation for our constant, put the isolation onto - // the function. - if (auto isolation = - getActorIsolationOfContext(constant.getInnermostDeclContext())) { - F->setActorIsolation(isolation); - } + F->setActorIsolation(getActorIsolationOfContext(constant.getInnermostDeclContext())); // Create a debug scope for the function using astNode as source location. F->setDebugScope(new (M) SILDebugScope(Loc, F)); diff --git a/lib/SILOptimizer/Utils/SILIsolationInfo.cpp b/lib/SILOptimizer/Utils/SILIsolationInfo.cpp index a438cb412c2..617c912a90a 100644 --- a/lib/SILOptimizer/Utils/SILIsolationInfo.cpp +++ b/lib/SILOptimizer/Utils/SILIsolationInfo.cpp @@ -509,59 +509,62 @@ SILIsolationInfo SILIsolationInfo::get(SILInstruction *inst) { // Treat function ref as either actor isolated or sendable. if (auto *fri = dyn_cast(inst)) { - auto isolation = fri->getReferencedFunction()->getActorIsolation(); + if (auto optIsolation = fri->getReferencedFunction()->getActorIsolation()) { + auto isolation = *optIsolation; - // First check if we are actor isolated at the AST level... if we are, then - // create the relevant actor isolated. - if (isolation.isActorIsolated()) { - if (isolation.isGlobalActor()) { - return SILIsolationInfo::getGlobalActorIsolated( - fri, isolation.getGlobalActor()); + // First check if we are actor isolated at the AST level... if we are, + // then create the relevant actor isolated. + if (isolation.isActorIsolated()) { + if (isolation.isGlobalActor()) { + return SILIsolationInfo::getGlobalActorIsolated( + fri, isolation.getGlobalActor()); + } + + // TODO: We need to be able to support flow sensitive actor instances + // like we do for partial apply. Until we do so, just store SILValue() + // for this. This could cause a problem if we can construct a function + // ref and invoke it with two different actor instances of the same type + // and pass in the same parameters to both. We should error and we would + // not with this impl since we could not distinguish the two. + if (isolation.getKind() == ActorIsolation::ActorInstance) { + return SILIsolationInfo::getFlowSensitiveActorIsolated(fri, + isolation); + } + + assert(isolation.getKind() != ActorIsolation::Erased && + "Implement this!"); } - // TODO: We need to be able to support flow sensitive actor instances like - // we do for partial apply. Until we do so, just store SILValue() for - // this. This could cause a problem if we can construct a function ref and - // invoke it with two different actor instances of the same type and pass - // in the same parameters to both. We should error and we would not with - // this impl since we could not distinguish the two. - if (isolation.getKind() == ActorIsolation::ActorInstance) { - return SILIsolationInfo::getFlowSensitiveActorIsolated(fri, isolation); - } - - assert(isolation.getKind() != ActorIsolation::Erased && - "Implement this!"); - } - - // Then check if we have something that is nonisolated unsafe. - if (isolation.isNonisolatedUnsafe()) { - // First check if our function_ref is a method of a global actor isolated - // type. In such a case, we create a global actor isolated - // nonisolated(unsafe) so that if we assign the value to another variable, - // the variable still says that it is the appropriate global actor - // isolated thing. - // - // E.x.: - // - // @MainActor - // struct X { nonisolated(unsafe) var x: NonSendableThing { ... } } - // - // We want X.x to be safe to use... but to have that 'z' in the following - // is considered MainActor isolated. - // - // let z = X.x - // - auto *func = fri->getReferencedFunction(); - auto funcType = func->getLoweredFunctionType(); - if (funcType->hasSelfParam()) { - auto selfParam = funcType->getSelfInstanceType( - fri->getModule(), func->getTypeExpansionContext()); - if (auto *nomDecl = selfParam->getNominalOrBoundGenericNominal()) { - auto isolation = swift::getActorIsolation(nomDecl); - if (isolation.isGlobalActor()) { - return SILIsolationInfo::getGlobalActorIsolated( - fri, isolation.getGlobalActor()) - .withUnsafeNonIsolated(true); + // Then check if we have something that is nonisolated unsafe. + if (isolation.isNonisolatedUnsafe()) { + // First check if our function_ref is a method of a global actor + // isolated type. In such a case, we create a global actor isolated + // nonisolated(unsafe) so that if we assign the value to another + // variable, the variable still says that it is the appropriate global + // actor isolated thing. + // + // E.x.: + // + // @MainActor + // struct X { nonisolated(unsafe) var x: NonSendableThing { ... } } + // + // We want X.x to be safe to use... but to have that 'z' in the + // following is considered MainActor isolated. + // + // let z = X.x + // + auto *func = fri->getReferencedFunction(); + auto funcType = func->getLoweredFunctionType(); + if (funcType->hasSelfParam()) { + auto selfParam = funcType->getSelfInstanceType( + fri->getModule(), func->getTypeExpansionContext()); + if (auto *nomDecl = selfParam->getNominalOrBoundGenericNominal()) { + auto nomDeclIsolation = swift::getActorIsolation(nomDecl); + if (nomDeclIsolation.isGlobalActor()) { + return SILIsolationInfo::getGlobalActorIsolated( + fri, nomDeclIsolation.getGlobalActor()) + .withUnsafeNonIsolated(true); + } } } } @@ -868,8 +871,11 @@ SILIsolationInfo SILIsolationInfo::get(SILArgument *arg) { // code. In the case of a non-actor, we can only have an allocator that is // global actor isolated, so we will never hit this code path. if (declRef.kind == SILDeclRef::Kind::Allocator) { - if (fArg->getFunction()->getActorIsolation().isActorInstanceIsolated()) { - return SILIsolationInfo::getDisconnected(false /*nonisolated(unsafe)*/); + if (auto isolation = fArg->getFunction()->getActorIsolation()) { + if (isolation->isActorInstanceIsolated()) { + return SILIsolationInfo::getDisconnected( + false /*nonisolated(unsafe)*/); + } } } @@ -878,13 +884,13 @@ SILIsolationInfo SILIsolationInfo::get(SILArgument *arg) { // we need to pass in a "fake" ActorInstance that users know is a sentinel // for the self value. if (auto functionIsolation = fArg->getFunction()->getActorIsolation()) { - if (functionIsolation.isActorInstanceIsolated() && declRef.getDecl()) { + if (functionIsolation->isActorInstanceIsolated() && declRef.getDecl()) { if (auto *accessor = dyn_cast_or_null(declRef.getFuncDecl())) { if (accessor->isInitAccessor()) { return SILIsolationInfo::getActorInstanceIsolated( fArg, ActorInstance::getForActorAccessorInit(), - functionIsolation.getActor()); + functionIsolation->getActor()); } } } @@ -894,15 +900,15 @@ SILIsolationInfo SILIsolationInfo::get(SILArgument *arg) { // Otherwise, if we do not have an isolated argument and are not in an // allocator, then we might be isolated via global isolation. if (auto functionIsolation = fArg->getFunction()->getActorIsolation()) { - if (functionIsolation.isActorIsolated()) { - if (functionIsolation.isGlobalActor()) { + if (functionIsolation->isActorIsolated()) { + if (functionIsolation->isGlobalActor()) { return SILIsolationInfo::getGlobalActorIsolated( - fArg, functionIsolation.getGlobalActor()); + fArg, functionIsolation->getGlobalActor()); } return SILIsolationInfo::getActorInstanceIsolated( fArg, ActorInstance::getForActorAccessorInit(), - functionIsolation.getActor()); + functionIsolation->getActor()); } } diff --git a/lib/Sema/TypeCheckConcurrency.cpp b/lib/Sema/TypeCheckConcurrency.cpp index e4a5bacd089..38589b44007 100644 --- a/lib/Sema/TypeCheckConcurrency.cpp +++ b/lib/Sema/TypeCheckConcurrency.cpp @@ -5495,6 +5495,12 @@ InferredActorIsolation ActorIsolationRequest::evaluate( ActorIsolation defaultIsolation = ActorIsolation::forUnspecified(); IsolationSource defaultIsolationSource; + // If we are supposed to infer main actor isolation by default, make our + // default isolation main actor. + if (ctx.LangOpts.hasFeature(Feature::UnspecifiedMeansMainActorIsolated)) { + defaultIsolation = ActorIsolation::forMainActor(ctx); + } + if (auto func = dyn_cast(value)) { // A @Sendable function is assumed to be actor-independent. if (func->isSendable()) { @@ -5520,6 +5526,9 @@ InferredActorIsolation ActorIsolationRequest::evaluate( overriddenIso = defaultIsolation; } + // NOTE: After this point, the default has been set. Only touch the default + // isolation above this point since code below assumes it is now constant. + // Function used when returning an inferred isolation. auto inferredIsolation = [&](ActorIsolation inferred, bool onlyGlobal = false) { @@ -5633,6 +5642,32 @@ InferredActorIsolation ActorIsolationRequest::evaluate( } } + // If this is an actor, use the actor isolation of the actor. + if (ctx.LangOpts.hasFeature(Feature::UnspecifiedMeansMainActorIsolated)) { + // non-async inits and deinits need to be always nonisolated since we can + // run the deinit anywhere. + // + // TODO: We should add a check for if they are marked with global actor + // isolation. + if (auto *func = dyn_cast(value)) { + if (isa(func) && !func->isAsyncContext()) + return {ActorIsolation::forNonisolated(false /*unsafe*/), + IsolationSource(func, IsolationSource::LexicalContext)}; + + if (isa(func) && !func->isAsyncContext()) + return {ActorIsolation::forNonisolated(false /*unsafe*/), + IsolationSource(func, IsolationSource::LexicalContext)}; + } + + if (auto nominal = dyn_cast(value)) { + if (nominal->isActor() && !nominal->isGlobalActor()) { + auto isolation = ActorIsolation::forActorInstanceSelf(value); + return {inferredIsolation(isolation), + IsolationSource(nominal, IsolationSource::LexicalContext)}; + } + } + } + // If this is an accessor, use the actor isolation of its storage // declaration. if (auto accessor = dyn_cast(value)) { diff --git a/test/Concurrency/actor_isolation_filecheck.swift b/test/Concurrency/actor_isolation_filecheck.swift new file mode 100644 index 00000000000..55b61d2b642 --- /dev/null +++ b/test/Concurrency/actor_isolation_filecheck.swift @@ -0,0 +1,34 @@ +// RUN: %target-swift-frontend -swift-version 6 -disable-availability-checking %s -emit-silgen -o - | %FileCheck %s +// RUN: %target-swift-frontend -swift-version 6 -disable-availability-checking %s -emit-sil -o /dev/null -verify + +// README: This file contains FileCheck tests that validate that specific Swift +// entities have their respective SILFunctions assigned the correct actor +// isolation by FileChecking against SILGen. + +//////////////////////// +// MARK: Declarations // +//////////////////////// + +func useValueAsync(_ t: T) async {} + +///////////////// +// MARK: Tests // +///////////////// + +// CHECK: // synchronousActorIsolatedFinalClassMethodError() +// CHECK-NEXT: // Isolation: global_actor. type: MainActor +// CHECK-NEXT: sil hidden [ossa] @$s25actor_isolation_filecheck45synchronousActorIsolatedFinalClassMethodErroryyYaF : $@convention(thin) @async () -> () { +@MainActor func synchronousActorIsolatedFinalClassMethodError() async { + @MainActor final class Test { + // CHECK: // foo() in Test #1 in synchronousActorIsolatedFinalClassMethodError() + // CHECK-NEXT: // Isolation: global_actor. type: MainActor + // CHECK-NEXT: sil private [ossa] @$s25actor_isolation_filecheck45synchronousActorIsolatedFinalClassMethodErroryyYaF4TestL_C3fooyyF : $@convention(method) (@guaranteed Test) -> () { + func foo() {} + } + + let t = Test() + let erased: () -> Void = t.foo + + await useValueAsync(erased) // expected-error {{sending 'erased' risks causing data races}} + // expected-note @-1 {{sending main actor-isolated 'erased' to nonisolated global function 'useValueAsync' risks causing data races between nonisolated and main actor-isolated uses}} +} diff --git a/test/Concurrency/assume_mainactor.swift b/test/Concurrency/assume_mainactor.swift new file mode 100644 index 00000000000..17672121178 --- /dev/null +++ b/test/Concurrency/assume_mainactor.swift @@ -0,0 +1,199 @@ +// RUN: %target-swift-frontend -swift-version 6 -emit-silgen -enable-experimental-feature UnspecifiedMeansMainActorIsolated %s | %FileCheck %s +// RUN: %target-swift-frontend -swift-version 6 -emit-sil -enable-experimental-feature UnspecifiedMeansMainActorIsolated %s -verify + +// READ THIS! This test is meant to FileCheck the specific isolation when +// UnspecifiedMeansMainActorIsolated is enabled. Please do not put other types +// of tests in here. + +class Klass { + // Implicit deinit + // CHECK: // Klass.deinit + // CHECK-NEXT: // Isolation: nonisolated + // CHECK-NEXT: sil hidden [ossa] @$s16assume_mainactor5KlassCfd : $@convention(method) (@guaranteed Klass) -> @owned Builtin.NativeObject { + + // Implicit deallocating deinit + // CHECK: // Klass.__deallocating_deinit + // CHECK-NEXT: // Isolation: nonisolated + // CHECK-NEXT: sil hidden [ossa] @$s16assume_mainactor5KlassCfD : $@convention(method) (@owned Klass) -> () { + + // Implicit allocating init + // CHECK: // Klass.__allocating_init() + // CHECK-NEXT: // Isolation: nonisolated + // CHECK-NEXT: sil hidden [exact_self_class] [ossa] @$s16assume_mainactor5KlassCACycfC : $@convention(method) (@thick Klass.Type) -> @owned Klass { + + // Implicit designated init + // CHECK: // Klass.init() + // CHECK-NEXT: // Isolation: nonisolated + // CHECK-NEXT: sil hidden [ossa] @$s16assume_mainactor5KlassCACycfc : $@convention(method) (@owned Klass) -> @owned Klass { +} + +struct StructContainingKlass { + // CHECK: // variable initialization expression of StructContainingKlass.k + // CHECK-NEXT: // Isolation: global_actor. type: MainActor + // CHECK-NEXT: sil hidden [transparent] [ossa] @$s16assume_mainactor21StructContainingKlassV1kAA0E0Cvpfi : $@convention(thin) () -> @owned Klass { + + // CHECK: // StructContainingKlass.k.getter + // CHECK-NEXT: // Isolation: global_actor. type: MainActor + // CHECK-NEXT: sil hidden [transparent] [ossa] @$s16assume_mainactor21StructContainingKlassV1kAA0E0Cvg : $@convention(method) (@guaranteed StructContainingKlass) -> @owned Klass { + + // CHECK: // StructContainingKlass.k.setter + // CHECK-NEXT: // Isolation: global_actor. type: MainActor + // CHECK-NEXT: sil hidden [transparent] [ossa] @$s16assume_mainactor21StructContainingKlassV1kAA0E0Cvs : $@convention(method) (@owned Klass, @inout StructContainingKlass) -> () { + var k = Klass() + + // CHECK: // StructContainingKlass.init() + // CHECK-NEXT: // Isolation: nonisolated + // CHECK-NEXT: sil hidden [ossa] @$s16assume_mainactor21StructContainingKlassVACycfC : $@convention(method) (@thin StructContainingKlass.Type) -> @owned StructContainingKlass { +} + +// TODO: Allow for nonisolated to be applied to structs. +struct NonIsolatedStructContainingKlass { + // CHECK: // variable initialization expression of NonIsolatedStructContainingKlass.k + // CHECK-NEXT: // Isolation: global_actor. type: MainActor + // CHECK-NEXT: sil hidden [transparent] [ossa] @$s16assume_mainactor32NonIsolatedStructContainingKlassV1kAA0G0Cvpfi : $@convention(thin) () -> @owned Klass { + + // CHECK: // NonIsolatedStructContainingKlass.k.getter + // CHECK-NEXT: // Isolation: global_actor. type: MainActor + // CHECK-NEXT: sil hidden [transparent] [ossa] @$s16assume_mainactor32NonIsolatedStructContainingKlassV1kAA0G0Cvg : $@convention(method) (@guaranteed NonIsolatedStructContainingKlass) -> @owned Klass { + + // CHECK: // NonIsolatedStructContainingKlass.k.setter + // CHECK-NEXT: // Isolation: global_actor. type: MainActor + // CHECK-NEXT: sil hidden [transparent] [ossa] @$s16assume_mainactor32NonIsolatedStructContainingKlassV1kAA0G0Cvs : $@convention(method) (@owned Klass, @inout NonIsolatedStructContainingKlass) -> () { + var k = Klass() + + // CHECK: // NonIsolatedStructContainingKlass.init() + // CHECK-NEXT: // Isolation: nonisolated + // CHECK-NEXT: sil hidden [ossa] @$s16assume_mainactor32NonIsolatedStructContainingKlassVACycfC : $@convention(method) (@thin NonIsolatedStructContainingKlass.Type) -> @owned NonIsolatedStructContainingKlass { +} + +@globalActor +actor CustomActor { + static let shared = CustomActor() +} + +// CHECK: // unspecifiedAsync(_:) +// CHECK-NEXT: // Isolation: global_actor. type: MainActor +// CHECK-NEXT: sil hidden [ossa] @$s16assume_mainactor16unspecifiedAsyncyyxYalF : $@convention(thin) @async (@in_guaranteed T) -> () { +func unspecifiedAsync(_ t: T) async {} + +// CHECK: // nonisolatedAsync(_:) +// CHECK-NEXT: // Isolation: nonisolated +// CHECK-NEXT: sil hidden [ossa] @$s16assume_mainactor16nonisolatedAsyncyyxYalF : $@convention(thin) @async (@in_guaranteed T) -> () { +nonisolated func nonisolatedAsync(_ t: T) async {} + +// CHECK: // mainActorAsync(_:) +// CHECK-NEXT: // Isolation: global_actor. type: MainActor +// CHECK-NEXT: sil hidden [ossa] @$s16assume_mainactor14mainActorAsyncyyxYalF : $@convention(thin) @async (@in_guaranteed T) -> () { +@MainActor func mainActorAsync(_ t: T) async {} + +// CHECK: // customActorAsync(_:) +// CHECK-NEXT: // Isolation: global_actor. type: CustomActor +// CHECK-NEXT: sil hidden [ossa] @$s16assume_mainactor16customActorAsyncyyxYalF : $@convention(thin) @async (@in_guaranteed T) -> () { +@CustomActor func customActorAsync(_ t: T) async {} + + +@CustomActor +struct CustomActorStruct { + // Variable expression is custom actor... but since we have a nonisolated + // init, we should be fine? + // + // CHECK: // variable initialization expression of CustomActorStruct.k + // CHECK-NEXT: // Isolation: global_actor. type: CustomActor + // CHECK-NEXT: sil hidden [transparent] [ossa] @$s16assume_mainactor17CustomActorStructV1kAA5KlassCvpfi : $@convention(thin) () -> @owned Klass { + + // CHECK: // CustomActorStruct.k.getter + // CHECK-NEXT: // Isolation: global_actor. type: CustomActor + // CHECK-NEXT: sil hidden [transparent] [ossa] @$s16assume_mainactor17CustomActorStructV1kAA5KlassCvg : $@convention(method) (@guaranteed CustomActorStruct) -> @owned Klass { + + // CHECK: // CustomActorStruct.k.setter + // CHECK-NEXT: // Isolation: global_actor. type: CustomActor + // CHECK-NEXT: sil hidden [transparent] [ossa] @$s16assume_mainactor17CustomActorStructV1kAA5KlassCvs : $@convention(method) (@owned Klass, @inout CustomActorStruct) -> () { + var k = Klass() +} + +// CHECK: // unspecifiedFunctionTest() +// CHECK-NEXT: // Isolation: global_actor. type: MainActor +// CHECK-NEXT: sil hidden [ossa] @$s16assume_mainactor23unspecifiedFunctionTestyyYaF : $@convention(thin) @async () -> () { +func unspecifiedFunctionTest() async { + let k = Klass() + await unspecifiedAsync(k) + await nonisolatedAsync(k) + await mainActorAsync(k) +} + +// CHECK: // unspecifiedFunctionTest2() +// CHECK-NEXT: // Isolation: global_actor. type: MainActor +// CHECK-NEXT: sil hidden [ossa] @$s16assume_mainactor24unspecifiedFunctionTest2yyYaF : $@convention(thin) @async () -> () { +func unspecifiedFunctionTest2() async { + let k = StructContainingKlass() + await unspecifiedAsync(k) + await nonisolatedAsync(k) + await mainActorAsync(k) + + await unspecifiedAsync(k.k) + await nonisolatedAsync(k.k) + await mainActorAsync(k.k) +} + +// CHECK: // unspecifiedFunctionTest3() +// CHECK-NEXT: // Isolation: global_actor. type: MainActor +// CHECK-NEXT: sil hidden [ossa] @$s16assume_mainactor24unspecifiedFunctionTest3yyYaF : $@convention(thin) @async () -> () { +func unspecifiedFunctionTest3() async { + let k = NonIsolatedStructContainingKlass() + await unspecifiedAsync(k) + await nonisolatedAsync(k) + await mainActorAsync(k) + + await unspecifiedAsync(k.k) + await nonisolatedAsync(k.k) + await mainActorAsync(k.k) +} + +// CHECK: // nonisolatedFunctionTest() +// CHECK-NEXT: // Isolation: nonisolated +// CHECK-NEXT: sil hidden [ossa] @$s16assume_mainactor23nonisolatedFunctionTestyyYaF : $@convention(thin) @async () -> () { +nonisolated func nonisolatedFunctionTest() async { + let k = NonIsolatedStructContainingKlass() + await unspecifiedAsync(k.k) + await nonisolatedAsync(k.k) + await mainActorAsync(k.k) +} + +actor MyActor { + // CHECK: // variable initialization expression of MyActor.k + // CHECK-NEXT: // Isolation: actor_instance + // CHECK-NEXT: sil hidden [transparent] [ossa] @$s16assume_mainactor7MyActorC1kAA5KlassCvpfi : $@convention(thin) () -> @owned Klass { + + // CHECK: // MyActor.k.getter + // CHECK-NEXT: // Isolation: actor_instance. name: 'self' + // CHECK-NEXT: sil hidden [transparent] [ossa] @$s16assume_mainactor7MyActorC1kAA5KlassCvg : $@convention(method) (@sil_isolated @guaranteed MyActor) -> @owned Klass { + + // CHECK: // MyActor.k.setter + // CHECK-NEXT: // Isolation: actor_instance. name: 'self' + // CHECK-NEXT: sil hidden [transparent] [ossa] @$s16assume_mainactor7MyActorC1kAA5KlassCvs : $@convention(method) (@owned Klass, @sil_isolated @guaranteed MyActor) -> () { + var k = Klass() + + // Implicit deinit + // CHECK: // MyActor.deinit + // CHECK-NEXT: // Isolation: nonisolated + // CHECK-NEXT: sil hidden [ossa] @$s16assume_mainactor7MyActorCfd : $@convention(method) (@guaranteed MyActor) -> @owned Builtin.NativeObject { + + // Non-async init should be nonisolated + // CHECK: // MyActor.init() + // CHECK-NEXT: // Isolation: nonisolated + // CHECK-NEXT: sil hidden [ossa] @$s16assume_mainactor7MyActorCACycfc : $@convention(method) (@owned MyActor) -> @owned MyActor { +} + +actor MyActor2 { + // CHECK: // MyActor2.init() + // CHECK-NEXT: // Isolation: global_actor. type: MainActor + // CHECK-NEXT: sil hidden [ossa] @$s16assume_mainactor8MyActor2CACycfc : $@convention(method) (@owned MyActor2) -> @owned MyActor2 { + @MainActor + init() {} + + // CHECK: // MyActor2.init(x:) + // CHECK-NEXT: // Isolation: global_actor. type: CustomActor + // CHECK-NEXT: sil hidden [ossa] @$s16assume_mainactor8MyActor2C1xACyt_tcfc : $@convention(method) (@owned MyActor2) -> @owned MyActor2 { + @CustomActor + init(x: ()) {} +} diff --git a/test/Concurrency/assume_mainactor_typechecker_errors.swift b/test/Concurrency/assume_mainactor_typechecker_errors.swift new file mode 100644 index 00000000000..26739e6b9c3 --- /dev/null +++ b/test/Concurrency/assume_mainactor_typechecker_errors.swift @@ -0,0 +1,71 @@ +// RUN: %target-swift-frontend -swift-version 6 -emit-sil -enable-experimental-feature UnspecifiedMeansMainActorIsolated %s -verify + +// READ THIS! This test is meant to check the specific isolation when +// UnspecifiedMeansMainActorIsolated is enabled in combination with validating +// behavior around explicitly non-Sendable types that trigger type checker +// specific errors. Please do not put other types of tests in here. + +// Fake Sendable Data +class SendableData : @unchecked Sendable {} + +nonisolated func getDataFromSocket() -> SendableData { SendableData() } + +class Klass { // expected-note 3 {{}} + let s = SendableData() + + init() { s = SendableData() } + init(_ s: SendableData) {} + + func doSomething() {} +} + +@available(*, unavailable) +extension Klass : Sendable {} + +struct StructContainingKlass { + var k = Klass() +} + +func unspecifiedAsync(_ t: T) async {} +nonisolated func nonisolatedAsync(_ t: T) async {} +@MainActor func mainActorAsync(_ t: T) async {} + +func unspecifiedFunctionTest() async { + let k = Klass() + await unspecifiedAsync(k) + await nonisolatedAsync(k) + await mainActorAsync(k) +} + +func unspecifiedFunctionTest2() async { + let k = StructContainingKlass() + await unspecifiedAsync(k) + await nonisolatedAsync(k) + await mainActorAsync(k) + + await unspecifiedAsync(k.k) + await nonisolatedAsync(k.k) + await mainActorAsync(k.k) +} + +nonisolated func nonisolatedFunctionTest() async { + let k = StructContainingKlass() + await unspecifiedAsync(k.k) // expected-error {{non-sendable type 'Klass' of property 'k' cannot exit main actor-isolated context}} + await nonisolatedAsync(k.k) // expected-error {{non-sendable type 'Klass' of property 'k' cannot exit main actor-isolated context}} + await mainActorAsync(k.k) // expected-error {{non-sendable type 'Klass' of property 'k' cannot exit main actor-isolated context}} +} + +func testTask() async { + Task { + let k = Klass(getDataFromSocket()) + k.doSomething() + } +} + +func testTaskDetached() async { + Task.detached { + let k = Klass(getDataFromSocket()) + // Have to pop back onto the main thread to do something. + await k.doSomething() + } +} diff --git a/test/Interop/Cxx/class/safe-interop-mode.swift b/test/Interop/Cxx/class/safe-interop-mode.swift new file mode 100644 index 00000000000..8949037b690 --- /dev/null +++ b/test/Interop/Cxx/class/safe-interop-mode.swift @@ -0,0 +1,43 @@ + +// RUN: rm -rf %t +// RUN: split-file %s %t +// RUN: %target-swift-frontend -typecheck -verify -I %swift_src_root/lib/ClangImporter/SwiftBridging -I %t/Inputs %t/test.swift -enable-experimental-feature AllowUnsafeAttribute -enable-experimental-feature WarnUnsafe -enable-experimental-feature NonescapableTypes -enable-experimental-feature SafeInterop -cxx-interoperability-mode=default -diagnostic-style llvm 2>&1 + +// REQUIRES: objc_interop + +//--- Inputs/module.modulemap +module Test { + header "nonescapable.h" + requires cplusplus +} + +//--- Inputs/nonescapable.h +#include "swift/bridging" + +struct SWIFT_NONESCAPABLE View { + __attribute__((swift_attr("@lifetime(immortal)"))) + View() : member(nullptr) {} + __attribute__((swift_attr("@lifetime(p)"))) + View(const int *p [[clang::lifetimebound]]) : member(p) {} + View(const View&) = default; +private: + const int *member; +}; + +struct SWIFT_ESCAPABLE Owner {}; + +struct Unannotated {}; + +//--- test.swift + +import Test +import CoreFoundation + +func useUnsafeParam(x: Unannotated) { // expected-warning{{reference to unsafe struct 'Unannotated'}} +} + +func useSafeParams(x: Owner, y: View) { +} + +func useCfType(x: CFArray) { +} diff --git a/test/SILGen/default_constructor.swift b/test/SILGen/default_constructor.swift index a7f826cbc1b..f78be6f2327 100644 --- a/test/SILGen/default_constructor.swift +++ b/test/SILGen/default_constructor.swift @@ -97,6 +97,7 @@ struct G { // CHECK-NOT: default_constructor.G.init() // CHECK-LABEL: default_constructor.G.init(bar: Swift.Optional) +// CHECK-NEXT: // Isolation: // CHECK-NEXT: sil hidden [ossa] @$s19default_constructor1GV{{[_0-9a-zA-Z]*}}fC // CHECK-NOT: default_constructor.G.init() diff --git a/test/SILGen/functions.swift b/test/SILGen/functions.swift index 6f0cb1befc7..cf8460ffa34 100644 --- a/test/SILGen/functions.swift +++ b/test/SILGen/functions.swift @@ -481,6 +481,7 @@ func testNoescape() { } // CHECK-LABEL: functions.testNoescape() -> () +// CHECK-NEXT: // Isolation: // CHECK-NEXT: sil hidden [ossa] @$s9functions12testNoescapeyyF : $@convention(thin) () -> () // CHECK: function_ref closure #1 () -> () in functions.testNoescape() -> () // CHECK-NEXT: function_ref @$s9functions12testNoescapeyyFyyXEfU_ : $@convention(thin) (@guaranteed { var Int }) -> () diff --git a/test/SILGen/global_init_attribute.swift b/test/SILGen/global_init_attribute.swift index 95167c71270..2a3e12f8160 100644 --- a/test/SILGen/global_init_attribute.swift +++ b/test/SILGen/global_init_attribute.swift @@ -10,6 +10,7 @@ import def_global let InternalConst = 42 // CHECK-NOT: [global_init] // CHECK: // global_init_attribute.InternalConst.unsafeMutableAddressor : Swift.Int +// CHECK-NEXT: // Isolation: // CHECK-NEXT: sil hidden [global_init] [ossa] @$s21global_init_attribute13InternalConstSivau func foo() -> Int { @@ -22,10 +23,12 @@ func bar(i: Int) { // CHECK-NOT: [global_init] // CHECK: // def_global.ExportedVar.unsafeMutableAddressor : Swift.Int +// CHECK-NEXT: // Isolation: // CHECK-NEXT: sil [global_init] @$s10def_global11ExportedVarSivau var InternalFoo = foo() // CHECK-NOT: [global_init] // CHECK: // global_init_attribute.InternalFoo.unsafeMutableAddressor : Swift.Int +// CHECK-NEXT: // Isolation: // CHECK-NEXT: sil hidden [global_init] [ossa] @$s21global_init_attribute11InternalFooSivau diff --git a/test/SILGen/package_sil_linkage.swift b/test/SILGen/package_sil_linkage.swift index 0b0cead4117..04eb678517a 100644 --- a/test/SILGen/package_sil_linkage.swift +++ b/test/SILGen/package_sil_linkage.swift @@ -12,11 +12,11 @@ /// Check serialization in SILGEN with resilience enabled. // RUN: %target-swift-emit-silgen -emit-verbose-sil -sil-verify-all -enable-library-evolution -module-name Utils %t/Utils.swift -package-name mypkg -I %t > %t/Utils-Res.sil -// RUN: %FileCheck %s --check-prefixes=UTILS-RES,UTILS-COMMON < %t/Utils-Res.sil +// RUN: %FileCheck %s --check-prefixes=UTILS-RES,UTILS-COMMON -input-file=%t/Utils-Res.sil /// Check for indirect access with a resiliently built module dependency. // RUN: %target-swift-emit-silgen -sil-verify-all %t/Client.swift -package-name mypkg -I %t > %t/Client-Res.sil -// RUN: %FileCheck %s --check-prefixes=CLIENT-RES,CLIENT-COMMON < %t/Client-Res.sil +// RUN: %FileCheck %s --check-prefixes=CLIENT-RES,CLIENT-COMMON -input-file=%t/Client-Res.sil // RUN: rm -rf %t/Utils.swiftmodule @@ -30,11 +30,11 @@ /// Check serialization in SILGEN with resilience not enabled. // RUN: %target-swift-emit-silgen -emit-verbose-sil -sil-verify-all -module-name Utils %t/Utils.swift -package-name mypkg -I %t > %t/Utils-NonRes.sil -// RUN: %FileCheck %s --check-prefixes=UTILS-NONRES,UTILS-COMMON < %t/Utils-NonRes.sil +// RUN: %FileCheck %s --check-prefixes=UTILS-NONRES,UTILS-COMMON -input-file %t/Utils-NonRes.sil /// Check for indirect access with a non-resiliently built module dependency. // RUN: %target-swift-emit-silgen -sil-verify-all %t/Client.swift -package-name mypkg -I %t > %t/Client-NonRes.sil -// RUN: %FileCheck %s --check-prefixes=CLIENT-NONRES,CLIENT-COMMON < %t/Client-NonRes.sil +// RUN: %FileCheck %s --check-prefixes=CLIENT-NONRES,CLIENT-COMMON -input-file %t/Client-NonRes.sil //--- Utils.swift @@ -538,11 +538,14 @@ package func f(_ arg: PublicStruct) -> Int { } // CLIENT-RES-LABEL: // f(_:) +// CLIENT-RES-NEXT: // Isolation: unspecified // CLIENT-RES-NEXT: sil package [ossa] @$s6Client1fySi5Utils12PublicStructVF : $@convention(thin) (@in_guaranteed PublicStruct) -> Int // CLIENT-RES-LABEL: // PublicStruct.data.getter +// CLIENT-RES-NEXT: // Isolation: unspecified // CLIENT-RES-NEXT: sil @$s5Utils12PublicStructV4dataSivg : $@convention(method) (@in_guaranteed PublicStruct) -> Int // CLIENT-NONRES-LABEL: // f(_:) +// CLIENT-NONRES-NEXT: // Isolation: unspecified // CLIENT-NONRES-NEXT: sil package [ossa] @$s6Client1fySi5Utils12PublicStructVF : $@convention(thin) (PublicStruct) -> Int public func ff(_ arg: PublicStruct) -> Int { @@ -550,9 +553,11 @@ public func ff(_ arg: PublicStruct) -> Int { } // CLIENT-RES-LABEL: // ff(_:) +// CLIENT-RES-NEXT: // Isolation: unspecified // CLIENT-RES-NEXT: sil [ossa] @$s6Client2ffySi5Utils12PublicStructVF : $@convention(thin) (@in_guaranteed PublicStruct) -> Int // CLIENT-NONRES-LABEL: // ff(_:) +// CLIENT-NONRES-NEXT: // Isolation: unspecified // CLIENT-NONRES-NEXT: sil [ossa] @$s6Client2ffySi5Utils12PublicStructVF : $@convention(thin) (PublicStruct) -> Int @@ -587,11 +592,14 @@ package func g(_ arg: PkgStruct) -> Int { } // CLIENT-RES-LABEL: // g(_:) +// CLIENT-RES-NEXT: // Isolation: unspecified // CLIENT-RES-NEXT: sil package [ossa] @$s6Client1gySi5Utils9PkgStructVF : $@convention(thin) (@in_guaranteed PkgStruct) -> Int // CLIENT-RES-LABEL: // PkgStruct.data.getter +// CLIENT-RES-NEXT: // Isolation: unspecified // CLIENT-RES-NEXT: sil package_external @$s5Utils9PkgStructV4dataSivg : $@convention(method) (@in_guaranteed PkgStruct) -> Int // CLIENT-NONRES-LABEL: // g(_:) +// CLIENT-NONRES-NEXT: // Isolation: unspecified // CLIENT-NONRES-NEXT: sil package [ossa] @$s6Client1gySi5Utils9PkgStructVF : $@convention(thin) (PkgStruct) -> Int package func gx(_ arg: UfiPkgClass) -> Int { @@ -599,6 +607,7 @@ package func gx(_ arg: UfiPkgClass) -> Int { } // CLIENT-COMMON-LABEL: // gx(_:) +// CLIENT-COMMON-NEXT: // Isolation: unspecified // CLIENT-COMMON-NEXT: sil package [ossa] @$s6Client2gxySi5Utils11UfiPkgClassCF : $@convention(thin) (@guaranteed UfiPkgClass) -> Int { package func m(_ arg: PkgStructGeneric) -> T { @@ -606,12 +615,15 @@ package func m(_ arg: PkgStructGeneric) -> T { } // CLIENT-RES-LABEL: // m(_:) +// CLIENT-RES-NEXT: // Isolation: unspecified // CLIENT-RES-NEXT: sil package [ossa] @$s6Client1myx5Utils16PkgStructGenericVyxGlF : $@convention(thin) (@in_guaranteed PkgStructGeneric) -> @out T { // CLIENT-RES-LABEL: // PkgStructGeneric.data.getter +// CLIENT-RES-NEXT: // Isolation: unspecified // CLIENT-RES-NEXT: sil package_external @$s5Utils16PkgStructGenericV4dataxvg : $@convention(method) <τ_0_0> (@in_guaranteed PkgStructGeneric<τ_0_0>) -> @out τ_0_0 // CLIENT-NONRES-LABEL: // m(_:) +// CLIENT-NONRES-NEXT: // Isolation: unspecified // CLIENT-NONRES-NEXT: sil package [ossa] @$s6Client1myx5Utils16PkgStructGenericVyxGlF : $@convention(thin) (@in_guaranteed PkgStructGeneric) -> @out T { @@ -625,12 +637,16 @@ package func n(_ arg: PkgStructWithPublicMember) -> Int { } // CLIENT-RES-LABEL: // n(_:) +// CLIENT-RES-NEXT: // Isolation: unspecified // CLIENT-RES-NEXT: sil package [ossa] @$s6Client1nySi5Utils25PkgStructWithPublicMemberVF : $@convention(thin) (@in_guaranteed PkgStructWithPublicMember) -> Int + // CLIENT-RES-LABEL: // PkgStructWithPublicMember.member.getter +// CLIENT-RES-NEXT: // Isolation: unspecified // CLIENT-RES-NEXT: sil package_external @$s5Utils25PkgStructWithPublicMemberV6memberAA0eC0Vvg : $@convention(method) (@in_guaranteed PkgStructWithPublicMember) -> @out PublicStruct // CLIENT-NONRES-LABEL: // n(_:) +// CLIENT-NONRES-NEXT: // Isolation: unspecified // CLIENT-NONRES-NEXT: sil package [ossa] @$s6Client1nySi5Utils25PkgStructWithPublicMemberVF : $@convention(thin) (PkgStructWithPublicMember) -> Int package func p(_ arg: PkgStructWithPublicExistential) -> any PublicProto { @@ -638,13 +654,16 @@ package func p(_ arg: PkgStructWithPublicExistential) -> any PublicProto { } // CLIENT-RES-LABEL: // p(_:) +// CLIENT-RES-NEXT: // Isolation: unspecified // CLIENT-RES-NEXT: sil package [ossa] @$s6Client1py5Utils11PublicProto_pAC013PkgStructWithC11ExistentialVF : $@convention(thin) (@in_guaranteed PkgStructWithPublicExistential) -> @out any PublicProto { // CLIENT-RES-LABEL: // PkgStructWithPublicExistential.member.getter +// CLIENT-RES-NEXT: // Isolation: unspecified // CLIENT-RES-NEXT: sil package_external @$s5Utils30PkgStructWithPublicExistentialV6memberAA0E5Proto_pvg : $@convention(method) (@in_guaranteed PkgStructWithPublicExistential) -> @out any PublicProto // CLIENT-NONRES-LABEL: // p(_:) +// CLIENT-NONRES-NEXT: // Isolation: unspecified // CLIENT-NONRES-NEXT: sil package [ossa] @$s6Client1py5Utils11PublicProto_pAC013PkgStructWithC11ExistentialVF : $@convention(thin) (@in_guaranteed PkgStructWithPublicExistential) -> @out any PublicProto { package func q(_ arg: PkgStructWithPkgExistential) -> any PkgProto { @@ -652,13 +671,16 @@ package func q(_ arg: PkgStructWithPkgExistential) -> any PkgProto { } // CLIENT-RES-LABEL: // q(_:) +// CLIENT-RES-NEXT: // Isolation: unspecified // CLIENT-RES-NEXT: sil package [ossa] @$s6Client1qy5Utils8PkgProto_pAC0c10StructWithC11ExistentialVF : $@convention(thin) (@in_guaranteed PkgStructWithPkgExistential) -> @out any PkgProto { // CLIENT-RES-LABEL: // PkgStructWithPkgExistential.member.getter +// CLIENT-RES-NEXT: // Isolation: unspecified // CLIENT-RES-NEXT: sil package_external @$s5Utils013PkgStructWithB11ExistentialV6memberAA0B5Proto_pvg : $@convention(method) (@in_guaranteed PkgStructWithPkgExistential) -> @out any PkgProto // CLIENT-NONRES-LABEL: // q(_:) +// CLIENT-NONRES-NEXT: // Isolation: unspecified // CLIENT-NONRES-NEXT: sil package [ossa] @$s6Client1qy5Utils8PkgProto_pAC0c10StructWithC11ExistentialVF : $@convention(thin) (@in_guaranteed PkgStructWithPkgExistential) -> @out any PkgProto { package func r(_ arg: PublicProto) -> Int { @@ -666,6 +688,7 @@ package func r(_ arg: PublicProto) -> Int { } // CLIENT-COMMON-LABEL: // r(_:) +// CLIENT-COMMON-NEXT: // Isolation: unspecified // CLIENT-COMMON-NEXT: sil package [ossa] @$s6Client1rySi5Utils11PublicProto_pF : $@convention(thin) (@in_guaranteed any PublicProto) -> Int { package func s(_ arg: PkgProto) -> Int { @@ -673,6 +696,7 @@ package func s(_ arg: PkgProto) -> Int { } // CLIENT-COMMON-LABEL: // s(_:) +// CLIENT-COMMON-NEXT: // Isolation: unspecified // CLIENT-COMMON-NEXT: sil package [ossa] @$s6Client1sySi5Utils8PkgProto_pF : $@convention(thin) (@in_guaranteed any PkgProto) -> Int { public func t(_ arg: any PublicProto) -> Int { @@ -700,4 +724,5 @@ package func w(_ arg: PkgKlass) -> Int { } // CLIENT-COMMON-LABEL: // w(_:) +// CLIENT-COMMON-NEXT: // Isolation: unspecified // CLIENT-COMMON-NEXT: sil package [ossa] @$s6Client1wySi5Utils8PkgKlassCF : $@convention(thin) (@guaranteed PkgKlass) -> Int diff --git a/test/SILGen/stored_property_default_arg.swift b/test/SILGen/stored_property_default_arg.swift index 8c9948ff537..4d7ecfa1b4e 100644 --- a/test/SILGen/stored_property_default_arg.swift +++ b/test/SILGen/stored_property_default_arg.swift @@ -3,6 +3,7 @@ // Currently, this only appears for memberwise initializers. // CHECK: default argument 0 of A.init(b:c:) +// CHECK-NEXT: // Isolation: unspecified // CHECK-NEXT: sil hidden [ossa] @$s27stored_property_default_arg1AV1b1cACSi_SbtcfcfA_ : $@convention(thin) () -> Int { // CHECK-NEXT: bb0: // CHECK-NEXT: function_ref variable initialization expression of A.b @@ -12,6 +13,7 @@ // CHECK-NEXT: } // CHECK: default argument 1 of A.init(b:c:) +// CHECK-NEXT: // Isolation: unspecified // CHECK-NEXT: sil hidden [ossa] @$s27stored_property_default_arg1AV1b1cACSi_SbtcfcfA0_ : $@convention(thin) () -> Bool { // CHECK-NEXT: bb0: // CHECK-NEXT: function_ref variable initialization expression of A.c @@ -45,6 +47,7 @@ func checkConcreteType() { } // CHECK: default argument 1 of F.init(g:h:) +// CHECK-NEXT: // Isolation: unspecified // CHECK-NEXT: sil hidden [ossa] @$s27stored_property_default_arg1FV1g1hACyxGx_SitcfcfA0_ : $@convention(thin) () -> Int { // CHECK-NEXT: bb0: // CHECK-NEXT: function_ref variable initialization expression of F.h @@ -90,6 +93,7 @@ func checkOptionalNil() { } // CHECK: default argument 0 of O.init(p:q:) +// CHECK-NEXT: // Isolation: unspecified // CHECK-NEXT: sil hidden [ossa] @$s27stored_property_default_arg1OV1p1qACyxGx_x_SittcfcfA_ : $@convention(thin) () -> @out T { // CHECK: bb0([[PARAM_0:.*]] : $*T): // CHECK-NEXT: function_ref variable initialization expression of O.p @@ -100,6 +104,7 @@ func checkOptionalNil() { // CHECK-NEXT: } // CHECK: default argument 1 of O.init(p:q:) +// CHECK-NEXT: // Isolation: unspecified // CHECK-NEXT: sil hidden [ossa] @$s27stored_property_default_arg1OV1p1qACyxGx_x_SittcfcfA0_ : $@convention(thin) () -> (@out T, Int) { // CHECK: bb0([[PARAM_0:.*]] : $*T): // CHECK-NEXT: function_ref variable initialization expression of O.q @@ -135,6 +140,7 @@ func checkIndirect() { } // CHECK: default argument 0 of U.init(v:w:) +// CHECK-NEXT: // Isolation: unspecified // CHECK-NEXT: sil hidden [ossa] @$s27stored_property_default_arg1UV1v1wAcA1TCSg_AGtcfcfA_ : $@convention(thin) () -> @owned Optional { // CHECK-NEXT: bb0: // CHECK-NEXT: function_ref variable initialization expression of U.v @@ -144,6 +150,7 @@ func checkIndirect() { // CHECK-NEXT: } // CHECK: default argument 1 of U.init(v:w:) +// CHECK-NEXT: // Isolation: unspecified // CHECK-NEXT: sil hidden [ossa] @$s27stored_property_default_arg1UV1v1wAcA1TCSg_AGtcfcfA0_ : $@convention(thin) () -> @owned T { // CHECK-NEXT: bb0: // CHECK-NEXT: function_ref variable initialization expression of U.w @@ -179,6 +186,7 @@ func checkReferenceTypes() { } // CHECK: default argument 0 of AA.init(ab:) +// CHECK-NEXT: // Isolation: unspecified // CHECK-NEXT: sil hidden [ossa] @$s27stored_property_default_arg2AAV2abAcA1ZCSg2ac_AG2adt_tcfcfA_ : $@convention(thin) () -> (@owned Optional, @owned Optional) { // CHECK-NEXT: bb0: // CHECK-NEXT: function_ref variable initialization expression of AA.ab diff --git a/test/SILGen/synthesized_conformance_class.swift b/test/SILGen/synthesized_conformance_class.swift index a19db139c78..5db67fe9dbf 100644 --- a/test/SILGen/synthesized_conformance_class.swift +++ b/test/SILGen/synthesized_conformance_class.swift @@ -64,14 +64,17 @@ class Nonfinal { extension Final: Encodable where T: Encodable {} // CHECK-LABEL: // Final.encode(to:) +// CHECK-NEXT: // Isolation: unspecified // CHECK-NEXT: sil hidden [ossa] @$s29synthesized_conformance_class5FinalCAASERzlE6encode2toys7Encoder_p_tKF : $@convention(method) (@in_guaranteed any Encoder, @guaranteed Final) -> @error any Error { extension Final: Decodable where T: Decodable {} // CHECK-LABEL: // Final.init(from:) +// CHECK-NEXT: // Isolation: unspecified // CHECK-NEXT: sil hidden [exact_self_class] [ossa] @$s29synthesized_conformance_class5FinalCAASeRzlE4fromACyxGs7Decoder_p_tKcfC : $@convention(method) (@in any Decoder, @thick Final.Type) -> (@owned Final, @error any Error) { extension Nonfinal: Encodable where T: Encodable {} // CHECK-LABEL: // Nonfinal.encode(to:) +// CHECK-NEXT: // Isolation: unspecified // CHECK-NEXT: sil hidden [ossa] @$s29synthesized_conformance_class8NonfinalCAASERzlE6encode2toys7Encoder_p_tKF : $@convention(method) (@in_guaranteed any Encoder, @guaranteed Nonfinal) -> @error any Error { final class FinalHashableClass : Hashable { diff --git a/test/SILGen/synthesized_conformance_enum.swift b/test/SILGen/synthesized_conformance_enum.swift index c168af1dea9..9d0f4fcf644 100644 --- a/test/SILGen/synthesized_conformance_enum.swift +++ b/test/SILGen/synthesized_conformance_enum.swift @@ -36,22 +36,28 @@ enum NoValues { extension Enum: Equatable where T: Equatable {} // CHECK-FRAGILE-LABEL: // static Enum.__derived_enum_equals(_:_:) +// CHECK-FRAGILE-NEXT: // Isolation: unspecified // CHECK-FRAGILE-NEXT: sil hidden [ossa] @$s28synthesized_conformance_enum4EnumOAASQRzlE010__derived_C7_equalsySbACyxG_AEtFZ : $@convention(method) (@in_guaranteed Enum, @in_guaranteed Enum, @thin Enum.Type) -> Bool { // CHECK-RESILIENT-LABEL: // static Enum.== infix(_:_:) +// CHECK-RESILIENT-NEXT: // Isolation: unspecified // CHECK-RESILIENT-NEXT: sil hidden [ossa] @$s28synthesized_conformance_enum4EnumOAASQRzlE2eeoiySbACyxG_AEtFZ : $@convention(method) (@in_guaranteed Enum, @in_guaranteed Enum, @thin Enum.Type) -> Bool { extension Enum: Hashable where T: Hashable {} // CHECK-LABEL: // Enum.hash(into:) +// CHECK-NEXT: // Isolation: unspecified // CHECK-NEXT: sil hidden [ossa] @$s28synthesized_conformance_enum4EnumOAASHRzlE4hash4intoys6HasherVz_tF : $@convention(method) (@inout Hasher, @in_guaranteed Enum) -> () { // CHECK-LABEL: // Enum.hashValue.getter +// CHECK-NEXT: // Isolation: unspecified // CHECK-NEXT: sil hidden [ossa] @$s28synthesized_conformance_enum4EnumOAASHRzlE9hashValueSivg : $@convention(method) (@in_guaranteed Enum) -> Int { extension Enum: Codable where T: Codable {} // CHECK-LABEL: // Enum.encode(to:) +// CHECK-NEXT: // Isolation: unspecified // CHECK-NEXT: sil hidden [ossa] @$s28synthesized_conformance_enum4EnumOAASeRzSERzlE6encode2toys7Encoder_p_tKF : $@convention(method) (@in_guaranteed any Encoder, @in_guaranteed Enum) -> @error any Error { // CHECK-LABEL: // Enum.init(from:) +// CHECK-NEXT: // Isolation: unspecified // CHECK-NEXT: sil hidden [ossa] @$s28synthesized_conformance_enum4EnumOAASeRzSERzlE4fromACyxGs7Decoder_p_tKcfC : $@convention(method) (@in any Decoder, @thin Enum.Type) -> (@out Enum, @error any Error) extension NoValues: CaseIterable {} @@ -61,9 +67,11 @@ extension NoValues: CaseIterable {} extension NoValues: Codable {} // CHECK-LABEL: // NoValues.encode(to:) +// CHECK-NEXT: // Isolation: unspecified // CHECK-NEXT: sil hidden [ossa] @$s28synthesized_conformance_enum8NoValuesO6encode2toys7Encoder_p_tKF : $@convention(method) (@in_guaranteed any Encoder, NoValues) -> @error any Error { // CHECK-LABEL: // NoValues.init(from:) +// CHECK-NEXT: // Isolation: unspecified // CHECK-NEXT: sil hidden [ossa] @$s28synthesized_conformance_enum8NoValuesO4fromACs7Decoder_p_tKcfC : $@convention(method) (@in any Decoder, @thin NoValues.Type) -> (NoValues, @error any Error) // Witness tables for Enum diff --git a/test/SILGen/synthesized_conformance_struct.swift b/test/SILGen/synthesized_conformance_struct.swift index e5e58cfe317..d173b002565 100644 --- a/test/SILGen/synthesized_conformance_struct.swift +++ b/test/SILGen/synthesized_conformance_struct.swift @@ -35,22 +35,28 @@ struct Struct { extension Struct: Equatable where T: Equatable {} // CHECK-FRAGILE-LABEL: // static Struct.__derived_struct_equals(_:_:) +// CHECK-FRAGILE-NEXT: // Isolation: unspecified // CHECK-FRAGILE-NEXT: sil hidden [ossa] @$s30synthesized_conformance_struct6StructVAASQRzlE010__derived_C7_equalsySbACyxG_AEtFZ : $@convention(method) (@in_guaranteed Struct, @in_guaranteed Struct, @thin Struct.Type) -> Bool { // CHECK-RESILIENT-LABEL: // static Struct.== infix(_:_:) +// CHECK-RESILIENT-NEXT: // Isolation: unspecified // CHECK-RESILIENT-NEXT: sil hidden [ossa] @$s30synthesized_conformance_struct6StructVAASQRzlE2eeoiySbACyxG_AEtFZ : $@convention(method) (@in_guaranteed Struct, @in_guaranteed Struct, @thin Struct.Type) -> Bool { extension Struct: Hashable where T: Hashable {} // CHECK-LABEL: // Struct.hash(into:) +// CHECK-NEXT: // Isolation: unspecified // CHECK-NEXT: sil hidden [ossa] @$s30synthesized_conformance_struct6StructVAASHRzlE4hash4intoys6HasherVz_tF : $@convention(method) (@inout Hasher, @in_guaranteed Struct) -> () { // CHECK-LABEL: // Struct.hashValue.getter +// CHECK-NEXT: // Isolation: unspecified // CHECK-NEXT: sil hidden [ossa] @$s30synthesized_conformance_struct6StructVAASHRzlE9hashValueSivg : $@convention(method) (@in_guaranteed Struct) -> Int { extension Struct: Codable where T: Codable {} // CHECK-LABEL: // Struct.encode(to:) +// CHECK-NEXT: // Isolation: unspecified // CHECK-NEXT: sil hidden [ossa] @$s30synthesized_conformance_struct6StructVAASeRzSERzlE6encode2toys7Encoder_p_tKF : $@convention(method) (@in_guaranteed any Encoder, @in_guaranteed Struct) -> @error any Error { // CHECK-LABEL: // Struct.init(from:) +// CHECK-NEXT: // Isolation: unspecified // CHECK-NEXT: sil hidden [ossa] @$s30synthesized_conformance_struct6StructVAASeRzSERzlE4fromACyxGs7Decoder_p_tKcfC : $@convention(method) (@in any Decoder, @thin Struct.Type) -> (@out Struct, @error any Error) diff --git a/test/SILOptimizer/moveonly_raw_layout.swift b/test/SILOptimizer/moveonly_raw_layout.swift index b5a05836e72..c080d3d8f35 100644 --- a/test/SILOptimizer/moveonly_raw_layout.swift +++ b/test/SILOptimizer/moveonly_raw_layout.swift @@ -13,6 +13,7 @@ struct Lock: ~Copyable { var _address: Builtin.RawPointer { return Builtin.addressOfBorrow(self) } // CHECK-LABEL: // Lock.init() + // CHECK-NEXT: Isolation: unspecified // CHECK-NEXT: sil{{.*}} @[[INIT:\$.*4LockV.*fC]] : init() { // CHECK-NOT: destroy_addr @@ -26,6 +27,7 @@ struct Lock: ~Copyable { } // CHECK-LABEL: // Lock.deinit + // CHECK-NEXT: Isolation: unspecified // CHECK-NEXT: sil{{.*}} @[[DEINIT:\$.*4LockV.*fD]] : deinit { // CHECK-NOT: destroy_addr diff --git a/test/SILOptimizer/specialize_self.swift b/test/SILOptimizer/specialize_self.swift index 4cd5f81b69e..7d186a35774 100644 --- a/test/SILOptimizer/specialize_self.swift +++ b/test/SILOptimizer/specialize_self.swift @@ -4,12 +4,14 @@ // CHECK-NOT: generic specialization of specialize_self.cast (A) -> Swift.Optional // CHECK-LABEL: specialize_self.cast(A) -> Swift.Optional +// CHECK-NEXT: Isolation: unspecified // CHECK-NEXT: sil hidden @$s15specialize_self4cast{{[_0-9a-zA-Z]*}}F : $@convention(thin) (@in_guaranteed T) -> @out Optional func cast(_ x: T) -> R? { return x as? R } // CHECK-LABEL: static specialize_self.Base.returnIfSelf(Swift.AnyObject) -> Swift.Optional +// CHECK-NEXT: Isolation: unspecified // CHECK-NEXT: sil hidden @$s15specialize_self4BaseC12returnIfSelf{{[_0-9a-zA-Z]*}}FZ : $@convention(method) (@guaranteed AnyObject, @thick Base.Type) -> @owned Optional // CHECK: [[CAST:%[0-9]+]] = function_ref @$s15specialize_self4cast{{[_0-9a-zA-Z]*}}F // CHECK: apply [[CAST]] diff --git a/test/Serialization/nested-protocols.swift b/test/Serialization/nested-protocols.swift index cd3173332bf..204756c96d7 100644 --- a/test/Serialization/nested-protocols.swift +++ b/test/Serialization/nested-protocols.swift @@ -4,9 +4,11 @@ import nestedprotocolsource // CHECK: usesNested(_:) +// CHECK-NEXT: Isolation: unspecified // CHECK-NEXT: sil @$s4main10usesNestedyyx20nestedprotocolsource5OuterV5InnerRzlF : public func usesNested(_ x: some Outer.Inner) {} // CHECK: usesNestedInExtension(_:) +// CHECK-NEXT: Isolation: unspecified // CHECK-NEXT: sil @$s4main21usesNestedInExtensionyyx20nestedprotocolsource5OuterV05InnerdE0RzlF : -public func usesNestedInExtension(_ x: some Outer.InnerInExtension) {} \ No newline at end of file +public func usesNestedInExtension(_ x: some Outer.InnerInExtension) {}