-
Notifications
You must be signed in to change notification settings - Fork 10.5k
Introduce Import Resolution as a Frontend Action #17645
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -425,7 +425,21 @@ shouldImplicityImportSwiftOnoneSupportModule(CompilerInvocation &Invocation) { | |
return Invocation.getFrontendOptions().isCreatingSIL(); | ||
} | ||
|
||
void CompilerInstance::performParseAndResolveImportsOnly() { | ||
performSemaUpTo(SourceFile::NameBound); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm personally not sure we need these helper functions, and think we could just add an argument to |
||
} | ||
|
||
void CompilerInstance::performSema() { | ||
performSemaUpTo(SourceFile::TypeChecked); | ||
} | ||
|
||
void CompilerInstance::performSemaUpTo(SourceFile::ASTStage_t LimitStage) { | ||
// FIXME: A lot of the logic in `performParseOnly` is a stripped-down version | ||
// of the logic in `performSemaUpTo`. We should try to unify them over time. | ||
if (LimitStage <= SourceFile::Parsed) { | ||
return performParseOnly(); | ||
} | ||
|
||
FrontendStatsTracer tracer(Context->Stats, "perform-sema"); | ||
Context->LoadedModules[MainModule->getName()] = getMainModule(); | ||
|
||
|
@@ -457,7 +471,7 @@ void CompilerInstance::performSema() { | |
if (MainBufferID != NO_SUCH_BUFFER) | ||
addMainFileToModule(implicitImports); | ||
|
||
parseAndCheckTypes(implicitImports); | ||
parseAndCheckTypesUpTo(implicitImports, LimitStage); | ||
} | ||
|
||
CompilerInstance::ImplicitImports::ImplicitImports(CompilerInstance &compiler) { | ||
|
@@ -575,8 +589,8 @@ void CompilerInstance::addMainFileToModule( | |
addAdditionalInitialImportsTo(MainFile, implicitImports); | ||
} | ||
|
||
void CompilerInstance::parseAndCheckTypes( | ||
const ImplicitImports &implicitImports) { | ||
void CompilerInstance::parseAndCheckTypesUpTo( | ||
const ImplicitImports &implicitImports, SourceFile::ASTStage_t limitStage) { | ||
FrontendStatsTracer tracer(Context->Stats, "parse-and-check-types"); | ||
// Delayed parsing callback for the primary file, or all files | ||
// in non-WMO mode. | ||
|
@@ -611,8 +625,8 @@ void CompilerInstance::parseAndCheckTypes( | |
// In addition, the main file has parsing and type-checking | ||
// interwined. | ||
if (MainBufferID != NO_SUCH_BUFFER) { | ||
parseAndTypeCheckMainFile(PersistentState, PrimaryDelayedCB.get(), | ||
TypeCheckOptions); | ||
parseAndTypeCheckMainFileUpTo(limitStage, PersistentState, | ||
PrimaryDelayedCB.get(), TypeCheckOptions); | ||
} | ||
|
||
assert(llvm::all_of(MainModule->getFiles(), [](const FileUnit *File) -> bool { | ||
|
@@ -623,6 +637,11 @@ void CompilerInstance::parseAndCheckTypes( | |
}) && "some files have not yet had their imports resolved"); | ||
MainModule->setHasResolvedImports(); | ||
|
||
// If the limiting AST stage is name binding, we're done. | ||
if (limitStage <= SourceFile::NameBound) { | ||
return; | ||
} | ||
|
||
const auto &options = Invocation.getFrontendOptions(); | ||
forEachFileToTypeCheck([&](SourceFile &SF) { | ||
performTypeChecking(SF, PersistentState.getTopLevelContext(), | ||
|
@@ -720,7 +739,8 @@ bool CompilerInstance::parsePartialModulesAndLibraryFiles( | |
return hadLoadError; | ||
} | ||
|
||
void CompilerInstance::parseAndTypeCheckMainFile( | ||
void CompilerInstance::parseAndTypeCheckMainFileUpTo( | ||
SourceFile::ASTStage_t LimitStage, | ||
PersistentParserState &PersistentState, | ||
DelayedParsingCallbacks *DelayedParseCB, | ||
OptionSet<TypeCheckingFlags> TypeCheckOptions) { | ||
|
@@ -747,15 +767,27 @@ void CompilerInstance::parseAndTypeCheckMainFile( | |
parseIntoSourceFile(MainFile, MainFile.getBufferID().getValue(), &Done, | ||
TheSILModule ? &SILContext : nullptr, &PersistentState, | ||
DelayedParseCB); | ||
|
||
if (mainIsPrimary) { | ||
const auto &options = Invocation.getFrontendOptions(); | ||
performTypeChecking(MainFile, PersistentState.getTopLevelContext(), | ||
TypeCheckOptions, CurTUElem, | ||
options.WarnLongFunctionBodies, | ||
options.WarnLongExpressionTypeChecking, | ||
options.SolverExpressionTimeThreshold, | ||
options.SwitchCheckingInvocationThreshold); | ||
switch (LimitStage) { | ||
case SourceFile::Parsing: | ||
case SourceFile::Parsed: | ||
llvm_unreachable("invalid limit stage"); | ||
case SourceFile::NameBound: | ||
performNameBinding(MainFile, CurTUElem); | ||
break; | ||
case SourceFile::TypeChecked: | ||
const auto &options = Invocation.getFrontendOptions(); | ||
performTypeChecking(MainFile, PersistentState.getTopLevelContext(), | ||
TypeCheckOptions, CurTUElem, | ||
options.WarnLongFunctionBodies, | ||
options.WarnLongExpressionTypeChecking, | ||
options.SolverExpressionTimeThreshold, | ||
options.SwitchCheckingInvocationThreshold); | ||
break; | ||
} | ||
} | ||
|
||
CurTUElem = MainFile.Decls.size(); | ||
} while (!Done); | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -31,6 +31,7 @@ bool FrontendOptions::needsProperModuleName(ActionType action) { | |
switch (action) { | ||
case ActionType::NoneAction: | ||
case ActionType::Parse: | ||
case ActionType::ResolveImports: | ||
case ActionType::Typecheck: | ||
case ActionType::DumpParse: | ||
case ActionType::DumpAST: | ||
|
@@ -65,6 +66,7 @@ bool FrontendOptions::isActionImmediate(ActionType action) { | |
switch (action) { | ||
case ActionType::NoneAction: | ||
case ActionType::Parse: | ||
case ActionType::ResolveImports: | ||
case ActionType::Typecheck: | ||
case ActionType::DumpParse: | ||
case ActionType::DumpAST: | ||
|
@@ -134,6 +136,7 @@ FrontendOptions::suffixForPrincipalOutputFileForAction(ActionType action) { | |
return StringRef(); | ||
|
||
case ActionType::Parse: | ||
case ActionType::ResolveImports: | ||
case ActionType::Typecheck: | ||
case ActionType::DumpParse: | ||
case ActionType::DumpInterfaceHash: | ||
|
@@ -184,6 +187,7 @@ FrontendOptions::suffixForPrincipalOutputFileForAction(ActionType action) { | |
bool FrontendOptions::canActionEmitDependencies(ActionType action) { | ||
switch (action) { | ||
case ActionType::NoneAction: | ||
case ActionType::Parse: | ||
case ActionType::DumpParse: | ||
case ActionType::DumpInterfaceHash: | ||
case ActionType::DumpAST: | ||
|
@@ -194,7 +198,39 @@ bool FrontendOptions::canActionEmitDependencies(ActionType action) { | |
case ActionType::Immediate: | ||
case ActionType::REPL: | ||
return false; | ||
case ActionType::ResolveImports: | ||
case ActionType::Typecheck: | ||
case ActionType::MergeModules: | ||
case ActionType::EmitModuleOnly: | ||
case ActionType::EmitPCH: | ||
case ActionType::EmitSILGen: | ||
case ActionType::EmitSIL: | ||
case ActionType::EmitSIBGen: | ||
case ActionType::EmitSIB: | ||
case ActionType::EmitIR: | ||
case ActionType::EmitBC: | ||
case ActionType::EmitAssembly: | ||
case ActionType::EmitObject: | ||
case ActionType::EmitImportedModules: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wonder if |
||
return true; | ||
} | ||
} | ||
|
||
bool FrontendOptions::canActionEmitReferenceDependencies(ActionType action) { | ||
switch (action) { | ||
case ActionType::NoneAction: | ||
case ActionType::Parse: | ||
case ActionType::ResolveImports: | ||
case ActionType::DumpParse: | ||
case ActionType::DumpInterfaceHash: | ||
case ActionType::DumpAST: | ||
case ActionType::EmitSyntax: | ||
case ActionType::PrintAST: | ||
case ActionType::DumpScopeMaps: | ||
case ActionType::DumpTypeRefinementContexts: | ||
case ActionType::Immediate: | ||
case ActionType::REPL: | ||
return false; | ||
case ActionType::Typecheck: | ||
case ActionType::MergeModules: | ||
case ActionType::EmitModuleOnly: | ||
|
@@ -227,6 +263,7 @@ bool FrontendOptions::canActionEmitObjCHeader(ActionType action) { | |
case ActionType::REPL: | ||
return false; | ||
case ActionType::Parse: | ||
case ActionType::ResolveImports: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Actually, I think Parse and ResolveImports belong in the "false" section for this one. It definitely needs a type-checked AST. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'll submit another patch for that one. |
||
case ActionType::Typecheck: | ||
case ActionType::MergeModules: | ||
case ActionType::EmitModuleOnly: | ||
|
@@ -257,6 +294,7 @@ bool FrontendOptions::canActionEmitLoadedModuleTrace(ActionType action) { | |
case ActionType::Immediate: | ||
case ActionType::REPL: | ||
return false; | ||
case ActionType::ResolveImports: | ||
case ActionType::Typecheck: | ||
case ActionType::MergeModules: | ||
case ActionType::EmitModuleOnly: | ||
|
@@ -278,6 +316,7 @@ bool FrontendOptions::canActionEmitModule(ActionType action) { | |
switch (action) { | ||
case ActionType::NoneAction: | ||
case ActionType::Parse: | ||
case ActionType::ResolveImports: | ||
case ActionType::Typecheck: | ||
case ActionType::DumpParse: | ||
case ActionType::DumpInterfaceHash: | ||
|
@@ -312,6 +351,7 @@ bool FrontendOptions::canActionEmitModuleDoc(ActionType action) { | |
bool FrontendOptions::doesActionProduceOutput(ActionType action) { | ||
switch (action) { | ||
case ActionType::Parse: | ||
case ActionType::ResolveImports: | ||
case ActionType::Typecheck: | ||
case ActionType::DumpParse: | ||
case ActionType::DumpAST: | ||
|
@@ -357,6 +397,7 @@ bool FrontendOptions::doesActionProduceTextualOutput(ActionType action) { | |
return false; | ||
|
||
case ActionType::Parse: | ||
case ActionType::ResolveImports: | ||
case ActionType::Typecheck: | ||
case ActionType::DumpParse: | ||
case ActionType::DumpInterfaceHash: | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -895,11 +895,14 @@ static bool performCompile(CompilerInstance &Instance, | |
if (Invocation.getInputKind() == InputFileKind::IFK_LLVM_IR) | ||
return compileLLVMIR(Invocation, Instance, Stats); | ||
|
||
if (FrontendOptions::shouldActionOnlyParse(Action)) | ||
if (FrontendOptions::shouldActionOnlyParse(Action)) { | ||
Instance.performParseOnly(/*EvaluateConditionals*/ | ||
Action == FrontendOptions::ActionType::EmitImportedModules); | ||
else | ||
} else if (Action == FrontendOptions::ActionType::ResolveImports) { | ||
Instance.performParseAndResolveImportsOnly(); | ||
} else { | ||
Instance.performSema(); | ||
} | ||
|
||
SWIFT_DEFER { | ||
// Emit request-evaluator graph via GraphViz, if requested. | ||
|
@@ -912,8 +915,15 @@ static bool performCompile(CompilerInstance &Instance, | |
} | ||
}; | ||
|
||
ASTContext &Context = Instance.getASTContext(); | ||
if (Action == FrontendOptions::ActionType::Parse) | ||
return Instance.getASTContext().hadError(); | ||
return Context.hadError(); | ||
|
||
(void)emitMakeDependenciesIfNeeded(Context.Diags, | ||
Instance.getDependencyTracker(), opts); | ||
|
||
if (Action == FrontendOptions::ActionType::ResolveImports) | ||
return Context.hadError(); | ||
|
||
if (observer) | ||
observer->performedSemanticAnalysis(Instance); | ||
|
@@ -929,8 +939,6 @@ static bool performCompile(CompilerInstance &Instance, | |
debugFailWithCrash(); | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Arguably these crashes should happen even in -parse or -resolve-imports. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For future reference: Had an offline chat about this. Filed SR-8252 about it. |
||
|
||
ASTContext &Context = Instance.getASTContext(); | ||
|
||
verifyGenericSignaturesIfNeeded(Invocation, Context); | ||
|
||
(void)migrator::updateCodeAndEmitRemapIfNeeded(&Instance, Invocation); | ||
|
@@ -948,9 +956,6 @@ static bool performCompile(CompilerInstance &Instance, | |
if (opts.PrintClangStats && Context.getClangModuleLoader()) | ||
Context.getClangModuleLoader()->printStatistics(); | ||
|
||
(void)emitMakeDependenciesIfNeeded(Context.Diags, | ||
Instance.getDependencyTracker(), opts); | ||
|
||
emitReferenceDependenciesForAllPrimaryInputsIfNeeded(Invocation, Instance); | ||
|
||
(void)emitLoadedModuleTraceForAllPrimariesIfNeeded( | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you feel like it, it would be nice to actually include the referred-to mode in the error message. I understand if it's outside the scope of this change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Most of these errors are already caught at the driver level, so checking for them in the frontend just helps test authors. That means there's not really a problem with talking about specific frontend arguments, which I'd normally be worried about.