Skip to content

Commit 6575431

Browse files
committed
[ModuleInterface] Version string (semi)finalization, format version checking.
1 parent c6ac386 commit 6575431

File tree

5 files changed

+62
-10
lines changed

5 files changed

+62
-10
lines changed

include/swift/AST/DiagnosticsFrontend.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,9 @@ WARNING(parseable_interface_scoped_import_unsupported,none,
265265
())
266266
ERROR(error_extracting_version_from_parseable_interface,none,
267267
"error extracting version from parseable module interface", ())
268+
ERROR(unsupported_version_of_parseable_interface,none,
269+
"unsupported version of parseable module interface '%0': '%1'",
270+
(StringRef, llvm::VersionTuple))
268271
ERROR(error_extracting_flags_from_parseable_interface,none,
269272
"error extracting flags from parseable module interface", ())
270273
ERROR(missing_dependency_of_parseable_module_interface,none,

include/swift/Frontend/ParseableInterfaceSupport.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ struct ParseableInterfaceOptions {
2929
std::string ParseableInterfaceFlags;
3030
};
3131

32-
llvm::Regex getSwiftInterfaceToolsVersionRegex();
32+
llvm::Regex getSwiftInterfaceFormatVersionRegex();
3333
llvm::Regex getSwiftInterfaceModuleFlagsRegex();
3434

3535
/// Emit a stable, parseable interface for \p M, which can be used by a client

lib/Frontend/ParseableInterfaceSupport.cpp

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,12 @@
3939
using namespace swift;
4040
using FileDependency = SerializationOptions::FileDependency;
4141

42+
#define SWIFT_INTERFACE_FORMAT_VERSION_KEY "swift-interface-format-version"
4243
#define SWIFT_TOOLS_VERSION_KEY "swift-tools-version"
4344
#define SWIFT_MODULE_FLAGS_KEY "swift-module-flags"
4445

46+
static swift::version::Version InterfaceFormatVersion({1, 0});
47+
4548
static bool
4649
extractSwiftInterfaceVersionAndArgs(DiagnosticEngine &Diags,
4750
clang::vfs::FileSystem &FS,
@@ -56,7 +59,7 @@ extractSwiftInterfaceVersionAndArgs(DiagnosticEngine &Diags,
5659
return true;
5760
}
5861
auto SB = FileOrError.get()->getBuffer();
59-
auto VersRe = getSwiftInterfaceToolsVersionRegex();
62+
auto VersRe = getSwiftInterfaceFormatVersionRegex();
6063
auto FlagRe = getSwiftInterfaceModuleFlagsRegex();
6164
SmallVector<StringRef, 1> VersMatches, FlagMatches;
6265
if (!VersRe.match(SB, &VersMatches)) {
@@ -286,6 +289,17 @@ static bool buildSwiftModuleFromSwiftInterface(
286289
return;
287290
}
288291

292+
// For now: we support anything with the same "major version" and assume
293+
// minor versions might be interesting for debugging, or special-casing a
294+
// compatible field variant.
295+
if (Vers.asMajorVersion() != InterfaceFormatVersion.asMajorVersion()) {
296+
Diags.diagnose(SourceLoc(),
297+
diag::unsupported_version_of_parseable_interface,
298+
InPath, Vers);
299+
SubError = true;
300+
return;
301+
}
302+
289303
if (SubInvocation.parseArgs(SubArgs, Diags)) {
290304
SubError = true;
291305
return;
@@ -415,21 +429,26 @@ static void diagnoseScopedImports(DiagnosticEngine &diags,
415429
}
416430
}
417431

418-
/// Prints to \p out a comment containing a tool-versions identifier as well
419-
/// as any relevant command-line flags in \p Opts used to construct \p M.
432+
/// Prints to \p out a comment containing a format version number, tool version
433+
/// string as well as any relevant command-line flags in \p Opts used to
434+
/// construct \p M.
420435
static void printToolVersionAndFlagsComment(raw_ostream &out,
421436
ParseableInterfaceOptions const &Opts,
422437
ModuleDecl *M) {
423438
auto &Ctx = M->getASTContext();
439+
auto ToolsVersion = swift::version::getSwiftFullVersion(
440+
Ctx.LangOpts.EffectiveLanguageVersion);
441+
out << "// " SWIFT_INTERFACE_FORMAT_VERSION_KEY ": "
442+
<< InterfaceFormatVersion << "\n";
424443
out << "// " SWIFT_TOOLS_VERSION_KEY ": "
425-
<< Ctx.LangOpts.EffectiveLanguageVersion << "\n";
444+
<< ToolsVersion << "\n";
426445
out << "// " SWIFT_MODULE_FLAGS_KEY ": "
427446
<< Opts.ParseableInterfaceFlags << "\n";
428447
}
429448

430-
llvm::Regex swift::getSwiftInterfaceToolsVersionRegex() {
431-
return llvm::Regex("^// " SWIFT_TOOLS_VERSION_KEY ": ([0-9\\.]+)$",
432-
llvm::Regex::Newline);
449+
llvm::Regex swift::getSwiftInterfaceFormatVersionRegex() {
450+
return llvm::Regex("^// " SWIFT_INTERFACE_FORMAT_VERSION_KEY
451+
": ([0-9\\.]+)$", llvm::Regex::Newline);
433452
}
434453

435454
llvm::Regex swift::getSwiftInterfaceModuleFlagsRegex() {
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %empty-directory(%t/modulecache)
3+
//
4+
// Test will build a module TestModule that depends LeafModule (built from leaf.swift).
5+
//
6+
// RUN: echo 'public func LeafFunc() -> Int { return 10; }' >%t/leaf.swift
7+
//
8+
// RUN: %target-swift-frontend -I %t -emit-parseable-module-interface-path %t/LeafModule.swiftinterface -module-name LeafModule %t/leaf.swift -emit-module -o /dev/null
9+
// RUN: test -f %t/LeafModule.swiftinterface
10+
// RUN: %FileCheck %s -check-prefix=CHECK-LEAFINTERFACE <%t/LeafModule.swiftinterface
11+
// CHECK-LEAFINTERFACE: {{swift-interface-format-version: [0-9\\.]+}}
12+
// CHECK-LEAFINTERFACE: LeafFunc
13+
//
14+
// Break LeafModule's version number
15+
// RUN: sed -i.prev -e 's/swift-interface-format-version:.*/swift-interface-format-version: 9999.999/' %t/LeafModule.swiftinterface
16+
//
17+
// Try to build TestModule into a .swiftmodule explicitly using LeafModule via LeafModule.swiftinterface, but fail because version mismatch in LeafModule.swiftinterface.
18+
//
19+
// RUN: not %target-swift-frontend -I %t -module-cache-path %t/modulecache -enable-parseable-module-interface -emit-module -o %t/TestModule.swiftmodule -module-name TestModule %s >%t/err.txt 2>&1
20+
// RUN: test ! -f %t/TestModule.swiftmodule
21+
// RUN: test ! -f %t/modulecache/LeafModule-*.swiftmodule
22+
// RUN: %FileCheck %s -check-prefix=CHECK-ERR <%t/err.txt
23+
// CHECK-ERR: {{error: unsupported version of parseable module interface '.*/LeafModule.swiftinterface': '9999.999'}}
24+
// CHECK-ERR: error: no such module 'LeafModule
25+
26+
import LeafModule
27+
28+
public func TestFunc() {
29+
print(LeafFunc())
30+
}

test/ParseableInterface/ModuleCache/module-cache-diagnostics.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,8 @@
5454
// RUN: not %target-swift-frontend -I %t -module-cache-path %t/modulecache -enable-parseable-module-interface -emit-module -o %t/TestModule.swiftmodule -module-name TestModule %s >%t/err.txt 2>&1
5555
// RUN: %S/Inputs/check-is-old.py %t/modulecache/OtherModule-*.swiftmodule %t/modulecache/LeafModule-*.swiftmodule
5656
// RUN: %FileCheck %s -check-prefix=CHECK-ERROR <%t/err.txt
57-
// CHECK-ERROR: LeafModule.swiftinterface:5:8: error: no such module 'NotAModule'
58-
// CHECK-ERROR: OtherModule.swiftinterface:3:8: error: no such module 'LeafModule'
57+
// CHECK-ERROR: LeafModule.swiftinterface:6:8: error: no such module 'NotAModule'
58+
// CHECK-ERROR: OtherModule.swiftinterface:4:8: error: no such module 'LeafModule'
5959
//
6060
//
6161
// Next test: same as above, but with a .dia file

0 commit comments

Comments
 (0)