Skip to content

Update metro to v0.11.0#6245

Merged
jmartinesp merged 3 commits intodevelopfrom
renovate/metro
Feb 25, 2026
Merged

Update metro to v0.11.0#6245
jmartinesp merged 3 commits intodevelopfrom
renovate/metro

Conversation

@renovate
Copy link
Contributor

@renovate renovate bot commented Feb 25, 2026

This PR contains the following updates:

Package Change Age Confidence
dev.zacsweers.metro 0.10.40.11.0 age confidence
dev.zacsweers.metro:runtime 0.10.40.11.0 age confidence
dev.zacsweers.metro:gradle-plugin 0.10.40.11.0 age confidence

Warning

Some dependencies could not be looked up. Check the Dependency Dashboard for more information.


Release Notes

ZacSweers/metro (dev.zacsweers.metro)

v0.11.0

Compare Source

2026-02-25

New

Metro now has an informal proposal system inspired by Kotlin KEEPs called MEEPs! Importantly, the P in MEEP stands for proposal, not process. It's an informal system for myself and future maintainers to seek broader community input on newer, splashier features and changes to Metro going forward.

[MEEP-1826] @Assisted parameters now rely on matching parameter names.

Historically, Dagger/Guice's @Assisted parameters allowed specifying a custom identifier via @Assisted("some string"), and Metro matched this behavior. However, this is a vestige of Java support, which did not include parameter names in bytecode until Java 8's -parameters flag.

Since Metro is in an all-Kotlin world and parameter names are a first-class citizen in Kotlin APIs, Metro is now leveraging that and phasing out support for implicit type matching and custom identifiers.

This means that @Assisted parameter names in assisted-inject constructors/top-level-functions must match their analogous parameters in @AssistedFactory creators. No more matching by types, no more disambiguating with @Assisted("customIdentifier").

// Before: Using type matching or custom identifiers
@​AssistedInject
class Taco(
  @​Assisted("name") val name: String,
  @​Assisted("type") val type: String,
  @​Assisted val spiciness: Int,
  val tortilla: Tortilla
) {
  @​AssistedFactory
  interface Factory {
    fun create(
      @​Assisted("name") name: String,
      @​Assisted("type") type: String,
      @​Assisted spiciness: Int
    ): TacoFactory
  }
}

// After: Using parameter name matching
@​AssistedInject
class Taco(
  @​Assisted val name: String,
  @​Assisted val type: String,
  @​Assisted val spiciness: Int,
  val tortilla: Tortilla
) {
  @​AssistedFactory
  interface Factory {
    // Parameter names must match the constructor exactly
    fun create(name: String, type: String, spiciness: Int): TacoFactory
  }
}

To ease migration to this, this will be rolled out in phases.

  1. Starting with this release, @Assisted.value is soft-deprecated. This is controlled by the assistedIdentifierSeverity Gradle DSL option, which is set to WARN by default in this release. This control allows for easy disabling or promotion to error.
  2. In a future release, assistedIdentifierSeverity will be removed and @Assisted.value will be formally deprecated.
  3. In a future release after that, @Assisted.value will be fully deleted and legacy behavior will be unsupported with Metro's first-party annotation.

Note that interop annotations are not affected by this change, and any previous Dagger/Guice interop @Assisted annotation's custom identifiers will still be respected.

If you want to completely restore the legacy behavior, you can disable this new mode via useAssistedParamNamesAsIdentifiers Gradle DSL option. Note, however, that this option will eventually be removed.

[MEEP-1770] Allow use of () -> T as Provider types.

Metro's primary provider type remains Provider, but as of this release there are a couple of important changes in this space to allow more idiomatic use.

  1. Provider now implements () -> T on supported platfroms (all but Kotlin/JS).
  2. There is a new enableFunctionProviders option to allow use of Kotlin's () -> T higher order functions. This is disabled by default, but will possibly be promoted to the default behavior in the future. Please share feedback in the linked MEEP.
    • This is inspired by kotlin-inject's support of the same feature, albeit with adjustments to work within Metro's existing Provider system.
    • On Kotlin/JS, the underlying Function0 type will be wrapped/unwrapped like other Provider interop scenarios do. This limitation is because JS does not allow extending function types.

This now allows you to write code like this.

@​DependencyGraph
interface AppGraph {
  val stringProvider: () -> String

  @​Provides fun provideString(): String = "Hello, world!"
}

fun main() {
  val provider = createGraph<AppGraph>().stringProvider
  println(provider())
}

The primary caveat of this new feature is that, if enabled, it essentially prohibits using function types as regular bindings in your graph. If you rely on this behavior, you may need to migrate to something more strongly typed.

[MEEP-1769] Introduce @GraphPrivate API.

Up to now, all bindings in graphs are implicitly available to all graph extensions.

Indicates this @Provides or @Binds declaration shall be private to the graph it's provided in. This means the following:

  • This binding may not be exposed directly via accessor.
  • This binding will not be exposed directly to extensions of this graph.

This is a mechanism to enforce that annotated bindings cannot be directly leaked. It may be depended on by any bindings within this graph as an implementation detail or encapsulation.

This is useful for a few situations.

  • Users may want certain bindings to stay confined to a given graph, such as a base HttpClient.
  • Users may want to omit certain contributions to multibindings from leaking to extensions.
  • Sometimes the same type may exist in multiple graph scopes, requiring use of qualifiers like @ForScope to disambiguate which one you need. By marking each provision in a graph as private, you can trust that parent graph instances are not being accidentally leaked to your extension's scope.
@&#8203;DependencyGraph(AppScope::class)
interface AppGraph {
  @&#8203;GraphPrivate
  @&#8203;Provides
  @&#8203;SingleIn(AppScope::class)
  fun provideCoroutineScope(): CoroutineScope = ...

  // Error
  val coroutineScope: CoroutineScope

  val loggedInGraph: LoggedInGraph
}

@&#8203;GraphExtension
interface LoggedInGraph {
  // Error, no longer implicitly visible
  val coroutineScope: CoroutineScope
}

This feature is experimental, please share any feedback on the original MEEP.

Misc new stuff
  • [Runtime]: Make Provider implement () -> T on applicable platforms (everything but Kotlin/JS).
  • [Runtime]: Add new @ExperimentalMetroApi experimental annotation to better indicate which APIs are experimental and likely to change.
  • [Gradle]: Add new @RequiresIdeSupport experimental annotation to better indicate which APIs require IDE support.
  • [Gradle]: Add new @ExperimentalMetroGradleApi experimental annotation to better indicate which APIs are experimental and likely to change.
  • [Gradle]: Add new @DangerousMetroGradleApi experimental annotation with ERROR severity to better propagate severity of certain APIs.
  • [FIR/Gradle]: Add new publicScopedProviderSeverity property with a more narrow focus. The previous publicProviderSeverity is now deprecated and just calls through to this.
Enhancements
  • [FIR]: Disallow _ assisted context parameter names in top-level function injection.
  • [FIR/IR]: When generating class and provider factories now, the compiler dedupes non-assisted, non-optional injections of the same type key (i.e. type ± qualifier). This shrinks generated code size in (uncommon) scenarios where you inject the same type multiple types.
  • [IR]: Significantly rework the IR pipeline.

Previously, Metro's IR would run in two passes:

  1. Collect contribution data and transform MetroContribution interfaces.
  2. Run all other transformations.

Now, Metro runs in a single pass. Most of Metro's core transformations are run in the first full pass, collects any seen dependency graphs along the way, then they are processed at the end (rather than visit the whole IR tree a second time).

  • [Gradle]: Allow DiagnosticSeverity metro extension properties to be configurable as metro.* gradle properties of the same name.
  • [Runtime]: Remove atomicfu dependency from Metro's core runtime artifact. The base concurrency primitives are now built on ReentrantLock (JVM), a port of the stdlib's Lazy spinlock on (Native), and no-op on web targets.
Fixes
  • [FIR]: Improve optional binding member injections detection.
  • [FIR]: Add @HiddenFromObjC to generated top-level composable classes for native compilations.
  • [FIR]: Fix evaluation of top-level constants used in annotations like @Assisted or @Named.
  • [FIR/IR]: Support generic @BindingContainer classes included via @Includes with concrete type arguments (e.g., @Includes TypedBindings<Int>). Type parameters are now properly propagated to generated factory classes and substituted during binding resolution.
  • [IR]: Fix propagation of Map graph inputs down to graph extensions.
  • [IR]: Guard against identity mappings (T -> T) to prevent infinite recursion when remapping generic types.
  • [IR]: Fix directly providing a scoped Map instance not getting reused at injection sites.
  • [IR]: Fix graph extensions not being able to replace @Binds-provided bindings from parent graphs.
  • [IR]: Fix dynamic binding containers not being propagated to graph extensions in some cases.
  • [IC]: Fix an IC edge case where generated assisted factory impl classes sometimes missed changes to injected constructor parameters in the target class.
  • [FIR/IR/Reports]: Restructure reports to use hierarchical nesting instead of top-level concatenated names. This fixes 'file name too long' exceptions when generating reports for deeply nested graphs. For example, the report file reports/keys-populated-test_Graph_ChildGraph.txt will now be generated as reports/keys-populated/test/Graph/ChildGraph.txt
  • [IR/Sharding]: Fix an issue where assisted inject classes are skipped while computing shard dependencies, which causes a failure while generating graph property accessors.
  • [IR/Sharding/Reports]: Fix an edge case where assisted inject classes are not on the graph but are still included in list of bindings to be validated for sharding diagnostics.
Changes
  • enableGraphSharding is now enabled by default. Note this only kicks in (by default) for graphs with 2000+ bindings by default.
  • unusedGraphInputsSeverity is now enabled to WARN severity by default.
  • Mentioned in enhancements, but worth reiterating that the underlying concurrency primitives have changed in the runtime but should be an improvement as they now use more modern reentrant locks.
  • Add Amper setup to installation docs (requires AMPER-5095).
  • Test Kotlin 2.3.20-RC.
  • Test Android Studio 2025.3.1.8 Panda 1 Patch 1.
  • Set minimum Gradle version to 8.8 via Gradle's not-so-obvious GRADLE_PLUGIN_API_VERSION_ATTRIBUTE API.
  • Freshen up the doc site navigation to better organize with tabs.
  • [Gradle]: Annotate forceEnableFirInIde and compilerVersion with @DangerousMetroGradleApi.
  • [Gradle]: Annotate generateAssistedFactories, enableTopLevelFunctionInjection with @RequiresIdeSupport.
  • [Gradle]: Annotate generateContributionHintsInFir, supportedHintContributionPlatforms, enableKlibParamsCheck, patchKlibParams, with @ExperimentalMetroGradleApi.
  • [Gradle]: Annotate enableFullBindingGraphValidation, shrinkUnusedBindings, with @DelicateMetroGradleApi.
  • [Gradle]: Deprecate chunkFieldInits, this will always be enabled in the future.
  • [Gradle]: Deprecate publicProviderSeverity, this now just calls through to publicScopedProviderSeverity.
  • [Gradle]: Promote transformProvidersToPrivate deprecation level to ERROR.
Contributors

Special thanks to the following contributors for contributing to this release!


Configuration

📅 Schedule: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.

Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 Ignore: Close this PR and you won't be reminded about these updates again.


  • If you want to rebase/retry this PR, check this box

This PR was generated by Mend Renovate. View the repository job log.

@renovate renovate bot requested a review from a team as a code owner February 25, 2026 06:12
@renovate renovate bot added the PR-Dependencies Pull requests that update a dependency file label Feb 25, 2026
@renovate renovate bot requested review from jmartinesp and removed request for a team February 25, 2026 06:12
@renovate renovate bot added the PR-Dependencies Pull requests that update a dependency file label Feb 25, 2026
Now the injected variables in the factories must match the names in the constructors
@jmartinesp jmartinesp requested a review from a team February 25, 2026 11:58
@jmartinesp
Copy link
Member

Since I made the changes, someone else should approve it.

@renovate
Copy link
Contributor Author

renovate bot commented Feb 25, 2026

Edited/Blocked Notification

Renovate will not automatically rebase this PR, because it does not recognize the last commit author and assumes somebody else may have edited the PR.

You can manually request rebase by checking the rebase/retry box above.

⚠️ Warning: custom changes will be lost.

@github-actions
Copy link
Contributor

📱 Scan the QR code below to install the build (arm64 only) for this PR.
QR code
If you can't scan the QR code you can install the build via this link: https://i.diawi.com/gjbUXh

@sonarqubecloud
Copy link

@ElementBot
Copy link
Collaborator

Warnings
⚠️

gradle/libs.versions.toml#L6 - A newer version of com.android.tools.build:gradle than 8.13.2 is available: 9.0.1

⚠️

gradle/libs.versions.toml#L42 - A newer version of io.coil-kt.coil3:coil-test than 3.3.0 is available: 3.4.0

⚠️

gradle/libs.versions.toml#L194 - A newer version of org.jsoup:jsoup than 1.21.2 is available: 1.22.1

⚠️

gradle/libs.versions.toml#L222 - A newer version of com.posthog:posthog-android than 3.32.2 is available: 3.33.0

⚠️

gradle/libs.versions.toml#L235 - A newer version of io.element.android:element-call-embedded than 0.16.3 is available: 0.17.0

Generated by 🚫 dangerJS against e78ebda

Copy link
Member

@bmarty bmarty left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! Out of curiosity, were all the changes you made required?

@jmartinesp
Copy link
Member

Thanks! Out of curiosity, were all the changes you made required?

Yes, it seems like it's a breaking change:

@Assisted parameters now rely on matching parameter names.

We could have enabled some temporary compatibility mode in the meantime, but it seemed better to just fix it. What's weird is I didn't see locally a lot of the issues the CI reported 🫤 .

@codecov
Copy link

codecov bot commented Feb 25, 2026

Codecov Report

❌ Patch coverage is 45.45455% with 6 lines in your changes missing coverage. Please review.
✅ Project coverage is 81.41%. Comparing base (01aeca7) to head (e78ebda).
⚠️ Report is 5 commits behind head on develop.

Files with missing lines Patch % Lines
...viewer/impl/gallery/voice/VoiceMessagePresenter.kt 0.00% 5 Missing ⚠️
...es/matrix/impl/workmanager/VacuumDatabaseWorker.kt 0.00% 1 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff            @@
##           develop    #6245   +/-   ##
========================================
  Coverage    81.41%   81.41%           
========================================
  Files         2571     2571           
  Lines        69850    69850           
  Branches      8964     8964           
========================================
  Hits         56869    56869           
  Misses        9653     9653           
  Partials      3328     3328           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@jmartinesp jmartinesp merged commit 896d62a into develop Feb 25, 2026
30 of 32 checks passed
@jmartinesp jmartinesp deleted the renovate/metro branch February 25, 2026 15:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

PR-Dependencies Pull requests that update a dependency file

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants