roc-lang / roc

A fast, friendly, functional language.
https://roc-lang.org
Universal Permissive License v1.0
4.46k stars 313 forks source link

Cannot define a function using the try operator `?` in an `expect` statement #7081

Closed ageron closed 1 month ago

ageron commented 2 months ago

The following code fails with roc nightly pre-release, built from commit 9a4d556 on Mon Sep 9 09:02:33 UTC 2024:

app [main] {
    pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.15.0/SlwdbJ-3GR7uBWQo6zlmYWNYOxnvo8r6YABXD-45UOw.tar.br",
}

import pf.Stdout

inc = \i ->
    if i > 2 then
        Err MaxReached
    else
        Ok (i + 1)

expect
    run = \i ->
        newi =
            i
            |> inc?
            |> inc?
        Ok newi
    result = run 0
    result == Ok 2

main =
    Stdout.line! "Hello world"

The error is:

An internal compiler expectation was broken.
This is definitely a compiler bug.
Please file an issue here: <https://github.com/roc-lang/roc/issues/new/choose>
a Expr::TrySuffix expression was not completely removed in desugar_value_def_suffixed
Location: crates/compiler/can/src/expr.rs:1125:40

The problem disappears if I define the run function outside the expect statement. However, I'd like to avoid polluting the global scope, and I'd like to keep the function tied to the expect statement.

ageron commented 1 month ago

Here's a shorter example, in a module:

# Inc.roc
module [inc]

inc = \i -> if i > 2 then Err TooBig else Ok (i + 1)

expect
    result = inc? 0
    result == 1

Just run roc test Inc.roc

ageron commented 1 month ago

🥳 thanks @lukewilliamboswell !