super_errors: expand warning + error fixture coverage (#8429)
* super_errors: add fixtures for unused-* warnings
Adds one-fixture-per-printed-branch snapshots for warnings that
previously had zero coverage:
warning 12 - redundant sub-pattern
warning 33 - unused open
warning 34 - unused type declaration
warning 35 - unused for-loop index
warning 37 - unused constructor (all 3 message branches)
warning 38 - unused extension constructor / exception (2 branches each)
warning 39 - unused rec flag
warning 60 - unused module
warning 101 - unused @bs.* attribute
Each fixture uses a private module signature to ensure the warning
fires consistently regardless of whether the file has consumers.
Naming convention: warning_NN_<short_description>.res so coverage
gaps stay easy to grep for.
* super_errors: add fixture for warning 43 (non-optional label)
Adds coverage for Nonoptional_label, the warning that fires when a
caller uses `~x=?` syntax against a non-optional labeled argument.
Inventory finding: warnings 16 (Unerasable_optional_argument) and 48
(Eliminated_optional_arguments) are effectively dead in current ReScript.
- 16 is raised inside type_function (typecore.ml:3525) but is
explicitly disabled at the start of the same function
(typecore.ml:3479) with the comment "Disable
Unerasable_optional_argument for uncurried functions". Since
ReScript is fully uncurried, the warning never fires.
- 48 has the variant declared in warnings.ml but no
`prerr_warning Eliminated_optional_arguments` call exists
anywhere in the codebase, so it can never be raised.
No fixtures written for 16 or 48.
* super_errors: add fixtures for attribute / pattern / shadow / type-decl / bs_* warnings
Adds one-fixture-per-printed-branch coverage for previously untested
warnings, plus extra branches for warnings whose printed text varies
with payload shape:
warning 23 - useless record `with` spread (all fields overridden)
warning 28 - wildcard pattern on a constant constructor
warning 30 - duplicate constructor in mutually-recursive type defs
warning 41 - ambiguous field labels across multiple record types
warning 44 - open shadows an existing value identifier
warning 45 - open shadows a constructor (also fires 44 because
the parent type is shadowed at the same time; both
are captured)
warning 47 - illegal payload on @inline attribute
warning 52 - fragile literal pattern (matching on Invalid_argument
payload string)
warning 53 - misplaced @inline on a non-constant let binding
(the constant case is consumed by bs_builtin_ppx
inline-const transform before it reaches translcore)
warning 54 - duplicated @inline attribute
warning 57 - ambiguous or-pattern variables under guard, both
single-var and multi-var printed branches
warning 103 - @string redundant on a payload-less polymorphic
variant in an external
warning 104 - @deriving applied to a non-applicable type
(`accessors` requires a record type)
Inventory notes (no fixtures added):
- warnings 5 (Partial_application) and 10 (Statement_type): these
are now handled as enriched type errors via the `Statement
FunctionCall` type-clash context in error_message_utils.ml,
rather than as warnings. The `prerr_warning` call sites in
typecore.ml still exist but the user-visible behaviour is a
type error, not a warning.
- warnings 14 (Illegal_backslash), 29 (Eol_in_string),
105 (Bs_fragile_external), 106 (Bs_unimplemented_primitive),
108 (Bs_uninterpreted_delimiters), 50 (Bad_docstring):
no `prerr_warning` calls for these anywhere in the compiler.
Variant exists in warnings.ml but is unreachable.
- warning 109 None branch (no help text) is raised only when
polymorphic-variant tag unification fails (typecore.ml:4524).
Hard to trigger from user code; the two reachable branches
(Some FunctionCall, Some Other) are already covered by
existing top_level_*_not_unit fixtures.
- warning 8 empty-hint branch ("") is a `try ... with _ -> ""`
defensive fallback in parmatch.ml when example-pattern
printing raises. Not reachable from normal user code.
* super_errors: add fixture for warning 62 (Constraint_on_gadt)
Constraint clause on a GADT (variant where at least one constructor
has a result type ascription). ReScript GADT syntax requires `type
rec` and `t<'a>` parametric notation; the OCaml `type _ t` form
isn't accepted by the ReScript parser.
The fixture also triggers a follow-up type error because the
constraint `'a = int` makes `t<bool>` unsatisfiable — captured in
the snapshot as part of documenting the full diagnostic flow.
* super_errors: add fixtures for high-value typecore errors + format previous batch
New error fixtures:
multiply_bound_variable.res - `let (x, x) = ...` (pattern
binds same name twice)
label_multiply_defined_literal.res - `{a: 1, a: 2}` record literal
with duplicate label
illegal_letrec_pat.res - `let rec (x, y) = ...`
(let rec LHS must be a variable)
exception_pattern_below_toplevel.res - `Some(exception Not_found)`
(exception patterns must be at
the top of a switch case)
or_pattern_type_clash.res - `| 1 | "hello" => ...` on an
`int`-typed scrutinee
orpat_vars_unbalanced.res - `| Some(n) | None => ...`
(variable bound on only one
side of an or-pattern)
Also reformats the previous warning batch via `make format`:
- `when` → `if` for switch guards (modern ReScript syntax)
- layout fixes for warning_53/57/62 to match the formatter
- snapshots regenerated against the formatted fixtures
Inventory finding: char/int interval patterns (`'5' .. '0'`) parse
silently in current ReScript — Invalid_interval (typecore Error
variant) appears to be unreachable from the surface syntax. Skipped.
* super_errors: add fixtures for typedecl + typemod errors
repeated_type_parameter.res - `type t<'a, 'a>` (param name
used twice in the param list)
duplicate_variant_constructor.res - `type t = Foo | Foo`
type_abbrev_missing_rec.res - `type t = t` without `rec`,
which surfaces as Unbound_type
with a "did you mean type rec?"
hint rather than as a cycle
recursive_type_abbrev_cycle.res - `type rec t = t` (true cyclic
abbrev, no indirection)
unbound_type_var.res - `type t = ('a, int)` (uses 'a
without declaring it)
record_literal_missing_fields.res - `let r: t = {}` where `t` has
a required field (this fires
Labels_missing, not the
Empty_record_literal variant
which appears to be unreachable
for record-typed scrutinees)
duplicate_module_in_scope.res - two `module M = {…}` declarations
in the same structure (typemod
Repeated_name)
* super_errors: add fixtures for typetexp / module / function call errors
type_arity_mismatch.res - `array<int, string>`
(wrong number of type args)
typetexp_unbound_type_constructor.res - `let x: nonexistent_type = 1`
(typetexp variant; surfaces
with the same "did you mean
type rec?" hint as the
typedecl variant)
apply_wrong_label.res - calling a labeled-arg
function with the wrong
label name
too_many_arguments.res - passing 3 unlabelled args
to a 2-arg function
invalid_type_variable_name.res - `'_invalid` (type variable
starting with underscore
is not allowed)
functor_apply_arg_mismatch.res - applying a functor with a
module that doesn't satisfy
the parameter signature
(exercises includemod's
Module_type_mismatch path)
* super_errors: add fixtures for bs_syntaxerr (FFI / deriving)
duplicated_bs_deriving.res - two `@deriving(...)` attributes
on the same type declaration
conflicting_ffi_attributes.res - `@val @send` on the same external
(these FFI annotations are
mutually exclusive)
* Update changelog J
Jono Prest committed
04cbb91e563ca62bdb7396029606d3588dbb2b36
Parent: 892d3aa
Committed by GitHub <noreply@github.com>
on 5/19/2026, 3:01:27 PM