Skip to content

Commit ccb1c9a

Browse files
committed
[SIL Parser] Handle parsing of ‘Self’ in default witness tables.
There is no good way to do this, so take a shortcut for now of pre-resolving ‘Self’.
1 parent 2ef9363 commit ccb1c9a

File tree

2 files changed

+50
-6
lines changed

2 files changed

+50
-6
lines changed

lib/ParseSIL/ParseSIL.cpp

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5812,6 +5812,41 @@ ProtocolConformance *SILParser::parseProtocolConformanceHelper(
58125812
return retVal;
58135813
}
58145814

5815+
/// Bind any unqualified 'Self' references to the given protocol's 'Self'
5816+
/// generic parameter.
5817+
///
5818+
/// FIXME: This is a hack to work around the lack of a DeclContext for
5819+
/// witness tables.
5820+
static void bindProtocolSelfInTypeRepr(TypeLoc &TL, ProtocolDecl *proto) {
5821+
if (auto typeRepr = TL.getTypeRepr()) {
5822+
// AST walker to update 'Self' references.
5823+
class BindProtocolSelf : public ASTWalker {
5824+
ProtocolDecl *proto;
5825+
GenericTypeParamDecl *selfParam;
5826+
Identifier selfId;
5827+
5828+
public:
5829+
BindProtocolSelf(ProtocolDecl *proto)
5830+
: proto(proto),
5831+
selfParam(proto->getProtocolSelfType()->getDecl()),
5832+
selfId(proto->getASTContext().Id_Self) {
5833+
}
5834+
5835+
virtual bool walkToTypeReprPre(TypeRepr *T) override {
5836+
if (auto ident = dyn_cast<IdentTypeRepr>(T)) {
5837+
auto firstComponent = ident->getComponentRange().front();
5838+
if (firstComponent->getIdentifier() == selfId)
5839+
firstComponent->setValue(selfParam, proto);
5840+
}
5841+
5842+
return true;
5843+
}
5844+
};
5845+
5846+
typeRepr->walk(BindProtocolSelf(proto));
5847+
}
5848+
}
5849+
58155850
/// Parser a single SIL vtable entry and add it to either \p witnessEntries
58165851
/// or \c conditionalConformances.
58175852
static bool parseSILVTableEntry(
@@ -5820,6 +5855,7 @@ static bool parseSILVTableEntry(
58205855
ProtocolDecl *proto,
58215856
GenericEnvironment *witnessEnv,
58225857
SILParser &witnessState,
5858+
bool isDefaultWitnessTable,
58235859
std::vector<SILWitnessTable::Entry> &witnessEntries,
58245860
std::vector<SILWitnessTable::ConditionalConformance>
58255861
&conditionalConformances) {
@@ -5865,6 +5901,8 @@ static bool parseSILVTableEntry(
58655901
if (TyR.isNull())
58665902
return true;
58675903
TypeLoc Ty = TyR.get();
5904+
if (isDefaultWitnessTable)
5905+
bindProtocolSelfInTypeRepr(Ty, proto);
58685906
if (swift::performTypeLocChecking(P.Context, Ty,
58695907
/*isSILMode=*/false,
58705908
/*isSILType=*/false,
@@ -5921,6 +5959,8 @@ static bool parseSILVTableEntry(
59215959
if (TyR.isNull())
59225960
return true;
59235961
TypeLoc Ty = TyR.get();
5962+
if (isDefaultWitnessTable)
5963+
bindProtocolSelfInTypeRepr(Ty, proto);
59245964
if (swift::performTypeLocChecking(P.Context, Ty,
59255965
/*isSILMode=*/false,
59265966
/*isSILType=*/false,
@@ -6046,7 +6086,7 @@ bool SILParserTUState::parseSILWitnessTable(Parser &P) {
60466086

60476087
if (P.Tok.isNot(tok::r_brace)) {
60486088
do {
6049-
if (parseSILVTableEntry(P, M, proto, witnessEnv, WitnessState,
6089+
if (parseSILVTableEntry(P, M, proto, witnessEnv, WitnessState, false,
60506090
witnessEntries, conditionalConformances))
60516091
return true;
60526092
} while (P.Tok.isNot(tok::r_brace) && P.Tok.isNot(tok::eof));
@@ -6092,6 +6132,8 @@ bool SILParserTUState::parseSILDefaultWitnessTable(Parser &P) {
60926132

60936133
// Parse the protocol.
60946134
ProtocolDecl *protocol = parseProtocolDecl(P, WitnessState);
6135+
if (!protocol)
6136+
return true;
60956137

60966138
// Parse the body.
60976139
SourceLoc LBraceLoc = P.Tok.getLoc();
@@ -6106,8 +6148,9 @@ bool SILParserTUState::parseSILDefaultWitnessTable(Parser &P) {
61066148

61076149
if (P.Tok.isNot(tok::r_brace)) {
61086150
do {
6109-
if (parseSILVTableEntry(P, M, protocol, nullptr, WitnessState,
6110-
witnessEntries, conditionalConformances))
6151+
if (parseSILVTableEntry(P, M, protocol, protocol->getGenericEnvironment(),
6152+
WitnessState, true, witnessEntries,
6153+
conditionalConformances))
61116154
return true;
61126155
} while (P.Tok.isNot(tok::r_brace) && P.Tok.isNot(tok::eof));
61136156
}

test/SIL/Parser/default_witness_tables.sil

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@
44
sil_stage raw
55

66
public protocol Proto {}
7+
public struct Wrapper<T>: Proto { }
78

89
public protocol ResilientProtocol {
9-
associatedtype T : Proto
10+
associatedtype T : Proto = Wrapper<Self>
1011
func noDefaultA()
1112
func noDefaultB()
1213
func defaultC()
@@ -48,7 +49,7 @@ bb0(%0 : $*Self):
4849

4950
// CHECK-LABEL: sil_default_witness_table ResilientProtocol {
5051
// CHECK: no_default
51-
// CHECK: no_default
52+
// CHECK: associated_type T: Wrapper<Self>
5253
// CHECK: no_default
5354
// CHECK: no_default
5455
// CHECK: method #ResilientProtocol.defaultC!1: {{.*}} : @defaultC
@@ -58,7 +59,7 @@ bb0(%0 : $*Self):
5859

5960
sil_default_witness_table ResilientProtocol {
6061
no_default
61-
no_default
62+
associated_type T: Wrapper<Self>
6263
no_default
6364
no_default
6465
method #ResilientProtocol.defaultC!1: @defaultC

0 commit comments

Comments
 (0)