Module Sarek_unsupported

Refusal text for the OCaml constructs the Sarek kernel parser does not implement (backlog-192).

WHY THIS MODULE EXISTS. Sarek_parse reads the ppxlib Parsetree and builds Sarek_ast. Where the surface language offers something the kernel subset does not implement, the parser used in several places to drop it and carry on — the when-guard drop fixed in backlog-191 is the measured instance: pc_guard was never read, so the guard vanished upstream of the typer, of every lowering pass and of backend selection, and the kernel compiled and computed a different function than its source said.

A dropped construct is worse than a refused one in a specific way: the user gets no diagnostic at all, and the wrongness surfaces (if it surfaces) as a wrong ANSWER on a device, arbitrarily far from its cause. So the accepted subset has to be a boundary the parser states out loud, not a filter it applies quietly.

WHY THE TABLES BELOW HAVE NO WILDCARD ARM. Each *_refusal function matches every arm of its Parsetree variant explicitly, so the OCaml compiler is what notices when ppxlib grows a constructor: the build stops until somebody writes down what the new arm is, instead of it reaching a user as silence. A | _ -> here would hand that back.

What makes the build actually stop is -warn-error +8 in sarek/ppx/dune, on this library. Measured 2026-07-31 by deleting the Pexp_try arm below: dune's dev :standard already turns warning 8 into an error (exit 1), but --profile=release left it a plain warning and the build SUCCEEDED at exit 0 until that flag was added; with it, release fails at exit 1 too and the unmutated tree builds at 0 in both profiles. -w +8, which was the flag this comment used to credit, changes nothing in either profile — :standard supplies the dev error and supplies nothing in release. The guarantee is scoped to sarek_frontend, the library this module is in: none of the PPX's other libraries carries the flag, and one test directory (sarek/tests/codegen_golden) already carried it before this change.

WHAT THESE FUNCTIONS ARE NOT. They are not a claim that everything they name is refused THROUGH THEM. Several arms below are partially implemented — the parser handles a shape and falls through to its catch-all for the rest (an identifier is read at depth one, M.x, and no deeper; a for binder is read when it is a variable, and not when it is _). For those the text states the subset that IS accepted, because "not supported" alone would be false. Which arms are in that state is recorded per-site in kb/sarek/ppx/parser.md, not here.

val kernel_extensions : string

The four extension points Sarek_parse.parse_expression interprets inside a kernel body. Written without brackets on purpose: this string is embedded in refusal text, and a bracketed sigil spelling in message text is a claim about a declared construct that scripts/check-ppx-construct-names.sh checks against the PPX's own name table. These four are matched by hand on the AST rather than declared through Extension.declare, so no declaration context exists to check a sigil count against.

val expression_refusal : Ppxlib.expression_desc -> string

Refusal text for an expression the kernel subset does not accept.

Reached from Sarek_parse.parse_expression's final arm, so it is asked about BOTH constructs that are wholly unimplemented and shapes of partially-implemented constructs that the earlier arms did not match.

val pattern_refusal : Ppxlib.pattern_desc -> string

Refusal text for a pattern the kernel subset does not accept. Reached from Sarek_parse_helpers.parse_pattern's final arm.

val core_type_refusal : Ppxlib.core_type_desc -> string

Refusal text for a core_type the kernel subset does not accept. Reached from Sarek_parse_helpers.parse_type's final arm, which until backlog-192 returned the type constructor named "unknown" instead — a name the typer resolves to an EMPTY RECORD type, so an unsupported annotation became a phantom type rather than an error.

val structure_item_refusal : Ppxlib.structure_item_desc -> string

Refusal text for a structure item inside a kernel payload's let module M = struct ... end. Reached from Sarek_parse.parse_payload, whose module-item fold until backlog-192 returned its accumulator unchanged for everything it did not recognise — so a helper the user wrote in that module simply was not there, and the kernel failed later with an unbound name, or (worse) resolved a same-named binding from somewhere else.