380380 val inconsistent_quantifiers :
381381 pos :Position .t -> t1 :Types .datatype -> t2 :Types .datatype -> unit
382382
383+ val escaped_quantifier :
384+ pos :Position .t ->
385+ var :string ->
386+ annotation :Types .datatype ->
387+ escapees :((string * Types .datatype ) list ) ->
388+ unit
389+
383390end
384391 = struct
385392 type griper =
@@ -1515,6 +1522,20 @@ end
15151522 " but the currently allowed effects are" ^ nli () ^
15161523 code ppr_lt)
15171524
1525+ let escaped_quantifier ~pos ~var ~annotation ~escapees =
1526+ let escaped_tys = List. map snd escapees in
1527+ build_tyvar_names (annotation :: escaped_tys);
1528+ let policy () = { (error_policy () ) with Types.Print. quantifiers = true } in
1529+ let display_ty (var , ty ) =
1530+ Printf. sprintf " %s: %s" var
1531+ (Types. string_of_datatype ~policy ~refresh_tyvar_names: false ty) in
1532+ let displayed_tys =
1533+ List. map display_ty escapees
1534+ |> String. concat (nli () ) in
1535+ die pos (" The quantifiers in the type of function" ^ nli () ^
1536+ display_ty (var, annotation) ^ nl () ^
1537+ " escape their scope, as they are present in the types:" ^ nli () ^
1538+ displayed_tys)
15181539end
15191540
15201541type context = Types .typing_environment = {
@@ -4009,16 +4030,16 @@ and type_binding : context -> binding -> binding * context * usagemap =
40094030 let t_ann = resolve_type_annotation bndr t_ann' in
40104031
40114032 (* Check that any annotation matches the shape of the function *)
4012- let context_body, ft =
4033+ let context_body, ft, quantifiers =
40134034 match t_ann with
40144035 | None ->
4015- context, make_ft lin pats effects return_type
4036+ context, make_ft lin pats effects return_type, []
40164037 | Some t ->
40174038 (* Debug.print ("t: " ^ Types.string_of_datatype t); *)
40184039 (* make sure the annotation has the right shape *)
40194040 let shape = make_ft lin pats effects return_type in
40204041 let ft = if unsafe then make_unsafe_signature t else t in
4021- let _ , ft_mono = TypeUtils. split_quantified_type ft in
4042+ let quantifiers , ft_mono = TypeUtils. split_quantified_type ft in
40224043
40234044 (* Debug.print ("ft_mono: " ^ Types.string_of_datatype ft_mono); *)
40244045 let () = unify pos ~handle: Gripers. bind_fun_annotation (no_pos shape, no_pos ft_mono) in
@@ -4029,7 +4050,7 @@ and type_binding : context -> binding -> binding * context * usagemap =
40294050 the original name as the function is not
40304051 recursive) *)
40314052 let v = Utils. dummy_source_name () in
4032- bind_var context (v, ft_mono), ft in
4053+ bind_var context (v, ft_mono), ft, quantifiers in
40334054
40344055 (* We make the patterns monomorphic after unifying with the signature. *)
40354056 make_mono pats;
@@ -4070,6 +4091,27 @@ and type_binding : context -> binding -> binding * context * usagemap =
40704091 (usages body)
40714092 else () in
40724093
4094+ (* Check that quantifiers have not escaped into the typing context *)
4095+ let check_escaped_quantifiers quantifiers env =
4096+ let quantifier_set = IntSet. of_list (List. map fst quantifiers) in
4097+ (* Note that `type_predicate` returns true iff *all* child nodes of
4098+ * the type satisfy the predicate. Thus the checker returns true if
4099+ * *all* type variables are *not* in quantifier_set *)
4100+ let checker = object (_self )
4101+ inherit Types. type_predicate
4102+ method! var_satisfies (i, _, _) = not (IntSet. mem i quantifier_set)
4103+ end in
4104+ let (is_safe, _) = checker#predicates in
4105+ let escapees =
4106+ Env. filter (fun _ dt -> not (is_safe dt)) env
4107+ |> Env. bindings in
4108+ if not (ListUtils. empty escapees) then
4109+ Gripers. escaped_quantifier ~pos ~var: name ~annotation: ft ~escapees in
4110+
4111+ let () =
4112+ if not (quantifiers = [] ) then
4113+ check_escaped_quantifiers quantifiers context.var_env in
4114+
40734115 let ft = if unsafe then check_unsafe_signature context unify_nopos ft t_ann' else ft in
40744116 let (tyvars, _), ft =
40754117 if fun_frozen then (TypeUtils. quantifiers ft, [] ), ft
0 commit comments