Add workaround flag for lazy import-as-member

In rdar://123649082, a project failed to build because of the lazy import-as-member loading changes in #71320. That project was configured in a way that broke modularization and the correct solution is to fix it, but out of an abundance of caution, add a `-disable-named-lazy-import-as-member-loading` frontend flag in case a project needs to temporarily restore the old behavior.

As a bonus, this lets us write a test to verify that lazy import-as-member loading has positive performance impact.
This commit is contained in:
Becca Royal-Gordon
2024-03-01 14:44:16 -08:00
parent 1a97803c8c
commit 54fd4b01b6
7 changed files with 50 additions and 3 deletions

View File

@@ -377,6 +377,11 @@ namespace swift {
/// Enable experimental eager Clang module diagnostics.
bool EnableExperimentalEagerClangModuleDiagnostics = false;
/// Force ClangImporter's import-as-member extensions to load thier members
/// immediately, bypassing their SwiftLookupTables. This emulates an
/// implementation quirk of previous compilers.
bool DisableNamedLazyImportAsMemberLoading = false;
/// Enable inference of Sendable conformances for public types.
bool EnableInferPublicSendable = false;

View File

@@ -372,7 +372,13 @@ def debug_constraints_on_line_EQ : Joined<["-"], "debug-constraints-on-line=">,
Alias<debug_constraints_on_line>;
def disable_named_lazy_member_loading : Flag<["-"], "disable-named-lazy-member-loading">,
HelpText<"Disable per-name lazy member loading">;
HelpText<"Disable per-name lazy member loading (obsolete)">;
def disable_named_lazy_import_as_member_loading :
Flag<["-"], "disable-named-lazy-import-as-member-loading">,
HelpText<"Import all of a type's import-as-member globals together, as Swift "
"5.10 and earlier did; temporary workaround for modules that are "
"sensitive to this change">;
def dump_requirement_machine : Flag<["-"], "dump-requirement-machine">,
HelpText<"Enables dumping rewrite systems from the generics implementation">;

View File

@@ -1446,10 +1446,25 @@ void MemberLookupTable::addMembers(DeclRange members) {
}
}
static bool shouldLoadMembersImmediately(ExtensionDecl *ext) {
assert(ext->hasLazyMembers());
if (ext->wasDeserialized() || ext->hasClangNode())
return false;
// This extension is lazy but is not deserialized or backed by a clang node,
// so it's a ClangImporter extension containing import-as-member globals.
// Historically, Swift forced these extensions to load their members
// immediately, bypassing the module's SwiftLookupTable. Using the
// SwiftLookupTable *ought* to work the same, but in practice it sometimes
// gives different results when a header is not properly modularized. Provide
// a flag to temporarily re-enable the old behavior.
return ext->getASTContext().LangOpts.DisableNamedLazyImportAsMemberLoading;
}
void MemberLookupTable::addExtension(ExtensionDecl *ext) {
// If we can lazy-load this extension, only take the members we've loaded
// so far.
if (ext->hasLazyMembers()) {
if (ext->hasLazyMembers() && !shouldLoadMembersImmediately(ext)) {
addMembers(ext->getCurrentMembersWithoutLoading());
clearLazilyCompleteCache();
clearLazilyCompleteForMacroExpansionCache();

View File

@@ -623,6 +623,9 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args,
!Args.hasArg(OPT_disable_experimental_clang_importer_diagnostics) &&
Args.hasArg(OPT_enable_experimental_eager_clang_module_diagnostics);
Opts.DisableNamedLazyImportAsMemberLoading |=
Args.hasArg(OPT_disable_named_lazy_import_as_member_loading);
Opts.DisableImplicitConcurrencyModuleImport |=
Args.hasArg(OPT_disable_implicit_concurrency_module_import);

View File

@@ -3,7 +3,6 @@
// RUN: %target-typecheck-verify-swift -dump-clang-lookup-tables -import-objc-header %S/Inputs/swift_name.h -I %S/Inputs/custom-modules > %t.frontend.log 2>&1
// RUN: %FileCheck %s < %t.frontend.log
// RUN: false
// REQUIRES: objc_interop
import ImportAsMember

View File

@@ -138,3 +138,6 @@
@interface PrivateDoer(Category) <PrivateMethods>
@end
typedef NSString * const SimpleDoerMode NS_TYPED_ENUM NS_SWIFT_NAME(SimpleDoer.Mode);
typedef NSString * const SimpleDoerKind NS_TYPED_ENUM NS_SWIFT_NAME(SimpleDoer.Kind);

View File

@@ -0,0 +1,16 @@
// REQUIRES: objc_interop
// REQUIRES: OS=macosx
// RUN: %empty-directory(%t/stats-lazy)
// RUN: %empty-directory(%t/stats-eager)
// RUN: %target-swift-frontend -typecheck -I %S/Inputs/NamedLazyMembers %s -stats-output-dir %t/stats-lazy
// RUN: %target-swift-frontend -typecheck -I %S/Inputs/NamedLazyMembers %s -stats-output-dir %t/stats-eager -disable-named-lazy-import-as-member-loading
// stats-lazy should only have imported SimpleDoer.Mode; stats-eager should also
// have imported SimpleDoer.Kind
// RUN: %{python} %utils/process-stats-dir.py --evaluate-delta 'NumTotalClangImportedEntities == 1' %t/stats-lazy %t/stats-eager
import NamedLazyMembers
func fn(_: SimpleDoer.Mode) {}