Skip to content

[TrimmableTypeMap] Stop generating dead Java.Interop.__TypeRegistrations class #11663

Description

@simonrozsival

Part of #10958.

The binding generator still emits a Java.Interop.__TypeRegistrations class into every binding assembly (including Mono.Android.dll itself), but the runtime code that consumed it was removed in #9471 (commit 6ac69bee2, 2024-11-08). The generated class is now pure dead code — it is never invoked and the dictionary it populates is never read. We should stop generating it.

Background: how it used to work

__TypeRegistrations.RegisterPackages() called Java.Interop.TypeManager.RegisterPackages(string[] packages, Converter<string, Type?>[] lookups), which populated a packageLookup dictionary. The Java→managed type resolver (GetJavaToManagedTypeCore) had a TypeRegistrationFallback(class_name) path that lazily invoked __TypeRegistrations.RegisterPackages() and then read packageLookup to resolve a managed Type by package + class name.

This fallback was:

Today, GetJavaToManagedTypeCore resolves types exclusively via the native typemap (monovm_typemap_java_to_managed / clr_typemap_java_to_managed) or, on the trimmable path, TrimmableTypeMapTypeManager. The [TrimmableTypeMap] work makes this generated class even more clearly obsolete.

Evidence it is dead code (verified on main)

  • No caller of the no-arg __TypeRegistrations.RegisterPackages () exists anywhere in source. The generated class has no [ModuleInitializer]/static-ctor hook, so it is never auto-invoked.
  • Java.Interop.TypeManager.packageLookup is write-only: RegisterPackage / RegisterPackages populate it (src/Mono.Android/Java.Interop/TypeManager.cs:465-497); nothing reads it.
  • The Lookup(...) helper and per-package lookup_<pkg>_package converters in the generated file are unreferenced.
  • Mono.Android's own emitted copy is 2448 lines / 174 converters (src/Mono.Android/obj/.../mcw/Java.Interop.__TypeRegistrations.cs) of dead code; every binding assembly carries a similar file.

Current locations

  • Generator (primary target): external/Java.Interop/tools/generator/Java.Interop.Tools.Generator.ObjectModel/ClassGen.cs
    • GenerateTypeRegistrations(opt, gen_info) (line ~172) writes the partial class __TypeRegistrations with RegisterPackages(), Lookup(...), and the per-package converters. It already early-returns for CodeGenerationTarget.JavaInterop1.
  • Generator call site: external/Java.Interop/tools/generator/CodeGenerator.cs:251 (ClassGen.GenerateTypeRegistrations(opt, gen_info);).
  • Runtime plumbing now unused: src/Mono.Android/Java.Interop/TypeManager.cs
    • packageLookup field + LazyInitPackageLookup() (lines ~456-463)
    • RegisterPackage(string, Converter<string, Type>) (line ~465)
    • RegisterPackages(string[], Converter<string, Type?>[]) (line ~476)
    • LookupTypeMapping(string[], string) (line ~90) — only used by the generated Lookup.
  • Public shim: src/Mono.Android/Android.Runtime/TypeManager.cs (the [Obsolete] wrappers forwarding to the above).
  • Generator test baselines: external/Java.Interop/tests/generator-Tests/expected.xaji/*/Java.Interop.__TypeRegistrations.cs (one per fixture) plus the generator-Tests support TypeManager.cs.

Suggested implementation

  1. Stop generating __TypeRegistrations for the XAJavaInterop1 target as well (the method already no-ops for JavaInterop1). Simplest: make GenerateTypeRegistrations return early for all targets, or remove the method and its call in CodeGenerator.cs.
  2. Update / delete the expected.xaji generator-test baselines accordingly so generator-Tests stay green.
  3. Remove the now-unused runtime plumbing in Java.Interop/TypeManager.cs (packageLookup, LazyInitPackageLookup, RegisterPackage, the internal RegisterPackages body, and LookupTypeMapping if it has no remaining callers).

Public API consideration

Java.Interop.TypeManager.RegisterPackages(string[], Converter<string, Type?>[]), RegisterPackage(...), LookupTypeMapping(...) and the [Obsolete] Android.Runtime.TypeManager shims are shipped public API (present in src/Mono.Android/PublicAPI/*/PublicAPI.Shipped.txt). Removing the generation is safe and self-contained; removing the public members must go through the normal API-removal process (or they can be kept as no-op stubs). This issue can be split into two PRs: (a) stop generating __TypeRegistrations, (b) retire the public API.

Acceptance criteria

  • The binding generator no longer emits Java.Interop.__TypeRegistrations for any codegen target.
  • generator-Tests baselines updated; generator-Tests pass.
  • Mono.Android.dll and customer binding assemblies no longer contain the dead class (verify the file disappears from obj/.../mcw/ and from a built binding).
  • No behavioral change: Java→managed type resolution continues to go through the native typemap / TrimmableTypeMapTypeManager.
  • Existing Mono.Android and device tests pass.

References

Metadata

Metadata

Labels

copilot`copilot-cli` or other AIs were used to author thistrimmable-type-map

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions