Skip to content

Commit e553ab9

Browse files
committed
Simplify type-mismatch messages.
1 parent fa5ef4c commit e553ab9

File tree

1 file changed

+158
-5
lines changed

1 file changed

+158
-5
lines changed

src/boot/me/type.ml

+158-5
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ type fn_ctx = {
2323
mutable fnctx_just_saw_ret: bool
2424
}
2525

26-
exception Type_error of string * Ast.ty
26+
exception Type_error of string * string
2727

2828
let log cx =
2929
Session.log
@@ -37,7 +37,159 @@ let iflog cx thunk =
3737
else ()
3838
;;
3939

40-
let type_error expected actual = raise (Type_error (expected, actual))
40+
let head_only ty =
41+
match ty with
42+
43+
Ast.TY_tup _ -> "tup(...)"
44+
| Ast.TY_rec _ -> "rec(...)"
45+
46+
| Ast.TY_fn _ -> "fn (...) -> ..."
47+
48+
| Ast.TY_vec _ -> "vec[...]"
49+
| Ast.TY_chan _ -> "chan[...]"
50+
| Ast.TY_port _ -> "port[...]"
51+
52+
| Ast.TY_obj _ -> "obj { ... }"
53+
| Ast.TY_box _ -> "@(...)"
54+
| Ast.TY_mutable _ -> "(mutable ...)"
55+
| Ast.TY_constrained _ -> "(... : <constrained>)"
56+
57+
| _ -> Printf.sprintf "%a" Ast.sprintf_ty ty
58+
;;
59+
60+
61+
let rec rec_diff
62+
(a:Ast.ty_rec) (b:Ast.ty_rec)
63+
(abuf:Buffer.t) (bbuf:Buffer.t)
64+
: unit =
65+
66+
Buffer.add_string abuf "rec(";
67+
Buffer.add_string bbuf "rec(";
68+
69+
let rec append_first_diff buf a b i =
70+
let alen = Array.length a in
71+
let blen = Array.length b in
72+
if i >= alen
73+
then
74+
Buffer.add_string buf "...)"
75+
else
76+
if i >= blen
77+
then
78+
Printf.bprintf buf
79+
"... <%d elements>)" (blen - i)
80+
else
81+
let (alab, aty) = a.(i) in
82+
let (blab, bty) = b.(i) in
83+
if alab <> blab
84+
then
85+
Printf.bprintf buf "... <ty> %s ...)" alab
86+
else
87+
if aty <> bty
88+
then
89+
let (a,_) = summarize_difference aty bty in
90+
Printf.bprintf buf "... %s %s ...)" a alab
91+
else
92+
append_first_diff buf a b (i+1)
93+
in
94+
append_first_diff abuf a b 0;
95+
append_first_diff bbuf b a 0;
96+
Buffer.add_string abuf ")";
97+
Buffer.add_string bbuf ")";
98+
99+
100+
and tup_diff
101+
(a:Ast.ty_tup) (b:Ast.ty_tup)
102+
(abuf:Buffer.t) (bbuf:Buffer.t)
103+
: unit =
104+
105+
Buffer.add_string abuf "tup(";
106+
Buffer.add_string bbuf "tup(";
107+
108+
let rec append_first_diff buf a b i =
109+
let alen = Array.length a in
110+
let blen = Array.length b in
111+
if i >= alen
112+
then
113+
Buffer.add_string buf "...)"
114+
else
115+
if i >= blen
116+
then
117+
Printf.bprintf buf
118+
"... <%d elements>)" (blen - i)
119+
else
120+
let (aty) = a.(i) in
121+
let (bty) = b.(i) in
122+
if aty <> bty
123+
then
124+
let (a,_) = summarize_difference aty bty in
125+
Printf.bprintf buf "... %s ...)" a
126+
else
127+
append_first_diff buf a b (i+1)
128+
in
129+
append_first_diff abuf a b 0;
130+
append_first_diff bbuf b a 0;
131+
Buffer.add_string abuf ")";
132+
Buffer.add_string bbuf ")";
133+
134+
135+
and summarize_difference (expected:Ast.ty) (actual:Ast.ty)
136+
: (string * string) =
137+
if expected = actual
138+
then ("_", "_")
139+
else
140+
begin
141+
let ebuf = Buffer.create 10 in
142+
let abuf = Buffer.create 10 in
143+
144+
let p s =
145+
Buffer.add_string ebuf s;
146+
Buffer.add_string abuf s
147+
in
148+
149+
let sub e a =
150+
let (e, a) = summarize_difference e a in
151+
Printf.bprintf ebuf "%s" e;
152+
Printf.bprintf abuf "%s" a;
153+
in
154+
155+
begin
156+
match expected, actual with
157+
(Ast.TY_tup etys, Ast.TY_tup atys) ->
158+
tup_diff etys atys ebuf abuf
159+
160+
| (Ast.TY_rec eelts, Ast.TY_rec aelts) ->
161+
rec_diff eelts aelts ebuf abuf
162+
163+
| (Ast.TY_vec e, Ast.TY_vec a) ->
164+
p "vec["; sub e a; p "]";
165+
166+
| (Ast.TY_chan e, Ast.TY_port a) ->
167+
p "chan["; sub e a; p "]";
168+
169+
| (Ast.TY_port e, Ast.TY_port a) ->
170+
p "port["; sub e a; p "]";
171+
172+
| (Ast.TY_box e, Ast.TY_box a) ->
173+
p "@"; sub e a;
174+
175+
| (Ast.TY_mutable e, Ast.TY_mutable a) ->
176+
p "mutable "; sub e a;
177+
178+
| (e, a) ->
179+
Buffer.add_string ebuf (head_only e);
180+
Buffer.add_string abuf (head_only a)
181+
end;
182+
(Buffer.contents ebuf, Buffer.contents abuf)
183+
end
184+
;;
185+
186+
let type_error_full expected actual =
187+
raise (Type_error (expected, actual))
188+
;;
189+
190+
let type_error expected actual =
191+
type_error_full expected (head_only actual)
192+
;;
41193

42194
(* We explicitly curry [cx] like this to avoid threading it through all the
43195
* inner functions. *)
@@ -101,7 +253,8 @@ let check_stmt (cx:Semant.ctxt) : (fn_ctx -> Ast.stmt -> unit) =
101253
let demand (expected:Ast.ty) (actual:Ast.ty) : unit =
102254
let expected, actual = fundamental_ty expected, fundamental_ty actual in
103255
if expected <> actual then
104-
type_error (Printf.sprintf "%a" Ast.sprintf_ty expected) actual
256+
let (e,a) = summarize_difference expected actual in
257+
type_error_full e a
105258
in
106259
let demand_integer (actual:Ast.ty) : unit =
107260
if not (is_integer (fundamental_ty actual)) then
@@ -982,9 +1135,9 @@ let check_stmt (cx:Semant.ctxt) : (fn_ctx -> Ast.stmt -> unit) =
9821135
with Type_error (expected, actual) ->
9831136
Common.err
9841137
(Some stmt.Common.id)
985-
"mismatched types: expected %s but found %a"
1138+
"mismatched types: expected %s but found %s"
9861139
expected
987-
Ast.sprintf_ty actual
1140+
actual
9881141
in
9891142
check_stmt'
9901143
in

0 commit comments

Comments
 (0)