Skip to content

Commit b36b946

Browse files
committed
Sema: Only add implicit imports to module interface during resilience typechecking.
Previously, implicit imports were also being added to the module interface during override checking (without any diagnostic). Additionally, correct the structure of the import which contained an extra, duplicated path component. It would be diagnosed as a scoped import and written into the interface like this: ``` import UIKit/*.UIKit*/ ``` Resolves rdar://104935794
1 parent 6b0c22c commit b36b946

File tree

3 files changed

+92
-24
lines changed

3 files changed

+92
-24
lines changed

lib/AST/Module.cpp

-15
Original file line numberDiff line numberDiff line change
@@ -3115,21 +3115,6 @@ RestrictedImportKind SourceFile::getRestrictedImportKind(const ModuleDecl *modul
31153115
if (imports.isImportedBy(module, getParentModule()))
31163116
return RestrictedImportKind::None;
31173117

3118-
if (importKind == RestrictedImportKind::MissingImport &&
3119-
(module->getLibraryLevel() == LibraryLevel::API ||
3120-
getParentModule()->getLibraryLevel() != LibraryLevel::API)) {
3121-
// Hack to fix swiftinterfaces in case of missing imports.
3122-
// We can get rid of this logic when we don't leak the use of non-locally
3123-
// imported things in API.
3124-
ImportPath::Element pathElement = {module->getName(), SourceLoc()};
3125-
auto pathArray = getASTContext().AllocateCopy(
3126-
llvm::makeArrayRef(pathElement));
3127-
auto missingImport = ImportedModule(
3128-
ImportPath::Access(pathArray),
3129-
const_cast<ModuleDecl *>(module));
3130-
addMissingImportedModule(missingImport);
3131-
}
3132-
31333118
return importKind;
31343119
}
31353120

lib/Sema/ResilienceDiagnostics.cpp

+28-9
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,27 @@
2828

2929
using namespace swift;
3030

31+
static bool addMissingImport(SourceLoc loc, const Decl *D,
32+
const ExportContext &where) {
33+
ASTContext &ctx = where.getDeclContext()->getASTContext();
34+
ModuleDecl *M = D->getModuleContext();
35+
auto *SF = where.getDeclContext()->getParentSourceFile();
36+
37+
// Only add imports of API level modules if this is an API level module.
38+
if (M->getLibraryLevel() != LibraryLevel::API &&
39+
SF->getParentModule()->getLibraryLevel() == LibraryLevel::API)
40+
return false;
41+
42+
// Hack to fix swiftinterfaces in case of missing imports. We can get rid of
43+
// this logic when we don't leak the use of non-locally imported things in
44+
// API.
45+
auto missingImport = ImportedModule(ImportPath::Access(),
46+
const_cast<ModuleDecl *>(M));
47+
SF->addMissingImportedModule(missingImport);
48+
ctx.Diags.diagnose(loc, diag::missing_import_inserted, M->getName());
49+
return true;
50+
}
51+
3152
bool TypeChecker::diagnoseInlinableDeclRefAccess(SourceLoc loc,
3253
const ValueDecl *D,
3354
const ExportContext &where) {
@@ -184,8 +205,7 @@ static bool diagnoseTypeAliasDeclRefExportability(SourceLoc loc,
184205

185206
if (originKind == DisallowedOriginKind::MissingImport &&
186207
!ctx.LangOpts.isSwiftVersionAtLeast(6))
187-
ctx.Diags.diagnose(loc, diag::missing_import_inserted,
188-
definingModule->getName());
208+
addMissingImport(loc, D, where);
189209

190210
return true;
191211
}
@@ -202,7 +222,7 @@ static bool diagnoseValueDeclRefExportability(SourceLoc loc, const ValueDecl *D,
202222
if (originKind == DisallowedOriginKind::None)
203223
return false;
204224

205-
ASTContext &ctx = definingModule->getASTContext();
225+
ASTContext &ctx = where.getDeclContext()->getASTContext();
206226

207227
auto fragileKind = where.getFragileFunctionKind();
208228
auto reason = where.getExportabilityReason();
@@ -236,8 +256,7 @@ static bool diagnoseValueDeclRefExportability(SourceLoc loc, const ValueDecl *D,
236256

237257
if (originKind == DisallowedOriginKind::MissingImport &&
238258
downgradeToWarning == DowngradeToWarning::Yes)
239-
ctx.Diags.diagnose(loc, diag::missing_import_inserted,
240-
definingModule->getName());
259+
addMissingImport(loc, D, where);
241260
}
242261

243262
return true;
@@ -296,9 +315,9 @@ TypeChecker::diagnoseConformanceExportability(SourceLoc loc,
296315
originKind == DisallowedOriginKind::MissingImport,
297316
6);
298317

299-
if (originKind == DisallowedOriginKind::MissingImport &&
300-
!ctx.LangOpts.isSwiftVersionAtLeast(6))
301-
ctx.Diags.diagnose(loc, diag::missing_import_inserted,
302-
M->getName());
318+
if (originKind == DisallowedOriginKind::MissingImport &&
319+
!ctx.LangOpts.isSwiftVersionAtLeast(6))
320+
addMissingImport(loc, ext, where);
321+
303322
return true;
304323
}
+64
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: split-file %s %t
3+
4+
// RUN: %target-swift-emit-module-interface(%t/DefinesProtocol.swiftinterface) -I %t %t/DefinesProtocol.swift -module-name DefinesProtocol
5+
// RUN: %target-swift-typecheck-module-from-interface(%t/DefinesProtocol.swiftinterface) -I %t -module-name DefinesProtocol
6+
7+
// RUN: %target-swift-emit-module-interface(%t/DefinesTypealias.swiftinterface) -I %t %t/DefinesTypealias.swift -module-name DefinesTypealias
8+
// RUN: %target-swift-typecheck-module-from-interface(%t/DefinesTypealias.swiftinterface) -I %t -module-name DefinesTypealias
9+
10+
// RUN: %target-swift-emit-module-interface(%t/DefinesStruct.swiftinterface) -I %t %t/DefinesStruct.swift -module-name DefinesStruct
11+
// RUN: %target-swift-typecheck-module-from-interface(%t/DefinesStruct.swiftinterface) -I %t -module-name DefinesStruct
12+
13+
// RUN: %target-swift-emit-module-interface(%t/DefinesExtension.swiftinterface) -I %t %t/DefinesExtension.swift -module-name DefinesExtension
14+
// RUN: %target-swift-typecheck-module-from-interface(%t/DefinesExtension.swiftinterface) -I %t -module-name DefinesExtension
15+
16+
// RUN: %target-swift-emit-module-interface(%t/Client.swiftinterface) -verify -I %t %t/File2.swift %t/File1.swift -module-name Client
17+
// RUN: %target-swift-typecheck-module-from-interface(%t/Client.swiftinterface) -I %t -module-name Client
18+
// RUN: %FileCheck %t/File2.swift < %t/Client.swiftinterface
19+
20+
//--- DefinesProtocol.swift
21+
22+
public protocol P {}
23+
24+
//--- DefinesTypealias.swift
25+
26+
import DefinesProtocol
27+
28+
public typealias Q = P
29+
30+
//--- DefinesStruct.swift
31+
32+
public struct C {}
33+
34+
//--- DefinesExtension.swift
35+
36+
import DefinesStruct
37+
38+
extension C {
39+
public func foo() {}
40+
}
41+
42+
//--- File1.swift
43+
44+
import DefinesExtension
45+
46+
//--- File2.swift
47+
48+
// CHECK: import DefinesExtension
49+
// CHECK-NEXT: import DefinesProtocol
50+
// CHECK-NEXT: import DefinesStruct
51+
// CHECK-NEXT: import DefinesTypealias
52+
53+
import DefinesTypealias
54+
import DefinesStruct
55+
56+
public func takesQ<T>(_ b: T) where T: Q { }
57+
// expected-warning @-1 {{'Q' aliases 'DefinesProtocol.P' and cannot be used here because 'DefinesProtocol' was not imported by this file; this is an error in Swift 6}}
58+
// expected-note @-2 {{The missing import of module 'DefinesProtocol' will be added implicitly}}
59+
60+
@inlinable public func takesC(_ c: C) {
61+
c.foo()
62+
// expected-warning @-1 {{instance method 'foo()' cannot be used in an '@inlinable' function because 'DefinesExtension' was not imported by this file; this is an error in Swift 6}}
63+
// expected-note @-2 {{The missing import of module 'DefinesExtension' will be added implicitly}}
64+
}

0 commit comments

Comments
 (0)