Skip to content

Commit 64dc2e9

Browse files
committed
SILGen: Avoid crashing for invalid conformances.
Force resolution of value witnesses and check the conformance for validity before proceeding to witness table emission in SILGen to avoid crashing because of unexpected errors in the AST. Resolves rdar://123027739
1 parent a312225 commit 64dc2e9

File tree

10 files changed

+47
-19
lines changed

10 files changed

+47
-19
lines changed

include/swift/AST/ProtocolConformance.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -747,6 +747,9 @@ class NormalProtocolConformance : public RootProtocolConformance,
747747
/// Override the witness for a given requirement.
748748
void overrideWitness(ValueDecl *requirement, Witness newWitness);
749749

750+
/// Triggers a request that resolves all of the conformance's value witnesses.
751+
void resolveValueWitnesses() const;
752+
750753
/// Determine whether the witness for the given type requirement
751754
/// is the default definition.
752755
bool usesDefaultDefinition(AssociatedTypeDecl *requirement) const {

lib/AST/ProtocolConformance.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -706,6 +706,13 @@ void NormalProtocolConformance::overrideWitness(ValueDecl *requirement,
706706
Mapping[requirement] = witness;
707707
}
708708

709+
void NormalProtocolConformance::resolveValueWitnesses() const {
710+
auto mutableThis = const_cast<NormalProtocolConformance *>(this);
711+
evaluateOrDefault(getProtocol()->getASTContext().evaluator,
712+
ResolveValueWitnessesRequest{mutableThis},
713+
evaluator::SideEffect());
714+
}
715+
709716
SpecializedProtocolConformance::SpecializedProtocolConformance(
710717
Type conformingType,
711718
NormalProtocolConformance *genericConformance,

lib/SILGen/SILGen.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2106,7 +2106,7 @@ class SILGenModuleRAII {
21062106
SGM.pendingForcedFunctions.pop_front();
21072107
}
21082108
while (!SGM.pendingConformances.empty()) {
2109-
SGM.getWitnessTable(SGM.pendingConformances.front());
2109+
(void)SGM.getWitnessTable(SGM.pendingConformances.front());
21102110
SGM.pendingConformances.pop_front();
21112111
}
21122112
}

lib/SILGen/SILGenType.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@
2323
#include "Scope.h"
2424
#include "swift/AST/ASTMangler.h"
2525
#include "swift/AST/GenericEnvironment.h"
26-
#include "swift/AST/ProtocolConformance.h"
2726
#include "swift/AST/PrettyStackTrace.h"
2827
#include "swift/AST/PropertyWrappers.h"
28+
#include "swift/AST/ProtocolConformance.h"
2929
#include "swift/AST/SourceFile.h"
3030
#include "swift/AST/SubstitutionMap.h"
3131
#include "swift/AST/TypeMemberVisitor.h"
@@ -529,6 +529,11 @@ class SILGenConformance : public SILGenWitnessTable<SILGenConformance> {
529529
PrettyStackTraceConformance trace("generating SIL witness table",
530530
Conformance);
531531

532+
// Check whether the conformance is valid first.
533+
Conformance->resolveValueWitnesses();
534+
if (Conformance->isInvalid())
535+
return nullptr;
536+
532537
auto *proto = Conformance->getProtocol();
533538
visitProtocolDecl(proto);
534539

@@ -1150,7 +1155,7 @@ class SILGenType : public TypeMemberVisitor<SILGenType> {
11501155
for (auto *conformance : theType->getLocalConformances(
11511156
ConformanceLookupKind::NonInherited)) {
11521157
if (auto *normal = dyn_cast<NormalProtocolConformance>(conformance))
1153-
SGM.getWitnessTable(normal);
1158+
(void)SGM.getWitnessTable(normal);
11541159
}
11551160
}
11561161

@@ -1309,7 +1314,7 @@ class SILGenExtension : public TypeMemberVisitor<SILGenExtension> {
13091314
for (auto *conformance : e->getLocalConformances(
13101315
ConformanceLookupKind::All)) {
13111316
if (auto *normal =dyn_cast<NormalProtocolConformance>(conformance))
1312-
SGM.getWitnessTable(normal);
1317+
(void)SGM.getWitnessTable(normal);
13131318
}
13141319
}
13151320
}

lib/Sema/CSDiagnostics.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3473,9 +3473,7 @@ bool ContextualFailure::tryProtocolConformanceFixIt(
34733473
evaluateOrDefault(getASTContext().evaluator,
34743474
ResolveTypeWitnessesRequest{conformance},
34753475
evaluator::SideEffect());
3476-
evaluateOrDefault(getASTContext().evaluator,
3477-
ResolveValueWitnessesRequest{conformance},
3478-
evaluator::SideEffect());
3476+
conformance->resolveValueWitnesses();
34793477

34803478
fakeConformances.push_back(conformance);
34813479
}

lib/Sema/CodeSynthesis.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1401,9 +1401,7 @@ ResolveImplicitMemberRequest::evaluate(Evaluator &evaluator,
14011401
// FIXME: This should be more fine-grained to avoid having to check
14021402
// for a cycle here.
14031403
if (!evaluator.hasActiveRequest(ResolveValueWitnessesRequest{conformance})) {
1404-
evaluateOrDefault(evaluator,
1405-
ResolveValueWitnessesRequest{conformance},
1406-
evaluator::SideEffect());
1404+
conformance->resolveValueWitnesses();
14071405
}
14081406
}
14091407

lib/Sema/TypeCheckDecl.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2870,9 +2870,7 @@ static ArrayRef<Decl *> evaluateMembersRequest(
28702870
}
28712871

28722872
if (isDerivable) {
2873-
evaluateOrDefault(ctx.evaluator,
2874-
ResolveValueWitnessesRequest{normal},
2875-
evaluator::SideEffect());
2873+
normal->resolveValueWitnesses();
28762874
}
28772875
}
28782876

lib/Sema/TypeCheckProtocol.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2472,9 +2472,7 @@ checkIndividualConformance(NormalProtocolConformance *conformance) {
24722472
ensureRequirementsAreSatisfied(Context, conformance);
24732473

24742474
// Check non-type requirements.
2475-
evaluateOrDefault(Context.evaluator,
2476-
ResolveValueWitnessesRequest{conformance},
2477-
evaluator::SideEffect());
2475+
conformance->resolveValueWitnesses();
24782476
}
24792477

24802478
/// Add the next associated type deduction to the string representation

lib/Sema/TypeCheckStorage.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -169,9 +169,7 @@ static void computeLoweredProperties(NominalTypeDecl *decl,
169169
evaluateOrDefault(ctx.evaluator,
170170
ResolveTypeWitnessesRequest{normal},
171171
evaluator::SideEffect());
172-
evaluateOrDefault(ctx.evaluator,
173-
ResolveValueWitnessesRequest{normal},
174-
evaluator::SideEffect());
172+
normal->resolveValueWitnesses();
175173
}
176174
}
177175
};
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// RUN: %target-swift-frontend -emit-silgen %s -parse-as-library -module-name Test -enable-library-evolution -experimental-lazy-typecheck -verify
2+
3+
public protocol Proto {
4+
func req()
5+
}
6+
7+
public struct ConformsToProtoMissingRequirement: Proto {
8+
// expected-error@-1 {{type 'ConformsToProtoMissingRequirement' does not conform to protocol 'Proto'}}
9+
}
10+
11+
public struct ConformsToProtoNearMiss: Proto {
12+
// expected-error@-1 {{type 'ConformsToProtoNearMiss' does not conform to protocol 'Proto'}}
13+
14+
public func req(x: Int) {}
15+
}
16+
17+
public protocol ProtoWithAssociatedType {
18+
associatedtype A
19+
}
20+
21+
public struct ConformsToProtoProtoWithAssociatedType: ProtoWithAssociatedType {
22+
// expected-error@-1 {{type 'ConformsToProtoProtoWithAssociatedType' does not conform to protocol 'ProtoWithAssociatedType'}}
23+
}

0 commit comments

Comments
 (0)