Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 44 additions & 39 deletions lib/SILGen/SILGenApply.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -211,17 +211,19 @@ static ManagedValue borrowedCastToOriginalSelfType(SILGenFunction &SGF,
originalSelfType);
}

static ManagedValue convertOwnershipConventionGivenParamInfo(SILGenFunction &SGF,
SILParameterInfo param,
ManagedValue value,
SILLocation loc) {
static ManagedValue convertOwnershipConventionGivenParamInfo(
SILGenFunction &SGF, SILParameterInfo param, ManagedValue value,
SILLocation loc, bool isForCoroutine) {
if (param.isConsumed() &&
value.getOwnershipKind() == ValueOwnershipKind::Guaranteed) {
return value.copyUnmanaged(SGF, loc);
}

if (SGF.F.getModule().getOptions().EnableSILOwnership &&
value.getOwnershipKind() == ValueOwnershipKind::Owned) {
// If we are emitting arguments for a coroutine, we need to borrow owned
// values to ensure that they are live over the entire closure invocation. If
// we do not have a coroutine, then we have an immediate non-consuming use so
// no borrow is necessary.
if (isForCoroutine && value.getOwnershipKind() == ValueOwnershipKind::Owned) {
if (param.isDirectGuaranteed() || (!SGF.silConv.useLoweredAddresses() &&
param.isIndirectInGuaranteed())) {
return value.borrow(SGF, loc);
Expand All @@ -232,16 +234,15 @@ static ManagedValue convertOwnershipConventionGivenParamInfo(SILGenFunction &SGF
}

static void convertOwnershipConventionsGivenParamInfos(
SILGenFunction &SGF,
ArrayRef<SILParameterInfo> params,
ArrayRef<ManagedValue> values,
SILLocation loc,
SILGenFunction &SGF, ArrayRef<SILParameterInfo> params,
ArrayRef<ManagedValue> values, SILLocation loc, bool isForCoroutine,
llvm::SmallVectorImpl<ManagedValue> &outVar) {
assert(params.size() == values.size() &&
"Different number of params from arguments");
transform(indices(params), std::back_inserter(outVar),
[&](unsigned i) -> ManagedValue {
return convertOwnershipConventionGivenParamInfo(SGF, params[i], values[i], loc);
return convertOwnershipConventionGivenParamInfo(
SGF, params[i], values[i], loc, isForCoroutine);
});
}

Expand Down Expand Up @@ -2571,6 +2572,7 @@ class ArgEmitter {
SILGenFunction &SGF;
SILFunctionTypeRepresentation Rep;
bool IsYield;
bool IsForCoroutine;
Optional<ForeignErrorConvention> ForeignError;
ImportAsMemberStatus ForeignSelf;
ClaimedParamsRef ParamInfos;
Expand All @@ -2583,16 +2585,16 @@ class ArgEmitter {
Optional<ArgSpecialDestArray> SpecialDests;
public:
ArgEmitter(SILGenFunction &SGF, SILFunctionTypeRepresentation Rep,
bool isYield, ClaimedParamsRef paramInfos,
bool isYield, bool isForCoroutine, ClaimedParamsRef paramInfos,
SmallVectorImpl<ManagedValue> &args,
SmallVectorImpl<DelayedArgument> &delayedArgs,
const Optional<ForeignErrorConvention> &foreignError,
ImportAsMemberStatus foreignSelf,
Optional<ArgSpecialDestArray> specialDests = None)
: SGF(SGF), Rep(Rep), IsYield(isYield), ForeignError(foreignError),
ForeignSelf(foreignSelf),
ParamInfos(paramInfos),
Args(args), DelayedArguments(delayedArgs), SpecialDests(specialDests) {
: SGF(SGF), Rep(Rep), IsYield(isYield), IsForCoroutine(isForCoroutine),
ForeignError(foreignError), ForeignSelf(foreignSelf),
ParamInfos(paramInfos), Args(args), DelayedArguments(delayedArgs),
SpecialDests(specialDests) {
assert(!specialDests || specialDests->size() == paramInfos.size());
}

Expand Down Expand Up @@ -2961,7 +2963,8 @@ class ArgEmitter {
auto loc = arg.getLocation();

auto convertOwnershipConvention = [&](ManagedValue value) {
return convertOwnershipConventionGivenParamInfo(SGF, param, value, loc);
return convertOwnershipConventionGivenParamInfo(SGF, param, value, loc,
IsForCoroutine);
};

auto contexts = getRValueEmissionContexts(loweredSubstArgType, param);
Expand Down Expand Up @@ -3224,11 +3227,11 @@ void DelayedArgument::emitDefaultArgument(SILGenFunction &SGF,
SmallVector<ManagedValue, 4> loweredArgs;
SmallVector<DelayedArgument, 4> delayedArgs;
Optional<ForeignErrorConvention> errorConvention = None;
auto emitter = ArgEmitter(SGF, info.functionRepresentation, /*yield*/ false,
info.paramsToEmit,
loweredArgs, delayedArgs,
errorConvention, ImportAsMemberStatus());
auto emitter =
ArgEmitter(SGF, info.functionRepresentation, /*yield*/ false,
/*coroutine*/ false, info.paramsToEmit, loweredArgs,
delayedArgs, errorConvention, ImportAsMemberStatus());

emitter.emitSingleArg(ArgumentSource(info.loc, std::move(value)),
info.origResultType);
assert(delayedArgs.empty());
Expand Down Expand Up @@ -3707,7 +3710,7 @@ void TupleShuffleArgEmitter::emit(ArgEmitter &parent) {

// Emit the inner expression.
if (!innerParams.empty()) {
ArgEmitter(parent.SGF, parent.Rep, parent.IsYield,
ArgEmitter(parent.SGF, parent.Rep, parent.IsYield, parent.IsForCoroutine,
ClaimedParamsRef(innerParams), innerArgs, innerDelayedArgs,
/*foreign error*/ None, /*foreign self*/ ImportAsMemberStatus(),
(innerSpecialDests ? ArgSpecialDestArray(*innerSpecialDests)
Expand Down Expand Up @@ -3965,16 +3968,17 @@ class CallSite {

/// Evaluate arguments and begin any inout formal accesses.
void emit(SILGenFunction &SGF, AbstractionPattern origFormalType,
ParamLowering &lowering, SmallVectorImpl<ManagedValue> &args,
CanSILFunctionType substFnType, ParamLowering &lowering,
SmallVectorImpl<ManagedValue> &args,
SmallVectorImpl<DelayedArgument> &delayedArgs,
const Optional<ForeignErrorConvention> &foreignError,
ImportAsMemberStatus foreignSelf) && {
auto params = lowering.claimParams(origFormalType, getParams(),
foreignError, foreignSelf);

ArgEmitter emitter(SGF, lowering.Rep, /*yield*/ false,
params, args, delayedArgs,
foreignError, foreignSelf);
/*isForCoroutine*/ substFnType->isCoroutine(), params,
args, delayedArgs, foreignError, foreignSelf);
emitter.emitPreparedArgs(std::move(Args), origFormalType);
}

Expand Down Expand Up @@ -4603,8 +4607,8 @@ ApplyOptions CallEmission::emitArgumentsForNormalApply(

bool isParamSite = &site == &uncurriedSites.back();

std::move(site).emit(SGF, origFormalType, paramLowering, args.back(),
delayedArgs,
std::move(site).emit(SGF, origFormalType, substFnType, paramLowering,
args.back(), delayedArgs,
// Claim the foreign error with the method
// formal params.
isParamSite ? foreignError : None,
Expand Down Expand Up @@ -4683,8 +4687,9 @@ RValue CallEmission::applyRemainingCallSites(RValue &&result,
ArgumentScope argScope(SGF, loc);

std::move(extraSites[i])
.emit(SGF, origFormalType, paramLowering, siteArgs, delayedArgs,
calleeTypeInfo.foreignError, calleeTypeInfo.foreignSelf);
.emit(SGF, origFormalType, substFnType, paramLowering, siteArgs,
delayedArgs, calleeTypeInfo.foreignError,
calleeTypeInfo.foreignSelf);
if (!delayedArgs.empty()) {
emitDelayedArguments(SGF, delayedArgs, siteArgs);
}
Expand Down Expand Up @@ -5049,10 +5054,9 @@ void SILGenFunction::emitYield(SILLocation loc,
}

ArgEmitter emitter(*this, fnType->getRepresentation(), /*yield*/ true,
ClaimedParamsRef(substYieldTys),
/*isForCoroutine*/ false, ClaimedParamsRef(substYieldTys),
yieldArgs, delayedArgs,
/*foreign error*/None,
ImportAsMemberStatus());
/*foreign error*/ None, ImportAsMemberStatus());

for (auto i : indices(valueSources)) {
emitter.emitSingleArg(std::move(valueSources[i]), origTypes[i]);
Expand Down Expand Up @@ -5234,8 +5238,9 @@ SILGenFunction::emitApplyOfLibraryIntrinsic(SILLocation loc,

SILFunctionConventions silConv(calleeTypeInfo.substFnType, getModule());
llvm::SmallVector<ManagedValue, 8> finalArgs;
convertOwnershipConventionsGivenParamInfos(*this, silConv.getParameters(),
args, loc, finalArgs);
convertOwnershipConventionsGivenParamInfos(
*this, silConv.getParameters(), args, loc,
/*isForCoroutine*/ calleeTypeInfo.substFnType->isCoroutine(), finalArgs);

ResultPlanPtr resultPlan =
ResultPlanBuilder::computeResultPlan(*this, calleeTypeInfo, loc, ctx);
Expand Down Expand Up @@ -5834,11 +5839,11 @@ SILGenFunction::prepareSubscriptIndices(SubscriptDecl *subscript,
SmallVector<ManagedValue, 4> argValues;
SmallVector<DelayedArgument, 2> delayedArgs;

ArgEmitter emitter(*this, SILFunctionTypeRepresentation::Thin, /*yield*/false,
ClaimedParamsRef(substParamTys),
ArgEmitter emitter(*this, SILFunctionTypeRepresentation::Thin,
/*yield*/ false,
/*isForCoroutine*/ false, ClaimedParamsRef(substParamTys),
argValues, delayedArgs,
/*foreign error*/None,
ImportAsMemberStatus());
/*foreign error*/ None, ImportAsMemberStatus());

emitter.emitTopLevel(indexExpr, AbstractionPattern(substFnType));

Expand Down
6 changes: 2 additions & 4 deletions test/SILGen/assignment.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,11 @@ func test1() {
// CHECK: [[T0:%.*]] = metatype $@thick D.Type
// CHECK: [[CTOR:%.*]] = function_ref @$s10assignment1DC{{[_0-9a-zA-Z]*}}fC
// CHECK: [[D:%.*]] = apply [[CTOR]]([[T0]])
// CHECK: [[BORROWED_D:%.*]] = begin_borrow [[D]]
// CHECK: [[T0:%.*]] = metatype $@thick C.Type
// CHECK: [[CTOR:%.*]] = function_ref @$s10assignment1CC{{[_0-9a-zA-Z]*}}fC
// CHECK: [[C:%.*]] = apply [[CTOR]]([[T0]]) : $@convention(method) (@thick C.Type) -> @owned C
// CHECK: [[SETTER:%.*]] = class_method [[BORROWED_D]] : $D, #D.child!setter.1
// CHECK: apply [[SETTER]]([[C]], [[BORROWED_D]])
// CHECK: end_borrow [[BORROWED_D]]
// CHECK: [[SETTER:%.*]] = class_method [[D]] : $D, #D.child!setter.1
// CHECK: apply [[SETTER]]([[C]], [[D]])
// CHECK: destroy_value [[D]]
D().child = C()
}
Expand Down
3 changes: 1 addition & 2 deletions test/SILGen/borrow.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,8 @@ func useD(_ d: D) {}
// CHECK: [[LOADED_VALUE:%.*]] = load [copy] [[ACCESS]]
// CHECK: end_borrow [[BORROWED_CLASS]]
// CHECK: destroy_value [[CLASS]]
// CHECK: [[BORROWED_LOADED_VALUE:%.*]] = begin_borrow [[LOADED_VALUE]]
// CHECK: [[FUNC:%.*]] = function_ref @$s6borrow4useD{{.*}} : $@convention(thin) (@guaranteed D) -> ()
// CHECK: apply [[FUNC]]([[BORROWED_LOADED_VALUE]])
// CHECK: apply [[FUNC]]([[LOADED_VALUE]])
// CHECK: destroy_value [[BOX]]
// CHECK: } // end sil function '$s6borrow44lvalueBorrowShouldBeAtEndOfFormalAccessScope{{.*}}'
func lvalueBorrowShouldBeAtEndOfFormalAccessScope() {
Expand Down
3 changes: 1 addition & 2 deletions test/SILGen/class_bound_protocols.swift
Original file line number Diff line number Diff line change
Expand Up @@ -132,9 +132,8 @@ func class_bound_method(x: ClassBound) {
// CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[XBOX_PB]] : $*ClassBound
// CHECK: [[X:%.*]] = load [copy] [[READ]] : $*ClassBound
// CHECK: [[PROJ:%.*]] = open_existential_ref [[X]] : $ClassBound to $[[OPENED:@opened(.*) ClassBound]]
// CHECK: [[BORROWED_PROJ:%.*]] = begin_borrow [[PROJ]]
// CHECK: [[METHOD:%.*]] = witness_method $[[OPENED]], #ClassBound.classBoundMethod!1
// CHECK: apply [[METHOD]]<[[OPENED]]>([[BORROWED_PROJ]])
// CHECK: apply [[METHOD]]<[[OPENED]]>([[PROJ]])
// CHECK: destroy_value [[PROJ]]
// CHECK: destroy_value [[XBOX]]
}
Expand Down
24 changes: 8 additions & 16 deletions test/SILGen/closures.swift
Original file line number Diff line number Diff line change
Expand Up @@ -443,9 +443,8 @@ class SuperSub : SuperBase {
// CHECK: = apply [[CLASS_METHOD]]([[ARG]])
// CHECK: [[ARG_COPY:%.*]] = copy_value [[ARG]]
// CHECK: [[ARG_COPY_SUPER:%.*]] = upcast [[ARG_COPY]] : $SuperSub to $SuperBase
// CHECK: [[BORROWED_ARG_COPY_SUPER:%.*]] = begin_borrow [[ARG_COPY_SUPER]]
// CHECK: [[SUPER_METHOD:%[0-9]+]] = function_ref @$s8closures9SuperBaseC4boomyyF : $@convention(method) (@guaranteed SuperBase) -> ()
// CHECK: = apply [[SUPER_METHOD]]([[BORROWED_ARG_COPY_SUPER]])
// CHECK: = apply [[SUPER_METHOD]]([[ARG_COPY_SUPER]])
// CHECK: destroy_value [[ARG_COPY_SUPER]]
// CHECK: } // end sil function '[[INNER_FUNC_1]]'
func a1() {
Expand Down Expand Up @@ -473,9 +472,8 @@ class SuperSub : SuperBase {
// CHECK: = apply [[CLASS_METHOD]]([[ARG]]) : $@convention(method) (@guaranteed SuperSub) -> ()
// CHECK: [[ARG_COPY:%.*]] = copy_value [[ARG]]
// CHECK: [[ARG_COPY_SUPER:%.*]] = upcast [[ARG_COPY]] : $SuperSub to $SuperBase
// CHECK: [[BORROWED_ARG_COPY_SUPER:%.*]] = begin_borrow [[ARG_COPY_SUPER]]
// CHECK: [[SUPER_METHOD:%.*]] = function_ref @$s8closures9SuperBaseC4boomyyF : $@convention(method) (@guaranteed SuperBase) -> ()
// CHECK: = apply [[SUPER_METHOD]]([[BORROWED_ARG_COPY_SUPER]]) : $@convention(method) (@guaranteed SuperBase)
// CHECK: = apply [[SUPER_METHOD]]([[ARG_COPY_SUPER]]) : $@convention(method) (@guaranteed SuperBase)
// CHECK: destroy_value [[ARG_COPY_SUPER]]
// CHECK: } // end sil function '[[INNER_FUNC_2]]'
func b2() {
Expand Down Expand Up @@ -508,9 +506,8 @@ class SuperSub : SuperBase {
// CHECK: = apply [[CLASS_METHOD]]([[ARG]]) : $@convention(method) (@guaranteed SuperSub) -> ()
// CHECK: [[ARG_COPY:%.*]] = copy_value [[ARG]]
// CHECK: [[ARG_COPY_SUPER:%.*]] = upcast [[ARG_COPY]] : $SuperSub to $SuperBase
// CHECK: [[BORROWED_ARG_COPY_SUPER:%.*]] = begin_borrow [[ARG_COPY_SUPER]]
// CHECK: [[SUPER_METHOD:%[0-9]+]] = function_ref @$s8closures9SuperBaseC4boomyyF : $@convention(method) (@guaranteed SuperBase) -> ()
// CHECK: = apply [[SUPER_METHOD]]([[BORROWED_ARG_COPY_SUPER]])
// CHECK: = apply [[SUPER_METHOD]]([[ARG_COPY_SUPER]])
// CHECK: destroy_value [[ARG_COPY_SUPER]]
// CHECK: } // end sil function '[[INNER_FUNC_1]]'
let c1 = { () -> Void in
Expand Down Expand Up @@ -545,9 +542,8 @@ class SuperSub : SuperBase {
// CHECK: bb0([[ARG:%.*]] : @guaranteed $SuperSub):
// CHECK: [[ARG_COPY:%.*]] = copy_value [[ARG]]
// CHECK: [[ARG_COPY_SUPER:%.*]] = upcast [[ARG_COPY]] : $SuperSub to $SuperBase
// CHECK: [[BORROWED_ARG_COPY_SUPER:%.*]] = begin_borrow [[ARG_COPY_SUPER]]
// CHECK: [[SUPER_METHOD:%.*]] = function_ref @$s8closures9SuperBaseC4boomyyF : $@convention(method) (@guaranteed SuperBase) -> ()
// CHECK: = apply [[SUPER_METHOD]]([[BORROWED_ARG_COPY_SUPER]])
// CHECK: = apply [[SUPER_METHOD]]([[ARG_COPY_SUPER]])
// CHECK: destroy_value [[ARG_COPY_SUPER]]
// CHECK: } // end sil function '[[INNER_FUNC_2]]'
func d2() {
Expand Down Expand Up @@ -583,9 +579,8 @@ class SuperSub : SuperBase {
// CHECK: bb0([[ARG:%.*]] : @guaranteed $SuperSub):
// CHECK: [[ARG_COPY:%.*]] = copy_value [[ARG]]
// CHECK: [[ARG_COPY_SUPERCAST:%.*]] = upcast [[ARG_COPY]] : $SuperSub to $SuperBase
// CHECK: [[BORROWED_ARG_COPY_SUPERCAST:%.*]] = begin_borrow [[ARG_COPY_SUPERCAST]]
// CHECK: [[SUPER_METHOD:%.*]] = function_ref @$s8closures9SuperBaseC4boomyyF : $@convention(method) (@guaranteed SuperBase) -> ()
// CHECK: = apply [[SUPER_METHOD]]([[BORROWED_ARG_COPY_SUPERCAST]])
// CHECK: = apply [[SUPER_METHOD]]([[ARG_COPY_SUPERCAST]])
// CHECK: destroy_value [[ARG_COPY_SUPERCAST]]
// CHECK: return
// CHECK: } // end sil function '[[INNER_FUNC_NAME2]]'
Expand Down Expand Up @@ -622,9 +617,8 @@ class SuperSub : SuperBase {
// CHECK: bb0([[ARG:%.*]] : @guaranteed $SuperSub):
// CHECK: [[ARG_COPY:%.*]] = copy_value [[ARG]]
// CHECK: [[ARG_COPY_SUPER:%.*]] = upcast [[ARG_COPY]] : $SuperSub to $SuperBase
// CHECK: [[BORROWED_ARG_COPY_SUPER:%.*]] = begin_borrow [[ARG_COPY_SUPER]]
// CHECK: [[SUPER_METHOD:%.*]] = function_ref @$s8closures9SuperBaseC4boomyyF : $@convention(method) (@guaranteed SuperBase) -> ()
// CHECK: = apply [[SUPER_METHOD]]([[BORROWED_ARG_COPY_SUPER]]) : $@convention(method) (@guaranteed SuperBase) -> ()
// CHECK: = apply [[SUPER_METHOD]]([[ARG_COPY_SUPER]]) : $@convention(method) (@guaranteed SuperBase) -> ()
// CHECK: destroy_value [[ARG_COPY_SUPER]]
// CHECK: } // end sil function '[[INNER_FUNC_2]]'
nil ?? super.boom()
Expand Down Expand Up @@ -654,9 +648,8 @@ class SuperSub : SuperBase {
// CHECK: bb0([[ARG:%.*]] : @guaranteed $SuperSub):
// CHECK: [[ARG_COPY:%.*]] = copy_value [[ARG]]
// CHECK: [[ARG_COPY_SUPER:%.*]] = upcast [[ARG_COPY]] : $SuperSub to $SuperBase
// CHECK: [[BORROWED_ARG_COPY_SUPER:%.*]] = begin_borrow [[ARG_COPY_SUPER]]
// CHECK: [[SUPER_METHOD:%.*]] = function_ref @$s8closures9SuperBaseC4boomyyF : $@convention(method) (@guaranteed SuperBase) -> ()
// CHECK: = apply [[SUPER_METHOD]]([[BORROWED_ARG_COPY_SUPER]])
// CHECK: = apply [[SUPER_METHOD]]([[ARG_COPY_SUPER]])
// CHECK: destroy_value [[ARG_COPY_SUPER]]
// CHECK: } // end sil function '[[INNER_FUNC_2]]'
nil ?? super.boom()
Expand Down Expand Up @@ -742,9 +735,8 @@ class ConcreteBase {
// CHECK: bb0([[ARG:%.*]] : @guaranteed $GenericDerived<Ocean>):
// CHECK: [[ARG_COPY:%.*]] = copy_value [[ARG]]
// CHECK: [[ARG_COPY_SUPER:%.*]] = upcast [[ARG_COPY]] : $GenericDerived<Ocean> to $ConcreteBase
// CHECK: [[BORROWED_ARG_COPY_SUPER:%.*]] = begin_borrow [[ARG_COPY_SUPER]]
// CHECK: [[METHOD:%.*]] = function_ref @$s8closures12ConcreteBaseC4swimyyF
// CHECK: apply [[METHOD]]([[BORROWED_ARG_COPY_SUPER]]) : $@convention(method) (@guaranteed ConcreteBase) -> ()
// CHECK: apply [[METHOD]]([[ARG_COPY_SUPER]]) : $@convention(method) (@guaranteed ConcreteBase) -> ()
// CHECK: destroy_value [[ARG_COPY_SUPER]]
// CHECK: } // end sil function '$s8closures14GenericDerivedC4swimyyFyyXEfU_'

Expand Down
8 changes: 2 additions & 6 deletions test/SILGen/collection_subtype_downcast.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,7 @@ struct S { var x, y: Int }
// CHECK-NEXT: [[ARG_COPY:%.*]] = copy_value [[ARG]]
// CHECK-NEXT: // function_ref
// CHECK-NEXT: [[FN:%.*]] = function_ref @$ss21_arrayConditionalCastySayq_GSgSayxGr0_lF
// CHECK-NEXT: [[BORROWED_ARG_COPY:%.*]] = begin_borrow [[ARG_COPY]]
// CHECK-NEXT: [[RESULT:%.*]] = apply [[FN]]<Any, S>([[BORROWED_ARG_COPY]]) : $@convention(thin) <τ_0_0, τ_0_1> (@guaranteed Array<τ_0_0>) -> @owned Optional<Array<τ_0_1>>
// CHECK-NEXT: end_borrow
// CHECK-NEXT: [[RESULT:%.*]] = apply [[FN]]<Any, S>([[ARG_COPY]]) : $@convention(thin) <τ_0_0, τ_0_1> (@guaranteed Array<τ_0_0>) -> @owned Optional<Array<τ_0_1>>
// CHECK-NEXT: destroy_value [[ARG_COPY]]
// CHECK-NEXT: return [[RESULT]]
func array_downcast(array: [Any]) -> [S]? {
Expand All @@ -34,9 +32,7 @@ func ==(lhs: S, rhs: S) -> Bool {
// CHECK: [[ARG_COPY:%.*]] = copy_value [[ARG]]
// CHECK: // function_ref
// CHECK: [[FN:%.*]] = function_ref @$ss30_dictionaryDownCastConditionalySDyq0_q1_GSgSDyxq_GSHRzSHR0_r2_lF
// CHECK: [[BORROWED_ARG_COPY:%.*]] = begin_borrow [[ARG_COPY]]
// CHECK: [[RESULT:%.*]] = apply [[FN]]<S, Any, S, Int>([[BORROWED_ARG_COPY]]) : $@convention(thin) <τ_0_0, τ_0_1, τ_0_2, τ_0_3 where τ_0_0 : Hashable, τ_0_2 : Hashable> (@guaranteed Dictionary<τ_0_0, τ_0_1>) -> @owned Optional<Dictionary<τ_0_2, τ_0_3>>
// CHECK: end_borrow [[BORROWED_ARG_COPY]]
// CHECK: [[RESULT:%.*]] = apply [[FN]]<S, Any, S, Int>([[ARG_COPY]]) : $@convention(thin) <τ_0_0, τ_0_1, τ_0_2, τ_0_3 where τ_0_0 : Hashable, τ_0_2 : Hashable> (@guaranteed Dictionary<τ_0_0, τ_0_1>) -> @owned Optional<Dictionary<τ_0_2, τ_0_3>>
// CHECK: destroy_value [[ARG_COPY]]
// CHECK: return [[RESULT]]
func dict_downcast(dict: [S: Any]) -> [S: Int]? {
Expand Down
Loading