From 30dde0907e575c44d03e6f60ef9b606ee2a7e575 Mon Sep 17 00:00:00 2001 From: Jono Prest Date: Tue, 19 May 2026 14:28:09 +0200 Subject: [PATCH 01/34] super_errors: cover typecore Label_not_mutable, Apply_non_function, Invalid_for_loop_index, Field_access_on_dict_type, Private_label --- .../expected/apply_non_function.res.expected | 11 +++++++++++ .../expected/field_access_on_dict_type.res.expected | 10 ++++++++++ .../expected/invalid_for_loop_index.res.expected | 9 +++++++++ .../expected/label_not_mutable.res.expected | 10 ++++++++++ .../super_errors/expected/private_label.res.expected | 10 ++++++++++ .../super_errors/fixtures/apply_non_function.res | 3 +++ .../fixtures/field_access_on_dict_type.res | 3 +++ .../super_errors/fixtures/invalid_for_loop_index.res | 3 +++ .../super_errors/fixtures/label_not_mutable.res | 4 ++++ .../super_errors/fixtures/private_label.res | 10 ++++++++++ 10 files changed, 73 insertions(+) create mode 100644 tests/build_tests/super_errors/expected/apply_non_function.res.expected create mode 100644 tests/build_tests/super_errors/expected/field_access_on_dict_type.res.expected create mode 100644 tests/build_tests/super_errors/expected/invalid_for_loop_index.res.expected create mode 100644 tests/build_tests/super_errors/expected/label_not_mutable.res.expected create mode 100644 tests/build_tests/super_errors/expected/private_label.res.expected create mode 100644 tests/build_tests/super_errors/fixtures/apply_non_function.res create mode 100644 tests/build_tests/super_errors/fixtures/field_access_on_dict_type.res create mode 100644 tests/build_tests/super_errors/fixtures/invalid_for_loop_index.res create mode 100644 tests/build_tests/super_errors/fixtures/label_not_mutable.res create mode 100644 tests/build_tests/super_errors/fixtures/private_label.res diff --git a/tests/build_tests/super_errors/expected/apply_non_function.res.expected b/tests/build_tests/super_errors/expected/apply_non_function.res.expected new file mode 100644 index 0000000000..b083926815 --- /dev/null +++ b/tests/build_tests/super_errors/expected/apply_non_function.res.expected @@ -0,0 +1,11 @@ + + We've found a bug for you! + /.../fixtures/apply_non_function.res:3:9 + + 1 │ let x = 1 + 2 │ + 3 │ let y = x(2) + 4 │ + + This can't be called, it's not a function. + The function has type: int \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/field_access_on_dict_type.res.expected b/tests/build_tests/super_errors/expected/field_access_on_dict_type.res.expected new file mode 100644 index 0000000000..de48f798d4 --- /dev/null +++ b/tests/build_tests/super_errors/expected/field_access_on_dict_type.res.expected @@ -0,0 +1,10 @@ + + We've found a bug for you! + /.../fixtures/field_access_on_dict_type.res:3:11 + + 1 │ let d: dict = dict{"a": 1} + 2 │ + 3 │ let v = d.a + 4 │ + + Direct field access on a dict is not supported. Use Dict.get instead. \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/invalid_for_loop_index.res.expected b/tests/build_tests/super_errors/expected/invalid_for_loop_index.res.expected new file mode 100644 index 0000000000..e7cdd69e26 --- /dev/null +++ b/tests/build_tests/super_errors/expected/invalid_for_loop_index.res.expected @@ -0,0 +1,9 @@ + + We've found a bug for you! + /.../fixtures/invalid_for_loop_index.res:1:14-19 + + 1 │ let () = for (a, b) in 0 to 10 { + 2 │ ignore((a, b)) + 3 │ } + + Invalid for-loop index: only variables and _ are allowed. \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/label_not_mutable.res.expected b/tests/build_tests/super_errors/expected/label_not_mutable.res.expected new file mode 100644 index 0000000000..0d469460da --- /dev/null +++ b/tests/build_tests/super_errors/expected/label_not_mutable.res.expected @@ -0,0 +1,10 @@ + + We've found a bug for you! + /.../fixtures/label_not_mutable.res:4:10-17 + + 2 │ + 3 │ let p = {x: 1, y: 2} + 4 │ let () = p.x = 10 + 5 │ + + The record field x is not mutable \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/private_label.res.expected b/tests/build_tests/super_errors/expected/private_label.res.expected new file mode 100644 index 0000000000..7db5e011a5 --- /dev/null +++ b/tests/build_tests/super_errors/expected/private_label.res.expected @@ -0,0 +1,10 @@ + + We've found a bug for you! + /.../fixtures/private_label.res:10:12 + + 8 │ + 9 │ let r = M.make(1) + 10 │ let () = r.x = 2 + 11 │ + + Cannot assign field x of the private type M.t \ No newline at end of file diff --git a/tests/build_tests/super_errors/fixtures/apply_non_function.res b/tests/build_tests/super_errors/fixtures/apply_non_function.res new file mode 100644 index 0000000000..42b3881370 --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/apply_non_function.res @@ -0,0 +1,3 @@ +let x = 1 + +let y = x(2) diff --git a/tests/build_tests/super_errors/fixtures/field_access_on_dict_type.res b/tests/build_tests/super_errors/fixtures/field_access_on_dict_type.res new file mode 100644 index 0000000000..6b2bb8154a --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/field_access_on_dict_type.res @@ -0,0 +1,3 @@ +let d: dict = dict{"a": 1} + +let v = d.a diff --git a/tests/build_tests/super_errors/fixtures/invalid_for_loop_index.res b/tests/build_tests/super_errors/fixtures/invalid_for_loop_index.res new file mode 100644 index 0000000000..3a266867b0 --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/invalid_for_loop_index.res @@ -0,0 +1,3 @@ +let () = for (a, b) in 0 to 10 { + ignore((a, b)) +} diff --git a/tests/build_tests/super_errors/fixtures/label_not_mutable.res b/tests/build_tests/super_errors/fixtures/label_not_mutable.res new file mode 100644 index 0000000000..6b1659a70b --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/label_not_mutable.res @@ -0,0 +1,4 @@ +type point = {x: int, y: int} + +let p = {x: 1, y: 2} +let () = p.x = 10 diff --git a/tests/build_tests/super_errors/fixtures/private_label.res b/tests/build_tests/super_errors/fixtures/private_label.res new file mode 100644 index 0000000000..43aad5d7db --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/private_label.res @@ -0,0 +1,10 @@ +module M: { + type t = private {mutable x: int} + let make: int => t +} = { + type t = {mutable x: int} + let make = v => {x: v} +} + +let r = M.make(1) +let () = r.x = 2 From 06505b006351a55a66b414eb1dfd49151995d66b Mon Sep 17 00:00:00 2001 From: Jono Prest Date: Tue, 19 May 2026 14:30:03 +0200 Subject: [PATCH 02/34] super_errors: cover typedecl Boxed_and_unboxed, Bad_unboxed_attribute, Constraint_failed --- .../bad_unboxed_attribute_abstract.res.expected | 8 ++++++++ .../bad_unboxed_attribute_mutable.res.expected | 8 ++++++++ .../expected/boxed_and_unboxed.res.expected | 9 +++++++++ .../expected/constraint_failed.res.expected | 10 ++++++++++ .../fixtures/bad_unboxed_attribute_abstract.res | 1 + .../fixtures/bad_unboxed_attribute_mutable.res | 1 + .../super_errors/fixtures/boxed_and_unboxed.res | 2 ++ .../super_errors/fixtures/constraint_failed.res | 3 +++ 8 files changed, 42 insertions(+) create mode 100644 tests/build_tests/super_errors/expected/bad_unboxed_attribute_abstract.res.expected create mode 100644 tests/build_tests/super_errors/expected/bad_unboxed_attribute_mutable.res.expected create mode 100644 tests/build_tests/super_errors/expected/boxed_and_unboxed.res.expected create mode 100644 tests/build_tests/super_errors/expected/constraint_failed.res.expected create mode 100644 tests/build_tests/super_errors/fixtures/bad_unboxed_attribute_abstract.res create mode 100644 tests/build_tests/super_errors/fixtures/bad_unboxed_attribute_mutable.res create mode 100644 tests/build_tests/super_errors/fixtures/boxed_and_unboxed.res create mode 100644 tests/build_tests/super_errors/fixtures/constraint_failed.res diff --git a/tests/build_tests/super_errors/expected/bad_unboxed_attribute_abstract.res.expected b/tests/build_tests/super_errors/expected/bad_unboxed_attribute_abstract.res.expected new file mode 100644 index 0000000000..933861bbfc --- /dev/null +++ b/tests/build_tests/super_errors/expected/bad_unboxed_attribute_abstract.res.expected @@ -0,0 +1,8 @@ + + We've found a bug for you! + /.../fixtures/bad_unboxed_attribute_abstract.res:1:10-15 + + 1 │ @unboxed type t + 2 │ + + This type cannot be unboxed because it is abstract. \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/bad_unboxed_attribute_mutable.res.expected b/tests/build_tests/super_errors/expected/bad_unboxed_attribute_mutable.res.expected new file mode 100644 index 0000000000..9b3e9ebfcf --- /dev/null +++ b/tests/build_tests/super_errors/expected/bad_unboxed_attribute_mutable.res.expected @@ -0,0 +1,8 @@ + + We've found a bug for you! + /.../fixtures/bad_unboxed_attribute_mutable.res:1:10-38 + + 1 │ @unboxed type t = {mutable value: int} + 2 │ + + This type cannot be unboxed because it is mutable. \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/boxed_and_unboxed.res.expected b/tests/build_tests/super_errors/expected/boxed_and_unboxed.res.expected new file mode 100644 index 0000000000..96719069ef --- /dev/null +++ b/tests/build_tests/super_errors/expected/boxed_and_unboxed.res.expected @@ -0,0 +1,9 @@ + + We've found a bug for you! + /.../fixtures/boxed_and_unboxed.res:2:1-17 + + 1 │ @unboxed @boxed + 2 │ type t = One(int) + 3 │ + + A type cannot be boxed and unboxed at the same time. \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/constraint_failed.res.expected b/tests/build_tests/super_errors/expected/constraint_failed.res.expected new file mode 100644 index 0000000000..52c041bd52 --- /dev/null +++ b/tests/build_tests/super_errors/expected/constraint_failed.res.expected @@ -0,0 +1,10 @@ + + We've found a bug for you! + /.../fixtures/constraint_failed.res:3:14-19 + + 1 │ type t<'a> = 'a constraint 'a = int + 2 │ + 3 │ type bad = t<string> + 4 │ + + This type string should be an instance of type int \ No newline at end of file diff --git a/tests/build_tests/super_errors/fixtures/bad_unboxed_attribute_abstract.res b/tests/build_tests/super_errors/fixtures/bad_unboxed_attribute_abstract.res new file mode 100644 index 0000000000..a9c8362ed2 --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/bad_unboxed_attribute_abstract.res @@ -0,0 +1 @@ +@unboxed type t diff --git a/tests/build_tests/super_errors/fixtures/bad_unboxed_attribute_mutable.res b/tests/build_tests/super_errors/fixtures/bad_unboxed_attribute_mutable.res new file mode 100644 index 0000000000..f5185f4dd1 --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/bad_unboxed_attribute_mutable.res @@ -0,0 +1 @@ +@unboxed type t = {mutable value: int} diff --git a/tests/build_tests/super_errors/fixtures/boxed_and_unboxed.res b/tests/build_tests/super_errors/fixtures/boxed_and_unboxed.res new file mode 100644 index 0000000000..803c980c00 --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/boxed_and_unboxed.res @@ -0,0 +1,2 @@ +@unboxed @boxed +type t = One(int) diff --git a/tests/build_tests/super_errors/fixtures/constraint_failed.res b/tests/build_tests/super_errors/fixtures/constraint_failed.res new file mode 100644 index 0000000000..49c2a9617f --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/constraint_failed.res @@ -0,0 +1,3 @@ +type t<'a> = 'a constraint 'a = int + +type bad = t From d428a01f5648a7995280c4836252653ca11231a2 Mon Sep 17 00:00:00 2001 From: Jono Prest Date: Tue, 19 May 2026 14:31:37 +0200 Subject: [PATCH 03/34] super_errors: cover translcore Unknown_builtin_primitive and typecore Less_general --- .../expected/less_general_universal.res.expected | 9 +++++++++ .../expected/unknown_builtin_primitive.res.expected | 10 ++++++++++ .../super_errors/fixtures/less_general_universal.res | 1 + .../fixtures/unknown_builtin_primitive.res | 3 +++ 4 files changed, 23 insertions(+) create mode 100644 tests/build_tests/super_errors/expected/less_general_universal.res.expected create mode 100644 tests/build_tests/super_errors/expected/unknown_builtin_primitive.res.expected create mode 100644 tests/build_tests/super_errors/fixtures/less_general_universal.res create mode 100644 tests/build_tests/super_errors/fixtures/unknown_builtin_primitive.res diff --git a/tests/build_tests/super_errors/expected/less_general_universal.res.expected b/tests/build_tests/super_errors/expected/less_general_universal.res.expected new file mode 100644 index 0000000000..f0d4bc18dd --- /dev/null +++ b/tests/build_tests/super_errors/expected/less_general_universal.res.expected @@ -0,0 +1,9 @@ + + We've found a bug for you! + /.../fixtures/less_general_universal.res:1:23-39 + + 1 │ let f: 'a. 'a => 'a = (x: int) => x + 1 + 2 │ + + This definition has type int => int + which is less general than 'a. 'a => 'a \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/unknown_builtin_primitive.res.expected b/tests/build_tests/super_errors/expected/unknown_builtin_primitive.res.expected new file mode 100644 index 0000000000..24eb916337 --- /dev/null +++ b/tests/build_tests/super_errors/expected/unknown_builtin_primitive.res.expected @@ -0,0 +1,10 @@ + + We've found a bug for you! + /.../fixtures/unknown_builtin_primitive.res:3:9-16 + + 1 │ external bogus: int => int = "%nonexistent_primitive" + 2 │ + 3 │ let _ = bogus(1) + 4 │ + + Unknown builtin primitive "%nonexistent_primitive" \ No newline at end of file diff --git a/tests/build_tests/super_errors/fixtures/less_general_universal.res b/tests/build_tests/super_errors/fixtures/less_general_universal.res new file mode 100644 index 0000000000..84a662f87c --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/less_general_universal.res @@ -0,0 +1 @@ +let f: 'a. 'a => 'a = (x: int) => x + 1 diff --git a/tests/build_tests/super_errors/fixtures/unknown_builtin_primitive.res b/tests/build_tests/super_errors/fixtures/unknown_builtin_primitive.res new file mode 100644 index 0000000000..208b8dc84c --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/unknown_builtin_primitive.res @@ -0,0 +1,3 @@ +external bogus: int => int = "%nonexistent_primitive" + +let _ = bogus(1) From bb417afbb42d6ec24533dd18149ebc3f51e724e5 Mon Sep 17 00:00:00 2001 From: Jono Prest Date: Tue, 19 May 2026 14:32:46 +0200 Subject: [PATCH 04/34] super_errors: cover typemod With_no_component, Cannot_apply, Recursive_module_require_explicit_type --- .../expected/cannot_apply_non_functor.res.expected | 12 ++++++++++++ ...cursive_module_require_explicit_type.res.expected | 10 ++++++++++ .../expected/with_no_component.res.expected | 10 ++++++++++ .../fixtures/cannot_apply_non_functor.res | 5 +++++ .../recursive_module_require_explicit_type.res | 3 +++ .../super_errors/fixtures/with_no_component.res | 5 +++++ 6 files changed, 45 insertions(+) create mode 100644 tests/build_tests/super_errors/expected/cannot_apply_non_functor.res.expected create mode 100644 tests/build_tests/super_errors/expected/recursive_module_require_explicit_type.res.expected create mode 100644 tests/build_tests/super_errors/expected/with_no_component.res.expected create mode 100644 tests/build_tests/super_errors/fixtures/cannot_apply_non_functor.res create mode 100644 tests/build_tests/super_errors/fixtures/recursive_module_require_explicit_type.res create mode 100644 tests/build_tests/super_errors/fixtures/with_no_component.res diff --git a/tests/build_tests/super_errors/expected/cannot_apply_non_functor.res.expected b/tests/build_tests/super_errors/expected/cannot_apply_non_functor.res.expected new file mode 100644 index 0000000000..5d80920d65 --- /dev/null +++ b/tests/build_tests/super_errors/expected/cannot_apply_non_functor.res.expected @@ -0,0 +1,12 @@ + + We've found a bug for you! + /.../fixtures/cannot_apply_non_functor.res:5:12 + + 3 │ } + 4 │ + 5 │ module N = M() + 6 │ + + This module is not a functor; it has type { + let x: int +} \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/recursive_module_require_explicit_type.res.expected b/tests/build_tests/super_errors/expected/recursive_module_require_explicit_type.res.expected new file mode 100644 index 0000000000..90182f07f2 --- /dev/null +++ b/tests/build_tests/super_errors/expected/recursive_module_require_explicit_type.res.expected @@ -0,0 +1,10 @@ + + We've found a bug for you! + /.../fixtures/recursive_module_require_explicit_type.res:1:16-3:1 + + 1 │ module rec M = { + 2 │  let x = 1 + 3 │ } + 4 │ + + Recursive modules require an explicit module type. \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/with_no_component.res.expected b/tests/build_tests/super_errors/expected/with_no_component.res.expected new file mode 100644 index 0000000000..4912769dd5 --- /dev/null +++ b/tests/build_tests/super_errors/expected/with_no_component.res.expected @@ -0,0 +1,10 @@ + + We've found a bug for you! + /.../fixtures/with_no_component.res:5:17-41 + + 3 │ } + 4 │ + 5 │ module type T = S with type missing = int + 6 │ + + The signature constrained by `with' has no component named missing \ No newline at end of file diff --git a/tests/build_tests/super_errors/fixtures/cannot_apply_non_functor.res b/tests/build_tests/super_errors/fixtures/cannot_apply_non_functor.res new file mode 100644 index 0000000000..c88f9bec40 --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/cannot_apply_non_functor.res @@ -0,0 +1,5 @@ +module M = { + let x = 1 +} + +module N = M() diff --git a/tests/build_tests/super_errors/fixtures/recursive_module_require_explicit_type.res b/tests/build_tests/super_errors/fixtures/recursive_module_require_explicit_type.res new file mode 100644 index 0000000000..7e51670d2d --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/recursive_module_require_explicit_type.res @@ -0,0 +1,3 @@ +module rec M = { + let x = 1 +} diff --git a/tests/build_tests/super_errors/fixtures/with_no_component.res b/tests/build_tests/super_errors/fixtures/with_no_component.res new file mode 100644 index 0000000000..d999a917b5 --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/with_no_component.res @@ -0,0 +1,5 @@ +module type S = { + type t +} + +module type T = S with type missing = int From efd21b7c5b789ec4ad76e90a9e3cb45c20054c39 Mon Sep 17 00:00:00 2001 From: Jono Prest Date: Tue, 19 May 2026 14:34:06 +0200 Subject: [PATCH 05/34] super_errors: cover translmod Fragile_pattern_in_toplevel and transl_recmodule Circular_dependency --- .../fragile_pattern_toplevel.res.expected | 20 +++++++++++++++++++ ...recmodule_circular_dependency.res.expected | 13 ++++++++++++ .../fixtures/fragile_pattern_toplevel.res | 3 +++ .../recmodule_circular_dependency.res | 10 ++++++++++ 4 files changed, 46 insertions(+) create mode 100644 tests/build_tests/super_errors/expected/fragile_pattern_toplevel.res.expected create mode 100644 tests/build_tests/super_errors/expected/recmodule_circular_dependency.res.expected create mode 100644 tests/build_tests/super_errors/fixtures/fragile_pattern_toplevel.res create mode 100644 tests/build_tests/super_errors/fixtures/recmodule_circular_dependency.res diff --git a/tests/build_tests/super_errors/expected/fragile_pattern_toplevel.res.expected b/tests/build_tests/super_errors/expected/fragile_pattern_toplevel.res.expected new file mode 100644 index 0000000000..b07c08cdd4 --- /dev/null +++ b/tests/build_tests/super_errors/expected/fragile_pattern_toplevel.res.expected @@ -0,0 +1,20 @@ + + Warning number 8 + /.../fixtures/fragile_pattern_toplevel.res:1:5-11 + + 1 │ let Some(x) = Some(1) + 2 │ + 3 │ let _ = x + + You forgot to handle a possible case here, for example: + | None + + + We've found a bug for you! + /.../fixtures/fragile_pattern_toplevel.res:1:5-11 + + 1 │ let Some(x) = Some(1) + 2 │ + 3 │ let _ = x + + Such fragile pattern not allowed in the toplevel \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/recmodule_circular_dependency.res.expected b/tests/build_tests/super_errors/expected/recmodule_circular_dependency.res.expected new file mode 100644 index 0000000000..105b9841bc --- /dev/null +++ b/tests/build_tests/super_errors/expected/recmodule_circular_dependency.res.expected @@ -0,0 +1,13 @@ + + We've found a bug for you! + /.../fixtures/recmodule_circular_dependency.res:3:5-5:1 + + 1 │ module rec A: { + 2 │ let v: int + 3 │ } = { + 4 │  let v = B.v + 5 │ } + 6 │ and B: { + 7 │ let v: int + + Cannot safely evaluate the definition of the recursively-defined module A \ No newline at end of file diff --git a/tests/build_tests/super_errors/fixtures/fragile_pattern_toplevel.res b/tests/build_tests/super_errors/fixtures/fragile_pattern_toplevel.res new file mode 100644 index 0000000000..9f6fbe7039 --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/fragile_pattern_toplevel.res @@ -0,0 +1,3 @@ +let Some(x) = Some(1) + +let _ = x diff --git a/tests/build_tests/super_errors/fixtures/recmodule_circular_dependency.res b/tests/build_tests/super_errors/fixtures/recmodule_circular_dependency.res new file mode 100644 index 0000000000..ec64536d29 --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/recmodule_circular_dependency.res @@ -0,0 +1,10 @@ +module rec A: { + let v: int +} = { + let v = B.v +} +and B: { + let v: int +} = { + let v = A.v +} From 46b9a97e0e2d5d5c6792f3bc806cbe2c97f4cc13 Mon Sep 17 00:00:00 2001 From: Jono Prest Date: Tue, 19 May 2026 14:35:14 +0200 Subject: [PATCH 06/34] super_errors: cover includemod signature-mismatch errors (Missing_field, Value_descriptions, Type_declarations) --- .../include_missing_field.res.expected | 24 ++++++++++++++++ .../include_type_decl_mismatch.res.expected | 28 +++++++++++++++++++ .../include_value_type_mismatch.res.expected | 25 +++++++++++++++++ .../fixtures/include_missing_field.res | 6 ++++ .../fixtures/include_type_decl_mismatch.res | 5 ++++ .../fixtures/include_value_type_mismatch.res | 5 ++++ 6 files changed, 93 insertions(+) create mode 100644 tests/build_tests/super_errors/expected/include_missing_field.res.expected create mode 100644 tests/build_tests/super_errors/expected/include_type_decl_mismatch.res.expected create mode 100644 tests/build_tests/super_errors/expected/include_value_type_mismatch.res.expected create mode 100644 tests/build_tests/super_errors/fixtures/include_missing_field.res create mode 100644 tests/build_tests/super_errors/fixtures/include_type_decl_mismatch.res create mode 100644 tests/build_tests/super_errors/fixtures/include_value_type_mismatch.res diff --git a/tests/build_tests/super_errors/expected/include_missing_field.res.expected b/tests/build_tests/super_errors/expected/include_missing_field.res.expected new file mode 100644 index 0000000000..77aa8ca856 --- /dev/null +++ b/tests/build_tests/super_errors/expected/include_missing_field.res.expected @@ -0,0 +1,24 @@ + + We've found a bug for you! + /.../fixtures/include_missing_field.res:4:5-6:1 + + 2 │ let x: int + 3 │ let y: string + 4 │ } = { + 5 │  let x = 1 + 6 │ } + 7 │ + + Signature mismatch: + Modules do not match: + { + let x: int +} + is not included in + { + let x: int + let y: string +} + The value `y' is required but not provided + /.../fixtures/include_missing_field.res:3:3-15: + Expected declaration \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/include_type_decl_mismatch.res.expected b/tests/build_tests/super_errors/expected/include_type_decl_mismatch.res.expected new file mode 100644 index 0000000000..b659d115ba --- /dev/null +++ b/tests/build_tests/super_errors/expected/include_type_decl_mismatch.res.expected @@ -0,0 +1,28 @@ + + We've found a bug for you! + /.../fixtures/include_type_decl_mismatch.res:3:5-5:1 + + 1 │ module M: { + 2 │ type t = int + 3 │ } = { + 4 │  type t = string + 5 │ } + 6 │ + + Signature mismatch: + Modules do not match: + { + type t = string +} + is not included in + { + type t = int +} + Type declarations do not match: + type t = string + is not included in + type t = int + /.../fixtures/include_type_decl_mismatch.res:2:3-14: + Expected declaration + /.../fixtures/include_type_decl_mismatch.res:4:3-17: + Actual declaration \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/include_value_type_mismatch.res.expected b/tests/build_tests/super_errors/expected/include_value_type_mismatch.res.expected new file mode 100644 index 0000000000..5e9aa17990 --- /dev/null +++ b/tests/build_tests/super_errors/expected/include_value_type_mismatch.res.expected @@ -0,0 +1,25 @@ + + We've found a bug for you! + /.../fixtures/include_value_type_mismatch.res:3:5-5:1 + + 1 │ module M: { + 2 │ let x: int + 3 │ } = { + 4 │  let x = "wrong" + 5 │ } + 6 │ + + Signature mismatch: + Modules do not match: + { + let x: string +} + is not included in + { + let x: int +} + Values do not match: let x: string is not included in let x: int + /.../fixtures/include_value_type_mismatch.res:2:3-12: + Expected declaration + /.../fixtures/include_value_type_mismatch.res:4:7: + Actual declaration \ No newline at end of file diff --git a/tests/build_tests/super_errors/fixtures/include_missing_field.res b/tests/build_tests/super_errors/fixtures/include_missing_field.res new file mode 100644 index 0000000000..807e2f85d3 --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/include_missing_field.res @@ -0,0 +1,6 @@ +module M: { + let x: int + let y: string +} = { + let x = 1 +} diff --git a/tests/build_tests/super_errors/fixtures/include_type_decl_mismatch.res b/tests/build_tests/super_errors/fixtures/include_type_decl_mismatch.res new file mode 100644 index 0000000000..b936c884b1 --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/include_type_decl_mismatch.res @@ -0,0 +1,5 @@ +module M: { + type t = int +} = { + type t = string +} diff --git a/tests/build_tests/super_errors/fixtures/include_value_type_mismatch.res b/tests/build_tests/super_errors/fixtures/include_value_type_mismatch.res new file mode 100644 index 0000000000..4803995815 --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/include_value_type_mismatch.res @@ -0,0 +1,5 @@ +module M: { + let x: int +} = { + let x = "wrong" +} From 92af7badf00f28b011ce7ed37c78d2d75e0f7a04 Mon Sep 17 00:00:00 2001 From: Jono Prest Date: Tue, 19 May 2026 14:37:21 +0200 Subject: [PATCH 07/34] super_errors: cover typecore Not_an_extension_constructor, Invalid_extension_constructor_payload, Inlined_record_expected --- .../expected/inlined_record_expected.res.expected | 10 ++++++++++ .../invalid_extension_constructor_payload.res.expected | 8 ++++++++ .../expected/not_an_extension_constructor.res.expected | 10 ++++++++++ .../super_errors/fixtures/inlined_record_expected.res | 3 +++ .../fixtures/invalid_extension_constructor_payload.res | 1 + .../fixtures/not_an_extension_constructor.res | 3 +++ 6 files changed, 35 insertions(+) create mode 100644 tests/build_tests/super_errors/expected/inlined_record_expected.res.expected create mode 100644 tests/build_tests/super_errors/expected/invalid_extension_constructor_payload.res.expected create mode 100644 tests/build_tests/super_errors/expected/not_an_extension_constructor.res.expected create mode 100644 tests/build_tests/super_errors/fixtures/inlined_record_expected.res create mode 100644 tests/build_tests/super_errors/fixtures/invalid_extension_constructor_payload.res create mode 100644 tests/build_tests/super_errors/fixtures/not_an_extension_constructor.res diff --git a/tests/build_tests/super_errors/expected/inlined_record_expected.res.expected b/tests/build_tests/super_errors/expected/inlined_record_expected.res.expected new file mode 100644 index 0000000000..3b8d3ffdb5 --- /dev/null +++ b/tests/build_tests/super_errors/expected/inlined_record_expected.res.expected @@ -0,0 +1,10 @@ + + We've found a bug for you! + /.../fixtures/inlined_record_expected.res:3:9-12 + + 1 │ type t = A({x: int}) + 2 │ + 3 │ let _ = A(1) + 4 │ + + This constructor expects an inlined record argument. \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/invalid_extension_constructor_payload.res.expected b/tests/build_tests/super_errors/expected/invalid_extension_constructor_payload.res.expected new file mode 100644 index 0000000000..73f16cf7ae --- /dev/null +++ b/tests/build_tests/super_errors/expected/invalid_extension_constructor_payload.res.expected @@ -0,0 +1,8 @@ + + We've found a bug for you! + /.../fixtures/invalid_extension_constructor_payload.res:1:9-37 + + 1 │ let _ = %extension_constructor(1 + 1) + 2 │ + + Invalid [%extension_constructor] payload, a constructor is expected. \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/not_an_extension_constructor.res.expected b/tests/build_tests/super_errors/expected/not_an_extension_constructor.res.expected new file mode 100644 index 0000000000..e9e410d2a5 --- /dev/null +++ b/tests/build_tests/super_errors/expected/not_an_extension_constructor.res.expected @@ -0,0 +1,10 @@ + + We've found a bug for you! + /.../fixtures/not_an_extension_constructor.res:3:32 + + 1 │ type t = A + 2 │ + 3 │ let _ = %extension_constructor(A) + 4 │ + + This constructor is not an extension constructor. \ No newline at end of file diff --git a/tests/build_tests/super_errors/fixtures/inlined_record_expected.res b/tests/build_tests/super_errors/fixtures/inlined_record_expected.res new file mode 100644 index 0000000000..2844909d6a --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/inlined_record_expected.res @@ -0,0 +1,3 @@ +type t = A({x: int}) + +let _ = A(1) diff --git a/tests/build_tests/super_errors/fixtures/invalid_extension_constructor_payload.res b/tests/build_tests/super_errors/fixtures/invalid_extension_constructor_payload.res new file mode 100644 index 0000000000..a8cd8bf06e --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/invalid_extension_constructor_payload.res @@ -0,0 +1 @@ +let _ = %extension_constructor(1 + 1) diff --git a/tests/build_tests/super_errors/fixtures/not_an_extension_constructor.res b/tests/build_tests/super_errors/fixtures/not_an_extension_constructor.res new file mode 100644 index 0000000000..3cffdf20af --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/not_an_extension_constructor.res @@ -0,0 +1,3 @@ +type t = A + +let _ = %extension_constructor(A) From 8883005bbaca1e3007d2a62440debf167212f095 Mon Sep 17 00:00:00 2001 From: Jono Prest Date: Tue, 19 May 2026 14:39:26 +0200 Subject: [PATCH 08/34] super_errors: cover rec_check Illegal_letrec_expr --- .../expected/illegal_letrec_expr.res.expected | 8 ++++++++ .../super_errors/fixtures/illegal_letrec_expr.res | 1 + 2 files changed, 9 insertions(+) create mode 100644 tests/build_tests/super_errors/expected/illegal_letrec_expr.res.expected create mode 100644 tests/build_tests/super_errors/fixtures/illegal_letrec_expr.res diff --git a/tests/build_tests/super_errors/expected/illegal_letrec_expr.res.expected b/tests/build_tests/super_errors/expected/illegal_letrec_expr.res.expected new file mode 100644 index 0000000000..0b98483c37 --- /dev/null +++ b/tests/build_tests/super_errors/expected/illegal_letrec_expr.res.expected @@ -0,0 +1,8 @@ + + We've found a bug for you! + /.../fixtures/illegal_letrec_expr.res:1:13-17 + + 1 │ let rec x = x + 1 + 2 │ + + This kind of expression is not allowed as right-hand side of `let rec' \ No newline at end of file diff --git a/tests/build_tests/super_errors/fixtures/illegal_letrec_expr.res b/tests/build_tests/super_errors/fixtures/illegal_letrec_expr.res new file mode 100644 index 0000000000..6aced9f703 --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/illegal_letrec_expr.res @@ -0,0 +1 @@ +let rec x = x + 1 From fb5609115679aaefc31c4c09f3f7aa0cc9671d94 Mon Sep 17 00:00:00 2001 From: Jono Prest Date: Tue, 19 May 2026 14:41:12 +0200 Subject: [PATCH 09/34] super_errors: cover typedecl Nonrec_gadt, Not_extensible_type, Cannot_extend_private_type --- .../expected/cannot_extend_private_type.res.expected | 10 ++++++++++ .../super_errors/expected/nonrec_gadt.res.expected | 10 ++++++++++ .../expected/not_extensible_type.res.expected | 10 ++++++++++ .../fixtures/cannot_extend_private_type.res | 7 +++++++ .../build_tests/super_errors/fixtures/nonrec_gadt.res | 1 + .../super_errors/fixtures/not_extensible_type.res | 3 +++ 6 files changed, 41 insertions(+) create mode 100644 tests/build_tests/super_errors/expected/cannot_extend_private_type.res.expected create mode 100644 tests/build_tests/super_errors/expected/nonrec_gadt.res.expected create mode 100644 tests/build_tests/super_errors/expected/not_extensible_type.res.expected create mode 100644 tests/build_tests/super_errors/fixtures/cannot_extend_private_type.res create mode 100644 tests/build_tests/super_errors/fixtures/nonrec_gadt.res create mode 100644 tests/build_tests/super_errors/fixtures/not_extensible_type.res diff --git a/tests/build_tests/super_errors/expected/cannot_extend_private_type.res.expected b/tests/build_tests/super_errors/expected/cannot_extend_private_type.res.expected new file mode 100644 index 0000000000..f6a2fe83f9 --- /dev/null +++ b/tests/build_tests/super_errors/expected/cannot_extend_private_type.res.expected @@ -0,0 +1,10 @@ + + We've found a bug for you! + /.../fixtures/cannot_extend_private_type.res:7:13 + + 5 │ } + 6 │ + 7 │ type M.t += C + 8 │ + + Cannot extend private type definition M.t \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/nonrec_gadt.res.expected b/tests/build_tests/super_errors/expected/nonrec_gadt.res.expected new file mode 100644 index 0000000000..546c876e0f --- /dev/null +++ b/tests/build_tests/super_errors/expected/nonrec_gadt.res.expected @@ -0,0 +1,10 @@ + + We've found a bug for you! + /.../fixtures/nonrec_gadt.res:1:1-27 + + 1 │ type t<'a> = A(int): t + 2 │ + + GADTs require recursive type syntax. +Define your type using `type rec` instead of `type`. +Example: type rec t = ... \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/not_extensible_type.res.expected b/tests/build_tests/super_errors/expected/not_extensible_type.res.expected new file mode 100644 index 0000000000..4a3eea6b71 --- /dev/null +++ b/tests/build_tests/super_errors/expected/not_extensible_type.res.expected @@ -0,0 +1,10 @@ + + We've found a bug for you! + /.../fixtures/not_extensible_type.res:3:1-11 + + 1 │ type t = A | B + 2 │ + 3 │ type t += C + 4 │ + + Type definition t is not extensible \ No newline at end of file diff --git a/tests/build_tests/super_errors/fixtures/cannot_extend_private_type.res b/tests/build_tests/super_errors/fixtures/cannot_extend_private_type.res new file mode 100644 index 0000000000..122b16f3ce --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/cannot_extend_private_type.res @@ -0,0 +1,7 @@ +module M: { + type t = private .. +} = { + type t = .. +} + +type M.t += C diff --git a/tests/build_tests/super_errors/fixtures/nonrec_gadt.res b/tests/build_tests/super_errors/fixtures/nonrec_gadt.res new file mode 100644 index 0000000000..b4cee70d45 --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/nonrec_gadt.res @@ -0,0 +1 @@ +type t<'a> = A(int): t diff --git a/tests/build_tests/super_errors/fixtures/not_extensible_type.res b/tests/build_tests/super_errors/fixtures/not_extensible_type.res new file mode 100644 index 0000000000..80d78d4556 --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/not_extensible_type.res @@ -0,0 +1,3 @@ +type t = A | B + +type t += C From 66253ffa8a0e710ead3c178fbe3f58840c38b32c Mon Sep 17 00:00:00 2001 From: Jono Prest Date: Tue, 19 May 2026 14:43:17 +0200 Subject: [PATCH 10/34] super_errors: cover typedecl Object_spread_with_record_field --- .../object_spread_with_record_field.res.expected | 11 +++++++++++ .../fixtures/object_spread_with_record_field.res | 3 +++ 2 files changed, 14 insertions(+) create mode 100644 tests/build_tests/super_errors/expected/object_spread_with_record_field.res.expected create mode 100644 tests/build_tests/super_errors/fixtures/object_spread_with_record_field.res diff --git a/tests/build_tests/super_errors/expected/object_spread_with_record_field.res.expected b/tests/build_tests/super_errors/expected/object_spread_with_record_field.res.expected new file mode 100644 index 0000000000..9712c4c559 --- /dev/null +++ b/tests/build_tests/super_errors/expected/object_spread_with_record_field.res.expected @@ -0,0 +1,11 @@ + + We've found a bug for you! + /.../fixtures/object_spread_with_record_field.res:3:19-24 + + 1 │ type obj = {"x": int} + 2 │ + 3 │ type t = {...obj, y: int} + 4 │ + + You cannot mix a record field with an object type spread. + Remove the record field or change it to an object field (e.g. "y": ...). \ No newline at end of file diff --git a/tests/build_tests/super_errors/fixtures/object_spread_with_record_field.res b/tests/build_tests/super_errors/fixtures/object_spread_with_record_field.res new file mode 100644 index 0000000000..4da7399218 --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/object_spread_with_record_field.res @@ -0,0 +1,3 @@ +type obj = {"x": int} + +type t = {...obj, y: int} From 36d12348415f3fdff251095f5ca97282858562d2 Mon Sep 17 00:00:00 2001 From: Jono Prest Date: Tue, 19 May 2026 15:08:36 +0200 Subject: [PATCH 11/34] super_errors: cover typetexp Unbound_value, Unbound_constructor, Unbound_label, Unbound_modtype --- .../typetexp_unbound_constructor.res.expected | 16 ++++++++++++++++ .../expected/typetexp_unbound_label.res.expected | 12 ++++++++++++ .../typetexp_unbound_modtype.res.expected | 8 ++++++++ .../expected/typetexp_unbound_value.res.expected | 8 ++++++++ .../fixtures/typetexp_unbound_constructor.res | 3 +++ .../fixtures/typetexp_unbound_label.res | 5 +++++ .../fixtures/typetexp_unbound_modtype.res | 1 + .../fixtures/typetexp_unbound_value.res | 1 + 8 files changed, 54 insertions(+) create mode 100644 tests/build_tests/super_errors/expected/typetexp_unbound_constructor.res.expected create mode 100644 tests/build_tests/super_errors/expected/typetexp_unbound_label.res.expected create mode 100644 tests/build_tests/super_errors/expected/typetexp_unbound_modtype.res.expected create mode 100644 tests/build_tests/super_errors/expected/typetexp_unbound_value.res.expected create mode 100644 tests/build_tests/super_errors/fixtures/typetexp_unbound_constructor.res create mode 100644 tests/build_tests/super_errors/fixtures/typetexp_unbound_label.res create mode 100644 tests/build_tests/super_errors/fixtures/typetexp_unbound_modtype.res create mode 100644 tests/build_tests/super_errors/fixtures/typetexp_unbound_value.res diff --git a/tests/build_tests/super_errors/expected/typetexp_unbound_constructor.res.expected b/tests/build_tests/super_errors/expected/typetexp_unbound_constructor.res.expected new file mode 100644 index 0000000000..d261c26e04 --- /dev/null +++ b/tests/build_tests/super_errors/expected/typetexp_unbound_constructor.res.expected @@ -0,0 +1,16 @@ + + We've found a bug for you! + /.../fixtures/typetexp_unbound_constructor.res:3:9-19 + + 1 │ type t = A | B + 2 │ + 3 │ let v = MissingCtor + 4 │ + + The variant constructor MissingCtor can't be found. + + - If it's defined in another module or file, bring it into scope by: + - Prefixing it with said module name: TheModule.MissingCtor + - Or specifying its type: let theValue: TheModule.theType = MissingCtor + - Constructors and modules are both capitalized. Did you want the latter? + Then instead of let foo = Bar, try module Foo = Bar. \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/typetexp_unbound_label.res.expected b/tests/build_tests/super_errors/expected/typetexp_unbound_label.res.expected new file mode 100644 index 0000000000..b5a0be4f2b --- /dev/null +++ b/tests/build_tests/super_errors/expected/typetexp_unbound_label.res.expected @@ -0,0 +1,12 @@ + + We've found a bug for you! + /.../fixtures/typetexp_unbound_label.res:5:11-22 + + 3 │ let r = {x: 1, y: 2} + 4 │ + 5 │ let v = r.missingLabel + 6 │ + + The field missingLabel does not belong to type t + + This expression has type t \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/typetexp_unbound_modtype.res.expected b/tests/build_tests/super_errors/expected/typetexp_unbound_modtype.res.expected new file mode 100644 index 0000000000..cced36deeb --- /dev/null +++ b/tests/build_tests/super_errors/expected/typetexp_unbound_modtype.res.expected @@ -0,0 +1,8 @@ + + We've found a bug for you! + /.../fixtures/typetexp_unbound_modtype.res:1:17-33 + + 1 │ module type T = MissingModuleType + 2 │ + + Unbound module type MissingModuleType \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/typetexp_unbound_value.res.expected b/tests/build_tests/super_errors/expected/typetexp_unbound_value.res.expected new file mode 100644 index 0000000000..a922f445de --- /dev/null +++ b/tests/build_tests/super_errors/expected/typetexp_unbound_value.res.expected @@ -0,0 +1,8 @@ + + We've found a bug for you! + /.../fixtures/typetexp_unbound_value.res:1:15-26 + + 1 │ let f = () => missingValue + 1 + 2 │ + + The value missingValue can't be found \ No newline at end of file diff --git a/tests/build_tests/super_errors/fixtures/typetexp_unbound_constructor.res b/tests/build_tests/super_errors/fixtures/typetexp_unbound_constructor.res new file mode 100644 index 0000000000..a7529238a2 --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/typetexp_unbound_constructor.res @@ -0,0 +1,3 @@ +type t = A | B + +let v = MissingCtor diff --git a/tests/build_tests/super_errors/fixtures/typetexp_unbound_label.res b/tests/build_tests/super_errors/fixtures/typetexp_unbound_label.res new file mode 100644 index 0000000000..e17d2623e3 --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/typetexp_unbound_label.res @@ -0,0 +1,5 @@ +type t = {x: int, y: int} + +let r = {x: 1, y: 2} + +let v = r.missingLabel diff --git a/tests/build_tests/super_errors/fixtures/typetexp_unbound_modtype.res b/tests/build_tests/super_errors/fixtures/typetexp_unbound_modtype.res new file mode 100644 index 0000000000..82d4527484 --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/typetexp_unbound_modtype.res @@ -0,0 +1 @@ +module type T = MissingModuleType diff --git a/tests/build_tests/super_errors/fixtures/typetexp_unbound_value.res b/tests/build_tests/super_errors/fixtures/typetexp_unbound_value.res new file mode 100644 index 0000000000..b5d70cce66 --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/typetexp_unbound_value.res @@ -0,0 +1 @@ +let f = () => missingValue + 1 From a0fc98840c9e761af4143499d071f5478ac0ed60 Mon Sep 17 00:00:00 2001 From: Jono Prest Date: Tue, 19 May 2026 15:11:44 +0200 Subject: [PATCH 12/34] super_errors: cover let-module scope escape, typemod Apply_generative and With_mismatch --- .../expected/apply_generative.res.expected | 11 +++++++++++ .../expected/scoping_let_module.res.expected | 13 +++++++++++++ .../expected/with_mismatch.res.expected | 19 +++++++++++++++++++ .../fixtures/apply_generative.res | 7 +++++++ .../fixtures/scoping_let_module.res | 12 ++++++++++++ .../super_errors/fixtures/with_mismatch.res | 5 +++++ 6 files changed, 67 insertions(+) create mode 100644 tests/build_tests/super_errors/expected/apply_generative.res.expected create mode 100644 tests/build_tests/super_errors/expected/scoping_let_module.res.expected create mode 100644 tests/build_tests/super_errors/expected/with_mismatch.res.expected create mode 100644 tests/build_tests/super_errors/fixtures/apply_generative.res create mode 100644 tests/build_tests/super_errors/fixtures/scoping_let_module.res create mode 100644 tests/build_tests/super_errors/fixtures/with_mismatch.res diff --git a/tests/build_tests/super_errors/expected/apply_generative.res.expected b/tests/build_tests/super_errors/expected/apply_generative.res.expected new file mode 100644 index 0000000000..a3ff759ca1 --- /dev/null +++ b/tests/build_tests/super_errors/expected/apply_generative.res.expected @@ -0,0 +1,11 @@ + + We've found a bug for you! + /.../fixtures/apply_generative.res:5:12 + + 3 │ } + 4 │ + 5 │ module M = F({ + 6 │ let y = 2 + 7 │ }) + + This is a generative functor. It can only be applied to () \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/scoping_let_module.res.expected b/tests/build_tests/super_errors/expected/scoping_let_module.res.expected new file mode 100644 index 0000000000..bdf1a88f27 --- /dev/null +++ b/tests/build_tests/super_errors/expected/scoping_let_module.res.expected @@ -0,0 +1,13 @@ + + We've found a bug for you! + /.../fixtures/scoping_let_module.res:9:3-5 + + 7 │ let v: t = 1 + 8 │ } + 9 │ M.v + 10 │ } + 11 │ + + This has type: M.t + But it's expected to have type: 'a + The type constructor M.t would escape its scope \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/with_mismatch.res.expected b/tests/build_tests/super_errors/expected/with_mismatch.res.expected new file mode 100644 index 0000000000..6f5e2b4713 --- /dev/null +++ b/tests/build_tests/super_errors/expected/with_mismatch.res.expected @@ -0,0 +1,19 @@ + + We've found a bug for you! + /.../fixtures/with_mismatch.res:5:17-38 + + 3 │ } + 4 │ + 5 │ module type T = S with type t = string + 6 │ + + In this `with' constraint, the new definition of t + does not match its original definition in the constrained signature: + Type declarations do not match: + type t = string + is not included in + type t = int + /.../fixtures/with_mismatch.res:2:3-14: + Expected declaration + /.../fixtures/with_mismatch.res:5:29: + Actual declaration \ No newline at end of file diff --git a/tests/build_tests/super_errors/fixtures/apply_generative.res b/tests/build_tests/super_errors/fixtures/apply_generative.res new file mode 100644 index 0000000000..60942d2dfb --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/apply_generative.res @@ -0,0 +1,7 @@ +module F = () => { + let x = 1 +} + +module M = F({ + let y = 2 +}) diff --git a/tests/build_tests/super_errors/fixtures/scoping_let_module.res b/tests/build_tests/super_errors/fixtures/scoping_let_module.res new file mode 100644 index 0000000000..8737eec243 --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/scoping_let_module.res @@ -0,0 +1,12 @@ +let leaked = { + module M: { + type t + let v: t + } = { + type t = int + let v: t = 1 + } + M.v +} + +let _ = leaked diff --git a/tests/build_tests/super_errors/fixtures/with_mismatch.res b/tests/build_tests/super_errors/fixtures/with_mismatch.res new file mode 100644 index 0000000000..d2d4fc0cc3 --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/with_mismatch.res @@ -0,0 +1,5 @@ +module type S = { + type t = int +} + +module type T = S with type t = string From a3d619d5e89b7ef6f9eae0a757a989ced5297128 Mon Sep 17 00:00:00 2001 From: Jono Prest Date: Tue, 19 May 2026 15:14:09 +0200 Subject: [PATCH 13/34] super_errors: cover bs_syntaxerr Invalid_bs_int_type, Invalid_bs_string_type, Invalid_bs_unwrap_type --- .../expected/bs_invalid_bs_int_type.res.expected | 9 +++++++++ .../expected/bs_invalid_bs_string_type.res.expected | 9 +++++++++ .../expected/bs_invalid_bs_unwrap_type.res.expected | 10 ++++++++++ .../super_errors/fixtures/bs_invalid_bs_int_type.res | 3 +++ .../fixtures/bs_invalid_bs_string_type.res | 3 +++ .../fixtures/bs_invalid_bs_unwrap_type.res | 3 +++ 6 files changed, 37 insertions(+) create mode 100644 tests/build_tests/super_errors/expected/bs_invalid_bs_int_type.res.expected create mode 100644 tests/build_tests/super_errors/expected/bs_invalid_bs_string_type.res.expected create mode 100644 tests/build_tests/super_errors/expected/bs_invalid_bs_unwrap_type.res.expected create mode 100644 tests/build_tests/super_errors/fixtures/bs_invalid_bs_int_type.res create mode 100644 tests/build_tests/super_errors/fixtures/bs_invalid_bs_string_type.res create mode 100644 tests/build_tests/super_errors/fixtures/bs_invalid_bs_unwrap_type.res diff --git a/tests/build_tests/super_errors/expected/bs_invalid_bs_int_type.res.expected b/tests/build_tests/super_errors/expected/bs_invalid_bs_int_type.res.expected new file mode 100644 index 0000000000..b75b9d053a --- /dev/null +++ b/tests/build_tests/super_errors/expected/bs_invalid_bs_int_type.res.expected @@ -0,0 +1,9 @@ + + We've found a bug for you! + /.../fixtures/bs_invalid_bs_int_type.res:1:18-25 + + 1 │ external f: @int [#A(int)] => unit = "f" + 2 │ + 3 │ let _ = f(#A(1)) + + Not a valid type for %@int \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/bs_invalid_bs_string_type.res.expected b/tests/build_tests/super_errors/expected/bs_invalid_bs_string_type.res.expected new file mode 100644 index 0000000000..97588a15fb --- /dev/null +++ b/tests/build_tests/super_errors/expected/bs_invalid_bs_string_type.res.expected @@ -0,0 +1,9 @@ + + We've found a bug for you! + /.../fixtures/bs_invalid_bs_string_type.res:1:21-33 + + 1 │ external f: @string [#A | #B(int)] => unit = "f" + 2 │ + 3 │ let _ = f(#A) + + Not a valid type for %@string \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/bs_invalid_bs_unwrap_type.res.expected b/tests/build_tests/super_errors/expected/bs_invalid_bs_unwrap_type.res.expected new file mode 100644 index 0000000000..00e23444fb --- /dev/null +++ b/tests/build_tests/super_errors/expected/bs_invalid_bs_unwrap_type.res.expected @@ -0,0 +1,10 @@ + + We've found a bug for you! + /.../fixtures/bs_invalid_bs_unwrap_type.res:1:21-23 + + 1 │ external f: @unwrap int => unit = "f" + 2 │ + 3 │ let _ = f(1) + + Not a valid type for %@unwrap. Type must be an inline variant (closed), and +each constructor must have an argument. \ No newline at end of file diff --git a/tests/build_tests/super_errors/fixtures/bs_invalid_bs_int_type.res b/tests/build_tests/super_errors/fixtures/bs_invalid_bs_int_type.res new file mode 100644 index 0000000000..e4da33de2d --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/bs_invalid_bs_int_type.res @@ -0,0 +1,3 @@ +external f: @int [#A(int)] => unit = "f" + +let _ = f(#A(1)) diff --git a/tests/build_tests/super_errors/fixtures/bs_invalid_bs_string_type.res b/tests/build_tests/super_errors/fixtures/bs_invalid_bs_string_type.res new file mode 100644 index 0000000000..6af4b33034 --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/bs_invalid_bs_string_type.res @@ -0,0 +1,3 @@ +external f: @string [#A | #B(int)] => unit = "f" + +let _ = f(#A) diff --git a/tests/build_tests/super_errors/fixtures/bs_invalid_bs_unwrap_type.res b/tests/build_tests/super_errors/fixtures/bs_invalid_bs_unwrap_type.res new file mode 100644 index 0000000000..6afd310c29 --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/bs_invalid_bs_unwrap_type.res @@ -0,0 +1,3 @@ +external f: @unwrap int => unit = "f" + +let _ = f(1) From 014aa81a8aca9bc0825df519e3270a1fb360e215 Mon Sep 17 00:00:00 2001 From: Jono Prest Date: Tue, 19 May 2026 15:18:53 +0200 Subject: [PATCH 14/34] super_errors: cover bs_syntaxerr Conflict_attributes --- .../expected/bs_conflict_attributes.res.expected | 9 +++++++++ .../super_errors/fixtures/bs_conflict_attributes.res | 3 +++ 2 files changed, 12 insertions(+) create mode 100644 tests/build_tests/super_errors/expected/bs_conflict_attributes.res.expected create mode 100644 tests/build_tests/super_errors/fixtures/bs_conflict_attributes.res diff --git a/tests/build_tests/super_errors/expected/bs_conflict_attributes.res.expected b/tests/build_tests/super_errors/expected/bs_conflict_attributes.res.expected new file mode 100644 index 0000000000..13e9ed3e72 --- /dev/null +++ b/tests/build_tests/super_errors/expected/bs_conflict_attributes.res.expected @@ -0,0 +1,9 @@ + + We've found a bug for you! + /.../fixtures/bs_conflict_attributes.res:1:21-24 + + 1 │ external f: @string @int [#A | #B] => unit = "f" + 2 │ + 3 │ let _ = f(#A) + + conflicting attributes \ No newline at end of file diff --git a/tests/build_tests/super_errors/fixtures/bs_conflict_attributes.res b/tests/build_tests/super_errors/fixtures/bs_conflict_attributes.res new file mode 100644 index 0000000000..173eaf7af5 --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/bs_conflict_attributes.res @@ -0,0 +1,3 @@ +external f: @string @int [#A | #B] => unit = "f" + +let _ = f(#A) From f005778bd647a961b7cf1753fb6159724da9e304 Mon Sep 17 00:00:00 2001 From: Jono Prest Date: Tue, 19 May 2026 15:21:27 +0200 Subject: [PATCH 15/34] super_errors: cover bs_syntaxerr Expect_string/int_literal and includemod Module_types, Extension_constructors --- .../bs_expect_int_literal.res.expected | 9 ++++++ .../bs_expect_string_literal.res.expected | 9 ++++++ ...tension_constructors_mismatch.res.expected | 31 ++++++++++++++++++ ...include_module_types_mismatch.res.expected | 32 +++++++++++++++++++ .../fixtures/bs_expect_int_literal.res | 3 ++ .../fixtures/bs_expect_string_literal.res | 3 ++ ...nclude_extension_constructors_mismatch.res | 7 ++++ .../include_module_types_mismatch.res | 13 ++++++++ 8 files changed, 107 insertions(+) create mode 100644 tests/build_tests/super_errors/expected/bs_expect_int_literal.res.expected create mode 100644 tests/build_tests/super_errors/expected/bs_expect_string_literal.res.expected create mode 100644 tests/build_tests/super_errors/expected/include_extension_constructors_mismatch.res.expected create mode 100644 tests/build_tests/super_errors/expected/include_module_types_mismatch.res.expected create mode 100644 tests/build_tests/super_errors/fixtures/bs_expect_int_literal.res create mode 100644 tests/build_tests/super_errors/fixtures/bs_expect_string_literal.res create mode 100644 tests/build_tests/super_errors/fixtures/include_extension_constructors_mismatch.res create mode 100644 tests/build_tests/super_errors/fixtures/include_module_types_mismatch.res diff --git a/tests/build_tests/super_errors/expected/bs_expect_int_literal.res.expected b/tests/build_tests/super_errors/expected/bs_expect_int_literal.res.expected new file mode 100644 index 0000000000..6b22692092 --- /dev/null +++ b/tests/build_tests/super_errors/expected/bs_expect_int_literal.res.expected @@ -0,0 +1,9 @@ + + We've found a bug for you! + /.../fixtures/bs_expect_int_literal.res:1:19-21 + + 1 │ external f: @int [@as("hello") #A | #B] => unit = "f" + 2 │ + 3 │ let _ = f(#A) + + expect int literal \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/bs_expect_string_literal.res.expected b/tests/build_tests/super_errors/expected/bs_expect_string_literal.res.expected new file mode 100644 index 0000000000..bcda2f3f99 --- /dev/null +++ b/tests/build_tests/super_errors/expected/bs_expect_string_literal.res.expected @@ -0,0 +1,9 @@ + + We've found a bug for you! + /.../fixtures/bs_expect_string_literal.res:1:22-24 + + 1 │ external f: @string [@as(1) #A | #B] => unit = "f" + 2 │ + 3 │ let _ = f(#A) + + expect string literal \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/include_extension_constructors_mismatch.res.expected b/tests/build_tests/super_errors/expected/include_extension_constructors_mismatch.res.expected new file mode 100644 index 0000000000..871f0add4d --- /dev/null +++ b/tests/build_tests/super_errors/expected/include_extension_constructors_mismatch.res.expected @@ -0,0 +1,31 @@ + + We've found a bug for you! + /.../fixtures/include_extension_constructors_mismatch.res:4:5-7:1 + + 2 │ type t = .. + 3 │ type t += E(int) + 4 │ } = { + 5 │  type t = .. + 6 │  type t += E(string) + 7 │ } + 8 │ + + Signature mismatch: + Modules do not match: + { + type t = .. + type t += E(string) +} + is not included in + { + type t = .. + type t += E(int) +} + Extension declarations do not match: + type t += E(string) + is not included in + type t += E(int) + /.../fixtures/include_extension_constructors_mismatch.res:3:13-18: + Expected declaration + /.../fixtures/include_extension_constructors_mismatch.res:6:13-21: + Actual declaration \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/include_module_types_mismatch.res.expected b/tests/build_tests/super_errors/expected/include_module_types_mismatch.res.expected new file mode 100644 index 0000000000..7ff5e9513d --- /dev/null +++ b/tests/build_tests/super_errors/expected/include_module_types_mismatch.res.expected @@ -0,0 +1,32 @@ + + We've found a bug for you! + /.../fixtures/include_module_types_mismatch.res:9:19-13:1 + + 7 │ } + 8 │ + 9 │ module M: Outer = { + 10 │  module M = { + 11 │  let a = "wrong type" + 12 │  } + 13 │ } + 14 │ + + Signature mismatch: + Modules do not match: + { + module M: { + let a: string + } +} + is not included in + Outer + In module M: + Modules do not match: { + let a: string +} is not included in Inner + In module M: + Values do not match: let a: string is not included in let a: int + /.../fixtures/include_module_types_mismatch.res:2:3-12: + Expected declaration + /.../fixtures/include_module_types_mismatch.res:11:9: + Actual declaration \ No newline at end of file diff --git a/tests/build_tests/super_errors/fixtures/bs_expect_int_literal.res b/tests/build_tests/super_errors/fixtures/bs_expect_int_literal.res new file mode 100644 index 0000000000..0caed57cd1 --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/bs_expect_int_literal.res @@ -0,0 +1,3 @@ +external f: @int [@as("hello") #A | #B] => unit = "f" + +let _ = f(#A) diff --git a/tests/build_tests/super_errors/fixtures/bs_expect_string_literal.res b/tests/build_tests/super_errors/fixtures/bs_expect_string_literal.res new file mode 100644 index 0000000000..348dc161a5 --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/bs_expect_string_literal.res @@ -0,0 +1,3 @@ +external f: @string [@as(1) #A | #B] => unit = "f" + +let _ = f(#A) diff --git a/tests/build_tests/super_errors/fixtures/include_extension_constructors_mismatch.res b/tests/build_tests/super_errors/fixtures/include_extension_constructors_mismatch.res new file mode 100644 index 0000000000..258ab9b637 --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/include_extension_constructors_mismatch.res @@ -0,0 +1,7 @@ +module M: { + type t = .. + type t += E(int) +} = { + type t = .. + type t += E(string) +} diff --git a/tests/build_tests/super_errors/fixtures/include_module_types_mismatch.res b/tests/build_tests/super_errors/fixtures/include_module_types_mismatch.res new file mode 100644 index 0000000000..6ff4b2c077 --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/include_module_types_mismatch.res @@ -0,0 +1,13 @@ +module type Inner = { + let a: int +} + +module type Outer = { + module M: Inner +} + +module M: Outer = { + module M = { + let a = "wrong type" + } +} From 729a9a273748123c0df2e06229dc08415820cf09 Mon Sep 17 00:00:00 2001 From: Jono Prest Date: Tue, 19 May 2026 15:36:54 +0200 Subject: [PATCH 16/34] super_errors: cover includemod Modtype_infos and typedecl Unbound_type_var_ext --- ...nclude_modtype_infos_mismatch.res.expected | 49 +++++++++++++++++++ .../unbound_type_var_extension.res.expected | 10 ++++ .../include_modtype_infos_mismatch.res | 9 ++++ .../fixtures/unbound_type_var_extension.res | 3 ++ 4 files changed, 71 insertions(+) create mode 100644 tests/build_tests/super_errors/expected/include_modtype_infos_mismatch.res.expected create mode 100644 tests/build_tests/super_errors/expected/unbound_type_var_extension.res.expected create mode 100644 tests/build_tests/super_errors/fixtures/include_modtype_infos_mismatch.res create mode 100644 tests/build_tests/super_errors/fixtures/unbound_type_var_extension.res diff --git a/tests/build_tests/super_errors/expected/include_modtype_infos_mismatch.res.expected b/tests/build_tests/super_errors/expected/include_modtype_infos_mismatch.res.expected new file mode 100644 index 0000000000..e5b33c1377 --- /dev/null +++ b/tests/build_tests/super_errors/expected/include_modtype_infos_mismatch.res.expected @@ -0,0 +1,49 @@ + + We've found a bug for you! + /.../fixtures/include_modtype_infos_mismatch.res:5:5-9:1 + + 3 │ let x: int + 4 │ } + 5 │ } = { + 6 │  module type T = { + 7 │  let x: string + 8 │  } + 9 │ } + 10 │ + + Signature mismatch: + Modules do not match: + { + module type T = { + let x: string + } +} + is not included in + { + module type T = { + let x: int + } +} + Module type declarations do not match: + module type T = { + let x: string +} + does not match + module type T = { + let x: int +} + At position module type T = + Modules do not match: + { + let x: string +} + is not included in + { + let x: int +} + At position module type T = + Values do not match: let x: string is not included in let x: int + /.../fixtures/include_modtype_infos_mismatch.res:3:5-14: + Expected declaration + /.../fixtures/include_modtype_infos_mismatch.res:7:5-17: + Actual declaration \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/unbound_type_var_extension.res.expected b/tests/build_tests/super_errors/expected/unbound_type_var_extension.res.expected new file mode 100644 index 0000000000..703fbe7542 --- /dev/null +++ b/tests/build_tests/super_errors/expected/unbound_type_var_extension.res.expected @@ -0,0 +1,10 @@ + + We've found a bug for you! + /.../fixtures/unbound_type_var_extension.res:3:14 + + 1 │ type t = .. + 2 │ + 3 │ type t += E('a) + 4 │ + + Unbound type parameter 'a \ No newline at end of file diff --git a/tests/build_tests/super_errors/fixtures/include_modtype_infos_mismatch.res b/tests/build_tests/super_errors/fixtures/include_modtype_infos_mismatch.res new file mode 100644 index 0000000000..62fc3a0f0d --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/include_modtype_infos_mismatch.res @@ -0,0 +1,9 @@ +module M: { + module type T = { + let x: int + } +} = { + module type T = { + let x: string + } +} diff --git a/tests/build_tests/super_errors/fixtures/unbound_type_var_extension.res b/tests/build_tests/super_errors/fixtures/unbound_type_var_extension.res new file mode 100644 index 0000000000..a390886422 --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/unbound_type_var_extension.res @@ -0,0 +1,3 @@ +type t = .. + +type t += E('a) From 2c247ec53d2b2360ca943ef26cafcd9ae5739fc3 Mon Sep 17 00:00:00 2001 From: Jono Prest Date: Tue, 19 May 2026 15:39:49 +0200 Subject: [PATCH 17/34] super_errors: cover typetexp Method_mismatch and typedecl Bad_immediate_attribute --- .../expected/bad_immediate_attribute.res.expected | 10 ++++++++++ .../expected/object_method_mismatch.res.expected | 8 ++++++++ .../super_errors/fixtures/bad_immediate_attribute.res | 2 ++ .../super_errors/fixtures/object_method_mismatch.res | 1 + 4 files changed, 21 insertions(+) create mode 100644 tests/build_tests/super_errors/expected/bad_immediate_attribute.res.expected create mode 100644 tests/build_tests/super_errors/expected/object_method_mismatch.res.expected create mode 100644 tests/build_tests/super_errors/fixtures/bad_immediate_attribute.res create mode 100644 tests/build_tests/super_errors/fixtures/object_method_mismatch.res diff --git a/tests/build_tests/super_errors/expected/bad_immediate_attribute.res.expected b/tests/build_tests/super_errors/expected/bad_immediate_attribute.res.expected new file mode 100644 index 0000000000..6911f72ec2 --- /dev/null +++ b/tests/build_tests/super_errors/expected/bad_immediate_attribute.res.expected @@ -0,0 +1,10 @@ + + We've found a bug for you! + /.../fixtures/bad_immediate_attribute.res:2:1-15 + + 1 │ @immediate + 2 │ type t = string + 3 │ + + Types marked with the immediate attribute must be + non-pointer types like int or bool \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/object_method_mismatch.res.expected b/tests/build_tests/super_errors/expected/object_method_mismatch.res.expected new file mode 100644 index 0000000000..f051de4bd3 --- /dev/null +++ b/tests/build_tests/super_errors/expected/object_method_mismatch.res.expected @@ -0,0 +1,8 @@ + + We've found a bug for you! + /.../fixtures/object_method_mismatch.res:1:26-31 + + 1 │ type t = {"x": int, "x": string} + 2 │ + + Method 'x' has type string, which should be int \ No newline at end of file diff --git a/tests/build_tests/super_errors/fixtures/bad_immediate_attribute.res b/tests/build_tests/super_errors/fixtures/bad_immediate_attribute.res new file mode 100644 index 0000000000..a32a1b1c5a --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/bad_immediate_attribute.res @@ -0,0 +1,2 @@ +@immediate +type t = string diff --git a/tests/build_tests/super_errors/fixtures/object_method_mismatch.res b/tests/build_tests/super_errors/fixtures/object_method_mismatch.res new file mode 100644 index 0000000000..2b85cb243a --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/object_method_mismatch.res @@ -0,0 +1 @@ +type t = {"x": int, "x": string} From 70646054988f45939752ca33438f513363304489 Mon Sep 17 00:00:00 2001 From: Jono Prest Date: Tue, 19 May 2026 15:41:57 +0200 Subject: [PATCH 18/34] super_errors: cover typetexp Multiple_constraints_on_type --- .../expected/multiple_constraints_on_type.res.expected | 10 ++++++++++ .../fixtures/multiple_constraints_on_type.res | 5 +++++ 2 files changed, 15 insertions(+) create mode 100644 tests/build_tests/super_errors/expected/multiple_constraints_on_type.res.expected create mode 100644 tests/build_tests/super_errors/fixtures/multiple_constraints_on_type.res diff --git a/tests/build_tests/super_errors/expected/multiple_constraints_on_type.res.expected b/tests/build_tests/super_errors/expected/multiple_constraints_on_type.res.expected new file mode 100644 index 0000000000..fffc502cf5 --- /dev/null +++ b/tests/build_tests/super_errors/expected/multiple_constraints_on_type.res.expected @@ -0,0 +1,10 @@ + + We've found a bug for you! + /.../fixtures/multiple_constraints_on_type.res:5:13-59 + + 3 │ } + 4 │ + 5 │ let f = (m: module(S with type t = int and type t = string)) => m + 6 │ + + Multiple constraints for type t \ No newline at end of file diff --git a/tests/build_tests/super_errors/fixtures/multiple_constraints_on_type.res b/tests/build_tests/super_errors/fixtures/multiple_constraints_on_type.res new file mode 100644 index 0000000000..b7855df4e0 --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/multiple_constraints_on_type.res @@ -0,0 +1,5 @@ +module type S = { + type t +} + +let f = (m: module(S with type t = int and type t = string)) => m From 7ccb84e7d2dfd2984ba5f1870e194659de281d0f Mon Sep 17 00:00:00 2001 From: Jono Prest Date: Tue, 19 May 2026 15:50:22 +0200 Subject: [PATCH 19/34] super_errors: cover typetexp Access_functor_as_structure, Constructor_mismatch, typedecl Inconsistent_constraint --- .../expected/access_functor_as_structure.res.expected | 10 ++++++++++ .../expected/inconsistent_constraint.res.expected | 9 +++++++++ .../polyvariant_constructor_mismatch.res.expected | 9 +++++++++ .../fixtures/access_functor_as_structure.res | 9 +++++++++ .../super_errors/fixtures/inconsistent_constraint.res | 1 + .../fixtures/polyvariant_constructor_mismatch.res | 1 + 6 files changed, 39 insertions(+) create mode 100644 tests/build_tests/super_errors/expected/access_functor_as_structure.res.expected create mode 100644 tests/build_tests/super_errors/expected/inconsistent_constraint.res.expected create mode 100644 tests/build_tests/super_errors/expected/polyvariant_constructor_mismatch.res.expected create mode 100644 tests/build_tests/super_errors/fixtures/access_functor_as_structure.res create mode 100644 tests/build_tests/super_errors/fixtures/inconsistent_constraint.res create mode 100644 tests/build_tests/super_errors/fixtures/polyvariant_constructor_mismatch.res diff --git a/tests/build_tests/super_errors/expected/access_functor_as_structure.res.expected b/tests/build_tests/super_errors/expected/access_functor_as_structure.res.expected new file mode 100644 index 0000000000..6430aad2a7 --- /dev/null +++ b/tests/build_tests/super_errors/expected/access_functor_as_structure.res.expected @@ -0,0 +1,10 @@ + + We've found a bug for you! + /.../fixtures/access_functor_as_structure.res:9:8-10 + + 7 │ } + 8 │ + 9 │ let _: F.v = 1 + 10 │ + + The module F is a functor, not a structure \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/inconsistent_constraint.res.expected b/tests/build_tests/super_errors/expected/inconsistent_constraint.res.expected new file mode 100644 index 0000000000..71a930f4b9 --- /dev/null +++ b/tests/build_tests/super_errors/expected/inconsistent_constraint.res.expected @@ -0,0 +1,9 @@ + + We've found a bug for you! + /.../fixtures/inconsistent_constraint.res:1:37-58 + + 1 │ type t<'a> = 'a constraint 'a = int constraint 'a = string + 2 │ + + The type constraints are not consistent. +Type int is not compatible with type string \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/polyvariant_constructor_mismatch.res.expected b/tests/build_tests/super_errors/expected/polyvariant_constructor_mismatch.res.expected new file mode 100644 index 0000000000..add7ea4c7a --- /dev/null +++ b/tests/build_tests/super_errors/expected/polyvariant_constructor_mismatch.res.expected @@ -0,0 +1,9 @@ + + We've found a bug for you! + /.../fixtures/polyvariant_constructor_mismatch.res:1:10-30 + + 1 │ type t = [#A(int) | #A(string)] + 2 │ + + This variant type contains a constructor [#A(string)] which should be + [#A(int)] \ No newline at end of file diff --git a/tests/build_tests/super_errors/fixtures/access_functor_as_structure.res b/tests/build_tests/super_errors/fixtures/access_functor_as_structure.res new file mode 100644 index 0000000000..5447959aca --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/access_functor_as_structure.res @@ -0,0 +1,9 @@ +module F = ( + M: { + let x: int + }, +) => { + let v = M.x +} + +let _: F.v = 1 diff --git a/tests/build_tests/super_errors/fixtures/inconsistent_constraint.res b/tests/build_tests/super_errors/fixtures/inconsistent_constraint.res new file mode 100644 index 0000000000..e670b2bcc7 --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/inconsistent_constraint.res @@ -0,0 +1 @@ +type t<'a> = 'a constraint 'a = int constraint 'a = string diff --git a/tests/build_tests/super_errors/fixtures/polyvariant_constructor_mismatch.res b/tests/build_tests/super_errors/fixtures/polyvariant_constructor_mismatch.res new file mode 100644 index 0000000000..4ef263d07a --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/polyvariant_constructor_mismatch.res @@ -0,0 +1 @@ +type t = [#A(int) | #A(string)] From c7e530924284ea6a3c06ff89ed67fb9d4ee5c4b1 Mon Sep 17 00:00:00 2001 From: Jono Prest Date: Tue, 19 May 2026 15:52:52 +0200 Subject: [PATCH 20/34] super_errors: cover typemod Structure_expected via opening a functor --- .../expected/open_functor.res.expected | 17 +++++++++++++++++ .../super_errors/fixtures/open_functor.res | 9 +++++++++ 2 files changed, 26 insertions(+) create mode 100644 tests/build_tests/super_errors/expected/open_functor.res.expected create mode 100644 tests/build_tests/super_errors/fixtures/open_functor.res diff --git a/tests/build_tests/super_errors/expected/open_functor.res.expected b/tests/build_tests/super_errors/expected/open_functor.res.expected new file mode 100644 index 0000000000..bc3e5a1e99 --- /dev/null +++ b/tests/build_tests/super_errors/expected/open_functor.res.expected @@ -0,0 +1,17 @@ + + We've found a bug for you! + /.../fixtures/open_functor.res:9:6 + + 7 │ } + 8 │ + 9 │ open F + 10 │ + + This module is not a structure; it has type + ( + M: { + let v: int + }, +) => { + let doubled: int +} \ No newline at end of file diff --git a/tests/build_tests/super_errors/fixtures/open_functor.res b/tests/build_tests/super_errors/fixtures/open_functor.res new file mode 100644 index 0000000000..f8ec7d0a4e --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/open_functor.res @@ -0,0 +1,9 @@ +module F = ( + M: { + let v: int + }, +) => { + let doubled = M.v * 2 +} + +open F From 45be027c8587958102b46c14d49d62a5ae6ab6af Mon Sep 17 00:00:00 2001 From: Jono Prest Date: Tue, 19 May 2026 15:55:09 +0200 Subject: [PATCH 21/34] super_errors: cover typecore Constructor_arity_mismatch and Private_type construction --- .../expected/constructor_arity_mismatch.res.expected | 11 +++++++++++ .../expected/private_type_construction.res.expected | 10 ++++++++++ .../fixtures/constructor_arity_mismatch.res | 7 +++++++ .../fixtures/private_type_construction.res | 9 +++++++++ 4 files changed, 37 insertions(+) create mode 100644 tests/build_tests/super_errors/expected/constructor_arity_mismatch.res.expected create mode 100644 tests/build_tests/super_errors/expected/private_type_construction.res.expected create mode 100644 tests/build_tests/super_errors/fixtures/constructor_arity_mismatch.res create mode 100644 tests/build_tests/super_errors/fixtures/private_type_construction.res diff --git a/tests/build_tests/super_errors/expected/constructor_arity_mismatch.res.expected b/tests/build_tests/super_errors/expected/constructor_arity_mismatch.res.expected new file mode 100644 index 0000000000..2aaf35114c --- /dev/null +++ b/tests/build_tests/super_errors/expected/constructor_arity_mismatch.res.expected @@ -0,0 +1,11 @@ + + We've found a bug for you! + /.../fixtures/constructor_arity_mismatch.res:5:9-15 + + 3 │ | Single(string) + 4 │ + 5 │ let x = Pair(1) + 6 │ + 7 │ let y = Single(1, 2) + + This variant constructor Pair expects 2 arguments, but it's only being passed 1. \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/private_type_construction.res.expected b/tests/build_tests/super_errors/expected/private_type_construction.res.expected new file mode 100644 index 0000000000..860fb9effa --- /dev/null +++ b/tests/build_tests/super_errors/expected/private_type_construction.res.expected @@ -0,0 +1,10 @@ + + We've found a bug for you! + /.../fixtures/private_type_construction.res:9:9-17 + + 7 │ } + 8 │ + 9 │ let v = M.Wrap(1) + 10 │ + + Cannot create values of the private type M.t \ No newline at end of file diff --git a/tests/build_tests/super_errors/fixtures/constructor_arity_mismatch.res b/tests/build_tests/super_errors/fixtures/constructor_arity_mismatch.res new file mode 100644 index 0000000000..85f8be5598 --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/constructor_arity_mismatch.res @@ -0,0 +1,7 @@ +type t = + | Pair(int, int) + | Single(string) + +let x = Pair(1) + +let y = Single(1, 2) diff --git a/tests/build_tests/super_errors/fixtures/private_type_construction.res b/tests/build_tests/super_errors/fixtures/private_type_construction.res new file mode 100644 index 0000000000..feedce77bc --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/private_type_construction.res @@ -0,0 +1,9 @@ +module M: { + type t = private Wrap(int) + let make: int => t +} = { + type t = Wrap(int) + let make = v => Wrap(v) +} + +let v = M.Wrap(1) From 64696e3588cb479a17d28e1ec24fc684816561b9 Mon Sep 17 00:00:00 2001 From: Jono Prest Date: Tue, 19 May 2026 16:08:51 +0200 Subject: [PATCH 22/34] super_errors: cover typemod Not_a_packed_module, typecore Cannot_infer_signature, typedecl Bad_variance --- .../super_errors/expected/bad_variance.res.expected | 10 ++++++++++ .../expected/cannot_infer_signature.res.expected | 10 ++++++++++ .../expected/not_a_packed_module.res.expected | 11 +++++++++++ .../super_errors/fixtures/bad_variance.res | 1 + .../super_errors/fixtures/cannot_infer_signature.res | 4 ++++ .../super_errors/fixtures/not_a_packed_module.res | 3 +++ 6 files changed, 39 insertions(+) create mode 100644 tests/build_tests/super_errors/expected/bad_variance.res.expected create mode 100644 tests/build_tests/super_errors/expected/cannot_infer_signature.res.expected create mode 100644 tests/build_tests/super_errors/expected/not_a_packed_module.res.expected create mode 100644 tests/build_tests/super_errors/fixtures/bad_variance.res create mode 100644 tests/build_tests/super_errors/fixtures/cannot_infer_signature.res create mode 100644 tests/build_tests/super_errors/fixtures/not_a_packed_module.res diff --git a/tests/build_tests/super_errors/expected/bad_variance.res.expected b/tests/build_tests/super_errors/expected/bad_variance.res.expected new file mode 100644 index 0000000000..def96c9f42 --- /dev/null +++ b/tests/build_tests/super_errors/expected/bad_variance.res.expected @@ -0,0 +1,10 @@ + + We've found a bug for you! + /.../fixtures/bad_variance.res:1:1-24 + + 1 │ type t<+'a> = 'a => unit + 2 │ + + In this definition, expected parameter variances are not satisfied. + The 1st type parameter was expected to be covariant, + but it is injective contravariant. \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/cannot_infer_signature.res.expected b/tests/build_tests/super_errors/expected/cannot_infer_signature.res.expected new file mode 100644 index 0000000000..f3055bd02a --- /dev/null +++ b/tests/build_tests/super_errors/expected/cannot_infer_signature.res.expected @@ -0,0 +1,10 @@ + + We've found a bug for you! + /.../fixtures/cannot_infer_signature.res:2:14-22 + + 1 │ let extract = m => { + 2 │ module M = unpack(m) + 3 │ M + 4 │ } + + The signature for this packaged module couldn't be inferred. \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/not_a_packed_module.res.expected b/tests/build_tests/super_errors/expected/not_a_packed_module.res.expected new file mode 100644 index 0000000000..378b767056 --- /dev/null +++ b/tests/build_tests/super_errors/expected/not_a_packed_module.res.expected @@ -0,0 +1,11 @@ + + We've found a bug for you! + /.../fixtures/not_a_packed_module.res:3:12-20 + + 1 │ let x = 1 + 2 │ + 3 │ module M = unpack(x) + 4 │ + + This expression is not a packed module. It has type +int \ No newline at end of file diff --git a/tests/build_tests/super_errors/fixtures/bad_variance.res b/tests/build_tests/super_errors/fixtures/bad_variance.res new file mode 100644 index 0000000000..28e6742c7f --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/bad_variance.res @@ -0,0 +1 @@ +type t<+'a> = 'a => unit diff --git a/tests/build_tests/super_errors/fixtures/cannot_infer_signature.res b/tests/build_tests/super_errors/fixtures/cannot_infer_signature.res new file mode 100644 index 0000000000..d44822b978 --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/cannot_infer_signature.res @@ -0,0 +1,4 @@ +let extract = m => { + module M = unpack(m) + M +} diff --git a/tests/build_tests/super_errors/fixtures/not_a_packed_module.res b/tests/build_tests/super_errors/fixtures/not_a_packed_module.res new file mode 100644 index 0000000000..483cb12f92 --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/not_a_packed_module.res @@ -0,0 +1,3 @@ +let x = 1 + +module M = unpack(x) From 3504be63c407bd1c80850cfbed1790db8ac838f1 Mon Sep 17 00:00:00 2001 From: Jono Prest Date: Tue, 19 May 2026 16:12:43 +0200 Subject: [PATCH 23/34] super_errors: cover typedecl Bad_unboxed_attribute many-fields and extensible cases --- .../bad_unboxed_attribute_extensible.res.expected | 10 ++++++++++ .../bad_unboxed_attribute_many_fields.res.expected | 9 +++++++++ .../fixtures/bad_unboxed_attribute_extensible.res | 2 ++ .../fixtures/bad_unboxed_attribute_many_fields.res | 2 ++ 4 files changed, 23 insertions(+) create mode 100644 tests/build_tests/super_errors/expected/bad_unboxed_attribute_extensible.res.expected create mode 100644 tests/build_tests/super_errors/expected/bad_unboxed_attribute_many_fields.res.expected create mode 100644 tests/build_tests/super_errors/fixtures/bad_unboxed_attribute_extensible.res create mode 100644 tests/build_tests/super_errors/fixtures/bad_unboxed_attribute_many_fields.res diff --git a/tests/build_tests/super_errors/expected/bad_unboxed_attribute_extensible.res.expected b/tests/build_tests/super_errors/expected/bad_unboxed_attribute_extensible.res.expected new file mode 100644 index 0000000000..09789923fc --- /dev/null +++ b/tests/build_tests/super_errors/expected/bad_unboxed_attribute_extensible.res.expected @@ -0,0 +1,10 @@ + + We've found a bug for you! + /.../fixtures/bad_unboxed_attribute_extensible.res:2:1-11 + + 1 │ @unboxed + 2 │ type t = .. + 3 │ + + This type cannot be unboxed because + extensible variant types cannot be unboxed. \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/bad_unboxed_attribute_many_fields.res.expected b/tests/build_tests/super_errors/expected/bad_unboxed_attribute_many_fields.res.expected new file mode 100644 index 0000000000..2eb9c42dcb --- /dev/null +++ b/tests/build_tests/super_errors/expected/bad_unboxed_attribute_many_fields.res.expected @@ -0,0 +1,9 @@ + + We've found a bug for you! + /.../fixtures/bad_unboxed_attribute_many_fields.res:2:1-25 + + 1 │ @unboxed + 2 │ type t = {a: int, b: int} + 3 │ + + This type cannot be unboxed because it has more than one field. \ No newline at end of file diff --git a/tests/build_tests/super_errors/fixtures/bad_unboxed_attribute_extensible.res b/tests/build_tests/super_errors/fixtures/bad_unboxed_attribute_extensible.res new file mode 100644 index 0000000000..5f88b51ea2 --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/bad_unboxed_attribute_extensible.res @@ -0,0 +1,2 @@ +@unboxed +type t = .. diff --git a/tests/build_tests/super_errors/fixtures/bad_unboxed_attribute_many_fields.res b/tests/build_tests/super_errors/fixtures/bad_unboxed_attribute_many_fields.res new file mode 100644 index 0000000000..a49e4305ac --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/bad_unboxed_attribute_many_fields.res @@ -0,0 +1,2 @@ +@unboxed +type t = {a: int, b: int} From 619a40893c190de2f20a684db5e8a7cb4a1690bc Mon Sep 17 00:00:00 2001 From: Jono Prest Date: Tue, 19 May 2026 16:13:01 +0200 Subject: [PATCH 24/34] super_errors: cover typedecl Bad_variance contravariant case --- .../expected/bad_variance_contra.res.expected | 10 ++++++++++ .../super_errors/fixtures/bad_variance_contra.res | 1 + 2 files changed, 11 insertions(+) create mode 100644 tests/build_tests/super_errors/expected/bad_variance_contra.res.expected create mode 100644 tests/build_tests/super_errors/fixtures/bad_variance_contra.res diff --git a/tests/build_tests/super_errors/expected/bad_variance_contra.res.expected b/tests/build_tests/super_errors/expected/bad_variance_contra.res.expected new file mode 100644 index 0000000000..aec1b06e49 --- /dev/null +++ b/tests/build_tests/super_errors/expected/bad_variance_contra.res.expected @@ -0,0 +1,10 @@ + + We've found a bug for you! + /.../fixtures/bad_variance_contra.res:1:1-16 + + 1 │ type t<-'a> = 'a + 2 │ + + In this definition, expected parameter variances are not satisfied. + The 1st type parameter was expected to be contravariant, + but it is injective covariant. \ No newline at end of file diff --git a/tests/build_tests/super_errors/fixtures/bad_variance_contra.res b/tests/build_tests/super_errors/fixtures/bad_variance_contra.res new file mode 100644 index 0000000000..9af2e4df2f --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/bad_variance_contra.res @@ -0,0 +1 @@ +type t<-'a> = 'a From 1db2ee9ae161d7e94d35251b7715f2b4ff1813f9 Mon Sep 17 00:00:00 2001 From: Jono Prest Date: Tue, 19 May 2026 16:15:09 +0200 Subject: [PATCH 25/34] super_errors: cover typetexp Not_an_object and Opened_object via object inheritance --- .../object_inherit_not_an_object.res.expected | 10 ++++++++++ .../expected/object_inherit_opened.res.expected | 11 +++++++++++ .../fixtures/object_inherit_not_an_object.res | 3 +++ .../super_errors/fixtures/object_inherit_opened.res | 3 +++ 4 files changed, 27 insertions(+) create mode 100644 tests/build_tests/super_errors/expected/object_inherit_not_an_object.res.expected create mode 100644 tests/build_tests/super_errors/expected/object_inherit_opened.res.expected create mode 100644 tests/build_tests/super_errors/fixtures/object_inherit_not_an_object.res create mode 100644 tests/build_tests/super_errors/fixtures/object_inherit_opened.res diff --git a/tests/build_tests/super_errors/expected/object_inherit_not_an_object.res.expected b/tests/build_tests/super_errors/expected/object_inherit_not_an_object.res.expected new file mode 100644 index 0000000000..5ec585ee82 --- /dev/null +++ b/tests/build_tests/super_errors/expected/object_inherit_not_an_object.res.expected @@ -0,0 +1,10 @@ + + We've found a bug for you! + /.../fixtures/object_inherit_not_an_object.res:3:14 + + 1 │ type a = int + 2 │ + 3 │ type b = {...a, "x": int} + 4 │ + + The type int is not an object type \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/object_inherit_opened.res.expected b/tests/build_tests/super_errors/expected/object_inherit_opened.res.expected new file mode 100644 index 0000000000..9844cb5b02 --- /dev/null +++ b/tests/build_tests/super_errors/expected/object_inherit_opened.res.expected @@ -0,0 +1,11 @@ + + We've found a bug for you! + /.../fixtures/object_inherit_opened.res:3:14-18 + + 1 │ type a<'a> = {.."x": int} as 'a + 2 │ + 3 │ type b = {...a<'b>, "y": int} + 4 │ + + Illegal open object type +a \ No newline at end of file diff --git a/tests/build_tests/super_errors/fixtures/object_inherit_not_an_object.res b/tests/build_tests/super_errors/fixtures/object_inherit_not_an_object.res new file mode 100644 index 0000000000..4af370324c --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/object_inherit_not_an_object.res @@ -0,0 +1,3 @@ +type a = int + +type b = {...a, "x": int} diff --git a/tests/build_tests/super_errors/fixtures/object_inherit_opened.res b/tests/build_tests/super_errors/fixtures/object_inherit_opened.res new file mode 100644 index 0000000000..12af21b52b --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/object_inherit_opened.res @@ -0,0 +1,3 @@ +type a<'a> = {.."x": int} as 'a + +type b = {...a<'b>, "y": int} From 13ade3b99c0c2dc6996ff1b9374ed58159a9ca28 Mon Sep 17 00:00:00 2001 From: Jono Prest Date: Tue, 19 May 2026 16:17:32 +0200 Subject: [PATCH 26/34] super_errors: cover typedecl Definition_mismatch and typecore Constructor_arity_mismatch in pattern context --- .../constructor_arity_mismatch_pattern.res.expected | 11 +++++++++++ .../expected/definition_mismatch.res.expected | 9 +++++++++ .../fixtures/constructor_arity_mismatch_pattern.res | 6 ++++++ .../super_errors/fixtures/definition_mismatch.res | 1 + 4 files changed, 27 insertions(+) create mode 100644 tests/build_tests/super_errors/expected/constructor_arity_mismatch_pattern.res.expected create mode 100644 tests/build_tests/super_errors/expected/definition_mismatch.res.expected create mode 100644 tests/build_tests/super_errors/fixtures/constructor_arity_mismatch_pattern.res create mode 100644 tests/build_tests/super_errors/fixtures/definition_mismatch.res diff --git a/tests/build_tests/super_errors/expected/constructor_arity_mismatch_pattern.res.expected b/tests/build_tests/super_errors/expected/constructor_arity_mismatch_pattern.res.expected new file mode 100644 index 0000000000..93fc65eebb --- /dev/null +++ b/tests/build_tests/super_errors/expected/constructor_arity_mismatch_pattern.res.expected @@ -0,0 +1,11 @@ + + We've found a bug for you! + /.../fixtures/constructor_arity_mismatch_pattern.res:5:5-11 + + 3 │ let f = x => + 4 │ switch x { + 5 │ | Pair(a) => a + 6 │ } + 7 │ + + This variant constructor Pair expects 2 arguments, but it's only being passed 1. \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/definition_mismatch.res.expected b/tests/build_tests/super_errors/expected/definition_mismatch.res.expected new file mode 100644 index 0000000000..1d506f55c7 --- /dev/null +++ b/tests/build_tests/super_errors/expected/definition_mismatch.res.expected @@ -0,0 +1,9 @@ + + We've found a bug for you! + /.../fixtures/definition_mismatch.res:1:1-26 + + 1 │ type t = list = Empty + 2 │ + + This variant or record definition does not match that of type list + They have different arities. \ No newline at end of file diff --git a/tests/build_tests/super_errors/fixtures/constructor_arity_mismatch_pattern.res b/tests/build_tests/super_errors/fixtures/constructor_arity_mismatch_pattern.res new file mode 100644 index 0000000000..aa917b2cd9 --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/constructor_arity_mismatch_pattern.res @@ -0,0 +1,6 @@ +type t = Pair(int, int) + +let f = x => + switch x { + | Pair(a) => a + } diff --git a/tests/build_tests/super_errors/fixtures/definition_mismatch.res b/tests/build_tests/super_errors/fixtures/definition_mismatch.res new file mode 100644 index 0000000000..8c9ad1a82d --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/definition_mismatch.res @@ -0,0 +1 @@ +type t = list = Empty From f6f39737c88f5c2f827bc2f62e4673f335e04be6 Mon Sep 17 00:00:00 2001 From: Jono Prest Date: Tue, 19 May 2026 16:19:26 +0200 Subject: [PATCH 27/34] super_errors: cover typedecl Invalid_attribute for @notUndefined on non-abstract type --- .../invalid_attribute_not_undefined.res.expected | 9 +++++++++ .../fixtures/invalid_attribute_not_undefined.res | 2 ++ 2 files changed, 11 insertions(+) create mode 100644 tests/build_tests/super_errors/expected/invalid_attribute_not_undefined.res.expected create mode 100644 tests/build_tests/super_errors/fixtures/invalid_attribute_not_undefined.res diff --git a/tests/build_tests/super_errors/expected/invalid_attribute_not_undefined.res.expected b/tests/build_tests/super_errors/expected/invalid_attribute_not_undefined.res.expected new file mode 100644 index 0000000000..fe75ea5d4e --- /dev/null +++ b/tests/build_tests/super_errors/expected/invalid_attribute_not_undefined.res.expected @@ -0,0 +1,9 @@ + + We've found a bug for you! + /.../fixtures/invalid_attribute_not_undefined.res:2:1-12 + + 1 │ @notUndefined + 2 │ type t = int + 3 │ + + @notUndefined can only be used on abstract types \ No newline at end of file diff --git a/tests/build_tests/super_errors/fixtures/invalid_attribute_not_undefined.res b/tests/build_tests/super_errors/fixtures/invalid_attribute_not_undefined.res new file mode 100644 index 0000000000..cdd9eb9de1 --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/invalid_attribute_not_undefined.res @@ -0,0 +1,2 @@ +@notUndefined +type t = int From 3de9e9f5f608b85353bb12beec06f1b150659c13 Mon Sep 17 00:00:00 2001 From: Jono Prest Date: Tue, 19 May 2026 16:20:43 +0200 Subject: [PATCH 28/34] super_errors: cover typedecl Variant_spread_fail when source isn't a variant --- .../expected/variant_spread_non_variant.res.expected | 11 +++++++++++ .../fixtures/variant_spread_non_variant.res | 5 +++++ 2 files changed, 16 insertions(+) create mode 100644 tests/build_tests/super_errors/expected/variant_spread_non_variant.res.expected create mode 100644 tests/build_tests/super_errors/fixtures/variant_spread_non_variant.res diff --git a/tests/build_tests/super_errors/expected/variant_spread_non_variant.res.expected b/tests/build_tests/super_errors/expected/variant_spread_non_variant.res.expected new file mode 100644 index 0000000000..ee7beb48c1 --- /dev/null +++ b/tests/build_tests/super_errors/expected/variant_spread_non_variant.res.expected @@ -0,0 +1,11 @@ + + We've found a bug for you! + /.../fixtures/variant_spread_non_variant.res:4:8 + + 2 │ + 3 │ type b = + 4 │ | ...a + 5 │ | C + 6 │ + + This type is not a valid type to spread. It's only possible to spread other variants. \ No newline at end of file diff --git a/tests/build_tests/super_errors/fixtures/variant_spread_non_variant.res b/tests/build_tests/super_errors/fixtures/variant_spread_non_variant.res new file mode 100644 index 0000000000..727ef06e0d --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/variant_spread_non_variant.res @@ -0,0 +1,5 @@ +type a = int + +type b = + | ...a + | C From beb5c71daaa76399e1adefd7835d5cb43627f714 Mon Sep 17 00:00:00 2001 From: Jono Prest Date: Tue, 19 May 2026 16:34:35 +0200 Subject: [PATCH 29/34] super_errors: cover bs_syntaxerr Not_supported_directive_in_bs_return, Expect_opt_in_bs_return_to_opt, Illegal_attribute --- .../bs_expect_opt_in_bs_return_to_opt.res.expected | 11 +++++++++++ .../expected/bs_illegal_attribute_scope.res.expected | 9 +++++++++ ..._not_supported_directive_in_bs_return.res.expected | 9 +++++++++ .../fixtures/bs_expect_opt_in_bs_return_to_opt.res | 4 ++++ .../fixtures/bs_illegal_attribute_scope.res | 4 ++++ .../bs_not_supported_directive_in_bs_return.res | 4 ++++ 6 files changed, 41 insertions(+) create mode 100644 tests/build_tests/super_errors/expected/bs_expect_opt_in_bs_return_to_opt.res.expected create mode 100644 tests/build_tests/super_errors/expected/bs_illegal_attribute_scope.res.expected create mode 100644 tests/build_tests/super_errors/expected/bs_not_supported_directive_in_bs_return.res.expected create mode 100644 tests/build_tests/super_errors/fixtures/bs_expect_opt_in_bs_return_to_opt.res create mode 100644 tests/build_tests/super_errors/fixtures/bs_illegal_attribute_scope.res create mode 100644 tests/build_tests/super_errors/fixtures/bs_not_supported_directive_in_bs_return.res diff --git a/tests/build_tests/super_errors/expected/bs_expect_opt_in_bs_return_to_opt.res.expected b/tests/build_tests/super_errors/expected/bs_expect_opt_in_bs_return_to_opt.res.expected new file mode 100644 index 0000000000..f43b6c6514 --- /dev/null +++ b/tests/build_tests/super_errors/expected/bs_expect_opt_in_bs_return_to_opt.res.expected @@ -0,0 +1,11 @@ + + We've found a bug for you! + /.../fixtures/bs_expect_opt_in_bs_return_to_opt.res:1:1-2:31 + + 1 │ @return(null_to_opt) + 2 │ external f: string => int = "f" + 3 │ + 4 │ let _ = f("x") + + %@return directive *_to_opt expect return type to be +syntax wise `_ option` for safety \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/bs_illegal_attribute_scope.res.expected b/tests/build_tests/super_errors/expected/bs_illegal_attribute_scope.res.expected new file mode 100644 index 0000000000..5a3fb5882a --- /dev/null +++ b/tests/build_tests/super_errors/expected/bs_illegal_attribute_scope.res.expected @@ -0,0 +1,9 @@ + + We've found a bug for you! + /.../fixtures/bs_illegal_attribute_scope.res:1:1-6 + + 1 │ @scope @val + 2 │ external x: int = "x" + 3 │ + + Illegal attributes \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/bs_not_supported_directive_in_bs_return.res.expected b/tests/build_tests/super_errors/expected/bs_not_supported_directive_in_bs_return.res.expected new file mode 100644 index 0000000000..7e02a37804 --- /dev/null +++ b/tests/build_tests/super_errors/expected/bs_not_supported_directive_in_bs_return.res.expected @@ -0,0 +1,9 @@ + + We've found a bug for you! + /.../fixtures/bs_not_supported_directive_in_bs_return.res:1:1-7 + + 1 │ @return(bogus) + 2 │ external f: string => int = "f" + 3 │ + + Not supported return directive \ No newline at end of file diff --git a/tests/build_tests/super_errors/fixtures/bs_expect_opt_in_bs_return_to_opt.res b/tests/build_tests/super_errors/fixtures/bs_expect_opt_in_bs_return_to_opt.res new file mode 100644 index 0000000000..9114603b2d --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/bs_expect_opt_in_bs_return_to_opt.res @@ -0,0 +1,4 @@ +@return(null_to_opt) +external f: string => int = "f" + +let _ = f("x") diff --git a/tests/build_tests/super_errors/fixtures/bs_illegal_attribute_scope.res b/tests/build_tests/super_errors/fixtures/bs_illegal_attribute_scope.res new file mode 100644 index 0000000000..760f03f39b --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/bs_illegal_attribute_scope.res @@ -0,0 +1,4 @@ +@scope @val +external x: int = "x" + +let _ = x diff --git a/tests/build_tests/super_errors/fixtures/bs_not_supported_directive_in_bs_return.res b/tests/build_tests/super_errors/fixtures/bs_not_supported_directive_in_bs_return.res new file mode 100644 index 0000000000..a04a3761cc --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/bs_not_supported_directive_in_bs_return.res @@ -0,0 +1,4 @@ +@return(bogus) +external f: string => int = "f" + +let _ = f("x") From bb03634fe2f4aad967b39c06f5508d9f94810b80 Mon Sep 17 00:00:00 2001 From: Jono Prest Date: Tue, 19 May 2026 16:42:55 +0200 Subject: [PATCH 30/34] super_errors: cover typecore Undefined_method via object field access --- .../expected/undefined_method.res.expected | 12 ++++++++++++ .../super_errors/fixtures/undefined_method.res | 3 +++ 2 files changed, 15 insertions(+) create mode 100644 tests/build_tests/super_errors/expected/undefined_method.res.expected create mode 100644 tests/build_tests/super_errors/fixtures/undefined_method.res diff --git a/tests/build_tests/super_errors/expected/undefined_method.res.expected b/tests/build_tests/super_errors/expected/undefined_method.res.expected new file mode 100644 index 0000000000..53441a6dda --- /dev/null +++ b/tests/build_tests/super_errors/expected/undefined_method.res.expected @@ -0,0 +1,12 @@ + + We've found a bug for you! + /.../fixtures/undefined_method.res:3:21 + + 1 │ type t = {"existing": int} + 2 │ + 3 │ let get = (o: t) => o["missing"] + 4 │ + + This expression has type t + It has no field missing +Hint: Did you mean existing? \ No newline at end of file diff --git a/tests/build_tests/super_errors/fixtures/undefined_method.res b/tests/build_tests/super_errors/fixtures/undefined_method.res new file mode 100644 index 0000000000..9e1bc348d1 --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/undefined_method.res @@ -0,0 +1,3 @@ +type t = {"existing": int} + +let get = (o: t) => o["missing"] From 5f96c00cf16fcb6cdb905d834f0b9613786d7e55 Mon Sep 17 00:00:00 2001 From: Jono Prest Date: Tue, 19 May 2026 16:46:19 +0200 Subject: [PATCH 31/34] super_errors: cover includemod Modtype_permutation --- .../include_modtype_permutation.res.expected | 40 +++++++++++++++++++ .../fixtures/include_modtype_permutation.res | 11 +++++ 2 files changed, 51 insertions(+) create mode 100644 tests/build_tests/super_errors/expected/include_modtype_permutation.res.expected create mode 100644 tests/build_tests/super_errors/fixtures/include_modtype_permutation.res diff --git a/tests/build_tests/super_errors/expected/include_modtype_permutation.res.expected b/tests/build_tests/super_errors/expected/include_modtype_permutation.res.expected new file mode 100644 index 0000000000..aa7c49df7f --- /dev/null +++ b/tests/build_tests/super_errors/expected/include_modtype_permutation.res.expected @@ -0,0 +1,40 @@ + + We've found a bug for you! + /.../fixtures/include_modtype_permutation.res:6:5-11:1 + + 4 │ let b: int + 5 │ } + 6 │ } = { + 7 │  module type T = { + . │ ... + 10 │  } + 11 │ } + 12 │ + + Signature mismatch: + Modules do not match: + { + module type T = { + let b: int + let a: int + } +} + is not included in + { + module type T = { + let a: int + let b: int + } +} + Module type declarations do not match: + module type T = { + let b: int + let a: int +} + does not match + module type T = { + let a: int + let b: int +} + At position module type T = + Illegal permutation of structure fields \ No newline at end of file diff --git a/tests/build_tests/super_errors/fixtures/include_modtype_permutation.res b/tests/build_tests/super_errors/fixtures/include_modtype_permutation.res new file mode 100644 index 0000000000..efcbd8ac4b --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/include_modtype_permutation.res @@ -0,0 +1,11 @@ +module M: { + module type T = { + let a: int + let b: int + } +} = { + module type T = { + let b: int + let a: int + } +} From 75f37a548a05edfb7508c40b5bdc691c37b9d2fb Mon Sep 17 00:00:00 2001 From: Jono Prest Date: Tue, 19 May 2026 16:50:28 +0200 Subject: [PATCH 32/34] super_errors: cover typemod Not_allowed_in_functor_body, Incomplete_packed_module, Non_generalizable --- .../incomplete_packed_module.res.expected | 12 ++++++++++++ .../expected/non_generalizable.res.expected | 14 ++++++++++++++ .../not_allowed_in_functor_body.res.expected | 12 ++++++++++++ .../fixtures/incomplete_packed_module.res | 9 +++++++++ .../fixtures/non_generalizable.res | 2 ++ .../fixtures/not_allowed_in_functor_body.res | 19 +++++++++++++++++++ 6 files changed, 68 insertions(+) create mode 100644 tests/build_tests/super_errors/expected/incomplete_packed_module.res.expected create mode 100644 tests/build_tests/super_errors/expected/non_generalizable.res.expected create mode 100644 tests/build_tests/super_errors/expected/not_allowed_in_functor_body.res.expected create mode 100644 tests/build_tests/super_errors/fixtures/incomplete_packed_module.res create mode 100644 tests/build_tests/super_errors/fixtures/non_generalizable.res create mode 100644 tests/build_tests/super_errors/fixtures/not_allowed_in_functor_body.res diff --git a/tests/build_tests/super_errors/expected/incomplete_packed_module.res.expected b/tests/build_tests/super_errors/expected/incomplete_packed_module.res.expected new file mode 100644 index 0000000000..a21547cb95 --- /dev/null +++ b/tests/build_tests/super_errors/expected/incomplete_packed_module.res.expected @@ -0,0 +1,12 @@ + + We've found a bug for you! + /.../fixtures/incomplete_packed_module.res:7:14-22 + + 5 │ + 6 │ let extract = (p: module(S with type t = 'a)) => { + 7 │ module M = unpack(p) + 8 │ M.v + 9 │ } + + The type of this packed module contains variables: +module(S with type t = 'a) \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/non_generalizable.res.expected b/tests/build_tests/super_errors/expected/non_generalizable.res.expected new file mode 100644 index 0000000000..216c9a535b --- /dev/null +++ b/tests/build_tests/super_errors/expected/non_generalizable.res.expected @@ -0,0 +1,14 @@ + + We've found a bug for you! + /.../fixtures/non_generalizable.res:2:5-11 + + 1 │ let identity = x => x + 2 │ let applied = identity(identity) + 3 │ + + This expression's type contains type variables that cannot be generalized: + '_weak1 => '_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. \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/not_allowed_in_functor_body.res.expected b/tests/build_tests/super_errors/expected/not_allowed_in_functor_body.res.expected new file mode 100644 index 0000000000..c1ded55de1 --- /dev/null +++ b/tests/build_tests/super_errors/expected/not_allowed_in_functor_body.res.expected @@ -0,0 +1,12 @@ + + We've found a bug for you! + /.../fixtures/not_allowed_in_functor_body.res:17:14-25 + + 15 │ } + 16 │ ) + 17 │ module M = unpack(pack) + 18 │ let _ = M.v + 19 │ } + + This expression creates fresh types. + It is not allowed inside applicative functors. \ No newline at end of file diff --git a/tests/build_tests/super_errors/fixtures/incomplete_packed_module.res b/tests/build_tests/super_errors/fixtures/incomplete_packed_module.res new file mode 100644 index 0000000000..5931e03c7d --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/incomplete_packed_module.res @@ -0,0 +1,9 @@ +module type S = { + type t + let v: t +} + +let extract = (p: module(S with type t = 'a)) => { + module M = unpack(p) + M.v +} diff --git a/tests/build_tests/super_errors/fixtures/non_generalizable.res b/tests/build_tests/super_errors/fixtures/non_generalizable.res new file mode 100644 index 0000000000..4ae785662d --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/non_generalizable.res @@ -0,0 +1,2 @@ +let identity = x => x +let applied = identity(identity) diff --git a/tests/build_tests/super_errors/fixtures/not_allowed_in_functor_body.res b/tests/build_tests/super_errors/fixtures/not_allowed_in_functor_body.res new file mode 100644 index 0000000000..4bc97701dd --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/not_allowed_in_functor_body.res @@ -0,0 +1,19 @@ +module type S = { + type t + let v: t +} + +module F = ( + X: { + let unused: int + }, +) => { + let pack: module(S) = module( + { + type t = int + let v = 1 + } + ) + module M = unpack(pack) + let _ = M.v +} From edcd7c144093f3e8585804f358059b409c669af5 Mon Sep 17 00:00:00 2001 From: Jono Prest Date: Tue, 19 May 2026 16:53:06 +0200 Subject: [PATCH 33/34] super_errors: cover typetexp Alias_type_mismatch --- .../expected/typetexp_alias_type_mismatch.res.expected | 8 ++++++++ .../fixtures/typetexp_alias_type_mismatch.res | 1 + 2 files changed, 9 insertions(+) create mode 100644 tests/build_tests/super_errors/expected/typetexp_alias_type_mismatch.res.expected create mode 100644 tests/build_tests/super_errors/fixtures/typetexp_alias_type_mismatch.res diff --git a/tests/build_tests/super_errors/expected/typetexp_alias_type_mismatch.res.expected b/tests/build_tests/super_errors/expected/typetexp_alias_type_mismatch.res.expected new file mode 100644 index 0000000000..50a8d003ac --- /dev/null +++ b/tests/build_tests/super_errors/expected/typetexp_alias_type_mismatch.res.expected @@ -0,0 +1,8 @@ + + We've found a bug for you! + /.../fixtures/typetexp_alias_type_mismatch.res:1:25-36 + + 1 │ type pair = (int as 'a, string as 'a) + 2 │ + + This alias is bound to type string but is used as an instance of type int \ No newline at end of file diff --git a/tests/build_tests/super_errors/fixtures/typetexp_alias_type_mismatch.res b/tests/build_tests/super_errors/fixtures/typetexp_alias_type_mismatch.res new file mode 100644 index 0000000000..a5cab7bc1b --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/typetexp_alias_type_mismatch.res @@ -0,0 +1 @@ +type pair = (int as 'a, string as 'a) From 655251a6cd043ef1aa3f7f45f2f3df2a09155364 Mon Sep 17 00:00:00 2001 From: Jono Prest Date: Tue, 19 May 2026 17:40:23 +0200 Subject: [PATCH 34/34] Update changelog for #8432 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7d97f8251f..2e8230fc22 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -44,6 +44,7 @@ - Remove `Primitive_option.toUndefined`; use `valFromOption` for optional ffi args. https://github.com/rescript-lang/rescript/pull/8380 - Expand `super_errors` fixture coverage for warnings and errors. https://github.com/rescript-lang/rescript/pull/8429 - Run `super_errors` fixtures in parallel (~2.4× faster locally). https://github.com/rescript-lang/rescript/pull/8430 +- Expand `super_errors` fixture coverage for the remaining reachable single-file error variants. https://github.com/rescript-lang/rescript/pull/8432 # 13.0.0-alpha.4