Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

This module shouldn't bring kotlin-reflect 1.5 as a transitive dependency #566

Open
Spikhalskiy opened this issue May 23, 2022 · 6 comments
Labels

Comments

@Spikhalskiy
Copy link
Contributor

Spikhalskiy commented May 23, 2022

Describe the bug
Currently, when I build my project with Kotlin 1.4 and using this module, I get errors and warnings which are caused by this module bringing kotlin-reflect 1.5 as a transitive dependency into Kotlin 1.4 classpath and runtime:

> Task :temporal-kotlin:compileKotlin
w: Runtime JAR files in the classpath should have the same version. These files were found in the classpath:
    /Users/dmitry/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib-jdk8/1.4.32/3302f9ec8a5c1ed220781dbd37770072549bd333/kotlin-stdlib-jdk8-1.4.32.jar (version 1.4)
    /Users/dmitry/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib-jdk7/1.4.32/3546900a3ebff0c43f31190baf87a9220e37b7ea/kotlin-stdlib-jdk7-1.4.32.jar (version 1.4)
    /Users/dmitry/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-reflect/1.5.30/6773e974437dd6432aa646cc2f8ab71de42b5773/kotlin-reflect-1.5.30.jar (version 1.5)
    /Users/dmitry/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib/1.5.30/d68efdea04955974ac1020f8f66ef8176bfbce1f/kotlin-stdlib-1.5.30.jar (version 1.5)
    /Users/dmitry/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib-common/1.5.30/649ffab7767038323fec0cc41e2d7b0a8f65a378/kotlin-stdlib-common-1.5.30.jar (version 1.5)
w: Some runtime JAR files in the classpath have an incompatible version. Consider removing them from the classpath
e: org.jetbrains.kotlin.codegen.CompilationException: Back-end (JVM) Internal error: Couldn't inline method call 'toJavaDuration' into
@kotlin.time.ExperimentalTime public inline fun ConnectedWorkflowServiceStubs(timeout: kotlin.time.Duration, options: @io.temporal.kotlin.TemporalDsl() (io.temporal.serviceclient.WorkflowServiceStubsOptions.Builder.() -> kotlin.Unit)): io.temporal.serviceclient.WorkflowServiceStubs defined in io.temporal.serviceclient in file WorkflowServiceStubsExt.kt
/**
 * Create WorkflowService gRPC stubs using provided [options].
 *
 * @see WorkflowServiceStubs.newConnectedServiceStubs
 */
@ExperimentalTime
inline fun ConnectedWorkflowServiceStubs(
  timeout: Duration,
  options: @TemporalDsl WorkflowServiceStubsOptions.Builder.() -> Unit,
): WorkflowServiceStubs {
  return ConnectedWorkflowServiceStubs(timeout.toJavaDuration(), options)
}
Cause: Not generated
File being compiled: (99,48) in /Users/dmitry/Projects/temporal/java-sdk/temporal-kotlin/src/main/kotlin/io/temporal/serviceclient/WorkflowServiceStubsExt.kt
The root cause java.lang.IllegalStateException was thrown at: org.jetbrains.kotlin.codegen.inline.InlineCodegen$Companion.getCompiledMethodNodeInner(InlineCodegen.kt:596)
        at org.jetbrains.kotlin.codegen.inline.InlineCodegen.throwCompilationException(InlineCodegen.kt:105)
        at org.jetbrains.kotlin.codegen.inline.InlineCodegen.performInline(InlineCodegen.kt:149)
        at org.jetbrains.kotlin.codegen.inline.PsiInlineCodegen.genCallInner(PsiInlineCodegen.kt:67)
        at org.jetbrains.kotlin.codegen.CallGenerator$DefaultImpls.genCall(CallGenerator.kt:115)
        at org.jetbrains.kotlin.codegen.inline.PsiInlineCodegen.genCall(PsiInlineCodegen.kt:33)
        at org.jetbrains.kotlin.codegen.ExpressionCodegen.invokeMethodWithArguments(ExpressionCodegen.java:2772)
        at org.jetbrains.kotlin.codegen.ExpressionCodegen.invokeMethodWithArguments(ExpressionCodegen.java:2714)
        at org.jetbrains.kotlin.codegen.Callable$invokeMethodWithArguments$1.invoke(Callable.kt:42)
        at org.jetbrains.kotlin.codegen.Callable$invokeMethodWithArguments$1.invoke(Callable.kt:41)
        at org.jetbrains.kotlin.codegen.OperationStackValue.putSelector(StackValue.kt:79)
        at org.jetbrains.kotlin.codegen.StackValue.put(StackValue.java:125)
        at org.jetbrains.kotlin.codegen.StackValue.put(StackValue.java:118)
        at org.jetbrains.kotlin.codegen.inline.InlineCodegen.putArgumentOrCapturedToLocalVal(InlineCodegen.kt:375)
        at org.jetbrains.kotlin.codegen.inline.PsiInlineCodegen.putValueIfNeeded(PsiInlineCodegen.kt:187)
        at org.jetbrains.kotlin.codegen.inline.PsiInlineCodegen.genValueAndPut(PsiInlineCodegen.kt:158)
        at org.jetbrains.kotlin.codegen.CallBasedArgumentGenerator.generateExpression(CallBasedArgumentGenerator.kt:42)
        at org.jetbrains.kotlin.codegen.ArgumentGenerator.generate(ArgumentGenerator.kt:70)
        at org.jetbrains.kotlin.codegen.ExpressionCodegen.invokeMethodWithArguments(ExpressionCodegen.java:2743)
        at org.jetbrains.kotlin.codegen.ExpressionCodegen.invokeMethodWithArguments(ExpressionCodegen.java:2714)
        at org.jetbrains.kotlin.codegen.Callable$invokeMethodWithArguments$1.invoke(Callable.kt:42)
        at org.jetbrains.kotlin.codegen.Callable$invokeMethodWithArguments$1.invoke(Callable.kt:41)
        at org.jetbrains.kotlin.codegen.OperationStackValue.putSelector(StackValue.kt:79)
        at org.jetbrains.kotlin.codegen.StackValue.put(StackValue.java:125)
        at org.jetbrains.kotlin.codegen.StackValue.put(StackValue.java:118)
        at org.jetbrains.kotlin.codegen.ExpressionCodegen.putStackValue(ExpressionCodegen.java:442)
        at org.jetbrains.kotlin.codegen.ExpressionCodegen.lambda$visitReturnExpression$11(ExpressionCodegen.java:1752)
        at org.jetbrains.kotlin.codegen.OperationStackValue.putSelector(StackValue.kt:79)
        at org.jetbrains.kotlin.codegen.StackValueWithLeaveTask.putSelector(StackValue.kt:67)
        at org.jetbrains.kotlin.codegen.StackValue.put(StackValue.java:125)
        at org.jetbrains.kotlin.codegen.StackValue.put(StackValue.java:118)
        at org.jetbrains.kotlin.codegen.ExpressionCodegen.putStackValue(ExpressionCodegen.java:442)
        at org.jetbrains.kotlin.codegen.ExpressionCodegen.gen(ExpressionCodegen.java:423)
        at org.jetbrains.kotlin.codegen.ExpressionCodegen.returnExpression(ExpressionCodegen.java:1846)
        at org.jetbrains.kotlin.codegen.FunctionGenerationStrategy$FunctionDefault.doGenerateBody(FunctionGenerationStrategy.java:64)
        at org.jetbrains.kotlin.codegen.FunctionGenerationStrategy$CodegenBased.generateBody(FunctionGenerationStrategy.java:86)
        at org.jetbrains.kotlin.codegen.FunctionCodegen.generateMethodBody(FunctionCodegen.java:649)
        at org.jetbrains.kotlin.codegen.inline.PsiSourceCompilerForInline.generateMethodBody(SourceCompilerForInline.kt:206)
        at org.jetbrains.kotlin.codegen.inline.PsiSourceCompilerForInline.doCreateMethodNodeFromSource(SourceCompilerForInline.kt:304)
        at org.jetbrains.kotlin.codegen.inline.InlineCodegen$Companion.createInlineMethodNode$backend(InlineCodegen.kt:544)
        at org.jetbrains.kotlin.codegen.inline.InlineCodegen.performInline(InlineCodegen.kt:140)
        at org.jetbrains.kotlin.codegen.inline.PsiInlineCodegen.genCallInner(PsiInlineCodegen.kt:67)
        at org.jetbrains.kotlin.codegen.CallGenerator$DefaultImpls.genCall(CallGenerator.kt:115)
        at org.jetbrains.kotlin.codegen.inline.PsiInlineCodegen.genCall(PsiInlineCodegen.kt:33)
        at org.jetbrains.kotlin.codegen.ExpressionCodegen.invokeMethodWithArguments(ExpressionCodegen.java:2772)
        at org.jetbrains.kotlin.codegen.ExpressionCodegen.invokeMethodWithArguments(ExpressionCodegen.java:2714)
        at org.jetbrains.kotlin.codegen.Callable$invokeMethodWithArguments$1.invoke(Callable.kt:42)
        at org.jetbrains.kotlin.codegen.Callable$invokeMethodWithArguments$1.invoke(Callable.kt:41)
        at org.jetbrains.kotlin.codegen.OperationStackValue.putSelector(StackValue.kt:79)
        at org.jetbrains.kotlin.codegen.StackValue.put(StackValue.java:125)
        at org.jetbrains.kotlin.codegen.StackValue.put(StackValue.java:118)
        at org.jetbrains.kotlin.codegen.ExpressionCodegen.putStackValue(ExpressionCodegen.java:442)
        at org.jetbrains.kotlin.codegen.ExpressionCodegen.lambda$visitReturnExpression$11(ExpressionCodegen.java:1752)
        at org.jetbrains.kotlin.codegen.OperationStackValue.putSelector(StackValue.kt:79)
        at org.jetbrains.kotlin.codegen.StackValueWithLeaveTask.putSelector(StackValue.kt:67)
        at org.jetbrains.kotlin.codegen.StackValue.put(StackValue.java:125)
        at org.jetbrains.kotlin.codegen.StackValue.put(StackValue.java:118)
        at org.jetbrains.kotlin.codegen.ExpressionCodegen.putStackValue(ExpressionCodegen.java:442)
        at org.jetbrains.kotlin.codegen.ExpressionCodegen.gen(ExpressionCodegen.java:423)
        at org.jetbrains.kotlin.codegen.ExpressionCodegen.returnExpression(ExpressionCodegen.java:1846)
        at org.jetbrains.kotlin.codegen.FunctionGenerationStrategy$FunctionDefault.doGenerateBody(FunctionGenerationStrategy.java:64)
        at org.jetbrains.kotlin.codegen.FunctionGenerationStrategy$CodegenBased.generateBody(FunctionGenerationStrategy.java:86)
        at org.jetbrains.kotlin.codegen.FunctionCodegen.generateMethodBody(FunctionCodegen.java:649)
        at org.jetbrains.kotlin.codegen.FunctionCodegen.generateMethodBody(FunctionCodegen.java:484)
        at org.jetbrains.kotlin.codegen.FunctionCodegen.generateMethod(FunctionCodegen.java:260)
        at org.jetbrains.kotlin.codegen.FunctionCodegen.generateMethod(FunctionCodegen.java:165)
        at org.jetbrains.kotlin.codegen.FunctionCodegen.gen(FunctionCodegen.java:136)
        at org.jetbrains.kotlin.codegen.MemberCodegen.genSimpleMember(MemberCodegen.java:197)
        at org.jetbrains.kotlin.codegen.PackagePartCodegen.generateBody(PackagePartCodegen.java:98)
        at org.jetbrains.kotlin.codegen.MemberCodegen.generate(MemberCodegen.java:129)
        at org.jetbrains.kotlin.codegen.PackageCodegenImpl.generateFile(PackageCodegenImpl.java:149)
        at org.jetbrains.kotlin.codegen.PackageCodegenImpl.generate(PackageCodegenImpl.java:70)
        at org.jetbrains.kotlin.codegen.DefaultCodegenFactory.generatePackage(CodegenFactory.kt:77)
        at org.jetbrains.kotlin.codegen.DefaultCodegenFactory.generateModule(CodegenFactory.kt:62)
        at org.jetbrains.kotlin.codegen.KotlinCodegenFacade.compileCorrectFiles(KotlinCodegenFacade.java:35)
        at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.generate(KotlinToJVMBytecodeCompiler.kt:595)
        at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.compileModules$cli(KotlinToJVMBytecodeCompiler.kt:211)
        at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.compileModules$cli$default(KotlinToJVMBytecodeCompiler.kt:154)
        at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:169)
        at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:52)
        at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:88)
        at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:44)
        at org.jetbrains.kotlin.cli.common.CLITool.exec(CLITool.kt:98)
        at org.jetbrains.kotlin.incremental.IncrementalJvmCompilerRunner.runCompiler(IncrementalJvmCompilerRunner.kt:386)
        at org.jetbrains.kotlin.incremental.IncrementalJvmCompilerRunner.runCompiler(IncrementalJvmCompilerRunner.kt:110)
        at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileIncrementally(IncrementalCompilerRunner.kt:286)
        at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileImpl$rebuild(IncrementalCompilerRunner.kt:99)
        at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileImpl(IncrementalCompilerRunner.kt:114)
        at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compile(IncrementalCompilerRunner.kt:74)
        at org.jetbrains.kotlin.daemon.CompileServiceImplBase.execIncrementalCompiler(CompileServiceImpl.kt:607)
        at org.jetbrains.kotlin.daemon.CompileServiceImplBase.access$execIncrementalCompiler(CompileServiceImpl.kt:96)
        at org.jetbrains.kotlin.daemon.CompileServiceImpl.compile(CompileServiceImpl.kt:1659)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:566)
        at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:359)
        at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:200)
        at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:197)
        at java.base/java.security.AccessController.doPrivileged(Native Method)
        at java.rmi/sun.rmi.transport.Transport.serviceCall(Transport.java:196)
        at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:562)
        at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:796)
        at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:677)
        at java.base/java.security.AccessController.doPrivileged(Native Method)
        at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:676)
        at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
        at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
        at java.base/java.lang.Thread.run(Thread.java:829)
Caused by: java.lang.IllegalStateException: Couldn't obtain compiled function body for @kotlin.SinceKotlin @kotlin.time.ExperimentalTime @kotlin.internal.InlineOnly public inline fun kotlin.time.Duration.toJavaDuration(): java.time.Duration defined in kotlin.time[DeserializedSimpleFunctionDescriptor@3fc0dd9f]
        at org.jetbrains.kotlin.codegen.inline.InlineCodegen$Companion.getCompiledMethodNodeInner(InlineCodegen.kt:596)
        at org.jetbrains.kotlin.codegen.inline.InlineCodegen$Companion.createInlineMethodNode$backend(InlineCodegen.kt:549)
        at org.jetbrains.kotlin.codegen.inline.InlineCodegen.performInline(InlineCodegen.kt:140)
        ... 106 more

It's caused by the following descriptor:

        <dependency>
            <groupId>org.jetbrains.kotlin</groupId>
            <artifactId>kotlin-stdlib</artifactId>
            <version>${version.kotlin}</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.jetbrains.kotlin</groupId>
            <artifactId>kotlin-reflect</artifactId>
            <version>${version.kotlin}</version>
            <scope>compile</scope>
        </dependency>

kotlin-stdlib is correctly defined as provided, but kotlin-reflect for some reason is defined as compile explicitly, which is weird. This was introduced in the commit: eedfb16#diff-9c5fb3d1b7e3b0f54bc5c4182965c4fe1f9023d449017cece3005d3f90e8e4d8R89
before this dependency was scoped as provided.

It forces us to have the following configuration in our project:

    implementation "org.jetbrains.kotlin:kotlin-reflect"
    implementation ("com.fasterxml.jackson.module:jackson-module-kotlin")
    {
        exclude group: 'org.jetbrains.kotlin', module: 'kotlin-reflect'
    }

Expected behavior
This module should

  • define kotlin-reflect as provided dependency
  • OR depend on kotlin-reflect 1.4 as a minimum supported version (not technically possible now, it will not compile)
@k163377
Copy link
Contributor

k163377 commented Feb 26, 2023

Unfortunately, Kotlin 1.4 has been deprecated in the absence of the maintainer.
Therefore, we do not plan to make any modifications to support Kotlin 1.4.
We also plan to modify the documentation in the near future. #632

In order to avoid similar problems, our policy will be to use the most recent patch version within the smallest minor version that has not been deprecated.

@k163377 k163377 closed this as completed Feb 26, 2023
@Spikhalskiy
Copy link
Contributor Author

Spikhalskiy commented Feb 26, 2023

@k163377 the issues with Kotlin 1.4 was actually resolved in #557
And the current state is fully compatible with Kotlin 1.4, we run Kotlin 1.4 pipelines with the new releases of Jackson as a part of Temporal CI/CD.

Unfortunately, Kotlin 1.4 has been deprecated in the absence of the maintainer.

I did take care of Kotlin 1.4 and can do it for some time.

In order to avoid similar problems, our policy will be to use the most recent patch version within the smallest minor version that has not been deprecated.

I personally don't think it's a very user-friendly version. Even JetBrains officially update and support the last three minor Kotlin releases.

We also plan to modify the documentation in the near future.

Not just the documentation, but the target will need to change. If Kotlin 1.4 is officially not supported, there should be no binary compatibility with Kotlin 1.4 (not being able to run at all is better that running incorrectly)

@k163377
Copy link
Contributor

k163377 commented Feb 26, 2023

@Spikhalskiy
I am reading and writing English by machine translation, so please forgive me if I may have misunderstood or misrepresented something.

I personally don't think it's a very user-friendly version. Even JetBrains officially update and support the last three minor Kotlin releases.

For example, we currently use within Kotlin 1.5 and intend to use Kotlin 1.6 when Kotlin 1.5 is deprecated (i.e. Kotlin 1.9 is released).
Is this policy not user-friendly?

Not just the documentation, but the target will need to change. If Kotlin 1.4 is officially not supported, there should be no binary compatibility with Kotlin 1.4 (not being able to run at all is better that running incorrectly)

To be precise, we were going to update the documentation and remove the tests in CI regarding Kotlin 1.4.
Are you saying that this work is not enough?

I noticed that it would be preferable to also remove the code for compatibility with Kotlin 1.4, is this what you are referring to?
https:/FasterXML/jackson-module-kotlin/blob/7493f7d3d4fc9ea52b1dfc2adc781f4465ab4fdc/src/main/kotlin/com/fasterxml/ jackson/module/kotlin/KotlinAnnotationIntrospector.kt#L68

@Spikhalskiy
Copy link
Contributor Author

Spikhalskiy commented Feb 26, 2023

For example, we currently use within Kotlin 1.5 and intend to use Kotlin 1.6 when Kotlin 1.5 is deprecated (i.e. Kotlin 1.9 is released).
Is this policy not user-friendly?

This sounds good. Supporting [1.5,) when 1.8 is the latest released version is good enough!

To be precise, we were going to update the documentation and remove the tests in CI regarding Kotlin 1.4.
Are you saying that this work is not enough?

Correct. I think we should make jackson-module-kotlin BINARY incompatible with Kotlin 1.4. So users get a build-time error if they try to use jackson-module-kotlin + Kotlin 1.4.

This can be achieved by building against Kotlin 1.6. Because Kotlin supports binary compatibility with one minor version down. So building against Kotlin 1.6 brings compatibility with 1.5, but not 1.4.
Reference:
https://kotlinlang.org/docs/kotlin-evolution.html#evolving-the-binary-format

Preferably (but we can't guarantee it), the binary format is mostly forwards compatible with the next feature release, but not later ones (in the cases when new features are not used, e.g. 1.3 can understand most binaries from 1.4, but not 1.5).

@Spikhalskiy
Copy link
Contributor Author

Spikhalskiy commented Feb 26, 2023

This specific issue should be solved by declaring kotlin-reflect dependency as optional. Deprecation of Kotlin 1.4 will not solve it. Imagine the user having Kotlin 1.8 stdlib and jackson-module-kotlin bringing kotlin-reflect 1.5 in.
I will submit a PR for it later.
See how a similar situation with kotlin-reflect solved in micrometer: https:/micrometer-metrics/micrometer/blob/main/micrometer-core/build.gradle#L86

@Spikhalskiy Spikhalskiy reopened this Feb 26, 2023
@nmck257
Copy link

nmck257 commented Mar 14, 2023

Hey @Spikhalskiy -- have you had a chance to try this yet?

This specific issue should be solved by declaring kotlin-reflect dependency as optional. Deprecation of Kotlin 1.4 will not solve it. Imagine the user having Kotlin 1.8 stdlib and jackson-module-kotlin bringing kotlin-reflect 1.5 in. I will submit a PR for it later.

I encountered the same issue and imagined the same solution. If you're busy, I can try it myself, but if you already tried it and learned something, can you share?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants