Skip to content

Commit 77c26a7

Browse files
authored
Merge pull request #70707 from rjmccall/variadic-generic-class-method-dispatch
Fix variadic-generic class method dispatch
2 parents 6f3eeb5 + 5f0357f commit 77c26a7

File tree

4 files changed

+103
-4
lines changed

4 files changed

+103
-4
lines changed

include/swift/AST/ConcreteDeclRef.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,9 @@ class ConcreteDeclRef {
6868
/// Retrieve a reference to the declaration this one overrides.
6969
ConcreteDeclRef getOverriddenDecl() const;
7070

71+
/// Retrieve a reference to the given declaration that this one overrides.
72+
ConcreteDeclRef getOverriddenDecl(ValueDecl *overriddenDecl) const;
73+
7174
/// Determine whether this reference specializes the declaration to which
7275
/// it refers.
7376
bool isSpecialized() const { return !substitutions.empty(); }

lib/AST/ConcreteDeclRef.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,29 @@ ConcreteDeclRef ConcreteDeclRef::getOverriddenDecl() const {
4343
return ConcreteDeclRef(baseDecl, subs);
4444
}
4545

46+
ConcreteDeclRef ConcreteDeclRef::getOverriddenDecl(ValueDecl *baseDecl) const {
47+
auto *derivedDecl = getDecl();
48+
if (baseDecl == derivedDecl) return *this;
49+
50+
#ifndef NDEBUG
51+
{
52+
auto cur = derivedDecl;
53+
for (; cur && cur != baseDecl; cur = cur->getOverriddenDecl()) {}
54+
assert(cur && "decl is not an indirect override of baseDecl");
55+
}
56+
#endif
57+
58+
if (!baseDecl->getInnermostDeclContext()->isGenericContext()) {
59+
return ConcreteDeclRef(baseDecl);
60+
}
61+
62+
auto subs = SubstitutionMap::getOverrideSubstitutions(baseDecl, derivedDecl);
63+
if (auto derivedSubs = getSubstitutions()) {
64+
subs = subs.subst(derivedSubs);
65+
}
66+
return ConcreteDeclRef(baseDecl, subs);
67+
}
68+
4669
void ConcreteDeclRef::dump(raw_ostream &os) const {
4770
if (!getDecl()) {
4871
os << "**NULL**";

lib/SILGen/SILGenApply.cpp

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -444,17 +444,34 @@ class Callee {
444444
auto base = c.getOverriddenVTableEntry();
445445
auto &baseCI = SGF.getConstantInfo(SGF.getTypeExpansionContext(), base);
446446
auto &derivedCI = SGF.getConstantInfo(SGF.getTypeExpansionContext(), c);
447+
subs = subs.mapIntoTypeExpansionContext(SGF.getTypeExpansionContext());
448+
449+
// We use an orig function type based on the overridden vtable entry, but
450+
// the substitutions we have are for the current function. To get subs
451+
// that will work on the overridden entry, we need to construct the
452+
// override substitutions.
453+
auto origFunctionType = baseCI.FormalPattern;
454+
if (base.getDecl() == c.getDecl()) {
455+
origFunctionType = origFunctionType.withSubstitutions(subs);
456+
} else {
457+
auto derivedCDR = ConcreteDeclRef(c.getDecl(), subs);
458+
auto baseCDR = derivedCDR.getOverriddenDecl(base.getDecl());
459+
origFunctionType =
460+
origFunctionType.withSubstitutions(baseCDR.getSubstitutions());
461+
}
462+
447463
return Callee(
448-
Kind::ClassMethod, SGF, c, baseCI.FormalPattern, derivedCI.FormalType,
449-
subs.mapIntoTypeExpansionContext(SGF.getTypeExpansionContext()), l);
464+
Kind::ClassMethod, SGF, c, origFunctionType, derivedCI.FormalType,
465+
subs, l);
450466
}
451467
static Callee forSuperMethod(SILGenFunction &SGF,
452468
SILDeclRef c, SubstitutionMap subs,
453469
SILLocation l) {
454470
auto &ci = SGF.getConstantInfo(SGF.getTypeExpansionContext(), c);
471+
subs = subs.mapIntoTypeExpansionContext(SGF.getTypeExpansionContext());
472+
auto origFunctionType = ci.FormalPattern.withSubstitutions(subs);
455473
return Callee(
456-
Kind::SuperMethod, SGF, c, ci.FormalPattern, ci.FormalType,
457-
subs.mapIntoTypeExpansionContext(SGF.getTypeExpansionContext()), l);
474+
Kind::SuperMethod, SGF, c, origFunctionType, ci.FormalType, subs, l);
458475
}
459476
static Callee forWitnessMethod(SILGenFunction &SGF,
460477
CanType protocolSelfType,
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// RUN: %target-swift-emit-silgen -disable-availability-checking %s | %FileCheck %s
2+
3+
public class A<each T> {
4+
public func f(_ action: (repeat each T) -> ()) {}
5+
}
6+
7+
// CHECK-LABEL: sil hidden [ossa] @$s4main5test02fnyySi_SftXE_tF :
8+
// CHECK: [[CTOR:%.*]] = function_ref @$s4main1ACACyxxQp_QPGycfC :
9+
// CHECK: [[OBJECT:%.*]] = apply [[CTOR]]<Pack{Int, Float}>
10+
// CHECK: [[METHOD:%.*]] = class_method [[OBJECT]] : $A<Int, Float>, #A.f : <each T> (A<repeat each T>) -> ((repeat each T) -> ()) -> ()
11+
// CHECK: apply [[METHOD]]<Pack{Int, Float}>
12+
func test0(fn: (Int, Float) -> ()) {
13+
A<Int, Float>().f(fn)
14+
}
15+
16+
// CHECK-LABEL: sil hidden [ossa] @$s4main5test1yyF :
17+
// CHECK: [[CTOR:%.*]] = function_ref @$s4main1ACACyxxQp_QPGycfC :
18+
// CHECK: [[OBJECT:%.*]] = apply [[CTOR]]<Pack{Int, Float}>
19+
// CHECK: [[METHOD:%.*]] = class_method [[OBJECT]] : $A<Int, Float>, #A.f : <each T> (A<repeat each T>) -> ((repeat each T) -> ()) -> ()
20+
// CHECK: apply [[METHOD]]<Pack{Int, Float}>
21+
func test1() {
22+
A<Int, Float>().f { a, b in }
23+
}
24+
25+
// These are all currently forbidden
26+
#if false
27+
public class B<each T> : A<repeat each T> {
28+
public override func f(_ action: (repeat each T) -> ()) {
29+
super.f(action)
30+
}
31+
}
32+
33+
func test2() {
34+
B<Int, Float>().f { a, b in }
35+
}
36+
37+
public class C<T, each U> : A<T, repeat each U> {
38+
public override func f(_ action: (T, repeat each U) -> ()) {
39+
super.f(action)
40+
}
41+
}
42+
43+
func test3() {
44+
C<Int, Float>().f { a, b in }
45+
}
46+
47+
public class D : A<Int, Float> {
48+
public override func f(_ action: (Int, Float) -> ()) {
49+
super.f(action)
50+
}
51+
}
52+
53+
func test4() {
54+
D().f { a, b in }
55+
}
56+
#endif

0 commit comments

Comments
 (0)