Merge pull request #19416 from jckarter/better-missing-metadata-warnings-4.2
[4.2] Make runtime warnings about missing metadata more descriptive.
diff --git a/include/swift/Runtime/Debug.h b/include/swift/Runtime/Debug.h
index 792eb85..a575286 100644
--- a/include/swift/Runtime/Debug.h
+++ b/include/swift/Runtime/Debug.h
@@ -97,6 +97,10 @@
/// swift::warning() emits a warning from the runtime.
extern void
+warningv(uint32_t flags, const char *format, va_list args);
+
+/// swift::warning() emits a warning from the runtime.
+extern void
warning(uint32_t flags, const char *format, ...);
// swift_dynamicCastFailure halts using fatalError()
diff --git a/stdlib/public/runtime/Errors.cpp b/stdlib/public/runtime/Errors.cpp
index c3f1781..ff49065 100644
--- a/stdlib/public/runtime/Errors.cpp
+++ b/stdlib/public/runtime/Errors.cpp
@@ -349,22 +349,29 @@
// Report a warning to system console and stderr.
void
-swift::warning(uint32_t flags, const char *format, ...)
+swift::warningv(uint32_t flags, const char *format, va_list args)
{
- va_list args;
- va_start(args, format);
-
char *log;
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wuninitialized"
swift_vasprintf(&log, format, args);
#pragma GCC diagnostic pop
-
+
reportNow(flags, log);
-
+
free(log);
}
+// Report a warning to system console and stderr.
+void
+swift::warning(uint32_t flags, const char *format, ...)
+{
+ va_list args;
+ va_start(args, format);
+
+ warningv(flags, format, args);
+}
+
// Crash when a deleted method is called by accident.
SWIFT_RUNTIME_EXPORT
LLVM_ATTRIBUTE_NORETURN
diff --git a/stdlib/public/runtime/MetadataLookup.cpp b/stdlib/public/runtime/MetadataLookup.cpp
index be28b62..d8344b7 100644
--- a/stdlib/public/runtime/MetadataLookup.cpp
+++ b/stdlib/public/runtime/MetadataLookup.cpp
@@ -1115,6 +1115,47 @@
});
}
+struct swift_closure {
+ void *fptr;
+ HeapObject *context;
+};
+SWIFT_RUNTIME_STDLIB_API SWIFT_CC(swift) swift_closure
+MANGLE_SYM(s20_playgroundPrintHookySScSgvg)();
+
+static bool _shouldReportMissingReflectionMetadataWarnings() {
+ // Missing metadata warnings noise up playground sessions and aren't really
+ // actionable in playground contexts. If we're running in a playground,
+ // suppress warnings.
+ //
+ // Guesstimate whether we're in a playground by looking at the
+ // _playgroundPrintHook variable in the standard library, which is set during
+ // playground execution.
+ auto hook = MANGLE_SYM(s20_playgroundPrintHookySScSgvg)();
+ if (hook.fptr) {
+ swift_release(hook.context);
+ return false;
+ } else {
+ return true;
+ }
+}
+
+/// Raise a warning about reflection metadata that could not be found
+/// at runtime. This is usually mostly harmless, but it's good to alert
+/// users that it happens.
+static void
+missing_reflection_metadata_warning(const char *fmt, ...) {
+ bool shouldWarn =
+ SWIFT_LAZY_CONSTANT(_shouldReportMissingReflectionMetadataWarnings());
+
+ if (!shouldWarn)
+ return;
+
+ va_list args;
+ va_start(args, fmt);
+
+ warningv(0, fmt, args);
+}
+
void swift::swift_getFieldAt(
const Metadata *base, unsigned index,
void (*callback)(const char *name, const Metadata *type, void *ctx), void *callbackCtx) {
@@ -1182,10 +1223,12 @@
// a log message.
if (typeInfo == nullptr) {
typeInfo = TypeInfo(&METADATA_SYM(EMPTY_TUPLE_MANGLING), {});
- warning(0, "SWIFT RUNTIME BUG: unable to demangle type of field '%*s'. "
- "mangled type name is '%*s'\n",
- (int)name.size(), name.data(),
- (int)typeName.size(), typeName.data());
+ missing_reflection_metadata_warning(
+ "warning: the Swift runtime was unable to demangle the type "
+ "of field '%*s'. the mangled type name is '%*s'. this field will "
+ "show up as an empty tuple in Mirrors\n",
+ (int)name.size(), name.data(),
+ (int)typeName.size(), typeName.data());
}
callback(name, FieldType()
@@ -1235,8 +1278,11 @@
// If we failed to find the field descriptor metadata for the type, fall
// back to returning an empty tuple as a standin.
auto typeName = swift_getTypeName(base, /*qualified*/ true);
- warning(0, "SWIFT RUNTIME BUG: unable to find field metadata for type '%*s'\n",
- (int)typeName.length, typeName.data);
+ missing_reflection_metadata_warning(
+ "warning: the Swift runtime found no field metadata for "
+ "type '%*s' that claims to be reflectable. Its fields will show up as "
+ "'unknown' in Mirrors\n",
+ (int)typeName.length, typeName.data);
callback("unknown",
FieldType()
.withType(TypeInfo(&METADATA_SYM(EMPTY_TUPLE_MANGLING), {}))
diff --git a/unittests/runtime/Stdlib.cpp b/unittests/runtime/Stdlib.cpp
index 04ecf72..def4bd6 100644
--- a/unittests/runtime/Stdlib.cpp
+++ b/unittests/runtime/Stdlib.cpp
@@ -252,3 +252,15 @@
// type metadata accessor for Swift._ClassMirror
SWIFT_RUNTIME_STDLIB_INTERNAL
const long long $Ss12_ClassMirrorVMa[1] = {0};
+
+// playground print hook
+
+struct swift_closure {
+ void *fptr;
+ HeapObject *context;
+};
+SWIFT_RUNTIME_STDLIB_API SWIFT_CC(swift) swift_closure
+MANGLE_SYM(s20_playgroundPrintHookySScSgvg)() {
+ return {nullptr, nullptr};
+}
+