1 // Copyright (c) Facebook, Inc. and its affiliates.
3 // This source code is licensed under the MIT license found in the
4 // LICENSE file in the "hack" directory of this source tree.
6 use arena_trait::Arena;
7 use bumpalo::collections::Vec;
8 use bumpalo::{vec, Bump};
10 use naming_special_names_rust::{classes, collections};
11 use oxidized::pos::Pos;
12 use oxidized::{aast_defs::Sid, ast_defs::Id, ident};
14 use crate::typing_defs_core::{Ty, *};
15 use crate::typing_logic::{SubtypeProp, SubtypePropEnum};
16 use crate::typing_reason::*;
18 // Struct off which we call type builder methods
19 // This gives us the option to keep some state here e.g. for hash consing
20 pub struct TypeBuilder<'a> {
21 // Well-known identifiers
22 // We could initialize the positions to their actual definition site in hhi
23 // This makes more sense than inheriting the position from the use
24 // But for now, let's just put none as the position
25 // TODO: we might consider creating a SymbolBuilder type
27 id_keyed_traversable: Id,
28 id_keyed_container: Id,
31 id_async_generator: Id,
32 id_async_iterator: Id,
33 id_async_keyed_iterator: Id,
41 id_datetime_immutable: Id,
43 id_const_collection: Id,
49 impl<'a> Arena for TypeBuilder<'a> {
51 fn alloc<T>(&self, val: T) -> &mut T {
52 return self.alloc.alloc(val);
56 // Copying of string is bad
57 // Perhaps best is to actually *resolve* well-known classes
58 // as though they appear in the source, so we get the position
59 // from the definition e.g. in hhi file.
60 fn mk_special_id(name: &str) -> Id {
61 Id(Pos::make_none(), name.to_string())
64 impl<'a> TypeBuilder<'a> {
65 pub fn new(alloc: &'a Bump) -> Self {
69 id_traversable: mk_special_id(collections::TRAVERSABLE),
70 id_keyed_traversable: mk_special_id(collections::KEYED_TRAVERSABLE),
71 id_keyed_container: mk_special_id(collections::KEYED_CONTAINER),
72 id_awaitable: mk_special_id(classes::AWAITABLE),
73 id_generator: mk_special_id(classes::GENERATOR),
74 id_async_generator: mk_special_id(classes::ASYNC_GENERATOR),
75 id_async_iterator: mk_special_id(classes::ASYNC_ITERATOR),
76 id_async_keyed_iterator: mk_special_id(classes::ASYNC_KEYED_ITERATOR),
77 id_pair: mk_special_id(collections::PAIR),
78 id_dict: mk_special_id(collections::DICT),
79 id_keyset: mk_special_id(collections::KEYSET),
80 id_vec: mk_special_id(collections::VEC),
81 id_container: mk_special_id(collections::CONTAINER),
82 id_throwable: mk_special_id(classes::THROWABLE),
83 id_datetime: mk_special_id(classes::DATE_TIME),
84 id_datetime_immutable: mk_special_id(classes::DATE_TIME_IMMUTABLE),
85 id_const_vector: mk_special_id(collections::CONST_VECTOR),
86 id_const_collection: mk_special_id(collections::CONST_COLLECTION),
87 id_collection: mk_special_id(collections::COLLECTION),
92 /// All type builders go here
93 impl<'a> TypeBuilder<'a> {
94 // All type construction should go through here
95 fn mk(&'a self, reason: PReason<'a>, ty_: Ty_<'a>) -> Ty<'a> {
96 Ty::mk(reason, self.alloc(ty_))
99 pub fn prim(&'a self, reason: PReason<'a>, kind: PrimKind<'a>) -> Ty<'a> {
100 self.mk(reason, Ty_::Tprim(kind))
102 pub fn class(&'a self, reason: PReason<'a>, name: &'a Sid, tys: Vec<'a, Ty<'a>>) -> Ty<'a> {
103 self.mk(reason, Ty_::Tclass(name, Exact::Nonexact, tys))
105 pub fn traversable(&'a self, reason: PReason<'a>, ty: Ty<'a>) -> Ty<'a> {
106 self.class(reason, &self.id_traversable, vec![in &self.alloc; ty])
108 pub fn keyed_traversable(&'a self, reason: PReason<'a>, kty: Ty<'a>, vty: Ty<'a>) -> Ty<'a> {
111 &self.id_keyed_traversable,
112 vec![in &self.alloc; kty, vty],
115 pub fn keyed_container(&'a self, reason: PReason<'a>, kty: Ty<'a>, vty: Ty<'a>) -> Ty<'a> {
118 &self.id_keyed_container,
119 vec![in &self.alloc; kty, vty],
122 pub fn awaitable(&'a self, reason: PReason<'a>, ty: Ty<'a>) -> Ty<'a> {
123 self.class(reason, &self.id_awaitable, vec![in &self.alloc; ty])
135 vec![in &self.alloc; key, value, send],
138 pub fn async_generator(
147 &self.id_async_generator,
148 vec![in &self.alloc; key, value, send],
151 pub fn async_iterator(&'a self, reason: PReason<'a>, ty: Ty<'a>) -> Ty<'a> {
152 self.class(reason, &self.id_async_iterator, vec![in &self.alloc; ty])
154 pub fn async_keyed_iterator(&'a self, reason: PReason<'a>, kty: Ty<'a>, vty: Ty<'a>) -> Ty<'a> {
157 &self.id_async_keyed_iterator,
158 vec![in &self.alloc; kty, vty],
161 pub fn pair(&'a self, reason: PReason<'a>, ty1: Ty<'a>, ty2: Ty<'a>) -> Ty<'a> {
162 self.class(reason, &self.id_pair, vec![in &self.alloc; ty1, ty2])
164 pub fn dict(&'a self, reason: PReason<'a>, kty: Ty<'a>, vty: Ty<'a>) -> Ty<'a> {
165 self.class(reason, &self.id_dict, vec![in &self.alloc; kty, vty])
167 pub fn keyset(&'a self, reason: PReason<'a>, ty: Ty<'a>) -> Ty<'a> {
168 self.class(reason, &self.id_keyset, vec![in &self.alloc; ty])
170 pub fn vec(&'a self, reason: PReason<'a>, ty: Ty<'a>) -> Ty<'a> {
171 self.class(reason, &self.id_vec, vec![in &self.alloc; ty])
173 pub fn container(&'a self, reason: PReason<'a>, ty: Ty<'a>) -> Ty<'a> {
174 self.class(reason, &self.id_container, vec![in &self.alloc; ty])
176 pub fn const_vector(&'a self, reason: PReason<'a>, ty: Ty<'a>) -> Ty<'a> {
177 self.class(reason, &self.id_const_vector, vec![in &self.alloc; ty])
179 pub fn const_collection(&'a self, reason: PReason<'a>, ty: Ty<'a>) -> Ty<'a> {
180 self.class(reason, &self.id_const_collection, vec![in &self.alloc; ty])
182 pub fn collection(&'a self, reason: PReason<'a>, ty: Ty<'a>) -> Ty<'a> {
183 self.class(reason, &self.id_collection, vec![in &self.alloc; ty])
185 pub fn throwable(&'a self, reason: PReason<'a>) -> Ty<'a> {
186 self.class(reason, &self.id_throwable, vec![in &self.alloc; ])
188 pub fn datetime(&'a self, reason: PReason<'a>) -> Ty<'a> {
189 self.class(reason, &self.id_datetime, vec![in &self.alloc])
191 pub fn datetime_immutable(&'a self, reason: PReason<'a>) -> Ty<'a> {
192 self.class(reason, &self.id_datetime_immutable, vec![in &self.alloc])
194 pub fn int(&'a self, reason: PReason<'a>) -> Ty<'a> {
195 self.prim(reason, PrimKind::Tint)
197 pub fn bool(&'a self, reason: PReason<'a>) -> Ty<'a> {
198 self.prim(reason, PrimKind::Tbool)
200 pub fn string(&'a self, reason: PReason<'a>) -> Ty<'a> {
201 self.prim(reason, PrimKind::Tstring)
203 pub fn float(&'a self, reason: PReason<'a>) -> Ty<'a> {
204 self.prim(reason, PrimKind::Tfloat)
206 pub fn arraykey(&'a self, reason: PReason<'a>) -> Ty<'a> {
207 self.prim(reason, PrimKind::Tarraykey)
209 pub fn void(&'a self, reason: PReason<'a>) -> Ty<'a> {
210 self.prim(reason, PrimKind::Tvoid)
212 pub fn null(&'a self, reason: PReason<'a>) -> Ty<'a> {
213 self.prim(reason, PrimKind::Tnull)
215 pub fn nonnull(&'a self, reason: PReason<'a>) -> Ty<'a> {
216 self.mk(reason, Ty_::Tnonnull)
218 pub fn dynamic(&'a self, reason: PReason<'a>) -> Ty<'a> {
219 self.mk(reason, Ty_::Tdynamic)
222 pub fn object(&'a self, reason: PReason<'a>) -> Ty<'a> {
223 self.mk(reason, Ty_::Tobject)
226 pub fn tyvar(&'a self, reason: PReason<'a>, v: ident::Ident) -> Ty<'a> {
227 self.mk(reason, Ty_::Tvar(v))
229 pub fn union(&'a self, reason: PReason<'a>, tys: Vec<'a, Ty<'a>>) -> Ty<'a> {
230 self.mk(reason, Ty_::Tunion(tys))
232 pub fn intersection(&'a self, reason: PReason<'a>, tys: Vec<'a, Ty<'a>>) -> Ty<'a> {
233 self.mk(reason, Ty_::Tintersection(tys))
235 pub fn nothing(&'a self, reason: PReason<'a>) -> Ty<'a> {
236 self.union(reason, Vec::new_in(self.alloc))
238 pub fn nullable(&'a self, reason: PReason<'a>, ty: Ty<'a>) -> Ty<'a> {
239 self.mk(reason, Ty_::Toption(ty))
241 pub fn mixed(&'a self, reason: PReason<'a>) -> Ty<'a> {
242 self.nullable(reason, self.nonnull(reason))
244 pub fn generic(&'a self, reason: PReason<'a>, name: &'a str) -> Ty<'a> {
245 self.mk(reason, Ty_::Tgeneric(name))
247 pub fn conj(&'a self, v: Vec<'a, SubtypeProp<'a>>) -> SubtypeProp<'a> {
248 self.alloc(SubtypePropEnum::Conj(v))
250 pub fn disj(&'a self, v: Vec<'a, SubtypeProp<'a>>) -> SubtypeProp<'a> {
251 self.alloc(SubtypePropEnum::Disj(v))
253 pub fn is_subtype(&'a self, ty1: InternalType<'a>, ty2: InternalType<'a>) -> SubtypeProp<'a> {
254 self.alloc(SubtypePropEnum::IsSubtype(ty1, ty2))
256 pub fn valid(&'a self) -> SubtypeProp<'a> {
258 .alloc(SubtypePropEnum::Conj(Vec::new_in(self.alloc)))
260 pub fn invalid(&'a self) -> SubtypeProp<'a> {
262 .alloc(SubtypePropEnum::Disj(Vec::new_in(self.alloc)))
264 pub fn loclty(&'a self, ty: Ty<'a>) -> InternalType<'a> {
265 self.alloc(InternalType_::LoclType(ty))
267 pub fn constraintty(&'a self, ty: ConstraintType<'a>) -> InternalType<'a> {
268 self.alloc(InternalType_::ConstraintType(ty))
272 /// All reason builders go here
273 impl<'a> TypeBuilder<'a> {
274 fn mk_reason(&'a self, pos: Option<&'a Pos>, reason: Reason<'a>) -> PReason<'a> {
275 self.alloc(PReason_ { pos, reason })
278 /// Make an Rnone reason. This does not belong here, but:
279 pub fn mk_rnone(&'a self) -> PReason<'a> {
280 self.mk_reason(None, Reason::Rnone)