DIP 1017--Add Bottom Type--Final Review

Johannes Loher johannes.loher at fg4f.de
Wed Jan 16 08:09:39 UTC 2019


On Wednesday, 16 January 2019 at 07:04:37 UTC, Neia Neutuladh 
wrote:
> Kotlin has a type called Nothing. It doesn't do implicit 
> conversions. It supports the ternary logic that this DIP 
> proposes as a side effect (you can use throw and return in the 
> same way). You can have variables of this type, pass it to 
> functions, assign it to things, etc.
>
>     fun foo(): Nothing {
>         throw Exception("this doesn't work")
>     }
>     fun foo2(n: Nothing) {}
>     fun bar() {
>         try {
>             var n: Nothing = foo()
>             foo2(n)
>             var n2 = if (true) { 12 } else { foo() }
>         } catch (e: Exception) {}
>     }

This is not completely accurate. Nothing actually is the bottom 
type in Kotlin in the sense that it DOES implicitly convert to 
any type. E.g.

```
fun foo() : Nothing {
     throw Exception()
}

fun bar(s: String)
{

}

fun main(args: Array<String>) {
     bar(foo())
}
```

is a valid Kotlin program.

As you mention, you can however pass around variables of type 
`Nothing`. You can also somewhat do this with the type proposed 
by the DIP, but it is kind of limited: You can return expressions 
of type `Tbottom`, but you cannot declare a variable of that type 
or use it as parameter, similar to `void`. The reason for this is 
probably that in D every declared variable must by default be 
initiated to some value and this is not possible for void and 
`Tbottom`. However, I think this limitation is a bit arbitrary. 
We also have other types which do not have default 
initialization. Also this is valid D:

```
struct Tbottom {
     @disable this();

     this(const ref Tbottom t)
     {
     }

     @disable static Tbottom init() @property;
}

struct A {}

Tbottom fun()
{
     assert(0);
     return cast(Tbottom) A();
}

void main()
{
     Tbottom t = fun();
}
```

Granted, this still allows casting to `Tbottom` and this type is 
not implicitly convertible to every other type (these properties 
need to be baked into the language, I think) and you can still 
use the struct literal syntax to initialize variables of type 
`Tbottom`.

But I think this showcases that it is not necessary conceptually 
to disallow declaring variables of type Tbottom. They just need 
to be initialized to an expression of type `Tbottom`. They still 
can never have an actual value or be used because by definition, 
the expression they are initialized to never returns. The same is 
true for function parameters.

I actually also think it is correct to do the same for `void`, 
but `void` should even a single value and thus it should be 
default constructible and have an `init` property. As I mentioned 
earlier in this thread, this would make `void` a proper unit 
type, drawing a clear line between `Tbottom` and `void`. It is 
however very complicated to get this to work with 
C-interoperability.


More information about the Digitalmars-d mailing list