Changelog¶
Unreleased¶
0.5.4¶
2025-08-01
- Enhancement: Support
excludes
,bindingContainers
, andadditionalScopes
in@ContributesGraphExtension
. - Enhancement: Allow binding containers and regular contributed classes to replace each other in contribution merging.
- Enhancement: Allow
@ElementsIntoSet
on properties. - Enhancement: Don’t run FIR extensions on Java sources.
- Fix: Report incompatible scopes in nested contributed graphs to
MessageCollector
until Kotlin 2.2.20. - Fix: Report binding issues from externally contributed graphs to
MessageCollector
until Kotlin 2.2.20. - Fix: Preserve nullability when remapping type parameters.
- Fix: Don’t double-add
@ContributesTo
contributions while merging contributed graphs. - Fix: Check
rawStatus
for overrides when merging contributed supertypes. - Fix: Correctly extract the element type when creating implicit
Set
multibindings from@ElementsIntoSet
contributors. - Fix: Check
additionalScopes
when merging binding containers too. - Fix: Don’t fail if multiple contributing annotations on binding containers match the target scope when aggregating them.
- Fix: Dedupe binding containers during graph node generation.
- Fix: Add a checker for
@Provides
constructor parameters in binding containers. - Fix: Fix reading repeated external contributed annotations.
- Fix: Filter by matching scopes when merging contributed types with repeated annotations.
Special thanks to @hossain-khan, @gabrielittner, @kevinguitar, @JoelWilcox, and @martinbonnin for contributing to this release!
0.5.3¶
2025-07-28
- Behavior change: The
enableScopedInjectClassHints
option is no longer enabled by default. This option is tricky to get right and will be iterated on further in #764. - Enhancement: Generate synthetic
$$BindsMirror
classes to…- support full IC compatibility with changing annotations and return types on
@Binds
and@Multibinds
declarations - allow these declarations to be
private
- support full IC compatibility with changing annotations and return types on
- Enhancement: Allow
@Binds
and@Multibinds
functions to be private. - Enhancement: Allow “static graphs” via companions implementing the graph interface itself.
- Enhancement: Allow graphs to aggregate
internal
contributions from other compilations IFF those compilations are marked as friend paths. This mainly allows for test graphs to consume contributions from their corresponding main source sets. - Enhancement: Allow
internal
graphs to extendinternal
contributed interfaces from other compilations IFF those compilations are marked as friend paths. - Fix: Sort soft edges before hard edges within (valid) cycles. Previously we would just apply a standard topological sort here, but in this scenario we want to add extra weight to ready-up nodes that depend directly on the deferred type being used to break the cycle first.
- Fix: When recording IC lookups of overridable declarations, only record the original declaration and not fake overrides.
- Fix: Record IC lookups to
@Multibinds
declarations. - Fix: Write
@Multibinds
information to metro metadata. - Fix: Always write metro metadata to
@BindingContainer
classes, even if empty. - Fix: When
@Includes
-ing other graphs, link against the original interface accessor rather than the generated$$MetroGraph
accessor. - Fix: Disambiguate contributed nullable bindings from non-nullable bindings.
- Fix: When computing
@Includes
graph dependencies from accessors, only consider directly included graphs and not transitively included graphs. - Fix: Expose
@Includes
graph dependencies as synthetic_metroAccessor
types for extended graphs rather than exposing the included graph directly. - Fix: Prohibit calling
.asContribution()
on@ContributesGraphExtension
-annotated types.@ContributesGraphExtension
-annotated types cannot be validated at compile-time with this function as their generated class is definitionally contextual and the compiler cannot infer that from callsites of this function alone. - Fix: Only process
@DependencyGraph
types in FIR supertype generation. Contributed graph extension supertypes are merged only in IR. - Fix: Generate
$$MetroContribution
binds functions before aggregating contributions. - Fix: Don’t short-circuit class visiting in contribution visiting in IR.
- Fix: Propagate property annotations for
@Provides
-properties, previously only the accessor function annotations were being included. - Fix: Propagate class annotations for
@Inject
-annotated constructors to factory class mirror functions, previously only the constructor’s annotations were being included. - Fix: Fix dispatch receiver for
DelegateFactory
fields whenchunkFieldInits
is enabled. - Fix: Fix compilation error for members-injected classes with no direct, but only inherited
@Inject
attributes. - Fix: Always look up member injectors of ancestor classes of classes member-injected by graphs (sorry, word soup I know).
- Fix: Ensure
$$MetroContribution
interfaces are not generated for binding containers by ensuring binding container annotations are readable during their generation. - Change to
UnsupportedOperationException
for compiler intrinsic stubs, matching what the stdlib does. - Add a
ViewModel
assisted injection example tocompose-navigation-app
sample. - Small improvements to the doc site (404 page, favicon, etc.)
Special thanks to @hossain-khan, @bnorm, @yschimke, @kevinguitar, and @JoelWilcox for contributing to this release!
0.5.2¶
2025-07-21
- Enhancement: De-dupe contributions before processing in contributed graphs.
- Fix: Don’t extend contributed binding container classes in generated contributed graphs.
- Small doc fixes.
Special thanks to @bnorm and @alexvanyo for contributing to this release!
0.5.1¶
2025-07-18
- Breaking change: Rename the
generateHintProperties
Gradle DSL property togenerateContributionHints
. - Enhancement: Chunk field initializers and constructor statements across multiple init functions to avoid
MethodTooLargeException
in large graphs. This is currently experimental and gated behind thechunkFieldInits()
Gradle DSL. - Enhancement: Mark generated factories and member injectors’ constructors as
private
, matching the same change in Dagger 2.57. - Enhancement: Add a new Metro option
warnOnInjectAnnotationPlacement
to disable suggestion to lift @Inject to class when there is only one constructor, the warning applies to constructors with params too. - Fix: Fix
@Contributes*.replaces
not working if the contributed type is in the same compilation but a different file. - Fix: Fix generated
MembersInjector.create()
return types’ generic argument to use the target class. - Fix: Don’t generated nested MetroContribution classes for binding containers.
- Fix: Fix contributing binding containers across compilations.
Special thanks to @kevinguitar and @ChristianKatzmann for contributing to this release!
0.5.0¶
2025-07-14
- New: Experimental support for “binding containers” via
@BindingContainer
. See their docs for more details. - New: Add
keys-scopedProviderFields-*.txt
andkeys-providerFields-*.txt
reports to see generated field reports for graphs. - Enhancement: Remove
Any
constraint frombinding<T>()
, allowing bindings to satisfy nullable variants. - Enhancement: Add diagnostic to check for scoped
@Binds
declarations. These are simple pipes and should not have scope annotations. - Enhancement: Move graph dependency cycle checks to earlier in validation.
- Enhancement: When using Dagger interop, default
allowEmpty
to true when using Dagger’s@Multibinds
annotation. - Enhancement: Make Dagger interop providers/lazy instances a
dagger.internal.Provider
internally for better compatibility with Dagger internals. Some dagger-generated code assumes this type at runtime. - Enhancement: Support javax/jakarta
Provider
types as multibinding Map value types when Dagger interop is enabled. - Enhancement: Completely skip processing local and enum classes as they’re irrelevant to Metro’s compiler.
- Enhancement: When reporting
@Binds
declarations in binding stacks, report the original declaration rather than inherited fake overrides. - Enhancement: Add interop support for kotlin-inject’s
@AssistedFactory
annotations. - Enhancement: Add diagnostic to check for graph classes directly extending other graph classes. You should use
@Extends
. - Enhancement: Add diagnostic to check for
@Assisted
parameters in provides functions. - Enhancement: Add diagnostic to check duplicate
@Provides
declaration names in the same class. - Fix: Within (valid) cycles, topographically sort bindings within the cycle. Previously these would fall back to a deterministic-but-wrong alphabetical sort.
- Fix: Handle enum entry arguments to qualifier, scope, and map key annotations.
- Fix: Report the original location of declarations in fake overrides in error reporting.
- Fix: Handle default values on provides parameters with absent bindings during graph population.
- Fix: Don’t try to read private accessors of
@Includes
parameters. - Fix: Don’t quietly stub accessors for missing
Binding.Provided
bindings. - Fix: Check constructor-annotated injections when discovering scoped classes in parent graphs.
- Fix: Fix
BaseDoubleCheck.isInitialized()
. - Fix: Gracefully fall back to
MessageCollector
for graph seal and contributed graph errors on sourceless declarations. - Fix: Fix supporting overloads of binds functions from parent graphs or external supertypes.
- Fix: Fix generating binding functions with names that contain dashes.
- Fix: Treat interop’d Dagger/Anvil/KI components as implicitly extendable.
- Fix: Record lookups of
@Binds
declarations for IC. - Fix: Record lookups of generated class factories and their constructor signatures for IC.
Special thanks to @kevinguitar, @gabrielittner, @chrisbanes, @yschimke, and @ajarl for contributing to this release!
0.4.0¶
2025-06-23
- New: Injected constructors may now be private. This can be useful for scenarios where you want
@Inject
-annotated constructors to only be invokable by Metro’s generated code. - New: If reporting is enabled, write unused bindings diagnostics to
keys-unused-*.txt
. - New: Support for generic assisted injection.
- New: Support for generic member injection.
- New: Add diagnostic to prohibit type parameters on injected member functions.
- Enhancement: Enable child graphs to depend on parent-scoped dependencies that are unused and not referenced in the parent scope. This involves generating hints for scoped
@Inject
classes and is gated on a new Metro optionenableScopedInjectClassHints
, which is enabled by default. - Enhancement: Check for context parameters in top-level function injection checker.
- Enhancement: Store member injection info in metro metadata to slightly optimize member injection code gen.
- Enhancement: Avoid writing providers fields in graphs for unused bindings.
- Enhancement: Improve missing binding trace originating from root member injectors.
- Fix: Fix support for generic injected constructor parameters.
- Fix: Fix support for repeated contributes annotations by moving contribution binding function generation to IR.
- Fix: Ensure scope/qualifier annotation changes on constructor-injected classes dirty consuming graphs in incremental compilation.
- Fix: Report member injection dependencies when looking up constructor-injected classes during graph population.
- Fix: Disable IR hint generation on JS targets too, as these now have the same limitation as native/WASM targets in Kotlin 2.2. Pending upstream support for generating top-level FIR declarations in KT-75865.
- Fix: Ensure private provider function annotations are propagated across compilation boundaries.
- Fix: Substitute copied FIR type parameter symbols with symbols from their target functions.
- Fix: Improved support for generic member injection.
- Fix: Propagate qualifiers on graph member injector functions.
- Fix: Fix support for requesting
MembersInjector
types. - [internal] Report IR errors through
IrDiagnosticReporter
. - [internal] Significantly refactor + simplify IR parameter handling.
- Fix publishing Apple native targets in snapshots.
- Update to Kotlin
2.2.0
. - Update Gradle plugin to target Kotlin language version to
1.9
(requires Gradle 8.3+).
Special thanks to @kevinguitar, @gabrielittner, and @JoelWilcox for contributing to this release!
0.3.8¶
2025-06-16
- Enhancement: Disambiguate
MetroContribution
class names based on scope to better support IC when changing scopes. - Enhancement: Minimize deferred types when breaking cycles.
- Fix: Disallow injection of
Lazy<T>
whereT
is an@AssistedFactory
-annotated class. - Fix: Don’t short-circuit assisted injection validation if only an accessor exists.
- Fix: Allow cycles of assisted factories to their target classes.
- Update shaded okio to
3.13.0
. - Update atomicfu to
0.28.0
.
Special thanks to @kevinguitar, @bnorm, and @JoelWilcox for contributing to this release!
0.3.7¶
2025-06-08
- Fix: Record lookups of generated static member inject functions for IC.
- Fix: Dedupe merged overrides of
@Includes
accessors.
Special thanks to @kevinguitar for contributing to this release!
0.3.6¶
2025-06-06
- New: Add new
Provider.map
,Provider.flatMap
,Provider.zip
, andProvider.memoize
utility APIs. - Enhancement: Improve graph validation performance by avoiding unnecessary intermediate sorts (again).
- Enhancement: Fail eagerly with a clear error message if
languageVersion
is too old. - Enhancement: Validate improperly depending on assisted-injected classes directly at compile-time.
- Fix: Support constructing nested function return types for provider functions.
- Fix: Propagate
@Include
bindings from parent graphs to extension graphs. - Fix: Reparent copied lambda default values in IR.
- [internal] Make internal renderings of
IrType
more deterministic.
Special thanks to @kevinguitar for contributing to this release!
0.3.5¶
2025-05-31
- New: Implement top-level function injection checkers.
- Change: Disallow top-level function injections to be scoped.
- Fix: Support type parameters with
where
bounds. - Fix: Support injected class type parameters with any bounds.
- Fix: Support generic graph factory interfaces.
- Fix: In the presence of multiple contributing annotations to the same scope, ensure only hint function/file is generated.
- Fix: Improve shading to avoid packaging in stdlib and other dependency classes.
- Fix: Revert #483 as it broke some cases we haven’t been able to debug yet.
Special thanks to @gabrielittner and @kevinguitar for contributing to this release!
0.3.4¶
2025-05-27
- Enhancement: Use a simple numbered (but deterministic) naming for contributed graph classes to avoid long class names.
- Enhancement: Improve graph validation performance by avoiding unnecessary intermediate sorts.
- Enhancement: Move binding validation into graph validation step.
- Enhancement: Avoid unnecessary BFS graph walk in provider field collection.
- Fix: Fix provider field populating missing types that previously seen types dependent on.
Special thanks to @ChristianKatzmann and @madisp for contributing to this release!
0.3.3¶
2025-05-26
- Enhancement: Don’t unnecessarily wrap
Provider
graph accessors. - Enhancement: Allow multiple contributed graphs to the same parent graph.
- Fix: Don’t unnecessarily recompute bindings for roots when populating graphs.
- Fix: Better handle generic assisted factory interfaces.
- Fix: Use fully qualified names when generating hint files to avoid collisions.
- Fix: Support provides functions with capitalized names.
- Fix: Prohibit consuming
Provider<Lazy<...>>
graph accessors. - [internal] Migrate to new IR
parameters
/arguments
/typeArguments
compiler APIs.
Special thanks to @gabrielittner for contributing to this release!
0.3.2¶
2025-05-15
- Enhancement: Optimize supertype lookups in IR.
- Fix: Fix generic members inherited from generic supertypes of contributed graphs.
- Fix: Fix
@ContributedGraphExtension
that extends the same interface as the parent causes a duplicate binding error. - Fix: Fix contributed binding replacements not being respected in contributed graphs.
- Fix: Fix contributed providers not being visible to N+2+ descendant graphs.
- Fix: Collect bindings from member injectors as well as exposed accessors when determining scoped provider fields.
- Fix: Fix a few
-Xverify-ir
and-Xverify-ir-visibility
issues + run all tests with these enabled now.
Special thanks to @bnorm, @gabrielittner, @kevinguitar, and @JoelWilcox for contributing to this release!
0.3.1¶
2025-05-13
- Enhancement: Rewrite graph resolution using topological sorting to vastly improve performance and simplify generation.
- Enhancement: Return early once an externally-compiled dependency graph is found.
- Enhancement: Simplify multibinding contributor handling in graph resolution by generating synthetic qualifiers for each of them. This allows them to participate in standard graph resolution.
- Enhancement: When there are multiple empty
@Multibinds
errors, report them all at once. - Enhancement: Avoid unnecessary
StringBuilder
allocations. - Fix: Don’t transform
@Provides
function’s to be private if its visibility is already explicitly defined. - Fix: Fix a comparator infinite loop vector.
- Fix: Fix
@ElementsIntoSet
multibinding contributions triggering a dependency cycle in some situations. - Fix: Fix assertion error for generated multibinding name hint when using both @Multibinds and @ElementsIntoSet for the same multibinding.
- Fix: Fix contributed graph extensions not inheriting empty declared multibindings.
- Fix: Ensure we report the
@Multibinds
declaration location in errors if one is available. - Fix: Dedupe overrides by all parameters not just value parameters.
- Fix: Dedupe overrides by signature rather than name when generating contributed graphs.
- Fix: Fix accidentally adding contributed graphs as child elements of parent graphs twice.
- Fix: Fix not deep copying
extensionReceiverParameter
when implementing fake overrides in contributed graphs. - Fix: Report fully qualified qualifier renderings in diagnostics.
- Fix: Don’t generate provider fields for multibinding elements unnecessarily.
- When debug logging + reports dir is enabled, output a
logTrace.txt
to the reports dir for tracing data. - Update to Kotlin
2.1.21
.
Special thanks to @asapha, @gabrielittner, @jzbrooks, and @JoelWilcox for contributing to this release!
0.3.0¶
2025-05-05
- New: Add support for
@ContributesGraphExtension
! See the docs for more info. - New: Add a
asContribution()
compiler intrinsic to upcast graphs to expected contribution types. For example:val contributedInterface = appGraph.asContribution<ContributedInterface>()
. This is validated at compile-time. - New: Automatically transform
@Provides
functions to beprivate
. This is enabled by defaults and supersedes thepublicProviderSeverity
when enabled, and can be disabled via the Gradle extension ortransform-providers-to-private
compiler option. Note that properties and providers with any annotations withKClass
arguments are not supported yet pending upstream kotlinc changes. - Enhancement: Rewrite the internal
BindingGraph
implementation to be more performant, accurate, and testable. - Enhancement: Add diagnostic to check that graph factories don’t provide their target graphs as parameters.
- Enhancement: Add diagnostic to check that a primary scope is defined if any additionalScopes are also defined on a graph annotation.
- Enhancement: Add diagnostic to validate that contributed types do not have narrower visibility that aggregating graphs. i.e. detect if you accidentally try to contribute an
internal
type to apublic
graph. - Enhancement: Optimize supertype lookups when building binding classes by avoiding previously visited classes.
- Enhancement: Don’t generate hints for contributed types with non-public API visibility.
- Enhancement: When reporting duplicate binding errors where one of the bindings is contributed, report the contributing class in the error message.
- Enhancement: When reporting scope incompatibility, check any extended parents match the scope and suggest a workaround in the error diagnostic.
- Enhancement: Allow AssistedFactory methods to be protected.
- Fix: Fix incremental compilation when a parent graph or supertype modifies/removes a provider.
- Fix: Fix rank processing error when the outranked binding is contributed using Metro’s ContributesBinding annotation.
- Fix: Fix
@Provides
graph parameters not getting passed on to extended child graphs. - Fix: Fix qualifiers on bindings not getting seen by extended child graphs.
- Fix: Fix qualifiers getting ignored on accessors from
@Includes
dependencies. - Fix: Fix transitive scoped dependencies not always getting initialized first in graph provider fields.
- Fix: Fix injected
lateinit var
properties being treated as if they have default values. - Fix: Alias bindings not always having their backing type visited during graph validation.
- Fix: Fix race condition in generating parent graphs first even if child graph is encountered first in processing.
- Fix: Fallback
AssistedInjectChecker
error report to the declaration source. - Fix: Fix missing parent supertype bindings in graph extensions.
- Change:
InstanceFactory
is no longer a value class. This wasn’t going to offer much value in practice. - Change: Change debug reports dir to be per-compilation rather than per-platform.
Special thanks to @gabrielittner, @kevinguitar, @JoelWilcox, and @japplin for contributing to this release!
0.2.0¶
2025-04-21
- New: Nullable bindings are now allowed! See the nullability docs for more info.
- Enhancement: Add diagnostics for multibindings with star projections.
- Enhancement: Add diagnostic for map multibindings with nullable keys.
- Fix: Ensure assisted factories’ target bindings’ parameters are processed in MetroGraph creation. Previously, these weren’t processed and could result in scoped bindings not being cached.
- Fix: Fix duplicate field accessors generated for graph supertypes.
- Add compose navigation sample.
Special thanks to @bnorm and @yschimke for contributing to this release!
0.1.3¶
2025-04-18
- Change: Multibindings may not be empty by default. To allow an empty multibinding,
@Multibinds(allowEmpty = true)
must be explicitly declared now. - New: Write graph metadata to reports (if enabled).
- New: Support configuring debug and reports globally via
metro.debug
andmetro.reportsDestination
Gradle properties (respectively). - Enhancement: Change how aggregation hints are generated to improve incremental compilation. Externally contributed hints are now looked up lazily per-scope instead of all at once.
- Enhancement: Optimize empty map multibindings to reuse a singleton instance.
- Enhancement: Report error diagnostic if Dagger’s
@Reusable
is used on a provider or injected class. - Enhancement: Tweak diagnostic error strings for members so that IDE terminals auto-link them better. i.e., instead of printing
example.AppGraph.provideString
, Metro will printexample.AppGraph#provideString
instead. - Enhancement: Support repeatable @ContributesBinding annotations with different scopes.
- Fix: Fix incremental compilation when
@Includes
-annotated graph parameters change accessor signatures. - Fix: Don’t allow graph extensions to use the same scope as any extended ancestor graphs.
- Fix: Don’t allow multiple ancestor graphs of graph extensions to use the same scope.
- Fix: Handle scenarios where the compose-compiler plugin runs before Metro’s when generating wrapper classes for top-level
@Composable
functions. - Fix: Fix an edge case in graph extensions where child graphs would miss a provided scoped binding in a parent graph that was also exposed as an accessor.
- Fix: Fix Dagger interop issue when calling Javax/Jakarta/Dagger providers from Metro factories.
- Fix: Fix Dagger interop issue when calling
dagger.Lazy
from Metro factories. - Fix: Preserve the original
Provider
orLazy
type used in injected types when generating factory creators. - Temporarily disable hint generation in WASM targets to avoid file count mismatches until KT-75865.
- Add an Android sample: https://github.com/ZacSweers/metro/tree/main/samples/android-app
- Add a multiplatform Circuit sample: https://github.com/ZacSweers/metro/tree/main/samples/circuit-app
- Add samples docs: https://zacsweers.github.io/metro/samples
- Add FAQ docs: https://zacsweers.github.io/metro/faq
Special thanks to @JoelWilcox, @bnorm, and @japplin for contributing to this release!
0.1.2¶
2025-04-08
- Enhancement: Implement
createGraph
andcreateGraphFactory
FIR checkers for better error diagnostics on erroneous type arguments. - Enhancement: Add
ContributesBinding.rank
interop support with Anvil. - Enhancement: Check Kotlin version compatibility. Use the
metro.version.check=false
Gradle property to disable these warnings if you’re feeling adventurous. - Fix: Fix class-private qualifiers on multibinding contributions in other modules not being recognized in downstream graphs.
- Fix: Fix member injectors not getting properly visited in graph validation.
- Fix: Fix a bug where
Map<Key, Provider<Value>>
multibindings weren’t always unwrapped correctly. - Fix: Fix
Map<Key, Provider<Value>>
type keys not correctly interpreting the underlying type key asMap<Key, Value>
. - Change: Change
InstanceFactory
to a value class. - Change: Make
providerOf
useInstanceFactory
under the hood.
Special thanks to @JoelWilcox, @bnorm, @japplin, @kevinguitar, and @erawhctim for contributing to this release!
0.1.1¶
2025-04-03
Initial release!
See the announcement blog post: https://www.zacsweers.dev/introducing-metro/