[Opt-In Reflection Metadata] Last updates and discussion

We've been examining the feedback we received from the last iteration on the proposal and we are providing this update.

Since the last revision, there have been made some changes in the compiler:

https://reviews.llvm.org/D104496

which improved the dead-stripability for nominal type metadata (NTD) in general and for reflection metadata in particular. However, even with those improvements not all of the issues were addressed.

Namely, the usage of reflection metadata may not be safe as we would like it to be. There is still no way to mark an API as consuming Reflection metadata explicitly. This can cause situations when Reflection is disabled for some reason, but source code still uses such APIs. That can cause runtime issues in production, if for some reason that wasn’t detected by the developers or QA before shipping the bundle. (This happened to us recently when Reflection metadata emission was disabled by mistake for modules using SwiftUI)

A simple example of how that could work:

stdlib:
@reflectable
public protocol Reflectable {}

Library:
public func print<T: Reflectable>(value: T) {}
or
public func print<T>(value: @reflectable T) {}

main:
class A: Reflectable {}
print(A())

Another issue is that the current solution doesn’t allow stripping the Reflection metadata for cases when NTD metadata is referenced somewhere in the code, while the Reflection metadata isn’t used anywhere. It might be the case when a metatype is accessed with a “Type.self” construction. It seems pretty difficult to statically determine such cases if it is possible at all.

So we would like to discuss the possible options we have in order to address the remaining issues and make the API safe and finer-grained.

For example, a mixed approach would help to address many of the concerns raised during the review of the previous proposal:

We could still use @reflectable (or a marker protocol Reflectable) to mark all types that are required to have reflection metadata at runtime, but introduce a new compiler flag allowing for 3 levels of reflection metadata behavior.

  1. Full (All reflection symbols are emitted in full and not allowed to be stripped)
  2. Strippable (The way as it works right now with Make VFE / WME / conditional records work even with ObjC interop and with reflection metadata by kubamracek · Pull Request #39808 · apple/swift · GitHub)
  3. Reflectable-Only (Emit Reflection symbols only for types that are marked with @reflectable or require metadata by the compiler like unspecialized generics instantiations)

We believe the explicit Reflection metadata generation will make API safer by enabling the compiler to detect usages of Reflectless Types in the APIs that require Reflection metadata to be present and emit error for such cases. Secondly, it will give the developers, who need this opportunity, more control over the emission of Reflection metadata and make the process more predictable.

Please, let us know what you think about it in order to come up with the next steps in this area.

Many thanks!

cc @Joe_Groff , @kubamracek, @mren, @ctp

1 Like
Terms of Service

Privacy Policy

Cookie Policy