Skip to content

Commit 06ac238

Browse files
committed
IRGen: Correctly set and honor the "is reflectable" bit on structs and classes.
If we only emit an opaque reflection record for a struct or class, then we can't reflect its fields. We failed both to clear the "is reflectable" bit in the context descriptor for non-reflectable structs, and to check for the bit before trying to present a struct's fields as children in the runtime. rdar://problem/41274260
1 parent 55eb35c commit 06ac238

File tree

3 files changed

+29
-1
lines changed

3 files changed

+29
-1
lines changed

lib/IRGen/GenMeta.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -700,7 +700,10 @@ namespace {
700700
uint16_t getKindSpecificFlags() {
701701
TypeContextDescriptorFlags flags;
702702

703-
flags.setIsReflectable(true); // struct always reflectable
703+
// Structs are reflectable unless we emit them with opaque reflection
704+
// metadata.
705+
flags.setIsReflectable(
706+
!IGM.shouldEmitOpaqueTypeMetadataRecord(getType()));
704707

705708
getClangImportedFlags(flags);
706709
return flags.getOpaqueValue();

stdlib/public/runtime/ReflectionMirror.mm

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,11 +257,21 @@ AnyReturn subscript(intptr_t i, const char **outName,
257257

258258
// Implementation for structs.
259259
struct StructImpl : ReflectionMirrorImpl {
260+
bool isReflectable() {
261+
const auto *Struct = static_cast<const StructMetadata *>(type);
262+
const auto &Description = Struct->getDescription();
263+
return Description->getTypeContextDescriptorFlags().isReflectable();
264+
}
265+
260266
char displayStyle() {
261267
return 's';
262268
}
263269

264270
intptr_t count() {
271+
if (!isReflectable()) {
272+
return 0;
273+
}
274+
265275
auto *Struct = static_cast<const StructMetadata *>(type);
266276
return Struct->getDescription()->NumFields;
267277
}
@@ -399,11 +409,20 @@ AnyReturn subscript(intptr_t i, const char **outName,
399409

400410
// Implementation for classes.
401411
struct ClassImpl : ReflectionMirrorImpl {
412+
bool isReflectable() {
413+
const auto *Class = static_cast<const ClassMetadata *>(type);
414+
const auto &Description = Class->getDescription();
415+
return Description->getTypeContextDescriptorFlags().isReflectable();
416+
}
417+
402418
char displayStyle() {
403419
return 'c';
404420
}
405421

406422
intptr_t count() {
423+
if (!isReflectable())
424+
return 0;
425+
407426
auto *Clas = static_cast<const ClassMetadata*>(type);
408427
auto count = Clas->getDescription()->NumFields;
409428

test/stdlib/Reflection_objc.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
import Swift
1616
import Foundation
17+
import simd
1718

1819
#if os(macOS)
1920
import AppKit
@@ -284,6 +285,11 @@ testQLO(HasStringQLO.self)
284285
// CHECK-NEXT: HasStringQLO overboard
285286
// CHECK-NEXT: CanaryBase overboard
286287

288+
// simd types get no reflection info, so should have no mirror children
289+
let x = float4(0)
290+
print("float4 has \(Mirror(reflecting: x).children.count) children")
291+
// CHECK-NEXT: float4 has 0 children
292+
287293
// CHECK-LABEL: and now our song is done
288294
print("and now our song is done")
289295

0 commit comments

Comments
 (0)