Skip to content

[Mirror] Handle fields of thin metatypes. #76309

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions stdlib/public/runtime/ReflectionMirror.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,29 @@ static AnyReturn copyFieldContents(OpaqueValue *fieldData,
auto ownership = fieldType.getReferenceOwnership();
auto *destContainer = type->allocateBoxForExistentialIn(&outValue.Buffer);

// If the field's type is a thin metatype, then there's no actual data at
// fieldData, and we need to obtain the metatype value from the field type.
if (auto *metatype = dyn_cast<MetatypeMetadata>(type)) {
switch (metatype->InstanceType->getKind()) {
case MetadataKind::Struct:
case MetadataKind::Enum:
case MetadataKind::Optional:
case MetadataKind::Tuple:
case MetadataKind::Function:
case MetadataKind::Existential: {
// These kinds don't have subtypes and thus have thin representations.
auto asOpaque = const_cast<OpaqueValue *>(
reinterpret_cast<const OpaqueValue *>(&metatype->InstanceType));
type->vw_initializeWithCopy(destContainer, asOpaque);
return AnyReturn(outValue);
}

default:
// Other kinds have subtypes and will not have a thin representation.
break;
}
}

if (ownership.isStrong()) {
type->vw_initializeWithCopy(destContainer, fieldData);
}
Expand Down
43 changes: 43 additions & 0 deletions test/stdlib/Mirror.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
// REQUIRES: reflection

// rdar://96439408
// UNSUPPORTED: back_deployment_runtime
// UNSUPPORTED: use_os_stdlib

import StdlibUnittest
Expand Down Expand Up @@ -1669,6 +1670,48 @@ mirrors.test("MetatypeMirror") {
}
}

class MetatypeExampleClass {}
class MetatypeExampleSubclass: MetatypeExampleClass {}
final class MetatypeExampleFinalClass {}
enum MetatypeExampleEnum {}
struct MetatypeContainer {
var before = 42
var before2 = 43
var structType = String.self
var enumType = MetatypeExampleEnum.self
var tupleType = (Int, String, AnyObject).self
var functionType = (() -> Void).self
var classType = MetatypeExampleClass.self
var subclassType: MetatypeExampleClass.Type = MetatypeExampleSubclass.self
var finalClassType = MetatypeExampleFinalClass.self
var existentialType: (any Any).Type = Any.self
var existentialType2: Any.Type = Any.self
var after = 45
}

mirrors.test("MetatypeFields") {
var output = ""
let container = MetatypeContainer()
dump(container, to: &output)
expectEqual("""
▿ Mirror.MetatypeContainer
- before: 42
- before2: 43
- structType: Swift.String #0
- enumType: Mirror.MetatypeExampleEnum #1
- tupleType: (Swift.Int, Swift.String, Swift.AnyObject) #2
- functionType: () -> () #3
- classType: Mirror.MetatypeExampleClass #4
- subclassType: Mirror.MetatypeExampleSubclass #5
- finalClassType: Mirror.MetatypeExampleFinalClass #6
- existentialType: Any #7
- existentialType2: Any #7
- after: 45

""",
output)
}

//===--- Tuples -----------------------------------------------------------===//
//===----------------------------------------------------------------------===//

Expand Down