Skip to content

Commit 4848aaa

Browse files
committed
[SILGen] Fall back to module lookup on invalid conformance when building subst. maps for vtable thunks
1 parent 9971422 commit 4848aaa

File tree

4 files changed

+75
-4
lines changed

4 files changed

+75
-4
lines changed

include/swift/AST/SubstitutionMap.h

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,8 +111,30 @@ class SubstitutionMap {
111111

112112
/// Build an interface type substitution map for the given generic
113113
/// signature using the mapping in the given substitutions.
114+
///
115+
/// \Note
116+
/// Currently, \p fallBackToModuleConformanceLookup is only necessary
117+
/// when we emit a reabstraction thunk for an override, because we might
118+
/// not have enough information in the substitution map alone.
119+
///
120+
/// For example, combining the override substitutions with the invocation
121+
/// generic signature for the following override requires recovering
122+
/// the implied conformance Foo : P.
123+
///
124+
/// \code
125+
/// class Base<T> {
126+
/// func foo<U>(u: U) where T == Foo {}
127+
/// }
128+
/// class Derived<T>: Base<T> {
129+
/// override func foo<U>(u: U) where T: P {}
130+
/// }
131+
/// \endcode
132+
///
133+
/// \param fallBackToModuleConformanceLookup Fall back to module lookup
134+
/// if a conformance could not be found otherwise.
114135
static SubstitutionMap get(GenericSignature genericSig,
115-
SubstitutionMap substitutions);
136+
SubstitutionMap substitutions,
137+
bool fallBackToModuleConformanceLookup = false);
116138

117139
/// Build an interface type substitution map for the given generic signature
118140
/// from a type substitution function and conformance lookup function.

lib/AST/SubstitutionMap.cpp

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -178,19 +178,49 @@ SubstitutionMap SubstitutionMap::getCanonical() const {
178178

179179

180180
SubstitutionMap SubstitutionMap::get(GenericSignature genericSig,
181-
SubstitutionMap substitutions) {
181+
SubstitutionMap substitutions,
182+
bool fallBackToModuleConformanceLookup) {
182183
if (!genericSig) {
183184
assert(!substitutions.hasAnySubstitutableParams() &&
184185
"Shouldn't have substitutions here");
185186
return SubstitutionMap();
186187
}
187188

189+
LookupConformanceFn lookupConformanceFn;
190+
if (fallBackToModuleConformanceLookup) {
191+
/// Like \c LookUpConformanceInSubstitutionMap , but falls back to module
192+
/// lookup if the conformance could not be found.
193+
class LookUpConformanceInSubstitutionMapOrModule {
194+
SubstitutionMap Subs;
195+
public:
196+
LookUpConformanceInSubstitutionMapOrModule(SubstitutionMap Subs)
197+
: Subs(Subs) {}
198+
199+
ProtocolConformanceRef operator()(CanType dependentType,
200+
Type conformingReplacementType,
201+
ProtocolDecl *conformedProtocol) const {
202+
auto conformance = LookUpConformanceInSubstitutionMap(Subs)
203+
(dependentType, conformingReplacementType, conformedProtocol);
204+
205+
if (conformance.isInvalid())
206+
return conformedProtocol->getParentModule()->lookupConformance(
207+
conformingReplacementType, conformedProtocol);
208+
return conformance;
209+
};
210+
};
211+
212+
lookupConformanceFn =
213+
LookUpConformanceInSubstitutionMapOrModule(substitutions);
214+
} else {
215+
lookupConformanceFn = LookUpConformanceInSubstitutionMap(substitutions);
216+
}
217+
188218
return SubstitutionMap::get(genericSig,
189219
[&](SubstitutableType *type) -> Type {
190220
return substitutions.lookupSubstitution(
191221
CanSubstitutableType(type));
192222
},
193-
LookUpConformanceInSubstitutionMap(substitutions));
223+
lookupConformanceFn);
194224
}
195225

196226
/// Build an interface type substitution map for the given generic signature

lib/SILGen/SILGenPoly.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3744,7 +3744,8 @@ SILGenFunction::emitVTableThunk(SILDeclRef base,
37443744

37453745
auto subs = getForwardingSubstitutionMap();
37463746
if (auto genericSig = derivedFTy->getInvocationGenericSignature()) {
3747-
subs = SubstitutionMap::get(genericSig, subs);
3747+
subs = SubstitutionMap::get(genericSig, subs,
3748+
/*fallBackToModuleConformanceLookup*/true);
37483749

37493750
derivedFTy =
37503751
derivedFTy->substGenericArgs(SGM.M, subs, getTypeExpansionContext());

test/SILGen/vtable_thunks_reabstraction.swift

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -484,11 +484,14 @@ class ConcreteOptional: Opaque<S?> {
484484
class GenericBase<T> {
485485
func doStuff<U>(t: T, u: U) {}
486486
init<U>(t: T, u: U) {}
487+
488+
func doStuff2<U>(u: U) where T == Int {}
487489
}
488490

489491
// CHECK-LABEL: sil_vtable GenericBase {
490492
// CHECK-NEXT: #GenericBase.doStuff!1: <T><U> (GenericBase<T>) -> (T, U) -> () : @$s27vtable_thunks_reabstraction11GenericBaseC7doStuff1t1uyx_qd__tlF // GenericBase.doStuff<A>(t:u:)
491493
// CHECK-NEXT: #GenericBase.init!allocator.1: <T><U> (GenericBase<T>.Type) -> (T, U) -> GenericBase<T> : @$s27vtable_thunks_reabstraction11GenericBaseC1t1uACyxGx_qd__tclufC
494+
// CHECK-NEXT: #GenericBase.doStuff2!1: <T where T == Int><U> (GenericBase<T>) -> (U) -> () : @$s27vtable_thunks_reabstraction11GenericBaseC8doStuff21uyqd___tSiRszlF
492495
// CHECK-NEXT: #GenericBase.deinit!deallocator.1: @$s27vtable_thunks_reabstraction11GenericBaseCfD // GenericBase.__deallocating_deinit
493496
// CHECK-NEXT: }
494497

@@ -504,6 +507,7 @@ class ConcreteSub : GenericBase<Int> {
504507
// CHECK-LABEL: sil_vtable ConcreteSub {
505508
// CHECK-NEXT: #GenericBase.doStuff!1: <T><U> (GenericBase<T>) -> (T, U) -> () : @$s27vtable_thunks_reabstraction11ConcreteSubC7doStuff1t1uySi_xtlFAA11GenericBaseCAdeFyx_qd__tlFTV [override] // vtable thunk for GenericBase.doStuff<A>(t:u:) dispatching to ConcreteSub.doStuff<A>(t:u:)
506509
// CHECK-NEXT: #GenericBase.init!allocator.1: <T><U> (GenericBase<T>.Type) -> (T, U) -> GenericBase<T> : @$s27vtable_thunks_reabstraction11ConcreteSubC1t1uACSi_xtclufCAA11GenericBaseCAdeGyxGx_qd__tclufCTV [override]
510+
// CHECK-NEXT: #GenericBase.doStuff2!1: <T where T == Int><U> {{.*}}F [inherited]
507511
// CHECK-NEXT: #ConcreteSub.deinit!deallocator.1: @$s27vtable_thunks_reabstraction11ConcreteSubCfD // ConcreteSub.__deallocating_deinit
508512
// CHECK-NEXT: }
509513

@@ -543,6 +547,7 @@ class MoreGenericSub1<T, TT> : GenericBase<T> {
543547
// CHECK-LABEL: sil_vtable MoreGenericSub1 {
544548
// CHECK-NEXT: #GenericBase.doStuff!1: <T><U> (GenericBase<T>) -> (T, U) -> () : @$s27vtable_thunks_reabstraction15MoreGenericSub1C7doStuff1t1uyx_qd__tlF [override] // MoreGenericSub1.doStuff<A>(t:u:)
545549
// CHECK-NEXT: #GenericBase.init!allocator.1: <T><U> (GenericBase<T>.Type) -> (T, U) -> GenericBase<T> : @$s27vtable_thunks_reabstraction15MoreGenericSub1C1t1uACyxq_Gx_qd__tclufC [override]
550+
// CHECK-NEXT: #GenericBase.doStuff2!1: <T where T == Int><U> {{.*}}F [inherited]
546551
// CHECK-NEXT: #MoreGenericSub1.deinit!deallocator.1: @$s27vtable_thunks_reabstraction15MoreGenericSub1CfD // MoreGenericSub1.__deallocating_deinit
547552
// CHECK-NEXT: }
548553

@@ -555,5 +560,18 @@ class MoreGenericSub2<TT, T> : GenericBase<T> {
555560
// CHECK-LABEL: sil_vtable MoreGenericSub2 {
556561
// CHECK-NEXT: #GenericBase.doStuff!1: <T><U> (GenericBase<T>) -> (T, U) -> () : @$s27vtable_thunks_reabstraction15MoreGenericSub2C7doStuff1t1uyq__qd__tlF [override] // MoreGenericSub2.doStuff<A>(t:u:)
557562
// CHECK-NEXT: #GenericBase.init!allocator.1: <T><U> (GenericBase<T>.Type) -> (T, U) -> GenericBase<T> : @$s27vtable_thunks_reabstraction15MoreGenericSub2C1t1uACyxq_Gq__qd__tclufC [override]
563+
// CHECK-NEXT: #GenericBase.doStuff2!1: <T where T == Int><U> {{.*}}F [inherited]
558564
// CHECK-NEXT: #MoreGenericSub2.deinit!deallocator.1: @$s27vtable_thunks_reabstraction15MoreGenericSub2CfD // MoreGenericSub2.__deallocating_deinit
559565
// CHECK-NEXT: }
566+
567+
class GenericSub2<T>: GenericBase<T> {
568+
override func doStuff2<U>(u: U) where T: FixedWidthInteger {}
569+
}
570+
571+
// CHECK-LABEL: sil_vtable GenericSub2 {
572+
// CHECK-NEXT: #GenericBase.doStuff!1: <T><U> {{.*}}F [inherited]
573+
// CHECK-NEXT: #GenericBase.init
574+
// CHECK-NEXT: #GenericBase.doStuff2!1: <T where T == Int><U> (GenericBase<T>) -> (U) -> () : @$s27vtable_thunks_reabstraction11GenericSub2C8doStuff21uyqd___ts17FixedWidthIntegerRzlFAA0D4BaseCAdEyqd___tSiRszlFTV [override]
575+
// CHECK-NEXT: #GenericSub2.doStuff2!1: <T where T : FixedWidthInteger><U> (GenericSub2<T>) -> (U) -> () : @$s27vtable_thunks_reabstraction11GenericSub2C8doStuff21uyqd___ts17FixedWidthIntegerRzlF
576+
// CHECK-NEXT: #GenericSub2.deinit
577+
// CHECK-NEXT: }

0 commit comments

Comments
 (0)