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

UncheckedReifiedCast #7142

Open
mgroth0 opened this issue Apr 6, 2024 · 0 comments
Open

UncheckedReifiedCast #7142

mgroth0 opened this issue Apr 6, 2024 · 0 comments
Labels

Comments

@mgroth0
Copy link
Contributor

mgroth0 commented Apr 6, 2024

Expected Behavior of the rule

Report whenever a reference is casted to reified type parameter.

Context

Kotlin has an open issue that the compiler doesn't warn about problematic casts in inline functions with reified generics
The way I worded it in my issue is False negative UNCHECKED_CAST when casting to reified type. My issue was left open but marked as a duplicate of the other one.

I will summarize the problem here.

In Kotlin we can cast in a way that is "checked" or "unchecked". By "checked", we mean here that the cast is checked at runtime. Whatever type we tell the compiler to check as, at runtime it will be asserted that the reference is of that type. "unchecked" means that the compiler will assume that the reference is of the requested type, but will not check (or will not fully check) at runtime.

Example of a checked cast:

list is List<*>

Example of a unchecked cast:

list is List<Int>

The kotlin compiler detects some (but not all) unchecked casts. It emits a warning which can be suppressd with @Suppress("UNCHECKED_CAST"). If -Werror is enabled, compilation will fail on the unchecked casts it detects, but will not fail or even warn on the ones it does not detect.

The unchecked casts that are not detected by the compiler are in inline functions which cast to a reified type.

For example, this program contains an unchecked cast will not be reported by the kotlin compiler.

fun main() {
    listOf("1","2","3").assumedIs<List<Int>> { listOfInts -> 
        println(listOfInts[0]+1)
    }
}
inline fun <reified T> Any?.assumedIs(op: (T) -> Any) {
    op(this as T)
}

As a result, it throws a ClassCastException at runtime.

In theory, this rule would enable compilations that make it impossible for user code to throw a ClassCastException (can't prevent library code from throwing it). If we have:

If all of the above are implemented for a compilation, I think it might just logically prevent any ClassCastException from possibly being thrown directly from the code being compiled (of course dependencies can still throw it)

@mgroth0 mgroth0 added the rules label Apr 6, 2024
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

1 participant