Sakura Lang

V3002 effect_label_not_permitted

A closed effect row was required to be empty or smaller, but an effect label had to be in it (row unification {A | r} ~ {} failed, design §5.2).

An error from the effect phase. sakura explain V3002 prints this explanation offline.

A closed effect row was required to be empty or smaller, but an effect label had to be in it (row unification {A | r} ~ {} failed, design §5.2). The usual cause is passing an effectful function where a parameter's type is a pure fn() -> T. Make the parameter's row a variable so the callee carries the argument's effects through, or handle the effect before passing the function.

Wrong:

fn apply(f: fn() -> Int) -> Int { f() }
fn noisy() -> Int ! {Console} { apply(loud_one) }

Fixed:

fn apply<e>(f: fn() -> Int ! e) -> Int ! e { f() }

Wrong program

compiler/tests/ui/V3002_effect_label_not_permitted.sakura, which the compiler's ui suite runs through sakura check:

fn apply(f: fn() -> Int) -> Int { f() }

fn loud_one() -> Int ! {Console} {
  Console.print("side effect")
  1
}

fn noisy() -> Int ! {Console} { apply(loud_one) }

sakura check --json reports this record (pretty-printed; $DIR is the fixture's directory):

{
  "schema_version": "1.0",
  "kind": "diagnostic",
  "id": "d:eecd3c1441de6f7a",
  "code": "V3002",
  "severity": "error",
  "phase": "effect",
  "message": "expected `fn() -> Int`, found `fn() -> Int ! {Console}`: effect `Console` is performed by this value but not allowed by the expected type",
  "snapshot": "sha256:$SNAPSHOT",
  "symbol_id": "main::V3002_effect_label_not_permitted::noisy",
  "spans": [
    {
      "uri": "file://$DIR/V3002_effect_label_not_permitted.sakura",
      "content_hash": "sha256:a4b6e19ab0cafb694cd04bc0664109475cfca1b6e88f0e7eafea82702d83df5f",
      "start_byte": 186,
      "end_byte": 194,
      "role": "primary",
      "label": "this has type `fn() -> Int ! {Console}`"
    }
  ],
  "related_ids": [],
  "expected": {
    "render": "fn() -> Int"
  },
  "actual": {
    "render": "fn() -> Int ! {Console}"
  },
  "obligation": null,
  "counterexample": null,
  "explanation_uri": "sakura://explain/V3002",
  "fixes": []
}

Fixed program

compiler/tests/ui/V3002_effect_label_not_permitted.fixed.sakura, which sakura check accepts with no diagnostics:

fn apply<e>(f: fn() -> Int ! e) -> Int ! e { f() }

fn loud_one() -> Int ! {Console} {
  Console.print("side effect")
  1
}

fn noisy() -> Int ! {Console} { apply(loud_one) }
Edit on GitHub

On this page