Skip to content

Commit 6de8597

Browse files
authored
Merge pull request #68166 from tshortli/emit-module-lazy-typecheck
2 parents ebc98be + 430cd58 commit 6de8597

20 files changed

+256
-69
lines changed

include/swift/Basic/LangOptions.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -802,6 +802,10 @@ namespace swift {
802802

803803
/// Defer typechecking of declarations to their use at runtime
804804
bool DeferToRuntime = false;
805+
806+
/// Allow request evalutation to perform type checking lazily, instead of
807+
/// eagerly typechecking source files after parsing.
808+
bool EnableLazyTypecheck = false;
805809
};
806810

807811
/// Options for controlling the behavior of the Clang importer.

include/swift/Frontend/FrontendOptions.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,6 @@ class FrontendOptions {
155155
NoneAction, ///< No specific action
156156
Parse, ///< Parse only
157157
ResolveImports, ///< Parse and resolve imports only
158-
LazyTypecheck, ///< Parse and then do minimal type-checking for outputs
159158
Typecheck, ///< Parse and type-check only
160159
DumpParse, ///< Parse only and dump AST
161160
DumpInterfaceHash, ///< Parse and dump the interface token hash.
@@ -268,7 +267,6 @@ class FrontendOptions {
268267
/// \see ModuleDecl::arePrivateImportsEnabled
269268
bool EnablePrivateImports = false;
270269

271-
272270
/// Indicates whether we add implicit dynamic.
273271
///
274272
/// \see ModuleDecl::isImplicitDynamicEnabled
@@ -323,6 +321,10 @@ class FrontendOptions {
323321
/// times) when compiling a module interface?
324322
bool SerializeModuleInterfaceDependencyHashes = false;
325323

324+
/// Should we only serialize decls that may be referenced externally in the
325+
/// binary module?
326+
bool SerializeExternalDeclsOnly = false;
327+
326328
/// Should we warn if an imported module needed to be rebuilt from a
327329
/// module interface file?
328330
bool RemarkOnRebuildFromModuleInterface = false;

include/swift/Option/FrontendOptions.td

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,10 @@ def serialize_debugging_options : Flag<["-"], "serialize-debugging-options">,
166166
def serialized_path_obfuscate : Separate<["-"], "serialized-path-obfuscate">,
167167
HelpText<"Remap source paths in debug info">, MetaVarName<"<prefix=replacement>">;
168168

169+
def experimental_serialize_external_decls_only
170+
: Flag<["-"], "experimental-serialize-external-decls-only">,
171+
HelpText<"Only serialize decls that should be exposed to clients">;
172+
169173
def empty_abi_descriptor : Flag<["-"], "empty-abi-descriptor">,
170174
HelpText<"Avoid printing actual module content into ABI descriptor file">;
171175

@@ -406,6 +410,9 @@ def debug_forbid_typecheck_prefix : Separate<["-"], "debug-forbid-typecheck-pref
406410
HelpText<"Triggers llvm fatal_error if typechecker tries to typecheck a decl "
407411
"with the provided prefix name">;
408412

413+
def experimental_lazy_typecheck : Flag<["-"], "experimental-lazy-typecheck">,
414+
HelpText<"Type-check lazily as needed to produce requested outputs">;
415+
409416
def debug_emit_invalid_swiftinterface_syntax : Flag<["-"], "debug-emit-invalid-swiftinterface-syntax">,
410417
HelpText<"Write an invalid declaration into swiftinterface files">;
411418

include/swift/Option/Options.td

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1164,9 +1164,6 @@ def resolve_imports : Flag<["-"], "resolve-imports">,
11641164
def typecheck : Flag<["-"], "typecheck">,
11651165
HelpText<"Parse and type-check input file(s)">, ModeOpt,
11661166
Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild]>;
1167-
def experimental_lazy_typecheck : Flag<["-"], "experimental-lazy-typecheck">,
1168-
HelpText<"Parse input file(s), then type-check lazily as needed to produce requested outputs">, ModeOpt,
1169-
Flags<[FrontendOption, NoInteractiveOption, HelpHidden, DoesNotAffectIncrementalBuild]>;
11701167
def dump_parse : Flag<["-"], "dump-parse">,
11711168
HelpText<"Parse input file(s) and dump AST(s)">, ModeOpt,
11721169
Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild]>;

include/swift/Serialization/SerializationOptions.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ namespace swift {
156156
bool StaticLibrary = false;
157157
bool HermeticSealAtLink = false;
158158
bool IsOSSA = false;
159+
bool SerializeExternalDeclsOnly = false;
159160
};
160161

161162
} // end namespace swift

lib/Frontend/ArgsToFrontendOptionsConverter.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,8 @@ bool ArgsToFrontendOptionsConverter::convert(
318318
A->getOption().matches(OPT_serialize_debugging_options);
319319
}
320320

321+
Opts.SerializeExternalDeclsOnly |=
322+
Args.hasArg(OPT_experimental_serialize_external_decls_only);
321323
Opts.DebugPrefixSerializedDebuggingOptions |=
322324
Args.hasArg(OPT_prefix_serialized_debugging_options);
323325
Opts.EnableSourceImport |= Args.hasArg(OPT_enable_source_import);
@@ -552,8 +554,6 @@ ArgsToFrontendOptionsConverter::determineRequestedAction(const ArgList &args) {
552554
return FrontendOptions::ActionType::Parse;
553555
if (Opt.matches(OPT_resolve_imports))
554556
return FrontendOptions::ActionType::ResolveImports;
555-
if (Opt.matches(OPT_experimental_lazy_typecheck))
556-
return FrontendOptions::ActionType::LazyTypecheck;
557557
if (Opt.matches(OPT_typecheck))
558558
return FrontendOptions::ActionType::Typecheck;
559559
if (Opt.matches(OPT_dump_parse))

lib/Frontend/CompilerInvocation.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1423,6 +1423,8 @@ static bool ParseTypeCheckerArgs(TypeCheckerOptions &Opts, ArgList &Args,
14231423

14241424
Opts.DebugGenericSignatures |= Args.hasArg(OPT_debug_generic_signatures);
14251425

1426+
Opts.EnableLazyTypecheck |= Args.hasArg(OPT_experimental_lazy_typecheck);
1427+
14261428
return HadError;
14271429
}
14281430

lib/Frontend/Frontend.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,9 @@ SerializationOptions CompilerInvocation::computeSerializationOptions(
225225

226226
serializationOpts.IsOSSA = getSILOptions().EnableOSSAModules;
227227

228+
serializationOpts.SerializeExternalDeclsOnly =
229+
opts.SerializeExternalDeclsOnly;
230+
228231
return serializationOpts;
229232
}
230233

@@ -1395,6 +1398,11 @@ bool CompilerInstance::performParseAndResolveImportsOnly() {
13951398
void CompilerInstance::performSema() {
13961399
performParseAndResolveImportsOnly();
13971400

1401+
// Skip eager type checking. Instead, let later stages of compilation drive
1402+
// type checking as needed through request evaluation.
1403+
if (getASTContext().TypeCheckerOpts.EnableLazyTypecheck)
1404+
return;
1405+
13981406
FrontendStatsTracer tracer(getStatsReporter(), "perform-sema");
13991407

14001408
forEachFileToTypeCheck([&](SourceFile &SF) {

lib/Frontend/FrontendOptions.cpp

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ bool FrontendOptions::needsProperModuleName(ActionType action) {
3333
case ActionType::NoneAction:
3434
case ActionType::Parse:
3535
case ActionType::ResolveImports:
36-
case ActionType::LazyTypecheck:
3736
case ActionType::Typecheck:
3837
case ActionType::DumpParse:
3938
case ActionType::DumpAST:
@@ -105,7 +104,6 @@ bool FrontendOptions::doesActionRequireSwiftStandardLibrary(ActionType action) {
105104
case ActionType::PrintFeature:
106105
return false;
107106
case ActionType::ResolveImports:
108-
case ActionType::LazyTypecheck:
109107
case ActionType::Typecheck:
110108
case ActionType::DumpAST:
111109
case ActionType::PrintAST:
@@ -151,7 +149,6 @@ bool FrontendOptions::doesActionRequireInputs(ActionType action) {
151149
case ActionType::CompileModuleFromInterface:
152150
case ActionType::TypecheckModuleFromInterface:
153151
case ActionType::ResolveImports:
154-
case ActionType::LazyTypecheck:
155152
case ActionType::Typecheck:
156153
case ActionType::DumpAST:
157154
case ActionType::PrintAST:
@@ -194,7 +191,6 @@ bool FrontendOptions::doesActionPerformEndOfPipelineActions(ActionType action) {
194191
case ActionType::CompileModuleFromInterface:
195192
case ActionType::TypecheckModuleFromInterface:
196193
case ActionType::ResolveImports:
197-
case ActionType::LazyTypecheck:
198194
case ActionType::Typecheck:
199195
case ActionType::DumpAST:
200196
case ActionType::PrintAST:
@@ -234,7 +230,6 @@ bool FrontendOptions::supportCompilationCaching(ActionType action) {
234230
case ActionType::EmitImportedModules:
235231
case ActionType::ScanDependencies:
236232
case ActionType::ResolveImports:
237-
case ActionType::LazyTypecheck:
238233
case ActionType::Typecheck:
239234
case ActionType::DumpAST:
240235
case ActionType::PrintAST:
@@ -295,7 +290,6 @@ FrontendOptions::formatForPrincipalOutputFileForAction(ActionType action) {
295290

296291
case ActionType::Parse:
297292
case ActionType::ResolveImports:
298-
case ActionType::LazyTypecheck:
299293
case ActionType::Typecheck:
300294
case ActionType::TypecheckModuleFromInterface:
301295
case ActionType::DumpParse:
@@ -383,7 +377,6 @@ bool FrontendOptions::canActionEmitDependencies(ActionType action) {
383377
case ActionType::PrintFeature:
384378
return false;
385379
case ActionType::ResolveImports:
386-
case ActionType::LazyTypecheck:
387380
case ActionType::Typecheck:
388381
case ActionType::MergeModules:
389382
case ActionType::EmitModuleOnly:
@@ -410,7 +403,6 @@ bool FrontendOptions::canActionEmitReferenceDependencies(ActionType action) {
410403
case ActionType::NoneAction:
411404
case ActionType::Parse:
412405
case ActionType::ResolveImports:
413-
case ActionType::LazyTypecheck:
414406
case ActionType::DumpParse:
415407
case ActionType::DumpInterfaceHash:
416408
case ActionType::DumpAST:
@@ -453,7 +445,6 @@ bool FrontendOptions::canActionEmitModuleSummary(ActionType action) {
453445
case ActionType::NoneAction:
454446
case ActionType::Parse:
455447
case ActionType::ResolveImports:
456-
case ActionType::LazyTypecheck:
457448
case ActionType::DumpParse:
458449
case ActionType::DumpInterfaceHash:
459450
case ActionType::DumpAST:
@@ -515,7 +506,6 @@ bool FrontendOptions::canActionEmitClangHeader(ActionType action) {
515506
case ActionType::PrintVersion:
516507
case ActionType::PrintFeature:
517508
return false;
518-
case ActionType::LazyTypecheck:
519509
case ActionType::Typecheck:
520510
case ActionType::MergeModules:
521511
case ActionType::EmitModuleOnly:
@@ -557,7 +547,6 @@ bool FrontendOptions::canActionEmitLoadedModuleTrace(ActionType action) {
557547
case ActionType::PrintFeature:
558548
return false;
559549
case ActionType::ResolveImports:
560-
case ActionType::LazyTypecheck:
561550
case ActionType::Typecheck:
562551
case ActionType::MergeModules:
563552
case ActionType::EmitModuleOnly:
@@ -587,7 +576,6 @@ bool FrontendOptions::canActionEmitModuleSemanticInfo(ActionType action) {
587576
case ActionType::NoneAction:
588577
case ActionType::Parse:
589578
case ActionType::ResolveImports:
590-
case ActionType::LazyTypecheck:
591579
case ActionType::DumpParse:
592580
case ActionType::DumpInterfaceHash:
593581
case ActionType::DumpAST:
@@ -631,7 +619,6 @@ bool FrontendOptions::canActionEmitConstValues(ActionType action) {
631619
case ActionType::NoneAction:
632620
case ActionType::Parse:
633621
case ActionType::ResolveImports:
634-
case ActionType::LazyTypecheck:
635622
case ActionType::DumpParse:
636623
case ActionType::DumpInterfaceHash:
637624
case ActionType::DumpAST:
@@ -673,7 +660,6 @@ bool FrontendOptions::canActionEmitModule(ActionType action) {
673660
case ActionType::NoneAction:
674661
case ActionType::Parse:
675662
case ActionType::ResolveImports:
676-
case ActionType::LazyTypecheck:
677663
case ActionType::Typecheck:
678664
case ActionType::DumpParse:
679665
case ActionType::DumpInterfaceHash:
@@ -741,7 +727,6 @@ bool FrontendOptions::canActionEmitInterface(ActionType action) {
741727
case ActionType::PrintFeature:
742728
return false;
743729
case ActionType::ResolveImports:
744-
case ActionType::LazyTypecheck:
745730
case ActionType::Typecheck:
746731
case ActionType::MergeModules:
747732
case ActionType::EmitModuleOnly:
@@ -762,7 +747,6 @@ bool FrontendOptions::doesActionProduceOutput(ActionType action) {
762747
switch (action) {
763748
case ActionType::Parse:
764749
case ActionType::ResolveImports:
765-
case ActionType::LazyTypecheck:
766750
case ActionType::Typecheck:
767751
case ActionType::DumpParse:
768752
case ActionType::DumpAST:
@@ -821,7 +805,6 @@ bool FrontendOptions::doesActionProduceTextualOutput(ActionType action) {
821805

822806
case ActionType::Parse:
823807
case ActionType::ResolveImports:
824-
case ActionType::LazyTypecheck:
825808
case ActionType::Typecheck:
826809
case ActionType::DumpParse:
827810
case ActionType::DumpInterfaceHash:
@@ -851,7 +834,6 @@ bool FrontendOptions::doesActionGenerateSIL(ActionType action) {
851834
case ActionType::NoneAction:
852835
case ActionType::Parse:
853836
case ActionType::ResolveImports:
854-
case ActionType::LazyTypecheck:
855837
case ActionType::Typecheck:
856838
case ActionType::DumpParse:
857839
case ActionType::DumpInterfaceHash:
@@ -903,7 +885,6 @@ bool FrontendOptions::doesActionGenerateIR(ActionType action) {
903885
case ActionType::DumpTypeInfo:
904886
case ActionType::CompileModuleFromInterface:
905887
case ActionType::TypecheckModuleFromInterface:
906-
case ActionType::LazyTypecheck:
907888
case ActionType::Typecheck:
908889
case ActionType::ResolveImports:
909890
case ActionType::MergeModules:

lib/FrontendTool/FrontendTool.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1359,9 +1359,6 @@ static bool performAction(CompilerInstance &Instance,
13591359
return performParseOnly(*Instance.getMainModule());
13601360
case FrontendOptions::ActionType::ResolveImports:
13611361
return Instance.performParseAndResolveImportsOnly();
1362-
case FrontendOptions::ActionType::LazyTypecheck:
1363-
// For now, this action is just an alias of ResolveImports.
1364-
return Instance.performParseAndResolveImportsOnly();
13651362
case FrontendOptions::ActionType::Typecheck:
13661363
return withSemanticAnalysis(Instance, observer,
13671364
[](CompilerInstance &Instance) {

lib/Serialization/Serialization.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3258,6 +3258,7 @@ class Serializer::DeclSerializer : public DeclVisitor<DeclSerializer> {
32583258
}
32593259
}
32603260

3261+
public:
32613262
/// Determine if \p decl is safe to deserialize when it's public
32623263
/// or otherwise needed by the client in normal builds, this should usually
32633264
/// correspond to logic in type-checking ensuring these safe decls don't
@@ -3336,6 +3337,7 @@ class Serializer::DeclSerializer : public DeclVisitor<DeclSerializer> {
33363337
return false;
33373338
}
33383339

3340+
private:
33393341
/// Write a \c DeserializationSafetyLayout record only when \p decl is unsafe
33403342
/// to deserialize.
33413343
///
@@ -3505,6 +3507,9 @@ class Serializer::DeclSerializer : public DeclVisitor<DeclSerializer> {
35053507

35063508
SmallVector<DeclID, 16> memberIDs;
35073509
for (auto member : members) {
3510+
if (S.shouldSkipDecl(member))
3511+
continue;
3512+
35083513
if (!shouldSerializeMember(member))
35093514
continue;
35103515

@@ -4888,6 +4893,14 @@ static bool canSkipWhenInvalid(const Decl *D) {
48884893
return false;
48894894
}
48904895

4896+
bool Serializer::shouldSkipDecl(const Decl *D) const {
4897+
if (Options.SerializeExternalDeclsOnly &&
4898+
!DeclSerializer::isDeserializationSafe(D))
4899+
return true;
4900+
4901+
return false;
4902+
}
4903+
48914904
void Serializer::writeASTBlockEntity(const Decl *D) {
48924905
using namespace decls_block;
48934906

@@ -6358,6 +6371,9 @@ void Serializer::writeAST(ModuleOrSourceFile DC) {
63586371
continue;
63596372
}
63606373

6374+
if (shouldSkipDecl(D))
6375+
continue;
6376+
63616377
if (auto VD = dyn_cast<ValueDecl>(D)) {
63626378
if (!VD->hasName())
63636379
continue;
@@ -6406,6 +6422,8 @@ void Serializer::writeAST(ModuleOrSourceFile DC) {
64066422
nextFile->getOpaqueReturnTypeDecls(opaqueReturnTypeDecls);
64076423

64086424
for (auto TD : localTypeDecls) {
6425+
if (shouldSkipDecl(TD))
6426+
continue;
64096427

64106428
// FIXME: We should delay parsing function bodies so these type decls
64116429
// don't even get added to the file.
@@ -6436,6 +6454,9 @@ void Serializer::writeAST(ModuleOrSourceFile DC) {
64366454
}
64376455

64386456
for (auto OTD : opaqueReturnTypeDecls) {
6457+
if (shouldSkipDecl(OTD))
6458+
continue;
6459+
64396460
// FIXME: We should delay parsing function bodies so these type decls
64406461
// don't even get added to the file.
64416462
if (OTD->getDeclContext()->getInnermostSkippedFunctionContext())

lib/Serialization/Serialization.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,9 @@ class Serializer : public SerializerBase {
332332
/// Check if a decl is cross-referenced.
333333
bool isDeclXRef(const Decl *D) const;
334334

335+
/// Check if a decl should be skipped during serialization.
336+
bool shouldSkipDecl(const Decl *D) const;
337+
335338
/// Writes a reference to a decl in another module.
336339
void writeCrossReference(const DeclContext *DC, uint32_t pathLen = 1);
337340

test/Driver/emit-interface.swift

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,3 @@
2626
// CHECK-FILELIST: swift{{(-frontend|c)?(\.exe)?"?}} -frontend
2727
// CHECK-FILELIST-SAME: -supplementary-output-file-map
2828
// CHECK-FILELIST-NOT: emit-interface.swift{{ }}
29-
30-
// RUN: %swiftc_driver -driver-print-jobs -target x86_64-apple-macosx10.9 -experimental-lazy-typecheck %s -emit-module-interface -o %t/foo 2>&1 | %FileCheck -check-prefix=CHECK-LAZY-TYPECHECK %s
31-
32-
// CHECK-LAZY-TYPECHECK: swift{{(-frontend|c)?(\.exe)?"?}} -frontend
33-
// CHECK-LAZY-TYPECHECK-SAME: -experimental-lazy-typecheck
34-
// CHECK-LAZY-TYPECHECK-SAME: emit-interface.swift

0 commit comments

Comments
 (0)