Skip to content

Commit a8ef08c

Browse files
committed
[SILGen] Ensure type params in witness method conformances match the witness method signatures.
A witness method of a class can have its generic parameters rephrased: a parameters of the class, like τ_0_0, get pushed to the next depth, like τ_1_0, to make way for a τ_0_0 parameter with a τ_0_0: Class<...> subclass constraint. When this wasn't accounted for, IRGen would find that it couldn't satisfy conditional requirements on the rewritten type parameters, and they'd incorrectly be passed as additional arguments of a witness method thunk rather than pulled out of the Self witness table's private area inside the thunk. Fixes rdar://problem/40078863.
1 parent b8ea62e commit a8ef08c

File tree

3 files changed

+31
-2
lines changed

3 files changed

+31
-2
lines changed

lib/SILGen/SILGenType.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -614,6 +614,20 @@ SILFunction *SILGenModule::emitProtocolWitness(
614614
auto input = reqtOrigTy->getInput().subst(reqtSubMap)->getCanonicalType();
615615
auto result = reqtOrigTy->getResult().subst(reqtSubMap)->getCanonicalType();
616616

617+
// If there's something to map to for the witness thunk, the conformance
618+
// should be phrased in the same terms. This particularly applies to classes
619+
// where a thunk for a method in a conformance like `extension Class: P where
620+
// T: Q` will go from its native signature of `<τ_0_0 where τ_0_0: Q>` (with T
621+
// canonicalised to τ_0_0), to `<τ_0_0, τ_1_0 where τ_0_0: Class<τ_1_0>,
622+
// τ_1_0: Q>` (with T now represented by τ_1_0). Find the right conformance by
623+
// looking for the conformance of 'Self'.
624+
if (!reqtSubMap.empty()) {
625+
auto requirement = conformance.getRequirement();
626+
auto self = requirement->getProtocolSelfType()->getCanonicalType();
627+
628+
conformance = *reqtSubMap.lookupConformance(self, requirement);
629+
}
630+
617631
CanAnyFunctionType reqtSubstTy;
618632
if (genericEnv) {
619633
auto *genericSig = genericEnv->getGenericSignature();
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// RUN: %target-swift-frontend -emit-ir %s -module-name x | %FileCheck %s
2+
3+
// rdar://problem/40078863 - witness signatures get adjusted and the
4+
// ProtocolConformances accompanying them did not, resulting in an extra witness
5+
// table parameter.
6+
7+
protocol Foo {
8+
func bar()
9+
}
10+
extension Foo {
11+
func bar() {}
12+
}
13+
class Box<T> {}
14+
extension Box: Foo where T: Foo {}
15+
// CHECK-LABEL: define internal swiftcc void @"$S1x3BoxCyqd__GAA3FooA2aEP3baryyFTW"(%T1x3BoxC.0** noalias nocapture swiftself dereferenceable({{[48]}}), %swift.type* %Self, i8** %SelfWitnessTable)

test/SILGen/witnesses_class.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ class UsesDefaults<X : Barable> : HasDefaults {}
7777

7878
// Covariant Self:
7979

80-
// CHECK-LABEL: sil private [transparent] [thunk] @$S15witnesses_class12UsesDefaultsCyxGAA03HasD0A2aEP10hasDefaultyyFTW : $@convention(witness_method: HasDefaults) <τ_0_0><τ_1_0 where τ_0_0 : UsesDefaults<τ_1_0>, τ_1_0 : Barable> (@in_guaranteed τ_0_0) -> ()
80+
// CHECK-LABEL: sil private [transparent] [thunk] @$S15witnesses_class12UsesDefaultsCyqd__GAA03HasD0A2aEP10hasDefaultyyFTW : $@convention(witness_method: HasDefaults) <τ_0_0><τ_1_0 where τ_0_0 : UsesDefaults<τ_1_0>, τ_1_0 : Barable> (@in_guaranteed τ_0_0) -> () {
8181
// CHECK: [[FN:%.*]] = function_ref @$S15witnesses_class11HasDefaultsPAAE10hasDefaultyyF : $@convention(method) <τ_0_0 where τ_0_0 : HasDefaults> (@in_guaranteed τ_0_0) -> ()
8282
// CHECK: apply [[FN]]<τ_0_0>(
8383
// CHECK: return
@@ -91,7 +91,7 @@ class UsesDefaults<X : Barable> : HasDefaults {}
9191

9292
// Covariant Self:
9393

94-
// CHECK-LABEL: sil private [transparent] [thunk] @$S15witnesses_class12UsesDefaultsCyxGAA03HasD0A2aEP17hasDefaultGenericyyqd__AA7FooableRd__lFTW : $@convention(witness_method: HasDefaults) <τ_0_0><τ_1_0 where τ_0_0 : UsesDefaults<τ_1_0>, τ_1_0 : Barable><τ_2_0 where τ_2_0 : Fooable> (@guaranteed τ_2_0, @in_guaranteed τ_0_0) -> ()
94+
// CHECK-LABEL: sil private [transparent] [thunk] @$S15witnesses_class12UsesDefaultsCyqd__GAA03HasD0A2aEP17hasDefaultGenericyyqd__AA7FooableRd__lFTW : $@convention(witness_method: HasDefaults) <τ_0_0><τ_1_0 where τ_0_0 : UsesDefaults<τ_1_0>, τ_1_0 : Barable><τ_2_0 where τ_2_0 : Fooable> (@guaranteed τ_2_0, @in_guaranteed τ_0_0) -> () {
9595
// CHECK: [[FN:%.*]] = function_ref @$S15witnesses_class11HasDefaultsPAAE17hasDefaultGenericyyqd__AA7FooableRd__lF : $@convention(method) <τ_0_0 where τ_0_0 : HasDefaults><τ_1_0 where τ_1_0 : Fooable> (@guaranteed τ_1_0, @in_guaranteed τ_0_0) -> ()
9696
// CHECK: apply [[FN]]<τ_0_0, τ_2_0>(
9797
// CHECK: return

0 commit comments

Comments
 (0)