Function visibility in nested blocks with a receiver type

Is there a way to prevent a nested receiver block from being able to access functions or variables without defining those parent functions as private? Take for example:

abstract class Foo {
  fun bar(block: Bar.() -> Unit) {
    val bar: Bar = Bar()
    block.invoke(bar)
  }
}

class Bar {}

class Baz : Foo() {
  init {
    bar {
      bar {} // compiler doesn't complain
    }
  }
}

In the Baz#init, I can call bar {} within another bar {} block because there is this which would be a Baz and then also a this@Baz so I believe that’s where the call to bar {} is possible even though I’m in a block of Bar receiver type.

Is there a way to prevent this?

Yep, it’s called DSL-marker and added in 1.1

your code will become

@DslMarker annotation class Component

@Component
abstract class Foo {
    fun bar(block: Bar.() -> Unit) {
        val bar: Bar = Bar()
        block(bar)
    }
}

@Component class Bar

class Baz : Foo() {
    init {
        bar {
            bar {} // compiler makes it more difficult to do
        }
    }
}

for more info see:
https://kotlinlang.org/docs/reference/type-safe-builders.html#scope-control-dslmarker-since-11

1 Like

Ah, works perfectly. Thank you very much!

1 Like