Alejandro Serrano.Mena
07/10/2026, 12:33 PMid("io.arrow-kt.optics") version "2.3.0-alpha.1" , and remove the KSP plugin, and you should be good to go! As a bonus, the optics are generated directly in the companion object, instead of as extensions thereof.
If you also want to see the generated optics in IntelliJ, go to Help > Edit custom properties, and add kotlin.k2.only.bundled.compiler.plugins.enabled=false and restart. You should get something similar to the attached screenshot. It's a known issue that @optics.copy sometimes crashes the IDE, but @optics only should be fine
Please report any problems, or any feedback you may havesindrenm
07/11/2026, 5:51 PMsindrenm
07/13/2026, 11:34 AMarrowOptics() inside the kotlin {} block in our build scripts anymore? The arrow.optics.plugin.arrowOptics no longer exists for me.sindrenm
07/13/2026, 12:07 PMSomewhere in file /home/sindre/code/sats-group/member-app-android/core/domain/src/main/kotlin/com/sats/core/domain/activities/models/Abc.kt: org.jetbrains.kotlin.utils.exceptions.KotlinIllegalArgumentExceptionWithAttachments: Unexpected returnTypeRef. Expected is FirResolvedTypeRef, but was FirUserTypeRefImpl
at org.jetbrains.kotlin.util.AnalysisExceptionsKt.wrapIntoFileAnalysisExceptionIfNeeded(AnalysisExceptions.kt:62)
at org.jetbrains.kotlin.fir.FirCliExceptionHandler.handleExceptionOnFileAnalysis(Utils.kt:270)
at org.jetbrains.kotlin.fir.resolve.transformers.plugin.FirCompanionGenerationTransformer.transformFile(FirCompanionGenerationProcessor.kt:113)
at org.jetbrains.kotlin.fir.resolve.transformers.plugin.FirCompanionGenerationTransformer.transformFile(FirCompanionGenerationProcessor.kt:39)
at org.jetbrains.kotlin.fir.declarations.FirFile.transform(FirFile.kt:47)
at org.jetbrains.kotlin.fir.resolve.transformers.FirTransformerBasedResolveProcessor.processFile(FirResolveProcessor.kt:53)
at org.jetbrains.kotlin.fir.resolve.transformers.FirTotalResolveProcessor.process(FirTotalResolveProcessor.kt:39)
at org.jetbrains.kotlin.fir.pipeline.AnalyseKt.runResolution(analyse.kt:25)
Caused by: org.jetbrains.kotlin.utils.exceptions.KotlinIllegalArgumentExceptionWithAttachments: Unexpected returnTypeRef. Expected is FirResolvedTypeRef, but was FirUserTypeRefImpl
at org.jetbrains.kotlin.fir.symbols.impl.UtilsKt.errorInLazyResolve(Utils.kt:42)
at org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol.calculateReturnType(FirCallableSymbol.kt:48)
at org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol.getResolvedReturnTypeRef(FirCallableSymbol.kt:40)
at org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol.getResolvedReturnType(FirCallableSymbol.kt:53)
at arrow.optics.plugin.fir.FirOpticsExtractor.constructorFoci(FirOpticsExtractor.kt:232)
at arrow.optics.plugin.fir.FirOpticsExtractor.foci(FirOpticsExtractor.kt:76)
at arrow.optics.plugin.fir.OpticsDslGenerator.dslFoci(OpticsDslGenerator.kt:60)
at arrow.optics.plugin.fir.OpticsDslGenerator.getTopLevelCallableIds(OpticsDslGenerator.kt:67)
Abc.kt was created by me now to try and isolate the issue. It only contains this enum class:
package com.sats.core.domain.activities.models
enum class Abc {
A, B, C
}
It's not even being referenced anywhere. The same issue happens with both 2.3.0-alpha.1 and 2.3.0-alpha.2. Want me to file an issue on GH, even if I'm not able to recreate the issue in a repro project (yet)?sindrenm
07/13/2026, 12:24 PMAbc, it just happens on another enum class we have called ActivityTagType, that's also just a simple enum class, but that's being referenced somewhere else. I created Abc because I suspected it happened to the first enum it parsed in alphabetical order.sindrenm
07/13/2026, 12:52 PMenum class Abc to a sealed interface, then Abc is fine, but the error moves forward to the ActivityTagType.kt , which is alphabetically next in the list of files in the project.Alejandro Serrano.Mena
07/13/2026, 2:00 PM2.3.0-alpha.2... I'll try to reproduce and release a new artifactAlejandro Serrano.Mena
07/13/2026, 2:00 PMarrowOptics() in the build flesindrenm
07/13/2026, 2:23 PMAlejandro Serrano.Mena
07/13/2026, 3:30 PMcalculateReturnType from getTopCallableIds (this was exactly the change from alpha.1 to alpha.2) πsindrenm
07/13/2026, 4:13 PMsindrenm
07/14/2026, 8:56 AMcalculateReturnType() is gone from the stack trace, but the (seemingly) same error persists:
org.jetbrains.kotlin.util.FileAnalysisException: Somewhere in file /home/sindre/code/sats-group/member-app-android/core/domain/src/main/kotlin/com/sats/core/domain/activities/models/ActivityTagType.kt: org.jetbrains.kotlin.utils.exceptions.KotlinIllegalArgumentExceptionWithAttachments: Unexpected status. Expected is FirResolvedDeclarationStatus, but was FirDeclarationStatusImpl
at org.jetbrains.kotlin.util.AnalysisExceptionsKt.wrapIntoFileAnalysisExceptionIfNeeded(AnalysisExceptions.kt:62)
at org.jetbrains.kotlin.fir.FirCliExceptionHandler.handleExceptionOnFileAnalysis(Utils.kt:270)
at org.jetbrains.kotlin.fir.resolve.transformers.plugin.FirCompanionGenerationTransformer.transformFile(FirCompanionGenerationProcessor.kt:113)
at org.jetbrains.kotlin.fir.resolve.transformers.plugin.FirCompanionGenerationTransformer.transformFile(FirCompanionGenerationProcessor.kt:39)
at org.jetbrains.kotlin.fir.declarations.FirFile.transform(FirFile.kt:47)
at org.jetbrains.kotlin.fir.resolve.transformers.FirTransformerBasedResolveProcessor.processFile(FirResolveProcessor.kt:53)
at org.jetbrains.kotlin.fir.resolve.transformers.FirTotalResolveProcessor.process(FirTotalResolveProcessor.kt:39)
at org.jetbrains.kotlin.fir.pipeline.AnalyseKt.runResolution(analyse.kt:25)
at org.jetbrains.kotlin.fir.pipeline.FirUtilsKt.resolveAndCheckFir(firUtils.kt:78)
at org.jetbrains.kotlin.cli.pipeline.jvm.JvmFrontendPipelinePhase.executePhase(JvmFrontendPipelinePhase.kt:168)
at org.jetbrains.kotlin.cli.pipeline.jvm.JvmFrontendPipelinePhase.executePhase(JvmFrontendPipelinePhase.kt:51)
at org.jetbrains.kotlin.cli.pipeline.PipelinePhase.phaseBody(PipelinePhase.kt:63)
at org.jetbrains.kotlin.cli.pipeline.PipelinePhase.phaseBody(PipelinePhase.kt:53)
at org.jetbrains.kotlin.config.phaser.NamedCompilerPhase.invoke(CompilerPhase.kt:102)
at org.jetbrains.kotlin.backend.common.phaser.CompositePhase.invoke(PhaseBuilders.kt:22)
at org.jetbrains.kotlin.config.phaser.CompilerPhaseKt.invokeToplevel(CompilerPhase.kt:53)
at org.jetbrains.kotlin.cli.pipeline.AbstractCliPipeline.runPhasedPipeline(AbstractCliPipeline.kt:135)
at org.jetbrains.kotlin.cli.pipeline.AbstractCliPipeline.executeAndReturnPipeLineArtifact(AbstractCliPipeline.kt:89)
at org.jetbrains.kotlin.cli.pipeline.AbstractCliPipeline.executeAndReturnPipeLineArtifact$default(AbstractCliPipeline.kt:49)
at org.jetbrains.kotlin.cli.pipeline.AbstractCliPipeline.execute(AbstractCliPipeline.kt:40)
at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecutePhased(K2JVMCompiler.kt:54)
at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecutePhased(K2JVMCompiler.kt:45)
at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:94)
at org.jetbrains.kotlin.cli.common.CLICompiler.exec(CLICompiler.kt:366)
at org.jetbrains.kotlin.incremental.IncrementalJvmCompilerRunnerBase.runCompiler(IncrementalJvmCompilerRunnerBase.kt:211)
at org.jetbrains.kotlin.incremental.IncrementalJvmCompilerRunnerBase.runCompiler(IncrementalJvmCompilerRunnerBase.kt:53)
at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.doCompile(IncrementalCompilerRunner.kt:539)
at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileImpl(IncrementalCompilerRunner.kt:451)
at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileNonIncrementally(IncrementalCompilerRunner.kt:327)
at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compile(IncrementalCompilerRunner.kt:139)
at org.jetbrains.kotlin.daemon.CompileServiceImplBase.execIncrementalCompiler(CompileServiceImpl.kt:782)
at org.jetbrains.kotlin.daemon.CompileServiceImplBase.access$execIncrementalCompiler(CompileServiceImpl.kt:108)
at org.jetbrains.kotlin.daemon.CompileServiceImpl.compile(CompileServiceImpl.kt:2046)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(Unknown Source)
at java.base/java.lang.reflect.Method.invoke(Unknown Source)
at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(Unknown Source)
at java.rmi/sun.rmi.transport.Transport$1.run(Unknown Source)
at java.rmi/sun.rmi.transport.Transport$1.run(Unknown Source)
at java.base/java.security.AccessController.doPrivileged(Unknown Source)
at java.rmi/sun.rmi.transport.Transport.serviceCall(Unknown Source)
at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(Unknown Source)
at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(Unknown Source)
at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(Unknown Source)
at java.base/java.security.AccessController.doPrivileged(Unknown Source)
at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(Unknown Source)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.base/java.lang.Thread.run(Unknown Source)
Caused by: org.jetbrains.kotlin.utils.exceptions.KotlinIllegalArgumentExceptionWithAttachments: Unexpected status. Expected is FirResolvedDeclarationStatus, but was FirDeclarationStatusImpl
at org.jetbrains.kotlin.fir.symbols.impl.UtilsKt.errorInLazyResolve(Utils.kt:42)
at org.jetbrains.kotlin.fir.symbols.impl.UtilsKt.resolvedStatus(Utils.kt:30)
at org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol.getResolvedStatus(FirCallableSymbol.kt:68)
at arrow.optics.plugin.fir.FirOpticsExtractor.sealedLensFoci$lambda$0(FirOpticsExtractor.kt:352)
at org.jetbrains.kotlin.fir.scopes.impl.FirClassDeclaredMemberScopeImpl.processPropertiesByName(FirClassDeclaredMemberScope.kt:146)
at org.jetbrains.kotlin.fir.scopes.FirContainingNamesAwareScopeKt.processAllCallables(FirContainingNamesAwareScope.kt:39)
at org.jetbrains.kotlin.fir.declarations.DeclarationUtilsKt.processAllDeclarations(declarationUtils.kt:138)
at org.jetbrains.kotlin.fir.declarations.DeclarationUtilsKt.processAllDeclarations(declarationUtils.kt:163)Alejandro Serrano.Mena
07/15/2026, 7:23 AMsealedLensFoci, so it seems I need to do some extra work theresindrenm
07/15/2026, 9:23 AMAlejandro Serrano.Mena
07/16/2026, 6:52 AMsindrenm
07/16/2026, 8:32 AMsindrenm
07/16/2026, 8:32 AMAlejandro Serrano.Mena
07/16/2026, 8:41 AMsindrenm
07/16/2026, 10:08 AMsindrenm
07/20/2026, 11:40 AMsindrenm
07/20/2026, 11:40 AM@optics
sealed interface MySealedInterface {
@optics
data object MyObject : MySealedInterface
@optics
data class MyClass(val myString: String) : MySealedInterface
}
fun main() {
val source: MySealedInterface = MySealedInterface.MyClass("Hello")
MySealedInterface.myClass.myString.set(source, "World")
}
However, this fails to compile:
@optics
sealed interface MySealedInterface {
@optics
data object MyObject : MySealedInterface
@optics
data class MyClass(val myString: String) : MySealedInterface
companion object // added this, compilation fails
}
fun main() {
val source: MySealedInterface = MySealedInterface.MyClass("Hello")
MySealedInterface.myClass.myString.set(source, "World")
}
Error message:
e: file:///path/to/optics-test.kt:18:36 Cannot infer type for type parameter '__S'. Specify it explicitly.
e: file:///path/to/optics-test.kt:18:36 Unresolved reference. None of the following candidates is applicable because of a receiver type mismatch:
val <__S> PPrism<__S, __S, MySealedInterface, MySealedInterface>.myClass: PPrism<__S, __S, MySealedInterface.MyClass, MySealedInterface.MyClass>
e: file:///path/to/optics-test.kt:18:44 Cannot infer type for type parameter '__S'. Specify it explicitly.
e: file:///path/to/optics-test.kt:39:21 Cannot infer type for type parameter '__S'. Specify it explicitly.
e: file:///path/to/optics-test.kt:39:21 Unresolved reference. None of the following candidates is applicable because of a receiver type mismatch:
val <__S> PPrism<__S, __S, MySealedInterface, MySealedInterface>.myClass: PPrism<__S, __S, MySealedInterface.MyClass, MySealedInterface.MyClass>
e: file:///path/to/optics-test.kt:39:29 Cannot infer type for type parameter '__S'. Specify it explicitly.sindrenm
07/20/2026, 11:58 AMcompanion object and rely on the generated one. However, some of our optics-annotated classes are also @Serializable from kotlinx-serialization, and the two plugins seem to collide in that case:
@optics
@Serializable
sealed interface MySealedInterface {
@optics
data object MyObject : MySealedInterface
@optics
data class MyClass(val myString: String) : MySealedInterface
}
java.lang.IllegalStateException: Multiple plugins generated nested class with same name Companion for class com/sindrenm/templates/project/MySealedInterface:
public final companion object Companion : R|kotlin/Any| {
}
public final companion object Companion : R|kotlin/Any| {
}sindrenm
07/20/2026, 1:30 PM/** Monomorphic `@optics`-annotated source classes for which the DSL target is enabled. */
private fun annotatedSources(): List<FirRegularClassSymbol> = session.predicateBasedProvider.getSymbolsByPredicate(lookupPredicate)
.filterIsInstance<FirRegularClassSymbol>()
.filter { it.typeParameterSymbols.isEmpty() && FirOpticsExtractor.dslEnabled(it) }
(github.com/arrow-kt/arrow/blob/β¦/OpticsDslGenerator.kt#β¦)
Is that due to a compiler plugin limitation? We have the following:
@optics
sealed interface UiState<out Data> {
data object Loading : UiState<Nothing>
@optics
data class Content<out Data>(val data: Data) : UiState<Data> {
companion object
}
@optics
data class Error(val message: RetryableErrorMessage) : UiState<Nothing> {
companion object
}
}
And previously we could do UiState.content<Foo>.data()..., but that is no longer generated, it seems. We can create that one on our own for now, though. πAlejandro Serrano.Mena
07/22/2026, 6:50 AMalpha.4 fixes both problems
(for serialization you need to write the companion object by hand -- a limitation of compiler plugins -- but I've added a error message when we detect that @Serializable is being used)sindrenm
07/22/2026, 10:20 AMsindrenm
07/23/2026, 10:24 AMimport arrow.optics.optics
@optics
data class ScreenContent(
val state: ScreenState = ScreenState.Loading,
)
@optics
sealed interface ScreenState {
@optics
data class Content(val text: String? = null) : ScreenState
data object Loading : ScreenState
}
// KSP generated this extension, but the compiler plugin does not:
//val <S> Optional<S, ScreenState>.content: Optional<S, ScreenState.Content>
// get() = this + ScreenState.content
fun setText(state: ScreenContent, text: String?): ScreenContent {
return ScreenContent.state
.content // compilation error here without the manually created extension above
.text.set(state, text)
}
Here are the errors:
e: file:///path/to/OptionalExtensions.kt:22:10 Unresolved reference 'content'.
e: file:///path/to/OptionalExtensions.kt:23:10 Cannot infer type for type parameter '__S'. Specify it explicitly.Alejandro Serrano.Mena
07/23/2026, 11:54 AMsindrenm
07/23/2026, 11:57 AMsindrenm
07/23/2026, 12:18 PMsindrenm
07/23/2026, 12:53 PMenum class anywhere in your compilation. Neither have to be explicitly used, but adding both triggers the issue.
import arrow.optics.optics
import kotlinx.serialization.Serializable
import kotlin.collections.set
// Enabling Serialization and adding this will trigger the error.
enum class ImAnEnum {
Foo, Bar, Baz
}
@optics
@Serializable
data class ScreenContent(
val state: ScreenState = ScreenState.Loading,
) {
companion object
}
@optics
sealed interface ScreenState {
@optics
data class Content(val text: String? = null) : ScreenState
data object Loading : ScreenState
}
// KSP generated this extension, but the compiler plugin does not:
//val <S> Optional<S, ScreenState>.content: Optional<S, ScreenState.Content>
// get() = this + ScreenState.content
fun main() {
val content = ScreenContent(state = ScreenState.Content())
println(content)
val updated = setText(content, "hello")
println(updated)
}
fun setText(state: ScreenContent, text: String?): ScreenContent {
return ScreenContent.state
.content // compilation error here without the manually created extension above
.text.set(state, text)
}sindrenm
07/23/2026, 12:59 PMsindrenm
07/23/2026, 2:36 PMAlejandro Serrano.Mena
07/24/2026, 10:16 AMsindrenm
07/24/2026, 10:41 AMsindrenm
07/27/2026, 7:43 AM