Skip to content

Commit bbbf02e

Browse files
authored
Merge pull request #19415 from jckarter/better-missing-metadata-warnings
Make runtime warnings about missing metadata more descriptive.
2 parents 13468cf + e9b4517 commit bbbf02e

File tree

4 files changed

+82
-13
lines changed

4 files changed

+82
-13
lines changed

include/swift/Runtime/Debug.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,10 @@ SWIFT_RUNTIME_ATTRIBUTE_NORETURN
8787
extern void
8888
fatalError(uint32_t flags, const char *format, ...);
8989

90+
/// swift::warning() emits a warning from the runtime.
91+
extern void
92+
warningv(uint32_t flags, const char *format, va_list args);
93+
9094
/// swift::warning() emits a warning from the runtime.
9195
extern void
9296
warning(uint32_t flags, const char *format, ...);

stdlib/public/runtime/Errors.cpp

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -352,22 +352,29 @@ swift::fatalError(uint32_t flags, const char *format, ...)
352352

353353
// Report a warning to system console and stderr.
354354
void
355-
swift::warning(uint32_t flags, const char *format, ...)
355+
swift::warningv(uint32_t flags, const char *format, va_list args)
356356
{
357-
va_list args;
358-
va_start(args, format);
359-
360357
char *log;
361358
#pragma GCC diagnostic push
362359
#pragma GCC diagnostic ignored "-Wuninitialized"
363360
swift_vasprintf(&log, format, args);
364361
#pragma GCC diagnostic pop
365-
362+
366363
reportNow(flags, log);
367-
364+
368365
free(log);
369366
}
370367

368+
// Report a warning to system console and stderr.
369+
void
370+
swift::warning(uint32_t flags, const char *format, ...)
371+
{
372+
va_list args;
373+
va_start(args, format);
374+
375+
warningv(flags, format, args);
376+
}
377+
371378
// Crash when a deleted method is called by accident.
372379
SWIFT_RUNTIME_EXPORT
373380
LLVM_ATTRIBUTE_NORETURN

stdlib/public/runtime/ReflectionMirror.mm

Lines changed: 53 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
//
1111
//===----------------------------------------------------------------------===//
1212

13+
#include "swift/Basic/Lazy.h"
1314
#include "swift/Runtime/Reflection.h"
1415
#include "swift/Runtime/Casting.h"
1516
#include "swift/Runtime/Config.h"
@@ -253,6 +254,47 @@ AnyReturn subscript(intptr_t i, const char **outName,
253254
return AnyReturn(result);
254255
}
255256
};
257+
258+
struct swift_closure {
259+
void *fptr;
260+
HeapObject *context;
261+
};
262+
SWIFT_RUNTIME_STDLIB_API SWIFT_CC(swift) swift_closure
263+
MANGLE_SYM(s20_playgroundPrintHookySScSgvg)();
264+
265+
static bool _shouldReportMissingReflectionMetadataWarnings() {
266+
// Missing metadata warnings noise up playground sessions and aren't really
267+
// actionable in playground contexts. If we're running in a playground,
268+
// suppress warnings.
269+
//
270+
// Guesstimate whether we're in a playground by looking at the
271+
// _playgroundPrintHook variable in the standard library, which is set during
272+
// playground execution.
273+
auto hook = MANGLE_SYM(s20_playgroundPrintHookySScSgvg)();
274+
if (hook.fptr) {
275+
swift_release(hook.context);
276+
return false;
277+
} else {
278+
return true;
279+
}
280+
}
281+
282+
/// Raise a warning about reflection metadata that could not be found
283+
/// at runtime. This is usually mostly harmless, but it's good to alert
284+
/// users that it happens.
285+
static void
286+
missing_reflection_metadata_warning(const char *fmt, ...) {
287+
bool shouldWarn =
288+
SWIFT_LAZY_CONSTANT(_shouldReportMissingReflectionMetadataWarnings());
289+
290+
if (!shouldWarn)
291+
return;
292+
293+
va_list args;
294+
va_start(args, fmt);
295+
296+
warningv(0, fmt, args);
297+
}
256298

257299
static std::pair<StringRef /*name*/, FieldType /*fieldInfo*/>
258300
getFieldAt(const Metadata *base, unsigned index) {
@@ -262,9 +304,11 @@ AnyReturn subscript(intptr_t i, const char **outName,
262304
// back to returning an empty tuple as a standin.
263305
auto failedToFindMetadata = [&]() -> std::pair<StringRef, FieldType> {
264306
auto typeName = swift_getTypeName(base, /*qualified*/ true);
265-
warning(0, "SWIFT RUNTIME BUG: no field metadata for type '%*s' that claims "
266-
"to be reflectable\n",
267-
(int)typeName.length, typeName.data);
307+
missing_reflection_metadata_warning(
308+
"warning: the Swift runtime found no field metadata for "
309+
"type '%*s' that claims to be reflectable. Its fields will show up as "
310+
"'unknown' in Mirrors\n",
311+
(int)typeName.length, typeName.data);
268312
return {"unknown",
269313
FieldType()
270314
.withType(TypeInfo(&METADATA_SYM(EMPTY_TUPLE_MANGLING), {}))
@@ -331,10 +375,12 @@ AnyReturn subscript(intptr_t i, const char **outName,
331375
// a log message.
332376
if (typeInfo == nullptr) {
333377
typeInfo = TypeInfo(&METADATA_SYM(EMPTY_TUPLE_MANGLING), {});
334-
warning(0, "SWIFT RUNTIME BUG: unable to demangle type of field '%*s'. "
335-
"mangled type name is '%*s'\n",
336-
(int)name.size(), name.data(),
337-
(int)typeName.size(), typeName.data());
378+
missing_reflection_metadata_warning(
379+
"warning: the Swift runtime was unable to demangle the type "
380+
"of field '%*s'. the mangled type name is '%*s'. this field will "
381+
"show up as an empty tuple in Mirrors\n",
382+
(int)name.size(), name.data(),
383+
(int)typeName.size(), typeName.data());
338384
}
339385

340386
return {name, FieldType()

unittests/runtime/Stdlib.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,3 +259,15 @@ SWIFT_RUNTIME_STDLIB_SPI
259259
const HeapObject *swift_getKeyPathImpl(const void *p, const void *a) {
260260
abort();
261261
}
262+
263+
// playground print hook
264+
265+
struct swift_closure {
266+
void *fptr;
267+
HeapObject *context;
268+
};
269+
SWIFT_RUNTIME_STDLIB_API SWIFT_CC(swift) swift_closure
270+
MANGLE_SYM(s20_playgroundPrintHookySScSgvg)() {
271+
return {nullptr, nullptr};
272+
}
273+

0 commit comments

Comments
 (0)