Skip to content

kt-builder: ElideCompile drops --compiler_plugin_options/--stubs_plugin_options and --kotlin_{api,language}_version (compiler-plugin options + Kotlin version silently lost) #8

@sgammon

Description

@sgammon

Branch/commit: feat/kotlin-builder @ e9cd16a

Summary

Under the drop-in Elide Kotlin toolchain (register_elide_kotlin_toolchain), the builder forwards compiler-plugin classpaths but not compiler-plugin options, and ignores the requested Kotlin api/language version. Two visible consequences downstream:

  1. A compiler plugin that needs options misbehaves. Concretely, a Metro @DependencyGraph fails because Metro's interop-include-jakarta-annotations=true option is dropped, so jakarta.inject.@Inject constructors aren't recognized:
    error: [Metro/MissingBinding] Cannot find an @Inject constructor or @Provides-annotated
    function/property for: <impl class with a jakarta.inject.@Inject constructor>
    
    Tellingly, object bindings (companion objects, no construction) resolve fine, while every class binding fails — the signature of "plugin loaded but its options were lost."
  2. Every fast-path compile logs warning: the argument '-Xcontext-parameters' is redundant for the current language version 2.4 even though the target requests --kotlin_language_version 2.1 / --kotlin_api_version 2.1elide kotlinc falls back to its built-in default (2.4).

Both compile fine under stock rules_kotlin.

Root cause

elide/kotlin/builder/Flagfile.kt parses only a subset of the KotlinBuilder flagfile. The action's *-kt.jar-0.params contains all of:

--kotlin_api_version
2.1
--kotlin_language_version
2.1
--stubs_plugin_classpath
.../metro/compiler/0.13.2/processed_compiler-0.13.2.jar
--stubs_plugin_options
dev.zacsweers.metro.compiler:interop-include-jakarta-annotations=true
--compiler_plugin_classpath
.../metro/compiler/0.13.2/processed_compiler-0.13.2.jar
--compiler_plugin_options
dev.zacsweers.metro.compiler:interop-include-jakarta-annotations=true

but Flagfile reads --compiler_plugin_classpath / --stubs_plugin_classpath (so the plugin jar reaches kotlinc via -Xplugin, which is why Metro runs) and has no fields for --compiler_plugin_options, --stubs_plugin_options, --kotlin_api_version, or --kotlin_language_version. Correspondingly ElideCompile.plan() emits exactly one -P plugin:… (the jvm-abi-gen outputDir it injects itself) plus req.passthroughFlags — it never forwards arbitrary plugin options, -language-version, or -api-version. (-Xcontext-parameters survives only because it rides in --kotlin_passthrough_flags.)

Verified downstream: swapping the failing impl's constructor annotation from jakarta.inject.@Inject to Metro-native dev.zacsweers.metro.@Inject makes the MissingBinding error vanish under the Elide toolchain — confirming the lost interop-include-jakarta-annotations option is the cause, not the plugin classpath.

Suggested fix

In Flagfile.kt, parse the four keys into new fields (compilerPluginOptions, stubsPluginOptions, apiVersion, languageVersion). In ElideCompile.plan(), forward them to elide kotlinc:

  • for each plugin option <id>:<key>=<value>-P plugin:<id>:<key>=<value> (alongside an -Xplugin=<jar> for each --compiler_plugin_classpath entry);
  • -language-version <X> and -api-version <X> when set.

This blocks any optioned compiler plugin (Metro, etc.) under the Elide toolchain and silently relaxes the Kotlin version. Diagnosed downstream during a HEATWAVE trial alongside #6/#7.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions