diff --git a/include/swift/AST/ActorIsolation.h b/include/swift/AST/ActorIsolation.h index 3f6f9956fcdff..2adf24b7d87ea 100644 --- a/include/swift/AST/ActorIsolation.h +++ b/include/swift/AST/ActorIsolation.h @@ -160,6 +160,8 @@ class ActorIsolation { return getKind() == GlobalActor || getKind() == GlobalActorUnsafe; } + bool isMainActor() const; + bool isDistributedActor() const; Type getGlobalActor() const { diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h index fbe06c6907106..b551089716d70 100644 --- a/include/swift/AST/Decl.h +++ b/include/swift/AST/Decl.h @@ -3834,6 +3834,9 @@ class NominalTypeDecl : public GenericTypeDecl, public IterableDeclContext { /// Whether this nominal type qualifies as any actor (plain or distributed). bool isAnyActor() const; + /// Whether this nominal type is the `MainActor` global actor. + bool isMainActor() const; + /// Return the range of semantics attributes attached to this NominalTypeDecl. auto getSemanticsAttrs() const -> decltype(getAttrs().getSemanticsAttrs()) { diff --git a/include/swift/PrintAsClang/ClangMacros.def b/include/swift/PrintAsClang/ClangMacros.def index 233b46ca10fbb..0d3144c5d32b7 100644 --- a/include/swift/PrintAsClang/ClangMacros.def +++ b/include/swift/PrintAsClang/ClangMacros.def @@ -133,7 +133,7 @@ CLANG_MACRO_BODY("SWIFT_CLASS", \ "SWIFT_RUNTIME_NAME(SWIFT_NAME) __attribute__((objc_subclassing_restricted)) " \ "SWIFT_CLASS_EXTRA\n" \ "# define SWIFT_CLASS_NAMED(SWIFT_NAME) " \ - "__attribute((objc_subclassing_restricted)) SWIFT_COMPILE_NAME(SWIFT_NAME) " \ + "__attribute__((objc_subclassing_restricted)) SWIFT_COMPILE_NAME(SWIFT_NAME) " \ "SWIFT_CLASS_EXTRA\n" \ "# else\n" \ "# define SWIFT_CLASS(SWIFT_NAME) " \ @@ -175,7 +175,7 @@ CLANG_MACRO_CONDITIONAL("SWIFT_ENUM_ATTR", "(_extensibility)", \ CLANG_MACRO_BODY("SWIFT_ENUM", \ "# define SWIFT_ENUM(_type, _name, _extensibility) " \ "enum _name : _type _name; " \ - "enum SWIFT_ENUM_ATTR(_extensibility) SWIFT_ENUM_EXTRA _name: _type\n" \ + "enum SWIFT_ENUM_ATTR(_extensibility) SWIFT_ENUM_EXTRA _name : _type\n" \ "# if __has_feature(generalized_swift_name)\n" \ "# define SWIFT_ENUM_NAMED(_type, _name, SWIFT_NAME, _extensibility) " \ "enum _name : _type _name SWIFT_COMPILE_NAME(SWIFT_NAME); " \ @@ -197,7 +197,7 @@ CLANG_MACRO("SWIFT_DEPRECATED", , "__attribute__((deprecated))") CLANG_MACRO("SWIFT_DEPRECATED_MSG", "(...)", "__attribute__((deprecated(__VA_ARGS__)))") CLANG_MACRO_ALTERNATIVE("SWIFT_DEPRECATED_OBJC", "(Msg)", \ - "__has_feature(attribute_diagnost_if_objc)", \ + "__has_feature(attribute_diagnose_if_objc)", \ "__attribute__((diagnose_if(1, Msg, \"warning\")))", \ "SWIFT_DEPRECATED_MSG(Msg)") diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 173429d81e85d..807b518385fea 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -4567,6 +4567,11 @@ bool NominalTypeDecl::isAnyActor() const { return isActor() || isDistributedActor(); } +bool NominalTypeDecl::isMainActor() const { + return getName().is("MainActor") && + getParentModule()->getName() == getASTContext().Id_Concurrency; +} + GenericTypeDecl::GenericTypeDecl(DeclKind K, DeclContext *DC, Identifier name, SourceLoc nameLoc, ArrayRef inherited, @@ -9614,6 +9619,15 @@ void swift::simple_display(llvm::raw_ostream &out, AnyFunctionRef fn) { out << "closure"; } +bool ActorIsolation::isMainActor() const { + if (isGlobalActor()) { + if (auto *nominal = getGlobalActor()->getAnyNominal()) + return nominal->isMainActor(); + } + + return false; +} + bool ActorIsolation::isDistributedActor() const { return getKind() == ActorInstance && getActor()->isDistributedActor(); } diff --git a/lib/AST/DiagnosticEngine.cpp b/lib/AST/DiagnosticEngine.cpp index bda5424e5c8dd..8ee6eddaaa110 100644 --- a/lib/AST/DiagnosticEngine.cpp +++ b/lib/AST/DiagnosticEngine.cpp @@ -576,18 +576,6 @@ static bool typeSpellingIsAmbiguous(Type type, return false; } -/// Determine whether this is the main actor type. -static bool isMainActor(Type type) { - if (auto nominal = type->getAnyNominal()) { - if (nominal->getName().is("MainActor") && - nominal->getParentModule()->getName() == - nominal->getASTContext().Id_Concurrency) - return true; - } - - return false; -} - void swift::printClangDeclName(const clang::NamedDecl *ND, llvm::raw_ostream &os) { ND->getNameForDiagnostic(os, ND->getASTContext().getPrintingPolicy(), false); @@ -841,10 +829,10 @@ static void formatDiagnosticArgument(StringRef Modifier, case ActorIsolation::GlobalActor: case ActorIsolation::GlobalActorUnsafe: { - Type globalActor = isolation.getGlobalActor(); - if (isMainActor(globalActor)) { + if (isolation.isMainActor()) { Out << "main actor-isolated"; } else { + Type globalActor = isolation.getGlobalActor(); Out << "global actor " << FormatOpts.OpeningQuotationMark << globalActor.getString() << FormatOpts.ClosingQuotationMark << "-isolated"; diff --git a/lib/AST/Module.cpp b/lib/AST/Module.cpp index db15aa540fa64..ab9db5e738ae9 100644 --- a/lib/AST/Module.cpp +++ b/lib/AST/Module.cpp @@ -1128,6 +1128,9 @@ void ModuleDecl::getDisplayDecls(SmallVectorImpl &Results, bool Recursive llvm::SmallDenseMap, 4> QualifiedImports; collectParsedExportedImports(this, Modules, QualifiedImports); for (const auto &QI : QualifiedImports) { + auto Module = QI.getFirst(); + if (Modules.contains(Module)) continue; + auto &Decls = QI.getSecond(); Results.append(Decls.begin(), Decls.end()); } diff --git a/lib/SILGen/SILGenProlog.cpp b/lib/SILGen/SILGenProlog.cpp index 46cf9cd37b19a..b904b2bc764d7 100644 --- a/lib/SILGen/SILGenProlog.cpp +++ b/lib/SILGen/SILGenProlog.cpp @@ -712,6 +712,11 @@ void SILGenFunction::emitProlog(CaptureInfo captureInfo, !isInActorDestructor(FunctionDC) && !F.isDefer(); + // FIXME: Avoid loading and checking the expected executor if concurrency is + // unavailable. This is specifically relevant for MainActor isolated contexts, + // which are allowed to be available on OSes where concurrency is not + // available. rdar://106827064 + // Local function to load the expected executor from a local actor auto loadExpectedExecutorForLocalVar = [&](VarDecl *var) { auto loc = RegularLocation::getAutoGeneratedLocation(F.getLocation()); diff --git a/lib/SILOptimizer/Mandatory/PredictableMemOpt.cpp b/lib/SILOptimizer/Mandatory/PredictableMemOpt.cpp index ecd815545fd82..26ea71feeef49 100644 --- a/lib/SILOptimizer/Mandatory/PredictableMemOpt.cpp +++ b/lib/SILOptimizer/Mandatory/PredictableMemOpt.cpp @@ -1219,7 +1219,7 @@ void AvailableValueAggregator::addHandOffCopyDestroysForPhis( // Otherwise, we need to insert one last destroy after the load for our phi. auto next = std::next(load->getIterator()); SILBuilderWithScope builder(next); - builder.emitDestroyValueOperation(next->getLoc(), phi); + builder.emitDestroyValueOperation(RegularLocation(next->getLoc()), phi); } // Alright! In summary, we just lifetime extended all of our phis, @@ -1251,7 +1251,7 @@ void AvailableValueAggregator::addMissingDestroysForCopiedValues( assert(li->getParent() == load->getParent()); auto next = std::next(load->getIterator()); SILBuilderWithScope builder(next); - builder.emitDestroyValueOperation(next->getLoc(), li); + builder.emitDestroyValueOperation(RegularLocation(next->getLoc()), li); continue; } } @@ -1301,7 +1301,7 @@ void AvailableValueAggregator::addMissingDestroysForCopiedValues( // Otherwise, we need to insert one last destroy after the load for our phi. auto next = std::next(load->getIterator()); SILBuilderWithScope builder(next); - builder.emitDestroyValueOperation(next->getLoc(), cvi); + builder.emitDestroyValueOperation(RegularLocation(next->getLoc()), cvi); } } diff --git a/lib/SILOptimizer/Utils/InstOptUtils.cpp b/lib/SILOptimizer/Utils/InstOptUtils.cpp index e94779694fce6..794a59b82b206 100644 --- a/lib/SILOptimizer/Utils/InstOptUtils.cpp +++ b/lib/SILOptimizer/Utils/InstOptUtils.cpp @@ -1507,7 +1507,7 @@ void swift::insertDeallocOfCapturedArguments(PartialApplyInst *pai, } else { insertionPoint = terminator; } - auto builder = SILBuilder(insertionPoint); + SILBuilderWithScope builder(insertionPoint); builder.createDeallocStack(CleanupLocation(insertionPoint->getLoc()), arg.get()); } diff --git a/lib/Sema/TypeCheckAccess.cpp b/lib/Sema/TypeCheckAccess.cpp index 3c2683e2cf48b..1938c28a8730f 100644 --- a/lib/Sema/TypeCheckAccess.cpp +++ b/lib/Sema/TypeCheckAccess.cpp @@ -1744,13 +1744,23 @@ class DeclAvailabilityChecker : public DeclVisitor { explicit DeclAvailabilityChecker(ExportContext where) : Where(where) {} + void checkGlobalActor(Decl *D) { + auto globalActor = D->getGlobalActorAttr(); + if (!globalActor) + return; + + // Avoid checking the availability for a @MainActor constraint since it does + // not carry an inherent ABI impact. + if (globalActor->second->isMainActor()) + return; + + auto customAttr = globalActor->first; + checkType(customAttr->getType(), customAttr->getTypeRepr(), D); + } + void visit(Decl *D) { DeclVisitor::visit(D); - - if (auto globalActor = D->getGlobalActorAttr()) { - auto customAttr = globalActor->first; - checkType(customAttr->getType(), customAttr->getTypeRepr(), D); - } + checkGlobalActor(D); } // Force all kinds to be handled at a lower level. diff --git a/lib/Sema/TypeCheckAttr.cpp b/lib/Sema/TypeCheckAttr.cpp index 70c5c9335de7e..e49a3df47f07c 100644 --- a/lib/Sema/TypeCheckAttr.cpp +++ b/lib/Sema/TypeCheckAttr.cpp @@ -3538,15 +3538,6 @@ void AttributeChecker::visitFrozenAttr(FrozenAttr *attr) { } } -/// Determine whether this is the main actor type. -/// FIXME: the diagnostics engine and TypeCheckConcurrency both have a copy of -/// this -static bool isMainActor(NominalTypeDecl *nominal) { - return nominal->getName().is("MainActor") && - nominal->getParentModule()->getName() == - nominal->getASTContext().Id_Concurrency; -} - void AttributeChecker::visitCustomAttr(CustomAttr *attr) { auto dc = D->getDeclContext(); @@ -3582,7 +3573,7 @@ void AttributeChecker::visitCustomAttr(CustomAttr *attr) { return; } - if (isMainActor(nominal) && Ctx.LangOpts.isConcurrencyModelTaskToThread() && + if (nominal->isMainActor() && Ctx.LangOpts.isConcurrencyModelTaskToThread() && !AvailableAttr::isUnavailable(D)) { Ctx.Diags.diagnose(attr->getLocation(), diag::concurrency_task_to_thread_model_main_actor, diff --git a/lib/Sema/TypeCheckConcurrency.cpp b/lib/Sema/TypeCheckConcurrency.cpp index ee96876ca6fe8..9049885f95269 100644 --- a/lib/Sema/TypeCheckConcurrency.cpp +++ b/lib/Sema/TypeCheckConcurrency.cpp @@ -1193,14 +1193,9 @@ void swift::diagnoseMissingExplicitSendable(NominalTypeDecl *nominal) { } /// Determine whether this is the main actor type. -/// FIXME: the diagnostics engine has a copy of this. static bool isMainActor(Type type) { - if (auto nominal = type->getAnyNominal()) { - if (nominal->getName().is("MainActor") && - nominal->getParentModule()->getName() == - nominal->getASTContext().Id_Concurrency) - return true; - } + if (auto nominal = type->getAnyNominal()) + return nominal->isMainActor(); return false; } diff --git a/test/SILOptimizer/closure-lifetime-fixup.sil b/test/SILOptimizer/closure-lifetime-fixup.sil index 3c8774d83196a..017b364db0a47 100644 --- a/test/SILOptimizer/closure-lifetime-fixup.sil +++ b/test/SILOptimizer/closure-lifetime-fixup.sil @@ -1,4 +1,4 @@ -// RUN: %target-sil-opt -enable-sil-verify-all -closure-lifetime-fixup %s | %FileCheck %s +// RUN: %target-sil-opt -enable-sil-verify-all -sil-print-debuginfo -closure-lifetime-fixup %s | %FileCheck %s sil_stage raw @@ -261,16 +261,16 @@ bb3: // CHECK: [[STACK:%[^,]+]] = alloc_stack $Self // CHECK: try_apply undef() {{.*}}, normal [[SUCCESS_1:bb[0-9]+]], error [[FAILURE_1:bb[0-9]+]] // CHECK: [[SUCCESS_1]] -// CHECK: copy_addr [[INSTANCE]] to [init] [[STACK]] : $*Self +// CHECK: copy_addr [[INSTANCE]] to [init] [[STACK]] : $*Self, {{.*}} scope [[STACK_SCOPE:[0-9]+]] // CHECK: [[CLOSURE:%[^,]+]] = partial_apply [callee_guaranteed] [on_stack] undef([[STACK]]) // CHECK: [[DEPENDENCY:%[^,]+]] = mark_dependence [[CLOSURE]] {{.*}} on [[STACK]] // CHECK: try_apply undef([[DEPENDENCY]]) {{.*}}, normal [[SUCCESS_2:bb[0-9]+]], error [[FAILURE_2:bb[0-9]+]] // CHECK: [[SUCCESS_2]] // CHECK: dealloc_stack [[CLOSURE]] // CHECK: destroy_addr [[STACK]] -// CHECK: dealloc_stack [[STACK]] : $*Self +// CHECK: dealloc_stack [[STACK]] : $*Self, {{.*}} scope [[STACK_SCOPE]] // CHECK: [[FAILURE_1]] -// CHECK: dealloc_stack [[STACK]] +// CHECK: dealloc_stack [[STACK]] : $*Self, {{.*}} scope [[STACK_SCOPE]] // CHECK: throw // CHECK: [[FAILURE_2]] // CHECK-NOT: dealloc_stack diff --git a/test/Sema/availability_main_actor.swift b/test/Sema/availability_main_actor.swift new file mode 100644 index 0000000000000..5acf60b46c71f --- /dev/null +++ b/test/Sema/availability_main_actor.swift @@ -0,0 +1,20 @@ +// RUN: %target-typecheck-verify-swift + +// REQUIRES: concurrency + +// This test is meant to verify that a @MainActor constraint is accepted without +// any availability restrictions for all targets. + +@MainActor +struct AlwaysAvailable {} + +@MainActor(unsafe) +struct AlwaysAvailableUnsafe {} + +@available(SwiftStdlib 5.1, *) +@MainActor +struct AvailableSwift5_1 {} + +@available(SwiftStdlib 5.1, *) +@MainActor(unsafe) +struct AvailableSwift5_1Unsafe {} diff --git a/test/SymbolGraph/Module/DuplicateExportedImport.swift b/test/SymbolGraph/Module/DuplicateExportedImport.swift new file mode 100644 index 0000000000000..174cdc105ec60 --- /dev/null +++ b/test/SymbolGraph/Module/DuplicateExportedImport.swift @@ -0,0 +1,11 @@ +// RUN: %empty-directory(%t) +// RUN: %target-swift-frontend %S/Inputs/DuplicateExportedImport/A.swift -module-name A -emit-module -emit-module-path %t/A.swiftmodule +// RUN: %target-swift-frontend %s -module-name DuplicateExportedImport -emit-module -emit-module-path /dev/null -I %t -emit-symbol-graph -emit-symbol-graph-dir %t/ +// RUN: %FileCheck %s --input-file %t/DuplicateExportedImport.symbols.json + +// REQUIRES: asserts + +// CHECK-COUNT-1: "precise":"s:1A8ClassTwoC" + +@_exported import A +@_exported import class A.ClassTwo diff --git a/test/SymbolGraph/Module/Inputs/DuplicateExportedImport/A.swift b/test/SymbolGraph/Module/Inputs/DuplicateExportedImport/A.swift new file mode 100644 index 0000000000000..8733c3c56bed6 --- /dev/null +++ b/test/SymbolGraph/Module/Inputs/DuplicateExportedImport/A.swift @@ -0,0 +1,3 @@ +public class ClassOne {} + +public class ClassTwo {} diff --git a/test/stdlib/NSStringAPI.swift b/test/stdlib/NSStringAPI.swift index c29ca48ce2269..bff90e261f881 100644 --- a/test/stdlib/NSStringAPI.swift +++ b/test/stdlib/NSStringAPI.swift @@ -12,6 +12,9 @@ // Tests for the NSString APIs as exposed by String // +// Temporarily disabled as it is taking too long to execute. +// REQUIRES: rdar106755810 + import StdlibUnittest diff --git a/validation-test/ParseableInterface/unsafe-mainactor.swift b/validation-test/ParseableInterface/unsafe-mainactor.swift new file mode 100644 index 0000000000000..e1f23fec22330 --- /dev/null +++ b/validation-test/ParseableInterface/unsafe-mainactor.swift @@ -0,0 +1,14 @@ +// RUN: %empty-directory(%t) +// RUN: %target-swift-emit-module-interface(%t/Library.swiftinterface) %s -module-name Library +// RUN: %target-swift-typecheck-module-from-interface(%t/Library.swiftinterface) -module-name Library +// RUN: %FileCheck %s < %t/Library.swiftinterface + +// REQUIRES: OS=macosx + +import AppKit + +// CHECK: @objc @_inheritsConvenienceInitializers @_Concurrency.MainActor(unsafe) public class Subclass : AppKit.NSView { +public class Subclass: NSView { + // CHECK: @_Concurrency.MainActor(unsafe) @objc override dynamic public init(frame frameRect: Foundation.NSRect) + // CHECK: @_Concurrency.MainActor(unsafe) @objc required dynamic public init?(coder: Foundation.NSCoder) +}