Skip to content

Commit 19b5ddd

Browse files
committed
propagate expected dict value type into dict literal typing
1 parent b0dffe8 commit 19b5ddd

4 files changed

Lines changed: 54 additions & 7 deletions

File tree

compiler/ml/typecore.ml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2259,6 +2259,15 @@ let extract_function_name funct =
22592259
| Texp_ident (path, _, _) -> Some (Longident.parse (Path.name path))
22602260
| _ -> None
22612261
2262+
let is_primitive_dict_make = function
2263+
| {
2264+
pexp_desc =
2265+
Pexp_ident
2266+
{txt = Longident.Ldot (Longident.Lident "Primitive_dict", "make")};
2267+
} ->
2268+
true
2269+
| _ -> false
2270+
22622271
type lazy_args =
22632272
(Asttypes.arg_label * (unit -> Typedtree.expression) option) list
22642273
@@ -2460,6 +2469,15 @@ and type_expect_ ?deprecated_context ~context ?in_function ?(recarg = Rejected)
24602469
let funct =
24612470
type_exp ~deprecated_context:FunctionCall ~context:None env sfunct
24622471
in
2472+
(if is_primitive_dict_make sfunct then
2473+
(* Dict literals lower to Primitive_dict.make, so thread the expected
2474+
dict value type into the application before typing the tuple values. *)
2475+
let _, ty_res =
2476+
filter_arrow ~env
2477+
~arity:(Some (List.length sargs))
2478+
funct.exp_type Nolabel
2479+
in
2480+
unify_exp_types ~context:None loc env ty_res (instance env ty_expected));
24632481
let ty = instance env funct.exp_type in
24642482
end_def ();
24652483
wrap_trace_gadt_instances env (lower_args env []) ty;
Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,12 @@
11

22
We've found a bug for you!
3-
/.../fixtures/dict_show_no_coercion.res:2:23-35
3+
/.../fixtures/dict_show_no_coercion.res:2:33-34
44

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

11-
This has type: dict<float>
12-
But it's expected to have type: dict<JSON.t>
13-
14-
The incompatible parts:
15-
float vs JSON.t (defined as JSON.t)
11+
This has type: float
12+
But it's expected to have type: JSON.t (defined as JSON.t)
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Generated by ReScript, PLEASE EDIT WITH CARE
2+
3+
4+
let Hidden = {};
5+
6+
let dictValueInference = {
7+
health: {
8+
get: 200
9+
}
10+
};
11+
12+
let primitiveMakeValueInference = {
13+
health: {
14+
get: 200
15+
}
16+
};
17+
18+
export {
19+
Hidden,
20+
dictValueInference,
21+
primitiveMakeValueInference,
22+
}
23+
/* No side effect */
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
module Hidden = {
2+
type routeHandlerObject = {get: int}
3+
}
4+
5+
let dictValueInference: Dict.t<Hidden.routeHandlerObject> = dict{
6+
"health": {get: 200},
7+
}
8+
9+
let primitiveMakeValueInference: Dict.t<Hidden.routeHandlerObject> = dict{"health": {get: 200}}

0 commit comments

Comments
 (0)