Enhancements
- [FIR] Warn when a
@ContributesTointerface only exposes bindings and recommend making it a binding container with@BindingContainer. The latter is preferable as it reduces generated code. - [FIR] Warn about array class literals in qualifiers, map keys, and scopes that kotlinc can confuse across modules. For example,
Array<IntArray>::classcan be read asIntArray::class. - [FIR/IR] Support
priorityon@ContributesBindingand@ContributesIntoMap, allowing higher-priority contributions to replace conflicting bindings or map entries without directly referencing the lower-priority implementation. - [IR] Reuse completed member-injector lookups for classes without injectable members.
- [IR] Support suspend providers with switching providers.
- [IR] Avoid revisiting shared supertypes when resolving generic bindings through diamond inheritance.
- [IR] Reduce per-entry memory overhead in more long-lived graph and contribution caches by using scatter maps.
- [IR] Reduce repeated work when validating suspend multibindings and reporting suspend-binding errors. Error traces now use cached, deterministic shortest paths to a suspend binding.
- [IR] Reduce repeated dependency scans when checking cycles in graphs with large multibindings.
- [IR] Avoid initializing the rich terminal renderer for plain compiler diagnostics.
- [IR/interop] Support Hilt interop when IR class generation is enabled.
- [Reports] Explain binding choices in graph reports. Includes things like selection precedence, contribution filtering, and parent-graph ownership.
- [Reports] Count emitted provider inlines in graph reports.
- [Reports] Report when deferred access or unavailable values prevent provider inlining.
Fixes
- [FIR] Fix a compiler crash when using typealiases as contribution scopes.
- [FIR] Fix a compiler crash on zero-parameter member-injection functions.
- [FIR] Fix graphs accidentally implementing binding-container interfaces when contributions use different scopes. Basically, checking another scope won't turn a container that supplies bindings into an interface the graph implements.
- [FIR] Keep contributed graph accessors when their replacement or its origin is excluded.
- [FIR] Avoid annotation-cache races during concurrent IDE analysis.
- [FIR] Fix assisted factories whose return types nest or reorder factory type parameters.
- [FIR/IR/interop] Fix recognition of
@get:BindsOptionalOfproperties when Dagger interop is enabled. - [IR] Keep dynamic graph arguments aligned when container order changes.
- [IR] Prevent dynamic graph class name collisions when a generic binding container is used with different type arguments. Basically, graphs using
Bindings<Int>andBindings<Long>can coexist in the same file. - [IR] Avoid generated dynamic graph name collisions across sibling files.
- [IR] Keep all transitively included binding containers when multiple graphs enter the same include cycle from different containers. Basically, improve compiler caching when containers are used in multiple graphs.
- [IR] Resolve graph extension bindings before running parallel graph analysis. This keeps compiler lookups and cache writes on one thread, including for nested extensions and bindings loaded from dependencies.
- [IR] Report required dependencies when an earlier parameter has a default value for the same missing type.
- [IR] Fix a runtime crash when an assisted-injected class with no assisted parameters is used across modules with IR class generation.
- [IR] Restore primitive and string inline provider values from dependency metadata.
- [IR] Report an error when an assisted-injected constructor requests a set or eager map backed by suspend providers. Basically, assisted factories now get the same suspend-multibinding checks as ordinary injection.
- [IR] Fix a compiler crash when reading
@Bindsdeclarations from generic binding containers. - [IR] Fix
@Bindsresolution when multiple graphs use the same generic binding container with different type arguments. Each graph now resolves bindings using its own container's type arguments. - [IR] Fix missing bindings for internal contributed objects across modules when
generateContributionProviders,generateClassesInIr, andcontributesAsInjectare enabled together. - [IR] Report duplicate map keys when different key annotations unwrap to the same value, including implicit class keys.
- [IR] Apply contribution replacements only in the scopes that declare them.
- [IR] Report missing required graph bindings even when an
@OptionalBindingaccessor requests the same type, regardless of declaration order. - [IR] Compare annotation values structurally so hash collisions don't merge distinct bindings.
- [IR] Preserve JVM array component types and dimensions in source class-literal qualifiers.
- [IR] Resolve JVM binary annotation defaults on Kotlin
2.3.0and2.3.10. - [IR/interop] Fix
Class-keyed maps wrapped in providers or lazy values whenKClass/Classinterop is enabled. - [IR/interop] Fix a runtime
ClassCastExceptionwhen aClass-keyed map is injected into a provider-created class across modules withKClass/Classinterop enabled. - [IR/interop] Respect
@GraphPrivateon Dagger@BindsOptionalOfdeclarations inherited by graph extensions, while preserving public declarations for the same key. - [IR/interop] Preserve Kotlin nullability in member-injection metadata when Dagger interop is enabled.
Changes
- [IR] Annotation default matching is limited for KLIB dependencies on Kotlin
2.3.0and2.3.10. We recommend upgrading to Kotlin2.3.20or newer. - Build against Kotlin
2.4.20. Note the runtime artifacts still target Kotlin2.3.0and Metro supports a wide range of compiler versions. See the compatibility docs for a full table of compatible versions. - Update embedded Okio dependency to
3.18.2. - Raise Kotlin
2.5.0support to2.5.0-dev-4967for IntelliJ 2026.3 EAPs. This replaces the2.5.0-dev-498and2.5.0-dev-3513compat modules. - Test Kotlin
2.5.0-dev-6460. - Test Kotlin
2.4.20. - Test Kotlin
2.4.20-RC2. - Test Kotlin
2.4.20-RC3. - Test IntelliJ 2026.2.2.
- Test IntelliJ 2026.3 EAPs (
263.3889.65). - Test Android Studio Quail 4.
- Test Android Studio Rabbit canaries (
canary 4).
Contributors
Special thanks to the following contributors for contributing to this release!
Consider sponsoring Metro's development
What's Changed
- Update Metro bootstrap to v1.4.2 by @renovate[bot] in #2665
- Update dependency com.squareup.okhttp3:okhttp to v5.5.0 by @renovate[bot] in #2669
- Update dependency zensical to v0.0.55 by @renovate[bot] in #2668
- Update dependency com.android.tools:r8 to v9.4.14 by @renovate[bot] in #2667
- Update IDE version mappings by @ZacSweers in #2671
- Remove out of date warning by @WhosNickDoglio in #2672
- Update dependency com.google.guava:guava to v33.7.1-jre by @renovate[bot] in #2673
- Update dependency Pygments to v2.21.0 by @renovate[bot] in #2670
- Update dependency zensical to v0.0.56 by @renovate[bot] in #2675
- Improve generated class name limiting by @ZacSweers in #2674
- Update wire to v6.4.6 by @renovate[bot] in #2676
- Fix FIR annotation cache race by @ZacSweers in #2680
- Fix AssistedInject runtime crash on Kotlin 2.4.20-RC by @grandstaish in #2679
- enableKClassToClassMapKeyInterop skipped for Provider/Lazy-wrapped maps by @grandstaish in #2677
- Add IDEA icons by @ZacSweers in #2682
- Add IDEA settings and inspection fixes by @ZacSweers in #2684
- Add IDEA build tools by @ZacSweers in #2685
- Share compiler types and naming utilities by @ZacSweers in #2681
- Share compiler diagnostics by @ZacSweers in #2683
- Add IDEA error reporting by @ZacSweers in #2687
- Share binding graph internals by @ZacSweers in #2688
- Share graph validation by @ZacSweers in #2691
- Share contribution helpers by @ZacSweers in #2690
- Update dependency com.bugsnag:bugsnag to v4.0.1 by @renovate[bot] in #2689
- Add graph benchmarks by @ZacSweers in #2692
- Add IDEA binding index by @ZacSweers in #2693
- Add IDEA editor hints by @ZacSweers in #2694
- Add IDEA graph validation by @ZacSweers in #2695
- Improve unused declaration detection by @ZacSweers in #2697
- Load IDEA test runtime classpath lazily by @ZacSweers in #2699
- Share provider type sets by @ZacSweers in #2698
- Add IDEA graph browser by @ZacSweers in #2696
- Update Gradle to v9.7.1 by @renovate[bot] in #2686
- Add IDEA graph tools by @ZacSweers in #2700
- Document the IDEA plugin by @ZacSweers in #2701
- Update IDE version mappings by @ZacSweers in #2702
- Rename Metro IDE project service by @ZacSweers in #2703
- Modernize IDEA Gradle configurations by @ZacSweers in #2704
- Move IDEA unused declaration support by @ZacSweers in #2705
- Cleanup docs by @ZacSweers in #2706
- Update IDE version mappings by @ZacSweers in #2709
- Update dependency mkdocs-git-revision-date-localized-plugin to v1.5.4 by @renovate[bot] in #2708
- Update dependency org.robolectric:robolectric to v4.17-beta-3 by @renovate[bot] in #2707
- Update dependency zensical to v0.0.57 by @renovate[bot] in #2714
- Show IDEA graph validation progress by @ZacSweers in #2711
- Support dynamic graphs in the IDEA plugin by @ZacSweers in #2712
- Add graph context pinning to the IDEA plugin by @ZacSweers in #2713
- Implement suspend switching providers by @ZacSweers in #2716
- Add priority properties to ContributesBinding and ContributesIntoSet by @ZacSweers in #2710
- Update dependency pymdown-extensions to v11.0.2 by @renovate[bot] in #2717
- Update dependency org.robolectric:robolectric to v4.17-beta-4 by @renovate[bot] in #2719
- Update circuit to v0.37.1 by @renovate[bot] in #2718
- IDEA plugin:Fix missing binding with type-use qualifier by @kevinguitar in #2721
- Update actions/setup-java action to v6 by @renovate[bot] in #2723
- Update wire to v6.4.7 by @renovate[bot] in #2722
- Fix read action on main thread by @ZacSweers in #2726
- Add find usages integration by @ZacSweers in #2728
- Fix binding container race in interop by @ZacSweers in #2729
- Update plugin testkit to v0.20 by @renovate[bot] in #2733
- Update dependency com.autonomousapps:gradle-testkit-support to v0.28 by @renovate[bot] in #2732
- Fix member injection nullability metadata with interop by @ZacSweers in #2734
- Update IDE version mappings by @ZacSweers in #2736
- Fix support for zero-arg function member injection by @ZacSweers in #2737
- Update dependency click to v8.5.0 by @renovate[bot] in #2741
- Update circuit to v0.38.0 by @renovate[bot] in #2740
- Update dependency com.android.tools:r8 to v9.4.17 by @renovate[bot] in #2738
- Update dependency mkdocs-callouts to v1.17.0 by @renovate[bot] in #2742
- Update tracing to v2.0.1 by @renovate[bot] in #2739
- Update IDE version mappings by @ZacSweers in #2743
- Update dependency mkdocs-callouts to v1.17.1 by @renovate[bot] in #2744
- Update dependency com.github.ajalt.mordant:mordant-core to v3.1.0 by @renovate[bot] in #2746
- Fix MapKey's kdoc by @kevinguitar in #2753
- Update IDE version mappings by @ZacSweers in #2757
- Update dependency zensical to v0.0.58 by @renovate[bot] in #2758
- Make shared graph analysis cooperatively cancellable by @ZacSweers in #2747
- Publish immutable IDE indexes with scoped resolution sessions by @ZacSweers in #2748
- Coordinate IDE index and presentation builds in the background by @ZacSweers in #2749
- Scope background graph validation and guard result publication by @ZacSweers in #2750
- Use background snapshots for IDE presentation and navigation by @ZacSweers in #2730
- Fix class map key interop across modules by @ZacSweers in #2759
- Small doc fixes by @ZacSweers in #2760
- Test newer RCs by @ZacSweers in #2761
- Fix sharding docs by @grandstaish in #2766
- Update dependency org.slf4j:slf4j-nop to v2.0.19 by @renovate[bot] in #2765
- Update dependency zensical to v0.0.59 by @renovate[bot] in #2764
- Fix docs for ClockWidgetClass to ClockWidget in context parameter generated code by @alexvanyo in #2767
- Final pass at a bunch of small IDE fixes and cleanups by @ZacSweers in #2763
- Update IDE version mappings by @ZacSweers in #2762
- Add IDEA tracing support by @ZacSweers in #2769
- Add checker for contributed interfaces that could be containers by @ZacSweers in #2770
- Update dependency com.squareup.okio:okio to v3.18.2 by @renovate[bot] in #2768
- Fix internal object contribution providers in IR class gen by @ZacSweers in #2771
- Parallelize graph analysis in IDEA by @ZacSweers in #2772
- Update tested IDE versions by @ZacSweers in #2773
- Fix generic assisted factory parameter checks by @ZacSweers in #2775
- Cache complete binding container closures by @ZacSweers in #2776
- Beef up IrAnnotation equality by @ZacSweers in #2774
- Ignore replacements from excluded contributions by @ZacSweers in #2778
- Visit each instantiated supertype once by @ZacSweers in #2777
- Compare effective map keys by @ZacSweers in #2779
- Index hard dependencies during graph sorting by @ZacSweers in #2780
- Check suspend multibindings used by assisted factories by @ZacSweers in #2783
- Keep dynamic graph types and arguments aligned by @ZacSweers in #2784
- Restore inline provider values from metadata by @ZacSweers in #2781
- Filter source contributions by graph scope by @ZacSweers in #2782
- Speed up CI by @ZacSweers in #2785
- Fix generic binding container aliases by @ZacSweers in #2786
- Report provider inline counts by @ZacSweers in #2787
- Keep required dependencies separate from optional lookup misses by @ZacSweers in #2788
- Reuse missing member injector results by @ZacSweers in #2791
- Limit contribution replacements to graph scopes by @ZacSweers in #2789
- Fix early scope resolution for generic typealiases by @ZacSweers in #2790
- Warn about array class literals in annotation keys by @ZacSweers in #2792
- Clean up sample warnings by @ZacSweers in #2793
- Rework compiler parallelism by @ZacSweers in #2794
- Update dependency cairosvg to v2.9.1 by @renovate[bot] in #2795
- Update plugin gradleTestRetry to v1.6.6 by @renovate[bot] in #2796
- 2.4.20 final by @ZacSweers in #2797
- Build against 2.4.20 and clean up tested versions by @ZacSweers in #2798
- Fix class gen tests on main by @ZacSweers in #2799
Full Changelog: 1.4.2...1.4.3