Skip to content

Commit 449e5ec

Browse files
committed
[Serialization] Give swiftdocs a stable version
We're committing to this as a forwards-compatible format, and in most cases probably backwards-compatible as well!
1 parent f3ea8bd commit 449e5ec

File tree

12 files changed

+87
-9
lines changed

12 files changed

+87
-9
lines changed

include/swift/Serialization/ModuleFile.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -631,6 +631,9 @@ class ModuleFile
631631
theModule.reset(new ModuleFile(std::move(moduleInputBuffer),
632632
std::move(moduleDocInputBuffer),
633633
isFramework, info, extInfo));
634+
assert(info.status == Status::Valid ||
635+
info.status == theModule->getStatus());
636+
info.status = theModule->getStatus();
634637
return info;
635638
}
636639

lib/Serialization/DocFormat.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,26 @@ using llvm::BCVBR;
3333
/// Magic number for serialized documentation files.
3434
const unsigned char SWIFTDOC_SIGNATURE[] = { 0xE2, 0x9C, 0xA8, 0x07 };
3535

36+
/// Serialized swiftdoc format major version number.
37+
///
38+
/// Increment this value when making a backwards-incompatible change, which
39+
/// should be rare. When incrementing this value, reset SWIFTDOC_VERSION_MINOR
40+
/// to 0.
41+
const uint16_t SWIFTDOC_VERSION_MAJOR = 1;
42+
43+
/// Serialized swiftdoc format minor version number.
44+
///
45+
/// Increment this value when making a backwards-compatible change that might
46+
/// be interesting to test for. However, if old swiftdoc files are fully
47+
/// compatible with the new change, you do not need to increment this.
48+
///
49+
/// To ensure that two separate changes don't silently get merged into one
50+
/// in source control, you should also update the comment to briefly
51+
/// describe what change you made. The content of this comment isn't important;
52+
/// it just ensures a conflict if two people change the module format.
53+
/// Don't worry about adhering to the 80-column limit for this line.
54+
const uint16_t SWIFTDOC_VERSION_MINOR = 1; // Last change: skipping 0 for testing purposes
55+
3656
/// The record types within the comment block.
3757
///
3858
/// Be very careful when changing this block; it must remain stable. Adding new

lib/Serialization/ModuleFile.cpp

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ static bool readOptionsBlock(llvm::BitstreamCursor &cursor,
129129
static ValidationInfo
130130
validateControlBlock(llvm::BitstreamCursor &cursor,
131131
SmallVectorImpl<uint64_t> &scratch,
132+
std::pair<uint16_t, uint16_t> expectedVersion,
132133
ExtendedValidationInfo *extendedInfo) {
133134
// The control block is malformed until we've at least read a major version
134135
// number.
@@ -174,18 +175,18 @@ validateControlBlock(llvm::BitstreamCursor &cursor,
174175
}
175176

176177
uint16_t versionMajor = scratch[0];
177-
if (versionMajor > SWIFTMODULE_VERSION_MAJOR)
178+
if (versionMajor > expectedVersion.first)
178179
result.status = Status::FormatTooNew;
179-
else if (versionMajor < SWIFTMODULE_VERSION_MAJOR)
180+
else if (versionMajor < expectedVersion.first)
180181
result.status = Status::FormatTooOld;
181182
else
182183
result.status = Status::Valid;
183184

184185
// Major version 0 does not have stable minor versions.
185186
if (versionMajor == 0) {
186187
uint16_t versionMinor = scratch[1];
187-
if (versionMinor != SWIFTMODULE_VERSION_MINOR) {
188-
if (versionMinor < SWIFTMODULE_VERSION_MINOR)
188+
if (versionMinor != expectedVersion.second) {
189+
if (versionMinor < expectedVersion.second)
189190
result.status = Status::FormatTooOld;
190191
else
191192
result.status = Status::FormatTooNew;
@@ -263,7 +264,10 @@ ValidationInfo serialization::validateSerializedAST(
263264

264265
if (topLevelEntry.ID == CONTROL_BLOCK_ID) {
265266
cursor.EnterSubBlock(CONTROL_BLOCK_ID);
266-
result = validateControlBlock(cursor, scratch, extendedInfo);
267+
result = validateControlBlock(cursor, scratch,
268+
{SWIFTMODULE_VERSION_MAJOR,
269+
SWIFTMODULE_VERSION_MINOR},
270+
extendedInfo);
267271
if (result.status == Status::Malformed)
268272
return result;
269273
} else {
@@ -1106,7 +1110,10 @@ bool ModuleFile::readModuleDocIfPresent() {
11061110
case CONTROL_BLOCK_ID: {
11071111
docCursor.EnterSubBlock(CONTROL_BLOCK_ID);
11081112

1109-
info = validateControlBlock(docCursor, scratch, /*extendedInfo*/nullptr);
1113+
info = validateControlBlock(docCursor, scratch,
1114+
{SWIFTDOC_VERSION_MAJOR,
1115+
SWIFTDOC_VERSION_MINOR},
1116+
/*extendedInfo*/nullptr);
11101117
if (info.status != Status::Valid)
11111118
return false;
11121119
// Check that the swiftdoc is actually for this module.
@@ -1174,7 +1181,10 @@ ModuleFile::ModuleFile(
11741181
case CONTROL_BLOCK_ID: {
11751182
cursor.EnterSubBlock(CONTROL_BLOCK_ID);
11761183

1177-
info = validateControlBlock(cursor, scratch, extInfo);
1184+
info = validateControlBlock(cursor, scratch,
1185+
{SWIFTMODULE_VERSION_MAJOR,
1186+
SWIFTMODULE_VERSION_MINOR},
1187+
extInfo);
11781188
if (info.status != Status::Valid) {
11791189
error(info.status);
11801190
return;

lib/Serialization/SerializeDoc.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -472,8 +472,7 @@ void DocSerializer::writeDocHeader() {
472472
control_block::TargetLayout Target(Out);
473473

474474
auto& LangOpts = M->getASTContext().LangOpts;
475-
Metadata.emit(ScratchRecord,
476-
SWIFTMODULE_VERSION_MAJOR, SWIFTMODULE_VERSION_MINOR,
475+
Metadata.emit(ScratchRecord, SWIFTDOC_VERSION_MAJOR, SWIFTDOC_VERSION_MINOR,
477476
/*short version string length*/0, /*compatibility length*/0,
478477
version::getSwiftFullVersion(
479478
LangOpts.EffectiveLanguageVersion));
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-swift-frontend -emit-module -o %t %S/../Inputs/empty.swift
3+
// RUN: %target-swift-frontend -typecheck -I %t %s
4+
5+
// RUN: touch %t/empty.swiftdoc
6+
// RUN: %target-swift-frontend -typecheck -I %t %s -verify -show-diagnostics-after-fatal
7+
8+
// RUN: echo -n 'a' > %t/empty.swiftdoc
9+
// RUN: %target-swift-frontend -typecheck -I %t %s -verify -show-diagnostics-after-fatal
10+
11+
// RUN: echo -n 'abcd' > %t/empty.swiftdoc
12+
// RUN: %target-swift-frontend -typecheck -I %t %s -verify -show-diagnostics-after-fatal
13+
14+
// RUN: echo -n 'abcde' > %t/empty.swiftdoc
15+
// RUN: %target-swift-frontend -typecheck -I %t %s -verify -show-diagnostics-after-fatal
16+
17+
import empty // expected-error{{malformed module file}}

0 commit comments

Comments
 (0)