1 (***********************************************************************)
5 (* Xavier Leroy, projet Cristal, INRIA Rocquencourt *)
7 (* Copyright 1996 Institut National de Recherche en Informatique et *)
8 (* en Automatique. All rights reserved. This file is distributed *)
9 (* under the terms of the Q Public License version 1.0. *)
11 (***********************************************************************)
13 (* typetexp.ml,v 1.34.4.9 2002/01/07 08:39:16 garrigue Exp *)
15 (* Typechecking of type expressions for the core language *)
22 exception Already_bound
25 Unbound_type_variable
of string
26 | Unbound_type_constructor
of Longident.t
27 | Unbound_type_constructor_2
of Path.t
28 | Type_arity_mismatch
of Longident.t
* int * int
29 | Bound_type_variable
of string
31 | Unbound_class
of Longident.t
32 | Unbound_row_variable
of Longident.t
33 | Type_mismatch
of (type_expr
* type_expr
) list
34 | Alias_type_mismatch
of (type_expr
* type_expr
) list
35 | Present_has_conjunction
of string
36 | Present_has_no_type
of string
37 | Constructor_mismatch
of type_expr
* type_expr
38 | Not_a_variant
of type_expr
39 | Variant_tags
of string * string
40 | Invalid_variable_name
of string
41 | Cannot_quantify
of string * type_expr
43 exception Error
of Location.t
* error
45 type variable_context
= int * (string, type_expr
) Tbl.t
47 (* Translation of type expressions *)
49 let type_variables = ref (Tbl.empty
: (string, type_expr
) Tbl.t
)
50 let univars = ref ([] : (string * type_expr
) list
)
51 let pre_univars = ref ([] : type_expr list
)
52 let used_variables = ref (Tbl.empty
: (string, type_expr
* Location.t
) Tbl.t
)
54 let reset_type_variables () =
55 reset_global_level
();
56 type_variables := Tbl.empty
59 (increase_global_level
(), !type_variables)
62 restore_global_level gl
;
65 let enter_type_variable strict loc name
=
67 if name
<> "" && name
.[0] = '_'
then
68 raise
(Error
(loc
, Invalid_variable_name
("'" ^ name
)));
69 let v = Tbl.find name
!type_variables in
70 if strict
then raise Already_bound
;
73 let v = new_global_var
() in
74 type_variables := Tbl.add name
v !type_variables;
77 let type_variable loc name
=
79 Tbl.find name
!type_variables
81 raise
(Error
(loc
, Unbound_type_variable
("'" ^ name
)))
84 match (Ctype.repr ty
).desc
with
86 | _
-> Ctype.newty
(Tpoly
(ty
, []))
88 let new_pre_univar () =
89 let v = newvar
() in pre_univars := v :: !pre_univars; v
91 let rec swap_list = function
92 x
:: y
:: l
-> y
:: x
:: swap_list l
95 type policy
= Fixed
| Extensible
| Univars
97 let rec transl_type env policy styp
=
98 match styp
.ptyp_desc
with
100 if policy
= Univars
then new_pre_univar () else
101 if policy
= Fixed
then
102 raise
(Error
(styp
.ptyp_loc
, Unbound_type_variable
"_"))
105 if name
<> "" && name
.[0] = '_'
then
106 raise
(Error
(styp
.ptyp_loc
, Invalid_variable_name
("'" ^ name
)));
108 instance
(List.assoc name
!univars)
109 with Not_found
-> try
110 instance
(fst
(Tbl.find name
!used_variables))
113 if policy
= Univars
then new_pre_univar () else newvar
() in
114 used_variables := Tbl.add name
(v, styp
.ptyp_loc
) !used_variables;
117 | Ptyp_arrow
(l
, st1
, st2
) ->
118 let ty1 = transl_type env policy st1
in
119 let ty2 = transl_type env policy st2
in
120 newty
(Tarrow
(l
, ty1, ty2, Cok
))
122 newty
(Ttuple
(List.map
(transl_type env policy
) stl
))
123 | Ptyp_constr
(lid
, stl
) ->
126 Env.lookup_type lid env
128 raise
(Error
(styp
.ptyp_loc
, Unbound_type_constructor lid
)) in
129 if List.length stl
<> decl
.type_arity
then
130 raise
(Error
(styp
.ptyp_loc
, Type_arity_mismatch
(lid
, decl
.type_arity
,
132 let args = List.map
(transl_type env policy
) stl
in
133 let params = Ctype.instance_list decl
.type_params
in
135 match decl
.type_manifest
with
138 if (repr ty
).level
= Btype.generic_level
then unify_var
else unify
141 (fun (sty
, ty
) ty'
->
142 try unify_param env ty' ty
with Unify trace
->
143 raise
(Error
(sty
.ptyp_loc
, Type_mismatch
(swap_list trace
))))
144 (List.combine stl
args) params;
145 let constr = newconstr path
args in
147 Ctype.enforce_constraints env
constr
149 raise
(Error
(styp
.ptyp_loc
, Type_mismatch trace
))
152 | Ptyp_object fields
->
153 newobj
(transl_fields env policy fields
)
154 | Ptyp_class
(lid
, stl
, present
) ->
155 let (path
, decl
, is_variant
) =
157 let (path
, decl
) = Env.lookup_type lid env
in
159 match decl
.type_manifest
with
160 None
-> raise Not_found
162 match (repr ty
).desc
with
163 Tvariant row
when Btype.static_row row
-> ()
164 | Tconstr
(path
, _
, _
) ->
165 check (Env.find_type path env
)
166 | _
-> raise Not_found
168 Location.prerr_warning styp
.ptyp_loc
Warnings.Deprecated
;
170 with Not_found
-> try
171 if present
<> [] then raise Not_found
;
174 Longident.Lident s
-> Longident.Lident
("#" ^ s
)
175 | Longident.Ldot
(r
, s
) -> Longident.Ldot
(r
, "#" ^ s
)
176 | Longident.Lapply
(_
, _
) -> fatal_error
"Typetexp.transl_type"
178 let (path
, decl
) = Env.lookup_type
lid2 env
in
181 raise
(Error
(styp
.ptyp_loc
, Unbound_class lid
))
183 if List.length stl
<> decl
.type_arity
then
184 raise
(Error
(styp
.ptyp_loc
, Type_arity_mismatch
(lid
, decl
.type_arity
,
186 let args = List.map
(transl_type env policy
) stl
in
187 let params = Ctype.instance_list decl
.type_params
in
189 (fun (sty
, ty
) ty'
->
190 try unify_var env ty' ty
with Unify trace
->
191 raise
(Error
(sty
.ptyp_loc
, Type_mismatch
(swap_list trace
))))
192 (List.combine stl
args) params;
194 try Ctype.expand_head env
(newconstr path
args)
196 raise
(Error
(styp
.ptyp_loc
, Type_mismatch trace
))
198 begin match ty.desc
with
200 let row = Btype.row_repr
row in
202 (fun l
-> if not
(List.mem_assoc l
row.row_fields
) then
203 raise
(Error
(styp
.ptyp_loc
, Present_has_no_type l
)))
208 if List.mem l present
then f
else
209 match Btype.row_field_repr f
with
210 | Rpresent
(Some
ty) ->
211 Reither
(false, [ty], false, ref None
)
213 Reither
(true, [], false, ref None
)
217 let row = { row_closed
= true; row_fields
= fields;
218 row_bound
= (); row_name
= Some
(path
, args);
219 row_fixed
= false; row_more
= newvar
() } in
220 let static = Btype.static_row
row in
222 if static || policy
<> Univars
then row
223 else { row with row_more
= new_pre_univar () }
227 let _, tv
= flatten_fields fi
in
228 if policy
= Univars
then pre_univars := tv
:: !pre_univars;
233 | Ptyp_alias
(st
, alias
) ->
237 try List.assoc alias
!univars
239 instance
(fst
(Tbl.find alias
!used_variables))
241 let ty = transl_type env policy st
in
242 begin try unify_var env
t ty with Unify trace
->
243 let trace = swap_list trace in
244 raise
(Error
(styp
.ptyp_loc
, Alias_type_mismatch
trace))
248 if !Clflags.principal
then begin_def
();
250 used_variables := Tbl.add alias
(t, styp
.ptyp_loc
) !used_variables;
251 let ty = transl_type env policy st
in
252 begin try unify_var env
t ty with Unify
trace ->
253 let trace = swap_list trace in
254 raise
(Error
(styp
.ptyp_loc
, Alias_type_mismatch
trace))
256 if !Clflags.principal
then begin
258 generalize_structure
t;
262 | Ptyp_variant
(fields, closed
, present
) ->
263 let name = ref None
in
265 newty
(Tvariant
{row_fields
=[l
,f
]; row_more
=newvar
();
266 row_bound
=(); row_closed
=true;
267 row_fixed
=false; row_name
=None
}) in
268 let hfields = Hashtbl.create
17 in
269 let add_typed_field loc l f
=
270 let h = Btype.hash_variant l
in
272 let (l'
,f'
) = Hashtbl.find
hfields h in
273 (* Check for tag conflicts *)
274 if l
<> l'
then raise
(Error
(styp
.ptyp_loc
, Variant_tags
(l
, l'
)));
275 let ty = mkfield l f
and ty'
= mkfield l f'
in
276 if equal env
false [ty] [ty'
] then () else
278 with Unify
trace -> raise
(Error
(loc
, Constructor_mismatch
(ty,ty'
)))
280 Hashtbl.add
hfields h (l
,f
)
282 let rec add_field = function
285 let f = match present
with
286 Some present
when not
(List.mem l present
) ->
287 let tl = List.map
(transl_type env policy
) stl
in
288 Reither
(c
, tl, false, ref None
)
290 if List.length stl
> 1 || c
&& stl
<> [] then
291 raise
(Error
(styp
.ptyp_loc
, Present_has_conjunction l
));
292 match stl
with [] -> Rpresent None
293 | st
:: _ -> Rpresent
(Some
(transl_type env policy st
))
295 add_typed_field styp
.ptyp_loc l
f
297 let ty = transl_type env policy sty
in
300 {desc
=Tconstr
(p
, tl, _)} -> Some
(p
, tl)
304 (* Set name if there are no fields yet *)
305 Hashtbl.iter
(fun _ _ -> raise Exit
) hfields;
308 (* Unset it otherwise *)
311 let fl = match expand_head env
ty, nm with
312 {desc
=Tvariant
row}, _ when Btype.static_row
row ->
313 let row = Btype.row_repr
row in
315 | {desc
=Tvar
}, Some
(p
, _) ->
316 raise
(Error
(sty
.ptyp_loc
, Unbound_type_constructor_2 p
))
318 raise
(Error
(sty
.ptyp_loc
, Not_a_variant
ty))
322 let f = match present
with
323 Some present
when not
(List.mem l present
) ->
326 Reither
(false, [ty], false, ref None
)
328 Reither
(true, [], false, ref None
)
334 add_typed_field sty
.ptyp_loc l
f)
337 List.iter
add_field fields;
338 let fields = Hashtbl.fold
(fun _ p l
-> p
:: l
) hfields [] in
339 begin match present
with None
-> ()
342 (fun l
-> if not
(List.mem_assoc l
fields) then
343 raise
(Error
(styp
.ptyp_loc
, Present_has_no_type l
)))
347 { row_fields
= List.rev
fields; row_more
= newvar
();
348 row_bound
= (); row_closed
= closed
;
349 row_fixed
= false; row_name
= !name } in
350 let static = Btype.static_row
row in
352 if static then row else
355 raise
(Error
(styp
.ptyp_loc
, Unbound_type_variable
".."))
357 | Univars
-> { row with row_more
= new_pre_univar () }
360 | Ptyp_poly
(vars
, st
) ->
362 let new_univars = List.map
(fun name -> name, newvar
()) vars
in
363 let old_univars = !univars in
364 univars := new_univars @ !univars;
365 let ty = transl_type env policy st
in
366 univars := old_univars;
371 (fun tyl
(name, ty1) ->
372 let v = Btype.proxy
ty1 in
373 if deep_occur
v ty then begin
374 if v.level
<> Btype.generic_level
|| v.desc
<> Tvar
then
375 raise
(Error
(styp
.ptyp_loc
, Cannot_quantify
(name, v)));
381 let ty'
= Btype.newgenty
(Tpoly
(ty, List.rev
ty_list)) in
382 unify_var env
(newvar
()) ty'
;
385 and transl_fields env policy
=
389 | ({pfield_desc
= Pfield_var
} as pf
)::_ ->
390 begin match policy
with
391 Fixed
-> raise
(Error
(pf
.pfield_loc
, Unbound_type_variable
".."))
392 | Extensible
-> newvar
()
393 | Univars
-> new_pre_univar ()
395 | {pfield_desc
= Pfield
(s
, e
)}::l
->
396 let ty1 = transl_type env policy e
in
397 let ty2 = transl_fields env policy l
in
398 newty
(Tfield
(s
, Fpresent
, ty1, ty2))
401 (* Make the rows "fixed" in this type, to make universal check easier *)
402 let rec make_fixed_univars ty =
404 if ty.level
>= Btype.lowest_level
then begin
405 Btype.mark_type_node
ty;
408 let row = Btype.row_repr
row in
409 if (Btype.row_more
row).desc
= Tunivar
then
411 {row with row_fixed
=true;
412 row_fields
= List.map
413 (fun (s
,f as p
) -> match Btype.row_field_repr
f with
414 Reither
(c
, tl, m
, r
) -> s
, Reither
(c
, tl, true, r
)
417 Btype.iter_row
make_fixed_univars row
419 Btype.iter_type_expr
make_fixed_univars ty
422 let make_fixed_univars ty =
423 make_fixed_univars ty;
426 let globalize_used_variables env fixed
=
429 (fun name (ty, loc
) ->
430 let v = new_global_var
() in
431 let snap = Btype.snapshot
() in
432 if try unify env
v ty; true with _ -> Btype.backtrack
snap; false
434 r := (loc
, v, Tbl.find
name !type_variables) :: !r
436 if fixed
&& (repr
ty).desc
= Tvar
then
437 raise
(Error
(loc
, Unbound_type_variable
("'"^
name)));
438 let v2 = new_global_var
() in
439 r := (loc
, v, v2) :: !r;
440 type_variables := Tbl.add
name v2 !type_variables)
442 used_variables := Tbl.empty
;
445 (function (loc
, t1
, t2
) ->
446 try unify env t1 t2
with Unify
trace ->
447 raise
(Error
(loc
, Type_mismatch
trace)))
450 let transl_simple_type env fixed styp
=
451 univars := []; used_variables := Tbl.empty
;
452 let typ = transl_type env
(if fixed
then Fixed
else Extensible
) styp
in
453 globalize_used_variables env fixed
();
454 make_fixed_univars typ;
457 let transl_simple_type_univars env styp
=
458 univars := []; used_variables := Tbl.empty
; pre_univars := [];
460 let typ = transl_type env Univars styp
in
461 (* Only keep already global variables in used_variables *)
462 let new_variables = !used_variables in
463 used_variables := Tbl.empty
;
466 if Tbl.mem
name !type_variables then
467 used_variables := Tbl.add
name p
!used_variables)
469 globalize_used_variables env
false ();
476 if v.level
<> Btype.generic_level
|| v.desc
<> Tvar
then acc
477 else (v.desc
<- Tunivar
; v :: acc
))
480 make_fixed_univars typ;
481 instance
(Btype.newgenty
(Tpoly
(typ, univs)))
483 let transl_simple_type_delayed env styp
=
484 univars := []; used_variables := Tbl.empty
;
485 let typ = transl_type env Extensible styp
in
486 (typ, globalize_used_variables env
false)
488 let transl_type_scheme env styp
=
489 reset_type_variables();
491 let typ = transl_simple_type env
false styp
in
501 let report_error ppf
= function
502 | Unbound_type_variable
name ->
503 fprintf ppf
"Unbound type parameter %s" name
504 | Unbound_type_constructor lid
->
505 fprintf ppf
"Unbound type constructor %a" longident lid
506 | Unbound_type_constructor_2 p
->
507 fprintf ppf
"The type constructor@ %a@ is not yet completely defined"
509 | Type_arity_mismatch
(lid
, expected
, provided
) ->
511 "@[The type constructor %a@ expects %i argument(s),@ \
512 but is here applied to %i argument(s)@]"
513 longident lid expected provided
514 | Bound_type_variable
name ->
515 fprintf ppf
"Already bound type parameter '%s" name
517 fprintf ppf
"This type is recursive"
518 | Unbound_class lid
->
519 fprintf ppf
"Unbound class %a" longident lid
520 | Unbound_row_variable lid
->
521 fprintf ppf
"Unbound row variable in #%a" longident lid
522 | Type_mismatch
trace ->
523 Printtyp.unification_error
true trace
525 fprintf ppf
"This type")
528 fprintf ppf
"should be an instance of type")
529 | Alias_type_mismatch
trace ->
530 Printtyp.unification_error
true trace
532 fprintf ppf
"This alias is bound to type")
535 fprintf ppf
"but is used as an instance of type")
536 | Present_has_conjunction l
->
537 fprintf ppf
"The present constructor %s has a conjunctive type" l
538 | Present_has_no_type l
->
539 fprintf ppf
"The present constructor %s has no type" l
540 | Constructor_mismatch
(ty, ty'
) ->
541 Printtyp.reset_and_mark_loops_list
[ty; ty'
];
542 fprintf ppf
"@[<hov>%s %a@ %s@ %a@]"
543 "This variant type contains a constructor"
544 Printtyp.type_expr
ty
546 Printtyp.type_expr
ty'
547 | Not_a_variant
ty ->
548 Printtyp.reset_and_mark_loops
ty;
549 fprintf ppf
"@[The type %a@ is not a polymorphic variant type@]"
550 Printtyp.type_expr
ty
551 | Variant_tags
(lab1
, lab2
) ->
553 "Variant tags `%s@ and `%s have same hash value.@ Change one of them."
555 | Invalid_variable_name
name ->
556 fprintf ppf
"The type variable name %s is not allowed in programs" name
557 | Cannot_quantify
(name, v) ->
558 fprintf ppf
"This type scheme cannot quantify '%s :@ %s." name
559 (if v.desc
= Tvar
then "it escapes this scope" else
560 if v.desc
= Tunivar
then "it is aliased to another variable"
561 else "it is not a variable")