Skip to content

super_errors: expand warning + error fixture coverage#8429

Open
JonoPrest wants to merge 9 commits into
rescript-lang:masterfrom
JonoPrest:jono/expand-coverage
Open

super_errors: expand warning + error fixture coverage#8429
JonoPrest wants to merge 9 commits into
rescript-lang:masterfrom
JonoPrest:jono/expand-coverage

Conversation

@JonoPrest
Copy link
Copy Markdown
Contributor

Summary

Adds 50 fixtures to tests/build_tests/super_errors/ covering compiler warnings (29) and errors (21). Drives the existing snapshot framework — shells out to bsc, diffs stderr — so tests are implementation-independent.

Coverage moved from 49.79% → 50.83%, with bigger wins on the warning/error modules:

Module Before After
warnings.ml 46.75% 62.34%
includemod.ml 45.61% 53.54%
typetexp.ml 53.74% 60.32%
typedecl.ml 54.92% 59.31%
typemod.ml 35.91% 39.62%
typecore.ml 71.58% 73.83%

Scope

  • Warnings: every reachable variant in warnings.ml now has a fixture, with one fixture per printed message branch (e.g. warning 37 has 3 — basic/pattern-only/private — matching the three arms in Warnings.message).
  • Errors: strategic sweep, not exhaustive. Targets high-value variants (duplicate label, illegal letrec, type arity mismatch, functor mismatch, conflicting FFI attrs, etc.). Many error variants remain — follow-up work.

Warning fixtures use warning_NN_<description>.res so coverage gaps stay greppable.

Dead-warning findings (no fixtures added, documented in commits)

  • Disabled globally: 16 (Unerasable_optional_argument — disabled in type_function for uncurried).
  • No prerr_warning call site: 1, 2, 14, 29, 48, 50, 105, 106, 108.
  • Class-related (no OCaml classes in ReScript): 7, 13, 15.
  • Superseded by enriched type errors: 5, 10.

JonoPrest added 9 commits May 18, 2026 13:07
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.
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.
…cl / 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.
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.
…evious 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.
  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)
  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)
  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)
@JonoPrest JonoPrest requested review from cknitt and jfrolich May 18, 2026 13:44
@JonoPrest
Copy link
Copy Markdown
Contributor Author

@codex review

@zth
Copy link
Copy Markdown
Member

zth commented May 18, 2026

Great stuff @JonoPrest!

@chatgpt-codex-connector
Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 🎉

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented May 18, 2026

Open in StackBlitz

rescript

npm i https://pkg.pr.new/rescript@8429

@rescript/darwin-arm64

npm i https://pkg.pr.new/@rescript/darwin-arm64@8429

@rescript/darwin-x64

npm i https://pkg.pr.new/@rescript/darwin-x64@8429

@rescript/linux-arm64

npm i https://pkg.pr.new/@rescript/linux-arm64@8429

@rescript/linux-x64

npm i https://pkg.pr.new/@rescript/linux-x64@8429

@rescript/runtime

npm i https://pkg.pr.new/@rescript/runtime@8429

@rescript/win32-x64

npm i https://pkg.pr.new/@rescript/win32-x64@8429

commit: 7755ed0

@codecov
Copy link
Copy Markdown

codecov Bot commented May 18, 2026

Welcome to Codecov 🎉

Once you merge this PR into your default branch, you're all set! Codecov will compare coverage reports and display results in all future pull requests.

Thanks for integrating Codecov - We've got you covered ☂️

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants