|
@@ -1270,7 +1270,7 @@ and unify_to_field ab tl b ?(allow_transitive_cast=true) (t,cfo) =
|
|
let athis = map ab.a_this in
|
|
let athis = map ab.a_this in
|
|
(* we cannot allow implicit casts when the this type is not completely known yet *)
|
|
(* we cannot allow implicit casts when the this type is not completely known yet *)
|
|
if has_mono athis then raise (Unify_error []);
|
|
if has_mono athis then raise (Unify_error []);
|
|
- type_eq EqStrict athis (map ta);
|
|
|
|
|
|
+ with_variance (type_eq EqStrict) athis (map ta);
|
|
(* immediate constraints checking is ok here because we know there are no monomorphs *)
|
|
(* immediate constraints checking is ok here because we know there are no monomorphs *)
|
|
List.iter2 (fun m (name,t) -> match follow t with
|
|
List.iter2 (fun m (name,t) -> match follow t with
|
|
| TInst ({ cl_kind = KTypeParameter constr },_) when constr <> [] ->
|
|
| TInst ({ cl_kind = KTypeParameter constr },_) when constr <> [] ->
|
|
@@ -1289,33 +1289,47 @@ and unify_to_field ab tl b ?(allow_transitive_cast=true) (t,cfo) =
|
|
b
|
|
b
|
|
end
|
|
end
|
|
|
|
|
|
|
|
+and unify_with_variance t1 t2 =
|
|
|
|
+ let allows_variance_to t (tf,cfo) = match cfo with
|
|
|
|
+ | None -> type_iseq tf t
|
|
|
|
+ | Some _ -> false
|
|
|
|
+ in
|
|
|
|
+ match follow t1,follow t2 with
|
|
|
|
+ | TInst(c1,tl1),TInst(c2,tl2) when c1 == c2 ->
|
|
|
|
+ List.iter2 unify_with_variance tl1 tl2
|
|
|
|
+ | TEnum(en1,tl1),TEnum(en2,tl2) when en1 == en2 ->
|
|
|
|
+ List.iter2 unify_with_variance tl1 tl2
|
|
|
|
+ | TAbstract(a1,pl1),TAbstract(a2,pl2) ->
|
|
|
|
+ let ta1 = apply_params a1.a_types pl1 a1.a_this in
|
|
|
|
+ let ta2 = apply_params a2.a_types pl2 a2.a_this in
|
|
|
|
+ type_eq EqStrict ta1 ta2;
|
|
|
|
+ if not (List.exists (allows_variance_to ta2) a1.a_to) && not (List.exists (allows_variance_to ta1) a2.a_from) then error [cannot_unify t1 t2]
|
|
|
|
+ | TAbstract(a,pl),t ->
|
|
|
|
+ type_eq EqStrict (apply_params a.a_types pl a.a_this) t;
|
|
|
|
+ if not (List.exists (allows_variance_to t) a.a_to) then error [cannot_unify t1 t2]
|
|
|
|
+ | t,TAbstract(a,pl) ->
|
|
|
|
+ type_eq EqStrict t (apply_params a.a_types pl a.a_this);
|
|
|
|
+ if not (List.exists (allows_variance_to t) a.a_from) then error [cannot_unify t1 t2]
|
|
|
|
+ | _ ->
|
|
|
|
+ error [cannot_unify t1 t2]
|
|
|
|
+
|
|
and unify_types a b tl1 tl2 =
|
|
and unify_types a b tl1 tl2 =
|
|
List.iter2 (fun t1 t2 ->
|
|
List.iter2 (fun t1 t2 ->
|
|
try
|
|
try
|
|
- type_eq EqRightDynamic t1 t2
|
|
|
|
|
|
+ with_variance (type_eq EqRightDynamic) t1 t2
|
|
with Unify_error l ->
|
|
with Unify_error l ->
|
|
let err = cannot_unify a b in
|
|
let err = cannot_unify a b in
|
|
- let allows_variance_to t (tf,cfo) = match cfo with
|
|
|
|
- | None -> type_iseq tf t
|
|
|
|
- | Some _ -> false
|
|
|
|
- in
|
|
|
|
- (try (match follow t1, follow t2 with
|
|
|
|
- | TAbstract({a_impl = Some _} as a1,pl1),TAbstract({a_impl = Some _ } as a2,pl2) ->
|
|
|
|
- let ta1 = apply_params a1.a_types pl1 a1.a_this in
|
|
|
|
- let ta2 = apply_params a2.a_types pl2 a2.a_this in
|
|
|
|
- type_eq EqStrict ta1 ta2;
|
|
|
|
- if not (List.exists (allows_variance_to ta2) a1.a_to) && not (List.exists (allows_variance_to ta1) a2.a_from) then raise (Unify_error l)
|
|
|
|
- | TAbstract({a_impl = Some _} as a,pl),t ->
|
|
|
|
- type_eq EqStrict (apply_params a.a_types pl a.a_this) t;
|
|
|
|
- if not (List.exists (allows_variance_to t) a.a_to) then raise (Unify_error l)
|
|
|
|
- | t,TAbstract({a_impl = Some _ } as a,pl) ->
|
|
|
|
- type_eq EqStrict t (apply_params a.a_types pl a.a_this);
|
|
|
|
- if not (List.exists (allows_variance_to t) a.a_from) then raise (Unify_error l)
|
|
|
|
- | _ -> raise (Unify_error l))
|
|
|
|
- with Unify_error _ ->
|
|
|
|
- error (err :: (Invariant_parameter (t1,t2)) :: l))
|
|
|
|
|
|
+ error (err :: (Invariant_parameter (t1,t2)) :: l)
|
|
) tl1 tl2
|
|
) tl1 tl2
|
|
|
|
|
|
|
|
+and with_variance f t1 t2 =
|
|
|
|
+ try
|
|
|
|
+ f t1 t2
|
|
|
|
+ with Unify_error l -> try
|
|
|
|
+ unify_with_variance t1 t2
|
|
|
|
+ with Unify_error _ ->
|
|
|
|
+ raise (Unify_error l)
|
|
|
|
+
|
|
and unify_with_access t1 f2 =
|
|
and unify_with_access t1 f2 =
|
|
match f2.cf_kind with
|
|
match f2.cf_kind with
|
|
(* write only *)
|
|
(* write only *)
|