From 01f17f8a10b98b7e7f1a1f294cbf1099d29559ba Mon Sep 17 00:00:00 2001 From: Jono Prest Date: Mon, 18 May 2026 13:07:13 +0200 Subject: [PATCH 1/9] super_errors: add fixtures for unused-* warnings Adds one-fixture-per-printed-branch snapshots for warnings that previously had zero coverage: warning 12 - redundant sub-pattern warning 33 - unused open warning 34 - unused type declaration warning 35 - unused for-loop index warning 37 - unused constructor (all 3 message branches) warning 38 - unused extension constructor / exception (2 branches each) warning 39 - unused rec flag warning 60 - unused module warning 101 - unused @bs.* attribute Each fixture uses a private module signature to ensure the warning fires consistently regardless of whether the file has consumers. Naming convention: warning_NN_.res so coverage gaps stay easy to grep for. --- ...rning_101_bs_unused_attribute.res.expected | 11 ++++++ .../warning_12_unused_pat.res.expected | 11 ++++++ .../warning_33_unused_open.res.expected | 9 +++++ .../warning_34_unused_type.res.expected | 11 ++++++ .../warning_35_unused_for_index.res.expected | 12 +++++++ ...warning_37_unused_constructor.res.expected | 35 +++++++++++++++++++ ...used_constructor_pattern_only.res.expected | 25 +++++++++++++ ...37_unused_constructor_private.res.expected | 25 +++++++++++++ .../warning_38_unused_exception.res.expected | 11 ++++++ .../warning_38_unused_extension.res.expected | 11 ++++++ ...unused_extension_pattern_only.res.expected | 12 +++++++ .../warning_39_unused_rec_flag.res.expected | 9 +++++ .../warning_60_unused_module.res.expected | 25 +++++++++++++ .../warning_101_bs_unused_attribute.res | 2 ++ .../fixtures/warning_12_unused_pat.res | 7 ++++ .../fixtures/warning_33_unused_open.res | 3 ++ .../fixtures/warning_34_unused_type.res | 6 ++++ .../fixtures/warning_35_unused_for_index.res | 5 +++ .../warning_37_unused_constructor.res | 6 ++++ ...ing_37_unused_constructor_pattern_only.res | 11 ++++++ .../warning_37_unused_constructor_private.res | 7 ++++ .../fixtures/warning_38_unused_exception.res | 6 ++++ .../fixtures/warning_38_unused_extension.res | 7 ++++ ...rning_38_unused_extension_pattern_only.res | 12 +++++++ .../fixtures/warning_39_unused_rec_flag.res | 3 ++ .../fixtures/warning_60_unused_module.res | 8 +++++ 26 files changed, 290 insertions(+) create mode 100644 tests/build_tests/super_errors/expected/warning_101_bs_unused_attribute.res.expected create mode 100644 tests/build_tests/super_errors/expected/warning_12_unused_pat.res.expected create mode 100644 tests/build_tests/super_errors/expected/warning_33_unused_open.res.expected create mode 100644 tests/build_tests/super_errors/expected/warning_34_unused_type.res.expected create mode 100644 tests/build_tests/super_errors/expected/warning_35_unused_for_index.res.expected create mode 100644 tests/build_tests/super_errors/expected/warning_37_unused_constructor.res.expected create mode 100644 tests/build_tests/super_errors/expected/warning_37_unused_constructor_pattern_only.res.expected create mode 100644 tests/build_tests/super_errors/expected/warning_37_unused_constructor_private.res.expected create mode 100644 tests/build_tests/super_errors/expected/warning_38_unused_exception.res.expected create mode 100644 tests/build_tests/super_errors/expected/warning_38_unused_extension.res.expected create mode 100644 tests/build_tests/super_errors/expected/warning_38_unused_extension_pattern_only.res.expected create mode 100644 tests/build_tests/super_errors/expected/warning_39_unused_rec_flag.res.expected create mode 100644 tests/build_tests/super_errors/expected/warning_60_unused_module.res.expected create mode 100644 tests/build_tests/super_errors/fixtures/warning_101_bs_unused_attribute.res create mode 100644 tests/build_tests/super_errors/fixtures/warning_12_unused_pat.res create mode 100644 tests/build_tests/super_errors/fixtures/warning_33_unused_open.res create mode 100644 tests/build_tests/super_errors/fixtures/warning_34_unused_type.res create mode 100644 tests/build_tests/super_errors/fixtures/warning_35_unused_for_index.res create mode 100644 tests/build_tests/super_errors/fixtures/warning_37_unused_constructor.res create mode 100644 tests/build_tests/super_errors/fixtures/warning_37_unused_constructor_pattern_only.res create mode 100644 tests/build_tests/super_errors/fixtures/warning_37_unused_constructor_private.res create mode 100644 tests/build_tests/super_errors/fixtures/warning_38_unused_exception.res create mode 100644 tests/build_tests/super_errors/fixtures/warning_38_unused_extension.res create mode 100644 tests/build_tests/super_errors/fixtures/warning_38_unused_extension_pattern_only.res create mode 100644 tests/build_tests/super_errors/fixtures/warning_39_unused_rec_flag.res create mode 100644 tests/build_tests/super_errors/fixtures/warning_60_unused_module.res diff --git a/tests/build_tests/super_errors/expected/warning_101_bs_unused_attribute.res.expected b/tests/build_tests/super_errors/expected/warning_101_bs_unused_attribute.res.expected new file mode 100644 index 0000000000..395cc146bc --- /dev/null +++ b/tests/build_tests/super_errors/expected/warning_101_bs_unused_attribute.res.expected @@ -0,0 +1,11 @@ + + Warning number 101 (configured as error) + /.../fixtures/warning_101_bs_unused_attribute.res:1:1-3 + + 1 │ @as("foo") + 2 │ let x = 1 + 3 │ + + Unused attribute: @as +This attribute has no effect here. +For example, some attributes are only meaningful in externals. \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/warning_12_unused_pat.res.expected b/tests/build_tests/super_errors/expected/warning_12_unused_pat.res.expected new file mode 100644 index 0000000000..7a7e755a9f --- /dev/null +++ b/tests/build_tests/super_errors/expected/warning_12_unused_pat.res.expected @@ -0,0 +1,11 @@ + + Warning number 12 + /.../fixtures/warning_12_unused_pat.res:3:14 + + 1 │ let describe = x => + 2 │ switch x { + 3 │ | Some(0 | 0) => "zero" + 4 │ | _ => "other" + 5 │ } + + this sub-pattern is unused. \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/warning_33_unused_open.res.expected b/tests/build_tests/super_errors/expected/warning_33_unused_open.res.expected new file mode 100644 index 0000000000..fee85d9dd7 --- /dev/null +++ b/tests/build_tests/super_errors/expected/warning_33_unused_open.res.expected @@ -0,0 +1,9 @@ + + Warning number 33 + /.../fixtures/warning_33_unused_open.res:1:1-17 + + 1 │ open Stdlib_Array + 2 │ + 3 │ let x = 1 + + unused open Stdlib_Array. \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/warning_34_unused_type.res.expected b/tests/build_tests/super_errors/expected/warning_34_unused_type.res.expected new file mode 100644 index 0000000000..fed0335a68 --- /dev/null +++ b/tests/build_tests/super_errors/expected/warning_34_unused_type.res.expected @@ -0,0 +1,11 @@ + + Warning number 34 + /.../fixtures/warning_34_unused_type.res:4:3-23 + + 2 │ let v: int + 3 │ } = { + 4 │ type unusedType = int + 5 │ let v = 1 + 6 │ } + + unused type unusedType. \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/warning_35_unused_for_index.res.expected b/tests/build_tests/super_errors/expected/warning_35_unused_for_index.res.expected new file mode 100644 index 0000000000..954c1d8235 --- /dev/null +++ b/tests/build_tests/super_errors/expected/warning_35_unused_for_index.res.expected @@ -0,0 +1,12 @@ + + Warning number 35 + /.../fixtures/warning_35_unused_for_index.res:2:3-4:3 + + 1 │ let run = () => { + 2 │ for i in 0 to 10 { + 3 │  Console.log("hi") + 4 │  } + 5 │ } + 6 │ + + unused for-loop index i. \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/warning_37_unused_constructor.res.expected b/tests/build_tests/super_errors/expected/warning_37_unused_constructor.res.expected new file mode 100644 index 0000000000..1edbe4de36 --- /dev/null +++ b/tests/build_tests/super_errors/expected/warning_37_unused_constructor.res.expected @@ -0,0 +1,35 @@ + + Warning number 34 + /.../fixtures/warning_37_unused_constructor.res:4:3-20 + + 2 │ let v: int + 3 │ } = { + 4 │ type t = Foo | Bar + 5 │ let v = 1 + 6 │ } + + unused type t. + + + Warning number 37 + /.../fixtures/warning_37_unused_constructor.res:4:3-20 + + 2 │ let v: int + 3 │ } = { + 4 │ type t = Foo | Bar + 5 │ let v = 1 + 6 │ } + + unused constructor Foo. + + + Warning number 37 + /.../fixtures/warning_37_unused_constructor.res:4:3-20 + + 2 │ let v: int + 3 │ } = { + 4 │ type t = Foo | Bar + 5 │ let v = 1 + 6 │ } + + unused constructor Bar. \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/warning_37_unused_constructor_pattern_only.res.expected b/tests/build_tests/super_errors/expected/warning_37_unused_constructor_pattern_only.res.expected new file mode 100644 index 0000000000..373848f043 --- /dev/null +++ b/tests/build_tests/super_errors/expected/warning_37_unused_constructor_pattern_only.res.expected @@ -0,0 +1,25 @@ + + Warning number 37 + /.../fixtures/warning_37_unused_constructor_pattern_only.res:4:3-20 + + 2 │ let v: int + 3 │ } = { + 4 │ type t = Foo | Bar + 5 │ let _describe = (x: t) => + 6 │ switch x { + + constructor Foo is never used to build values. +(However, this constructor appears in patterns.) + + + Warning number 37 + /.../fixtures/warning_37_unused_constructor_pattern_only.res:4:3-20 + + 2 │ let v: int + 3 │ } = { + 4 │ type t = Foo | Bar + 5 │ let _describe = (x: t) => + 6 │ switch x { + + constructor Bar is never used to build values. +(However, this constructor appears in patterns.) \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/warning_37_unused_constructor_private.res.expected b/tests/build_tests/super_errors/expected/warning_37_unused_constructor_private.res.expected new file mode 100644 index 0000000000..2c91395b71 --- /dev/null +++ b/tests/build_tests/super_errors/expected/warning_37_unused_constructor_private.res.expected @@ -0,0 +1,25 @@ + + Warning number 37 + /.../fixtures/warning_37_unused_constructor_private.res:5:3-20 + + 3 │ let v: int + 4 │ } = { + 5 │ type t = Foo | Bar + 6 │ let v = 1 + 7 │ } + + constructor Foo is never used to build values. +Its type is exported as a private type. + + + Warning number 37 + /.../fixtures/warning_37_unused_constructor_private.res:5:3-20 + + 3 │ let v: int + 4 │ } = { + 5 │ type t = Foo | Bar + 6 │ let v = 1 + 7 │ } + + constructor Bar is never used to build values. +Its type is exported as a private type. \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/warning_38_unused_exception.res.expected b/tests/build_tests/super_errors/expected/warning_38_unused_exception.res.expected new file mode 100644 index 0000000000..66852ef48e --- /dev/null +++ b/tests/build_tests/super_errors/expected/warning_38_unused_exception.res.expected @@ -0,0 +1,11 @@ + + Warning number 38 + /.../fixtures/warning_38_unused_exception.res:4:3-19 + + 2 │ let v: int + 3 │ } = { + 4 │ exception MyError + 5 │ let v = 1 + 6 │ } + + unused exception MyError \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/warning_38_unused_extension.res.expected b/tests/build_tests/super_errors/expected/warning_38_unused_extension.res.expected new file mode 100644 index 0000000000..e508d2bd31 --- /dev/null +++ b/tests/build_tests/super_errors/expected/warning_38_unused_extension.res.expected @@ -0,0 +1,11 @@ + + Warning number 38 + /.../fixtures/warning_38_unused_extension.res:5:13-15 + + 3 │ } = { + 4 │ type t = .. + 5 │ type t += Foo + 6 │ let v = 1 + 7 │ } + + unused extension constructor Foo \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/warning_38_unused_extension_pattern_only.res.expected b/tests/build_tests/super_errors/expected/warning_38_unused_extension_pattern_only.res.expected new file mode 100644 index 0000000000..5a129ed09c --- /dev/null +++ b/tests/build_tests/super_errors/expected/warning_38_unused_extension_pattern_only.res.expected @@ -0,0 +1,12 @@ + + Warning number 38 + /.../fixtures/warning_38_unused_extension_pattern_only.res:5:13-15 + + 3 │ } = { + 4 │ type t = .. + 5 │ type t += Foo + 6 │ let _describe = (x: t) => + 7 │ switch x { + + extension constructor Foo is never used to build values. +(However, this constructor appears in patterns.) \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/warning_39_unused_rec_flag.res.expected b/tests/build_tests/super_errors/expected/warning_39_unused_rec_flag.res.expected new file mode 100644 index 0000000000..5723d38585 --- /dev/null +++ b/tests/build_tests/super_errors/expected/warning_39_unused_rec_flag.res.expected @@ -0,0 +1,9 @@ + + Warning number 39 + /.../fixtures/warning_39_unused_rec_flag.res:1:9-28 + + 1 │ let rec notActuallyRecursive = () => 42 + 2 │ + 3 │ let _ = notActuallyRecursive() + + unused rec flag. \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/warning_60_unused_module.res.expected b/tests/build_tests/super_errors/expected/warning_60_unused_module.res.expected new file mode 100644 index 0000000000..71603e991a --- /dev/null +++ b/tests/build_tests/super_errors/expected/warning_60_unused_module.res.expected @@ -0,0 +1,25 @@ + + Warning number 32 + /.../fixtures/warning_60_unused_module.res:5:9 + + 3 │ } = { + 4 │ module Helper = { + 5 │ let f = 1 + 6 │ } + 7 │ let v = 1 + + unused value f. + + + Warning number 60 + /.../fixtures/warning_60_unused_module.res:4:10-6:3 + + 2 │ let v: int + 3 │ } = { + 4 │ module Helper = { + 5 │  let f = 1 + 6 │  } + 7 │ let v = 1 + 8 │ } + + unused module Helper. \ No newline at end of file diff --git a/tests/build_tests/super_errors/fixtures/warning_101_bs_unused_attribute.res b/tests/build_tests/super_errors/fixtures/warning_101_bs_unused_attribute.res new file mode 100644 index 0000000000..73dc385515 --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/warning_101_bs_unused_attribute.res @@ -0,0 +1,2 @@ +@as("foo") +let x = 1 diff --git a/tests/build_tests/super_errors/fixtures/warning_12_unused_pat.res b/tests/build_tests/super_errors/fixtures/warning_12_unused_pat.res new file mode 100644 index 0000000000..bcfdeebd99 --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/warning_12_unused_pat.res @@ -0,0 +1,7 @@ +let describe = x => + switch x { + | Some(0 | 0) => "zero" + | _ => "other" + } + +let _ = describe(Some(1)) diff --git a/tests/build_tests/super_errors/fixtures/warning_33_unused_open.res b/tests/build_tests/super_errors/fixtures/warning_33_unused_open.res new file mode 100644 index 0000000000..1090425310 --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/warning_33_unused_open.res @@ -0,0 +1,3 @@ +open Stdlib_Array + +let x = 1 diff --git a/tests/build_tests/super_errors/fixtures/warning_34_unused_type.res b/tests/build_tests/super_errors/fixtures/warning_34_unused_type.res new file mode 100644 index 0000000000..0ee73af619 --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/warning_34_unused_type.res @@ -0,0 +1,6 @@ +module M: { + let v: int +} = { + type unusedType = int + let v = 1 +} diff --git a/tests/build_tests/super_errors/fixtures/warning_35_unused_for_index.res b/tests/build_tests/super_errors/fixtures/warning_35_unused_for_index.res new file mode 100644 index 0000000000..09a64e06dc --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/warning_35_unused_for_index.res @@ -0,0 +1,5 @@ +let run = () => { + for i in 0 to 10 { + Console.log("hi") + } +} diff --git a/tests/build_tests/super_errors/fixtures/warning_37_unused_constructor.res b/tests/build_tests/super_errors/fixtures/warning_37_unused_constructor.res new file mode 100644 index 0000000000..bba634765d --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/warning_37_unused_constructor.res @@ -0,0 +1,6 @@ +module M: { + let v: int +} = { + type t = Foo | Bar + let v = 1 +} diff --git a/tests/build_tests/super_errors/fixtures/warning_37_unused_constructor_pattern_only.res b/tests/build_tests/super_errors/fixtures/warning_37_unused_constructor_pattern_only.res new file mode 100644 index 0000000000..12928f4300 --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/warning_37_unused_constructor_pattern_only.res @@ -0,0 +1,11 @@ +module M: { + let v: int +} = { + type t = Foo | Bar + let _describe = (x: t) => + switch x { + | Foo => "foo" + | Bar => "bar" + } + let v = 1 +} diff --git a/tests/build_tests/super_errors/fixtures/warning_37_unused_constructor_private.res b/tests/build_tests/super_errors/fixtures/warning_37_unused_constructor_private.res new file mode 100644 index 0000000000..f000dc87f5 --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/warning_37_unused_constructor_private.res @@ -0,0 +1,7 @@ +module M: { + type t = private Foo | Bar + let v: int +} = { + type t = Foo | Bar + let v = 1 +} diff --git a/tests/build_tests/super_errors/fixtures/warning_38_unused_exception.res b/tests/build_tests/super_errors/fixtures/warning_38_unused_exception.res new file mode 100644 index 0000000000..dba44783ca --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/warning_38_unused_exception.res @@ -0,0 +1,6 @@ +module M: { + let v: int +} = { + exception MyError + let v = 1 +} diff --git a/tests/build_tests/super_errors/fixtures/warning_38_unused_extension.res b/tests/build_tests/super_errors/fixtures/warning_38_unused_extension.res new file mode 100644 index 0000000000..6e515cd642 --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/warning_38_unused_extension.res @@ -0,0 +1,7 @@ +module M: { + let v: int +} = { + type t = .. + type t += Foo + let v = 1 +} diff --git a/tests/build_tests/super_errors/fixtures/warning_38_unused_extension_pattern_only.res b/tests/build_tests/super_errors/fixtures/warning_38_unused_extension_pattern_only.res new file mode 100644 index 0000000000..8be8bbb6b8 --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/warning_38_unused_extension_pattern_only.res @@ -0,0 +1,12 @@ +module M: { + let v: int +} = { + type t = .. + type t += Foo + let _describe = (x: t) => + switch x { + | Foo => "foo" + | _ => "other" + } + let v = 1 +} diff --git a/tests/build_tests/super_errors/fixtures/warning_39_unused_rec_flag.res b/tests/build_tests/super_errors/fixtures/warning_39_unused_rec_flag.res new file mode 100644 index 0000000000..1fe772b1fb --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/warning_39_unused_rec_flag.res @@ -0,0 +1,3 @@ +let rec notActuallyRecursive = () => 42 + +let _ = notActuallyRecursive() diff --git a/tests/build_tests/super_errors/fixtures/warning_60_unused_module.res b/tests/build_tests/super_errors/fixtures/warning_60_unused_module.res new file mode 100644 index 0000000000..1e8e4ac6b4 --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/warning_60_unused_module.res @@ -0,0 +1,8 @@ +module M: { + let v: int +} = { + module Helper = { + let f = 1 + } + let v = 1 +} From 1d8465c9fc3b7799a8b830a18983a25138255a48 Mon Sep 17 00:00:00 2001 From: Jono Prest Date: Mon, 18 May 2026 13:09:22 +0200 Subject: [PATCH 2/9] super_errors: add fixture for warning 43 (non-optional label) Adds coverage for Nonoptional_label, the warning that fires when a caller uses `~x=?` syntax against a non-optional labeled argument. Inventory finding: warnings 16 (Unerasable_optional_argument) and 48 (Eliminated_optional_arguments) are effectively dead in current ReScript. - 16 is raised inside type_function (typecore.ml:3525) but is explicitly disabled at the start of the same function (typecore.ml:3479) with the comment "Disable Unerasable_optional_argument for uncurried functions". Since ReScript is fully uncurried, the warning never fires. - 48 has the variant declared in warnings.ml but no `prerr_warning Eliminated_optional_arguments` call exists anywhere in the codebase, so it can never be raised. No fixtures written for 16 or 48. --- .../expected/warning_43_nonoptional_label.res.expected | 9 +++++++++ .../fixtures/warning_43_nonoptional_label.res | 2 ++ 2 files changed, 11 insertions(+) create mode 100644 tests/build_tests/super_errors/expected/warning_43_nonoptional_label.res.expected create mode 100644 tests/build_tests/super_errors/fixtures/warning_43_nonoptional_label.res diff --git a/tests/build_tests/super_errors/expected/warning_43_nonoptional_label.res.expected b/tests/build_tests/super_errors/expected/warning_43_nonoptional_label.res.expected new file mode 100644 index 0000000000..ae2776a460 --- /dev/null +++ b/tests/build_tests/super_errors/expected/warning_43_nonoptional_label.res.expected @@ -0,0 +1,9 @@ + + Warning number 43 + /.../fixtures/warning_43_nonoptional_label.res:2:15-21 + + 1 │ let f = (~x) => x + 2 │ let _ = f(~x=?Some(1)) + 3 │ + + the label x is not optional. \ No newline at end of file diff --git a/tests/build_tests/super_errors/fixtures/warning_43_nonoptional_label.res b/tests/build_tests/super_errors/fixtures/warning_43_nonoptional_label.res new file mode 100644 index 0000000000..ea533fbda8 --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/warning_43_nonoptional_label.res @@ -0,0 +1,2 @@ +let f = (~x) => x +let _ = f(~x=?Some(1)) From 10021933d0879de7a683ff3005ee954c04f1a42a Mon Sep 17 00:00:00 2001 From: Jono Prest Date: Mon, 18 May 2026 13:19:56 +0200 Subject: [PATCH 3/9] super_errors: add fixtures for attribute / pattern / shadow / type-decl / bs_* warnings Adds one-fixture-per-printed-branch coverage for previously untested warnings, plus extra branches for warnings whose printed text varies with payload shape: warning 23 - useless record `with` spread (all fields overridden) warning 28 - wildcard pattern on a constant constructor warning 30 - duplicate constructor in mutually-recursive type defs warning 41 - ambiguous field labels across multiple record types warning 44 - open shadows an existing value identifier warning 45 - open shadows a constructor (also fires 44 because the parent type is shadowed at the same time; both are captured) warning 47 - illegal payload on @inline attribute warning 52 - fragile literal pattern (matching on Invalid_argument payload string) warning 53 - misplaced @inline on a non-constant let binding (the constant case is consumed by bs_builtin_ppx inline-const transform before it reaches translcore) warning 54 - duplicated @inline attribute warning 57 - ambiguous or-pattern variables under guard, both single-var and multi-var printed branches warning 103 - @string redundant on a payload-less polymorphic variant in an external warning 104 - @deriving applied to a non-applicable type (`accessors` requires a record type) Inventory notes (no fixtures added): - warnings 5 (Partial_application) and 10 (Statement_type): these are now handled as enriched type errors via the `Statement FunctionCall` type-clash context in error_message_utils.ml, rather than as warnings. The `prerr_warning` call sites in typecore.ml still exist but the user-visible behaviour is a type error, not a warning. - warnings 14 (Illegal_backslash), 29 (Eol_in_string), 105 (Bs_fragile_external), 106 (Bs_unimplemented_primitive), 108 (Bs_uninterpreted_delimiters), 50 (Bad_docstring): no `prerr_warning` calls for these anywhere in the compiler. Variant exists in warnings.ml but is unreachable. - warning 109 None branch (no help text) is raised only when polymorphic-variant tag unification fails (typecore.ml:4524). Hard to trigger from user code; the two reachable branches (Some FunctionCall, Some Other) are already covered by existing top_level_*_not_unit fixtures. - warning 8 empty-hint branch ("") is a `try ... with _ -> ""` defensive fallback in parmatch.ml when example-pattern printing raises. Not reachable from normal user code. --- .../expected/warning_103_bs_ffi.res.expected | 9 ++++++ .../warning_104_bs_derive.res.expected | 19 +++++++++++++ ...arning_23_useless_record_with.res.expected | 11 ++++++++ ...ldcard_arg_to_constant_constr.res.expected | 11 ++++++++ ...ning_30_duplicate_definitions.res.expected | 9 ++++++ .../warning_41_ambiguous_field.res.expected | 28 +++++++++++++++++++ ...ing_44_open_shadow_identifier.res.expected | 11 ++++++++ ...open_shadow_label_constructor.res.expected | 23 +++++++++++++++ .../warning_47_attribute_payload.res.expected | 10 +++++++ ...ng_52_fragile_literal_pattern.res.expected | 13 +++++++++ ...arning_53_misplaced_attribute.res.expected | 12 ++++++++ ...rning_54_duplicated_attribute.res.expected | 9 ++++++ ...ng_57_ambiguous_pattern_multi.res.expected | 13 +++++++++ ...g_57_ambiguous_pattern_single.res.expected | 12 ++++++++ .../fixtures/warning_103_bs_ffi.res | 3 ++ .../fixtures/warning_104_bs_derive.res | 2 ++ .../warning_23_useless_record_with.res | 6 ++++ ...ing_28_wildcard_arg_to_constant_constr.res | 7 +++++ .../warning_30_duplicate_definitions.res | 2 ++ .../fixtures/warning_41_ambiguous_field.res | 5 ++++ .../warning_44_open_shadow_identifier.res | 9 ++++++ ...rning_45_open_shadow_label_constructor.res | 9 ++++++ .../fixtures/warning_47_attribute_payload.res | 4 +++ .../warning_52_fragile_literal_pattern.res | 7 +++++ .../warning_53_misplaced_attribute.res | 6 ++++ .../warning_54_duplicated_attribute.res | 4 +++ .../warning_57_ambiguous_pattern_multi.res | 5 ++++ .../warning_57_ambiguous_pattern_single.res | 5 ++++ 28 files changed, 264 insertions(+) create mode 100644 tests/build_tests/super_errors/expected/warning_103_bs_ffi.res.expected create mode 100644 tests/build_tests/super_errors/expected/warning_104_bs_derive.res.expected create mode 100644 tests/build_tests/super_errors/expected/warning_23_useless_record_with.res.expected create mode 100644 tests/build_tests/super_errors/expected/warning_28_wildcard_arg_to_constant_constr.res.expected create mode 100644 tests/build_tests/super_errors/expected/warning_30_duplicate_definitions.res.expected create mode 100644 tests/build_tests/super_errors/expected/warning_41_ambiguous_field.res.expected create mode 100644 tests/build_tests/super_errors/expected/warning_44_open_shadow_identifier.res.expected create mode 100644 tests/build_tests/super_errors/expected/warning_45_open_shadow_label_constructor.res.expected create mode 100644 tests/build_tests/super_errors/expected/warning_47_attribute_payload.res.expected create mode 100644 tests/build_tests/super_errors/expected/warning_52_fragile_literal_pattern.res.expected create mode 100644 tests/build_tests/super_errors/expected/warning_53_misplaced_attribute.res.expected create mode 100644 tests/build_tests/super_errors/expected/warning_54_duplicated_attribute.res.expected create mode 100644 tests/build_tests/super_errors/expected/warning_57_ambiguous_pattern_multi.res.expected create mode 100644 tests/build_tests/super_errors/expected/warning_57_ambiguous_pattern_single.res.expected create mode 100644 tests/build_tests/super_errors/fixtures/warning_103_bs_ffi.res create mode 100644 tests/build_tests/super_errors/fixtures/warning_104_bs_derive.res create mode 100644 tests/build_tests/super_errors/fixtures/warning_23_useless_record_with.res create mode 100644 tests/build_tests/super_errors/fixtures/warning_28_wildcard_arg_to_constant_constr.res create mode 100644 tests/build_tests/super_errors/fixtures/warning_30_duplicate_definitions.res create mode 100644 tests/build_tests/super_errors/fixtures/warning_41_ambiguous_field.res create mode 100644 tests/build_tests/super_errors/fixtures/warning_44_open_shadow_identifier.res create mode 100644 tests/build_tests/super_errors/fixtures/warning_45_open_shadow_label_constructor.res create mode 100644 tests/build_tests/super_errors/fixtures/warning_47_attribute_payload.res create mode 100644 tests/build_tests/super_errors/fixtures/warning_52_fragile_literal_pattern.res create mode 100644 tests/build_tests/super_errors/fixtures/warning_53_misplaced_attribute.res create mode 100644 tests/build_tests/super_errors/fixtures/warning_54_duplicated_attribute.res create mode 100644 tests/build_tests/super_errors/fixtures/warning_57_ambiguous_pattern_multi.res create mode 100644 tests/build_tests/super_errors/fixtures/warning_57_ambiguous_pattern_single.res diff --git a/tests/build_tests/super_errors/expected/warning_103_bs_ffi.res.expected b/tests/build_tests/super_errors/expected/warning_103_bs_ffi.res.expected new file mode 100644 index 0000000000..eda93851af --- /dev/null +++ b/tests/build_tests/super_errors/expected/warning_103_bs_ffi.res.expected @@ -0,0 +1,9 @@ + + Warning number 103 + /.../fixtures/warning_103_bs_ffi.res:1:32-43 + + 1 │ @val external setMode: @string [#Foo | #Bar] => unit = "setMode" + 2 │ + 3 │ let _ = setMode(#Foo) + + FFI warning: @string is redundant here, you can safely remove it \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/warning_104_bs_derive.res.expected b/tests/build_tests/super_errors/expected/warning_104_bs_derive.res.expected new file mode 100644 index 0000000000..000350dc80 --- /dev/null +++ b/tests/build_tests/super_errors/expected/warning_104_bs_derive.res.expected @@ -0,0 +1,19 @@ + + Warning number 104 + /.../fixtures/warning_104_bs_derive.res:2:1-12 + + 1 │ @deriving(accessors) + 2 │ type t = int + 3 │ + + @deriving warning: accessors not applicable to this type + + + Warning number 104 + /.../fixtures/warning_104_bs_derive.res:2:1-12 + + 1 │ @deriving(accessors) + 2 │ type t = int + 3 │ + + @deriving warning: accessors not applicable to this type \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/warning_23_useless_record_with.res.expected b/tests/build_tests/super_errors/expected/warning_23_useless_record_with.res.expected new file mode 100644 index 0000000000..e41a861e5b --- /dev/null +++ b/tests/build_tests/super_errors/expected/warning_23_useless_record_with.res.expected @@ -0,0 +1,11 @@ + + Warning number 23 + /.../fixtures/warning_23_useless_record_with.res:4:10-27 + + 2 │ + 3 │ let r = {a: 1, b: 2} + 4 │ let r2 = {...r, a: 3, b: 4} + 5 │ + 6 │ let _ = r2 + + All the fields are already explicitly listed in this record. You can remove the `...` spread. \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/warning_28_wildcard_arg_to_constant_constr.res.expected b/tests/build_tests/super_errors/expected/warning_28_wildcard_arg_to_constant_constr.res.expected new file mode 100644 index 0000000000..d6a9b170d3 --- /dev/null +++ b/tests/build_tests/super_errors/expected/warning_28_wildcard_arg_to_constant_constr.res.expected @@ -0,0 +1,11 @@ + + Warning number 28 + /.../fixtures/warning_28_wildcard_arg_to_constant_constr.res:5:9 + + 3 │ let f = x => + 4 │ switch x { + 5 │ | Foo(_) => 0 + 6 │ | Bar(_) => 1 + 7 │ } + + wildcard pattern given as argument to a constant constructor \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/warning_30_duplicate_definitions.res.expected b/tests/build_tests/super_errors/expected/warning_30_duplicate_definitions.res.expected new file mode 100644 index 0000000000..78b7f27ff4 --- /dev/null +++ b/tests/build_tests/super_errors/expected/warning_30_duplicate_definitions.res.expected @@ -0,0 +1,9 @@ + + Warning number 30 + /.../fixtures/warning_30_duplicate_definitions.res:2:9-11 + + 1 │ type a = Foo + 2 │ and b = Foo + 3 │ + + the constructor Foo is defined in both types a and b. \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/warning_41_ambiguous_field.res.expected b/tests/build_tests/super_errors/expected/warning_41_ambiguous_field.res.expected new file mode 100644 index 0000000000..6591b52236 --- /dev/null +++ b/tests/build_tests/super_errors/expected/warning_41_ambiguous_field.res.expected @@ -0,0 +1,28 @@ + + Warning number 41 + /.../fixtures/warning_41_ambiguous_field.res:4:9-20 + + 2 │ type b = {x: int, y: int} + 3 │ + 4 │ let r = {x: 1, y: 2} + 5 │ let _: a = r + 6 │ + + these field labels belong to several types: b a +The first one was selected. Disambiguate if this is wrong. + + + We've found a bug for you! + /.../fixtures/warning_41_ambiguous_field.res:5:12 + + 3 │ + 4 │ let r = {x: 1, y: 2} + 5 │ let _: a = r + 6 │ + + This has type: b + But it's expected to have type: a + + Possible solutions: + - These types are compatible at runtime. You can use the coercion operator to convert to the expected type: (r :> a) + \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/warning_44_open_shadow_identifier.res.expected b/tests/build_tests/super_errors/expected/warning_44_open_shadow_identifier.res.expected new file mode 100644 index 0000000000..9ac8026d65 --- /dev/null +++ b/tests/build_tests/super_errors/expected/warning_44_open_shadow_identifier.res.expected @@ -0,0 +1,11 @@ + + Warning number 44 + /.../fixtures/warning_44_open_shadow_identifier.res:8:1-6 + + 6 │ + 7 │ let _ = foo + 8 │ open M + 9 │ let _ = foo + 10 │ + + this open statement shadows the value identifier foo (which is later used) \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/warning_45_open_shadow_label_constructor.res.expected b/tests/build_tests/super_errors/expected/warning_45_open_shadow_label_constructor.res.expected new file mode 100644 index 0000000000..fe8e879dc1 --- /dev/null +++ b/tests/build_tests/super_errors/expected/warning_45_open_shadow_label_constructor.res.expected @@ -0,0 +1,23 @@ + + Warning number 44 + /.../fixtures/warning_45_open_shadow_label_constructor.res:8:1-6 + + 6 │ + 7 │ let _: t = Foo + 8 │ open M + 9 │ let _: t = Foo + 10 │ + + this open statement shadows the type identifier t (which is later used) + + + Warning number 45 + /.../fixtures/warning_45_open_shadow_label_constructor.res:8:1-6 + + 6 │ + 7 │ let _: t = Foo + 8 │ open M + 9 │ let _: t = Foo + 10 │ + + this open statement shadows the constructor Foo (which is later used) \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/warning_47_attribute_payload.res.expected b/tests/build_tests/super_errors/expected/warning_47_attribute_payload.res.expected new file mode 100644 index 0000000000..91df1eeaa1 --- /dev/null +++ b/tests/build_tests/super_errors/expected/warning_47_attribute_payload.res.expected @@ -0,0 +1,10 @@ + + Warning number 47 + /.../fixtures/warning_47_attribute_payload.res:1:1-7 + + 1 │ @inline("sometimes") + 2 │ let f = x => x + 1 + 3 │ + + illegal payload for attribute 'inline'. +It must be either empty, 'always' or 'never' \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/warning_52_fragile_literal_pattern.res.expected b/tests/build_tests/super_errors/expected/warning_52_fragile_literal_pattern.res.expected new file mode 100644 index 0000000000..9c64200b92 --- /dev/null +++ b/tests/build_tests/super_errors/expected/warning_52_fragile_literal_pattern.res.expected @@ -0,0 +1,13 @@ + + Warning number 52 + /.../fixtures/warning_52_fragile_literal_pattern.res:3:22-26 + + 1 │ let describe = e => + 2 │ switch e { + 3 │ | Invalid_argument("Foo") => "specific" + 4 │ | _ => "other" + 5 │ } + + Code should not depend on the actual values of +this constructor's arguments. They are only for information +and may change in future versions. (See manual section 8.5) \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/warning_53_misplaced_attribute.res.expected b/tests/build_tests/super_errors/expected/warning_53_misplaced_attribute.res.expected new file mode 100644 index 0000000000..0c36f4e5f1 --- /dev/null +++ b/tests/build_tests/super_errors/expected/warning_53_misplaced_attribute.res.expected @@ -0,0 +1,12 @@ + + Warning number 53 + /.../fixtures/warning_53_misplaced_attribute.res:3:1-4:13 + + 1 │ let y = 5 + 2 │ + 3 │ @inline + 4 │ let x = y + 1 + 5 │ + 6 │ let _ = x + + the "inline1" attribute cannot appear in this context \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/warning_54_duplicated_attribute.res.expected b/tests/build_tests/super_errors/expected/warning_54_duplicated_attribute.res.expected new file mode 100644 index 0000000000..18f1232928 --- /dev/null +++ b/tests/build_tests/super_errors/expected/warning_54_duplicated_attribute.res.expected @@ -0,0 +1,9 @@ + + Warning number 54 + /.../fixtures/warning_54_duplicated_attribute.res:1:9-15 + + 1 │ @inline @inline + 2 │ let f = x => x + 1 + 3 │ + + the "inline" attribute is used more than once on this expression \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/warning_57_ambiguous_pattern_multi.res.expected b/tests/build_tests/super_errors/expected/warning_57_ambiguous_pattern_multi.res.expected new file mode 100644 index 0000000000..eb85c9a681 --- /dev/null +++ b/tests/build_tests/super_errors/expected/warning_57_ambiguous_pattern_multi.res.expected @@ -0,0 +1,13 @@ + + Warning number 57 + /.../fixtures/warning_57_ambiguous_pattern_multi.res:3:5-49 + + 1 │ let f = pair => + 2 │ switch pair { + 3 │ | (Some(a), Some(b), _) | (_, Some(a), Some(b)) when a + b > 0 => a + + │ b + 4 │ | _ => 0 + 5 │ } + + Ambiguous or-pattern variables under guard; +variables a,b may match different arguments. (See manual section 8.5) \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/warning_57_ambiguous_pattern_single.res.expected b/tests/build_tests/super_errors/expected/warning_57_ambiguous_pattern_single.res.expected new file mode 100644 index 0000000000..e083ac7467 --- /dev/null +++ b/tests/build_tests/super_errors/expected/warning_57_ambiguous_pattern_single.res.expected @@ -0,0 +1,12 @@ + + Warning number 57 + /.../fixtures/warning_57_ambiguous_pattern_single.res:3:5-31 + + 1 │ let f = pair => + 2 │ switch pair { + 3 │ | (Some(n), _) | (_, Some(n)) when n > 0 => n + 4 │ | _ => 0 + 5 │ } + + Ambiguous or-pattern variables under guard; +variable n may match different arguments. (See manual section 8.5) \ No newline at end of file diff --git a/tests/build_tests/super_errors/fixtures/warning_103_bs_ffi.res b/tests/build_tests/super_errors/fixtures/warning_103_bs_ffi.res new file mode 100644 index 0000000000..32b7a053ff --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/warning_103_bs_ffi.res @@ -0,0 +1,3 @@ +@val external setMode: @string [#Foo | #Bar] => unit = "setMode" + +let _ = setMode(#Foo) diff --git a/tests/build_tests/super_errors/fixtures/warning_104_bs_derive.res b/tests/build_tests/super_errors/fixtures/warning_104_bs_derive.res new file mode 100644 index 0000000000..938c3e7352 --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/warning_104_bs_derive.res @@ -0,0 +1,2 @@ +@deriving(accessors) +type t = int diff --git a/tests/build_tests/super_errors/fixtures/warning_23_useless_record_with.res b/tests/build_tests/super_errors/fixtures/warning_23_useless_record_with.res new file mode 100644 index 0000000000..e59245c7bb --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/warning_23_useless_record_with.res @@ -0,0 +1,6 @@ +type t = {a: int, b: int} + +let r = {a: 1, b: 2} +let r2 = {...r, a: 3, b: 4} + +let _ = r2 diff --git a/tests/build_tests/super_errors/fixtures/warning_28_wildcard_arg_to_constant_constr.res b/tests/build_tests/super_errors/fixtures/warning_28_wildcard_arg_to_constant_constr.res new file mode 100644 index 0000000000..5ce9220cf0 --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/warning_28_wildcard_arg_to_constant_constr.res @@ -0,0 +1,7 @@ +type t = Foo | Bar(int) + +let f = x => + switch x { + | Foo(_) => 0 + | Bar(_) => 1 + } diff --git a/tests/build_tests/super_errors/fixtures/warning_30_duplicate_definitions.res b/tests/build_tests/super_errors/fixtures/warning_30_duplicate_definitions.res new file mode 100644 index 0000000000..da92df0e24 --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/warning_30_duplicate_definitions.res @@ -0,0 +1,2 @@ +type a = Foo +and b = Foo diff --git a/tests/build_tests/super_errors/fixtures/warning_41_ambiguous_field.res b/tests/build_tests/super_errors/fixtures/warning_41_ambiguous_field.res new file mode 100644 index 0000000000..3107223b21 --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/warning_41_ambiguous_field.res @@ -0,0 +1,5 @@ +type a = {x: int, y: int} +type b = {x: int, y: int} + +let r = {x: 1, y: 2} +let _: a = r diff --git a/tests/build_tests/super_errors/fixtures/warning_44_open_shadow_identifier.res b/tests/build_tests/super_errors/fixtures/warning_44_open_shadow_identifier.res new file mode 100644 index 0000000000..ac84889fd5 --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/warning_44_open_shadow_identifier.res @@ -0,0 +1,9 @@ +let foo = 1 + +module M = { + let foo = 2 +} + +let _ = foo +open M +let _ = foo diff --git a/tests/build_tests/super_errors/fixtures/warning_45_open_shadow_label_constructor.res b/tests/build_tests/super_errors/fixtures/warning_45_open_shadow_label_constructor.res new file mode 100644 index 0000000000..1b3ffebca5 --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/warning_45_open_shadow_label_constructor.res @@ -0,0 +1,9 @@ +type t = Foo + +module M = { + type t = Foo +} + +let _: t = Foo +open M +let _: t = Foo diff --git a/tests/build_tests/super_errors/fixtures/warning_47_attribute_payload.res b/tests/build_tests/super_errors/fixtures/warning_47_attribute_payload.res new file mode 100644 index 0000000000..89c20c3663 --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/warning_47_attribute_payload.res @@ -0,0 +1,4 @@ +@inline("sometimes") +let f = x => x + 1 + +let _ = f(1) diff --git a/tests/build_tests/super_errors/fixtures/warning_52_fragile_literal_pattern.res b/tests/build_tests/super_errors/fixtures/warning_52_fragile_literal_pattern.res new file mode 100644 index 0000000000..11b763c816 --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/warning_52_fragile_literal_pattern.res @@ -0,0 +1,7 @@ +let describe = e => + switch e { + | Invalid_argument("Foo") => "specific" + | _ => "other" + } + +let _ = describe(Invalid_argument("bar")) diff --git a/tests/build_tests/super_errors/fixtures/warning_53_misplaced_attribute.res b/tests/build_tests/super_errors/fixtures/warning_53_misplaced_attribute.res new file mode 100644 index 0000000000..a81839ab66 --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/warning_53_misplaced_attribute.res @@ -0,0 +1,6 @@ +let y = 5 + +@inline +let x = y + 1 + +let _ = x diff --git a/tests/build_tests/super_errors/fixtures/warning_54_duplicated_attribute.res b/tests/build_tests/super_errors/fixtures/warning_54_duplicated_attribute.res new file mode 100644 index 0000000000..f4ffa40223 --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/warning_54_duplicated_attribute.res @@ -0,0 +1,4 @@ +@inline @inline +let f = x => x + 1 + +let _ = f(1) diff --git a/tests/build_tests/super_errors/fixtures/warning_57_ambiguous_pattern_multi.res b/tests/build_tests/super_errors/fixtures/warning_57_ambiguous_pattern_multi.res new file mode 100644 index 0000000000..f2cb20e465 --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/warning_57_ambiguous_pattern_multi.res @@ -0,0 +1,5 @@ +let f = pair => + switch pair { + | (Some(a), Some(b), _) | (_, Some(a), Some(b)) when a + b > 0 => a + b + | _ => 0 + } diff --git a/tests/build_tests/super_errors/fixtures/warning_57_ambiguous_pattern_single.res b/tests/build_tests/super_errors/fixtures/warning_57_ambiguous_pattern_single.res new file mode 100644 index 0000000000..353d910ea5 --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/warning_57_ambiguous_pattern_single.res @@ -0,0 +1,5 @@ +let f = pair => + switch pair { + | (Some(n), _) | (_, Some(n)) when n > 0 => n + | _ => 0 + } From a2a2ec5bec4a3d9a23a973680dff875d3cec60ff Mon Sep 17 00:00:00 2001 From: Jono Prest Date: Mon, 18 May 2026 13:20:59 +0200 Subject: [PATCH 4/9] super_errors: add fixture for warning 62 (Constraint_on_gadt) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Constraint clause on a GADT (variant where at least one constructor has a result type ascription). ReScript GADT syntax requires `type rec` and `t<'a>` parametric notation; the OCaml `type _ t` form isn't accepted by the ReScript parser. The fixture also triggers a follow-up type error because the constraint `'a = int` makes `t` unsatisfiable — captured in the snapshot as part of documenting the full diagnostic flow. --- ...warning_62_constraint_on_gadt.res.expected | 23 +++++++++++++++++++ .../warning_62_constraint_on_gadt.res | 4 ++++ 2 files changed, 27 insertions(+) create mode 100644 tests/build_tests/super_errors/expected/warning_62_constraint_on_gadt.res.expected create mode 100644 tests/build_tests/super_errors/fixtures/warning_62_constraint_on_gadt.res diff --git a/tests/build_tests/super_errors/expected/warning_62_constraint_on_gadt.res.expected b/tests/build_tests/super_errors/expected/warning_62_constraint_on_gadt.res.expected new file mode 100644 index 0000000000..fdb3168eca --- /dev/null +++ b/tests/build_tests/super_errors/expected/warning_62_constraint_on_gadt.res.expected @@ -0,0 +1,23 @@ + + Warning number 62 + /.../fixtures/warning_62_constraint_on_gadt.res:4:1-19 + + 2 │ | Int(int): t + 3 │ | Bool(bool): t + 4 │ constraint 'a = int + 5 │ + + Type constraints do not apply to GADT cases of variant types. + + + We've found a bug for you! + /.../fixtures/warning_62_constraint_on_gadt.res:3:17-23 + + 1 │ type rec t<'a> = + 2 │ | Int(int): t + 3 │ | Bool(bool): t + 4 │ constraint 'a = int + 5 │ + + Constraints are not satisfied in this type. + Type t should be an instance of t \ No newline at end of file diff --git a/tests/build_tests/super_errors/fixtures/warning_62_constraint_on_gadt.res b/tests/build_tests/super_errors/fixtures/warning_62_constraint_on_gadt.res new file mode 100644 index 0000000000..5080de937b --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/warning_62_constraint_on_gadt.res @@ -0,0 +1,4 @@ +type rec t<'a> = + | Int(int): t + | Bool(bool): t +constraint 'a = int From fbd5bc63624b5429f4216cae10ed2e676022dc19 Mon Sep 17 00:00:00 2001 From: Jono Prest Date: Mon, 18 May 2026 13:37:47 +0200 Subject: [PATCH 5/9] super_errors: add fixtures for high-value typecore errors + format previous batch MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit New error fixtures: multiply_bound_variable.res - `let (x, x) = ...` (pattern binds same name twice) label_multiply_defined_literal.res - `{a: 1, a: 2}` record literal with duplicate label illegal_letrec_pat.res - `let rec (x, y) = ...` (let rec LHS must be a variable) exception_pattern_below_toplevel.res - `Some(exception Not_found)` (exception patterns must be at the top of a switch case) or_pattern_type_clash.res - `| 1 | "hello" => ...` on an `int`-typed scrutinee orpat_vars_unbalanced.res - `| Some(n) | None => ...` (variable bound on only one side of an or-pattern) Also reformats the previous warning batch via `make format`: - `when` → `if` for switch guards (modern ReScript syntax) - layout fixes for warning_53/57/62 to match the formatter - snapshots regenerated against the formatted fixtures Inventory finding: char/int interval patterns (`'5' .. '0'`) parse silently in current ReScript — Invalid_interval (typecore Error variant) appears to be unreachable from the surface syntax. Skipped. --- ...eption_pattern_below_toplevel.res.expected | 11 +++++++++++ .../expected/illegal_letrec_pat.res.expected | 19 +++++++++++++++++++ ...abel_multiply_defined_literal.res.expected | 11 +++++++++++ .../multiply_bound_variable.res.expected | 9 +++++++++ .../or_pattern_type_clash.res.expected | 12 ++++++++++++ .../orpat_vars_unbalanced.res.expected | 11 +++++++++++ ...arning_53_misplaced_attribute.res.expected | 9 +++++---- ...ng_57_ambiguous_pattern_multi.res.expected | 3 +-- ...g_57_ambiguous_pattern_single.res.expected | 2 +- ...warning_62_constraint_on_gadt.res.expected | 13 ++++++------- .../exception_pattern_below_toplevel.res | 5 +++++ .../fixtures/illegal_letrec_pat.res | 2 ++ .../label_multiply_defined_literal.res | 4 ++++ .../fixtures/multiply_bound_variable.res | 2 ++ .../fixtures/or_pattern_type_clash.res | 7 +++++++ .../fixtures/orpat_vars_unbalanced.res | 7 +++++++ .../warning_53_misplaced_attribute.res | 3 ++- .../warning_57_ambiguous_pattern_multi.res | 2 +- .../warning_57_ambiguous_pattern_single.res | 2 +- .../warning_62_constraint_on_gadt.res | 3 +-- 20 files changed, 118 insertions(+), 19 deletions(-) create mode 100644 tests/build_tests/super_errors/expected/exception_pattern_below_toplevel.res.expected create mode 100644 tests/build_tests/super_errors/expected/illegal_letrec_pat.res.expected create mode 100644 tests/build_tests/super_errors/expected/label_multiply_defined_literal.res.expected create mode 100644 tests/build_tests/super_errors/expected/multiply_bound_variable.res.expected create mode 100644 tests/build_tests/super_errors/expected/or_pattern_type_clash.res.expected create mode 100644 tests/build_tests/super_errors/expected/orpat_vars_unbalanced.res.expected create mode 100644 tests/build_tests/super_errors/fixtures/exception_pattern_below_toplevel.res create mode 100644 tests/build_tests/super_errors/fixtures/illegal_letrec_pat.res create mode 100644 tests/build_tests/super_errors/fixtures/label_multiply_defined_literal.res create mode 100644 tests/build_tests/super_errors/fixtures/multiply_bound_variable.res create mode 100644 tests/build_tests/super_errors/fixtures/or_pattern_type_clash.res create mode 100644 tests/build_tests/super_errors/fixtures/orpat_vars_unbalanced.res diff --git a/tests/build_tests/super_errors/expected/exception_pattern_below_toplevel.res.expected b/tests/build_tests/super_errors/expected/exception_pattern_below_toplevel.res.expected new file mode 100644 index 0000000000..7fe94855d8 --- /dev/null +++ b/tests/build_tests/super_errors/expected/exception_pattern_below_toplevel.res.expected @@ -0,0 +1,11 @@ + + We've found a bug for you! + /.../fixtures/exception_pattern_below_toplevel.res:3:10-28 + + 1 │ let run = action => + 2 │ switch action() { + 3 │ | Some(exception Not_found) => "nested exception pattern is invalid" + 4 │ | _ => "ok" + 5 │ } + + Exception patterns must be at the top level of a match case. \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/illegal_letrec_pat.res.expected b/tests/build_tests/super_errors/expected/illegal_letrec_pat.res.expected new file mode 100644 index 0000000000..09132c53e6 --- /dev/null +++ b/tests/build_tests/super_errors/expected/illegal_letrec_pat.res.expected @@ -0,0 +1,19 @@ + + Warning number 39 + /.../fixtures/illegal_letrec_pat.res:1:9-14 + + 1 │ let rec (x, y) = (1, 2) + 2 │ let _ = x + y + 3 │ + + unused rec flag. + + + We've found a bug for you! + /.../fixtures/illegal_letrec_pat.res:1:9-14 + + 1 │ let rec (x, y) = (1, 2) + 2 │ let _ = x + y + 3 │ + + Only variables are allowed as left-hand side of `let rec' \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/label_multiply_defined_literal.res.expected b/tests/build_tests/super_errors/expected/label_multiply_defined_literal.res.expected new file mode 100644 index 0000000000..f06003e045 --- /dev/null +++ b/tests/build_tests/super_errors/expected/label_multiply_defined_literal.res.expected @@ -0,0 +1,11 @@ + + We've found a bug for you! + /.../fixtures/label_multiply_defined_literal.res:3:19 + + 1 │ type t = {a: int, b: int} + 2 │ + 3 │ let r: t = {a: 1, a: 2, b: 3} + 4 │ let _ = r + 5 │ + + The record field label a is defined several times \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/multiply_bound_variable.res.expected b/tests/build_tests/super_errors/expected/multiply_bound_variable.res.expected new file mode 100644 index 0000000000..bece9f7892 --- /dev/null +++ b/tests/build_tests/super_errors/expected/multiply_bound_variable.res.expected @@ -0,0 +1,9 @@ + + We've found a bug for you! + /.../fixtures/multiply_bound_variable.res:1:9 + + 1 │ let (x, x) = (1, 2) + 2 │ let _ = x + 3 │ + + Variable x is bound several times in this matching \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/or_pattern_type_clash.res.expected b/tests/build_tests/super_errors/expected/or_pattern_type_clash.res.expected new file mode 100644 index 0000000000..a582b19b9e --- /dev/null +++ b/tests/build_tests/super_errors/expected/or_pattern_type_clash.res.expected @@ -0,0 +1,12 @@ + + We've found a bug for you! + /.../fixtures/or_pattern_type_clash.res:3:9-15 + + 1 │ let f = (x: int) => + 2 │ switch x { + 3 │ | 1 | "hello" => "weird" + 4 │ | _ => "other" + 5 │ } + + This pattern matches values of type string + but a pattern was expected which matches values of type int \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/orpat_vars_unbalanced.res.expected b/tests/build_tests/super_errors/expected/orpat_vars_unbalanced.res.expected new file mode 100644 index 0000000000..7f487b3495 --- /dev/null +++ b/tests/build_tests/super_errors/expected/orpat_vars_unbalanced.res.expected @@ -0,0 +1,11 @@ + + We've found a bug for you! + /.../fixtures/orpat_vars_unbalanced.res:3:5-18 + + 1 │ let f = x => + 2 │ switch x { + 3 │ | Some(n) | None => n + 4 │ | _ => 0 + 5 │ } + + Variable n must occur on both sides of this | pattern \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/warning_53_misplaced_attribute.res.expected b/tests/build_tests/super_errors/expected/warning_53_misplaced_attribute.res.expected index 0c36f4e5f1..5f19d21a0f 100644 --- a/tests/build_tests/super_errors/expected/warning_53_misplaced_attribute.res.expected +++ b/tests/build_tests/super_errors/expected/warning_53_misplaced_attribute.res.expected @@ -1,12 +1,13 @@ Warning number 53 - /.../fixtures/warning_53_misplaced_attribute.res:3:1-4:13 + /.../fixtures/warning_53_misplaced_attribute.res:3:1-5:7 1 │ let y = 5 2 │ 3 │ @inline - 4 │ let x = y + 1 - 5 │ - 6 │ let _ = x + 4 │ let x = + 5 │  y + 1 + 6 │ + 7 │ let _ = x the "inline1" attribute cannot appear in this context \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/warning_57_ambiguous_pattern_multi.res.expected b/tests/build_tests/super_errors/expected/warning_57_ambiguous_pattern_multi.res.expected index eb85c9a681..3552f4424c 100644 --- a/tests/build_tests/super_errors/expected/warning_57_ambiguous_pattern_multi.res.expected +++ b/tests/build_tests/super_errors/expected/warning_57_ambiguous_pattern_multi.res.expected @@ -4,8 +4,7 @@ 1 │ let f = pair => 2 │ switch pair { - 3 │ | (Some(a), Some(b), _) | (_, Some(a), Some(b)) when a + b > 0 => a + - │ b + 3 │ | (Some(a), Some(b), _) | (_, Some(a), Some(b)) if a + b > 0 => a + b 4 │ | _ => 0 5 │ } diff --git a/tests/build_tests/super_errors/expected/warning_57_ambiguous_pattern_single.res.expected b/tests/build_tests/super_errors/expected/warning_57_ambiguous_pattern_single.res.expected index e083ac7467..3d0c41e79d 100644 --- a/tests/build_tests/super_errors/expected/warning_57_ambiguous_pattern_single.res.expected +++ b/tests/build_tests/super_errors/expected/warning_57_ambiguous_pattern_single.res.expected @@ -4,7 +4,7 @@ 1 │ let f = pair => 2 │ switch pair { - 3 │ | (Some(n), _) | (_, Some(n)) when n > 0 => n + 3 │ | (Some(n), _) | (_, Some(n)) if n > 0 => n 4 │ | _ => 0 5 │ } diff --git a/tests/build_tests/super_errors/expected/warning_62_constraint_on_gadt.res.expected b/tests/build_tests/super_errors/expected/warning_62_constraint_on_gadt.res.expected index fdb3168eca..19ae8d414f 100644 --- a/tests/build_tests/super_errors/expected/warning_62_constraint_on_gadt.res.expected +++ b/tests/build_tests/super_errors/expected/warning_62_constraint_on_gadt.res.expected @@ -1,11 +1,11 @@ Warning number 62 - /.../fixtures/warning_62_constraint_on_gadt.res:4:1-19 + /.../fixtures/warning_62_constraint_on_gadt.res:3:25-43 + 1 │ type rec t<'a> = 2 │ | Int(int): t - 3 │ | Bool(bool): t - 4 │ constraint 'a = int - 5 │ + 3 │ | Bool(bool): t constraint 'a = int + 4 │ Type constraints do not apply to GADT cases of variant types. @@ -15,9 +15,8 @@ 1 │ type rec t<'a> = 2 │ | Int(int): t - 3 │ | Bool(bool): t - 4 │ constraint 'a = int - 5 │ + 3 │ | Bool(bool): t constraint 'a = int + 4 │ Constraints are not satisfied in this type. Type t should be an instance of t \ No newline at end of file diff --git a/tests/build_tests/super_errors/fixtures/exception_pattern_below_toplevel.res b/tests/build_tests/super_errors/fixtures/exception_pattern_below_toplevel.res new file mode 100644 index 0000000000..20bbfe27b0 --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/exception_pattern_below_toplevel.res @@ -0,0 +1,5 @@ +let run = action => + switch action() { + | Some(exception Not_found) => "nested exception pattern is invalid" + | _ => "ok" + } diff --git a/tests/build_tests/super_errors/fixtures/illegal_letrec_pat.res b/tests/build_tests/super_errors/fixtures/illegal_letrec_pat.res new file mode 100644 index 0000000000..b0ad347623 --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/illegal_letrec_pat.res @@ -0,0 +1,2 @@ +let rec (x, y) = (1, 2) +let _ = x + y diff --git a/tests/build_tests/super_errors/fixtures/label_multiply_defined_literal.res b/tests/build_tests/super_errors/fixtures/label_multiply_defined_literal.res new file mode 100644 index 0000000000..0890651abb --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/label_multiply_defined_literal.res @@ -0,0 +1,4 @@ +type t = {a: int, b: int} + +let r: t = {a: 1, a: 2, b: 3} +let _ = r diff --git a/tests/build_tests/super_errors/fixtures/multiply_bound_variable.res b/tests/build_tests/super_errors/fixtures/multiply_bound_variable.res new file mode 100644 index 0000000000..7142eef27a --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/multiply_bound_variable.res @@ -0,0 +1,2 @@ +let (x, x) = (1, 2) +let _ = x diff --git a/tests/build_tests/super_errors/fixtures/or_pattern_type_clash.res b/tests/build_tests/super_errors/fixtures/or_pattern_type_clash.res new file mode 100644 index 0000000000..90f31b3880 --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/or_pattern_type_clash.res @@ -0,0 +1,7 @@ +let f = (x: int) => + switch x { + | 1 | "hello" => "weird" + | _ => "other" + } + +let _ = f(1) diff --git a/tests/build_tests/super_errors/fixtures/orpat_vars_unbalanced.res b/tests/build_tests/super_errors/fixtures/orpat_vars_unbalanced.res new file mode 100644 index 0000000000..4463e9b402 --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/orpat_vars_unbalanced.res @@ -0,0 +1,7 @@ +let f = x => + switch x { + | Some(n) | None => n + | _ => 0 + } + +let _ = f(Some(1)) diff --git a/tests/build_tests/super_errors/fixtures/warning_53_misplaced_attribute.res b/tests/build_tests/super_errors/fixtures/warning_53_misplaced_attribute.res index a81839ab66..1897832b33 100644 --- a/tests/build_tests/super_errors/fixtures/warning_53_misplaced_attribute.res +++ b/tests/build_tests/super_errors/fixtures/warning_53_misplaced_attribute.res @@ -1,6 +1,7 @@ let y = 5 @inline -let x = y + 1 +let x = + y + 1 let _ = x diff --git a/tests/build_tests/super_errors/fixtures/warning_57_ambiguous_pattern_multi.res b/tests/build_tests/super_errors/fixtures/warning_57_ambiguous_pattern_multi.res index f2cb20e465..3dac89cbda 100644 --- a/tests/build_tests/super_errors/fixtures/warning_57_ambiguous_pattern_multi.res +++ b/tests/build_tests/super_errors/fixtures/warning_57_ambiguous_pattern_multi.res @@ -1,5 +1,5 @@ let f = pair => switch pair { - | (Some(a), Some(b), _) | (_, Some(a), Some(b)) when a + b > 0 => a + b + | (Some(a), Some(b), _) | (_, Some(a), Some(b)) if a + b > 0 => a + b | _ => 0 } diff --git a/tests/build_tests/super_errors/fixtures/warning_57_ambiguous_pattern_single.res b/tests/build_tests/super_errors/fixtures/warning_57_ambiguous_pattern_single.res index 353d910ea5..e02fa9d7a1 100644 --- a/tests/build_tests/super_errors/fixtures/warning_57_ambiguous_pattern_single.res +++ b/tests/build_tests/super_errors/fixtures/warning_57_ambiguous_pattern_single.res @@ -1,5 +1,5 @@ let f = pair => switch pair { - | (Some(n), _) | (_, Some(n)) when n > 0 => n + | (Some(n), _) | (_, Some(n)) if n > 0 => n | _ => 0 } diff --git a/tests/build_tests/super_errors/fixtures/warning_62_constraint_on_gadt.res b/tests/build_tests/super_errors/fixtures/warning_62_constraint_on_gadt.res index 5080de937b..be30976786 100644 --- a/tests/build_tests/super_errors/fixtures/warning_62_constraint_on_gadt.res +++ b/tests/build_tests/super_errors/fixtures/warning_62_constraint_on_gadt.res @@ -1,4 +1,3 @@ type rec t<'a> = | Int(int): t - | Bool(bool): t -constraint 'a = int + | Bool(bool): t constraint 'a = int From 4bbf0d983538d6237cf481169ff83f8654c30fcd Mon Sep 17 00:00:00 2001 From: Jono Prest Date: Mon, 18 May 2026 14:02:01 +0200 Subject: [PATCH 6/9] super_errors: add fixtures for typedecl + typemod errors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit repeated_type_parameter.res - `type t<'a, 'a>` (param name used twice in the param list) duplicate_variant_constructor.res - `type t = Foo | Foo` type_abbrev_missing_rec.res - `type t = t` without `rec`, which surfaces as Unbound_type with a "did you mean type rec?" hint rather than as a cycle recursive_type_abbrev_cycle.res - `type rec t = t` (true cyclic abbrev, no indirection) unbound_type_var.res - `type t = ('a, int)` (uses 'a without declaring it) record_literal_missing_fields.res - `let r: t = {}` where `t` has a required field (this fires Labels_missing, not the Empty_record_literal variant which appears to be unreachable for record-typed scrutinees) duplicate_module_in_scope.res - two `module M = {…}` declarations in the same structure (typemod Repeated_name) --- .../expected/duplicate_module_in_scope.res.expected | 13 +++++++++++++ .../duplicate_variant_constructor.res.expected | 8 ++++++++ .../record_literal_missing_fields.res.expected | 10 ++++++++++ .../recursive_type_abbrev_cycle.res.expected | 8 ++++++++ .../expected/repeated_type_parameter.res.expected | 8 ++++++++ .../expected/type_abbrev_missing_rec.res.expected | 9 +++++++++ .../expected/unbound_type_var.res.expected | 8 ++++++++ .../fixtures/duplicate_module_in_scope.res | 7 +++++++ .../fixtures/duplicate_variant_constructor.res | 1 + .../fixtures/record_literal_missing_fields.res | 3 +++ .../fixtures/recursive_type_abbrev_cycle.res | 1 + .../fixtures/repeated_type_parameter.res | 1 + .../fixtures/type_abbrev_missing_rec.res | 1 + .../super_errors/fixtures/unbound_type_var.res | 1 + 14 files changed, 79 insertions(+) create mode 100644 tests/build_tests/super_errors/expected/duplicate_module_in_scope.res.expected create mode 100644 tests/build_tests/super_errors/expected/duplicate_variant_constructor.res.expected create mode 100644 tests/build_tests/super_errors/expected/record_literal_missing_fields.res.expected create mode 100644 tests/build_tests/super_errors/expected/recursive_type_abbrev_cycle.res.expected create mode 100644 tests/build_tests/super_errors/expected/repeated_type_parameter.res.expected create mode 100644 tests/build_tests/super_errors/expected/type_abbrev_missing_rec.res.expected create mode 100644 tests/build_tests/super_errors/expected/unbound_type_var.res.expected create mode 100644 tests/build_tests/super_errors/fixtures/duplicate_module_in_scope.res create mode 100644 tests/build_tests/super_errors/fixtures/duplicate_variant_constructor.res create mode 100644 tests/build_tests/super_errors/fixtures/record_literal_missing_fields.res create mode 100644 tests/build_tests/super_errors/fixtures/recursive_type_abbrev_cycle.res create mode 100644 tests/build_tests/super_errors/fixtures/repeated_type_parameter.res create mode 100644 tests/build_tests/super_errors/fixtures/type_abbrev_missing_rec.res create mode 100644 tests/build_tests/super_errors/fixtures/unbound_type_var.res diff --git a/tests/build_tests/super_errors/expected/duplicate_module_in_scope.res.expected b/tests/build_tests/super_errors/expected/duplicate_module_in_scope.res.expected new file mode 100644 index 0000000000..4a29993d33 --- /dev/null +++ b/tests/build_tests/super_errors/expected/duplicate_module_in_scope.res.expected @@ -0,0 +1,13 @@ + + We've found a bug for you! + /.../fixtures/duplicate_module_in_scope.res:5:8 + + 3 │ } + 4 │ + 5 │ module M = { + 6 │ let x = 2 + 7 │ } + + Multiple definition of the module name M + at /.../fixtures/duplicate_module_in_scope.res:1:8 + Names must be unique in a given structure or signature. \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/duplicate_variant_constructor.res.expected b/tests/build_tests/super_errors/expected/duplicate_variant_constructor.res.expected new file mode 100644 index 0000000000..55d6a6ef02 --- /dev/null +++ b/tests/build_tests/super_errors/expected/duplicate_variant_constructor.res.expected @@ -0,0 +1,8 @@ + + We've found a bug for you! + /.../fixtures/duplicate_variant_constructor.res:1:1-18 + + 1 │ type t = Foo | Foo + 2 │ + + Two constructors are named Foo \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/record_literal_missing_fields.res.expected b/tests/build_tests/super_errors/expected/record_literal_missing_fields.res.expected new file mode 100644 index 0000000000..ab0b30b5c9 --- /dev/null +++ b/tests/build_tests/super_errors/expected/record_literal_missing_fields.res.expected @@ -0,0 +1,10 @@ + + We've found a bug for you! + /.../fixtures/record_literal_missing_fields.res:3:12-13 + + 1 │ type t = {a: int} + 2 │ + 3 │ let r: t = {} + 4 │ + + Some required record fields are missing: a. \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/recursive_type_abbrev_cycle.res.expected b/tests/build_tests/super_errors/expected/recursive_type_abbrev_cycle.res.expected new file mode 100644 index 0000000000..be67dfc1fe --- /dev/null +++ b/tests/build_tests/super_errors/expected/recursive_type_abbrev_cycle.res.expected @@ -0,0 +1,8 @@ + + We've found a bug for you! + /.../fixtures/recursive_type_abbrev_cycle.res:1:1-14 + + 1 │ type rec t = t + 2 │ + + The type abbreviation t is cyclic \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/repeated_type_parameter.res.expected b/tests/build_tests/super_errors/expected/repeated_type_parameter.res.expected new file mode 100644 index 0000000000..8fb08faee0 --- /dev/null +++ b/tests/build_tests/super_errors/expected/repeated_type_parameter.res.expected @@ -0,0 +1,8 @@ + + We've found a bug for you! + /.../fixtures/repeated_type_parameter.res:1:13 + + 1 │ type t<'a, 'a> = ('a, 'a) + 2 │ + + A type parameter occurs several times \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/type_abbrev_missing_rec.res.expected b/tests/build_tests/super_errors/expected/type_abbrev_missing_rec.res.expected new file mode 100644 index 0000000000..d02968126b --- /dev/null +++ b/tests/build_tests/super_errors/expected/type_abbrev_missing_rec.res.expected @@ -0,0 +1,9 @@ + + We've found a bug for you! + /.../fixtures/type_abbrev_missing_rec.res:1:10 + + 1 │ type t = t + 2 │ + + This type constructor, `t`, can't be found. + If you wanted to write a recursive type, don't forget the `rec` in `type rec` \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/unbound_type_var.res.expected b/tests/build_tests/super_errors/expected/unbound_type_var.res.expected new file mode 100644 index 0000000000..addd4a2004 --- /dev/null +++ b/tests/build_tests/super_errors/expected/unbound_type_var.res.expected @@ -0,0 +1,8 @@ + + We've found a bug for you! + /.../fixtures/unbound_type_var.res:1:12 + + 1 │ type t = ('a, int) + 2 │ + + Unbound type parameter 'a \ No newline at end of file diff --git a/tests/build_tests/super_errors/fixtures/duplicate_module_in_scope.res b/tests/build_tests/super_errors/fixtures/duplicate_module_in_scope.res new file mode 100644 index 0000000000..0cecfd571c --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/duplicate_module_in_scope.res @@ -0,0 +1,7 @@ +module M = { + let x = 1 +} + +module M = { + let x = 2 +} diff --git a/tests/build_tests/super_errors/fixtures/duplicate_variant_constructor.res b/tests/build_tests/super_errors/fixtures/duplicate_variant_constructor.res new file mode 100644 index 0000000000..dfb2004fc7 --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/duplicate_variant_constructor.res @@ -0,0 +1 @@ +type t = Foo | Foo diff --git a/tests/build_tests/super_errors/fixtures/record_literal_missing_fields.res b/tests/build_tests/super_errors/fixtures/record_literal_missing_fields.res new file mode 100644 index 0000000000..5dec4cd3a4 --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/record_literal_missing_fields.res @@ -0,0 +1,3 @@ +type t = {a: int} + +let r: t = {} diff --git a/tests/build_tests/super_errors/fixtures/recursive_type_abbrev_cycle.res b/tests/build_tests/super_errors/fixtures/recursive_type_abbrev_cycle.res new file mode 100644 index 0000000000..1a870f5521 --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/recursive_type_abbrev_cycle.res @@ -0,0 +1 @@ +type rec t = t diff --git a/tests/build_tests/super_errors/fixtures/repeated_type_parameter.res b/tests/build_tests/super_errors/fixtures/repeated_type_parameter.res new file mode 100644 index 0000000000..e8b4814bc8 --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/repeated_type_parameter.res @@ -0,0 +1 @@ +type t<'a, 'a> = ('a, 'a) diff --git a/tests/build_tests/super_errors/fixtures/type_abbrev_missing_rec.res b/tests/build_tests/super_errors/fixtures/type_abbrev_missing_rec.res new file mode 100644 index 0000000000..0cadcd45ce --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/type_abbrev_missing_rec.res @@ -0,0 +1 @@ +type t = t diff --git a/tests/build_tests/super_errors/fixtures/unbound_type_var.res b/tests/build_tests/super_errors/fixtures/unbound_type_var.res new file mode 100644 index 0000000000..e688c598c2 --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/unbound_type_var.res @@ -0,0 +1 @@ +type t = ('a, int) From 7f4db78004bfd5cf67699f9a15df059b1498fefa Mon Sep 17 00:00:00 2001 From: Jono Prest Date: Mon, 18 May 2026 14:05:13 +0200 Subject: [PATCH 7/9] super_errors: add fixtures for typetexp / module / function call errors type_arity_mismatch.res - `array` (wrong number of type args) typetexp_unbound_type_constructor.res - `let x: nonexistent_type = 1` (typetexp variant; surfaces with the same "did you mean type rec?" hint as the typedecl variant) apply_wrong_label.res - calling a labeled-arg function with the wrong label name too_many_arguments.res - passing 3 unlabelled args to a 2-arg function invalid_type_variable_name.res - `'_invalid` (type variable starting with underscore is not allowed) functor_apply_arg_mismatch.res - applying a functor with a module that doesn't satisfy the parameter signature (exercises includemod's Module_type_mismatch path) --- .../expected/apply_wrong_label.res.expected | 11 +++++++++++ .../functor_apply_arg_mismatch.res.expected | 17 +++++++++++++++++ .../invalid_type_variable_name.res.expected | 8 ++++++++ .../expected/too_many_arguments.res.expected | 14 ++++++++++++++ .../expected/type_arity_mismatch.res.expected | 9 +++++++++ ...petexp_unbound_type_constructor.res.expected | 9 +++++++++ .../super_errors/fixtures/apply_wrong_label.res | 3 +++ .../fixtures/functor_apply_arg_mismatch.res | 14 ++++++++++++++ .../fixtures/invalid_type_variable_name.res | 1 + .../fixtures/too_many_arguments.res | 3 +++ .../fixtures/type_arity_mismatch.res | 1 + .../typetexp_unbound_type_constructor.res | 1 + 12 files changed, 91 insertions(+) create mode 100644 tests/build_tests/super_errors/expected/apply_wrong_label.res.expected create mode 100644 tests/build_tests/super_errors/expected/functor_apply_arg_mismatch.res.expected create mode 100644 tests/build_tests/super_errors/expected/invalid_type_variable_name.res.expected create mode 100644 tests/build_tests/super_errors/expected/too_many_arguments.res.expected create mode 100644 tests/build_tests/super_errors/expected/type_arity_mismatch.res.expected create mode 100644 tests/build_tests/super_errors/expected/typetexp_unbound_type_constructor.res.expected create mode 100644 tests/build_tests/super_errors/fixtures/apply_wrong_label.res create mode 100644 tests/build_tests/super_errors/fixtures/functor_apply_arg_mismatch.res create mode 100644 tests/build_tests/super_errors/fixtures/invalid_type_variable_name.res create mode 100644 tests/build_tests/super_errors/fixtures/too_many_arguments.res create mode 100644 tests/build_tests/super_errors/fixtures/type_arity_mismatch.res create mode 100644 tests/build_tests/super_errors/fixtures/typetexp_unbound_type_constructor.res diff --git a/tests/build_tests/super_errors/expected/apply_wrong_label.res.expected b/tests/build_tests/super_errors/expected/apply_wrong_label.res.expected new file mode 100644 index 0000000000..1d64b1b186 --- /dev/null +++ b/tests/build_tests/super_errors/expected/apply_wrong_label.res.expected @@ -0,0 +1,11 @@ + + We've found a bug for you! + /.../fixtures/apply_wrong_label.res:3:22-28 + + 1 │ let greet = (~name) => "Hello " ++ name + 2 │ + 3 │ let _ = greet(~names="world") + 4 │ + + This function does not take the argument ~names. + This function has type: (~name: string) => string \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/functor_apply_arg_mismatch.res.expected b/tests/build_tests/super_errors/expected/functor_apply_arg_mismatch.res.expected new file mode 100644 index 0000000000..1a386c7ffa --- /dev/null +++ b/tests/build_tests/super_errors/expected/functor_apply_arg_mismatch.res.expected @@ -0,0 +1,17 @@ + + We've found a bug for you! + /.../fixtures/functor_apply_arg_mismatch.res:13:22-29 + + 11 │ } + 12 │ + 13 │ module Result = Make(Concrete) + 14 │ let _ = Result.bar + 15 │ + + Signature mismatch: + Modules do not match: { + let unrelated: string +} is not included in HasFoo + The value `foo' is required but not provided + /.../fixtures/functor_apply_arg_mismatch.res:2:3-14: + Expected declaration \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/invalid_type_variable_name.res.expected b/tests/build_tests/super_errors/expected/invalid_type_variable_name.res.expected new file mode 100644 index 0000000000..cec3fd9534 --- /dev/null +++ b/tests/build_tests/super_errors/expected/invalid_type_variable_name.res.expected @@ -0,0 +1,8 @@ + + We've found a bug for you! + /.../fixtures/invalid_type_variable_name.res:1:9-16 + + 1 │ type t<'_invalid> = list<'_invalid> + 2 │ + + The type variable name '_invalid is not allowed in programs \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/too_many_arguments.res.expected b/tests/build_tests/super_errors/expected/too_many_arguments.res.expected new file mode 100644 index 0000000000..ca66a6e2d5 --- /dev/null +++ b/tests/build_tests/super_errors/expected/too_many_arguments.res.expected @@ -0,0 +1,14 @@ + + We've found a bug for you! + /.../fixtures/too_many_arguments.res:3:9-11 + + 1 │ let add = (x, y) => x + y + 2 │ + 3 │ let _ = add(1, 2, 3) + 4 │ + + This function call is incorrect. + The function has type: + (int, int) => int + + - The function takes just 2 unlabelled arguments, but is called with 3 \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/type_arity_mismatch.res.expected b/tests/build_tests/super_errors/expected/type_arity_mismatch.res.expected new file mode 100644 index 0000000000..aed12a938f --- /dev/null +++ b/tests/build_tests/super_errors/expected/type_arity_mismatch.res.expected @@ -0,0 +1,9 @@ + + We've found a bug for you! + /.../fixtures/type_arity_mismatch.res:1:9-26 + + 1 │ let xs: array = [] + 2 │ + + The type constructor array expects 1 argument(s), + but is here applied to 2 argument(s) \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/typetexp_unbound_type_constructor.res.expected b/tests/build_tests/super_errors/expected/typetexp_unbound_type_constructor.res.expected new file mode 100644 index 0000000000..6f05e99050 --- /dev/null +++ b/tests/build_tests/super_errors/expected/typetexp_unbound_type_constructor.res.expected @@ -0,0 +1,9 @@ + + We've found a bug for you! + /.../fixtures/typetexp_unbound_type_constructor.res:1:8-23 + + 1 │ let x: nonexistent_type = 1 + 2 │ + + This type constructor, `nonexistent_type`, can't be found. + If you wanted to write a recursive type, don't forget the `rec` in `type rec` \ No newline at end of file diff --git a/tests/build_tests/super_errors/fixtures/apply_wrong_label.res b/tests/build_tests/super_errors/fixtures/apply_wrong_label.res new file mode 100644 index 0000000000..1e2f1865fe --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/apply_wrong_label.res @@ -0,0 +1,3 @@ +let greet = (~name) => "Hello " ++ name + +let _ = greet(~names="world") diff --git a/tests/build_tests/super_errors/fixtures/functor_apply_arg_mismatch.res b/tests/build_tests/super_errors/fixtures/functor_apply_arg_mismatch.res new file mode 100644 index 0000000000..48a3e8a602 --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/functor_apply_arg_mismatch.res @@ -0,0 +1,14 @@ +module type HasFoo = { + let foo: int +} + +module Make = (M: HasFoo) => { + let bar = M.foo + 1 +} + +module Concrete = { + let unrelated = "string" +} + +module Result = Make(Concrete) +let _ = Result.bar diff --git a/tests/build_tests/super_errors/fixtures/invalid_type_variable_name.res b/tests/build_tests/super_errors/fixtures/invalid_type_variable_name.res new file mode 100644 index 0000000000..f8108009b8 --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/invalid_type_variable_name.res @@ -0,0 +1 @@ +type t<'_invalid> = list<'_invalid> diff --git a/tests/build_tests/super_errors/fixtures/too_many_arguments.res b/tests/build_tests/super_errors/fixtures/too_many_arguments.res new file mode 100644 index 0000000000..7d6c559485 --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/too_many_arguments.res @@ -0,0 +1,3 @@ +let add = (x, y) => x + y + +let _ = add(1, 2, 3) diff --git a/tests/build_tests/super_errors/fixtures/type_arity_mismatch.res b/tests/build_tests/super_errors/fixtures/type_arity_mismatch.res new file mode 100644 index 0000000000..a5e7415f36 --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/type_arity_mismatch.res @@ -0,0 +1 @@ +let xs: array = [] diff --git a/tests/build_tests/super_errors/fixtures/typetexp_unbound_type_constructor.res b/tests/build_tests/super_errors/fixtures/typetexp_unbound_type_constructor.res new file mode 100644 index 0000000000..f733f648f5 --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/typetexp_unbound_type_constructor.res @@ -0,0 +1 @@ +let x: nonexistent_type = 1 From a67110876acf26c4ec918a924ad7e13066aae8ae Mon Sep 17 00:00:00 2001 From: Jono Prest Date: Mon, 18 May 2026 14:06:21 +0200 Subject: [PATCH 8/9] super_errors: add fixtures for bs_syntaxerr (FFI / deriving) duplicated_bs_deriving.res - two `@deriving(...)` attributes on the same type declaration conflicting_ffi_attributes.res - `@val @send` on the same external (these FFI annotations are mutually exclusive) --- .../expected/conflicting_ffi_attributes.res.expected | 10 ++++++++++ .../expected/duplicated_bs_deriving.res.expected | 9 +++++++++ .../fixtures/conflicting_ffi_attributes.res | 4 ++++ .../super_errors/fixtures/duplicated_bs_deriving.res | 2 ++ 4 files changed, 25 insertions(+) create mode 100644 tests/build_tests/super_errors/expected/conflicting_ffi_attributes.res.expected create mode 100644 tests/build_tests/super_errors/expected/duplicated_bs_deriving.res.expected create mode 100644 tests/build_tests/super_errors/fixtures/conflicting_ffi_attributes.res create mode 100644 tests/build_tests/super_errors/fixtures/duplicated_bs_deriving.res diff --git a/tests/build_tests/super_errors/expected/conflicting_ffi_attributes.res.expected b/tests/build_tests/super_errors/expected/conflicting_ffi_attributes.res.expected new file mode 100644 index 0000000000..f8cc47da4f --- /dev/null +++ b/tests/build_tests/super_errors/expected/conflicting_ffi_attributes.res.expected @@ -0,0 +1,10 @@ + + We've found a bug for you! + /.../fixtures/conflicting_ffi_attributes.res:1:1-2:50 + + 1 │ @val @send + 2 │ external doThing: (string, int) => int = "doThing" + 3 │ + 4 │ let _ = doThing("x", 1) + + Conflicting attributes: Attribute found that conflicts with %@val \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/duplicated_bs_deriving.res.expected b/tests/build_tests/super_errors/expected/duplicated_bs_deriving.res.expected new file mode 100644 index 0000000000..138150e799 --- /dev/null +++ b/tests/build_tests/super_errors/expected/duplicated_bs_deriving.res.expected @@ -0,0 +1,9 @@ + + We've found a bug for you! + /.../fixtures/duplicated_bs_deriving.res:1:22-30 + + 1 │ @deriving(accessors) @deriving(jsConverter) + 2 │ type t = One | Two + 3 │ + + duplicate @deriving attribute \ No newline at end of file diff --git a/tests/build_tests/super_errors/fixtures/conflicting_ffi_attributes.res b/tests/build_tests/super_errors/fixtures/conflicting_ffi_attributes.res new file mode 100644 index 0000000000..157c5475e7 --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/conflicting_ffi_attributes.res @@ -0,0 +1,4 @@ +@val @send +external doThing: (string, int) => int = "doThing" + +let _ = doThing("x", 1) diff --git a/tests/build_tests/super_errors/fixtures/duplicated_bs_deriving.res b/tests/build_tests/super_errors/fixtures/duplicated_bs_deriving.res new file mode 100644 index 0000000000..a8128ed7b4 --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/duplicated_bs_deriving.res @@ -0,0 +1,2 @@ +@deriving(accessors) @deriving(jsConverter) +type t = One | Two From 7755ed08835dad6b56ad3136dff854849b8f597a Mon Sep 17 00:00:00 2001 From: Jono Prest Date: Mon, 18 May 2026 15:41:07 +0200 Subject: [PATCH 9/9] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6a6509c2d0..bf74f78518 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -42,6 +42,7 @@ #### :house: Internal - 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 # 13.0.0-alpha.4