Skip to content

Do not show coercion suggestion when coercion isn't possible #7721

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jul 25, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@

- Apply heuristic to suggest using JSX fragments where we guess that might be what the user wanted. https://github.com/rescript-lang/rescript/pull/7714

#### :bug: Bug fix

- Fix error message that falsely suggested using coercion when it wouldn't work. https://github.com/rescript-lang/rescript/pull/7721

# 12.0.0-beta.3

#### :boom: Breaking Change
Expand Down
19 changes: 13 additions & 6 deletions compiler/ml/error_message_utils.ml
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ let extract_string_constant text =
| _ -> None

let print_extra_type_clash_help ~extract_concrete_typedecl ~env loc ppf
(bottom_aliases : (Types.type_expr * Types.type_expr) option)
(bottom_aliases : (Types.type_expr * Types.type_expr) option) trace
type_clash_context =
match (type_clash_context, bottom_aliases) with
| Some (MathOperator {for_float; operator; is_constant}), _ -> (
Expand Down Expand Up @@ -623,10 +623,16 @@ let print_extra_type_clash_help ~extract_concrete_typedecl ~env loc ppf
| None -> ())
| None -> ())
| _ -> ())
| _, Some (t1, t2) ->
| _, Some (_supplied_type, target_type) ->
(* Coercion should always target the top level types. *)
let top_level_types =
match trace with
| (_, t1_top) :: (_, t2_top) :: _ -> Some (t1_top, t2_top)
| _ -> None
in
let can_show_coercion_message =
match (t1.desc, t2.desc) with
| Tvariant _, Tvariant _ ->
match top_level_types with
| Some ({Types.desc = Tvariant _}, {Types.desc = Tvariant _}) ->
(* Subtyping polymorphic variants give some weird messages sometimes,
so let's turn it off for now. For an example, turn them on again and try:
```
Expand All @@ -635,13 +641,14 @@ let print_extra_type_clash_help ~extract_concrete_typedecl ~env loc ppf
```
*)
false
| _ -> (
| Some (t1, t2) -> (
try
Ctype.subtype env t1 t2 ();
true
with _ -> false)
| None -> false
in
let target_type_string = Format.asprintf "%a" type_expr t2 in
let target_type_string = Format.asprintf "%a" type_expr target_type in
let target_expr_text = Parser.extract_text_at_loc loc in
let suggested_rewrite =
match
Expand Down
2 changes: 1 addition & 1 deletion compiler/ml/typecore.ml
Original file line number Diff line number Diff line change
Expand Up @@ -800,7 +800,7 @@ let print_expr_type_clash ~context env loc trace ppf =
| ppf -> error_type_text ppf context)
(function ppf -> error_expected_type_text ppf context);
print_extra_type_clash_help ~extract_concrete_typedecl ~env loc ppf
bottom_aliases_result context;
bottom_aliases_result trace context;
show_extra_help ppf env trace

let report_arity_mismatch ~arity_a ~arity_b ppf =
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@

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

1 │ // This should not show coercion suggestion since just the inner types a
│ re coercable, not the full type + expression (dict<float> -> dict<JSON.t
│ >)
2 │ let x: dict<JSON.t> = dict{"1": 1.}
3 │

This has type: dict<float>
But it's expected to have type: dict<JSON.t>

The incompatible parts:
float vs JSON.t (defined as JSON.t)
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// This should not show coercion suggestion since just the inner types are coercable, not the full type + expression (dict<float> -> dict<JSON.t>)
let x: dict<JSON.t> = dict{"1": 1.}