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.
12 module Env
= Typing_env
13 module Reason
= Typing_reason
14 module Cls
= Folded_class
15 module SN
= Naming_special_names
19 inherit Type_validator.type_validator
as super
21 (* Only comes about because naming has reported an error and left Hany *)
22 method! on_tany acc _
= acc
24 method! on_tprim acc r prim
=
26 | Aast.Tvoid
-> this#invalid acc r
"the `void` type"
27 | Aast.Tnoreturn
-> this#invalid acc r
"the `noreturn` type"
30 method! on_tfun acc r _fun_type
= this#invalid acc r
"a function type"
32 method! on_tvar acc r _id
= this#invalid acc r
"an unknown type"
34 method! on_typeconst acc class_ typeconst
=
35 match typeconst
.ttc_kind
with
36 | TCConcrete _
-> super#on_typeconst acc class_ typeconst
38 when (* get_typeconst_enforceability should always return Some here, since we
39 know the typeconst exists (else we wouldn't be in this method).
40 But since we have to map it to a bool anyway, we just use
45 (Cls.get_typeconst_enforceability
47 (snd typeconst
.ttc_name
)) ->
48 super#on_typeconst acc class_ typeconst
50 let (pos
, tconst
) = typeconst
.ttc_name
in
51 let r = Reason.witness_from_decl pos
in
53 @@ "the abstract type constant "
55 ^
" because it is not marked `<<__Enforceable>>`"
57 method! on_tgeneric acc
r name _tyargs
=
58 (* If we allow higher-kinded generics to be enforceable at some point,
59 handle type arguments here *)
60 this#check_generic acc
r name
62 method! on_newtype acc
r sid _ as_cstr _super_cstr _
=
63 if String.equal
(snd sid
) SN.Classes.cSupportDyn
then
64 this#on_type acc
(with_reason as_cstr
r)
66 this#invalid acc
r "a `newtype`"
68 method! on_tlike acc _r ty
= this#on_type acc ty
70 method! on_class acc
r cls tyl
=
71 match Env.get_class acc
.Type_validator.env
(snd cls
) with
72 | Decl_entry.Found tc
->
73 (match Cls.kind tc
with
74 | Ast_defs.Ctrait
-> this#invalid acc
r "a trait name"
76 let tparams = Cls.tparams tc
in
80 (* this case should really be handled by the fold2,
81 but we still allow class hints without args in certain places *)
83 List.Or_unequal_lengths.(
90 ~f
:(fun acc targ tparam
->
91 let inside_reified_class_generic_position =
94 .inside_reified_class_generic_position
96 if this#is_wildcard targ
then begin
97 if inside_reified_class_generic_position then
101 "a reified type containing a wildcard (`_`)"
105 Aast.(equal_reify_kind tparam
.tp_reified Reified
)
111 .inside_reified_class_generic_position = true;
114 else if inside_reified_class_generic_position then
115 this#on_type acc targ
118 "a type with an erased generic type argument"
120 this#invalid acc
r error_message)
122 | Ok new_acc
-> new_acc
123 | Unequal_lengths
-> acc
(* arity error elsewhere *)
126 | Decl_entry.DoesNotExist
127 | Decl_entry.NotYetAvailable
->
130 method! on_alias acc
r _id tyl ty
=
131 match List.filter ~f
:(fun ty
-> not
@@ this#is_wildcard ty
) tyl
with
132 | [] -> this#on_type acc ty
137 "a type with generics, because generics are erased at runtime"
139 method! on_tunion acc
r tyl
=
141 | [] -> this#invalid acc
r "the `nothing` type"
142 | _
-> super#on_tunion acc
r tyl
144 method! on_tintersection acc
r _
=
148 "an intersection type, which is restricted to coeffects"
150 method is_wildcard ty
=
151 match get_node ty
with
155 method check_for_wildcards acc tyl s
=
156 match List.filter tyl ~f
:this#is_wildcard
with
161 (List.map tyl ~f
:(fun ty
->
162 ( Typing_defs_core.get_reason ty
,
163 "_ in a " ^ s ^
" (use `mixed` instead)" )))
165 method! on_ttuple acc _ tyl
=
166 let acc = List.fold_left tyl ~f
:this#on_type ~init
:acc in
167 this#check_for_wildcards
acc tyl
"tuple"
169 method! on_tshape
acc _
{ s_fields
= fdm
; _
} =
170 let tyl = TShapeMap.values fdm
|> List.map ~f
:(fun s
-> s
.sft_ty
) in
171 let acc = List.fold_left
tyl ~init
:acc ~f
:this#on_type
in
172 this#check_for_wildcards
acc tyl "shape"
174 method check_generic
acc r name
=
175 (* No need to look at type arguments of generic var, as higher-kinded type params
176 cannot be enforcable *)
177 (* TODO(T70069116) implement enforcability check *)
179 ( Env.get_reified
acc.Type_validator.env name
,
180 Env.get_enforceable
acc.Type_validator.env name
)
182 | (Aast.Erased
, _
) ->
183 this#invalid
acc r "an erased generic type parameter"
184 | (Aast.SoftReified
, _
) ->
185 this#invalid
acc r "a soft reified generic type parameter"
186 | (Aast.Reified
, false) ->
187 (* If a reified generic is an argument to a reified class it does not
188 * need to be enforceable *)
189 if acc.Type_validator.inside_reified_class_generic_position then
195 "a reified type parameter that is not marked `<<__Enforceable>>`"
196 | (Aast.Reified
, true) -> acc
199 let validate_hint = validator#
validate_hint ?reification
:None
201 let validate_type = validator#
validate_type ?reification
:None