# V0017 field_outside_record

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

> A block statement is headed name: …, an anonymous record literal's field (design §17.297 (6), §17.305 (3)).

An error from the `parse` phase. `sakura explain V0017` prints this explanation offline.

A block statement is headed `name: …`, an anonymous record literal's field (design §17.297 (6),
§17.305 (3)). `{ request: 0, cap: 0 }` in expression position is a block, not a record: Sakura
Lang has no anonymous records, so a record literal names its type. Each `name: …` is one record
at the name, whether or not `name` is in scope, and the value up to the next `,` or the line's
end is skipped. Declare a record type and name it in the literal.

Wrong:

```sakura
let c = { request: 0, cap: 0 }
```

Fixed:

```sakura
type Budget = { request: Int, cap: Int }
let c = Budget { request: 0, cap: 0 }
```

## Wrong program [#wrong-program]

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

```sakura
// §17.294 WP-6, §17.297 (6), §17.305 (3): `{ request: 0, cap: 0 }` in expression position is a
// block, so each `name: …` is reported once at its name and the parser takes the value up to the
// next `,` or the line's end with it: a k-field literal is k `V0017`, with no `V0009` cascade. The
// message says a record literal names its type, no `import std/llm.{request}` is offered though
// std/llm exports a `request`, and a name that resolves (`cap` below) is reported all the same.
pub fn budget() -> Int {
  let c = { request: 0, cap: 0 }
  let cap = 1
  let d = {
    request: List.len([1, 2])
    cap: cap
  }
  0
}
```

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

```json
{
  "schema_version": "1.0",
  "kind": "diagnostic",
  "id": "d:7c924d073117b6b5",
  "code": "V0017",
  "severity": "error",
  "phase": "parse",
  "message": "`request: …` is not a statement; a record literal names its type: `Type { request: …, … }`",
  "snapshot": "sha256:$SNAPSHOT",
  "symbol_id": "main::V0017_anonymous_record_literal::budget",
  "spans": [
    {
      "uri": "file://$DIR/V0017_anonymous_record_literal.sak",
      "content_hash": "sha256:c60e0016a7cda15056e16b58c85ff055bc21e240fbd7429de2d6f465e9e631e5",
      "start_byte": 582,
      "end_byte": 589,
      "role": "primary"
    }
  ],
  "related_ids": [],
  "expected": null,
  "actual": null,
  "obligation": null,
  "counterexample": null,
  "explanation_uri": "sakura://explain/V0017",
  "fixes": []
}
```

## Fixed program [#fixed-program]

No fixed program is checked in for this code yet; the explanation above describes the repair.
