Hi, I have stumbled onto something that confuses m...
# compiler
k
Hi, I have stumbled onto something that confuses me.
Copy code
inline fun destructInlineLambda(x: () -> Int) {
    val (a, b, c) = x
    println("$a$b$c")
}


inline operator fun (() -> Int).component1() = this().toString()[0] - '0'
inline operator fun (() -> Int).component2() = this().toString()[0] - '0'
inline operator fun (() -> Int).component3() = this().toString()[0] - '0'
Now, running this with
destructInlineLambda{456}
prints "456" to the console as expected. However I get 4 warnings, all 3 operator functions had the typical "nothing to inline" warning ("Expected performance impact from inlining is insignificant. Inlining works best for functions with parameters of functional types"), and at the place where
x
is used I got this: "Deprecated usage of inline-parameter 'x' in 'public final inline fun destructInlineLambda(x: () -> Int): Unit defined in pkg.TestDestructors'. Add 'noinline' modifier to the parameter declaration. See https://youtrack.jetbrains.com/issue/KT-52502" Now this is weird cause they are all wrong. The component functions get properly inlined as can be shown below, and the KT-52502 assumes (quote:) "However, extension receivers are implicitly noinline", which again see below is not true.
Copy code
run{
    	for (i in 990..1010)
        	destructInlineLambda{if (i in 100..999) i else return@run}
}
    	
println("bye")
This compiles and runs as expected, meaning that the lambda had to be inlined for the
return@run
to work. Should I make multiple bug reports for this / do there already exists reports for these?
I also couldn't find anything in the spec saying that receivers are implicitly noinline
e
The warnings on
inline
are perfectly reasonable. There is no reason to mark those extensions as
inline
. However, the no-inline status of receivers should be better documented, indeed. To be fair, using functional types in the receiver position is extremely rare in Kotlin.
k
But they are being inlined?
I also noticed that the warning on the usage of
x
is only present in IntelliJ idea and in the online playground, but running the compiler on the code only produces warnings for the "useless"
inline
and not for
x
e
Sometimes it is inlined, sometimes it crashes the compiler. Anyway, we plan to deprecate the case when it was inlining it (see https://youtrack.jetbrains.com/issue/KT-52502)
k
I feel like my issue isn't getting across properly, so let me restate some stuff. KT-52502 claims the following: • "However, extension receivers are implicitly noinline, and it means we need USAGE_IS_NOT_INLINABLE diagnostic here." • "Such code always caused the compiler to fail with exception" The compiler produces warnings seemingly agreeing with the assumption that "extension receivers are implicitly noinline", by producing warnings that there isn't anything to inline. However the compiler does inline the receiver and therfore allows
x
to be passed as a receiver to the
componentN
functions. I checked this by included non local returns in the lambda and running and by checking decompiled bytecode for multiple cases.
So the issues: • Some parts of the compiler (and the Kotlin team) seem to be assuming that receiver parameters don't get inlined, even though it seems they are? • Based on this assumption, the KT-52502 warning is placed on all cases where an inlined functional type is accepted, instead of only on the cases where the function type is converted to Any? or similar. I'm guessing that some kind of checker isn't properly flagging the receiver as inline and that is what's causing both the "nothing to inline" and the KT-52502 warning to appear (idk how the compiler works). Or the compiler is compiling the code when it wasn't expected to do so?
Huh, looking a bit further, this feels like an undocumented change that made receivers no longer be "noinline"
e
Receivers were never supposed to be inlineable, it was never tested nor supposed to work. But sometimes it accidentally worked without crashing the compiler.