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

Using flow.collect { } causes cannot be cast to kotlinx.coroutines.flow.FlowCollector #3159

Closed
sohail77 opened this issue Jan 26, 2022 · 6 comments

Comments

@sohail77
Copy link

sohail77 commented Jan 26, 2022

Hello Team,

We've recently updated to v1.6.0 and started to see these cannot be cast to kotlinx.coroutines.flow.FlowCollector exceptions when using this collect extension function . It mistakes it for this direct collect() function. Whenever this used to happen in the previous versions the fix was to use the correct import statement import kotlinx.coroutines.flow.collect (It doesn't work anymore).

Here's an example code that causes this error.

class Example(
        private val notificationReceiver: NotificationReceiver,
        private val io: CoroutineDispatcher
) {
    init {
        CoroutineScope(io).launch { 
            notificationReceiver.notificationState.collect { 
                doSomething(it)
            }
        }
    }
}
interface NotificationReceiver {
    val notificationState: Flow<PushNotification>
}

Currently, our workaround, for now, is to do something like this

class Example(
        private val notificationReceiver: NotificationReceiver,
        private val io: CoroutineDispatcher
) {
    init {
        CoroutineScope(io).launch { 
            notificationReceiver.notificationState.onEach { 
                doSomething(it)
            }.collect()
        }
    }
}

Here's the error log

Exception in thread "Test worker @coroutine#6" java.lang.ClassCastException: class com.sohail.Example$1$1 cannot be cast to class kotlinx.coroutines.flow.FlowCollector (com.sohail.Example$1$1 and kotlinx.coroutines.flow.FlowCollector are in unnamed module of loader 'app')
	at com.sohail.Example$1.invokeSuspend(TracerImpl.kt:78)
	at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
	at kotlinx.coroutines.internal.DispatchedContinuationKt.resumeCancellableWith(DispatchedContinuation.kt:367)
	at kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable(Cancellable.kt:30)
	at kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable$default(Cancellable.kt:25)
	at kotlinx.coroutines.CoroutineStart.invoke(CoroutineStart.kt:110)
	at kotlinx.coroutines.AbstractCoroutine.start(AbstractCoroutine.kt:126)
	at kotlinx.coroutines.BuildersKt__Builders_commonKt.launch(Builders.common.kt:56)
	at kotlinx.coroutines.BuildersKt.launch(Unknown Source)
	at kotlinx.coroutines.BuildersKt__Builders_commonKt.launch$default(Builders.common.kt:47)
	at kotlinx.coroutines.BuildersKt.launch$default(Unknown Source)
	at com.sohail.Example.<init>(TracerImpl.kt:77)
@fvasco
Copy link
Contributor

fvasco commented Jan 26, 2022

See #3107

@qwwdfsad
Copy link
Member

Could you please provide a self-contained snippet of code that one can copy-paste and run? I've tried to run your example with some tweaks, but it seems working just fine.

This is likely to be the compiler bug, as collect {} extension and the corresponding SAM-conversion should be completely identical. CCE is a good indicator of some compiler misbehaviour here, especially when onEach{}.collect() works

@sohail77
Copy link
Author

Could you please provide a self-contained snippet of code that one can copy-paste and run? I've tried to run your example with some tweaks, but it seems working just fine.

This is likely to be the compiler bug, as collect {} extension and the corresponding SAM-conversion should be completely identical. CCE is a good indicator of some compiler misbehaviour here, especially when onEach{}.collect() works

I've updated the dependency to 1.6 but missed changing the language version of kotlinCompileOptions in my grade file. It was still using 1.4, changing that to 1.6 fixed this issue. I'm closing this.

@bennyhuo
Copy link

This is caused by the legacy compiler when using Kotlin 1.6.10. Enable IR compiler by removing useOldBackend = true to fix this issue.

@james-novino
Copy link

The compiler change does have some unwanted impacts on reflection-based annotation scanning, what's the proposed solution for dealing with this for systems that must use "useOldBackend" until those dependencies support the upgrade?

@elizarov
Copy link
Contributor

elizarov commented Jun 7, 2022

james-novino The compiler change does have some unwanted impacts on reflection-based annotation scanning, what's the proposed solution for dealing with this for systems that must use "useOldBackend" until those dependencies support the upgrade?

You should report this "unwanted impact on reflection-based annotation scanning" as a separate regression in the current JVM IR backend to http://kotl.in/issue if you want a workaround for them to be implemented. The old backend and useOldBackend option will be removed soon.

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

No branches or pull requests

6 participants