Skip to content

Commit e146630

Browse files
author
Nathan Hawes
committed
[ParseableInterface] Fix failing to build a module when the importing file has errors.
We were checking the parent invocation's DiagnosticEnginer rather than the subinstance's to determine if there were any errors building the module, which meant we would fail to load the module if there were errors prior to the import statement in the importing file. This also meant code completion would fail to load the module, because it always emits a bogus error in order to mark the AST as erroneous so that different parts of the compiler (e.g. the verifier) have less strict assumptions. rdar://problem/43906499
1 parent 4fa53c1 commit e146630

File tree

6 files changed

+80
-1
lines changed

6 files changed

+80
-1
lines changed

lib/Frontend/ParseableInterfaceSupport.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -452,7 +452,7 @@ bool ParseableInterfaceModuleLoader::buildSwiftModuleFromSwiftInterface(
452452
return;
453453
}
454454

455-
SubError = Diags.hadAnyError();
455+
SubError = SubInstance.getDiags().hadAnyError();
456456
});
457457
return !RunSuccess || SubError;
458458
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %empty-directory(%t/modulecache)
3+
//
4+
// Setup builds a parseable interface for a module SomeModule (built from some-module.swift).
5+
// This test checks we still build and load its corresponding .swiftmodule when the file that imports it contains an error prior to the import statement.
6+
7+
// Setup phase 1: Write the input file.
8+
//
9+
// RUN: echo 'public func SomeFunc() -> Int { return 42; }' >>%t/some-module.swift
10+
11+
// Setup phase 2: build the module.
12+
//
13+
// RUN: %target-swift-frontend -I %t -emit-parseable-module-interface-path %t/SomeModule.swiftinterface -module-name SomeModule %t/some-module.swift -emit-module -o /dev/null
14+
15+
// Actual test: compile and verify the import succeeds (i.e. we only report the error in this file)
16+
//
17+
// RUN: %target-swift-frontend -typecheck -verify -I %t -module-cache-path %t/modulecache -enable-parseable-module-interface %s
18+
19+
unresolved // expected-error {{use of unresolved identifier 'unresolved'}}
20+
21+
import SomeModule
22+
23+
print(SomeFunc())
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
public struct MyPoint {
2+
public let x: Double
3+
public let y: Double
4+
5+
public init(x: Double, y: Double) {
6+
self.x = x
7+
self.y = y
8+
}
9+
10+
public var magnitudeSquared: Double {
11+
return x*x + y*y
12+
}
13+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import MyPoint
2+
3+
public extension MyPoint {
4+
var magnitude: Double {
5+
return magnitudeSquared.squareRoot()
6+
}
7+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %empty-directory(%t/modulecache)
3+
4+
// 1) Build .swiftinterface files for MyPoint and MyExtensions, using a non-default module cache path
5+
// RUN: %target-swift-frontend -emit-parseable-module-interface-path %t/MyPoint.swiftinterface -module-name MyPoint -emit-module -o /dev/null %S/Inputs/parseable-interface/MyPoint.swift
6+
// RUN: %target-swift-frontend -emit-parseable-module-interface-path %t/MyPointExtensions.swiftinterface -module-name MyPointExtensions -emit-module -o /dev/null -enable-parseable-module-interface -module-cache-path %t/modulecache -I %t %S/Inputs/parseable-interface/MyPointExtensions.swift
7+
// RUN: %empty-directory(%t/modulecache)
8+
9+
// 2) Check completion using the default (cold) module cache
10+
// RUN: %target-swift-ide-test -code-completion -code-completion-token=MEMBER -source-filename %s -I %t | %FileCheck %s
11+
12+
// 3) Check completion again with a warm module cache
13+
// RUN: %target-swift-ide-test -code-completion -code-completion-token=MEMBER -source-filename %s -I %t | %FileCheck %s
14+
15+
import MyPoint
16+
import MyPointExtensions
17+
18+
let x = MyPoint(x: 1, y: 10.5)
19+
20+
print(x.#^MEMBER^#)
21+
22+
// CHECK: Begin completions, 5 items
23+
// CHECK: Keyword[self]/CurrNominal: self[#MyPoint#]; name=self
24+
// CHECK: Decl[InstanceVar]/CurrNominal: x[#Double#]; name=x
25+
// CHECK: Decl[InstanceVar]/CurrNominal: y[#Double#]; name=y
26+
// CHECK: Decl[InstanceVar]/CurrNominal: magnitudeSquared[#Double#]; name=magnitudeSquared
27+
// CHECK: Decl[InstanceVar]/CurrNominal: magnitude[#Double#]; name=magnitude
28+
// CHECK: End completions

tools/swift-ide-test/swift-ide-test.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,12 @@ static llvm::cl::opt<std::string>
264264
ModuleCachePath("module-cache-path", llvm::cl::desc("Clang module cache path"),
265265
llvm::cl::cat(Category));
266266

267+
static llvm::cl::opt<bool>
268+
EnableParseableModuleInterface("enable-parseable-module-interface",
269+
llvm::cl::desc("Enable loading .swiftinterface files when available"),
270+
llvm::cl::cat(Category),
271+
llvm::cl::init(true));
272+
267273
static llvm::cl::opt<std::string>
268274
PCHOutputDir("pch-output-dir",
269275
llvm::cl::desc("place autogenerated PCH files in this directory"),
@@ -3201,6 +3207,8 @@ int main(int argc, char *argv[]) {
32013207
InitInvok.getLangOptions().EffectiveLanguageVersion = actual.getValue();
32023208
}
32033209
}
3210+
InitInvok.getFrontendOptions().EnableParseableModuleInterface =
3211+
options::EnableParseableModuleInterface;
32043212
InitInvok.getClangImporterOptions().ModuleCachePath =
32053213
options::ModuleCachePath;
32063214
InitInvok.getClangImporterOptions().PrecompiledHeaderOutputDir =

0 commit comments

Comments
 (0)