mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
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:
@@ -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(
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
public final class ClsA {
|
||||
public static func doit(value: Bool = true) {
|
||||
print("value: \(value)")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
public final class ClsA {
|
||||
public static func doit(value: Bool = false) {
|
||||
print("value: \(value)")
|
||||
}
|
||||
}
|
||||
31
test/Serialization/incremental-imports.swift
Normal file
31
test/Serialization/incremental-imports.swift
Normal 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>
|
||||
Reference in New Issue
Block a user