Skip to content

Commit 58388a2

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 04ca7e2 commit 58388a2

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
@@ -268,6 +268,12 @@ static llvm::cl::opt<std::string>
268268
ModuleCachePath("module-cache-path", llvm::cl::desc("Clang module cache path"),
269269
llvm::cl::cat(Category));
270270

271+
static llvm::cl::opt<bool>
272+
EnableParseableModuleInterface("enable-parseable-module-interface",
273+
llvm::cl::desc("Enable loading .swiftinterface files when available"),
274+
llvm::cl::cat(Category),
275+
llvm::cl::init(true));
276+
271277
static llvm::cl::opt<std::string>
272278
PCHOutputDir("pch-output-dir",
273279
llvm::cl::desc("place autogenerated PCH files in this directory"),
@@ -3256,6 +3262,8 @@ int main(int argc, char *argv[]) {
32563262
InitInvok.getLangOptions().EffectiveLanguageVersion = actual.getValue();
32573263
}
32583264
}
3265+
InitInvok.getFrontendOptions().EnableParseableModuleInterface =
3266+
options::EnableParseableModuleInterface;
32593267
InitInvok.getClangImporterOptions().ModuleCachePath =
32603268
options::ModuleCachePath;
32613269
InitInvok.getClangImporterOptions().PrecompiledHeaderOutputDir =

0 commit comments

Comments
 (0)