[Reflection] Selectively keep the reflection metadata

Hi guys!

I work for Facebook on Swift adoption and recently we faced a case where it makes sense for us to be able to enable reflection metadata selectively.
At this moment, the only option is to keep it enabled/disabled for a whole module without fine-grained options to control it.
-disable-reflection-names also doesn't help much, saving up only several bytes of binary size.

Therefore, we'd like to start a discussion about implementing that feature upstream.

Currently, I see two ways:

  1. After reading some threads on the forum I saw a few mentions about some new Reflection API which is pretty desirable, but not a lot of work is done in that direction yet. I think the best option would be to support Pay-For-What-You-Use in the design of a new API.

  2. To create an addition for current API:
    Introduce a new flag -enable-selective-reflection-metadata and some options to let the compiler know which types require enabled metadata like:

  • Custom attribute for a declaration.
  • Introduce a new protocol like Reflectable.
  • Reusing an existing protocol like CustomReflectable.

While the first option is definitely better in long term, the further direction of Reflection evolution is not clear, Reflection Manifesto doesn't exist yet and the implementation can take a lot of time.
The second approach looks not so great as the first one but can help a lot for teams that care about binary size. Moreover, it doesn't seem very difficult and time-consuming from implementation point of view.

Any opinions on that?
Do you think it would be a good feature to have in the Language?

1 Like

I think that opt-in reflection metadata is the right direction to go, but it would need to be phased in to avoid disrupting existing code and frameworks that depend on metadata. Any new reflection API would most likely be built on the existing metadata ABI, so I see #1 as being orthogonal to this issue. I think we'd want both an attribute you can put on types to say their metadata is required, as well as an attribute you can apply to protocols to indicate their conforming types ought to emit metadata, since things like SwiftUI.View or CustomStringConvertible will always require some runtime metadata to be used for their intended purpose.

4 Likes

I'm looking back at the LLVM Dev talk "Efficiently Implementing Runtime Metadata", and it has a slide that says:

Metadata needs to be:

  • Detailed enough to be useful
  • Ubiquitous to be reliable
  • Cheap enough to be acceptable

Has your perspective changed since then (and if yes, I'm curious what caused the changed)? Or is it different for different kinds of metadata?

To me, unintentional secrecy leakage and lost optimization opportunities are additional concerns on top of code size. If all types are discoverable at runtime, that limits our ability to do dead code elimination or other optimizations that would rely on statically knowing all uses of the type. If we don't need to support runtime lookup for a type, we can redact names from its metadata, or eliminate the metadata entirely if it's never statically used. We already do this for private types, but we could stand to do it for internal types, and maybe public types in modules where library evolution is disabled too.

7 Likes

Nice! Thanks for the feedback @Joe_Groff!
I'll prepare a formal proposal and a prototype then.

1 Like