···121121 is given. This allows to work around problems with GADTs in as-patterns.
122122 (Jacques Garrigue, report by Leo White, review by Gabriel Scherer)
123123124124+- #11891, #12507: Allow to name new locally abstract types in constructor type
125125+ annotations.
126126+ (Jacques Garrigue, report and review by Gabriel Scherer and Florian Angeletti)
127127+124128### Runtime system:
125129126130- #12193: Re-introduce GC compaction for shared pools
+15-2
manual/src/tutorials/gadtexamples.etex
···249249type ('arg,'result,'aux) fn =
250250 | Fun: ('a ->'b) -> ('a,'b,unit) fn
251251 | Mem1: ('a ->'b) * 'a * 'b -> ('a, 'b, 'a * 'b) fn
252252- let apply: ('arg,'result, _ ) fn -> 'arg -> 'result = fun f x ->
252252+let apply: ('arg,'result, _ ) fn -> 'arg -> 'result = fun f x ->
253253 match f with
254254 | Fun f -> f x
255255 | Mem1 (f,y,fy) -> if x = y then fy else f x
···272272type _ closure = Closure : ('a -> 'b) * 'a -> 'b closure
273273let eval = fun (Closure (type a) (f, x : (a -> _) * _)) -> f (x : a)
274274\end{caml_example*}
275275-All existential type variables of the constructor must by introduced by
275275+All existential type variables of the constructor must be introduced by
276276the ("type" ...) construct and bound by a type annotation on the
277277outside of the constructor argument.
278278+279279+One can additionally bind existentials that were freshly introduced
280280+by the refinement of another existential type, if they appear in the
281281+type of the arguments.
282282+\begin{caml_example*}{verbatim}
283283+type _ ty =
284284+ | Int : int ty
285285+ | Pair : 'b ty * 'c ty -> ('b * 'c) ty
286286+let rec default : type a. a ty -> a = function
287287+ | Int -> 0
288288+ | Pair (type b c) (b, c : b ty * c ty) ->
289289+ (default b : b), (default c : c)
290290+\end{caml_example*}
278291279292\section{s:gadt-equation-nonlocal-abstract}{Equations on non-local abstract types}
280293
+130-4
testsuite/tests/typing-gadts/name_existentials.ml
···3737Line 1, characters 42-50:
38381 | let ko2 = function Dyn (type a b) (a, x : a ty * b) -> ignore (x : b)
3939 ^^^^^^^^
4040-Error: This pattern matches values of type "a ty * b"
4141- but a pattern was expected which matches values of type "a ty * a"
4242- Type "b" is not compatible with type "a"
4040+Error: The local name "b" can only be given to an existential variable
4141+ introduced by this GADT constructor.
4242+ The type annotation tries to bind it to the name "a"
4343+ that is already bound.
4344|}]
44454546type u = C : 'a * ('a -> 'b list) -> u
···8485Line 2, characters 22-23:
85862 | | Int (type b) (n : a) -> n
8687 ^
8787-Error: This type does not bind all existentials in the constructor: "type b. a"
8888+Error: The local name "b" can only be given to an existential variable
8989+ introduced by this GADT constructor.
9090+ The type annotation tries to bind it to the type "'a"
9191+ that is not a locally abstract type.
8892|}]
89939094(* Strange wildcard *)
···117121type ('a, 'b) pair = Pair of 'a * 'b
118122val f : (int, int) pair -> int = <fun>
119123|}]
124124+125125+126126+(* #11891: allow naming more types *)
127127+(* We stillonly allow to name freshly introduced existentials *)
128128+129129+type _ ty =
130130+ | Int : int ty
131131+ | Pair : 'b ty * 'c ty -> ('b * 'c) ty
132132+let rec example : type a . a ty -> a = function
133133+| Int -> 0
134134+| Pair (x, y) -> (example x, example y)
135135+let rec example : type a . a ty -> a = function
136136+| Int -> 0
137137+| Pair (type b c) (x, y : b ty * c ty) -> (example x, example y)
138138+[%%expect{|
139139+type _ ty = Int : int ty | Pair : 'b ty * 'c ty -> ('b * 'c) ty
140140+val example : 'a ty -> 'a = <fun>
141141+val example : 'a ty -> 'a = <fun>
142142+|}]
143143+144144+let rec example : type a . a ty -> a = function
145145+| Int -> 0
146146+| Pair (type b c) (x, y : b ty * c ty) -> (example x, example (*error*)x)
147147+[%%expect{|
148148+Line 3, characters 54-72:
149149+3 | | Pair (type b c) (x, y : b ty * c ty) -> (example x, example (*error*)x)
150150+ ^^^^^^^^^^^^^^^^^^
151151+Error: This expression has type "b" = "$0" but an expression was expected of type
152152+ "$1"
153153+|}]
154154+155155+type _ th =
156156+ | Thunk : 'a * ('a -> 'b) -> 'b th
157157+let f1 (type a) : a th -> a = function
158158+ | Thunk (type b) (x, f : b * (b -> _)) -> f x
159159+let f2 (type a) : a th -> a = function
160160+ | Thunk (type b c) (x, f : b * (b -> c)) -> f x
161161+[%%expect{|
162162+type _ th = Thunk : 'a * ('a -> 'b) -> 'b th
163163+val f1 : 'a th -> 'a = <fun>
164164+Line 6, characters 29-41:
165165+6 | | Thunk (type b c) (x, f : b * (b -> c)) -> f x
166166+ ^^^^^^^^^^^^
167167+Error: The local name "c" can only be given to an existential variable
168168+ introduced by this GADT constructor.
169169+ The type annotation tries to bind it to the name "a"
170170+ that was defined before.
171171+|}]
172172+(* Do not allow to deduce extra assumptions *)
173173+let ko1 (type a) : a th -> a = function
174174+ | Thunk (type b c) (x, f : b * (b -> c option)) -> f x
175175+[%%expect{|
176176+Line 2, characters 29-48:
177177+2 | | Thunk (type b c) (x, f : b * (b -> c option)) -> f x
178178+ ^^^^^^^^^^^^^^^^^^^
179179+Error: This pattern matches values of type "b * (b -> c option)"
180180+ but a pattern was expected which matches values of type "b * (b -> a)"
181181+ Type "c option" is not compatible with type "a"
182182+|}]
183183+(* Can only name fresh existentials *)
184184+let ko2 = function
185185+ | Thunk (type b c) (x, f : b * (b -> c)) -> f x
186186+[%%expect{|
187187+Line 2, characters 29-41:
188188+2 | | Thunk (type b c) (x, f : b * (b -> c)) -> f x
189189+ ^^^^^^^^^^^^
190190+Error: The local name "c" can only be given to an existential variable
191191+ introduced by this GADT constructor.
192192+ The type annotation tries to bind it to the type "'a"
193193+ that is not a locally abstract type.
194194+|}]
195195+let ko3 () =
196196+ match [] with
197197+ | [Thunk (type b c) (x, f : b * (b -> c))] -> f x
198198+ | _ -> assert false
199199+[%%expect{|
200200+Line 3, characters 30-42:
201201+3 | | [Thunk (type b c) (x, f : b * (b -> c))] -> f x
202202+ ^^^^^^^^^^^^
203203+Error: The local name "c" can only be given to an existential variable
204204+ introduced by this GADT constructor.
205205+ The type annotation tries to bind it to the type "'a"
206206+ that is not a locally abstract type.
207207+|}]
208208+209209+type _ tho =
210210+ | Thunk_opt : 'b * ('b -> 'c option) -> 'c option tho
211211+let f3 (type a) : a tho -> a = function
212212+ | Thunk_opt (type b c) (x, f : b * (b -> c option)) -> f x
213213+[%%expect{|
214214+type _ tho = Thunk_opt : 'b * ('b -> 'c option) -> 'c option tho
215215+val f3 : 'a tho -> 'a = <fun>
216216+|}]
217217+218218+219219+(* check locality *)
220220+type 'a wrap = Wrap of 'a
221221+type _ ty = Int : int ty | Pair : ('b ty * 'c ty) wrap -> ('b * 'c) ty
222222+(* ok *)
223223+let rec default : type a. a ty -> a = function
224224+ | Int -> 0
225225+ | Pair (type b c) (Wrap (b, c) : (b ty * c ty) wrap) ->
226226+ (default b : b), (default c : c)
227227+[%%expect{|
228228+type 'a wrap = Wrap of 'a
229229+type _ ty = Int : int ty | Pair : ('b ty * 'c ty) wrap -> ('b * 'c) ty
230230+val default : 'a ty -> 'a = <fun>
231231+|}]
232232+(* ko *)
233233+let rec default : type a. a ty -> a = function
234234+ | Int -> 0
235235+ | Pair (Wrap (type b c) (b, c : b ty * c ty)) ->
236236+ (default b : b), (default c : c)
237237+[%%expect{|
238238+Line 3, characters 34-45:
239239+3 | | Pair (Wrap (type b c) (b, c : b ty * c ty)) ->
240240+ ^^^^^^^^^^^
241241+Error: The local name "b" can only be given to an existential variable
242242+ introduced by this GADT constructor.
243243+ The type annotation tries to bind it to the name "$0"
244244+ that was defined before.
245245+|}]
···5050 [create_*], or if they are both persistent and have the same
5151 name. *)
52525353+val compare_stamp: t -> t -> int
5454+ (** Compare only the internal stamps, 0 if absent *)
5555+5356val compare: t -> t -> int
5757+ (** Compare identifiers structurally, including the name *)
54585559val global: t -> bool
5660val is_predef: t -> bool
+82-15
typing/typecore.ml
···9696 | In_class_def (** or in [class c = let ... in ...] *)
9797 | In_self_pattern (** or in self pattern *)
98989999+type existential_binding =
100100+ | Bind_already_bound
101101+ | Bind_not_in_scope
102102+ | Bind_non_locally_abstract
103103+99104type error =
100105 | Constructor_arity_mismatch of Longident.t * int * int
101106 | Label_mismatch of Longident.t * Errortrace.unification_error
···189194 | Andop_type_clash of string * Errortrace.unification_error
190195 | Bindings_type_clash of Errortrace.unification_error
191196 | Unbound_existential of Ident.t list * type_expr
197197+ | Bind_existential of existential_binding * Ident.t * type_expr
192198 | Missing_type_constraint
193199 | Wrong_expected_kind of wrong_kind_sort * wrong_kind_context * type_expr
194200 | Expr_not_a_record_type of type_expr
···747753 vars
748754749755let solve_constructor_annotation
750750- tps (penv : Pattern_env.t) name_list sty ty_args ty_ex =
756756+ tps (penv : Pattern_env.t) name_list sty ty_args ty_ex unify_res =
751757 let expansion_scope = penv.equations_scope in
752752- let ids =
758758+ (* Introduce fresh type names that expand to type variables.
759759+ They should eventually be bound to ground types. *)
760760+ let ids_decls =
753761 List.map
754762 (fun name ->
755755- let decl = new_local_type ~loc:name.loc Definition in
763763+ let tv = newvar () in
764764+ let decl =
765765+ new_local_type ~loc:name.loc Definition
766766+ ~manifest_and_scope:(tv, Ident.lowest_scope) in
756767 let (id, new_env) =
757768 Env.enter_type ~scope:expansion_scope name.txt decl !!penv in
758769 Pattern_env.set_env penv new_env;
759759- {name with txt = id})
770770+ ({name with txt = id}, (decl, tv)))
760771 name_list
761772 in
773773+ (* Translate the type annotation using these type names. *)
762774 let cty, ty, force =
763775 with_local_level ~post:(fun (_,ty,_) -> generalize_structure ty)
764776 (fun () -> Typetexp.transl_simple_type_delayed !!penv sty)
765777 in
766778 tps.tps_pattern_force <- force :: tps.tps_pattern_force;
779779+ (* Only unify the return type after generating the ids *)
780780+ unify_res ();
767781 let ty_args =
768782 let ty1 = instance ty and ty2 = instance ty in
769783 match ty_args with
···777791 Ttuple tyl -> tyl
778792 | _ -> assert false
779793 in
780780- if ids <> [] then ignore begin
781781- let ids = List.map (fun x -> x.txt) ids in
794794+ if ids_decls <> [] then begin
795795+ let ids_decls = List.map (fun (x,dm) -> (x.txt,dm)) ids_decls in
796796+ let ids = List.map fst ids_decls in
782797 let rem =
798798+ (* First process the existentials introduced by this constructor.
799799+ Just need to make their definitions abstract. *)
783800 List.fold_left
784801 (fun rem tv ->
785802 match get_desc tv with
786786- Tconstr(Path.Pident id, [], _) when List.mem id rem ->
787787- list_remove id rem
803803+ Tconstr(Path.Pident id, [], _) when List.mem_assoc id rem ->
804804+ let decl, tv' = List.assoc id ids_decls in
805805+ let env =
806806+ Env.add_type ~check:false id
807807+ {decl with type_manifest = None} !!penv
808808+ in
809809+ Pattern_env.set_env penv env;
810810+ (* We have changed the definition, so clean up *)
811811+ Btype.cleanup_abbrev ();
812812+ (* Since id is now abstract, this does not create a cycle *)
813813+ unify_pat_types cty.ctyp_loc env tv tv';
814814+ List.remove_assoc id rem
788815 | _ ->
789816 raise (Error (cty.ctyp_loc, !!penv,
790817 Unbound_existential (ids, ty))))
791791- ids ty_ex
818818+ ids_decls ty_ex
792819 in
793793- if rem <> [] then
794794- raise (Error (cty.ctyp_loc, !!penv,
795795- Unbound_existential (ids, ty)))
820820+ (* The other type names should be bound to newly introduced existentials. *)
821821+ let bound_ids = ref ids in
822822+ List.iter
823823+ (fun (id, (decl, tv')) ->
824824+ let tv' = expand_head !!penv tv' in
825825+ begin match get_desc tv' with
826826+ | Tconstr (Path.Pident id', [], _) ->
827827+ if List.exists (Ident.same id') !bound_ids then
828828+ raise (Error (cty.ctyp_loc, !!penv,
829829+ Bind_existential (Bind_already_bound, id, tv')));
830830+ (* Both id and id' are Scoped identifiers, so their stamps grow *)
831831+ if Ident.scope id' <> penv.equations_scope
832832+ || Ident.compare_stamp id id' > 0 then
833833+ raise (Error (cty.ctyp_loc, !!penv,
834834+ Bind_existential (Bind_not_in_scope, id, tv')));
835835+ bound_ids := id' :: !bound_ids
836836+ | _ ->
837837+ raise (Error (cty.ctyp_loc, !!penv,
838838+ Bind_existential
839839+ (Bind_non_locally_abstract, id, tv')));
840840+ end;
841841+ let env =
842842+ Env.add_type ~check:false id
843843+ {decl with type_manifest = Some (correct_levels tv')} !!penv
844844+ in
845845+ Pattern_env.set_env penv env)
846846+ rem;
847847+ if rem <> [] then Btype.cleanup_abbrev ();
796848 end;
797797- ty_args, Some (ids, cty)
849849+ ty_args, Some (List.map fst ids_decls, cty)
798850799851let solve_Ppat_construct ~refine tps penv loc constr no_existentials
800852 existential_styp expected_ty =
···832884 let ty_args, ty_res, ty_ex =
833885 instance_constructor existential_treatment constr
834886 in
835835- let equated_types = unify_res ty_res expected_ty in
887887+ let equated_types = lazy (unify_res ty_res expected_ty) in
836888 let ty_args, existential_ctyp =
837889 solve_constructor_annotation tps penv name_list sty ty_args ty_ex
890890+ (fun () -> ignore (Lazy.force equated_types))
838891 in
839839- ty_args, ty_res, equated_types, existential_ctyp
892892+ ty_args, ty_res, Lazy.force equated_types, existential_ctyp
840893 in
841894 if constr.cstr_existentials <> [] then
842895 lower_variables_only !!penv penv.Pattern_env.equations_scope ty_res;
···68646917 "@[<2>%s:@ %a@]"
68656918 "This type does not bind all existentials in the constructor"
68666919 (Style.as_inline_code pp_type) (ids, ty)
69206920+ | Bind_existential (reason, id, ty) ->
69216921+ let reason1, reason2 = match reason with
69226922+ | Bind_already_bound -> "the name", "that is already bound"
69236923+ | Bind_not_in_scope -> "the name", "that was defined before"
69246924+ | Bind_non_locally_abstract -> "the type",
69256925+ "that is not a locally abstract type"
69266926+ in
69276927+ Location.errorf ~loc
69286928+ "@[<hov0>The local name@ %a@ %s@ %s.@ %s@ %s@ %a@ %s.@]"
69296929+ (Style.as_inline_code Printtyp.ident) id
69306930+ "can only be given to an existential variable"
69316931+ "introduced by this GADT constructor"
69326932+ "The type annotation tries to bind it to"
69336933+ reason1 (Style.as_inline_code Printtyp.type_expr) ty reason2
68676934 | Missing_type_constraint ->
68686935 Location.errorf ~loc
68696936 "@[%s@ %s@]"
+6
typing/typecore.mli
···142142143143val self_coercion : (Path.t * Location.t list ref) list ref
144144145145+type existential_binding =
146146+ | Bind_already_bound
147147+ | Bind_not_in_scope
148148+ | Bind_non_locally_abstract
149149+145150type error =
146151 | Constructor_arity_mismatch of Longident.t * int * int
147152 | Label_mismatch of Longident.t * Errortrace.unification_error
···223228 | Andop_type_clash of string * Errortrace.unification_error
224229 | Bindings_type_clash of Errortrace.unification_error
225230 | Unbound_existential of Ident.t list * type_expr
231231+ | Bind_existential of existential_binding * Ident.t * type_expr
226232 | Missing_type_constraint
227233 | Wrong_expected_kind of wrong_kind_sort * wrong_kind_context * type_expr
228234 | Expr_not_a_record_type of type_expr