From 83a006582f5512e9afea81e3156b60f347a5a5aa Mon Sep 17 00:00:00 2001 From: Wilfred Hughes Date: Tue, 10 Aug 2021 18:11:11 -0700 Subject: [PATCH] Add .mli file for nastInitCheck Summary: Add a `.mli` file for `nastInitCheck`, as we only use one function externally. Also move the top-level function to the end of the file, as it doesn't need to be recursive. Reviewed By: hgoldstein Differential Revision: D30234229 fbshipit-source-id: c5a9d24fb3ea735a2598c6de8bbaf6446ef31a86 --- hphp/hack/src/typing/nastInitCheck.ml | 164 ++++++++++++++++----------------- hphp/hack/src/typing/nastInitCheck.mli | 9 ++ 2 files changed, 91 insertions(+), 82 deletions(-) create mode 100644 hphp/hack/src/typing/nastInitCheck.mli diff --git a/hphp/hack/src/typing/nastInitCheck.ml b/hphp/hack/src/typing/nastInitCheck.ml index 2fcd190b22f..be76d87f803 100644 --- a/hphp/hack/src/typing/nastInitCheck.ml +++ b/hphp/hack/src/typing/nastInitCheck.ml @@ -255,87 +255,6 @@ let class_prop_pos class_name prop_name ctx : Pos_or_decl.t = in Pos_or_decl.of_raw_pos @@ fst cv.Aast.cv_id)) -let rec class_ tenv c = - if not FileInfo.(equal_mode c.c_mode Mhhi) then - List.iter c.c_vars ~f:(fun cv -> - match cv.cv_expr with - | Some _ when is_lateinit cv -> - Errors.lateinit_with_default (fst cv.cv_id) - | None when cv.cv_is_static -> - let ty_opt = - Option.map - ~f:(Decl_hint.hint tenv.Typing_env_types.decl_env) - (hint_of_type_hint cv.cv_type) - in - if - is_lateinit cv - || cv.cv_abstract - || type_does_not_require_init tenv ty_opt - then - () - else - Errors.missing_assign (fst cv.cv_id) - | _ -> ()); - let (c_constructor, _, _) = split_methods c.c_methods in - match c_constructor with - | _ when Ast_defs.is_c_interface c.c_kind -> () - | Some { m_body = { fb_annotation = Nast.NamedWithUnsafeBlocks; _ }; _ } -> () - | _ -> - let p = - match c_constructor with - | Some m -> fst m.m_name - | None -> fst c.c_name - in - let env = Env.make tenv c in - let inits = constructor env c_constructor in - let check_inits inits = - let uninit_props = - SMap.filter (fun k _ -> not (SSet.mem k inits)) env.props - in - if not (SMap.is_empty uninit_props) then - if SMap.mem DeferredMembers.parent_init_prop uninit_props then - Errors.no_construct_parent p - else - let class_uninit_props = - SMap.filter - (fun prop _ -> not (SSet.mem prop env.init_not_required_props)) - uninit_props - in - if not (SMap.is_empty class_uninit_props) then - Errors.not_initialized - (p, snd c.c_name) - (SMap.bindings class_uninit_props - |> List.map ~f:(fun (name, _) -> - let pos = - class_prop_pos - (snd c.c_name) - name - (Typing_env.get_ctx tenv) - in - (pos, name))) - in - let check_throws_or_init_all inits = - match inits with - | S.Top -> - (* Constructor always throw, so checking that all properties are - * initialized is irrelevant. *) - () - | S.Set inits -> check_inits inits - in - if Ast_defs.is_c_trait c.c_kind || Ast_defs.is_c_abstract c.c_kind then - let has_constructor = - match c_constructor with - | None -> false - | Some m when m.m_abstract -> false - | Some _ -> true - in - if has_constructor then - check_throws_or_init_all inits - else - () - else - check_throws_or_init_all inits - (** * Returns the set of properties initialized by the constructor. * More exactly, returns a SSetWTop.t, i.e. either a set, or Top, which is @@ -367,7 +286,7 @@ let rec class_ tenv c = * set S of properties, S is included in `Top`, such that `S = S1 /\ S2` * still holds. *) -and constructor env cstr = +let rec constructor env cstr = match cstr with | None -> S.empty | Some cstr -> @@ -668,3 +587,84 @@ and fun_param env acc param = | Some x -> expr env acc x and fun_paraml env acc l = List.fold_left ~f:(fun_param env) ~init:acc l + +let class_ tenv c = + if not FileInfo.(equal_mode c.c_mode Mhhi) then + List.iter c.c_vars ~f:(fun cv -> + match cv.cv_expr with + | Some _ when is_lateinit cv -> + Errors.lateinit_with_default (fst cv.cv_id) + | None when cv.cv_is_static -> + let ty_opt = + Option.map + ~f:(Decl_hint.hint tenv.Typing_env_types.decl_env) + (hint_of_type_hint cv.cv_type) + in + if + is_lateinit cv + || cv.cv_abstract + || type_does_not_require_init tenv ty_opt + then + () + else + Errors.missing_assign (fst cv.cv_id) + | _ -> ()); + let (c_constructor, _, _) = split_methods c.c_methods in + match c_constructor with + | _ when Ast_defs.is_c_interface c.c_kind -> () + | Some { m_body = { fb_annotation = Nast.NamedWithUnsafeBlocks; _ }; _ } -> () + | _ -> + let p = + match c_constructor with + | Some m -> fst m.m_name + | None -> fst c.c_name + in + let env = Env.make tenv c in + let inits = constructor env c_constructor in + let check_inits inits = + let uninit_props = + SMap.filter (fun k _ -> not (SSet.mem k inits)) env.props + in + if not (SMap.is_empty uninit_props) then + if SMap.mem DeferredMembers.parent_init_prop uninit_props then + Errors.no_construct_parent p + else + let class_uninit_props = + SMap.filter + (fun prop _ -> not (SSet.mem prop env.init_not_required_props)) + uninit_props + in + if not (SMap.is_empty class_uninit_props) then + Errors.not_initialized + (p, snd c.c_name) + (SMap.bindings class_uninit_props + |> List.map ~f:(fun (name, _) -> + let pos = + class_prop_pos + (snd c.c_name) + name + (Typing_env.get_ctx tenv) + in + (pos, name))) + in + let check_throws_or_init_all inits = + match inits with + | S.Top -> + (* Constructor always throw, so checking that all properties are + * initialized is irrelevant. *) + () + | S.Set inits -> check_inits inits + in + if Ast_defs.is_c_trait c.c_kind || Ast_defs.is_c_abstract c.c_kind then + let has_constructor = + match c_constructor with + | None -> false + | Some m when m.m_abstract -> false + | Some _ -> true + in + if has_constructor then + check_throws_or_init_all inits + else + () + else + check_throws_or_init_all inits diff --git a/hphp/hack/src/typing/nastInitCheck.mli b/hphp/hack/src/typing/nastInitCheck.mli new file mode 100644 index 00000000000..36754bc7788 --- /dev/null +++ b/hphp/hack/src/typing/nastInitCheck.mli @@ -0,0 +1,9 @@ +(* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the "hack" directory of this source tree. + * + *) + +val class_ : Typing_env_types.env -> Nast.class_ -> unit -- 2.11.4.GIT