Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
aed04a9
tests: add compiler error variant catalog
JonoPrest May 20, 2026
0378983
super_errors: add fixtures for typecore ☐ variants
JonoPrest May 21, 2026
4d24326
super_errors: add fixtures for typedecl rebind variants
JonoPrest May 21, 2026
97cd98c
super_errors: add fixtures for bs_syntaxerr ☐ variants
JonoPrest May 21, 2026
b765dc0
ERROR_VARIANTS: sync with new fixtures and document dead warnings
JonoPrest May 21, 2026
a39366c
super_errors_multi: add fixtures for includecore type_mismatch variants
JonoPrest May 21, 2026
baa6e08
super_errors: add typetexp Type_mismatch and Not_a_variant fixtures
JonoPrest May 21, 2026
baa1bed
super_errors: add fixtures for untagged_variants + typemod Signature_…
JonoPrest May 21, 2026
f8a3454
super_errors: cover bs_syntaxerr Invalid_underscore_type_in_external
JonoPrest May 21, 2026
a5ddb00
super_errors: cover typedecl Extension_mismatch
JonoPrest May 21, 2026
abb7840
ERROR_VARIANTS: document harness-bound and PPX-only variants
JonoPrest May 21, 2026
788e8a3
ERROR_VARIANTS: classify remaining ☐ rows by required harness or status
JonoPrest May 21, 2026
8c35656
super_errors: cover three Expr_type_clash sub-cases
JonoPrest May 21, 2026
61e9383
super_errors: resolve every ? variant — fixtures or formal dead reason
JonoPrest May 21, 2026
ea961d2
super_errors: re-snapshot fixtures after make format
JonoPrest May 21, 2026
f05efbe
super_errors: add high-value sub-case fixtures from coverage audit
JonoPrest May 21, 2026
06e5eaf
Update changelog for #8446
JonoPrest May 26, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 19 additions & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,25 @@ tests/
2. **Integration tests** (`tests/tests/`) - End-to-end behavior
3. **Unit tests** (`tests/ounit_tests/`) - Compiler functions
4. **Build tests** (`tests/build_tests/`) - Error cases and edge cases
5. **Type tests** (`tests/build_tests/super_errors/`) - Type checking behavior
5. **Type tests** (`tests/build_tests/super_errors/`) - Single-file type checking errors
6. **Multi-file error tests** (`tests/build_tests/super_errors_multi/`) - Cross-module errors that need separate `.res` / `.resi` files

#### Error variant catalog

[`tests/ERROR_VARIANTS.md`](tests/ERROR_VARIANTS.md) is a per-module
catalog of every error and warning variant the compiler can emit, with
each entry mapped to a fixture (or a documented reason it's unreachable).

**When adding or removing an error variant**, also update the catalog:

1. Add (or remove) the row in the relevant module section.
2. Set the status (`✓` covered / `⚠` unreachable / `☐` TODO).
3. If covered, link the fixture path; if unreachable, note the reason.

**When adding or removing a fixture**, update the corresponding row's
`Fixture` and status columns so the catalog stays in sync with the test
suite. The catalog is the primary tool for finding coverage gaps and
dead-code removal candidates; stale entries make both jobs harder.

## Build Commands & Development

Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
- Expand `super_errors` fixture coverage for the remaining reachable single-file error variants. https://github.com/rescript-lang/rescript/pull/8432
- Cache OPAM env, rewatch build, and instrumented dune state in the coverage workflow. https://github.com/rescript-lang/rescript/pull/8434
- Add a multi-file fixture harness (`super_errors_multi`) for cross-module errors and warnings. https://github.com/rescript-lang/rescript/pull/8433
- Catalog every named compiler error variant in `tests/ERROR_VARIANTS.md` and add fixtures for the remaining reachable ones. https://github.com/rescript-lang/rescript/pull/8446


# 13.0.0-alpha.4
Expand Down
605 changes: 605 additions & 0 deletions tests/ERROR_VARIANTS.md

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@

We've found a bug for you!
/.../fixtures/UntaggedAtMostOneBigint.res:2:20-30

1 │ @unboxed
2 │ type t = A(bigint) | B(bigint)
3 │

This untagged variant definition is invalid: At most one case can be a bigint type.
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@

We've found a bug for you!
/.../fixtures/UntaggedAtMostOneBoolean.res:2:18-26

1 │ @unboxed
2 │ type t = A(bool) | B(bool)
3 │

This untagged variant definition is invalid: At most one case can be a boolean type.
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@

We've found a bug for you!
/.../fixtures/UntaggedAtMostOneFunction.res:2:24-44

1 │ @unboxed
2 │ type t = A(int => int) | B(string => string)
3 │

This untagged variant definition is invalid: At most one case can be a function type.
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@

We've found a bug for you!
/.../fixtures/UntaggedAtMostOneInstance.res:2:20-30

1 │ @unboxed
2 │ type t = A(Date.t) | B(Date.t)
3 │

This untagged variant definition is invalid: At most one case can be a Date type.
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@

We've found a bug for you!
/.../fixtures/UntaggedAtMostOneNumber.res:2:17-26

1 │ @unboxed
2 │ type t = A(int) | B(float)
3 │

This untagged variant definition is invalid: At most one case can be a number type (int or float).
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@

We've found a bug for you!
/.../fixtures/UntaggedAtMostOneObject.res:4:15-20

2 │ type b = {y: int}
3 │ @unboxed
4 │ type t = A(a) | B(b)
5 │

This untagged variant definition is invalid: At most one case can be an object type.
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@

We've found a bug for you!
/.../fixtures/UntaggedConstructorMoreThanOneArg.res:2:1-32

1 │ @unboxed
2 │ type t = A(int, int) | B(string)
3 │

This untagged variant definition is invalid: Constructor A has more than one argument.
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@

We've found a bug for you!
/.../fixtures/UntaggedDuplicateLiteral.res:2:23-34

1 │ @unboxed
2 │ type t = | @as("x") A | @as("x") B
3 │

This untagged variant definition is invalid: Duplicate literal x.
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@

We've found a bug for you!
/.../fixtures/UntaggedDuplicatedBsAs.res:2:21-23

1 │ @unboxed
2 │ type t = | @as("x") @as("y") A | B
3 │

duplicate @as
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@

We've found a bug for you!
/.../fixtures/UntaggedInvalidVariantAsAnnotation.res:1:12-14

1 │ type t = | @as(foo) A | B
2 │

A variant case annotation @as(...) must be a string or integer, boolean, null, undefined
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@

We've found a bug for you!
/.../fixtures/UntaggedInvalidVariantTagAnnotation.res:1:1-4

1 │ @tag(123)
2 │ type t = A({foo: int}) | B({bar: string})
3 │

A variant tag annotation @tag(...) must be a string
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@

We've found a bug for you!
/.../fixtures/UntaggedOnlyOneUnknown.res:4:10-18

2 │
3 │ @unboxed
4 │ type t = A(opaque) | B(int)
5 │

This untagged variant definition is invalid: Case A has a payload that is not of one of the recognized shapes (object, array, etc). Then it must be the only case with payloads.
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@

We've found a bug for you!
/.../fixtures/UntaggedTagFieldNameConflict.res:3:3-18

1 │ @tag("kind")
2 │ type t =
3 │ | A({kind: int})
4 │ | B({other: string})
5 │

Constructor "A": the @tag name "kind" conflicts with the runtime value of inline record field "kind". Use a different @tag name or rename the field.
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@

We've found a bug for you!
/.../fixtures/bs_expect_int_or_string_or_json_literal.res:1:21-23

1 │ @val external foo: (@as(true) _, int) => unit = "foo"
2 │

expect int, string literal or json literal {json|text here|json}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@

We've found a bug for you!
/.../fixtures/bs_invalid_underscore_type_in_external.res:1:26

1 │ @obj external make: (~x: _) => _ = ""
2 │

_ is not allowed in combination with external optional type
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@

We've found a bug for you!
/.../fixtures/bs_optional_in_uncurried_bs_attribute.res:1:15-55

1 │ let f = @this (self, ~x=?) => self + x->Option.getOr(0)
2 │

Uncurried function doesn't support optional arguments yet
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@

We've found a bug for you!
/.../fixtures/bs_this_simple_pattern.res:1:16-21

1 │ let f = @this ((a, b), x) => a + b + x
2 │

%@this expect its pattern variable to be simple form
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@

We've found a bug for you!
/.../fixtures/bs_unsupported_predicates.res:1:19-23

1 │ type t = {..@get({weird: true}) "x": int}
2 │

unsupported predicates
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@

We've found a bug for you!
/.../fixtures/cannot_quantify.res:1:14-35

1 │ type t = {f: 'a. (int as 'a) => int}
2 │

The universal type variable 'a cannot be generalized: it is not a variable.
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@

We've found a bug for you!
/.../fixtures/empty_record_literal.res:1:11-12

1 │ let bad = {}
2 │

Empty record literal {} should be type annotated or used in a record context.
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@

We've found a bug for you!
/.../fixtures/extension_arity_mismatch.res:3:1-16

1 │ type t<'a> = ..
2 │
3 │ type t += A(int)
4 │

This extension does not match the definition of type t
They have different arities.
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@

We've found a bug for you!
/.../fixtures/extension_rebind_mismatch.res:5:15

3 │
4 │ type a += A(int)
5 │ type b += B = A
6 │

The constructor A has type a but was expected to be of type b
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@

We've found a bug for you!
/.../fixtures/extension_rebind_private.res:5:15

3 │ type t += private A(int)
4 │
5 │ type t += B = A
6 │

The constructor A is private
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@

We've found a bug for you!
/.../fixtures/if_return_type_mismatch.res:2:3

1 │ let x: string = if true {
2 │ 1
3 │ } else {
4 │ 2

This has type: int
But this if statement is expected to return: string

if expressions must return the same type in all branches (if, else if, else).

You can convert int to string with Int.toString.
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@

We've found a bug for you!
/.../fixtures/illegal_recursive_module_reference.res:1:15-17

1 │ module rec A: B.S = {
2 │ let x = 1
3 │ }

Illegal recursive module reference
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@

We've found a bug for you!
/.../fixtures/labeled_fn_argument_type_clash.res:3:14-17

1 │ let f = (~x: int) => x
2 │
3 │ let _ = f(~x="hi")
4 │

This has type: string
But this function argument ~x is expecting: int

You can convert string to int with Int.fromString.
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@

We've found a bug for you!
/.../fixtures/maybe_unwrap_option.res:1:14-20

1 │ let x: int = Some(5)
2 │

This has type: option<'a>
But it's expected to have type: int
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@

We've found a bug for you!
/.../fixtures/no_value_clauses.res:2:3-4:3

1 │ let f = x =>
2 │ switch x {
3 │  | exception Not_found => 1
4 │  }
5 │

None of the patterns in this 'match' expression match values.
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@

We've found a bug for you!
/.../fixtures/non_generalizable_module.res:1:8-5:1

1 │ module M = {
2 │  module Inner = {
3 │  let r = ref(None)
4 │  }
5 │ }
6 │

The type of this module contains type variables that cannot be generalized:
{
module Inner: {
let r: ref<option<'_weak1>>
}
}

This happens when the type system senses there's a mutation/side-effect,
in combination with a polymorphic value.
Using or annotating that value usually solves it.
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@

We've found a bug for you!
/.../fixtures/pattern_type_clash_polyvariant.res:3:5-6

1 │ let f = (x: int) =>
2 │ switch x {
3 │ | #A => 1
4 │ | _ => 0
5 │ }

This pattern matches values of type [? #A]
but a pattern was expected which matches values of type int
Loading
Loading