2 * Copyright (c) 2018, 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.
15 module Reason
= Typing_reason
17 let check_valid_rvalue p env ty
=
18 let rec iter_over_types env tyl
=
24 let env, ety
= Env.expand_type
env ty
in
26 | r
, Tprim Tnoreturn
->
27 Errors.noreturn_usage p
28 (Reason.to_string
"A noreturn function always throws or exits" r
);
33 (Reason.to_string
"A void function doesn't return a value" r
);
36 | _
, Tunresolved tyl2
->
37 iter_over_types env (tyl2
@ tyl
)
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;
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;
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
)
65 this#disallow_non_returning
(fun () -> this#on_expr
env e1
);
66 Option.iter e2
(this#on_expr
env);
69 this#disallow_non_returning
(fun () -> this#on_expr
env e1
);
72 List.iter el
(this#on_expr
env)
74 List.iter el
(this#on_expr
env)
76 this#allow_non_returning
(fun () -> this#on_expr
env e
)
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
84 this#allow_non_returning
(fun () -> this#on_expr
env 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
);
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
);
97 this#allow_non_returning
(fun () -> super#on_stmt
env stmt
)
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
)
106 inherit Tast_visitor.handler_base
108 method! at_stmt
= visitor#on_stmt