Skip to content

Commit 12da7c6

Browse files
committed
[SIL Parser] Extend the hack for Self in default witness tables.
We *still* need a better way to model this, eventually, but this keeps the SIL parser limping along for default witness tables.
1 parent fb62977 commit 12da7c6

File tree

3 files changed

+77
-54
lines changed

3 files changed

+77
-54
lines changed

lib/AST/NameLookup.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -709,6 +709,7 @@ UnqualifiedLookup::UnqualifiedLookup(DeclName Name, DeclContext *DC,
709709
};
710710

711711
if (Loc.isValid() &&
712+
DC->getParentSourceFile() &&
712713
DC->getParentSourceFile()->Kind != SourceFileKind::REPL &&
713714
Ctx.LangOpts.EnableASTScopeLookup) {
714715
// Find the source file in which we are performing the lookup.

lib/ParseSIL/ParseSIL.cpp

Lines changed: 74 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,8 @@ namespace {
181181
ProtocolConformance *
182182
parseProtocolConformanceHelper(ProtocolDecl *&proto,
183183
GenericEnvironment *GenericEnv,
184-
bool localScope);
184+
bool localScope,
185+
ProtocolDecl *defaultForProto);
185186
public:
186187
SILParser(Parser &P)
187188
: P(P), SILMod(static_cast<SILParserTUState *>(P.SIL)->M),
@@ -391,15 +392,18 @@ namespace {
391392
bool isStartOfSILInstruction();
392393

393394
bool parseSubstitutions(SmallVectorImpl<ParsedSubstitution> &parsed,
394-
GenericEnvironment *GenericEnv=nullptr);
395+
GenericEnvironment *GenericEnv=nullptr,
396+
ProtocolDecl *defaultForProto = nullptr);
395397

396398
ProtocolConformance *parseProtocolConformance(ProtocolDecl *&proto,
397399
GenericEnvironment *&genericEnv,
398-
bool localScope);
399-
ProtocolConformance *parseProtocolConformance() {
400+
bool localScope,
401+
ProtocolDecl *defaultForProto);
402+
ProtocolConformance *parseProtocolConformance(
403+
ProtocolDecl *defaultForProto) {
400404
ProtocolDecl *dummy;
401405
GenericEnvironment *env;
402-
return parseProtocolConformance(dummy, env, true);
406+
return parseProtocolConformance(dummy, env, true, defaultForProto);
403407
}
404408

405409
Optional<llvm::coverage::Counter>
@@ -1012,6 +1016,8 @@ bool SILParser::performTypeLocChecking(TypeLoc &T, bool IsSILType,
10121016

10131017
if (!DC)
10141018
DC = &P.SF;
1019+
else if (!GenericEnv)
1020+
GenericEnv = DC->getGenericEnvironmentOfContext();
10151021

10161022
return swift::performTypeLocChecking(P.Context, T,
10171023
/*isSILMode=*/true, IsSILType,
@@ -1510,10 +1516,46 @@ bool SILParser::parseSILBBArgsAtBranch(SmallVector<SILValue, 6> &Args,
15101516
return false;
15111517
}
15121518

1519+
/// Bind any unqualified 'Self' references to the given protocol's 'Self'
1520+
/// generic parameter.
1521+
///
1522+
/// FIXME: This is a hack to work around the lack of a DeclContext for
1523+
/// witness tables.
1524+
static void bindProtocolSelfInTypeRepr(TypeLoc &TL, ProtocolDecl *proto) {
1525+
if (auto typeRepr = TL.getTypeRepr()) {
1526+
// AST walker to update 'Self' references.
1527+
class BindProtocolSelf : public ASTWalker {
1528+
ProtocolDecl *proto;
1529+
GenericTypeParamDecl *selfParam;
1530+
Identifier selfId;
1531+
1532+
public:
1533+
BindProtocolSelf(ProtocolDecl *proto)
1534+
: proto(proto),
1535+
selfParam(proto->getProtocolSelfType()->getDecl()),
1536+
selfId(proto->getASTContext().Id_Self) {
1537+
}
1538+
1539+
virtual bool walkToTypeReprPre(TypeRepr *T) override {
1540+
if (auto ident = dyn_cast<IdentTypeRepr>(T)) {
1541+
auto firstComponent = ident->getComponentRange().front();
1542+
if (firstComponent->getIdentifier() == selfId)
1543+
firstComponent->setValue(selfParam, proto);
1544+
}
1545+
1546+
return true;
1547+
}
1548+
};
1549+
1550+
typeRepr->walk(BindProtocolSelf(proto));
1551+
}
1552+
}
1553+
15131554
/// Parse the substitution list for an apply instruction or
15141555
/// specialized protocol conformance.
15151556
bool SILParser::parseSubstitutions(SmallVectorImpl<ParsedSubstitution> &parsed,
1516-
GenericEnvironment *GenericEnv) {
1557+
GenericEnvironment *GenericEnv,
1558+
ProtocolDecl *defaultForProto) {
15171559
// Check for an opening '<' bracket.
15181560
if (!P.Tok.isContextualPunctuator("<"))
15191561
return false;
@@ -1529,7 +1571,10 @@ bool SILParser::parseSubstitutions(SmallVectorImpl<ParsedSubstitution> &parsed,
15291571
if (TyR.isNull())
15301572
return true;
15311573
TypeLoc Ty = TyR.get();
1532-
if (performTypeLocChecking(Ty, /*IsSILType=*/ false, GenericEnv))
1574+
if (defaultForProto)
1575+
bindProtocolSelfInTypeRepr(Ty, defaultForProto);
1576+
if (performTypeLocChecking(Ty, /*IsSILType=*/ false, GenericEnv,
1577+
defaultForProto))
15331578
return true;
15341579
parsed.push_back({Loc, Ty.getType()});
15351580
} while (P.consumeIf(tok::comma));
@@ -5725,7 +5770,8 @@ static NormalProtocolConformance *parseNormalProtocolConformance(Parser &P,
57255770
ProtocolConformance *SILParser::parseProtocolConformance(
57265771
ProtocolDecl *&proto,
57275772
GenericEnvironment *&genericEnv,
5728-
bool localScope) {
5773+
bool localScope,
5774+
ProtocolDecl *defaultForProto) {
57295775
// Parse generic params for the protocol conformance. We need to make sure
57305776
// they have the right scope.
57315777
Optional<Scope> GenericsScope;
@@ -5741,7 +5787,8 @@ ProtocolConformance *SILParser::parseProtocolConformance(
57415787
}
57425788

57435789
ProtocolConformance *retVal =
5744-
parseProtocolConformanceHelper(proto, genericEnv, localScope);
5790+
parseProtocolConformanceHelper(proto, genericEnv, localScope,
5791+
defaultForProto);
57455792

57465793
if (localScope) {
57475794
GenericsScope.reset();
@@ -5752,13 +5799,19 @@ ProtocolConformance *SILParser::parseProtocolConformance(
57525799
ProtocolConformance *SILParser::parseProtocolConformanceHelper(
57535800
ProtocolDecl *&proto,
57545801
GenericEnvironment *witnessEnv,
5755-
bool localScope) {
5802+
bool localScope,
5803+
ProtocolDecl *defaultForProto) {
57565804
// Parse AST type.
57575805
ParserResult<TypeRepr> TyR = P.parseType();
57585806
if (TyR.isNull())
57595807
return nullptr;
57605808
TypeLoc Ty = TyR.get();
5761-
if (performTypeLocChecking(Ty, /*IsSILType=*/ false, witnessEnv))
5809+
if (defaultForProto) {
5810+
bindProtocolSelfInTypeRepr(Ty, defaultForProto);
5811+
}
5812+
5813+
if (performTypeLocChecking(Ty, /*IsSILType=*/ false, witnessEnv,
5814+
defaultForProto))
57625815
return nullptr;
57635816
auto ConformingTy = Ty.getType();
57645817

@@ -5770,15 +5823,16 @@ ProtocolConformance *SILParser::parseProtocolConformanceHelper(
57705823

57715824
// Parse substitutions for specialized conformance.
57725825
SmallVector<ParsedSubstitution, 4> parsedSubs;
5773-
if (parseSubstitutions(parsedSubs, witnessEnv))
5826+
if (parseSubstitutions(parsedSubs, witnessEnv, defaultForProto))
57745827
return nullptr;
57755828

57765829
if (P.parseToken(tok::l_paren, diag::expected_sil_witness_lparen))
57775830
return nullptr;
57785831
ProtocolDecl *dummy;
57795832
GenericEnvironment *specializedEnv;
57805833
auto genericConform =
5781-
parseProtocolConformance(dummy, specializedEnv, localScope);
5834+
parseProtocolConformance(dummy, specializedEnv, localScope,
5835+
defaultForProto);
57825836
if (!genericConform)
57835837
return nullptr;
57845838
if (P.parseToken(tok::r_paren, diag::expected_sil_witness_rparen))
@@ -5799,7 +5853,7 @@ ProtocolConformance *SILParser::parseProtocolConformanceHelper(
57995853

58005854
if (P.parseToken(tok::l_paren, diag::expected_sil_witness_lparen))
58015855
return nullptr;
5802-
auto baseConform = parseProtocolConformance();
5856+
auto baseConform = parseProtocolConformance(defaultForProto);
58035857
if (!baseConform)
58045858
return nullptr;
58055859
if (P.parseToken(tok::r_paren, diag::expected_sil_witness_rparen))
@@ -5812,41 +5866,6 @@ ProtocolConformance *SILParser::parseProtocolConformanceHelper(
58125866
return retVal;
58135867
}
58145868

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-
58505869
/// Parser a single SIL vtable entry and add it to either \p witnessEntries
58515870
/// or \c conditionalConformances.
58525871
static bool parseSILVTableEntry(
@@ -5859,6 +5878,7 @@ static bool parseSILVTableEntry(
58595878
std::vector<SILWitnessTable::Entry> &witnessEntries,
58605879
std::vector<SILWitnessTable::ConditionalConformance>
58615880
&conditionalConformances) {
5881+
ProtocolDecl *defaultForProto = isDefaultWitnessTable ? proto : nullptr;
58625882
Identifier EntryKeyword;
58635883
SourceLoc KeywordLoc;
58645884
if (P.parseIdentifier(EntryKeyword, KeywordLoc,
@@ -5878,7 +5898,8 @@ static bool parseSILVTableEntry(
58785898
return true;
58795899
if (P.parseToken(tok::colon, diag::expected_sil_witness_colon))
58805900
return true;
5881-
ProtocolConformance *conform = witnessState.parseProtocolConformance();
5901+
ProtocolConformance *conform =
5902+
witnessState.parseProtocolConformance(defaultForProto);
58825903
if (!conform) // Ignore this witness entry for now.
58835904
return false;
58845905

@@ -5925,7 +5946,7 @@ static bool parseSILVTableEntry(
59255946

59265947
ProtocolConformanceRef conformance(proto);
59275948
if (P.Tok.getText() != "dependent") {
5928-
auto concrete = witnessState.parseProtocolConformance();
5949+
auto concrete = witnessState.parseProtocolConformance(defaultForProto);
59295950
if (!concrete) // Ignore this witness entry for now.
59305951
return false;
59315952
conformance = ProtocolConformanceRef(concrete);
@@ -6045,7 +6066,8 @@ bool SILParserTUState::parseSILWitnessTable(Parser &P) {
60456066
GenericEnvironment *witnessEnv;
60466067
auto conf = WitnessState.parseProtocolConformance(proto,
60476068
witnessEnv,
6048-
false/*localScope*/);
6069+
false/*localScope*/,
6070+
nullptr);
60496071
WitnessState.ContextGenericEnv = witnessEnv;
60506072

60516073
NormalProtocolConformance *theConformance = conf ?

test/SIL/Parser/default_witness_tables.sil

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ bb0(%0 : $*Self):
4848

4949

5050
// CHECK-LABEL: sil_default_witness_table ResilientProtocol {
51-
// CHECK: no_default
51+
// CHECK: associated_type_protocol (T: Proto): Wrapper<Self>: specialize <Self> (<T> Wrapper<T>: Proto module witness_tables)
5252
// CHECK: associated_type T: Wrapper<Self>
5353
// CHECK: no_default
5454
// CHECK: no_default
@@ -58,7 +58,7 @@ bb0(%0 : $*Self):
5858
// CHECK: }
5959

6060
sil_default_witness_table ResilientProtocol {
61-
no_default
61+
associated_type_protocol (T: Proto): Wrapper<Self>: specialize <Self> (<T> Wrapper<T>: Proto module witness_tables)
6262
associated_type T: Wrapper<Self>
6363
no_default
6464
no_default

0 commit comments

Comments
 (0)