From 24312e30f107fa7dd77c51d516a7c2789f717a8e Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Fri, 4 Aug 2023 09:50:34 +0200 Subject: [PATCH 1/2] print message that this might be a component conditionally via a simple heuristic --- .../component_missing_prop.res.expected | 12 ++++++++++ ...variant_spread_inline_records.res.expected | 3 +-- .../fixtures/component_missing_prop.res | 6 +++++ jscomp/ml/typecore.ml | 24 ++++++++++++------- jscomp/ml/typecore.mli | 2 +- 5 files changed, 36 insertions(+), 11 deletions(-) create mode 100644 jscomp/build_tests/super_errors/expected/component_missing_prop.res.expected create mode 100644 jscomp/build_tests/super_errors/fixtures/component_missing_prop.res diff --git a/jscomp/build_tests/super_errors/expected/component_missing_prop.res.expected b/jscomp/build_tests/super_errors/expected/component_missing_prop.res.expected new file mode 100644 index 0000000000..3df4b8fc86 --- /dev/null +++ b/jscomp/build_tests/super_errors/expected/component_missing_prop.res.expected @@ -0,0 +1,12 @@ + + We've found a bug for you! + /.../fixtures/component_missing_prop.res:5:34-35 + + 3 │ type props<'name> = {name: 'name} + 4 │ + 5 │ let make = (): props<'name> => {} + 6 │ } + 7 │ + + Some required record fields are missing: + name. If this is a component, add the missing props. \ No newline at end of file diff --git a/jscomp/build_tests/super_errors/expected/variant_spread_inline_records.res.expected b/jscomp/build_tests/super_errors/expected/variant_spread_inline_records.res.expected index 2bc8eb1566..f34a0fa42a 100644 --- a/jscomp/build_tests/super_errors/expected/variant_spread_inline_records.res.expected +++ b/jscomp/build_tests/super_errors/expected/variant_spread_inline_records.res.expected @@ -6,5 +6,4 @@ 3 │ 4 │ let b: b = One({name: "hello"}) - Some required record fields are missing: - age. If this is a component, add the missing props. \ No newline at end of file + Some required record fields are missing: age. \ No newline at end of file diff --git a/jscomp/build_tests/super_errors/fixtures/component_missing_prop.res b/jscomp/build_tests/super_errors/fixtures/component_missing_prop.res new file mode 100644 index 0000000000..6dbe26bb05 --- /dev/null +++ b/jscomp/build_tests/super_errors/fixtures/component_missing_prop.res @@ -0,0 +1,6 @@ +// Since the React transform isn't active in the tests, mimic what the transform outputs. +module Component = { + type props<'name> = {name: 'name} + + let make = (): props<'name> => {} +} diff --git a/jscomp/ml/typecore.ml b/jscomp/ml/typecore.ml index 287888ebee..ff86952cd6 100644 --- a/jscomp/ml/typecore.ml +++ b/jscomp/ml/typecore.ml @@ -35,7 +35,7 @@ type error = | Apply_non_function of type_expr | Apply_wrong_label of arg_label * type_expr | Label_multiply_defined of string - | Labels_missing of string list + | Labels_missing of string list * bool | Label_not_mutable of Longident.t | Wrong_name of string * type_expr * string * Path.t * string * string list | Name_type_mismatch of @@ -1963,6 +1963,11 @@ let rec lower_args env seen ty_fun = let not_function env ty = let ls, tvar = list_labels env ty in ls = [] && not tvar + +let check_might_be_component env ty_record = + match (expand_head env ty_record).desc with + | Tconstr (path, _, _) when path |> Path.last = "props" -> true + | _ -> false type lazy_args = (Asttypes.arg_label * (unit -> Typedtree.expression) option) list @@ -2299,8 +2304,9 @@ and type_expect_ ?in_function ?(recarg=Rejected) env sexp ty_expected = else Some name in let labels_missing = fields |> List.filter_map filter_missing in - if labels_missing <> [] then - raise(Error(loc, env, Labels_missing labels_missing)); + if labels_missing <> [] then ( + let might_be_component = check_might_be_component env ty_record in + raise(Error(loc, env, Labels_missing (labels_missing, might_be_component)))); [||], representation | [], _ -> if fields = [] && repr_opt <> None then @@ -2324,8 +2330,9 @@ and type_expect_ ?in_function ?(recarg=Rejected) env sexp ty_expected = Overridden ({loc ; txt = Lident lbl.lbl_name}, option_none lbl.lbl_arg loc)) label_descriptions in - if !labels_missing <> [] then - raise(Error(loc, env, Labels_missing (List.rev !labels_missing))); + if !labels_missing <> [] then ( + let might_be_component = check_might_be_component env ty_record in + raise(Error(loc, env, Labels_missing ((List.rev !labels_missing), might_be_component)))); let fields = Array.map2 (fun descr def -> descr, def) label_descriptions label_definitions @@ -3862,11 +3869,12 @@ let report_error env ppf = function type_expr ty print_label l | Label_multiply_defined s -> fprintf ppf "The record field label %s is defined several times" s - | Labels_missing labels -> + | Labels_missing (labels, might_be_component) -> let print_labels ppf = List.iter (fun lbl -> fprintf ppf "@ %s" ( lbl)) in - fprintf ppf "@[Some required record fields are missing:%a. If this is a component, add the missing props.@]" - print_labels labels + let component_text = if might_be_component then " If this is a component, add the missing props." else "" in + fprintf ppf "@[Some required record fields are missing:%a.%s@]" + print_labels labels component_text | Label_not_mutable lid -> fprintf ppf "The record field %a is not mutable" longident lid | Wrong_name (eorp, ty, kind, p, name, valid_names) -> diff --git a/jscomp/ml/typecore.mli b/jscomp/ml/typecore.mli index 502e4a689e..19e99c40ff 100644 --- a/jscomp/ml/typecore.mli +++ b/jscomp/ml/typecore.mli @@ -72,7 +72,7 @@ type error = | Apply_non_function of type_expr | Apply_wrong_label of arg_label * type_expr | Label_multiply_defined of string - | Labels_missing of string list + | Labels_missing of string list * bool | Label_not_mutable of Longident.t | Wrong_name of string * type_expr * string * Path.t * string * string list | Name_type_mismatch of From 1641c1845cb221a200838bdab3217ff18945cde4 Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Fri, 4 Aug 2023 10:03:18 +0200 Subject: [PATCH 2/2] changelog --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 27de446739..12757619fe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,9 @@ - `$$default` is no longer exported from the generated JavaScript when using default exports. https://github.com/rescript-lang/rescript-compiler/pull/6328 +#### :nail_care: Polish +- Conditionally print error message about record with missing label potentially being a component. https://github.com/rescript-lang/rescript-compiler/pull/6337 + # 11.0.0-beta.4 #### :rocket: New Feature