Skip to content

Commit e26c08f

Browse files
authored
Merge pull request #8666 from jrose-apple/more-experimental-deserialization-recovery
More -enable-experimental-deserialization-recovery
2 parents 51e3917 + a2e0e27 commit e26c08f

File tree

10 files changed

+133
-21
lines changed

10 files changed

+133
-21
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -553,6 +553,10 @@ ERROR(serialization_fatal,Fatal,
553553
"fatal error encountered while reading from module '%0'; "
554554
"please file a bug report with your project and the crash log",
555555
(StringRef))
556+
NOTE(serialization_compatibility_version_mismatch,none,
557+
"compiling as Swift %0, with '%1' built as Swift %2 "
558+
"(this is supported but may expose additional compiler issues)",
559+
(StringRef, StringRef, StringRef))
556560

557561
ERROR(reserved_member_name,none,
558562
"type member may not be named %0, since it would conflict with the"

include/swift/Serialization/ModuleFile.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,9 @@ class ModuleFile : public LazyMemberLoader {
7272
/// The target the module was built for.
7373
StringRef TargetTriple;
7474

75+
/// The Swift compatibility version in use when this module was built.
76+
StringRef CompatibilityVersion;
77+
7578
/// The data blob containing all of the module's identifiers.
7679
StringRef IdentifierData;
7780

include/swift/Serialization/ModuleFormat.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,7 @@ namespace control_block {
443443
BCFixed<16>, // Module format major version
444444
BCFixed<16>, // Module format minor version
445445
BCVBR<8>, // length of "short version string" in the blob
446+
BCVBR<8>, // length of "short compatibility version string" in the blob
446447
BCBlob // misc. version information
447448
>;
448449

include/swift/Serialization/Validation.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ struct ValidationInfo {
7171
StringRef name = {};
7272
StringRef targetTriple = {};
7373
StringRef shortVersion = {};
74+
StringRef compatibilityVersion = {};
7475
size_t bytes = 0;
7576
Status status = Status::Malformed;
7677
};

lib/Serialization/Deserialization.cpp

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,17 @@ static bool skipRecord(llvm::BitstreamCursor &cursor, unsigned recordKind) {
344344
void ModuleFile::fatal(llvm::Error error) {
345345
if (FileContext) {
346346
getContext().Diags.diagnose(SourceLoc(), diag::serialization_fatal, Name);
347+
348+
if (!CompatibilityVersion.empty()) {
349+
SmallString<16> buffer;
350+
llvm::raw_svector_ostream out(buffer);
351+
out << getContext().LangOpts.EffectiveLanguageVersion;
352+
if (out.str() != CompatibilityVersion) {
353+
getContext().Diags.diagnose(
354+
SourceLoc(), diag::serialization_compatibility_version_mismatch,
355+
out.str(), Name, CompatibilityVersion);
356+
}
357+
}
347358
}
348359

349360
logAllUnhandledErrors(std::move(error), llvm::errs(),
@@ -1231,9 +1242,7 @@ bool ModuleFile::readMembers(SmallVectorImpl<Decl *> &Members) {
12311242
if (!getContext().LangOpts.EnableDeserializationRecovery)
12321243
fatal(D.takeError());
12331244

1234-
// Silently drop the member if there was a problem.
1235-
// FIXME: This isn't sound for protocols; we need to at least record that
1236-
// it happened.
1245+
// Silently drop the member if it had an override-related problem.
12371246
llvm::handleAllErrors(D.takeError(),
12381247
[](const OverrideError &) { /* expected */ },
12391248
[&](std::unique_ptr<llvm::ErrorInfoBase> unhandled){

lib/Serialization/ModuleFile.cpp

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -193,9 +193,20 @@ validateControlBlock(llvm::BitstreamCursor &cursor,
193193
}
194194
}
195195

196-
// This field was added later; be resilient against its absence.
197-
if (scratch.size() > 2) {
196+
// These fields were added later; be resilient against their absence.
197+
switch (scratch.size()) {
198+
default:
199+
// Add new cases here, in descending order.
200+
case 4:
201+
result.compatibilityVersion = blobData.substr(scratch[2]+1, scratch[3]);
202+
LLVM_FALLTHROUGH;
203+
case 3:
198204
result.shortVersion = blobData.slice(0, scratch[2]);
205+
LLVM_FALLTHROUGH;
206+
case 2:
207+
case 1:
208+
case 0:
209+
break;
199210
}
200211

201212
versionSeen = true;
@@ -932,6 +943,7 @@ ModuleFile::ModuleFile(
932943
}
933944
Name = info.name;
934945
TargetTriple = info.targetTriple;
946+
CompatibilityVersion = info.compatibilityVersion;
935947

936948
hasValidControlBlock = true;
937949
break;

lib/Serialization/Serialization.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -709,10 +709,14 @@ void Serializer::writeHeader(const SerializationOptions &options) {
709709
llvm::raw_svector_ostream versionString(versionStringBuf);
710710
versionString << Version::getCurrentLanguageVersion();
711711
size_t shortVersionStringLength = versionString.tell();
712-
versionString << '/' << version::getSwiftFullVersion(
713-
M->getASTContext().LangOpts.EffectiveLanguageVersion);
712+
versionString << '('
713+
<< M->getASTContext().LangOpts.EffectiveLanguageVersion;
714+
size_t compatibilityVersionStringLength =
715+
versionString.tell() - shortVersionStringLength - 1;
716+
versionString << ")/" << version::getSwiftFullVersion();
714717
Metadata.emit(ScratchRecord,
715718
VERSION_MAJOR, VERSION_MINOR, shortVersionStringLength,
719+
compatibilityVersionStringLength,
716720
versionString.str());
717721

718722
Target.emit(ScratchRecord, M->getASTContext().LangOpts.Target.str());
@@ -772,7 +776,7 @@ void Serializer::writeDocHeader() {
772776
auto& LangOpts = M->getASTContext().LangOpts;
773777
Metadata.emit(ScratchRecord,
774778
VERSION_MAJOR, VERSION_MINOR,
775-
/*short version string length*/0,
779+
/*short version string length*/0, /*compatibility length*/0,
776780
version::getSwiftFullVersion(
777781
LangOpts.EffectiveLanguageVersion));
778782

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,35 @@
1-
@interface Base
2-
#ifndef BAD
3-
- (void)method;
1+
@interface Object
2+
- (nonnull instancetype)init;
3+
@end
4+
5+
@interface Base : Object
6+
#if !BAD
7+
- (void)disappearingMethod;
8+
- (nullable id)nullabilityChangeMethod;
9+
- (nonnull id)typeChangeMethod;
10+
#else
11+
//- (void)disappearingMethod;
12+
- (nonnull id)nullabilityChangeMethod;
13+
- (nonnull Base *)typeChangeMethod;
14+
#endif
15+
@end
16+
17+
@interface Base (ExtraMethodsToTriggerCircularReferences)
18+
#if !BAD
19+
- (void)disappearingMethodWithOverload;
20+
#else
21+
//- (void)disappearingMethodWithOverload;
22+
#endif
23+
@end
24+
25+
@interface GenericBase<Element>: Object
26+
#if !BAD
27+
- (void)disappearingMethod;
28+
- (nullable Element)nullabilityChangeMethod;
29+
- (nonnull id)typeChangeMethod;
30+
#else
31+
//- (void)disappearingMethod;
32+
- (nonnull Element)nullabilityChangeMethod;
33+
- (nonnull Element)typeChangeMethod;
434
#endif
535
@end
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// RUN: rm -rf %t && mkdir -p %t
2+
// RUN: %target-swift-frontend -emit-module -o %t -module-name Lib -I %S/Inputs/custom-modules -swift-version 3 %s
3+
4+
// RUN: not --crash %target-swift-ide-test -source-filename=x -print-module -module-to-print Lib -I %t -I %S/Inputs/custom-modules -swift-version 3 -Xcc -DBAD 2>&1 | %FileCheck -check-prefix CHECK-CRASH -check-prefix CHECK-CRASH-3 %s
5+
// RUN: not --crash %target-swift-ide-test -source-filename=x -print-module -module-to-print Lib -I %t -I %S/Inputs/custom-modules -swift-version 4 -Xcc -DBAD 2>&1 | %FileCheck -check-prefix CHECK-CRASH -check-prefix CHECK-CRASH-4 %s
6+
7+
// REQUIRES: objc_interop
8+
9+
import Overrides
10+
11+
public class Sub: Base {
12+
public override func disappearingMethod() {}
13+
}
14+
15+
// CHECK-CRASH: error: fatal error encountered while reading from module 'Lib'; please file a bug report with your project and the crash log
16+
// CHECK-CRASH-3-NOT: note
17+
// CHECK-CRASH-4: note: compiling as Swift 4.0, with 'Lib' built as Swift 3.1
18+
// CHECK-CRASH-LABEL: *** DESERIALIZATION FAILURE (please include this section in any bug report) ***
19+
// CHECK-CRASH: could not find 'disappearingMethod()' in parent class
20+
// CHECK-CRASH: While loading members for 'Sub' in module 'Lib'

test/Serialization/Recovery/overrides.swift

Lines changed: 38 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,25 +3,53 @@
33

44
// RUN: %target-swift-ide-test -source-filename=x -print-module -module-to-print Lib -I %t -I %S/Inputs/custom-modules | %FileCheck %s
55

6-
// RUN: not --crash %target-swift-ide-test -source-filename=x -print-module -module-to-print Lib -I %t -I %S/Inputs/custom-modules -Xcc -DBAD 2>&1 | %FileCheck -check-prefix CHECK-CRASH %s
76
// RUN: %target-swift-ide-test -source-filename=x -print-module -module-to-print Lib -I %t -I %S/Inputs/custom-modules -Xcc -DBAD -enable-experimental-deserialization-recovery | %FileCheck -check-prefix CHECK-RECOVERY %s
87

98
// REQUIRES: objc_interop
109

1110
import Overrides
1211

13-
public class Sub: Base {
14-
public override func method() {}
12+
// Please use prefixes to keep the printed parts of this file in alphabetical
13+
// order.
14+
15+
public class SwiftOnlyClass {}
16+
17+
public class A_Sub: Base {
18+
public override func disappearingMethod() {}
19+
public override func nullabilityChangeMethod() -> Any? { return nil }
20+
public override func typeChangeMethod() -> Any { return self }
21+
public override func disappearingMethodWithOverload() {}
1522
}
1623

17-
// CHECK-LABEL: class Sub : Base {
18-
// CHECK-NEXT: func method()
24+
// CHECK-LABEL: class A_Sub : Base {
25+
// CHECK-NEXT: func disappearingMethod()
26+
// CHECK-NEXT: func nullabilityChangeMethod() -> Any?
27+
// CHECK-NEXT: func typeChangeMethod() -> Any
28+
// CHECK-NEXT: func disappearingMethodWithOverload()
29+
// CHECK-NEXT: init()
1930
// CHECK-NEXT: {{^}$}}
2031

21-
// CHECK-CRASH: error: fatal error encountered while reading from module 'Lib'; please file a bug report with your project and the crash log
22-
// CHECK-CRASH-LABEL: *** DESERIALIZATION FAILURE (please include this section in any bug report) ***
23-
// CHECK-CRASH: could not find 'method()' in parent class
24-
// CHECK-CRASH: While loading members for 'Sub' in module 'Lib'
32+
// CHECK-RECOVERY-LABEL: class A_Sub : Base {
33+
// CHECK-RECOVERY-NEXT: init()
34+
// CHECK-RECOVERY-NEXT: {{^}$}}
35+
36+
extension Base {
37+
@nonobjc func disappearingMethodWithOverload() -> SwiftOnlyClass? { return nil }
38+
}
39+
40+
public class B_GenericSub : GenericBase<Base> {
41+
public override func disappearingMethod() {}
42+
public override func nullabilityChangeMethod() -> Base? { return nil }
43+
public override func typeChangeMethod() -> Any { return self }
44+
}
45+
46+
// CHECK-LABEL: class B_GenericSub : GenericBase<Base> {
47+
// CHECK-NEXT: func disappearingMethod()
48+
// CHECK-NEXT: func nullabilityChangeMethod() -> Base?
49+
// CHECK-NEXT: func typeChangeMethod() -> Any
50+
// CHECK-NEXT: init()
51+
// CHECK-NEXT: {{^}$}}
2552

26-
// CHECK-RECOVERY-LABEL: class Sub : Base {
53+
// CHECK-RECOVERY-LABEL: class B_GenericSub : GenericBase<Base> {
54+
// CHECK-RECOVERY-NEXT: init()
2755
// CHECK-RECOVERY-NEXT: {{^}$}}

0 commit comments

Comments
 (0)