Skip to content

Commit d24f4bc

Browse files
committed
SIL: a new library intrinsic to "finalize" array literals
For COW support in SIL it's required to "finalize" array literals. _finalizeUninitializedArray is a compiler known stdlib function which is called after all elements of an array literal are stored. This runtime function marks the array literal as finished. %uninitialized_result_tuple = apply %_allocateUninitializedArray(%count) %mutable_array = tuple_extract %uninitialized_result_tuple, 0 %elem_base_address = tuple_extract %uninitialized_result_tuple, 1 ... store %elem_0 to %elem_addr_0 store %elem_1 to %elem_addr_1 ... %final_array = apply %_finalizeUninitializedArray(%mutable_array) In this commit _finalizeUninitializedArray is still a no-op because the COW support is not used in the Array implementation yet.
1 parent 976c86d commit d24f4bc

18 files changed

+163
-46
lines changed

include/swift/AST/KnownDecls.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ FUNC_DECL(AllocateUninitializedArray,
4444
"_allocateUninitializedArray")
4545
FUNC_DECL(DeallocateUninitializedArray,
4646
"_deallocateUninitializedArray")
47+
FUNC_DECL(FinalizeUninitializedArray,
48+
"_finalizeUninitializedArray")
4749

4850
FUNC_DECL(ForceBridgeFromObjectiveC,
4951
"_forceBridgeFromObjectiveC")

lib/SIL/IR/SILModule.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,7 @@ bool SILModule::linkFunction(SILFunction *F, SILModule::LinkingMode Mode) {
355355

356356
SILFunction *SILModule::findFunction(StringRef Name, SILLinkage Linkage) {
357357
assert((Linkage == SILLinkage::Public ||
358+
Linkage == SILLinkage::SharedExternal ||
358359
Linkage == SILLinkage::PublicExternal) &&
359360
"Only a lookup of public functions is supported currently");
360361

@@ -405,6 +406,9 @@ SILFunction *SILModule::findFunction(StringRef Name, SILLinkage Linkage) {
405406
// compilation, simply convert it into an external declaration,
406407
// so that a compiled version from the shared library is used.
407408
if (F->isDefinition() &&
409+
// Don't eliminate bodies of _alwaysEmitIntoClient functions
410+
// (PublicNonABI linkage is de-serialized as SharedExternal)
411+
F->getLinkage() != SILLinkage::SharedExternal &&
408412
!F->getModule().getOptions().shouldOptimize()) {
409413
F->convertToDeclaration();
410414
}

lib/SILGen/SILGenApply.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4962,6 +4962,22 @@ void SILGenFunction::emitUninitializedArrayDeallocation(SILLocation loc,
49624962
SGFContext());
49634963
}
49644964

4965+
ManagedValue SILGenFunction::emitUninitializedArrayFinalization(SILLocation loc,
4966+
SILValue array) {
4967+
auto &Ctx = getASTContext();
4968+
auto finalize = Ctx.getFinalizeUninitializedArray();
4969+
4970+
CanType arrayTy = array->getType().getASTType();
4971+
4972+
// Invoke the intrinsic.
4973+
auto subMap = arrayTy->getContextSubstitutionMap(SGM.M.getSwiftModule(),
4974+
Ctx.getArrayDecl());
4975+
RValue result = emitApplyOfLibraryIntrinsic(loc, finalize, subMap,
4976+
ManagedValue::forUnmanaged(array),
4977+
SGFContext());
4978+
return std::move(result).getScalarValue();
4979+
}
4980+
49654981
namespace {
49664982
/// A cleanup that deallocates an uninitialized array.
49674983
class DeallocateUninitializedArray: public Cleanup {

lib/SILGen/SILGenExpr.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2113,10 +2113,11 @@ ManagedValue Lowering::emitEndVarargs(SILGenFunction &SGF, SILLocation loc,
21132113
SGF.Cleanups.setCleanupState(varargs.getAbortCleanup(), CleanupState::Dead);
21142114

21152115
// Reactivate the result cleanup.
2116-
auto result = varargs.getArray();
2117-
if (result.hasCleanup())
2118-
SGF.Cleanups.setCleanupState(result.getCleanup(), CleanupState::Active);
2119-
return result;
2116+
auto array = varargs.getArray();
2117+
if (array.hasCleanup())
2118+
SGF.Cleanups.setCleanupState(array.getCleanup(), CleanupState::Active);
2119+
2120+
return SGF.emitUninitializedArrayFinalization(loc, array.forward(SGF));
21202121
}
21212122

21222123
RValue RValueEmitter::visitTupleExpr(TupleExpr *E, SGFContext C) {

lib/SILGen/SILGenFunction.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1187,6 +1187,7 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction
11871187

11881188
CleanupHandle enterDeallocateUninitializedArrayCleanup(SILValue array);
11891189
void emitUninitializedArrayDeallocation(SILLocation loc, SILValue array);
1190+
ManagedValue emitUninitializedArrayFinalization(SILLocation loc, SILValue array);
11901191

11911192
/// Emit a cleanup for an owned value that should be written back at end of
11921193
/// scope if the value is not forwarded.

lib/SILOptimizer/LoopTransforms/COWArrayOpt.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -642,7 +642,7 @@ bool COWArrayOpt::hasLoopOnlyDestructorSafeArrayOperations() {
642642

643643
// Semantic calls are safe.
644644
ArraySemanticsCall Sem(Inst);
645-
if (Sem) {
645+
if (Sem && Sem.hasSelf()) {
646646
auto Kind = Sem.getKind();
647647
// Safe because they create new arrays.
648648
if (Kind == ArrayCallKind::kArrayInit ||

lib/SILOptimizer/LoopTransforms/ForEachLoopUnroll.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -323,8 +323,15 @@ void ArrayInfo::classifyUsesOfArray(SILValue arrayValue) {
323323
// as the array itself is not modified (which is possible with reference
324324
// types).
325325
ArraySemanticsCall arrayOp(user);
326-
if (!arrayOp.doesNotChangeArray())
327-
mayBeWritten = true;
326+
if (arrayOp.doesNotChangeArray())
327+
continue;
328+
329+
if (arrayOp.getKind() == swift::ArrayCallKind::kArrayFinalizeIntrinsic) {
330+
classifyUsesOfArray((ApplyInst *)arrayOp);
331+
continue;
332+
}
333+
334+
mayBeWritten = true;
328335
}
329336
}
330337

lib/SILOptimizer/Mandatory/OSLogOptimization.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -539,6 +539,15 @@ static SILValue emitCodeForConstantArray(ArrayRef<SILValue> elements,
539539
module.findFunction(allocatorMangledName, SILLinkage::PublicExternal);
540540
assert(arrayAllocateFun);
541541

542+
FuncDecl *arrayFinalizeDecl = astContext.getFinalizeUninitializedArray();
543+
assert(arrayFinalizeDecl);
544+
std::string finalizeMangledName =
545+
SILDeclRef(arrayFinalizeDecl, SILDeclRef::Kind::Func).mangle();
546+
SILFunction *arrayFinalizeFun =
547+
module.findFunction(finalizeMangledName, SILLinkage::SharedExternal);
548+
assert(arrayFinalizeFun);
549+
module.linkFunction(arrayFinalizeFun);
550+
542551
// Call the _allocateUninitializedArray function with numElementsSIL. The
543552
// call returns a two-element tuple, where the first element is the newly
544553
// created array and the second element is a pointer to the internal storage
@@ -596,7 +605,12 @@ static SILValue emitCodeForConstantArray(ArrayRef<SILValue> elements,
596605
StoreOwnershipQualifier::Init);
597606
elementIndex++;
598607
}
599-
return arraySIL;
608+
FunctionRefInst *arrayFinalizeRef =
609+
builder.createFunctionRef(loc, arrayFinalizeFun);
610+
ApplyInst *finalizedArray = builder.createApply(
611+
loc, arrayFinalizeRef, subMap, ArrayRef<SILValue>(arraySIL));
612+
613+
return finalizedArray;
600614
}
601615

602616
/// Given a SILValue \p value, return the instruction immediately following the

stdlib/public/core/ArrayShared.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,18 @@ func _deallocateUninitializedArray<Element>(
6464
array._deallocateUninitialized()
6565
}
6666

67+
@_alwaysEmitIntoClient
68+
@_semantics("array.finalize_intrinsic")
69+
@_effects(readnone)
70+
public // COMPILER_INTRINSIC
71+
func _finalizeUninitializedArray<Element>(
72+
_ array: __owned Array<Element>
73+
) -> Array<Element> {
74+
var mutableArray = array
75+
// TODO: enable this once Array had an _endMutation function
76+
// mutableArray._endMutation()
77+
return mutableArray
78+
}
6779

6880
extension Collection {
6981
// Utility method for collections that wish to implement

test/IRGen/unmanaged_objc_throw_func.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,11 @@ import Foundation
1515
// CHECK-NEXT: %[[T2:.+]] = extractvalue { %swift.bridge*, i8* } %[[T0]], 1
1616
// CHECK-NEXT: %[[T3:.+]] = bitcast i8* %[[T2]] to %TSi*
1717
// CHECK-NEXT: %._value = getelementptr inbounds %TSi, %TSi* %[[T3]], i32 0, i32 0
18-
// CHECK-NEXT: store i{{32|64}} 1, i{{32|64}}* %._value, align {{[0-9]+}}
19-
// CHECK-NEXT: %[[T4:.+]] = call swiftcc %TSo7NSArrayC* @"$sSa10FoundationE19_bridgeToObjectiveCSo7NSArrayCyF"(%swift.bridge* %[[T1]], %swift.type* @"$sSiN")
18+
// CHECK: %[[T7:.+]] = call swiftcc %swift.bridge* @"$ss27_finalizeUninitializedArrayySayxGABnlF"(%swift.bridge* %[[T1]], %swift.type* @"$sSiN")
19+
// CHECK: %[[T4:.+]] = call swiftcc %TSo7NSArrayC* @"$sSa10FoundationE19_bridgeToObjectiveCSo7NSArrayCyF"(%swift.bridge* %[[T7]], %swift.type* @"$sSiN")
2020
// CHECK-NEXT: %[[T5:.+]] = bitcast %TSo7NSArrayC* %[[T4]] to %TSo10CFArrayRefa*
2121
// CHECK-NEXT: store %TSo10CFArrayRefa* %[[T5]]
22-
// CHECK-NEXT: call void @swift_bridgeObjectRelease(%swift.bridge* %[[T1]]) #{{[0-9]+}}
22+
// CHECK-NEXT: call void @swift_bridgeObjectRelease(%swift.bridge* %{{[0-9]+}}) #{{[0-9]+}}
2323
// CHECK-NEXT: %[[T6:.+]] = bitcast %TSo10CFArrayRefa* %[[T5]] to i8*
2424
// CHECK-NEXT: call void @llvm.objc.release(i8* %[[T6]])
2525
// CHECK-NEXT: ret %TSo10CFArrayRefa* %[[T5]]

test/SILGen/arguments.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ func _allocateUninitializedArray<T>(_: Builtin.Word)
1414
Builtin.int_trap()
1515
}
1616

17+
func _finalizeUninitializedArray<T>(_ a: Array<T>) -> Array<T> {
18+
return a
19+
}
20+
1721
func _deallocateUninitializedArray<T>(_: Array<T>) {}
1822

1923
var i:Int, f:Float, c:UnicodeScalar

test/SILGen/errors.swift

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -639,10 +639,12 @@ func test_variadic(_ cat: Cat) throws {
639639
// CHECK: [[NORM_3]]([[CAT3:%.*]] : @owned $Cat):
640640
// CHECK-NEXT: store [[CAT3]] to [init] [[ELT3]]
641641
// Complete the call and return.
642+
// CHECK: [[FIN_FN:%.*]] = function_ref @$ss27_finalizeUninitializedArrayySayxGABnlF
643+
// CHECK: [[FIN_ARRAY:%.*]] = apply [[FIN_FN]]<Cat>([[ARRAY]])
642644
// CHECK: [[TAKE_FN:%.*]] = function_ref @$s6errors14take_many_catsyyAA3CatCd_tKF : $@convention(thin) (@guaranteed Array<Cat>) -> @error Error
643-
// CHECK-NEXT: try_apply [[TAKE_FN]]([[ARRAY]]) : $@convention(thin) (@guaranteed Array<Cat>) -> @error Error, normal [[NORM_CALL:bb[0-9]+]], error [[ERR_CALL:bb[0-9]+]]
645+
// CHECK-NEXT: try_apply [[TAKE_FN]]([[FIN_ARRAY]]) : $@convention(thin) (@guaranteed Array<Cat>) -> @error Error, normal [[NORM_CALL:bb[0-9]+]], error [[ERR_CALL:bb[0-9]+]]
644646
// CHECK: [[NORM_CALL]]([[T0:%.*]] : $()):
645-
// CHECK-NEXT: destroy_value [[ARRAY]]
647+
// CHECK-NEXT: destroy_value [[FIN_ARRAY]]
646648
// CHECK-NEXT: [[T0:%.*]] = tuple ()
647649
// CHECK-NEXT: return
648650
// Failure from element 0.
@@ -671,7 +673,7 @@ func test_variadic(_ cat: Cat) throws {
671673
// CHECK-NEXT: br [[RETHROW]]([[ERROR]] : $Error)
672674
// Failure from call.
673675
// CHECK: [[ERR_CALL]]([[ERROR:%.*]] : @owned $Error):
674-
// CHECK-NEXT: destroy_value [[ARRAY]]
676+
// CHECK-NEXT: destroy_value [[FIN_ARRAY]]
675677
// CHECK-NEXT: br [[RETHROW]]([[ERROR]] : $Error)
676678
// Rethrow.
677679
// CHECK: [[RETHROW]]([[ERROR:%.*]] : @owned $Error):

test/SILGen/keypaths.swift

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -470,19 +470,25 @@ func test_variadics() {
470470
// CHECK: [[FN_REF:%[0-9]+]] = function_ref @$ss27_allocateUninitializedArrayySayxG_BptBwlF
471471
// CHECK: [[MAKE_ARR:%[0-9]+]] = apply [[FN_REF]]<Int>([[ARR_COUNT]])
472472
// CHECK: ([[ARR:%[0-9]+]], %{{[0-9]+}}) = destructure_tuple [[MAKE_ARR]] : $(Array<Int>, Builtin.RawPointer)
473-
// CHECK: keypath $KeyPath<SubscriptVariadic1, Int>, (root $SubscriptVariadic1; gettable_property $Int, id @$s8keypaths18SubscriptVariadic1VyS2id_tcig : $@convention(method) (@guaranteed Array<Int>, SubscriptVariadic1) -> Int, getter @$s8keypaths18SubscriptVariadic1VyS2id_tcipACTK : $@convention(thin) (@in_guaranteed SubscriptVariadic1, UnsafeRawPointer) -> @out Int, indices [%$0 : $Array<Int> : $Array<Int>], indices_equals @$sSaySiGTH : $@convention(thin) (UnsafeRawPointer, UnsafeRawPointer) -> Bool, indices_hash @$sSaySiGTh : $@convention(thin) (UnsafeRawPointer) -> Int) ([[ARR]])
473+
// CHECK: [[FIN_REF:%[0-9]+]] = function_ref @$ss27_finalizeUninitializedArrayySayxGABnlF
474+
// CHECK: [[FIN_ARR:%[0-9]+]] = apply [[FIN_REF]]<Int>([[ARR]])
475+
// CHECK: keypath $KeyPath<SubscriptVariadic1, Int>, (root $SubscriptVariadic1; gettable_property $Int, id @$s8keypaths18SubscriptVariadic1VyS2id_tcig : $@convention(method) (@guaranteed Array<Int>, SubscriptVariadic1) -> Int, getter @$s8keypaths18SubscriptVariadic1VyS2id_tcipACTK : $@convention(thin) (@in_guaranteed SubscriptVariadic1, UnsafeRawPointer) -> @out Int, indices [%$0 : $Array<Int> : $Array<Int>], indices_equals @$sSaySiGTH : $@convention(thin) (UnsafeRawPointer, UnsafeRawPointer) -> Bool, indices_hash @$sSaySiGTh : $@convention(thin) (UnsafeRawPointer) -> Int) ([[FIN_ARR]])
474476
_ = \SubscriptVariadic1.[1, 2, 3]
475477
// CHECK: [[ARR_COUNT:%[0-9]+]] = integer_literal $Builtin.Word, 1
476478
// CHECK: [[FN_REF:%[0-9]+]] = function_ref @$ss27_allocateUninitializedArrayySayxG_BptBwlF
477479
// CHECK: [[MAKE_ARR:%[0-9]+]] = apply [[FN_REF]]<Int>([[ARR_COUNT]])
478480
// CHECK: ([[ARR:%[0-9]+]], %{{[0-9]+}}) = destructure_tuple [[MAKE_ARR]] : $(Array<Int>, Builtin.RawPointer)
479-
// CHECK: keypath $KeyPath<SubscriptVariadic1, Int>, (root $SubscriptVariadic1; gettable_property $Int, id @$s8keypaths18SubscriptVariadic1VyS2id_tcig : $@convention(method) (@guaranteed Array<Int>, SubscriptVariadic1) -> Int, getter @$s8keypaths18SubscriptVariadic1VyS2id_tcipACTK : $@convention(thin) (@in_guaranteed SubscriptVariadic1, UnsafeRawPointer) -> @out Int, indices [%$0 : $Array<Int> : $Array<Int>], indices_equals @$sSaySiGTH : $@convention(thin) (UnsafeRawPointer, UnsafeRawPointer) -> Bool, indices_hash @$sSaySiGTh : $@convention(thin) (UnsafeRawPointer) -> Int) ([[ARR]])
481+
// CHECK: [[FIN_REF:%[0-9]+]] = function_ref @$ss27_finalizeUninitializedArrayySayxGABnlF
482+
// CHECK: [[FIN_ARR:%[0-9]+]] = apply [[FIN_REF]]<Int>([[ARR]])
483+
// CHECK: keypath $KeyPath<SubscriptVariadic1, Int>, (root $SubscriptVariadic1; gettable_property $Int, id @$s8keypaths18SubscriptVariadic1VyS2id_tcig : $@convention(method) (@guaranteed Array<Int>, SubscriptVariadic1) -> Int, getter @$s8keypaths18SubscriptVariadic1VyS2id_tcipACTK : $@convention(thin) (@in_guaranteed SubscriptVariadic1, UnsafeRawPointer) -> @out Int, indices [%$0 : $Array<Int> : $Array<Int>], indices_equals @$sSaySiGTH : $@convention(thin) (UnsafeRawPointer, UnsafeRawPointer) -> Bool, indices_hash @$sSaySiGTh : $@convention(thin) (UnsafeRawPointer) -> Int) ([[FIN_ARR]])
480484
_ = \SubscriptVariadic1.[1]
481485
// CHECK: [[ARR_COUNT:%[0-9]+]] = integer_literal $Builtin.Word, 0
482486
// CHECK: [[FN_REF:%[0-9]+]] = function_ref @$ss27_allocateUninitializedArrayySayxG_BptBwlF
483487
// CHECK: [[MAKE_ARR:%[0-9]+]] = apply [[FN_REF]]<Int>([[ARR_COUNT]])
484488
// CHECK: ([[ARR:%[0-9]+]], %{{[0-9]+}}) = destructure_tuple [[MAKE_ARR]] : $(Array<Int>, Builtin.RawPointer)
485-
// CHECK: keypath $KeyPath<SubscriptVariadic1, Int>, (root $SubscriptVariadic1; gettable_property $Int, id @$s8keypaths18SubscriptVariadic1VyS2id_tcig : $@convention(method) (@guaranteed Array<Int>, SubscriptVariadic1) -> Int, getter @$s8keypaths18SubscriptVariadic1VyS2id_tcipACTK : $@convention(thin) (@in_guaranteed SubscriptVariadic1, UnsafeRawPointer) -> @out Int, indices [%$0 : $Array<Int> : $Array<Int>], indices_equals @$sSaySiGTH : $@convention(thin) (UnsafeRawPointer, UnsafeRawPointer) -> Bool, indices_hash @$sSaySiGTh : $@convention(thin) (UnsafeRawPointer) -> Int) ([[ARR]])
489+
// CHECK: [[FIN_REF:%[0-9]+]] = function_ref @$ss27_finalizeUninitializedArrayySayxGABnlF
490+
// CHECK: [[FIN_ARR:%[0-9]+]] = apply [[FIN_REF]]<Int>([[ARR]])
491+
// CHECK: keypath $KeyPath<SubscriptVariadic1, Int>, (root $SubscriptVariadic1; gettable_property $Int, id @$s8keypaths18SubscriptVariadic1VyS2id_tcig : $@convention(method) (@guaranteed Array<Int>, SubscriptVariadic1) -> Int, getter @$s8keypaths18SubscriptVariadic1VyS2id_tcipACTK : $@convention(thin) (@in_guaranteed SubscriptVariadic1, UnsafeRawPointer) -> @out Int, indices [%$0 : $Array<Int> : $Array<Int>], indices_equals @$sSaySiGTH : $@convention(thin) (UnsafeRawPointer, UnsafeRawPointer) -> Bool, indices_hash @$sSaySiGTh : $@convention(thin) (UnsafeRawPointer) -> Int) ([[FIN_ARR]])
486492
_ = \SubscriptVariadic1.[]
487493

488494
_ = \SubscriptVariadic2.["", "1"]
@@ -491,7 +497,9 @@ func test_variadics() {
491497
// CHECK: [[FN_REF:%[0-9]+]] = function_ref @$ss27_allocateUninitializedArrayySayxG_BptBwlF
492498
// CHECK: [[MAKE_ARR:%[0-9]+]] = apply [[FN_REF]]<String>([[ARR_COUNT]])
493499
// CHECK: ([[ARR:%[0-9]+]], %{{[0-9]+}}) = destructure_tuple [[MAKE_ARR]] : $(Array<String>, Builtin.RawPointer)
494-
// CHECK: keypath $KeyPath<SubscriptVariadic2, String>, (root $SubscriptVariadic2; gettable_property $String, id @$s8keypaths18SubscriptVariadic2Vyxxd_tcs26ExpressibleByStringLiteralRzluig : $@convention(method) <τ_0_0 where τ_0_0 : ExpressibleByStringLiteral> (@guaranteed Array<τ_0_0>, SubscriptVariadic2) -> @out τ_0_0, getter @$s8keypaths18SubscriptVariadic2Vyxxd_tcs26ExpressibleByStringLiteralRzluipACSSTK : $@convention(thin) (@in_guaranteed SubscriptVariadic2, UnsafeRawPointer) -> @out String, indices [%$0 : $Array<String> : $Array<String>], indices_equals @$sSaySSGTH : $@convention(thin) (UnsafeRawPointer, UnsafeRawPointer) -> Bool, indices_hash @$sSaySSGTh : $@convention(thin) (UnsafeRawPointer) -> Int) ([[ARR]])
500+
// CHECK: [[FIN_REF:%[0-9]+]] = function_ref @$ss27_finalizeUninitializedArrayySayxGABnlF
501+
// CHECK: [[FIN_ARR:%[0-9]+]] = apply [[FIN_REF]]<String>([[ARR]])
502+
// CHECK: keypath $KeyPath<SubscriptVariadic2, String>, (root $SubscriptVariadic2; gettable_property $String, id @$s8keypaths18SubscriptVariadic2Vyxxd_tcs26ExpressibleByStringLiteralRzluig : $@convention(method) <τ_0_0 where τ_0_0 : ExpressibleByStringLiteral> (@guaranteed Array<τ_0_0>, SubscriptVariadic2) -> @out τ_0_0, getter @$s8keypaths18SubscriptVariadic2Vyxxd_tcs26ExpressibleByStringLiteralRzluipACSSTK : $@convention(thin) (@in_guaranteed SubscriptVariadic2, UnsafeRawPointer) -> @out String, indices [%$0 : $Array<String> : $Array<String>], indices_equals @$sSaySSGTH : $@convention(thin) (UnsafeRawPointer, UnsafeRawPointer) -> Bool, indices_hash @$sSaySSGTh : $@convention(thin) (UnsafeRawPointer) -> Int) ([[FIN_ARR]])
495503
_ = \SubscriptVariadic2.["", #function]
496504

497505
_ = \SubscriptVariadic3<String>.[""]

0 commit comments

Comments
 (0)