# Type.Bottom

**URL:** <https://ziggit.dev/t/type-bottom/5558>\
**Category:** Brainstorming\
**Tags:** language, comptime, type-system\
**Created:** [August 8, 2024, 10:10pm UTC](https://ziggit.dev/t/type-bottom/5558 "2024-08-08T22:10:24Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![mnemnion](https://ziggit.dev/user_avatar/ziggit.dev/mnemnion/32/2478_2.png) [@mnemnion](https://ziggit.dev/u/mnemnion)\
**Post date:** [August 8, 2024, 10:10pm UTC](https://ziggit.dev/t/type-bottom/5558/1 "2024-08-08T22:10:24Z")

</div>

Continuing the discussion from [Code review: initialization via tuple of tuples](https://ziggit.dev/t/code-review-initialization-via-tuple-of-tuples/5548/5):

> [@Code review: initialization via tuple of tuples](https://ziggit.dev/t/code-review-initialization-via-tuple-of-tuples/5548/5):
>
> Makes me think of Common Lisp, where T (meaning true) is the root of the type system. It would be nice if this comparison could be tested at compile time without a compile error.

Zig has a type system the way C does (but much better designed): the focus is on defining how memory is used, and establishing how that memory gets into and out of functions. So it doesn’t need a ‘top’ type, like a type-of-all-types, because it doesn’t have a type hierarchy, just some useful rules for when the compiler allows you to coerce one type into another. `anytype` doesn’t really function like a top type, it’s more of a placeholder: “any type can go here, stick something in this slot and see if the function compiles”. `type` isn’t a top type either, that’s a specific tagged union called `Type`, which exists at comptime and can be used accordingly. Zig’s type system is engineering, not mathematics.

But the type-of-no-types would be helpful, specifically so that `@TypeOf(a, b)` could return a value when `a` and `b` have no type they mutually coerce to. This would just be a branch of the tagged union, `Type.Bottom` would be traditional, but `Type.NoType` would work just as well. The essence of what a bottom type is, is that it’s what the type system returns when a value can’t inhabit the type which is demanded by a statement.

It isn’t necessary that `@TypeOf(a_u8_slice, a_bool)` throws an error, this just means that type reflection has to be careful about checking if a peer coercion is possible.

Because it isn’t even catchable:

```zig
test "bottom type" {
    const a: []const u8 = "abcd";
    const b: bool = true;
    _ = @TypeOf(a, b) catch |e| {
        std.debug.print("{!}", .{e});
    };
}

```

This is just a compile error, making this kind of reflection very difficult.

---

<div class="post-metadata">

**Author:** ![anticrisis](https://ziggit.dev/user_avatar/ziggit.dev/anticrisis/32/2960_2.png) [@anticrisis](https://ziggit.dev/u/anticrisis)\
**Post date:** [August 8, 2024, 10:19pm UTC](https://ziggit.dev/t/type-bottom/5558/2 "2024-08-08T22:19:37Z")

</div>

Other relevant analogues: the use of `0` in counting things, even though it doesn’t make sense to have zero of anything. And the use of `std::monostate` in C++, even though it doesn’t make sense to use C++.

---

<div class="post-metadata">

**Author:** ![mlugg](https://ziggit.dev/user_avatar/ziggit.dev/mlugg/32/437_2.png) [@mlugg](https://ziggit.dev/u/mlugg)\
**Post date:** [August 10, 2024, 4:27am UTC](https://ziggit.dev/t/type-bottom/5558/3 "2024-08-10T04:27:47Z")

</div>

The type you’re describing is `noreturn`.

---

<div class="post-metadata">

**Author:** ![mnemnion](https://ziggit.dev/user_avatar/ziggit.dev/mnemnion/32/2478_2.png) [@mnemnion](https://ziggit.dev/u/mnemnion)\
**Post date:** [August 10, 2024, 3:01pm UTC](https://ziggit.dev/t/type-bottom/5558/4 "2024-08-10T15:01:04Z")

</div>

That occurred to me, yes.

The issue I saw there is this:

> When resolving types together, such as `if` clauses or `switch` prongs, the `noreturn` type is compatible with every other type.

There is, so far as I know, no way to create an instance of type `noreturn`, just an expression which ‘returns’ that type. So unless I’m missing a trick, there’s no current way to use `@TypeOf(a, b)` to check peer coercion of a `noreturn` value, since those don’t exist. But the description lead me to think that for all T, `@TypeOf(instance<T>, instance<noreturn>)` would be T, which doesn’t quite fit the bill.

So yes, `noreturn` is a bottom type by any reasonable measure, but it’s an inhabited one.

If you think that `noreturn` is a reasonable return value for calling `@TypeOf(a, b)` on values which have no common peer resolution, then that’s great, the `Type.Bottom` I’ve been talking about already has a name, `Type.NoReturn`, and providing this affordance would be a smaller change. If the type system already represents a contradictory peer type coercion as `Type.NoReturn`, then this is the obvious choice.

I don’t know enough about the mechanics of semantic analysis in Zig to say anything intelligent about the consequences of doing it that way, vs. having a, let’s say `Type.Empty` now, which is by definition uninhabited, and exists only as the return value of incompatible type coercion. But if it works, that’s great! Only add complexity when you need it.
