A per-module table of every named error and warning variant the compiler declares, tagged with whether a test fixture currently exercises it.
The catalog has two practical uses:
- Coverage expansion — find rows tagged
☐(reachable but no fixture) and add asuper_errors/super_errors_multifixture for each. The Notes column points at the trigger site and any required AST shape. - Dead-code removal — rows tagged
⚠are variants whose trigger site is unreachable in the current parser / compiler, with a named blocker. They can be deleted in a follow-up PR.
| Symbol | Meaning |
|---|---|
| ✓ | Covered by at least one fixture under tests/build_tests/super_errors/ or tests/build_tests/super_errors_multi/. |
| ⚠ | Verified unreachable: the trigger site has a specific blocker named in source (an exception declared but never raised, an AST node the parser doesn't construct, a guard that's always false). Candidate for dead-code removal. |
| ☐ | Reachable but no fixture yet; would be valuable to add. |
| ? | Trigger site is live but reachability from regular ReScript source isn't confirmed. Distinct from ⚠: a ? means "I couldn't find a fixture that reaches it" rather than "the path is provably blocked". |
The removal audit section below records variants that have already been deleted or retained after re-validation.
This catalog enumerates named error variants — constructors of
type error = … declarations across compiler/. The compiler also has
~94 Location.raise_errorf and similar inline calls that produce
user-facing errors without a named variant. Those are not catalogued
here because there's no constructor to track. If someone wants to add
coverage for one of those messages, the first step is refactoring it
into a named variant.
Diagnostic types in vendored third-party sources are also excluded. In
particular, Flow parser Parse_error.t values cross into the ReScript compiler
as warning 103 (Bs_ffi_warning), whose integration boundary is covered by
warning_103_flow_parser.res.
- Single-file fixtures live in
build_tests/super_errors/fixtures/with expected output inbuild_tests/super_errors/expected/. - Multi-file fixtures live in
build_tests/super_errors_multi/fixtures/<FixtureName>/with expected output inbuild_tests/super_errors_multi/expected/<FixtureName>.expected.
When you add or remove an error variant in compiler/, update the
corresponding row here too:
- Add (or remove) the row in the appropriate module section below.
- Write a fixture if the variant is reachable. Use
super_errors/for single-file scenarios,super_errors_multi/for cross-file ones. - Snapshot with
node tests/build_tests/super_errors{,_multi}/input.js update. - Set the status column accordingly.
If a variant turns out to be unreachable, document the named blocker
here (so it gets ⚠ instead of ?) and file a follow-up to delete the
dead code.
Two classes of removal. Truly dead variants — no raise site under
compiler/, or a guard whose predicate is always false — are deleted
entirely (declaration, raise, reporter, supporting helpers). Defensive
unreachable variants whose raise sites exist but are unreachable from
the ReScript parser keep their named-variant form removed and the raise
site is replaced with assert false (* reason *), matching the
established convention in the typer modules (57 existing uses).
Truly dead — declaration + raise + reporter all removed:
ctype:Tags,Recursive_abbrev,Unification_recursive_abbrevexceptions (declared, never raised)typecore:Recursive_local_constraint(relay wrapper for the deadUnification_recursive_abbrev)typetexp:Variant_tags(relay wrapper for the deadTags)bs_syntaxerr:Conflict_bs_bs_this_bs_meth(no construction site)warnings:Comment_start,Comment_not_end,Method_override,Instance_variable_override,Illegal_backslash,Implicit_public_methods,Eol_in_string,Eliminated_optional_arguments,Bad_docstring,Bs_fragile_external,Bs_unimplemented_primitive(declared, never raised);Statement_type(caller hard-codesstatement=false),Unerasable_optional_argument(disabled around its only check),Bs_uninterpreted_delimiters(trigger AST rewritten by builtin PPX before the warning iterator runs)
Defensive unreachable — raise site becomes assert false (* reason *),
variant + reporter removed:
typecore:Invalid_for_of_pattern(parser'snormalize_for_of_patternreplaces non-var patterns withPpat_any, so the typer only ever seesPpat_var/Ppat_anyin for-of bindings)typetexp:Ill_typed_functor_application,Apply_structure_as_functor(both needLongident.Lapply, never constructed by the parser —compiler/syntax/src/only buildsLident/Ldot)typedecl:Val_in_structure(pval_prim = []/ a barevaloutside a signature is only produced by the parser's external-recovery, which emits a syntax error and aborts before the typer runs)bs_syntaxerr:Unhandled_poly_type(its only raise site is inast_core_type.list_of_arrow;Ptyp_polycannot appear in an external's arrow chain — external types never route throughparse_poly_type_expr, and anyPtyp_polyin a record/object field is an opaque arg leaf, never the recursed return type)
⚠️ Reachability re-audit correction. An earlier pass mislabelled several of these as unreachable on plausible-but-untested reasoning. A follow-up audit (empirical: eachassert falsewas driven to a real crash with a minimal.res) found 8 that are actually reachable or unproven, and they were restored as named variants (see the retained list below). 7 of the 8 now have a reproducing fixture confirming they are live; the last (typedecl.Type_clash) resisted ~37 attempts and has a structural argument for unreachability but no airtight proof, so it is retained rather than removed. The remaining entries above are backed by either a parser grammar fact or a structural proof, not just a guess.
Re-validation found a number of previously-flagged items that are not completely dead and have been retained as named variants:
typedecl.Rebind_wrong_type— live via extension rebinding across incompatible extension types.typecore.Label_mismatch— live when a record literal without an expected type mixes fields from two different record types (label_mismatch_record_literal.res).typecore.Abstract_wrong_label— live when a multi-arg function literal has a mislabelled inner argument (abstract_wrong_label.res).typemod.With_cannot_remove_constrained_type— live when destructive substitution is applied to a constrained type (with_cannot_remove_constrained_type.res).typetexp.Unbound_type_constructor_2— live when an identity type aliastype t<'a> = 'ais used in an inherit position with a type-variable argument:expand_headcollapsest<'b>to a bareTvarwhile the unexpanded repr is stillTconstr. Reachable from both poly-variant inherit (incomplete_type_constructor_polyvariant.res) and object spread (incomplete_type_constructor_object.res). The earlier "parser-rejected leading-'a" reasoning was wrong; both raise sites reproduce as a compiler crash if removed.typecore.Invalid_interval— live: the parser does constructPpat_interval(res_core.ml,<const> .. <const>). Only thePconst_charinterval is rewritten; any other constant interval (e.g.1 .. 5) reaches this branch (pattern_interval_non_char.res).typedecl.Null_arity_external— live: an external whose name starts with?(e.g.external x: int = "?nodeFs") skips the magicprim_native_nameencoding and reaches the typer with arity 0 (external_null_arity.res).typedecl.Varying_anonymous— live: a variance annotation on a GADT parameter whose return type constrains it (e.g.type rec t<+'a> = K(int): t<int>) triggers it — not_params (gadt_varying_anonymous.res).typedecl.Parameters_differ— live: non-uniform recursion through an object/record manifest (e.g.type rec t<'a> = {"f": t<int>}) is caught bycheck_regular, notCycle_in_def(recursive_type_parameters_differ.res).typedecl.Bad_fixed_type— live: a fully-bounded closed private polymorphic variant (e.g.type t = private [< #A | #B > #A #B]) satisfiesis_fixed_typebut has a static (non-Tvar) row (fixed_type_no_row_variable.res).env.Illegal_value_name— live: escaped-identifier syntax reachescheck_value_nameduring definition;let \"->" = 1is rejected with a clean diagnostic (illegal_value_name.res). The parser does not reject\"->".typecore.Too_many_arguments— removed: with structural n-ary arrows the expected type is committed to an arrow of the function literal's shape up front, so every path that used to reach this error now surfaces as a regular type clash orUncurried_arity_mismatch(too_many_arguments.resexercises the latter).typedecl.Type_clash— retained but appears dead: its only raise site (update_type) unifiest<fresh params>againstt's own manifest — a type against an alpha-renamed copy of itself — which cannot head-clash, and every genuine inconsistency is caught by a dedicated check (Cycle_in_def,Recursive_abbrev,Parameters_differ,Constraint_failed,Type_arity_mismatch). ~37 recursive / mutual / constraint / row / object / alias shapes were tried without reaching it. Kept as a named variant with an explanatory comment at the definition and raise site, pending an airtight proof, rather thanassert false.bs_syntaxerr.Misplaced_label_syntax— live when labelled args are passed via operator-identifier syntax like\"->"(x, ~b=...)(misplaced_label_syntax.res).typemod.Cannot_eliminate_dependency,typemod.Scoping_pack,typemod.With_makes_applicative_functor_ill_typed— reproduction attempts couldn't reach them but couldn't conclusively prove unreachability either; retained on the conservative side.includemod.Unbound_modtype_pathcan still represent a stale compiled-interface failure.Syntaxerr.Variable_in_scopeis live but lacks a registered printer.- The UTF-8 helper error families are still raised by test/defensive helper entry points.
The largest error type; covers expression / pattern type-checking.
Source: type error in typecore.ml.
| Variant | Status | Fixture | Notes |
|---|---|---|---|
Polymorphic_label |
✓ | polymorphic_label.res |
Pattern that instantiates a polymorphic record field: ({f: (f: int => int)}: t) => constrains the universal 'a of f: 'a. 'a => 'a to int => int. |
Constructor_arity_mismatch |
✓ | constructor_arity_mismatch.res, constructor_arity_mismatch_pattern.res, constructor_tuple_arity_mismatch.res, constructor_tuple_arity_mismatch_pattern.res, arity_mismatch*.res |
Triggers in both expression and pattern paths, after semantic argument normalization. |
Label_mismatch |
✓ | label_mismatch_record_literal.res |
Record literal without expected type mixing fields from two different record types — disambiguation picks one type per label, and the cross-type unify fails inside type_label_exp. |
Pattern_type_clash |
✓ | many *_pattern_type_clash.res etc. |
Most-fired pattern error. Sub-case fixtures: pattern_matching_on_option_but_value_not_option.res and pattern_matching_on_value_but_is_option.res (option-vs-non-option trace), pattern_type_clash_polyvariant.res (polyvariant tag against concrete type), pattern_type_clash_tuple_arity.res (tuple arity mismatch). |
Or_pattern_type_clash |
✓ | or_pattern_type_clash.res |
|
Multiply_bound_variable |
✓ | multiply_bound_variable.res |
|
Orpat_vars |
✓ | orpat_vars_unbalanced.res |
|
Expr_type_clash |
✓ | many *.res |
Most-fired expression error. Trace-shape sub-cases covered: if_return_type_mismatch.res (IfReturn), string_concat_non_string.res (StringConcat), labeled_fn_argument_type_clash.res (FunctionArgument with explicit label), math_operator_*.res (MathOperator family), ternary_branch_mismatch.res, switch_different_types.res, try_catch_same_type.res, comparison_operator.res, array_item_type_mismatch.res, array_literal_passed_to_tuple.res, if_condition_mismatch.res, while_condition.res, for_loop_condition.res, assert_condition.res, function_call_mismatch.res, awaiting_non_promise.res, maybe_unwrap_option.res, multiple jsx_* fixtures (including jsx_preserve_external_function.res for a plain-function external in a JSX component position), object_literal_for_poly_field.res (object literal against a polymorphic field annotation), dict_spread_type_mismatch.res (dict spread of an incompatible dict type, located at the spread expression). |
Apply_non_function |
✓ | apply_non_function.res |
|
Apply_wrong_label |
✓ | apply_wrong_label.res |
|
Label_multiply_defined |
✓ | label_multiply_defined_literal.res |
|
Dict_key_multiply_defined |
✓ | dict_pattern_duplicate_key.res |
|
Record_syntax_on_dict_type |
✓ | dict_record_literal.res, dict_record_pattern.res, dict_record_update.res |
|
Labels_missing |
✓ | missing_label.res, missing_labels.res |
|
Label_not_mutable |
✓ | label_not_mutable.res |
|
Wrong_name |
✓ | wrong_name_record_field.res, Cross_record_extra_field (multi) |
|
Name_type_mismatch |
✓ | super_errors_multi/Cross_qualified_constructor_mismatch |
Cross-module constructor disambiguation. |
Undefined_method |
✓ | super_errors_multi/Cross_module_alias_dot_access, undefined_method |
|
Object_field_not_mutable |
✓ | object_write_closed_row, object_write_alias, object_write_after_forgetting, object_private_row_write, object_private_row_write_through_signature |
Assignment to a field without @set. object_write_alias pins that promotion is per equivalence class, and object_write_after_forgetting pins that a coercion never grants write capability. The private-row fixtures pin that a Tconstr row terminator is structurally open but cannot be strengthened: writing through type t = private {.."x": int} (directly or via a signature) is rejected, matching unify_mutability. |
Private_type |
✓ | private_type_construction.res |
|
Private_label |
✓ | private_label.res |
|
Not_subtype |
✓ | subtype_*.res, coercion_arity_mismatch.res, dict_show_no_coercion.res, etc. |
|
Abstract_wrong_label |
✓ | abstract_wrong_label.res |
Multi-arg function literal where an inner argument label doesn't match the expected arrow's label (e.g. let f: (~a, ~b) => int = (~a, ~c) => …). |
Scoping_let_module |
✓ | scoping_let_module.res |
|
Not_a_variant_type |
✓ | variant_spread_pattern_not_a_variant.res |
Pattern-level variant spread of a non-variant type. |
Less_general |
✓ | less_general_universal.res, object_write_poly_field_less_general.res |
The latter pins that assigning to a polymorphic object field checks the value against the field's scheme. |
Modules_not_allowed |
✓ | super_errors_multi/Modules_not_allowed_toplevel |
Toplevel let module(M) = … pattern with allow_modules=false. |
Cannot_infer_signature |
✓ | cannot_infer_signature.res |
|
Not_a_packed_module |
✓ | not_a_packed_module.res |
|
Unexpected_existential |
✓ | super_errors_multi/Unexpected_existential_in_let |
Destructuring GADT constructor with existential in toplevel let. |
Unqualified_gadt_pattern |
✓ | super_errors_multi/Cross_gadt_pattern |
Only reachable via cross-module GADT disambiguation; in single-file matching the constructor would resolve before this check. |
Invalid_interval |
✓ | pattern_interval_non_char.res |
Non-char constant interval pattern (e.g. 1 .. 5); the parser builds Ppat_interval and only the Pconst_char interval is rewritten. |
Invalid_for_loop_index |
✓ | invalid_for_loop_index.res |
|
No_value_clauses |
✓ | no_value_clauses.res |
|
Exception_pattern_below_toplevel |
✓ | exception_pattern_below_toplevel.res |
|
Inlined_record_escape |
✓ | inline_record_escape.res |
|
Inlined_record_expected |
✓ | inlined_record_expected.res, super_errors_multi/Cross_inline_record_constructor |
|
Invalid_extension_constructor_payload |
✓ | invalid_extension_constructor_payload.res |
|
Not_an_extension_constructor |
✓ | not_an_extension_constructor.res |
|
Break_outside_loop |
✓ | break_outside_loop.res, break_in_nested_function.res |
|
Continue_outside_loop |
✓ | continue_outside_loop.res, continue_in_nested_function.res |
|
Literal_overflow |
✓ | intoverflow.res |
|
Polyvar_literal_overflow |
✓ | polyvar_int_overflow.res, polyvar_int_overflow_payload.res, polyvar_int_overflow_pattern.res |
|
Unknown_literal |
✓ | unknown_literal.res |
|
Invalid_string_escape_sequence |
☐ | — | Regular source is rejected by the parser; the typer check remains defensive for malformed AST produced by a PPX. syntaxErrors_invalid_ordinary_template_escape.res covers the parser diagnostic. |
Json_literal_outside_external |
✓ | json_literal_outside_external.res |
Constant json payloads are reserved for external attributes such as @as. |
Illegal_letrec_pat |
✓ | illegal_letrec_pat.res |
|
Empty_record_literal |
✓ | empty_record_literal.res |
|
Uncurried_arity_mismatch |
✓ | arity_mismatch3.res etc. |
|
Field_not_optional |
✓ | fieldNotOptional.res |
|
Record_rest |
✓ | record_rest_*.res |
Wrapper for record-rest validation errors reported by typecore_record_rest.ml; fixtures cover missing annotation, invalid rest type, non-record and unresolved rest types, private and unboxed record types, mutable source records, field mismatch/missing/extra cases, runtime-name mismatch, non-optional overlap errors, optional overlap warnings, module destructure rejection, and singular/plural missing messages. |
Type_params_not_supported |
✓ | variant_spread_pattern_type_params.res |
Pattern-level variant spread (` |
Field_access_on_dict_type |
✓ | field_access_on_dict_type.res |
|
Jsx_not_enabled |
☐ (needs harness flag) | — | typecore.ml, the Pexp_jsx_element cases of iter_expression and type_expect_. Fires when JSX is used without -bs-jsx N. The super_errors runner hard-codes -bs-jsx 4 in bscFlags; adding a per-fixture opt-out (e.g. a .opts sidecar) would expose this. Until then, it's reachable in real code but blocked at the harness level. |
Tagged_template_non_tag |
✓ | tagged_template_non_tag.res |
Backtick tagged-template syntax used on a value whose type is not taggedTemplate<'param, 'output>. |
Type-declaration errors. Source: type error in typedecl.ml.
| Variant | Status | Fixture | Notes |
|---|---|---|---|
Repeated_parameter |
✓ | repeated_type_parameter.res |
|
Duplicate_constructor |
✓ | duplicate_variant_constructor.res |
|
Duplicate_label |
✓ | duplicate_labels_error.res |
|
Object_spread_with_record_field |
✓ | object_spread_with_record_field.res |
|
Recursive_abbrev |
✓ | recursive_type_abbrev_cycle.res |
type rec t = t reports "The type abbreviation t is cyclic". |
Cycle_in_def |
? | — | No fixture reports "The definition of … contains a cycle"; recursive_type_abbrev_cycle.res reports Recursive_abbrev. |
Definition_mismatch |
✓ | definition_mismatch.res |
|
Constraint_failed |
✓ | constraint_failed.res |
|
Inconsistent_constraint |
✓ | inconsistent_constraint.res |
|
Type_clash |
⚠ | — | Appears dead; retained pending proof. update_type unifies t<fresh> against t's own manifest (an alpha-renamed copy of itself), which can't head-clash; real inconsistencies hit Cycle_in_def/Recursive_abbrev/Parameters_differ first. ~37 shapes tried without reaching it. |
Parameters_differ |
✓ | recursive_type_parameters_differ.res |
Non-uniform recursion through an object/record manifest (type rec t<'a> = {"f": t<int>}), caught by check_regular rather than Cycle_in_def. |
Null_arity_external |
✓ | external_null_arity.res |
External whose name starts with ? (e.g. external x: int = "?nodeFs") skips the magic prim_native_name encoding and reaches the typer with arity 0. |
Unbound_type_var |
✓ | unbound_type_var.res |
|
Cannot_extend_private_type |
✓ | cannot_extend_private_type.res |
|
Not_extensible_type |
✓ | not_extensible_type.res |
|
Extension_mismatch |
✓ | extension_arity_mismatch.res |
type t<'a> = .. extended with type t += A(int) — arity differs from the extensible type. |
Rebind_wrong_type |
✓ | extension_rebind_mismatch.res |
Rebinding constructor into a different extensible type fails while unifying the source constructor result with the extension target. |
Rebind_mismatch |
? | — | The later declaration-shape check after Rebind_wrong_type; no source fixture was confirmed in this pass. |
Rebind_private |
✓ | extension_rebind_private.res |
Rebinding a private extension constructor as public. |
Bad_variance |
✓ | bad_variance.res, bad_variance_contra.res, object_settable_field_covariant_param.res |
The latter pins that a settable object field is an invariant occurrence, like a mutable record label. |
Unavailable_type_constructor |
☐ (needs build harness) | — | typedecl.ml, check_constraints_rec and check_coherence. Requires a type path findable at parse time but missing during constraint enforcement; only cross-unit scenarios where a .cmi was found but later removed. |
Bad_fixed_type |
✓ | fixed_type_no_row_variable.res |
Fully-bounded closed private polymorphic variant (`type t = private [< #A |
Unbound_type_var_ext |
✓ | unbound_type_var_extension.res |
|
Varying_anonymous |
✓ | gadt_varying_anonymous.res |
Variance annotation on a GADT parameter whose return type constrains it (type rec t<+'a> = K(int): t<int>). |
Invalid_attribute |
✓ | invalid_attribute_not_undefined.res |
|
Bad_immediate_attribute |
✓ | bad_immediate_attribute.res |
|
Bad_unboxed_attribute |
✓ | bad_unboxed_attribute_abstract.res, bad_unboxed_attribute_mutable.res, bad_unboxed_attribute_many_fields.res, bad_unboxed_attribute_extensible.res |
All 4 sub-cases covered. |
Boxed_and_unboxed |
✓ | boxed_and_unboxed.res |
|
Nonrec_gadt |
✓ | nonrec_gadt.res |
|
Variant_runtime_representation_mismatch |
✓ | variant_coercion_*.res (many) |
|
Variant_spread_fail |
✓ | variant_spread_*.res (many), variant_spread_non_variant.res |
Module-level errors. Source: type error in typemod.ml.
| Variant | Status | Fixture | Notes |
|---|---|---|---|
Cannot_apply |
✓ | cannot_apply_non_functor.res |
|
Not_included |
✓ | All super_errors_multi/Iface_* fixtures wrap to this via compunit. |
|
Signature_expected |
✓ | typemod_signature_expected.res |
with type M.t = … where M is functor-typed inside the outer signature. |
Structure_expected |
✓ | super_errors_multi/Smoke_unbound_module_reference (indirect); also open_functor.res |
|
With_no_component |
✓ | with_no_component.res |
|
With_mismatch |
✓ | with_mismatch.res |
|
With_makes_applicative_functor_ill_typed |
? | — | typemod.ml, check_usage_of_path_of_substituted_item. Fires when a with constraint on a signature containing a Path.Papply makes that application ill-typed. Reachable via destructive substitution on applicative functors; reproduction attempts surfaced not a signature first. Retained on the conservative side. |
With_cannot_remove_constrained_type |
✓ | with_cannot_remove_constrained_type.res |
Destructive substitution on a constrained type, e.g. S with type t<'a> := 'a where S has type t<'a> constraint 'a = int. |
With_changes_module_alias |
☐ (needs build harness) | — | typemod.ml, check_usage_of_path_of_substituted_item. Fires during with module := M2 substitution when an aliased sub-module inside the constrained signature is affected. ReScript parses with module N := M2 (destructive substitution), but constructing a sub-module alias chain that gets invalidated requires multiple .resi files and a specific shape I couldn't reproduce single-file. |
Cannot_eliminate_dependency |
? | — | typemod.ml, the Pmod_apply case of type_module_aux. Fires when Mtype.nondep_supertype raises Not_found during functor-application result-type computation. Reproduction attempts routed through Incomplete_packed_module or escapes its scope. Retained on the conservative side. |
Scoping_pack |
? | — | typemod.ml, type_package. Fires during first-class module packing with with type constraints whose constrained type isn't a free Tvar. Reproduction attempts routed through Incomplete_packed_module. Retained on the conservative side. |
Repeated_name |
✓ | repeated_def_*.res (multiple) |
|
Non_generalizable |
✓ | non_generalizable.res |
|
Non_generalizable_module |
✓ | non_generalizable_module.res |
Nested module containing let r = ref(None) — the outer module's md_type carries the free '_weak1 from the inner ref, so closed_modtype returns false and the Sig_module branch fires. |
Interface_not_compiled |
✓ | super_errors_multi/Iface_not_compiled |
|
Not_allowed_in_functor_body |
✓ | not_allowed_in_functor_body.res |
|
Not_a_packed_module |
✓ | not_a_packed_module.res |
|
Incomplete_packed_module |
✓ | incomplete_packed_module.res |
|
Recursive_module_require_explicit_type |
✓ | recursive_module_require_explicit_type.res |
|
Apply_generative |
✓ | apply_generative.res |
|
Cannot_scrape_alias |
☐ (needs build harness) | — | typemod.ml, extract_sig, extract_sig_open and the Pmod_apply case of type_module_aux. Requires Env.scrape_alias to return Mty_alias for an alias whose target .cmi couldn't be loaded. The super_errors_multi runner pre-compiles every file in the fixture, so the alias target is always present. |
Type-expression errors. Source: type error in typetexp.ml.
| Variant | Status | Fixture | Notes |
|---|---|---|---|
Unbound_type_variable |
✓ | (covered indirectly via many fixtures) | |
Unbound_type_constructor |
✓ | typetexp_unbound_type_constructor.res |
|
Unbound_type_constructor_2 |
✓ | incomplete_type_constructor_polyvariant.res, incomplete_type_constructor_object.res |
Identity alias type t<'a> = 'a used in an inherit position with a type-variable arg; expand_head collapses t<'b> to a bare Tvar while the repr stays Tconstr. Reachable from poly-variant inherit and object spread. |
Type_arity_mismatch |
✓ | type_arity_mismatch.res, record_rest_type_arity_mismatch.res |
|
Type_mismatch |
✓ | typetexp_type_mismatch.res |
Type-constructor application that violates a constraint 'a = … on the declaration. |
Alias_type_mismatch |
✓ | typetexp_alias_type_mismatch.res |
|
Present_has_conjunction |
✓ | polyvariant_present_has_conjunction.res |
[< #A(int) & (string) > #A] — < syntax marks #A as a "present" tag, and the body has both (int) and & (string) types, so the conjunctive payload triggers the check in the Ptyp_variant case of transl_type_aux. |
Present_has_no_type |
✓ | polyvariant_present_has_no_type.res |
[< #B > #A] — #A is listed as a "present" tag but isn't defined in the polyvariant body. |
Constructor_mismatch |
✓ | polyvariant_constructor_mismatch.res |
|
Not_a_variant |
✓ | typetexp_not_a_variant.res |
Polyvariant [#X | a] where a is not a polyvariant. |
Invalid_variable_name |
✓ | invalid_type_variable_name.res |
|
Cannot_quantify |
✓ | cannot_quantify.res |
type t = {f: 'a. (int as 'a) => int} — 'a is universally quantified but the alias int as 'a rebinds it to int, so the proxy is no longer a fresh Tvar when the quantification check runs. |
Multiple_constraints_on_type |
✓ | multiple_constraints_on_type.res |
|
Method_mismatch |
✓ | object_method_mismatch.res |
|
Unbound_value |
✓ | typetexp_unbound_value.res |
|
Unbound_constructor |
✓ | typetexp_unbound_constructor.res |
|
Unbound_label |
✓ | typetexp_unbound_label.res |
|
Unbound_module |
✓ | suggest_module_for_missing_identifier.res, super_errors_multi/Smoke_unbound_module_reference |
|
Unbound_modtype |
✓ | typetexp_unbound_modtype.res |
|
Illegal_reference_to_recursive_module |
✓ | illegal_recursive_module_reference.res |
module rec A: B.S = … references another recmodule's module-type before signatures are sealed. During approx_modtype of A, Env.lookup_module B returns the #recmod# placeholder and raises Env.Recmodule. |
Access_functor_as_structure |
✓ | access_functor_as_structure.res |
|
Cannot_scrape_alias |
☐ (needs build harness) | — | typetexp.ml, the Ldot case of narrow_unbound_lid_error. The trigger needs Env.scrape_alias to return Mty_alias — an alias whose target .cmi couldn't be loaded. The super_errors_multi harness pre-compiles every alias target. |
Opened_object |
✓ | object_inherit_opened.res |
|
Not_an_object |
✓ | object_inherit_not_an_object.res |
Wrapper symptoms attached to inclusion failures. Source: type symptom in includemod.ml.
| Variant | Status | Fixture | Notes |
|---|---|---|---|
Missing_field |
✓ | super_errors_multi/Iface_missing_value |
|
Value_descriptions |
✓ | super_errors_multi/Iface_value_descriptions, super_errors_multi/Iface_value_arity_mismatch, super_errors_multi/Smoke_interface_mismatch, super_errors_multi/Cross_external_spec_mismatch, super_errors_multi/Cross_external_payload_name, super_errors_multi/Cross_external_import_attrs, module_sig_value_arity_mismatch*.res, object_value_signature_set_mismatch.res, inline_bigint_signature_mismatch.res |
Arity mismatches print a dedicated hint (implementation vs interface argument counts), including through aliases and nested function types. The object fixture pins that a value signature cannot drop @set from an object type (moregeneral requires equal field mutability). The inline-bigint fixture pins the sign printed for @inline(<bigint>) values. |
Type_declarations |
✓ | super_errors_multi/Iface_type_decl_record, super_errors_multi/Iface_type_decl_variant, RecordInclusion.res, type_decl_function_arity_mismatch.res |
|
Extension_constructors |
✓ | super_errors_multi/Iface_extension_constructors |
|
Module_types |
✓ | super_errors_multi/Iface_module_types |
|
Modtype_infos |
✓ | super_errors_multi/Iface_modtype_infos |
|
Modtype_permutation |
✓ | include_modtype_permutation.res |
|
Interface_mismatch |
✓ | wrapper added to all Iface_* failures by compunit. |
|
Unbound_modtype_path |
☐ (needs stale-cmi harness) | — | includemod.ml, expand_module_path. Re-validated during removal: not completely dead. It represents Env.find_modtype failing during module-type path comparison, which can happen only with a stale or inconsistent compiled interface. The source-only harness cannot produce that state because it pre-compiles every fixture, so this needs a build/binary-state harness rather than deletion. |
Unbound_module_path |
☐ (needs build harness) | — | includemod.ml, expand_module_alias and try_modtypes. Alias comparison where Env.normalize_path raises Not_found. Requires a module alias whose target .cmi is absent at inclusion time — multi-unit only. |
Invalid_module_alias |
☐ (needs build harness) | — | includemod.ml, try_modtypes. Requires both sides Mty_alias with one pointing to a functor argument. Reachable only when the alias chain crosses a functor application that the super_errors_multi harness doesn't construct. |
Sub-symptoms produced during signature inclusion (rendered inside Type_declarations).
Source: type type_mismatch in includecore.ml.
| Variant | Status | Fixture | Notes |
|---|---|---|---|
Arity |
✓ | definition_mismatch.res |
|
Privacy |
✓ | super_errors_multi/Iface_privacy_mismatch |
|
Kind |
✓ | super_errors_multi/Iface_kind_mismatch |
Record-in-impl vs variant-in-interface. |
Constraint |
✓ | super_errors_multi/Iface_constraint_mismatch |
Implementation adds a constraint 'a = …; interface has none. |
Manifest |
✓ | super_errors_multi/Iface_manifest_mismatch, type_decl_function_arity_mismatch.res, object_private_row_grants_set.res, object_manifest_set_mismatch.res |
Manifest types differ, including function types with different arities. The object fixtures pin the @set inclusion matrix: a private row's signature cannot grant @set its implementation lacks (but may forget it — pinned compiling in object_mutability_pin.res), while a transparent manifest is an equation and cannot forget it either. |
Variance |
✓ | super_errors_multi/Iface_variance_mismatch |
Interface annotates +'a; implementation's inferred variance differs. |
Field_type |
✓ | super_errors_multi/Iface_type_decl_record |
|
Field_mutable |
✓ | super_errors_multi/Iface_field_mutable_mismatch |
|
Field_optional |
✓ | super_errors_multi/Iface_field_optional_mismatch |
|
Field_arity |
✓ | super_errors_multi/Iface_field_arity_mismatch |
Constructor with different argument count between .resi / .res. |
Field_names |
✓ | super_errors_multi/Iface_field_names_mismatch |
Record field names differ at the same position. |
Field_missing |
✓ | super_errors_multi/Iface_missing_value (indirect) |
|
Record_representation |
✓ | super_errors_multi/Iface_record_representation_mismatch |
Interface declares @unboxed; implementation is boxed. |
Unboxed_representation |
✓ | super_errors_multi/Iface_unboxed_variant_mismatch |
|
Immediate |
✓ | super_errors_multi/Iface_immediate_mismatch |
Interface adds @immediate; implementation manifests a non-immediate (string). |
Tag_name |
✓ | super_errors_multi/Iface_tag_name_mismatch |
|
Variant_representation |
✓ | super_errors_multi/Iface_variant_representation_mismatch |
FFI / attribute / experimental-feature errors. Source: type error in bs_syntaxerr.ml.
| Variant | Status | Fixture | Notes |
|---|---|---|---|
Duplicated_bs_deriving |
✓ | duplicated_bs_deriving.res |
|
Conflict_attributes |
✓ | bs_conflict_attributes.res |
|
Expect_int_literal |
✓ | bs_expect_int_literal.res |
|
Expect_string_literal |
✓ | bs_expect_string_literal.res |
|
Expect_int_or_string_or_json_literal |
✓ | bs_expect_int_or_string_or_json_literal.res |
@as(true) on a wildcard external argument. |
Invalid_underscore_type_in_external |
✓ | bs_invalid_underscore_type_in_external.res |
@obj external make: (~x: _) => _ = "" — _ at an optional-label position without @as. |
Invalid_bs_string_type |
✓ | bs_invalid_bs_string_type.res |
|
Invalid_bs_int_type |
✓ | bs_invalid_bs_int_type.res |
|
Invalid_bs_unwrap_type |
✓ | bs_invalid_bs_unwrap_type.res |
|
Conflict_ffi_attribute |
✓ | conflicting_ffi_attributes.res |
|
Illegal_attribute |
✓ | bs_illegal_attribute_scope.res |
|
Not_supported_directive_in_bs_return |
✓ | bs_not_supported_directive_in_bs_return.res |
|
Expect_opt_in_bs_return_to_opt |
✓ | bs_expect_opt_in_bs_return_to_opt.res |
|
Optional_in_uncurried_bs_attribute |
✓ | bs_optional_in_uncurried_bs_attribute.res |
@this function with optional argument. |
Bs_this_simple_pattern |
✓ | bs_this_simple_pattern.res |
@this with destructured self pattern. |
Experimental_feature_not_enabled |
✓ | let_unwrap_on_top_level_not_enabled.res (and other let-unwrap variants) |
Currently only LetUnwrap is checked. |
LetUnwrap_not_supported_in_position |
✓ | let_unwrap_on_top_level.res, let_unwrap_on_not_supported_variant.res |
|
Misplaced_label_syntax |
✓ | misplaced_label_syntax.res |
Labelled args passed via the operator-identifier syntax (->), (#=), (##), e.g. \"->"(x, ~b=...). |
Untagged-variant validation errors. Source: type untagged_error and type error in ast_untagged_variants.ml.
| Variant | Status | Fixture | Notes |
|---|---|---|---|
OnlyOneUnknown |
✓ | UntaggedOnlyOneUnknown.res |
Abstract payload alongside another payload-carrying case. |
AtMostOneObject |
✓ | UntaggedAtMostOneObject.res |
Two record payloads in the same untagged variant. |
AtMostOneInstance |
✓ | UntaggedAtMostOneInstance.res |
Two cases with the same JS instance type (Date.t in both). |
AtMostOneFunction |
✓ | UntaggedAtMostOneFunction.res |
Two function-typed payloads. |
AtMostOneString |
✓ | UntaggedNonUnary*.res (some sub-cases) |
|
AtMostOneNumber |
✓ | UntaggedAtMostOneNumber.res |
int and float payloads collide on the number runtime check. |
AtMostOneBigint |
✓ | UntaggedAtMostOneBigint.res |
Two bigint payloads. |
AtMostOneBoolean |
✓ | UntaggedAtMostOneBoolean.res |
Two boolean payloads. |
UnreachableBoolean |
✓ | UntaggedUnreachableBoolean.res |
Boolean payload alongside both @as(true) and @as(false) cases. |
DuplicateLiteral |
✓ | UntaggedDuplicateLiteral.res |
@as("x") on two different constructors. |
ConstructorMoreThanOneArg |
✓ | UntaggedConstructorMoreThanOneArg.res, UntaggedConstructorAttributeMoreThanOneArg.res |
Multiple payload arguments with type-level or constructor-level @unboxed. |
| Variant | Status | Fixture | Notes |
|---|---|---|---|
InvalidVariantAsAnnotation |
✓ | UntaggedInvalidVariantAsAnnotation.res |
@as(foo) with a non-null / non-undefined identifier payload. |
VariantAsIntegerOutOfRange |
✓ | VariantAsIntegerOutOfRange.res |
Integer literal in a constructor @as annotation exceeds the compiler's integer range. |
Duplicated_bs_as |
✓ | UntaggedDuplicatedBsAs.res |
Two @as("...") attributes on the same constructor. |
InvalidVariantTagAnnotation |
✓ | UntaggedInvalidVariantTagAnnotation.res |
@tag(123) (non-string payload). |
InvalidUntaggedVariantDefinition |
✓ | UntaggedUnknown.res, UntaggedNonUnary*.res, UntaggedTupleAndArray.res, UntaggedImplIntf.res, etc. |
|
TagFieldNameConflict |
✓ | UntaggedTagFieldNameConflict.res |
@tag("kind") plus inline record field named kind on a constructor. |
Build / dependency errors. Mostly need the rescript build runtime to fire — not reachable from raw bsc. Source: type error in bs_exception.ml.
| Variant | Status | Fixture | Notes |
|---|---|---|---|
Cmj_not_found |
☐ (needs build harness) | — | Missing .cmj from a dependent module. Reachable from rescript build but not from raw bsc. |
Js_not_found |
✓ | implicitly — bypassed via -bs-cmi-only in super_errors_multi runner. Not a fixture, but the harness commit documents the workaround. |
|
Bs_duplicate_exports |
☐ (needs build harness) | — | Same export emitted twice across compilation units. |
Missing_ml_dependency |
☐ (needs build harness) | — | Compile-time missing dependency from a .cmj lookup table. |
Dependency_script_module_dependent_not |
☐ (needs build harness) | — | string_of_module_id in core/platform/native/js_name_of_module_id.ml. Reachable when a dependent module is in script mode (Package_script) but the current module is in package mode (Package_found _). Legacy script-vs-package interaction; needs rescript.json harness. |
Environment / .cmi-consistency errors. Source: type error in env.ml.
| Variant | Status | Fixture | Notes |
|---|---|---|---|
Illegal_renaming |
☐ (needs build harness) | — | Triggered when a .cmi filename and the module name inside it disagree. Reachable via rescript.json setups that rename the produced artefact, but not from a single-process bsc invocation that always writes Module.cmi to match the source. |
Inconsistent_import |
☐ (needs build harness) | — | Triggered when two .cmi files transitively imported by the same unit declare different CRCs for the same type. Needs an artificially-mutated build state across multiple compile invocations. |
Missing_module |
☐ (needs build harness) | — | .cmi referenced but absent from -I paths at compile time. The super_errors_multi runner pre-compiles every fixture file via -bs-read-cmi, so it never reaches this code path. |
Illegal_value_name |
✓ | illegal_value_name.res |
Escaped identifier reaching check_value_name during definition (let \"->" = 1); the parser does not reject \"->". |
.cmi file format errors. Need binary-level manipulation to trigger
(write a non-.cmi file in place of one and reference it; downgrade
compiler version; truncate the file). Out of scope for the
super_errors{,_multi} harnesses, which only invoke bsc on
hand-written .res / .resi sources.
| Variant | Status | Fixture | Notes |
|---|---|---|---|
Not_an_interface |
☐ (needs binary harness) | — | Pass an arbitrary file as .cmi. |
Wrong_version_interface |
☐ (needs binary harness) | — | Mismatched compiler versions writing/reading. |
Corrupted_interface |
☐ (needs binary harness) | — | Truncated or corrupted .cmi. |
PPX-runtime errors. Source: type error in cmd_ast_exception.ml.
Both require running bsc with -ppx <executable> and exercising the
external process boundary. Not reachable from the single-file or
multi-file harnesses, which never set -ppx.
| Variant | Status | Fixture | Notes |
|---|---|---|---|
CannotRun |
☐ (needs PPX harness) | — | PPX binary fails to execute (missing or non-executable). |
WrongMagic |
☐ (needs PPX harness) | — | PPX returns wrong AST magic number (e.g. PPX built against a different compiler ABI). |
| Module | Variant | Status | Fixture | Notes |
|---|---|---|---|---|
compiler/ml/translcore.ml |
Unknown_builtin_primitive |
✓ | unknown_builtin_primitive.res |
|
compiler/ml/translmod.ml |
Fragile_pattern_in_toplevel |
✓ | fragile_pattern_toplevel.res |
|
compiler/ml/transl_recmodule.ml |
Circular_dependency |
✓ | recmodule_circular_dependency.res |
|
compiler/ml/rec_check.ml |
Illegal_letrec_expr |
✓ | illegal_letrec_expr.res |
|
compiler/ml/syntaxerr.ml |
Variable_in_scope |
? (live, broken printer) | — | Reachable via let f: type t. (t, 't) => t = … (locally-abstract t collides with type variable 't during varify_constructors), but Syntaxerr.error has no registered pretty-printer, so it propagates as an uncaught Fatal error: exception Syntaxerr.Error(_). Not removed because the variant is live; the fix should wire up a printer or convert the check into a regular typed diagnostic. |
compiler/ml/cmt_format_common.ml |
Not_a_typedtree |
☐ (needs binary harness) | — | cmt_format_common.ml, read_cmt. Fires when a tool reads a .cmt file whose first block isn't a typed tree. Reachable in principle by pointing the analyzer at an arbitrary file with a .cmt extension; out of scope for the source-only fixture harnesses. |
compiler/ext/bsc_args.ml |
Unknown |
☐ (needs CLI harness) | — | bsc_args.ml, type error. Reachable trivially via bsc --bogus, but the super_errors{,_multi} runners only pass bsc a fixed flag list plus the source file — they can't exercise CLI-level errors. |
compiler/ext/bsc_args.ml |
Missing |
☐ (needs CLI harness) | — | Same as above: bsc -o (no following filename). Needs a harness that invokes bsc with crafted argv. |
All variants that were confirmed completely dead in this pass are listed
in Removed in jono/remove-dead-errors above and no longer appear in
the module tables. Previously flagged entries that were only unreachable
from regular source, but still possible through stale build artifacts,
PPX/malformed ASTs, or test helper APIs, were retained and reclassified.
Warnings are declared in compiler/ext/warnings.ml.
The default warning set is +a-4-9-20-41-102
(compiler/ext/bsc_warnings.ml), so
warnings 4, 9, 20, 41, and 102 are disabled by default; the rest are
enabled. Fixtures use -w +A (everything on) so default-disabled
warnings still fire.
Fixtures follow the naming convention warning_<NN>_<description>.res
so coverage gaps stay greppable. Warning 11 (Unused_match) is covered by
warning_11_equivalent_string_patterns.res.
The warning constructors listed in Removed in jono/remove-dead-errors
were deleted. Their numeric warning slots remain holes; no warning number
was reused.
Warning 24 (Bad_module_name) was removed later for the same reason: it
had no raise site. Its slot is likewise left unused.
These warnings have prerr_warning raise sites in compiler/ and are
reachable from regular ReScript code, but no super_errors fixture
currently exercises them.
| Number | Variant | Trigger |
|---|---|---|
| 5 | Partial_application |
typecore.ml, check_application_result and the ignore special case of type_application. The type_application branch needs not total_app, which would require ignore(arg, ...) partial application — syntactically non-sensical. The check_application_result site fires via a delayed check whose only path is hard to trigger from plain source. Status: live raise sites but I couldn't construct a reproduction; may be effectively dead. |