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
16 module TySet
= Typing_set
17 module Cls
= Decl_provider.Class
22 inherit type_validator
as super
24 (* Only comes about because naming has reported an error and left Hany *)
25 method! on_tany acc _
= acc
27 (* Already reported an error *)
28 method! on_terr acc _
= acc
30 method! on_tprim acc r prim
=
32 | Aast.Tvoid
-> this#invalid acc r
"the `void` type"
33 | Aast.Tnoreturn
-> this#invalid acc r
"the `noreturn` type"
36 method! on_tfun acc r _fun_type
= this#invalid acc r
"a function type"
38 method! on_tvar acc r _id
= this#invalid acc r
"an unknown type"
40 method! on_typeconst acc is_concrete typeconst
=
41 match typeconst
.ttc_abstract
with
42 | _
when snd typeconst
.ttc_enforceable
|| is_concrete
->
43 super#on_typeconst acc is_concrete typeconst
45 let (pos
, tconst
) = typeconst
.ttc_name
in
46 let r = Reason.Rwitness pos
in
48 @@ "the abstract type constant "
50 ^
" because it is not marked `<<__Enforceable>>`"
52 method! on_tgeneric acc
r name _tyargs
=
53 (* If we allow higher-kinded generics to be enforceable at some point,
54 handle type arguments here *)
55 if acc
.like_context
then
58 this#check_generic acc
r name
60 method! on_newtype acc
r _ _ _ _
=
61 if acc
.like_context
then
64 this#invalid acc
r "a `newtype`"
66 method! on_tlike acc
r ty
=
67 if TypecheckerOptions.like_casts
(Tast_env.get_tcopt acc
.env
) then
68 super#on_tlike
{ acc
with like_context
= true } r ty
70 this#invalid acc
r "a like type"
72 method! on_class acc
r cls tyl
=
73 match Env.get_class acc
.env
(snd cls
) with
75 let tparams = Cls.tparams tc
in
79 (* this case should really be handled by the fold2,
80 but we still allow class hints without args in certain places *)
82 List.Or_unequal_lengths.(
85 List.fold2 ~init
:acc targs
tparams ~f
:(fun acc targ tparam
->
87 Ast_defs.(equal_variance tparam
.tp_variance Covariant
)
89 if this#is_wildcard targ
then
92 Aast.(equal_reify_kind tparam
.tp_reified Reified
)
93 || (acc
.like_context
&& covariant)
98 "a type with an erased generic type argument"
102 TypecheckerOptions.like_casts
103 (Tast_env.get_tcopt acc
.env
)
106 ^
", except in a like cast when the corresponding type parameter is covariant"
110 this#invalid acc
r error_message)
112 | Ok new_acc
-> new_acc
113 | Unequal_lengths
-> acc
(* arity error elsewhere *)
118 method! on_alias acc
r id tyl ty
=
119 if List.is_empty tyl
then
122 String.equal
(snd id
) Naming_special_names.FB.cIncorrectType
123 && Int.equal
(List.length tyl
) 1
125 let ty = List.hd_exn tyl
in
126 this#on_type
{ acc
with like_context
= true } ty
127 else if acc
.like_context
then
128 super#on_alias acc
r id tyl
ty
133 "a type with generics, because generics are erased at runtime"
135 method! on_tvarray acc
r tk
=
136 if acc
.like_context
then
139 this#invalid acc
r "an array type"
141 method! on_tdarray acc
r tk tv
=
142 if acc
.like_context
then
143 let acc = this#on_type
acc tk
in
146 this#invalid
acc r "an array type"
148 method! on_tvarray_or_darray
acc r tk tv
=
149 if acc.like_context
then
150 let acc = this#on_type
acc tk
in
153 this#invalid
acc r "an array type"
155 method is_wildcard
ty =
156 match get_node
ty with
157 | Tapply
((_
, name
), _
) -> String.equal name
SN.Typehints.wildcard
160 method check_for_wildcards
acc tyl s
=
161 match List.filter tyl ~f
:this#is_wildcard
with
166 (List.map tyl ~f
:(fun ty ->
167 ( Typing_defs_core.get_reason
ty,
168 "_ in a " ^ s ^
" (use `mixed` instead)" )))
170 method! on_ttuple
acc _ tyl
=
171 let acc = List.fold_left tyl ~f
:this#on_type ~init
:acc in
172 this#check_for_wildcards
acc tyl
"tuple"
174 method! on_tshape
acc _ _ fdm
=
175 let tyl = ShapeMap.values fdm
|> List.map ~f
:(fun s
-> s
.sft_ty
) in
176 let acc = List.fold_left
tyl ~init
:acc ~f
:this#on_type
in
177 this#check_for_wildcards
acc tyl "shape"
179 method check_generic
acc r name
=
180 (* No need to look at type arguments of generic var, as higher-kinded type params
181 cannot be enforcable *)
182 (* TODO(T70069116) implement enforcability check *)
184 (Env.get_reified
acc.env name
, Env.get_enforceable
acc.env name
)
186 | (Nast.Erased
, _
) ->
187 this#invalid
acc r "an erased generic type parameter"
188 | (Nast.SoftReified
, _
) ->
189 this#invalid
acc r "a soft reified generic type parameter"
190 | (Nast.Reified
, false) ->
194 "a reified type parameter that is not marked `<<__Enforceable>>`"
195 | (Nast.Reified
, true) -> acc