Avoid using decl_class_type wherever possible
[hiphop-php.git] / hphp / hack / src / typing / tast_check / rvalue_check.ml
blob1e81622eac869c312ca6702bd685048ad5ca4028
1 (**
2 * Copyright (c) 2018, Facebook, Inc.
3 * All rights reserved.
5 * This source code is licensed under the MIT license found in the
6 * LICENSE file in the "hack" directory of this source tree.
8 *)
10 open Core_kernel
11 open Tast
12 open Typing_defs
14 module Env = Tast_env
15 module Reason = Typing_reason
17 let check_valid_rvalue p env ty =
18 let rec iter_over_types env tyl =
19 match tyl with
20 | [] ->
21 env
23 | ty::tyl ->
24 let env, ety = Env.expand_type env ty in
25 match ety with
26 | r, Tprim Tnoreturn ->
27 Errors.noreturn_usage p
28 (Reason.to_string "A noreturn function always throws or exits" r);
29 env
31 | r, Tprim Tvoid ->
32 Errors.void_usage p
33 (Reason.to_string "A void function doesn't return a value" r);
34 env
36 | _, Tunresolved tyl2 ->
37 iter_over_types env (tyl2 @ tyl)
39 | _, _ ->
40 iter_over_types env tyl in
41 ignore (iter_over_types env [ty])
43 let visitor = object(this)
44 inherit [_] Tast.iter as super
46 val non_returning_allowed = ref true
48 method allow_non_returning f =
49 let is_non_returning_allowed = !non_returning_allowed in
50 non_returning_allowed := true;
51 f ();
52 non_returning_allowed := is_non_returning_allowed
54 method disallow_non_returning f =
55 let is_non_returning_allowed = !non_returning_allowed in
56 non_returning_allowed := false;
57 f ();
58 non_returning_allowed := is_non_returning_allowed
60 method! on_expr env ((p, ty), e as te) = match e with
61 | Binop (Ast.Eq None, e1, e2) ->
62 this#allow_non_returning (fun () -> this#on_expr env e1);
63 this#disallow_non_returning (fun () -> this#on_expr env e2)
64 | Eif (e1, e2, e3) ->
65 this#disallow_non_returning (fun () -> this#on_expr env e1);
66 Option.iter e2 (this#on_expr env);
67 this#on_expr env e3
68 | Pipe (_, e1, e2) ->
69 this#disallow_non_returning (fun () -> this#on_expr env e1);
70 this#on_expr env e2
71 | List el ->
72 List.iter el (this#on_expr env)
73 | Expr_list el ->
74 List.iter el (this#on_expr env)
75 | Suspend e ->
76 this#allow_non_returning (fun () -> this#on_expr env e)
77 | _ ->
78 if not !non_returning_allowed then
79 check_valid_rvalue p env ty;
80 this#disallow_non_returning (fun () -> super#on_expr env te)
82 method! on_stmt env stmt = match snd stmt with
83 | Expr e ->
84 this#allow_non_returning (fun () -> this#on_expr env e)
85 | Return (Some e) ->
86 this#allow_non_returning (fun () -> this#on_expr env e)
87 | For (e1, e2, e3, b) ->
88 this#allow_non_returning (fun () -> this#on_expr env e1);
89 this#disallow_non_returning (fun () -> this#on_expr env e2);
90 this#allow_non_returning (fun () -> this#on_expr env e3);
91 this#on_block env b
92 | Foreach (e1, e2, b) ->
93 this#disallow_non_returning (fun () -> this#on_expr env e1);
94 this#allow_non_returning (fun () -> this#on_as_expr env e2);
95 this#on_block env b
96 | Awaitall _ ->
97 this#allow_non_returning (fun () -> super#on_stmt env stmt)
98 | _ ->
99 this#disallow_non_returning (fun () -> super#on_stmt env stmt)
101 method! on_block env block =
102 this#allow_non_returning (fun () -> super#on_block env block)
105 let handler = object
106 inherit Tast_visitor.handler_base
108 method! at_stmt = visitor#on_stmt