2

How can I force a compile-time error, when somebody tries to use a function as expression that is not intended to be used like that?

fun someFunctionThatReturnsNothing() { println("Doing some stuff") }
// this should give an error:
val value = someFunctionThatReturnsNothing()

My use-case is generating a DSL where there can be name-clashes between DSL builders and sub DSLs in other builders depending on the scope of execution - e.g.:

// this is valid, calling RequestDSL.attribute(...) : Unit here,
val myRequest = request { 
  attribute {
    name = "foo"
    value = "bar"
  }
}

// this is valid, calling AttributeDSLKt.attribute(...) : Attribute
val special = attribute {
  name = "special"
  value = "ops"
}
val myRequest = request { 
  extraAttribute = special
}

// this does not compile, but is confusing,
// because the compiler does not complain where the error was made  
val myRequest = request {
  // the user intends to call AttributeKt.attribute(...) : Attribute,
  // but the compiler can only call RequestDSL.attribute(...) : Unit here
  val special = attribute {
    name = "special"
    value = "ops"
  }
  // this is confusing and should already have been prevented above:
  //    >> Type mismatch. Required: Attribute. Found: Unit. <<
  extraAttribute = special
}

If I could do something like RequestDSL.attribute(...) : void, the user wouldn't even be allowed to call attribute(...) as an expression inside the DSL. That would avoid the issue.

Can this be done somehow?

I tried Nothing, but it just makes all code unreachable after the function call.

I also tried Void, but it just force me to make the return nullable and return null instead of giving an error on the call side.

Mathias Henze
  • 2,190
  • 1
  • 12
  • 8
  • 1
    No, you won't be able to do this. (Also, `Void` isn't a Kotlin thing, it's Java's `void` wrapper type.) – Salem May 16 '20 at 12:52
  • A function like that _does_ return something (else, as the compiler points out, it would never reach the following code).  It just doesn't return a _useful_ value.  In these cases, Kotlin arranges for it to return the [Unit](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/) object.  But I don't think that's going to help you, as `Unit` is a perfectly valid type, and you can assign it to a variable if you want. – gidds May 16 '20 at 14:10
  • What about an annotation? I wouldn't mind if it's jvm-only, since it generates a wrapper DSLs for java builder patterns anyway. – Mathias Henze May 16 '20 at 14:23

0 Answers0