1995-08-09 08:06:35 -07:00
|
|
|
(***********************************************************************)
|
|
|
|
(* *)
|
2011-07-27 07:17:02 -07:00
|
|
|
(* OCaml *)
|
1995-08-09 08:06:35 -07:00
|
|
|
(* *)
|
|
|
|
(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *)
|
|
|
|
(* *)
|
1996-04-30 07:53:58 -07:00
|
|
|
(* Copyright 1996 Institut National de Recherche en Informatique et *)
|
1999-11-17 10:59:06 -08:00
|
|
|
(* en Automatique. All rights reserved. This file is distributed *)
|
|
|
|
(* under the terms of the Q Public License version 1.0. *)
|
1995-08-09 08:06:35 -07:00
|
|
|
(* *)
|
|
|
|
(***********************************************************************)
|
|
|
|
|
|
|
|
(* $Id$ *)
|
|
|
|
|
1995-05-04 03:15:53 -07:00
|
|
|
(* Inclusion checks for the core language *)
|
|
|
|
|
|
|
|
open Misc
|
2003-07-02 02:14:35 -07:00
|
|
|
open Asttypes
|
1995-05-04 03:15:53 -07:00
|
|
|
open Path
|
1996-09-23 04:33:27 -07:00
|
|
|
open Types
|
1995-05-04 03:15:53 -07:00
|
|
|
open Typedtree
|
|
|
|
|
1995-05-05 03:05:18 -07:00
|
|
|
(* Inclusion between value descriptions *)
|
1995-05-04 03:15:53 -07:00
|
|
|
|
1995-10-23 09:59:41 -07:00
|
|
|
exception Dont_match
|
|
|
|
|
1995-05-04 03:15:53 -07:00
|
|
|
let value_descriptions env vd1 vd2 =
|
1997-04-01 12:52:36 -08:00
|
|
|
if Ctype.moregeneral env true vd1.val_type vd2.val_type then begin
|
1996-04-22 04:15:41 -07:00
|
|
|
match (vd1.val_kind, vd2.val_kind) with
|
|
|
|
(Val_prim p1, Val_prim p2) ->
|
1995-10-23 09:59:41 -07:00
|
|
|
if p1 = p2 then Tcoerce_none else raise Dont_match
|
1996-04-22 04:15:41 -07:00
|
|
|
| (Val_prim p, _) -> Tcoerce_primitive p
|
|
|
|
| (_, Val_prim p) -> raise Dont_match
|
|
|
|
| (_, _) -> Tcoerce_none
|
1995-10-23 09:59:41 -07:00
|
|
|
end else
|
|
|
|
raise Dont_match
|
1995-05-04 03:15:53 -07:00
|
|
|
|
2003-07-02 02:14:35 -07:00
|
|
|
(* Inclusion between "private" annotations *)
|
|
|
|
|
2007-11-28 14:27:35 -08:00
|
|
|
let private_flags decl1 decl2 =
|
|
|
|
match decl1.type_private, decl2.type_private with
|
2007-10-17 20:58:07 -07:00
|
|
|
| Private, Public ->
|
2010-01-20 08:26:46 -08:00
|
|
|
decl2.type_kind = Type_abstract &&
|
|
|
|
(decl2.type_manifest = None || decl1.type_kind <> Type_abstract)
|
2007-10-09 03:29:37 -07:00
|
|
|
| _, _ -> true
|
2003-07-02 02:14:35 -07:00
|
|
|
|
2005-08-07 22:40:52 -07:00
|
|
|
(* Inclusion between manifest types (particularly for private row types) *)
|
2005-03-22 19:08:37 -08:00
|
|
|
|
|
|
|
let is_absrow env ty =
|
|
|
|
match ty.desc with
|
|
|
|
Tconstr(Pident id, _, _) ->
|
|
|
|
begin match Ctype.expand_head env ty with
|
|
|
|
{desc=Tobject _|Tvariant _} -> true
|
|
|
|
| _ -> false
|
|
|
|
end
|
|
|
|
| _ -> false
|
|
|
|
|
2008-12-03 10:09:09 -08:00
|
|
|
let type_manifest env ty1 params1 ty2 params2 priv2 =
|
2005-03-22 19:08:37 -08:00
|
|
|
let ty1' = Ctype.expand_head env ty1 and ty2' = Ctype.expand_head env ty2 in
|
|
|
|
match ty1'.desc, ty2'.desc with
|
|
|
|
Tvariant row1, Tvariant row2 when is_absrow env (Btype.row_more row2) ->
|
|
|
|
let row1 = Btype.row_repr row1 and row2 = Btype.row_repr row2 in
|
|
|
|
Ctype.equal env true (ty1::params1) (row2.row_more::params2) &&
|
2011-11-24 01:02:48 -08:00
|
|
|
begin match row1.row_more with
|
|
|
|
{desc=Tvar _|Tconstr _|Tnil} -> true
|
|
|
|
| _ -> false
|
|
|
|
end &&
|
2005-03-22 19:08:37 -08:00
|
|
|
let r1, r2, pairs =
|
2010-01-22 04:48:24 -08:00
|
|
|
Ctype.merge_row_fields row1.row_fields row2.row_fields in
|
2005-03-22 19:08:37 -08:00
|
|
|
(not row2.row_closed ||
|
|
|
|
row1.row_closed && Ctype.filter_row_fields false r1 = []) &&
|
|
|
|
List.for_all
|
2010-01-22 04:48:24 -08:00
|
|
|
(fun (_,f) -> match Btype.row_field_repr f with
|
|
|
|
Rabsent | Reither _ -> true | Rpresent _ -> false)
|
|
|
|
r2 &&
|
2005-03-22 19:08:37 -08:00
|
|
|
let to_equal = ref (List.combine params1 params2) in
|
|
|
|
List.for_all
|
2010-01-22 04:48:24 -08:00
|
|
|
(fun (_, f1, f2) ->
|
|
|
|
match Btype.row_field_repr f1, Btype.row_field_repr f2 with
|
|
|
|
Rpresent(Some t1),
|
|
|
|
(Rpresent(Some t2) | Reither(false, [t2], _, _)) ->
|
|
|
|
to_equal := (t1,t2) :: !to_equal; true
|
|
|
|
| Rpresent None, (Rpresent None | Reither(true, [], _, _)) -> true
|
|
|
|
| Reither(c1,tl1,_,_), Reither(c2,tl2,_,_)
|
|
|
|
when List.length tl1 = List.length tl2 && c1 = c2 ->
|
|
|
|
to_equal := List.combine tl1 tl2 @ !to_equal; true
|
|
|
|
| Rabsent, (Reither _ | Rabsent) -> true
|
|
|
|
| _ -> false)
|
|
|
|
pairs &&
|
2005-03-22 19:08:37 -08:00
|
|
|
let tl1, tl2 = List.split !to_equal in
|
|
|
|
Ctype.equal env true tl1 tl2
|
|
|
|
| Tobject (fi1, _), Tobject (fi2, _)
|
|
|
|
when is_absrow env (snd(Ctype.flatten_fields fi2)) ->
|
|
|
|
let (fields2,rest2) = Ctype.flatten_fields fi2 in
|
|
|
|
Ctype.equal env true (ty1::params1) (rest2::params2) &&
|
|
|
|
let (fields1,rest1) = Ctype.flatten_fields fi1 in
|
2011-09-22 02:05:42 -07:00
|
|
|
(match rest1 with {desc=Tnil|Tvar _|Tconstr _} -> true | _ -> false) &&
|
2005-03-22 19:08:37 -08:00
|
|
|
let pairs, miss1, miss2 = Ctype.associate_fields fields1 fields2 in
|
|
|
|
miss2 = [] &&
|
|
|
|
let tl1, tl2 =
|
2010-01-22 04:48:24 -08:00
|
|
|
List.split (List.map (fun (_,_,t1,_,t2) -> t1, t2) pairs) in
|
2005-03-22 19:08:37 -08:00
|
|
|
Ctype.equal env true (params1 @ tl1) (params2 @ tl2)
|
2007-10-09 03:29:37 -07:00
|
|
|
| _ ->
|
2008-12-03 10:09:09 -08:00
|
|
|
let rec check_super ty1 =
|
|
|
|
Ctype.equal env true (ty1 :: params1) (ty2 :: params2) ||
|
|
|
|
priv2 = Private &&
|
|
|
|
try check_super
|
|
|
|
(Ctype.try_expand_once_opt env (Ctype.expand_head env ty1))
|
|
|
|
with Ctype.Cannot_expand -> false
|
|
|
|
in check_super ty1
|
2005-03-22 19:08:37 -08:00
|
|
|
|
1995-05-04 03:15:53 -07:00
|
|
|
(* Inclusion between type declarations *)
|
|
|
|
|
2010-05-20 20:36:52 -07:00
|
|
|
type type_mismatch =
|
|
|
|
Arity
|
|
|
|
| Privacy
|
|
|
|
| Kind
|
|
|
|
| Constraint
|
|
|
|
| Manifest
|
|
|
|
| Variance
|
|
|
|
| Field_type of string
|
|
|
|
| Field_mutable of string
|
|
|
|
| Field_arity of string
|
2010-05-21 05:42:34 -07:00
|
|
|
| Field_names of int * string * string
|
2010-05-20 20:36:52 -07:00
|
|
|
| Field_missing of bool * string
|
2010-05-21 08:13:47 -07:00
|
|
|
| Record_representation of bool
|
2010-05-20 20:36:52 -07:00
|
|
|
|
|
|
|
let nth n =
|
|
|
|
if n = 1 then "first" else
|
|
|
|
if n = 2 then "2nd" else
|
|
|
|
if n = 3 then "3rd" else
|
|
|
|
string_of_int n ^ "th"
|
|
|
|
|
2010-05-21 08:13:47 -07:00
|
|
|
let report_type_mismatch0 first second decl ppf err =
|
|
|
|
let pr fmt = Format.fprintf ppf fmt in
|
|
|
|
match err with
|
|
|
|
Arity -> pr "They have different arities"
|
|
|
|
| Privacy -> pr "A private type would be revealed"
|
|
|
|
| Kind -> pr "Their kinds differ"
|
|
|
|
| Constraint -> pr "Their constraints differ"
|
|
|
|
| Manifest -> ()
|
|
|
|
| Variance -> pr "Their variances do not agree"
|
2010-05-20 20:36:52 -07:00
|
|
|
| Field_type s ->
|
2010-05-21 08:13:47 -07:00
|
|
|
pr "The types for field %s are not equal" s
|
2010-05-20 20:36:52 -07:00
|
|
|
| Field_mutable s ->
|
2010-05-21 08:13:47 -07:00
|
|
|
pr "The mutability of field %s is different" s
|
2010-05-20 20:36:52 -07:00
|
|
|
| Field_arity s ->
|
2010-05-21 08:13:47 -07:00
|
|
|
pr "The arities for field %s differ" s
|
2010-05-20 20:36:52 -07:00
|
|
|
| Field_names (n, name1, name2) ->
|
2010-05-21 08:13:47 -07:00
|
|
|
pr "Their %s fields have different names, %s and %s"
|
2010-05-20 20:36:52 -07:00
|
|
|
(nth n) name1 name2
|
|
|
|
| Field_missing (b, s) ->
|
2010-05-21 08:13:47 -07:00
|
|
|
pr "The field %s is only present in %s %s"
|
|
|
|
s (if b then second else first) decl
|
|
|
|
| Record_representation b ->
|
|
|
|
pr "Their internal representations differ:@ %s %s %s"
|
|
|
|
(if b then second else first) decl
|
|
|
|
"uses unboxed float representation"
|
|
|
|
|
|
|
|
let report_type_mismatch first second decl ppf =
|
|
|
|
List.iter
|
|
|
|
(fun err ->
|
|
|
|
if err = Manifest then () else
|
2010-05-23 23:52:16 -07:00
|
|
|
Format.fprintf ppf "@ %a." (report_type_mismatch0 first second decl) err)
|
2010-05-20 20:36:52 -07:00
|
|
|
|
|
|
|
let rec compare_variants env decl1 decl2 n cstrs1 cstrs2 =
|
|
|
|
match cstrs1, cstrs2 with
|
|
|
|
[], [] -> []
|
2010-09-12 22:28:30 -07:00
|
|
|
| [], (cstr2,_,_)::_ -> [Field_missing (true, cstr2)]
|
|
|
|
| (cstr1,_,_)::_, [] -> [Field_missing (false, cstr1)]
|
|
|
|
| (cstr1, arg1, ret1)::rem1, (cstr2, arg2,ret2)::rem2 ->
|
2010-05-20 20:36:52 -07:00
|
|
|
if cstr1 <> cstr2 then [Field_names (n, cstr1, cstr2)] else
|
|
|
|
if List.length arg1 <> List.length arg2 then [Field_arity cstr1] else
|
2010-09-12 22:28:30 -07:00
|
|
|
match ret1, ret2 with
|
|
|
|
| Some r1, Some r2 when not (Ctype.equal env true [r1] [r2]) ->
|
|
|
|
[Field_type cstr1]
|
|
|
|
| Some _, None | None, Some _ ->
|
|
|
|
[Field_type cstr1]
|
|
|
|
| _ ->
|
|
|
|
if Misc.for_all2
|
|
|
|
(fun ty1 ty2 ->
|
|
|
|
Ctype.equal env true (ty1::decl1.type_params)
|
|
|
|
(ty2::decl2.type_params))
|
|
|
|
(arg1) (arg2)
|
|
|
|
then
|
|
|
|
compare_variants env decl1 decl2 (n+1) rem1 rem2
|
|
|
|
else [Field_type cstr1]
|
|
|
|
|
|
|
|
|
2010-05-20 20:36:52 -07:00
|
|
|
let rec compare_records env decl1 decl2 n labels1 labels2 =
|
|
|
|
match labels1, labels2 with
|
|
|
|
[], [] -> []
|
2010-05-21 08:13:47 -07:00
|
|
|
| [], (lab2,_,_)::_ -> [Field_missing (true, lab2)]
|
|
|
|
| (lab1,_,_)::_, [] -> [Field_missing (false, lab1)]
|
2010-05-20 20:36:52 -07:00
|
|
|
| (lab1, mut1, arg1)::rem1, (lab2, mut2, arg2)::rem2 ->
|
|
|
|
if lab1 <> lab2 then [Field_names (n, lab1, lab2)] else
|
|
|
|
if mut1 <> mut2 then [Field_mutable lab1] else
|
|
|
|
if Ctype.equal env true (arg1::decl1.type_params)
|
|
|
|
(arg2::decl2.type_params)
|
|
|
|
then compare_records env decl1 decl2 (n+1) rem1 rem2
|
|
|
|
else [Field_type lab1]
|
|
|
|
|
2012-04-12 10:21:39 -07:00
|
|
|
let type_declarations env name decl1 id decl2 =
|
2010-05-20 20:36:52 -07:00
|
|
|
if decl1.type_arity <> decl2.type_arity then [Arity] else
|
|
|
|
if not (private_flags decl1 decl2) then [Privacy] else
|
|
|
|
let err = match (decl1.type_kind, decl2.type_kind) with
|
|
|
|
(_, Type_abstract) -> []
|
2007-10-09 03:29:37 -07:00
|
|
|
| (Type_variant cstrs1, Type_variant cstrs2) ->
|
2012-04-18 02:01:17 -07:00
|
|
|
let usage =
|
|
|
|
if decl1.type_private = Private || decl2.type_private = Public
|
|
|
|
then `Positive else `Privatize
|
|
|
|
in
|
|
|
|
List.iter
|
|
|
|
(fun (c, _, _) -> Env.mark_constructor_used usage name decl1 c)
|
|
|
|
cstrs1;
|
2010-05-20 20:36:52 -07:00
|
|
|
compare_variants env decl1 decl2 1 cstrs1 cstrs2
|
2007-10-09 03:29:37 -07:00
|
|
|
| (Type_record(labels1,rep1), Type_record(labels2,rep2)) ->
|
2010-05-21 08:13:47 -07:00
|
|
|
let err = compare_records env decl1 decl2 1 labels1 labels2 in
|
|
|
|
if err <> [] || rep1 = rep2 then err else
|
|
|
|
[Record_representation (rep2 = Record_float)]
|
2010-05-20 20:36:52 -07:00
|
|
|
| (_, _) -> [Kind]
|
|
|
|
in
|
|
|
|
if err <> [] then err else
|
|
|
|
let err = match (decl1.type_manifest, decl2.type_manifest) with
|
1997-02-20 12:39:02 -08:00
|
|
|
(_, None) ->
|
2010-05-20 20:36:52 -07:00
|
|
|
if Ctype.equal env true decl1.type_params decl2.type_params
|
|
|
|
then [] else [Constraint]
|
1995-09-26 13:23:29 -07:00
|
|
|
| (Some ty1, Some ty2) ->
|
2010-05-20 20:36:52 -07:00
|
|
|
if type_manifest env ty1 decl1.type_params ty2 decl2.type_params
|
|
|
|
decl2.type_private
|
|
|
|
then [] else [Manifest]
|
1995-09-26 13:23:29 -07:00
|
|
|
| (None, Some ty2) ->
|
1996-04-22 04:15:41 -07:00
|
|
|
let ty1 =
|
1997-03-24 12:11:22 -08:00
|
|
|
Btype.newgenty (Tconstr(Pident id, decl2.type_params, ref Mnil))
|
|
|
|
in
|
2010-05-20 20:36:52 -07:00
|
|
|
if Ctype.equal env true decl1.type_params decl2.type_params then
|
|
|
|
if Ctype.equal env false [ty1] [ty2] then []
|
|
|
|
else [Manifest]
|
|
|
|
else [Constraint]
|
|
|
|
in
|
|
|
|
if err <> [] then err else
|
2005-04-05 02:07:42 -07:00
|
|
|
if match decl2.type_kind with
|
2007-10-09 03:29:37 -07:00
|
|
|
| Type_record (_,_) | Type_variant _ -> decl2.type_private = Private
|
2005-04-05 02:07:42 -07:00
|
|
|
| Type_abstract ->
|
2007-10-09 03:29:37 -07:00
|
|
|
match decl2.type_manifest with
|
|
|
|
| None -> true
|
2005-04-05 02:07:42 -07:00
|
|
|
| Some ty -> Btype.has_constr_row (Ctype.expand_head env ty)
|
|
|
|
then
|
2010-05-20 20:36:52 -07:00
|
|
|
if List.for_all2
|
|
|
|
(fun (co1,cn1,ct1) (co2,cn2,ct2) -> (not co1 || co2)&&(not cn1 || cn2))
|
|
|
|
decl1.type_variance decl2.type_variance
|
|
|
|
then [] else [Variance]
|
|
|
|
else []
|
1995-05-04 03:15:53 -07:00
|
|
|
|
|
|
|
(* Inclusion between exception declarations *)
|
|
|
|
|
|
|
|
let exception_declarations env ed1 ed2 =
|
2012-03-06 11:03:17 -08:00
|
|
|
Misc.for_all2 (fun ty1 ty2 -> Ctype.equal env false [ty1] [ty2]) ed1.exn_args ed2.exn_args
|
1995-05-04 03:15:53 -07:00
|
|
|
|
1996-04-22 04:15:41 -07:00
|
|
|
(* Inclusion between class types *)
|
1996-05-14 08:38:36 -07:00
|
|
|
let encode_val (mut, ty) rem =
|
|
|
|
begin match mut with
|
|
|
|
Asttypes.Mutable -> Predef.type_unit
|
2011-09-22 02:05:42 -07:00
|
|
|
| Asttypes.Immutable -> Btype.newgenvar ()
|
1996-05-14 08:38:36 -07:00
|
|
|
end
|
|
|
|
::ty::rem
|
|
|
|
|
1997-05-11 14:48:21 -07:00
|
|
|
let meths meths1 meths2 =
|
|
|
|
Meths.fold
|
|
|
|
(fun nam t2 (ml1, ml2) ->
|
|
|
|
(begin try
|
|
|
|
Meths.find nam meths1 :: ml1
|
|
|
|
with Not_found ->
|
|
|
|
ml1
|
|
|
|
end,
|
|
|
|
t2 :: ml2))
|
|
|
|
meths2 ([], [])
|
|
|
|
|
1996-05-14 08:38:36 -07:00
|
|
|
let vars vars1 vars2 =
|
|
|
|
Vars.fold
|
|
|
|
(fun lab v2 (vl1, vl2) ->
|
|
|
|
(begin try
|
|
|
|
encode_val (Vars.find lab vars1) vl1
|
|
|
|
with Not_found ->
|
|
|
|
vl1
|
|
|
|
end,
|
|
|
|
encode_val v2 vl2))
|
|
|
|
vars2 ([], [])
|