Skip to content

Commit 483b569

Browse files
committed
[NCGenerics] trigger module mismatch
A swiftmodule can only be correctly ingested by a compiler that has a matching state of using or not-using NoncopyableGenerics. The reason for this is fundamental: the absence of a Copyable conformance in the swiftmodule indicates that a type is noncopyable. Thus, if a compiler with NoncopyableGenerics reads a swiftmodule that was not compiled with that feature, it will think every type in that module is noncopyable. Similarly, if a compiler with NoncopyableGenerics produces a swiftmodule, there will be Copyable requirements on each generic parameter that the compiler without the feature will become confused about. The solution here is to trigger a module mismatch, so that the compiler re-generates the swiftmodule file using the swiftinterface, which has been kept compatible with the compiler regardless of whether the feature is enabled.
1 parent 54dff6f commit 483b569

21 files changed

+323
-67
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -863,6 +863,9 @@ ERROR(serialization_target_too_new_repl,none,
863863
"deployment target of %0 %3: %4",
864864
(StringRef, llvm::VersionTuple, Identifier, llvm::VersionTuple,
865865
StringRef))
866+
ERROR(serialization_noncopyable_generics_mismatch,none,
867+
"module %0 was not compiled with NoncopyableGenerics",
868+
(Identifier))
866869

867870
ERROR(serialization_fatal,Fatal,
868871
"fatal error encountered while reading from module '%0'; "

include/swift/Frontend/ModuleInterfaceLoader.h

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -487,6 +487,19 @@ struct RequireOSSAModules_t {
487487
explicit operator bool() const { return bool(value); }
488488
};
489489

490+
/// Help prevent confusion between different bools being passed around.
491+
struct RequireNoncopyableGenerics_t {
492+
private:
493+
bool value;
494+
public:
495+
RequireNoncopyableGenerics_t(const ASTContext &ctx)
496+
: RequireNoncopyableGenerics_t(ctx.LangOpts) {}
497+
RequireNoncopyableGenerics_t(const LangOptions &opts)
498+
: value(opts.hasFeature(Feature::NoncopyableGenerics)) {}
499+
500+
explicit operator bool() const { return value; }
501+
};
502+
490503
class ModuleInterfaceCheckerImpl: public ModuleInterfaceChecker {
491504
friend class ModuleInterfaceLoader;
492505
ASTContext &Ctx;
@@ -495,22 +508,26 @@ class ModuleInterfaceCheckerImpl: public ModuleInterfaceChecker {
495508
std::string BackupInterfaceDir;
496509
ModuleInterfaceLoaderOptions Opts;
497510
RequireOSSAModules_t RequiresOSSAModules;
511+
RequireNoncopyableGenerics_t RequireNCGenerics;
498512

499513
public:
500514
explicit ModuleInterfaceCheckerImpl(ASTContext &Ctx, StringRef cacheDir,
501-
StringRef prebuiltCacheDir,
502-
StringRef BackupInterfaceDir,
503-
ModuleInterfaceLoaderOptions opts,
504-
RequireOSSAModules_t requiresOSSAModules)
515+
StringRef prebuiltCacheDir,
516+
StringRef BackupInterfaceDir,
517+
ModuleInterfaceLoaderOptions opts,
518+
RequireOSSAModules_t requiresOSSAModules,
519+
RequireNoncopyableGenerics_t requireNCGenerics)
505520
: Ctx(Ctx), CacheDir(cacheDir), PrebuiltCacheDir(prebuiltCacheDir),
506521
BackupInterfaceDir(BackupInterfaceDir),
507-
Opts(opts), RequiresOSSAModules(requiresOSSAModules) {}
522+
Opts(opts), RequiresOSSAModules(requiresOSSAModules),
523+
RequireNCGenerics(requireNCGenerics) {}
508524
explicit ModuleInterfaceCheckerImpl(ASTContext &Ctx, StringRef cacheDir,
509-
StringRef prebuiltCacheDir,
510-
ModuleInterfaceLoaderOptions opts,
511-
RequireOSSAModules_t requiresOSSAModules):
525+
StringRef prebuiltCacheDir,
526+
ModuleInterfaceLoaderOptions opts,
527+
RequireOSSAModules_t requiresOSSAModules,
528+
RequireNoncopyableGenerics_t requireNCGenerics):
512529
ModuleInterfaceCheckerImpl(Ctx, cacheDir, prebuiltCacheDir, StringRef(),
513-
opts, requiresOSSAModules) {}
530+
opts, requiresOSSAModules, requireNCGenerics) {}
514531
std::vector<std::string>
515532
getCompiledModuleCandidatesForInterface(StringRef moduleName,
516533
StringRef interfacePath) override;
@@ -586,6 +603,7 @@ class ModuleInterfaceLoader : public SerializedModuleLoaderBase {
586603
bool SerializeDependencyHashes,
587604
bool TrackSystemDependencies, ModuleInterfaceLoaderOptions Opts,
588605
RequireOSSAModules_t RequireOSSAModules,
606+
RequireNoncopyableGenerics_t RequireNCGenerics,
589607
bool silenceInterfaceDiagnostics);
590608

591609
/// Unconditionally build \p InPath (a swiftinterface file) to \p OutPath (as
@@ -640,7 +658,8 @@ struct InterfaceSubContextDelegateImpl: InterfaceSubContextDelegate {
640658
const LangOptions &LangOpts,
641659
const ClangImporterOptions &clangImporterOpts,
642660
bool suppressRemarks,
643-
RequireOSSAModules_t requireOSSAModules);
661+
RequireOSSAModules_t requireOSSAModules,
662+
RequireNoncopyableGenerics_t requireNCGenerics);
644663
bool extractSwiftInterfaceVersionAndArgs(CompilerInvocation &subInvocation,
645664
SwiftInterfaceInfo &interfaceInfo,
646665
StringRef interfacePath,
@@ -654,7 +673,8 @@ struct InterfaceSubContextDelegateImpl: InterfaceSubContextDelegate {
654673
StringRef moduleCachePath, StringRef prebuiltCachePath,
655674
StringRef backupModuleInterfaceDir,
656675
bool serializeDependencyHashes, bool trackSystemDependencies,
657-
RequireOSSAModules_t requireOSSAModules);
676+
RequireOSSAModules_t requireOSSAModules,
677+
RequireNoncopyableGenerics_t requireNCGenerics);
658678

659679
template<typename ...ArgTypes>
660680
static InFlightDiagnostic diagnose(StringRef interfacePath,

include/swift/Serialization/SerializedModuleLoader.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ class SerializedModuleLoaderBase : public ModuleLoader {
176176
ModuleLoadingBehavior transitiveBehavior,
177177
bool isFramework,
178178
bool isRequiredOSSAModules,
179+
bool isRequiredNoncopyableGenerics,
179180
StringRef SDKName,
180181
StringRef packageName,
181182
llvm::vfs::FileSystem *fileSystem,
@@ -205,6 +206,7 @@ class SerializedModuleLoaderBase : public ModuleLoader {
205206
bool isFramework);
206207

207208
bool isRequiredOSSAModules() const;
209+
bool isRequiredNoncopyableGenerics() const;
208210

209211
/// Check whether the module with a given name can be imported without
210212
/// importing it.

include/swift/Serialization/Validation.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,11 @@ enum class Status {
8282

8383
/// The module file was built with a different SDK than the one in use
8484
/// to build the client.
85-
SDKMismatch
85+
SDKMismatch,
86+
87+
/// The module file was not built with support for NoncopyableGenerics,
88+
/// yet that is required to by this compiler.
89+
NotUsingNoncopyableGenerics,
8690
};
8791

8892
/// Returns the string for the Status enum.
@@ -249,6 +253,8 @@ struct SearchPath {
249253
/// refers directly into this buffer.
250254
/// \param requiresOSSAModules If true, necessitates the module to be
251255
/// compiled with -enable-ossa-modules.
256+
/// \param requiresNoncopyableGenerics requires the module to have been built
257+
/// with the feature \c NoncopyableGenerics enabled.
252258
/// \param requiredSDK If not empty, only accept modules built with
253259
/// a compatible SDK. The StringRef represents the canonical SDK name.
254260
/// \param[out] extendedInfo If present, will be populated with additional
@@ -257,7 +263,8 @@ struct SearchPath {
257263
/// \param[out] dependencies If present, will be populated with list of
258264
/// input files the module depends on, if present in INPUT_BLOCK.
259265
ValidationInfo validateSerializedAST(
260-
StringRef data, bool requiresOSSAModules, StringRef requiredSDK,
266+
StringRef data, bool requiresOSSAModules, bool requiresNoncopyableGenerics,
267+
StringRef requiredSDK,
261268
ExtendedValidationInfo *extendedInfo = nullptr,
262269
SmallVectorImpl<SerializationOptions::FileDependency> *dependencies =
263270
nullptr,

lib/ASTSectionImporter/ASTSectionImporter.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,9 @@ swift::parseASTSection(MemoryBufferSerializedModuleLoader &Loader,
5757
// headers. Iterate over all AST modules.
5858
while (!buf.empty()) {
5959
auto info = serialization::validateSerializedAST(
60-
buf, Loader.isRequiredOSSAModules(), /*requiredSDK*/StringRef());
60+
buf, Loader.isRequiredOSSAModules(),
61+
Loader.isRequiredNoncopyableGenerics(),
62+
/*requiredSDK*/StringRef());
6163

6264
assert(info.name.size() < (2 << 10) && "name failed sanity check");
6365

lib/DependencyScan/ModuleDependencyScanner.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,8 @@ ModuleDependencyScanningWorker::ModuleDependencyScanningWorker(
161161
/*buildModuleCacheDirIfAbsent*/ false, ClangModuleCachePath,
162162
FEOpts.PrebuiltModuleCachePath, FEOpts.BackupModuleInterfaceDir,
163163
FEOpts.SerializeModuleInterfaceDependencyHashes,
164-
FEOpts.shouldTrackSystemDependencies(), RequireOSSAModules_t(SILOptions));
164+
FEOpts.shouldTrackSystemDependencies(), RequireOSSAModules_t(SILOptions),
165+
RequireNoncopyableGenerics_t(ScanASTContext));
165166

166167
// Set up the Clang importer.
167168
clangScannerModuleLoader = ClangImporter::create(

lib/Frontend/CompilerInvocation.cpp

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3247,8 +3247,13 @@ bool CompilerInvocation::parseArgs(
32473247
serialization::Status
32483248
CompilerInvocation::loadFromSerializedAST(StringRef data) {
32493249
serialization::ExtendedValidationInfo extendedInfo;
3250-
serialization::ValidationInfo info = serialization::validateSerializedAST(
3251-
data, getSILOptions().EnableOSSAModules, LangOpts.SDKName, &extendedInfo);
3250+
serialization::ValidationInfo info =
3251+
serialization::validateSerializedAST(
3252+
data,
3253+
getSILOptions().EnableOSSAModules,
3254+
LangOpts.hasFeature(Feature::NoncopyableGenerics),
3255+
LangOpts.SDKName,
3256+
&extendedInfo);
32523257

32533258
if (info.status != serialization::Status::Valid)
32543259
return info.status;
@@ -3283,8 +3288,11 @@ CompilerInvocation::setUpInputForSILTool(
32833288
InputFile(inputFilename, bePrimary, fileBufOrErr.get().get(), file_types::TY_SIL));
32843289

32853290
auto result = serialization::validateSerializedAST(
3286-
fileBufOrErr.get()->getBuffer(), getSILOptions().EnableOSSAModules,
3287-
LangOpts.SDKName, &extendedInfo);
3291+
fileBufOrErr.get()->getBuffer(),
3292+
getSILOptions().EnableOSSAModules,
3293+
LangOpts.hasFeature(Feature::NoncopyableGenerics),
3294+
LangOpts.SDKName,
3295+
&extendedInfo);
32883296
bool hasSerializedAST = result.status == serialization::Status::Valid;
32893297

32903298
if (hasSerializedAST) {

lib/Frontend/Frontend.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -774,7 +774,8 @@ bool CompilerInstance::setUpModuleLoaders() {
774774
std::make_unique<ModuleInterfaceCheckerImpl>(
775775
*Context, ModuleCachePath, FEOpts.PrebuiltModuleCachePath,
776776
FEOpts.BackupModuleInterfaceDir, LoaderOpts,
777-
RequireOSSAModules_t(Invocation.getSILOptions())));
777+
RequireOSSAModules_t(Invocation.getSILOptions()),
778+
RequireNoncopyableGenerics_t(Invocation.getLangOptions())));
778779

779780
// Install an explicit module loader if it was created earlier.
780781
if (ESML) {
@@ -815,7 +816,8 @@ bool CompilerInstance::setUpModuleLoaders() {
815816
FEOpts.PrebuiltModuleCachePath, FEOpts.BackupModuleInterfaceDir,
816817
FEOpts.SerializeModuleInterfaceDependencyHashes,
817818
FEOpts.shouldTrackSystemDependencies(),
818-
RequireOSSAModules_t(Invocation.getSILOptions()));
819+
RequireOSSAModules_t(Invocation.getSILOptions()),
820+
RequireNoncopyableGenerics_t(Invocation.getLangOptions()));
819821
auto mainModuleName = Context->getIdentifier(FEOpts.ModuleName);
820822
std::unique_ptr<PlaceholderSwiftModuleScanner> PSMS =
821823
std::make_unique<PlaceholderSwiftModuleScanner>(
@@ -1495,8 +1497,8 @@ bool CompilerInstance::loadStdlibIfNeeded() {
14951497

14961498
// If we failed to load, we should have already diagnosed.
14971499
if (M->failedToLoad()) {
1498-
assert(Diagnostics.hadAnyError() &&
1499-
"Module failed to load but nothing was diagnosed?");
1500+
// assert(Diagnostics.hadAnyError() &&
1501+
// "Module failed to load but nothing was diagnosed?");
15001502
return true;
15011503
}
15021504
return false;

0 commit comments

Comments
 (0)