Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
e87d243
Fix support for subscript default arguments in KeyPath
zoecarver Oct 31, 2019
0376dd0
Refactor as suggested by @xedin
zoecarver Oct 31, 2019
4da9c42
Stash progress before changing branches
zoecarver Oct 31, 2019
14a2ad6
Move default argument lowering into coerceCallArguments
zoecarver Nov 1, 2019
ff29b8e
Clean up spacing and remove lingering debugging calls
zoecarver Nov 1, 2019
5b4e385
Merge branch 'master' into key-path-default-arg
zoecarver Nov 6, 2019
327c08a
Add edgecases to tests
zoecarver Nov 6, 2019
00ebbee
Fix based on review comments
zoecarver Nov 6, 2019
3da2799
Emit default arguments in silgen
zoecarver Nov 10, 2019
ecba9c3
Merge branch 'master' into key-path-default-arg
zoecarver Nov 10, 2019
8c3bfc5
Move default arg generation into SILGen
zoecarver Nov 10, 2019
f7dd813
Run code through clang-format
zoecarver Nov 10, 2019
b6bca52
Remove lingering newline
zoecarver Nov 10, 2019
b0877fb
Re-enable tests (oops)
zoecarver Nov 10, 2019
921c1eb
Move default arg generation into lambda instead of modifing AST
zoecarver Nov 11, 2019
18f918b
Regenerate labels in CSApply instead of keeping two sizes
zoecarver Nov 11, 2019
e385439
Use ArgEmitter
zoecarver Nov 12, 2019
51dc7c8
Create emitKeyPathSubscriptOperands to lower all the args properly (i…
zoecarver Nov 12, 2019
27ffff1
Use range-based for-loop
zoecarver Nov 12, 2019
0f3dd52
Use correct function type to prevent conflicting argument types
zoecarver Nov 12, 2019
0824469
Format properly
zoecarver Nov 12, 2019
853dfbe
Copy labels and conformances
zoecarver Nov 12, 2019
5e1e907
Fix spacing
zoecarver Nov 12, 2019
800feda
Fix spacing
zoecarver Nov 12, 2019
775c062
Fix spacing (again)
zoecarver Nov 12, 2019
0374c94
Fix merge conflict
zoecarver Nov 12, 2019
3a98452
Add FileCheck tests
zoecarver Nov 13, 2019
976c8c9
Add tests
zoecarver Nov 17, 2019
fd02663
More tests
zoecarver Nov 17, 2019
a8953b1
Format with clang-format
zoecarver Nov 17, 2019
b8947c4
Add more FileCheck tests
zoecarver Nov 18, 2019
3f7ee85
Fix nits
zoecarver Nov 18, 2019
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
33 changes: 33 additions & 0 deletions lib/SILGen/SILGenApply.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6067,6 +6067,39 @@ RValue SILGenFunction::emitDynamicSubscriptExpr(DynamicSubscriptExpr *e,
return RValue(*this, e, emitManagedRValueWithCleanup(optResult, optTL));
}

SmallVector<ManagedValue, 4> SILGenFunction::emitKeyPathSubscriptOperands(
SubscriptDecl *subscript, SubstitutionMap subs, Expr *indexExpr) {
Type interfaceType = subscript->getInterfaceType();
CanFunctionType substFnType =
subs ? cast<FunctionType>(interfaceType->castTo<GenericFunctionType>()
->substGenericArgs(subs)
->getCanonicalType())
: cast<FunctionType>(interfaceType->getCanonicalType());
AbstractionPattern origFnType(substFnType);
auto fnType =
getLoweredType(origFnType, substFnType).castTo<SILFunctionType>();

SmallVector<ManagedValue, 4> argValues;
SmallVector<DelayedArgument, 2> delayedArgs;
ArgEmitter emitter(*this, fnType->getRepresentation(),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! Using ArgEmitter is definitely the right approach here.

It appears that the old code didn't correctly handle keypaths with variadic subscript components either, eg

struct S {
  subscript<T>(x: T...) -> Int { get {} set {} }
}

let k = \S.[1, 2, 3]

Crashes with this on master

Assertion failed: (hashables.size() == SubscriptSize), function setSubscriptIndexHashableConformances, file /Users/spestov/src/swift/lib/AST/Expr.cpp, line 2129.
Stack dump:
0.	Program arguments: /Users/spestov/src/build/Ninja-RelWithDebInfoAssert/swift-macosx-x86_64/bin/swift -frontend -c -primary-file var.swift -target x86_64-apple-darwin19.0.0 -enable-objc-interop -color-diagnostics -module-name var -o /var/folders/wg/nmvf884n4b14lt0yw4khjsv00000gn/T/var-9e61ce.o 
1.	Swift version 5.1.1-dev (Swift 69c2de1727)
2.	While type-checking statement at [var.swift:5:1 - line:5:20] RangeText="let k = \S.[1, 2, 3"
3.	While type-checking declaration 0x7fd9ed0ca3a0 (at var.swift:5:1)
4.	While evaluating request PatternBindingEntryRequest((unknown decl), 0)
5.	While type-checking expression at [var.swift:5:9 - line:5:20] RangeText="\S.[1, 2, 3"

It looks like a similar issue. Can you see if your fix addresses this as well? If not, a follow up PR would be great :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll have to create a follow-up patch for variadics as it looks like that will require some additional work.

/*yield*/ false,
/*isForCoroutine*/ false,
ClaimedParamsRef(fnType, fnType->getParameters()),
argValues, delayedArgs,
/*foreign error*/ None, ImportAsMemberStatus());

auto prepared =
prepareSubscriptIndices(subscript, subs,
// Strategy doesn't matter
AccessStrategy::getStorage(), indexExpr);
emitter.emitPreparedArgs(std::move(prepared), origFnType);

if (!delayedArgs.empty())
emitDelayedArguments(*this, delayedArgs, argValues);

return argValues;
}

ManagedValue ArgumentScope::popPreservingValue(ManagedValue mv) {
formalEvalScope.pop();
return normalScope.popPreservingValue(mv);
Expand Down
36 changes: 11 additions & 25 deletions lib/SILGen/SILGenExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3553,27 +3553,6 @@ RValue RValueEmitter::visitKeyPathExpr(KeyPathExpr *E, SGFContext C) {

auto baseTy = rootTy;
SmallVector<SILValue, 4> operands;

auto lowerSubscriptOperands =
[this, &operands, E](const KeyPathExpr::Component &component) {
if (!component.getIndexExpr())
return;

// Evaluate the index arguments.
SmallVector<RValue, 2> indexValues;
auto indexResult = visit(component.getIndexExpr(), SGFContext());
if (isa<TupleType>(indexResult.getType())) {
std::move(indexResult).extractElements(indexValues);
} else {
indexValues.push_back(std::move(indexResult));
}

for (auto &rv : indexValues) {
operands.push_back(
std::move(rv).forwardAsSingleValue(SGF, E));
}
};


for (auto &component : E->getComponents()) {
switch (auto kind = component.getKind()) {
Expand All @@ -3593,11 +3572,18 @@ RValue RValueEmitter::visitKeyPathExpr(KeyPathExpr *E, SGFContext C) {
component.getSubscriptIndexHashableConformances(),
baseTy,
/*for descriptor*/ false));
lowerSubscriptOperands(component);

assert(numOperands == operands.size()
&& "operand count out of sync");
baseTy = loweredComponents.back().getComponentType();
if (kind == KeyPathExpr::Component::Kind::Property)
break;

auto subscript = cast<SubscriptDecl>(decl);
auto loweredArgs = SGF.emitKeyPathSubscriptOperands(
subscript, component.getDeclRef().getSubstitutions(),
component.getIndexExpr());

for (auto &arg : loweredArgs) {
operands.push_back(arg.forward(SGF));
}

break;
}
Expand Down
14 changes: 13 additions & 1 deletion lib/SILGen/SILGenFunction.h
Original file line number Diff line number Diff line change
Expand Up @@ -664,7 +664,19 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction
SubstitutionMap witnessSubs,
IsFreeFunctionWitness_t isFree,
bool isSelfConformance);


/// Generates subscript arguments for keypath. This function handles lowering
/// of all index expressions including default arguments.
///
/// \returns Lowered index arguments.
/// \param subscript - The subscript decl who's arguments are being lowered.
/// \param subs - Used to get subscript function type and to substitute generic args.
/// \param indexExpr - An expression holding the indices of the
/// subscript (either a TupleExpr or a ParenExpr).
SmallVector<ManagedValue, 4>
emitKeyPathSubscriptOperands(SubscriptDecl *subscript, SubstitutionMap subs,
Expr *indexExpr);

/// Convert a block to a native function with a thunk.
ManagedValue emitBlockToFunc(SILLocation loc,
ManagedValue block,
Expand Down
14 changes: 8 additions & 6 deletions lib/Sema/CSApply.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4590,9 +4590,6 @@ namespace {
/*applyExpr*/ nullptr, labels,
/*hasTrailingClosure*/ false, locator);

auto component = KeyPathExpr::Component::forSubscriptWithPrebuiltIndexExpr(
ref, newIndexExpr, labels, resolvedTy, componentLoc, {});

// We need to be able to hash the captured index values in order for
// KeyPath itself to be hashable, so check that all of the subscript
// index components are hashable and collect their conformances here.
Expand All @@ -4602,7 +4599,10 @@ namespace {
cs.getASTContext().getProtocol(KnownProtocolKind::Hashable);

auto fnType = overload.openedType->castTo<FunctionType>();
for (const auto &param : fnType->getParams()) {
SmallVector<Identifier, 4> newLabels;
for (auto &param : fnType->getParams()) {
newLabels.push_back(param.getLabel());

auto indexType = simplifyType(param.getPlainType());
// Index type conformance to Hashable protocol has been
// verified by the solver, we just need to get it again
Expand All @@ -4615,8 +4615,10 @@ namespace {
conformances.push_back(hashableConformance);
}

component.setSubscriptIndexHashableConformances(conformances);
return component;
return KeyPathExpr::Component::forSubscriptWithPrebuiltIndexExpr(
ref, newIndexExpr, cs.getASTContext().AllocateCopy(newLabels),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like KeyPathExpr::Component::getSubscriptLabels() is only called for KeyPathExpr::Component::Kind::UnresolvedSubscript. It might be worth a try to stick an assertion there if the kind is anything else, and remove the parameter from forSubscriptWithPrebuiltIndexExpr() altogether.

resolvedTy, componentLoc,
cs.getASTContext().AllocateCopy(conformances));
}

Expr *visitKeyPathDotExpr(KeyPathDotExpr *E) {
Expand Down
12 changes: 12 additions & 0 deletions test/SILGen/Inputs/default_arg_other.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@

public func foo(x: Int = 0) -> Int { x }

public struct Subscript1 {
public init() { }
public subscript(x: Int = 0) -> Int { x }
}

public struct Subscript2 {
public init() { }
public subscript(x: String = #function) -> String { x }
}
53 changes: 53 additions & 0 deletions test/SILGen/default_arg_multiple_modules.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend -emit-module -emit-module-path=%t/default_arg_other.swiftmodule -module-name=default_arg_other %S/Inputs/default_arg_other.swift
// RUN: %target-swift-emit-silgen -module-name default_arg_multiple_modules -I %t %s | %FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-%target-runtime

import default_arg_other

// CHECK-LABEL: sil hidden [ossa] @${{.*}}test1{{.*}}
func test1() -> Int {
// CHECK: [[DEF_ARG_FN:%[0-9]+]] = function_ref @$s17default_arg_other3foo1xS2i_tFfA_ : $@convention(thin) () -> Int
// CHECK: [[DEF_ARG:%[0-9]+]] = apply [[DEF_ARG_FN]]() {{.*}}
// CHECK: [[FN:%[0-9]+]] = function_ref @$s17default_arg_other3foo1xS2i_tF : $@convention(thin) (Int) -> Int
// CHECK: [[CALL:%[0-9]+]] = apply [[FN]]([[DEF_ARG]]) {{.*}}
// CHECK: return [[CALL]] : $Int
return foo()
}

// CHECK-LABEL: sil hidden [ossa] @${{.*}}test2{{.*}}
func test2() -> Int {
// CHECK: [[DEF_ARG_FN:%[0-9]+]] = function_ref @$s17default_arg_other10Subscript1VyS2icipfA_ : $@convention(thin) () -> Int
// CHECK: [[DEF_ARG:%[0-9]+]] = apply [[DEF_ARG_FN]]() {{.*}}
// CHECK: [[FN:%[0-9]+]] = function_ref @$s17default_arg_other10Subscript1VyS2icig : $@convention(method) (Int, Subscript1) -> Int
// CHECK: [[CALL:%[0-9]+]] = apply [[FN]]([[DEF_ARG]], {{.*}}
// CHECK: return [[CALL]] : $Int
return Subscript1()[]
}

// CHECK-LABEL: sil hidden [ossa] @${{.*}}test3{{.*}}
func test3() -> String {
// This should not call default arg constructor
// CHECK: [[STR_LIT:%[0-9]+]] = string_literal utf8 "test3()"
// CHECK: [[DEF_ARG:%[0-9]+]] = apply %{{[0-9]+}}([[STR_LIT]], {{.*}}
// CHECK: [[FN:%[0-9]+]] = function_ref @$s17default_arg_other10Subscript2VyS2Scig : $@convention(method) (@guaranteed String, Subscript2) -> @owned String
// CHECK: [[CALL:%[0-9]+]] = apply [[FN]]([[DEF_ARG]], {{.*}}
// CHECK: return [[CALL]] : $String
return Subscript2()[]
}

// CHECK-LABEL: sil hidden [ossa] @${{.*}}test4{{.*}}
func test4() {
// CHECK: [[DEF_ARG_FN:%[0-9]+]] = function_ref @$s17default_arg_other10Subscript1VyS2icipfA_ : $@convention(thin) () -> Int
// CHECK: [[DEF_ARG:%[0-9]+]] = apply [[DEF_ARG_FN]]() {{.*}}
// CHECK: keypath $KeyPath<Subscript1, Int>, (root $Subscript1; gettable_property $Int, id @$s17default_arg_other10Subscript1VyS2icig : $@convention(method) (Int, Subscript1) -> Int, getter @$s17default_arg_other10Subscript1VyS2icipACTK : $@convention(thin) (@in_guaranteed Subscript1, UnsafeRawPointer) -> @out Int, indices [%$0 : $Int : $Int], indices_equals @$sSiTH : $@convention(thin) (UnsafeRawPointer, UnsafeRawPointer) -> Bool, indices_hash @$sSiTh : $@convention(thin) (UnsafeRawPointer) -> Int, external #Subscript1.subscript) ([[DEF_ARG]])
_ = \Subscript1.[]
}

// CHECK-LABEL: sil hidden [ossa] @${{.*}}test5{{.*}}
func test5() {
// This should not call default arg constructor
// CHECK: [[STR_LIT:%[0-9]+]] = string_literal utf8 "test5()"
// CHECK: [[DEF_ARG:%[0-9]+]] = apply %{{[0-9]+}}([[STR_LIT]], {{.*}}
// CHECK: keypath $KeyPath<Subscript2, String>, (root $Subscript2; gettable_property $String, id @$s17default_arg_other10Subscript2VyS2Scig : $@convention(method) (@guaranteed String, Subscript2) -> @owned String, getter @$s17default_arg_other10Subscript2VyS2ScipACTK : $@convention(thin) (@in_guaranteed Subscript2, UnsafeRawPointer) -> @out String, indices [%$0 : $String : $String], indices_equals @$sSSTH : $@convention(thin) (UnsafeRawPointer, UnsafeRawPointer) -> Bool, indices_hash @$sSSTh : $@convention(thin) (UnsafeRawPointer) -> Int, external #Subscript2.subscript) ([[DEF_ARG]])
_ = \Subscript2.[]
}
100 changes: 99 additions & 1 deletion test/SILGen/keypaths.swift
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,54 @@ struct Subscripts<T> {
}
}

// CHECK-LABEL: sil hidden [ossa] @{{.*}}10subscripts
struct SubscriptDefaults1 {
subscript(x: Int = 0) -> Int {
get { fatalError() }
set { fatalError() }
}
subscript(x: Int, y: Int, z: Int = 0) -> Int {
get { fatalError() }
set { fatalError() }
}
subscript(x: Bool, bool y: Bool = false) -> Bool {
get { fatalError() }
set { fatalError() }
}
subscript(bool x: Bool, y: Int, z: Int = 0) -> Int {
get { fatalError() }
set { fatalError() }
}
}

struct SubscriptDefaults2 {
subscript(x: Int? = nil) -> Int {
get { fatalError() }
set { fatalError() }
}
}

struct SubscriptDefaults3 {
subscript(x: Int = #line) -> Int {
get { fatalError() }
set { fatalError() }
}
}

struct SubscriptDefaults4 {
subscript<T : Numeric>(x x: T, y y: T = 0) -> T {
get { fatalError() }
set { fatalError() }
}
}

struct SubscriptDefaults5 {
subscript<T : ExpressibleByStringLiteral>(x x: T, y y: T = #function) -> T {
get { fatalError() }
set { fatalError() }
}
}

// CHECK-LABEL: sil hidden [ossa] @{{.*}}10subscripts1x1y1syx_q_SStSHRzSHR_r0_lF
func subscripts<T: Hashable, U: Hashable>(x: T, y: U, s: String) {
_ = \Subscripts<T>.[]
_ = \Subscripts<T>.[generic: x]
Expand Down Expand Up @@ -352,6 +399,57 @@ func subscripts<T: Hashable, U: Hashable>(x: T, y: U, s: String) {

_ = \Subscripts<T>.[Bass()]
_ = \Subscripts<T>.[Treble()]

_ = \SubscriptDefaults1.[]
_ = \SubscriptDefaults1.[0]
_ = \SubscriptDefaults1.[0, 0]
_ = \SubscriptDefaults1.[0, 0, 0]
_ = \SubscriptDefaults1.[false]
_ = \SubscriptDefaults1.[false, bool: false]
_ = \SubscriptDefaults1.[bool: false, 0]
_ = \SubscriptDefaults1.[bool: false, 0, 0]

_ = \SubscriptDefaults2.[]
_ = \SubscriptDefaults2.[0]
_ = \SubscriptDefaults3.[]
_ = \SubscriptDefaults3.[0]
_ = \SubscriptDefaults4.[x: 0]
_ = \SubscriptDefaults4.[x: 0, y: 0]
_ = \SubscriptDefaults5.[x: ""]
_ = \SubscriptDefaults5.[x: "", y: ""]
}

// CHECK-LABEL: sil hidden [ossa] @{{.*}}check_default_subscripts
func check_default_subscripts() {
// CHECK: [[INTX:%[0-9]+]] = integer_literal $Builtin.IntLiteral, 0
// CHECK: [[IX:%[0-9]+]] = apply %{{[0-9]+}}([[INTX]], {{.*}}
// CHECK: [[INTY:%[0-9]+]] = integer_literal $Builtin.IntLiteral, 0
// CHECK: [[IY:%[0-9]+]] = apply %{{[0-9]+}}([[INTY]], {{.*}}
// CHECK: [[KEYPATH:%[0-9]+]] = keypath $WritableKeyPath<SubscriptDefaults4, Int>, (root $SubscriptDefaults4; settable_property $Int, id @$s8keypaths18SubscriptDefaults4V1x1yxx_xtcSjRzluig : $@convention(method) <τ_0_0 where τ_0_0 : Numeric> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_0, SubscriptDefaults4) -> @out τ_0_0, getter @$s8keypaths18SubscriptDefaults4V1x1yxx_xtcSjRzluipACSiTK : $@convention(thin) (@in_guaranteed SubscriptDefaults4, UnsafeRawPointer) -> @out Int, setter @$s8keypaths18SubscriptDefaults4V1x1yxx_xtcSjRzluipACSiTk : $@convention(thin) (@in_guaranteed Int, @inout SubscriptDefaults4, UnsafeRawPointer) -> (), indices [%$0 : $Int : $Int, %$1 : $Int : $Int], indices_equals @$sS2iTH : $@convention(thin) (UnsafeRawPointer, UnsafeRawPointer) -> Bool, indices_hash @$sS2iTh : $@convention(thin) (UnsafeRawPointer) -> Int) ([[IX]], [[IY]])
_ = \SubscriptDefaults4.[x: 0, y: 0]

// CHECK: [[INTINIT:%[0-9]+]] = integer_literal $Builtin.IntLiteral, 0
// CHECK: [[I:%[0-9]+]] = apply %{{[0-9]+}}([[INTINIT]], {{.*}}
// CHECK: [[DFN:%[0-9]+]] = function_ref @$s8keypaths18SubscriptDefaults4V1x1yxx_xtcSjRzluipfA0_ : $@convention(thin) <τ_0_0 where τ_0_0 : Numeric> () -> @out τ_0_0
// CHECK: [[ALLOC:%[0-9]+]] = alloc_stack $Int
// CHECK: apply [[DFN]]<Int>([[ALLOC]]) : $@convention(thin) <τ_0_0 where τ_0_0 : Numeric> () -> @out τ_0_0
// CHECK: [[LOAD:%[0-9]+]] = load [trivial] [[ALLOC]] : $*Int
// CHECK: [[KEYPATH:%[0-9]+]] = keypath $WritableKeyPath<SubscriptDefaults4, Int>, (root $SubscriptDefaults4; settable_property $Int, id @$s8keypaths18SubscriptDefaults4V1x1yxx_xtcSjRzluig : $@convention(method) <τ_0_0 where τ_0_0 : Numeric> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_0, SubscriptDefaults4) -> @out τ_0_0, getter @$s8keypaths18SubscriptDefaults4V1x1yxx_xtcSjRzluipACSiTK : $@convention(thin) (@in_guaranteed SubscriptDefaults4, UnsafeRawPointer) -> @out Int, setter @$s8keypaths18SubscriptDefaults4V1x1yxx_xtcSjRzluipACSiTk : $@convention(thin) (@in_guaranteed Int, @inout SubscriptDefaults4, UnsafeRawPointer) -> (), indices [%$0 : $Int : $Int, %$1 : $Int : $Int], indices_equals @$sS2iTH : $@convention(thin) (UnsafeRawPointer, UnsafeRawPointer) -> Bool, indices_hash @$sS2iTh : $@convention(thin) (UnsafeRawPointer) -> Int) ([[I]], [[LOAD]])
_ = \SubscriptDefaults4.[x: 0]

// CHECK: [[STRX_LIT:%[0-9]+]] = string_literal utf8 ""
// CHECK: [[STRX:%[0-9]+]] = apply %{{[0-9]+}}([[STRX_LIT]], {{.*}}
// CHECK: [[STRY_LIT:%[0-9]+]] = string_literal utf8 "check_default_subscripts()"
// CHECK: [[DEF_ARG:%[0-9]+]] = apply %{{[0-9]+}}([[STRY_LIT]], {{.*}}
// CHECK: keypath $WritableKeyPath<SubscriptDefaults5, String>, (root $SubscriptDefaults5; settable_property $String, id @$s8keypaths18SubscriptDefaults5V1x1yxx_xtcs26ExpressibleByStringLiteralRzluig : $@convention(method) <τ_0_0 where τ_0_0 : ExpressibleByStringLiteral> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_0, SubscriptDefaults5) -> @out τ_0_0, getter @$s8keypaths18SubscriptDefaults5V1x1yxx_xtcs26ExpressibleByStringLiteralRzluipACSSTK : $@convention(thin) (@in_guaranteed SubscriptDefaults5, UnsafeRawPointer) -> @out String, setter @$s8keypaths18SubscriptDefaults5V1x1yxx_xtcs26ExpressibleByStringLiteralRzluipACSSTk : $@convention(thin) (@in_guaranteed String, @inout SubscriptDefaults5, UnsafeRawPointer) -> (), indices [%$0 : $String : $String, %$1 : $String : $String], indices_equals @$sS2STH : $@convention(thin) (UnsafeRawPointer, UnsafeRawPointer) -> Bool, indices_hash @$sS2STh : $@convention(thin) (UnsafeRawPointer) -> Int) ([[STRX]], [[DEF_ARG]])
_ = \SubscriptDefaults5.[x: ""]

// CHECK: [[STRX_LIT:%[0-9]+]] = string_literal utf8 ""
// CHECK: [[STRX:%[0-9]+]] = apply %{{[0-9]+}}([[STRX_LIT]], {{.*}}
// CHECK: [[STRY_LIT:%[0-9]+]] = string_literal utf8 ""
// CHECK: [[STRY:%[0-9]+]] = apply %{{[0-9]+}}([[STRY_LIT]], {{.*}}
// CHECK: keypath $WritableKeyPath<SubscriptDefaults5, String>, (root $SubscriptDefaults5; settable_property $String, id @$s8keypaths18SubscriptDefaults5V1x1yxx_xtcs26ExpressibleByStringLiteralRzluig : $@convention(method) <τ_0_0 where τ_0_0 : ExpressibleByStringLiteral> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_0, SubscriptDefaults5) -> @out τ_0_0, getter @$s8keypaths18SubscriptDefaults5V1x1yxx_xtcs26ExpressibleByStringLiteralRzluipACSSTK : $@convention(thin) (@in_guaranteed SubscriptDefaults5, UnsafeRawPointer) -> @out String, setter @$s8keypaths18SubscriptDefaults5V1x1yxx_xtcs26ExpressibleByStringLiteralRzluipACSSTk : $@convention(thin) (@in_guaranteed String, @inout SubscriptDefaults5, UnsafeRawPointer) -> (), indices [%$0 : $String : $String, %$1 : $String : $String], indices_equals @$sS2STH : $@convention(thin) (UnsafeRawPointer, UnsafeRawPointer) -> Bool, indices_hash @$sS2STh : $@convention(thin) (UnsafeRawPointer) -> Int) ([[STRX]], [[STRY]])
_ = \SubscriptDefaults5.[x: "", y: ""]
}

// CHECK-LABEL: sil hidden [ossa] @{{.*}}subclass_generics
Expand Down