Skip to content

Commit 7a0e642

Browse files
authored
Merge pull request #61374 from jckarter/single-closure-for-dynamic-metatype-static-partial-applications
Sema: Use capture list to represent dynamic metatype bases for partial applications.
2 parents c9e619e + a7e4e61 commit 7a0e642

File tree

6 files changed

+250
-54
lines changed

6 files changed

+250
-54
lines changed

lib/Sema/CSApply.cpp

Lines changed: 108 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1186,10 +1186,30 @@ namespace {
11861186
thunk->setParameterList(thunkParamList);
11871187
thunk->setThunkKind(AutoClosureExpr::Kind::SingleCurryThunk);
11881188
cs.cacheType(thunk);
1189+
1190+
// If the `self` type is existential, it must be opened.
1191+
OpaqueValueExpr *baseOpened = nullptr;
1192+
Expr *origBaseExpr = baseExpr;
1193+
if (baseExpr) {
1194+
auto baseTy = cs.getType(baseExpr);
1195+
if (baseTy->isAnyExistentialType()) {
1196+
Type openedTy = solution.OpenedExistentialTypes.lookup(
1197+
cs.getConstraintLocator(locator));
1198+
assert(openedTy);
1199+
1200+
Type opaqueValueTy = openedTy;
1201+
if (baseTy->is<ExistentialMetatypeType>())
1202+
opaqueValueTy = MetatypeType::get(opaqueValueTy);
1203+
1204+
baseOpened = new (ctx) OpaqueValueExpr(SourceLoc(), opaqueValueTy);
1205+
cs.cacheType(baseOpened);
1206+
baseExpr = baseOpened;
1207+
}
1208+
}
11891209

11901210
Expr *thunkBody = buildSingleCurryThunkBodyCall(
11911211
baseExpr, fnExpr, declOrClosure, thunkParamList, locator);
1192-
1212+
11931213
// If we called a function with a dynamic 'Self' result, we may need some
11941214
// special handling.
11951215
if (baseExpr) {
@@ -1219,6 +1239,15 @@ namespace {
12191239
// Now, coerce to the result type of the thunk.
12201240
thunkBody = coerceToType(thunkBody, thunkTy->getResult(), locator);
12211241

1242+
// Close up the existential if necessary.
1243+
if (baseOpened) {
1244+
thunkBody = new (ctx) OpenExistentialExpr(origBaseExpr,
1245+
baseOpened,
1246+
thunkBody,
1247+
thunkBody->getType());
1248+
cs.cacheType(thunkBody);
1249+
}
1250+
12221251
if (thunkTy->getExtInfo().isThrowing()) {
12231252
thunkBody = new (ctx)
12241253
TryExpr(thunkBody->getStartLoc(), thunkBody, cs.getType(thunkBody),
@@ -1529,13 +1558,14 @@ namespace {
15291558
// inside the curry thunk as well. This reduces abstraction and
15301559
// post-factum function type conversions, and results in better SILGen.
15311560
//
1532-
// For a partial application of a class method, however, we always want
1533-
// the thunk to accept a class to avoid potential abstraction, so the
1534-
// existential base must be opened eagerly in order to be upcast to the
1535-
// appropriate class reference type before it is passed to the thunk.
1561+
// For a partial application of a class instance method, however, we
1562+
// always want the thunk to accept a class to avoid potential
1563+
// abstraction, so the existential base must be opened eagerly in order
1564+
// to be upcast to the appropriate class reference type before it is
1565+
// passed to the thunk.
15361566
if (!needsCurryThunk ||
15371567
(!member->getDeclContext()->getSelfProtocolDecl() &&
1538-
!isUnboundInstanceMember)) {
1568+
baseIsInstance && member->isInstanceMember())) {
15391569
// Open the existential before performing the member reference.
15401570
base = openExistentialReference(base, knownOpened->second, member);
15411571
baseTy = knownOpened->second;
@@ -1790,26 +1820,79 @@ namespace {
17901820
memberLocator);
17911821
} else if (needsCurryThunk) {
17921822
// Another case where we want to build a single closure is when
1793-
// we have a partial application of a static member on a statically-
1794-
// derived metatype value. Again, there are no order of evaluation
1795-
// concerns here, and keeping the call and base together in the AST
1796-
// improves SILGen.
1797-
if ((isa<ConstructorDecl>(member)
1798-
|| member->isStatic()) &&
1799-
cs.isStaticallyDerivedMetatype(base)) {
1800-
// Add a useless ".self" to avoid downstream diagnostics.
1801-
base = new (context) DotSelfExpr(base, SourceLoc(), base->getEndLoc(),
1802-
cs.getType(base));
1803-
cs.setType(base, base->getType());
1804-
1805-
auto *closure = buildSingleCurryThunk(
1806-
base, declRefExpr, cast<AbstractFunctionDecl>(member),
1823+
// we have a partial application of a static member. It is better
1824+
// to either push the base reference down into the closure (if it's
1825+
// just a literal type reference, in which case there are no order of
1826+
// operation concerns with capturing vs. evaluating it in the closure),
1827+
// or to evaluate the base as a capture and hand it down via the
1828+
// capture list.
1829+
if (isa<ConstructorDecl>(member) || member->isStatic()) {
1830+
if (cs.isStaticallyDerivedMetatype(base)) {
1831+
// Add a useless ".self" to avoid downstream diagnostics.
1832+
base = new (context) DotSelfExpr(base, SourceLoc(), base->getEndLoc(),
1833+
cs.getType(base));
1834+
cs.setType(base, base->getType());
1835+
1836+
auto *closure = buildSingleCurryThunk(
1837+
base, declRefExpr, cast<AbstractFunctionDecl>(member),
1838+
memberLocator);
1839+
1840+
// Skip the code below -- we're not building an extra level of
1841+
// call by applying the metatype; instead, the closure we just
1842+
// built is the curried reference.
1843+
return closure;
1844+
} else {
1845+
// Add a useless ".self" to avoid downstream diagnostics, in case
1846+
// the type ref is still a TypeExpr.
1847+
base = new (context) DotSelfExpr(base, SourceLoc(), base->getEndLoc(),
1848+
cs.getType(base));
1849+
// Introduce a capture variable.
1850+
cs.cacheType(base);
1851+
solution.setExprTypes(base);
1852+
auto capture = new (context) VarDecl(/*static*/ false,
1853+
VarDecl::Introducer::Let,
1854+
SourceLoc(),
1855+
context.getIdentifier("$base$"),
1856+
dc);
1857+
capture->setImplicit();
1858+
capture->setInterfaceType(base->getType()->mapTypeOutOfContext());
1859+
1860+
NamedPattern *capturePat = new (context) NamedPattern(capture);
1861+
capturePat->setImplicit();
1862+
capturePat->setType(base->getType());
1863+
1864+
auto capturePBE = PatternBindingEntry(capturePat,
1865+
SourceLoc(), base, dc);
1866+
auto captureDecl = PatternBindingDecl::create(context, SourceLoc(),
1867+
{}, SourceLoc(),
1868+
capturePBE,
1869+
dc);
1870+
captureDecl->setImplicit();
1871+
1872+
// Write the closure in terms of the capture.
1873+
auto baseRef = new (context)
1874+
DeclRefExpr(capture, DeclNameLoc(base->getLoc()), /*implicit*/ true);
1875+
baseRef->setType(base->getType());
1876+
cs.cacheType(baseRef);
1877+
1878+
auto *closure = buildSingleCurryThunk(
1879+
baseRef, declRefExpr, cast<AbstractFunctionDecl>(member),
1880+
simplifyType(adjustedOpenedType)->castTo<FunctionType>(),
18071881
memberLocator);
1808-
1809-
// Skip the code below -- we're not building an extra level of
1810-
// call by applying the metatype; instead, the closure we just
1811-
// built is the curried reference.
1812-
return closure;
1882+
1883+
// Wrap the closure in a capture list.
1884+
auto captureEntry = CaptureListEntry(captureDecl);
1885+
auto captureExpr = CaptureListExpr::create(context, captureEntry,
1886+
closure);
1887+
captureExpr->setImplicit();
1888+
captureExpr->setType(cs.getType(closure));
1889+
cs.cacheType(captureExpr);
1890+
1891+
Expr *finalExpr = captureExpr;
1892+
closeExistentials(finalExpr, locator,
1893+
/*force*/ openedExistential);
1894+
return finalExpr;
1895+
}
18131896
}
18141897

18151898
FunctionType *curryThunkTy = nullptr;

test/SILGen/closure_literal_reabstraction.swift

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,24 @@ struct Butt {
1414
static prefix func !=< (a: Butt) -> Butt { return a }
1515
}
1616

17+
class AbstractButt {
18+
required init(x: Int) {}
19+
20+
class func create(x: Int) -> Self { return self.init(x: x) }
21+
}
22+
23+
class AbstractGenericButt<T> {
24+
required init(c: Int) {}
25+
class func create(c: Int) -> Self { return self.init(c: c) }
26+
}
27+
28+
func abstractButtFactory() -> AbstractButt.Type { return AbstractButt.self }
29+
30+
protocol Buttable {
31+
init(p: Int)
32+
static func create(p: Int) -> Self
33+
}
34+
1735
// CHECK-LABEL: sil {{.*}} @{{.*}}reabstractCaptureListExprArgument
1836
// CHECK: [[CLOSURE_FN:%.*]] = function_ref {{.*}}U_
1937
// CHECK: [[CLOSURE:%.*]] = partial_apply {{.*}}[[CLOSURE_FN]]
@@ -65,7 +83,110 @@ func reabstractCoercedMemberOperatorRef() {
6583
gen(f: (!=<) as (Butt) -> Butt)
6684
}
6785

86+
// CHECK-LABEL: sil {{.*}} @{{.*}}reabstractDynamicMetatypeInitializerRef
87+
// CHECK: [[CLOSURE_FN:%.*]] = function_ref {{.*}}u_
88+
// CHECK: [[CLOSURE:%.*]] = partial_apply [callee_guaranteed] [[CLOSURE_FN]]
89+
// CHECK: [[CLOSURE_NE:%.*]] = convert_escape_to_noescape [not_guaranteed] [[CLOSURE]]
90+
// CHECK: apply {{.*}}<Int, AbstractButt>([[CLOSURE_NE]])
91+
func reabstractDynamicMetatypeInitializerRef() {
92+
gen(f: abstractButtFactory().init)
93+
}
94+
95+
// CHECK-LABEL: sil {{.*}} @{{.*}}reabstractDynamicMetatypeStaticMemberRef
96+
// CHECK: [[CLOSURE_FN:%.*]] = function_ref {{.*}}u_
97+
// CHECK: [[CLOSURE:%.*]] = partial_apply [callee_guaranteed] [[CLOSURE_FN]]
98+
// CHECK: [[CLOSURE_NE:%.*]] = convert_escape_to_noescape [not_guaranteed] [[CLOSURE]]
99+
// CHECK: apply {{.*}}<Int, AbstractButt>([[CLOSURE_NE]])
100+
func reabstractDynamicMetatypeStaticMemberRef() {
101+
gen(f: abstractButtFactory().create)
102+
}
103+
104+
// CHECK-LABEL: sil {{.*}} @{{.*}}reabstractGenericInitializerRef
105+
// CHECK: [[CLOSURE_FN:%.*]] = function_ref {{.*}}u_
106+
// CHECK: [[CLOSURE:%.*]] = partial_apply [callee_guaranteed] [[CLOSURE_FN]]
107+
// CHECK: [[CLOSURE_C:%.*]] = convert_function [[CLOSURE]]
108+
// CHECK: [[CLOSURE_NE:%.*]] = convert_escape_to_noescape [not_guaranteed] [[CLOSURE_C]]
109+
// CHECK: apply {{.*}}<Int, T>([[CLOSURE_NE]])
110+
func reabstractGenericInitializerRef<T: Buttable>(butt: T) {
111+
gen(f: T.init)
112+
}
113+
114+
// CHECK-LABEL: sil {{.*}} @{{.*}}reabstractGenericStaticMemberRef
115+
// CHECK: [[CLOSURE_FN:%.*]] = function_ref {{.*}}u_
116+
// CHECK: [[CLOSURE:%.*]] = partial_apply [callee_guaranteed] [[CLOSURE_FN]]
117+
// CHECK: [[CLOSURE_C:%.*]] = convert_function [[CLOSURE]]
118+
// CHECK: [[CLOSURE_NE:%.*]] = convert_escape_to_noescape [not_guaranteed] [[CLOSURE_C]]
119+
// CHECK: apply {{.*}}<Int, T>([[CLOSURE_NE]])
120+
func reabstractGenericStaticMemberRef<T: Buttable>(butt: T) {
121+
gen(f: T.create)
122+
}
123+
124+
// CHECK-LABEL: sil {{.*}} @{{.*}}reabstractDynamicGenericStaticMemberRef
125+
// CHECK: [[CLOSURE_FN:%.*]] = function_ref {{.*}}u_
126+
// CHECK: [[CLOSURE:%.*]] = partial_apply [callee_guaranteed] [[CLOSURE_FN]]<T>(%0)
127+
// CHECK: [[CLOSURE_C:%.*]] = convert_function [[CLOSURE]]
128+
// CHECK: [[CLOSURE_NE:%.*]] = convert_escape_to_noescape [not_guaranteed] [[CLOSURE_C]]
129+
// CHECK: apply {{.*}}<Int, T>([[CLOSURE_NE]])
130+
func reabstractDynamicGenericStaticMemberRef<T: Buttable>(t: T.Type) {
131+
gen(f: t.create)
132+
}
133+
134+
// CHECK-LABEL: sil {{.*}} @{{.*}}reabstractExistentialInitializerRef
135+
// CHECK: [[CLOSURE_FN:%.*]] = function_ref {{.*}}u_
136+
// CHECK: [[CLOSURE:%.*]] = partial_apply [callee_guaranteed] [[CLOSURE_FN]](%0)
137+
// CHECK: [[CLOSURE_NE:%.*]] = convert_escape_to_noescape [not_guaranteed] [[CLOSURE]]
138+
// CHECK: apply {{.*}}<Int, any Buttable>([[CLOSURE_NE]])
139+
func reabstractExistentialInitializerRef(butt: any Buttable.Type) {
140+
gen(f: butt.init)
141+
}
142+
143+
// CHECK-LABEL: sil {{.*}} @{{.*}}reabstractExistentialStaticMemberRef
144+
// CHECK: [[CLOSURE_FN:%.*]] = function_ref {{.*}}u_
145+
// CHECK: [[CLOSURE:%.*]] = partial_apply [callee_guaranteed] [[CLOSURE_FN]](%0)
146+
// CHECK: [[CLOSURE_NE:%.*]] = convert_escape_to_noescape [not_guaranteed] [[CLOSURE]]
147+
// CHECK: apply {{.*}}<Int, any Buttable>([[CLOSURE_NE]])
148+
func reabstractExistentialStaticMemberRef(butt: any Buttable.Type) {
149+
gen(f: butt.create)
150+
}
151+
152+
// CHECK-LABEL: sil {{.*}} @{{.*}}reabstractClassCompInitializerRefs
153+
func reabstractClassCompInitializerRefs<T>(
154+
butt: any (AbstractGenericButt<T> & Buttable).Type
155+
) {
156+
// CHECK: [[CLOSURE_FN:%.*]] = function_ref {{.*}}u_
157+
// CHECK: [[CLOSURE:%.*]] = partial_apply [callee_guaranteed] [[CLOSURE_FN]]<T>(%0)
158+
// CHECK: [[CLOSURE_C:%.*]] = convert_function [[CLOSURE]]
159+
// CHECK: [[CLOSURE_NE:%.*]] = convert_escape_to_noescape [not_guaranteed] [[CLOSURE_C]]
160+
// CHECK: apply {{.*}}<Int, any (AbstractGenericButt<T> & Buttable)>([[CLOSURE_NE]])
161+
gen(f: butt.init(c:))
162+
// CHECK: [[CLOSURE_FN:%.*]] = function_ref {{.*}}u0_
163+
// CHECK: [[CLOSURE:%.*]] = partial_apply [callee_guaranteed] [[CLOSURE_FN]]<T>(%0)
164+
// CHECK: [[CLOSURE_C:%.*]] = convert_function [[CLOSURE]]
165+
// CHECK: [[CLOSURE_NE:%.*]] = convert_escape_to_noescape [not_guaranteed] [[CLOSURE_C]]
166+
// CHECK: apply {{.*}}<Int, any (AbstractGenericButt<T> & Buttable)>([[CLOSURE_NE]])
167+
gen(f: butt.init(p:))
168+
}
169+
170+
// CHECK-LABEL: sil {{.*}} @{{.*}}reabstractClassCompStaticMemberRefs
171+
func reabstractClassCompStaticMemberRefs<T>(
172+
butt: any (AbstractGenericButt<T> & Buttable).Type
173+
) {
174+
// CHECK: [[CLOSURE_FN:%.*]] = function_ref {{.*}}u_
175+
// CHECK: [[CLOSURE:%.*]] = partial_apply [callee_guaranteed] [[CLOSURE_FN]]<T>(%0)
176+
// CHECK: [[CLOSURE_C:%.*]] = convert_function [[CLOSURE]]
177+
// CHECK: [[CLOSURE_NE:%.*]] = convert_escape_to_noescape [not_guaranteed] [[CLOSURE_C]]
178+
// CHECK: apply {{.*}}<Int, any (AbstractGenericButt<T> & Buttable)>([[CLOSURE_NE]])
179+
gen(f: butt.create(c:))
180+
// CHECK: [[CLOSURE_FN:%.*]] = function_ref {{.*}}u0_
181+
// CHECK: [[CLOSURE:%.*]] = partial_apply [callee_guaranteed] [[CLOSURE_FN]]<T>(%0)
182+
// CHECK: [[CLOSURE_C:%.*]] = convert_function [[CLOSURE]]
183+
// CHECK: [[CLOSURE_NE:%.*]] = convert_escape_to_noescape [not_guaranteed] [[CLOSURE_C]]
184+
// CHECK: apply {{.*}}<Int, any (AbstractGenericButt<T> & Buttable)>([[CLOSURE_NE]])
185+
gen(f: butt.create(p:))
186+
}
187+
68188
// TODO
189+
69190
func reabstractInstanceMethodRef(instance: Butt) {
70191
gen(f: instance.getX)
71192
}

test/SILGen/objc_protocols.swift

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
21
// RUN: %target-swift-emit-silgen -module-name objc_protocols -sdk %S/Inputs -I %S/Inputs -enable-source-import %s -disable-objc-attr-requires-foundation-module | %FileCheck %s
3-
42
// REQUIRES: objc_interop
53

64
import gizmo
@@ -50,7 +48,7 @@ func objc_generic_partial_apply<T : NSRuncing>(_ x: T) {
5048
// CHECK: [[FN:%.*]] = function_ref @$s14objc_protocols0A22_generic_partial_applyyyxAA9NSRuncingRzlFSo8NSObjectCycxcfu1_
5149
_ = T.runce
5250

53-
// CHECK: [[FN:%.*]] = function_ref @$s14objc_protocols0A22_generic_partial_applyyyxAA9NSRuncingRzlFSo8NSObjectCycxmcfu3_
51+
// CHECK: [[FN:%.*]] = function_ref @$s14objc_protocols0A22_generic_partial_applyyyxAA9NSRuncingRzlFSo8NSObjectCycfu3_
5452
_ = T.mince
5553
// CHECK-NOT: destroy_value [[ARG]]
5654
}
@@ -75,13 +73,9 @@ func objc_generic_partial_apply<T : NSRuncing>(_ x: T) {
7573
// CHECK: } // end sil function '$s14objc_protocols0A22_generic_partial_applyyyxAA9NSRuncingRzlFSo8NSObjectCycxcfu1_AEycfu2_'
7674

7775

78-
// CHECK-LABEL: sil private [ossa] @$s14objc_protocols0A22_generic_partial_applyyyxAA9NSRuncingRzlFSo8NSObjectCycxmcfu3_ : $@convention(thin) <T where T : NSRuncing> (@thick T.Type) -> @owned @callee_guaranteed () -> @owned NSObject
79-
// CHECK: function_ref @$s14objc_protocols0A22_generic_partial_applyyyxAA9NSRuncingRzlFSo8NSObjectCycxmcfu3_AEycfu4_ : $@convention(thin) <τ_0_0 where τ_0_0 : NSRuncing> (@thick τ_0_0.Type) -> @owned NSObject
80-
// CHECK: } // end sil function '$s14objc_protocols0A22_generic_partial_applyyyxAA9NSRuncingRzlFSo8NSObjectCycxmcfu3_'
81-
82-
// CHECK-LABEL: sil private [ossa] @$s14objc_protocols0A22_generic_partial_applyyyxAA9NSRuncingRzlFSo8NSObjectCycxmcfu3_AEycfu4_ : $@convention(thin) <T where T : NSRuncing> (@thick T.Type) -> @owned NSObject
76+
// CHECK-LABEL: sil private [ossa] @$s14objc_protocols0A22_generic_partial_applyyyxAA9NSRuncingRzlFSo8NSObjectCycfu3_ : $@convention(thin) <T where T : NSRuncing> (@thick T.Type) -> @owned NSObject
8377
// CHECK: objc_method %2 : $@objc_metatype T.Type, #NSRuncing.mince!foreign : <Self where Self : NSRuncing> (Self.Type) -> () -> NSObject, $@convention(objc_method) <τ_0_0 where τ_0_0 : NSRuncing> (@objc_metatype τ_0_0.Type) -> @autoreleased NSObject
84-
// CHECK: } // end sil function '$s14objc_protocols0A22_generic_partial_applyyyxAA9NSRuncingRzlFSo8NSObjectCycxmcfu3_AEycfu4_'
78+
// CHECK: } // end sil function '$s14objc_protocols0A22_generic_partial_applyyyxAA9NSRuncingRzlFSo8NSObjectCycfu3_'
8579

8680

8781
// CHECK-LABEL: sil hidden [ossa] @$s14objc_protocols0A9_protocol{{[_0-9a-zA-Z]*}}F

test/SILGen/partial_apply_generic.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,21 +14,21 @@ protocol Foo {
1414

1515
// CHECK-LABEL: sil hidden [ossa] @$s21partial_apply_generic14getStaticFunc1{{[_0-9a-zA-Z]*}}F
1616
func getStaticFunc1<T: Foo>(t: T.Type) -> () -> () {
17-
// CHECK: function_ref @$s21partial_apply_generic14getStaticFunc11tyycxm_tAA3FooRzlFyycxmcfu_ : $@convention(thin) <τ_0_0 where τ_0_0 : Foo> (@thick τ_0_0.Type) -> @owned @callee_guaranteed () -> ()
17+
// CHECK: function_ref @$s21partial_apply_generic14getStaticFunc11tyycxm_tAA3FooRzlFyycfu_ : $@convention(thin) <τ_0_0 where τ_0_0 : Foo> (@thick τ_0_0.Type) -> ()
1818
return t.staticFunc
1919
}
2020

21-
// CHECK-LABEL: sil private [ossa] @$s21partial_apply_generic14getStaticFunc11tyycxm_tAA3FooRzlFyycxmcfu_yycfu0_ : $@convention(thin) <T where T : Foo> (@thick T.Type) -> ()
21+
// CHECK-LABEL: sil private [ossa] @$s21partial_apply_generic14getStaticFunc11tyycxm_tAA3FooRzlFyycfu_ : $@convention(thin) <T where T : Foo> (@thick T.Type) -> ()
2222
// CHECK: witness_method $T, #Foo.staticFunc :
2323

2424

2525
// CHECK-LABEL: sil hidden [ossa] @$s21partial_apply_generic14getStaticFunc2{{[_0-9a-zA-Z]*}}F
2626
func getStaticFunc2<T: Foo>(t: T) -> () -> () {
27-
// CHECK: function_ref @$s21partial_apply_generic14getStaticFunc21tyycx_tAA3FooRzlFyycxmcfu_ : $@convention(thin) <τ_0_0 where τ_0_0 : Foo> (@thick τ_0_0.Type) -> @owned @callee_guaranteed () -> ()
27+
// CHECK: function_ref @$s21partial_apply_generic14getStaticFunc21tyycx_tAA3FooRzlFyycfu_ : $@convention(thin) <τ_0_0 where τ_0_0 : Foo> (@thick τ_0_0.Type) -> ()
2828
return T.staticFunc
2929
}
3030

31-
// CHECK-LABEL: sil private [ossa] @$s21partial_apply_generic14getStaticFunc21tyycx_tAA3FooRzlFyycxmcfu_yycfu0_ : $@convention(thin) <T where T : Foo> (@thick T.Type) -> ()
31+
// CHECK-LABEL: sil private [ossa] @$s21partial_apply_generic14getStaticFunc21tyycx_tAA3FooRzlFyycfu_ : $@convention(thin) <T where T : Foo> (@thick T.Type) -> ()
3232
// CHECK: witness_method $T, #Foo.staticFunc :
3333

3434

0 commit comments

Comments
 (0)