Module Sarek_error

type unlowered_reason =
  1. | Warp_collective
    (*

    A warp-level collective that is typed and convergence-checked but not lowered by any backend yet (vote, ballot, active mask). The shuffles, warp_size and lane_id ARE lowered and never reach this reason.

    *)
  2. | Early_return
    (*

    return_unit: Sarek has no early return and no backend lowers it soundly.

    *)

Why an intrinsic that type-checks is nevertheless refused at PPX time. The mapping from intrinsic to reason is the single table Sarek_unlowered.table; this type only selects the wording.

type error =
  1. | Unbound_variable of string * Sarek_ast.loc
  2. | Unknown_qualified_name of {
    1. name : string;
    2. known : string list;
    3. loc : Sarek_ast.loc;
    }
    (*

    M.f inside a kernel names nothing the kernel PPX knows: no intrinsic, [@sarek.module] item or binding. known lists the names the PPX does know under the same module prefix (for typos).

    *)
  3. | Unbound_constructor of string * Sarek_ast.loc
  4. | Unbound_field of string * Sarek_ast.loc
  5. | Unbound_type of string * Sarek_ast.loc
  6. | Type_mismatch of {
    1. expected : Sarek_types.typ;
    2. got : Sarek_types.typ;
    3. loc : Sarek_ast.loc;
    }
  7. | Cannot_unify of Sarek_types.typ * Sarek_types.typ * Sarek_ast.loc
  8. | Not_a_function of Sarek_types.typ * Sarek_ast.loc
  9. | Wrong_arity of {
    1. expected : int;
    2. got : int;
    3. loc : Sarek_ast.loc;
    }
  10. | Not_a_vector of Sarek_types.typ * Sarek_ast.loc
  11. | Not_an_array of Sarek_types.typ * Sarek_ast.loc
  12. | Not_a_record of Sarek_types.typ * Sarek_ast.loc
  13. | Field_not_found of string * Sarek_types.typ * Sarek_ast.loc
  14. | Immutable_variable of string * Sarek_ast.loc
  15. | Recursive_type of Sarek_types.typ * Sarek_ast.loc
  16. | Unsupported_expression of string * Sarek_ast.loc
  17. | Parse_error of string * Sarek_ast.loc
  18. | Invalid_kernel of string * Sarek_ast.loc
  19. | Duplicate_field of string * Sarek_ast.loc
  20. | Missing_type_annotation of string * Sarek_ast.loc
  21. | Invalid_intrinsic of string * Sarek_ast.loc
  22. | Barrier_in_diverged_flow of Sarek_ast.loc
  23. | Warp_collective_in_diverged_flow of string * Sarek_ast.loc
  24. | Reserved_keyword of string * Sarek_ast.loc
  25. | Reserved_prefix of string * Sarek_ast.loc
  26. | Unsupported_type_in_registration of string * Sarek_ast.loc
  27. | Unsupported_constructor_form of Sarek_ast.loc
  28. | Unsupported_registration_form of Sarek_ast.loc
  29. | Unsupported_tuple_in_variant of Sarek_ast.loc
  30. | Unsupported_function_in_variant of Sarek_ast.loc
  31. | Unknown_variant_type of string * Sarek_ast.loc
  32. | Expression_needs_statement_context of string * Sarek_ast.loc
  33. | Invalid_lvalue of Sarek_ast.loc
  34. | Function_value_escapes of string * Sarek_types.typ * Sarek_ast.loc
  35. | Instantiation_mismatch of {
    1. callee : string;
    2. t1 : Sarek_types.typ;
    3. t2 : Sarek_types.typ;
    4. loc : Sarek_ast.loc;
    }
    (*

    A call site could not be typed against the callee's type. Reported instead of a bare Cannot_unify when the callee is NAMED, because the bare form ("Cannot unify types: float32 and float64") gives the user two type names and no indication of which function they came from — the reported failure mode of a polymorphic @sarek.module helper instantiated at a non-default element type (#97).

    *)
  36. | Aggregate_equality_operand of string * Sarek_types.typ * Sarek_ast.loc
    (*

    backlog-194: a value with no comparable device representation reached = or <> — a tuple, record or variant (a struct: no backend lowers the comparison field-wise, and the C-family emitters print a == b, which those compilers reject), or a function (inlined at its call sites and never emitted, so f == g named identifiers that do not exist in the generated source). The set is Sarek_types.is_uncomparable_operand_typ; the typ is the operand type, so the message can name what was compared. Pointer-shaped operands (a vector, a local array) are NOT this error: src = dst emits (src == dst), which clang -x cl and glslangValidator both accept.

    *)
  37. | Unlowered_intrinsic of {
    1. name : string;
    2. reason : unlowered_reason;
    3. loc : Sarek_ast.loc;
    }
    (*

    name resolved to an intrinsic that no backend lowers soundly (see unlowered_reason). Refused at the use site, with a located error.

    *)
  38. | Float16_operand of string * Sarek_ast.loc
    (*

    An f16 value reached an operator. f16 is a storage-only type, so this is always a user error with a specific remedy; reporting it as Type_mismatch {expected = int32} (what check_numeric's fall-through produced) told the user nothing. The string names the operator.

    *)
  39. | Warp_shuffle_value_type of string * Sarek_types.typ * Sarek_ast.loc
    (*

    A warp shuffle applied to a value that is not int32, float32 or float64: the primitive's name, the offending type.

    *)

Error types

val error_loc : error -> Sarek_ast.loc

Get the location from an error

val binop_display_name : Sarek_ast.binop -> string

Human-readable operator name for diagnostics, e.g. '=' -> "'='". Lives here rather than in Sarek_typer because two modules render an operator into a diagnostic — the typer's infer_binop and the aggregate-equality backstop in Sarek_lower_ir (backlog-194) — and a per-module match over binop is two spellings of one name with nothing comparing them.

val aggregate_equality_body : Sarek_types.typ -> string

backlog-194. The body of the aggregate-equality refusal, WITHOUT the leading operator name. It is a function rather than inline text in pp_error because two sites emit this refusal — the typer's, through Aggregate_equality_operand, and the post-monomorphisation backstop in Sarek_lower_ir, which raises a located Ppxlib error directly. An earlier revision had the second site build an Aggregate_equality_operand with a FAKE location purely to borrow this printer; sharing the body instead is what lets the two agree on the wording without either lying about a loc.

What the text does and does not claim. It says no backend lowers the comparison field-wise, which is true of all seven. It does NOT enumerate what each backend prints: that was a standing claim about six modules with nothing tying it to them, and it is the per-backend evidence, dated, that belongs in the negative-test headers instead.

The remedy is given in SOURCE terms. It previously advised a._0 = b._0 for a tuple, which is not writable: _0 is the synthesized field name of the internal _tup_* record, and a field access on a tuple-typed value is refused by the typer with Not_a_record. Destructuring is the spelling that works.

val unlowered_reason_body : unlowered_reason -> string

The body of the Unlowered_intrinsic refusal, after the intrinsic's name. Separate from pp_error so the wording per reason is read in one place.

val pp_error : Stdlib.Format.formatter -> error -> unit

Pretty print an error

val error_to_string : error -> string

Convert error to string

val pp_error_with_loc : Stdlib.Format.formatter -> error -> unit

Print error with location

type 'a result = ('a, error list) Stdlib.Result.t

Result type for error accumulation

val (let*) : ('a, 'b) Stdlib.result -> ('a -> ('c, 'b) Stdlib.result) -> ('c, 'b) Stdlib.result

Monadic operations for error handling

val ok : 'a -> ('a, 'b) Stdlib.result
val error : 'a -> ('b, 'a list) Stdlib.result
val errors : 'a -> ('b, 'a) Stdlib.result
val map_result : ('a -> 'b) -> ('a, 'c) Stdlib.result -> ('b, 'c) Stdlib.result
val combine_results : ('a, 'b list) Stdlib.result list -> ('a list, 'b list) Stdlib.result
val report_error : error -> 'a

Report error to ppxlib

val report_errors : error list -> unit

Report multiple errors

exception Sarek_error of error

Raise error as OCaml exception for use in PPX

val raise_error : error -> 'a