diff --git a/include/swift/AST/Availability.h b/include/swift/AST/Availability.h index 6cdb09b250bff..b36f7c674c2a5 100644 --- a/include/swift/AST/Availability.h +++ b/include/swift/AST/Availability.h @@ -377,13 +377,6 @@ class AvailabilityInference { annotatedAvailableRangeForAttr(const SpecializeAttr *attr, ASTContext &ctx); }; -/// Given a declaration upon which an availability attribute would appear in -/// concrete syntax, return a declaration to which the parser -/// actually attaches the attribute in the abstract syntax tree. We use this -/// function to determine whether the concrete syntax already has an -/// availability attribute. -const Decl *abstractSyntaxDeclForAvailableAttribute(const Decl *D); - } // end namespace swift #endif diff --git a/include/swift/AST/TypeCheckRequests.h b/include/swift/AST/TypeCheckRequests.h index d035263fa78b0..cf65ce8111e18 100644 --- a/include/swift/AST/TypeCheckRequests.h +++ b/include/swift/AST/TypeCheckRequests.h @@ -63,7 +63,6 @@ class TypeAliasDecl; class TypeLoc; class Witness; class TypeResolution; -class TypeRefinementContext; struct TypeWitnessAndDecl; class ValueDecl; enum class OpaqueReadOwnership: uint8_t; @@ -4434,25 +4433,6 @@ class InitAccessorReferencedVariablesRequest bool isCached() const { return true; } }; -/// Expand the children of the type refinement context for the given -/// declaration. -class ExpandChildTypeRefinementContextsRequest - : public SimpleRequest { -public: - using SimpleRequest::SimpleRequest; - -private: - friend SimpleRequest; - - bool evaluate(Evaluator &evaluator, Decl *decl, - TypeRefinementContext *parentTRC) const; - -public: - bool isCached() const { return true; } -}; - #define SWIFT_TYPEID_ZONE TypeChecker #define SWIFT_TYPEID_HEADER "swift/AST/TypeCheckerTypeIDZone.def" #include "swift/Basic/DefineTypeIDZone.h" diff --git a/include/swift/AST/TypeCheckerTypeIDZone.def b/include/swift/AST/TypeCheckerTypeIDZone.def index 0d322e7501c01..e26034a3df926 100644 --- a/include/swift/AST/TypeCheckerTypeIDZone.def +++ b/include/swift/AST/TypeCheckerTypeIDZone.def @@ -506,6 +506,3 @@ SWIFT_REQUEST(TypeChecker, InitAccessorReferencedVariablesRequest, ArrayRef(DeclAttribute *, AccessorDecl *, ArrayRef), Cached, NoLocationInfo) -SWIFT_REQUEST(TypeChecker, ExpandChildTypeRefinementContextsRequest, - bool(Decl *, TypeRefinementContext *), - Cached, NoLocationInfo) diff --git a/include/swift/AST/TypeRefinementContext.h b/include/swift/AST/TypeRefinementContext.h index 22e78af500955..dbe492476b8b7 100644 --- a/include/swift/AST/TypeRefinementContext.h +++ b/include/swift/AST/TypeRefinementContext.h @@ -297,9 +297,6 @@ class TypeRefinementContext : public ASTAllocated { static StringRef getReasonName(Reason R); }; -void simple_display(llvm::raw_ostream &out, - const TypeRefinementContext *trc); - } // end namespace swift #endif diff --git a/lib/AST/Availability.cpp b/lib/AST/Availability.cpp index 38a0732da6133..eb233b0882e05 100644 --- a/lib/AST/Availability.cpp +++ b/lib/AST/Availability.cpp @@ -225,8 +225,6 @@ AvailabilityInference::attrForAnnotatedAvailableRange(const Decl *D, ASTContext &Ctx) { const AvailableAttr *bestAvailAttr = nullptr; - D = abstractSyntaxDeclForAvailableAttribute(D); - for (auto Attr : D->getAttrs()) { auto *AvailAttr = dyn_cast(Attr); if (AvailAttr == nullptr || !AvailAttr->Introduced.has_value() || @@ -751,31 +749,3 @@ ASTContext::getSwift5PlusAvailability(llvm::VersionTuple swiftVersion) { bool ASTContext::supportsVersionedAvailability() const { return minimumAvailableOSVersionForTriple(LangOpts.Target).has_value(); } - -const Decl * -swift::abstractSyntaxDeclForAvailableAttribute(const Decl *ConcreteSyntaxDecl) { - // This function needs to be kept in sync with its counterpart, - // concreteSyntaxDeclForAvailableAttribute(). - - if (auto *PBD = dyn_cast(ConcreteSyntaxDecl)) { - // Existing @available attributes in the AST are attached to VarDecls - // rather than PatternBindingDecls, so we return the first VarDecl for - // the pattern binding declaration. - // This is safe, even though there may be multiple VarDecls, because - // all parsed attribute that appear in the concrete syntax upon on the - // PatternBindingDecl are added to all of the VarDecls for the pattern - // binding. - for (auto index : range(PBD->getNumPatternEntries())) { - if (auto VD = PBD->getAnchoringVarDecl(index)) - return VD; - } - } else if (auto *ECD = dyn_cast(ConcreteSyntaxDecl)) { - // Similar to the PatternBindingDecl case above, we return the - // first EnumElementDecl. - if (auto *Elem = ECD->getFirstElement()) { - return Elem; - } - } - - return ConcreteSyntaxDecl; -} diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 72168b6a28080..44f15ea3d4246 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -2079,23 +2079,19 @@ bool VarDecl::isLayoutExposedToClients() const { if (!parent) return false; if (isStatic()) return false; - - auto nominalAccess = - parent->getFormalAccessScope(/*useDC=*/nullptr, - /*treatUsableFromInlineAsPublic=*/true); - if (!nominalAccess.isPublic()) return false; - - if (!parent->getAttrs().hasAttribute() && - !parent->getAttrs().hasAttribute()) - return false; - if (!hasStorage() && !getAttrs().hasAttribute() && !hasAttachedPropertyWrapper()) { return false; } - return true; + auto nominalAccess = + parent->getFormalAccessScope(/*useDC=*/nullptr, + /*treatUsableFromInlineAsPublic=*/true); + if (!nominalAccess.isPublic()) return false; + + return (parent->getAttrs().hasAttribute() || + parent->getAttrs().hasAttribute()); } /// Check whether the given type representation will be diff --git a/lib/AST/TypeRefinementContext.cpp b/lib/AST/TypeRefinementContext.cpp index cde3ebff744b2..99e84e26b6c55 100644 --- a/lib/AST/TypeRefinementContext.cpp +++ b/lib/AST/TypeRefinementContext.cpp @@ -20,7 +20,6 @@ #include "swift/AST/Stmt.h" #include "swift/AST/Expr.h" #include "swift/AST/SourceFile.h" -#include "swift/AST/TypeCheckRequests.h" #include "swift/AST/TypeRefinementContext.h" #include "swift/Basic/SourceManager.h" @@ -193,18 +192,6 @@ TypeRefinementContext::findMostRefinedSubContext(SourceLoc Loc, !rangeContainsTokenLocWithGeneratedSource(SM, SrcRange, Loc)) return nullptr; - // If this context is for a declaration, ensure that we've expanded the - // children of the declaration. - if (Node.getReason() == Reason::Decl || - Node.getReason() == Reason::DeclImplicit) { - if (auto decl = Node.getAsDecl()) { - ASTContext &ctx = decl->getASTContext(); - (void)evaluateOrDefault( - ctx.evaluator, ExpandChildTypeRefinementContextsRequest{decl, this}, - false); - } - } - // For the moment, we perform a linear search here, but we can and should // do something more efficient. for (TypeRefinementContext *Child : Children) { @@ -367,10 +354,6 @@ void TypeRefinementContext::print(raw_ostream &OS, SourceManager &SrcMgr, OS << "extension." << ED->getExtendedType().getString(); } else if (isa(D)) { OS << ""; - } else if (auto PBD = dyn_cast(D)) { - if (auto VD = PBD->getAnchoringVarDecl(0)) { - OS << VD->getName(); - } } } @@ -428,8 +411,3 @@ StringRef TypeRefinementContext::getReasonName(Reason R) { llvm_unreachable("Unhandled Reason in switch."); } - -void swift::simple_display( - llvm::raw_ostream &out, const TypeRefinementContext *trc) { - out << "TRC @" << trc; -} diff --git a/lib/Sema/TypeCheckAvailability.cpp b/lib/Sema/TypeCheckAvailability.cpp index 37b8e0b321e15..07a9579331577 100644 --- a/lib/Sema/TypeCheckAvailability.cpp +++ b/lib/Sema/TypeCheckAvailability.cpp @@ -308,8 +308,6 @@ ExportContext::getExportabilityReason() const { /// on the target platform. static const AvailableAttr *getActiveAvailableAttribute(const Decl *D, ASTContext &AC) { - D = abstractSyntaxDeclForAvailableAttribute(D); - for (auto Attr : D->getAttrs()) if (auto AvAttr = dyn_cast(Attr)) { if (!AvAttr->isInvalid() && AvAttr->isActivePlatform(AC)) { @@ -390,6 +388,20 @@ class TypeRefinementContextBuilder : private ASTWalker { }; std::vector DeclBodyContextStack; + /// A mapping from abstract storage declarations with accessors to + /// to the type refinement contexts for those declarations. We refer to + /// this map to determine the appropriate parent TRC to use when + /// walking the accessor function. + llvm::DenseMap + StorageContexts; + + /// A mapping from pattern binding storage declarations to the type refinement + /// contexts for those declarations. We refer to this map to determine the + /// appropriate parent TRC to use when walking a var decl that belongs to a + /// pattern containing multiple vars. + llvm::DenseMap + PatternBindingContexts; + TypeRefinementContext *getCurrentTRC() { return ContextStack.back().TRC; } @@ -428,8 +440,6 @@ class TypeRefinementContextBuilder : private ASTWalker { return "building type refinement context for"; } - friend class swift::ExpandChildTypeRefinementContextsRequest; - public: TypeRefinementContextBuilder(TypeRefinementContext *TRC, ASTContext &Context) : Context(Context) { @@ -470,9 +480,19 @@ class TypeRefinementContextBuilder : private ASTWalker { PreWalkAction walkToDeclPre(Decl *D) override { PrettyStackTraceDecl trace(stackTraceAction(), D); + // Adds in a parent TRC for decls which are syntactically nested but are not + // represented that way in the AST. (Particularly, AbstractStorageDecl + // parents for AccessorDecl children.) + if (auto ParentTRC = getEffectiveParentContextForDecl(D)) { + pushContext(ParentTRC, D); + } + // Adds in a TRC that covers the entire declaration. if (auto DeclTRC = getNewContextForSignatureOfDecl(D)) { pushContext(DeclTRC, D); + + // Possibly use this as an effective parent context later. + recordEffectiveParentContext(D, DeclTRC); } // Create TRCs that cover only the body of the declaration. @@ -493,13 +513,53 @@ class TypeRefinementContextBuilder : private ASTWalker { return Action::Continue(); } + TypeRefinementContext *getEffectiveParentContextForDecl(Decl *D) { + // FIXME: Can we assert that we won't walk parent decls later that should + // have been returned here? + if (auto *accessor = dyn_cast(D)) { + // Use TRC of the storage rather the current TRC when walking this + // function. + auto it = StorageContexts.find(accessor->getStorage()); + if (it != StorageContexts.end()) { + return it->second; + } + } else if (auto *VD = dyn_cast(D)) { + // Use the TRC of the pattern binding decl as the parent for var decls. + if (auto *PBD = VD->getParentPatternBinding()) { + auto it = PatternBindingContexts.find(PBD); + if (it != PatternBindingContexts.end()) { + return it->second; + } + } + } + + return nullptr; + } + + /// If necessary, records a TRC so it can be returned by subsequent calls to + /// `getEffectiveParentContextForDecl()`. + void recordEffectiveParentContext(Decl *D, TypeRefinementContext *NewTRC) { + if (auto *StorageDecl = dyn_cast(D)) { + // Stash the TRC for the storage declaration to use as the parent of + // accessor decls later. + if (StorageDecl->hasParsedAccessors()) + StorageContexts[StorageDecl] = NewTRC; + } + + if (auto *VD = dyn_cast(D)) { + // Stash the TRC for the var decl if its parent pattern binding decl has + // more than one entry so that the sibling var decls can reuse it. + if (auto *PBD = VD->getParentPatternBinding()) { + if (PBD->getNumPatternEntries() > 1) + PatternBindingContexts[PBD] = NewTRC; + } + } + } + /// Returns a new context to be introduced for the declaration, or nullptr /// if no new context should be introduced. TypeRefinementContext *getNewContextForSignatureOfDecl(Decl *D) { - if (!isa(D) && - !isa(D) && - !isa(D) && - !isa(D)) + if (!isa(D) && !isa(D) && !isa(D)) return nullptr; // Only introduce for an AbstractStorageDecl if it is not local. We @@ -508,17 +568,19 @@ class TypeRefinementContextBuilder : private ASTWalker { if (isa(D) && D->getDeclContext()->isLocalContext()) return nullptr; - // Don't introduce for variable declarations that have a parent pattern - // binding; all of the relevant information is on the pattern binding. - if (auto var = dyn_cast(D)) { - if (var->getParentPatternBinding()) - return nullptr; - } - // Ignore implicit declarations (mainly skips over `DeferStmt` functions). if (D->isImplicit()) return nullptr; + // Skip introducing additional contexts for var decls past the first in a + // pattern. The context necessary for the pattern as a whole was already + // introduced if necessary by the first var decl. + if (auto *VD = dyn_cast(D)) { + if (auto *PBD = VD->getParentPatternBinding()) + if (VD != PBD->getAnchoringVarDecl(0)) + return nullptr; + } + // Declarations with an explicit availability attribute always get a TRC. if (hasActiveAvailableAttribute(D, Context)) { AvailabilityContext DeclaredAvailability = @@ -535,17 +597,11 @@ class TypeRefinementContextBuilder : private ASTWalker { // internal property in a public struct can be effectively less available // than the containing struct decl because the internal property will only // be accessed by code running at the deployment target or later. - // - // For declarations that have their child construction delayed, always - // create this implicit declaration context. It will be used to trigger - // lazy creation of the child TRCs. AvailabilityContext CurrentAvailability = getCurrentTRC()->getAvailabilityInfo(); AvailabilityContext EffectiveAvailability = getEffectiveAvailabilityForDeclSignature(D, CurrentAvailability); - if ((isa(D) && - refinementSourceRangeForDecl(D).isValid()) || - CurrentAvailability.isSupersetOf(EffectiveAvailability)) + if (CurrentAvailability.isSupersetOf(EffectiveAvailability)) return TypeRefinementContext::createForDeclImplicit( Context, D, getCurrentTRC(), EffectiveAvailability, refinementSourceRangeForDecl(D)); @@ -620,6 +676,19 @@ class TypeRefinementContextBuilder : private ASTWalker { // the bodies of its accessors. SourceRange Range = storageDecl->getSourceRange(); + // For a variable declaration (without accessors) we use the range of the + // containing pattern binding declaration to make sure that we include + // any type annotation in the type refinement context range. We also + // need to include any attached property wrappers. + if (auto *varDecl = dyn_cast(storageDecl)) { + if (auto *PBD = varDecl->getParentPatternBinding()) + Range = PBD->getSourceRange(); + + for (auto *propertyWrapper : varDecl->getAttachedPropertyWrappers()) { + Range.widen(propertyWrapper->getRange()); + } + } + // HACK: For synthesized trivial accessors we may have not a valid // location for the end of the braces, so in that case we will fall back // to using the range for the storage declaration. The right fix here is @@ -627,95 +696,38 @@ class TypeRefinementContextBuilder : private ASTWalker { // locations and have callers of that method provide appropriate source // locations. SourceRange BracesRange = storageDecl->getBracesRange(); - if (BracesRange.isValid()) { + if (storageDecl->hasParsedAccessors() && BracesRange.isValid()) { Range.widen(BracesRange); } return Range; } - - // For pattern binding declarations, include the attributes in the source - // range so that we're sure to cover any property wrappers. - if (auto patternBinding = dyn_cast(D)) { - return D->getSourceRangeIncludingAttrs(); - } - + return D->getSourceRange(); } - // Creates an implicit decl TRC specifying the deployment - // target for `range` in decl `D`. - TypeRefinementContext * - createImplicitDeclContextForDeploymentTarget(Decl *D, SourceRange range){ - AvailabilityContext Availability = - AvailabilityContext::forDeploymentTarget(Context); - Availability.intersectWith(getCurrentTRC()->getAvailabilityInfo()); - - return TypeRefinementContext::createForDeclImplicit( - Context, D, getCurrentTRC(), Availability, range); - } - - /// Build contexts for a pattern binding declaration. - void buildContextsForPatternBindingDecl(PatternBindingDecl *pattern) { - // Build contexts for each of the pattern entries. - for (unsigned index : range(pattern->getNumPatternEntries())) { - auto var = pattern->getAnchoringVarDecl(index); - if (!var) - continue; - - // Var decls may have associated pattern binding decls or property wrappers - // with init expressions. Those expressions need to be constrained to the - // deployment target unless they are exposed to clients. - if (!var->hasInitialValue() || var->isInitExposedToClients()) - continue; - - auto *initExpr = pattern->getInit(index); - if (initExpr && !initExpr->isImplicit()) { - assert(initExpr->getSourceRange().isValid()); - - // Create a TRC for the init written in the source. The ASTWalker - // won't visit these expressions so instead of pushing these onto the - // stack we build them directly. - auto *initTRC = createImplicitDeclContextForDeploymentTarget( - var, initExpr->getSourceRange()); - TypeRefinementContextBuilder(initTRC, Context).build(initExpr); - } - } - - // Ideally any init expression would be returned by `getInit()` above. - // However, for property wrappers it doesn't get populated until - // typechecking completes (which is too late). Instead, we find the - // the property wrapper attribute and use its source range to create a - // TRC for the initializer expression. - // - // FIXME: Since we don't have an expression here, we can't build out its - // TRC. If the Expr that will eventually be created contains a closure - // expression, then it might have AST nodes that need to be refined. For - // example, property wrapper initializers that takes block arguments - // are not handled correctly because of this (rdar://77841331). - if (auto firstVar = pattern->getAnchoringVarDecl(0)) { - if (firstVar->hasInitialValue() && !firstVar->isInitExposedToClients()) { - for (auto *wrapper : firstVar->getAttachedPropertyWrappers()) { - createImplicitDeclContextForDeploymentTarget( - firstVar, wrapper->getRange()); - } - } - } - } - void buildContextsForBodyOfDecl(Decl *D) { // Are we already constrained by the deployment target? If not, adding // new contexts won't change availability. if (isCurrentTRCContainedByDeploymentTarget()) return; + // A lambda that creates an implicit decl TRC specifying the deployment + // target for `range` in decl `D`. + auto createContext = [this](Decl *D, SourceRange range) { + AvailabilityContext Availability = + AvailabilityContext::forDeploymentTarget(Context); + Availability.intersectWith(getCurrentTRC()->getAvailabilityInfo()); + + return TypeRefinementContext::createForDeclImplicit( + Context, D, getCurrentTRC(), Availability, range); + }; + // Top level code always uses the deployment target. if (auto tlcd = dyn_cast(D)) { if (auto bodyStmt = tlcd->getBody()) { - pushDeclBodyContext( - createImplicitDeclContextForDeploymentTarget( - tlcd, tlcd->getSourceRange()), - tlcd, bodyStmt); + pushDeclBodyContext(createContext(tlcd, tlcd->getSourceRange()), tlcd, + bodyStmt); } return; } @@ -726,14 +738,51 @@ class TypeRefinementContextBuilder : private ASTWalker { if (!afd->isImplicit() && afd->getResilienceExpansion() != ResilienceExpansion::Minimal) { if (auto body = afd->getBody(/*canSynthesize*/ false)) { - pushDeclBodyContext( - createImplicitDeclContextForDeploymentTarget( - afd, afd->getBodySourceRange()), - afd, body); + pushDeclBodyContext(createContext(afd, afd->getBodySourceRange()), + afd, body); } } return; } + + // Var decls may have associated pattern binding decls or property wrappers + // with init expressions. Those expressions need to be constrained to the + // deployment target unless they are exposed to clients. + if (auto vd = dyn_cast(D)) { + if (!vd->hasInitialValue() || vd->isInitExposedToClients()) + return; + + if (auto *pbd = vd->getParentPatternBinding()) { + int idx = pbd->getPatternEntryIndexForVarDecl(vd); + auto *initExpr = pbd->getInit(idx); + if (initExpr && !initExpr->isImplicit()) { + assert(initExpr->getSourceRange().isValid()); + + // Create a TRC for the init written in the source. The ASTWalker + // won't visit these expressions so instead of pushing these onto the + // stack we build them directly. + auto *initTRC = createContext(vd, initExpr->getSourceRange()); + TypeRefinementContextBuilder(initTRC, Context).build(initExpr); + } + + // Ideally any init expression would be returned by `getInit()` above. + // However, for property wrappers it doesn't get populated until + // typechecking completes (which is too late). Instead, we find the + // the property wrapper attribute and use its source range to create a + // TRC for the initializer expression. + // + // FIXME: Since we don't have an expression here, we can't build out its + // TRC. If the Expr that will eventually be created contains a closure + // expression, then it might have AST nodes that need to be refined. For + // example, property wrapper initializers that takes block arguments + // are not handled correctly because of this (rdar://77841331). + for (auto *wrapper : vd->getAttachedPropertyWrappers()) { + createContext(vd, wrapper->getRange()); + } + } + + return; + } } PreWalkResult walkToStmtPre(Stmt *S) override { @@ -1225,25 +1274,6 @@ TypeChecker::getOrBuildTypeRefinementContext(SourceFile *SF) { return TRC; } -bool ExpandChildTypeRefinementContextsRequest::evaluate( - Evaluator &evaluator, Decl *decl, TypeRefinementContext *parentTRC -) const { - // If the parent TRC is already contained by the deployment target, there's - // nothing more to do. - ASTContext &ctx = decl->getASTContext(); - if (computeContainedByDeploymentTarget(parentTRC, ctx)) - return false; - - // Pattern binding declarations can have children corresponding to property - // wrappers and the initial values provided in each pattern binding entry. - if (auto *binding = dyn_cast(decl)) { - TypeRefinementContextBuilder builder(parentTRC, ctx); - builder.buildContextsForPatternBindingDecl(binding); - } - - return false; -} - AvailabilityContext TypeChecker::overApproximateAvailabilityAtLocation(SourceLoc loc, const DeclContext *DC, @@ -1578,6 +1608,38 @@ concreteSyntaxDeclForAvailableAttribute(const Decl *AbstractSyntaxDecl) { return AbstractSyntaxDecl; } +/// Given a declaration upon which an availability attribute would appear in +/// concrete syntax, return a declaration to which the parser +/// actually attaches the attribute in the abstract syntax tree. We use this +/// function to determine whether the concrete syntax already has an +/// availability attribute. +static const Decl * +abstractSyntaxDeclForAvailableAttribute(const Decl *ConcreteSyntaxDecl) { + // This function needs to be kept in sync with its counterpart, + // concreteSyntaxDeclForAvailableAttribute(). + + if (auto *PBD = dyn_cast(ConcreteSyntaxDecl)) { + // Existing @available attributes in the AST are attached to VarDecls + // rather than PatternBindingDecls, so we return the first VarDecl for + // the pattern binding declaration. + // This is safe, even though there may be multiple VarDecls, because + // all parsed attribute that appear in the concrete syntax upon on the + // PatternBindingDecl are added to all of the VarDecls for the pattern + // binding. + if (PBD->getNumPatternEntries() != 0) { + return PBD->getAnchoringVarDecl(0); + } + } else if (auto *ECD = dyn_cast(ConcreteSyntaxDecl)) { + // Similar to the PatternBindingDecl case above, we return the + // first EnumElementDecl. + if (auto *Elem = ECD->getFirstElement()) { + return Elem; + } + } + + return ConcreteSyntaxDecl; +} + /// Given a declaration, return a better related declaration for which /// to suggest an @available fixit, or the original declaration /// if no such related declaration exists. diff --git a/test/Sema/availability_versions.swift b/test/Sema/availability_versions.swift index da27f7b9b695e..7618d2943bf86 100644 --- a/test/Sema/availability_versions.swift +++ b/test/Sema/availability_versions.swift @@ -1741,25 +1741,3 @@ func useHasUnavailableExtension(_ s: HasUnavailableExtension) { s.inheritsUnavailable() // expected-error {{'inheritsUnavailable()' is unavailable in macOS}} s.moreAvailableButStillUnavailable() // expected-error {{'moreAvailableButStillUnavailable()' is unavailable in macOS}} } - -@available(macOS 10.15, *) -func f() -> Int { 17 } - -class StoredPropertiesWithAvailabilityInClosures { - private static let value: Int = { - if #available(macOS 10.15, *) { - return f() - } - - return 0 - }() - - @available(macOS 10.14, *) - private static let otherValue: Int = { - if #available(macOS 10.15, *) { - return f() - } - - return 0 - }() -} diff --git a/test/stdlib/Observation/Inputs/ObservableClass.swift b/test/stdlib/Observation/Inputs/ObservableClass.swift deleted file mode 100644 index 16819bdada192..0000000000000 --- a/test/stdlib/Observation/Inputs/ObservableClass.swift +++ /dev/null @@ -1,7 +0,0 @@ -import Foundation -import Observation - -@available(SwiftStdlib 5.9, *) -@Observable final public class ObservableClass { - public var state: State = .unused -} diff --git a/test/stdlib/Observation/ObservableAvailabilityCycle.swift b/test/stdlib/Observation/ObservableAvailabilityCycle.swift deleted file mode 100644 index 7343740f2b259..0000000000000 --- a/test/stdlib/Observation/ObservableAvailabilityCycle.swift +++ /dev/null @@ -1,19 +0,0 @@ -// REQUIRES: swift_swift_parser - -// RUN: %target-swift-frontend -typecheck -parse-as-library -enable-experimental-feature InitAccessors -external-plugin-path %swift-host-lib-dir/plugins#%swift-plugin-server -primary-file %s %S/Inputs/ObservableClass.swift - -// RUN: %target-swift-frontend -typecheck -parse-as-library -enable-experimental-feature InitAccessors -external-plugin-path %swift-host-lib-dir/plugins#%swift-plugin-server %s -primary-file %S/Inputs/ObservableClass.swift - -// REQUIRES: observation -// REQUIRES: concurrency -// REQUIRES: objc_interop -// UNSUPPORTED: use_os_stdlib -// UNSUPPORTED: back_deployment_runtime - -@available(SwiftStdlib 5.9, *) -extension ObservableClass { - @frozen public enum State: Sendable { - case unused - case used - } -}