Permalink
Browse files

Conditional reactivity

Summary:
Prior to this diff functions can be conditionally reactive only for the parameter of the receiver. 'Conditionally reactive' function with condition type `T `here means that function can be invoked in reactive context if static type of the receiver is known to be a subtype of `T` or have a condition type `T2` which is a subtype of `T`. With this diff condition for conditionally reactive function can be attached to any parameter of the function - for example
```
<<__Rx, __OnlyRxIfArgs
function f(<<__OnlyRxIfImpl(Rx::class)>> A $a): void { ... }
```
here call to function `f` is allowed in reactive context only if argument that correspond to parameter `$a` is s subtype of `Rx` - receiver is treated similarly to any other parameters.

In order to  associate condition type with parameter type (`Rx` with `A` in example above) we do the following: when localizing function parameters if parameter has associated conditional type we'll create a generic type with name uniquely derived from the pair (declared type + condition type). This name is used as a key for the map in `env` that maps name of generic parameter to a condition type. Then we set declared type as a constraint for this fresh generic type and return generic type as type of parameter. This allows to retrieve condition type for a given parameter type later when we do checks for function calls.

Reviewed By: jamesjwu

Differential Revision: D8601706

fbshipit-source-id: 4169dace804d63a8596fefab5e0166e7799bd1d4
  • Loading branch information...
vladima authored and hhvm-bot committed Jun 25, 2018
1 parent ff6566a commit 826d91fd106cc7a49bc0b67a20e3384272a5ef22
Showing with 1,109 additions and 270 deletions.
  1. +8 −19 hphp/hack/src/decl/decl.ml
  2. +3 −4 hphp/hack/src/decl/decl.mli
  3. +2 −0 hphp/hack/src/errors/error_codes.ml
  4. +40 −9 hphp/hack/src/errors/errors.ml
  5. +6 −1 hphp/hack/src/errors/errors_sig.ml
  6. +72 −19 hphp/hack/src/typing/typing.ml
  7. +16 −0 hphp/hack/src/typing/typing_defs.ml
  8. +9 −0 hphp/hack/src/typing/typing_env.ml
  9. +3 −0 hphp/hack/src/typing/typing_env.mli
  10. +5 −0 hphp/hack/src/typing/typing_env_types.ml
  11. +5 −0 hphp/hack/src/typing/typing_env_types_sig.mli
  12. +237 −54 hphp/hack/src/typing/typing_reactivity.ml
  13. +218 −114 hphp/hack/src/typing/typing_subtype.ml
  14. +2 −0 hphp/hack/test/errors/error_map.ml
  15. +4 −2 hphp/hack/test/integration_ml/test_function_arg_rx_if_implements1.ml
  16. +4 −2 hphp/hack/test/integration_ml/test_function_arg_rx_if_implements2.ml
  17. +18 −0 hphp/hack/test/typecheck/generic_condition_type1.php
  18. +1 −0 hphp/hack/test/typecheck/generic_condition_type1.php.exp
  19. +21 −0 hphp/hack/test/typecheck/generic_condition_type2.php
  20. +1 −0 hphp/hack/test/typecheck/generic_condition_type2.php.exp
  21. +4 −2 hphp/hack/test/typecheck/reactive/call_on_subtype_of_condition_type.php.exp
  22. +14 −0 hphp/hack/test/typecheck/reactive/conditional_rx1.php
  23. +1 −0 hphp/hack/test/typecheck/reactive/conditional_rx1.php.exp
  24. +15 −0 hphp/hack/test/typecheck/reactive/conditional_rx2.php
  25. +1 −0 hphp/hack/test/typecheck/reactive/conditional_rx2.php.exp
  26. +18 −0 hphp/hack/test/typecheck/reactive/conditional_rx3.php
  27. +6 −0 hphp/hack/test/typecheck/reactive/conditional_rx3.php.exp
  28. +14 −0 hphp/hack/test/typecheck/reactive/conditional_rx4.php
  29. +1 −0 hphp/hack/test/typecheck/reactive/conditional_rx4.php.exp
  30. +14 −0 hphp/hack/test/typecheck/reactive/conditional_rx5.php
  31. +1 −0 hphp/hack/test/typecheck/reactive/conditional_rx5.php.exp
  32. +4 −2 hphp/hack/test/typecheck/reactive/mayberx14.php.exp
  33. +4 −2 hphp/hack/test/typecheck/reactive/mayberx15.php.exp
  34. +19 −0 hphp/hack/test/typecheck/reactive/mayberx16.php
  35. +11 −0 hphp/hack/test/typecheck/reactive/mayberx16.php.exp
  36. +13 −0 hphp/hack/test/typecheck/reactive/mayberx16_1.php
  37. +1 −0 hphp/hack/test/typecheck/reactive/mayberx16_1.php.exp
  38. +17 −0 hphp/hack/test/typecheck/reactive/mayberx17.php
  39. +1 −0 hphp/hack/test/typecheck/reactive/mayberx17.php.exp
  40. +17 −0 hphp/hack/test/typecheck/reactive/mayberx18.php
  41. +11 −0 hphp/hack/test/typecheck/reactive/mayberx18.php.exp
  42. +17 −0 hphp/hack/test/typecheck/reactive/mayberx19.php
  43. +1 −0 hphp/hack/test/typecheck/reactive/mayberx19.php.exp
  44. +17 −0 hphp/hack/test/typecheck/reactive/mayberx20.php
  45. +1 −0 hphp/hack/test/typecheck/reactive/mayberx20.php.exp
  46. +21 −0 hphp/hack/test/typecheck/reactive/mayberx21.php
  47. +1 −0 hphp/hack/test/typecheck/reactive/mayberx21.php.exp
  48. +4 −2 hphp/hack/test/typecheck/reactive/mayberx7_1.php.exp
  49. +4 −2 hphp/hack/test/typecheck/reactive/mayberx7_2.php.exp
  50. +4 −2 hphp/hack/test/typecheck/reactive/mayberx8.php.exp
  51. +4 −2 hphp/hack/test/typecheck/reactive/mayberx9.php.exp
  52. +4 −2 hphp/hack/test/typecheck/reactive/nullable_mayberx2.php.exp
  53. +26 −0 hphp/hack/test/typecheck/reactive/only_rx_if_impl_arg1.php
  54. +1 −0 hphp/hack/test/typecheck/reactive/only_rx_if_impl_arg1.php.exp
  55. +21 −0 hphp/hack/test/typecheck/reactive/onlyrx_if_impl1.php
  56. +1 −0 hphp/hack/test/typecheck/reactive/onlyrx_if_impl1.php.exp
  57. +22 −0 hphp/hack/test/typecheck/reactive/onlyrx_if_impl2.php
  58. +4 −0 hphp/hack/test/typecheck/reactive/onlyrx_if_impl2.php.exp
  59. +23 −0 hphp/hack/test/typecheck/reactive/rx_conditional2.php
  60. +1 −0 hphp/hack/test/typecheck/reactive/rx_conditional2.php.exp
  61. +4 −2 hphp/hack/test/typecheck/reactive/rx_if_arg_impl2.php.exp
  62. +4 −2 hphp/hack/test/typecheck/reactive/rx_if_impl_local.php.exp
  63. +4 −2 hphp/hack/test/typecheck/reactive/rx_if_implements16.php.exp
  64. +4 −2 hphp/hack/test/typecheck/reactive/rx_if_implements24.php.exp
  65. +4 −2 hphp/hack/test/typecheck/reactive/rx_if_implements25.php.exp
  66. +4 −2 hphp/hack/test/typecheck/reactive/rx_if_implements27.php.exp
  67. +4 −2 hphp/hack/test/typecheck/reactive/rx_if_implements28.php.exp
  68. +4 −2 hphp/hack/test/typecheck/reactive/rx_if_implements29.php.exp
  69. +4 −2 hphp/hack/test/typecheck/reactive/rx_if_implements30.php.exp
  70. +4 −2 hphp/hack/test/typecheck/reactive/static_rx_if_implements5.php.exp
  71. +4 −2 hphp/hack/test/typecheck/reactive/static_rx_if_implements6.php.exp
  72. +4 −2 hphp/hack/test/typecheck/reactive/static_rx_if_implements7.php.exp
  73. +4 −2 hphp/hack/test/typecheck/reactive/static_rx_if_implements8.php.exp
  74. +4 −2 hphp/hack/test/typecheck/reactive/static_rx_if_implements8_1.php.exp
  75. +4 −2 hphp/hack/test/typecheck/reactive/static_rx_if_implements8_2.php.exp
  76. +9 −0 hphp/hack/test/typecheck/typealias_as_condition_type1.php
  77. +1 −0 hphp/hack/test/typecheck/typealias_as_condition_type1.php.exp
@@ -41,36 +41,25 @@ let conditionally_reactive_attribute_to_hint env { ua_params = l; _ } =
naming step, do nothing *)
Reason.none, Tany
let condition_type_from_attributes env user_attributes =
Attributes.find SN.UserAttributes.uaOnlyRxIfImpl user_attributes
|> Option.map ~f:(conditionally_reactive_attribute_to_hint env)
let fun_reactivity env user_attributes =
let has attr = Attributes.mem attr user_attributes in
let module UA = SN.UserAttributes in
let rx_condition =
Attributes.find UA.uaOnlyRxIfImpl user_attributes
|> Option.map ~f:(conditionally_reactive_attribute_to_hint env) in
let rx_condition = condition_type_from_attributes env user_attributes in
if has UA.uaReactive then Reactive rx_condition
else if has UA.uaShallowReactive then Shallow rx_condition
else if has UA.uaLocalReactive then Local rx_condition
else Nonreactive
let adjust_reactivity_of_mayberx_parameter attrs reactivity param_ty =
let has_only_rx_if_args =
Attributes.mem SN.UserAttributes.uaOnlyRxIfArgs attrs in
(* strip conditional reactivity if parent has one *)
let reactivity =
match reactivity with
| Local (Some _) -> Local None
| Shallow (Some _) -> Shallow None
| Reactive (Some _) -> Reactive None
| r -> r in
match has_only_rx_if_args, param_ty with
| true, (r, Tfun tfun) ->
r, Tfun { tfun with ft_reactive = MaybeReactive reactivity }
| true, (r, Toption (r1, Tfun tfun)) ->
r, Toption (r1, Tfun { tfun with ft_reactive = MaybeReactive reactivity })
| _ ->
param_ty
if Attributes.mem SN.UserAttributes.uaOnlyRxIfArgs attrs
then make_function_type_mayberx reactivity param_ty
else param_ty
(*****************************************************************************)
(* Checking that the kind of a class is compatible with its parent
@@ -17,11 +17,10 @@ val fun_reactivity :
Nast.user_attribute list ->
Typing_defs.reactivity
val adjust_reactivity_of_mayberx_parameter:
val condition_type_from_attributes:
Decl_env.env ->
Nast.user_attribute list ->
Typing_defs.reactivity ->
Typing_defs.decl Typing_defs.ty ->
Typing_defs.decl Typing_defs.ty
Typing_defs.decl Typing_defs.ty option
(*
* This function works by side effects. It is adding in the
@@ -470,6 +470,8 @@ module Typing = struct
| ShapesIdxWithNonExistentField
| NonClassMember
| PassingArrayCellByRef
| CallSiteReactivityMismatch
| RxParameterConditionMismatch
(* EXTEND HERE WITH NEW VALUES IF NEEDED *)
[@@ deriving enum, show { with_path = false } ]
let err_code = to_enum
@@ -2262,15 +2262,6 @@ let untyped_lambda_strict_mode pos =
in
add (Typing.err_code Typing.UntypedLambdaStrictMode) pos msg
let invalid_conditionally_reactive_call pos def_pos condition_type receiver_type =
add_list (Typing.err_code Typing.InvalidConditionallyReactiveCall) [
pos, "Conditionally reactive method with condition type '" ^ condition_type ^
"' cannot be called";
def_pos, "Calling such methods is allowed only from conditionally " ^
"reactive methods with the same condition type or if static type of method " ^
"receiver is a subtype of condition type, now '" ^ receiver_type ^ "'."
]
let echo_in_reactive_context pos =
add (Typing.err_code Typing.EchoInReactiveContext) pos (
"'echo' or 'print' are not allowed in reactive or shallow-reactive functions."
@@ -2383,6 +2374,40 @@ let mutable_in_nonreactive_context pos =
add (Typing.err_code Typing.MutableInNonreactiveContext) pos
("\\HH\\Rx\\mutable can only be used in reactive functions")
let invalid_argument_type_for_condition_in_rx
~is_receiver f_pos def_pos arg_pos expected_type actual_type =
let arg_msg =
if is_receiver then "Receiver type" else "Argument type" in
let arg_msg =
arg_msg ^ " must be a subtype of " ^ expected_type ^
", now " ^ actual_type ^ "." in
add_list (Typing.err_code Typing.InvalidConditionallyReactiveCall) [
f_pos, "Cannot invoke conditionally reactive function in reactive context, \
because at least one reactivity condition is not met.";
arg_pos, arg_msg;
def_pos, "This is the function declaration";
]
let callsite_reactivity_mismatch f_pos def_pos callee_reactivity caller_reactivity =
add_list (Typing.err_code Typing.CallSiteReactivityMismatch) [
f_pos, "Reactivity mismatch: " ^ caller_reactivity ^ " function cannot call " ^
callee_reactivity ^ " function.";
def_pos, "This is declaration of the function being called."
]
let invalid_function_type_for_condition_in_rx
f_pos def_pos arg_pos actual_reactivity expected_reactivity =
let arg_msg =
"Argument type is must be " ^ expected_reactivity ^ " function, " ^
actual_reactivity ^ " given." in
add_list (Typing.err_code Typing.InvalidConditionallyReactiveCall) [
f_pos, "Cannot invoke conditionally reactive function in reactive context, \
because at least one reactivity condition is not met.";
arg_pos, arg_msg;
def_pos, "This is the function declaration";
]
let invalid_argument_of_rx_mutable_function pos =
add (Typing.err_code Typing.InvalidArgumentOfRxMutableFunction) pos (
"Single argument to \\HH\\Rx\\mutable should be an expression that yields new \
@@ -2964,6 +2989,12 @@ let rx_enabled_in_lambdas pos =
"\\HH\\Rx\\IS_ENABLED cannot be used inside lambdas."
)
let rx_parameter_condition_mismatch cond pos def_pos =
add_list (Typing.err_code Typing.RxParameterConditionMismatch) [
pos, "This parameter does not satisfy "^ cond ^ " condition defined on \
matching parameter in function super type.";
def_pos, "This is parameter declaration from the function super type."
]
let nonreactive_append pos =
let msg = "Cannot append to a Hack Collection object in a reactive context" in
add (Typing.err_code Typing.NonreactiveAppend) pos msg
@@ -522,7 +522,6 @@ module type S = sig
val binding_ref_in_array : Pos.t -> unit
val return_ref_in_array : Pos.t -> unit
val passing_array_cell_by_ref : Pos.t -> unit
val invalid_conditionally_reactive_call : Pos.t -> Pos.t -> string -> string -> unit
val conditionally_reactive_function : Pos.t -> unit
val multiple_conditionally_reactive_annotations : Pos.t -> string -> unit
val conditionally_reactive_annotation_invalid_arguments : is_method:bool -> Pos.t -> unit
@@ -556,4 +555,10 @@ module type S = sig
val shapes_idx_with_non_existent_field: Pos.t -> string -> Pos.t -> [< `Undefined | `Unset] -> unit
val forward_compatibility_not_current: Pos.t -> ForwardCompatibilityLevel.t -> unit
val forward_compatibility_below_minimum: Pos.t -> ForwardCompatibilityLevel.t -> unit
val invalid_argument_type_for_condition_in_rx:
is_receiver: bool -> Pos.t -> Pos.t -> Pos.t -> string -> string -> unit
val invalid_function_type_for_condition_in_rx:
Pos.t -> Pos.t -> Pos.t -> string -> string -> unit
val callsite_reactivity_mismatch: Pos.t -> Pos.t -> string -> string -> unit
val rx_parameter_condition_mismatch: string -> Pos.t -> Pos.t -> unit
end
@@ -46,6 +46,7 @@ module TySet = Typing_set
module C = Typing_continuations
module CMap = C.Map
module Try = Typing_try
module TR = Typing_reactivity
(*****************************************************************************)
(* Debugging *)
@@ -237,6 +238,12 @@ let enforce_param_not_disposable env param ty =
| None ->
()
let fun_reactivity env attrs =
let r = Decl.fun_reactivity env attrs in
if Attributes.mem Naming_special_names.UserAttributes.uaOnlyRxIfArgs attrs
then MaybeReactive r
else r
(* This function is used to determine the type of an argument.
* When we want to type-check the body of a function, we need to
* introduce the type of the arguments of the function in the environment
@@ -292,12 +299,43 @@ let make_param_local_ty attrs env param =
env, (r, ty)
| Some x ->
let ty = Decl_hint.hint env.Env.decl_env x in
let ty =
Decl.adjust_reactivity_of_mayberx_parameter
attrs
(Env.env_reactivity env)
ty in
Phase.localize ~ety_env env ty
let condition_type =
Decl.condition_type_from_attributes env.Env.decl_env param.param_user_attributes in
let fresh_type_argument_name =
Option.bind condition_type
(Typing_reactivity.generate_fresh_name_for_target_of_condition_type env ty) in
begin match condition_type, fresh_type_argument_name with
(* if parameter has associated condition type and we can generate
a name N that identifies pair (parameter type * condition type) -
instead of using declared type of parameter as is we create generic type
with name N and constrain it to declared type. Also condition type is stored in
env with N as as key. As a consequence later we can obtain condition type
using name of generic type as a key. *)
| Some condition_ty, Some fresh_type_argument_name ->
let param_ty = Reason.none, Tabstract ((AKgeneric fresh_type_argument_name), None) in
(* if generic type is already registered this means we already saw
parameter with the same pair (declared type * condition type) so there
is no need to add condition type to env again *)
if Env.is_generic_parameter env fresh_type_argument_name
then env, param_ty
else begin
let env, ty = Phase.localize ~ety_env env ty in
(* constraint type argument to hint *)
let env = Env.add_upper_bound env fresh_type_argument_name ty in
(* link type argument name to condition type *)
let env = Env.set_condition_type env fresh_type_argument_name condition_ty in
env, param_ty
end
| _ when Attributes.mem SN.UserAttributes.uaOnlyRxIfArgs attrs ->
let env, ty = Phase.localize ~ety_env env ty in
(* expand type to track aliased function types *)
let env, expanded_ty = Env.expand_type env ty in
let adjusted_ty =
make_function_type_mayberx (Env.env_reactivity env) expanded_ty in
env, if adjusted_ty == expanded_ty then ty else adjusted_ty
| _ ->
Phase.localize ~ety_env env ty
end
in
let ty = match ty with
| _, t when param.param_is_variadic ->
@@ -400,7 +438,7 @@ and fun_def tcopt f =
);
let env = Env.set_env_function_pos env pos in
let env = Typing_attributes.check_def env new_object SN.AttributeKinds.fn f.f_user_attributes in
let reactive = Decl.fun_reactivity env.Env.decl_env f.f_user_attributes in
let reactive = fun_reactivity env.Env.decl_env f.f_user_attributes in
let mut = TUtils.fun_mutable f.f_user_attributes in
let env = Env.set_env_reactive env reactive in
let env = Env.set_fun_mutable env mut in
@@ -2299,7 +2337,7 @@ and expr_
end;
(* Is the return type declared? *)
let is_explicit_ret = Option.is_some f.f_ret in
let reactivity = Decl.fun_reactivity env.Env.decl_env f.f_user_attributes in
let reactivity = fun_reactivity env.Env.decl_env f.f_user_attributes in
let check_body_under_known_params ?ret_ty ft =
let old_reactivity = Env.env_reactivity env in
let env = Env.set_env_reactive env reactivity in
@@ -2403,7 +2441,7 @@ and expr_
("Typing.expr Efun unknown params",
[Typing_log.Log_type ("declared_ft", (Reason.Rwitness p, Tfun declared_ft))])];
(* check for recursive function calls *)
let reactivity = Decl.fun_reactivity env.Env.decl_env f.f_user_attributes in
let reactivity = fun_reactivity env.Env.decl_env f.f_user_attributes in
let old_reactivity = Env.env_reactivity env in
let env = Env.set_env_reactive env reactivity in
let is_coroutine, counter, pos, anon = anon_make env p f declared_ft idl in
@@ -3969,7 +4007,10 @@ and is_abstract_ft fty = match fty with
let fty = check_abstract_parent_meth (snd m) p fty in
check_coroutine_call env fty;
let env, tel, tuel, ty =
call ~expected ~is_expr_statement ~receiver_type:ty1 p env fty el uel in
call ~expected ~is_expr_statement
~method_call_info:(TR.make_call_info ~receiver_is_self:false
~is_static:true ty1 (snd m))
p env fty el uel in
make_call env (T.make_typed_expr fpos fty
(T.Class_const (tcid, m))) hl tel tuel ty
end
@@ -3992,7 +4033,9 @@ and is_abstract_ft fty = match fty with
let fty = check_abstract_parent_meth (snd m) p fty in
check_coroutine_call env fty;
let env, _tel, _tuel, method_ = call ~expected
~receiver_type:ty1 p env fty el uel in
~method_call_info:(TR.make_call_info ~receiver_is_self:false
~is_static:false ty1 (snd m))
p env fty el uel in
env, method_, None
end
k_lhs
@@ -4004,7 +4047,11 @@ and is_abstract_ft fty = match fty with
class_get ~is_method:true ~is_const:false ~explicit_tparams:hl env ty1 m CIparent in
let fty = check_abstract_parent_meth (snd m) p fty in
check_coroutine_call env fty;
let env, tel, tuel, ty = call ~expected ~receiver_type:ty1 p env fty el uel in
let env, tel, tuel, ty =
call ~expected
~method_call_info:(TR.make_call_info ~receiver_is_self:false
~is_static:true ty1 (snd m))
p env fty el uel in
make_call env (T.make_typed_expr fpos fty
(T.Class_const (tcid, m))) hl tel tuel ty
end
@@ -4048,7 +4095,10 @@ and is_abstract_ft fty = match fty with
| _ -> () in
check_coroutine_call env fty;
let env, tel, tuel, ty =
call ~expected ~receiver_type:ty1 ~is_expr_statement p env fty el uel in
call ~expected
~method_call_info:(TR.make_call_info ~receiver_is_self:(e1 = CIself)
~is_static:true ty1 (snd m))
~is_expr_statement p env fty el uel in
make_call env (T.make_typed_expr fpos fty
(T.Class_const(te1, m))) hl tel tuel ty
@@ -4065,7 +4115,10 @@ and is_abstract_ft fty = match fty with
let k = (fun (env, fty, _) ->
check_coroutine_call env fty;
let env, tel_, tuel_, method_ =
call ~expected ~receiver_type:ty1 ~is_expr_statement p env fty el uel in
call ~expected
~method_call_info:(TR.make_call_info ~receiver_is_self:false
~is_static:false ty1 (snd m))
~is_expr_statement p env fty el uel in
tel := tel_; tuel := tuel_;
tftyl := fty :: !tftyl;
env, method_, None) in
@@ -5187,8 +5240,8 @@ and inout_write_back env { fp_type; _ } (_, e) =
env
| _ -> env
and call ~expected ?(is_expr_statement=false) ?receiver_type pos env fty el uel =
let env, tel, tuel, ty = call_ ~expected ~is_expr_statement ~receiver_type pos env fty el uel in
and call ~expected ?(is_expr_statement=false) ?method_call_info pos env fty el uel =
let env, tel, tuel, ty = call_ ~expected ~is_expr_statement ~method_call_info pos env fty el uel in
(* We need to solve the constraints after every single function call.
* The type-checker is control-flow sensitive, the same value could
* have different type depending on the branch that we are in.
@@ -5197,7 +5250,7 @@ and call ~expected ?(is_expr_statement=false) ?receiver_type pos env fty el uel
let env = Env.check_todo env in
env, tel, tuel, ty
and call_ ~expected ~receiver_type ~is_expr_statement pos env fty el uel =
and call_ ~expected ~method_call_info ~is_expr_statement pos env fty el uel =
let make_unpacked_traversable_ty pos ty =
let unpack_r = Reason.Runpack_param pos in
unpack_r, Tclass ((pos, SN.Collections.cTraversable), [ty])
@@ -5304,7 +5357,7 @@ and call_ ~expected ~receiver_type ~is_expr_statement pos env fty el uel =
let tel, tys =
let l = List.map rl (fun (_, opt) -> get_param opt) in
Core_list.unzip l in
Typing_reactivity.check_call env receiver_type pos r2 ft tys;
TR.check_call env method_call_info pos r2 ft tys;
let env, tuel, arity, did_unpack =
match uel with
| [] -> env, [], List.length el, false
@@ -6678,7 +6731,7 @@ and method_def env m =
let env = Env.set_env_function_pos env pos in
let env = Typing_attributes.check_def env new_object
SN.AttributeKinds.mthd m.m_user_attributes in
let reactive = Decl.fun_reactivity env.Env.decl_env m.m_user_attributes in
let reactive = fun_reactivity env.Env.decl_env m.m_user_attributes in
let mut =
TUtils.fun_mutable m.m_user_attributes ||
(* <<__Mutable>> is implicit on constructors *)
@@ -794,3 +794,19 @@ let rec ty_compare ty1 ty2 =
abstract_kind_con_ordinal t1 - abstract_kind_con_ordinal t2
let ty_equal ty1 ty2 = ty_compare ty1 ty2 = 0
let make_function_type_mayberx reactivity param_ty =
(* strip conditional reactivity if parent has one *)
let reactivity =
match reactivity with
| Local _ | MaybeReactive (Local _) -> Local None
| Shallow _ | MaybeReactive (Shallow _) -> Shallow None
| Reactive _ | MaybeReactive (Reactive _) -> Reactive None
| r -> r in
match param_ty with
| (r, Tfun tfun) ->
r, Tfun { tfun with ft_reactive = MaybeReactive reactivity }
| (r, Toption (r1, Tfun tfun)) ->
r, Toption (r1, Tfun { tfun with ft_reactive = MaybeReactive reactivity })
| _ ->
param_ty
@@ -337,6 +337,7 @@ let empty tcopt file ~droot = {
return_void_to_rx = false;
};
params = Local_id.Map.empty;
condition_types = SMap.empty;
self_id = "";
self = Reason.none, Tany;
static = false;
@@ -356,6 +357,14 @@ let set_env_reactive env reactive =
let set_env_function_pos env function_pos =
{ env with function_pos }
let set_condition_type env n ty =
{ env with genv = {
env.genv with condition_types = SMap.add n ty env.genv.condition_types }
}
let get_condition_type env n =
SMap.get n env.genv.condition_types
let env_reactivity env =
env.lenv.local_reactive
Oops, something went wrong.

0 comments on commit 826d91f

Please sign in to comment.