Skip to content

Fix same-config change advice crash in KMP projects#1650

Closed
NikolayMetchev wants to merge 2 commits intoautonomousapps:mainfrom
NikolayMetchev:fix/same-config-advice-kmp-1649
Closed

Fix same-config change advice crash in KMP projects#1650
NikolayMetchev wants to merge 2 commits intoautonomousapps:mainfrom
NikolayMetchev:fix/same-config-advice-kmp-1649

Conversation

@NikolayMetchev
Copy link
Copy Markdown

Summary

Test plan

  • New functional test SameConfigKmpProject reproduces the crash (verified it fails without the fix)
  • All existing KMP tests pass (11/11 including 3 new)
  • Unit tests pass

🤖 Generated with Claude Code

…ousapps#1649)

In KMP projects with both Android and JVM targets, a dependency declared
on androidMainImplementation that is used in androidMain would crash
buildHealth with "Change advice cannot be from and to the same
configuration". This happened because simplify() paired an add and
remove for the same configuration and tried to create an invalid change
advice. Now, when from == to, the add and remove cancel out silently.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown
Owner

@autonomousapps autonomousapps left a comment

Choose a reason for hiding this comment

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

I am not certain this is the correct solution. If we get to this point with from and to being the same configuration, that implies something flawed in the analysis. Simply not crashing here might hide a deeper flaw.

KmpSourceKind was a data class whose equality included compileClasspathName
and runtimeClasspathName. When KmpSourceKind.of(compilation) constructed a
sourceKind from real Android compilations (e.g. debugCompileClasspath), it
differed from what ConfigurationNames.sourceKindFrom("androidMainImplementation")
produced (androidMainCompileClasspath). This mismatch caused usages and
declarations to never match in computeAdvice(), generating both ofAdd and
ofRemove for the same configuration, which then crashed in simplify() with
IllegalArgumentException (from == to).

Fix: override equals/hashCode/compareTo in KmpSourceKind to compare by name
only. KMP source set names are unique identifiers; classpath names are derived
values that don't provide additional discriminating power.

Also reverts the prior symptomatic fix (skipping from==to in simplify()) in
favour of this proper root cause fix, and adds a unit test that directly
reproduces the crash (IllegalArgumentException) without requiring Android SDK.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@NikolayMetchev
Copy link
Copy Markdown
Author

You're right — the original fix was masking a deeper flaw. I've pushed a new commit that addresses the root cause.

Root cause: KmpSourceKind is a data class whose equality included compileClasspathName and runtimeClasspathName. These fields are constructed via two different paths:

  1. KmpSourceKind.of(compilation) — built from a real Kotlin compilation; for Android, this yields e.g. debugCompileClasspath
  2. ConfigurationNames.sourceKindFrom("androidMainImplementation") — inferred from a config name; yields androidMainCompileClasspath

Because these differ, usage and declaration SourceKinds never matched in computeAdvice(). This caused both ofAdd and ofRemove to be generated for the same configuration, which then crashed in simplify() when it tried to create a change advice with from == to.

Fix: Override equals/hashCode/compareTo in KmpSourceKind to compare by name only. KMP source set names are unique identifiers; the classpath names are derived values that don't add discriminating power and shouldn't participate in equality.

The prior symptomatic guard in simplify() has been reverted. I've also added a unit test (StandardTransformTest) that directly reproduces the IllegalArgumentException without requiring the Android SDK, making it easy to verify the red→green cycle.

@autonomousapps
Copy link
Copy Markdown
Owner

See #1673

Also, please note that I have recently added a code of conduct, and now LLM-generated content is strictly forbidden for both issues and PRs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Change advice cannot be from and to the same configuration (androidMainImplementation) in KMP project

2 participants