Skip to content

Commit 8668aec

Browse files
committed
structure for improving subtype errors
1 parent 974674e commit 8668aec

21 files changed

+413
-76
lines changed

compiler/ml/ast_untagged_variants.ml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,17 @@ type block_type =
7171
| ObjectType
7272
| UnknownType
7373

74+
let block_type_to_string = function
75+
| IntType -> "int"
76+
| StringType -> "string"
77+
| FloatType -> "float"
78+
| BigintType -> "bigint"
79+
| BooleanType -> "bool"
80+
| InstanceType i -> Instance.to_string i
81+
| FunctionType -> "function"
82+
| ObjectType -> "object"
83+
| UnknownType -> "unknown"
84+
7485
(*
7586
Type of the runtime representation of a tag.
7687
Can be a literal (case with no payload), or a block (case with payload).
@@ -89,6 +100,16 @@ type tag = {name: string; tag_type: tag_type option}
89100
type block = {tag: tag; tag_name: string option; block_type: block_type option}
90101
type switch_names = {consts: tag array; blocks: block array}
91102

103+
let tag_type_to_type_string = function
104+
| String _ -> "string"
105+
| Int _ -> "int"
106+
| Float _ -> "float"
107+
| BigInt _ -> "bigint"
108+
| Bool _ -> "bool"
109+
| Null -> "null"
110+
| Undefined -> "undefined"
111+
| Untagged block_type -> block_type_to_string block_type
112+
92113
let untagged = "unboxed"
93114

94115
let block_type_can_be_undefined = function

compiler/ml/ctype.ml

Lines changed: 93 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,26 @@ let () =
6969
l l')
7070
| _ -> None)
7171

72-
exception Subtype of (type_expr * type_expr) list * (type_expr * type_expr) list
72+
type subtype_context =
73+
| Generic of {errorCode: string}
74+
| Primitive_coercion_target_variant_not_unboxed of {
75+
variant_name: Path.t;
76+
primitive: Path.t;
77+
}
78+
| Primitive_coercion_target_variant_no_catch_all of {
79+
variant_name: Path.t;
80+
primitive: Path.t;
81+
}
82+
| Variant_constructor_runtime_representation_mismatch of {
83+
variant_name: Path.t;
84+
issues: Variant_coercion.variant_runtime_representation_issue list;
85+
}
86+
87+
exception
88+
Subtype of
89+
(type_expr * type_expr) list
90+
* (type_expr * type_expr) list
91+
* subtype_context option
7392

7493
exception Cannot_expand
7594

@@ -3544,8 +3563,8 @@ let enlarge_type env ty =
35443563

35453564
let subtypes = TypePairs.create 17
35463565

3547-
let subtype_error env trace =
3548-
raise (Subtype (expand_trace env (List.rev trace), []))
3566+
let subtype_error ?ctx env trace =
3567+
raise (Subtype (expand_trace env (List.rev trace), [], ctx))
35493568

35503569
let extract_concrete_typedecl_opt env t =
35513570
match extract_concrete_typedecl env t with
@@ -3563,7 +3582,7 @@ let rec subtype_rec env trace t1 t2 cstrs =
35633582
with Not_found -> (
35643583
TypePairs.add subtypes (t1, t2) ();
35653584
match (t1.desc, t2.desc) with
3566-
| Tvar _, _ | _, Tvar _ -> (trace, t1, t2, !univar_pairs) :: cstrs
3585+
| Tvar _, _ | _, Tvar _ -> (trace, t1, t2, !univar_pairs, None) :: cstrs
35673586
| Tarrow (l1, t1, u1, _, _), Tarrow (l2, t2, u2, _, _)
35683587
when Asttypes.Noloc.same_arg_label l1 l2 ->
35693588
let cstrs = subtype_rec env ((t2, t1) :: trace) t2 t1 cstrs in
@@ -3593,13 +3612,14 @@ let rec subtype_rec env trace t1 t2 cstrs =
35933612
( trace,
35943613
newty2 t1.level (Ttuple [t1]),
35953614
newty2 t2.level (Ttuple [t2]),
3596-
!univar_pairs )
3615+
!univar_pairs,
3616+
None )
35973617
:: cstrs
35983618
else subtype_rec env ((t1, t2) :: trace) t1 t2 cstrs
35993619
else if cn then subtype_rec env ((t2, t1) :: trace) t2 t1 cstrs
36003620
else cstrs)
36013621
cstrs decl.type_variance (List.combine tl1 tl2)
3602-
with Not_found -> (trace, t1, t2, !univar_pairs) :: cstrs)
3622+
with Not_found -> (trace, t1, t2, !univar_pairs, None) :: cstrs)
36033623
| Tconstr (p1, _, _), _ when generic_private_abbrev env p1 ->
36043624
subtype_rec env trace (expand_abbrev_opt env t1) t2 cstrs
36053625
| Tconstr (p1, [], _), Tconstr (p2, [], _)
@@ -3617,13 +3637,34 @@ let rec subtype_rec env trace t1 t2 cstrs =
36173637
Variant_coercion.can_try_coerce_variant_to_primitive_opt
36183638
(extract_concrete_typedecl_opt env t2)
36193639
with
3620-
| Some (constructors, true) ->
3640+
| Some (p, _, false) ->
3641+
(* Not @unboxed *)
3642+
( trace,
3643+
t1,
3644+
t2,
3645+
!univar_pairs,
3646+
Some
3647+
(Primitive_coercion_target_variant_not_unboxed
3648+
{variant_name = p; primitive = path}) )
3649+
:: cstrs
3650+
| Some (p, constructors, true) ->
36213651
if
36223652
Variant_coercion.variant_has_catch_all_case constructors (fun p ->
36233653
Path.same p path)
36243654
then cstrs
3625-
else (trace, t1, t2, !univar_pairs) :: cstrs
3626-
| _ -> (trace, t1, t2, !univar_pairs) :: cstrs)
3655+
else
3656+
( trace,
3657+
t1,
3658+
t2,
3659+
!univar_pairs,
3660+
Some
3661+
(Primitive_coercion_target_variant_no_catch_all
3662+
{variant_name = p; primitive = path}) )
3663+
:: cstrs
3664+
| None ->
3665+
(* Unclear when this case actually happens. *)
3666+
(trace, t1, t2, !univar_pairs, Some (Generic {errorCode = "VCPMMVD"}))
3667+
:: cstrs)
36273668
| Tconstr (_, [], _), Tconstr (path, [], _)
36283669
when Variant_coercion.can_coerce_primitive path
36293670
&& extract_concrete_typedecl_opt env t1
@@ -3634,15 +3675,25 @@ let rec subtype_rec env trace t1 t2 cstrs =
36343675
Variant_coercion.can_try_coerce_variant_to_primitive_opt
36353676
(extract_concrete_typedecl_opt env t1)
36363677
with
3637-
| Some (constructors, unboxed) ->
3638-
if
3678+
| Some (p, constructors, unboxed) ->
3679+
let runtime_representation_issues =
36393680
constructors
36403681
|> Variant_coercion
36413682
.variant_has_same_runtime_representation_as_target
36423683
~target_path:path ~unboxed
3643-
then cstrs
3644-
else (trace, t1, t2, !univar_pairs) :: cstrs
3645-
| None -> (trace, t1, t2, !univar_pairs) :: cstrs)
3684+
in
3685+
if List.length runtime_representation_issues <> 0 then
3686+
( trace,
3687+
t1,
3688+
t2,
3689+
!univar_pairs,
3690+
Some
3691+
(Variant_constructor_runtime_representation_mismatch
3692+
{issues = runtime_representation_issues; variant_name = p})
3693+
)
3694+
:: cstrs
3695+
else cstrs
3696+
| None -> (trace, t1, t2, !univar_pairs, None) :: cstrs)
36463697
| Tconstr (_, [], _), Tconstr (_, [], _) -> (
36473698
(* type coercion for variants and records *)
36483699
match
@@ -3655,11 +3706,11 @@ let rec subtype_rec env trace t1 t2 cstrs =
36553706
Variant_coercion.variant_configuration_can_be_coerced t1attrs
36563707
t2attrs
36573708
= false
3658-
then (trace, t1, t2, !univar_pairs) :: cstrs
3709+
then (trace, t1, t2, !univar_pairs, None) :: cstrs
36593710
else
36603711
let c1_len = List.length c1 in
36613712
if c1_len > List.length c2 then
3662-
(trace, t1, t2, !univar_pairs) :: cstrs
3713+
(trace, t1, t2, !univar_pairs, None) :: cstrs
36633714
else
36643715
let constructor_map = Hashtbl.create c1_len in
36653716
c2
@@ -3716,7 +3767,7 @@ let rec subtype_rec env trace t1 t2 cstrs =
37163767
else false
37173768
| _ -> false)
37183769
then cstrs
3719-
else (trace, t1, t2, !univar_pairs) :: cstrs
3770+
else (trace, t1, t2, !univar_pairs, None) :: cstrs
37203771
| ( (_, _, {type_kind = Type_record (fields1, repr1)}),
37213772
(_, _, {type_kind = Type_record (fields2, repr2)}) ) ->
37223773
let same_repr =
@@ -3732,21 +3783,21 @@ let rec subtype_rec env trace t1 t2 cstrs =
37323783
let violation, tl1, tl2 =
37333784
Record_coercion.check_record_fields fields1 fields2
37343785
in
3735-
if violation then (trace, t1, t2, !univar_pairs) :: cstrs
3786+
if violation then (trace, t1, t2, !univar_pairs, None) :: cstrs
37363787
else subtype_list env trace tl1 tl2 cstrs
3737-
else (trace, t1, t2, !univar_pairs) :: cstrs
3738-
| _ -> (trace, t1, t2, !univar_pairs) :: cstrs
3739-
| exception Not_found -> (trace, t1, t2, !univar_pairs) :: cstrs)
3788+
else (trace, t1, t2, !univar_pairs, None) :: cstrs
3789+
| _ -> (trace, t1, t2, !univar_pairs, None) :: cstrs
3790+
| exception Not_found -> (trace, t1, t2, !univar_pairs, None) :: cstrs)
37403791
(* | (_, Tconstr(p2, _, _)) when generic_private_abbrev false env p2 ->
37413792
subtype_rec env trace t1 (expand_abbrev_opt env t2) cstrs *)
37423793
| Tobject (f1, _), Tobject (f2, _)
37433794
when is_Tvar (object_row f1) && is_Tvar (object_row f2) ->
37443795
(* Same row variable implies same object. *)
3745-
(trace, t1, t2, !univar_pairs) :: cstrs
3796+
(trace, t1, t2, !univar_pairs, None) :: cstrs
37463797
| Tobject (f1, _), Tobject (f2, _) -> subtype_fields env trace f1 f2 cstrs
37473798
| Tvariant row1, Tvariant row2 -> (
37483799
try subtype_row env trace row1 row2 cstrs
3749-
with Exit -> (trace, t1, t2, !univar_pairs) :: cstrs)
3800+
with Exit -> (trace, t1, t2, !univar_pairs, None) :: cstrs)
37503801
| Tvariant {row_closed = true; row_fields}, Tconstr (_, [], _)
37513802
when extract_concrete_typedecl_opt env t2
37523803
|> Variant_coercion.type_is_variant -> (
@@ -3758,8 +3809,8 @@ let rec subtype_rec env trace t1 t2 cstrs =
37583809
~variant_constructors ~type_attributes
37593810
with
37603811
| Ok _ -> cstrs
3761-
| Error _ -> (trace, t1, t2, !univar_pairs) :: cstrs)
3762-
| _ -> (trace, t1, t2, !univar_pairs) :: cstrs)
3812+
| Error _ -> (trace, t1, t2, !univar_pairs, None) :: cstrs)
3813+
| _ -> (trace, t1, t2, !univar_pairs, None) :: cstrs)
37633814
| Tvariant v, _ when !variant_is_subtype env (row_repr v) t2 -> cstrs
37643815
| Tpoly (u1, []), Tpoly (u2, []) -> subtype_rec env trace u1 u2 cstrs
37653816
| Tpoly (u1, tl1), Tpoly (u2, []) ->
@@ -3769,7 +3820,7 @@ let rec subtype_rec env trace t1 t2 cstrs =
37693820
try
37703821
enter_poly env univar_pairs u1 tl1 u2 tl2 (fun t1 t2 ->
37713822
subtype_rec env trace t1 t2 cstrs)
3772-
with Unify _ -> (trace, t1, t2, !univar_pairs) :: cstrs)
3823+
with Unify _ -> (trace, t1, t2, !univar_pairs, None) :: cstrs)
37733824
| Tpackage (p1, nl1, tl1), Tpackage (p2, nl2, tl2) -> (
37743825
try
37753826
let ntl1 = complete_type_list env nl2 t1.level (Mty_ident p1) nl1 tl1
@@ -3779,24 +3830,25 @@ let rec subtype_rec env trace t1 t2 cstrs =
37793830
in
37803831
let cstrs' =
37813832
List.map
3782-
(fun (n2, t2) -> (trace, List.assoc n2 ntl1, t2, !univar_pairs))
3833+
(fun (n2, t2) ->
3834+
(trace, List.assoc n2 ntl1, t2, !univar_pairs, None))
37833835
ntl2
37843836
in
37853837
if eq_package_path env p1 p2 then cstrs' @ cstrs
37863838
else
37873839
(* need to check module subtyping *)
37883840
let snap = Btype.snapshot () in
37893841
try
3790-
List.iter (fun (_, t1, t2, _) -> unify env t1 t2) cstrs';
3842+
List.iter (fun (_, t1, t2, _, _) -> unify env t1 t2) cstrs';
37913843
if !package_subtype env p1 nl1 tl1 p2 nl2 tl2 then (
37923844
Btype.backtrack snap;
37933845
cstrs' @ cstrs)
37943846
else raise (Unify [])
37953847
with Unify _ ->
37963848
Btype.backtrack snap;
37973849
raise Not_found
3798-
with Not_found -> (trace, t1, t2, !univar_pairs) :: cstrs)
3799-
| _, _ -> (trace, t1, t2, !univar_pairs) :: cstrs)
3850+
with Not_found -> (trace, t1, t2, !univar_pairs, None) :: cstrs)
3851+
| _, _ -> (trace, t1, t2, !univar_pairs, None) :: cstrs)
38003852

38013853
and subtype_list env trace tl1 tl2 cstrs =
38023854
if List.length tl1 <> List.length tl2 then subtype_error env trace;
@@ -3814,7 +3866,11 @@ and subtype_fields env trace ty1 ty2 cstrs =
38143866
else if miss1 = [] then
38153867
subtype_rec env ((rest1, rest2) :: trace) rest1 rest2 cstrs
38163868
else
3817-
(trace, build_fields (repr ty1).level miss1 rest1, rest2, !univar_pairs)
3869+
( trace,
3870+
build_fields (repr ty1).level miss1 rest1,
3871+
rest2,
3872+
!univar_pairs,
3873+
None )
38183874
:: cstrs
38193875
in
38203876
let cstrs =
@@ -3823,7 +3879,8 @@ and subtype_fields env trace ty1 ty2 cstrs =
38233879
( trace,
38243880
rest1,
38253881
build_fields (repr ty2).level miss2 (newvar ()),
3826-
!univar_pairs )
3882+
!univar_pairs,
3883+
None )
38273884
:: cstrs
38283885
in
38293886
List.fold_left
@@ -3880,12 +3937,14 @@ let subtype env ty1 ty2 =
38803937
| () ->
38813938
List.iter
38823939
(function
3883-
| trace0, t1, t2, pairs -> (
3940+
| trace0, t1, t2, pairs, ctx -> (
38843941
try unify_pairs (ref env) t1 t2 pairs
38853942
with Unify trace ->
38863943
raise
38873944
(Subtype
3888-
(expand_trace env (List.rev trace0), List.tl (List.tl trace)))))
3945+
( expand_trace env (List.rev trace0),
3946+
List.tl (List.tl trace),
3947+
ctx ))))
38893948
(List.rev cstrs)
38903949

38913950
(*******************)

compiler/ml/ctype.mli

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,28 @@
1818
open Asttypes
1919
open Types
2020

21+
type subtype_context =
22+
| Generic of {errorCode: string}
23+
| Primitive_coercion_target_variant_not_unboxed of {
24+
variant_name: Path.t;
25+
primitive: Path.t;
26+
}
27+
| Primitive_coercion_target_variant_no_catch_all of {
28+
variant_name: Path.t;
29+
primitive: Path.t;
30+
}
31+
| Variant_constructor_runtime_representation_mismatch of {
32+
variant_name: Path.t;
33+
issues: Variant_coercion.variant_runtime_representation_issue list;
34+
}
35+
2136
exception Unify of (type_expr * type_expr) list
2237
exception Tags of label * label
23-
exception Subtype of (type_expr * type_expr) list * (type_expr * type_expr) list
38+
exception
39+
Subtype of
40+
(type_expr * type_expr) list
41+
* (type_expr * type_expr) list
42+
* subtype_context option
2443
exception Cannot_expand
2544
exception Cannot_apply
2645
exception Recursive_abbrev

0 commit comments

Comments
 (0)