Type mismatch, CapturedType expected

I have this java code:

class ScratchBot extends TelegramLongPollingBot {
    private final Action handler = new UpdateHandler();

    @Override public void onUpdateReceived(Update update) {
        BotApiMethod<out BotApiObject> action = 
                handler.createExecutableForChat(update.getMessage().getChatId());
        execute(action);
    }
}

interface Action {
    BotApiMethod<? extends BotApiObject> createExecutableForChat(long chatId);
}

class UpdateHandler implements Action {

    @Override
    public BotApiMethod<? extends BotApiObject> createExecutableForChat(long chatId) {
        return new SendMessage();
    }
}

It works perfectly in java, but when i convert it in Kolin it breaks and this code below doesnā€™t work.

internal class ScratchBot : TelegramLongPollingBot() {

    private val handler: Action = UpdateHandler()
    override fun onUpdateReceived(update: Update) {
        val action: BotApiMethod<out BotApiObject?> =
               handler.createExecutableForChat(update.message.chatId)
        execute(action)
    }
}

internal interface Action {
    fun createExecutableForChat(chatId: Long): BotApiMethod<out BotApiObject?>?
}

internal class UpdateHandler : Action {
    override fun createExecutableForChat(chatId: Long): BotApiMethod<out BotApiObject?> {
        return SendMessage()
    }
}

Compiler throws this exception on execute call

Type mismatch.
Required:
BotApiMethod<CapturedType(out BotApiObject?)!>!
Found:
BotApiMethod<out BotApiObject?>?

I use library rubenlagus/TelegramBots: Java library to create bots using Telegram Bots API
And here is some its source code to show class hierarchy:

// Signature of execute() method that's used in my java code, be careful, Method here is a TypeVariable
public <T extends Serializable, Method extends BotApiMethod<T>> T execute(Method method) { /* */ }
// What my handler actually returns
public class SendMessage extends BotApiMethod<Message> { /* */ }
// My handler return type is java's BotApiMethod<? extends BotApiObject> or kotlin's BotApiMethod<out BotApiObject>
public abstract class BotApiMethod<T extends Serializable> extends PartialBotApiMethod<T> { /* */ }
public class Message implements BotApiObject { /* */ }
public interface BotApiObject extends Serializable { /* */ }

I also should mention that first i tried to write it in kotlin, and only after struggling for ~2 days i rewrote the ScratchBot class in java. Yeah, it also works with kotlin classes, so even if i leave Action and UpdateHandler in kotlin, i still can use them in java without any problems.

The issue is right there in the error message. Iā€™ll try to highlight the difference.

Type mismatch.
Required:
BotApiMethod<CapturedType(out BotApiObject?)!>! ā† not nullable BotApiMethod
Found:
BotApiMethod<out BotApiObject?>? ā† nullable BotApiMethod

Either createExecutableForChat should not be returning a nullable type (is null a valid return value?), or val action should be a nullable type.

Yeah, maybe thatā€™s an issue, but the error message tells something different. Iā€™ve just changed type to not-nullable, and nothing changed. I mentioned that first time i wrote this in kotlin and in case when i write in kotlin i donā€™t use nullable types. So thereā€™s something different from just nullable / not-nullable type mismatch.

As I said the error message you posted is about passing a providing a nullable type where a no null type is expected.

Hereā€™s an example of code that does compile (added stubs for the library)

class ScratchBot : TelegramLongPollingBot() {
    private val handler: Action = UpdateHandler()
    override fun onUpdateReceived(update: Update) {
        val action: BotApiMethod<out BotApiObject?> =
               handler.createExecutableForChat(update.message.chatId)
        execute(action)
    }
}
 interface Action {
    fun createExecutableForChat(chatId: Long): BotApiMethod<out BotApiObject?>
}
 class UpdateHandler : Action {
    override fun createExecutableForChat(chatId: Long): BotApiMethod<out BotApiObject?> {
        return SendMessage()
    }
}

open class BotApiMethod<T>
interface BotApiObject
abstract class TelegramLongPollingBot {
    open fun onUpdateReceived(update: Update) {} 
}
class Update(val message: Message) 
class Message(val chatId: Long) : BotApiObject

fun <T> execute(a: BotApiMethod<out T>) {} 
class SendMessage : BotApiMethod<Message>() 

fun main() {
    println("Hello world") 
}    

Your execute method signature differs from the original.

// yours
fun <T> execute(a: BotApiMethod<out T>)
// original
fun <T : Serializable?, Method : BotApiMethod<T>?> execute(method: Method): T? = null

After i corrected it iā€™ve noticed that error message also changed to it:

Type mismatch.
Required:
Serializable?
Found:
Scratch_2.BotApiObject

So i also noticed that your signature of BotApiObject is also incorrect

// yours
interface BotApiObject
// original
interface BotApiObject : Serializable

And after correcting all your mistakes weā€™ve returned to starting point

Type mismatch.
Required:
Scratch_2.BotApiMethod<CapturedType(out BotApiObject)>?
Found:
Scratch_2.BotApiMethod<out Scratch_2.BotApiObject>

also i still donā€™t understand why is original execute method was made in such a weird way, it could be just

fun execute(method: BotApiMethod<out Serializable>): Serializable? = null
Serializable execute(BotApiMethod<? extends Serializable> method) { return null; }

It did not appear relevant based on the bug message (a simple nullable non-nullable mismatch) so I didnā€™t bother converting manually (was on phone).

Itā€™d really be simpler to help if you included runnable code to start with. Start with ```run-kotlin line and then end with a ``` line and the code between will be runnable like in my reply. If thatā€™s not possible, including which line is actually showing the error is helpful. When I fixed those two errors, I did not get the same error. I saw an error related to passing action with covariant type BotApiMethod<out BotApiObject> into execute which expected an invariant type BotApiMethod<T>.

Not quite. public <T extends Serializable, Method extends BotApiMethod<T>> T execute(Method method) is not exactly the same as public <T extends Serializable, Method extends BotApiMethod<? extends T>> T execute(Method method) (see difference for the type argument of BotApiMethod).

The second which provides BotApiMethod with a covariant argument type (as opposed to the invariant definition of the first), when converted to Kotlin will give you:

fun <T : Serializable?, Method : BotApiMethod<out T>?> execute(method: Method): T?

Hereā€™s some code that executes that hopefully doesnā€™t include any other errors:

import java.io.Serializable

fun <T : Serializable, Method : BotApiMethod<out T>> execute(method: Method): T { /* */
    return null as T //just so it will compile
}

internal class ScratchBot : TelegramLongPollingBot() {
    private val handler: Action = UpdateHandler()
    override fun onUpdateReceived(update: Update) {
        val action = handler.createExecutableForChat(update.message.chatId)
        execute(action)
    }
}

internal interface Action {
    fun createExecutableForChat(chatId: Long): BotApiMethod<out BotApiObject>
}

internal class UpdateHandler : Action {
    override fun createExecutableForChat(chatId: Long): BotApiMethod<out BotApiObject> {
        return SendMessage()
    }
}

// What my handler actually returns
class SendMessage : BotApiMethod<Message>() { /* */ }

// My handler return type is java's BotApiMethod<? extends BotApiObject> or kotlin's BotApiMethod<out BotApiObject>
abstract class BotApiMethod<T : Serializable> : PartialBotApiMethod<T>() { /* */ }
abstract class PartialBotApiMethod<T : Serializable>
class Message : BotApiObject { /* */ }
interface BotApiObject : Serializable { /* */ }
internal abstract class TelegramLongPollingBot {
    abstract fun onUpdateReceived(update: Update)
}

interface Update {
    val message: UpdateMessage
}

interface UpdateMessage {
    val chatId: Long
}
fun main() = println("Hello world")

LMAOOOO kotlin is so bad!
Look at this:

public abstract class TelegramLongPollingBot {
    abstract void onUpdate(Update update);

    public <T extends Serializable, Method extends BotApiMethod<T>>
    T execute(Method method) {
        return null;
    }
}
abstract class TelegramLongPollingBotKt {
    abstract fun onUpdate(update: Update?)

    fun <T : Serializable, Method : BotApiMethod<T>>
    execute(method: Method): T {
        return null as T
    }
}

Thatā€™s two absolutely identical classes. But look here:

class ScratchBotWithJava : TelegramLongPollingBot() { // Java class

    private val handler: Action = UpdateHandler()
    override fun onUpdate(update: Update?) {
        val action = handler.createExecutableForChat(update!!.message.chatId)
        execute(action) // <-- Type mismatch
        //Required: BotApiMethod<CapturedType(out BotApiObject)!>!
        //Found:    BotApiMethod<out BotApiObject>!
    }
}

class ScratchBotWithKotlin : TelegramLongPollingBotKt() { // Kotlin class

    private val handler: Action = UpdateHandler()
    override fun onUpdate(update: Update?) {
        val action = handler.createExecutableForChat(update!!.message.chatId)
        execute(action)
    }
}

private interface Action {
    fun createExecutableForChat(chatId: Long): BotApiMethod<out BotApiObject>
}

private class UpdateHandler : Action {
    override fun createExecutableForChat(chatId: Long): BotApiMethod<out BotApiObject> {
        return SendMessage()
    }
}

But if i correct java classā€™ execute method signature like this:

public <T extends Serializable, Method extends BotApiMethod<? extends T>>
// now it has <? extends T> instead of just <T>  right here ^
T execute(Method method) { return null; }

It compiles!
So at this point i thought that kotlin compiles itā€™s

fun <T : Serializable, Method : BotApiMethod<T>> execute(method: Method): T

into javaā€™s

public <T extends Serializable, Method extends BotApiMethod<? extends T>> T execute(Method method);

But using javap tool from jdk i inspected both classesā€™ bytecode and signature was identical:

Compiled from "TelegramLongPollingBot.kt"
public abstract class telegram.bot.test.TelegramLongPollingBotKt {
  public final <T extends java.io.Serializable, Method extends org.telegram.telegrambots.meta.api.methods.BotApiMethod<T>> T execute(Method);
// More output, not neccessary

Compiled from "TelegramLongPollingBot.java"
public abstract class telegram.bot.test.TelegramLongPollingBot {
  public <T extends java.io.Serializable, Method extends org.telegram.telegrambots.meta.api.methods.BotApiMethod<T>> T execute(Method);
// more output

And look: signature only differs on final keyword, the rest of it is identical.

And the funniest part.
The solution.

class WorkingBot : org.telegram.telegrambots.bots.TelegramLongPollingBot() { // not a mock

    // Here i override method just changing nullable generic types to not-nullable
    // that's signature that IntlliJ offers me:
    override fun <T : Serializable?, Method : BotApiMethod<T>?> execute(method: Method): T =
        super.execute(method)
    // and here's working signature, the solution
    override fun <T : Serializable, Method : BotApiMethod<T>> execute(method: Method): T =
        super.execute(method)

    private val handler: Action = UpdateHandler()
    
    override fun onUpdateReceived(update: Update?) {
        val action = handler.createExecutableForChat(update!!.message.chatId)
        execute(action)
    }
}

VayKekaz/kotlin-java-interop-telegrambot (github.com) - the test repo with all the code.

1 Like

I had exactly the same issueā€¦ thank you for sharing your solution!

1 Like