2 * Copyright (c) 2015, Facebook, Inc.
5 * This source code is licensed under the MIT license found in the
6 * LICENSE file in the "hack" directory of this source tree.
11 (* This module performs checks after the naming has been done.
12 Basically any check that doesn't fall in the typing category. *)
13 (* Check of type application arity *)
14 (* Check no `new AbstractClass` (or trait, or interface) *)
15 (* Check no top-level break / continue *)
17 (* NOTE: since the typing environment does not generally contain
18 information about non-Hack code, some of these checks can
19 only be done in strict (i.e. "everything is Hack") mode. Use
20 `if Env.is_strict env.tenv` style checks accordingly.
31 module Env
= Typing_env
32 module Inst
= Decl_instantiate
33 module Phase
= Typing_phase
34 module SN
= Naming_special_names
35 module TGenConstraint
= Typing_generic_constraint
36 module Subst
= Decl_subst
37 module TUtils
= Typing_utils
40 type control_context
=
47 function_name
: string option;
48 class_name
: string option;
49 class_kind
: Ast.class_kind
option;
50 imm_ctrl_ctx
: control_context
;
51 typedef_tparams
: Nast.tparam list
;
52 is_array_append_allowed
: bool;
53 is_reactive
: bool; (* The enclosing function is reactive *)
57 let coroutines_enabled env
=
58 TypecheckerOptions.experimental_feature_enabled
59 (Env.get_options env
.tenv
)
60 TypecheckerOptions.experimental_coroutines
62 let report_coroutines_not_enabled p
=
63 Errors.experimental_feature p
"coroutines"
65 let check_coroutines_enabled condition env p
=
66 if condition
&& not
(coroutines_enabled env
)
67 then report_coroutines_not_enabled p
69 let check_coroutine_constructor name is_coroutine p
=
70 if name
= SN.Members.__construct
&& is_coroutine
71 then Errors.coroutine_in_constructor p
73 let error_on_attr env attrs attr f
=
74 if not
(TypecheckerOptions.unsafe_rx
(Env.get_options env
.tenv
))
75 then match Attributes.find attr attrs
with
76 | Some
{ ua_name
= (p
, _
); _
} -> f p
;
79 let error_if_has_atmost_rx_as_rxfunc_attribute env attrs
=
80 error_on_attr env attrs
81 SN.UserAttributes.uaOnlyRxIfRxFunc_do_not_use
Errors.atmost_rx_as_rxfunc_invalid_location
;
82 error_on_attr env attrs
83 SN.UserAttributes.uaAtMostRxAsFunc
Errors.atmost_rx_as_rxfunc_invalid_location
;
85 module CheckFunctionBody
= struct
86 let rec stmt f_type env st
= match f_type
, st
with
87 | Ast.FSync
, Return
(_
, None
)
88 | Ast.FAsync
, Return
(_
, None
) -> ()
89 | Ast.FSync
, Return
(_
, Some e
)
90 | Ast.FAsync
, Return
(_
, Some e
) ->
91 expr_allow_await f_type env e
;
93 | (Ast.FGenerator
| Ast.FAsyncGenerator
), Return
(p
, e
) ->
96 | Some _
-> Errors.return_in_gen p
);
98 | Ast.FCoroutine
, Return
(_
, e
) ->
99 Option.iter e ~f
:(expr f_type env
)
103 expr_allow_await_or_rx_move f_type env e
;
105 | _
, ( Noop
| Fallthrough
| GotoLabel _
| Goto _
| Break _
| Continue _
106 | Static_var _
| Global_var _
| Unsafe_block _
) -> ()
107 | _
, If
(cond
, b1
, b2
) ->
108 expr f_type env cond
;
120 | _
, Using
(has_await
, e
, b
) ->
121 if has_await
then found_await f_type
(fst e
);
122 expr_allow_await_list f_type env e
;
125 | _
, For
(init
, cond
, incr
, b
) ->
126 expr f_type env init
;
127 expr f_type env cond
;
128 expr f_type env incr
;
131 | _
, Switch
(e
, cl
) ->
133 List.iter cl
(case f_type env
);
135 | _
, Foreach
(_
, (Await_as_v
(p
, _
) | Await_as_kv
(p
, _
, _
)), _
) ->
138 | _
, Foreach
(v
, _
, b
) ->
142 | _
, Try
(b
, cl
, fb
) ->
144 List.iter cl
(catch f_type env
);
145 block f_type
{ env
with t_is_finally
= true } fb
;
147 | _
, Let
((p
, x
), _
, e
) ->
148 (* We treat let statement as an assignment expression *)
149 let fake_expr = (p
, Binop
(Ast.Eq None
, (p
, Lvar
(p
, x
)), e
)) in
150 expr_allow_await f_type env
fake_expr;
153 and found_await ftype p
=
155 | Ast.FCoroutine
-> Errors.await_in_coroutine p
156 | Ast.FSync
| Ast.FGenerator
-> Errors.await_in_sync_function p
159 and block f_type env stl
=
160 List.iter stl
(stmt f_type env
)
162 and start f_type env stl
=
164 | [If
((_
, Id
(_
, c
)), then_stmt
, else_stmt
) ]
166 (* this is the only case when HH\Rx\IS_ENABLED can appear in
167 function body, other occurences are considered errors *)
169 if (HH\Rx\IS_ENABLED
) {}
173 when c
= SN.Rx.is_enabled
->
174 block f_type env then_stmt
;
175 block f_type env else_stmt
;
179 and case f_type env
= function
180 | Default b
-> block f_type env b
182 expr f_type env cond
;
186 and catch f_type env
(_
, _
, b
) = block f_type env b
188 and afield f_type env
= function
189 | AFvalue e
-> expr f_type env e
190 | AFkvalue
(e1
, e2
) -> expr2 f_type env
(e1
, e2
)
192 and expr f_type env
(p
, e
) =
195 and expr_allow_await_list f_type env
((_
, exp
) as e
) =
198 List.iter el
(expr_allow_await f_type env
)
200 expr_allow_await f_type env e
202 and expr_allow_await ?
(is_rhs
=false) f_type env
(p
, exp
) = match f_type
, exp
with
203 | Ast.FAsync
, Await e
204 | Ast.FAsyncGenerator
, Await e
-> expr f_type env e
; ()
205 | Ast.FAsync
, Binop
(Ast.Eq None
, e1
, (_
, Await e
))
206 | Ast.FAsyncGenerator
, Binop
(Ast.Eq None
, e1
, (_
, Await e
)) when not is_rhs
->
210 | _
-> expr_ p f_type env exp
; ()
212 and expr_allow_rx_move orelse f_type env exp
=
214 | _
, Call
(_
, e
, _
, el
, uel
) when is_rx_move e
->
216 List.iter el ~f
:(expr f_type env
);
217 List.iter uel ~f
:(expr f_type env
);
220 orelse f_type env exp
222 and expr_allow_await_or_rx_move f_type env exp
=
224 | _
, Binop
(Ast.Eq None
, e1
, rhs
) ->
226 expr_allow_rx_move
(expr_allow_await ~is_rhs
:true) f_type env rhs
228 expr_allow_await f_type env exp
232 | _
, Id
(_
, v
) -> v
= SN.Rx.move
235 and expr2 f_type env
(e1
, e2
) =
240 and expr_ p f_type env exp
= match f_type
, exp
with
242 | _
, Class_const
((_pos
, CIparent
), ((_
, construct
)))
243 when construct
= SN.Members.__construct
->
244 let () = match Env.get_class env
.tenv
(Env.get_parent_id env
.tenv
) with
245 | Some parent_class
->
246 begin match fst parent_class
.tc_construct
with
247 | None
when parent_class
.tc_kind
= Ast.Cabstract
->
248 Errors.parent_abstract_call construct p parent_class
.tc_pos
;
262 | _
, Dollardollar _
-> ()
263 | _
, Id
(pos
, const
) when const
= SN.Rx.is_enabled
->
264 Errors.rx_is_enabled_invalid_location pos
272 | _
, Pipe
(_
, l
, r
) ->
276 List.iter afl
(afield f_type env
);
279 List.iter afl
(expr2 f_type env
);
282 List.iter afl
(expr f_type env
);
284 | _
, ValCollection
(_
, el
) ->
285 List.iter el
(expr f_type env
);
287 | _
, KeyValCollection
(_
, fdl
) ->
288 List.iter fdl
(expr2 f_type env
);
290 | _
, Clone e
-> expr f_type env e
; ()
291 | _
, Obj_get
(e
, (_
, Id _s
), _
) ->
294 | _
, Obj_get
(e1
, e2
, _
) ->
295 expr2 f_type env
(e1
, e2
);
297 | _
, Array_get
(e
, eopt
) ->
299 maybe
(expr f_type
) env eopt
;
301 | _
, Call
(_
, e
, _
, _
, _
) when is_rx_move e
->
302 Errors.rx_move_invalid_location
(fst e
);
304 | _
, Call
(_
, e
, _
, el
, uel
) ->
306 List.iter el
(expr_allow_rx_move expr f_type env
);
307 List.iter uel
(expr_allow_rx_move expr f_type env
);
309 | _
, True
| _
, False
| _
, Int _
310 | _
, Float _
| _
, Null
| _
, String _
-> ()
311 | _
, PrefixedString
(_
, e
) ->
315 List.iter el
(expr f_type env
);
318 List.iter el
(expr f_type env
);
320 | _
, Pair
(e1
, e2
) ->
321 expr2 f_type env
(e1
, e2
);
324 List.iter el
(expr f_type env
);
326 | _
, Unop
(_
, e
) -> expr f_type env e
327 | _
, Binop
(_
, e1
, e2
) ->
328 expr2 f_type env
(e1
, e2
);
330 | _
, Eif
(e1
, None
, e3
) ->
331 expr2 f_type env
(e1
, e3
);
333 | _
, Eif
(e1
, Some e2
, e3
) ->
334 List.iter
[e1
; e2
; e3
] (expr f_type env
);
336 | _
, New
(_
, el
, uel
) ->
337 List.iter el
(expr f_type env
);
338 List.iter uel
(expr f_type env
);
340 | _
, InstanceOf
(e
, _
)
348 | Ast.FGenerator
, Yield_break
349 | Ast.FAsyncGenerator
, Yield_break
-> ()
350 | Ast.FGenerator
, Yield af
351 | Ast.FAsyncGenerator
, Yield af
-> afield f_type env af
; ()
352 | Ast.FGenerator
, Yield_from e
353 | Ast.FAsyncGenerator
, Yield_from e
-> expr f_type env e
; ()
354 (* Should never happen -- presence of yield should make us FGenerator or
355 * FAsyncGenerator. *)
356 | (Ast.FSync
| Ast.FAsync
), (Yield _
| Yield_from _
| Yield_break
) -> assert false
358 | (Ast.FGenerator
| Ast.FSync
| Ast.FCoroutine
), Await _
->
361 | Ast.FAsync
, Await _
362 | Ast.FAsyncGenerator
, Await _
-> Errors.await_not_allowed p
364 | Ast.FCoroutine
, (Yield _
| Yield_break
| Yield_from _
) ->
365 Errors.yield_in_coroutine p
366 | (Ast.FSync
| Ast.FAsync
| Ast.FGenerator
| Ast.FAsyncGenerator
), Suspend _
->
367 if not
(coroutines_enabled env
)
368 then report_coroutines_not_enabled p
369 else Errors.suspend_outside_of_coroutine p
370 | Ast.FCoroutine
, Suspend _
->
371 if not
(coroutines_enabled env
)
372 then report_coroutines_not_enabled p
373 else if env
.t_is_finally
374 then Errors.suspend_in_finally p
;
375 | _
, Special_func func
->
378 | Gen_array_rec e
-> expr f_type env e
379 | Genva el
-> List.iter el
(expr f_type env
));
381 | _
, Xml
(_
, attrl
, el
) ->
382 List.iter attrl
(fun attr
-> expr f_type env
(get_xhp_attr_expr attr
));
383 List.iter el
(expr f_type env
);
385 | _
, Unsafe_expr _
-> ()
386 | _
, Callconv
(_
, e
) ->
389 | _
, Execution_operator _
-> ()
390 | _
, Assert
(AE_assert e
) ->
394 ShapeMap.iter
(fun _ v
-> expr f_type env v
) fdm
;
400 let h = Caml.Hashtbl.create
23 in
401 let a x
= Caml.Hashtbl.add
h x
true in
402 let _ = SSet.iter
(fun m
-> if m
<> SN.Members.__toString
then a m
) SN.Members.as_set
in
409 let check_conditionally_reactive_annotation_params p params ~is_method
=
411 | [_, Class_const
(_, (_, prop
))] when prop
= "class" -> ()
412 | _ -> Errors.conditionally_reactive_annotation_invalid_arguments ~is_method p
414 let check_conditionally_reactive_annotations is_reactive p method_name user_attributes
=
415 let rec check l seen
=
418 | { ua_name
= (_, name
); ua_params
} :: xs
when name
= SN.UserAttributes.uaOnlyRxIfImpl
->
421 then Errors.multiple_conditionally_reactive_annotations p method_name
423 then check_conditionally_reactive_annotation_params ~is_method
:true p ua_params
;
426 | _ :: xs
-> check xs seen
in
427 check user_attributes
false
429 let is_some_reactivity_attribute { ua_name
= (_, name
); _ } =
430 name
= SN.UserAttributes.uaReactive
||
431 name
= SN.UserAttributes.uaLocalReactive
||
432 name
= SN.UserAttributes.uaShallowReactive
434 (* During NastCheck, all reactivity kinds are the same *)
435 let fun_is_reactive user_attributes
=
436 List.exists user_attributes ~f
:is_some_reactivity_attribute
438 let rec fun_ tenv f named_body
=
439 if !auto_complete
then ()
441 let env = { t_is_finally
= false;
442 is_array_append_allowed
= false;
443 class_name
= None
; class_kind
= None
;
444 imm_ctrl_ctx
= Toplevel
;
445 typedef_tparams
= [];
447 function_name
= None
;
448 is_reactive
= fun_is_reactive f
.f_user_attributes
450 func
env f named_body
453 and func
env f named_body
=
454 let p, fname
= f
.f_name
in
455 let fname_lower = String.lowercase
(strip_ns fname
) in
456 if fname_lower = SN.Members.__construct
|| fname_lower = "using"
457 then Errors.illegal_function_name
p fname
;
458 check_coroutines_enabled (f
.f_fun_kind
= Ast.FCoroutine
) env p;
459 (* Add type parameters to typing environment and localize the bounds *)
460 let tenv, constraints
=
461 Phase.localize_generic_parameters_with_bounds
env.tenv f
.f_tparams
462 ~ety_env
:(Phase.env_with_self
env.tenv) in
463 let tenv = add_constraints
p tenv constraints
in
464 Typing_instantiability.check_tparams_instantiable
tenv f
.f_tparams
;
465 Typing_instantiability.check_params_instantiable
tenv f
.f_params
;
467 tenv = Env.set_mode
tenv f
.f_mode
;
468 t_is_finally
= false;
469 is_reactive
= fun_is_reactive f
.f_user_attributes
;
471 maybe hint
env f
.f_ret
;
472 (* Functions can't be mutable, only methods can *)
473 if Attributes.mem
SN.UserAttributes.uaMutable f
.f_user_attributes
then
474 Errors.mutable_attribute_on_function
p;
475 if Attributes.mem
SN.UserAttributes.uaMaybeMutable f
.f_user_attributes
then
476 Errors.maybe_mutable_attribute_on_function
p;
477 if Attributes.mem
SN.UserAttributes.uaMutableReturn f
.f_user_attributes
478 && not
env.is_reactive
then
479 Errors.mutable_return_annotated_decls_must_be_reactive
"function" p fname
;
481 error_if_has_atmost_rx_as_rxfunc_attribute env f
.f_user_attributes
;
482 check_maybe_rx_attributes_on_params
env f
.f_user_attributes f
.f_params
;
486 && not
(TypecheckerOptions.unsafe_rx
(Env.get_options
env.tenv))
487 then Errors.reference_in_rx
p;
489 List.iter f
.f_tparams
(tparam
env);
490 let byref = List.find f
.f_params ~f
:(fun x
-> x
.param_is_reference
) in
491 List.iter f
.f_params
(fun_param
env f
.f_name f
.f_fun_kind
byref);
493 TypecheckerOptions.disallow_return_by_ref
(Env.get_options
env.tenv)
494 then Errors.illegal_return_by_ref
p;
495 let inout = List.find f
.f_params ~f
:(
496 fun x
-> x
.param_callconv
= Some
Ast.Pinout
) in
499 if Attributes.mem
SN.UserAttributes.uaMemoize f
.f_user_attributes
||
500 Attributes.mem
SN.UserAttributes.uaMemoizeLSB f
.f_user_attributes
501 then Errors.inout_params_memoize
p param
.param_pos
;
502 if f
.f_ret_by_ref
then Errors.inout_params_ret_by_ref
p param
.param_pos
;
506 (match f
.f_variadic
with
507 | FVvariadicArg vparam
->
508 Typing_instantiability.check_param_instantiable
tenv vparam
;
509 if vparam
.param_is_reference
then
510 Errors.variadic_byref_param vparam
.param_pos
513 block
env named_body
.fnb_nast
;
514 CheckFunctionBody.start
519 and tparam
env (_, _, cstrl
, _) =
520 List.iter cstrl
(fun (_, h) -> hint
env h)
522 and hint
env (p, h) =
525 and hint_
env p = function
526 | Hany
| Hmixed
| Hnonnull
| Hprim
_ | Hthis
| Haccess
_ | Habstr
_ | Hdynamic
->
528 | Harray
(ty1
, ty2
) ->
531 | Hdarray
(ty1
, ty2
) ->
534 | Hvarray_or_darray ty
537 | Htuple hl
-> List.iter hl
(hint
env)
540 | Hfun
(_, is_coroutine
, hl
, _, variadic_hint
, h) ->
541 check_coroutines_enabled is_coroutine
env p;
542 List.iter hl
(hint
env);
544 begin match variadic_hint
with
545 | Hvariadic
(Some
h) -> hint
env h;
546 | Hvariadic
(None
) when Env.is_strict
env.tenv ->
547 Errors.ellipsis_strict_mode ~require
:`Type
p;
550 | Happly
((_, x
), hl
) as h when Env.is_typedef x
->
551 begin match Typing_lazy_heap.get_typedef
(Env.get_options
env.tenv) x
with
552 | Some
{td_tparams
; _} ->
553 check_happly
env.typedef_tparams
env.tenv (p, h);
554 check_tparams
env p x td_tparams hl
557 | Happly
((_, x
), hl
) as h ->
558 (match Env.get_class
env.tenv x
with
561 check_happly
env.typedef_tparams
env.tenv (p, h);
562 check_tparams
env p x class_
.tc_tparams hl
565 | Hshape
{ nsi_allows_unknown_fields
=_; nsi_field_map
} ->
566 let compute_hint_for_shape_field_info _ { sfi_hint
; _; } =
567 Typing_instantiability.check_instantiable
env.tenv sfi_hint
;
570 ShapeMap.iter
compute_hint_for_shape_field_info nsi_field_map
572 and check_tparams
env p x tparams hl
=
573 let arity = List.length tparams
in
574 check_arity
env p x
arity (List.length hl
);
575 List.iter hl
(hint
env);
577 and check_arity
env p tname
arity size
=
578 if size
= arity then () else
579 if size
= 0 && not
(Typing_env.is_strict
env.tenv)
580 && not
(TypecheckerOptions.experimental_feature_enabled
(Env.get_options
env.tenv)
581 TypecheckerOptions.experimental_generics_arity
)
584 let nargs = soi
arity in
585 Errors.type_arity
p tname
nargs
587 and check_happly unchecked_tparams
env h =
588 let env = { env with Env.pos
= (fst
h) } in
589 let decl_ty = Decl_hint.hint
env.Env.decl_env
h in
590 let unchecked_tparams =
591 List.map
unchecked_tparams begin fun (v
, sid
, cstrl
, reified
) ->
592 let cstrl = List.map
cstrl (fun (ck
, cstr
) ->
593 let cstr = Decl_hint.hint
env.Env.decl_env
cstr in
595 (v
, sid
, cstrl, reified
)
600 (fun (_, (p, _), _, _) -> Reason.Rwitness
p, Tany
) in
601 let subst = Inst.make_subst
unchecked_tparams tyl in
602 let decl_ty = Inst.instantiate
subst decl_ty in
604 | _, Tapply
(_, tyl) when tyl <> [] ->
605 let env, locl_ty
= Phase.localize_with_self
env decl_ty in
606 begin match TUtils.get_base_type
env locl_ty
with
607 | _, Tclass
(cls
, tyl) ->
608 (match Env.get_class
env (snd cls
) with
609 | Some
{ tc_tparams
; _ } ->
610 (* We want to instantiate the class type parameters with the
611 * type list of the class we are localizing. We do not want to
612 * add any more constraints when we localize the constraints
613 * stored in the class_type since it may lead to infinite
617 { (Phase.env_with_self
env) with
618 substs
= Subst.make tc_tparams
tyl;
620 iter2_shortest
begin fun (_, (p, x
), cstrl, _) ty
->
621 List.iter
cstrl (fun (ck
, cstr_ty
) ->
622 let r = Reason.Rwitness
p in
623 let env, cstr_ty
= Phase.localize ~
ety_env env cstr_ty
in
624 ignore
@@ Errors.try_
626 TGenConstraint.check_constraint
env ck cstr_ty ty
629 Reason.explain_generic_constraint
env.Env.pos
r x l
;
640 if !auto_complete
then () else begin
641 let cname = Some
(snd c
.c_name
) in
642 let env = { t_is_finally
= false;
643 is_array_append_allowed
= false;
645 class_kind
= Some c
.c_kind
;
646 imm_ctrl_ctx
= Toplevel
;
647 typedef_tparams
= [];
649 function_name
= None
;
651 (* Add type parameters to typing environment and localize the bounds *)
652 let tenv, constraints
= Phase.localize_generic_parameters_with_bounds
653 tenv (fst c
.c_tparams
)
654 ~
ety_env:(Phase.env_with_self
tenv) in
655 let tenv = add_constraints
(fst c
.c_name
) tenv constraints
in
656 Typing_instantiability.check_tparams_instantiable
tenv (fst c
.c_tparams
);
657 let env = { env with tenv = Env.set_mode
tenv c
.c_mode
} in
659 error_if_has_atmost_rx_as_rxfunc_attribute env c
.c_user_attributes
;
662 * prevent for abstract final classes, traits, and interfaces
664 if Attributes.mem
SN.UserAttributes.uaConst c
.c_user_attributes
665 then begin match c
.c_kind
, c
.c_final
with
666 | Ast.Cabstract
, true
670 Errors.const_attribute_prohibited
671 (fst c
.c_name
) (Typing_print.class_kind c
.c_kind c
.c_final
);
672 | Ast.Cabstract
, false
673 | Ast.Cnormal
, _ -> ();
675 if c
.c_kind
= Ast.Cabstract
&& c
.c_final
then begin
676 List.iter c
.c_methods
(fun m
-> Errors.nonstatic_method_in_abstract_final_class
(fst m
.m_name
));
677 Option.iter c
.c_constructor
678 (fun m
-> Errors.nonstatic_method_in_abstract_final_class
(fst m
.m_name
))
681 if c
.c_kind
= Ast.Cinterface
then begin
685 maybe method_
(env, true) c
.c_constructor
;
687 List.iter
(fst c
.c_tparams
) (tparam
env);
688 List.iter c
.c_extends
(hint
env);
689 List.iter c
.c_implements
(hint
env);
690 List.iter c
.c_consts
(class_const
env);
691 List.iter c
.c_typeconsts
(typeconst
(env, (fst c
.c_tparams
)));
692 List.iter c
.c_static_vars
(class_var
env);
693 List.iter c
.c_vars
(class_var
env);
694 List.iter c
.c_static_methods
(method_
(env, true));
695 List.iter c
.c_methods
(method_
(env, false));
696 List.iter c
.c_implements
(check_is_interface
(env, "implement"));
697 List.iter c
.c_req_implements
698 (check_is_interface
(env, "require implementation of"));
699 List.iter c
.c_req_extends
(check_is_class
env);
700 List.iter c
.c_uses
(check_is_trait
env);
701 let disallow_static_memoized = TypecheckerOptions.experimental_feature_enabled
702 (Env.get_options
env.tenv)
703 TypecheckerOptions.experimental_disallow_static_memoized
in
704 if disallow_static_memoized && not c
.c_final
then
706 List.iter c
.c_static_methods
(check_static_memoized_function
);
707 maybe
(fun _ m
-> check_static_memoized_function m
) () c
.c_constructor
712 (** Make sure that the given hint points to an interface *)
713 and check_is_interface
(env, error_verb
) (x
: hint
) =
716 (match Env.get_class
env.tenv (snd id
) with
718 (* in partial mode, we can fail to find the class if it's
720 (* in strict mode, we catch the unknown class error before
721 even reaching here. *)
723 | Some
{ tc_kind
= Ast.Cinterface
; _ } -> ()
724 | Some
{ tc_name
; _ } ->
725 Errors.non_interface
(fst x
) tc_name error_verb
728 Errors.non_interface
(fst x
) "generic" error_verb
730 Errors.non_interface
(fst x
) "invalid type hint" error_verb
732 (** Make sure that the given hint points to a non-final class *)
733 and check_is_class
env (x
: hint
) =
736 (match Env.get_class
env.tenv (snd id
) with
738 (* in partial mode, we can fail to find the class if it's
740 (* in strict mode, we catch the unknown class error before
741 even reaching here. *)
743 | Some
{ tc_kind
= Ast.(Cabstract
| Cnormal
); tc_final
; tc_name
; _ } ->
744 if tc_final
then Errors.requires_final_class
(fst x
) tc_name
745 | Some
{ tc_kind
; tc_name
; _ } ->
746 Errors.requires_non_class
(fst x
) tc_name
(Ast.string_of_class_kind tc_kind
)
749 Errors.requires_non_class
(fst x
) name
"a generic"
751 Errors.requires_non_class
(fst x
) "This" "an invalid type hint"
754 * Make sure that all "use"s are with traits, and not
755 * classes, interfaces, etc.
757 and check_is_trait
env (h : hint
) =
758 (* Second part of a hint contains Happly information *)
760 (* An Happly contains identifying info (sid) and hint list (which we *)
761 (* do not care about at this time *)
762 | Happly
(pos_and_name
, _) ->
763 (* Env.get_class will get the type info associated with the name *)
764 let type_info = Env.get_class
env.tenv (snd pos_and_name
) in
765 (match type_info with
766 (* in partial mode, it's possible to not find the trait, because the *)
767 (* trait may live in PHP land. In strict mode, we catch the unknown *)
768 (* trait error before even reaching here. so it's ok to just return *)
771 (* tc_kind is part of the type_info. If we are a trait, all is good *)
772 | Some
{ tc_kind
= Ast.Ctrait
; _ } -> ()
773 (* Anything other than a trait we are going to throw an error *)
774 (* using the tc_kind and tc_name fields of our type_info *)
775 | Some
{ tc_kind
; tc_name
; _ } ->
776 Errors.uses_non_trait
(fst
h) tc_name
(Ast.string_of_class_kind tc_kind
)
778 | _ -> failwith
"assertion failure: trait isn't an Happly"
781 (* Class properties can only be initialized with a static literal expression. *)
782 and check_class_property_initialization prop
=
783 (* Only do the check if property is initialized. *)
784 Option.iter prop
.cv_expr ~f
:begin fun e
->
785 let rec rec_assert_static_literal e
=
788 | Id
_ | Class_const
_ | True
| False
| Int
_ | Float
_
789 | Null
| String
_ | PrefixedString
_ | Unsafe_expr
_
790 | Execution_operator
_ ->
792 | Array field_list
->
793 List.iter field_list
begin function
794 | AFvalue expr
-> rec_assert_static_literal expr
795 | AFkvalue
(expr1
, expr2
) ->
796 rec_assert_static_literal expr1
;
797 rec_assert_static_literal expr2
;
799 | Darray fl
-> List.iter fl assert_static_literal_for_field_list
800 | Varray el
-> List.iter el
rec_assert_static_literal
801 | Shape fl
-> ShapeMap.iter
(fun _ -> rec_assert_static_literal) fl
805 | ValCollection
(_, el
) -> List.iter el
rec_assert_static_literal
806 | Pair
(expr1
, expr2
)
807 | Binop
(_, expr1
, expr2
) ->
808 rec_assert_static_literal expr1
;
809 rec_assert_static_literal expr2
;
810 | KeyValCollection
(_, field_list
) ->
811 List.iter field_list assert_static_literal_for_field_list
814 rec_assert_static_literal e
;
815 | Eif
(expr1
, optional_expr
, expr2
) ->
816 rec_assert_static_literal expr1
;
817 Option.iter optional_expr
rec_assert_static_literal;
818 rec_assert_static_literal expr2
;
819 | This
| Lvar
_ | ImmutableVar
_ | Lplaceholder
_ | Dollardollar
_ | Fun_id
_
820 | Method_id
_ | Dollar
_
821 | Method_caller
_ | Smethod_id
_ | Obj_get
_ | Array_get
_ | Class_get
_
822 | Call
_ | Special_func
_ | Yield_break
| Yield
_ | Yield_from
_ | Suspend
_
823 | Await
_ | InstanceOf
_ | Is
_ | New
_ | Efun
_ | Xml
_ | Callconv
_
824 | Assert
_ | Clone
_ | As
_ | Pipe
_ ->
825 Errors.class_property_only_static_literal
(fst e
)
826 and assert_static_literal_for_field_list
(expr1
, expr2
) =
827 rec_assert_static_literal expr1
;
828 rec_assert_static_literal expr2
830 rec_assert_static_literal e
;
834 let enforce_no_body = begin fun m
->
836 | UnnamedBody
{ fub_ast
= [] ; _}
837 | NamedBody
{ fnb_nast
= [] ; _} ->
838 if m
.m_visibility
= Private
839 then Errors.not_public_or_protected_interface
(fst m
.m_name
)
841 | _ -> Errors.abstract_body
(fst m
.m_name
)
843 (* make sure that interface methods are not async, in line with HHVM *)
844 let enforce_not_async = begin fun m
->
845 match m
.m_fun_kind
with
846 | Ast.FAsync
-> Errors.async_in_interface
(fst m
.m_name
)
847 | Ast.FAsyncGenerator
-> Errors.async_in_interface
(fst m
.m_name
)
850 (* make sure that interfaces only have empty public methods *)
851 List.iter
(c
.c_static_methods
@ c
.c_methods
) enforce_no_body;
852 List.iter
(c
.c_static_methods
@ c
.c_methods
) enforce_not_async;
853 (* make sure constructor has no body *)
854 Option.iter c
.c_constructor
enforce_no_body;
855 Option.iter c
.c_constructor
enforce_not_async;
856 List.iter
(c
.c_uses
) (fun (p, _) ->
857 Errors.interface_use_trait
p
859 (* make sure that interfaces don't have any member variables *)
862 let pos = fst
(hd
.cv_id
) in
863 Errors.interface_with_member_variable
pos
865 (* make sure that interfaces don't have static variables *)
866 match c
.c_static_vars
with
868 let pos = fst
(hd
.cv_id
) in
869 Errors.interface_with_static_member_variable
pos
871 (* make sure interfaces do not contain partially abstract type constants *)
872 List.iter c
.c_typeconsts
begin fun tc
->
873 if tc
.c_tconst_constraint
<> None
&& tc
.c_tconst_type
<> None
then
874 Errors.interface_with_partial_typeconst
(fst tc
.c_tconst_name
)
877 and class_const
env (h, _, e
) =
882 and typeconst
(env, class_tparams
) tconst
=
883 maybe hint
env tconst
.c_tconst_type
;
884 maybe hint
env tconst
.c_tconst_constraint
;
885 (* need to ensure that tconst.c_tconst_type is not Habstr *)
886 maybe check_no_class_tparams class_tparams tconst
.c_tconst_type
;
887 maybe check_no_class_tparams class_tparams tconst
.c_tconst_constraint
889 (* Check to make sure we are not using class type params for type const decls *)
890 and check_no_class_tparams class_tparams
(pos, ty
) =
891 let check_tparams = check_no_class_tparams class_tparams
in
892 let maybe_check_tparams = maybe check_no_class_tparams class_tparams
in
893 let matches_class_tparam tp_name
=
894 List.iter class_tparams
begin fun (_, (c_tp_pos
, c_tp_name
), _, _) ->
895 if c_tp_name
= tp_name
896 then Errors.typeconst_depends_on_external_tparam
pos c_tp_pos c_tp_name
899 | Hany
| Hmixed
| Hnonnull
| Hprim
_ | Hthis
| Hdynamic
-> ()
900 (* We have found a type parameter. Make sure its name does not match
901 * a name in class_tparams *)
902 | Habstr tparam_name
->
903 matches_class_tparam tparam_name
904 | Harray
(ty1
, ty2
) ->
905 maybe_check_tparams ty1
;
906 maybe_check_tparams ty2
907 | Hdarray
(ty1
, ty2
) ->
910 | Hvarray_or_darray ty
913 | Htuple
tyl -> List.iter
tyl check_tparams
914 | Hoption ty_
-> check_tparams ty_
915 | Hfun
(_, _, tyl, _, _, ty_
) ->
916 List.iter
tyl check_tparams;
918 | Happly
(_, tyl) -> List.iter
tyl check_tparams
919 | Hshape
{ nsi_allows_unknown_fields
=_; nsi_field_map
} ->
920 ShapeMap.iter
(fun _ v
-> check_tparams v
.sfi_hint
) nsi_field_map
921 | Haccess
(root_ty
, _) ->
922 check_tparams root_ty
924 and class_var
env cv
=
925 check_class_property_initialization cv
;
927 (* If this is an XHP attribute and we're in strict mode,
928 relax to partial mode to allow the use of generic
929 classes without specifying type parameters. This is
930 a temporary hack to support existing code for now. *)
931 (* Task #5815945: Get rid of this Hack *)
932 if cv
.cv_is_xhp
&& (Typing_env.is_strict
env.tenv)
933 then { env with tenv = Typing_env.set_mode
env.tenv FileInfo.Mpartial
}
935 maybe hint
hint_env cv
.cv_type
;
936 maybe expr
env cv
.cv_expr
;
939 and check__toString m is_static
=
940 if snd m
.m_name
= SN.Members.__toString
942 if m
.m_visibility
<> Public
|| is_static
943 then Errors.toString_visibility
(fst m
.m_name
);
945 | Some
(_, Hprim Tstring
) -> ()
946 | Some
(p, _) -> Errors.toString_returns_string
p
950 and add_constraint
pos tenv (ty1
, ck
, ty2
) =
951 Typing_subtype.add_constraint
pos tenv ck ty1 ty2
953 and add_constraints
pos tenv (cstrs
: locl where_constraint list
) =
954 List.fold_left cstrs ~init
:tenv ~f
:(add_constraint
pos)
956 and check_static_memoized_function m
=
957 if Attributes.mem
SN.UserAttributes.uaMemoize m
.m_user_attributes
||
958 Attributes.mem
SN.UserAttributes.uaMemoizeLSB m
.m_user_attributes
then
959 Errors.static_memoized_function
(fst m
.m_name
);
962 and method_
(env, is_static
) m
=
964 { env with is_reactive
= fun_is_reactive m
.m_user_attributes
} in
965 let named_body = assert_named_body m
.m_body
in
966 check__toString m is_static
;
967 let env = { env with function_name
= Some
(snd m
.m_name
) } in
968 let p, name
= m
.m_name
in
969 let is_coroutine = m
.m_fun_kind
= Ast.FCoroutine
in
970 check_coroutines_enabled is_coroutine env p;
971 check_coroutine_constructor name
is_coroutine p;
972 (* Add method type parameters to environment and localize the bounds *)
973 let tenv, constraints
=
974 Phase.localize_generic_parameters_with_bounds
env.tenv m
.m_tparams
975 ~
ety_env:(Phase.env_with_self
env.tenv) in
976 let tenv = add_constraints
(fst m
.m_name
) tenv constraints
in
977 Typing_instantiability.check_tparams_instantiable
tenv m
.m_tparams
;
978 Typing_instantiability.check_params_instantiable
tenv m
.m_params
;
979 let env = { env with tenv = tenv } in
981 (* If this is a destructor make sure it is allowed *)
982 if name
= SN.Members.__destruct
983 && not
(Attributes.mem
SN.UserAttributes.uaOptionalDestruct m
.m_user_attributes
)
984 then Errors.illegal_destructor
p;
986 let is_mutable, is_mutable_pos
=
987 Attributes.find
SN.UserAttributes.uaMutable m
.m_user_attributes
989 ~default
:(false, Pos.none
)
990 ~f
:(fun { ua_name
= (p, _); _ } -> true, p) in
993 let is_maybe_mutable =
994 Attributes.mem
SN.UserAttributes.uaMaybeMutable m
.m_user_attributes
in
996 (* Mutable methods must be reactive *)
997 if not
env.is_reactive
then begin
999 then Errors.mutable_methods_must_be_reactive
p name
;
1001 then Errors.maybe_mutable_methods_must_be_reactive
p name
;
1006 then Errors.conflicting_mutable_and_maybe_mutable_attributes
p;
1007 if is_static
&& name
<> SN.Members.__construct
1008 then Errors.mutable_on_static is_mutable_pos
;
1011 (*Methods annotated with MutableReturn attribute must be reactive *)
1012 if Attributes.mem
SN.UserAttributes.uaMutableReturn m
.m_user_attributes
1013 && not
env.is_reactive
then
1014 Errors.mutable_return_annotated_decls_must_be_reactive
"method" p name
;
1016 check_conditionally_reactive_annotations env.is_reactive
p name m
.m_user_attributes
;
1017 error_if_has_atmost_rx_as_rxfunc_attribute env m
.m_user_attributes
;
1018 check_maybe_rx_attributes_on_params
env m
.m_user_attributes m
.m_params
;
1020 let byref = List.find m
.m_params ~f
:(fun x
-> x
.param_is_reference
) in
1021 List.iter m
.m_params
(fun_param
env m
.m_name m
.m_fun_kind
byref);
1022 if m
.m_ret_by_ref
&&
1023 TypecheckerOptions.disallow_return_by_ref
(Env.get_options
env.tenv)
1024 then Errors.illegal_return_by_ref
p;
1025 let inout = List.find m
.m_params ~f
:(
1026 fun x
-> x
.param_callconv
= Some
Ast.Pinout
) in
1029 if Attributes.mem
SN.UserAttributes.uaMemoize m
.m_user_attributes
||
1030 Attributes.mem
SN.UserAttributes.uaMemoizeLSB m
.m_user_attributes
1031 then Errors.inout_params_memoize
p param
.param_pos
;
1032 if m
.m_ret_by_ref
then Errors.inout_params_ret_by_ref
p param
.param_pos
;
1036 (match m
.m_variadic
with
1037 | FVvariadicArg vparam
->
1038 Typing_instantiability.check_param_instantiable
tenv vparam
;
1039 if vparam
.param_is_reference
then
1040 Errors.variadic_byref_param vparam
.param_pos
1043 List.iter m
.m_tparams
(tparam
env);
1044 block
env named_body.fnb_nast
;
1045 maybe hint
env m
.m_ret
;
1046 CheckFunctionBody.start
1049 named_body.fnb_nast
;
1050 if m
.m_abstract
&& named_body.fnb_nast
<> []
1051 then Errors.abstract_with_body m
.m_name
;
1052 if not
(Env.is_decl
env.tenv) && not m
.m_abstract
&& named_body.fnb_nast
= []
1053 then Errors.not_abstract_without_body m
.m_name
;
1054 (match env.class_name
with
1056 let p, mname
= m
.m_name
in
1057 if String.lowercase
(strip_ns
cname) = String.lowercase mname
1058 && env.class_kind
<> Some
Ast.Ctrait
1059 then Errors.dangerous_method_name
p
1061 | None
-> assert false)
1063 and check_maybe_rx_attributes_on_params
env parent_attrs params
=
1064 let parent_only_rx_if_args =
1065 Attributes.find2
SN.UserAttributes.uaOnlyRxIfArgs_do_not_use
1066 SN.UserAttributes.uaAtMostRxAsArgs parent_attrs
in
1067 let check_param seen_atmost_rx_as_rxfunc
p =
1068 let only_rx_if_rxfunc_attr =
1069 Attributes.find2
SN.UserAttributes.uaOnlyRxIfRxFunc_do_not_use
1070 SN.UserAttributes.uaAtMostRxAsFunc
p.param_user_attributes
in
1071 let only_rx_if_impl_attr =
1072 Attributes.find
SN.UserAttributes.uaOnlyRxIfImpl
p.param_user_attributes
in
1073 match only_rx_if_rxfunc_attr, only_rx_if_impl_attr with
1074 | Some
{ ua_name
= (p, _); _ }, _ ->
1075 if parent_only_rx_if_args = None
|| not
env.is_reactive
1076 then Errors.atmost_rx_as_rxfunc_invalid_location
p;
1078 | _, Some
{ ua_name
= (p, _); ua_params
; _ } ->
1079 if parent_only_rx_if_args = None
|| not
env.is_reactive
1080 then Errors.atmost_rx_as_rxfunc_invalid_location
p
1081 else check_conditionally_reactive_annotation_params ~is_method
:false p ua_params
;
1083 | _ -> seen_atmost_rx_as_rxfunc
in
1084 let has_param_with_atmost_rx_as_rxfunc =
1085 List.fold_left params ~init
:false ~f
:check_param in
1086 match parent_only_rx_if_args, has_param_with_atmost_rx_as_rxfunc with
1087 | Some
{ ua_name
= (p, _); _ }, false ->
1088 Errors.no_atmost_rx_as_rxfunc_for_rx_if_args
p
1091 and param_is_mutable
p =
1092 Attributes.mem
SN.UserAttributes.uaMutable
p.param_user_attributes
1094 and param_is_maybe_mutable
p =
1095 Attributes.mem
SN.UserAttributes.uaMaybeMutable
p.param_user_attributes
1097 and fun_param
env (pos, name
) f_type
byref param
=
1098 maybe hint
env param
.param_hint
;
1099 maybe expr
env param
.param_expr
;
1100 let is_mutable = param_is_mutable param
in
1101 let is_maybe_mutable = param_is_maybe_mutable param
in
1102 if not
env.is_reactive
then begin
1104 then Errors.mutable_methods_must_be_reactive param
.param_pos name
;
1106 then Errors.maybe_mutable_methods_must_be_reactive param
.param_pos name
;
1110 && param
.param_is_reference
1111 && not
(TypecheckerOptions.unsafe_rx
(Env.get_options
env.tenv))
1112 then Errors.reference_in_rx
pos;
1114 match param
.param_callconv
with
1116 | Some
Ast.Pinout
->
1117 let pos = param
.param_pos
in
1118 if f_type
<> Ast.FSync
then Errors.inout_params_outside_of_sync
pos;
1119 if SSet.mem name
SN.Members.as_set
then Errors.inout_params_special
pos;
1120 Option.iter
byref ~f
:(fun param
->
1121 Errors.inout_params_mix_byref
pos param
.param_pos
);
1124 and stmt env = function
1125 | Return
(p, _) when env.t_is_finally
->
1126 Errors.return_in_finally
p; ()
1134 match env.imm_ctrl_ctx
with
1135 | Toplevel
-> Errors.toplevel_break
p
1138 | Continue
p -> begin
1139 match env.imm_ctrl_ctx
with
1140 | Toplevel
-> Errors.toplevel_continue
p
1141 | SwitchContext
-> Errors.continue_in_switch
p
1144 | Return
(_, Some e
)
1145 | Expr e
| Throw
(_, e
) ->
1157 block
{ env with imm_ctrl_ctx
= LoopContext
} b
;
1162 block
{ env with imm_ctrl_ctx
= LoopContext
} b
;
1164 | Using
(_has_await
, e
, b
) ->
1168 | For
(e1
, e2
, e3
, b
) ->
1172 block
{ env with imm_ctrl_ctx
= LoopContext
} b
;
1176 List.iter cl
(case
{ env with imm_ctrl_ctx
= SwitchContext
});
1178 | Foreach
(e1
, ae
, b
) ->
1181 block
{ env with imm_ctrl_ctx
= LoopContext
} b
;
1183 | Try
(b
, cl
, fb
) ->
1185 List.iter cl
(catch
env);
1186 block
{ env with t_is_finally
= true } fb
;
1188 | Let
((p, x
), _, e
) ->
1189 (* We treat let statement as assignment expresssions *)
1190 let fake_expr = (p, Binop
(Ast.Eq None
, (p, Lvar
(p, x
)), e
)) in
1194 and as_expr
env = function
1196 | Await_as_v
(_, e
) -> expr
env e
1198 | Await_as_kv
(_, e1
, e2
) ->
1203 and afield
env = function
1204 | AFvalue e
-> expr
env e
1205 | AFkvalue
(e1
, e2
) -> expr
env e1
; expr
env e2
;
1208 List.iter stl
(stmt env)
1210 and expr
env (p, e
) =
1213 and expr_
env p = function
1225 | Unsafe_expr
_ -> ()
1226 | Class_const
(cid
, ((_, m_name
) as mid
)) ->
1227 let func_name = env.function_name
in
1229 (not
(is_parent cid
) || func_name <> Some m_name
)
1230 then Errors.magic mid
;
1233 let env'
= {env with is_array_append_allowed
= false} in
1235 | Pipe
(_, e1
, e2
) ->
1240 (* Check that __CLASS__ and __TRAIT__ are used appropriately *)
1241 | Id
(pos, const
) ->
1242 if SN.PseudoConsts.is_pseudo_const const
then
1243 if const
= SN.PseudoConsts.g__CLASS__
then
1244 (match env.class_kind
with
1246 | _ -> Errors.illegal_CLASS
pos)
1247 else if const
= SN.PseudoConsts.g__TRAIT__
then
1248 (match env.class_kind
with
1249 | Some
Ast.Ctrait
-> ()
1250 | _ -> Errors.illegal_TRAIT
pos);
1253 List.iter afl
(afield
env);
1256 List.iter fdl
(field
env);
1259 List.iter el
(expr
env);
1261 | ValCollection
(_, el
) ->
1262 List.iter el
(expr
env);
1264 | KeyValCollection
(_, fdl
) ->
1265 List.iter fdl
(field
env);
1267 | Clone e
-> expr
env e
; ()
1268 | Obj_get
(e
, (_, Id s
), _) ->
1270 then Errors.magic s
;
1271 let env'
= {env with is_array_append_allowed
= false} in
1274 | Obj_get
(e1
, e2
, _) ->
1275 let env'
= {env with is_array_append_allowed
= false} in
1279 | Array_get
((p, _), None
) when not
env.is_array_append_allowed
->
1280 Errors.reading_from_append
p;
1282 | Array_get
(e
, eopt
) ->
1283 let env'
= {env with is_array_append_allowed
= false} in
1285 maybe expr
env' eopt
;
1287 | Call
(_, e
, _, el
, uel
) ->
1289 List.iter el
(expr
env);
1290 List.iter uel
(expr
env);
1292 | True
| False
| Int
_
1293 | Float
_ | Null
| String
_ | PrefixedString
_ -> ()
1295 List.iter el
(expr
env);
1297 | Unop
(Ast.Uref
, e
) ->
1299 begin match snd e
with
1301 Errors.illegal_by_ref_expr
p SN.SpecialIdents.this
1302 | Dollardollar
(_, id
)
1303 when Local_id.to_string id
= SN.SpecialIdents.dollardollar
->
1304 Errors.illegal_by_ref_expr
p SN.SpecialIdents.dollardollar
1307 | Unop
(_, e
) -> expr
env e
;
1309 | Special_func func
->
1312 | Gen_array_rec e
->
1315 List.iter el
(expr
env));
1330 List.iter el
(expr
env);
1337 List.iter el
(expr
env);
1343 | Binop
(op
, e1
, e2
) ->
1344 let lvalue_env = match op
with
1345 | Ast.Eq
_ -> { env with is_array_append_allowed
= true }
1350 | Eif
(e1
, None
, e3
) ->
1354 | Eif
(e1
, Some e2
, e3
) ->
1359 | Assert
(AE_assert e
) ->
1362 | InstanceOf
(e
, e2
) ->
1364 | _, CIexpr
(_, Class_const
((_, CI
((_, classname
), _)), (p, "class"))) ->
1365 Errors.classname_const_instanceof
(Utils.strip_ns classname
) p;
1374 | New
(_, el
, uel
) ->
1375 List.iter el
(expr
env);
1376 List.iter uel
(expr
env);
1379 check_coroutines_enabled (f
.f_fun_kind
= Ast.FCoroutine
) env p;
1380 let env = { env with imm_ctrl_ctx
= Toplevel
} in
1381 let body = Nast.assert_named_body f
.f_body
in
1383 | Xml
(_, attrl
, el
) ->
1384 List.iter attrl
(fun attr
-> expr
env (get_xhp_attr_expr attr
));
1385 List.iter el
(expr
env);
1387 | Callconv
(_, e
) ->
1389 let rec aux = function
1391 | _, Array_get
(e1
, Some
_) -> aux e1
1394 if not
(aux e
) then Errors.inout_argument_bad_expr
(fst e
);
1396 | Execution_operator
_ -> ()
1398 ShapeMap.iter
(fun _ v
-> expr
env v
) fdm
1400 and case
env = function
1401 | Default b
-> block
env b
1407 and catch
env (_, _, b
) = block
env b
1408 and field
env (e1
, e2
) =
1413 let typedef tenv t
=
1414 let env = { t_is_finally
= false;
1415 is_array_append_allowed
= false;
1416 class_name
= None
; class_kind
= None
;
1417 imm_ctrl_ctx
= Toplevel
;
1418 function_name
= None
;
1419 (* Since typedefs cannot have constraints we shouldn't check
1420 * if its type params satisfy the constraints of any tapply it
1423 typedef_tparams
= t
.t_tparams
;
1427 maybe hint
env t
.t_constraint
;