Skip to content

Commit 948e40c

Browse files
beccadaxglessard
authored andcommitted
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 swiftlang#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 a83444b commit 948e40c

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
@@ -380,6 +380,11 @@ namespace swift {
380380
/// Enable experimental eager Clang module diagnostics.
381381
bool EnableExperimentalEagerClangModuleDiagnostics = false;
382382

383+
/// Force ClangImporter's import-as-member extensions to load thier members
384+
/// immediately, bypassing their SwiftLookupTables. This emulates an
385+
/// implementation quirk of previous compilers.
386+
bool DisableNamedLazyImportAsMemberLoading = false;
387+
383388
/// Enable inference of Sendable conformances for public types.
384389
bool EnableInferPublicSendable = false;
385390

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
@@ -1487,10 +1487,25 @@ void MemberLookupTable::addMembers(DeclRange members) {
14871487
}
14881488
}
14891489

1490+
static bool shouldLoadMembersImmediately(ExtensionDecl *ext) {
1491+
assert(ext->hasLazyMembers());
1492+
if (ext->wasDeserialized() || ext->hasClangNode())
1493+
return false;
1494+
1495+
// This extension is lazy but is not deserialized or backed by a clang node,
1496+
// so it's a ClangImporter extension containing import-as-member globals.
1497+
// Historically, Swift forced these extensions to load their members
1498+
// immediately, bypassing the module's SwiftLookupTable. Using the
1499+
// SwiftLookupTable *ought* to work the same, but in practice it sometimes
1500+
// gives different results when a header is not properly modularized. Provide
1501+
// a flag to temporarily re-enable the old behavior.
1502+
return ext->getASTContext().LangOpts.DisableNamedLazyImportAsMemberLoading;
1503+
}
1504+
14901505
void MemberLookupTable::addExtension(ExtensionDecl *ext) {
14911506
// If we can lazy-load this extension, only take the members we've loaded
14921507
// so far.
1493-
if (ext->hasLazyMembers()) {
1508+
if (ext->hasLazyMembers() && !shouldLoadMembersImmediately(ext)) {
14941509
addMembers(ext->getCurrentMembersWithoutLoading());
14951510
clearLazilyCompleteCache();
14961511
clearLazilyCompleteForMacroExpansionCache();

lib/Frontend/CompilerInvocation.cpp

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

629+
Opts.DisableNamedLazyImportAsMemberLoading |=
630+
Args.hasArg(OPT_disable_named_lazy_import_as_member_loading);
631+
629632
Opts.DisableImplicitConcurrencyModuleImport |=
630633
Args.hasArg(OPT_disable_implicit_concurrency_module_import);
631634

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)