Skip to content

Commit bc0dfb8

Browse files
committed
[Macros] Return plugin loading error as result
Instead of emitting an warning to the diagnostic engine, return the plugin loading error as the result of the request. So that the user can decide to emit it as a warning or an error.
1 parent 58fa6ca commit bc0dfb8

File tree

13 files changed

+173
-68
lines changed

13 files changed

+173
-68
lines changed

include/swift/AST/DiagnosticsFrontend.def

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -536,9 +536,6 @@ REMARK(warning_in_access_notes_file,none,
536536
"ignored invalid content in access notes file: %0",
537537
(StringRef))
538538

539-
WARNING(compiler_plugin_not_loaded,none,
540-
"compiler plugin not loaded: %0; loader error: %1", (StringRef, StringRef))
541-
542539
ERROR(dont_enable_interop_and_compat,none,
543540
"do not pass both '-enable-experimental-cxx-interop' and "
544541
"'-cxx-interoperability-mode'; remove '-enable-experimental-cxx-interop'", ())

include/swift/AST/MacroDefinition.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,8 @@ struct ExternalMacroDefinition {
4343
static_cast<const void *>(message.data())};
4444
}
4545
bool isError() const { return kind == PluginKind::Error; }
46-
llvm::StringRef getErrorMessage() const {
47-
return llvm::StringRef(static_cast<const char *>(opaqueHandle));
46+
NullTerminatedStringRef getErrorMessage() const {
47+
return static_cast<const char *>(opaqueHandle);
4848
}
4949
};
5050

include/swift/AST/PluginLoader.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,14 +76,15 @@ class PluginLoader {
7676
/// returns a nullptr.
7777
/// NOTE: This method is idempotent. If the plugin is already loaded, the same
7878
/// instance is simply returned.
79-
LoadedLibraryPlugin *loadLibraryPlugin(llvm::StringRef path);
79+
llvm::Expected<LoadedLibraryPlugin *> loadLibraryPlugin(llvm::StringRef path);
8080

8181
/// Launch the specified executable plugin path resolving the path with the
8282
/// current VFS. If it fails to load the plugin, a diagnostic is emitted, and
8383
/// returns a nullptr.
8484
/// NOTE: This method is idempotent. If the plugin is already loaded, the same
8585
/// instance is simply returned.
86-
LoadedExecutablePlugin *loadExecutablePlugin(llvm::StringRef path);
86+
llvm::Expected<LoadedExecutablePlugin *>
87+
loadExecutablePlugin(llvm::StringRef path);
8788
};
8889

8990
} // namespace swift

include/swift/AST/TypeCheckRequests.h

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4214,34 +4214,57 @@ class ExpandSynthesizedMemberMacroRequest
42144214
};
42154215

42164216
/// Represent a loaded plugin either an in-process library or an executable.
4217-
class LoadedCompilerPlugin {
4218-
llvm::PointerUnion<LoadedLibraryPlugin *, LoadedExecutablePlugin *> ptr;
4217+
class CompilerPluginLoadResult {
4218+
enum class PluginKind : uint8_t {
4219+
Error = 0,
4220+
Library,
4221+
Executable,
4222+
};
4223+
PluginKind Kind;
4224+
void *opaqueHandle;
4225+
4226+
CompilerPluginLoadResult(PluginKind K, void *opaque)
4227+
: Kind(K), opaqueHandle(opaque) {}
42194228

42204229
public:
4221-
LoadedCompilerPlugin(std::nullptr_t) : ptr(nullptr) {}
4222-
LoadedCompilerPlugin(LoadedLibraryPlugin *ptr) : ptr(ptr){};
4223-
LoadedCompilerPlugin(LoadedExecutablePlugin *ptr) : ptr(ptr){};
4230+
CompilerPluginLoadResult(LoadedLibraryPlugin *ptr)
4231+
: CompilerPluginLoadResult(PluginKind::Library, ptr){};
4232+
CompilerPluginLoadResult(LoadedExecutablePlugin *ptr)
4233+
: CompilerPluginLoadResult(PluginKind::Executable, ptr){};
4234+
static CompilerPluginLoadResult error(NullTerminatedStringRef message) {
4235+
return CompilerPluginLoadResult(PluginKind::Error,
4236+
const_cast<char *>(message.data()));
4237+
}
42244238

42254239
LoadedLibraryPlugin *getAsLibraryPlugin() const {
4226-
return ptr.dyn_cast<LoadedLibraryPlugin *>();
4240+
if (Kind != PluginKind::Library)
4241+
return nullptr;
4242+
return static_cast<LoadedLibraryPlugin *>(opaqueHandle);
42274243
}
42284244
LoadedExecutablePlugin *getAsExecutablePlugin() const {
4229-
return ptr.dyn_cast<LoadedExecutablePlugin *>();
4245+
if (Kind != PluginKind::Executable)
4246+
return nullptr;
4247+
return static_cast<LoadedExecutablePlugin *>(opaqueHandle);
4248+
}
4249+
bool isError() const { return Kind == PluginKind::Error; }
4250+
NullTerminatedStringRef getErrorMessage() const {
4251+
assert(isError());
4252+
return static_cast<const char *>(opaqueHandle);
42304253
}
42314254
};
42324255

42334256
class CompilerPluginLoadRequest
42344257
: public SimpleRequest<CompilerPluginLoadRequest,
4235-
LoadedCompilerPlugin(ASTContext *, Identifier),
4258+
CompilerPluginLoadResult(ASTContext *, Identifier),
42364259
RequestFlags::Cached> {
42374260
public:
42384261
using SimpleRequest::SimpleRequest;
42394262

42404263
private:
42414264
friend SimpleRequest;
42424265

4243-
LoadedCompilerPlugin evaluate(Evaluator &evaluator, ASTContext *ctx,
4244-
Identifier moduleName) const;
4266+
CompilerPluginLoadResult evaluate(Evaluator &evaluator, ASTContext *ctx,
4267+
Identifier moduleName) const;
42454268

42464269
public:
42474270
// Source location

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -454,7 +454,7 @@ SWIFT_REQUEST(TypeChecker, MacroDefinitionRequest,
454454
MacroDefinition(MacroDecl *),
455455
Cached, NoLocationInfo)
456456
SWIFT_REQUEST(TypeChecker, CompilerPluginLoadRequest,
457-
LoadedCompilerPlugin(ASTContext *, Identifier),
457+
CompilerPluginLoadResult(ASTContext *, Identifier),
458458
Cached, NoLocationInfo)
459459
SWIFT_REQUEST(TypeChecker, ExternalMacroDefinitionRequest,
460460
ExternalMacroDefinition(ASTContext *, Identifier, Identifier),

include/swift/Basic/StringExtras.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -497,6 +497,10 @@ class NullTerminatedStringRef {
497497
NullTerminatedStringRef(llvm::Twine Str, Allocator &A) : Ref("") {
498498
if (Str.isTriviallyEmpty())
499499
return;
500+
if (Str.isSingleStringLiteral()) {
501+
Ref = Str.getSingleStringRef();
502+
return;
503+
}
500504
llvm::SmallString<0> stash;
501505
auto _ref = Str.toStringRef(stash);
502506

lib/AST/PluginLoader.cpp

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -158,13 +158,12 @@ PluginLoader::lookupPluginByModuleName(Identifier moduleName) {
158158
}
159159
}
160160

161-
LoadedLibraryPlugin *PluginLoader::loadLibraryPlugin(StringRef path) {
161+
llvm::Expected<LoadedLibraryPlugin *>
162+
PluginLoader::loadLibraryPlugin(StringRef path) {
162163
auto fs = Ctx.SourceMgr.getFileSystem();
163164
SmallString<128> resolvedPath;
164165
if (auto err = fs->getRealPath(path, resolvedPath)) {
165-
Ctx.Diags.diagnose(SourceLoc(), diag::compiler_plugin_not_loaded, path,
166-
err.message());
167-
return nullptr;
166+
return llvm::createStringError(err, err.message());
168167
}
169168

170169
// Track the dependency.
@@ -174,21 +173,25 @@ LoadedLibraryPlugin *PluginLoader::loadLibraryPlugin(StringRef path) {
174173
// Load the plugin.
175174
auto plugin = getRegistry()->loadLibraryPlugin(resolvedPath);
176175
if (!plugin) {
177-
Ctx.Diags.diagnose(SourceLoc(), diag::compiler_plugin_not_loaded, path,
178-
llvm::toString(plugin.takeError()));
179-
return nullptr;
176+
resolvedPath.push_back(0);
177+
return llvm::handleErrors(
178+
plugin.takeError(), [&](const llvm::ErrorInfoBase &err) {
179+
return llvm::createStringError(
180+
err.convertToErrorCode(),
181+
"compiler plugin not loaded: %s; loader error: %s",
182+
resolvedPath.data(), err.message().data());
183+
});
180184
}
181185

182-
return plugin.get();
186+
return plugin;
183187
}
184188

185-
LoadedExecutablePlugin *PluginLoader::loadExecutablePlugin(StringRef path) {
189+
llvm::Expected<LoadedExecutablePlugin *>
190+
PluginLoader::loadExecutablePlugin(StringRef path) {
186191
auto fs = Ctx.SourceMgr.getFileSystem();
187192
SmallString<128> resolvedPath;
188193
if (auto err = fs->getRealPath(path, resolvedPath)) {
189-
Ctx.Diags.diagnose(SourceLoc(), diag::compiler_plugin_not_loaded, path,
190-
err.message());
191-
return nullptr;
194+
return llvm::createStringError(err, err.message());
192195
}
193196

194197
// Track the dependency.
@@ -198,10 +201,15 @@ LoadedExecutablePlugin *PluginLoader::loadExecutablePlugin(StringRef path) {
198201
// Load the plugin.
199202
auto plugin = getRegistry()->loadExecutablePlugin(resolvedPath);
200203
if (!plugin) {
201-
Ctx.Diags.diagnose(SourceLoc(), diag::compiler_plugin_not_loaded, path,
202-
llvm::toString(plugin.takeError()));
203-
return nullptr;
204+
resolvedPath.push_back(0);
205+
return llvm::handleErrors(
206+
plugin.takeError(), [&](const llvm::ErrorInfoBase &err) {
207+
return llvm::createStringError(
208+
err.convertToErrorCode(),
209+
"compiler plugin not loaded: %s; loader error: %s",
210+
resolvedPath.data(), err.message().data());
211+
});
204212
}
205213

206-
return plugin.get();
214+
return plugin;
207215
}

lib/ASTGen/Sources/ASTGen/PluginHost.swift

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,8 @@ public func _initializePlugin(
3737
try plugin.initialize()
3838
return true
3939
} catch {
40-
diagEngine?.diagnose(
41-
message: "compiler plugin not loaded: '\(plugin.executableFilePath); failed to initialize",
42-
severity: .warning)
40+
// Don't care the actual error. Probably the plugin is completely broken.
41+
// The failure is diagnosed in the caller.
4342
return false
4443
}
4544
}

lib/Sema/TypeCheckMacros.cpp

Lines changed: 48 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,7 @@ MacroDefinition MacroDefinitionRequest::evaluate(
284284
#endif
285285
}
286286

287-
static LoadedExecutablePlugin *
287+
static llvm::Expected<LoadedExecutablePlugin *>
288288
initializeExecutablePlugin(ASTContext &ctx,
289289
LoadedExecutablePlugin *executablePlugin,
290290
StringRef libraryPath, Identifier moduleName) {
@@ -298,7 +298,10 @@ initializeExecutablePlugin(ASTContext &ctx,
298298
if (!executablePlugin->isInitialized()) {
299299
#if SWIFT_BUILD_SWIFT_SYNTAX
300300
if (!swift_ASTGen_initializePlugin(executablePlugin, &ctx.Diags)) {
301-
return nullptr;
301+
return llvm::createStringError(
302+
llvm::inconvertibleErrorCode(),
303+
"failed to initialize executable plugin '" +
304+
StringRef(executablePlugin->getExecutablePath()) + "'");
302305
}
303306

304307
// Resend the compiler capability on reconnect.
@@ -321,9 +324,7 @@ initializeExecutablePlugin(ASTContext &ctx,
321324
llvm::SmallString<128> resolvedLibraryPath;
322325
auto fs = ctx.SourceMgr.getFileSystem();
323326
if (auto err = fs->getRealPath(libraryPath, resolvedLibraryPath)) {
324-
ctx.Diags.diagnose(SourceLoc(), diag::compiler_plugin_not_loaded,
325-
executablePlugin->getExecutablePath(), err.message());
326-
return nullptr;
327+
return llvm::createStringError(err, err.message());
327328
}
328329
std::string resolvedLibraryPathStr(resolvedLibraryPath);
329330
std::string moduleNameStr(moduleName.str());
@@ -332,7 +333,11 @@ initializeExecutablePlugin(ASTContext &ctx,
332333
executablePlugin, resolvedLibraryPathStr.c_str(), moduleNameStr.c_str(),
333334
&ctx.Diags);
334335
if (!loaded)
335-
return nullptr;
336+
return llvm::createStringError(
337+
llvm::inconvertibleErrorCode(),
338+
"failed to load library plugin '" + resolvedLibraryPathStr +
339+
"' in plugin server '" +
340+
StringRef(executablePlugin->getExecutablePath()) + "'");
336341

337342
// Set a callback to load the library again on reconnections.
338343
auto *callback = new std::function<void(void)>(
@@ -355,37 +360,59 @@ initializeExecutablePlugin(ASTContext &ctx,
355360
return executablePlugin;
356361
}
357362

358-
LoadedCompilerPlugin
363+
CompilerPluginLoadResult
359364
CompilerPluginLoadRequest::evaluate(Evaluator &evaluator, ASTContext *ctx,
360365
Identifier moduleName) const {
361366
PluginLoader &loader = ctx->getPluginLoader();
362367
const auto &entry = loader.lookupPluginByModuleName(moduleName);
363368

369+
std::string errorMessage;
370+
364371
if (!entry.executablePath.empty()) {
365-
if (LoadedExecutablePlugin *executablePlugin =
366-
loader.loadExecutablePlugin(entry.executablePath)) {
372+
llvm::Expected<LoadedExecutablePlugin *> executablePlugin =
373+
loader.loadExecutablePlugin(entry.executablePath);
374+
if (executablePlugin) {
367375
if (ctx->LangOpts.EnableMacroLoadingRemarks) {
368376
unsigned tag = entry.libraryPath.empty() ? 1 : 2;
369377
ctx->Diags.diagnose(SourceLoc(), diag::macro_loaded, moduleName, tag,
370378
entry.executablePath, entry.libraryPath);
371379
}
372380

373-
return initializeExecutablePlugin(*ctx, executablePlugin,
374-
entry.libraryPath, moduleName);
381+
executablePlugin = initializeExecutablePlugin(
382+
*ctx, executablePlugin.get(), entry.libraryPath, moduleName);
375383
}
384+
if (executablePlugin)
385+
return executablePlugin.get();
386+
llvm::handleAllErrors(
387+
executablePlugin.takeError(),
388+
[&](const llvm::ErrorInfoBase &err) { errorMessage += err.message(); });
376389
} else if (!entry.libraryPath.empty()) {
377-
if (LoadedLibraryPlugin *libraryPlugin =
378-
loader.loadLibraryPlugin(entry.libraryPath)) {
390+
391+
llvm::Expected<LoadedLibraryPlugin *> libraryPlugin =
392+
loader.loadLibraryPlugin(entry.libraryPath);
393+
if (libraryPlugin) {
379394
if (ctx->LangOpts.EnableMacroLoadingRemarks) {
380395
ctx->Diags.diagnose(SourceLoc(), diag::macro_loaded, moduleName, 0,
381396
entry.libraryPath, StringRef());
382397
}
383398

384-
return libraryPlugin;
399+
return libraryPlugin.get();
400+
} else {
401+
llvm::handleAllErrors(libraryPlugin.takeError(),
402+
[&](const llvm::ErrorInfoBase &err) {
403+
errorMessage += err.message();
404+
});
385405
}
386406
}
387-
388-
return nullptr;
407+
if (!errorMessage.empty()) {
408+
NullTerminatedStringRef err(errorMessage, *ctx);
409+
return CompilerPluginLoadResult::error(err);
410+
} else {
411+
NullTerminatedStringRef errMsg("plugin that can handle module '" +
412+
moduleName.str() + "' not found",
413+
*ctx);
414+
return CompilerPluginLoadResult::error(errMsg);
415+
}
389416
}
390417

391418
static ExternalMacroDefinition
@@ -439,6 +466,8 @@ resolveExecutableMacro(ASTContext &ctx,
439466
return ExternalMacroDefinition{
440467
ExternalMacroDefinition::PluginKind::Executable, execMacro};
441468
}
469+
// NOTE: this is not reachable because executable macro resolution always
470+
// succeeds.
442471
NullTerminatedStringRef err(
443472
"macro implementation type '" + moduleName.str() + "." + typeName.str() +
444473
"' could not be found in executable plugin" +
@@ -456,8 +485,8 @@ ExternalMacroDefinitionRequest::evaluate(Evaluator &evaluator, ASTContext *ctx,
456485
// Try to load a plugin module from the plugin search paths. If it
457486
// succeeds, resolve in-process from that plugin
458487
CompilerPluginLoadRequest loadRequest{ctx, moduleName};
459-
LoadedCompilerPlugin loaded =
460-
evaluateOrDefault(evaluator, loadRequest, nullptr);
488+
CompilerPluginLoadResult loaded = evaluateOrDefault(
489+
evaluator, loadRequest, CompilerPluginLoadResult::error("request error"));
461490

462491
if (auto loadedLibrary = loaded.getAsLibraryPlugin()) {
463492
return resolveInProcessMacro(*ctx, moduleName, typeName, loadedLibrary);
@@ -467,10 +496,7 @@ ExternalMacroDefinitionRequest::evaluate(Evaluator &evaluator, ASTContext *ctx,
467496
return resolveExecutableMacro(*ctx, executablePlugin, moduleName, typeName);
468497
}
469498

470-
NullTerminatedStringRef err("plugin that can handle module '" +
471-
moduleName.str() + "' not found",
472-
*ctx);
473-
return ExternalMacroDefinition::error(err);
499+
return ExternalMacroDefinition::error(loaded.getErrorMessage());
474500
}
475501

476502
/// Adjust the given mangled name for a macro expansion to produce a valid

test/Macros/macro_plugin_broken.swift

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,8 @@
1818

1919
// RUN: c-index-test -read-diagnostics %t/macro_expand.dia 2>&1 | %FileCheck -check-prefix CHECK %s
2020

21-
// CHECK: (null):0:0: warning: compiler plugin not loaded: {{.+}}broken-plugin; failed to initialize
22-
// CHECK: test.swift:1:33: warning: external macro implementation type 'TestPlugin.FooMacro' could not be found for macro 'fooMacro'
23-
// CHECK: test.swift:4:7: error: external macro implementation type 'TestPlugin.FooMacro' could not be found for macro 'fooMacro'
21+
// CHECK: test.swift:1:33: warning: external macro implementation type 'TestPlugin.FooMacro' could not be found for macro 'fooMacro'; failed to initialize executable plugin '{{.*}}broken-plugin'
22+
// CHECK: test.swift:4:7: error: external macro implementation type 'TestPlugin.FooMacro' could not be found for macro 'fooMacro'; failed to initialize executable plugin '{{.*}}broken-plugin'
2423
// CHECK: +-{{.+}}test.swift:1:33: note: 'fooMacro' declared here
2524

2625
//--- test.swift

0 commit comments

Comments
 (0)