question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Scoping blocks reformatted to invalid Kotlin

See original GitHub issue

Scoping blocks ({ val doesntEscapeScope }) are reformatted by ktfmt to cause semantically different Kotlin, leading to a compiler error or production bug. For example:

someMethod()

{
   // do some things in a scope
}

becomes:

someMethod() {
  // do some things in a lambda argument to someMethod
}

Even worse, because of trailing semicolon stripping, there is no way for the author to prevent this behavior:

someMethod();

{
   // do some things in a scope
}

is semantically equivalent to

someMethod(); {
  // do some things in a scope
}

but becomes the aforementioned

someMethod() {
  // do some things in a lambda argument to someMethod
}

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Reactions:2
  • Comments:5 (3 by maintainers)

github_iconTop GitHub Comments

1reaction
aragoscommented, Dec 9, 2021

Thanks for the heads up! The “unused lambda” situation is indeed very problematic - while it is a compiler warning it seems severe enough that we’re looking to ban it via lint check in our codebase.

Meanwhile, there are some legitimate cases where the formatter still creates problems, such as this:

fun returnDeferredLambda(): Deferred<Input -> Output> =
  async {
    val values = do_async_things()
    { input -> turn_input_to_output(input, values) }
  }

Here the “standalone” lambda is the return value of the async call and should not be treated as an argument to do_async_things.

So if you could help in addressing them that would be much appreciated!

0reactions
strulovichcommented, Dec 20, 2021

Sorry for the delay, took a look today. Kotlin considers this lambda to be an argument to the function call, no matter the spacing.

I tried writing an simpler example for it:

fun main() {
    f {
        println("1")
        val l = { println("2") }
        l // this is ok
    }
    f {
        println("3")
        { println("4") } // this does not compile:
        // Type mismatch: inferred type is Unit but () -> Unit was expected
        // Type mismatch: inferred type is Unit but () -> Unit was expected
        // Too many arguments for public inline fun println(): Unit defined in kotlin.io
        // Expression is treated as a trailing lambda argument; consider separating it from call with semicolon
    }
}

fun f(block: () -> (() -> Unit)) {
    val innerBlock = block.invoke()
    innerBlock.invoke()
}
Read more comments on GitHub >

github_iconTop Results From Across the Web

Kotlin: how to limit scope within a block? - Stack Overflow
You can use run for this purpose: inline fun <R> run(block: () -> R): R (source) Calls the specified function block and returns...
Read more >
Functions | Kotlin
Consider the reformat() function, which has 4 arguments with default values. You can skip all the ones with default values: reformat("This is a ......
Read more >
IntelliJ plugin behaves weird when auto-completing Jetpack ...
I would think it's irrelevant because it's compose which is kotlin only. ... Scoping blocks reformatted to invalid Kotlin #262.
Read more >
Converting to Kotlin - Android Developers
In this codelab, you'll learn how to convert your Java code to Kotlin.
Read more >
Groovy Language Documentation
Package scope visibility; 3.2.5. ARM blocks; 3.2.6. Inner classes. Static inner classes; Anonymous Inner Classes; Creating Instances of Non-Static Inner ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found