Repair Fingerprint Lookup Across Modules

Cross-module incremental builds require a stable source of fingerprint
information for iterable decl contexts. This is provided by the
incremental frontends when they produce partial swift module files.
Embedded in these files is a table of fingerprints, which are consumed
by merge-modules to construct a module-wide dependency graph that is
then serialized into the final merged swift module file. Unfortunately,
the implementation here iterated through the files in the module and
asked for the first fingerprint that would load for a particular
iterable decl context. If (more likely, when) the DeclID for that
serialized iterable decl context collided with another DeclID in the
wrong file, we would load that fingerprint instead.

Locate up to the module-scope context for an iterable decl context and
only load the fingerprint from there. This ensures that the fingerprints
in the partial modules matches the fingerprints in the merged modules.

rdar://77005039
This commit is contained in:
Robert Widmann
2021-04-27 17:44:55 -07:00
parent 5900a0fdac
commit 43a9f54b0f
6 changed files with 45 additions and 14 deletions

View File

@@ -594,9 +594,6 @@ public:
ObjCSelector selector,
SmallVectorImpl<AbstractFunctionDecl *> &results) const;
Optional<Fingerprint>
loadFingerprint(const IterableDeclContext *IDC) const;
/// Find all SPI names imported from \p importedModule by this module,
/// collecting the identifiers in \p spiGroups.
void lookupImportedSPIGroups(

View File

@@ -680,15 +680,6 @@ void ModuleDecl::lookupObjCMethods(
FORWARD(lookupObjCMethods, (selector, results));
}
Optional<Fingerprint>
ModuleDecl::loadFingerprint(const IterableDeclContext *IDC) const {
for (auto file : getFiles()) {
if (auto FP = file->loadFingerprint(IDC))
return FP;
}
return None;
}
void ModuleDecl::lookupImportedSPIGroups(
const ModuleDecl *importedModule,
llvm::SmallSetVector<Identifier, 4> &spiGroups) const {

View File

@@ -52,6 +52,8 @@ ParseMembersRequest::evaluate(Evaluator &evaluator,
IterableDeclContext *idc) const {
SourceFile *sf = idc->getAsGenericContext()->getParentSourceFile();
ASTContext &ctx = idc->getDecl()->getASTContext();
auto fileUnit
= dyn_cast<FileUnit>(idc->getAsGenericContext()->getModuleScopeContext());
if (!sf) {
// If there is no parent source file, this is a deserialized or synthesized
// declaration context, in which case `getMembers()` has all of the members.
@@ -64,8 +66,8 @@ ParseMembersRequest::evaluate(Evaluator &evaluator,
}
Optional<Fingerprint> fp = None;
if (!idc->getDecl()->isImplicit()) {
fp = idc->getDecl()->getModuleContext()->loadFingerprint(idc);
if (!idc->getDecl()->isImplicit() && fileUnit) {
fp = fileUnit->loadFingerprint(idc);
}
return FingerprintAndMembers{fp, ctx.AllocateCopy(members)};
}

View File

@@ -0,0 +1,5 @@
public final class ClsA {
public static func doit(value: Bool = true) {
print("value: \(value)")
}
}

View File

@@ -0,0 +1,5 @@
public final class ClsA {
public static func doit(value: Bool = false) {
print("value: \(value)")
}
}

View File

@@ -0,0 +1,31 @@
// RUN: %empty-directory(%t)
// RUN: cp %S/Inputs/incremental-imports/* %t
// RUN: cp %t/A{-before,}.swift
// RUN: %target-swift-frontend -emit-module -module-name IncrementalImports -o %t/IncrementalImports~A.swiftmodule -primary-file %t/A.swift
// RUN: %target-swift-frontend -merge-modules -emit-module -module-name IncrementalImports -o %t/IncrementalImports.swiftmodule %t/IncrementalImports~A.swiftmodule
// RUN: llvm-bcanalyzer -dump %t/IncrementalImports.swiftmodule | %FileCheck %s --check-prefix=INCREMENTAL-IMPORTS-BASELINE
// INCREMENTAL-IMPORTS-BASELINE-LABEL: <INCREMENTAL_INFORMATION_BLOCK
// Test for the fingerprint for the class
// INCREMENTAL-IMPORTS-BASELINE-DAG: blob data = '7de0a38047d74950f4f2ced447ab0242'
// And for its member
// INCREMENTAL-IMPORTS-BASELINE-DAG: blob data = 'e79735e7b1e8c65831c70766207a75f3'
// INCREMENTAL-IMPORTS-BASELINE-LABEL: </INCREMENTAL_INFORMATION_BLOCK>
// RUN: %empty-directory(%t)
// RUN: cp %S/Inputs/incremental-imports/* %t
// RUN: cp %t/A{-after,}.swift
// RUN: %target-swift-frontend -emit-module -module-name IncrementalImports -o %t/IncrementalImports~A.swiftmodule -primary-file %t/A.swift
// RUN: %target-swift-frontend -merge-modules -emit-module -module-name IncrementalImports -o %t/IncrementalImports.swiftmodule %t/IncrementalImports~A.swiftmodule
// RUN: llvm-bcanalyzer -dump %t/IncrementalImports.swiftmodule | %FileCheck %s --check-prefix=INCREMENTAL-IMPORTS-MUTATION
// INCREMENTAL-IMPORTS-MUTATION-LABEL: <INCREMENTAL_INFORMATION_BLOCK
// Make sure the fingerprint for the class doesn't change
// INCREMENTAL-IMPORTS-MUTATION-DAG: blob data = '7de0a38047d74950f4f2ced447ab0242'
// Make sure the fingerprint for the member changes
// INCREMENTAL-IMPORTS-MUTATION-DAG: blob data = '99bb01bb4d9177dc6f902d1f2326caad'
// INCREMENTAL-IMPORTS-MUTATION-LABEL: </INCREMENTAL_INFORMATION_BLOCK>