Skip to content

Commit aa3c3f7

Browse files
frank-emrichfacebook-github-bot
authored andcommitted
delete most HKT-specific logic from type integrity checking
Summary: This diff is part of a series that removes the implementation of higher-kinded types from the type-checker. This diff removes code paths from `Typing_type_integrity` (the main place where we check well-kindedness/integrity of types) that were only used in the presence of higher-kinded types. Reviewed By: mheiber Differential Revision: D74463560 fbshipit-source-id: 5ef051c39fad2f787b2a1909d715896bf37670f7
1 parent 11d2c0f commit aa3c3f7

File tree

3 files changed

+8
-239
lines changed

3 files changed

+8
-239
lines changed

hphp/hack/src/typing/typing_phase.ml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1358,8 +1358,7 @@ let localize_targ_with_kind
13581358
~in_signature:false
13591359
~should_check_package_boundary
13601360
env
1361-
ty
1362-
nkind;
1361+
ty;
13631362
let ety_env =
13641363
empty_expand_env_with_on_error
13651364
(Typing_error.Reasons_callback.invalid_type_hint hint_pos)

hphp/hack/src/typing/typing_type_integrity.ml

Lines changed: 7 additions & 236 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,11 @@
77
*)
88
open Hh_prelude
99
open Common
10-
open Utils
1110
open Typing_defs
1211
open Typing_kinding_defs
1312
module Env = Typing_env
1413
module Cls = Folded_class
1514
module KindDefs = Typing_kinding_defs
16-
module TGenConstraint = Typing_generic_constraint
17-
module TUtils = Typing_utils
18-
module Subst = Decl_subst
1915

2016
(* TOOD(T222659258) This whole file needs updating once HKTs are removed *)
2117

@@ -159,138 +155,6 @@ module Locl_Inst = struct
159155
Tsplat t_splat
160156
end
161157

162-
(* TODO(T70068435)
163-
This is a workaround for the problem that alias and newtype definitions do not spell out
164-
the constraints they may implicitly impose on their parameters.
165-
Consider:
166-
class Foo<T1 as num> {...}
167-
type Bar<T2> = Foo<T2>;
168-
169-
Here, T2 of Bar implicitly has the bound T2 as num. However, in the current design, we only
170-
ever check that when expanding Bar, the argument in place of T2 satisfies all the
171-
implicit bounds.
172-
However, this is not feasible for using aliases and newtypes as higher-kinded types, where we
173-
use them without expanding them.
174-
In the long-term, we would like to be able to infer the implicit bounds and use those for
175-
the purposes of kind-checking. For now, we just detect if there *are* implicit bounds, and
176-
if so reject using the alias/newtype as an HK type.
177-
*)
178-
let check_typedef_usable_as_hk_type env use_pos typedef_name typedef_info =
179-
let report_constraint violating_type used_class used_class_tparam_name =
180-
let tparams_in_ty = Env.get_tparams env violating_type in
181-
let tparams_of_typedef =
182-
List.fold typedef_info.td_tparams ~init:SSet.empty ~f:(fun s tparam ->
183-
SSet.add (snd tparam.tp_name) s)
184-
in
185-
let intersection = SSet.inter tparams_in_ty tparams_of_typedef in
186-
if SSet.is_empty intersection then
187-
(* Just violated constraints inside the typedef that do not involve
188-
the type parameters of the typedef we are looking at. Nothing to report at this point *)
189-
None
190-
else
191-
(* We choose an arbitrary element. If a constraint violation were to contain multiple
192-
tparams of the typedef, we can live with only showing the user one of them. *)
193-
let typedef_tparam_name = SSet.min_elt intersection in
194-
let (used_class_in_def_pos, used_class_in_def_name) = used_class in
195-
let typedef_pos = typedef_info.td_pos in
196-
Some
197-
Typing_error.(
198-
Reasons_callback.always
199-
@@ primary
200-
@@ Primary.HKT_alias_with_implicit_constraints
201-
{
202-
pos = use_pos;
203-
typedef_pos;
204-
used_class_in_def_pos;
205-
typedef_name;
206-
typedef_tparam_name;
207-
used_class_in_def_name;
208-
used_class_tparam_name;
209-
})
210-
in
211-
let check_tapply r class_sid type_args =
212-
let decl_ty = Typing_make_type.apply r class_sid type_args in
213-
let ((env, ty_err_opt), locl_ty) =
214-
TUtils.localize_no_subst env ~ignore_errors:true decl_ty
215-
in
216-
Option.iter ~f:(Typing_error_utils.add_typing_error ~env) ty_err_opt;
217-
match get_node (TUtils.get_base_type env locl_ty) with
218-
| Tclass (cls_name, _, tyl) when not (List.is_empty tyl) ->
219-
(match Env.get_class env (snd cls_name) with
220-
| Decl_entry.Found cls ->
221-
let tc_tparams = Cls.tparams cls in
222-
let ety_env =
223-
{ empty_expand_env with substs = Subst.make_locl tc_tparams tyl }
224-
in
225-
iter2_shortest
226-
begin
227-
fun { tp_name = (_p, x); tp_constraints = cstrl; _ } ty ->
228-
List.iter cstrl ~f:(fun (ck, cstr_ty) ->
229-
let ((env, ty_err1), cstr_ty) =
230-
TUtils.localize ~ety_env env cstr_ty
231-
in
232-
Option.iter
233-
~f:(Typing_error_utils.add_typing_error ~env)
234-
ty_err1;
235-
let (_env, ty_err2) =
236-
TGenConstraint.check_constraint env ck ty ~cstr_ty
237-
@@ report_constraint ty cls_name x
238-
in
239-
Option.iter
240-
ty_err2
241-
~f:(Typing_error_utils.add_typing_error ~env))
242-
end
243-
tc_tparams
244-
tyl
245-
| _ -> ())
246-
| _ -> ()
247-
in
248-
249-
let visitor =
250-
object
251-
inherit [unit] Type_visitor.decl_type_visitor
252-
253-
method! on_tapply _ r name args = check_tapply r name args
254-
end
255-
in
256-
(match typedef_info.td_type_assignment with
257-
| SimpleTypeDef (_vis, td_type) -> visitor#on_type () td_type
258-
| CaseType (variant, variants) ->
259-
List.iter (List.map (variant :: variants) ~f:fst) ~f:(visitor#on_type ()));
260-
maybe visitor#on_type () typedef_info.td_as_constraint;
261-
maybe visitor#on_type () typedef_info.td_super_constraint
262-
263-
(* TODO(T70068435)
264-
This is a workaround until we support proper kind-checking of HK types that impose constraints
265-
on their arguments.
266-
For now, we reject using any class as a HK type that has any constraints on its type parameters.
267-
*)
268-
let check_class_usable_as_hk_type pos class_info =
269-
let class_name = Cls.name class_info in
270-
let tparams = Cls.tparams class_info in
271-
let has_tparam_constraints =
272-
List.exists tparams ~f:(fun tp -> not (List.is_empty tp.tp_constraints))
273-
in
274-
if has_tparam_constraints then
275-
Errors.add_error
276-
Naming_error.(
277-
to_user_error @@ HKT_class_with_constraints_used { pos; class_name })
278-
279-
let report_kind_error env ~use_pos ~def_pos ~tparam_name ~expected ~actual =
280-
let actual_kind = Simple.description_of_kind actual in
281-
let expected_kind = Simple.description_of_kind expected in
282-
Typing_error_utils.add_typing_error ~env
283-
@@ Typing_error.(
284-
primary
285-
@@ Primary.Kind_mismatch
286-
{
287-
pos = use_pos;
288-
decl_pos = def_pos;
289-
tparam_name;
290-
actual_kind;
291-
expected_kind;
292-
})
293-
294158
module Simple = struct
295159
(* TODO(T70068435) Once we support constraints on higher-kinded types, this should only be used
296160
during the localization of declaration site types, everything else should be doing full
@@ -364,27 +228,9 @@ module Simple = struct
364228
`No
365229
in
366230
match get_node tyarg with
367-
| Twildcard ->
368-
let is_higher_kinded = Simple.get_arity kind > 0 in
369-
if is_higher_kinded then (
370-
let pos =
371-
get_reason tyarg |> Reason.to_pos |> Pos_or_decl.unsafe_to_raw_pos
372-
in
373-
Errors.add_error Naming_error.(to_user_error @@ HKT_wildcard pos);
374-
check_well_kinded
375-
~in_signature
376-
~should_check_package_boundary
377-
env
378-
tyarg
379-
nkind
380-
)
231+
| Twildcard -> ()
381232
| _ ->
382-
check_well_kinded
383-
~in_signature
384-
~should_check_package_boundary
385-
env
386-
tyarg
387-
nkind
233+
check_well_kinded ~in_signature ~should_check_package_boundary env tyarg
388234

389235
(** Traverse a type and for each encountered type argument of a type X,
390236
check that it complies with the corresponding type parameter of X (arity and kinds, but not constraints),
@@ -466,23 +312,7 @@ module Simple = struct
466312
List.iter ft_params ~f:(fun p ->
467313
check ~should_check_package_boundary:`No p.fp_type)
468314
(* Interesting cases--------------------------------- *)
469-
| Tgeneric name -> begin
470-
let targs = [] in
471-
match Env.get_pos_and_kind_of_generic env name with
472-
| Some (def_pos, (gen_kind : kind)) ->
473-
let (tparams_named_kinds : Simple.named_kind list) =
474-
Simple.from_full_kind gen_kind |> Simple.get_named_parameter_kinds
475-
in
476-
check_targs_well_kinded
477-
~allow_missing_targs:false
478-
~in_signature
479-
~def_pos
480-
~use_pos
481-
env
482-
targs
483-
tparams_named_kinds
484-
| None -> ()
485-
end
315+
| Tgeneric _ -> ()
486316
| Tapply ((_p, cid), argl) -> begin
487317
match Env.get_class_or_typedef env cid with
488318
| Decl_entry.Found (Env.ClassResult class_info) ->
@@ -530,72 +360,13 @@ module Simple = struct
530360
We use the optional arguments `in_typeconst`, `in_typehint`, `in_targ`
531361
and in_tp_constraint` to determine whether we should bypass package visibility check. *)
532362
and check_well_kinded
363+
~in_signature ~should_check_package_boundary env (ty : decl_ty) =
364+
check_well_kinded_type
365+
~allow_missing_targs:false
533366
~in_signature
534367
~should_check_package_boundary
535368
env
536-
(ty : decl_ty)
537-
(expected_nkind : Simple.named_kind) =
538-
let (expected_name, (expected_kind : Simple.kind)) = expected_nkind in
539-
let r = get_reason ty in
540-
let use_pos = Reason.to_pos r |> Pos_or_decl.unsafe_to_raw_pos in
541-
let kind_error actual_kind env =
542-
let (def_pos, tparam_name) = expected_name in
543-
report_kind_error
544-
env
545-
~use_pos
546-
~def_pos
547-
~tparam_name
548-
~actual:actual_kind
549-
~expected:expected_kind
550-
in
551-
let check_against_tparams tparams =
552-
let overall_kind = Simple.type_with_params_to_simple_kind tparams in
553-
if not (is_subkind env ~sub:overall_kind ~sup:expected_kind) then
554-
kind_error overall_kind env
555-
in
556-
557-
if Int.( = ) (Simple.get_arity expected_kind) 0 then
558-
check_well_kinded_type
559-
~allow_missing_targs:false
560-
~in_signature
561-
~should_check_package_boundary
562-
env
563-
ty
564-
else
565-
match get_node ty with
566-
| Tapply ((_pos, name), []) -> begin
567-
match Env.get_class_or_typedef env name with
568-
| Decl_entry.Found (Env.ClassResult class_info) ->
569-
let tparams = Cls.tparams class_info in
570-
check_class_usable_as_hk_type use_pos class_info;
571-
check_against_tparams tparams
572-
| Decl_entry.Found (Env.TypedefResult typedef) ->
573-
let tparams = typedef.td_tparams in
574-
check_typedef_usable_as_hk_type env use_pos name typedef;
575-
check_against_tparams tparams
576-
| Decl_entry.DoesNotExist
577-
| Decl_entry.NotYetAvailable ->
578-
()
579-
end
580-
| Tgeneric name -> begin
581-
match Env.get_pos_and_kind_of_generic env name with
582-
| Some (_pos, gen_kind) ->
583-
let get_kind = Simple.from_full_kind gen_kind in
584-
if not (is_subkind env ~sub:get_kind ~sup:expected_kind) then
585-
kind_error get_kind env
586-
| None -> ()
587-
end
588-
| Tapply (_, targs) ->
589-
Errors.add_error
590-
Naming_error.(
591-
to_user_error
592-
@@ HKT_partial_application
593-
{
594-
pos = Reason.to_pos r |> Pos_or_decl.unsafe_to_raw_pos;
595-
count = List.length targs;
596-
})
597-
| Tany _ -> ()
598-
| _ -> kind_error (Simple.fully_applied_type ()) env
369+
ty
599370

600371
let check_well_kinded_hint
601372
~in_signature ~should_check_package_boundary env hint =

hphp/hack/src/typing/typing_type_integrity.mli

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ module Simple : sig
2727
should_check_package_boundary:Typing_packages.check_reason ->
2828
Typing_env_types.env ->
2929
decl_ty ->
30-
KindDefs.Simple.named_kind ->
3130
unit
3231

3332
(** Traverse a type and for each encountered type argument of a type X,

0 commit comments

Comments
 (0)