diff --git a/include/swift/ABI/TaskStatus.h b/include/swift/ABI/TaskStatus.h index 9c75247f98b37..937fa128439f0 100644 --- a/include/swift/ABI/TaskStatus.h +++ b/include/swift/ABI/TaskStatus.h @@ -164,14 +164,21 @@ class ChildTaskStatusRecord : public TaskStatusRecord { /// and are only tracked by their respective `TaskGroupTaskStatusRecord`. class TaskGroupTaskStatusRecord : public TaskStatusRecord { AsyncTask *FirstChild; + AsyncTask *LastChild; public: TaskGroupTaskStatusRecord() - : TaskStatusRecord(TaskStatusRecordKind::TaskGroup), FirstChild(nullptr) { + : TaskStatusRecord(TaskStatusRecordKind::TaskGroup), + FirstChild(nullptr), + LastChild(nullptr) { } TaskGroupTaskStatusRecord(AsyncTask *child) - : TaskStatusRecord(TaskStatusRecordKind::TaskGroup), FirstChild(child) {} + : TaskStatusRecord(TaskStatusRecordKind::TaskGroup), + FirstChild(child), + LastChild(child) { + assert(!LastChild || !LastChild->childFragment()->getNextChild()); + } TaskGroup *getGroup() { return reinterpret_cast(this); } @@ -185,38 +192,28 @@ class TaskGroupTaskStatusRecord : public TaskStatusRecord { assert(child->hasGroupChildFragment()); assert(child->groupChildFragment()->getGroup() == getGroup()); + auto oldLastChild = LastChild; + LastChild = child; + if (!FirstChild) { // This is the first child we ever attach, so store it as FirstChild. FirstChild = child; return; } - // We need to traverse the siblings to find the last one and add the child - // there. - // FIXME: just set prepend to the current head, no need to traverse. - - auto cur = FirstChild; - while (cur) { - // no need to check hasChildFragment, all tasks we store here have them. - auto fragment = cur->childFragment(); - if (auto next = fragment->getNextChild()) { - cur = next; - } else { - // we're done searching and `cur` is the last - break; - } - } - - cur->childFragment()->setNextChild(child); + oldLastChild->childFragment()->setNextChild(child); } void detachChild(AsyncTask *child) { assert(child && "cannot remove a null child from group"); if (FirstChild == child) { FirstChild = getNextChildTask(child); + if (FirstChild == nullptr) { + LastChild = nullptr; + } return; } - + AsyncTask *prev = FirstChild; // Remove the child from the linked list, i.e.: // prev -> afterPrev -> afterChild @@ -230,6 +227,9 @@ class TaskGroupTaskStatusRecord : public TaskStatusRecord { if (afterPrev == child) { auto afterChild = getNextChildTask(child); prev->childFragment()->setNextChild(afterChild); + if (child == LastChild) { + LastChild = prev; + } return; } diff --git a/include/swift/AST/ActorIsolation.h b/include/swift/AST/ActorIsolation.h index 0f1707f0dc0da..142874452c222 100644 --- a/include/swift/AST/ActorIsolation.h +++ b/include/swift/AST/ActorIsolation.h @@ -109,6 +109,20 @@ class ActorIsolation { bool isIndependent() const { return kind == Independent; } + bool isActorIsolated() const { + switch (getKind()) { + case ActorInstance: + case DistributedActorInstance: + case GlobalActor: + case GlobalActorUnsafe: + return true; + + case Unspecified: + case Independent: + return false; + } + } + NominalTypeDecl *getActor() const { assert(getKind() == ActorInstance || getKind() == DistributedActorInstance); return actor; diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def index a61dd3bdc6890..5a0ce80bc1643 100644 --- a/include/swift/AST/DiagnosticsSema.def +++ b/include/swift/AST/DiagnosticsSema.def @@ -4475,10 +4475,6 @@ ERROR(global_actor_from_nonactor_context,none, "%0 %1 isolated to global actor %2 can not be %select{referenced|mutated|used 'inout'}4" " from %select{this|a non-isolated}3%select{| synchronous}5 context", (DescriptiveDeclKind, DeclName, Type, bool, unsigned, bool)) -ERROR(global_actor_from_initializing_expr,none, - "expression requiring global actor %0 cannot appear in " - "default-value expression of %1 %2", - (Type, DescriptiveDeclKind, DeclName)) ERROR(actor_isolated_call,none, "call to %0 function in a synchronous %1 context", (ActorIsolation, ActorIsolation)) diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index f3822b4418f72..eb0649a9a919d 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -8667,24 +8667,9 @@ ActorIsolation swift::getActorIsolationOfContext(DeclContext *dc) { if (auto *vd = dyn_cast_or_null(dc->getAsDecl())) return getActorIsolation(vd); - // In the context of the initializing or default-value expression of a - // stored property, the isolation varies between global and type members: - // - For a static stored property, the isolation matches the VarDecl. - // - For a field of a nominal type, the expression is not isolated. - // Without this distinction, a nominal can have non-async initializers - // with various kinds of isolation, so an impossible constraint can be - // created. See SE-0327 for details. - if (auto *var = dc->getNonLocalVarDecl()) { - - // Isolation officially changes, as described above, in Swift 6+ - if (dc->getASTContext().isSwiftVersionAtLeast(6) && - var->isInstanceMember() && - !var->getAttrs().hasAttribute()) { - return ActorIsolation::forUnspecified(); - } - + if (auto *var = dc->getNonLocalVarDecl()) return getActorIsolation(var); - } + if (auto *closure = dyn_cast(dc)) { switch (auto isolation = closure->getActorIsolation()) { diff --git a/lib/AST/GenericSignatureBuilder.cpp b/lib/AST/GenericSignatureBuilder.cpp index 9a09772a08d45..b982e140668fa 100644 --- a/lib/AST/GenericSignatureBuilder.cpp +++ b/lib/AST/GenericSignatureBuilder.cpp @@ -3988,8 +3988,16 @@ ConstraintResult GenericSignatureBuilder::expandConformanceRequirement( ProtocolDecl *proto, const RequirementSource *source, bool onlySameTypeConstraints) { - auto protocolSubMap = SubstitutionMap::getProtocolSubstitutions( - proto, selfType.getDependentType(*this), ProtocolConformanceRef(proto)); + auto selfTy = selfType.getDependentType(*this); + + auto subst = [&](Requirement req) -> Optional { + return req.subst( + [&](SubstitutableType *t) -> Type { + assert(isa(t)); + return selfTy; + }, + MakeAbstractConformanceForGenericType()); + }; // Use the requirement signature to avoid rewalking the entire protocol. This // cannot compute the requirement signature directly, because that may be @@ -4003,7 +4011,7 @@ ConstraintResult GenericSignatureBuilder::expandConformanceRequirement( if (onlySameTypeConstraints && req.getKind() != RequirementKind::SameType) continue; - auto substReq = req.subst(protocolSubMap); + auto substReq = subst(req); auto reqResult = substReq ? addRequirement(*substReq, innerSource, nullptr) : ConstraintResult::Conflicting; @@ -4032,8 +4040,9 @@ ConstraintResult GenericSignatureBuilder::expandConformanceRequirement( auto innerSource = FloatingRequirementSource::viaProtocolRequirement( source, proto, reqRepr->getSeparatorLoc(), /*inferred=*/false); - addRequirement(req, reqRepr, innerSource, - &protocolSubMap, nullptr); + + if (auto substReq = subst(req)) + addRequirement(*substReq, reqRepr, innerSource, nullptr); return false; }); @@ -4146,7 +4155,7 @@ ConstraintResult GenericSignatureBuilder::expandConformanceRequirement( source, proto, SourceLoc(), /*inferred=*/true); auto rawReq = Requirement(RequirementKind::SameType, firstType, secondType); - if (auto req = rawReq.subst(protocolSubMap)) + if (auto req = subst(rawReq)) addRequirement(*req, inferredSameTypeSource, proto->getParentModule()); }; @@ -4174,8 +4183,10 @@ ConstraintResult GenericSignatureBuilder::expandConformanceRequirement( auto innerSource = FloatingRequirementSource::viaProtocolRequirement( source, proto, reqRepr->getSeparatorLoc(), /*inferred=*/false); - addRequirement(req, reqRepr, innerSource, &protocolSubMap, - /*inferForModule=*/nullptr); + if (auto substReq = subst(req)) { + addRequirement(*substReq, reqRepr, innerSource, + /*inferForModule=*/nullptr); + } return false; }); @@ -5160,28 +5171,19 @@ ConstraintResult GenericSignatureBuilder::addRequirement(const Requirement &req, FloatingRequirementSource source, ModuleDecl *inferForModule) { - return addRequirement(req, nullptr, source, nullptr, inferForModule); + return addRequirement(req, nullptr, source, inferForModule); } ConstraintResult GenericSignatureBuilder::addRequirement(const Requirement &req, const RequirementRepr *reqRepr, FloatingRequirementSource source, - const SubstitutionMap *subMap, ModuleDecl *inferForModule) { - // Local substitution for types in the requirement. - auto subst = [&](Type t) { - if (subMap) - return t.subst(*subMap); - - return t; - }; - - auto firstType = subst(req.getFirstType()); + auto firstType = req.getFirstType(); switch (req.getKind()) { case RequirementKind::Superclass: case RequirementKind::Conformance: { - auto secondType = subst(req.getSecondType()); + auto secondType = req.getSecondType(); if (inferForModule) { inferRequirements(*inferForModule, firstType, @@ -5209,7 +5211,7 @@ GenericSignatureBuilder::addRequirement(const Requirement &req, } case RequirementKind::SameType: { - auto secondType = subst(req.getSecondType()); + auto secondType = req.getSecondType(); if (inferForModule) { inferRequirements(*inferForModule, firstType, @@ -8697,8 +8699,8 @@ InferredGenericSignatureRequest::evaluate( } } - builder.addRequirement(req, reqRepr, source, nullptr, - lookupDC->getParentModule()); + builder.addRequirement(req, reqRepr, source, + lookupDC->getParentModule()); return false; }; diff --git a/lib/AST/GenericSignatureBuilder.h b/lib/AST/GenericSignatureBuilder.h index 234237ced8fd4..1f24263547e2b 100644 --- a/lib/AST/GenericSignatureBuilder.h +++ b/lib/AST/GenericSignatureBuilder.h @@ -570,7 +570,6 @@ class GenericSignatureBuilder { ConstraintResult addRequirement(const Requirement &req, const RequirementRepr *reqRepr, FloatingRequirementSource source, - const SubstitutionMap *subMap, ModuleDecl *inferForModule); /// Add all of a generic signature's parameters and requirements. diff --git a/lib/AST/RequirementMachine/PropertyUnification.cpp b/lib/AST/RequirementMachine/PropertyUnification.cpp index 118e154e7f927..763f1dac7db82 100644 --- a/lib/AST/RequirementMachine/PropertyUnification.cpp +++ b/lib/AST/RequirementMachine/PropertyUnification.cpp @@ -491,9 +491,9 @@ void PropertyMap::concretizeNestedTypesFromConcreteParent( continue; } - // FIXME: Maybe this can happen if the concrete type is an - // opaque result type? - assert(!conformance.isAbstract()); + // This can happen if the concrete type is an opaque result type. + if (conformance.isAbstract()) + continue; auto *concrete = conformance.getConcrete(); diff --git a/lib/AST/TypeRepr.cpp b/lib/AST/TypeRepr.cpp index 4062e1fa66fc2..fbb49a5b32b1b 100644 --- a/lib/AST/TypeRepr.cpp +++ b/lib/AST/TypeRepr.cpp @@ -183,6 +183,8 @@ void AttributedTypeRepr::printAttrs(ASTPrinter &Printer, Printer.printSimpleAttr("@autoclosure") << " "; if (hasAttr(TAK_escaping)) Printer.printSimpleAttr("@escaping") << " "; + if (hasAttr(TAK_Sendable)) + Printer.printSimpleAttr("@Sendable") << " "; if (hasAttr(TAK_noDerivative)) Printer.printSimpleAttr("@noDerivative") << " "; diff --git a/lib/IRGen/MetadataRequest.cpp b/lib/IRGen/MetadataRequest.cpp index 9d56f89581dbd..b9ab33add2998 100644 --- a/lib/IRGen/MetadataRequest.cpp +++ b/lib/IRGen/MetadataRequest.cpp @@ -1670,8 +1670,12 @@ namespace { } auto layout = type.getExistentialLayout(); - - auto protocols = layout.getProtocols(); + + SmallVector protocols; + for (auto proto : layout.getProtocols()) { + if (!proto->getDecl()->isMarkerProtocol()) + protocols.push_back(proto); + } // Collect references to the protocol descriptors. auto descriptorArrayTy diff --git a/lib/SILGen/SILGenProlog.cpp b/lib/SILGen/SILGenProlog.cpp index 6b250c5bcfff9..8d81938b85511 100644 --- a/lib/SILGen/SILGenProlog.cpp +++ b/lib/SILGen/SILGenProlog.cpp @@ -314,7 +314,7 @@ struct ArgumentInitHelper { assert(type->isMaterializable()); ++ArgNo; - if (PD->hasName()) { + if (PD->hasName() || PD->isIsolated()) { makeArgumentIntoBinding(type, &*f.begin(), PD); return; } diff --git a/lib/Sema/MiscDiagnostics.cpp b/lib/Sema/MiscDiagnostics.cpp index a435e5f4f19e2..3c094519b527d 100644 --- a/lib/Sema/MiscDiagnostics.cpp +++ b/lib/Sema/MiscDiagnostics.cpp @@ -4717,31 +4717,43 @@ static void diagUnqualifiedAccessToMethodNamedSelf(const Expr *E, if (!E || isa(E) || !E->getType()) return {false, E}; - if (auto *declRefExpr = dyn_cast(E)) { - if (declRefExpr->getDecl()->getBaseName() == Ctx.Id_self && - declRefExpr->getType()->is()) { - if (auto typeContext = DC->getInnermostTypeContext()) { - // self() is not easily confusable - if (!isa(Parent.getAsExpr())) { - auto baseType = typeContext->getDeclaredInterfaceType(); - if (!baseType->getEnumOrBoundGenericEnum()) { - auto baseTypeString = baseType.getString(); - - Ctx.Diags.diagnose(E->getLoc(), diag::self_refers_to_method, - baseTypeString); - - Ctx.Diags - .diagnose(E->getLoc(), - diag::fix_unqualified_access_member_named_self, - baseTypeString) - .fixItInsert(E->getLoc(), diag::insert_type_qualification, - baseType); - } - } - } - } + auto *DRE = dyn_cast(E); + // If this is not an explicit 'self' reference, let's keep searching. + if (!DRE || DRE->isImplicit()) + return {true, E}; + + // If this not 'self' or it's not a function reference, it's unrelated. + if (!(DRE->getDecl()->getBaseName() == Ctx.Id_self && + DRE->getType()->is())) + return {true, E}; + + auto typeContext = DC->getInnermostTypeContext(); + // Use of 'self' in enums is not confusable. + if (!typeContext || typeContext->getSelfEnumDecl()) + return {true, E}; + + // self(...) is not easily confusable. + if (auto *parentExpr = Parent.getAsExpr()) { + if (isa(parentExpr)) + return {true, E}; + + // Explicit call to a static method 'self' of some type is not + // confusable. + if (isa(parentExpr) && !parentExpr->isImplicit()) + return {true, E}; } + auto baseType = typeContext->getDeclaredInterfaceType(); + auto baseTypeString = baseType.getString(); + + Ctx.Diags.diagnose(E->getLoc(), diag::self_refers_to_method, + baseTypeString); + + Ctx.Diags + .diagnose(E->getLoc(), diag::fix_unqualified_access_member_named_self, + baseTypeString) + .fixItInsert(E->getLoc(), diag::insert_type_qualification, baseType); + return {true, E}; } }; diff --git a/lib/Sema/TypeCheckConcurrency.cpp b/lib/Sema/TypeCheckConcurrency.cpp index 1632f7af40343..d3b8e26c6e001 100644 --- a/lib/Sema/TypeCheckConcurrency.cpp +++ b/lib/Sema/TypeCheckConcurrency.cpp @@ -1299,57 +1299,6 @@ namespace { return getDeclContext()->getParentModule(); } - /// In Swift 6, global-actor isolation is not carried-over to the - /// initializing expressions of non-static instance properties. - /// The actual change happens in \c getActorIsolationOfContext , - /// but this function exists to warn users of Swift 5 about this - /// isolation change, so that they can prepare ahead-of-time. - void warnAboutGlobalActorIsoChangeInSwift6(const ActorIsolation &reqIso, - const Expr *user) { - if (ctx.isSwiftVersionAtLeast(6)) - return; - - // Check our context stack for a PatternBindingInitializer environment. - DeclContext const* withinDC = nullptr; - for (auto dc = contextStack.rbegin(); dc != contextStack.rend(); dc++) { - if (isa(*dc)) { - withinDC = *dc; - break; - } - } - - // Not within a relevant decl context. - if (!withinDC) - return; - - // Check if this PatternBindingInitializer's isolation would change - // in Swift 6+ - if (auto *var = withinDC->getNonLocalVarDecl()) { - if (var->isInstanceMember() && - !var->getAttrs().hasAttribute()) { - // At this point, we know the isolation will change in Swift 6. - // So, let's check if that change will cause an error. - - auto dcIso = getActorIsolationOfContext( - const_cast(withinDC)); - - // If the isolation granted in Swift 5 is for a global actor, and - // the expression requires that global actor's isolation, then it will - // become an error in Swift 6. - if (dcIso.isGlobalActor() && dcIso == reqIso) { - ctx.Diags.diagnose(user->getLoc(), - diag::global_actor_from_initializing_expr, - reqIso.getGlobalActor(), - var->getDescriptiveKind(), var->getName()) - .highlight(user->getSourceRange()) - // make it a warning and attach the "this will become an error..." - // to the message. The error in Swift 6 will not be this diagnostic. - .warnUntilSwiftVersion(6); - } - } - } - } - /// Determine whether code in the given use context might execute /// concurrently with code in the definition context. bool mayExecuteConcurrentlyWith( @@ -2192,12 +2141,8 @@ namespace { // we are within that global actor already. Optional unsatisfiedIsolation; if (Type globalActor = fnType->getGlobalActor()) { - if (getContextIsolation().isGlobalActor() && - getContextIsolation().getGlobalActor()->isEqual(globalActor)) { - warnAboutGlobalActorIsoChangeInSwift6( - ActorIsolation::forGlobalActor(globalActor, false), - apply); - } else { + if (!(getContextIsolation().isGlobalActor() && + getContextIsolation().getGlobalActor()->isEqual(globalActor))) { unsatisfiedIsolation = ActorIsolation::forGlobalActor( globalActor, /*unsafe=*/false); } @@ -2333,8 +2278,6 @@ namespace { auto contextIsolation = getInnermostIsolatedContext(declContext); if (contextIsolation.isGlobalActor() && contextIsolation.getGlobalActor()->isEqual(globalActor)) { - - warnAboutGlobalActorIsoChangeInSwift6(contextIsolation, context); return false; } @@ -2860,6 +2803,21 @@ namespace { bool ActorIsolationChecker::mayExecuteConcurrentlyWith( const DeclContext *useContext, const DeclContext *defContext) { + // Fast path for when the use and definition contexts are the same. + if (useContext == defContext) + return false; + + // If both contexts are isolated to the same actor, then they will not + // execute concurrently. + auto useIsolation = getActorIsolationOfContext( + const_cast(useContext)); + if (useIsolation.isActorIsolated()) { + auto defIsolation = getActorIsolationOfContext( + const_cast(defContext)); + if (useIsolation == defIsolation) + return false; + } + // Walk the context chain from the use to the definition. while (useContext != defContext) { // If we find a concurrent closure... it can be run concurrently. diff --git a/stdlib/public/runtime/StackAllocator.h b/stdlib/public/runtime/StackAllocator.h index 13603354f2812..6fd6c0f541763 100644 --- a/stdlib/public/runtime/StackAllocator.h +++ b/stdlib/public/runtime/StackAllocator.h @@ -259,7 +259,10 @@ class StackAllocator { StackAllocator() : firstSlab(nullptr), firstSlabIsPreallocated(false) { } /// Construct a StackAllocator with a pre-allocated first slab. - StackAllocator(void *firstSlabBuffer, size_t bufferCapacity) { + StackAllocator(void *firstSlabBuffer, size_t bufferCapacity) : StackAllocator() { + // If the pre-allocated buffer can't hold a slab header, ignore it. + if (bufferCapacity <= Slab::headerSize()) + return; char *start = (char *)llvm::alignAddr(firstSlabBuffer, llvm::Align(alignment)); char *end = (char *)firstSlabBuffer + bufferCapacity; diff --git a/test/APIJSON/apigen.swift b/test/APIJSON/apigen.swift index 68ceefa5f993c..98e52a96609d4 100644 --- a/test/APIJSON/apigen.swift +++ b/test/APIJSON/apigen.swift @@ -1,6 +1,6 @@ // REQUIRES: objc_interop, OS=macosx // RUN: %empty-directory(%t) -// RUN: %target-swift-frontend %s -typecheck -emit-module-interface-path %t/MyModule.swiftinterface -enable-library-evolution -module-name MyModule -swift-version 5 +// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) %s -typecheck -emit-module-interface-path %t/MyModule.swiftinterface -enable-library-evolution -module-name MyModule -swift-version 5 // RUN: %target-swift-api-extract -o - -pretty-print %t/MyModule.swiftinterface -module-name MyModule -module-cache-path %t | %FileCheck %s import Foundation diff --git a/test/APIJSON/non-objc-class.swift b/test/APIJSON/non-objc-class.swift index 3ba94c0193e8c..f0accd014b3d7 100644 --- a/test/APIJSON/non-objc-class.swift +++ b/test/APIJSON/non-objc-class.swift @@ -1,6 +1,6 @@ // REQUIRES: objc_interop, OS=macosx // RUN: %empty-directory(%t) -// RUN: %target-swift-frontend %s -typecheck -emit-module-interface-path %t/MyModule.swiftinterface -enable-library-evolution -module-name MyModule -swift-version 5 +// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) %s -typecheck -emit-module-interface-path %t/MyModule.swiftinterface -enable-library-evolution -module-name MyModule -swift-version 5 // RUN: %target-swift-api-extract -o - -pretty-print %t/MyModule.swiftinterface -module-name MyModule -module-cache-path %t | %FileCheck %s import Foundation diff --git a/test/APIJSON/spi.swift b/test/APIJSON/spi.swift index 302757399da3b..294f26242b7f0 100644 --- a/test/APIJSON/spi.swift +++ b/test/APIJSON/spi.swift @@ -1,9 +1,9 @@ // REQUIRES: objc_interop, OS=macosx // RUN: %empty-directory(%t) -// RUN: %target-swift-frontend %s -typecheck -emit-module-interface-path %t/MyModule.swiftinterface -enable-library-evolution -module-name MyModule -swift-version 5 +// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) %s -typecheck -emit-module-interface-path %t/MyModule.swiftinterface -enable-library-evolution -module-name MyModule -swift-version 5 // RUN: %target-swift-api-extract -o - -pretty-print %t/MyModule.swiftinterface -module-name MyModule -module-cache-path %t | %FileCheck %s -// RUN: %target-swift-frontend %s -emit-module -emit-module-path %t/MyModule.swiftmodule -enable-library-evolution -module-name MyModule -swift-version 5 +// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) %s -emit-module -emit-module-path %t/MyModule.swiftmodule -enable-library-evolution -module-name MyModule -swift-version 5 // RUN: %target-swift-api-extract -o - -pretty-print %t/MyModule.swiftmodule -module-name MyModule -module-cache-path %t | %FileCheck %s --check-prefix=CHECK-SPI import Foundation diff --git a/test/Concurrency/actor_isolation.swift b/test/Concurrency/actor_isolation.swift index 8c016a4c3a2f1..2bbcc6536c370 100644 --- a/test/Concurrency/actor_isolation.swift +++ b/test/Concurrency/actor_isolation.swift @@ -979,31 +979,59 @@ actor MyServer : Server { // ---------------------------------------------------------------------- // @_inheritActorContext // ---------------------------------------------------------------------- +@available(SwiftStdlib 5.1, *) func acceptAsyncSendableClosure(_: @Sendable () async -> T) { } +@available(SwiftStdlib 5.1, *) func acceptAsyncSendableClosureInheriting(@_inheritActorContext _: @Sendable () async -> T) { } @available(SwiftStdlib 5.1, *) extension MyActor { func testSendableAndInheriting() { + var counter = 0 + acceptAsyncSendableClosure { - synchronous() // expected-error{{expression is 'async' but is not marked with 'await'}} + _ = synchronous() // expected-error{{expression is 'async' but is not marked with 'await'}} // expected-note@-1{{calls to instance method 'synchronous()' from outside of its actor context are implicitly asynchronous}} + + counter += 1 // expected-error{{mutation of captured var 'counter' in concurrently-executing code}} } acceptAsyncSendableClosure { - await synchronous() // ok + _ = await synchronous() // ok + counter += 1 // expected-error{{mutation of captured var 'counter' in concurrently-executing code}} } acceptAsyncSendableClosureInheriting { - synchronous() // okay + _ = synchronous() // okay + counter += 1 // okay } acceptAsyncSendableClosureInheriting { - await synchronous() // expected-warning{{no 'async' operations occur within 'await' expression}} + _ = await synchronous() // expected-warning{{no 'async' operations occur within 'await' expression}} + counter += 1 // okay } } } +@available(SwiftStdlib 5.1, *) +@SomeGlobalActor +func testGlobalActorInheritance() { + var counter = 0 + + acceptAsyncSendableClosure { + counter += 1 // expected-error{{mutation of captured var 'counter' in concurrently-executing code}} + } + + acceptAsyncSendableClosure { @SomeGlobalActor in + counter += 1 // ok + } + + + acceptAsyncSendableClosureInheriting { + counter += 1 // ok + } +} + @available(SwiftStdlib 5.1, *) @MainActor // expected-note {{'GloballyIsolatedProto' is isolated to global actor 'MainActor' here}} protocol GloballyIsolatedProto { diff --git a/test/Concurrency/global_actor_inference.swift b/test/Concurrency/global_actor_inference.swift index 6830543e02ced..d5d29200ed343 100644 --- a/test/Concurrency/global_actor_inference.swift +++ b/test/Concurrency/global_actor_inference.swift @@ -587,9 +587,9 @@ func replacesDynamicOnMainActor() { // ---------------------------------------------------------------------- class Cutter { - @MainActor var x = useFooInADefer() // expected-warning {{expression requiring global actor 'MainActor' cannot appear in default-value expression of property 'x'; this is an error in Swift 6}} + @MainActor var x = useFooInADefer() @MainActor var y = { () -> Bool in - var z = statefulThingy // expected-warning {{expression requiring global actor 'MainActor' cannot appear in default-value expression of property 'y'; this is an error in Swift 6}} + var z = statefulThingy return z }() } @@ -601,7 +601,7 @@ class Butter { nonisolated let b = statefulThingy // expected-error {{var 'statefulThingy' isolated to global actor 'MainActor' can not be referenced from a non-isolated synchronous context}} var c: Int = { - return getGlobal7() // expected-warning {{expression requiring global actor 'SomeGlobalActor' cannot appear in default-value expression of property 'c'; this is an error in Swift 6}} + return getGlobal7() }() lazy var d: Int = getGlobal7() diff --git a/test/Concurrency/property_initializers_swift6.swift b/test/Concurrency/property_initializers_swift6.swift index 14d39222ec481..4279ef6974876 100644 --- a/test/Concurrency/property_initializers_swift6.swift +++ b/test/Concurrency/property_initializers_swift6.swift @@ -3,17 +3,21 @@ // REQUIRES: asserts -@MainActor -func mainActorFn() -> Int { return 0 } // expected-note 2 {{calls to global function 'mainActorFn()' from outside of its actor context are implicitly asynchronous}} +@globalActor +actor GlobalActor { + static let shared = GlobalActor() +} + +@GlobalActor +func globalActorFn() -> Int { return 0 } // expected-note {{calls to global function 'globalActorFn()' from outside of its actor context are implicitly asynchronous}} -@MainActor +@GlobalActor class C { - var x: Int = mainActorFn() // expected-error {{call to main actor-isolated global function 'mainActorFn()' in a synchronous nonisolated context}} + var x: Int = globalActorFn() - lazy var y: Int = mainActorFn() + lazy var y: Int = globalActorFn() - static var z: Int = mainActorFn() + static var z: Int = globalActorFn() } -@MainActor -var x: Int = mainActorFn() // expected-error {{call to main actor-isolated global function 'mainActorFn()' in a synchronous nonisolated context}} +var x: Int = globalActorFn() // expected-error {{call to global actor 'GlobalActor'-isolated global function 'globalActorFn()' in a synchronous nonisolated context}} \ No newline at end of file diff --git a/test/Generics/opaque_archetype_concrete_requirement_recursive.swift b/test/Generics/opaque_archetype_concrete_requirement_recursive.swift new file mode 100644 index 0000000000000..69f057c7b323f --- /dev/null +++ b/test/Generics/opaque_archetype_concrete_requirement_recursive.swift @@ -0,0 +1,30 @@ +// RUN: %target-swift-frontend -emit-silgen %s -disable-availability-checking + +protocol P { + associatedtype T + + var t: T { get } +} + +protocol RecursiveP { + associatedtype T : RecursiveP +} + +struct S_RecursiveP : RecursiveP { + typealias T = S_RecursiveP +} + +struct DefinesRecursiveP : P { + var t: some RecursiveP { + return S_RecursiveP() + } +} + +protocol HasRecursiveP { + associatedtype T : RecursiveP +} + +extension HasRecursiveP where T == DefinesRecursiveP.T { + func checkSameType(_ t: T) -> DefinesRecursiveP.T { return t } +} + diff --git a/test/Generics/rdar89921930.swift b/test/Generics/rdar89921930.swift new file mode 100644 index 0000000000000..412de151ecbca --- /dev/null +++ b/test/Generics/rdar89921930.swift @@ -0,0 +1,16 @@ +// RUN: %target-swift-frontend -typecheck -verify %s + +// This used to hit a circularity. + +public protocol P {} + +public struct G {} + +public typealias A = G + +public protocol Circle { + associatedtype X : P + associatedtype Y where Y == A +} + + diff --git a/test/Generics/sr16040.swift b/test/Generics/sr16040.swift new file mode 100644 index 0000000000000..13521a4e7eabd --- /dev/null +++ b/test/Generics/sr16040.swift @@ -0,0 +1,40 @@ +// RUN: %target-swift-frontend -typecheck -verify %s -disable-availability-checking + +public protocol View { + associatedtype Body : View + var body: Body { get } +} + +public struct Text : View { + public init(_: String) {} + public var body: Self { return self } +} + +public protocol DisplayableValue {} + +public protocol SingleValueDisplay: View { + associatedtype DisplayedValue + init (_ singleValue: DisplayedValue) + var displayedValue: DisplayedValue { get } +} + +public protocol RawDisplayableValue: DisplayableValue { + associatedtype RawDisplay: SingleValueDisplay + where RawDisplay.DisplayedValue == Self +} + +public protocol RawTextDisplayableValue: RawDisplayableValue + where Self: CustomStringConvertible, + RawDisplay == RawTextDisplay { } + +public struct RawTextDisplay : SingleValueDisplay { + public var displayedValue: Value + + public init (_ singleValue: Value) { + self.displayedValue = singleValue + } + + public var body: some View { + Text(displayedValue.description) + } +} diff --git a/test/IRGen/marker_protocol_backdeploy.swift b/test/IRGen/marker_protocol_backdeploy.swift new file mode 100644 index 0000000000000..2e7f623dadf4a --- /dev/null +++ b/test/IRGen/marker_protocol_backdeploy.swift @@ -0,0 +1,34 @@ +// RUN: %target-swift-frontend -primary-file %s -target %target-cpu-apple-macosx10.15 -emit-ir -o - | %FileCheck %s + +// Marker protocols should have no ABI impact at all, so this source file checks +// for the absence of symbols related to marker protocols. + +// CHECK-NOT: $s26marker_protocol_backdeploy1PP +// CHECK-NOT: $s26marker_protocol_backdeploy1PMp + +// REQUIRES: PTRSIZE=64 +// REQUIRES: OS=macosx + +// Temporarily disable on arm (rdar://89910199) +// UNSUPPORTED: CPU=arm64, CPU=arm64e + +@_marker public protocol P { } +public protocol Q: P { } +protocol R { } + + +// Suppress marker protocols when forming existentials at runtime +public func takeAnyType(_: T.Type) { } + +// CHECK-LABEL: define {{.*}}@"$ss8Sendable_26marker_protocol_backdeploy1QAB1RpMa" +// CHECK: ss8Sendable_26marker_protocol_backdeploy1QAB1RpML +// CHECK-NOT: Sendable +// CHECK: s26marker_protocol_backdeploy1QMp +// CHECK-NOT: Sendable +// CHECK: s26marker_protocol_backdeploy1RMp +// CHECK-NOT: SENDABLE +// CHECK: swift_getExistentialTypeMetadata +public func passExistentialType() { + typealias Fn = (Sendable & P & Q & R) async -> Void + takeAnyType(Fn.self) +} diff --git a/test/ModuleInterface/concurrency.swift b/test/ModuleInterface/concurrency.swift index 4d9cf8b029d6e..ecee6e3d4f966 100644 --- a/test/ModuleInterface/concurrency.swift +++ b/test/ModuleInterface/concurrency.swift @@ -14,6 +14,11 @@ public func reasyncFn(_: () async -> ()) reasync { fatalError() } +@available(SwiftStdlib 5.5, *) +public func takesSendable( + _ block: @Sendable @escaping () async throws -> Void +) { } + // RUN: %target-typecheck-verify-swift -enable-experimental-concurrency -I %t #else @@ -29,3 +34,7 @@ func callFn() async { // CHECK: // swift-module-flags:{{.*}} -enable-experimental-concurrency // CHECK: public func fn() async // CHECK: public func reasyncFn(_: () async -> ()) reasync +// CHECK: public func takesSendable(_ block: @escaping @Sendable () async throws -> + +// RUN: %target-swift-frontend -typecheck -enable-library-evolution -enable-experimental-concurrency -emit-module-interface-path %t/Library.swiftinterface -DLIBRARY -module-name Library %s -module-interface-preserve-types-as-written +// RUN: %FileCheck %s <%t/Library.swiftinterface diff --git a/test/Parse/self_rebinding.swift b/test/Parse/self_rebinding.swift index 17cef308f34bb..4595f3a7a1b58 100644 --- a/test/Parse/self_rebinding.swift +++ b/test/Parse/self_rebinding.swift @@ -126,3 +126,8 @@ enum EnumCaseNamedSelf { self = EnumCaseNamedSelf.`self` // OK } } + +// rdar://90624344 - warning about `self` which cannot be fixed because it's located in implicitly generated code. +struct TestImplicitSelfUse : Codable { + let `self`: Int // Ok +} diff --git a/test/SILGen/isolated_parameters.swift b/test/SILGen/isolated_parameters.swift index 833d65ef85995..dc63c2ae2c85c 100644 --- a/test/SILGen/isolated_parameters.swift +++ b/test/SILGen/isolated_parameters.swift @@ -10,3 +10,17 @@ public actor A { // CHECK: sil{{.*}} [ossa] @$s4test13takesIsolatedyyAA1ACYiF @available(SwiftStdlib 5.1, *) public func takesIsolated(_: isolated A) { } + +@available(SwiftStdlib 5.1, *) +public func takeClosureWithIsolatedParam(body: (isolated A) async -> Void) { } + +// Emit the unnamed parameter when it's isolated, so that we can hop to it. +// CHECK-LABEL: sil private [ossa] @$s4test0A24ClosureWithIsolatedParamyyFyAA1ACYiYaXEfU_ : $@convention(thin) @async (@guaranteed A) +// CHECK: bb0(%0 : @guaranteed $A): +// CHECK: [[COPY:%.*]] = copy_value %0 : $A +// CHECK-NEXT: [[BORROW:%.*]] = begin_borrow [[COPY]] : $A +// CHECK-NEXT: hop_to_executor [[BORROW]] : $A +@available(SwiftStdlib 5.1, *) +public func testClosureWithIsolatedParam() { + takeClosureWithIsolatedParam { _ in } +} diff --git a/validation-test/Sema/SwiftUI/radar88971160.swift b/validation-test/Sema/SwiftUI/radar88971160.swift new file mode 100644 index 0000000000000..4f78c8b1bab6d --- /dev/null +++ b/validation-test/Sema/SwiftUI/radar88971160.swift @@ -0,0 +1,17 @@ +// RUN: %target-typecheck-verify-swift -target %target-cpu-apple-macosx10.15 -swift-version 5 +// REQUIRES: objc_interop +// REQUIRES: OS=macosx + +import SwiftUI + +@MainActor +class ContentState: ObservableObject { } + +struct SomeView: View { + @StateObject private var contentState = ContentState() + + var body: some View { + Text("Hello, world!") + } +} + diff --git a/validation-test/compiler_crashers_2_fixed/0159-rdar40009245.swift b/validation-test/compiler_crashers_2_fixed/0159-rdar40009245.swift index 9becb7b44a2a1..442d7928c0d1a 100644 --- a/validation-test/compiler_crashers_2_fixed/0159-rdar40009245.swift +++ b/validation-test/compiler_crashers_2_fixed/0159-rdar40009245.swift @@ -2,7 +2,6 @@ protocol P { associatedtype A : P where A.X == Self - // expected-error@-1{{'X' is not a member type of type 'Self.A'}} associatedtype X : P where P.A == Self // expected-error@-1{{associated type 'A' can only be used with a concrete type or generic parameter base}} }