min
09/20/2026, 8:46 AMprivate fun parseArgument(
maybeArgument: ConeKotlinType,
session: FirSession,
): Either<ClassId, ClassKind?> {
val id = maybeArgument.classId ?: return Either.Bar(null)
val kind = session.classFromId(id)?.classKind ?: return Either.Bar(null)
return when {
kind.isAnnotationClass -> Either.Foo(id)
else -> Either.Bar(kind)
}
}
How can I consolidate the duplicate return Either.Bar(null) statements?Youssef Shoaib [MOD]
09/20/2026, 9:05 AMval default = Either.Bar(null) and simply return that
Of course, there's a nice #C5UPMM0A0 solution here if you want it:
// Arrow's Either type has its type parameters the other way around
// You don't have to use Arrow's Either, you can make Raise work with your own type, I'm just using it for brevity
private fun parseArgument(
maybeArgument: ConeKotlinType,
session: FirSession,
): Either<ClassKind?, ClassId> = either {
singleton({ raise(null) }) { // singleton gives access to the `.bind()` syntax for nullables
val id = maybeArgument.classId.bind()
val kind = session.classFromId(id)?.classKind.bind()
ensure(<http://kind.is|kind.is>AnnotationClass) { id }
kind
}
}Marat Akhin
09/20/2026, 9:11 AMEither to a sealed hierarchy. Your Either is not a bi-state, it's a tri-state Id | Kind | Null . Then you'll get return InvalidArgument and writing it twice is fine.
2. Actually, writing something twice is totally fine even for the current form.
3. You can delay making the decision to the very last moment.
private fun parseArgument(
maybeArgument: ConeKotlinType,
session: FirSession,
): Either<ClassId, ClassKind?> {
val id: ClassId? = maybeArgument.classId
val kind: ClassKind? = id?.let { session.classFromId(it)?.classKind }
return when {
id == null | kind == null -> Either.Bar(null)
kind.isAnnotationClass -> Either.Foo(id)
else -> Either.Bar(kind)
}
}min
09/20/2026, 9:13 AMChange from@Marat Akhin I don’t understand what you mean by this.to a sealed hierarchy. […] Then you'll getEitherand writing it twice is fine.return InvalidArgument
Youssef Shoaib [MOD]
09/20/2026, 9:37 AMsealed interface AnnotationResult
data class AnnotationId(val id: ClassId): AnnotationResult
data class InvalidClassKind(val kind: ClassKind): AnnotationResult
data object InvalidArgument: AnnotationResult
This can work fine with Either though:
sealed interface AnnotationError
data class InvalidClassKind(val kind: ClassKind): AnnotationError
data object InvalidArgument: AnnotationError
typealias AnnotationResult = Either<ClassId, AnnotationError>