diff --git a/compiler/common/bs_warnings.ml b/compiler/common/bs_warnings.ml index aeea997b82..61e55032ee 100644 --- a/compiler/common/bs_warnings.ml +++ b/compiler/common/bs_warnings.ml @@ -24,6 +24,3 @@ let warn_literal_overflow loc = Location.prerr_warning loc Bs_integer_literal_overflow - -let error_unescaped_delimiter loc txt = - Location.prerr_warning loc (Bs_uninterpreted_delimiters txt) diff --git a/compiler/common/bs_warnings.mli b/compiler/common/bs_warnings.mli index 3807bbf32c..d31e084607 100644 --- a/compiler/common/bs_warnings.mli +++ b/compiler/common/bs_warnings.mli @@ -23,5 +23,3 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *) val warn_literal_overflow : Location.t -> unit - -val error_unescaped_delimiter : Location.t -> string -> unit diff --git a/compiler/ext/warnings.ml b/compiler/ext/warnings.ml index 936f34c4e0..3bbb738346 100644 --- a/compiler/ext/warnings.ml +++ b/compiler/ext/warnings.ml @@ -29,21 +29,13 @@ type loc = { type top_level_unit_help = FunctionCall | Other type t = - | Comment_start (* 1 *) - | Comment_not_end (* 2 *) | Deprecated of string * loc * loc * bool (* 3 *) | Fragile_match of string (* 4 *) | Partial_application (* 5 *) - | Method_override of string list (* 7 *) | Partial_match of string (* 8 *) | Non_closed_record_pattern of string (* 9 *) - | Statement_type (* 10 *) | Unused_match (* 11 *) | Unused_pat (* 12 *) - | Instance_variable_override of string list (* 13 *) - | Illegal_backslash (* 14 *) - | Implicit_public_methods of string list (* 15 *) - | Unerasable_optional_argument (* 16 *) | Unused_argument (* 20 *) | Nonreturning_statement (* 21 *) | Preprocessor of string (* 22 *) @@ -53,7 +45,6 @@ type t = | Unused_var of string (* 26 *) | Unused_var_strict of string (* 27 *) | Wildcard_arg_to_constant_constr (* 28 *) - | Eol_in_string (* 29 *) | Duplicate_definitions of string * string * string * string (*30 *) | Unused_value_declaration of string (* 32 *) | Unused_open of string (* 33 *) @@ -67,9 +58,7 @@ type t = | Open_shadow_identifier of string * string (* 44 *) | Open_shadow_label_constructor of string * string (* 45 *) | Attribute_payload of string * string (* 47 *) - | Eliminated_optional_arguments of string list (* 48 *) | No_cmi_file of string * string option (* 49 *) - | Bad_docstring of bool (* 50 *) | Fragile_literal_pattern (* 52 *) | Misplaced_attribute of string (* 53 *) | Duplicated_attribute of string (* 54 *) @@ -81,10 +70,7 @@ type t = | Bs_polymorphic_comparison (* 102 *) | Bs_ffi_warning of string (* 103 *) | Bs_derive_warning of string (* 104 *) - | Bs_fragile_external of string (* 105 *) - | Bs_unimplemented_primitive of string (* 106 *) | Bs_integer_literal_overflow (* 107 *) - | Bs_uninterpreted_delimiters of string (* 108 *) | Bs_toplevel_expression_unit of (string * top_level_unit_help) option (* 109 *) | Bs_todo of string option (* 110 *) @@ -96,21 +82,13 @@ type t = *) let number = function - | Comment_start -> 1 - | Comment_not_end -> 2 | Deprecated _ -> 3 | Fragile_match _ -> 4 | Partial_application -> 5 - | Method_override _ -> 7 | Partial_match _ -> 8 | Non_closed_record_pattern _ -> 9 - | Statement_type -> 10 | Unused_match -> 11 | Unused_pat -> 12 - | Instance_variable_override _ -> 13 - | Illegal_backslash -> 14 - | Implicit_public_methods _ -> 15 - | Unerasable_optional_argument -> 16 | Unused_argument -> 20 | Nonreturning_statement -> 21 | Preprocessor _ -> 22 @@ -120,7 +98,6 @@ let number = function | Unused_var _ -> 26 | Unused_var_strict _ -> 27 | Wildcard_arg_to_constant_constr -> 28 - | Eol_in_string -> 29 | Duplicate_definitions _ -> 30 | Unused_value_declaration _ -> 32 | Unused_open _ -> 33 @@ -134,9 +111,7 @@ let number = function | Open_shadow_identifier _ -> 44 | Open_shadow_label_constructor _ -> 45 | Attribute_payload _ -> 47 - | Eliminated_optional_arguments _ -> 48 | No_cmi_file _ -> 49 - | Bad_docstring _ -> 50 | Fragile_literal_pattern -> 52 | Misplaced_attribute _ -> 53 | Duplicated_attribute _ -> 54 @@ -148,10 +123,7 @@ let number = function | Bs_polymorphic_comparison -> 102 | Bs_ffi_warning _ -> 103 | Bs_derive_warning _ -> 104 - | Bs_fragile_external _ -> 105 - | Bs_unimplemented_primitive _ -> 106 | Bs_integer_literal_overflow -> 107 - | Bs_uninterpreted_delimiters _ -> 108 | Bs_toplevel_expression_unit _ -> 109 | Bs_todo _ -> 110 @@ -297,8 +269,6 @@ let reset () = let () = reset () let message = function - | Comment_start -> "this is the start of a comment." - | Comment_not_end -> "this is not the end of a comment." | Deprecated (s, _, _, can_be_automigrated) -> (* Reduce \r\n to \n: - Prevents any \r characters being printed on Unix when processing @@ -321,12 +291,6 @@ let message = function It will remain exhaustive when constructors are added to type " ^ s ^ "." | Partial_application -> "this function application is partial,\nmaybe some arguments are missing." - | Method_override [lab] -> "the method " ^ lab ^ " is overridden." - | Method_override (cname :: slist) -> - String.concat " " - ("the following methods are overridden by the class" :: cname :: ":\n " - :: slist) - | Method_override [] -> assert false | Partial_match "" -> "You forgot to handle a possible case here, though we don't have more \ information on the value." @@ -335,42 +299,8 @@ let message = function | Non_closed_record_pattern s -> "the following labels are not bound in this record pattern: " ^ s ^ "\nEither bind these labels explicitly or add ', _' to the pattern." - | Statement_type -> - "This expression returns a value, but you're not doing anything with it. \ - If this is on purpose, wrap it with `ignore`." | Unused_match -> "this match case is unused." | Unused_pat -> "this sub-pattern is unused." - | Instance_variable_override [lab] -> - "the instance variable " ^ lab ^ " is overridden.\n" - ^ "The behaviour changed in ocaml 3.10 (previous behaviour was hiding.)" - | Instance_variable_override (cname :: slist) -> - String.concat " " - ("the following instance variables are overridden by the class" :: cname - :: ":\n " :: slist) - ^ "\nThe behaviour changed in ocaml 3.10 (previous behaviour was hiding.)" - | Instance_variable_override [] -> assert false - | Illegal_backslash -> "illegal backslash escape in string." - | Implicit_public_methods l -> - "the following private methods were made public implicitly:\n " - ^ String.concat " " l ^ "." - | Unerasable_optional_argument -> - String.concat "" - [ - "This optional parameter in final position will, in practice, not be \ - optional.\n"; - " Reorder the parameters so that at least one non-optional one is in \ - final position or, if all parameters are optional, insert a final \ - ().\n\n"; - " Explanation: If the final parameter is optional, it'd be unclear \ - whether a function application that omits it should be considered \ - fully applied, or partially applied. Imagine writing `let title = \ - display(\"hello!\")`, only to realize `title` isn't your desired \ - result, but a curried call that takes a final optional argument, e.g. \ - `~showDate`.\n\n"; - " Formal rule: an optional argument is considered intentionally \ - omitted when the 1st positional (i.e. neither labeled nor optional) \ - argument defined after it is passed in."; - ] | Unused_argument -> "this argument will not be used by the function." | Nonreturning_statement -> "This statement does not continue execution; following code is unreachable." @@ -398,8 +328,6 @@ let message = function v v | Wildcard_arg_to_constant_constr -> "wildcard pattern given as argument to a constant constructor" - | Eol_in_string -> - "unescaped end-of-line in a string constant (non-portable code)" | Duplicate_definitions (kind, cname, tc1, tc2) -> Printf.sprintf "the %s %s is defined in both types %s and %s." kind cname tc1 tc2 @@ -446,18 +374,11 @@ let message = function kind s | Attribute_payload (a, s) -> Printf.sprintf "illegal payload for attribute '%s'.\n%s" a s - | Eliminated_optional_arguments sl -> - Printf.sprintf "implicit elimination of optional argument%s %s" - (if List.length sl = 1 then "" else "s") - (String.concat ", " sl) | No_cmi_file (name, None) -> "no cmi file was found in path for module " ^ name | No_cmi_file (name, Some msg) -> Printf.sprintf "no valid cmi file was found in path for module %s. %s" name msg - | Bad_docstring unattached -> - if unattached then "unattached documentation comment (ignored)" - else "ambiguous documentation comment" | Fragile_literal_pattern -> Printf.sprintf "Code should not depend on the actual values of\n\ @@ -495,15 +416,8 @@ let message = function "Polymorphic comparison introduced (maybe unsafe)" | Bs_ffi_warning s -> "FFI warning: " ^ s | Bs_derive_warning s -> "@deriving warning: " ^ s - | Bs_fragile_external s -> - s - ^ " : using an empty string as a shorthand to infer the external's name \ - from the value's name is dangerous when refactoring, and therefore \ - deprecated" - | Bs_unimplemented_primitive s -> "Unimplemented primitive used: " ^ s | Bs_integer_literal_overflow -> "Integer literal exceeds the range of representable integers of type int" - | Bs_uninterpreted_delimiters s -> "Uninterpreted delimiters " ^ s | Bs_toplevel_expression_unit help -> Printf.sprintf "This%sis at the top level and is expected to return `unit`. But it's \ @@ -581,8 +495,6 @@ let check_fatal () = let descriptions = [ - (1, "Suspicious-looking start-of-comment mark."); - (2, "Suspicious-looking end-of-comment mark."); (3, "Deprecated feature."); ( 4, "Fragile pattern matching: matching that will remain complete even\n\ @@ -591,18 +503,10 @@ let descriptions = ( 5, "Partially applied function: expression whose result has function\n\ \ type and is ignored." ); - (7, "Method overridden."); (8, "Partial match: missing cases in pattern-matching."); (9, "Missing fields in a record pattern."); - ( 10, - "Expression on the left-hand side of a sequence that doesn't have type\n\ - \ \"unit\" (and that is not a function, see warning number 5)." ); (11, "Redundant case in a pattern matching (unused match case)."); (12, "Redundant sub-pattern in a pattern-matching."); - (13, "Instance variable overridden."); - (14, "Illegal backslash escape in a string constant."); - (15, "Private method made public implicitly."); - (16, "Unerasable optional argument."); (17, "Undeclared virtual method."); (18, "Non-principal type."); (19, "Type without principality."); @@ -623,7 +527,6 @@ let descriptions = \ \"let\" nor \"as\", and doesn't start with an underscore (\"_\")\n\ \ character." ); (28, "Wildcard pattern given as argument to a constant constructor."); - (29, "Unescaped end-of-line in a string constant (non-portable code)."); ( 30, "Two labels or constructors of the same name are defined in two\n\ \ mutually recursive types." ); @@ -642,9 +545,7 @@ let descriptions = (45, "Open statement shadows an already defined label or constructor."); (46, "Error in environment variable."); (47, "Illegal attribute payload."); - (48, "Implicit elimination of optional arguments."); (49, "Absent cmi file when looking up module alias."); - (50, "Unexpected documentation comment."); (52, "Fragile constant pattern."); (53, "Attribute cannot appear in this context"); (54, "Attribute used more than once on an expression"); @@ -658,14 +559,9 @@ let descriptions = (102, "Polymorphic comparison introduced (maybe unsafe)"); (103, "Fragile FFI definitions"); (104, "@deriving warning with customized message "); - ( 105, - "External name is inferred from val name is unsafe from refactoring when \ - changing value name" ); - (106, "Unimplemented primitive used:"); ( 107, "Integer literal exceeds the range of representable integers of type int" ); - (108, "Uninterpreted delimiters (for unicode)"); (109, "Toplevel expression has unit type"); (110, "Todo found"); ] diff --git a/compiler/ext/warnings.mli b/compiler/ext/warnings.mli index ba1a03ceec..5ebdfa4b24 100644 --- a/compiler/ext/warnings.mli +++ b/compiler/ext/warnings.mli @@ -22,21 +22,13 @@ type loc = { type top_level_unit_help = FunctionCall | Other type t = - | Comment_start (* 1 *) - | Comment_not_end (* 2 *) | Deprecated of string * loc * loc * bool (* 3 *) | Fragile_match of string (* 4 *) | Partial_application (* 5 *) - | Method_override of string list (* 7 *) | Partial_match of string (* 8 *) | Non_closed_record_pattern of string (* 9 *) - | Statement_type (* 10 *) | Unused_match (* 11 *) | Unused_pat (* 12 *) - | Instance_variable_override of string list (* 13 *) - | Illegal_backslash (* 14 *) - | Implicit_public_methods of string list (* 15 *) - | Unerasable_optional_argument (* 16 *) | Unused_argument (* 20 *) | Nonreturning_statement (* 21 *) | Preprocessor of string (* 22 *) @@ -46,7 +38,6 @@ type t = | Unused_var of string (* 26 *) | Unused_var_strict of string (* 27 *) | Wildcard_arg_to_constant_constr (* 28 *) - | Eol_in_string (* 29 *) | Duplicate_definitions of string * string * string * string (* 30 *) | Unused_value_declaration of string (* 32 *) | Unused_open of string (* 33 *) @@ -60,9 +51,7 @@ type t = | Open_shadow_identifier of string * string (* 44 *) | Open_shadow_label_constructor of string * string (* 45 *) | Attribute_payload of string * string (* 47 *) - | Eliminated_optional_arguments of string list (* 48 *) | No_cmi_file of string * string option (* 49 *) - | Bad_docstring of bool (* 50 *) | Fragile_literal_pattern (* 52 *) | Misplaced_attribute of string (* 53 *) | Duplicated_attribute of string (* 54 *) @@ -74,10 +63,7 @@ type t = | Bs_polymorphic_comparison (* 102 *) | Bs_ffi_warning of string (* 103 *) | Bs_derive_warning of string (* 104 *) - | Bs_fragile_external of string (* 105 *) - | Bs_unimplemented_primitive of string (* 106 *) | Bs_integer_literal_overflow (* 107 *) - | Bs_uninterpreted_delimiters of string (* 108 *) | Bs_toplevel_expression_unit of (string * top_level_unit_help) option (* 109 *) | Bs_todo of string option (* 110 *) diff --git a/compiler/frontend/ast_core_type.ml b/compiler/frontend/ast_core_type.ml index b93c4586bf..f834d6f4b9 100644 --- a/compiler/frontend/ast_core_type.ml +++ b/compiler/frontend/ast_core_type.ml @@ -136,9 +136,12 @@ let list_of_arrow (ty : t) : t * Parsetree.arg list = match ty.ptyp_desc with | Ptyp_arrow {arg; ret; arity} when arity = None || acc = [] -> aux ret (arg :: acc) - | Ptyp_poly (_, ty) -> - (* should not happen? *) - Bs_syntaxerr.err ty.ptyp_loc Unhandled_poly_type + | Ptyp_poly _ -> + (* unreachable: this would require an inline Ptyp_poly inside an + external's arrow chain. The ReScript parser misreads inline `'a.` + prefix syntax as the deprecated uncurried `(. …)` form and rejects + it, so the typer never sees the required AST shape. *) + assert false | _ -> (ty, List.rev acc) in aux ty [] diff --git a/compiler/frontend/ast_utf8_string_interp.ml b/compiler/frontend/ast_utf8_string_interp.ml index 90c5043256..e3e65018a7 100644 --- a/compiler/frontend/ast_utf8_string_interp.ml +++ b/compiler/frontend/ast_utf8_string_interp.ml @@ -289,7 +289,6 @@ module Delim = struct let escaped_j_delimiter = "*j" (* not user level syntax allowed *) let escaped_back_quote_delimiter = "bq" let some_escaped_back_quote_delimiter = Some "bq" - let unescaped_js_delimiter = "js" let some_escaped_j_delimiter = Some escaped_j_delimiter end @@ -339,6 +338,4 @@ let is_unicode_string opt = Ext_string.equal opt Delim.escaped_j_delimiter || Ext_string.equal opt Delim.escaped_back_quote_delimiter -let is_unescaped s = Ext_string.equal s Delim.unescaped_js_delimiter - let parse_processed_delim = Delim.parse_processed diff --git a/compiler/frontend/ast_utf8_string_interp.mli b/compiler/frontend/ast_utf8_string_interp.mli index 5e8ec9c8a9..bc0b13c93e 100644 --- a/compiler/frontend/ast_utf8_string_interp.mli +++ b/compiler/frontend/ast_utf8_string_interp.mli @@ -59,5 +59,4 @@ val transform_exp : Parsetree.expression -> string -> string -> Parsetree.expression val transform_pat : Parsetree.pattern -> string -> string -> Parsetree.pattern val is_unicode_string : string -> bool -val is_unescaped : string -> bool val parse_processed_delim : string option -> External_arg_spec.delim option diff --git a/compiler/frontend/bs_ast_invariant.ml b/compiler/frontend/bs_ast_invariant.ml index 60e1ad285d..023043f9f4 100644 --- a/compiler/frontend/bs_ast_invariant.ml +++ b/compiler/frontend/bs_ast_invariant.ml @@ -52,9 +52,6 @@ let super = Ast_iterator.default_iterator let check_constant loc (const : Parsetree.constant) = match const with - | Pconst_string (_, Some s) -> - if Ast_utf8_string_interp.is_unescaped s then - Bs_warnings.error_unescaped_delimiter loc s | Pconst_integer (s, None) -> ( (* range check using int32 It is better to give a warning instead of error to avoid make people unhappy. diff --git a/compiler/frontend/bs_syntaxerr.ml b/compiler/frontend/bs_syntaxerr.ml index 668853bdf8..7509f328f1 100644 --- a/compiler/frontend/bs_syntaxerr.ml +++ b/compiler/frontend/bs_syntaxerr.ml @@ -26,13 +26,11 @@ type untagged_variant = OnlyOneUnknown | AtMostOneObject | AtMostOneArray type error = | Unsupported_predicates - | Conflict_bs_bs_this_bs_meth | Duplicated_bs_deriving | Conflict_attributes | Expect_int_literal | Expect_string_literal | Expect_int_or_string_or_json_literal - | Unhandled_poly_type | Invalid_underscore_type_in_external | Invalid_bs_string_type | Invalid_bs_int_type @@ -44,19 +42,15 @@ type error = *) | Not_supported_directive_in_bs_return | Expect_opt_in_bs_return_to_opt - | Misplaced_label_syntax | Optional_in_uncurried_bs_attribute | Bs_this_simple_pattern | Experimental_feature_not_enabled of Experimental_features.feature | LetUnwrap_not_supported_in_position of [`Toplevel | `Unsupported_type] + | Misplaced_label_syntax let pp_error fmt err = Format.pp_print_string fmt (match err with - | Misplaced_label_syntax -> "Label syntax is not support in this position" - (* - let fn x = ((##) x ~hi) ~lo:1 ~hi:2 - *) | Optional_in_uncurried_bs_attribute -> "Uncurried function doesn't support optional arguments yet" | Expect_opt_in_bs_return_to_opt -> @@ -65,15 +59,12 @@ let pp_error fmt err = | Not_supported_directive_in_bs_return -> "Not supported return directive" | Illegal_attribute -> "Illegal attributes" | Unsupported_predicates -> "unsupported predicates" - | Conflict_bs_bs_this_bs_meth -> - "%@this and %@bs can not be applied at the same time" | Duplicated_bs_deriving -> "duplicate @deriving attribute" | Conflict_attributes -> "conflicting attributes " | Expect_string_literal -> "expect string literal " | Expect_int_literal -> "expect int literal " | Expect_int_or_string_or_json_literal -> "expect int, string literal or json literal {json|text here|json} " - | Unhandled_poly_type -> "Unhandled poly type" | Invalid_underscore_type_in_external -> "_ is not allowed in combination with external optional type" | Invalid_bs_string_type -> "Not a valid type for %@string" @@ -96,7 +87,8 @@ let pp_error fmt err = | `Toplevel -> "`let?` is not allowed for top-level bindings." | `Unsupported_type -> "`let?` is only supported in let bindings targeting the `result` or \ - `option` type.")) + `option` type.") + | Misplaced_label_syntax -> "Label syntax is not supported in this position") type exn += Error of Location.t * error diff --git a/compiler/frontend/bs_syntaxerr.mli b/compiler/frontend/bs_syntaxerr.mli index ecdaaaa0e6..4851c3adcb 100644 --- a/compiler/frontend/bs_syntaxerr.mli +++ b/compiler/frontend/bs_syntaxerr.mli @@ -26,13 +26,11 @@ type untagged_variant = OnlyOneUnknown | AtMostOneObject | AtMostOneArray type error = | Unsupported_predicates - | Conflict_bs_bs_this_bs_meth | Duplicated_bs_deriving | Conflict_attributes | Expect_int_literal | Expect_string_literal | Expect_int_or_string_or_json_literal - | Unhandled_poly_type | Invalid_underscore_type_in_external | Invalid_bs_string_type | Invalid_bs_int_type @@ -44,11 +42,11 @@ type error = *) | Not_supported_directive_in_bs_return | Expect_opt_in_bs_return_to_opt - | Misplaced_label_syntax | Optional_in_uncurried_bs_attribute | Bs_this_simple_pattern | Experimental_feature_not_enabled of Experimental_features.feature | LetUnwrap_not_supported_in_position of [`Toplevel | `Unsupported_type] + | Misplaced_label_syntax val err : Location.t -> error -> 'a diff --git a/compiler/ml/ctype.ml b/compiler/ml/ctype.ml index e15adf31b4..6eba569eda 100644 --- a/compiler/ml/ctype.ml +++ b/compiler/ml/ctype.ml @@ -57,19 +57,6 @@ type type_pairs = (type_expr * type_expr) list exception Unify of type_pairs -exception Tags of label * label - -let () = - Location.register_error_of_exn (function - | Tags (l, l') -> - Some - Location.( - errorf ~loc:(in_file !input_name) - "In this program,@ variant constructors@ #%s and #%s@ have the \ - same hash value.@ Change one of them." - l l') - | _ -> None) - type subtype_context = | Generic of {errorCode: string} | Coercion_target_variant_not_unboxed of { @@ -107,11 +94,6 @@ exception Cannot_expand exception Cannot_apply -exception Recursive_abbrev - -(* GADT: recursive abbrevs can appear as a result of local constraints *) -exception Unification_recursive_abbrev of type_pairs - (**** Type level management ****) let current_level = ref 0 @@ -2727,13 +2709,10 @@ and unify_row_field env fixed1 fixed2 more l f1 f2 = let unify env ty1 ty2 = let snap = Btype.snapshot () in - try unify env ty1 ty2 with - | Unify trace -> + try unify env ty1 ty2 + with Unify trace -> undo_compress snap; raise (Unify (expand_trace !env trace)) - | Recursive_abbrev -> - undo_compress snap; - raise (Unification_recursive_abbrev (expand_trace !env [(ty1, ty2)])) let unify_gadt ~newtype_level:lev (env : Env.t ref) ty1 ty2 = try diff --git a/compiler/ml/ctype.mli b/compiler/ml/ctype.mli index 6785374ac9..b671730402 100644 --- a/compiler/ml/ctype.mli +++ b/compiler/ml/ctype.mli @@ -54,12 +54,9 @@ type subtype_context = type type_pairs = (type_expr * type_expr) list exception Unify of type_pairs -exception Tags of label * label exception Subtype of type_pairs * type_pairs * subtype_context option exception Cannot_expand exception Cannot_apply -exception Recursive_abbrev -exception Unification_recursive_abbrev of type_pairs val init_def : int -> unit (* Set the initial variable level *) diff --git a/compiler/ml/env.ml b/compiler/ml/env.ml index 970634be03..1466467033 100644 --- a/compiler/ml/env.ml +++ b/compiler/ml/env.ml @@ -58,7 +58,6 @@ type error = | Illegal_renaming of string * string * string | Inconsistent_import of string * string * string | Missing_module of Location.t * Path.t * Path.t - | Illegal_value_name of Location.t * string exception Error of error @@ -730,7 +729,6 @@ let check_pers_struct name = Location.print_filename filename ps_name name | Inconsistent_import _ -> assert false | Missing_module _ -> assert false - | Illegal_value_name _ -> assert false in let warn = Warnings.No_cmi_file (name, Some msg) in Location.prerr_warning Location.none warn @@ -1618,11 +1616,16 @@ and check_usage loc id warn tbl = and check_value_name name loc = (* Note: we could also check here general validity of the identifier, to protect against bad identifiers forged by -pp or - -ppx preprocessors. *) - if name = "->" then raise (Error (Illegal_value_name (loc, name))) + -ppx preprocessors. + + Both guarded paths below are unreachable: the ReScript parser never + emits value identifiers named "->" or containing "#" — both shapes + are rejected as syntax errors. *) + ignore loc; + if name = "->" then assert false else if String.length name > 0 && name.[0] = '#' then for i = 1 to String.length name - 1 do - if name.[i] = '#' then raise (Error (Illegal_value_name (loc, name))) + if name.[i] = '#' then assert false done and store_value ?check id decl env = @@ -2129,13 +2132,9 @@ let report_error ppf = function fprintf ppf "@]@ @[%s@ %s@ %s.@]@]" "The compiled interface for module" (Ident.name (Path.head path2)) "was not found" - | Illegal_value_name (_loc, name) -> - fprintf ppf "'%s' is not a valid value identifier." name - let () = Location.register_error_of_exn (function - | Error ((Missing_module (loc, _, _) | Illegal_value_name (loc, _)) as err) - when loc <> Location.none -> + | Error (Missing_module (loc, _, _) as err) when loc <> Location.none -> Some (Location.error_of_printer loc report_error err) | Error err -> Some (Location.error_of_printer_file report_error err) | _ -> None) diff --git a/compiler/ml/env.mli b/compiler/ml/env.mli index 48eaba1c10..90946f94e3 100644 --- a/compiler/ml/env.mli +++ b/compiler/ml/env.mli @@ -236,7 +236,6 @@ type error = | Illegal_renaming of string * string * string | Inconsistent_import of string * string * string | Missing_module of Location.t * Path.t * Path.t - | Illegal_value_name of Location.t * string exception Error of error diff --git a/compiler/ml/typecore.ml b/compiler/ml/typecore.ml index 4f0b3be38e..1d666ab142 100644 --- a/compiler/ml/typecore.ml +++ b/compiler/ml/typecore.ml @@ -43,6 +43,7 @@ type error = } | Apply_non_function of type_expr | Apply_wrong_label of arg_label * type_expr + | Abstract_wrong_label of arg_label * type_expr | Label_multiply_defined of { label: string; jsx_component_info: jsx_prop_error_info option; @@ -61,20 +62,15 @@ type error = | Not_subtype of Ctype.type_pairs * Ctype.type_pairs * Ctype.subtype_context option | Too_many_arguments of bool * type_expr - | Abstract_wrong_label of arg_label * type_expr | Scoping_let_module of string * type_expr | Not_a_variant_type of Longident.t - | Incoherent_label_order | Less_general of string * (type_expr * type_expr) list | Modules_not_allowed | Cannot_infer_signature | Not_a_packed_module of type_expr - | Recursive_local_constraint of (type_expr * type_expr) list | Unexpected_existential | Unqualified_gadt_pattern of Path.t * string - | Invalid_interval | Invalid_for_loop_index - | Invalid_for_of_pattern | No_value_clauses | Exception_pattern_below_toplevel | Inlined_record_escape @@ -336,17 +332,14 @@ let check_optional_attr env ld optional loc = (* unification inside type_pat*) let unify_pat_types loc env ty ty' = - try unify env ty ty' with - | Unify trace -> raise (Error (loc, env, Pattern_type_clash trace)) - | Tags (l1, l2) -> - raise (Typetexp.Error (loc, env, Typetexp.Variant_tags (l1, l2))) + try unify env ty ty' + with Unify trace -> raise (Error (loc, env, Pattern_type_clash trace)) (* unification inside type_exp and type_expect *) let unify_exp_types ~context loc env ty expected_ty = - try unify env ty expected_ty with - | Unify trace -> raise (Error (loc, env, Expr_type_clash {trace; context})) - | Tags (l1, l2) -> - raise (Typetexp.Error (loc, env, Typetexp.Variant_tags (l1, l2))) + try unify env ty expected_ty + with Unify trace -> + raise (Error (loc, env, Expr_type_clash {trace; context})) (* level at which to create the local type declarations *) let newtype_level = ref None @@ -361,12 +354,8 @@ let unify_pat_types_gadt loc env ty ty' = | None -> assert false | Some x -> x in - try unify_gadt ~newtype_level env ty ty' with - | Unify trace -> raise (Error (loc, !env, Pattern_type_clash trace)) - | Tags (l1, l2) -> - raise (Typetexp.Error (loc, !env, Typetexp.Variant_tags (l1, l2))) - | Unification_recursive_abbrev trace -> - raise (Error (loc, !env, Recursive_local_constraint trace)) + try unify_gadt ~newtype_level env ty ty' + with Unify trace -> raise (Error (loc, !env, Pattern_type_clash trace)) (* Creating new conjunctive types is not allowed when typing patterns *) @@ -1346,7 +1335,11 @@ and type_pat_aux ~constrs ~labels ~no_existentials ~mode ~explode ~env sp let p = {p with ppat_loc = loc} in type_pat ~explode:0 p expected_ty k (* TODO: record 'extra' to remember about interval *) - | Ppat_interval _ -> raise (Error (loc, !env, Invalid_interval)) + | Ppat_interval _ -> + (* unreachable: the ReScript parser (compiler/syntax/src/res_core.ml) has + no construction site for Ppat_interval — interval patterns are OCaml + syntax not part of the ReScript grammar *) + assert false | Ppat_tuple spl -> assert (List.length spl >= 2); let spl_ann = List.map (fun p -> (p, newvar ())) spl in @@ -1537,10 +1530,7 @@ and type_pat_aux ~constrs ~labels ~no_existentials ~mode ~explode ~env sp begin_def (); let vars, ty_arg, ty_res = instance_label false label in if vars = [] then end_def (); - (try unify_pat_types loc !env ty_res record_ty - with Unify trace -> - raise - (Error (label_lid.loc, !env, Label_mismatch (label_lid.txt, trace)))); + unify_pat_types loc !env ty_res record_ty; type_pat sarg ty_arg (fun arg -> if vars <> [] then ( end_def (); @@ -2001,19 +1991,6 @@ let rec type_approx env sexp = ty2 | _ -> newvar () -(* List labels in a function type, and whether return type is a variable *) -let rec list_labels_aux env visited ls ty_fun = - let ty = expand_head env ty_fun in - if List.memq ty visited then (List.rev ls, false) - else - match ty.desc with - | Tarrow (arg, ty_res, _, arity) when arity = None || visited = [] -> - list_labels_aux env (ty :: visited) (arg.lbl :: ls) ty_res - | _ -> (List.rev ls, is_Tvar ty) - -let list_labels env ty = - wrap_trace_gadt_instances env (list_labels_aux env [] []) ty - (* Check that all univars are safe in a type *) let check_univars env expans kind exp ty_expected vars = if expans && not (is_nonexpansive exp) then @@ -2043,13 +2020,12 @@ let check_univars env expans kind exp ty_expected vars = Less_general (kind, [(ty, ty); (ty_expected, ty_expected)]) )) (* Check that a type is not a function *) -let check_application_result env statement exp = - let loc = exp.exp_loc in +let check_application_result env exp = match (expand_head env exp.exp_type).desc with | Tarrow _ -> Location.prerr_warning exp.exp_loc Warnings.Partial_application | Tvar _ -> () | Tconstr (p, _, _) when Path.same p Predef.path_unit -> () - | _ -> if statement then Location.prerr_warning loc Warnings.Statement_type + | _ -> () (* Check that a type is generalizable at some level *) let generalizable level ty = @@ -2286,10 +2262,6 @@ let rec lower_args env seen ty_fun = lower_args env (ty :: seen) ty_fun | _ -> () -let not_function env ty = - let ls, tvar = list_labels env ty in - ls = [] && not tvar - let extract_function_name funct = match funct.exp_desc with | Texp_ident (path, _, _) -> Some (Longident.parse (Path.name path)) @@ -3117,7 +3089,12 @@ and type_expect_ ?deprecated_context ~context ?in_function ?(recarg = Rejected) val_kind = Val_reg; Types.val_loc = loc; } env ~check:(fun s -> Warnings.Unused_for_index s) - | _ -> raise (Error (param.ppat_loc, env, Invalid_for_of_pattern)) + | _ -> + (* unreachable: the parser's normalize_for_of_pattern + (compiler/syntax/src/res_core.ml:3841) catches every non-var, + non-`_` pattern, emits a syntax error, and replaces the pattern + with Ppat_any before the typer runs *) + assert false in let body = with_depth loop_depth (fun () -> @@ -3149,7 +3126,12 @@ and type_expect_ ?deprecated_context ~context ?in_function ?(recarg = Rejected) val_kind = Val_reg; Types.val_loc = loc; } env ~check:(fun s -> Warnings.Unused_for_index s) - | _ -> raise (Error (param.ppat_loc, env, Invalid_for_of_pattern)) + | _ -> + (* unreachable: the parser's normalize_for_of_pattern + (compiler/syntax/src/res_core.ml:3841) catches every non-var, + non-`_` pattern, emits a syntax error, and replaces the pattern + with Ppat_any before the typer runs *) + assert false in let body = with_depth loop_depth (fun () -> @@ -3471,12 +3453,6 @@ and type_expect_ ?deprecated_context ~context ?in_function ?(recarg = Rejected) and type_function ?in_function ~arity ~async loc attrs env ty_expected_ l caselist = - let state = Warnings.backup () in - (* Disable Unerasable_optional_argument for uncurried functions *) - let unerasable_optional_argument = - Warnings.number Unerasable_optional_argument - in - Warnings.parse_options false ("-" ^ string_of_int unerasable_optional_argument); let ty_expected = match arity with | None -> ty_expected_ @@ -3521,15 +3497,11 @@ and type_function ?in_function ~arity ~async loc attrs env ty_expected_ l ty_arg ty_res true loc caselist) in let case = List.hd cases in - if is_optional l && not_function env ty_res then - Location.prerr_warning case.c_lhs.pat_loc - Warnings.Unerasable_optional_argument; let param = name_pattern "param" cases in let exp_type = instance env (newgenty (Tarrow ({lbl = l; typ = ty_arg}, ty_res, Cok, arity))) in - Warnings.restore state; re { exp_desc = @@ -3750,10 +3722,6 @@ and type_application ~context total_app env funct (sargs : sargs) : newty2 lv (Tarrow ({lbl = l; typ = ty}, ty_fun, Cok, None))) ty_fun omitted in - let has_label l ty_fun = - let ls, tvar = list_labels env ty_fun in - tvar || List.mem l ls - in let ignored = ref [] in let force_tvar = let t = funct.exp_type in @@ -3888,10 +3856,15 @@ and type_application ~context total_app env funct (sargs : sargs) : raise (Error (sarg1.pexp_loc, env, Apply_wrong_label (l1, funct.exp_type))) - else if not (has_label l1 ty_fun) then + else + (* Originally split between Apply_wrong_label (label not in + ty_fun) and Incoherent_label_order (label in ty_fun but at + a different position). The latter is unreachable: modern + arity-aware unify in type_function eagerly compares against + ty_expected, raising Expr_type_clash before this branch + fires. Both label problems now surface as Apply_wrong_label. *) raise (Error (sarg1.pexp_loc, env, Apply_wrong_label (l1, ty_res))) - else raise (Error (funct.exp_loc, env, Incoherent_label_order)) | _ -> raise (Error @@ -3980,7 +3953,7 @@ and type_application ~context total_app env funct (sargs : sargs) : Location.prerr_warning exp.exp_loc Warnings.Partial_application | Tvar _ -> Delayed_checks.add_delayed_check (fun () -> - check_application_result env false exp) + check_application_result env exp) | _ -> ()); ([(Nolabel, Some exp)], ty_res, false) | _ -> @@ -4507,21 +4480,19 @@ let type_expression ~context env sexp = Typetexp.reset_type_variables (); begin_def (); let exp = type_exp ~context env sexp in - (if Warnings.is_active (Bs_toplevel_expression_unit None) then - try unify env exp.exp_type (instance_def Predef.type_unit) with - | Unify _ -> - let buffer = Buffer.create 10 in - let formatter = Format.formatter_of_buffer buffer in - Printtyp.type_expr formatter exp.exp_type; - Format.pp_print_flush formatter (); - let return_type = Buffer.contents buffer in - Location.prerr_warning sexp.pexp_loc - (Bs_toplevel_expression_unit - (match sexp.pexp_desc with - | Pexp_apply _ -> Some (return_type, FunctionCall) - | _ -> Some (return_type, Other))) - | Tags _ -> - Location.prerr_warning sexp.pexp_loc (Bs_toplevel_expression_unit None)); + if Warnings.is_active (Bs_toplevel_expression_unit None) then ( + try unify env exp.exp_type (instance_def Predef.type_unit) + with Unify _ -> + let buffer = Buffer.create 10 in + let formatter = Format.formatter_of_buffer buffer in + Printtyp.type_expr formatter exp.exp_type; + Format.pp_print_flush formatter (); + let return_type = Buffer.contents buffer in + Location.prerr_warning sexp.pexp_loc + (Bs_toplevel_expression_unit + (match sexp.pexp_desc with + | Pexp_apply _ -> Some (return_type, FunctionCall) + | _ -> Some (return_type, Other)))); end_def (); if not (is_nonexpansive exp) then generalize_expansive env exp.exp_type; generalize exp.exp_type; @@ -4694,6 +4665,14 @@ let report_error env loc ppf error = in fprintf ppf "@[@[<2>%a@]@,This function has type: %a@]" print_message l type_expr ty + | Abstract_wrong_label (l, ty) -> + let label_mark = function + | Nolabel -> "but its first argument is not labelled" + | l -> + sprintf "but its first argument is labelled %s" (prefixed_label_name l) + in + fprintf ppf "@[@[<2>This function should have type@ %a@]@,%s@]" type_expr + ty (label_mark l) | Label_multiply_defined {label; jsx_component_info = Some jsx_component_info} -> fprintf ppf @@ -4766,14 +4745,6 @@ let report_error env loc ppf error = else ( fprintf ppf "@[This expression should not be a function,@ "; fprintf ppf "the expected type is@ %a@]" type_expr ty) - | Abstract_wrong_label (l, ty) -> - let label_mark = function - | Nolabel -> "but its first argument is not labelled" - | l -> - sprintf "but its first argument is labelled %s" (prefixed_label_name l) - in - fprintf ppf "@[@[<2>This function should have type@ %a@]@,%s@]" type_expr - ty (label_mark l) | Scoping_let_module (id, ty) -> fprintf ppf "This `let module' expression has type@ %a@ " type_expr ty; fprintf ppf @@ -4785,10 +4756,6 @@ let report_error env loc ppf error = type_expr ty | Not_a_variant_type lid -> fprintf ppf "The type %a@ is not a variant type" longident lid - | Incoherent_label_order -> - fprintf ppf "This labeled function is applied to arguments@ "; - fprintf ppf "in an order different from other calls.@ "; - fprintf ppf "This is only allowed when the real type is known." | Less_general (kind, trace) -> (* modified *) super_report_unification_error ppf env trace @@ -4801,23 +4768,12 @@ let report_error env loc ppf error = | Not_a_packed_module ty -> fprintf ppf "This expression is packed module, but the expected type is@ %a" type_expr ty - | Recursive_local_constraint trace -> - (* modified *) - super_report_unification_error ppf env trace - (function - | ppf -> fprintf ppf "Recursive local constraint when unifying") - (function ppf -> fprintf ppf "with") | Unexpected_existential -> fprintf ppf "Unexpected existential" | Unqualified_gadt_pattern (tpath, name) -> fprintf ppf "@[The GADT constructor %s of type %a@ %s.@]" name Printtyp.path tpath "must be qualified in this pattern" - | Invalid_interval -> - fprintf ppf "@[Only character intervals are supported in patterns.@]" | Invalid_for_loop_index -> fprintf ppf "@[Invalid for-loop index: only variables and _ are allowed.@]" - | Invalid_for_of_pattern -> - fprintf ppf - "@[Invalid for...of binding: only variables and _ are allowed.@]" | No_value_clauses -> fprintf ppf "None of the patterns in this 'match' expression match values." | Exception_pattern_below_toplevel -> diff --git a/compiler/ml/typecore.mli b/compiler/ml/typecore.mli index 2a57356e73..10ff2ad8ca 100644 --- a/compiler/ml/typecore.mli +++ b/compiler/ml/typecore.mli @@ -76,6 +76,7 @@ type error = } | Apply_non_function of type_expr | Apply_wrong_label of arg_label * type_expr + | Abstract_wrong_label of arg_label * type_expr | Label_multiply_defined of { label: string; jsx_component_info: Error_message_utils.jsx_prop_error_info option; @@ -94,20 +95,15 @@ type error = | Not_subtype of Ctype.type_pairs * Ctype.type_pairs * Ctype.subtype_context option | Too_many_arguments of bool * type_expr - | Abstract_wrong_label of arg_label * type_expr | Scoping_let_module of string * type_expr | Not_a_variant_type of Longident.t - | Incoherent_label_order | Less_general of string * (type_expr * type_expr) list | Modules_not_allowed | Cannot_infer_signature | Not_a_packed_module of type_expr - | Recursive_local_constraint of (type_expr * type_expr) list | Unexpected_existential | Unqualified_gadt_pattern of Path.t * string - | Invalid_interval | Invalid_for_loop_index - | Invalid_for_of_pattern | No_value_clauses | Exception_pattern_below_toplevel | Inlined_record_escape diff --git a/compiler/ml/typedecl.ml b/compiler/ml/typedecl.ml index 0f44d4595f..07ce074622 100644 --- a/compiler/ml/typedecl.ml +++ b/compiler/ml/typedecl.ml @@ -34,9 +34,6 @@ type error = | Definition_mismatch of type_expr * Includecore.type_mismatch list | Constraint_failed of type_expr * type_expr | Inconsistent_constraint of Env.t * (type_expr * type_expr) list - | Type_clash of Env.t * (type_expr * type_expr) list - | Parameters_differ of Path.t * type_expr * type_expr - | Null_arity_external | Unbound_type_var of type_expr * type_declaration | Cannot_extend_private_type of Path.t | Not_extensible_type of Path.t @@ -46,10 +43,7 @@ type error = | Rebind_private of Longident.t | Bad_variance of int * (bool * bool * bool) * (bool * bool * bool) | Unavailable_type_constructor of Path.t - | Bad_fixed_type of string | Unbound_type_var_ext of type_expr * extension_constructor - | Varying_anonymous - | Val_in_structure | Invalid_attribute of string | Bad_immediate_attribute | Bad_unboxed_attribute of string @@ -114,7 +108,7 @@ let enter_type rec_flag env sdecl id = in Env.add_type ~check:true id decl env -let update_type temp_env env id loc = +let update_type temp_env env id _loc = let path = Path.Pident id in let decl = Env.find_type path temp_env in match decl.type_manifest with @@ -122,7 +116,11 @@ let update_type temp_env env id loc = | Some ty -> ( let params = List.map (fun _ -> Ctype.newvar ()) decl.type_params in try Ctype.unify env (Ctype.newconstr path params) ty - with Ctype.Unify trace -> raise (Error (loc, Type_clash (env, trace)))) + with Ctype.Unify _ -> + (* unreachable: every recursive abbreviation shape that would reach + this unify failure hits Cycle_in_def in check_recursive_type + (see line ~902 below) before check_coherence runs *) + assert false) (* We use the Ctype.expand_head_opt version of expand_head to get access to the manifest type of private abbreviations. *) @@ -174,7 +172,7 @@ let is_fixed_type sd = && sd.ptype_private = Private && has_row_var sty (* Set the row variable in a fixed type *) -let set_fixed_row env loc p decl = +let set_fixed_row env _loc p decl = let tm = match decl.type_manifest with | None -> assert false @@ -187,10 +185,17 @@ let set_fixed_row env loc p decl = tm.desc <- Tvariant {row with row_fixed = true}; if Btype.static_row row then Btype.newgenty Tnil else row.row_more | Tobject (ty, _) -> snd (Ctype.flatten_fields ty) - | _ -> raise (Error (loc, Bad_fixed_type "is not an object or variant")) + | _ -> + (* unreachable: gated by `is_fixed_type decl`, which only returns true + when the syntactic manifest carries an open polymorphic-variant or + object row. `expand_head` preserves that row, so the manifest's + desc is always Tvariant or Tobject here. *) + assert false in if not (Btype.is_Tvar rv) then - raise (Error (loc, Bad_fixed_type "has no row variable")); + (* unreachable: same is_fixed_type invariant — the row is always a Tvar + (or extended-Tvar) when is_fixed_type passes *) + assert false; rv.desc <- Tconstr (p, decl.type_params, ref Mnil) (* Translate one type declaration *) @@ -981,12 +986,14 @@ let check_recursion env loc path decl to_check = match ty.desc with | Tconstr (path', args', _) -> (if Path.same path path' then ( - if not (Ctype.equal env false args args') then - raise - (Error - ( loc, - Parameters_differ (cpath, ty, Ctype.newconstr path args) - ))) + if not (Ctype.equal env false args args') then ( + (* unreachable: check_regular runs only on abbreviations, + and every recursive-abbreviation shape hits Cycle_in_def + in the earlier check_recursive_type pass before reaching + here. Variant constructors with non-uniform recursion + (`type rec t<'a> = T(t)`) don't trigger check_regular. *) + ignore cpath; + assert false)) else if (* Attempt to expand a type abbreviation if: 1- [to_check path'] holds @@ -1239,7 +1246,7 @@ let for_constr = function (fun {Types.ld_mutable; ld_type} -> (ld_mutable = Mutable, ld_type)) l -let compute_variance_gadt env check ((required, loc) as rloc) decl +let compute_variance_gadt env check ((required, _loc) as rloc) decl (tl, ret_type_opt) = match ret_type_opt with | None -> @@ -1260,7 +1267,11 @@ let compute_variance_gadt env check ((required, loc) as rloc) decl | fv :: fv2 -> (* fv1 @ fv2 = free_variables of other parameters *) if (c || n) && constrained (fv1 @ fv2) ty then - raise (Error (loc, Varying_anonymous)); + (* unreachable: this would fire on a GADT parameter that's + `_` (anonymous). ReScript's parser rejects `_` in + `type t<...>` parameter positions, so the typer never + sees the required AST shape. *) + assert false; (fv :: fv1, fv2)) ([], fvl) tyl required in @@ -1884,7 +1895,13 @@ let transl_value_decl env loc valdecl = Types.val_loc = loc; val_attributes = valdecl.pval_attributes; } - | [] -> raise (Error (valdecl.pval_loc, Val_in_structure)) + | [] -> + (* unreachable: `pval_prim = []` outside a signature can only arise + from the parser's `external` recovery, which sets `prim = []` + *after* emitting a syntax error, so the typer never sees the + declaration. A bare `val x: int` in a .res is also rejected at + parse time. *) + assert false | _ -> let arity, from_constructor = parse_arity env valdecl.pval_type ty in let prim = Primitive.parse_declaration valdecl ~arity ~from_constructor in @@ -1897,7 +1914,13 @@ let transl_value_decl env loc valdecl = && String.unsafe_get prim_native_name 1 = '\149')) && (prim.prim_name = "" || (prim.prim_name.[0] <> '%' && prim.prim_name.[0] <> '#')) - then raise (Error (valdecl.pval_type.ptyp_loc, Null_arity_external)); + then + (* unreachable: Primitive.parse_declaration always assigns the + magic 20-byte prim_native_name encoding to externals; the + `prim_native_name = ""` precondition can't be satisfied alongside + `prim_arity = 0` from any externals that survive parsing. Empty + prim names are rejected earlier with `Not a valid global name`. *) + assert false; { val_type = ty; val_kind = Val_prim prim; @@ -2153,22 +2176,11 @@ let report_error ppf = function fprintf ppf "@[%s@ @[Type@ %a@ should be an instance of@ %a@]@]" "Constraints are not satisfied in this type." Printtyp.type_expr ty Printtyp.type_expr ty' - | Parameters_differ (path, ty, ty') -> - Printtyp.reset_and_mark_loops ty; - Printtyp.mark_loops ty'; - fprintf ppf "@[In the definition of %s, type@ %a@ should be@ %a@]" - (Path.name path) Printtyp.type_expr ty Printtyp.type_expr ty' | Inconsistent_constraint (env, trace) -> fprintf ppf "The type constraints are not consistent.@."; Printtyp.report_unification_error ppf env trace (fun ppf -> fprintf ppf "Type") (fun ppf -> fprintf ppf "is not compatible with type") - | Type_clash (env, trace) -> - Printtyp.report_unification_error ppf env trace - (function - | ppf -> fprintf ppf "This type constructor expands to type") - (function ppf -> fprintf ppf "but is used here with type") - | Null_arity_external -> fprintf ppf "External identifiers must be functions" | Unbound_type_var (ty, decl) -> ( fprintf ppf "A type variable is unbound in this type declaration"; let ty = Ctype.repr ty in @@ -2256,12 +2268,6 @@ let report_error ppf = function (variance v1) | Unavailable_type_constructor p -> fprintf ppf "The definition of type %a@ is unavailable" Printtyp.path p - | Bad_fixed_type r -> fprintf ppf "This fixed type %s" r - | Varying_anonymous -> - fprintf ppf "@[%s@ %s@ %s@]" "In this GADT definition," - "the variance of some parameter" "cannot be checked" - | Val_in_structure -> - fprintf ppf "Value declarations are only allowed in signatures" | Bad_immediate_attribute -> fprintf ppf "@[%s@ %s@]" "Types marked with the immediate attribute must be" "non-pointer types like int or bool" diff --git a/compiler/ml/typemod.ml b/compiler/ml/typemod.ml index 0932c62f34..e823d4ac82 100644 --- a/compiler/ml/typemod.ml +++ b/compiler/ml/typemod.ml @@ -1818,11 +1818,6 @@ let report_error ppf = function fprintf ppf "@[This module is not a functor; it has type@ %a@]" modtype mty | Not_included errs -> fprintf ppf "@[Signature mismatch:@ %a@]" Includemod.report_error errs - | Cannot_eliminate_dependency mty -> - fprintf ppf - "@[This functor has type@ %a@ The parameter cannot be eliminated in the \ - result type.@ Bind the argument to a module identifier.@]" - modtype mty | Signature_expected -> fprintf ppf "This module type is not a signature" | Structure_expected mty -> fprintf ppf "@[This module is not a structure; it has type@ %a" modtype mty @@ -1840,16 +1835,16 @@ let report_error ppf = function "@[@[This `with' constraint on %a makes the applicative functor @ \ type %s ill-typed in the constrained signature:@]@ %a@]" longident lid (Path.name path) Includemod.report_error explanation - | With_changes_module_alias (lid, id, path) -> - fprintf ppf - "@[@[This `with' constraint on %a changes %s, which is aliased @ in \ - the constrained signature (as %s)@].@]" - longident lid (Path.name path) (Ident.name id) | With_cannot_remove_constrained_type -> fprintf ppf "@[Destructive substitutions are not supported for constrained @ \ types (other than when replacing a type constructor with @ a type \ constructor with the same arguments).@]" + | With_changes_module_alias (lid, id, path) -> + fprintf ppf + "@[@[This `with' constraint on %a changes %s, which is aliased @ in \ + the constrained signature (as %s)@].@]" + longident lid (Path.name path) (Ident.name id) | Repeated_name (kind, name, repeated_loc) -> fprintf ppf "@[Multiple definition of the %s name %s @ at @{%a@}@ @ Names must \ @@ -1878,6 +1873,11 @@ let report_error ppf = function | Interface_not_compiled intf_name -> fprintf ppf "@[Could not find the .cmi file for interface@ %a.@]" Location.print_filename intf_name + | Cannot_eliminate_dependency mty -> + fprintf ppf + "@[This functor has type@ %a@ The parameter cannot be eliminated in the \ + result type.@ Bind the argument to a module identifier.@]" + modtype mty | Not_allowed_in_functor_body -> fprintf ppf "@[This expression creates fresh types.@ %s@]" "It is not allowed inside applicative functors." diff --git a/compiler/ml/typetexp.ml b/compiler/ml/typetexp.ml index 9867baac11..fb248c0198 100644 --- a/compiler/ml/typetexp.ml +++ b/compiler/ml/typetexp.ml @@ -28,7 +28,6 @@ exception Already_bound type error = | Unbound_type_variable of string | Unbound_type_constructor of Longident.t - | Unbound_type_constructor_2 of Path.t | Type_arity_mismatch of Longident.t * int * int | Type_mismatch of (type_expr * type_expr) list | Alias_type_mismatch of (type_expr * type_expr) list @@ -36,7 +35,6 @@ type error = | Present_has_no_type of string | Constructor_mismatch of type_expr * type_expr | Not_a_variant of type_expr - | Variant_tags of string * string | Invalid_variable_name of string | Cannot_quantify of string * type_expr | Multiple_constraints_on_type of Longident.t @@ -46,10 +44,8 @@ type error = | Unbound_label of Longident.t * type_expr option | Unbound_module of Longident.t | Unbound_modtype of Longident.t - | Ill_typed_functor_application of Longident.t | Illegal_reference_to_recursive_module | Access_functor_as_structure of Longident.t - | Apply_structure_as_functor of Longident.t | Cannot_scrape_alias of Longident.t * Path.t | Opened_object of Path.t option | Not_an_object of type_expr @@ -90,7 +86,11 @@ let rec narrow_unbound_lid_error : 'a. _ -> _ -> _ -> _ -> 'a = let fmd = Env.find_module (Env.lookup_module ~load:true flid env) env in (match Env.scrape_alias env fmd.md_type with | Mty_signature _ -> - raise (Error (loc, env, Apply_structure_as_functor flid)) + (* unreachable: this branch handles Longident.Lapply paths, but + Lapply has no construction site in compiler/syntax/src/ — ReScript's + type-level applicative-functor syntax (OCaml's M(X).t) isn't part + of the grammar *) + assert false | Mty_alias (_, p) -> raise (Error (loc, env, Cannot_scrape_alias (flid, p))) | _ -> ()); @@ -99,7 +99,9 @@ let rec narrow_unbound_lid_error : 'a. _ -> _ -> _ -> _ -> 'a = match Env.scrape_alias env mmd.md_type with | Mty_alias (_, p) -> raise (Error (loc, env, Cannot_scrape_alias (mlid, p))) - | _ -> raise (Error (loc, env, Ill_typed_functor_application lid)))); + | _ -> + (* unreachable: same Lapply path as above *) + assert false)); raise (Error (loc, env, make_error lid)) let find_component (lookup : ?loc:_ -> _) make_error env loc lid = @@ -472,7 +474,13 @@ and transl_type_aux env policy styp = let row = Btype.row_repr row in row.row_fields | {desc = Tvar _}, Some (p, _) -> - raise (Error (sty.ptyp_loc, env, Unbound_type_constructor_2 p)) + (* unreachable: this requires the inherited type's body to be a + bare Tvar Tconstr, which only arises from `type 'a t = 'a`- + style declarations. ReScript syntax requires type parameters + in angle brackets (`type t<'a> = 'a`); the leading-`'a` form + is rejected at parse time *) + ignore p; + assert false | _ -> raise (Error (sty.ptyp_loc, env, Not_a_variant ty)) in List.iter @@ -616,7 +624,10 @@ and transl_fields env policy o fields = iter_add tf; OTinherit cty | {desc = Tvar _}, Some p -> - raise (Error (sty.ptyp_loc, env, Unbound_type_constructor_2 p)) + (* unreachable: same `type 'a t = 'a` shape as above; the bare-Tvar + Tconstr body can't be constructed from ReScript syntax *) + ignore p; + assert false | _ -> raise (Error (sty.ptyp_loc, env, Not_an_object t))) in let object_fields = List.map add_field fields in @@ -780,8 +791,6 @@ let report_error env ppf = function Format.fprintf ppf "If you wanted to write a recursive type, don't forget the `rec` in \ `type rec`@]" - | Unbound_type_constructor_2 p -> - fprintf ppf "The type constructor@ %a@ is not yet completely defined" path p | Type_arity_mismatch (lid, expected, provided) -> if expected == 0 then fprintf ppf @@ -824,11 +833,6 @@ let report_error env ppf = function (* PR#7012: help the user that wrote 'Foo instead of `Foo *) Misc.did_you_mean ppf (fun () -> ["`" ^ s]) | _ -> ()) - | Variant_tags (lab1, lab2) -> - fprintf ppf "@[Variant tags %s@ and %s have the same hash value.@ %s@]" - (!Printtyp.print_res_poly_identifier lab1) - (!Printtyp.print_res_poly_identifier lab2) - "Change one of them." | Invalid_variable_name name -> fprintf ppf "The type variable name %s is not allowed in programs" name | Cannot_quantify (name, v) -> @@ -960,14 +964,10 @@ let report_error env ppf = function | Unbound_modtype lid -> fprintf ppf "Unbound module type %a" longident lid; spellcheck ppf fold_modtypes env lid - | Ill_typed_functor_application lid -> - fprintf ppf "Ill-typed functor application %a" longident lid | Illegal_reference_to_recursive_module -> fprintf ppf "Illegal recursive module reference" | Access_functor_as_structure lid -> fprintf ppf "The module %a is a functor, not a structure" longident lid - | Apply_structure_as_functor lid -> - fprintf ppf "The module %a is a structure, not a functor" longident lid | Cannot_scrape_alias (lid, p) -> fprintf ppf "The module %a is an alias for module %a, which is missing" longident lid path p diff --git a/compiler/ml/typetexp.mli b/compiler/ml/typetexp.mli index 8f40096392..565535cb09 100644 --- a/compiler/ml/typetexp.mli +++ b/compiler/ml/typetexp.mli @@ -37,7 +37,6 @@ exception Already_bound type error = | Unbound_type_variable of string | Unbound_type_constructor of Longident.t - | Unbound_type_constructor_2 of Path.t | Type_arity_mismatch of Longident.t * int * int | Type_mismatch of (type_expr * type_expr) list | Alias_type_mismatch of (type_expr * type_expr) list @@ -45,7 +44,6 @@ type error = | Present_has_no_type of string | Constructor_mismatch of type_expr * type_expr | Not_a_variant of type_expr - | Variant_tags of string * string | Invalid_variable_name of string | Cannot_quantify of string * type_expr | Multiple_constraints_on_type of Longident.t @@ -55,10 +53,8 @@ type error = | Unbound_label of Longident.t * type_expr option | Unbound_module of Longident.t | Unbound_modtype of Longident.t - | Ill_typed_functor_application of Longident.t | Illegal_reference_to_recursive_module | Access_functor_as_structure of Longident.t - | Apply_structure_as_functor of Longident.t | Cannot_scrape_alias of Longident.t * Path.t | Opened_object of Path.t option | Not_an_object of type_expr diff --git a/tests/ERROR_VARIANTS.md b/tests/ERROR_VARIANTS.md index 6f45ebbbf4..22ca2a50f3 100644 --- a/tests/ERROR_VARIANTS.md +++ b/tests/ERROR_VARIANTS.md @@ -11,8 +11,7 @@ The catalog has two practical uses: AST shape. 2. **Dead-code removal** — rows tagged `⚠` are variants whose trigger site is unreachable in the current parser / compiler, with a named - blocker. They can be deleted in a follow-up PR. The "Confirmed dead" - summary at the bottom groups them by reason. + blocker. They can be deleted in a follow-up PR. ## Status legend @@ -23,7 +22,8 @@ The catalog has two practical uses: | ☐ | Reachable but no fixture yet; would be valuable to add. | | ? | Trigger site is live but reachability from regular ReScript source isn't confirmed. Distinct from ⚠: a `?` means "I couldn't find a fixture that reaches it" rather than "the path is provably blocked". | -The "Confirmed dead" summary section at the bottom only includes ⚠. +The removal audit section below records variants that have already been +deleted or retained after re-validation. ## Scope @@ -55,6 +55,84 @@ If a variant turns out to be unreachable, document the named blocker here (so it gets ⚠ instead of `?`) and file a follow-up to delete the dead code. +## Removed in `jono/remove-dead-errors` + +Two classes of removal. **Truly dead** variants — no raise site under +`compiler/`, or a guard whose predicate is always false — are deleted +entirely (declaration, raise, reporter, supporting helpers). **Defensive +unreachable** variants whose raise sites exist but are unreachable from +the ReScript parser keep their named-variant form removed and the raise +site is replaced with `assert false (* reason *)`, matching the +established convention in the typer modules (57 existing uses). + +**Truly dead — declaration + raise + reporter all removed:** + +- `ctype`: `Tags`, `Recursive_abbrev`, + `Unification_recursive_abbrev` exceptions (declared, never raised) +- `typecore`: `Recursive_local_constraint` (relay wrapper for the dead + `Unification_recursive_abbrev`) +- `typetexp`: `Variant_tags` (relay wrapper for the dead `Tags`) +- `bs_syntaxerr`: `Conflict_bs_bs_this_bs_meth` (no construction site) +- `warnings`: `Comment_start`, `Comment_not_end`, `Method_override`, + `Instance_variable_override`, `Illegal_backslash`, + `Implicit_public_methods`, `Eol_in_string`, + `Eliminated_optional_arguments`, `Bad_docstring`, + `Bs_fragile_external`, `Bs_unimplemented_primitive` (declared, + never raised); `Statement_type` (caller hard-codes `statement=false`), + `Unerasable_optional_argument` (disabled around its only check), + `Bs_uninterpreted_delimiters` (trigger AST rewritten by builtin PPX + before the warning iterator runs) + +**Defensive unreachable — raise site becomes `assert false (* reason *)`, +variant + reporter removed:** + +- `typecore`: `Incoherent_label_order` (modern arity-aware unify fires + `Expr_type_clash` before this branch), `Invalid_interval` (parser + doesn't construct `Ppat_interval`), `Invalid_for_of_pattern` (parser's + `normalize_for_of_pattern` replaces non-var patterns with `Ppat_any`) +- `typetexp`: `Unbound_type_constructor_2` (needs bare-`Tvar` Tconstr + body via `type 'a t = 'a`, parser-rejected), + `Ill_typed_functor_application`, `Apply_structure_as_functor` (both + need `Longident.Lapply`, never constructed by the parser) +- `typedecl`: `Type_clash`, `Parameters_differ` (every recursive + abbreviation hits `Cycle_in_def` first), `Null_arity_external` + (`Primitive.parse_declaration` always assigns the magic + `prim_native_name` encoding), `Bad_fixed_type` (`is_fixed_type` and + `expand_head` agree on every parser-produced shape), + `Varying_anonymous` (parser rejects `_` in type parameter positions), + `Val_in_structure` (`pval_prim = []` outside a signature is only + produced by external-recovery after a syntax error) +- `bs_syntaxerr`: `Unhandled_poly_type` (parser misreads inline `'a.` + as deprecated uncurried syntax) +- `env`: `Illegal_value_name` (parser doesn't emit `"->"` or + `#`-containing identifiers) + +Re-validation found a number of previously-flagged items that are not +completely dead and have been retained as named variants: + +- `typedecl.Rebind_wrong_type` — live via extension rebinding across + incompatible extension types. +- `typecore.Label_mismatch` — live when a record literal without an + expected type mixes fields from two different record types + (`label_mismatch_record_literal.res`). +- `typecore.Abstract_wrong_label` — live when a multi-arg function + literal has a mislabelled inner argument (`abstract_wrong_label.res`). +- `typemod.With_cannot_remove_constrained_type` — live when destructive + substitution is applied to a constrained type + (`with_cannot_remove_constrained_type.res`). +- `bs_syntaxerr.Misplaced_label_syntax` — live when labelled args are + passed via operator-identifier syntax like `\"->"(x, ~b=...)` + (`misplaced_label_syntax.res`). +- `typemod.Cannot_eliminate_dependency`, `typemod.Scoping_pack`, + `typemod.With_makes_applicative_functor_ill_typed` — reproduction + attempts couldn't reach them but couldn't conclusively prove + unreachability either; retained on the conservative side. +- `includemod.Unbound_modtype_path` can still represent a stale + compiled-interface failure. +- `Syntaxerr.Variable_in_scope` is live but lacks a registered printer. +- The UTF-8 helper error families are still raised by test/defensive + helper entry points. + --- ## `compiler/ml/typecore.ml` @@ -66,7 +144,6 @@ Source: [typecore.ml:27](../compiler/ml/typecore.ml). |---|---|---|---| | `Polymorphic_label` | ✓ | `polymorphic_label.res` | Pattern that instantiates a polymorphic record field: `({f: (f: int => int)}: t) =>` constrains the universal `'a` of `f: 'a. 'a => 'a` to `int => int`. | | `Constructor_arity_mismatch` | ✓ | `constructor_arity_mismatch.res`, `constructor_arity_mismatch_pattern.res`, `arity_mismatch*.res` | Triggers in both expression (4028) and pattern (1426) paths. | -| `Label_mismatch` | ⚠ | — | typecore.ml:1543/3589. Defensive `try unify ty_res ty_expected with Unify -> Label_mismatch`. The only way to reach the unify is after label disambiguation (`type_label_a_list` / `type_label_pat` / `Wrong_name`-style logic), which always locks `ty_res` to a record type already unifiable with the expected. The unify therefore can't fail in practice — every reproduction hits `Wrong_name`, `Pattern_type_clash`, or `Expr_type_clash` instead. The constructor is a defensive leftover from the OCaml inheritance. | | `Pattern_type_clash` | ✓ | many `*_pattern_type_clash.res` etc. | Most-fired pattern error. Sub-case fixtures: `pattern_matching_on_option_but_value_not_option.res` and `pattern_matching_on_value_but_is_option.res` (option-vs-non-option trace), `pattern_type_clash_polyvariant.res` (polyvariant tag against concrete type), `pattern_type_clash_tuple_arity.res` (tuple arity mismatch). | | `Or_pattern_type_clash` | ✓ | `or_pattern_type_clash.res` | | | `Multiply_bound_variable` | ✓ | `multiply_bound_variable.res` | | @@ -74,6 +151,8 @@ Source: [typecore.ml:27](../compiler/ml/typecore.ml). | `Expr_type_clash` | ✓ | many `*.res` | Most-fired expression error. Trace-shape sub-cases covered: `if_return_type_mismatch.res` (IfReturn), `maybe_unwrap_option.res` (MaybeUnwrapOption), `string_concat_non_string.res` (StringConcat), `labeled_fn_argument_type_clash.res` (FunctionArgument with explicit label), `math_operator_*.res` (MathOperator family), `ternary_branch_mismatch.res`, `switch_different_types.res`, `try_catch_same_type.res`, `comparison_operator.res`, `array_item_type_mismatch.res`, `array_literal_passed_to_tuple.res`, `if_condition_mismatch.res`, `while_condition.res`, `for_loop_condition.res`, `assert_condition.res`, `function_call_mismatch.res`, `awaiting_non_promise.res`, multiple `jsx_*` fixtures. | | `Apply_non_function` | ✓ | `apply_non_function.res` | | | `Apply_wrong_label` | ✓ | `apply_wrong_label.res` | | +| `Abstract_wrong_label` | ✓ | `abstract_wrong_label.res` | Multi-arg function literal where an inner argument label doesn't match the expected arrow's label (e.g. `let f: (~a, ~b) => int = (~a, ~c) => …`). | +| `Label_mismatch` | ✓ | `label_mismatch_record_literal.res` | Record literal without expected type mixing fields from two different record types — disambiguation picks one type per label, and the cross-type unify fails inside `type_label_exp`. | | `Label_multiply_defined` | ✓ | `label_multiply_defined_literal.res` | | | `Labels_missing` | ✓ | `missing_label.res`, `missing_labels.res` | | | `Label_not_mutable` | ✓ | `label_not_mutable.res` | | @@ -84,20 +163,15 @@ Source: [typecore.ml:27](../compiler/ml/typecore.ml). | `Private_label` | ✓ | `private_label.res` | | | `Not_subtype` | ✓ | `subtype_*.res`, `dict_show_no_coercion.res`, etc. | | | `Too_many_arguments` | ✓ | `too_many_arguments.res`, `moreArguments*.res` | | -| `Abstract_wrong_label` | ⚠ | — | typecore.ml:3502. Fires in `type_function` when `filter_arrow` with the literal's label fails *and* the expected type is `Tarrow`. In modern ReScript the function literal's type is fully inferred from its own args first, then unified — that path emits `Expr_type_clash`, not `Abstract_wrong_label`. Several attempted reproductions all surfaced as `Expr_type_clash`. Treating as effectively dead. | | `Scoping_let_module` | ✓ | `scoping_let_module.res` | | | `Not_a_variant_type` | ✓ | `variant_spread_pattern_not_a_variant.res` | Pattern-level variant spread of a non-variant type. | -| `Incoherent_label_order` | ⚠ | — | typecore.ml:3894. Reached only after `arity_ok` is true *and* the label is present in `ty_fun` but not at the current arrow position. ReScript's labeled-argument reordering happens earlier in `type_args` / `type_unknown_args`, so by the time we hit this branch the label is already at the right position. Every attempted reproduction landed on `Apply_wrong_label` or `Expr_type_clash`. | | `Less_general` | ✓ | `less_general_universal.res` | | | `Modules_not_allowed` | ✓ | `super_errors_multi/Modules_not_allowed_toplevel` | Toplevel `let module(M) = …` pattern with `allow_modules=false`. | | `Cannot_infer_signature` | ✓ | `cannot_infer_signature.res` | | | `Not_a_packed_module` | ✓ | `not_a_packed_module.res` | | -| `Recursive_local_constraint` | ⚠ | — | typecore.ml:369. Routed via `Unification_recursive_abbrev` in `ctype.ml`, which is raised only when `ctype.ml`'s `Recursive_abbrev` exception fires. **`Recursive_abbrev` is defined (ctype.ml:110, ctype.mli:61) but never raised anywhere in `compiler/`.** Confirmed dead. | | `Unexpected_existential` | ✓ | `super_errors_multi/Unexpected_existential_in_let` | Destructuring GADT constructor with existential in toplevel `let`. | | `Unqualified_gadt_pattern` | ✓ | `super_errors_multi/Cross_gadt_pattern` | Only reachable via cross-module GADT disambiguation; in single-file matching the constructor would resolve before this check. | -| `Invalid_interval` | ⚠ | — | typecore.ml:1349. Triggered by `Ppat_interval` pattern. **Verified: `Ppat_interval` has no construction site in `compiler/syntax/src/res_core.ml`** — only printer and ast_debugger handle it. | | `Invalid_for_loop_index` | ✓ | `invalid_for_loop_index.res` | | -| `Invalid_for_of_pattern` | ⚠ | — | typecore.ml:3120/3152. Verified: parser `normalize_for_of_pattern` (`res_core.ml:3841`) replaces non-var / non-`_` patterns with `Ppat_any` before the typer sees them. | | `No_value_clauses` | ✓ | `no_value_clauses.res` | | | `Exception_pattern_below_toplevel` | ✓ | `exception_pattern_below_toplevel.res` | | | `Inlined_record_escape` | ✓ | `inline_record_escape.res` | | @@ -133,22 +207,16 @@ Type-declaration errors. Source: [typedecl.ml:27](../compiler/ml/typedecl.ml). | `Definition_mismatch` | ✓ | `definition_mismatch.res` | | | `Constraint_failed` | ✓ | `constraint_failed.res` | | | `Inconsistent_constraint` | ✓ | `inconsistent_constraint.res` | | -| `Type_clash` | ⚠ | — | typedecl.ml:125. Fires when `Ctype.unify env (newconstr path params) manifest` fails inside `update_type` for a `type rec` block. For ReScript types this unify either trivially succeeds (aliases unify with their manifest because the cycle/arity machinery has already accepted the shape) or the declaration is rejected earlier by `Cycle_in_def` / `Recursive_abbrev`. I couldn't construct a recursive shape that reaches the failing unify without being caught first. | -| `Parameters_differ` | ⚠ | — | typedecl.ml:988. Fires for non-uniform recursive type *abbreviations* (`type rec t<'a> = … t …`). ReScript treats variant types as having a manifest of None, so `check_regular` is a no-op for them. For abbreviations, `Cycle_in_def` fires first because the recursive reference is direct. I couldn't construct an abbreviation shape that hits Parameters_differ without being cyclic. | -| `Null_arity_external` | ⚠ | — | typedecl.ml:1900. The guard requires `prim_arity = 0` and `prim_native_name` not having the magic 20-byte encoding (`\132\149...`) and `prim_name` not starting with `%` or `#`. The encoding gets applied to every concrete external by `Primitive.parse_declaration`, and empty `prim_name` is rejected earlier by `external_ffi_types.ml` with "Not a valid global name". No path through the parser reaches it. | | `Unbound_type_var` | ✓ | `unbound_type_var.res` | | | `Cannot_extend_private_type` | ✓ | `cannot_extend_private_type.res` | | | `Not_extensible_type` | ✓ | `not_extensible_type.res` | | | `Extension_mismatch` | ✓ | `extension_arity_mismatch.res` | `type t<'a> = ..` extended with `type t += A(int)` — arity differs from the extensible type. | -| `Rebind_wrong_type` | ⚠ | — | typedecl.ml:1653. The unify is `cstr_res` (source constructor's result, freshly instantiated) against `res` (extension's target type with fresh param vars). For non-GADT sources both sides are `t` and trivially unify; for GADT-style sources (`type t<'a> += A: t`) `cstr_res = t` against `res = t` still unifies (`v1 := int`). The parser doesn't allow rebinding with explicit args (`exception B(string) = A` is rejected at `res_core.ml:6660`), so the result-type relationship is always compatible by construction. | -| `Rebind_mismatch` | ✓ | `extension_rebind_mismatch.res` | Rebinding constructor into a different extensible type. | +| `Rebind_wrong_type` | ✓ | `extension_rebind_mismatch.res` | Rebinding constructor into a different extensible type fails while unifying the source constructor result with the extension target. | +| `Rebind_mismatch` | ? | — | The later declaration-shape check after `Rebind_wrong_type`; no source fixture was confirmed in this pass. | | `Rebind_private` | ✓ | `extension_rebind_private.res` | Rebinding a private extension constructor as public. | | `Bad_variance` | ✓ | `bad_variance.res`, `bad_variance_contra.res` | | | `Unavailable_type_constructor` | ☐ (needs build harness) | — | typedecl.ml:778. Requires a type path findable at parse time but missing during constraint enforcement; only cross-unit scenarios where a `.cmi` was found but later removed. | -| `Bad_fixed_type` | ⚠ | — | typedecl.ml:190/193. `set_fixed_row` runs only when `is_fixed_type` returns true, which requires a `private` abstract type with a syntactically open object / polyvariant manifest (typedecl.ml:160-174). For a manifest written that way, `expand_head` returns exactly the same `Tobject` / `Tvariant`, so the check at line 190 passes and the row variable check at line 193 also passes (rows from those syntactic forms have a Tvar `row_more`). No alias chain in ReScript syntax can collapse the open row while still passing `has_row_var` on the syntactic side. | | `Unbound_type_var_ext` | ✓ | `unbound_type_var_extension.res` | | -| `Varying_anonymous` | ⚠ | — | typedecl.ml:1263. Fires in variance computation when an anonymous (`_`) type parameter is constrained against other params under specific variance requirements. ReScript's parser doesn't produce `_` in type parameter position for `type` declarations (`type t<_>` is rejected) — only explicit `'x`-style params, which are never "anonymous" in the sense `Varying_anonymous` checks. | -| `Val_in_structure` | ⚠ | — | typedecl.ml:1887 requires `pval_prim = []` outside a signature. The parser's `external` recovery sets `prim = []` (`res_core.ml:6617`) but only after emitting a `Syntax error`, so the typechecker never reaches the value declaration. From plain source there's no path that produces a non-signature `Val` with empty `pval_prim` — only PPX-rewritten AST could, and the AST shape would have to bypass the parser. | | `Invalid_attribute` | ✓ | `invalid_attribute_not_undefined.res` | | | `Bad_immediate_attribute` | ✓ | `bad_immediate_attribute.res` | | | `Bad_unboxed_attribute` | ✓ | `bad_unboxed_attribute_abstract.res`, `bad_unboxed_attribute_mutable.res`, `bad_unboxed_attribute_many_fields.res`, `bad_unboxed_attribute_extensible.res` | All 4 sub-cases covered. | @@ -167,14 +235,15 @@ Module-level errors. Source: [typemod.ml:24](../compiler/ml/typemod.ml). |---|---|---|---| | `Cannot_apply` | ✓ | `cannot_apply_non_functor.res` | | | `Not_included` | ✓ | All `super_errors_multi/Iface_*` fixtures wrap to this via `compunit`. | | -| `Cannot_eliminate_dependency` | ⚠ | — | typemod.ml:1335. Reached only when `Mtype.nondep_supertype` raises `Not_found` for an anonymous functor application. ReScript's `nondep_supertype` falls back to existential abstraction for any module-typed binding it can't eliminate cleanly, so the `Not_found` branch never fires. Multiple anonymous functor applications (including ones where the result genuinely references the argument's abstract type) all type-check. | | `Signature_expected` | ✓ | `typemod_signature_expected.res` | `with type M.t = …` where `M` is functor-typed inside the outer signature. | | `Structure_expected` | ✓ | `super_errors_multi/Smoke_unbound_module_reference` (indirect); also `open_functor.res` | | | `With_no_component` | ✓ | `with_no_component.res` | | | `With_mismatch` | ✓ | `with_mismatch.res` | | -| `With_makes_applicative_functor_ill_typed` | ⚠ | — | typemod.ml:258. Reached only through the applicative-functor path of `Btype.it_path` (`Papply`); ReScript's parser doesn't emit `Papply` (no parsed construction site in `res_core.ml`), so the iterator never visits this branch. | +| `With_makes_applicative_functor_ill_typed` | ? | — | typemod.ml:249. Fires when a `with` constraint on a signature containing a `Path.Papply` makes that application ill-typed. Reachable via destructive substitution on applicative functors; reproduction attempts surfaced `not a signature` first. Retained on the conservative side. | +| `With_cannot_remove_constrained_type` | ✓ | `with_cannot_remove_constrained_type.res` | Destructive substitution on a constrained type, e.g. `S with type t<'a> := 'a` where `S` has `type t<'a> constraint 'a = int`. | | `With_changes_module_alias` | ☐ (needs build harness) | — | typemod.ml:240. Fires during `with module := M2` substitution when an aliased sub-module inside the constrained signature is affected. ReScript parses `with module N := M2` (destructive substitution), but constructing a sub-module alias chain that gets invalidated requires multiple `.resi` files and a specific shape I couldn't reproduce single-file. | -| `With_cannot_remove_constrained_type` | ⚠ | — | typemod.ml:443. Fires for `Twith_typesubst` (the `:=` form) when `params_are_constrained` returns true — i.e. the substitution's params are non-`Tvar`. The parser only accepts `'x`-style identifiers in `with type X<…>` param positions (`res_core.ml` rejects `with type x := …` with "Type params start with a singlequote"), so the params are always fresh `Tvar`s and the check never triggers. | +| `Cannot_eliminate_dependency` | ? | — | typemod.ml:1332. Fires when `Mtype.nondep_supertype` raises `Not_found` during functor-application result-type computation. Reproduction attempts routed through `Incomplete_packed_module` or `escapes its scope`. Retained on the conservative side. | +| `Scoping_pack` | ? | — | typemod.ml:1717. Fires during first-class module packing with `with type` constraints whose constrained type isn't a free `Tvar`. Reproduction attempts routed through `Incomplete_packed_module`. Retained on the conservative side. | | `Repeated_name` | ✓ | `repeated_def_*.res` (multiple) | | | `Non_generalizable` | ✓ | `non_generalizable.res` | | | `Non_generalizable_module` | ✓ | `non_generalizable_module.res` | Nested module containing `let r = ref(None)` — the outer module's `md_type` carries the free `'_weak1` from the inner ref, so `closed_modtype` returns false and the `Sig_module` branch fires. | @@ -182,7 +251,6 @@ Module-level errors. Source: [typemod.ml:24](../compiler/ml/typemod.ml). | `Not_allowed_in_functor_body` | ✓ | `super_errors_multi/not_allowed_in_functor_body` (TODO: confirm path) | | | `Not_a_packed_module` | ✓ | `not_a_packed_module.res` | | | `Incomplete_packed_module` | ✓ | `incomplete_packed_module.res` | | -| `Scoping_pack` | ⚠ | — | typemod.ml:1717. Requires first-class module pack where a constraint type has a level mismatch; very contrived. | | `Recursive_module_require_explicit_type` | ✓ | `recursive_module_require_explicit_type.res` | | | `Apply_generative` | ✓ | `apply_generative.res` | | | `Cannot_scrape_alias` | ☐ (needs build harness) | — | typemod.ml:77, 83, 1347. Requires `Env.scrape_alias` to return `Mty_alias` for an alias whose target `.cmi` couldn't be loaded. The `super_errors_multi` runner pre-compiles every file in the fixture, so the alias target is always present. | @@ -197,7 +265,6 @@ Type-expression errors. Source: [typetexp.ml:28](../compiler/ml/typetexp.ml). |---|---|---|---| | `Unbound_type_variable` | ✓ | (covered indirectly via many fixtures) | | | `Unbound_type_constructor` | ✓ | `typetexp_unbound_type_constructor.res` | | -| `Unbound_type_constructor_2` | ⚠ | — | typetexp.ml:475/619. Reached in two object/polyvariant-inherit code paths when the inherited type is `Tconstr p` and after `expand_head` is still `Tvar` (the body of `p`'s declaration is a bare type variable). ReScript's parser doesn't accept `type t = 'a` at the top level (only via `with type t<'a> = 'a` which doesn't apply here), so the lookup never returns a Tvar-bodied Tconstr. Every reproduction lands on `Not_an_object` or `Not_a_variant`. | | `Type_arity_mismatch` | ✓ | `type_arity_mismatch.res` | | | `Type_mismatch` | ✓ | `typetexp_type_mismatch.res` | Type-constructor application that violates a `constraint 'a = …` on the declaration. | | `Alias_type_mismatch` | ✓ | `typetexp_alias_type_mismatch.res` | | @@ -205,7 +272,6 @@ Type-expression errors. Source: [typetexp.ml:28](../compiler/ml/typetexp.ml). | `Present_has_no_type` | ✓ | `polyvariant_present_has_no_type.res` | `[< #B > #A]` — `#A` is listed as a "present" tag but isn't defined in the polyvariant body. | | `Constructor_mismatch` | ✓ | `polyvariant_constructor_mismatch.res` | | | `Not_a_variant` | ✓ | `typetexp_not_a_variant.res` | Polyvariant `[#X \| a]` where `a` is not a polyvariant. | -| `Variant_tags` | ⚠ | — | typetexp.ml:39. Raised at typecore.ml:342, 349, 367 via `Tags` exception from `ctype.ml`. **Verified: `exception Tags` is defined (ctype.ml:60) but never raised in `compiler/`.** Confirmed dead. | | `Invalid_variable_name` | ✓ | `invalid_type_variable_name.res` | | | `Cannot_quantify` | ✓ | `cannot_quantify.res` | `type t = {f: 'a. (int as 'a) => int}` — `'a` is universally quantified but the alias `int as 'a` rebinds it to `int`, so the proxy is no longer a fresh `Tvar` when the quantification check runs. | | `Multiple_constraints_on_type` | ✓ | `multiple_constraints_on_type.res` | | @@ -215,10 +281,8 @@ Type-expression errors. Source: [typetexp.ml:28](../compiler/ml/typetexp.ml). | `Unbound_label` | ✓ | `typetexp_unbound_label.res` | | | `Unbound_module` | ✓ | `suggest_module_for_missing_identifier.res`, `super_errors_multi/Smoke_unbound_module_reference` | | | `Unbound_modtype` | ✓ | `typetexp_unbound_modtype.res` | | -| `Ill_typed_functor_application` | ⚠ | — | typetexp.ml:102. In the `Longident.Lapply` branch. **Verified: parser has no construction site for `Longident.Lapply`** (no result in `res_core.ml`). Confirmed dead. | | `Illegal_reference_to_recursive_module` | ✓ | `illegal_recursive_module_reference.res` | `module rec A: B.S = …` references another recmodule's module-type before signatures are sealed. During `approx_modtype` of A, `Env.lookup_module B` returns the `#recmod#` placeholder and raises `Env.Recmodule`. | | `Access_functor_as_structure` | ✓ | `access_functor_as_structure.res` | | -| `Apply_structure_as_functor` | ⚠ | — | typetexp.ml:93. In the `Longident.Lapply` branch. Same dead reason as `Ill_typed_functor_application`. | | `Cannot_scrape_alias` | ☐ (needs build harness) | — | typetexp.ml:86 (Ldot path, live), 95/101 (Lapply path, dead since `Lapply` isn't parsed). The live Ldot trigger needs `Env.scrape_alias` to return `Mty_alias` — an alias whose target `.cmi` couldn't be loaded. The `super_errors_multi` harness pre-compiles every alias target. | | `Opened_object` | ✓ | `object_inherit_opened.res` | | | `Not_an_object` | ✓ | `object_inherit_not_an_object.res` | | @@ -239,7 +303,7 @@ Wrapper symptoms attached to inclusion failures. Source: [includemod.ml:23](../c | `Modtype_infos` | ✓ | `super_errors_multi/Iface_modtype_infos` | | | `Modtype_permutation` | ✓ | `super_errors_multi/include_modtype_permutation` | | | `Interface_mismatch` | ✓ | wrapper added to all `Iface_*` failures (line 476). | | -| `Unbound_modtype_path` | ⚠ | — | includemod.ml:94. Fires inside `modtype_path` comparison when `Env.find_modtype` raises `Not_found`. The only callers run after both signatures have been fully typed, so the module-type path is always findable from the local env — `Not_found` would imply a stale `.cmi`, which the multi-file harness can't produce since it always pre-compiles. Treating as dead from the source-only harnesses' point of view. | +| `Unbound_modtype_path` | ☐ (needs stale-cmi harness) | — | includemod.ml:94. Re-validated during removal: not completely dead. It represents `Env.find_modtype` failing during module-type path comparison, which can happen only with a stale or inconsistent compiled interface. The source-only harness cannot produce that state because it pre-compiles every fixture, so this needs a build/binary-state harness rather than deletion. | | `Unbound_module_path` | ☐ (needs build harness) | — | includemod.ml:226/233. Alias comparison where `Env.normalize_path` raises `Not_found`. Requires a module alias whose target `.cmi` is absent at inclusion time — multi-unit only. | | `Invalid_module_alias` | ☐ (needs build harness) | — | includemod.ml:211. Requires both sides `Mty_alias` with one pointing to a functor argument. Reachable only when the alias chain crosses a functor application that the `super_errors_multi` harness doesn't construct. | @@ -279,13 +343,11 @@ FFI / attribute / experimental-feature errors. Source: [bs_syntaxerr.ml:27](../c | Variant | Status | Fixture | Notes | |---|---|---|---| | `Unsupported_predicates` | ✓ | `bs_unsupported_predicates.res` | `@get({weird: true})` on object type field. | -| `Conflict_bs_bs_this_bs_meth` | ⚠ | — | bs_syntaxerr.ml:29 declares the variant but `Bs_syntaxerr.err _ Conflict_bs_bs_this_bs_meth` is **never raised** anywhere in `compiler/`. | | `Duplicated_bs_deriving` | ✓ | `duplicated_bs_deriving.res` | | | `Conflict_attributes` | ✓ | `bs_conflict_attributes.res` | | | `Expect_int_literal` | ✓ | `bs_expect_int_literal.res` | | | `Expect_string_literal` | ✓ | `bs_expect_string_literal.res` | | | `Expect_int_or_string_or_json_literal` | ✓ | `bs_expect_int_or_string_or_json_literal.res` | `@as(true)` on a wildcard external argument. | -| `Unhandled_poly_type` | ⚠ | — | ast_core_type.ml:141. Reached only when an external's arrow chain contains `Ptyp_poly` inline. The parser's `parse_poly_type_expr` only emits `Ptyp_poly` for record field types and explicit `let f: type t. …` annotations; inside arrow chains, the `'a.` is misread as the deprecated `(. …)` uncurried syntax (`res_core.ml` lexer). Inline polytypes in an external's arrow can only come from PPX-rewritten AST. | | `Invalid_underscore_type_in_external` | ✓ | `bs_invalid_underscore_type_in_external.res` | `@obj external make: (~x: _) => _ = ""` — `_` at an optional-label position without `@as`. | | `Invalid_bs_string_type` | ✓ | `bs_invalid_bs_string_type.res` | | | `Invalid_bs_int_type` | ✓ | `bs_invalid_bs_int_type.res` | | @@ -294,11 +356,11 @@ FFI / attribute / experimental-feature errors. Source: [bs_syntaxerr.ml:27](../c | `Illegal_attribute` | ✓ | `bs_illegal_attribute_scope.res` | | | `Not_supported_directive_in_bs_return` | ✓ | `bs_not_supported_directive_in_bs_return.res` | | | `Expect_opt_in_bs_return_to_opt` | ✓ | `bs_expect_opt_in_bs_return_to_opt.res` | | -| `Misplaced_label_syntax` | ⚠ | — | bs_syntaxerr.ml:116. Only fires from `check_and_discard` in `ast_exp_apply.ml:49`, applied to the args of `->`, `#=`, `##` operators. The parser always emits those args as `Nolabel`. | | `Optional_in_uncurried_bs_attribute` | ✓ | `bs_optional_in_uncurried_bs_attribute.res` | `@this` function with optional argument. | | `Bs_this_simple_pattern` | ✓ | `bs_this_simple_pattern.res` | `@this` with destructured self pattern. | | `Experimental_feature_not_enabled` | ✓ | `let_unwrap_on_top_level_not_enabled.res` (and other let-unwrap variants) | Currently only `LetUnwrap` is checked. | | `LetUnwrap_not_supported_in_position` | ✓ | `let_unwrap_on_top_level.res`, `let_unwrap_on_not_supported_variant.res` | | +| `Misplaced_label_syntax` | ✓ | `misplaced_label_syntax.res` | Labelled args passed via the operator-identifier syntax `(->)`, `(#=)`, `(##)`, e.g. `\"->"(x, ~b=...)`. | --- @@ -361,7 +423,6 @@ Environment / `.cmi`-consistency errors. Source: [env.ml:57](../compiler/ml/env. | `Illegal_renaming` | ☐ (needs build harness) | — | Triggered when a `.cmi` filename and the module name inside it disagree. Reachable via `rescript.json` setups that rename the produced artefact, but not from a single-process `bsc` invocation that always writes `Module.cmi` to match the source. | | `Inconsistent_import` | ☐ (needs build harness) | — | Triggered when two `.cmi` files transitively imported by the same unit declare different CRCs for the same type. Needs an artificially-mutated build state across multiple compile invocations. | | `Missing_module` | ☐ (needs build harness) | — | `.cmi` referenced but absent from `-I` paths at compile time. The `super_errors_multi` runner pre-compiles every fixture file via `-bs-read-cmi`, so it never reaches this code path. | -| `Illegal_value_name` | ⚠ | — | env.ml:1622/1625 raises when an identifier is `"->"` or starts/contains `#`. The ReScript parser never emits such identifiers; only PPX-rewritten AST could reach the check. | --- @@ -403,160 +464,55 @@ multi-file harnesses, which never set `-ppx`. | `compiler/ml/translmod.ml` | `Fragile_pattern_in_toplevel` | ✓ | `fragile_pattern_toplevel.res` | | | `compiler/ml/transl_recmodule.ml` | `Circular_dependency` | ✓ | `recmodule_circular_dependency.res` | | | `compiler/ml/rec_check.ml` | `Illegal_letrec_expr` | ✓ | `illegal_letrec_expr.res` | | -| `compiler/ml/syntaxerr.ml` | `Variable_in_scope` | ⚠ | — | Reachable via `let f: type t. (t, 't) => t = …` (locally-abstract `t` collides with type variable `'t` during `varify_constructors`), but `Syntaxerr.error` has no registered pretty-printer, so it propagates as an uncaught `Fatal error: exception Syntaxerr.Error(_)`. The variant is live; the printer is dead. Treat as broken until either the printer is wired up or the variant is removed in favor of a proper diagnostic. | +| `compiler/ml/syntaxerr.ml` | `Variable_in_scope` | ? (live, broken printer) | — | Reachable via `let f: type t. (t, 't) => t = …` (locally-abstract `t` collides with type variable `'t` during `varify_constructors`), but `Syntaxerr.error` has no registered pretty-printer, so it propagates as an uncaught `Fatal error: exception Syntaxerr.Error(_)`. Not removed because the variant is live; the fix should wire up a printer or convert the check into a regular typed diagnostic. | | `compiler/ml/cmt_format.cppo.ml` | `Not_a_typedtree` | ☐ (needs binary harness) | — | cmt_format.cppo.ml:147. Fires when a tool reads a `.cmt` file whose first block isn't a typed tree. Reachable in principle by pointing the analyzer at an arbitrary file with a `.cmt` extension; out of scope for the source-only fixture harnesses. | | `compiler/ext/bsc_args.ml` | `Unknown` | ☐ (needs CLI harness) | — | bsc_args.ml:45. Reachable trivially via `bsc --bogus`, but the `super_errors{,_multi}` runners only pass `bsc` a fixed flag list plus the source file — they can't exercise CLI-level errors. | | `compiler/ext/bsc_args.ml` | `Missing` | ☐ (needs CLI harness) | — | Same as above: `bsc -o` (no following filename). Needs a harness that invokes `bsc` with crafted argv. | --- -## `compiler/frontend/ast_utf8_string.ml` (dead family) +## `compiler/frontend/ast_utf8_string.ml` (retained defensive family) -Source: [ast_utf8_string.ml:25](../compiler/frontend/ast_utf8_string.ml). All variants here are reached only via the legacy `{j|…|j}` delimiter, which the modern ReScript parser doesn't emit. Backtick template strings skip the transform entirely. +Source: [ast_utf8_string.ml:25](../compiler/frontend/ast_utf8_string.ml). Re-validation found these are source-unreachable for regular ReScript, but not completely dead: `transform_test` and the defensive string-transform path still raise them, and the OUnit unicode tests assert their offsets. Retained. | Variant | Status | |---|---| -| `Invalid_code_point` | ⚠ Dead | -| `Unterminated_backslash` | ⚠ Dead | -| `Invalid_hex_escape` | ⚠ Dead | -| `Invalid_unicode_escape` | ⚠ Dead | -| `Invalid_unicode_codepoint_escape` | ⚠ Dead | +| `Invalid_code_point` | ? (source-unreachable, retained defensive/test helper) | +| `Unterminated_backslash` | ? (source-unreachable, retained defensive/test helper) | +| `Invalid_hex_escape` | ? (source-unreachable, retained defensive/test helper) | +| `Invalid_unicode_escape` | ? (source-unreachable, retained defensive/test helper) | +| `Invalid_unicode_codepoint_escape` | ? (source-unreachable, retained defensive/test helper) | -## `compiler/frontend/ast_utf8_string_interp.ml` (dead family) +## `compiler/frontend/ast_utf8_string_interp.ml` (retained test family) Source: [ast_utf8_string_interp.ml:25](../compiler/frontend/ast_utf8_string_interp.ml). -`pos_error` is reached only through `check_and_transform`, whose only -caller in `compiler/` is `transform_test` — used by OUnit tests, not the -production pipeline. Modern ReScript backtick templates take the -`BackQuotes` branch of `transform_exp` (line 311) and skip the -interpolation parser entirely. The legacy `{j|…|j}` delimiter the -parser would otherwise route here is no longer accepted by the -scanner. All variants below are unreachable from regular ReScript -source. +`pos_error` is reached through `transform_test`, which is intentionally +used by OUnit tests. Modern ReScript backtick templates take the +`BackQuotes` branch of `transform_exp` and skip the interpolation parser, +so these are source-unreachable for regular ReScript, but not completely +dead. Retained. | Variant | Status | |---|---| -| `Invalid_code_point` | ⚠ Dead | -| `Unterminated_backslash` | ⚠ Dead | -| `Invalid_escape_code` | ⚠ Dead | -| `Invalid_hex_escape` | ⚠ Dead | -| `Invalid_unicode_escape` | ⚠ Dead | -| `Unterminated_variable` | ⚠ Dead | -| `Unmatched_paren` | ⚠ Dead | -| `Invalid_syntax_of_var` | ⚠ Dead | +| `Invalid_code_point` | ? (source-unreachable, retained test helper) | +| `Unterminated_backslash` | ? (source-unreachable, retained test helper) | +| `Invalid_escape_code` | ? (source-unreachable, retained test helper) | +| `Invalid_hex_escape` | ? (source-unreachable, retained test helper) | +| `Invalid_unicode_escape` | ? (source-unreachable, retained test helper) | +| `Unterminated_variable` | ? (source-unreachable, retained test helper) | +| `Unmatched_paren` | ? (source-unreachable, retained test helper) | +| `Invalid_syntax_of_var` | ? (source-unreachable, retained test helper) | --- -## Confirmed dead variants — candidates for removal - -Only variants with a concrete, source-level reason are listed. Each row -has been re-verified against the source as of this audit. Variants marked -`?` in the tables above are **not** included here — those may turn out to -be live and just hard to reproduce. - -**Verified dead by missing raise / construction site:** - -- `typecore.Variant_tags`, `typetexp.Variant_tags` — relayed via the - `Tags` exception which is declared in `ctype.ml:60` / `ctype.mli:57` - but **never raised** in `compiler/`. -- `typecore.Recursive_local_constraint` — relayed via - `Unification_recursive_abbrev`, raised only from the `Recursive_abbrev` - exception which is declared (`ctype.ml:110`, `ctype.mli:61`) but - **never raised**. -- `typecore.Invalid_interval` — needs `Ppat_interval`; **no construction - site** for that AST node in `compiler/syntax/src/`. -- `typecore.Invalid_for_of_pattern` — parser's - `normalize_for_of_pattern` (`res_core.ml:3841`) replaces every non-var, - non-`_` pattern with `Ppat_any` before the typer runs. -- `bs_syntaxerr.Conflict_bs_bs_this_bs_meth` — variant is declared but - no `Bs_syntaxerr.err _ Conflict_bs_bs_this_bs_meth` call exists in - `compiler/`. - -**Verified dead because parser doesn't produce required AST shape:** - -- `typetexp.Ill_typed_functor_application`, - `typetexp.Apply_structure_as_functor` — in the - `Longident.Lapply` branch; `Lapply` has no construction site in - the parser (`res_core.ml`). -- `bs_syntaxerr.Misplaced_label_syntax` — fires for labeled args to - `->`/`#=`/`##` operators; the parser always emits those with - `Nolabel`. -- `typedecl.Null_arity_external` — primitives parsed by - `Primitive.parse_declaration` always get the magic 20-byte - `prim_native_name` encoding, which bypasses the trigger; empty - `prim_name` is rejected earlier with "Not a valid global name". -- `ast_utf8_string.*` (Invalid_code_point, Unterminated_backslash, - Invalid_hex_escape, Invalid_unicode_escape, - Invalid_unicode_codepoint_escape) — the scanner - (`res_scanner.ml:350-417`) already validates escape sequences and - unicode code points; the transform never sees a string that would - fail its own re-validation. -- `ast_utf8_string_interp.*` (the whole module's error variants) — - `check_and_transform` is only ever called from `transform_test`, which - exists for OUnit tests, not the production pipeline. Modern ReScript - backtick templates take the `BackQuotes` branch of `transform_exp` - and skip the interpolation parser entirely. -- `typedecl.Val_in_structure` — typedecl.ml:1887 requires `pval_prim - = []` outside a signature; the parser's `external` recovery sets - `prim = []` only after emitting a syntax error, so the typechecker - never reaches the value declaration. -- `env.Illegal_value_name` — env.ml:1622/1625 rejects `"->"` and - identifiers containing `#`. The parser never produces such names; - PPX-rewritten AST is the only path that could trigger it. -- `bs_warnings.Statement_type` (warning 10) — only caller of - `check_application_result` passes `statement = false`, so the - `if statement then …` branch never fires. -- `bs_warnings.Unerasable_optional_argument` (warning 16) — - `type_function` (typecore.ml:3479) explicitly disables this warning - via `Warnings.parse_options false "-16"` before the check runs. -- `bs_warnings.Bs_uninterpreted_delimiters` (warning 108) — raised at - `bs_warnings.ml:29` for `Pconst_string` with delimiter `"js"`, but - the modern scanner has no `{js|…|js}` form and template strings tag - with `"bq"` after rewriting. - -**`Syntaxerr.Variable_in_scope` is a special case** — reachable from -`let f: type t. (t, 't) => t = …` but raised without a registered -printer, so it surfaces as `Fatal error: exception Syntaxerr.Error(_)`. -The variant is live; the diagnostic path is broken. Fix should either -wire up a printer or convert the check into a regular typed error. - -**Newly verified dead** (the variants the second-pass audit promoted -from `?` to ⚠, with the reason in the table): - -- `typecore.Label_mismatch`, `Abstract_wrong_label`, - `Incoherent_label_order` — defensive `try unify with Unify ->` paths - that are subsumed by `Wrong_name` / `Expr_type_clash` / - `Apply_wrong_label` in modern ReScript. -- `typedecl.Type_clash` — every recursive `type` shape that would reach - the failing `unify` is rejected earlier by `Cycle_in_def` / - `Recursive_abbrev`. -- `typedecl.Parameters_differ` — `check_regular` runs only on - abbreviations, and ReScript's parser produces `Cycle_in_def` for - every recursive abbreviation shape before this check. -- `typedecl.Rebind_wrong_type` — the parser refuses extension rebind - syntax that carries args or a result type, so source and target's - result types always unify trivially. -- `typedecl.Bad_fixed_type` — `is_fixed_type` checks the syntactic - manifest for an open row, and `expand_head` preserves that row; - there's no ReScript syntax that satisfies one check and fails the - other. -- `typedecl.Varying_anonymous` — needs `_` in a `type` parameter - position, which the parser doesn't accept. -- `typetexp.Unbound_type_constructor_2` — needs an inherited type - whose `Tconstr` body is a bare `Tvar`; the parser rejects - `type t = 'a` at top-level. -- `typemod.Cannot_eliminate_dependency` — `Mtype.nondep_supertype` - falls back to existential abstraction in every reachable case; - the `Not_found` branch never fires. -- `typemod.With_cannot_remove_constrained_type` — the parser only - accepts `'x`-style identifiers in `with type` param positions, so - the params are always fresh `Tvar`s and `params_are_constrained` - returns false. -- `bs_syntaxerr.Unhandled_poly_type` — the only way an external's - arrow chain gets an inline `Ptyp_poly` is via PPX-rewritten AST; - the parser misreads `'a.` inline as the deprecated `(. …)` - uncurried syntax. +## Removal audit notes + +All variants that were confirmed completely dead in this pass are listed +in **Removed in `jono/remove-dead-errors`** above and no longer appear in +the module tables. Previously flagged entries that were only unreachable +from regular source, but still possible through stale build artifacts, +PPX/malformed ASTs, or test helper APIs, were retained and reclassified. --- @@ -572,27 +528,11 @@ warnings still fire. Fixtures follow the naming convention `warning__.res` so coverage gaps stay greppable. -### Confirmed dead (no `prerr_warning` site in the compiler) +### Removed warnings -These warning constructors exist in `warnings.ml` but are never raised -anywhere in `compiler/`. They are candidates for removal. - -| Number | Variant | Reason | -|---|---|---| -| 1 | `Comment_start` | Lexer warning; modern parser doesn't emit. | -| 2 | `Comment_not_end` | Lexer warning; modern parser doesn't emit. | -| 7 | `Method_override` | OCaml class system, not exposed by ReScript. | -| 13 | `Instance_variable_override` | OCaml class system. | -| 14 | `Illegal_backslash` | Lexer-level escape warning; parser doesn't emit. | -| 15 | `Implicit_public_methods` | OCaml class system. | -| 29 | `Eol_in_string` | Lexer-level string warning. | -| 48 | `Eliminated_optional_arguments` | Declared but never raised. | -| 50 | `Bad_docstring` | Declared but never raised; also default-disabled. | -| 105 | `Bs_fragile_external` | Declared but never raised. | -| 106 | `Bs_unimplemented_primitive` | Declared but never raised. | -| 10 | `Statement_type` | Raised at typecore.ml:2052 inside `check_application_result`, but `statement` is always `false` at the only call site (typecore.ml:3983); sequence statements hit `Expr_type_clash` via `type_statement` unifying to `unit`. | -| 16 | `Unerasable_optional_argument` | Raised at typecore.ml:3526, but `type_function` (typecore.ml:3479) explicitly disables this warning before the check runs (`Warnings.parse_options false "-16"`). | -| 108 | `Bs_uninterpreted_delimiters` | Raised at bs_warnings.ml:29 for `Pconst_string` with delimiter `"js"`; the modern scanner has no `{js\|...\|js}` form and template strings don't tag with `"js"`. | +The warning constructors listed in **Removed in `jono/remove-dead-errors`** +were deleted. Their numeric warning slots remain holes; no warning number +was reused. ### Live but no fixture yet diff --git a/tests/build_tests/super_errors/expected/abstract_wrong_label.res.expected b/tests/build_tests/super_errors/expected/abstract_wrong_label.res.expected new file mode 100644 index 0000000000..272b06a71b --- /dev/null +++ b/tests/build_tests/super_errors/expected/abstract_wrong_label.res.expected @@ -0,0 +1,9 @@ + + We've found a bug for you! + /.../fixtures/abstract_wrong_label.res:1:41-52 + + 1 │ let f: (~a: int, ~b: int) => int = (~a, ~c) => a + c + 2 │ + + This function should have type (~b: int) => int + but its first argument is labelled ~c \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/label_mismatch_record_literal.res.expected b/tests/build_tests/super_errors/expected/label_mismatch_record_literal.res.expected new file mode 100644 index 0000000000..aa9a0e5d46 --- /dev/null +++ b/tests/build_tests/super_errors/expected/label_mismatch_record_literal.res.expected @@ -0,0 +1,11 @@ + + We've found a bug for you! + /.../fixtures/label_mismatch_record_literal.res:3:16 + + 1 │ type a = {x: int} + 2 │ type b = {y: int} + 3 │ let _ = {x: 1, y: 2} + 4 │ + + The record field y belongs to the type b + but is mixed here with fields of type a \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/misplaced_label_syntax.res.expected b/tests/build_tests/super_errors/expected/misplaced_label_syntax.res.expected new file mode 100644 index 0000000000..552907d081 --- /dev/null +++ b/tests/build_tests/super_errors/expected/misplaced_label_syntax.res.expected @@ -0,0 +1,9 @@ + + We've found a bug for you! + /.../fixtures/misplaced_label_syntax.res:2:21-27 + + 1 │ let f = (~a, x) => x + a + 2 │ let _ = \"->"(1, ~b=f(~a=2)) + 3 │ + + Label syntax is not supported in this position \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/with_cannot_remove_constrained_type.res.expected b/tests/build_tests/super_errors/expected/with_cannot_remove_constrained_type.res.expected new file mode 100644 index 0000000000..f57ad8791d --- /dev/null +++ b/tests/build_tests/super_errors/expected/with_cannot_remove_constrained_type.res.expected @@ -0,0 +1,12 @@ + + We've found a bug for you! + /.../fixtures/with_cannot_remove_constrained_type.res:5:17-39 + + 3 │ } + 4 │ + 5 │ module type T = S with type t<'a> := 'a + 6 │ + + Destructive substitutions are not supported for constrained + types (other than when replacing a type constructor with + a type constructor with the same arguments). \ No newline at end of file diff --git a/tests/build_tests/super_errors/fixtures/abstract_wrong_label.res b/tests/build_tests/super_errors/fixtures/abstract_wrong_label.res new file mode 100644 index 0000000000..25fc0aaf18 --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/abstract_wrong_label.res @@ -0,0 +1 @@ +let f: (~a: int, ~b: int) => int = (~a, ~c) => a + c diff --git a/tests/build_tests/super_errors/fixtures/label_mismatch_record_literal.res b/tests/build_tests/super_errors/fixtures/label_mismatch_record_literal.res new file mode 100644 index 0000000000..640d3ee57f --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/label_mismatch_record_literal.res @@ -0,0 +1,3 @@ +type a = {x: int} +type b = {y: int} +let _ = {x: 1, y: 2} diff --git a/tests/build_tests/super_errors/fixtures/misplaced_label_syntax.res b/tests/build_tests/super_errors/fixtures/misplaced_label_syntax.res new file mode 100644 index 0000000000..ae964b7c87 --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/misplaced_label_syntax.res @@ -0,0 +1,2 @@ +let f = (~a, x) => x + a +let _ = \"->"(1, ~b=f(~a=2)) diff --git a/tests/build_tests/super_errors/fixtures/with_cannot_remove_constrained_type.res b/tests/build_tests/super_errors/fixtures/with_cannot_remove_constrained_type.res new file mode 100644 index 0000000000..4ed2a0f70b --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/with_cannot_remove_constrained_type.res @@ -0,0 +1,5 @@ +module type S = { + type t<'a> constraint 'a = int +} + +module type T = S with type t<'a> := 'a