# V3003 try_unknown_failures

URL: /docs/errors/V3003
Markdown: /docs/errors/V3003.md

> try without catch must name every failure of its body in Result<T, E>.

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

`try` without `catch` must name every failure of its body in `Result<T, E>`. When the body's
row ends in a row variable `e` that is never written next to `Fail<…>` in its declaration, `e`
may hide failures nobody can name (design §5.2 rule 8, §5.3), so `E` cannot be written.
Declare the failures with a type parameter, which makes `e` Fail-free. (`try … catch` is fine:
its arms match the named tags and the hidden failures stay in the row.)

Wrong:

```sakura
fn wrap<e>(f: fn() -> Int ! e) -> Result<Int, Never> ! e { try { f() } }
```

Fixed:

```sakura
fn wrap<E, e>(f: fn() -> Int ! {Fail<E> | e}) -> Result<Int, E> ! e { try { f() } }
```

## Wrong program [#wrong-program]

[`compiler/tests/ui/V3003_try_unknown_failures.sakura`](https://github.com/icantcodefyi/sakuralang/blob/master/compiler/tests/ui/V3003_try_unknown_failures.sakura), which the compiler's ui suite runs through `sakura check`:

```sakura
fn wrap<e>(f: fn() -> Int ! e) -> Result<Int, Never> ! e { try { f() } }
```

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

```json
{
  "schema_version": "1.0",
  "kind": "diagnostic",
  "id": "d:488bcf070436dae6",
  "code": "V3003",
  "severity": "error",
  "phase": "effect",
  "message": "`try` cannot name the failures of its body: the row ends in `e`, which may hide `Fail<…>`; declare them with a type parameter (`fn f<E, e>(g: fn() -> T ! {Fail<E> | e}) -> Result<T, E> ! e`)",
  "snapshot": "sha256:$SNAPSHOT",
  "symbol_id": "main::V3003_try_unknown_failures::wrap",
  "spans": [
    {
      "uri": "file://$DIR/V3003_try_unknown_failures.sakura",
      "content_hash": "sha256:68cf14995b2b4537e9a972833172f335e9abd89eee9b5fba28a1f371d57f9873",
      "start_byte": 93,
      "end_byte": 104,
      "role": "primary"
    }
  ],
  "related_ids": [],
  "expected": null,
  "actual": {
    "render": "e",
    "row": {
      "labels": [],
      "tail": "e"
    }
  },
  "obligation": null,
  "counterexample": null,
  "explanation_uri": "sakura://explain/V3003",
  "fixes": [
    {
      "id": "f:488bcf070436dae6.0",
      "title": "Declare the failures of `e` as `Fail<E>` in the signature",
      "applicability": "incomplete",
      "impact": "interface_change",
      "edits": []
    }
  ]
}
```

## Fixed program [#fixed-program]

[`compiler/tests/ui/V3003_try_unknown_failures.fixed.sakura`](https://github.com/icantcodefyi/sakuralang/blob/master/compiler/tests/ui/V3003_try_unknown_failures.fixed.sakura), which `sakura check` accepts with no diagnostics:

```sakura
fn wrap<E, e>(f: fn() -> Int ! {Fail<E> | e}) -> Result<Int, E> ! e { try { f() } }
```
