SerenityOS / jakt

The Jakt Programming Language
BSD 2-Clause "Simplified" License
2.77k stars 244 forks source link

typechecker/codegen: `void?` is accepted as `void` #1544

Closed cg-jl closed 5 months ago

cg-jl commented 6 months ago

Given these two samples:

/// Expect:
/// - output: "PASS\n"

enum Foo {
    A
    B
}

fn may_throw() throws {}

fn thing() {
    let a = match Foo::A {
        A => try may_throw() catch {},
        B => {}
    }
}

fn main() {
    thing()
    println("PASS")
}
/// Expect:
/// - output: "PASS\n"

enum Foo {
    A
    B
}

fn may_throw() throws {}

fn is_void() {}

fn thing() {
    match Foo::A {
        A => try may_throw() catch { yield is_void() },
        B => {}
    }
}

fn main() {
    thing()
    println("PASS")
}

Both fail to compile the C++ for a couple of reasons:

  1. try codegen does not use statement-exprs when compiling void, so return <try> and return ExplicitValue(<try>) have statements inside them without having a block to support them.
  2. Optional<void> is used in both C++ outputs, the first one for the a variable, and the second one for the catch result value.

Depending on how we want to handle this, it's either typechecker's fault or codegen's fault: