Skip to content

Commit 2b05634

Browse files
committed
Verify that _Concurrency *can* be imported on implicit import.
In case the compiler is used with concurrency features enabled (by-default or otherwise), and an older SDK is used which does not include the `_Concurrency` module, do not load this module implicitly. Instead, emit a diagnostic indicating that no such module is found. rdar://76967260
1 parent 99c521b commit 2b05634

File tree

6 files changed

+74
-3
lines changed

6 files changed

+74
-3
lines changed

include/swift/AST/ASTContext.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -879,6 +879,13 @@ class ASTContext final {
879879
/// If there is no Clang module loader, returns a null pointer.
880880
/// The loader is owned by the AST context.
881881
ClangModuleLoader *getDWARFModuleLoader() const;
882+
883+
/// Check whether the module with a given name can be imported without
884+
/// importing it.
885+
///
886+
/// Note that even if this check succeeds, errors may still occur if the
887+
/// module is loaded in full.
888+
bool canImportModuleImpl(ImportPath::Element ModulePath) const;
882889
public:
883890
namelookup::ImportCache &getImportCache() const;
884891

@@ -908,6 +915,7 @@ class ASTContext final {
908915
/// Note that even if this check succeeds, errors may still occur if the
909916
/// module is loaded in full.
910917
bool canImportModule(ImportPath::Element ModulePath);
918+
bool canImportModule(ImportPath::Element ModulePath) const;
911919

912920
/// \returns a module with a given name that was already loaded. If the
913921
/// module was not loaded, returns nullptr.

include/swift/AST/DiagnosticsFrontend.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,9 @@ ERROR(cannot_emit_ir_skipping_function_bodies,none,
136136
WARNING(emit_reference_dependencies_without_primary_file,none,
137137
"ignoring -emit-reference-dependencies (requires -primary-file)", ())
138138

139+
WARNING(warn_implicit_concurrency_import_failed,none,
140+
"unable to perform implicit import of \"_Concurrency\" module: no such module found", ())
141+
139142
ERROR(error_module_name_required,none, "-module-name is required", ())
140143
ERROR(error_bad_module_name,none,
141144
"module name \"%0\" is not a valid identifier"

include/swift/Frontend/Frontend.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -529,6 +529,14 @@ class CompilerInstance {
529529
return getMainModule()->getPrimarySourceFiles();
530530
}
531531

532+
/// Verify that if an implicit import of the `Concurrency` module if expected,
533+
/// it can actually be imported. Emit a warning, otherwise.
534+
void verifyImplicitConcurrencyImport();
535+
536+
/// Whether the Swift Concurrency support library can be imported
537+
/// i.e. if it can be found.
538+
bool canImportSwiftConcurrency() const;
539+
532540
/// Gets the SourceFile which is the primary input for this CompilerInstance.
533541
/// \returns the primary SourceFile, or nullptr if there is no primary input;
534542
/// if there are _multiple_ primary inputs, fails with an assertion.

lib/AST/ASTContext.cpp

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1934,7 +1934,7 @@ bool ASTContext::shouldPerformTypoCorrection() {
19341934
return NumTypoCorrections <= LangOpts.TypoCorrectionLimit;
19351935
}
19361936

1937-
bool ASTContext::canImportModule(ImportPath::Element ModuleName) {
1937+
bool ASTContext::canImportModuleImpl(ImportPath::Element ModuleName) const {
19381938
// If this module has already been successfully imported, it is importable.
19391939
if (getLoadedModule(ImportPath::Module::Builder(ModuleName).get()) != nullptr)
19401940
return true;
@@ -1950,10 +1950,22 @@ bool ASTContext::canImportModule(ImportPath::Element ModuleName) {
19501950
}
19511951
}
19521952

1953-
FailedModuleImportNames.insert(ModuleName.Item);
19541953
return false;
19551954
}
19561955

1956+
bool ASTContext::canImportModule(ImportPath::Element ModuleName) {
1957+
if (canImportModuleImpl(ModuleName)) {
1958+
return true;
1959+
} else {
1960+
FailedModuleImportNames.insert(ModuleName.Item);
1961+
return false;
1962+
}
1963+
}
1964+
1965+
bool ASTContext::canImportModule(ImportPath::Element ModuleName) const {
1966+
return canImportModuleImpl(ModuleName);
1967+
}
1968+
19571969
ModuleDecl *
19581970
ASTContext::getModule(ImportPath::Module ModulePath) {
19591971
assert(!ModulePath.empty());

lib/Frontend/Frontend.cpp

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -799,6 +799,19 @@ bool CompilerInvocation::shouldImportSwiftONoneSupport() const {
799799
FrontendOptions::doesActionGenerateSIL(options.RequestedAction);
800800
}
801801

802+
void CompilerInstance::verifyImplicitConcurrencyImport() {
803+
if (Invocation.shouldImportSwiftConcurrency() &&
804+
!canImportSwiftConcurrency()) {
805+
Diagnostics.diagnose(SourceLoc(),
806+
diag::warn_implicit_concurrency_import_failed);
807+
}
808+
}
809+
810+
bool CompilerInstance::canImportSwiftConcurrency() const {
811+
return getASTContext().canImportModule(
812+
{getASTContext().getIdentifier(SWIFT_CONCURRENCY_NAME), SourceLoc()});
813+
}
814+
802815
ImplicitImportInfo CompilerInstance::getImplicitImportInfo() const {
803816
auto &frontendOpts = Invocation.getFrontendOptions();
804817

@@ -823,14 +836,18 @@ ImplicitImportInfo CompilerInstance::getImplicitImportInfo() const {
823836
pushImport(SWIFT_ONONE_SUPPORT);
824837
}
825838

839+
// FIXME: The canImport check is required for compatibility
840+
// with older SDKs. Longer term solution is to have the driver make
841+
// the decision on the implicit import: rdar://76996377
826842
if (Invocation.shouldImportSwiftConcurrency()) {
827843
switch (imports.StdlibKind) {
828844
case ImplicitStdlibKind::Builtin:
829845
case ImplicitStdlibKind::None:
830846
break;
831847

832848
case ImplicitStdlibKind::Stdlib:
833-
pushImport(SWIFT_CONCURRENCY_NAME);
849+
if (canImportSwiftConcurrency())
850+
pushImport(SWIFT_CONCURRENCY_NAME);
834851
break;
835852
}
836853
}
@@ -1042,6 +1059,8 @@ bool CompilerInstance::loadStdlibIfNeeded() {
10421059
return true;
10431060
}
10441061

1062+
verifyImplicitConcurrencyImport();
1063+
10451064
// If we failed to load, we should have already diagnosed.
10461065
if (M->failedToLoad()) {
10471066
assert(Diagnostics.hadAnyError() &&
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// This test ensures that if implicit import of the Concurrency module is enabled,
2+
// but no such module can be located (here verified by forcing explicit modules),
3+
// a warning diagnostic is emitted.
4+
// REQUIRES: concurrency
5+
// RUN: %empty-directory(%t)
6+
// RUN: mkdir -p %t/inputs
7+
8+
// RUN: echo "[{" > %/t/inputs/map.json
9+
// RUN: echo "\"moduleName\": \"Swift\"," >> %/t/inputs/map.json
10+
// RUN: echo "\"modulePath\": \"%/stdlib_module\"," >> %/t/inputs/map.json
11+
// RUN: echo "\"isFramework\": false" >> %/t/inputs/map.json
12+
// RUN: echo "}," >> %/t/inputs/map.json
13+
// RUN: echo "{" >> %/t/inputs/map.json
14+
// RUN: echo "\"moduleName\": \"SwiftOnoneSupport\"," >> %/t/inputs/map.json
15+
// RUN: echo "\"modulePath\": \"%/ononesupport_module\"," >> %/t/inputs/map.json
16+
// RUN: echo "\"isFramework\": false" >> %/t/inputs/map.json
17+
// RUN: echo "}]" >> %/t/inputs/map.json
18+
19+
// RUN: %target-swift-frontend -typecheck %s -explicit-swift-module-map-file %t/inputs/map.json -disable-implicit-swift-modules -enable-experimental-concurrency 2>&1 | %FileCheck %s
20+
import Swift
21+
// CHECK: warning: unable to perform implicit import of "_Concurrency" module: no such module found

0 commit comments

Comments
 (0)