Make Ty abstract
[hiphop-php.git] / hphp / hack / src / typing / typing_make_type.rs
blob91716ef198cf4a564db3f58ff5e2c58e260e63af
1 // Copyright (c) Facebook, Inc. and its affiliates.
2 //
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
26     id_traversable: Id,
27     id_keyed_traversable: Id,
28     id_keyed_container: Id,
29     id_awaitable: Id,
30     id_generator: Id,
31     id_async_generator: Id,
32     id_async_iterator: Id,
33     id_async_keyed_iterator: Id,
34     id_pair: Id,
35     id_dict: Id,
36     id_keyset: Id,
37     id_vec: Id,
38     id_container: Id,
39     id_throwable: Id,
40     id_datetime: Id,
41     id_datetime_immutable: Id,
42     id_const_vector: Id,
43     id_const_collection: Id,
44     id_collection: Id,
46     pub alloc: &'a Bump,
49 impl<'a> Arena for TypeBuilder<'a> {
50     #[inline(always)]
51     fn alloc<T>(&self, val: T) -> &mut T {
52         return self.alloc.alloc(val);
53     }
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 {
66         TypeBuilder {
67             alloc,
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),
88         }
89     }
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_))
97     }
99     pub fn prim(&'a self, reason: PReason<'a>, kind: PrimKind<'a>) -> Ty<'a> {
100         self.mk(reason, Ty_::Tprim(kind))
101     }
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))
104     }
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])
107     }
108     pub fn keyed_traversable(&'a self, reason: PReason<'a>, kty: Ty<'a>, vty: Ty<'a>) -> Ty<'a> {
109         self.class(
110             reason,
111             &self.id_keyed_traversable,
112             vec![in &self.alloc; kty, vty],
113         )
114     }
115     pub fn keyed_container(&'a self, reason: PReason<'a>, kty: Ty<'a>, vty: Ty<'a>) -> Ty<'a> {
116         self.class(
117             reason,
118             &self.id_keyed_container,
119             vec![in &self.alloc; kty, vty],
120         )
121     }
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])
124     }
125     pub fn generator(
126         &'a self,
127         reason: PReason<'a>,
128         key: Ty<'a>,
129         value: Ty<'a>,
130         send: Ty<'a>,
131     ) -> Ty<'a> {
132         self.class(
133             reason,
134             &self.id_generator,
135             vec![in &self.alloc; key, value, send],
136         )
137     }
138     pub fn async_generator(
139         &'a self,
140         reason: PReason<'a>,
141         key: Ty<'a>,
142         value: Ty<'a>,
143         send: Ty<'a>,
144     ) -> Ty<'a> {
145         self.class(
146             reason,
147             &self.id_async_generator,
148             vec![in &self.alloc; key, value, send],
149         )
150     }
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])
153     }
154     pub fn async_keyed_iterator(&'a self, reason: PReason<'a>, kty: Ty<'a>, vty: Ty<'a>) -> Ty<'a> {
155         self.class(
156             reason,
157             &self.id_async_keyed_iterator,
158             vec![in &self.alloc; kty, vty],
159         )
160     }
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])
163     }
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])
166     }
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])
169     }
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])
172     }
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])
175     }
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])
178     }
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])
181     }
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])
184     }
185     pub fn throwable(&'a self, reason: PReason<'a>) -> Ty<'a> {
186         self.class(reason, &self.id_throwable, vec![in &self.alloc; ])
187     }
188     pub fn datetime(&'a self, reason: PReason<'a>) -> Ty<'a> {
189         self.class(reason, &self.id_datetime, vec![in &self.alloc])
190     }
191     pub fn datetime_immutable(&'a self, reason: PReason<'a>) -> Ty<'a> {
192         self.class(reason, &self.id_datetime_immutable, vec![in &self.alloc])
193     }
194     pub fn int(&'a self, reason: PReason<'a>) -> Ty<'a> {
195         self.prim(reason, PrimKind::Tint)
196     }
197     pub fn bool(&'a self, reason: PReason<'a>) -> Ty<'a> {
198         self.prim(reason, PrimKind::Tbool)
199     }
200     pub fn string(&'a self, reason: PReason<'a>) -> Ty<'a> {
201         self.prim(reason, PrimKind::Tstring)
202     }
203     pub fn float(&'a self, reason: PReason<'a>) -> Ty<'a> {
204         self.prim(reason, PrimKind::Tfloat)
205     }
206     pub fn arraykey(&'a self, reason: PReason<'a>) -> Ty<'a> {
207         self.prim(reason, PrimKind::Tarraykey)
208     }
209     pub fn void(&'a self, reason: PReason<'a>) -> Ty<'a> {
210         self.prim(reason, PrimKind::Tvoid)
211     }
212     pub fn null(&'a self, reason: PReason<'a>) -> Ty<'a> {
213         self.prim(reason, PrimKind::Tnull)
214     }
215     pub fn nonnull(&'a self, reason: PReason<'a>) -> Ty<'a> {
216         self.mk(reason, Ty_::Tnonnull)
217     }
218     pub fn dynamic(&'a self, reason: PReason<'a>) -> Ty<'a> {
219         self.mk(reason, Ty_::Tdynamic)
220     }
221     /*
222     pub fn object(&'a self, reason: PReason<'a>) -> Ty<'a> {
223         self.mk(reason, Ty_::Tobject)
224     }
225     */
226     pub fn tyvar(&'a self, reason: PReason<'a>, v: ident::Ident) -> Ty<'a> {
227         self.mk(reason, Ty_::Tvar(v))
228     }
229     pub fn union(&'a self, reason: PReason<'a>, tys: Vec<'a, Ty<'a>>) -> Ty<'a> {
230         self.mk(reason, Ty_::Tunion(tys))
231     }
232     pub fn intersection(&'a self, reason: PReason<'a>, tys: Vec<'a, Ty<'a>>) -> Ty<'a> {
233         self.mk(reason, Ty_::Tintersection(tys))
234     }
235     pub fn nothing(&'a self, reason: PReason<'a>) -> Ty<'a> {
236         self.union(reason, Vec::new_in(self.alloc))
237     }
238     pub fn nullable(&'a self, reason: PReason<'a>, ty: Ty<'a>) -> Ty<'a> {
239         self.mk(reason, Ty_::Toption(ty))
240     }
241     pub fn mixed(&'a self, reason: PReason<'a>) -> Ty<'a> {
242         self.nullable(reason, self.nonnull(reason))
243     }
244     pub fn generic(&'a self, reason: PReason<'a>, name: &'a str) -> Ty<'a> {
245         self.mk(reason, Ty_::Tgeneric(name))
246     }
247     pub fn conj(&'a self, v: Vec<'a, SubtypeProp<'a>>) -> SubtypeProp<'a> {
248         self.alloc(SubtypePropEnum::Conj(v))
249     }
250     pub fn disj(&'a self, v: Vec<'a, SubtypeProp<'a>>) -> SubtypeProp<'a> {
251         self.alloc(SubtypePropEnum::Disj(v))
252     }
253     pub fn is_subtype(&'a self, ty1: InternalType<'a>, ty2: InternalType<'a>) -> SubtypeProp<'a> {
254         self.alloc(SubtypePropEnum::IsSubtype(ty1, ty2))
255     }
256     pub fn valid(&'a self) -> SubtypeProp<'a> {
257         self.alloc
258             .alloc(SubtypePropEnum::Conj(Vec::new_in(self.alloc)))
259     }
260     pub fn invalid(&'a self) -> SubtypeProp<'a> {
261         self.alloc
262             .alloc(SubtypePropEnum::Disj(Vec::new_in(self.alloc)))
263     }
264     pub fn loclty(&'a self, ty: Ty<'a>) -> InternalType<'a> {
265         self.alloc(InternalType_::LoclType(ty))
266     }
267     pub fn constraintty(&'a self, ty: ConstraintType<'a>) -> InternalType<'a> {
268         self.alloc(InternalType_::ConstraintType(ty))
269     }
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 })
276     }
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)
281     }