diff --git a/include/swift/AST/ExtInfo.h b/include/swift/AST/ExtInfo.h
index f76e0fd36085e..28f30af1d870b 100644
--- a/include/swift/AST/ExtInfo.h
+++ b/include/swift/AST/ExtInfo.h
@@ -537,7 +537,8 @@ class ASTExtInfoBuilder {
DifferentiabilityMaskOffset = 11,
DifferentiabilityMask = 0x7 << DifferentiabilityMaskOffset,
SendingResultMask = 1 << 14,
- NumMaskBits = 15
+ InOutResultMask = 1 << 15,
+ NumMaskBits = 16
};
static_assert(FunctionTypeIsolation::Mask == 0x7, "update mask manually");
@@ -660,6 +661,8 @@ class ASTExtInfoBuilder {
globalActor);
}
+ constexpr bool hasInOutResult() const { return bits & InOutResultMask; }
+
constexpr bool hasSelfParam() const {
switch (getSILRepresentation()) {
case SILFunctionTypeRepresentation::Thick:
@@ -782,6 +785,11 @@ class ASTExtInfoBuilder {
lifetimeDependencies);
}
+ [[nodiscard]] ASTExtInfoBuilder withHasInOutResult() const {
+ return ASTExtInfoBuilder((bits | InOutResultMask), clangTypeInfo,
+ globalActor, thrownError, lifetimeDependencies);
+ }
+
void Profile(llvm::FoldingSetNodeID &ID) const {
ID.AddInteger(bits);
ID.AddPointer(clangTypeInfo.getType());
@@ -877,6 +885,8 @@ class ASTExtInfo {
FunctionTypeIsolation getIsolation() const { return builder.getIsolation(); }
+ constexpr bool hasInOutResult() const { return builder.hasInOutResult(); }
+
/// Helper method for changing the representation.
///
/// Prefer using \c ASTExtInfoBuilder::withRepresentation for chaining.
diff --git a/include/swift/AST/Types.h b/include/swift/AST/Types.h
index b67c7f908819e..169af248f413f 100644
--- a/include/swift/AST/Types.h
+++ b/include/swift/AST/Types.h
@@ -407,7 +407,7 @@ class alignas(1 << TypeAlignInBits) TypeBase
}
protected:
- enum { NumAFTExtInfoBits = 15 };
+ enum { NumAFTExtInfoBits = 16 };
enum { NumSILExtInfoBits = 14 };
// clang-format off
@@ -444,8 +444,7 @@ class alignas(1 << TypeAlignInBits) TypeBase
HasExtInfo : 1,
HasClangTypeInfo : 1,
HasThrownError : 1,
- HasLifetimeDependencies : 1,
- NumParams : 15
+ HasLifetimeDependencies : 1
);
SWIFT_INLINE_BITFIELD_FULL(ArchetypeType, TypeBase, 1+1+16,
@@ -3350,7 +3349,8 @@ END_CAN_TYPE_WRAPPER(DynamicSelfType, Type)
/// represented at the binary level as a single function pointer.
class AnyFunctionType : public TypeBase {
const Type Output;
-
+ uint16_t NumParams;
+
public:
using Representation = FunctionTypeRepresentation;
@@ -3611,8 +3611,8 @@ class AnyFunctionType : public TypeBase {
Bits.AnyFunctionType.HasThrownError = false;
Bits.AnyFunctionType.HasLifetimeDependencies = false;
}
- Bits.AnyFunctionType.NumParams = NumParams;
- assert(Bits.AnyFunctionType.NumParams == NumParams && "Params dropped!");
+ this->NumParams = NumParams;
+ assert(this->NumParams == NumParams && "Params dropped!");
if (Info && CONDITIONAL_ASSERT_enabled()) {
unsigned maxLifetimeTarget = NumParams + 1;
@@ -3650,7 +3650,7 @@ class AnyFunctionType : public TypeBase {
Type getResult() const { return Output; }
ArrayRef getParams() const;
- unsigned getNumParams() const { return Bits.AnyFunctionType.NumParams; }
+ unsigned getNumParams() const { return NumParams; }
GenericSignature getOptGenericSignature() const;
diff --git a/include/swift/Sema/SyntacticElementTarget.h b/include/swift/Sema/SyntacticElementTarget.h
index 674a429ccf7b8..7347b3cb179c7 100644
--- a/include/swift/Sema/SyntacticElementTarget.h
+++ b/include/swift/Sema/SyntacticElementTarget.h
@@ -262,8 +262,9 @@ class SyntacticElementTarget {
unsigned patternBindingIndex, bool bindPatternVarsOneWay);
/// Form an expression target for a ReturnStmt.
- static SyntacticElementTarget
- forReturn(ReturnStmt *returnStmt, Type contextTy, DeclContext *dc);
+ static SyntacticElementTarget forReturn(ReturnStmt *returnStmt,
+ Expr *returnExpr, Type contextTy,
+ DeclContext *dc);
/// Form a target for the preamble of a for-in loop, excluding its where
/// clause and body.
diff --git a/lib/AST/ASTVerifier.cpp b/lib/AST/ASTVerifier.cpp
index 039f5db5bd67b..dca0ef13b3bd1 100644
--- a/lib/AST/ASTVerifier.cpp
+++ b/lib/AST/ASTVerifier.cpp
@@ -1097,9 +1097,15 @@ class Verifier : public ASTWalker {
void verifyChecked(ReturnStmt *S) {
auto func = Functions.back();
Type resultType;
+ bool hasInOutResult = false;
+
if (auto *FD = dyn_cast(func)) {
resultType = FD->getResultInterfaceType();
resultType = FD->mapTypeIntoContext(resultType);
+ hasInOutResult = FD->getInterfaceType()
+ ->castTo()
+ ->getExtInfo()
+ .hasInOutResult();
} else if (auto closure = dyn_cast(func)) {
resultType = closure->getResultType();
} else if (isa(func)) {
@@ -1112,6 +1118,9 @@ class Verifier : public ASTWalker {
auto result = S->getResult();
auto returnType = result->getType();
// Make sure that the return has the same type as the function.
+ if (hasInOutResult) {
+ resultType = InOutType::get(resultType);
+ }
checkSameType(resultType, returnType, "return type");
} else {
// Make sure that the function has a Void result type.
diff --git a/lib/ASTGen/Sources/ASTGen/SourceFile.swift b/lib/ASTGen/Sources/ASTGen/SourceFile.swift
index cfe23e0be7318..b6823c5a5f944 100644
--- a/lib/ASTGen/Sources/ASTGen/SourceFile.swift
+++ b/lib/ASTGen/Sources/ASTGen/SourceFile.swift
@@ -86,6 +86,7 @@ extension Parser.ExperimentalFeatures {
mapFeature(.OldOwnershipOperatorSpellings, to: .oldOwnershipOperatorSpellings)
mapFeature(.KeyPathWithMethodMembers, to: .keypathWithMethodMembers)
mapFeature(.DefaultIsolationPerFile, to: .defaultIsolationPerFile)
+ mapFeature(.BorrowAndMutateAccessors, to: .borrowAndMutateAccessors)
}
}
diff --git a/lib/SIL/IR/SILFunctionType.cpp b/lib/SIL/IR/SILFunctionType.cpp
index ef314cc6a3531..d7981cc106d0e 100644
--- a/lib/SIL/IR/SILFunctionType.cpp
+++ b/lib/SIL/IR/SILFunctionType.cpp
@@ -1377,6 +1377,22 @@ class Conventions {
}
};
+static bool isBorrowAccessor(std::optional constant) {
+ if (!constant || !constant->hasDecl())
+ return false;
+
+ auto accessor = dyn_cast(constant->getDecl());
+ return accessor && accessor->isBorrowAccessor();
+}
+
+static bool isMutateAccessor(std::optional constant) {
+ if (!constant || !constant->hasDecl())
+ return false;
+
+ auto accessor = dyn_cast(constant->getDecl());
+ return accessor && accessor->isMutateAccessor();
+}
+
/// A visitor for breaking down formal result types into a SILResultInfo
/// and possibly some number of indirect-out SILParameterInfos,
/// matching the abstraction patterns of the original type.
@@ -1386,22 +1402,21 @@ class DestructureResults {
SmallVectorImpl &Results;
TypeExpansionContext context;
bool hasSendingResult;
- bool isBorrowOrMutateAccessor;
+ std::optional constant;
public:
DestructureResults(TypeExpansionContext context, TypeConverter &TC,
const Conventions &conventions,
SmallVectorImpl &results,
- bool hasSendingResult, bool isBorrowOrMutateAccessor)
+ bool hasSendingResult, std::optional constant)
: TC(TC), Convs(conventions), Results(results), context(context),
- hasSendingResult(hasSendingResult),
- isBorrowOrMutateAccessor(isBorrowOrMutateAccessor) {}
+ hasSendingResult(hasSendingResult), constant(constant) {}
void destructure(AbstractionPattern origType, CanType substType) {
// Recur into tuples.
// Do not explode tuples for borrow and mutate accessors since we cannot
// explode and reconstruct addresses.
- if (origType.isTuple() && !isBorrowOrMutateAccessor) {
+ if (origType.isTuple() && !isBorrowAccessor(constant)) {
origType.forEachTupleElement(substType,
[&](TupleElementGenerator &elt) {
// If the original element type is not a pack expansion, just
@@ -1411,7 +1426,7 @@ class DestructureResults {
return;
}
- if (isBorrowOrMutateAccessor) {
+ if (isBorrowAccessor(constant)) {
llvm_unreachable(
"Returning packs from borrow/mutate accessor is not implemented");
}
@@ -1448,17 +1463,17 @@ class DestructureResults {
// Determine the result convention.
ResultConvention convention;
- if (isBorrowOrMutateAccessor) {
+ if (isBorrowAccessor(constant)) {
if (substResultTL.isTrivial()) {
convention = ResultConvention::Unowned;
} else if (isFormallyReturnedIndirectly(origType, substType,
substResultTLForConvention)) {
- assert(Convs.getResult(substResultTLForConvention) ==
- ResultConvention::Guaranteed);
convention = ResultConvention::GuaranteedAddress;
} else {
convention = ResultConvention::Guaranteed;
}
+ } else if (isMutateAccessor(constant)) {
+ convention = ResultConvention::GuaranteedAddress;
} else if (isFormallyReturnedIndirectly(origType, substType,
substResultTLForConvention)) {
convention = ResultConvention::Indirect;
@@ -2368,17 +2383,6 @@ getAsCoroutineAccessor(std::optional constant) {
return accessor;
}
-static bool isBorrowOrMutateAccessor(std::optional constant) {
- if (!constant || !constant->hasDecl())
- return false;
-
- auto accessor = dyn_cast(constant->getDecl());
- if (!accessor)
- return false;
-
- return accessor->isBorrowAccessor() || accessor->isMutateAccessor();
-}
-
static void destructureYieldsForReadAccessor(TypeConverter &TC,
TypeExpansionContext expansion,
AbstractionPattern origType,
@@ -2728,8 +2732,7 @@ static CanSILFunctionType getSILFunctionType(
SmallVector results;
{
DestructureResults destructurer(expansionContext, TC, conventions, results,
- hasSendingResult,
- isBorrowOrMutateAccessor(constant));
+ hasSendingResult, constant);
destructurer.destructure(origResultType, substFormalResultType);
}
@@ -3277,11 +3280,6 @@ static CanSILFunctionType getNativeSILFunctionType(
TC, context, origType, substInterfaceType, extInfoBuilder,
DefaultSetterConventions(), *constant);
}
- if (constant->isBorrowAccessor()) {
- return getSILFunctionTypeForConventions(
- DefaultConventions(NormalParameterConvention::Guaranteed,
- ResultConvention::Guaranteed));
- }
}
return getSILFunctionTypeForConventions(
DefaultConventions(NormalParameterConvention::Guaranteed));
diff --git a/lib/SILGen/SILGenApply.cpp b/lib/SILGen/SILGenApply.cpp
index 9493f7ae886b8..aeee55e000354 100644
--- a/lib/SILGen/SILGenApply.cpp
+++ b/lib/SILGen/SILGenApply.cpp
@@ -5225,7 +5225,7 @@ class CallEmission {
CleanupHandle applyCoroutine(SmallVectorImpl &yields);
- ManagedValue applyBorrowAccessor();
+ ManagedValue applyBorrowMutateAccessor();
RValue apply(SGFContext C = SGFContext()) {
initialWritebackScope.verify();
@@ -5426,7 +5426,7 @@ CleanupHandle SILGenFunction::emitBeginApply(
return endApplyHandle;
}
-ManagedValue CallEmission::applyBorrowAccessor() {
+ManagedValue CallEmission::applyBorrowMutateAccessor() {
auto origFormalType = callee.getOrigFormalType();
// Get the callee type information.
auto calleeTypeInfo = callee.getTypeInfo(SGF);
@@ -5453,14 +5453,14 @@ ManagedValue CallEmission::applyBorrowAccessor() {
lookThroughMoveOnlyCheckerPattern(selfArgMV.getValue()));
}
- auto value = SGF.applyBorrowAccessor(uncurriedLoc.value(), fnValue, canUnwind,
- callee.getSubstitutions(), uncurriedArgs,
- calleeTypeInfo.substFnType, options);
+ auto value = SGF.applyBorrowMutateAccessor(
+ uncurriedLoc.value(), fnValue, canUnwind, callee.getSubstitutions(),
+ uncurriedArgs, calleeTypeInfo.substFnType, options);
return value;
}
-ManagedValue SILGenFunction::applyBorrowAccessor(
+ManagedValue SILGenFunction::applyBorrowMutateAccessor(
SILLocation loc, ManagedValue fn, bool canUnwind, SubstitutionMap subs,
ArrayRef args, CanSILFunctionType substFnType,
ApplyOptions options) {
@@ -7888,7 +7888,7 @@ SILGenFunction::emitCoroutineAccessor(SILLocation loc, SILDeclRef accessor,
return endApplyHandle;
}
-ManagedValue SILGenFunction::emitBorrowAccessor(
+ManagedValue SILGenFunction::emitBorrowMutateAccessor(
SILLocation loc, SILDeclRef accessor, SubstitutionMap substitutions,
ArgumentSource &&selfValue, bool isSuper, bool isDirectUse,
PreparedArguments &&subscriptIndices, bool isOnSelfParameter) {
@@ -7913,7 +7913,7 @@ ManagedValue SILGenFunction::emitBorrowAccessor(
emission.setCanUnwind(false);
- return emission.applyBorrowAccessor();
+ return emission.applyBorrowMutateAccessor();
}
ManagedValue SILGenFunction::emitAsyncLetStart(
diff --git a/lib/SILGen/SILGenFunction.h b/lib/SILGen/SILGenFunction.h
index 7f254b17d9864..504f50cbbbdae 100644
--- a/lib/SILGen/SILGenFunction.h
+++ b/lib/SILGen/SILGenFunction.h
@@ -2079,18 +2079,18 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction
SmallVectorImpl &yields,
bool isOnSelfParameter);
- ManagedValue emitBorrowAccessor(SILLocation loc, SILDeclRef accessor,
- SubstitutionMap substitutions,
- ArgumentSource &&selfValue, bool isSuper,
- bool isDirectUse,
- PreparedArguments &&subscriptIndices,
- bool isOnSelfParameter);
-
- ManagedValue applyBorrowAccessor(SILLocation loc, ManagedValue fn,
- bool canUnwind, SubstitutionMap subs,
- ArrayRef args,
- CanSILFunctionType substFnType,
- ApplyOptions options);
+ ManagedValue emitBorrowMutateAccessor(SILLocation loc, SILDeclRef accessor,
+ SubstitutionMap substitutions,
+ ArgumentSource &&selfValue,
+ bool isSuper, bool isDirectUse,
+ PreparedArguments &&subscriptIndices,
+ bool isOnSelfParameter);
+
+ ManagedValue applyBorrowMutateAccessor(SILLocation loc, ManagedValue fn,
+ bool canUnwind, SubstitutionMap subs,
+ ArrayRef args,
+ CanSILFunctionType substFnType,
+ ApplyOptions options);
RValue emitApplyConversionFunction(SILLocation loc,
Expr *funcExpr,
diff --git a/lib/SILGen/SILGenLValue.cpp b/lib/SILGen/SILGenLValue.cpp
index 4d99d47ebac2c..9a24b81873af8 100644
--- a/lib/SILGen/SILGenLValue.cpp
+++ b/lib/SILGen/SILGenLValue.cpp
@@ -1255,6 +1255,11 @@ namespace {
if (!base.getType().isLoadable(SGF.F)) {
return base;
}
+
+ if (base.getValue()->getType().isTrivial(SGF.F)) {
+ return SGF.B.createLoadTrivial(loc, base);
+ }
+
auto result = SGF.B.createLoadBorrow(loc, base.getValue());
// Mark the load_borrow as unchecked. We can't stop the source code from
// trying to mutate or consume the same lvalue during this borrow, so
@@ -2286,15 +2291,16 @@ namespace {
namespace {
/// A physical component which involves calling borrow accessors.
-class BorrowAccessorComponent
+class BorrowMutateAccessorComponent
: public AccessorBasedComponent {
public:
- BorrowAccessorComponent(AbstractStorageDecl *decl, SILDeclRef accessor,
- bool isSuper, bool isDirectAccessorUse,
- SubstitutionMap substitutions, CanType baseFormalType,
- LValueTypeData typeData,
- ArgumentList *argListForDiagnostics,
- PreparedArguments &&indices, bool isOnSelfParameter)
+ BorrowMutateAccessorComponent(AbstractStorageDecl *decl, SILDeclRef accessor,
+ bool isSuper, bool isDirectAccessorUse,
+ SubstitutionMap substitutions,
+ CanType baseFormalType, LValueTypeData typeData,
+ ArgumentList *argListForDiagnostics,
+ PreparedArguments &&indices,
+ bool isOnSelfParameter)
: AccessorBasedComponent(BorrowMutateKind, decl, accessor, isSuper,
isDirectAccessorUse, substitutions,
baseFormalType, typeData, argListForDiagnostics,
@@ -2311,14 +2317,14 @@ class BorrowAccessorComponent
ManagedValue result;
auto args = std::move(*this).prepareAccessorArgs(SGF, loc, base, Accessor);
- auto value = SGF.emitBorrowAccessor(
+ auto value = SGF.emitBorrowMutateAccessor(
loc, Accessor, Substitutions, std::move(args.base), IsSuper,
IsDirectAccessorUse, std::move(args.Indices), IsOnSelfParameter);
return value;
}
void dump(raw_ostream &OS, unsigned indent) const override {
- printBase(OS, indent, "BorrowAccessorComponent");
+ printBase(OS, indent, "BorrowMutateAccessorComponent");
}
};
} // namespace
@@ -3427,16 +3433,15 @@ namespace {
AccessKind, FormalRValueType);
return asImpl().emitUsingInitAccessor(accessor, isDirect, typeData);
}
- case AccessorKind::Borrow: {
+ case AccessorKind::Borrow:
+ case AccessorKind::Mutate: {
auto typeData = getPhysicalStorageTypeData(
SGF.getTypeExpansionContext(), SGF.SGM, AccessKind, Storage, Subs,
FormalRValueType);
- return asImpl().emitUsingBorrowAccessor(accessor, isDirect, typeData);
+ return asImpl().emitUsingBorrowMutateAccessor(accessor, isDirect,
+ typeData);
}
- case AccessorKind::Mutate:
- llvm_unreachable("mutate accessor is not yet implemented");
}
-
llvm_unreachable("bad kind");
}
};
@@ -3526,9 +3531,9 @@ void LValue::addNonMemberVarComponent(
PreparedArguments(), /*isOnSelfParameter*/ false);
}
- void emitUsingBorrowAccessor(SILDeclRef accessor, bool isDirect,
- LValueTypeData typeData) {
- llvm_unreachable("borrow accessor is not implemented");
+ void emitUsingBorrowMutateAccessor(SILDeclRef accessor, bool isDirect,
+ LValueTypeData typeData) {
+ llvm_unreachable("borrow/mutate accessor is not implemented");
}
void emitUsingGetterSetter(SILDeclRef accessor,
@@ -3584,7 +3589,8 @@ void LValue::addNonMemberVarComponent(
std::optional enforcement;
if (!Storage->isLet()) {
- if (Options.IsNonAccessing) {
+ if (Options.IsNonAccessing || Options.ForGuaranteedReturn ||
+ Options.ForGuaranteedAddressReturn) {
enforcement = std::nullopt;
} else if (Storage->getDeclContext()->isLocalContext()) {
enforcement = SGF.getUnknownEnforcement(Storage);
@@ -4211,10 +4217,10 @@ struct MemberStorageAccessEmitter : AccessEmitter {
ArgListForDiagnostics, std::move(Indices), IsOnSelfParameter);
}
- void emitUsingBorrowAccessor(SILDeclRef accessor, bool isDirect,
- LValueTypeData typeData) {
+ void emitUsingBorrowMutateAccessor(SILDeclRef accessor, bool isDirect,
+ LValueTypeData typeData) {
assert(!ActorIso);
- LV.add(
+ LV.add(
Storage, accessor, IsSuper, isDirect, Subs, BaseFormalType, typeData,
ArgListForDiagnostics, std::move(Indices), IsOnSelfParameter);
}
@@ -5706,7 +5712,8 @@ std::optional
SILGenFunction::tryEmitProjectedLValue(SILLocation loc, LValue &&src,
TSanKind tsanKind) {
assert(src.getAccessKind() == SGFAccessKind::BorrowedAddressRead ||
- src.getAccessKind() == SGFAccessKind::BorrowedObjectRead);
+ src.getAccessKind() == SGFAccessKind::BorrowedObjectRead ||
+ src.getAccessKind() == SGFAccessKind::Write);
for (auto component = src.begin(); component != src.end(); component++) {
if (component->get()->getKind() != PathComponent::BorrowMutateKind &&
diff --git a/lib/SILGen/SILGenStmt.cpp b/lib/SILGen/SILGenStmt.cpp
index 97db94e7072c6..3b2acae1a78a2 100644
--- a/lib/SILGen/SILGenStmt.cpp
+++ b/lib/SILGen/SILGenStmt.cpp
@@ -726,8 +726,8 @@ SILValue SILGenFunction::emitUncheckedGuaranteedConversion(SILValue value) {
bool SILGenFunction::emitGuaranteedReturn(
SILLocation loc, Expr *ret, SmallVectorImpl &directResults) {
auto *afd = cast(FunctionDC->getAsDecl());
- assert(cast(afd)->isBorrowAccessor());
-
+ assert(cast(afd)->isBorrowAccessor() ||
+ cast(afd)->isMutateAccessor());
auto emitLoadBorrowFromGuaranteedAddress =
[&](ManagedValue guaranteedAddress) -> SILValue {
@@ -762,13 +762,25 @@ bool SILGenFunction::emitGuaranteedReturn(
// Emit return value at +0.
FormalEvaluationScope scope(*this);
LValueOptions options;
+
+ if (cast(afd)->isMutateAccessor()) {
+ options = options.forGuaranteedAddressReturn(true);
+ } else {
+ assert(cast(afd)->isBorrowAccessor());
+ if (F.getSelfArgument()->getType().isObject()) {
+ options = options.forGuaranteedReturn(true);
+ } else {
+ options = options.forGuaranteedAddressReturn(true);
+ }
+ }
+
auto lvalue = emitLValue(ret,
F.getSelfArgument()->getType().isObject()
? SGFAccessKind::BorrowedObjectRead
- : SGFAccessKind::BorrowedAddressRead,
- F.getSelfArgument()->getType().isObject()
- ? options.forGuaranteedReturn(true)
- : options.forGuaranteedAddressReturn(true));
+ : cast(afd)->isBorrowAccessor()
+ ? SGFAccessKind::BorrowedAddressRead
+ : SGFAccessKind::Write,
+ options);
// If the accessor is annotated with @_unsafeSelfDependentResultAttr,
// disable diagnosing the return expression.
@@ -793,7 +805,7 @@ bool SILGenFunction::emitGuaranteedReturn(
// }
if (afd->getAttrs().hasAttribute()) {
auto regularLoc = RegularLocation::getAutoGeneratedLocation();
- auto resultMV = emitBorrowedLValue(regularLoc, std::move(lvalue));
+ auto resultMV = emitRawProjectedLValue(regularLoc, std::move(lvalue));
SILValue result = resultMV.getValue();
if (resultMV.getType().isAddress() &&
F.getConventions().hasGuaranteedResult()) {
diff --git a/lib/Sema/SyntacticElementTarget.cpp b/lib/Sema/SyntacticElementTarget.cpp
index 1984908b9f2d9..6aa7a9e33cdcd 100644
--- a/lib/Sema/SyntacticElementTarget.cpp
+++ b/lib/Sema/SyntacticElementTarget.cpp
@@ -170,13 +170,14 @@ SyntacticElementTarget SyntacticElementTarget::forInitialization(
return result;
}
-SyntacticElementTarget
-SyntacticElementTarget::forReturn(ReturnStmt *returnStmt, Type contextTy,
- DeclContext *dc) {
+SyntacticElementTarget SyntacticElementTarget::forReturn(ReturnStmt *returnStmt,
+ Expr *returnExpr,
+ Type contextTy,
+ DeclContext *dc) {
assert(contextTy);
assert(returnStmt->hasResult() && "Must have result to be type-checked");
ContextualTypeInfo contextInfo(contextTy, CTP_ReturnStmt);
- SyntacticElementTarget target(returnStmt->getResult(), dc, contextInfo,
+ SyntacticElementTarget target(returnExpr, dc, contextInfo,
/*isDiscarded*/ false);
target.expression.parentReturnStmt = returnStmt;
return target;
diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp
index b91c36536f66b..38b5e6f246f9f 100644
--- a/lib/Sema/TypeCheckDecl.cpp
+++ b/lib/Sema/TypeCheckDecl.cpp
@@ -2060,8 +2060,7 @@ ResultTypeRequest::evaluate(Evaluator &evaluator, ValueDecl *decl) const {
return TupleType::getEmpty(ctx);
case AccessorKind::Mutate:
- // TODO: Temporary result representation for mutate accessors.
- return InOutType::get(storage->getValueInterfaceType());
+ return storage->getValueInterfaceType();
// Addressor result types can get complicated because of the owner.
case AccessorKind::Address:
@@ -2591,7 +2590,10 @@ InterfaceTypeRequest::evaluate(Evaluator &eval, ValueDecl *D) const {
selfInfoBuilder =
selfInfoBuilder.withLifetimeDependencies(*lifetimeDependenceInfo);
}
-
+ auto *accessor = dyn_cast(AFD);
+ if (accessor && accessor->isMutateAccessor()) {
+ selfInfoBuilder = selfInfoBuilder.withHasInOutResult();
+ }
// FIXME: Verify ExtInfo state is correct, not working by accident.
auto selfInfo = selfInfoBuilder.build();
if (sig) {
diff --git a/lib/Sema/TypeCheckStmt.cpp b/lib/Sema/TypeCheckStmt.cpp
index b1fe8cf1e426c..f762d99a4768e 100644
--- a/lib/Sema/TypeCheckStmt.cpp
+++ b/lib/Sema/TypeCheckStmt.cpp
@@ -1112,8 +1112,26 @@ class StmtChecker : public StmtVisitor {
return RS;
}
+ auto *accessor = TheFunc->getAccessorDecl();
+ auto *exprToCheck = RS->getResult();
+ InOutExpr *inout = nullptr;
+
+ if (accessor && accessor->isMutateAccessor()) {
+ // Check that the returned expression is a &.
+ if ((inout = dyn_cast(exprToCheck))) {
+ ResultTy = InOutType::get(ResultTy);
+ } else {
+ getASTContext()
+ .Diags
+ .diagnose(exprToCheck->getLoc(), diag::missing_address_of_return)
+ .highlight(exprToCheck->getSourceRange());
+ inout = new (getASTContext()) InOutExpr(
+ exprToCheck->getStartLoc(), exprToCheck, Type(), /*implicit*/ true);
+ }
+ }
using namespace constraints;
- auto target = SyntacticElementTarget::forReturn(RS, ResultTy, DC);
+ auto target =
+ SyntacticElementTarget::forReturn(RS, exprToCheck, ResultTy, DC);
auto resultTarget = TypeChecker::typeCheckTarget(target);
if (resultTarget) {
RS->setResult(resultTarget->getAsExpr());
diff --git a/test/SIL/borrow_accessor_e2e.swift b/test/SIL/borrow_accessor_e2e.swift
index 2a4e497d42489..13c29288ea8ca 100644
--- a/test/SIL/borrow_accessor_e2e.swift
+++ b/test/SIL/borrow_accessor_e2e.swift
@@ -7,7 +7,7 @@
// REQUIRES: executable_test
public struct Container: ~Copyable {
- var _storage: UnsafeBufferPointer
+ var _storage: UnsafeMutableBufferPointer
var _count: Int
var first: Element {
@@ -15,6 +15,10 @@ public struct Container: ~Copyable {
borrow {
return _storage.baseAddress.unsafelyUnwrapped.pointee
}
+ @_unsafeSelfDependentResult
+ mutate {
+ return &_storage.baseAddress.unsafelyUnwrapped.pointee
+ }
}
public subscript(index: Int) -> Element {
@@ -23,6 +27,11 @@ public struct Container: ~Copyable {
precondition(index >= 0 && index < _count, "Index out of bounds")
return _storage.baseAddress.unsafelyUnwrapped.advanced(by: index).pointee
}
+ @_unsafeSelfDependentResult
+ mutate {
+ precondition(index >= 0 && index < _count, "Index out of bounds")
+ return &_storage.baseAddress.unsafelyUnwrapped.advanced(by: index).pointee
+ }
}
}
@@ -30,9 +39,10 @@ extension Container: Copyable where Element: Copyable {}
func test() {
let n = 10_000
- let arr = Array(0...n)
- let sum = arr.withUnsafeBufferPointer { ubpointer in
- let container = Container(_storage: ubpointer, _count: arr.count)
+ var arr = Array(0...n)
+ let count = arr.count
+ let sum = arr.withUnsafeMutableBufferPointer { ubpointer in
+ let container = Container(_storage: ubpointer, _count: count)
var sum = 0
for i in 0.. Klass {
- return Klass()
-}
+public struct NC : ~Copyable {}
func use(_ t: Klass) {}
-public struct NC : ~Copyable {}
-
func use(_ t: borrowing NC) {}
-func consume(_ t: consuming T) {}
-
public struct S {
var _k: Klass
- var borrowKlass: Klass {
+ var k: Klass {
borrow {
return _k
}
- }
- var getKlass: Klass {
- get {
- return _k
- }
- }
- var readKlass: Klass {
- _read {
- yield _k
+ mutate {
+ return &_k
}
}
}
@@ -46,17 +31,8 @@ public struct Wrapper {
borrow {
return _s
}
- }
-
- var s_get: S {
- get {
- return _s
- }
- }
-
- var s_read: S {
- _read {
- yield _s
+ mutate {
+ return &_s
}
}
@@ -64,101 +40,44 @@ public struct Wrapper {
borrow {
return _k
}
- }
-
- var k_complex: Klass {
- borrow {
- consume(self)
- consume(_k)
- return _k
- }
- }
-
- var nested_borrow: Klass {
- borrow {
- return _s.borrowKlass
- }
- }
-
- var nested_get1: Klass {
- borrow {
- return _s.getKlass // expected-error{{invalid return value from borrow accessor}} // expected-note{{borrow accessors can return either literals, stored properties or computed properties that have borrow accessors}}
- }
- }
-
- var nested_get2: Klass {
- borrow {
- return s_get.borrowKlass // expected-error{{invalid return value from borrow accessor}} // expected-note{{borrow accessors can return either literals, stored properties or computed properties that have borrow accessors}}
+ mutate {
+ return &_k
}
}
- var nested_get3: Int {
+ var nested_borrow1: Klass {
borrow {
- return _s.getKlass.id
+ return _s.k
}
- }
-
- var nested_get4: Int {
- borrow {
- return s_get.borrowKlass.id
- }
- }
-
- var nested_read1: Klass {
- borrow {
- return _s.readKlass // expected-error{{invalid return value from borrow accessor}} // expected-note{{borrow accessors can return either literals, stored properties or computed properties that have borrow accessors}}
- }
- }
-
- var nested_read2: Klass {
- borrow {
- return s_read.readKlass // expected-error{{invalid return value from borrow accessor}} // expected-note{{borrow accessors can return either literals, stored properties or computed properties that have borrow accessors}}
+ mutate {
+ return &s._k
}
}
- var owned_value_direct: Klass {
- borrow {
- return getKlass() // expected-error{{invalid return value from borrow accessor}} // expected-note{{borrow accessors can return either literals, stored properties or computed properties that have borrow accessors}}
- }
- }
-
- var owned_value_projected: Klass {
- borrow {
- let w = Wrapper(_k: Klass(), _s: S(_k: Klass()))
- return w.k // expected-error{{invalid return value from borrow accessor}} // expected-note{{borrow accessors can return either literals, stored properties or computed properties that have borrow accessors}}
- }
- }
-
- var nested: Klass {
+ var nested_borrow2: Klass {
borrow {
return k
}
+ mutate {
+ return &_k
+ }
}
subscript(index: Int) -> Klass {
borrow {
return _k
}
+ mutate {
+ return &_k
+ }
}
-
+
var nested_subscript: Klass {
borrow {
return self[0]
}
- }
-
- var if_klass: Klass {
- borrow {
- if Int.random(in: 1..<100) == 0 {
- return _k
- }
- return _k // expected-error{{multiple return statements in borrow accessors are not yet supported}}
- }
- }
-
- var tuple_klass: (Klass, Klass) {
- borrow {
- return (_k, _k) // expected-error{{invalid return value from borrow accessor}} // expected-note{{borrow accessors can return either literals, stored properties or computed properties that have borrow accessors}}
+ mutate {
+ return &self[0]
}
}
@@ -167,35 +86,17 @@ public struct Wrapper {
return 0
}
}
-
- var opt_klass: Klass? {
- borrow {
- if Int.random(in: 1..<100) == 0 {
- return nil
- }
- return _k // expected-error{{invalid return value from borrow accessor}} // expected-note{{borrow accessors can return either literals, stored properties or computed properties that have borrow accessors}}
- }
- }
}
public struct SimpleWrapper {
var _prop: T
- var borrow_prop: T {
+ var prop: T {
borrow {
return _prop
}
- }
-
- var get_prop: T {
- get {
- return _prop
- }
- }
-
- var read_prop: T {
- _read {
- yield _prop
+ mutate {
+ return &_prop
}
}
}
@@ -203,61 +104,69 @@ public struct SimpleWrapper {
public struct GenWrapper {
var _prop: T
var _w: SimpleWrapper
- var _klass: Klass
+ var _k: Klass
var _s: S
public var prop: T {
borrow {
- return _prop
+ return _prop
}
- }
-
- var nested_prop: T {
- borrow {
- return _w.borrow_prop
+ mutate {
+ return &_prop
}
}
- var get_prop: T {
+ var s: S {
borrow {
- return _w.get_prop // expected-error{{invalid return value from borrow accessor}} // expected-note{{borrow accessors can return either literals, stored properties or computed properties that have borrow accessors}}
-
+ return _s
}
- }
-
- var read_prop: T {
- borrow {
- return _w.read_prop // expected-error{{invalid return value from borrow accessor}} // expected-note{{borrow accessors can return either literals, stored properties or computed properties that have borrow accessors}}
+ mutate {
+ return &_s
}
}
-
- var s: S {
+
+ var k: Klass {
borrow {
- return _s
+ return _k
+ }
+ mutate {
+ return &_k
}
}
- var nested: T {
+ var nested_prop1: T {
borrow {
- return prop
+ return _w.prop
+ }
+ mutate {
+ return &_w.prop
}
}
- var klass: Klass {
+ var nested_prop2: T {
borrow {
- return _klass
+ return prop
+ }
+ mutate {
+ return &prop
}
}
- var nested_klass1: Klass {
+ var nested_k1: Klass {
borrow {
- return _s.borrowKlass
+ return _s.k
+ }
+ mutate {
+ return &_s.k
}
}
- var nested_klass2: Klass {
+ var nested_k2: Klass {
borrow {
- return s.borrowKlass
+ return s.k
+ }
+ mutate {
+ return &s.k
}
}
@@ -265,26 +174,17 @@ public struct GenWrapper {
borrow {
return _prop
}
+ mutate {
+ return &_prop
+ }
}
-
+
var nested_subscript: T {
borrow {
return self[0]
}
- }
-
- var if_prop: T {
- borrow {
- if Int.random(in: 1..<100) == 0 {
- return _prop
- }
- return _prop // expected-error{{multiple return statements in borrow accessors are not yet supported}}
- }
- }
-
- var tuple_prop: (T, T) {
- borrow {
- return (_prop, _prop) // expected-error{{invalid return value from borrow accessor}} // expected-note{{borrow accessors can return either literals, stored properties or computed properties that have borrow accessors}}
+ mutate {
+ return &self[0]
}
}
@@ -293,181 +193,175 @@ public struct GenWrapper {
return 0
}
}
-
- var opt_T: T? {
- borrow {
- if Int.random(in: 1..<100) == 0 {
- return nil
- }
- return _prop // expected-error{{invalid return value from borrow accessor}} // expected-note{{borrow accessors can return either literals, stored properties or computed properties that have borrow accessors}}
-
- }
- }
}
-public struct SimpleNCWrapper : ~Copyable {
- var _prop: T
+public struct NCS: ~Copyable {
+ var _nc: NC
- var borrow_prop: T {
+ var nc: NC {
borrow {
- return _prop
- }
- }
-
- var get_prop: T {
- get {
- return _prop
+ return _nc
}
- }
-
- var read_prop: T {
- _read {
- yield _prop
+ mutate {
+ return &_nc
}
}
}
-public struct GenNCWrapper : ~Copyable {
- var _prop: T
- var _w: SimpleNCWrapper
+public struct NCWrapper: ~Copyable {
var _nc: NC
- var _ncw: NCWrapper
+ var _s: NCS
- public var prop: T {
+ var nc: NC {
borrow {
- return _prop
+ return _nc
}
- }
-
- var nested_prop: T {
- borrow {
- return _w.borrow_prop
+ mutate {
+ return &_nc
}
}
- var nc: NC {
+ var nested1: NC {
borrow {
- return _nc
+ return _s.nc
+ }
+ mutate {
+ return &_s.nc
}
}
- var ncw: NCWrapper {
+ var nested2: NC {
borrow {
- return _ncw
+ return nc
+ }
+ mutate {
+ return &nc
}
}
- var nested_nc1: NC {
+ subscript(index: Int) -> NC {
borrow {
- return _ncw.nc
+ return _nc
+ }
+ mutate {
+ return &_nc
}
}
- var nested_nc2: NC {
+ var nested_subscript: NC {
borrow {
- return ncw.nc
+ return self[0]
+ }
+ mutate {
+ return &self[0]
}
}
- var nested_get: T {
+ var literal: Int {
borrow {
- return _w.get_prop // expected-error{{invalid return value from borrow accessor}} // expected-note{{borrow accessors can return either literals, stored properties or computed properties that have borrow accessors}}
-
+ return 0
}
}
-
- var nested_read: T {
- borrow {
- return _w.read_prop // expected-error{{invalid return value from borrow accessor}} // expected-note{{borrow accessors can return either literals, stored properties or computed properties that have borrow accessors}}
+}
- }
- }
-
- var nested: T {
+public struct SimpleNCWrapper : ~Copyable {
+ var _prop: T
+
+ var prop: T {
borrow {
- return prop
+ return _prop
+ }
+ mutate {
+ return &_prop
}
}
+}
- subscript(index: Int) -> T {
+public struct GenNCWrapper : ~Copyable {
+ var _prop: T
+ var _w: SimpleNCWrapper
+ var _nc: NC
+ var _ncw: NCWrapper
+
+ public var prop: T {
borrow {
return _prop
}
- }
-
- var nested_subscript: T {
- borrow {
- return self[0]
+ mutate {
+ return &_prop
}
}
-
- var if_prop: T {
+
+ var nc: NC {
borrow {
- if Int.random(in: 1..<100) == 0 {
- return _prop
- }
- return _prop // expected-error{{multiple return statements in borrow accessors are not yet supported}}
+ return _nc
+ }
+ mutate {
+ return &_nc
}
}
- var literal: Int {
+ var ncw: NCWrapper {
borrow {
- return 0
+ return _ncw
}
- }
-
- var opt_T: T? {
- borrow {
- if Int.random(in: 1..<100) == 0 {
- return nil
- }
- return _prop // expected-error{{invalid return value from borrow accessor}} // expected-note{{borrow accessors can return either literals, stored properties or computed properties that have borrow accessors}}
+ mutate {
+ return &_ncw
}
}
-}
-public struct NCS: ~Copyable {
- var _nc: NC
-
- var nc: NC {
+ var nested_prop1: T {
borrow {
- return _nc
+ return _w.prop
+ }
+ mutate {
+ return &_w.prop
}
}
-}
-
-public struct NCWrapper: ~Copyable {
- var _nc: NC
- var _s: NCS
- var nc: NC {
+ var nested_prop2: T {
borrow {
- return _nc
+ return prop
+ }
+ mutate {
+ return &prop
}
}
- var nested1: NC {
+ var nested_nc1: NC {
borrow {
- return _s.nc
+ return _ncw.nc
+ }
+ mutate {
+ return &_ncw.nc
}
}
- var nested2: NC {
+ var nested_nc2: NC {
borrow {
- return nc
+ return ncw.nc
+ }
+ mutate {
+ return &ncw.nc
}
}
- subscript(index: Int) -> NC {
+ subscript(index: Int) -> T {
borrow {
- return _nc
+ return _prop
+ }
+ mutate {
+ return &_prop
}
}
- var nested_subscript: NC {
+ var nested_subscript: T {
borrow {
return self[0]
}
+ mutate {
+ return &self[0]
+ }
}
var literal: Int {
@@ -477,148 +371,189 @@ public struct NCWrapper: ~Copyable {
}
}
-func test() {
- let w1 = Wrapper(_k: Klass(), _s: S(_k: Klass()))
- use(w1.k)
- var k1 = w1.k
- use(k1)
- k1 = Klass()
- use(k1)
- use(w1.nested_borrow)
- use(w1.nested)
-
- let w2 = GenWrapper(_prop: Klass(), _w: SimpleWrapper(_prop: Klass()), _klass: Klass(), _s: S(_k: Klass()))
- use(w2.prop)
- var k2 = w2.prop
- use(k2)
- k2 = Klass()
- use(k2)
- use(w2.nested_prop)
- use(w2.nested)
-}
+// CHECK: sil hidden [ossa] @$s15borrow_accessor7WrapperV1sAA1SVvb : $@convention(method) (@guaranteed Wrapper) -> @guaranteed S {
+// CHECK: bb0([[REG0:%.*]] : @guaranteed $Wrapper):
+// CHECK: debug_value [[REG0]], let, name "self", argno 1
+// CHECK: [[REG2:%.*]] = struct_extract [[REG0]], #Wrapper._s
+// CHECK: return [[REG2]]
+// CHECK: }
-func nctest() {
- let w1 = GenNCWrapper(_prop: NC(), _w: SimpleNCWrapper(_prop: NC()), _nc: NC(), _ncw: NCWrapper(_nc: NC(), _s: NCS(_nc: NC())))
- use(w1.prop)
- var k2 = w1.prop // MoveOnlyChecker diagnoses the copy
- use(k2)
- k2 = NC()
- use(k2)
-}
+// CHECK: sil hidden [ossa] @$s15borrow_accessor7WrapperV1sAA1SVvz : $@convention(method) (@inout Wrapper) -> @guaranteed_addr S {
+// CHECK:bb0([[REG0:%.*]] : $*Wrapper):
+// CHECK: debug_value [[REG0]], var, name "self", argno 1, expr op_deref
+// CHECK: [[REG2:%.*]] = struct_element_addr [[REG0]], #Wrapper._s
+// CHECK: return [[REG2]]
+// CHECK: }
// CHECK: sil hidden [ossa] @$s15borrow_accessor7WrapperV1kAA5KlassCvb : $@convention(method) (@guaranteed Wrapper) -> @guaranteed Klass {
// CHECK: bb0([[REG0:%.*]] : @guaranteed $Wrapper):
-// CHECK: [[REG2:%.*]] = struct_extract [[REG0]], #Wrapper._k
-// CHECK: return [[REG2]]
-// CHECK: }
+// CHECK: debug_value [[REG0]], let, name "self", argno 1
+// CHECK: [[REG2:%.*]] = struct_extract [[REG0]], #Wrapper._k
+// CHECK: return [[REG2]]
+// CHECK: }
-// CHECK: sil hidden [ossa] @$s15borrow_accessor7WrapperV07nested_A0AA5KlassCvb : $@convention(method) (@guaranteed Wrapper) -> @guaranteed Klass {
-// CHECK: bb0([[REG0:%.*]] : @guaranteed $Wrapper):
-// CHECK: [[REG2:%.*]] = struct_extract [[REG0]], #Wrapper._s
-// CHECK: [[REG3:%.*]] = function_ref @$s15borrow_accessor1SV0A5KlassAA0C0Cvb : $@convention(method) (@guaranteed S) -> @guaranteed Klass
-// CHECK: [[REG4:%.*]] = apply [[REG3]]([[REG2]]) : $@convention(method) (@guaranteed S) -> @guaranteed Klass
-// CHECK: return [[REG4]]
-// CHECK: }
+// CHECK: sil hidden [ossa] @$s15borrow_accessor7WrapperV1kAA5KlassCvz : $@convention(method) (@inout Wrapper) -> @guaranteed_addr Klass {
+// CHECK:bb0([[REG0:%.*]] : $*Wrapper):
+// CHECK: debug_value [[REG0]], var, name "self", argno 1, expr op_deref
+// CHECK: [[REG2:%.*]] = struct_element_addr [[REG0]], #Wrapper._k
+// CHECK: return [[REG2]]
+// CHECK: }
-// CHECK: sil hidden [ossa] @$s15borrow_accessor7WrapperV11nested_get3Sivb : $@convention(method) (@guaranteed Wrapper) -> Int {
+// CHECK: sil hidden [ossa] @$s15borrow_accessor7WrapperV14nested_borrow1AA5KlassCvb : $@convention(method) (@guaranteed Wrapper) -> @guaranteed Klass {
// CHECK: bb0([[REG0:%.*]] : @guaranteed $Wrapper):
+// CHECK: debug_value [[REG0]], let, name "self", argno 1
// CHECK: [[REG2:%.*]] = struct_extract [[REG0]], #Wrapper._s
-// CHECK: [[REG3:%.*]] = copy_value [[REG2]]
-// CHECK: [[REG4:%.*]] = begin_borrow [[REG3]]
-// CHECK: [[REG5:%.*]] = function_ref @$s15borrow_accessor1SV8getKlassAA0D0Cvg : $@convention(method) (@guaranteed S) -> @owned Klass
-// CHECK: [[REG6:%.*]] = apply [[REG5]]([[REG4]]) : $@convention(method) (@guaranteed S) -> @owned Klass
-// CHECK: end_borrow [[REG4]]
-// CHECK: destroy_value [[REG3]]
-// CHECK: [[REG9:%.*]] = begin_borrow [[REG6]]
-// CHECK: [[REG10:%.*]] = class_method [[REG9]], #Klass.id!getter : (Klass) -> () -> Int, $@convention(method) (@guaranteed Klass) -> Int
-// CHECK: [[REG11:%.*]] = apply [[REG10]]([[REG9]]) : $@convention(method) (@guaranteed Klass) -> Int
-// CHECK: end_borrow [[REG9]]
-// CHECK: destroy_value [[REG6]]
-// CHECK: return [[REG11]]
+// CHECK: [[REG3:%.*]] = function_ref @$s15borrow_accessor1SV1kAA5KlassCvb : $@convention(method) (@guaranteed S) -> @guaranteed Klass
+// CHECK: [[REG4:%.*]] = apply [[REG3]]([[REG2]]) : $@convention(method) (@guaranteed S) -> @guaranteed Klass
+// CHECK: return [[REG4]]
// CHECK: }
-// CHECK: sil hidden [ossa] @$s15borrow_accessor7WrapperV11nested_get4Sivb : $@convention(method) (@guaranteed Wrapper) -> Int {
-// CHECK: bb0([[REG0:%.*]] : @guaranteed $Wrapper):
-// CHECK: [[REG2:%.*]] = function_ref @$s15borrow_accessor7WrapperV5s_getAA1SVvg : $@convention(method) (@guaranteed Wrapper) -> @owned S
-// CHECK: [[REG3:%.*]] = apply [[REG2]]([[REG0]]) : $@convention(method) (@guaranteed Wrapper) -> @owned S
-// CHECK: [[REG4:%.*]] = begin_borrow [[REG3]]
-// CHECK: [[REG5:%.*]] = function_ref @$s15borrow_accessor1SV0A5KlassAA0C0Cvb : $@convention(method) (@guaranteed S) -> @guaranteed Klass
-// CHECK: [[REG6:%.*]] = apply [[REG5]]([[REG4]]) : $@convention(method) (@guaranteed S) -> @guaranteed Klass
-// CHECK: [[REG7:%.*]] = copy_value [[REG6]]
-// CHECK: end_borrow [[REG4]]
-// CHECK: destroy_value [[REG3]]
-// CHECK: [[REG10:%.*]] = begin_borrow [[REG7]]
-// CHECK: [[REG11:%.*]] = class_method [[REG10]], #Klass.id!getter : (Klass) -> () -> Int, $@convention(method) (@guaranteed Klass) -> Int
-// CHECK: [[REG12:%.*]] = apply [[REG11]]([[REG10]]) : $@convention(method) (@guaranteed Klass) -> Int
-// CHECK: end_borrow [[REG10]]
-// CHECK: destroy_value [[REG7]]
-// CHECK: return [[REG12]]
+// CHECK: sil hidden [ossa] @$s15borrow_accessor7WrapperV14nested_borrow1AA5KlassCvz : $@convention(method) (@inout Wrapper) -> @guaranteed_addr Klass {
+// CHECK:bb0([[REG0:%.*]] : $*Wrapper):
+// CHECK: debug_value [[REG0]], var, name "self", argno 1, expr op_deref
+// CHECK: [[REG2:%.*]] = function_ref @$s15borrow_accessor7WrapperV1sAA1SVvz : $@convention(method) (@inout Wrapper) -> @guaranteed_addr S
+// CHECK: [[REG3:%.*]] = apply [[REG2]]([[REG0]]) : $@convention(method) (@inout Wrapper) -> @guaranteed_addr S
+// CHECK: [[REG4:%.*]] = struct_element_addr [[REG3]], #S._k
+// CHECK: return [[REG4]]
// CHECK: }
-// CHECK: sil hidden [ossa] @$s15borrow_accessor7WrapperV6nestedAA5KlassCvb : $@convention(method) (@guaranteed Wrapper) -> @guaranteed Klass {
+// CHECK: sil hidden [ossa] @$s15borrow_accessor7WrapperV14nested_borrow2AA5KlassCvb : $@convention(method) (@guaranteed Wrapper) -> @guaranteed Klass {
// CHECK: bb0([[REG0:%.*]] : @guaranteed $Wrapper):
-// CHECK: [[REG2:%.*]] = function_ref @$s15borrow_accessor7WrapperV1kAA5KlassCvb : $@convention(method) (@guaranteed Wrapper) -> @guaranteed Klass
-// CHECK: [[REG3:%.*]] = apply [[REG2]]([[REG0]]) : $@convention(method) (@guaranteed Wrapper) -> @guaranteed Klass
-// CHECK: return [[REG3]]
-// CHECK: }
+// CHECK: debug_value [[REG0]], let, name "self", argno 1
+// CHECK: [[REG2:%.*]] = function_ref @$s15borrow_accessor7WrapperV1kAA5KlassCvb : $@convention(method) (@guaranteed Wrapper) -> @guaranteed Klass
+// CHECK: [[REG3:%.*]] = apply [[REG2]]([[REG0]]) : $@convention(method) (@guaranteed Wrapper) -> @guaranteed Klass
+// CHECK: return [[REG3]]
+// CHECK: }
+
+// CHECK: sil hidden [ossa] @$s15borrow_accessor7WrapperV14nested_borrow2AA5KlassCvz : $@convention(method) (@inout Wrapper) -> @guaranteed_addr Klass {
+// CHECK:bb0([[REG0:%.*]] : $*Wrapper):
+// CHECK: debug_value [[REG0]], var, name "self", argno 1, expr op_deref
+// CHECK: [[REG2:%.*]] = struct_element_addr [[REG0]], #Wrapper._k
+// CHECK: return [[REG2]]
+// CHECK: }
// CHECK: sil hidden [ossa] @$s15borrow_accessor7WrapperVyAA5KlassCSicib : $@convention(method) (Int, @guaranteed Wrapper) -> @guaranteed Klass {
// CHECK: bb0([[REG0:%.*]] : $Int, [[REG1:%.*]] : @guaranteed $Wrapper):
-// CHECK: [[REG4:%.*]] = struct_extract [[REG1]], #Wrapper._k
-// CHECK: return [[REG4]]
-// CHECK: }
+// CHECK: debug_value [[REG0]], let, name "index", argno 1
+// CHECK: debug_value [[REG1]], let, name "self", argno 2
+// CHECK: [[REG4:%.*]] = struct_extract [[REG1]], #Wrapper._k
+// CHECK: return [[REG4]]
+// CHECK: }
+
+// CHECK: sil hidden [ossa] @$s15borrow_accessor7WrapperVyAA5KlassCSiciz : $@convention(method) (Int, @inout Wrapper) -> @guaranteed_addr Klass {
+// CHECK:bb0([[REG0:%.*]] : $Int, [[REG1:%.*]] : $*Wrapper):
+// CHECK: debug_value [[REG0]], let, name "index", argno 1
+// CHECK: debug_value [[REG1]], var, name "self", argno 2, expr op_deref
+// CHECK: [[REG4:%.*]] = struct_element_addr [[REG1]], #Wrapper._k
+// CHECK: return [[REG4]]
+// CHECK: }
// CHECK: sil hidden [ossa] @$s15borrow_accessor7WrapperV16nested_subscriptAA5KlassCvb : $@convention(method) (@guaranteed Wrapper) -> @guaranteed Klass {
// CHECK: bb0([[REG0:%.*]] : @guaranteed $Wrapper):
-// CHECK: [[REG2:%.*]] = integer_literal $Builtin.IntLiteral, 0
-// CHECK: [[REG3:%.*]] = metatype $@thin Int.Type
-// CHECK: [[REG4:%.*]] = function_ref @$sSi22_builtinIntegerLiteralSiBI_tcfC : $@convention(method) (Builtin.IntLiteral, @thin Int.Type) -> Int
-// CHECK: [[REG5:%.*]] = apply [[REG4]]([[REG2]], [[REG3]]) : $@convention(method) (Builtin.IntLiteral, @thin Int.Type) -> Int
-// CHECK: [[REG6:%.*]] = function_ref @$s15borrow_accessor7WrapperVyAA5KlassCSicib : $@convention(method) (Int, @guaranteed Wrapper) -> @guaranteed Klass
-// CHECK: [[REG7:%.*]] = apply [[REG6]]([[REG5]], [[REG0]]) : $@convention(method) (Int, @guaranteed Wrapper) -> @guaranteed Klass
-// CHECK: return [[REG7]]
-// CHECK: }
-
-// TODO-CHECK: sil hidden [ossa] @$s15borrow_accessor7WrapperV8if_klassAA5KlassCvb : $@convention(method) (@guaranteed Wrapper) -> @guaranteed Klass {
-// TODO-CHECK: bb0([[REG0:%.*]] : @guaranteed $Wrapper):
-// TODO-CHECK: cond_br {{.*}}, bb1, bb2
-// TODO-CHECK: bb1:
-// TODO-CHECK: [[EX1:%.*]] = struct_extract [[REG0]], #Wrapper._k
-// TODO-CHECK: br bb3([[EX1]])
-// TODO-CHECK: bb2:
-// TODO-CHECK: [[EX2:%.*]] = struct_extract [[REG0]], #Wrapper._k
-// TODO-CHECK: br bb3([[EX2]])
-// TODO-CHECK: bb3([[PHI:%.*]] : @guaranteed $Klass):
-// TODO-CHECK: return [[PHI]]
-// TODO-CHECK: }
+// CHECK: debug_value [[REG0]], let, name "self", argno 1
+// CHECK: [[REG2:%.*]] = integer_literal $Builtin.IntLiteral, 0
+// CHECK: [[REG3:%.*]] = metatype $@thin Int.Type
+// CHECK: [[REG4:%.*]] = function_ref @$sSi22_builtinIntegerLiteralSiBI_tcfC : $@convention(method) (Builtin.IntLiteral, @thin Int.Type) -> Int
+// CHECK: [[REG5:%.*]] = apply [[REG4]]([[REG2]], [[REG3]]) : $@convention(method) (Builtin.IntLiteral, @thin Int.Type) -> Int
+// CHECK: [[REG6:%.*]] = function_ref @$s15borrow_accessor7WrapperVyAA5KlassCSicib : $@convention(method) (Int, @guaranteed Wrapper) -> @guaranteed Klass
+// CHECK: [[REG7:%.*]] = apply [[REG6]]([[REG5]], [[REG0]]) : $@convention(method) (Int, @guaranteed Wrapper) -> @guaranteed Klass
+// CHECK: return [[REG7]]
+// CHECK: }
+
+// CHECK: sil hidden [ossa] @$s15borrow_accessor7WrapperV16nested_subscriptAA5KlassCvz : $@convention(method) (@inout Wrapper) -> @guaranteed_addr Klass {
+// CHECK:bb0([[REG0:%.*]] : $*Wrapper):
+// CHECK: debug_value [[REG0]], var, name "self", argno 1, expr op_deref
+// CHECK: [[REG2:%.*]] = integer_literal $Builtin.IntLiteral, 0
+// CHECK: [[REG3:%.*]] = metatype $@thin Int.Type
+// CHECK: [[REG4:%.*]] = function_ref @$sSi22_builtinIntegerLiteralSiBI_tcfC : $@convention(method) (Builtin.IntLiteral, @thin Int.Type) -> Int
+// CHECK: [[REG5:%.*]] = apply [[REG4]]([[REG2]], [[REG3]]) : $@convention(method) (Builtin.IntLiteral, @thin Int.Type) -> Int
+// CHECK: [[REG6:%.*]] = function_ref @$s15borrow_accessor7WrapperVyAA5KlassCSiciz : $@convention(method) (Int, @inout Wrapper) -> @guaranteed_addr Klass
+// CHECK: [[REG7:%.*]] = apply [[REG6]]([[REG5]], [[REG0]]) : $@convention(method) (Int, @inout Wrapper) -> @guaranteed_addr Klass
+// CHECK: return [[REG7]]
+// CHECK: }
// CHECK: sil [ossa] @$s15borrow_accessor10GenWrapperV4propxvb : $@convention(method) (@in_guaranteed GenWrapper) -> @guaranteed_addr T {
// CHECK: bb0([[REG0:%.*]] : $*GenWrapper):
-// CHECK: [[REG2:%.*]] = struct_element_addr [[REG0]], #GenWrapper._prop
-// CHECK: return [[REG2]]
-// CHECK: }
+// CHECK: debug_value [[REG0]], let, name "self", argno 1, expr op_deref
+// CHECK: [[REG2:%.*]] = struct_element_addr [[REG0]], #GenWrapper._prop
+// CHECK: return [[REG2]]
+// CHECK: }
-// CHECK: sil hidden [ossa] @$s15borrow_accessor10GenWrapperV11nested_propxvb : $@convention(method) (@in_guaranteed GenWrapper) -> @guaranteed_addr T {
+// CHECK: sil [ossa] @$s15borrow_accessor10GenWrapperV4propxvz : $@convention(method) (@inout GenWrapper) -> @guaranteed_addr T {
+// CHECK:bb0([[REG0:%.*]] : $*GenWrapper):
+// CHECK: debug_value [[REG0]], var, name "self", argno 1, expr op_deref
+// CHECK: [[REG2:%.*]] = struct_element_addr [[REG0]], #GenWrapper._prop
+// CHECK: return [[REG2]]
+// CHECK: }
+
+// CHECK: sil hidden [ossa] @$s15borrow_accessor10GenWrapperV1sAA1SVvb : $@convention(method) (@in_guaranteed GenWrapper) -> @guaranteed S {
// CHECK: bb0([[REG0:%.*]] : $*GenWrapper):
-// CHECK: [[REG2:%.*]] = struct_element_addr [[REG0]], #GenWrapper._w
-// CHECK: [[REG3:%.*]] = function_ref @$s15borrow_accessor13SimpleWrapperV0A5_propxvb : $@convention(method) <τ_0_0> (@in_guaranteed SimpleWrapper<τ_0_0>) -> @guaranteed_addr τ_0_0
-// CHECK: [[REG4:%.*]] = apply [[REG3]]([[REG2]]) : $@convention(method) <τ_0_0> (@in_guaranteed SimpleWrapper<τ_0_0>) -> @guaranteed_addr τ_0_0
-// CHECK: return [[REG4]]
-// CHECK: }
+// CHECK: debug_value [[REG0]], let, name "self", argno 1, expr op_deref
+// CHECK: [[REG2:%.*]] = struct_element_addr [[REG0]], #GenWrapper._s
+// CHECK: [[REG3:%.*]] = load_borrow [[REG2]]
+// CHECK: [[REG4:%.*]] = unchecked_ownership_conversion [[REG3]], @guaranteed to @unowned
+// CHECK: [[REG5:%.*]] = unchecked_ownership_conversion [[REG4]], @unowned to @guaranteed
+// CHECK: end_borrow [[REG3]]
+// CHECK: return [[REG5]]
+// CHECK: }
-// CHECK: sil hidden [ossa] @$s15borrow_accessor10GenWrapperV6nestedxvb : $@convention(method) (@in_guaranteed GenWrapper) -> @guaranteed_addr T {
+// CHECK: sil hidden [ossa] @$s15borrow_accessor10GenWrapperV1sAA1SVvz : $@convention(method) (@inout GenWrapper) -> @guaranteed_addr S {
+// CHECK:bb0([[REG0:%.*]] : $*GenWrapper):
+// CHECK: debug_value [[REG0]], var, name "self", argno 1, expr op_deref
+// CHECK: [[REG2:%.*]] = struct_element_addr [[REG0]], #GenWrapper._s
+// CHECK: return [[REG2]]
+// CHECK: }
+
+// CHECK: sil hidden [ossa] @$s15borrow_accessor10GenWrapperV1kAA5KlassCvb : $@convention(method) (@in_guaranteed GenWrapper) -> @guaranteed Klass {
// CHECK: bb0([[REG0:%.*]] : $*GenWrapper):
-// CHECK: [[REG2:%.*]] = function_ref @$s15borrow_accessor10GenWrapperV4propxvb : $@convention(method) <τ_0_0> (@in_guaranteed GenWrapper<τ_0_0>) -> @guaranteed_addr τ_0_0
-// CHECK: [[REG3:%.*]] = apply [[REG2]]([[REG0]]) : $@convention(method) <τ_0_0> (@in_guaranteed GenWrapper<τ_0_0>) -> @guaranteed_addr τ_0_0
-// CHECK: return [[REG3]]
-// CHECK: }
+// CHECK: debug_value [[REG0]], let, name "self", argno 1, expr op_deref
+// CHECK: [[REG2:%.*]] = struct_element_addr [[REG0]], #GenWrapper._k
+// CHECK: [[REG3:%.*]] = load_borrow [[REG2]]
+// CHECK: [[REG4:%.*]] = unchecked_ownership_conversion [[REG3]], @guaranteed to @unowned
+// CHECK: [[REG5:%.*]] = unchecked_ownership_conversion [[REG4]], @unowned to @guaranteed
+// CHECK: end_borrow [[REG3]]
+// CHECK: return [[REG5]]
+// CHECK: }
+
+// CHECK: sil hidden [ossa] @$s15borrow_accessor10GenWrapperV1kAA5KlassCvz : $@convention(method) (@inout GenWrapper) -> @guaranteed_addr Klass {
+// CHECK:bb0([[REG0:%.*]] : $*GenWrapper):
+// CHECK: debug_value [[REG0]], var, name "self", argno 1, expr op_deref
+// CHECK: [[REG2:%.*]] = struct_element_addr [[REG0]], #GenWrapper._k
+// CHECK: return [[REG2]]
+// CHECK: }
-// CHECK: sil hidden [ossa] @$s15borrow_accessor10GenWrapperV13nested_klass1AA5KlassCvb : $@convention(method) (@in_guaranteed GenWrapper) -> @guaranteed Klass {
+// CHECK: sil hidden [ossa] @$s15borrow_accessor10GenWrapperV12nested_prop1xvb : $@convention(method) (@in_guaranteed GenWrapper) -> @guaranteed_addr T {
+// CHECK: bb0([[REG0:%.*]] : $*GenWrapper):
+// CHECK: debug_value [[REG0]], let, name "self", argno 1, expr op_deref
+// CHECK: [[REG2:%.*]] = struct_element_addr [[REG0]], #GenWrapper._w
+// CHECK: [[REG3:%.*]] = function_ref @$s15borrow_accessor13SimpleWrapperV4propxvb : $@convention(method) <τ_0_0> (@in_guaranteed SimpleWrapper<τ_0_0>) -> @guaranteed_addr τ_0_0
+// CHECK: [[REG4:%.*]] = apply [[REG3]]([[REG2]]) : $@convention(method) <τ_0_0> (@in_guaranteed SimpleWrapper<τ_0_0>) -> @guaranteed_addr τ_0_0
+// CHECK: return [[REG4]]
+// CHECK: }
+
+// CHECK: sil hidden [ossa] @$s15borrow_accessor10GenWrapperV12nested_prop1xvz : $@convention(method) (@inout GenWrapper) -> @guaranteed_addr T {
+// CHECK:bb0([[REG0:%.*]] : $*GenWrapper):
+// CHECK: debug_value [[REG0]], var, name "self", argno 1, expr op_deref
+// CHECK: [[REG2:%.*]] = struct_element_addr [[REG0]], #GenWrapper._w
+// CHECK: [[REG3:%.*]] = function_ref @$s15borrow_accessor13SimpleWrapperV4propxvz : $@convention(method) <τ_0_0> (@inout SimpleWrapper<τ_0_0>) -> @guaranteed_addr τ_0_0
+// CHECK: [[REG4:%.*]] = apply [[REG3]]([[REG2]]) : $@convention(method) <τ_0_0> (@inout SimpleWrapper<τ_0_0>) -> @guaranteed_addr τ_0_0
+// CHECK: return [[REG4]]
+// CHECK: }
+
+// CHECK: sil hidden [ossa] @$s15borrow_accessor10GenWrapperV12nested_prop2xvb : $@convention(method) (@in_guaranteed GenWrapper) -> @guaranteed_addr T {
+// CHECK: bb0([[REG0:%.*]] : $*GenWrapper):
+// CHECK: debug_value [[REG0]], let, name "self", argno 1, expr op_deref
+// CHECK: [[REG2:%.*]] = function_ref @$s15borrow_accessor10GenWrapperV4propxvb : $@convention(method) <τ_0_0> (@in_guaranteed GenWrapper<τ_0_0>) -> @guaranteed_addr τ_0_0
+// CHECK: [[REG3:%.*]] = apply [[REG2]]([[REG0]]) : $@convention(method) <τ_0_0> (@in_guaranteed GenWrapper<τ_0_0>) -> @guaranteed_addr τ_0_0
+// CHECK: return [[REG3]]
+// CHECK: }
+
+// CHECK: sil hidden [ossa] @$s15borrow_accessor10GenWrapperV9nested_k1AA5KlassCvb : $@convention(method) (@in_guaranteed GenWrapper) -> @guaranteed Klass {
// CHECK: bb0([[REG0:%.*]] : $*GenWrapper):
// CHECK: debug_value [[REG0]], let, name "self", argno 1, expr op_deref
// CHECK: [[REG2:%.*]] = struct_element_addr [[REG0]], #GenWrapper._s
// CHECK: [[REG3:%.*]] = load_borrow [[REG2]]
-// CHECK: [[REG4:%.*]] = function_ref @$s15borrow_accessor1SV0A5KlassAA0C0Cvb : $@convention(method) (@guaranteed S) -> @guaranteed Klass
+// CHECK: [[REG4:%.*]] = function_ref @$s15borrow_accessor1SV1kAA5KlassCvb : $@convention(method) (@guaranteed S) -> @guaranteed Klass
// CHECK: [[REG5:%.*]] = apply [[REG4]]([[REG3]]) : $@convention(method) (@guaranteed S) -> @guaranteed Klass
// CHECK: [[REG6:%.*]] = unchecked_ownership_conversion [[REG5]], @guaranteed to @unowned
// CHECK: [[REG7:%.*]] = unchecked_ownership_conversion [[REG6]], @unowned to @guaranteed
@@ -626,32 +561,172 @@ func nctest() {
// CHECK: return [[REG7]]
// CHECK: }
-// CHECK: sil hidden [ossa] @$s15borrow_accessor10GenWrapperV13nested_klass2AA5KlassCvb : $@convention(method) (@in_guaranteed GenWrapper) -> @guaranteed Klass {
+// CHECK: sil hidden [ossa] @$s15borrow_accessor10GenWrapperV9nested_k1AA5KlassCvz : $@convention(method) (@inout GenWrapper) -> @guaranteed_addr Klass {
+// CHECK:bb0([[REG0:%.*]] : $*GenWrapper):
+// CHECK: debug_value [[REG0]], var, name "self", argno 1, expr op_deref
+// CHECK: [[REG2:%.*]] = struct_element_addr [[REG0]], #GenWrapper._s
+// CHECK: [[REG3:%.*]] = function_ref @$s15borrow_accessor1SV1kAA5KlassCvz : $@convention(method) (@inout S) -> @guaranteed_addr Klass
+// CHECK: [[REG4:%.*]] = apply [[REG3]]([[REG2]]) : $@convention(method) (@inout S) -> @guaranteed_addr Klass
+// CHECK: return [[REG4]]
+// CHECK: }
+
+// CHECK: sil hidden [ossa] @$s15borrow_accessor10GenWrapperV9nested_k2AA5KlassCvb : $@convention(method) (@in_guaranteed GenWrapper) -> @guaranteed Klass {
// CHECK: bb0([[REG0:%.*]] : $*GenWrapper):
// CHECK: debug_value [[REG0]], let, name "self", argno 1, expr op_deref
// CHECK: [[REG2:%.*]] = function_ref @$s15borrow_accessor10GenWrapperV1sAA1SVvb : $@convention(method) <τ_0_0> (@in_guaranteed GenWrapper<τ_0_0>) -> @guaranteed S
// CHECK: [[REG3:%.*]] = apply [[REG2]]([[REG0]]) : $@convention(method) <τ_0_0> (@in_guaranteed GenWrapper<τ_0_0>) -> @guaranteed S
-// CHECK: [[REG4:%.*]] = function_ref @$s15borrow_accessor1SV0A5KlassAA0C0Cvb : $@convention(method) (@guaranteed S) -> @guaranteed Klass
+// CHECK: [[REG4:%.*]] = function_ref @$s15borrow_accessor1SV1kAA5KlassCvb : $@convention(method) (@guaranteed S) -> @guaranteed Klass
// CHECK: [[REG5:%.*]] = apply [[REG4]]([[REG3]]) : $@convention(method) (@guaranteed S) -> @guaranteed Klass
// CHECK: return [[REG5]]
// CHECK: }
+// CHECK: sil hidden [ossa] @$s15borrow_accessor10GenWrapperV9nested_k2AA5KlassCvz : $@convention(method) (@inout GenWrapper) -> @guaranteed_addr Klass {
+// CHECK:bb0([[REG0:%.*]] : $*GenWrapper):
+// CHECK: debug_value [[REG0]], var, name "self", argno 1, expr op_deref
+// CHECK: [[REG2:%.*]] = function_ref @$s15borrow_accessor10GenWrapperV1sAA1SVvz : $@convention(method) <τ_0_0> (@inout GenWrapper<τ_0_0>) -> @guaranteed_addr S
+// CHECK: [[REG3:%.*]] = apply [[REG2]]([[REG0]]) : $@convention(method) <τ_0_0> (@inout GenWrapper<τ_0_0>) -> @guaranteed_addr S
+// CHECK: [[REG4:%.*]] = function_ref @$s15borrow_accessor1SV1kAA5KlassCvz : $@convention(method) (@inout S) -> @guaranteed_addr Klass
+// CHECK: [[REG5:%.*]] = apply [[REG4]]([[REG3]]) : $@convention(method) (@inout S) -> @guaranteed_addr Klass
+// CHECK: return [[REG5]]
+// CHECK: }
+
// CHECK: sil hidden [ossa] @$s15borrow_accessor10GenWrapperVyxSicib : $@convention(method) (Int, @in_guaranteed GenWrapper) -> @guaranteed_addr T {
// CHECK: bb0([[REG0:%.*]] : $Int, [[REG1:%.*]] : $*GenWrapper):
-// CHECK: [[REG4:%.*]] = struct_element_addr [[REG1]], #GenWrapper._prop
-// CHECK: return [[REG4]]
-// CHECK: }
+// CHECK: debug_value [[REG0]], let, name "index", argno 1
+// CHECK: debug_value [[REG1]], let, name "self", argno 2, expr op_deref
+// CHECK: [[REG4:%.*]] = struct_element_addr [[REG1]], #GenWrapper._prop
+// CHECK: return [[REG4]]
+// CHECK: }
+
+// CHECK: sil hidden [ossa] @$s15borrow_accessor10GenWrapperVyxSiciz : $@convention(method) (Int, @inout GenWrapper) -> @guaranteed_addr T {
+// CHECK:bb0([[REG0:%.*]] : $Int, [[REG1:%.*]] : $*GenWrapper):
+// CHECK: debug_value [[REG0]], let, name "index", argno 1
+// CHECK: debug_value [[REG1]], var, name "self", argno 2, expr op_deref
+// CHECK: [[REG4:%.*]] = struct_element_addr [[REG1]], #GenWrapper._prop
+// CHECK: return [[REG4]]
+// CHECK: }
// CHECK: sil hidden [ossa] @$s15borrow_accessor10GenWrapperV16nested_subscriptxvb : $@convention(method) (@in_guaranteed GenWrapper) -> @guaranteed_addr T {
-// CHECK: bb0([[REG0]] : $*GenWrapper):
-// CHECK: [[REG2:%.*]] = integer_literal $Builtin.IntLiteral, 0
-// CHECK: [[REG3:%.*]] = metatype $@thin Int.Type
-// CHECK: [[REG4:%.*]] = function_ref @$sSi22_builtinIntegerLiteralSiBI_tcfC : $@convention(method) (Builtin.IntLiteral, @thin Int.Type) -> Int
-// CHECK: [[REG5:%.*]] = apply [[REG4]]([[REG2]], [[REG3]]) : $@convention(method) (Builtin.IntLiteral, @thin Int.Type) -> Int
-// CHECK: [[REG6:%.*]] = function_ref @$s15borrow_accessor10GenWrapperVyxSicib : $@convention(method) <τ_0_0> (Int, @in_guaranteed GenWrapper<τ_0_0>) -> @guaranteed_addr τ_0_0
-// CHECK: [[REG7:%.*]] = apply [[REG6]]([[REG5]], [[REG0]]) : $@convention(method) <τ_0_0> (Int, @in_guaranteed GenWrapper<τ_0_0>) -> @guaranteed_addr τ_0_0
-// CHECK: return [[REG7]]
-// CHECK: }
+// CHECK: bb0([[REG0:%.*]] : $*GenWrapper):
+// CHECK: debug_value [[REG0]], let, name "self", argno 1, expr op_deref
+// CHECK: [[REG2:%.*]] = integer_literal $Builtin.IntLiteral, 0
+// CHECK: [[REG3:%.*]] = metatype $@thin Int.Type
+// CHECK: [[REG4:%.*]] = function_ref @$sSi22_builtinIntegerLiteralSiBI_tcfC : $@convention(method) (Builtin.IntLiteral, @thin Int.Type) -> Int
+// CHECK: [[REG5:%.*]] = apply [[REG4]]([[REG2]], [[REG3]]) : $@convention(method) (Builtin.IntLiteral, @thin Int.Type) -> Int
+// CHECK: [[REG6:%.*]] = function_ref @$s15borrow_accessor10GenWrapperVyxSicib : $@convention(method) <τ_0_0> (Int, @in_guaranteed GenWrapper<τ_0_0>) -> @guaranteed_addr τ_0_0
+// CHECK: [[REG7:%.*]] = apply [[REG6]]([[REG5]], [[REG0]]) : $@convention(method) <τ_0_0> (Int, @in_guaranteed GenWrapper<τ_0_0>) -> @guaranteed_addr τ_0_0
+// CHECK: return [[REG7]]
+// CHECK: }
+
+// CHECK: sil hidden [ossa] @$s15borrow_accessor10GenWrapperV16nested_subscriptxvz : $@convention(method) (@inout GenWrapper) -> @guaranteed_addr T {
+// CHECK:bb0([[REG0:%.*]] : $*GenWrapper):
+// CHECK: debug_value [[REG0]], var, name "self", argno 1, expr op_deref
+// CHECK: [[REG2:%.*]] = integer_literal $Builtin.IntLiteral, 0
+// CHECK: [[REG3:%.*]] = metatype $@thin Int.Type
+// CHECK: [[REG4:%.*]] = function_ref @$sSi22_builtinIntegerLiteralSiBI_tcfC : $@convention(method) (Builtin.IntLiteral, @thin Int.Type) -> Int
+// CHECK: [[REG5:%.*]] = apply [[REG4]]([[REG2]], [[REG3]]) : $@convention(method) (Builtin.IntLiteral, @thin Int.Type) -> Int
+// CHECK: [[REG6:%.*]] = function_ref @$s15borrow_accessor10GenWrapperVyxSiciz : $@convention(method) <τ_0_0> (Int, @inout GenWrapper<τ_0_0>) -> @guaranteed_addr τ_0_0
+// CHECK: [[REG7:%.*]] = apply [[REG6]]([[REG5]], [[REG0]]) : $@convention(method) <τ_0_0> (Int, @inout GenWrapper<τ_0_0>) -> @guaranteed_addr τ_0_0
+// CHECK: return [[REG7]]
+// CHECK: }
+
+// CHECK: sil [ossa] @$s15borrow_accessor12GenNCWrapperVAARi_zrlE4propxvb : $@convention(method) (@in_guaranteed GenNCWrapper) -> @guaranteed_addr T {
+// CHECK: bb0([[REG0:%.*]] : $*GenNCWrapper):
+// CHECK: debug_value [[REG0]], let, name "self", argno 1, expr op_deref
+// CHECK: [[REG2:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[REG0]]
+// CHECK: [[REG3:%.*]] = struct_element_addr [[REG2]], #GenNCWrapper._prop
+// CHECK: return [[REG3]]
+// CHECK: }
+
+// CHECK: sil [ossa] @$s15borrow_accessor12GenNCWrapperVAARi_zrlE4propxvz : $@convention(method) (@inout GenNCWrapper) -> @guaranteed_addr T {
+// CHECK:bb0([[REG0:%.*]] : $*GenNCWrapper):
+// CHECK: debug_value [[REG0]], var, name "self", argno 1, expr op_deref
+// CHECK: [[REG2:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[REG0]]
+// CHECK: [[REG3:%.*]] = struct_element_addr [[REG2]], #GenNCWrapper._prop
+// CHECK: return [[REG3]]
+// CHECK: }
+
+// CHECK: sil hidden [ossa] @$s15borrow_accessor12GenNCWrapperVAARi_zrlE2ncAA2NCVvb : $@convention(method) (@in_guaranteed GenNCWrapper) -> @guaranteed NC {
+// CHECK: bb0([[REG0:%.*]] : $*GenNCWrapper):
+// CHECK: debug_value [[REG0]], let, name "self", argno 1, expr op_deref
+// CHECK: [[REG2:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[REG0]]
+// CHECK: [[REG3:%.*]] = struct_element_addr [[REG2]], #GenNCWrapper._nc
+// CHECK: [[REG4:%.*]] = load_borrow [[REG3]]
+// CHECK: [[REG5:%.*]] = unchecked_ownership_conversion [[REG4]], @guaranteed to @unowned
+// CHECK: [[REG6:%.*]] = unchecked_ownership_conversion [[REG5]], @unowned to @guaranteed
+// CHECK: end_borrow [[REG4]]
+// CHECK: return [[REG6]]
+// CHECK: }
+
+// CHECK: sil hidden [ossa] @$s15borrow_accessor12GenNCWrapperVAARi_zrlE2ncAA2NCVvz : $@convention(method) (@inout GenNCWrapper) -> @guaranteed_addr NC {
+// CHECK:bb0([[REG0:%.*]] : $*GenNCWrapper):
+// CHECK: debug_value [[REG0]], var, name "self", argno 1, expr op_deref
+// CHECK: [[REG2:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[REG0]]
+// CHECK: [[REG3:%.*]] = struct_element_addr [[REG2]], #GenNCWrapper._nc
+// CHECK: return [[REG3]]
+// CHECK: }
+
+// CHECK: sil hidden [ossa] @$s15borrow_accessor12GenNCWrapperVAARi_zrlE3ncwAA0D0Vvb : $@convention(method) (@in_guaranteed GenNCWrapper) -> @guaranteed NCWrapper {
+// CHECK: bb0([[REG0:%.*]] : $*GenNCWrapper):
+// CHECK: debug_value [[REG0]], let, name "self", argno 1, expr op_deref
+// CHECK: [[REG2:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[REG0]]
+// CHECK: [[REG3:%.*]] = struct_element_addr [[REG2]], #GenNCWrapper._ncw
+// CHECK: [[REG4:%.*]] = load_borrow [[REG3]]
+// CHECK: [[REG5:%.*]] = unchecked_ownership_conversion [[REG4]], @guaranteed to @unowned
+// CHECK: [[REG6:%.*]] = unchecked_ownership_conversion [[REG5]], @unowned to @guaranteed
+// CHECK: end_borrow [[REG4]]
+// CHECK: return [[REG6]]
+// CHECK: }
+
+// CHECK: sil hidden [ossa] @$s15borrow_accessor12GenNCWrapperVAARi_zrlE3ncwAA0D0Vvz : $@convention(method) (@inout GenNCWrapper) -> @guaranteed_addr NCWrapper {
+// CHECK:bb0([[REG0:%.*]] : $*GenNCWrapper):
+// CHECK: debug_value [[REG0]], var, name "self", argno 1, expr op_deref
+// CHECK: [[REG2:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[REG0]]
+// CHECK: [[REG3:%.*]] = struct_element_addr [[REG2]], #GenNCWrapper._ncw
+// CHECK: return [[REG3]]
+// CHECK: }
+
+// CHECK: sil hidden [ossa] @$s15borrow_accessor12GenNCWrapperVAARi_zrlE12nested_prop1xvb : $@convention(method) (@in_guaranteed GenNCWrapper) -> @guaranteed_addr T {
+// CHECK: bb0([[REG0:%.*]] : $*GenNCWrapper):
+// CHECK: debug_value [[REG0]], let, name "self", argno 1, expr op_deref
+// CHECK: [[REG2:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[REG0]]
+// CHECK: [[REG3:%.*]] = struct_element_addr [[REG2]], #GenNCWrapper._w
+// CHECK: [[REG4:%.*]] = function_ref @$s15borrow_accessor15SimpleNCWrapperVAARi_zrlE4propxvb : $@convention(method) <τ_0_0 where τ_0_0 : ~Copyable> (@in_guaranteed SimpleNCWrapper<τ_0_0>) -> @guaranteed_addr τ_0_0
+// CHECK: [[REG5:%.*]] = apply [[REG4]]([[REG3]]) : $@convention(method) <τ_0_0 where τ_0_0 : ~Copyable> (@in_guaranteed SimpleNCWrapper<τ_0_0>) -> @guaranteed_addr τ_0_0
+// CHECK: [[REG6:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[REG5]]
+// CHECK: return [[REG6]]
+// CHECK: }
+
+// CHECK: sil hidden [ossa] @$s15borrow_accessor12GenNCWrapperVAARi_zrlE12nested_prop1xvz : $@convention(method) (@inout GenNCWrapper) -> @guaranteed_addr T {
+// CHECK:bb0([[REG0:%.*]] : $*GenNCWrapper):
+// CHECK: debug_value [[REG0]], var, name "self", argno 1, expr op_deref
+// CHECK: [[REG2:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[REG0]]
+// CHECK: [[REG3:%.*]] = struct_element_addr [[REG2]], #GenNCWrapper._w
+// CHECK: [[REG4:%.*]] = function_ref @$s15borrow_accessor15SimpleNCWrapperVAARi_zrlE4propxvz : $@convention(method) <τ_0_0 where τ_0_0 : ~Copyable> (@inout SimpleNCWrapper<τ_0_0>) -> @guaranteed_addr τ_0_0
+// CHECK: [[REG5:%.*]] = apply [[REG4]]([[REG3]]) : $@convention(method) <τ_0_0 where τ_0_0 : ~Copyable> (@inout SimpleNCWrapper<τ_0_0>) -> @guaranteed_addr τ_0_0
+// CHECK: [[REG6:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[REG5]]
+// CHECK: return [[REG6]]
+// CHECK: }
+
+// CHECK: sil hidden [ossa] @$s15borrow_accessor12GenNCWrapperVAARi_zrlE12nested_prop2xvb : $@convention(method) (@in_guaranteed GenNCWrapper) -> @guaranteed_addr T {
+// CHECK:bb0([[REG0:%.*]] : $*GenNCWrapper):
+// CHECK: debug_value [[REG0]], let, name "self", argno 1, expr op_deref
+// CHECK: [[REG2:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[REG0]]
+// CHECK: [[REG3:%.*]] = function_ref @$s15borrow_accessor12GenNCWrapperVAARi_zrlE4propxvb : $@convention(method) <τ_0_0 where τ_0_0 : ~Copyable> (@in_guaranteed GenNCWrapper<τ_0_0>) -> @guaranteed_addr τ_0_0
+// CHECK: [[REG4:%.*]] = apply [[REG3]]([[REG2]]) : $@convention(method) <τ_0_0 where τ_0_0 : ~Copyable> (@in_guaranteed GenNCWrapper<τ_0_0>) -> @guaranteed_addr τ_0_0
+// CHECK: [[REG5:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[REG4]]
+// CHECK: return [[REG5]]
+// CHECK: }
+
+// CHECK: sil hidden [ossa] @$s15borrow_accessor12GenNCWrapperVAARi_zrlE12nested_prop2xvz : $@convention(method) (@inout GenNCWrapper) -> @guaranteed_addr T {
+// CHECK:bb0([[REG0:%.*]] : $*GenNCWrapper):
+// CHECK: debug_value [[REG0]], var, name "self", argno 1, expr op_deref
+// CHECK: [[REG2:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[REG0]]
+// CHECK: [[REG3:%.*]] = function_ref @$s15borrow_accessor12GenNCWrapperVAARi_zrlE4propxvz : $@convention(method) <τ_0_0 where τ_0_0 : ~Copyable> (@inout GenNCWrapper<τ_0_0>) -> @guaranteed_addr τ_0_0
+// CHECK: [[REG4:%.*]] = apply [[REG3]]([[REG2]]) : $@convention(method) <τ_0_0 where τ_0_0 : ~Copyable> (@inout GenNCWrapper<τ_0_0>) -> @guaranteed_addr τ_0_0
+// CHECK: [[REG5:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[REG4]]
+// CHECK: return [[REG5]]
+// CHECK: }
// CHECK: sil hidden [ossa] @$s15borrow_accessor12GenNCWrapperVAARi_zrlE10nested_nc1AA2NCVvb : $@convention(method) (@in_guaranteed GenNCWrapper) -> @guaranteed NC {
// CHECK: bb0([[REG0:%.*]] : $*GenNCWrapper):
@@ -672,15 +747,15 @@ func nctest() {
// CHECK: return [[REG8]]
// CHECK: }
-// CHECK-LABEL: sil hidden [ossa] @$s15borrow_accessor9NCWrapperV2ncAA2NCVvb : $@convention(method) (@guaranteed NCWrapper) -> @guaranteed NC {
-// CHECK: bb0([[REG0]] : @guaranteed $NCWrapper):
-// CHECK: [[REG1:%.*]] = copy_value [[REG0]]
-// CHECK: [[REG2:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[REG1]]
-// CHECK: [[REG4:%.*]] = begin_borrow [[REG2]]
-// CHECK: [[REG5:%.*]] = struct_extract [[REG0]], #NCWrapper._nc
-// CHECK: end_borrow [[REG4]]
-// CHECK: destroy_value [[REG2]]
-// CHECK: return [[REG5]]
+// CHECK: sil hidden [ossa] @$s15borrow_accessor12GenNCWrapperVAARi_zrlE10nested_nc1AA2NCVvz : $@convention(method) (@inout GenNCWrapper) -> @guaranteed_addr NC {
+// CHECK:bb0([[REG0:%.*]] : $*GenNCWrapper):
+// CHECK: debug_value [[REG0]], var, name "self", argno 1, expr op_deref
+// CHECK: [[REG2:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[REG0]]
+// CHECK: [[REG3:%.*]] = struct_element_addr [[REG2]], #GenNCWrapper._ncw
+// CHECK: [[REG4:%.*]] = function_ref @$s15borrow_accessor9NCWrapperV2ncAA2NCVvz : $@convention(method) (@inout NCWrapper) -> @guaranteed_addr NC
+// CHECK: [[REG5:%.*]] = apply [[REG4]]([[REG3]]) : $@convention(method) (@inout NCWrapper) -> @guaranteed_addr NC
+// CHECK: [[REG6:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[REG5]]
+// CHECK: return [[REG6]]
// CHECK: }
// CHECK: sil hidden [ossa] @$s15borrow_accessor12GenNCWrapperVAARi_zrlE10nested_nc2AA2NCVvb : $@convention(method) (@in_guaranteed GenNCWrapper) -> @guaranteed NC {
@@ -704,53 +779,62 @@ func nctest() {
// CHECK: return [[REG9]]
// CHECK: }
-// CHECK-LABEL: sil hidden [ossa] @$s15borrow_accessor9NCWrapperV7nested1AA2NCVvb : $@convention(method) (@guaranteed NCWrapper) -> @guaranteed NC {
-// CHECK: bb0([[REG0]] : @guaranteed $NCWrapper):
-// CHECK: [[REG1:%.*]] = copy_value [[REG0]]
-// CHECK: [[REG2:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[REG1]]
-// CHECK: [[REG4:%.*]] = begin_borrow [[REG2]]
-// CHECK: [[REG5:%.*]] = struct_extract [[REG0]], #NCWrapper._s
-// CHECK: [[REG6:%.*]] = function_ref @$s15borrow_accessor3NCSV2ncAA2NCVvb : $@convention(method) (@guaranteed NCS) -> @guaranteed NC
-// CHECK: [[REG7:%.*]] = apply [[REG6]]([[REG5]]) : $@convention(method) (@guaranteed NCS) -> @guaranteed NC
-// CHECK: [[REG8:%.*]] = copy_value [[REG7]]
-// CHECK: [[REG9:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[REG8]]
-// CHECK: [[REG10:%.*]] = begin_borrow [[REG9]]
-// CHECK: end_borrow [[REG10]]
-// CHECK: destroy_value [[REG9]]
-// CHECK: end_borrow [[REG4]]
-// CHECK: destroy_value [[REG2]]
-// CHECK: return [[REG7]]
-// CHECK-LABEL: }
-
-// CHECK-LABEL: sil hidden [ossa] @$s15borrow_accessor9NCWrapperVyAA2NCVSicib : $@convention(method) (Int, @guaranteed NCWrapper) -> @guaranteed NC {
-// CHECK: bb0([[REG0]] : $Int, [[REG1]] : @guaranteed $NCWrapper):
-// CHECK: [[REG3:%.*]] = copy_value [[REG1]]
-// CHECK: [[REG4:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[REG3]]
-// CHECK: [[REG6:%.*]] = begin_borrow [[REG4]]
-// CHECK: [[REG7:%.*]] = struct_extract [[REG1]], #NCWrapper._nc
-// CHECK: end_borrow [[REG6]]
-// CHECK: destroy_value [[REG4]]
-// CHECK: return [[REG7]]
+// CHECK: sil hidden [ossa] @$s15borrow_accessor12GenNCWrapperVAARi_zrlE10nested_nc2AA2NCVvz : $@convention(method) (@inout GenNCWrapper) -> @guaranteed_addr NC {
+// CHECK:bb0([[REG0:%.*]] : $*GenNCWrapper):
+// CHECK: debug_value [[REG0]], var, name "self", argno 1, expr op_deref
+// CHECK: [[REG2:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[REG0]]
+// CHECK: [[REG3:%.*]] = function_ref @$s15borrow_accessor12GenNCWrapperVAARi_zrlE3ncwAA0D0Vvz : $@convention(method) <τ_0_0 where τ_0_0 : ~Copyable> (@inout GenNCWrapper<τ_0_0>) -> @guaranteed_addr NCWrapper
+// CHECK: [[REG4:%.*]] = apply [[REG3]]([[REG2]]) : $@convention(method) <τ_0_0 where τ_0_0 : ~Copyable> (@inout GenNCWrapper<τ_0_0>) -> @guaranteed_addr NCWrapper
+// CHECK: [[REG5:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[REG4]]
+// CHECK: [[REG6:%.*]] = function_ref @$s15borrow_accessor9NCWrapperV2ncAA2NCVvz : $@convention(method) (@inout NCWrapper) -> @guaranteed_addr NC
+// CHECK: [[REG7:%.*]] = apply [[REG6]]([[REG5]]) : $@convention(method) (@inout NCWrapper) -> @guaranteed_addr NC
+// CHECK: [[REG8:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[REG7]]
+// CHECK: return [[REG8]]
// CHECK: }
-// CHECK-LABEL: sil hidden [ossa] @$s15borrow_accessor9NCWrapperV16nested_subscriptAA2NCVvb : $@convention(method) (@guaranteed NCWrapper) -> @guaranteed NC {
-// CHECK: bb0([[REG0]] : @guaranteed $NCWrapper):
-// CHECK: [[REG1:%.*]] = copy_value [[REG0]]
-// CHECK: [[REG2:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[REG1]]
-// CHECK: [[REG4:%.*]] = begin_borrow [[REG2]]
-// CHECK: [[REG5:%.*]] = integer_literal $Builtin.IntLiteral, 0
-// CHECK: [[REG6:%.*]] = metatype $@thin Int.Type
-// CHECK: [[REG7:%.*]] = function_ref @$sSi22_builtinIntegerLiteralSiBI_tcfC : $@convention(method) (Builtin.IntLiteral, @thin Int.Type) -> Int
-// CHECK: [[REG8:%.*]] = apply [[REG7]]([[REG5]], [[REG6]]) : $@convention(method) (Builtin.IntLiteral, @thin Int.Type) -> Int
-// CHECK: [[REG9:%.*]] = function_ref @$s15borrow_accessor9NCWrapperVyAA2NCVSicib : $@convention(method) (Int, @guaranteed NCWrapper) -> @guaranteed NC
-// CHECK: [[REG10:%.*]] = apply [[REG9]]([[REG8]], [[REG0]]) : $@convention(method) (Int, @guaranteed NCWrapper) -> @guaranteed NC
-// CHECK: [[REG11:%.*]] = copy_value [[REG10]]
-// CHECK: [[REG12:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[REG11]]
-// CHECK: [[REG13:%.*]] = begin_borrow [[REG12]]
-// CHECK: end_borrow [[REG13]]
-// CHECK: destroy_value [[REG12]]
-// CHECK: end_borrow [[REG4]]
-// CHECK: destroy_value [[REG2]]
-// CHECK: return [[REG10]]
+// CHECK: sil hidden [ossa] @$s15borrow_accessor12GenNCWrapperVAARi_zrlEyxSicib : $@convention(method) (Int, @in_guaranteed GenNCWrapper) -> @guaranteed_addr T {
+// CHECK: bb0([[REG0:%.*]] : $Int, [[REG1:%.*]] : $*GenNCWrapper):
+// CHECK: debug_value [[REG0]], let, name "index", argno 1
+// CHECK: debug_value [[REG1]], let, name "self", argno 2, expr op_deref
+// CHECK: [[REG4:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[REG1]]
+// CHECK: [[REG5:%.*]] = struct_element_addr [[REG4]], #GenNCWrapper._prop
+// CHECK: return [[REG5]]
+// CHECK: }
+
+// CHECK: sil hidden [ossa] @$s15borrow_accessor12GenNCWrapperVAARi_zrlEyxSiciz : $@convention(method) (Int, @inout GenNCWrapper) -> @guaranteed_addr T {
+// CHECK:bb0([[REG0:%.*]] : $Int, [[REG1:%.*]] : $*GenNCWrapper):
+// CHECK: debug_value [[REG0]], let, name "index", argno 1
+// CHECK: debug_value [[REG1]], var, name "self", argno 2, expr op_deref
+// CHECK: [[REG4:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[REG1]]
+// CHECK: [[REG5:%.*]] = struct_element_addr [[REG4]], #GenNCWrapper._prop
+// CHECK: return [[REG5]]
+// CHECK: }
+
+// CHECK: sil hidden [ossa] @$s15borrow_accessor12GenNCWrapperVAARi_zrlE16nested_subscriptxvb : $@convention(method) (@in_guaranteed GenNCWrapper) -> @guaranteed_addr T {
+// CHECK: bb0([[REG0:%.*]] : $*GenNCWrapper):
+// CHECK: debug_value [[REG0]], let, name "self", argno 1, expr op_deref
+// CHECK: [[REG2:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[REG0]]
+// CHECK: [[REG3:%.*]] = integer_literal $Builtin.IntLiteral, 0
+// CHECK: [[REG4:%.*]] = metatype $@thin Int.Type
+// CHECK: [[REG5:%.*]] = function_ref @$sSi22_builtinIntegerLiteralSiBI_tcfC : $@convention(method) (Builtin.IntLiteral, @thin Int.Type) -> Int
+// CHECK: [[REG6:%.*]] = apply [[REG5]]([[REG3]], [[REG4]]) : $@convention(method) (Builtin.IntLiteral, @thin Int.Type) -> Int
+// CHECK: [[REG7:%.*]] = function_ref @$s15borrow_accessor12GenNCWrapperVAARi_zrlEyxSicib : $@convention(method) <τ_0_0 where τ_0_0 : ~Copyable> (Int, @in_guaranteed GenNCWrapper<τ_0_0>) -> @guaranteed_addr τ_0_0
+// CHECK: [[REG8:%.*]] = apply [[REG7]]([[REG6]], [[REG2]]) : $@convention(method) <τ_0_0 where τ_0_0 : ~Copyable> (Int, @in_guaranteed GenNCWrapper<τ_0_0>) -> @guaranteed_addr τ_0_0
+// CHECK: [[REG9:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[REG8]]
+// CHECK: return [[REG9]]
+// CHECK: }
+
+// CHECK: sil hidden [ossa] @$s15borrow_accessor12GenNCWrapperVAARi_zrlE16nested_subscriptxvz : $@convention(method) (@inout GenNCWrapper) -> @guaranteed_addr T {
+// CHECK:bb0([[REG0:%.*]] : $*GenNCWrapper):
+// CHECK: debug_value [[REG0]], var, name "self", argno 1, expr op_deref
+// CHECK: [[REG2:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[REG0]]
+// CHECK: [[REG3:%.*]] = integer_literal $Builtin.IntLiteral, 0
+// CHECK: [[REG4:%.*]] = metatype $@thin Int.Type
+// CHECK: [[REG5:%.*]] = function_ref @$sSi22_builtinIntegerLiteralSiBI_tcfC : $@convention(method) (Builtin.IntLiteral, @thin Int.Type) -> Int
+// CHECK: [[REG6:%.*]] = apply [[REG5]]([[REG3]], [[REG4]]) : $@convention(method) (Builtin.IntLiteral, @thin Int.Type) -> Int
+// CHECK: [[REG7:%.*]] = function_ref @$s15borrow_accessor12GenNCWrapperVAARi_zrlEyxSiciz : $@convention(method) <τ_0_0 where τ_0_0 : ~Copyable> (Int, @inout GenNCWrapper<τ_0_0>) -> @guaranteed_addr τ_0_0
+// CHECK: [[REG8:%.*]] = apply [[REG7]]([[REG6]], [[REG2]]) : $@convention(method) <τ_0_0 where τ_0_0 : ~Copyable> (Int, @inout GenNCWrapper<τ_0_0>) -> @guaranteed_addr τ_0_0
+// CHECK: [[REG9:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[REG8]]
+// CHECK: return [[REG9]]
// CHECK: }
diff --git a/test/SILGen/borrow_accessor_container.swift b/test/SILGen/borrow_accessor_container.swift
index e6a8c7cc1aad7..02a1fed16e061 100644
--- a/test/SILGen/borrow_accessor_container.swift
+++ b/test/SILGen/borrow_accessor_container.swift
@@ -11,6 +11,10 @@ public struct Container: ~Copyable {
borrow {
return _storage.baseAddress.unsafelyUnwrapped.pointee
}
+ @_unsafeSelfDependentResult
+ mutate {
+ return &_storage.baseAddress.unsafelyUnwrapped.pointee
+ }
}
public subscript(index: Int) -> Element {
@@ -19,11 +23,72 @@ public struct Container: ~Copyable {
precondition(index >= 0 && index < _count, "Index out of bounds")
return _storage.baseAddress.unsafelyUnwrapped.advanced(by: index).pointee
}
+ @_unsafeSelfDependentResult
+ mutate {
+ precondition(index >= 0 && index < _count, "Index out of bounds")
+ return &_storage.baseAddress.unsafelyUnwrapped.advanced(by: index).pointee
+ }
}
}
extension Container: Copyable where Element: Copyable {}
+// CHECK: sil hidden [ossa] @$s25borrow_accessor_container9ContainerVAARi_zrlE5firstxvb : $@convention(method) (@guaranteed Container) -> @guaranteed_addr Element {
+// CHECK: bb0([[REG0:%.*]] : @guaranteed $Container):
+// CHECK: [[REG1:%.*]] = copy_value [[REG0]]
+// CHECK: [[REG2:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[REG1]]
+// CHECK: debug_value [[REG2]], let, name "self", argno 1
+// CHECK: [[REG4:%.*]] = begin_borrow [[REG2]]
+// CHECK: [[REG5:%.*]] = struct_extract [[REG0]], #Container._storage
+// CHECK: [[REG6:%.*]] = alloc_stack $Optional>
+// CHECK: [[REG7:%.*]] = function_ref @$sSr11baseAddressSpyxGSgvg : $@convention(method) <τ_0_0 where τ_0_0 : ~Copyable> (UnsafeMutableBufferPointer<τ_0_0>) -> Optional>
+// CHECK: [[REG8:%.*]] = apply [[REG7]]([[REG5]]) : $@convention(method) <τ_0_0 where τ_0_0 : ~Copyable> (UnsafeMutableBufferPointer<τ_0_0>) -> Optional>
+// CHECK: store [[REG8]] to [trivial] [[REG6]]
+// CHECK: [[REG10:%.*]] = alloc_stack $UnsafeMutablePointer
+// CHECK: [[REG11:%.*]] = function_ref @$sSq17unsafelyUnwrappedxvg : $@convention(method) <τ_0_0 where τ_0_0 : ~Escapable> (@in_guaranteed Optional<τ_0_0>) -> @lifetime(copy 0) @out τ_0_0
+// CHECK: [[REG12:%.*]] = apply [[REG11]]>([[REG10]], [[REG6]]) : $@convention(method) <τ_0_0 where τ_0_0 : ~Escapable> (@in_guaranteed Optional<τ_0_0>) -> @lifetime(copy 0) @out τ_0_0
+// CHECK: [[REG13:%.*]] = load [trivial] [[REG10]]
+// CHECK: [[REG14:%.*]] = function_ref @$sSpsRi_zrlE7pointeexvlu : $@convention(method) <τ_0_0 where τ_0_0 : ~Copyable> (UnsafeMutablePointer<τ_0_0>) -> UnsafePointer<τ_0_0>
+// CHECK: [[REG15:%.*]] = apply [[REG14]]([[REG13]]) : $@convention(method) <τ_0_0 where τ_0_0 : ~Copyable> (UnsafeMutablePointer<τ_0_0>) -> UnsafePointer<τ_0_0>
+// CHECK: [[REG16:%.*]] = struct_extract [[REG15]], #UnsafePointer._rawValue
+// CHECK: [[REG17:%.*]] = pointer_to_address [[REG16]] to [strict] $*Element
+// CHECK: [[REG18:%.*]] = mark_dependence [unresolved] [[REG17]] on [[REG13]]
+// CHECK: [[REG19:%.*]] = begin_access [read] [unsafe] [[REG18]]
+// CHECK: [[REG20:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[REG19]]
+// CHECK: end_access [[REG19]]
+// CHECK: dealloc_stack [[REG10]]
+// CHECK: dealloc_stack [[REG6]]
+// CHECK: end_borrow [[REG4]]
+// CHECK: destroy_value [[REG2]]
+// CHECK: return [[REG20]]
+// CHECK: }
+
+// CHECK: sil hidden [ossa] @$s25borrow_accessor_container9ContainerVAARi_zrlE5firstxvz : $@convention(method) (@inout Container) -> @guaranteed_addr Element {
+// CHECK: bb0([[REG0:%.*]] : $*Container):
+// CHECK: debug_value [[REG0]], var, name "self", argno 1, expr op_deref
+// CHECK: [[REG2:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[REG0]]
+// CHECK: [[REG3:%.*]] = struct_element_addr [[REG2]], #Container._storage
+// CHECK: [[REG4:%.*]] = load [trivial] [[REG3]]
+// CHECK: [[REG5:%.*]] = alloc_stack $Optional>
+// CHECK: [[REG6:%.*]] = function_ref @$sSr11baseAddressSpyxGSgvg : $@convention(method) <τ_0_0 where τ_0_0 : ~Copyable> (UnsafeMutableBufferPointer<τ_0_0>) -> Optional>
+// CHECK: [[REG7:%.*]] = apply [[REG6]]([[REG4]]) : $@convention(method) <τ_0_0 where τ_0_0 : ~Copyable> (UnsafeMutableBufferPointer<τ_0_0>) -> Optional>
+// CHECK: store [[REG7]] to [trivial] [[REG5]]
+// CHECK: [[REG9:%.*]] = alloc_stack $UnsafeMutablePointer
+// CHECK: [[REG10:%.*]] = function_ref @$sSq17unsafelyUnwrappedxvg : $@convention(method) <τ_0_0 where τ_0_0 : ~Escapable> (@in_guaranteed Optional<τ_0_0>) -> @lifetime(copy 0) @out τ_0_0
+// CHECK: [[REG11:%.*]] = apply [[REG10]]>([[REG9]], [[REG5]]) : $@convention(method) <τ_0_0 where τ_0_0 : ~Escapable> (@in_guaranteed Optional<τ_0_0>) -> @lifetime(copy 0) @out τ_0_0
+// CHECK: [[REG12:%.*]] = load [trivial] [[REG9]]
+// CHECK: [[REG13:%.*]] = function_ref @$sSpsRi_zrlE7pointeexvau : $@convention(method) <τ_0_0 where τ_0_0 : ~Copyable> (UnsafeMutablePointer<τ_0_0>) -> UnsafeMutablePointer<τ_0_0>
+// CHECK: [[REG14:%.*]] = apply [[REG13]]([[REG12]]) : $@convention(method) <τ_0_0 where τ_0_0 : ~Copyable> (UnsafeMutablePointer<τ_0_0>) -> UnsafeMutablePointer<τ_0_0>
+// CHECK: [[REG15:%.*]] = struct_extract [[REG14]], #UnsafeMutablePointer._rawValue
+// CHECK: [[REG16:%.*]] = pointer_to_address [[REG15]] to [strict] $*Element
+// CHECK: [[REG17:%.*]] = mark_dependence [unresolved] [[REG16]] on [[REG12]]
+// CHECK: [[REG18:%.*]] = begin_access [modify] [unsafe] [[REG17]]
+// CHECK: [[REG19:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[REG18]]
+// CHECK: end_access [[REG18]]
+// CHECK: dealloc_stack [[REG9]]
+// CHECK: dealloc_stack [[REG5]]
+// CHECK: return [[REG19]]
+// CHECK: }
// CHECK: sil [ossa] @$s25borrow_accessor_container9ContainerVAARi_zrlEyxSicib : $@convention(method) (Int, @guaranteed Container) -> @guaranteed_addr Element {
// CHECK: bb0([[REG0:%.*]] : $Int, [[REG1:%.*]] : @guaranteed $Container):
@@ -61,7 +126,45 @@ extension Container: Copyable where Element: Copyable {}
// CHECK: destroy_value [[REG4]]
// CHECK: return [[REG32]]
// CHECK: }
-
+
+// CHECK: sil [ossa] @$s25borrow_accessor_container9ContainerVAARi_zrlEyxSiciz : $@convention(method) (Int, @inout Container) -> @guaranteed_addr Element {
+// CHECK: bb0([[REG0:%.*]] : $Int, [[REG1:%.*]] : $*Container):
+// CHECK: debug_value [[REG0]], let, name "index", argno 1
+// CHECK: debug_value [[REG1]], var, name "self", argno 2, expr op_deref
+// CHECK: [[REG4:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[REG1]]
+// CHECK: [[REG5:%.*]] = alloc_stack $UnsafeMutablePointer
+// CHECK: [[REG6:%.*]] = begin_access [read] [unknown] [[REG4]]
+// CHECK: [[REG7:%.*]] = struct_element_addr [[REG6]], #Container._storage
+// CHECK: [[REG8:%.*]] = load [trivial] [[REG7]]
+// CHECK: end_access [[REG6]]
+// CHECK: [[REG10:%.*]] = function_ref @$sSr11baseAddressSpyxGSgvg : $@convention(method) <τ_0_0 where τ_0_0 : ~Copyable> (UnsafeMutableBufferPointer<τ_0_0>) -> Optional>
+// CHECK: [[REG11:%.*]] = apply [[REG10]]([[REG8]]) : $@convention(method) <τ_0_0 where τ_0_0 : ~Copyable> (UnsafeMutableBufferPointer<τ_0_0>) -> Optional>
+// CHECK: [[REG12:%.*]] = alloc_stack $Optional>
+// CHECK: store [[REG11]] to [trivial] [[REG12]]
+// CHECK: [[REG14:%.*]] = alloc_stack $UnsafeMutablePointer
+// CHECK: [[REG15:%.*]] = function_ref @$sSq17unsafelyUnwrappedxvg : $@convention(method) <τ_0_0 where τ_0_0 : ~Escapable> (@in_guaranteed Optional<τ_0_0>) -> @lifetime(copy 0) @out τ_0_0
+// CHECK: [[REG16:%.*]] = apply [[REG15]]>([[REG14]], [[REG12]]) : $@convention(method) <τ_0_0 where τ_0_0 : ~Escapable> (@in_guaranteed Optional<τ_0_0>) -> @lifetime(copy 0) @out τ_0_0
+// CHECK: [[REG17:%.*]] = load [trivial] [[REG14]]
+// CHECK: [[REG18:%.*]] = alloc_stack $UnsafeMutablePointer
+// CHECK: store [[REG17]] to [trivial] [[REG18]]
+// CHECK: [[REG20:%.*]] = function_ref @$ss8_PointerPsE8advanced2byxSi_tF : $@convention(method) <τ_0_0 where τ_0_0 : _Pointer> (Int, @in_guaranteed τ_0_0) -> @out τ_0_0
+// CHECK: [[REG21:%.*]] = apply [[REG20]]>([[REG5]], [[REG0]], [[REG18]]) : $@convention(method) <τ_0_0 where τ_0_0 : _Pointer> (Int, @in_guaranteed τ_0_0) -> @out τ_0_0
+// CHECK: dealloc_stack [[REG18]]
+// CHECK: dealloc_stack [[REG14]]
+// CHECK: dealloc_stack [[REG12]]
+// CHECK: [[REG25:%.*]] = load [trivial] [[REG5]]
+// CHECK: [[REG26:%.*]] = function_ref @$sSpsRi_zrlE7pointeexvau : $@convention(method) <τ_0_0 where τ_0_0 : ~Copyable> (UnsafeMutablePointer<τ_0_0>) -> UnsafeMutablePointer<τ_0_0>
+// CHECK: [[REG27:%.*]] = apply [[REG26]]([[REG25]]) : $@convention(method) <τ_0_0 where τ_0_0 : ~Copyable> (UnsafeMutablePointer<τ_0_0>) -> UnsafeMutablePointer<τ_0_0>
+// CHECK: [[REG28:%.*]] = struct_extract [[REG27]], #UnsafeMutablePointer._rawValue
+// CHECK: [[REG29:%.*]] = pointer_to_address [[REG28]] to [strict] $*Element
+// CHECK: [[REG30:%.*]] = mark_dependence [unresolved] [[REG29]] on [[REG25]]
+// CHECK: [[REG31:%.*]] = begin_access [modify] [unsafe] [[REG30]]
+// CHECK: [[REG32:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[REG31]]
+// CHECK: end_access [[REG31]]
+// CHECK: dealloc_stack [[REG5]]
+// CHECK: return [[REG32]]
+// CHECK: }
+
public class Klass {}
public struct S {
@@ -85,6 +188,11 @@ public struct CopyableContainer {
precondition(index >= 0 && index < _count, "Index out of bounds")
return _storage.baseAddress.unsafelyUnwrapped.advanced(by: index).pointee._k
}
+ @_unsafeSelfDependentResult
+ mutate {
+ precondition(index >= 0 && index < _count, "Index out of bounds")
+ return &_storage.baseAddress.unsafelyUnwrapped.advanced(by: index).pointee._k
+ }
}
}
@@ -124,6 +232,43 @@ public struct CopyableContainer {
// CHECK: return [[REG32]]
// CHECK: }
+// CHECK: sil [ossa] @$s25borrow_accessor_container17CopyableContainerVyAA5KlassCSiciz : $@convention(method) (Int, @inout CopyableContainer) -> @guaranteed_addr Klass {
+// CHECK: bb0([[REG0:%.*]] : $Int, [[REG1:%.*]] : $*CopyableContainer):
+// CHECK: debug_value [[REG0]], let, name "index", argno 1
+// CHECK: debug_value [[REG1]], var, name "self", argno 2, expr op_deref
+// CHECK: [[REG4:%.*]] = alloc_stack $UnsafeMutablePointer
+// CHECK: [[REG5:%.*]] = begin_access [read] [unknown] [[REG1]]
+// CHECK: [[REG6:%.*]] = struct_element_addr [[REG5]], #CopyableContainer._storage
+// CHECK: [[REG7:%.*]] = load [trivial] [[REG6]]
+// CHECK: end_access [[REG5]]
+// CHECK: [[REG9:%.*]] = function_ref @$sSr11baseAddressSpyxGSgvg : $@convention(method) <τ_0_0 where τ_0_0 : ~Copyable> (UnsafeMutableBufferPointer<τ_0_0>) -> Optional>
+// CHECK: [[REG10:%.*]] = apply [[REG9]]([[REG7]]) : $@convention(method) <τ_0_0 where τ_0_0 : ~Copyable> (UnsafeMutableBufferPointer<τ_0_0>) -> Optional>
+// CHECK: [[REG11:%.*]] = alloc_stack $Optional>
+// CHECK: store [[REG10]] to [trivial] [[REG11]]
+// CHECK: [[REG13:%.*]] = alloc_stack $UnsafeMutablePointer
+// CHECK: [[REG14:%.*]] = function_ref @$sSq17unsafelyUnwrappedxvg : $@convention(method) <τ_0_0 where τ_0_0 : ~Escapable> (@in_guaranteed Optional<τ_0_0>) -> @lifetime(copy 0) @out τ_0_0
+// CHECK: [[REG15:%.*]] = apply [[REG14]]>([[REG13]], [[REG11]]) : $@convention(method) <τ_0_0 where τ_0_0 : ~Escapable> (@in_guaranteed Optional<τ_0_0>) -> @lifetime(copy 0) @out τ_0_0
+// CHECK: [[REG16:%.*]] = load [trivial] [[REG13]]
+// CHECK: [[REG17:%.*]] = alloc_stack $UnsafeMutablePointer
+// CHECK: store [[REG16]] to [trivial] [[REG17]]
+// CHECK: [[REG19:%.*]] = function_ref @$ss8_PointerPsE8advanced2byxSi_tF : $@convention(method) <τ_0_0 where τ_0_0 : _Pointer> (Int, @in_guaranteed τ_0_0) -> @out τ_0_0
+// CHECK: [[REG20:%.*]] = apply [[REG19]]>([[REG4]], [[REG0]], [[REG17]]) : $@convention(method) <τ_0_0 where τ_0_0 : _Pointer> (Int, @in_guaranteed τ_0_0) -> @out τ_0_0
+// CHECK: dealloc_stack [[REG17]]
+// CHECK: dealloc_stack [[REG13]]
+// CHECK: dealloc_stack [[REG11]]
+// CHECK: [[REG24:%.*]] = load [trivial] [[REG4]]
+// CHECK: [[REG25:%.*]] = function_ref @$sSpsRi_zrlE7pointeexvau : $@convention(method) <τ_0_0 where τ_0_0 : ~Copyable> (UnsafeMutablePointer<τ_0_0>) -> UnsafeMutablePointer<τ_0_0>
+// CHECK: [[REG26:%.*]] = apply [[REG25]]([[REG24]]) : $@convention(method) <τ_0_0 where τ_0_0 : ~Copyable> (UnsafeMutablePointer<τ_0_0>) -> UnsafeMutablePointer<τ_0_0>
+// CHECK: [[REG27:%.*]] = struct_extract [[REG26]], #UnsafeMutablePointer._rawValue
+// CHECK: [[REG28:%.*]] = pointer_to_address [[REG27]] to [strict] $*S
+// CHECK: [[REG29:%.*]] = mark_dependence [unresolved] [[REG28]] on [[REG24]]
+// CHECK: [[REG30:%.*]] = begin_access [modify] [unsafe] [[REG29]]
+// CHECK: [[REG31:%.*]] = struct_element_addr [[REG30]], #S._k
+// CHECK: end_access [[REG30]]
+// CHECK: dealloc_stack [[REG4]]
+// CHECK: return [[REG31]]
+// CHECK: }
+
public struct NC : ~Copyable {}
public struct NonCopyableContainer : ~Copyable {
@@ -143,6 +288,11 @@ public struct NonCopyableContainer : ~Copyable {
precondition(index >= 0 && index < _count, "Index out of bounds")
return _storage.baseAddress.unsafelyUnwrapped.advanced(by: index).pointee
}
+ @_unsafeSelfDependentResult
+ mutate {
+ precondition(index >= 0 && index < _count, "Index out of bounds")
+ return &_storage.baseAddress.unsafelyUnwrapped.advanced(by: index).pointee
+ }
}
}
@@ -187,4 +337,41 @@ public struct NonCopyableContainer : ~Copyable {
// CHECK: destroy_value [[REG4]]
// CHECK: return [[REG36]]
// CHECK: }
-
+
+// CHECK: sil [ossa] @$s25borrow_accessor_container20NonCopyableContainerVyAA2NCVSiciz : $@convention(method) (Int, @inout NonCopyableContainer) -> @guaranteed_addr NC {
+// CHECK: bb0([[REG0:%.*]] : $Int, [[REG1:%.*]] : $*NonCopyableContainer):
+// CHECK: debug_value [[REG0]], let, name "index", argno 1
+// CHECK: debug_value [[REG1]], var, name "self", argno 2, expr op_deref
+// CHECK: [[REG4:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[REG1]]
+// CHECK: [[REG5:%.*]] = alloc_stack $UnsafeMutablePointer
+// CHECK: [[REG6:%.*]] = begin_access [read] [unknown] [[REG4]]
+// CHECK: [[REG7:%.*]] = struct_element_addr [[REG6]], #NonCopyableContainer._storage
+// CHECK: [[REG8:%.*]] = load [trivial] [[REG7]]
+// CHECK: end_access [[REG6]]
+// CHECK: [[REG10:%.*]] = function_ref @$sSr11baseAddressSpyxGSgvg : $@convention(method) <τ_0_0 where τ_0_0 : ~Copyable> (UnsafeMutableBufferPointer<τ_0_0>) -> Optional>
+// CHECK: [[REG11:%.*]] = apply [[REG10]]([[REG8]]) : $@convention(method) <τ_0_0 where τ_0_0 : ~Copyable> (UnsafeMutableBufferPointer<τ_0_0>) -> Optional>
+// CHECK: [[REG12:%.*]] = alloc_stack $Optional>
+// CHECK: store [[REG11]] to [trivial] [[REG12]]
+// CHECK: [[REG14:%.*]] = alloc_stack $UnsafeMutablePointer
+// CHECK: [[REG15:%.*]] = function_ref @$sSq17unsafelyUnwrappedxvg : $@convention(method) <τ_0_0 where τ_0_0 : ~Escapable> (@in_guaranteed Optional<τ_0_0>) -> @lifetime(copy 0) @out τ_0_0
+// CHECK: [[REG16:%.*]] = apply [[REG15]]>([[REG14]], [[REG12]]) : $@convention(method) <τ_0_0 where τ_0_0 : ~Escapable> (@in_guaranteed Optional<τ_0_0>) -> @lifetime(copy 0) @out τ_0_0
+// CHECK: [[REG17:%.*]] = load [trivial] [[REG14]]
+// CHECK: [[REG18:%.*]] = alloc_stack $UnsafeMutablePointer
+// CHECK: store [[REG17]] to [trivial] [[REG18]]
+// CHECK: [[REG20:%.*]] = function_ref @$ss8_PointerPsE8advanced2byxSi_tF : $@convention(method) <τ_0_0 where τ_0_0 : _Pointer> (Int, @in_guaranteed τ_0_0) -> @out τ_0_0
+// CHECK: [[REG21:%.*]] = apply [[REG20]]>([[REG5]], [[REG0]], [[REG18]]) : $@convention(method) <τ_0_0 where τ_0_0 : _Pointer> (Int, @in_guaranteed τ_0_0) -> @out τ_0_0
+// CHECK: dealloc_stack [[REG18]]
+// CHECK: dealloc_stack [[REG14]]
+// CHECK: dealloc_stack [[REG12]]
+// CHECK: [[REG25:%.*]] = load [trivial] [[REG5]]
+// CHECK: [[REG26:%.*]] = function_ref @$sSpsRi_zrlE7pointeexvau : $@convention(method) <τ_0_0 where τ_0_0 : ~Copyable> (UnsafeMutablePointer<τ_0_0>) -> UnsafeMutablePointer<τ_0_0>
+// CHECK: [[REG27:%.*]] = apply [[REG26]]([[REG25]]) : $@convention(method) <τ_0_0 where τ_0_0 : ~Copyable> (UnsafeMutablePointer<τ_0_0>) -> UnsafeMutablePointer<τ_0_0>
+// CHECK: [[REG28:%.*]] = struct_extract [[REG27]], #UnsafeMutablePointer._rawValue
+// CHECK: [[REG29:%.*]] = pointer_to_address [[REG28]] to [strict] $*NC
+// CHECK: [[REG30:%.*]] = mark_dependence [unresolved] [[REG29]] on [[REG25]]
+// CHECK: [[REG31:%.*]] = begin_access [modify] [unsafe] [[REG30]]
+// CHECK: [[REG32:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[REG31]]
+// CHECK: end_access [[REG31]]
+// CHECK: dealloc_stack [[REG5]]
+// CHECK: return [[REG32]]
+// CHECK: }
diff --git a/test/SILGen/borrow_accessor_failues.swift b/test/SILGen/borrow_accessor_failues.swift
new file mode 100644
index 0000000000000..488665bacc6d3
--- /dev/null
+++ b/test/SILGen/borrow_accessor_failues.swift
@@ -0,0 +1,270 @@
+// RUN:%target-swift-frontend -emit-silgen %s -verify -enable-experimental-feature BorrowAndMutateAccessors
+
+// REQUIRES: swift_feature_BorrowAndMutateAccessors
+
+public class Klass {
+ var id: Int = 0
+}
+
+func get_k() -> Klass {
+ return Klass()
+}
+
+public struct S {
+ var _k: Klass
+
+ var borrow_k: Klass {
+ borrow {
+ return _k
+ }
+ }
+ var get_k: Klass {
+ get {
+ return _k
+ }
+ }
+ var read_k: Klass {
+ _read {
+ yield _k
+ }
+ }
+}
+
+public struct Wrapper {
+ var _k: Klass
+ var _s: S
+
+ var k: Klass {
+ borrow {
+ return _k
+ }
+ }
+
+ var s: S {
+ borrow {
+ return _s
+ }
+ }
+
+ var s_get: S {
+ get {
+ return _s
+ }
+ }
+
+ var s_read: S {
+ _read {
+ yield _s
+ }
+ }
+
+ var nested_get1: Klass {
+ borrow {
+ return _s.get_k // expected-error{{invalid return value from borrow accessor}} // expected-note{{borrow accessors can return either literals, stored properties or computed properties that have borrow accessors}}
+ }
+ }
+
+ var nested_get2: Klass {
+ borrow {
+ return s_get.borrow_k // expected-error{{invalid return value from borrow accessor}} // expected-note{{borrow accessors can return either literals, stored properties or computed properties that have borrow accessors}}
+ }
+ }
+
+ var nested_get3: Int {
+ borrow {
+ return _s.get_k.id // TODO: Diagnose this case
+ }
+ }
+
+ var nested_get4: Int {
+ borrow {
+ return s_get.borrow_k.id // TODO: Diagnose this case
+ }
+ }
+
+ var nested_read1: Klass {
+ borrow {
+ return _s.read_k // expected-error{{invalid return value from borrow accessor}} // expected-note{{borrow accessors can return either literals, stored properties or computed properties that have borrow accessors}}
+ }
+ }
+
+ var nested_read2: Klass {
+ borrow {
+ return s_read.read_k // expected-error{{invalid return value from borrow accessor}} // expected-note{{borrow accessors can return either literals, stored properties or computed properties that have borrow accessors}}
+ }
+ }
+
+ var owned_value_direct: Klass {
+ borrow {
+ return get_k() // expected-error{{invalid return value from borrow accessor}} // expected-note{{borrow accessors can return either literals, stored properties or computed properties that have borrow accessors}}
+ }
+ }
+
+ var owned_value_projected: Klass {
+ borrow {
+ let w = Wrapper(_k: Klass(), _s: S(_k: Klass()))
+ return w.k // expected-error{{invalid return value from borrow accessor}} // expected-note{{borrow accessors can return either literals, stored properties or computed properties that have borrow accessors}}
+ }
+ }
+
+ var if_klass: Klass {
+ borrow {
+ if Int.random(in: 1..<100) == 0 {
+ return _k
+ }
+ return _k // expected-error{{multiple return statements in borrow accessors are not yet supported}}
+ }
+ }
+
+ var tuple_klass: (Klass, Klass) {
+ borrow {
+ return (_k, _k) // expected-error{{invalid return value from borrow accessor}} // expected-note{{borrow accessors can return either literals, stored properties or computed properties that have borrow accessors}}
+ }
+ }
+
+ var opt_klass: Klass? {
+ borrow {
+ if Int.random(in: 1..<100) == 0 {
+ return nil
+ }
+ return _k // expected-error{{invalid return value from borrow accessor}} // expected-note{{borrow accessors can return either literals, stored properties or computed properties that have borrow accessors}}
+ }
+ }
+}
+
+public struct SimpleWrapper {
+ var _prop: T
+
+ var borrow_prop: T {
+ borrow {
+ return _prop
+ }
+ }
+
+ var get_prop: T {
+ get {
+ return _prop
+ }
+ }
+
+ var read_prop: T {
+ _read {
+ yield _prop
+ }
+ }
+}
+
+public struct GenWrapper {
+ var _prop: T
+ var _w: SimpleWrapper
+
+ public var prop: T {
+ borrow {
+ return _prop
+ }
+ }
+
+ var get_prop: T {
+ borrow {
+ return _w.get_prop // expected-error{{invalid return value from borrow accessor}} // expected-note{{borrow accessors can return either literals, stored properties or computed properties that have borrow accessors}}
+
+ }
+ }
+
+ var read_prop: T {
+ borrow {
+ return _w.read_prop // expected-error{{invalid return value from borrow accessor}} // expected-note{{borrow accessors can return either literals, stored properties or computed properties that have borrow accessors}}
+ }
+ }
+
+ var if_prop: T {
+ borrow {
+ if Int.random(in: 1..<100) == 0 {
+ return _prop
+ }
+ return _prop // expected-error{{multiple return statements in borrow accessors are not yet supported}}
+ }
+ }
+
+ var tuple_prop: (T, T) {
+ borrow {
+ return (_prop, _prop) // expected-error{{invalid return value from borrow accessor}} // expected-note{{borrow accessors can return either literals, stored properties or computed properties that have borrow accessors}}
+ }
+ }
+
+ var opt_T: T? {
+ borrow {
+ if Int.random(in: 1..<100) == 0 {
+ return nil
+ }
+ return _prop // expected-error{{invalid return value from borrow accessor}} // expected-note{{borrow accessors can return either literals, stored properties or computed properties that have borrow accessors}}
+
+ }
+ }
+}
+
+public struct SimpleNCWrapper : ~Copyable {
+ var _prop: T
+
+ var borrow_prop: T {
+ borrow {
+ return _prop
+ }
+ }
+
+ var get_prop: T {
+ get {
+ return _prop
+ }
+ }
+
+ var read_prop: T {
+ _read {
+ yield _prop
+ }
+ }
+}
+
+public struct GenNCWrapper : ~Copyable {
+ var _prop: T
+ var _w: SimpleNCWrapper
+
+ public var prop: T {
+ borrow {
+ return _prop
+ }
+ }
+
+ var nested_get: T {
+ borrow {
+ return _w.get_prop // expected-error{{invalid return value from borrow accessor}} // expected-note{{borrow accessors can return either literals, stored properties or computed properties that have borrow accessors}}
+
+ }
+ }
+
+ var nested_read: T {
+ borrow {
+ return _w.read_prop // expected-error{{invalid return value from borrow accessor}} // expected-note{{borrow accessors can return either literals, stored properties or computed properties that have borrow accessors}}
+
+ }
+ }
+
+ var if_prop: T {
+ borrow {
+ if Int.random(in: 1..<100) == 0 {
+ return _prop
+ }
+ return _prop // expected-error{{multiple return statements in borrow accessors are not yet supported}}
+ }
+ }
+
+ var opt_T: T? {
+ borrow {
+ if Int.random(in: 1..<100) == 0 {
+ return nil
+ }
+ return _prop // expected-error{{invalid return value from borrow accessor}} // expected-note{{borrow accessors can return either literals, stored properties or computed properties that have borrow accessors}}
+ }
+ }
+}
+