Skip to content

Commit b46d179

Browse files
committed
Serialization: Skip patterns with invalid types.
Prevents a crash during module emission with `-enable-lazy-typechecking` when the type of a `Pattern` cannot be resolved.
1 parent 65ea9c8 commit b46d179

File tree

4 files changed

+46
-4
lines changed

4 files changed

+46
-4
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -814,6 +814,9 @@ REMARK(serialization_skipped_invalid_decl,none,
814814
REMARK(serialization_skipped_invalid_type,none,
815815
"serialization skipped for invalid type %0",
816816
(TypeRepr *))
817+
REMARK(serialization_skipped_invalid_type_unknown_name,none,
818+
"serialization skipped for invalid type",
819+
())
817820
ERROR(serialization_failed,none,
818821
"serialization of module %0 failed due to the errors above",
819822
(const ModuleDecl *))

lib/Serialization/Serialization.cpp

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3659,27 +3659,37 @@ class Serializer::DeclSerializer : public DeclVisitor<DeclSerializer> {
36593659
}
36603660
case PatternKind::Named: {
36613661
auto named = cast<NamedPattern>(pattern);
3662+
auto ty = getPatternType();
3663+
if (S.skipTypeIfInvalid(ty, named->getLoc()))
3664+
break;
36623665

36633666
unsigned abbrCode = S.DeclTypeAbbrCodes[NamedPatternLayout::Code];
36643667
NamedPatternLayout::emitRecord(S.Out, S.ScratchRecord, abbrCode,
36653668
S.addDeclRef(named->getDecl()),
3666-
S.addTypeRef(getPatternType()));
3669+
S.addTypeRef(ty));
36673670
break;
36683671
}
36693672
case PatternKind::Any: {
3673+
auto ty = getPatternType();
3674+
if (S.skipTypeIfInvalid(ty, pattern->getLoc()))
3675+
break;
3676+
36703677
unsigned abbrCode = S.DeclTypeAbbrCodes[AnyPatternLayout::Code];
36713678
auto anyPattern = cast<AnyPattern>(pattern);
36723679
AnyPatternLayout::emitRecord(S.Out, S.ScratchRecord, abbrCode,
3673-
S.addTypeRef(getPatternType()),
3680+
S.addTypeRef(ty),
36743681
anyPattern->isAsyncLet());
36753682
break;
36763683
}
36773684
case PatternKind::Typed: {
36783685
auto typed = cast<TypedPattern>(pattern);
3686+
auto ty = getPatternType();
3687+
if (S.skipTypeIfInvalid(ty, typed->getTypeRepr()))
3688+
break;
36793689

36803690
unsigned abbrCode = S.DeclTypeAbbrCodes[TypedPatternLayout::Code];
36813691
TypedPatternLayout::emitRecord(S.Out, S.ScratchRecord, abbrCode,
3682-
S.addTypeRef(getPatternType()));
3692+
S.addTypeRef(ty));
36833693
writePattern(typed->getSubPattern());
36843694
break;
36853695
}
@@ -6813,7 +6823,7 @@ bool Serializer::skipDeclIfInvalid(const Decl *decl) {
68136823
}
68146824

68156825
bool Serializer::skipTypeIfInvalid(Type ty, TypeRepr *tyRepr) {
6816-
if (ty || allowCompilerErrors())
6826+
if ((ty && !ty->hasError()) || allowCompilerErrors())
68176827
return false;
68186828

68196829
if (Options.EnableSerializationRemarks) {
@@ -6825,6 +6835,19 @@ bool Serializer::skipTypeIfInvalid(Type ty, TypeRepr *tyRepr) {
68256835
return true;
68266836
}
68276837

6838+
bool Serializer::skipTypeIfInvalid(Type ty, SourceLoc loc) {
6839+
if ((ty && !ty->hasError()) || allowCompilerErrors())
6840+
return false;
6841+
6842+
if (Options.EnableSerializationRemarks) {
6843+
getASTContext().Diags.diagnose(
6844+
loc, diag::serialization_skipped_invalid_type_unknown_name);
6845+
}
6846+
6847+
hadError = true;
6848+
return true;
6849+
}
6850+
68286851
void serialization::writeToStream(
68296852
raw_ostream &os, ModuleOrSourceFile DC, const SILModule *M,
68306853
const SerializationOptions &options,

lib/Serialization/Serialization.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -583,6 +583,10 @@ class Serializer : public SerializerBase {
583583
/// If the type is invalid, records that an error occurred and returns
584584
/// true if the type should be skipped.
585585
bool skipTypeIfInvalid(Type ty, TypeRepr *tyRepr);
586+
587+
/// If the type is invalid, records that an error occurred and returns
588+
/// true if the type should be skipped.
589+
bool skipTypeIfInvalid(Type ty, SourceLoc loc);
586590
};
587591

588592
} // end namespace serialization

test/Serialization/lazy-typecheck-errors.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,15 @@ public func takesInvalidType(_ x: InvalidType) {}
2020
@InvalidCustomAttr public struct HasInvalidCustomAttr {}
2121
// FIXME: An error should be emitted for the invalid attribute
2222
// expected-serialization-remark@-2 {{serialization skipped for invalid type 'InvalidCustomAttr'}}
23+
24+
public var varWithExplicitInvalidType: InvalidType
25+
// expected-error@-1 {{cannot find type 'InvalidType' in scope}}
26+
// expected-serialization-remark@-2 {{serialization skipped invalid var 'varWithExplicitInvalidType'}}
27+
// expected-serialization-remark@-3 {{serialization skipped for invalid type 'InvalidType'}}
28+
29+
public var varWithImplicitInvalidType = (1 as InvalidType)
30+
// expected-error@-1 {{cannot find type 'InvalidType' in scope}}
31+
// expected-serialization-remark@-2 {{serialization skipped invalid var 'varWithImplicitInvalidType'}}
32+
// expected-serialization-remark@-3 {{serialization skipped for invalid type}}
33+
34+
public var _: InvalidType

0 commit comments

Comments
 (0)