Skip to content

Commit d29f6a1

Browse files
authored
Merge pull request #72286 from tshortli/silgen-lazy-typecheck-conformance-errors
SILGen: Avoid crashing for invalid conformances
2 parents 315a763 + f6dd524 commit d29f6a1

File tree

10 files changed

+85
-19
lines changed

10 files changed

+85
-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: 14 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"
@@ -260,6 +260,8 @@ class SILGenVTable : public SILVTableVisitor<SILGenVTable> {
260260
}
261261

262262
void emitVTable() {
263+
PrettyStackTraceDecl("silgen emitVTable", theClass);
264+
263265
// Imported types don't have vtables right now.
264266
if (theClass->hasClangNode())
265267
return;
@@ -529,6 +531,11 @@ class SILGenConformance : public SILGenWitnessTable<SILGenConformance> {
529531
PrettyStackTraceConformance trace("generating SIL witness table",
530532
Conformance);
531533

534+
// Check whether the conformance is valid first.
535+
Conformance->resolveValueWitnesses();
536+
if (Conformance->isInvalid())
537+
return nullptr;
538+
532539
auto *proto = Conformance->getProtocol();
533540
visitProtocolDecl(proto);
534541

@@ -1113,6 +1120,8 @@ class SILGenType : public TypeMemberVisitor<SILGenType> {
11131120

11141121
/// Emit SIL functions for all the members of the type.
11151122
void emitType() {
1123+
PrettyStackTraceDecl("silgen emitType", theType);
1124+
11161125
SGM.emitLazyConformancesForType(theType);
11171126

11181127
for (Decl *member : theType->getABIMembers()) {
@@ -1150,7 +1159,7 @@ class SILGenType : public TypeMemberVisitor<SILGenType> {
11501159
for (auto *conformance : theType->getLocalConformances(
11511160
ConformanceLookupKind::NonInherited)) {
11521161
if (auto *normal = dyn_cast<NormalProtocolConformance>(conformance))
1153-
SGM.getWitnessTable(normal);
1162+
(void)SGM.getWitnessTable(normal);
11541163
}
11551164
}
11561165

@@ -1287,6 +1296,8 @@ class SILGenExtension : public TypeMemberVisitor<SILGenExtension> {
12871296

12881297
/// Emit SIL functions for all the members of the extension.
12891298
void emitExtension(ExtensionDecl *e) {
1299+
PrettyStackTraceDecl("silgen emitExtension", e);
1300+
12901301
// Arguably, we should divert to SILGenType::emitType() here if it's an
12911302
// @_objcImplementation extension, but we don't actually need to do any of
12921303
// the stuff that it currently does.
@@ -1309,7 +1320,7 @@ class SILGenExtension : public TypeMemberVisitor<SILGenExtension> {
13091320
for (auto *conformance : e->getLocalConformances(
13101321
ConformanceLookupKind::All)) {
13111322
if (auto *normal =dyn_cast<NormalProtocolConformance>(conformance))
1312-
SGM.getWitnessTable(normal);
1323+
(void)SGM.getWitnessTable(normal);
13131324
}
13141325
}
13151326
}

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: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
// RUN: %target-swift-frontend -emit-silgen %s -parse-as-library -enable-library-evolution -module-name Test -experimental-lazy-typecheck -verify
2+
// RUN: %target-swift-frontend -emit-silgen %s -parse-as-library -enable-library-evolution -module-name Test -experimental-lazy-typecheck -experimental-skip-non-inlinable-function-bodies -verify
3+
// RUN: %target-swift-frontend -emit-silgen %s -parse-as-library -enable-library-evolution -module-name Test -experimental-lazy-typecheck -experimental-skip-non-inlinable-function-bodies -experimental-skip-non-exportable-decls -verify
4+
5+
6+
public protocol Proto {
7+
func req()
8+
}
9+
10+
public struct ConformsToProtoMissingRequirement: Proto {
11+
// expected-error@-1 {{type 'ConformsToProtoMissingRequirement' does not conform to protocol 'Proto'}}
12+
}
13+
14+
public struct ConformsToProtoNearMiss: Proto {
15+
// expected-error@-1 {{type 'ConformsToProtoNearMiss' does not conform to protocol 'Proto'}}
16+
17+
public func req(x: Int) {}
18+
}
19+
20+
public protocol ProtoWithAssociatedType {
21+
associatedtype A
22+
}
23+
24+
public struct ConformsToProtoProtoWithAssociatedType: ProtoWithAssociatedType {
25+
// expected-error@-1 {{type 'ConformsToProtoProtoWithAssociatedType' does not conform to protocol 'ProtoWithAssociatedType'}}
26+
}
27+
28+
public struct GenericStruct<T> {
29+
public var t: T
30+
}
31+
32+
public struct GenericStructWithInvalidParameterConstraint<T: NonExistent> {
33+
// expected-error@-1 {{cannot find type 'NonExistent' in scope}}
34+
}
35+
36+
extension GenericStruct where T == NonExistent {
37+
// expected-error@-1 {{cannot find type 'NonExistent' in scope}}
38+
public func methodInExtensionWithInvalidWhereClause() {}
39+
}
40+
41+
public class ValidClass {
42+
public func methodReturningNonExistentType() -> NonExistent {}
43+
// expected-error@-1 {{cannot find type 'NonExistent' in scope}}
44+
}
45+
46+
public class DerivedFromValidClass: ValidClass {
47+
override public func methodReturningNonExistentType() -> NonExistent {}
48+
// expected-error@-1 {{cannot find type 'NonExistent' in scope}}
49+
}
50+
51+
public class DerivedFromNonExistent: NonExistent {
52+
// expected-error@-1 {{cannot find type 'NonExistent' in scope}}
53+
54+
public func method() {}
55+
}

0 commit comments

Comments
 (0)