diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h index 026dce1948458..592d4dca350a1 100644 --- a/include/swift/AST/Decl.h +++ b/include/swift/AST/Decl.h @@ -5908,7 +5908,7 @@ class AbstractStorageDecl : public ValueDecl { friend class SetterAccessLevelRequest; friend class IsGetterMutatingRequest; friend class IsSetterMutatingRequest; - friend class OpaqueReadOwnershipRequest; + friend class DirectOpaqueReadOwnershipRequest; friend class StorageImplInfoRequest; friend class RequiresOpaqueAccessorsRequest; friend class RequiresOpaqueModifyCoroutineRequest; @@ -6254,9 +6254,7 @@ class AbstractStorageDecl : public ValueDecl { bool requiresOpaqueAccessor(AccessorKind kind) const; /// Does this storage require a 'get' accessor in its opaque-accessors set? - bool requiresOpaqueGetter() const { - return getOpaqueReadOwnership() != OpaqueReadOwnership::Borrowed; - } + bool requiresOpaqueGetter() const; /// Does this storage require a '_read' accessor in its opaque-accessors set? bool requiresOpaqueReadCoroutine() const; @@ -6275,10 +6273,9 @@ class AbstractStorageDecl : public ValueDecl { /// set? bool requiresOpaqueModify2Coroutine() const; - /// Given that CoroutineAccessors is enabled, is _read/_modify required for - /// ABI stability? - bool requiresCorrespondingUnderscoredCoroutineAccessor( - AccessorKind kind, AccessorDecl const *decl = nullptr) const; + /// Given that CoroutineAccessors is enabled, are the accessors still + /// required that would have been emitted when its not? + bool requiresAccessorsForABICompatibilityWithPreCoroutineAccessors() const; /// Does this storage have any explicit observers (willSet or didSet) attached /// to it? diff --git a/include/swift/AST/TypeCheckRequests.h b/include/swift/AST/TypeCheckRequests.h index 928484825f3b1..2842ebedda42e 100644 --- a/include/swift/AST/TypeCheckRequests.h +++ b/include/swift/AST/TypeCheckRequests.h @@ -1750,10 +1750,10 @@ class IsSetterMutatingRequest : }; /// Request whether reading the storage yields a borrowed value. -class OpaqueReadOwnershipRequest : - public SimpleRequest { +class DirectOpaqueReadOwnershipRequest + : public SimpleRequest { public: using SimpleRequest::SimpleRequest; diff --git a/include/swift/AST/TypeCheckerTypeIDZone.def b/include/swift/AST/TypeCheckerTypeIDZone.def index 3e6d7dbc18baf..6988bfcd1b1f6 100644 --- a/include/swift/AST/TypeCheckerTypeIDZone.def +++ b/include/swift/AST/TypeCheckerTypeIDZone.def @@ -255,7 +255,7 @@ SWIFT_REQUEST(TypeChecker, EnumElementExprPatternRequest, SWIFT_REQUEST(TypeChecker, ResolvePatternRequest, Pattern *(Pattern *, DeclContext *, bool), Cached, NoLocationInfo) -SWIFT_REQUEST(TypeChecker, OpaqueReadOwnershipRequest, +SWIFT_REQUEST(TypeChecker, DirectOpaqueReadOwnershipRequest, OpaqueReadOwnership(AbstractStorageDecl *), SeparatelyCached, NoLocationInfo) SWIFT_REQUEST(TypeChecker, OpaqueResultTypeRequest, diff --git a/lib/AST/ASTPrinter.cpp b/lib/AST/ASTPrinter.cpp index 98c4db743f140..61fc49fca0cd6 100644 --- a/lib/AST/ASTPrinter.cpp +++ b/lib/AST/ASTPrinter.cpp @@ -2672,6 +2672,10 @@ void PrintAST::printAccessors(const AbstractStorageDecl *ASD) { Options.SuppressCoroutineAccessors) { AddAccessorToPrint(AccessorKind::Read); } + if (ASD->getAccessor(AccessorKind::Get) && + Options.SuppressCoroutineAccessors) { + AddAccessorToPrint(AccessorKind::Get); + } AddAccessorToPrint(AccessorKind::Read2); break; case ReadImplKind::Borrow: diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 18712bf1b96b6..fe3c307b48f4c 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -3250,14 +3250,10 @@ static AccessStrategy getOpaqueReadAccessStrategy( ResilienceExpansion expansion, std::optional> location, bool useOldABI) { - if (useOldABI) { - assert(storage->requiresOpaqueRead2Coroutine()); - assert(storage->requiresOpaqueReadCoroutine()); - return AccessStrategy::getAccessor(AccessorKind::Read, dispatch); - } if (storage->requiresOpaqueRead2Coroutine() && mayReferenceUseCoroutineAccessorOnStorage(module, expansion, location, - storage)) + storage) && + !useOldABI) return AccessStrategy::getAccessor(AccessorKind::Read2, dispatch); if (storage->requiresOpaqueReadCoroutine()) return AccessStrategy::getAccessor(AccessorKind::Read, dispatch); @@ -3276,14 +3272,10 @@ static AccessStrategy getOpaqueReadWriteAccessStrategy( ResilienceExpansion expansion, std::optional> location, bool useOldABI) { - if (useOldABI) { - assert(storage->requiresOpaqueModify2Coroutine()); - assert(storage->requiresOpaqueModifyCoroutine()); - return AccessStrategy::getAccessor(AccessorKind::Modify, dispatch); - } if (storage->requiresOpaqueModify2Coroutine() && mayReferenceUseCoroutineAccessorOnStorage(module, expansion, location, - storage)) + storage) && + !useOldABI) return AccessStrategy::getAccessor(AccessorKind::Modify2, dispatch); if (storage->requiresOpaqueModifyCoroutine()) return AccessStrategy::getAccessor(AccessorKind::Modify, dispatch); @@ -3440,17 +3432,23 @@ bool AbstractStorageDecl::requiresOpaqueSetter() const { return true; } +bool AbstractStorageDecl::requiresOpaqueGetter() const { + return getOpaqueReadOwnership() != OpaqueReadOwnership::Borrowed; +} + bool AbstractStorageDecl::requiresOpaqueReadCoroutine() const { ASTContext &ctx = getASTContext(); - if (ctx.LangOpts.hasFeature(Feature::CoroutineAccessors)) - return requiresCorrespondingUnderscoredCoroutineAccessor( - AccessorKind::Read2); + if (ctx.LangOpts.hasFeature(Feature::CoroutineAccessors) && + !requiresAccessorsForABICompatibilityWithPreCoroutineAccessors()) { + return false; + } // If a borrow accessor is present, we don't need a read coroutine. if (getAccessor(AccessorKind::Borrow)) { return false; } - return getOpaqueReadOwnership() != OpaqueReadOwnership::Owned; + + return getOpaqueReadOwnership() == OpaqueReadOwnership::Borrowed; } bool AbstractStorageDecl::requiresOpaqueRead2Coroutine() const { @@ -3722,10 +3720,25 @@ AbstractStorageDecl::mutabilityInSwift( return mutability(useDC, base); } +static OpaqueReadOwnership +getDirectOpaqueReadOwnership(AbstractStorageDecl const *self) { + ASTContext &ctx = self->getASTContext(); + return evaluateOrDefault( + ctx.evaluator, + DirectOpaqueReadOwnershipRequest{const_cast(self)}, + {}); +} + OpaqueReadOwnership AbstractStorageDecl::getOpaqueReadOwnership() const { - ASTContext &ctx = getASTContext(); - return evaluateOrDefault(ctx.evaluator, - OpaqueReadOwnershipRequest{const_cast(this)}, {}); + auto *root = this; + while (true) { + auto *super = root->getOverriddenDecl(); + if (!super) + break; + root = super; + } + + return getDirectOpaqueReadOwnership(root); } bool ValueDecl::isInstanceMember() const { @@ -11342,8 +11355,8 @@ bool AccessorDecl::isRequirementWithSynthesizedDefaultImplementation() const { if (!requiresNewWitnessTableEntry()) { return false; } - return getStorage()->requiresCorrespondingUnderscoredCoroutineAccessor( - getAccessorKind(), this); + return getStorage() + ->requiresAccessorsForABICompatibilityWithPreCoroutineAccessors(); } bool AccessorDecl::doesAccessorHaveBody() const { diff --git a/lib/AST/TypeCheckRequests.cpp b/lib/AST/TypeCheckRequests.cpp index 96836b24a1c6d..a767647a4ea04 100644 --- a/lib/AST/TypeCheckRequests.cpp +++ b/lib/AST/TypeCheckRequests.cpp @@ -774,18 +774,19 @@ void IsSetterMutatingRequest::cacheResult(bool value) const { } //----------------------------------------------------------------------------// -// OpaqueReadOwnershipRequest computation. +// DirectOpaqueReadOwnershipRequest computation. //----------------------------------------------------------------------------// std::optional -OpaqueReadOwnershipRequest::getCachedResult() const { +DirectOpaqueReadOwnershipRequest::getCachedResult() const { auto *storage = std::get<0>(getStorage()); if (storage->LazySemanticInfo.OpaqueReadOwnershipComputed) return OpaqueReadOwnership(storage->LazySemanticInfo.OpaqueReadOwnership); return std::nullopt; } -void OpaqueReadOwnershipRequest::cacheResult(OpaqueReadOwnership value) const { +void DirectOpaqueReadOwnershipRequest::cacheResult( + OpaqueReadOwnership value) const { auto *storage = std::get<0>(getStorage()); storage->setOpaqueReadOwnership(value); } diff --git a/lib/SILGen/SILGenType.cpp b/lib/SILGen/SILGenType.cpp index d81293b243779..95b5bc4beff21 100644 --- a/lib/SILGen/SILGenType.cpp +++ b/lib/SILGen/SILGenType.cpp @@ -1159,13 +1159,16 @@ void SILGenModule::emitDefaultWitnessTable(ProtocolDecl *protocol) { namespace { -std::optional -originalAccessorKindForReplacementKind(AccessorKind kind) { +bool originalAccessorKindsForReplacementKind( + AccessorKind kind, SmallVectorImpl &kinds) { switch (kind) { case AccessorKind::Read2: - return {AccessorKind::Read}; + kinds.push_back(AccessorKind::Read); + kinds.push_back(AccessorKind::Get); + return true; case AccessorKind::Modify2: - return {AccessorKind::Modify}; + kinds.push_back(AccessorKind::Modify); + return true; case AccessorKind::Get: case AccessorKind::DistributedGet: case AccessorKind::Set: @@ -1178,7 +1181,7 @@ originalAccessorKindForReplacementKind(AccessorKind kind) { case AccessorKind::Init: case AccessorKind::Borrow: case AccessorKind::Mutate: - return std::nullopt; + return false; } } @@ -1213,13 +1216,21 @@ class SILGenDefaultOverrideTable if (!accessor) { return std::nullopt; } - // Specifically, read2 can replace _read and modify2 can replace _modify. - auto originalKind = - originalAccessorKindForReplacementKind(accessor->getAccessorKind()); - if (!originalKind) { + // Specifically, read2 can replace _read or get and modify2 can replace + // _modify. + SmallVector originalKinds; + if (!originalAccessorKindsForReplacementKind(accessor->getAccessorKind(), + originalKinds)) { return std::nullopt; } - auto *originalDecl = accessor->getStorage()->getAccessor(*originalKind); + assert(originalKinds.size() > 0); + AccessorDecl *originalDecl = nullptr; + for (auto originalKind : originalKinds) { + originalDecl = accessor->getStorage()->getAccessor(originalKind); + if (originalDecl) { + break; + } + } if (!originalDecl) { return std::nullopt; } @@ -1326,9 +1337,7 @@ SILFunction *SILGenModule::emitDefaultOverride(SILDeclRef replacement, assert(indirectErrors.size() == 0 && "coroutine accessor with indirect error!?"); SmallVector args; - for (auto result : indirectResults) { - args.push_back(result.forward(SGF)); - } + ASSERT(indirectResults.empty()); // Indirect errors would go here, but we don't currently support // throwing coroutines. if (implicitIsolationParam.isValid()) { @@ -1337,15 +1346,68 @@ SILFunction *SILGenModule::emitDefaultOverride(SILDeclRef replacement, for (auto param : params) { args.push_back(param.forward(SGF)); } - auto *bai = SGF.B.createBeginApply(loc, originalFn, subs, args); - auto *token = bai->getTokenResult(); - auto yieldedValues = bai->getYieldedValues(); + struct Get { + struct Direct { + SILValue value; + }; + struct Indirect { + AllocStackInst *asi; + }; + using Result = TaggedUnion; + SmallVector results; + }; + struct Read { + BeginApplyInst *bai; + }; + SmallVector yields; + using Apply = TaggedUnion; + Apply apply = [&] { + if (originalTy->getCoroutineKind() == SILCoroutineKind::None) { + auto get = Get{{}}; + SmallVector indirectResults; + auto indirectResultIterator = args.begin(); + for (auto result : originalConvention.getIndirectSILResults()) { + auto ty = originalConvention.getSILType( + result, function->getTypeExpansionContext()); + ty = function->mapTypeIntoContext(ty); + auto *asi = SGF.B.createAllocStack(loc, ty); + args.insert(indirectResultIterator, asi); + indirectResultIterator = std::next(indirectResultIterator); + indirectResults.push_back(asi); + } + auto *ai = SGF.B.createApply(loc, originalFn, subs, args); + auto directResults = ai->getResults(); + size_t directIndex = 0; + size_t indirectIndex = 0; + for (auto result : originalConvention.getResults()) { + if (result.isFormalIndirect()) { + ASSERT(indirectIndex < indirectResults.size()); + auto indirectResult = indirectResults[indirectIndex]; + get.results.push_back(Get::Indirect{indirectResult}); + yields.push_back(indirectResult); + indirectIndex += 1; + continue; + } + ASSERT(directIndex < directResults.size()); + auto directResult = directResults[directIndex]; + get.results.push_back(Get::Direct{directResult}); + yields.push_back(directResult); + directIndex += 1; + } + return Apply{get}; + } + + assert(originalTy->getCoroutineKind() == SILCoroutineKind::YieldOnce); + auto *bai = SGF.B.createBeginApply(loc, originalFn, subs, args); + auto yieldedValues = bai->getYieldedValues(); + for (auto yielded : yieldedValues) { + yields.push_back(yielded); + } + return Apply{Read{bai}}; + }(); + auto *normalBlock = function->createBasicBlockAfter(SGF.B.getInsertionBB()); auto *errorBlock = function->createBasicBlockAfter(normalBlock); - SmallVector yields; - for (auto yielded : yieldedValues) { - yields.push_back(yielded); - } SGF.B.createYield(loc, yields, normalBlock, errorBlock); SGF.B.setInsertionPoint(normalBlock); @@ -1374,12 +1436,38 @@ SILFunction *SILGenModule::emitDefaultOverride(SILDeclRef replacement, break; } } - SGF.B.createEndApply(loc, token, resultTy); + if (auto *get = apply.dyn_cast()) { + for (auto result : llvm::reverse(get->results)) { + if (auto *direct = result.dyn_cast()) { + SGF.B.emitDestroyValueOperation(loc, direct->value); + continue; + } + auto indirect = result.get(); + SGF.B.emitDestroyAddr(loc, indirect.asi); + SGF.B.createDeallocStack(loc, indirect.asi); + } + } else { + auto read = apply.get(); + SGF.B.createEndApply(loc, read.bai->getTokenResult(), resultTy); + } auto *retval = SGF.B.createTuple(loc, {}); SGF.B.createReturn(loc, retval); SGF.B.setInsertionPoint(errorBlock); - SGF.B.createAbortApply(loc, token); + if (auto *get = apply.dyn_cast()) { + for (auto result : llvm::reverse(get->results)) { + if (auto *direct = result.dyn_cast()) { + SGF.B.emitDestroyValueOperation(loc, direct->value); + continue; + } + auto indirect = result.get(); + SGF.B.emitDestroyAddr(loc, indirect.asi); + SGF.B.createDeallocStack(loc, indirect.asi); + } + } else { + auto read = apply.get(); + SGF.B.createAbortApply(loc, read.bai->getTokenResult()); + } SGF.B.createUnwind(loc); return function; } diff --git a/lib/Sema/TypeCheckStorage.cpp b/lib/Sema/TypeCheckStorage.cpp index b4533b79623e9..538ce386d351f 100644 --- a/lib/Sema/TypeCheckStorage.cpp +++ b/lib/Sema/TypeCheckStorage.cpp @@ -839,33 +839,33 @@ IsSetterMutatingRequest::evaluate(Evaluator &evaluator, llvm_unreachable("bad storage kind"); } -OpaqueReadOwnership -OpaqueReadOwnershipRequest::evaluate(Evaluator &evaluator, - AbstractStorageDecl *storage) const { - auto abiRole = ABIRoleInfo(storage); - if (!abiRole.providesAPI() && abiRole.getCounterpart()) - return abiRole.getCounterpart()->getOpaqueReadOwnership(); - - enum class DiagKind { - BorrowedAttr, - NoncopyableType - }; +namespace { +enum class DirectOpaqueReadOwnershipRequestDiagKind { + BorrowedAttr, + NoncopyableType +}; + +void diagnoseEffectfulGetterOnBorrowingRead( + AbstractStorageDecl *storage, + DirectOpaqueReadOwnershipRequestDiagKind kind) { + auto *getter = storage->getEffectfulGetAccessor(); + if (!getter) + return; + // Check for effects on the getter. + switch (kind) { + case DirectOpaqueReadOwnershipRequestDiagKind::NoncopyableType: + getter->diagnose(diag::noncopyable_effectful_getter, getter); + break; + case DirectOpaqueReadOwnershipRequestDiagKind::BorrowedAttr: + getter->diagnose(diag::borrowed_with_effect, getter); + break; + } +} - auto usesBorrowed = [&](DiagKind kind) -> OpaqueReadOwnership { - // Check for effects on the getter. - if (auto *getter = storage->getEffectfulGetAccessor()) { - switch (kind) { - case DiagKind::NoncopyableType: - getter->diagnose(diag::noncopyable_effectful_getter, getter); - break; - case DiagKind::BorrowedAttr: - getter->diagnose(diag::borrowed_with_effect, getter); - break; - } - } - return OpaqueReadOwnership::Borrowed; - }; +} // end anonymous namespace +static OpaqueReadOwnership +computeOpaqueReadOwnership(AbstractStorageDecl *storage) { if (auto *accessorDecl = storage->getAccessor(AccessorKind::Read)) { auto lifetimeDependencies = accessorDecl->getLifetimeDependencies(); if (lifetimeDependencies.has_value() && !lifetimeDependencies->empty()) { @@ -878,22 +878,46 @@ OpaqueReadOwnershipRequest::evaluate(Evaluator &evaluator, } } - if (storage->getAccessor(AccessorKind::Read2)) - return OpaqueReadOwnership::Borrowed; + using DiagKind = DirectOpaqueReadOwnershipRequestDiagKind; if (storage->getAccessor(AccessorKind::Borrow)) return OpaqueReadOwnership::Borrowed; - if (storage->getAttrs().hasAttribute()) - return usesBorrowed(DiagKind::BorrowedAttr); + if (storage->getAttrs().hasAttribute()) { + diagnoseEffectfulGetterOnBorrowingRead(storage, DiagKind::BorrowedAttr); + return OpaqueReadOwnership::Borrowed; + } - if (storage->getInnermostDeclContext()->mapTypeIntoContext( - storage->getValueInterfaceType())->isNoncopyable()) - return usesBorrowed(DiagKind::NoncopyableType); + if (storage->getInnermostDeclContext() + ->mapTypeIntoContext(storage->getValueInterfaceType()) + ->isNoncopyable()) { + diagnoseEffectfulGetterOnBorrowingRead(storage, DiagKind::NoncopyableType); + return OpaqueReadOwnership::Borrowed; + } return OpaqueReadOwnership::Owned; } +OpaqueReadOwnership +DirectOpaqueReadOwnershipRequest::evaluate(Evaluator &evaluator, + AbstractStorageDecl *storage) const { + auto computed = computeOpaqueReadOwnership(storage); + + if (!storage->getAccessor(AccessorKind::Read2)) + return computed; + + if (!storage->requiresAccessorsForABICompatibilityWithPreCoroutineAccessors()) + return OpaqueReadOwnership::Borrowed; + + switch (computed) { + case OpaqueReadOwnership::Owned: + case OpaqueReadOwnership::OwnedOrBorrowed: + return OpaqueReadOwnership::OwnedOrBorrowed; + case OpaqueReadOwnership::Borrowed: + return OpaqueReadOwnership::Borrowed; + } +} + /// Insert the specified decl into the DeclContext's member list. If the hint /// decl is specified, the new decl is inserted next to the hint. static void addMemberToContextIfNeeded(Decl *D, DeclContext *DC, @@ -2672,31 +2696,24 @@ RequiresOpaqueAccessorsRequest::evaluate(Evaluator &evaluator, return true; } -/// When the CoroutineAccessors feature is available, the coroutine accessor -/// _could_ be required. That non-underscored accessor would be preferred to -/// its underscored counterpart accessor. -/// -/// The underscored accessor could, however, still be required for ABI -/// stability. -static bool requiresCorrespondingUnderscoredCoroutineAccessorImpl( - AbstractStorageDecl const *storage, AccessorKind kind, - AccessorDecl const *decl, AbstractStorageDecl const *derived) { +/// When the CoroutineAccessors feature is available, different accessors may be +/// required (e.g. read2 and modify2). The accessors which were previously +/// required, however, may still be required for ABI compatibility. +static bool requiresAccessorsForABICompatibilityWithPreCoroutineAccessorsImpl( + AbstractStorageDecl const *storage, AbstractStorageDecl const *derived) { auto &ctx = storage->getASTContext(); - assert(ctx.LangOpts.hasFeature(Feature::CoroutineAccessors)); - assert(kind == AccessorKind::Modify2 || kind == AccessorKind::Read2); - - // If any overridden decl requires the underscored version, then this decl - // does too. Otherwise dispatch to the underscored version on a value - // statically the super but dynamically this subtype would not dispatch to an - // override of the underscored version but rather (incorrectly) the - // supertype's implementation. + // If any overridden storage requires accessors for ABI compatibility, then + // this storage does too. + // + // Otherwise dispatch to one of those required-by-some-overridden-storage + // accessor on an instance of a type that's statically the supertype but + // dynamically this subtype would not dispatch to an override provided by this + // subtype but rather (incorrectly) that supertype's implementation. if (storage == derived) { auto *current = storage; while ((current = current->getOverriddenDecl())) { - auto *currentDecl = cast_or_null( - decl ? decl->getOverriddenDecl() : nullptr); - if (requiresCorrespondingUnderscoredCoroutineAccessorImpl( - current, kind, currentDecl, derived)) { + if (requiresAccessorsForABICompatibilityWithPreCoroutineAccessorsImpl( + current, derived)) { return true; } } @@ -2711,12 +2728,6 @@ static bool requiresCorrespondingUnderscoredCoroutineAccessorImpl( if (!isExported(storage)) return false; - // The non-underscored accessor is not present, the underscored accessor - // won't be either. - auto *accessor = decl ? decl : storage->getOpaqueAccessor(kind); - if (!accessor) - return false; - // Availability checks are only relevant on targets which support versioned // availability. Otherwise, since we're building with library evolution, // conservatively assume that the binary must keep ABI compatibility with its @@ -2726,7 +2737,7 @@ static bool requiresCorrespondingUnderscoredCoroutineAccessorImpl( AvailabilityContext accessorAvailability = [&] { if (storage->getModuleContext()->isMainModule()) { - return AvailabilityContext::forDeclSignature(accessor); + return AvailabilityContext::forDeclSignature(storage); } // Calculate the availability of the imported declaration ourselves starting // from always available and constraining by walking the enclosing decl @@ -2750,30 +2761,35 @@ static bool requiresCorrespondingUnderscoredCoroutineAccessorImpl( featureAvailability)) return false; - // The underscored accessor is required for ABI stability. + // ABI stability requires that accessors provieded before CoroutineAccessors + // was enabled be provided still. + // + // In the case of modify2, that will always mean that modify is required. + // + // In the case of read2, that could mean read OR get is required. return true; } -bool AbstractStorageDecl::requiresCorrespondingUnderscoredCoroutineAccessor( - AccessorKind kind, AccessorDecl const *decl) const { - return requiresCorrespondingUnderscoredCoroutineAccessorImpl( - this, kind, decl, - /*derived=*/this); +bool AbstractStorageDecl:: + requiresAccessorsForABICompatibilityWithPreCoroutineAccessors() const { + return requiresAccessorsForABICompatibilityWithPreCoroutineAccessorsImpl( + this, /*derived=*/this); } bool RequiresOpaqueModifyCoroutineRequest::evaluate( Evaluator &evaluator, AbstractStorageDecl *storage, bool isUnderscored) const { auto &ctx = storage->getASTContext(); - bool hasModifyFeature = ctx.LangOpts.hasFeature(Feature::CoroutineAccessors); + bool hasCoroutineAccessorsFeature = ctx.LangOpts.hasFeature(Feature::CoroutineAccessors); // No `modify` accessor without the feature. - if (!hasModifyFeature && !isUnderscored) + if (!hasCoroutineAccessorsFeature && !isUnderscored) return false; - if (hasModifyFeature && isUnderscored) { - return storage->requiresCorrespondingUnderscoredCoroutineAccessor( - AccessorKind::Modify2); + if (hasCoroutineAccessorsFeature && isUnderscored && + !storage + ->requiresAccessorsForABICompatibilityWithPreCoroutineAccessors()) { + return false; } // Only for mutable storage. diff --git a/test/IRGen/default_override.sil b/test/IRGen/default_override.sil index 88c4fe6e4cb00..8b288f3bab6a9 100644 --- a/test/IRGen/default_override.sil +++ b/test/IRGen/default_override.sil @@ -18,6 +18,7 @@ struct Int { } open class B { + @_borrowed open var i: Int { read set } } diff --git a/test/Interpreter/borrowed_storage_override.swift b/test/Interpreter/borrowed_storage_override.swift new file mode 100644 index 0000000000000..b0a972ed886df --- /dev/null +++ b/test/Interpreter/borrowed_storage_override.swift @@ -0,0 +1,50 @@ +// RUN: %target-run-simple-swift | %FileCheck %s + +// REQUIRES: executable_test + +protocol P { + var i: Int { get } +} + +class C : P { + @_borrowed + var i: Int + + init() { + self.i = 5 + } +} + +class D : C { + override var i: Int { + get {42} + set {} + } +} + +func getFromC(_ c: C) -> Int { + return c.i +} + +func getFromD(_ c: D) -> Int { + return c.i +} + +func getFromP(_ c: T) -> Int { + return c.i +} + +func doit() { + let c = D() + let ic = getFromC(c) + print("as C:", ic) + // CHECK: as C: 42 + let id = getFromD(c) + print("as D:", id) + // CHECK: as D: 42 + let ip = getFromP(c) + print("as P:", ip) + // CHECK: as P: 42 +} + +doit() diff --git a/test/Interpreter/coroutine_accessors.swift b/test/Interpreter/coroutine_accessors.swift new file mode 100644 index 0000000000000..cfe1079e4886d --- /dev/null +++ b/test/Interpreter/coroutine_accessors.swift @@ -0,0 +1,100 @@ +// RUN: %empty-directory(%t) + +// RUN: split-file %s %t + +// RUN: %target-swift-frontend \ +// RUN: %t/Library.swift \ +// RUN: -enable-callee-allocated-coro-abi \ +// RUN: -emit-module \ +// RUN: -module-name Library \ +// RUN: -parse-as-library \ +// RUN: -enable-library-evolution \ +// RUN: -enable-experimental-feature CoroutineAccessors \ +// RUN: -emit-module-path %t/Library.swiftmodule + +// RUN: %target-build-swift-dylib(%t/%target-library-name(Library)) \ +// RUN: %t/Library.swift \ +// RUN: -Xfrontend -enable-callee-allocated-coro-abi \ +// RUN: -emit-module \ +// RUN: -enable-library-evolution \ +// RUN: -enable-experimental-feature CoroutineAccessors \ +// RUN: -emit-module-path %t/Library.swiftmodule \ +// RUN: -module-name Library + +// RUN: %target-swift-frontend \ +// RUN: %t/Executable.swift \ +// RUN: -enable-callee-allocated-coro-abi \ +// RUN: -c \ +// RUN: -parse-as-library \ +// RUN: -module-name Executable \ +// RUN: -I %t \ +// RUN: -o %t/Executable.o + +// RUN: %target-build-swift \ +// RUN: %t/Executable.o \ +// RUN: -lLibrary \ +// RUN: -L %t \ +// RUN: %target-rpath(%t) \ +// RUN: -o %t/main + +// RUN: %target-codesign %t/main %t/%target-library-name(Library) +// RUN: %target-run %t/main %t/%target-library-name(Library) | %FileCheck %s + +// REQUIRES: swift_feature_CoroutineAccessors +// REQUIRES: executable_test + +//--- Library.swift + +@frozen +public struct Uniquint { + public init(value: Int) { self.value = value } + public var value: Int +} + +var _i: Uniquint = Uniquint(value: 17) +open class Base { + public init() {} + open var i: Uniquint { + read { + yield _i + } + modify { + yield &_i + } + } +} + +public func unpack(_ b: Base) -> Int { + return b.i.value +} + +//--- Executable.swift + +import Library + +var j: Uniquint = Uniquint(value: 42) +class Derived : Base { + override init() { super.init() } + override var i: Uniquint { + get { + return Uniquint(value: 42) + } + set { + j = newValue + } + } +} + +@inline(never) +func myPrint(_ t: T) { + print(t) +} + +@main struct M { + static func main() { + let b = Derived() + let i = unpack(b) + // CHECK: 42 + myPrint(i) + } +} diff --git a/test/Interpreter/coroutine_accessors_default_implementations.swift b/test/Interpreter/coroutine_accessors_default_implementations.swift index ecd7b2bb97354..7e84284eaab56 100644 --- a/test/Interpreter/coroutine_accessors_default_implementations.swift +++ b/test/Interpreter/coroutine_accessors_default_implementations.swift @@ -203,6 +203,7 @@ struct I : P { open class B { public init() {} + @_borrowed open var i: Int { read { fatalError() @@ -211,6 +212,7 @@ open class B { fatalError() } } + @_borrowed open subscript(i : Int) -> Int { read { fatalError() diff --git a/test/ModuleInterface/coroutine_accessors.swift b/test/ModuleInterface/coroutine_accessors.swift index e41653338c220..69cdd769ad603 100644 --- a/test/ModuleInterface/coroutine_accessors.swift +++ b/test/ModuleInterface/coroutine_accessors.swift @@ -9,6 +9,7 @@ // REQUIRES: swift_feature_CoroutineAccessors var _i: Int = 0 +var _j: Int = 0 // CHECK: #if compiler(>=5.3) && $CoroutineAccessors // CHECK-NEXT: public var i: Swift.Int { @@ -21,6 +22,7 @@ var _i: Int = 0 // CHECK-NEXT: _modify // CHECK-NEXT: } // CHECK-NEXT: #endif +@_borrowed public var i: Int { read { yield _i @@ -29,3 +31,23 @@ public var i: Int { yield &_i } } + +// CHECK: #if compiler(>=5.3) && $CoroutineAccessors +// CHECK-NEXT: public var j: Swift.Int { +// CHECK-NEXT: read +// CHECK-NEXT: modify +// CHECK-NEXT: } +// CHECK-NEXT: #else +// CHECK-NEXT: public var j: Swift.Int { +// CHECK-NEXT: get +// CHECK-NEXT: _modify +// CHECK-NEXT: } +// CHECK-NEXT: #endif +public var j: Int { + read { + yield _j + } + modify { + yield &_j + } +} diff --git a/test/SIL/Parser/default_override.sil b/test/SIL/Parser/default_override.sil index 19cc6b35bfd27..94ba70b751dbc 100644 --- a/test/SIL/Parser/default_override.sil +++ b/test/SIL/Parser/default_override.sil @@ -14,6 +14,7 @@ struct Int { } open class B { + @_borrowed open var i: Int { read set } } diff --git a/test/SIL/Serialization/default_override.sil b/test/SIL/Serialization/default_override.sil index 2ee938086a4cf..68445c1433ee4 100644 --- a/test/SIL/Serialization/default_override.sil +++ b/test/SIL/Serialization/default_override.sil @@ -16,6 +16,7 @@ struct Int { } open class B { + @_borrowed open var i: Int { read set } } diff --git a/test/SILGen/coroutine_accessors.swift b/test/SILGen/coroutine_accessors.swift index 1630b058c3742..c30907e5a313e 100644 --- a/test/SILGen/coroutine_accessors.swift +++ b/test/SILGen/coroutine_accessors.swift @@ -22,6 +22,21 @@ public var o: any AnyObject public var _i: Int = 0 public var irm: Int { +// CHECK-LABEL: sil{{.*}} [ossa] @$s19coroutine_accessors1SV3irmSivg : +// CHECK-SAME: $@convention(method) +// CHECK-SAME: (@guaranteed S) +// CHECK-SAME: -> +// CHECK-SAME: Int +// CHECK-SAME: { +// CHECK: bb0( +// CHECK: [[SELF:%[^,]+]] : +// CHECK: ): +// CHECK: [[READER2:%[^,]+]] = function_ref @$s19coroutine_accessors1SV3irmSivy +// CHECK: ([[VALUE:%[^,]+]], [[TOKEN:%[^,]+]], [[ALLOCATION:%[^,]+]]) = begin_apply [[READER2]]([[SELF]]) +// CHECK: end_apply [[TOKEN]] +// CHECK: dealloc_stack [[ALLOCATION]] : $*Builtin.SILToken +// CHECK: return [[VALUE]] +// CHECK-LABEL: } // end sil function '$s19coroutine_accessors1SV3irmSivg' // CHECK-LABEL: sil [ossa] @$s19coroutine_accessors1SV3irmSivy : // CHECK-SAME: $@yield_once_2 // CHECK-SAME: @convention(method) @@ -44,26 +59,6 @@ public var irm: Int { modify { yield &_i } -// CHECK-LABEL: sil{{.*}} [ossa] @$s19coroutine_accessors1SV3irmSivr : -// CHECK-SAME: $@yield_once -// CHECK-SAME: @convention(method) -// CHECK-SAME: (@guaranteed S) -// CHECK-SAME: -> -// CHECK-SAME: @yields Int -// CHECK-SAME: { -// CHECK: bb0( -// CHECK: [[SELF:%[^,]+]] : -// CHECK: ): -// CHECK: [[READER2:%[^,]+]] = function_ref @$s19coroutine_accessors1SV3irmSivy -// CHECK: ([[VALUE_ADDRESS:%[^,]+]], [[TOKEN:%[^,]+]], [[ALLOCATION:%[^,]+]]) = begin_apply [[READER2]]([[SELF]]) -// CHECK: end_apply [[TOKEN]] -// CHECK: yield [[VALUE_ADDRESS]] : $Int, resume bb1, unwind bb2 -// CHECK: bb1: -// CHECK: dealloc_stack [[ALLOCATION]] : $*Builtin.SILToken -// CHECK: bb2: -// CHECK: dealloc_stack [[ALLOCATION]] : $*Builtin.SILToken -// CHECK: unwind -// CHECK-LABEL: } // end sil function '$s19coroutine_accessors1SV3irmSivr' // CHECK-LABEL: sil {{.*}}[ossa] @$s19coroutine_accessors1SV3irmSivs : // CHECK-SAME: $@convention(method) diff --git a/test/SILGen/coroutine_accessors_availability.swift b/test/SILGen/coroutine_accessors_availability.swift index aac2b43edcfe3..b828fbd1325fd 100644 --- a/test/SILGen/coroutine_accessors_availability.swift +++ b/test/SILGen/coroutine_accessors_availability.swift @@ -129,9 +129,9 @@ public func getOld() -> StructOld { public func readOldInlinableOld(_ n: StructOld) -> Int { // CHECK-LABEL: sil {{.*}}@readOldInlinableOld : {{.*}} { // Could be inlined into code that's running before CoroutineAccessors is -// available--must use read. - // function_ref StructOld.i.read -// CHECK: function_ref @$s7Library9StructOldV1iSivr +// available--must use get. + // function_ref StructOld.i.getter +// CHECK: function_ref @$s7Library9StructOldV1iSivg // CHECK-LABEL: } // end sil function 'readOldInlinableOld' return n.i } @@ -238,6 +238,60 @@ open class BaseClassOld { } } +public protocol ProtocolOld { + var i: Int { read set } +} + +// CHECK-LABEL: sil {{.*}}@modifyProtocolOldInlinableOld : {{.*}} { +// Binaries built with a deployment target earlier than the availability of the +// feature must use the old accessor because conforming types may not have the +// new accessor. +// CHECK-NOT: witness_method {{.*}}#ProtocolOld.i!modify2 +// CHECK: witness_method {{.*}}#ProtocolOld.i!modify +// CHECK-LABEL: } // end sil function 'modifyProtocolOldInlinableOld' +@inlinable +@_silgen_name("modifyProtocolOldInlinableOld") +public func modifyProtocolOldInlinableOld(_ p: inout ProtocolOld) { + p.i.increment() +} + +@_silgen_name("modifyProtocolOldNoninlinableOld") +public func modifyProtocolOldNoninlinableOld(_ p: inout ProtocolOld) { +// CHECK-LABEL: sil {{.*}}@modifyProtocolOldNoninlinableOld : {{.*}} { +// In the case of old binaries running against this version, this is correct +// because a default implementation of the accessor is provided by default +// witness table. +// CHECK: witness_method {{.*}}#ProtocolOld.i!modify2 +// CHECK-LABEL: } // end sil function 'modifyProtocolOldNoninlinableOld' + p.i.increment() +} + +@inlinable +@available(SwiftStdlib 9999, *) +@_silgen_name("modifyProtocolOldInlinableNew") +public func modifyProtocolOldInlinableNew(_ p: inout ProtocolOld) { +// CHECK-LABEL: sil {{.*}}@modifyProtocolOldInlinableNew : {{.*}} { +// CHECK: witness_method {{.*}}#ProtocolOld.i!modify2 +// CHECK-LABEL: } // end sil function 'modifyProtocolOldInlinableNew' + p.i.increment() +} + +@available(SwiftStdlib 9999, *) +public protocol ProtocolNew { + var i: Int { read set } +} + +// CHECK-LABEL: sil_default_witness_table ProtocolOld { +// getter: +// CHECK-NEXT: no_default +// CHECK-NEXT: method #ProtocolOld.i!read2 +// setter: +// CHECK-NEXT: no_default +// modify: +// CHECK-NEXT: no_default +// CHECK-NEXT: method #ProtocolOld.i!modify2 +// CHECK-NEXT: } + //--- Downstream.swift import Library @@ -290,8 +344,8 @@ func readOldOld() { // This module could be back-deployed to before CoroutineAccessors were // available, and nothing ensures the function is available only after the // feature is available--must use read. - // function_ref StructOld.i.read -// CHECK-OLD: function_ref @$s7Library9StructOldV1iSivr + // function_ref StructOld.i.getter +// CHECK-OLD: function_ref @$s7Library9StructOldV1iSivg // This module cannot be back-deployed (the deployment target is // available, and nothing ensures the function is available only after the // feature is available--must use read. @@ -382,7 +436,7 @@ public class DerivedOldFromBaseClassOld : BaseClassOld { // CHECK-LABEL: sil_vtable [serialized] DerivedOldFromBaseClassOld { // CHECK-NEXT: #BaseClassOld.init!allocator -// CHECK-NEXT: #BaseClassOld.i!read +// CHECK-NEXT: #BaseClassOld.i!getter // CHECK-NEXT: #BaseClassOld.i!read2 // CHECK-NEXT: #BaseClassOld.i!setter // CHECK-NEXT: #BaseClassOld.i!modify diff --git a/test/SILGen/coroutine_accessors_compat.swift b/test/SILGen/coroutine_accessors_compat.swift new file mode 100644 index 0000000000000..1ee0bca425dea --- /dev/null +++ b/test/SILGen/coroutine_accessors_compat.swift @@ -0,0 +1,30 @@ +// RUN: %target-swift-emit-silgen -Xllvm -sil-print-types \ +// RUN: %s \ +// RUN: -enable-callee-allocated-coro-abi \ +// RUN: -enable-library-evolution \ +// RUN: -enable-experimental-feature CoroutineAccessors \ +// RUN: | %FileCheck %s --check-prefixes=CHECK,CHECK-NOUNWIND + +// REQUIRES: swift_feature_CoroutineAccessors + +var _i: Int = 1 +public class C { + public var i: Int { + read { + yield _i + } + modify { + yield &_i + } + } +} + +// CHECK-LABEL: sil_vtable C { +// CHECK-NEXT: #C.i!getter +// CHECK-NEXT: #C.i!read2 +// CHECK-NEXT: #C.i!setter +// CHECK-NEXT: #C.i!modify +// CHECK-NEXT: #C.i!modify2 +// CHECK-NEXT: #C.init!allocator +// CHECK-NEXT: #C.deinit!deallocator +// CHECK-NEXT: } diff --git a/test/SILGen/default_override.swift b/test/SILGen/default_override.swift index f3db5b64847b0..07ef2abfa586f 100644 --- a/test/SILGen/default_override.swift +++ b/test/SILGen/default_override.swift @@ -22,14 +22,15 @@ public enum Open {} public enum Public {} public enum Internal {} -open class OpenBase { +open class OpenBase { + @_borrowed open var openField: T { // CHECK-LABEL: sil shared [serialized] [ossa] @$s16default_override8OpenBaseC9openFieldxvyTwd // CHECK-SAME: : $@yield_once_2 // CHECK-SAME: @convention(method) -// CHECK-SAME: <τ_0_0> +// CHECK-SAME: <τ_0_0, τ_0_1> // CHECK-SAME: ( -// CHECK-SAME: @guaranteed OpenBase<τ_0_0> +// CHECK-SAME: @guaranteed OpenBase<τ_0_0, τ_0_1> // CHECK-SAME: ) // CHECK-SAME: -> // CHECK-SAME: @yields @in_guaranteed τ_0_0 @@ -38,9 +39,9 @@ open class OpenBase { // CHECK-SAME: [[SELF:%[^,]+]] : // CHECK-SAME: ): // CHECK: [[ORIGINAL:%[^,]+]] = class_method [[SELF]], #OpenBase.openField!read -// CHECK-SAME: (OpenBase) -> () -> () -// CHECK-SAME: $@yield_once @convention(method) <τ_0_0> (@guaranteed OpenBase<τ_0_0>) -> @yields @in_guaranteed τ_0_0 -// CHECK: ([[ADDR:%[^,]+]], [[TOKEN:%[^,]+]]) = begin_apply [[ORIGINAL]]<τ_0_0>([[SELF]]) +// CHECK-SAME: (OpenBase) -> () -> () +// CHECK-SAME: $@yield_once @convention(method) <τ_0_0, τ_0_1> (@guaranteed OpenBase<τ_0_0, τ_0_1>) -> @yields @in_guaranteed τ_0_0 +// CHECK: ([[ADDR:%[^,]+]], [[TOKEN:%[^,]+]]) = begin_apply [[ORIGINAL]]<τ_0_0, τ_0_1>([[SELF]]) // CHECK: yield [[ADDR]] // CHECK-SAME: resume [[NORMAL:bb[0-9]+]] // CHECK-SAME: unwind [[UNWIND:bb[0-9]+]] @@ -58,9 +59,9 @@ open class OpenBase { // CHECK-LABEL: sil shared [serialized] [ossa] @$s16default_override8OpenBaseC9openFieldxvxTwd // CHECK-SAME: : $@yield_once_2 // CHECK-SAME: @convention(method) -// CHECK-SAME: <τ_0_0> +// CHECK-SAME: <τ_0_0, τ_0_1> // CHECK-SAME: ( -// CHECK-SAME: @guaranteed OpenBase<τ_0_0> +// CHECK-SAME: @guaranteed OpenBase<τ_0_0, τ_0_1> // CHECK-SAME: ) // CHECK-SAME: -> // CHECK-SAME: @yields @inout τ_0_0 @@ -69,9 +70,9 @@ open class OpenBase { // CHECK-SAME: [[SELF:%[^,]+]] : // CHECK-SAME: ): // CHECK: [[ORIGINAL:%[^,]+]] = class_method [[SELF]], #OpenBase.openField!modify -// CHECK: (OpenBase) -> () -> () -// CHECK: $@yield_once @convention(method) <τ_0_0> (@guaranteed OpenBase<τ_0_0>) -> @yields @inout τ_0_0 -// CHECK: ([[ADDR:%[^,]+]], [[TOKEN:%[^,]+]]) = begin_apply [[ORIGINAL]]<τ_0_0>([[SELF]]) +// CHECK: (OpenBase) -> () -> () +// CHECK: $@yield_once @convention(method) <τ_0_0, τ_0_1> (@guaranteed OpenBase<τ_0_0, τ_0_1>) -> @yields @inout τ_0_0 +// CHECK: ([[ADDR:%[^,]+]], [[TOKEN:%[^,]+]]) = begin_apply [[ORIGINAL]]<τ_0_0, τ_0_1>([[SELF]]) // CHECK: yield [[ADDR]] // CHECK: resume [[NORMAL:bb[0-9]+]] // CHECK: unwind [[UNWIND:bb[0-9]+]] @@ -87,17 +88,624 @@ open class OpenBase { Builtin.int_trap() } } - open subscript(_ u: U, _ _: Open.Type) -> T { -// CHECK-LABEL: sil shared [serialized] [ossa] @$s16default_override8OpenBaseCyxqd___AA0C0OmtcluiyTwd -// CHECK-SAME: : $@yield_once_2 -// CHECK-SAME: @convention(method) -// CHECK-SAME: <τ_0_0><τ_1_0> + @_borrowed + open var openField2: (T, T) { +// CHECK-LABEL: sil shared [serialized] [ossa] @$s16default_override8OpenBaseC10openField2x_xtvyTwd +// CHECK-SAME: : $@yield_once_2 +// CHECK-SAME: @convention(method) +// CHECK-SAME: <τ_0_0, τ_0_1> +// CHECK-SAME: ( +// CHECK-SAME: @guaranteed OpenBase<τ_0_0, τ_0_1> +// CHECK-SAME: ) +// CHECK-SAME: -> +// CHECK-SAME: @yields @in_guaranteed τ_0_0 +// CHECK-SAME: { +// CHECK: {{bb[0-9]+}}( +// CHECK-SAME: [[SELF:%[^,]+]] : +// CHECK-SAME: ): +// CHECK: [[ORIGINAL:%[^,]+]] = class_method [[SELF]], #OpenBase.openField2!read +// CHECK-SAME: (OpenBase) -> () -> () +// CHECK-SAME: $@yield_once @convention(method) <τ_0_0, τ_0_1> (@guaranteed OpenBase<τ_0_0, τ_0_1>) -> (@yields @in_guaranteed τ_0_0, @yields @in_guaranteed τ_0_0) +// CHECK: ([[ADDR_1:%[^,]+]], [[ADDR_2:%[^,]+]], [[TOKEN:%[^,]+]]) = begin_apply [[ORIGINAL]]<τ_0_0, τ_0_1>([[SELF]]) +// CHECK: yield ([[ADDR_1]], [[ADDR_2]]) +// CHECK-SAME: resume [[NORMAL:bb[0-9]+]] +// CHECK-SAME: unwind [[UNWIND:bb[0-9]+]] +// CHECK: [[NORMAL]]: +// CHECK: end_apply [[TOKEN]] +// CHECK: [[RETVAL:%[^,]+]] = tuple () +// CHECK: return [[RETVAL]] +// CHECK: [[UNWIND]]: +// CHECK: abort_apply [[TOKEN]] +// CHECK: unwind +// CHECK-LABEL: } // end sil function '$s16default_override8OpenBaseC10openField2x_xtvyTwd' + read { + Builtin.int_trap() + } +// CHECK-LABEL: sil shared [serialized] [ossa] @$s16default_override8OpenBaseC10openField2x_xtvxTwd +// CHECK-SAME: : $@yield_once_2 +// CHECK-SAME: @convention(method) +// CHECK-SAME: <τ_0_0, τ_0_1> +// CHECK-SAME: ( +// CHECK-SAME: @guaranteed OpenBase<τ_0_0, τ_0_1> +// CHECK-SAME: ) +// CHECK-SAME: -> +// CHECK-SAME: @yields @inout (τ_0_0, τ_0_0) +// CHECK-SAME: { +// CHECK: {{bb[0-9]+}}( +// CHECK-SAME: [[SELF:%[^,]+]] : +// CHECK-SAME: ): +// CHECK: [[ORIGINAL:%[^,]+]] = class_method [[SELF]], #OpenBase.openField2!modify +// CHECK: (OpenBase) -> () -> () +// CHECK: $@yield_once @convention(method) <τ_0_0, τ_0_1> (@guaranteed OpenBase<τ_0_0, τ_0_1>) -> @yields @inout (τ_0_0, τ_0_0) +// CHECK: ([[ADDR:%[^,]+]], [[TOKEN:%[^,]+]]) = begin_apply [[ORIGINAL]]<τ_0_0, τ_0_1>([[SELF]]) +// CHECK: yield [[ADDR]] +// CHECK: resume [[NORMAL:bb[0-9]+]] +// CHECK: unwind [[UNWIND:bb[0-9]+]] +// CHECK: [[NORMAL]]: +// CHECK: end_apply [[TOKEN]] +// CHECK: [[RETVAL:%[^,]+]] = tuple () +// CHECK: return [[RETVAL]] +// CHECK: [[UNWIND]]: +// CHECK: abort_apply [[TOKEN]] +// CHECK: unwind +// CHECK-LABEL: } // end sil function '$s16default_override8OpenBaseC10openField2x_xtvxTwd' + modify { + Builtin.int_trap() + } + } + @_borrowed + open var openField3: (T, Int) { +// CHECK-LABEL: sil shared [serialized] [ossa] @$s16default_override8OpenBaseC10openField3x_SitvyTwd +// CHECK-SAME: : $@yield_once_2 +// CHECK-SAME: @convention(method) +// CHECK-SAME: <τ_0_0, τ_0_1> +// CHECK-SAME: ( +// CHECK-SAME: @guaranteed OpenBase<τ_0_0, τ_0_1> +// CHECK-SAME: ) +// CHECK-SAME: -> +// CHECK-SAME: @yields @in_guaranteed τ_0_0 +// CHECK-SAME: { +// CHECK: {{bb[0-9]+}}( +// CHECK-SAME: [[SELF:%[^,]+]] : +// CHECK-SAME: ): +// CHECK: [[ORIGINAL:%[^,]+]] = class_method [[SELF]], #OpenBase.openField3!read +// CHECK-SAME: (OpenBase) -> () -> () +// CHECK-SAME: $@yield_once @convention(method) <τ_0_0, τ_0_1> (@guaranteed OpenBase<τ_0_0, τ_0_1>) -> (@yields @in_guaranteed τ_0_0, @yields Int) +// CHECK: ([[ADDR_1:%[^,]+]], [[ADDR_2:%[^,]+]], [[TOKEN:%[^,]+]]) = begin_apply [[ORIGINAL]]<τ_0_0, τ_0_1>([[SELF]]) +// CHECK: yield ([[ADDR_1]], [[ADDR_2]]) +// CHECK-SAME: resume [[NORMAL:bb[0-9]+]] +// CHECK-SAME: unwind [[UNWIND:bb[0-9]+]] +// CHECK: [[NORMAL]]: +// CHECK: end_apply [[TOKEN]] +// CHECK: [[RETVAL:%[^,]+]] = tuple () +// CHECK: return [[RETVAL]] +// CHECK: [[UNWIND]]: +// CHECK: abort_apply [[TOKEN]] +// CHECK: unwind +// CHECK-LABEL: } // end sil function '$s16default_override8OpenBaseC10openField3x_SitvyTwd' + read { + Builtin.int_trap() + } +// CHECK-LABEL: sil shared [serialized] [ossa] @$s16default_override8OpenBaseC10openField3x_SitvxTwd +// CHECK-SAME: : $@yield_once_2 +// CHECK-SAME: @convention(method) +// CHECK-SAME: <τ_0_0, τ_0_1> +// CHECK-SAME: ( +// CHECK-SAME: @guaranteed OpenBase<τ_0_0, τ_0_1> +// CHECK-SAME: ) +// CHECK-SAME: -> +// CHECK-SAME: @yields @inout (τ_0_0, Int) +// CHECK-SAME: { +// CHECK: {{bb[0-9]+}}( +// CHECK-SAME: [[SELF:%[^,]+]] : +// CHECK-SAME: ): +// CHECK: [[ORIGINAL:%[^,]+]] = class_method [[SELF]], #OpenBase.openField3!modify +// CHECK: (OpenBase) -> () -> () +// CHECK: $@yield_once @convention(method) <τ_0_0, τ_0_1> (@guaranteed OpenBase<τ_0_0, τ_0_1>) -> @yields @inout (τ_0_0, Int) +// CHECK: ([[ADDR:%[^,]+]], [[TOKEN:%[^,]+]]) = begin_apply [[ORIGINAL]]<τ_0_0, τ_0_1>([[SELF]]) +// CHECK: yield [[ADDR]] +// CHECK: resume [[NORMAL:bb[0-9]+]] +// CHECK: unwind [[UNWIND:bb[0-9]+]] +// CHECK: [[NORMAL]]: +// CHECK: end_apply [[TOKEN]] +// CHECK: [[RETVAL:%[^,]+]] = tuple () +// CHECK: return [[RETVAL]] +// CHECK: [[UNWIND]]: +// CHECK: abort_apply [[TOKEN]] +// CHECK: unwind +// CHECK-LABEL: } // end sil function '$s16default_override8OpenBaseC10openField3x_SitvxTwd' + modify { + Builtin.int_trap() + } + } + @_borrowed + open var openField4: (String, T) { +// CHECK-LABEL: sil shared [serialized] [ossa] @$s16default_override8OpenBaseC10openField4SS_xtvyTwd +// CHECK-SAME: : $@yield_once_2 +// CHECK-SAME: @convention(method) +// CHECK-SAME: <τ_0_0, τ_0_1> +// CHECK-SAME: ( +// CHECK-SAME: @guaranteed OpenBase<τ_0_0, τ_0_1> +// CHECK-SAME: ) +// CHECK-SAME: -> +// CHECK-SAME: @yields @in_guaranteed τ_0_0 +// CHECK-SAME: { +// CHECK: {{bb[0-9]+}}( +// CHECK-SAME: [[SELF:%[^,]+]] : +// CHECK-SAME: ): +// CHECK: [[ORIGINAL:%[^,]+]] = class_method [[SELF]], #OpenBase.openField4!read +// CHECK-SAME: (OpenBase) -> () -> () +// CHECK-SAME: $@yield_once @convention(method) <τ_0_0, τ_0_1> (@guaranteed OpenBase<τ_0_0, τ_0_1>) -> (@yields @guaranteed String, @yields @in_guaranteed τ_0_0) +// CHECK: ([[ADDR_1:%[^,]+]], [[ADDR_2:%[^,]+]], [[TOKEN:%[^,]+]]) = begin_apply [[ORIGINAL]]<τ_0_0, τ_0_1>([[SELF]]) +// CHECK: yield ([[ADDR_1]], [[ADDR_2]]) +// CHECK-SAME: resume [[NORMAL:bb[0-9]+]] +// CHECK-SAME: unwind [[UNWIND:bb[0-9]+]] +// CHECK: [[NORMAL]]: +// CHECK: end_apply [[TOKEN]] +// CHECK: [[RETVAL:%[^,]+]] = tuple () +// CHECK: return [[RETVAL]] +// CHECK: [[UNWIND]]: +// CHECK: abort_apply [[TOKEN]] +// CHECK: unwind +// CHECK-LABEL: } // end sil function '$s16default_override8OpenBaseC10openField4SS_xtvyTwd' + read { + Builtin.int_trap() + } +// CHECK-LABEL: sil shared [serialized] [ossa] @$s16default_override8OpenBaseC10openField4SS_xtvxTwd +// CHECK-SAME: : $@yield_once_2 +// CHECK-SAME: @convention(method) +// CHECK-SAME: <τ_0_0, τ_0_1> +// CHECK-SAME: ( +// CHECK-SAME: @guaranteed OpenBase<τ_0_0, τ_0_1> +// CHECK-SAME: ) +// CHECK-SAME: -> +// CHECK-SAME: @yields @inout (String, τ_0_0) +// CHECK-SAME: { +// CHECK: {{bb[0-9]+}}( +// CHECK-SAME: [[SELF:%[^,]+]] : +// CHECK-SAME: ): +// CHECK: [[ORIGINAL:%[^,]+]] = class_method [[SELF]], #OpenBase.openField4!modify +// CHECK: (OpenBase) -> () -> () +// CHECK: $@yield_once @convention(method) <τ_0_0, τ_0_1> (@guaranteed OpenBase<τ_0_0, τ_0_1>) -> @yields @inout (String, τ_0_0) +// CHECK: ([[ADDR:%[^,]+]], [[TOKEN:%[^,]+]]) = begin_apply [[ORIGINAL]]<τ_0_0, τ_0_1>([[SELF]]) +// CHECK: yield [[ADDR]] +// CHECK: resume [[NORMAL:bb[0-9]+]] +// CHECK: unwind [[UNWIND:bb[0-9]+]] +// CHECK: [[NORMAL]]: +// CHECK: end_apply [[TOKEN]] +// CHECK: [[RETVAL:%[^,]+]] = tuple () +// CHECK: return [[RETVAL]] +// CHECK: [[UNWIND]]: +// CHECK: abort_apply [[TOKEN]] +// CHECK: unwind +// CHECK-LABEL: } // end sil function '$s16default_override8OpenBaseC10openField4SS_xtvxTwd' + modify { + Builtin.int_trap() + } + } + @_borrowed + open var openField5: (T, U) { +// CHECK-LABEL: sil shared [serialized] [ossa] @$s16default_override8OpenBaseC10openField5x_q_tvyTwd +// CHECK-SAME: : $@yield_once_2 +// CHECK-SAME: @convention(method) +// CHECK-SAME: <τ_0_0, τ_0_1> +// CHECK-SAME: ( +// CHECK-SAME: @guaranteed OpenBase<τ_0_0, τ_0_1> +// CHECK-SAME: ) +// CHECK-SAME: -> +// CHECK-SAME: (@yields @in_guaranteed τ_0_0, @yields @in_guaranteed τ_0_1) +// CHECK-SAME: { +// CHECK: {{bb[0-9]+}}( +// CHECK-SAME: [[SELF:%[^,]+]] : +// CHECK-SAME: ): +// CHECK: [[ORIGINAL:%[^,]+]] = class_method [[SELF]], #OpenBase.openField5!read +// CHECK-SAME: (OpenBase) -> () -> () +// CHECK-SAME: $@yield_once @convention(method) <τ_0_0, τ_0_1> (@guaranteed OpenBase<τ_0_0, τ_0_1>) -> (@yields @in_guaranteed τ_0_0, @yields @in_guaranteed τ_0_1) +// CHECK: ([[ADDR_1:%[^,]+]], [[ADDR_2:%[^,]+]], [[TOKEN:%[^,]+]]) = begin_apply [[ORIGINAL]]<τ_0_0, τ_0_1>([[SELF]]) +// CHECK: yield ([[ADDR_1]], [[ADDR_2]]) +// CHECK-SAME: resume [[NORMAL:bb[0-9]+]] +// CHECK-SAME: unwind [[UNWIND:bb[0-9]+]] +// CHECK: [[NORMAL]]: +// CHECK: end_apply [[TOKEN]] +// CHECK: [[RETVAL:%[^,]+]] = tuple () +// CHECK: return [[RETVAL]] +// CHECK: [[UNWIND]]: +// CHECK: abort_apply [[TOKEN]] +// CHECK: unwind +// CHECK-LABEL: } // end sil function '$s16default_override8OpenBaseC10openField5x_q_tvyTwd' + read { + Builtin.int_trap() + } +// CHECK-LABEL: sil shared [serialized] [ossa] @$s16default_override8OpenBaseC10openField5x_q_tvxTwd +// CHECK-SAME: : $@yield_once_2 +// CHECK-SAME: @convention(method) +// CHECK-SAME: <τ_0_0, τ_0_1> +// CHECK-SAME: ( +// CHECK-SAME: @guaranteed OpenBase<τ_0_0, τ_0_1> +// CHECK-SAME: ) +// CHECK-SAME: -> +// CHECK-SAME: @yields @inout (τ_0_0, τ_0_1) +// CHECK-SAME: { +// CHECK: {{bb[0-9]+}}( +// CHECK-SAME: [[SELF:%[^,]+]] : +// CHECK-SAME: ): +// CHECK: [[ORIGINAL:%[^,]+]] = class_method [[SELF]], #OpenBase.openField5!modify +// CHECK: (OpenBase) -> () -> () +// CHECK: $@yield_once @convention(method) <τ_0_0, τ_0_1> (@guaranteed OpenBase<τ_0_0, τ_0_1>) -> @yields @inout (τ_0_0, τ_0_1) +// CHECK: ([[ADDR:%[^,]+]], [[TOKEN:%[^,]+]]) = begin_apply [[ORIGINAL]]<τ_0_0, τ_0_1>([[SELF]]) +// CHECK: yield [[ADDR]] +// CHECK: resume [[NORMAL:bb[0-9]+]] +// CHECK: unwind [[UNWIND:bb[0-9]+]] +// CHECK: [[NORMAL]]: +// CHECK: end_apply [[TOKEN]] +// CHECK: [[RETVAL:%[^,]+]] = tuple () +// CHECK: return [[RETVAL]] +// CHECK: [[UNWIND]]: +// CHECK: abort_apply [[TOKEN]] +// CHECK: unwind +// CHECK-LABEL: } // end sil function '$s16default_override8OpenBaseC10openField5x_q_tvxTwd' + modify { + Builtin.int_trap() + } + } + open var ownedOpenField: T { +// CHECK-LABEL: sil shared [serialized] [ossa] @$s16default_override8OpenBaseC05ownedC5FieldxvyTwd +// CHECK-SAME: : $@yield_once_2 +// CHECK-SAME: @convention(method) +// CHECK-SAME: <τ_0_0, τ_0_1> +// CHECK-SAME: ( +// CHECK-SAME: @guaranteed OpenBase<τ_0_0, τ_0_1> +// CHECK-SAME: ) +// CHECK-SAME: -> +// CHECK-SAME: @yields @in_guaranteed τ_0_0 +// CHECK-SAME: { +// CHECK: {{bb[0-9]+}}( +// CHECK-SAME: [[SELF:%[^,]+]] : +// CHECK-SAME: ): +// CHECK: [[ORIGINAL:%[^,]+]] = class_method [[SELF]], #OpenBase.ownedOpenField!getter +// CHECK-SAME: (OpenBase) -> () -> T +// CHECK-SAME: $@convention(method) <τ_0_0, τ_0_1> (@guaranteed OpenBase<τ_0_0, τ_0_1>) -> @out τ_0_0 +// CHECK: [[ADDR:%[^,]+]] = alloc_stack +// CHECK: [[EMPTY:%[^,]+]] = apply [[ORIGINAL]]<τ_0_0, τ_0_1>([[ADDR]], [[SELF]]) +// CHECK: yield [[ADDR]] +// CHECK-SAME: resume [[NORMAL:bb[0-9]+]] +// CHECK-SAME: unwind [[UNWIND:bb[0-9]+]] +// CHECK: [[NORMAL]]: +// CHECK: destroy_addr [[ADDR]] +// CHECK: dealloc_stack [[ADDR]] +// CHECK: [[RETVAL:%[^,]+]] = tuple () +// CHECK: return [[RETVAL]] +// CHECK: [[UNWIND]]: +// CHECK: destroy_addr [[ADDR]] +// CHECK: dealloc_stack [[ADDR]] +// CHECK: unwind +// CHECK-LABEL: } // end sil function '$s16default_override8OpenBaseC05ownedC5FieldxvyTwd' + read { + Builtin.int_trap() + } +// CHECK-LABEL: sil shared [serialized] [ossa] @$s16default_override8OpenBaseC05ownedC5FieldxvxTwd +// CHECK-SAME: : $@yield_once_2 +// CHECK-SAME: @convention(method) +// CHECK-SAME: <τ_0_0, τ_0_1> +// CHECK-SAME: ( +// CHECK-SAME: @guaranteed OpenBase<τ_0_0, τ_0_1> +// CHECK-SAME: ) +// CHECK-SAME: -> +// CHECK-SAME: @yields @inout τ_0_0 +// CHECK-SAME: { +// CHECK: {{bb[0-9]+}}( +// CHECK-SAME: [[SELF:%[^,]+]] : +// CHECK-SAME: ): +// CHECK: [[ORIGINAL:%[^,]+]] = class_method [[SELF]], #OpenBase.ownedOpenField!modify +// CHECK: (OpenBase) -> () -> () +// CHECK: $@yield_once @convention(method) <τ_0_0, τ_0_1> (@guaranteed OpenBase<τ_0_0, τ_0_1>) -> @yields @inout τ_0_0 +// CHECK: ([[ADDR:%[^,]+]], [[TOKEN:%[^,]+]]) = begin_apply [[ORIGINAL]]<τ_0_0, τ_0_1>([[SELF]]) +// CHECK: yield [[ADDR]] +// CHECK: resume [[NORMAL:bb[0-9]+]] +// CHECK: unwind [[UNWIND:bb[0-9]+]] +// CHECK: [[NORMAL]]: +// CHECK: end_apply [[TOKEN]] +// CHECK: [[RETVAL:%[^,]+]] = tuple () +// CHECK: return [[RETVAL]] +// CHECK: [[UNWIND]]: +// CHECK: abort_apply [[TOKEN]] +// CHECK: unwind +// CHECK-LABEL: } // end sil function '$s16default_override8OpenBaseC05ownedC5FieldxvxTwd' + modify { + Builtin.int_trap() + } + } + open var ownedOpenField2: (T, T) { +// CHECK-LABEL: sil shared [serialized] [ossa] @$s16default_override8OpenBaseC05ownedC6Field2x_xtvyTwd +// CHECK-SAME: : $@yield_once_2 +// CHECK-SAME: @convention(method) +// CHECK-SAME: <τ_0_0, τ_0_1> +// CHECK-SAME: ( +// CHECK-SAME: @guaranteed OpenBase<τ_0_0, τ_0_1> +// CHECK-SAME: ) +// CHECK-SAME: -> +// CHECK-SAME: (@yields @in_guaranteed τ_0_0, @yields @in_guaranteed τ_0_0) +// CHECK-SAME: { +// CHECK: {{bb[0-9]+}}( +// CHECK-SAME: [[SELF:%[^,]+]] : +// CHECK-SAME: ): +// CHECK: [[ORIGINAL:%[^,]+]] = class_method [[SELF]], #OpenBase.ownedOpenField2!getter +// CHECK-SAME: (OpenBase) -> () -> (T, T) +// CHECK-SAME: $@convention(method) <τ_0_0, τ_0_1> (@guaranteed OpenBase<τ_0_0, τ_0_1>) -> (@out τ_0_0, @out τ_0_0) +// CHECK: [[ADDR_1:%[^,]+]] = alloc_stack +// CHECK: [[ADDR_2:%[^,]+]] = alloc_stack +// CHECK: [[EMPTY:%[^,]+]] = apply [[ORIGINAL]]<τ_0_0, τ_0_1>([[ADDR_1]], [[ADDR_2]], [[SELF]]) +// CHECK: yield ([[ADDR_1]], [[ADDR_2]]) +// CHECK-SAME: resume [[NORMAL:bb[0-9]+]] +// CHECK-SAME: unwind [[UNWIND:bb[0-9]+]] +// CHECK: [[NORMAL]]: +// CHECK: destroy_addr [[ADDR_2]] +// CHECK: dealloc_stack [[ADDR_2]] +// CHECK: destroy_addr [[ADDR_1]] +// CHECK: dealloc_stack [[ADDR_1]] +// CHECK: [[RETVAL:%[^,]+]] = tuple () +// CHECK: return [[RETVAL]] +// CHECK: [[UNWIND]]: +// CHECK: destroy_addr [[ADDR_2]] +// CHECK: dealloc_stack [[ADDR_2]] +// CHECK: destroy_addr [[ADDR_1]] +// CHECK: dealloc_stack [[ADDR_1]] +// CHECK: unwind +// CHECK-LABEL: } // end sil function '$s16default_override8OpenBaseC05ownedC6Field2x_xtvyTwd' + read { + Builtin.int_trap() + } +// CHECK-LABEL: sil shared [serialized] [ossa] @$s16default_override8OpenBaseC05ownedC6Field2x_xtvxTwd +// CHECK-SAME: : $@yield_once_2 +// CHECK-SAME: @convention(method) +// CHECK-SAME: <τ_0_0, τ_0_1> +// CHECK-SAME: ( +// CHECK-SAME: @guaranteed OpenBase<τ_0_0, τ_0_1> +// CHECK-SAME: ) +// CHECK-SAME: -> +// CHECK-SAME: @yields @inout (τ_0_0, τ_0_0) +// CHECK-SAME: { +// CHECK: {{bb[0-9]+}}( +// CHECK-SAME: [[SELF:%[^,]+]] : +// CHECK-SAME: ): +// CHECK: [[ORIGINAL:%[^,]+]] = class_method [[SELF]], #OpenBase.ownedOpenField2!modify +// CHECK: (OpenBase) -> () -> () +// CHECK: $@yield_once @convention(method) <τ_0_0, τ_0_1> (@guaranteed OpenBase<τ_0_0, τ_0_1>) -> @yields @inout (τ_0_0, τ_0_0) +// CHECK: ([[ADDR:%[^,]+]], [[TOKEN:%[^,]+]]) = begin_apply [[ORIGINAL]]<τ_0_0, τ_0_1>([[SELF]]) +// CHECK: yield [[ADDR]] +// CHECK: resume [[NORMAL:bb[0-9]+]] +// CHECK: unwind [[UNWIND:bb[0-9]+]] +// CHECK: [[NORMAL]]: +// CHECK: end_apply [[TOKEN]] +// CHECK: [[RETVAL:%[^,]+]] = tuple () +// CHECK: return [[RETVAL]] +// CHECK: [[UNWIND]]: +// CHECK: abort_apply [[TOKEN]] +// CHECK: unwind +// CHECK-LABEL: } // end sil function '$s16default_override8OpenBaseC05ownedC6Field2x_xtvxTwd' + modify { + Builtin.int_trap() + } + } + open var ownedOpenField3: (T, Int) { +// CHECK-LABEL: sil shared [serialized] [ossa] @$s16default_override8OpenBaseC05ownedC6Field3x_SitvyTwd +// CHECK-SAME: : $@yield_once_2 +// CHECK-SAME: @convention(method) +// CHECK-SAME: <τ_0_0, τ_0_1> +// CHECK-SAME: ( +// CHECK-SAME: @guaranteed OpenBase<τ_0_0, τ_0_1> +// CHECK-SAME: ) +// CHECK-SAME: -> +// CHECK-SAME: @yields @in_guaranteed τ_0_0 +// CHECK-SAME: { +// CHECK: {{bb[0-9]+}}( +// CHECK-SAME: [[SELF:%[^,]+]] : +// CHECK-SAME: ): +// CHECK: [[ORIGINAL:%[^,]+]] = class_method [[SELF]], #OpenBase.ownedOpenField3!getter +// CHECK-SAME: (OpenBase) -> () -> (T, Int) +// CHECK-SAME: $@convention(method) <τ_0_0, τ_0_1> (@guaranteed OpenBase<τ_0_0, τ_0_1>) -> (@out τ_0_0, Int) +// CHECK: [[ADDR:%[^,]+]] = alloc_stack +// CHECK: [[INT:%[^,]+]] = apply [[ORIGINAL]]<τ_0_0, τ_0_1>([[ADDR]], [[SELF]]) +// CHECK: yield ([[ADDR]], [[INT]]) +// CHECK-SAME: resume [[NORMAL:bb[0-9]+]] +// CHECK-SAME: unwind [[UNWIND:bb[0-9]+]] +// CHECK: [[NORMAL]]: +// CHECK: destroy_addr [[ADDR]] +// CHECK: dealloc_stack [[ADDR]] +// CHECK: [[RETVAL:%[^,]+]] = tuple () +// CHECK: return [[RETVAL]] +// CHECK: [[UNWIND]]: +// CHECK: destroy_addr [[ADDR]] +// CHECK: dealloc_stack [[ADDR]] +// CHECK: unwind +// CHECK-LABEL: } // end sil function '$s16default_override8OpenBaseC05ownedC6Field3x_SitvyTwd' + read { + Builtin.int_trap() + } +// CHECK-LABEL: sil shared [serialized] [ossa] @$s16default_override8OpenBaseC05ownedC6Field3x_SitvxTwd +// CHECK-SAME: : $@yield_once_2 +// CHECK-SAME: @convention(method) +// CHECK-SAME: <τ_0_0, τ_0_1> +// CHECK-SAME: ( +// CHECK-SAME: @guaranteed OpenBase<τ_0_0, τ_0_1> +// CHECK-SAME: ) +// CHECK-SAME: -> +// CHECK-SAME: @yields @inout (τ_0_0, Int) +// CHECK-SAME: { +// CHECK: {{bb[0-9]+}}( +// CHECK-SAME: [[SELF:%[^,]+]] : +// CHECK-SAME: ): +// CHECK: [[ORIGINAL:%[^,]+]] = class_method [[SELF]], #OpenBase.ownedOpenField3!modify +// CHECK: (OpenBase) -> () -> () +// CHECK: $@yield_once @convention(method) <τ_0_0, τ_0_1> (@guaranteed OpenBase<τ_0_0, τ_0_1>) -> @yields @inout (τ_0_0, Int) +// CHECK: ([[ADDR:%[^,]+]], [[TOKEN:%[^,]+]]) = begin_apply [[ORIGINAL]]<τ_0_0, τ_0_1>([[SELF]]) +// CHECK: yield [[ADDR]] +// CHECK: resume [[NORMAL:bb[0-9]+]] +// CHECK: unwind [[UNWIND:bb[0-9]+]] +// CHECK: [[NORMAL]]: +// CHECK: end_apply [[TOKEN]] +// CHECK: [[RETVAL:%[^,]+]] = tuple () +// CHECK: return [[RETVAL]] +// CHECK: [[UNWIND]]: +// CHECK: abort_apply [[TOKEN]] +// CHECK: unwind +// CHECK-LABEL: } // end sil function '$s16default_override8OpenBaseC05ownedC6Field3x_SitvxTwd' + modify { + Builtin.int_trap() + } + } + open var ownedOpenField4: (String, T) { +// CHECK-LABEL: sil shared [serialized] [ossa] @$s16default_override8OpenBaseC05ownedC6Field4SS_xtvyTwd +// CHECK-SAME: : $@yield_once_2 +// CHECK-SAME: @convention(method) +// CHECK-SAME: <τ_0_0, τ_0_1> +// CHECK-SAME: ( +// CHECK-SAME: @guaranteed OpenBase<τ_0_0, τ_0_1> +// CHECK-SAME: ) +// CHECK-SAME: -> +// CHECK-SAME: (@yields @guaranteed String, @yields @in_guaranteed τ_0_0) +// CHECK-SAME: { +// CHECK: {{bb[0-9]+}}( +// CHECK-SAME: [[SELF:%[^,]+]] : +// CHECK-SAME: ): +// CHECK: [[ORIGINAL:%[^,]+]] = class_method [[SELF]], #OpenBase.ownedOpenField4!getter +// CHECK-SAME: (OpenBase) -> () -> (String, T) +// CHECK-SAME: $@convention(method) <τ_0_0, τ_0_1> (@guaranteed OpenBase<τ_0_0, τ_0_1>) -> (@owned String, @out τ_0_0) +// CHECK: [[ADDR:%[^,]+]] = alloc_stack +// CHECK: [[STRING:%[^,]+]] = apply [[ORIGINAL]]<τ_0_0, τ_0_1>([[ADDR]], [[SELF]]) +// CHECK: yield ([[STRING]], [[ADDR]]) +// CHECK-SAME: resume [[NORMAL:bb[0-9]+]] +// CHECK-SAME: unwind [[UNWIND:bb[0-9]+]] +// CHECK: [[NORMAL]]: +// CHECK: destroy_addr [[ADDR]] +// CHECK: dealloc_stack [[ADDR]] +// CHECK: destroy_value [[STRING]] +// CHECK: [[RETVAL:%[^,]+]] = tuple () +// CHECK: return [[RETVAL]] +// CHECK: [[UNWIND]]: +// CHECK: destroy_addr [[ADDR]] +// CHECK: dealloc_stack [[ADDR]] +// CHECK: destroy_value [[STRING]] +// CHECK: unwind +// CHECK-LABEL: } // end sil function '$s16default_override8OpenBaseC05ownedC6Field4SS_xtvyTwd' + read { + Builtin.int_trap() + } +// CHECK-LABEL: sil shared [serialized] [ossa] @$s16default_override8OpenBaseC05ownedC6Field4SS_xtvxTwd +// CHECK-SAME: : $@yield_once_2 +// CHECK-SAME: @convention(method) +// CHECK-SAME: <τ_0_0, τ_0_1> +// CHECK-SAME: ( +// CHECK-SAME: @guaranteed OpenBase<τ_0_0, τ_0_1> +// CHECK-SAME: ) +// CHECK-SAME: -> +// CHECK-SAME: @yields @inout (String, τ_0_0) +// CHECK-SAME: { +// CHECK: {{bb[0-9]+}}( +// CHECK-SAME: [[SELF:%[^,]+]] : +// CHECK-SAME: ): +// CHECK: [[ORIGINAL:%[^,]+]] = class_method [[SELF]], #OpenBase.ownedOpenField4!modify +// CHECK: (OpenBase) -> () -> () +// CHECK: $@yield_once @convention(method) <τ_0_0, τ_0_1> (@guaranteed OpenBase<τ_0_0, τ_0_1>) -> @yields @inout (String, τ_0_0) +// CHECK: ([[ADDR:%[^,]+]], [[TOKEN:%[^,]+]]) = begin_apply [[ORIGINAL]]<τ_0_0, τ_0_1>([[SELF]]) +// CHECK: yield [[ADDR]] +// CHECK: resume [[NORMAL:bb[0-9]+]] +// CHECK: unwind [[UNWIND:bb[0-9]+]] +// CHECK: [[NORMAL]]: +// CHECK: end_apply [[TOKEN]] +// CHECK: [[RETVAL:%[^,]+]] = tuple () +// CHECK: return [[RETVAL]] +// CHECK: [[UNWIND]]: +// CHECK: abort_apply [[TOKEN]] +// CHECK: unwind +// CHECK-LABEL: } // end sil function '$s16default_override8OpenBaseC05ownedC6Field4SS_xtvxTwd' + modify { + Builtin.int_trap() + } + } + open var ownedOpenField5: (T, U) { +// CHECK-LABEL: sil shared [serialized] [ossa] @$s16default_override8OpenBaseC05ownedC6Field5x_q_tvyTwd +// CHECK-SAME: : $@yield_once_2 +// CHECK-SAME: @convention(method) +// CHECK-SAME: <τ_0_0, τ_0_1> +// CHECK-SAME: ( +// CHECK-SAME: @guaranteed OpenBase<τ_0_0, τ_0_1> +// CHECK-SAME: ) +// CHECK-SAME: -> +// CHECK-SAME: @yields @in_guaranteed τ_0_0 +// CHECK-SAME: { +// CHECK: {{bb[0-9]+}}( +// CHECK-SAME: [[SELF:%[^,]+]] : +// CHECK-SAME: ): +// CHECK: [[ORIGINAL:%[^,]+]] = class_method [[SELF]], #OpenBase.ownedOpenField5!getter +// CHECK-SAME: (OpenBase) -> () -> (T, U) +// CHECK-SAME: $@convention(method) <τ_0_0, τ_0_1> (@guaranteed OpenBase<τ_0_0, τ_0_1>) -> (@out τ_0_0, @out τ_0_1) +// CHECK: [[ADDR_1:%[^,]+]] = alloc_stack +// CHECK: [[ADDR_2:%[^,]+]] = alloc_stack +// CHECK: [[EMPTY:%[^,]+]] = apply [[ORIGINAL]]<τ_0_0, τ_0_1>([[ADDR_1]], [[ADDR_2]], [[SELF]]) +// CHECK: yield ([[ADDR_1]], [[ADDR_2]]) +// CHECK-SAME: resume [[NORMAL:bb[0-9]+]] +// CHECK-SAME: unwind [[UNWIND:bb[0-9]+]] +// CHECK: [[NORMAL]]: +// CHECK: destroy_addr [[ADDR_2]] +// CHECK: dealloc_stack [[ADDR_2]] +// CHECK: destroy_addr [[ADDR_1]] +// CHECK: dealloc_stack [[ADDR_1]] +// CHECK: [[RETVAL:%[^,]+]] = tuple () +// CHECK: return [[RETVAL]] +// CHECK: [[UNWIND]]: +// CHECK: destroy_addr [[ADDR_2]] +// CHECK: dealloc_stack [[ADDR_2]] +// CHECK: destroy_addr [[ADDR_1]] +// CHECK: dealloc_stack [[ADDR_1]] +// CHECK: unwind +// CHECK-LABEL: } // end sil function '$s16default_override8OpenBaseC05ownedC6Field5x_q_tvyTwd' + read { + Builtin.int_trap() + } +// CHECK-LABEL: sil shared [serialized] [ossa] @$s16default_override8OpenBaseC05ownedC6Field5x_q_tvxTwd +// CHECK-SAME: : $@yield_once_2 +// CHECK-SAME: @convention(method) +// CHECK-SAME: <τ_0_0, τ_0_1> +// CHECK-SAME: ( +// CHECK-SAME: @guaranteed OpenBase<τ_0_0, τ_0_1> +// CHECK-SAME: ) +// CHECK-SAME: -> +// CHECK-SAME: @yields @inout (τ_0_0, τ_0_1) +// CHECK-SAME: { +// CHECK: {{bb[0-9]+}}( +// CHECK-SAME: [[SELF:%[^,]+]] : +// CHECK-SAME: ): +// CHECK: [[ORIGINAL:%[^,]+]] = class_method [[SELF]], #OpenBase.ownedOpenField5!modify +// CHECK: (OpenBase) -> () -> () +// CHECK: $@yield_once @convention(method) <τ_0_0, τ_0_1> (@guaranteed OpenBase<τ_0_0, τ_0_1>) -> @yields @inout (τ_0_0, τ_0_1) +// CHECK: ([[ADDR:%[^,]+]], [[TOKEN:%[^,]+]]) = begin_apply [[ORIGINAL]]<τ_0_0, τ_0_1>([[SELF]]) +// CHECK: yield [[ADDR]] +// CHECK: resume [[NORMAL:bb[0-9]+]] +// CHECK: unwind [[UNWIND:bb[0-9]+]] +// CHECK: [[NORMAL]]: +// CHECK: end_apply [[TOKEN]] +// CHECK: [[RETVAL:%[^,]+]] = tuple () +// CHECK: return [[RETVAL]] +// CHECK: [[UNWIND]]: +// CHECK: abort_apply [[TOKEN]] +// CHECK: unwind +// CHECK-LABEL: } // end sil function '$s16default_override8OpenBaseC05ownedC6Field5x_q_tvxTwd' + modify { + Builtin.int_trap() + } + } + open subscript(_ v: V, _ _: Open.Type) -> T { +// CHECK-LABEL: sil shared [serialized] [ossa] @$s16default_override8OpenBaseCyxqd___AA0C0OmtcluiyTwd +// CHECK-SAME: : $@yield_once_2 +// CHECK-SAME: @convention(method) +// CHECK-SAME: <τ_0_0, τ_0_1><τ_1_0> // CHECK-SAME: ( // CHECK-SAME: @in_guaranteed τ_1_0 // CHECK-SAME: @thin Open.Type -// CHECK-SAME: @guaranteed OpenBase<τ_0_0> -// CHECK-SAME: ) -// CHECK-SAME: -> +// CHECK-SAME: @guaranteed OpenBase<τ_0_0, τ_0_1> +// CHECK-SAME: ) +// CHECK-SAME: -> // CHECK-SAME: @yields @in_guaranteed τ_0_0 // CHECK-SAME: { // CHECK: {{bb[0-9]+}}( @@ -106,19 +714,22 @@ open class OpenBase { // CHECK-SAME: [[SELF:%[^,]+]] : // CHECK-SAME: ): // CHECK: [[ORIGINAL:%[^,]+]] = class_method [[SELF]] -// CHECK: #OpenBase.subscript!read -// CHECK: (OpenBase) -> (U, Open.Type) -> () -// CHECK: $@yield_once @convention(method) <τ_0_0><τ_1_0> (@in_guaranteed τ_1_0, @thin Open.Type, @guaranteed OpenBase<τ_0_0>) -> @yields @in_guaranteed τ_0_0 -// CHECK: ([[ADDR:%[^,]+]], [[TOKEN:%[^,]+]]) = begin_apply [[ORIGINAL]]<τ_0_0, τ_1_0>([[KEY]], [[OPEN_TY]], [[SELF]]) +// CHECK: #OpenBase.subscript!getter +// CHECK: (OpenBase) -> (V, Open.Type) -> T +// CHECK: $@convention(method) <τ_0_0, τ_0_1><τ_1_0> (@in_guaranteed τ_1_0, @thin Open.Type, @guaranteed OpenBase<τ_0_0, τ_0_1>) -> @out τ_0_0 +// CHECK: [[ADDR:%[^,]+]] = alloc_stack +// CHECK: [[EMPTY:%[^,]+]] = apply [[ORIGINAL]]<τ_0_0, τ_0_1, τ_1_0>([[ADDR]], [[KEY]], [[OPEN_TY]], [[SELF]]) // CHECK: yield [[ADDR]] // CHECK: resume bb1 // CHECK: unwind bb2 // CHECK: bb1: -// CHECK: end_apply [[TOKEN]] +// CHECK: destroy_addr [[ADDR]] +// CHECK: dealloc_stack [[ADDR]] // CHECK: [[RETVAL:%[^,]+]] = tuple () // CHECK: return [[RETVAL]] // CHECK: bb2: -// CHECK: abort_apply [[TOKEN]] +// CHECK: destroy_addr [[ADDR]] +// CHECK: dealloc_stack [[ADDR]] // CHECK: unwind // CHECK-LABEL: } // end sil function '$s16default_override8OpenBaseCyxqd___AA0C0OmtcluiyTwd' read { @@ -127,13 +738,13 @@ open class OpenBase { // CHECK-LABEL: sil shared [serialized] [ossa] @$s16default_override8OpenBaseCyxqd___AA0C0OmtcluixTwd // CHECK-SAME: : $@yield_once_2 // CHECK-SAME: @convention(method) -// CHECK-SAME: <τ_0_0><τ_1_0> +// CHECK-SAME: <τ_0_0, τ_0_1><τ_1_0> // CHECK-SAME: ( // CHECK-SAME: @in_guaranteed τ_1_0 // CHECK-SAME: @thin Open.Type -// CHECK-SAME: @guaranteed OpenBase<τ_0_0> -// CHECK-SAME: ) -// CHECK-SAME: -> +// CHECK-SAME: @guaranteed OpenBase<τ_0_0, τ_0_1> +// CHECK-SAME: ) +// CHECK-SAME: -> // CHECK-SAME: @yields @inout τ_0_0 // CHECK-SAME: { // CHECK: {{bb[0-9]+}}( @@ -143,9 +754,9 @@ open class OpenBase { // CHECK-SAME: ): // CHECK: [[ORIGINAL:%[^,]+]] = class_method [[SELF]] // CHECK-SAME: #OpenBase.subscript!modify -// CHECK-SAME: (OpenBase) -> (U, Open.Type) -> () -// CHECK-SAME: $@yield_once @convention(method) <τ_0_0><τ_1_0> (@in_guaranteed τ_1_0, @thin Open.Type, @guaranteed OpenBase<τ_0_0>) -> @yields @inout τ_0_0 -// CHECK: ([[ADDR:%[^,]+]], [[TOKEN:%[^,]+]]) = begin_apply [[ORIGINAL]]<τ_0_0, τ_1_0>([[KEY]], [[OPEN_TY]], [[SELF]]) +// CHECK-SAME: (OpenBase) -> (V, Open.Type) -> () +// CHECK-SAME: $@yield_once @convention(method) <τ_0_0, τ_0_1><τ_1_0> (@in_guaranteed τ_1_0, @thin Open.Type, @guaranteed OpenBase<τ_0_0, τ_0_1>) -> @yields @inout τ_0_0 +// CHECK: ([[ADDR:%[^,]+]], [[TOKEN:%[^,]+]]) = begin_apply [[ORIGINAL]]<τ_0_0, τ_0_1, τ_1_0>([[KEY]], [[OPEN_TY]], [[SELF]]) // CHECK: yield [[ADDR]] // CHECK: resume [[NORMAL:bb[0-9]+]] // CHECK: unwind [[UNWIND:bb[0-9]+]] @@ -169,7 +780,7 @@ open class OpenBase { Builtin.int_trap() } } - public subscript(_ u: U, _ _: Public.Type) -> T { + public subscript(_ v: V, _ _: Public.Type) -> T { read { Builtin.int_trap() } @@ -185,7 +796,7 @@ open class OpenBase { Builtin.int_trap() } } - subscript(_ u: U, _ _: Internal.Type) -> T { + subscript(_ v: V, _ _: Internal.Type) -> T { read { Builtin.int_trap() } @@ -195,7 +806,7 @@ open class OpenBase { } } -public class PublicBase { +public class PublicBase { open var openField: T { read { Builtin.int_trap() @@ -204,7 +815,7 @@ public class PublicBase { Builtin.int_trap() } } - open subscript(_ u: U, _ _: Open.Type) -> T { + open subscript(_ v: V, _ _: Open.Type) -> T { read { Builtin.int_trap() } @@ -220,7 +831,7 @@ public class PublicBase { Builtin.int_trap() } } - public subscript(_ u: U, _ _: Public.Type) -> T { + public subscript(_ v: V, _ _: Public.Type) -> T { read { Builtin.int_trap() } @@ -236,7 +847,7 @@ public class PublicBase { Builtin.int_trap() } } - subscript(_ u: U, _ _: Internal.Type) -> T { + subscript(_ v: V, _ _: Internal.Type) -> T { read { Builtin.int_trap() } @@ -246,7 +857,7 @@ public class PublicBase { } } -class InternalBase { +class InternalBase { open var openField: T { read { Builtin.int_trap() @@ -255,7 +866,7 @@ class InternalBase { Builtin.int_trap() } } - open subscript(_ u: U, _ _: Open.Type) -> T { + open subscript(_ v: V, _ _: Open.Type) -> T { read { Builtin.int_trap() } @@ -271,7 +882,7 @@ class InternalBase { Builtin.int_trap() } } - public subscript(_ u: U, _ _: Public.Type) -> T { + public subscript(_ v: V, _ _: Public.Type) -> T { read { Builtin.int_trap() } @@ -287,7 +898,7 @@ class InternalBase { Builtin.int_trap() } } - subscript(_ u: U, _ _: Internal.Type) -> T { + subscript(_ v: V, _ _: Internal.Type) -> T { read { Builtin.int_trap() } @@ -300,24 +911,78 @@ class InternalBase { // CHECK-LABEL: sil_default_override_table OpenBase { // CHECK-NEXT: #OpenBase.openField!read2 // CHECK-SAME: #OpenBase.openField!read -// CHECK-SAME: (OpenBase) -> () -> () +// CHECK-SAME: (OpenBase) -> () -> () // CHECK-SAME: @$s16default_override8OpenBaseC9openFieldxvyTwd // CHECK-NEXT: #OpenBase.openField!modify2 // CHECK-SAME: #OpenBase.openField!modify -// CHECK-SAME: (OpenBase) -> () -> () +// CHECK-SAME: (OpenBase) -> () -> () // CHECK-SAME: @$s16default_override8OpenBaseC9openFieldxvxTwd +// CHECK-NEXT: #OpenBase.openField2!read2 +// CHECK-SAME: #OpenBase.openField2!read: (OpenBase) -> () -> () +// CHECK-SAME: @$s16default_override8OpenBaseC10openField2x_xtvyTwd +// CHECK-NEXT: #OpenBase.openField2!modify2 +// CHECK-SAME: #OpenBase.openField2!modify: (OpenBase) -> () -> () +// CHECK-SAME: @$s16default_override8OpenBaseC10openField2x_xtvxTwd +// CHECK-NEXT: #OpenBase.openField3!read2 +// CHECK-SAME: #OpenBase.openField3!read: (OpenBase) -> () -> () +// CHECK-SAME: @$s16default_override8OpenBaseC10openField3x_SitvyTwd +// CHECK-NEXT: #OpenBase.openField3!modify2 +// CHECK-SAME: #OpenBase.openField3!modify: (OpenBase) -> () -> () +// CHECK-SAME: @$s16default_override8OpenBaseC10openField3x_SitvxTwd +// CHECK-NEXT: #OpenBase.openField4!read2 +// CHECK-SAME: #OpenBase.openField4!read: (OpenBase) -> () -> () +// CHECK-SAME: @$s16default_override8OpenBaseC10openField4SS_xtvyTwd +// CHECK-NEXT: #OpenBase.openField4!modify2 +// CHECK-SAME: #OpenBase.openField4!modify: (OpenBase) -> () -> () +// CHECK-SAME: @$s16default_override8OpenBaseC10openField4SS_xtvxTwd +// CHECK-NEXT: #OpenBase.openField5!read2 +// CHECK-SAME: #OpenBase.openField5!read: (OpenBase) -> () -> () +// CHECK-SAME: @$s16default_override8OpenBaseC10openField5x_q_tvyTwd +// CHECK-NEXT: #OpenBase.openField5!modify2 +// CHECK-SAME: #OpenBase.openField5!modify: (OpenBase) -> () -> () +// CHECK-SAME: @$s16default_override8OpenBaseC10openField5x_q_tvxTwd +// CHECK-NEXT: #OpenBase.ownedOpenField!read2 +// CHECK-SAME: #OpenBase.ownedOpenField!getter: (OpenBase) -> () -> () +// CHECK-SAME: @$s16default_override8OpenBaseC05ownedC5FieldxvyTwd +// CHECK-NEXT: #OpenBase.ownedOpenField!modify2 +// CHECK-SAME: #OpenBase.ownedOpenField!modify: (OpenBase) -> () -> () +// CHECK-SAME: @$s16default_override8OpenBaseC05ownedC5FieldxvxTwd +// CHECK-NEXT: #OpenBase.ownedOpenField2!read2 +// CHECK-SAME: #OpenBase.ownedOpenField2!getter: (OpenBase) -> () -> () +// CHECK-SAME: @$s16default_override8OpenBaseC05ownedC6Field2x_xtvyTwd +// CHECK-NEXT: #OpenBase.ownedOpenField2!modify2 +// CHECK-SAME: #OpenBase.ownedOpenField2!modify: (OpenBase) -> () -> () +// CHECK-SAME: @$s16default_override8OpenBaseC05ownedC6Field2x_xtvxTwd +// CHECK-NEXT: #OpenBase.ownedOpenField3!read2 +// CHECK-SAME: #OpenBase.ownedOpenField3!getter: (OpenBase) -> () -> () +// CHECK-SAME: @$s16default_override8OpenBaseC05ownedC6Field3x_SitvyTwd +// CHECK-NEXT: #OpenBase.ownedOpenField3!modify2 +// CHECK-SAME: #OpenBase.ownedOpenField3!modify: (OpenBase) -> () -> () +// CHECK-SAME: @$s16default_override8OpenBaseC05ownedC6Field3x_SitvxTwd +// CHECK-NEXT: #OpenBase.ownedOpenField4!read2 +// CHECK-SAME: #OpenBase.ownedOpenField4!getter: (OpenBase) -> () -> () +// CHECK-SAME: @$s16default_override8OpenBaseC05ownedC6Field4SS_xtvyTwd +// CHECK-NEXT: #OpenBase.ownedOpenField4!modify2 +// CHECK-SAME: #OpenBase.ownedOpenField4!modify: (OpenBase) -> () -> () +// CHECK-SAME: @$s16default_override8OpenBaseC05ownedC6Field4SS_xtvxTwd +// CHECK-NEXT: #OpenBase.ownedOpenField5!read2 +// CHECK-SAME: #OpenBase.ownedOpenField5!getter: (OpenBase) -> () -> () +// CHECK-SAME: @$s16default_override8OpenBaseC05ownedC6Field5x_q_tvyTwd +// CHECK-NEXT: #OpenBase.ownedOpenField5!modify2 +// CHECK-SAME: #OpenBase.ownedOpenField5!modify: (OpenBase) -> () -> () +// CHECK-SAME: @$s16default_override8OpenBaseC05ownedC6Field5x_q_tvxTwd // CHECK-NEXT: #OpenBase.subscript!read2 -// CHECK-SAME: #OpenBase.subscript!read -// CHECK-SAME: (OpenBase) -> (U, Open.Type) -> () +// CHECK-SAME: #OpenBase.subscript!getter +// CHECK-SAME: (OpenBase) -> (V, Open.Type) -> () // CHECK-SAME: @$s16default_override8OpenBaseCyxqd___AA0C0OmtcluiyTwd // CHECK-NEXT: #OpenBase.subscript!modify2 // CHECK-SAME: #OpenBase.subscript!modify -// CHECK-SAME: (OpenBase) -> (U, Open.Type) -> () +// CHECK-SAME: (OpenBase) -> (V, Open.Type) -> () // CHECK-SAME: @$s16default_override8OpenBaseCyxqd___AA0C0OmtcluixTwd // CHECK-NOT: #OpenBase.publicField!read2 // CHECK-NOT: #OpenBase.publicField!modify2 -// CHECK-NOT: #OpenBase.subscript!read2: #OpenBase.subscript!read: (OpenBase) -> (U, Public.Type) -> () -// CHECK-NOT: #OpenBase.subscript!modify2: #OpenBase.subscript!modify: (OpenBase) -> (U, Public.Type) -> () +// CHECK-NOT: #OpenBase.subscript!read2: #OpenBase.subscript!read: (OpenBase) -> (U, Public.Type) -> () +// CHECK-NOT: #OpenBase.subscript!modify2: #OpenBase.subscript!modify: (OpenBase) -> (U, Public.Type) -> () // CHECK-NEXT: } // CHECK-NOT: sil_default_override_table PublicBase {