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.
10 (* Typing code concerned with disposable types. *)
15 module Env
= Typing_env
17 let is_disposable_visitor env
=
19 inherit [string option] Type_visitor.type_visitor
20 (* Only bother looking at classish types. Other types can spuriously
21 * claim to implement these interfaces. Ideally we should check
22 * constrained generics, abstract types, etc.
24 method! on_tclass acc _
(_
, class_name
) tyl
=
26 List.fold_left tyl ~f
:this#on_type ~init
:acc
in
27 begin match Env.get_class env class_name
with
31 then Some
(Utils.strip_ns class_name
)
36 (* Does ty (or a type embedded in ty) implement IDisposable
37 * or IAsyncDisposable, directly or indirectly?
38 * Return Some class_name if it does, None if it doesn't.
40 let is_disposable_type env ty
=
41 match Env.expand_type env ty
with
43 (is_disposable_visitor env
)#on_type None ety
45 let enforce_is_disposable env hint
=
47 | (_
, Nast.Happly
((p
, c
), _
)) ->
48 begin match Decl_env.get_class_dep env
.Env.decl_env c
with
51 if not c
.Decl_defs.dc_is_disposable
52 then Errors.must_extend_disposable p
56 (* Ensure that `ty` is a subtype of IDisposable (for `using`) or
57 * IAsyncDisposable (for `await using`)
59 let enforce_is_disposable_type env has_await pos ty
=
62 then SN.Classes.cIAsyncDisposable
63 else SN.Classes.cIDisposable
in
64 let disposable_ty = (Reason.Rusing pos
, Tclass
((pos
, class_name), [])) in
65 Typing_ops.sub_type pos
Reason.URusing env ty
disposable_ty