Skip to content

Commit 54fd4b0

Browse files
committed
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.
1 parent 1a97803 commit 54fd4b0

File tree

7 files changed

+50
-3
lines changed

7 files changed

+50
-3
lines changed

include/swift/Basic/LangOptions.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,11 @@ namespace swift {
377377
/// Enable experimental eager Clang module diagnostics.
378378
bool EnableExperimentalEagerClangModuleDiagnostics = false;
379379

380+
/// Force ClangImporter's import-as-member extensions to load thier members
381+
/// immediately, bypassing their SwiftLookupTables. This emulates an
382+
/// implementation quirk of previous compilers.
383+
bool DisableNamedLazyImportAsMemberLoading = false;
384+
380385
/// Enable inference of Sendable conformances for public types.
381386
bool EnableInferPublicSendable = false;
382387

include/swift/Option/FrontendOptions.td

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -372,7 +372,13 @@ def debug_constraints_on_line_EQ : Joined<["-"], "debug-constraints-on-line=">,
372372
Alias<debug_constraints_on_line>;
373373

374374
def disable_named_lazy_member_loading : Flag<["-"], "disable-named-lazy-member-loading">,
375-
HelpText<"Disable per-name lazy member loading">;
375+
HelpText<"Disable per-name lazy member loading (obsolete)">;
376+
377+
def disable_named_lazy_import_as_member_loading :
378+
Flag<["-"], "disable-named-lazy-import-as-member-loading">,
379+
HelpText<"Import all of a type's import-as-member globals together, as Swift "
380+
"5.10 and earlier did; temporary workaround for modules that are "
381+
"sensitive to this change">;
376382

377383
def dump_requirement_machine : Flag<["-"], "dump-requirement-machine">,
378384
HelpText<"Enables dumping rewrite systems from the generics implementation">;

lib/AST/NameLookup.cpp

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1446,10 +1446,25 @@ void MemberLookupTable::addMembers(DeclRange members) {
14461446
}
14471447
}
14481448

1449+
static bool shouldLoadMembersImmediately(ExtensionDecl *ext) {
1450+
assert(ext->hasLazyMembers());
1451+
if (ext->wasDeserialized() || ext->hasClangNode())
1452+
return false;
1453+
1454+
// This extension is lazy but is not deserialized or backed by a clang node,
1455+
// so it's a ClangImporter extension containing import-as-member globals.
1456+
// Historically, Swift forced these extensions to load their members
1457+
// immediately, bypassing the module's SwiftLookupTable. Using the
1458+
// SwiftLookupTable *ought* to work the same, but in practice it sometimes
1459+
// gives different results when a header is not properly modularized. Provide
1460+
// a flag to temporarily re-enable the old behavior.
1461+
return ext->getASTContext().LangOpts.DisableNamedLazyImportAsMemberLoading;
1462+
}
1463+
14491464
void MemberLookupTable::addExtension(ExtensionDecl *ext) {
14501465
// If we can lazy-load this extension, only take the members we've loaded
14511466
// so far.
1452-
if (ext->hasLazyMembers()) {
1467+
if (ext->hasLazyMembers() && !shouldLoadMembersImmediately(ext)) {
14531468
addMembers(ext->getCurrentMembersWithoutLoading());
14541469
clearLazilyCompleteCache();
14551470
clearLazilyCompleteForMacroExpansionCache();

lib/Frontend/CompilerInvocation.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -623,6 +623,9 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args,
623623
!Args.hasArg(OPT_disable_experimental_clang_importer_diagnostics) &&
624624
Args.hasArg(OPT_enable_experimental_eager_clang_module_diagnostics);
625625

626+
Opts.DisableNamedLazyImportAsMemberLoading |=
627+
Args.hasArg(OPT_disable_named_lazy_import_as_member_loading);
628+
626629
Opts.DisableImplicitConcurrencyModuleImport |=
627630
Args.hasArg(OPT_disable_implicit_concurrency_module_import);
628631

test/IDE/dump_swift_lookup_tables.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33

44
// 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
55
// RUN: %FileCheck %s < %t.frontend.log
6-
// RUN: false
76

87
// REQUIRES: objc_interop
98
import ImportAsMember

test/NameLookup/Inputs/NamedLazyMembers/NamedLazyMembers.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,3 +138,6 @@
138138

139139
@interface PrivateDoer(Category) <PrivateMethods>
140140
@end
141+
142+
typedef NSString * const SimpleDoerMode NS_TYPED_ENUM NS_SWIFT_NAME(SimpleDoer.Mode);
143+
typedef NSString * const SimpleDoerKind NS_TYPED_ENUM NS_SWIFT_NAME(SimpleDoer.Kind);
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// REQUIRES: objc_interop
2+
// REQUIRES: OS=macosx
3+
4+
// RUN: %empty-directory(%t/stats-lazy)
5+
// RUN: %empty-directory(%t/stats-eager)
6+
7+
// RUN: %target-swift-frontend -typecheck -I %S/Inputs/NamedLazyMembers %s -stats-output-dir %t/stats-lazy
8+
// RUN: %target-swift-frontend -typecheck -I %S/Inputs/NamedLazyMembers %s -stats-output-dir %t/stats-eager -disable-named-lazy-import-as-member-loading
9+
10+
// stats-lazy should only have imported SimpleDoer.Mode; stats-eager should also
11+
// have imported SimpleDoer.Kind
12+
// RUN: %{python} %utils/process-stats-dir.py --evaluate-delta 'NumTotalClangImportedEntities == 1' %t/stats-lazy %t/stats-eager
13+
14+
import NamedLazyMembers
15+
16+
func fn(_: SimpleDoer.Mode) {}

0 commit comments

Comments
 (0)